From 4cb68857c19e5335a2b099100d0469638c123094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 5 Oct 2026 14:03:40 -0400 Subject: [PATCH 01/13] wip calendar --- attendee_list.go | 119 ++++++++++++++++++++++++++ calendar_events.go | 204 +++++++++++++++++++++++++++++++++++++++++++++ event_chip.go | 71 ++++++++++++++++ 3 files changed, 394 insertions(+) create mode 100644 attendee_list.go create mode 100644 calendar_events.go create mode 100644 event_chip.go diff --git a/attendee_list.go b/attendee_list.go new file mode 100644 index 0000000..32b3173 --- /dev/null +++ b/attendee_list.go @@ -0,0 +1,119 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// AttendeeStatus is an attendee's reply. +type AttendeeStatus int + +const ( + AttendeePending AttendeeStatus = iota + AttendeeAccepted + AttendeeTentative + AttendeeDeclined +) + +// Attendee is one person invited to an event. +type Attendee struct { + Name string + Email string + Status AttendeeStatus + Organizer bool + Optional bool +} + +// AttendeeListOptions configure an AttendeeList. +type AttendeeListOptions struct { + // Removable shows a remove button on everyone but the organizer. + Removable bool + Disabled bool + Label string +} + +// AttendeeListResult is the list and the attendee the user removed. +type AttendeeListResult struct { + Element *ui.Element + removed int +} + +// Removed returns the index of the attendee the user removed. +func (r AttendeeListResult) Removed() (int, bool) { return r.removed, r.removed >= 0 } + +// AttendeeList shows invitees with their reply, in words and an icon, and a reply summary. +func AttendeeList(c *ui.Context, attendees []Attendee, opts AttendeeListOptions) AttendeeListResult { + k := Tokens(c) + d := Density(c) + var counts [4]int + for _, a := range attendees { + if a.Status < AttendeePending || a.Status > AttendeeDeclined { + panic(fmt.Sprintf("mujica: AttendeeList status %d out of range", a.Status)) + } + counts[a.Status]++ + } + label := opts.Label + if label == "" { + label = msg(c, "attendee_list.label") + } + r := AttendeeListResult{removed: -1} + r.Element = ui.Column(c).Gap(d.Unit()).Role(ui.RoleList).Label(label).Disabled(opts.Disabled) + r.Element.Children(func() { + summary := fmt.Sprintf(msg(c, "attendee_list.summary"), counts[AttendeeAccepted], counts[AttendeeTentative], + counts[AttendeeDeclined], counts[AttendeePending]) + ui.Text(c, summary).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Role(ui.RoleStatus) + if len(attendees) == 0 { + ui.Text(c, msg(c, "attendee_list.empty")).TextColor(k.TextMuted) + } + for i, a := range attendees { + ui.Row(c).Key(i).MinHeight(d.ControlHeight()).Gap(d.Unit()*2).AlignItems(ui.Center).Role(ui.RoleListItem).Children(func() { + Avatar(c, a.Name, AvatarOptions{Size: 28}) + ui.Column(c).Grow(1).Shrink(1).Children(func() { + name := a.Name + if a.Organizer { + name += " · " + msg(c, "attendee_list.organizer") + } + if a.Optional { + name += " · " + msg(c, "attendee_list.optional") + } + ui.Text(c, name).TextColor(k.Text).SingleLine().Ellipsis("…") + if a.Email != "" { + ui.Text(c, a.Email).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine().Ellipsis("…") + } + }) + icon, fg := attendeeStatusLook(k, a.Status) + ui.Row(c).Gap(d.Unit()).AlignItems(ui.Center).Shrink(0).TextColor(fg).Children(func() { + ui.Icon(c, icons.Must(icon)).Size(16, 16) + ui.Text(c, msg(c, attendeeStatusKeys[a.Status])).FontSize(FontSize(c, theme.CaptionSize)) + }) + if opts.Removable && !a.Organizer { + b := iconAction(c, icons.Must("x"), fmt.Sprintf(msg(c, "attendee_list.remove"), a.Name)) + if b.Clicked() && !b.IsDisabled() { + slog.Debug("mujica: attendee_list remove", "index", i) + r.removed = i + } + } + }) + } + }) + return r +} + +var attendeeStatusKeys = [...]string{"attendee_list.pending", "attendee_list.accepted", "attendee_list.tentative", "attendee_list.declined"} + +func attendeeStatusLook(k theme.Tokens, s AttendeeStatus) (icon string, fg ui.Color) { + switch s { + case AttendeeAccepted: + return "circle-check", k.Success + case AttendeeTentative: + return "circle-alert", k.Warning + case AttendeeDeclined: + return "circle-x", k.Danger + } + return "clock", k.TextMuted +} diff --git a/calendar_events.go b/calendar_events.go new file mode 100644 index 0000000..6599680 --- /dev/null +++ b/calendar_events.go @@ -0,0 +1,204 @@ +package mujica + +import ( + "fmt" + "sort" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// EventColor picks an event's color from the theme's event palette. +type EventColor int + +const ( + EventAccent EventColor = iota + EventInfo + EventSuccess + EventWarning + EventDanger + EventNeutral +) + +// CalendarEvent is one entry of the calendar views. End is exclusive. +type CalendarEvent struct { + ID string + Title string + Start time.Time + End time.Time + AllDay bool + Color EventColor + Location string + // Attendees, Reminders and Repeat are edited by EventEditor. + Attendees []Attendee + Reminders []time.Duration + Repeat Recurrence +} + +// CalendarChangeKind says what a view gesture did. +type CalendarChangeKind int + +const ( + CalendarMove CalendarChangeKind = iota + CalendarResize + CalendarCreate +) + +// CalendarChange is a move, resize or new event a view asks the caller to apply. +type CalendarChange struct { + Kind CalendarChangeKind + ID string + Start, End time.Time + AllDay bool +} + +// CalendarViewResult is a calendar view and what the user asked of it. +type CalendarViewResult struct { + Element *ui.Element + opened string + change *CalendarChange + day Date +} + +// Opened returns the event the user activated. +func (r CalendarViewResult) Opened() (string, bool) { return r.opened, r.opened != "" } + +// Changed returns the move, resize or creation the user made. +func (r CalendarViewResult) Changed() (CalendarChange, bool) { + if r.change == nil { + return CalendarChange{}, false + } + return *r.change, true +} + +// DayChosen returns the day the user activated. +func (r CalendarViewResult) DayChosen() (Date, bool) { return r.day, !r.day.IsZero() } + +// eventPalette maps EventColor to tokens that keep 3:1 on Surface in both themes. +func eventPalette(k theme.Tokens) [6]ui.Color { + return [6]ui.Color{k.AccentText, k.Info, k.Success, k.Warning, k.Danger, k.TextMuted} +} + +func eventColor(k theme.Tokens, c EventColor) ui.Color { + if c < EventAccent || c > EventNeutral { + panic(fmt.Sprintf("mujica: EventColor %d out of range", c)) + } + return eventPalette(k)[c] +} + +// eventsCheck panics on events no view can place. +func eventsCheck(name string, events []CalendarEvent) { + for _, e := range events { + if e.ID == "" { + panic("mujica: " + name + " event without ID") + } + if !e.End.After(e.Start) { + panic(fmt.Sprintf("mujica: %s event %q ends before it starts", name, e.ID)) + } + } +} + +// eventsIndex caches the events overlapping a span, rebuilt only when data or span change. +type eventsIndex struct { + first *CalendarEvent + n int + version int + from, to time.Time + hits []int +} + +// eventsIn returns the indexes of events overlapping [from, to), by start time. +func eventsIn(e *ui.Element, events []CalendarEvent, version int, from, to time.Time) []int { + ix := ui.Local(e, "mujica.events.index", func() *eventsIndex { return &eventsIndex{} }) + var first *CalendarEvent + if len(events) > 0 { + first = &events[0] + } + if c := *ix; c.first == first && c.n == len(events) && c.version == version && c.from.Equal(from) && c.to.Equal(to) && c.hits != nil { + return c.hits + } + hits := []int{} + for i, ev := range events { + if ev.Start.Before(to) && ev.End.After(from) { + hits = append(hits, i) + } + } + sort.SliceStable(hits, func(a, b int) bool { + x, y := events[hits[a]], events[hits[b]] + if !x.Start.Equal(y.Start) { + return x.Start.Before(y.Start) + } + return x.End.After(y.End) + }) + **ix = eventsIndex{first, len(events), version, from, to, hits} + return hits +} + +// eventSpan is a placed interval, in any unit. +type eventSpan struct{ from, to float64 } + +// eventColumns lays out overlapping spans side by side: each gets a column and its cluster's width. +func eventColumns(spans []eventSpan) (col, cols []int) { + col, cols = make([]int, len(spans)), make([]int, len(spans)) + order := make([]int, len(spans)) + for i := range order { + order[i] = i + } + sort.SliceStable(order, func(a, b int) bool { return spans[order[a]].from < spans[order[b]].from }) + var ends []float64 + var cluster []int + clusterEnd := -1.0 + flush := func() { + for _, i := range cluster { + cols[i] = len(ends) + } + cluster, ends = cluster[:0], ends[:0] + } + for _, i := range order { + s := spans[i] + if len(cluster) > 0 && s.from >= clusterEnd { + flush() + } + placed := false + for c, end := range ends { + if end <= s.from { + ends[c], col[i], placed = s.to, c, true + break + } + } + if !placed { + col[i] = len(ends) + ends = append(ends, s.to) + } + cluster = append(cluster, i) + clusterEnd = max(clusterEnd, s.to) + } + flush() + return col, cols +} + +// eventDayStart is midnight of d in loc; a missing midnight resolves to the day's first instant. +func eventDayStart(d Date, loc *time.Location) time.Time { + return time.Date(d.Year, d.Month, d.Day, 0, 0, 0, 0, loc) +} + +// eventTimeText formats an event's wall-clock span in loc. +func eventTimeText(c *ui.Context, ev CalendarEvent, loc *time.Location, hour12 bool) string { + if ev.AllDay { + return msg(c, "event_chip.all_day") + } + cfg := timeConfig{hour12: hour12} + s, e := ev.Start.In(loc), ev.End.In(loc) + text := timeText(c, TimeOfDay{s.Hour(), s.Minute(), 0}, cfg) + " – " + timeText(c, TimeOfDay{e.Hour(), e.Minute(), 0}, cfg) + return text +} + +// eventLocation panics without a caller zone; views never assume UTC. +func eventLocation(name string, loc *time.Location) *time.Location { + if loc == nil { + panic("mujica: " + name + " needs a Location") + } + return loc +} diff --git a/event_chip.go b/event_chip.go new file mode 100644 index 0000000..51acf51 --- /dev/null +++ b/event_chip.go @@ -0,0 +1,71 @@ +package mujica + +import ( + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// EventChipOptions configure an EventChip. +type EventChipOptions struct { + // Location is the zone the time shows in; required. + Location *time.Location + Hour12 bool + // Inline puts time and title on one line. + Inline bool + Selected bool + Disabled bool +} + +// EventChip is a clickable event block: color stripe, time and title, truncated to fit. +func EventChip(c *ui.Context, ev CalendarEvent, opts EventChipOptions) *ui.Element { + loc := eventLocation("EventChip", opts.Location) + k := Tokens(c) + d := Density(c) + col := eventColor(k, ev.Color) + when := eventTimeText(c, ev, loc, opts.Hour12) + title := ev.Title + if title == "" { + title = msg(c, "event_chip.untitled") + } + b := ui.ButtonBase(c).MinHeight(theme.MinHitSize).MinWidth(theme.MinHitSize).Justify(ui.Start).AlignItems(ui.Start). + Radius(theme.ControlRadius).Padding(d.Unit(), d.Unit()*2).PaddingX(d.Unit()*2).Gap(d.Unit()). + Label(title + ", " + when).Disabled(opts.Disabled).Clip() + internal.Ring(b, k.Focus, theme.ControlRadius) + bg := col.Alpha(0.14).Over(k.Surface) + switch { + case opts.Selected: + bg = k.Selection + case b.Pressed(): + bg = col.Alpha(0.24).Over(k.Surface) + case b.Hovered(): + bg = col.Alpha(0.2).Over(k.Surface) + } + b.Background(bg).Transition(colorFade) + if !opts.Inline { + b.Column() + } + b.Draw(func(p *ui.Painter, r ui.Rect) { + p.Fill(ui.Rect{X: r.X, Y: r.Y, W: 3, H: r.H}, col, 0) + }) + selected := opts.Selected + b.DrawOver(func(p *ui.Painter, r ui.Rect) { + if selected { + datetimeSelectedMark(p, r, col) + } + }) + b.Children(func() { + small := FontSize(c, theme.CaptionSize) + if opts.Inline { + ui.Text(c, when).FontSize(small).TextColor(k.TextMuted).SingleLine().Shrink(0).FontFeatures("tnum") + } + ui.Text(c, title).FontSize(small).Bold().TextColor(k.Text).SingleLine().Ellipsis("…").Shrink(1) + if !opts.Inline { + ui.Text(c, when).FontSize(small).TextColor(k.TextMuted).SingleLine().Ellipsis("…").FontFeatures("tnum") + } + }) + return b +} From 7a6a44e05d676eaedc0d20f2161b50e14b4d30d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 5 Oct 2026 14:10:23 -0400 Subject: [PATCH 02/13] wip chat sessions --- artifact_card.go | 84 +++++++++++++ capability_cards.go | 94 +++++++++++++++ chat_empty_state.go | 58 +++++++++ conversation_export.go | 228 ++++++++++++++++++++++++++++++++++++ conversation_item.go | 144 +++++++++++++++++++++++ conversation_list.go | 198 +++++++++++++++++++++++++++++++ conversation_search.go | 176 ++++++++++++++++++++++++++++ cost_estimator.go | 90 ++++++++++++++ date_separator.go | 72 ++++++++++++ feedback_form.go | 108 +++++++++++++++++ messages_chatsession.go | 124 ++++++++++++++++++++ project_knowledge_panel.go | 122 +++++++++++++++++++ project_list.go | 212 +++++++++++++++++++++++++++++++++ prompt_library.go | 218 ++++++++++++++++++++++++++++++++++ regenerate_menu.go | 90 ++++++++++++++ shared_conversation_view.go | 107 +++++++++++++++++ stop_generating_button.go | 56 +++++++++ suggestion_chips.go | 76 ++++++++++++ system_prompt_editor.go | 95 +++++++++++++++ thinking_indicator.go | 55 +++++++++ welcome_screen.go | 49 ++++++++ 21 files changed, 2456 insertions(+) create mode 100644 artifact_card.go create mode 100644 capability_cards.go create mode 100644 chat_empty_state.go create mode 100644 conversation_export.go create mode 100644 conversation_item.go create mode 100644 conversation_list.go create mode 100644 conversation_search.go create mode 100644 cost_estimator.go create mode 100644 date_separator.go create mode 100644 feedback_form.go create mode 100644 messages_chatsession.go create mode 100644 project_knowledge_panel.go create mode 100644 project_list.go create mode 100644 prompt_library.go create mode 100644 regenerate_menu.go create mode 100644 shared_conversation_view.go create mode 100644 stop_generating_button.go create mode 100644 suggestion_chips.go create mode 100644 system_prompt_editor.go create mode 100644 thinking_indicator.go create mode 100644 welcome_screen.go diff --git a/artifact_card.go b/artifact_card.go new file mode 100644 index 0000000..478888f --- /dev/null +++ b/artifact_card.go @@ -0,0 +1,84 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// ArtifactKind is what an artifact holds. The zero value is ArtifactCode. +type ArtifactKind int + +const ( + ArtifactCode ArtifactKind = iota + ArtifactDocument + ArtifactWeb +) + +// ArtifactCardOptions configure an ArtifactCard. Title is required. +type ArtifactCardOptions struct { + Kind ArtifactKind + Title string + // Detail is a short fact, such as "Go · 120 lines". + Detail string + // Streaming shows the artifact is still being written. + Streaming bool + Disabled bool +} + +var artifactKinds = [3]struct{ icon, name string }{ + {"file", "artifact_card.code"}, {"file-text", "artifact_card.document"}, {"layout-grid", "artifact_card.web"}, +} + +// ArtifactCard stands for an artifact inside a message; a click or Enter asks to open the artifact panel. +func ArtifactCard(c *ui.Context, opts ArtifactCardOptions) ChoiceResult { + if opts.Title == "" { + panic("mujica: ArtifactCard needs a Title") + } + if opts.Kind < ArtifactCode || opts.Kind > ArtifactWeb { + panic("mujica: ArtifactCard Kind out of range") + } + k := Tokens(c) + d := Density(c) + kind := artifactKinds[opts.Kind] + var b *ui.Element + ui.Row(c).Shrink(0).Disabled(opts.Disabled).Children(func() { + b = ui.ButtonBase(c).MinWidth(260).MaxWidth(420).MinHeight(56).Padding(d.Unit()*2, d.Unit()*3).Gap(d.Unit()*3). + Justify(ui.Start).Radius(theme.CardRadius).Background(k.Surface).Border(theme.BorderWidth, k.ControlBorder). + Label(msg(c, kind.name) + ": " + opts.Title) + }) + internal.Ring(b, k.Focus, theme.CardRadius) + if b.Hovered() { + b.Background(k.SurfaceHover) + } + b.Transition(colorFade) + b.Children(func() { + ui.Box(c).Size(36, 36).Shrink(0).Center().Radius(theme.ControlRadius).Background(k.Selection).Children(func() { + ui.Icon(c, icons.Must(kind.icon)).Size(18, 18).TextColor(k.AccentText) + }) + ui.Column(c).Grow(1).MinWidth(0).Gap(2).Children(func() { + ui.Text(c, opts.Title).SingleLine().Bold().TextColor(k.Text) + ui.Row(c).Gap(d.Unit()).AlignItems(ui.Center).Children(func() { + detail := msg(c, kind.name) + if opts.Detail != "" { + detail += " · " + opts.Detail + } + ui.Text(c, detail).SingleLine().FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + if opts.Streaming { + Spinner(c, SpinnerOptions{Size: 12, Label: msg(c, "artifact_card.writing")}) + } + }) + }) + ui.Text(c, msg(c, "artifact_card.open")).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.AccentText).Shrink(0) + ui.Icon(c, icons.Must("chevron-right")).Size(14, 14).TextColor(k.AccentText) + }) + open := b.Clicked() && !b.IsDisabled() + if open { + slog.Debug("mujica: artifact_card open", "kind", opts.Kind) + } + return ChoiceResult{Element: b, changed: open} +} diff --git a/capability_cards.go b/capability_cards.go new file mode 100644 index 0000000..da12989 --- /dev/null +++ b/capability_cards.go @@ -0,0 +1,94 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// CapabilityCard explains one thing the assistant can do, with example prompts. +type CapabilityCard struct { + Title, Description string + Icon *ui.SVG + Examples []string +} + +// CapabilityCardsOptions configure CapabilityCards. +type CapabilityCardsOptions struct { + // Columns is the most cards per row; zero is 3. + Columns int + Disabled bool +} + +// CapabilityCardsView is built CapabilityCards and the example clicked this frame. +type CapabilityCardsView struct { + Element *ui.Element + // Example is the example prompt chosen, empty for none. + Example string +} + +// CapabilityCards shows what the assistant can do; clicking an example hands it to the caller. +func CapabilityCards(c *ui.Context, cards []CapabilityCard, opts CapabilityCardsOptions) CapabilityCardsView { + if opts.Columns < 0 { + panic("mujica: CapabilityCards Columns is negative") + } + cols := opts.Columns + if cols == 0 { + cols = 3 + } + k := Tokens(c) + d := Density(c) + g := ui.Grid(c).Columns(cols).Gap(d.Unit() * 3).Disabled(opts.Disabled) + v := CapabilityCardsView{Element: g} + g.Children(func() { + for i, card := range cards { + if card.Title == "" { + panic("mujica: CapabilityCard needs a Title") + } + box := ui.Column(c).Key(i).Gap(d.Unit()*2).Padding(d.Unit()*4).Background(k.Surface). + Border(theme.BorderWidth, k.Border).Radius(theme.CardRadius).Role(ui.RoleGroup).Label(card.Title) + box.Children(func() { + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + if card.Icon != nil { + ui.Icon(c, card.Icon).Size(20, 20).TextColor(k.AccentText) + } + ui.Text(c, card.Title).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).TextColor(k.Text) + }) + if card.Description != "" { + ui.Text(c, card.Description).TextColor(k.TextMuted) + } + ui.Column(c).Gap(d.Unit()).FocusGroup(ui.Vertical).Children(func() { + for _, ex := range card.Examples { + if capabilityExample(c, k, ex) { + v.Example = ex + } + } + }) + }) + } + }) + if v.Example != "" { + slog.Debug("mujica: capability_cards example", "len", len(v.Example)) + } + return v +} + +// capabilityExample is a quoted example prompt button; it reports a click. +func capabilityExample(c *ui.Context, k theme.Tokens, text string) bool { + d := Density(c) + b := ui.ButtonBase(c).MinHeight(d.ControlHeight()).Padding(d.Unit(), d.Unit()*3).Justify(ui.Start). + Radius(theme.ControlRadius).Background(k.Background).Border(theme.BorderWidth, k.Border).Label(text) + internal.Ring(b, k.Focus, theme.ControlRadius) + switch { + case b.Pressed(): + b.Background(k.Selection) + case b.Hovered(): + b.Background(k.SurfaceHover).Border(theme.BorderWidth, k.ControlBorder) + } + b.Transition(colorFade) + b.Children(func() { ui.Text(c, "“"+text+"”").TextColor(k.Text) }) + return b.Clicked() && !b.IsDisabled() +} diff --git a/chat_empty_state.go b/chat_empty_state.go new file mode 100644 index 0000000..38628f9 --- /dev/null +++ b/chat_empty_state.go @@ -0,0 +1,58 @@ +package mujica + +import ( + "cmp" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" +) + +// ChatEmptyKind is why a chat view is empty. The zero value is ChatEmptyNew. +type ChatEmptyKind int + +const ( + // ChatEmptyNew: a new conversation with no messages. + ChatEmptyNew ChatEmptyKind = iota + // ChatEmptyNoResults: a conversation search matched nothing. + ChatEmptyNoResults + // ChatEmptyOffline: the connection is down. + ChatEmptyOffline +) + +// ChatEmptyStateOptions configure a ChatEmptyState; empty texts use the kind's built-in copy. +type ChatEmptyStateOptions struct { + Kind ChatEmptyKind + // Query, for ChatEmptyNoResults, is named in the description. + Query string + Title string + Description string + // Action replaces the kind's button text: Start, Clear search or Retry. + Action string +} + +// ChatEmptyState explains an empty chat (new, no results, offline) and offers the next step. +func ChatEmptyState(c *ui.Context, opts ChatEmptyStateOptions) EmptyStateResult { + switch opts.Kind { + case ChatEmptyNew: + return EmptyState(c, EmptyStateOptions{ + Title: cmp.Or(opts.Title, msg(c, "chat_empty_state.new.title")), + Description: cmp.Or(opts.Description, msg(c, "chat_empty_state.new.description")), + Icon: icons.Must("star"), + Action: cmp.Or(opts.Action, msg(c, "chat_empty_state.new.action")), + }) + case ChatEmptyNoResults: + return EmptyState(c, EmptyStateOptions{ + Kind: EmptyNoResults, Query: opts.Query, Title: opts.Title, Description: opts.Description, + Action: cmp.Or(opts.Action, msg(c, "chat_empty_state.no_results.action")), + }) + case ChatEmptyOffline: + return EmptyState(c, EmptyStateOptions{ + Title: cmp.Or(opts.Title, msg(c, "chat_empty_state.offline.title")), + Description: cmp.Or(opts.Description, msg(c, "chat_empty_state.offline.description")), + Icon: icons.Must("wifi-off"), + Action: cmp.Or(opts.Action, msg(c, "chat_empty_state.offline.action")), + }) + } + panic("mujica: ChatEmptyState Kind out of range") +} diff --git a/conversation_export.go b/conversation_export.go new file mode 100644 index 0000000..e9c6f40 --- /dev/null +++ b/conversation_export.go @@ -0,0 +1,228 @@ +package mujica + +import ( + "encoding/json" + "fmt" + "log/slog" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// ExportFormat is the text form of an export. The zero value is ExportMarkdown. +type ExportFormat int + +const ( + ExportMarkdown ExportFormat = iota + ExportJSON + ExportText +) + +// ExportRange is which messages an export holds. The zero value is ExportAll. +type ExportRange int + +const ( + ExportAll ExportRange = iota + // ExportLast holds the last State.Last messages. + ExportLast + // ExportSelected holds the messages at Options.Selected. + ExportSelected +) + +var exportRoles = map[SessionRole]string{SessionUser: "user", SessionAssistant: "assistant", SessionSystem: "system"} + +// ExportConversation writes messages as Markdown, JSON or plain text; it does not parse their text. +func ExportConversation(title string, messages []SessionMessage, format ExportFormat) string { + var b strings.Builder + switch format { + case ExportMarkdown: + fmt.Fprintf(&b, "# %s\n", title) + for _, m := range messages { + fmt.Fprintf(&b, "\n**%s**%s\n\n%s\n", exportAuthor(m), exportTime(m, " · "), m.Text) + } + case ExportJSON: + type msgJSON struct { + Role string `json:"role"` + Author string `json:"author,omitempty"` + Text string `json:"text"` + Time string `json:"time,omitempty"` + } + doc := struct { + Title string `json:"title"` + Messages []msgJSON `json:"messages"` + }{Title: title, Messages: []msgJSON{}} + for _, m := range messages { + doc.Messages = append(doc.Messages, msgJSON{exportRoles[m.Role], m.Author, m.Text, exportTime(m, "")}) + } + out, err := json.MarshalIndent(doc, "", " ") + if err != nil { + panic(err) + } + b.Write(out) + b.WriteByte('\n') + case ExportText: + fmt.Fprintf(&b, "%s\n", title) + for _, m := range messages { + fmt.Fprintf(&b, "\n%s%s:\n%s\n", exportAuthor(m), exportTime(m, " "), m.Text) + } + default: + panic("mujica: unknown ExportFormat") + } + return b.String() +} + +func exportAuthor(m SessionMessage) string { + if m.Author != "" { + return m.Author + } + r, ok := exportRoles[m.Role] + if !ok { + panic("mujica: SessionMessage Role out of range") + } + return strings.ToUpper(r[:1]) + r[1:] +} + +func exportTime(m SessionMessage, sep string) string { + if m.Time.IsZero() { + return "" + } + if sep == "" { + return m.Time.Format(time.RFC3339) + } + return sep + "(" + m.Time.Format("2006-01-02 15:04") + ")" +} + +// ConversationExportState is the chosen format and range. +type ConversationExportState struct { + Format ExportFormat + Range ExportRange + // Last is the count for ExportLast; zero is 10. + Last float64 + cache conversationExportCache +} + +// conversationExportCache holds the last export text until its inputs change. +type conversationExportCache struct { + key conversationExportInputs + content string +} + +type conversationExportInputs struct { + title string + format ExportFormat + rng ExportRange + last float64 + first *SessionMessage + n int + sel string + built bool +} + +// conversationExportContent rebuilds the export only when its inputs change. +func conversationExportContent(s *ConversationExportState, messages []SessionMessage, opts ConversationExportOptions) string { + in := conversationExportInputs{title: opts.Title, format: s.Format, rng: s.Range, last: s.Last, n: len(messages), sel: fmt.Sprint(opts.Selected), built: true} + if len(messages) > 0 { + in.first = &messages[0] + } + if s.cache.key != in { + s.cache = conversationExportCache{in, ExportConversation(opts.Title, conversationExportPick(s, messages, opts.Selected), s.Format)} + } + return s.cache.content +} + +// ConversationExportOptions configure a ConversationExport. Title is required. +type ConversationExportOptions struct { + Title string + // Selected are message indices for ExportSelected. + Selected []int + Disabled bool +} + +// ConversationExportView is a built ConversationExport and the export asked for. +type ConversationExportView struct { + Element *ui.Element + // Exported reports Content is ready for the caller to write, as Format. + Exported bool + Content string + Format ExportFormat +} + +// ConversationExport picks a format and range, previews the result and hands the text to the caller to save. +func ConversationExport(c *ui.Context, s *ConversationExportState, messages []SessionMessage, opts ConversationExportOptions) ConversationExportView { + if s == nil || opts.Title == "" { + panic("mujica: ConversationExport needs a state and a Title") + } + for _, i := range opts.Selected { + if i < 0 || i >= len(messages) { + panic("mujica: ConversationExport Selected index out of range") + } + } + if s.Last == 0 { + s.Last = 10 + } + k := Tokens(c) + d := Density(c) + col := ui.Column(c).Gap(d.Unit() * 3).Disabled(opts.Disabled) + v := ConversationExportView{Element: col, Format: s.Format} + content := conversationExportContent(s, messages, opts) + col.Children(func() { + FormField(c, msg(c, "conversation_export.format"), FormFieldOptions{}, func() *ui.Element { + return RadioGroup(c, &s.Format, []RadioItem[ExportFormat]{ + {Value: ExportMarkdown, Label: "Markdown"}, {Value: ExportJSON, Label: "JSON"}, + {Value: ExportText, Label: msg(c, "conversation_export.text")}, + }, RadioGroupOptions{Horizontal: true, Label: msg(c, "conversation_export.format"), Disabled: opts.Disabled}).Element + }) + FormField(c, msg(c, "conversation_export.range"), FormFieldOptions{}, func() *ui.Element { + return ui.Row(c).Gap(d.Unit() * 3).AlignItems(ui.Center).Children(func() { + RadioGroup(c, &s.Range, []RadioItem[ExportRange]{ + {Value: ExportAll, Label: fmt.Sprintf(msg(c, "conversation_export.all"), len(messages))}, + {Value: ExportLast, Label: msg(c, "conversation_export.last")}, + {Value: ExportSelected, Label: fmt.Sprintf(msg(c, "conversation_export.selected"), len(opts.Selected)), Disabled: len(opts.Selected) == 0}, + }, RadioGroupOptions{Horizontal: true, Label: msg(c, "conversation_export.range"), Disabled: opts.Disabled}) + if s.Range == ExportLast { + NumberInput(c, &s.Last, NumberInputOptions{Min: 1, Max: float64(max(1, len(messages))), Step: 1, + Label: msg(c, "conversation_export.last"), Disabled: opts.Disabled}).Element.Width(120) + } + }) + }) + ui.Text(c, msg(c, "conversation_export.preview")).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + ui.Scroll(c).MaxHeight(220).Padding(d.Unit()*3).Background(k.Background).Border(theme.BorderWidth, k.Border). + Radius(theme.ControlRadius).Children(func() { + ui.Text(c, content).Font(theme.MonoFont).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.Text).Selectable() + }) + ui.Row(c).Justify(ui.End).Children(func() { + v.Exported = Button(c, msg(c, "conversation_export.export"), ButtonOptions{Icon: icons.Must("upload"), Disabled: opts.Disabled}).Clicked() + }) + }) + if v.Exported && !col.IsDisabled() { + v.Content = content + slog.Debug("mujica: conversation_export export", "format", s.Format, "bytes", len(content)) + } else { + v.Exported = false + } + return v +} + +// conversationExportPick returns the messages the range holds, in order. +func conversationExportPick(s *ConversationExportState, messages []SessionMessage, selected []int) []SessionMessage { + switch s.Range { + case ExportLast: + return messages[max(0, len(messages)-int(s.Last)):] + case ExportSelected: + var out []SessionMessage + for i := range messages { + for _, j := range selected { + if i == j { + out = append(out, messages[i]) + break + } + } + } + return out + } + return messages +} diff --git a/conversation_item.go b/conversation_item.go new file mode 100644 index 0000000..c3eb5b2 --- /dev/null +++ b/conversation_item.go @@ -0,0 +1,144 @@ +package mujica + +import ( + "cmp" + "log/slog" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// ConversationItemOptions configure a ConversationItem. +type ConversationItemOptions struct { + // Today decides the time stamp's form; zero uses the window clock. + Today Date + Selected bool + Disabled bool + // Draggable lets the row be dragged onto a ProjectList as a ConversationDrag. + Draggable bool +} + +// ConversationDrag is the value a dragged conversation carries. +type ConversationDrag struct{ ID string } + +// ConversationItemView is a built ConversationItem and what the user asked for this frame. +type ConversationItemView struct { + Element *ui.Element + // Opened, Deleted, Exported and PinToggled are requests for the caller to carry out. + Opened, Deleted, Exported, PinToggled bool + // Renamed reports a confirmed new title, already in conv.Title. + Renamed bool +} + +type conversationItemState struct { + editing, fresh bool + draft string +} + +type conversationItemKey struct{} + +// ConversationItem is a conversation row: title, time, and a menu to rename in place, pin, export or delete. +func ConversationItem(c *ui.Context, conv *ChatConversation, opts ConversationItemOptions) ConversationItemView { + if conv == nil || conv.ID == "" { + panic("mujica: ConversationItem needs a conversation with an ID") + } + k := Tokens(c) + d := Density(c) + today := opts.Today + if today.IsZero() { + today = DateOf(c.Now()) + } + row := ui.Row(c).Key(conv.ID).FillWidth().MinHeight(d.ControlHeight()).Gap(d.Unit()).AlignItems(ui.Center). + Radius(theme.ControlRadius).Disabled(opts.Disabled) + v := ConversationItemView{Element: row} + st := ui.Local(row, conversationItemKey{}, func() conversationItemState { return conversationItemState{} }) + if row.IsDisabled() { + st.editing = false + } + if opts.Selected { + row.Background(k.Selection) + } + title := cmp.Or(conv.Title, msg(c, "conversation_list.untitled")) + rename := false + row.Children(func() { + if st.editing { + conversationItemEditor(c, k, conv, st, &v) + } else { + main := ui.ButtonBase(c).Grow(1).MinWidth(0).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*2).Gap(d.Unit() * 2). + Justify(ui.Start).Radius(theme.ControlRadius).Label(title) + internal.Ring(main, k.Focus, theme.ControlRadius) + if opts.Draggable { + main.Drag(ConversationDrag{ID: conv.ID}) + } + if main.Hovered() && !opts.Selected { + main.Background(k.SurfaceHover) + } + main.Transition(colorFade) + main.Children(func() { + if conv.Pinned { + ui.Icon(c, icons.Must("star")).Size(14, 14).Shrink(0).TextColor(k.AccentText).Label(msg(c, "conversation_item.pinned")) + } + t := ui.Text(c, title).SingleLine().Grow(1).MinWidth(0) + if opts.Selected { + t.TextColor(k.AccentText) + } + ui.Text(c, dateSeparatorWhen(c, conv.Updated, today)).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Shrink(0) + }) + if !main.IsDisabled() { + v.Opened = main.Clicked() + rename = main.Shortcut(0, ui.KeyF2) + v.Deleted = main.Shortcut(0, ui.KeyDelete) + } + } + menu := DropdownMenu(c, "", DropdownMenuOptions{Icon: icons.Must("ellipsis"), Label: msg(c, "conversation_item.actions"), Disabled: opts.Disabled}, func(m *PopupMenu) { + rename = m.Item(msg(c, "conversation_item.rename"), PopupMenuItemOptions{}) || rename + pin := msg(c, "conversation_item.pin") + if conv.Pinned { + pin = msg(c, "conversation_item.unpin") + } + v.PinToggled = m.Item(pin, PopupMenuItemOptions{}) + v.Exported = m.Item(msg(c, "conversation_item.export"), PopupMenuItemOptions{}) + m.Separator() + v.Deleted = m.Item(msg(c, "conversation_item.delete"), PopupMenuItemOptions{}) || v.Deleted + }) + menu.Shrink(0).MinWidth(theme.MinHitSize).MinHeight(theme.MinHitSize) + }) + if rename && !row.IsDisabled() { + st.editing, st.fresh, st.draft = true, true, conv.Title + } + switch { + case v.Opened: + slog.Debug("mujica: conversation_item open", "id", conv.ID) + case v.Deleted, v.Exported, v.PinToggled: + slog.Debug("mujica: conversation_item action", "id", conv.ID, "delete", v.Deleted, "export", v.Exported, "pin", v.PinToggled) + } + return v +} + +// conversationItemEditor is the in-place title field: Enter keeps a non-blank title, Escape cancels. +func conversationItemEditor(c *ui.Context, k theme.Tokens, conv *ChatConversation, st *conversationItemState, v *ConversationItemView) { + d := Density(c) + in := ui.TextInputBase(c, &st.draft).Grow(1).MinHeight(d.ControlHeight()-4).Padding(0, d.Unit()*2). + Radius(theme.ControlRadius).Background(k.Surface).Border(theme.BorderWidth, k.AccentText). + Label(msg(c, "conversation_item.rename")) + internal.Ring(in, k.Focus, theme.ControlRadius) + switch { + case st.fresh: + st.fresh = false + in.Focus() + case in.IsDisabled(): + case in.Submitted(): + if t := strings.TrimSpace(st.draft); t != "" { + v.Renamed = t != conv.Title + conv.Title = t + } + st.editing = false + slog.Debug("mujica: conversation_item rename", "id", conv.ID, "changed", v.Renamed) + case in.Shortcut(0, ui.KeyEscape): + st.editing = false + } +} diff --git a/conversation_list.go b/conversation_list.go new file mode 100644 index 0000000..c6dae06 --- /dev/null +++ b/conversation_list.go @@ -0,0 +1,198 @@ +package mujica + +import ( + "cmp" + "log/slog" + "slices" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// ChatConversation is one saved conversation, as the caller stores it. +type ChatConversation struct { + ID, Title string + Updated time.Time + Pinned bool +} + +// ConversationListOptions configure a ConversationList. +type ConversationListOptions struct { + // Now dates the groups; zero uses the window clock. + Now time.Time + // Label names the list for assistive technology. + Label string + Disabled bool +} + +// ConversationListState is the chosen conversation and the list's place. +type ConversationListState struct { + // Selected is the chosen conversation's ID; empty for none. + Selected string + rows ui.ListState + cursor int + plan conversationListPlan +} + +// conversationListPlan is the grouped rows, rebuilt only when the data or day changes. +type conversationListPlan struct { + src []ChatConversation + day Date + rows []conversationListRow + built bool +} + +// conversationListRow is group header g (item < 0) or an index into the items. +type conversationListRow struct { + group, item int +} + +// ConversationListView is a built ConversationList and this frame's events. +type ConversationListView struct { + Element *ui.Element + changed bool + submitted bool +} + +// Changed reports a newly chosen conversation, in State.Selected. +func (v ConversationListView) Changed() bool { return v.changed } + +// Submitted reports Enter or a double click on the chosen conversation. +func (v ConversationListView) Submitted() bool { return v.submitted } + +// ConversationList groups conversations into pinned, today, yesterday, past 7 days and older, building only rows in view. +func ConversationList(c *ui.Context, s *ConversationListState, items []ChatConversation, opts ConversationListOptions, row func(conv ChatConversation)) ConversationListView { + if s == nil { + panic("mujica: ConversationList needs a state") + } + now := opts.Now + if now.IsZero() { + now = c.Now() + } + conversationListPlanRows(&s.plan, items, DateOf(now)) + rows := s.plan.rows + s.cursor = slices.IndexFunc(rows, func(r conversationListRow) bool { return r.item >= 0 && items[r.item].ID == s.Selected }) + before := s.cursor + k := Tokens(c) + d := Density(c) + cursor := &s.cursor + if opts.Disabled { + // A disabled list moves a copy of the cursor. + cp := s.cursor + cursor = &cp + } + s.rows.Key = func(i int) any { + if r := rows[i]; r.item >= 0 { + return items[r.item].ID + } + return conversationListGroups[rows[i].group] + } + s.rows.Header = func(i int) bool { return rows[i].item < 0 } + s.rows.Label = func(i int) string { return conversationListTitle(c, items, rows[i]) } + s.rows.Selected = cursor + var list *ui.Element + wrap := ui.Column(c).Grow(1).MinHeight(0).Disabled(opts.Disabled) + wrap.Children(func() { + restore := dataSelectTheme(c, 0) + list = ui.List(c, &s.rows, len(rows), func(i int) { + r := rows[i] + if r.item < 0 { + conversationListHeader(c, k, msg(c, conversationListGroups[r.group])) + return + } + conv := items[r.item] + ui.Row(c).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*2).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + ui.Box(c).Size(8, 8).Shrink(0).Draw(func(p *ui.Painter, b ui.Rect) { + if conv.ID == s.Selected { + p.FillPath(internal.Diamond(b.X+b.W/2, b.Y+b.H/2, 8), k.AccentText) + } + }) + if row != nil { + ui.Row(c).Grow(1).MinWidth(0).Children(func() { row(conv) }) + return + } + ui.Text(c, conversationListTitle(c, items, r)).SingleLine().Grow(1).MinWidth(0) + }) + }).Grow(1).MinHeight(0).Padding(d.Unit()).Background(k.Surface).Border(theme.BorderWidth, k.Border). + Radius(theme.ControlRadius).Label(opts.Label) + restore() + internal.Ring(list, k.Focus, theme.ControlRadius) + }) + v := ConversationListView{Element: wrap} + if !wrap.IsDisabled() { + if s.cursor != before && s.cursor >= 0 && rows[s.cursor].item >= 0 { + s.Selected, v.changed = items[rows[s.cursor].item].ID, true + slog.Debug("mujica: conversation_list select", "id", s.Selected) + } + v.submitted = list.Submitted() && s.Selected != "" + } + return v +} + +func conversationListTitle(c *ui.Context, items []ChatConversation, r conversationListRow) string { + if r.item < 0 { + return msg(c, conversationListGroups[r.group]) + } + return cmp.Or(items[r.item].Title, msg(c, "conversation_list.untitled")) +} + +func conversationListHeader(c *ui.Context, k theme.Tokens, title string) { + d := Density(c) + ui.Row(c).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*2).AlignItems(ui.Center).Background(k.Surface).Children(func() { + ui.Text(c, title).Font(theme.SerifFont).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.Ornament.Mix(k.Text, 0.35)).SingleLine() + }) +} + +// conversationListPlanRows regroups items when the slice or the day changed. +func conversationListPlanRows(p *conversationListPlan, items []ChatConversation, today Date) { + same := p.built && p.day == today && len(p.src) == len(items) && (len(items) == 0 || &p.src[0] == &items[0]) + if same { + return + } + p.src, p.day, p.built = items, today, true + order := make([]int, len(items)) + for i := range order { + order[i] = i + } + slices.SortStableFunc(order, func(a, b int) int { return items[b].Updated.Compare(items[a].Updated) }) + groups := [5][]int{} + for _, i := range order { + g := conversationListGroup(items[i], today) + groups[g] = append(groups[g], i) + } + p.rows = p.rows[:0] + for g, idx := range groups { + if len(idx) == 0 { + continue + } + p.rows = append(p.rows, conversationListRow{group: g, item: -1}) + for _, i := range idx { + p.rows = append(p.rows, conversationListRow{item: i}) + } + } + slog.Debug("mujica: conversation_list regroup", "count", len(items)) +} + +var conversationListGroups = [5]string{ + "conversation_list.pinned", "conversation_list.today", "conversation_list.yesterday", + "conversation_list.week", "conversation_list.older", +} + +// conversationListGroup is the group index of conv: pinned, today, yesterday, 7 days, older. +func conversationListGroup(conv ChatConversation, today Date) int { + day := DateOf(conv.Updated) + switch { + case conv.Pinned: + return 0 + case day.Compare(today) >= 0: + return 1 + case day == today.AddDays(-1): + return 2 + case day.Compare(today.AddDays(-7)) >= 0: + return 3 + } + return 4 +} diff --git a/conversation_search.go b/conversation_search.go new file mode 100644 index 0000000..0fc7865 --- /dev/null +++ b/conversation_search.go @@ -0,0 +1,176 @@ +package mujica + +import ( + "log/slog" + "unicode" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// ConversationSearchHit is one conversation the caller found for the query. +type ConversationSearchHit struct { + ID, Title string + // Snippet is matching message text, shown under the title. + Snippet string +} + +// ConversationSearchOptions configure a ConversationSearch. +type ConversationSearchOptions struct { + // Loading shows the caller's search for the query is under way. + Loading bool + // Error is the caller's failed search; it shows with a retry button. + Error string + Placeholder string + Label string + Disabled bool +} + +// ConversationSearchView is a built ConversationSearch and this frame's events. +type ConversationSearchView struct { + Element *ui.Element + // QueryChanged asks the caller to search again for the new query. + QueryChanged bool + // Chosen is the hit opened by a click or Enter, empty for none. + Chosen string + Retry bool +} + +type conversationSearchState struct { + cursor int + rows ui.ListState + enter bool +} + +type conversationSearchKey struct{} + +// ConversationSearch searches titles and content; the caller supplies hits for the query and the matches are highlighted. +func ConversationSearch(c *ui.Context, query *string, hits []ConversationSearchHit, opts ConversationSearchOptions) ConversationSearchView { + if query == nil { + panic("mujica: ConversationSearch needs a query") + } + k := Tokens(c) + d := Density(c) + col := ui.Column(c).Gap(d.Unit() * 2).MinHeight(0).Disabled(opts.Disabled) + v := ConversationSearchView{Element: col} + st := ui.Local(col, conversationSearchKey{}, func() *conversationSearchState { return &conversationSearchState{cursor: -1} }) + s := *st + s.cursor = min(s.cursor, len(hits)-1) + col.Children(func() { + in := SearchInput(c, query, SearchInputOptions{Placeholder: opts.Placeholder, Label: opts.Label, Disabled: opts.Disabled}) + v.QueryChanged = in.Changed() + if in.Input.Shortcut(0, ui.KeyDown) && !in.Input.IsDisabled() && len(hits) > 0 { + s.enter, s.cursor = true, max(s.cursor, 0) + } + switch { + case opts.Error != "": + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).TextColor(k.Danger).Children(func() { + ui.Icon(c, icons.Must("circle-alert")).Size(16, 16) + ui.Text(c, opts.Error).Role(ui.RoleStatus).Grow(1) + v.Retry = Button(c, msg(c, "conversation_search.retry"), ButtonOptions{Variant: Secondary, Icon: icons.Must("refresh-cw")}).Clicked() + }) + case opts.Loading && len(hits) == 0: + Spinner(c, SpinnerOptions{Label: msg(c, "conversation_search.searching"), ShowLabel: true}) + case len(hits) == 0 && *query != "": + ui.Text(c, msg(c, "conversation_search.no_results")).TextColor(k.TextMuted).Role(ui.RoleStatus) + case len(hits) > 0: + v.Chosen = conversationSearchList(c, s, *query, hits, opts.Loading) + } + }) + if v.QueryChanged { + s.cursor = -1 + slog.Debug("mujica: conversation_search query", "len", len(*query)) + } + if v.Chosen != "" { + slog.Debug("mujica: conversation_search choose", "id", v.Chosen) + } + return v +} + +func conversationSearchList(c *ui.Context, s *conversationSearchState, q string, hits []ConversationSearchHit, loading bool) string { + k := Tokens(c) + d := Density(c) + chosen := "" + s.rows.Key = func(i int) any { return hits[i].ID } + s.rows.Label = func(i int) string { return hits[i].Title } + s.rows.Selected = &s.cursor + restore := dataSelectTheme(c, 0) + list := ui.List(c, &s.rows, len(hits), func(i int) { + h := hits[i] + row := ui.Column(c).MinHeight(d.ControlHeight()).Padding(d.Unit(), d.Unit()*2).Gap(2).Justify(ui.Center) + if i == s.cursor { + row.DrawOver(func(p *ui.Painter, r ui.Rect) { + p.FillPath(internal.Diamond(r.X+3, r.Y+r.H/2, 6), k.AccentText) + }) + } + row.Children(func() { + ui.RichText(c, conversationSearchSpans(h.Title, q, k)...).SingleLine() + if h.Snippet != "" { + ui.RichText(c, conversationSearchSpans(h.Snippet, q, k)...).MaxLines(2).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)) + } + }) + if !row.IsDisabled() && row.Clicked() { + chosen = h.ID + } + }).MaxHeight(360).Padding(d.Unit()).Background(k.Surface).Border(theme.BorderWidth, k.Border). + Radius(theme.ControlRadius).Label(msg(c, "conversation_search.results")) + restore() + internal.Ring(list, k.Focus, theme.ControlRadius) + if s.enter { + s.enter = false + list.Focus() + } + if loading { + Spinner(c, SpinnerOptions{Size: 12, Label: msg(c, "conversation_search.searching")}) + } + if list.Submitted() && !list.IsDisabled() && s.cursor >= 0 && s.cursor < len(hits) { + chosen = hits[s.cursor].ID + } + return chosen +} + +// conversationSearchSpans splits text into spans, marking each case-insensitive match of q. +func conversationSearchSpans(text, q string, k theme.Tokens) []ui.Span { + r := []rune(text) + var spans []ui.Span + at := 0 + for _, m := range conversationSearchMatches(text, q) { + if m[0] > at { + spans = append(spans, ui.Span{Text: string(r[at:m[0]])}) + } + spans = append(spans, ui.Span{Text: string(r[m[0]:m[1]]), Weight: 700, Background: k.Selection, Underline: true}) + at = m[1] + } + if at < len(r) || len(spans) == 0 { + spans = append(spans, ui.Span{Text: string(r[at:])}) + } + return spans +} + +// conversationSearchMatches returns rune ranges of case-insensitive matches of q in text. +func conversationSearchMatches(text, q string) [][2]int { + t, p := []rune(text), []rune(q) + if len(p) == 0 { + return nil + } + var out [][2]int + for i := 0; i+len(p) <= len(t); { + ok := true + for j := range p { + if unicode.ToLower(t[i+j]) != unicode.ToLower(p[j]) { + ok = false + break + } + } + if ok { + out = append(out, [2]int{i, i + len(p)}) + i += len(p) + continue + } + i++ + } + return out +} diff --git a/cost_estimator.go b/cost_estimator.go new file mode 100644 index 0000000..553aa80 --- /dev/null +++ b/cost_estimator.go @@ -0,0 +1,90 @@ +package mujica + +import ( + "fmt" + "math" + "strconv" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// CostEstimatorOptions configure a CostEstimator. Prices are per million tokens, from the caller. +type CostEstimatorOptions struct { + InputTokens, OutputTokens int + InputPrice, OutputPrice float64 + // Currency prefixes amounts; empty is "$". + Currency string + // Digits is the decimals shown for amounts; zero is 4. + Digits int +} + +// CostEstimate is the cost of the input, the output and both. +type CostEstimate struct{ Input, Output, Total float64 } + +// EstimateCost prices token counts at per-million rates. +func EstimateCost(inputTokens, outputTokens int, inputPrice, outputPrice float64) CostEstimate { + in := float64(inputTokens) * inputPrice / 1e6 + out := float64(outputTokens) * outputPrice / 1e6 + return CostEstimate{in, out, in + out} +} + +// CostEstimator shows input and output tokens and their estimated cost at the caller's prices. +func CostEstimator(c *ui.Context, opts CostEstimatorOptions) *ui.Element { + if opts.InputTokens < 0 || opts.OutputTokens < 0 { + panic("mujica: CostEstimator token counts must not be negative") + } + for _, p := range []float64{opts.InputPrice, opts.OutputPrice} { + if p < 0 || math.IsNaN(p) || math.IsInf(p, 0) { + panic("mujica: CostEstimator prices must be finite and not negative") + } + } + if opts.Digits < 0 { + panic("mujica: CostEstimator Digits is negative") + } + digits := opts.Digits + if digits == 0 { + digits = 4 + } + cur := opts.Currency + if cur == "" { + cur = "$" + } + money := func(v float64) string { return cur + strconv.FormatFloat(v, 'f', digits, 64) } + est := EstimateCost(opts.InputTokens, opts.OutputTokens, opts.InputPrice, opts.OutputPrice) + k := Tokens(c) + d := Density(c) + total := fmt.Sprintf(msg(c, "cost_estimator.total_label"), money(est.Total)) + g := ui.Grid(c).ColumnTracks(ui.Fr(1), ui.FitContent(), ui.FitContent()).GapX(d.Unit()*4).GapY(d.Unit()). + Padding(d.Unit()*3).Background(k.Surface).Border(theme.BorderWidth, k.Border).Radius(theme.CardRadius). + Role(ui.RoleGroup).Label(total) + cell := func(s string, ink ui.Color, right bool) { + t := ui.Text(c, s).TextColor(ink).SingleLine().FontFeatures("tnum") + if right { + t.JustifySelf(ui.End) + } + } + g.Children(func() { + cell(msg(c, "cost_estimator.kind"), k.TextMuted, false) + cell(msg(c, "cost_estimator.tokens"), k.TextMuted, true) + cell(msg(c, "cost_estimator.cost"), k.TextMuted, true) + cell(msg(c, "cost_estimator.input"), k.Text, false) + cell(strconv.Itoa(opts.InputTokens), k.Text, true) + cell(money(est.Input), k.Text, true) + cell(msg(c, "cost_estimator.output"), k.Text, false) + cell(strconv.Itoa(opts.OutputTokens), k.Text, true) + cell(money(est.Output), k.Text, true) + ui.Box(c).ColumnSpan(3).Height(9).Draw(func(p *ui.Painter, r ui.Rect) { + internal.Rule(p, r.X, r.X+r.W, r.Y+r.H/2, k.Ornament) + }) + ui.Text(c, msg(c, "cost_estimator.total")).Font(theme.SerifFont).TextColor(k.Text) + cell(strconv.Itoa(opts.InputTokens+opts.OutputTokens), k.Text, true) + ui.Text(c, money(est.Total)).Bold().TextColor(k.AccentText).JustifySelf(ui.End).FontFeatures("tnum") + ui.Text(c, fmt.Sprintf(msg(c, "cost_estimator.rates"), cur+strconv.FormatFloat(opts.InputPrice, 'f', -1, 64), + cur+strconv.FormatFloat(opts.OutputPrice, 'f', -1, 64))). + ColumnSpan(3).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + }) + return g +} diff --git a/date_separator.go b/date_separator.go new file mode 100644 index 0000000..1d73c87 --- /dev/null +++ b/date_separator.go @@ -0,0 +1,72 @@ +package mujica + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// DateSeparatorOptions configure a DateSeparator. +type DateSeparatorOptions struct { + // Today decides "Today" and "Yesterday"; zero uses the window clock. + Today Date +} + +// DateSeparator marks where a day's messages begin: Today, Yesterday, or the full date in the window's language. +func DateSeparator(c *ui.Context, day Date, opts DateSeparatorOptions) *ui.Element { + if !day.Valid() { + panic("mujica: DateSeparator needs a valid date") + } + today := opts.Today + if today.IsZero() { + today = DateOf(c.Now()) + } + k := Tokens(c) + u := Density(c).Unit() + label := dateSeparatorLabel(c, day, today) + row := ui.Row(c).FillWidth().Gap(u*3).AlignItems(ui.Center).Padding(u*2, 0).Role(ui.RoleText).Label(label) + line := func() { + ui.Box(c).Grow(1).Height(9).Draw(func(p *ui.Painter, r ui.Rect) { + internal.Rule(p, r.X, r.X+r.W, r.Y+r.H/2, k.Border) + }) + } + row.Children(func() { + line() + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Shrink(0).Children(func() { + ui.Box(c).Size(6, 6).Draw(func(p *ui.Painter, r ui.Rect) { + p.FillPath(internal.Diamond(r.X+3, r.Y+3, 6), k.Ornament) + }) + ui.Text(c, label).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine() + }) + line() + }) + return row +} + +// dateSeparatorLabel names day relative to today, in the window's language. +func dateSeparatorLabel(c *ui.Context, day, today Date) string { + switch day { + case today: + return msg(c, "date_separator.today") + case today.AddDays(-1): + return msg(c, "date_separator.yesterday") + } + return fmt.Sprintf(msg(c, "calendar.day_label"), msg(c, fmt.Sprintf("calendar.weekday_long_%d", day.Weekday())), + msg(c, fmt.Sprintf("calendar.month_%d", day.Month)), day.Day, day.Year) +} + +// dateSeparatorWhen is a short time stamp: the clock today, else the relative day or date. +func dateSeparatorWhen(c *ui.Context, t time.Time, today Date) string { + day := DateOf(t) + if day == today { + return t.Format("15:04") + } + if day == today.AddDays(-1) { + return msg(c, "date_separator.yesterday") + } + return fmt.Sprintf(msg(c, "date_separator.short"), msg(c, fmt.Sprintf("calendar.month_%d", day.Month)), day.Day) +} diff --git a/feedback_form.go b/feedback_form.go new file mode 100644 index 0000000..4edcd75 --- /dev/null +++ b/feedback_form.go @@ -0,0 +1,108 @@ +package mujica + +import ( + "log/slog" + "slices" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// FeedbackRating is the thumb the user gave. The zero value is FeedbackUp. +type FeedbackRating int + +const ( + FeedbackUp FeedbackRating = iota + FeedbackDown +) + +// FeedbackValue is what the user wrote: chosen reasons and a comment. +type FeedbackValue struct { + Reasons []string + Comment string +} + +// FeedbackFormOptions configure a FeedbackForm. +type FeedbackFormOptions struct { + Rating FeedbackRating + // Reasons replaces the built-in reasons for the rating. + Reasons []string + // Submitting shows the caller sending the feedback and blocks the form. + Submitting bool + Disabled bool +} + +// FeedbackFormView is a built FeedbackForm and this frame's outcome. +type FeedbackFormView struct { + Element *ui.Element + Submitted, Cancelled bool +} + +var feedbackReasons = [2][]string{ + {"feedback_form.up.accurate", "feedback_form.up.helpful", "feedback_form.up.clear"}, + {"feedback_form.down.wrong", "feedback_form.down.unhelpful", "feedback_form.down.unsafe", "feedback_form.down.style"}, +} + +// FeedbackForm asks why after a thumbs up or down: reason chips and a comment, then Submit or Cancel. +func FeedbackForm(c *ui.Context, value *FeedbackValue, opts FeedbackFormOptions) FeedbackFormView { + if value == nil { + panic("mujica: FeedbackForm needs a value") + } + if opts.Rating != FeedbackUp && opts.Rating != FeedbackDown { + panic("mujica: FeedbackForm Rating out of range") + } + reasons := opts.Reasons + if reasons == nil { + for _, key := range feedbackReasons[opts.Rating] { + reasons = append(reasons, msg(c, key)) + } + } + k := Tokens(c) + d := Density(c) + blocked := opts.Disabled || opts.Submitting + col := ui.Column(c).Gap(d.Unit()*3).Padding(d.Unit()*4).Background(k.Surface).Border(theme.BorderWidth, k.Border). + Radius(theme.CardRadius).Role(ui.RoleGroup).Disabled(blocked) + v := FeedbackFormView{Element: col} + title := map[FeedbackRating]string{FeedbackUp: "feedback_form.up.title", FeedbackDown: "feedback_form.down.title"}[opts.Rating] + col.Label(msg(c, title)) + col.Children(func() { + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, msg(c, title)).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).TextColor(k.Text) + }) + ui.Row(c).Wrap().Gap(d.Unit() * 2).FocusGroup(ui.Horizontal).Children(func() { + for _, r := range reasons { + on := slices.Contains(value.Reasons, r) + was := on + Toggle(c, &on, r, ToggleOptions{Disabled: blocked}) + if on != was && !col.IsDisabled() { + if on { + value.Reasons = append(slices.Clone(value.Reasons), r) + } else { + value.Reasons = slices.DeleteFunc(slices.Clone(value.Reasons), func(x string) bool { return x == r }) + } + } + } + }) + TextArea(c, &value.Comment, TextAreaOptions{Placeholder: msg(c, "feedback_form.comment"), Label: msg(c, "feedback_form.comment"), + MinHeight: 72, Disabled: blocked}) + ui.Row(c).Gap(d.Unit() * 2).Justify(ui.End).Children(func() { + v.Cancelled = Button(c, msg(c, "feedback_form.cancel"), ButtonOptions{Variant: Ghost, Disabled: blocked}).Clicked() + v.Submitted = Button(c, msg(c, "feedback_form.submit"), ButtonOptions{Icon: icons.Must("check"), Loading: opts.Submitting, Disabled: opts.Disabled}).Clicked() + }) + }) + if !col.IsDisabled() && col.Shortcut(0, ui.KeyEscape) { + v.Cancelled = true + } + if col.IsDisabled() { + v.Submitted, v.Cancelled = false, false + } + switch { + case v.Submitted: + slog.Debug("mujica: feedback_form submit", "rating", opts.Rating, "reasons", len(value.Reasons)) + case v.Cancelled: + slog.Debug("mujica: feedback_form cancel") + } + return v +} diff --git a/messages_chatsession.go b/messages_chatsession.go new file mode 100644 index 0000000..6151bf6 --- /dev/null +++ b/messages_chatsession.go @@ -0,0 +1,124 @@ +package mujica + +func init() { + addMessages(map[string][2]string{ + "conversation_list.pinned": {"Pinned", "置顶"}, + "conversation_list.today": {"Today", "今天"}, + "conversation_list.yesterday": {"Yesterday", "昨天"}, + "conversation_list.week": {"Previous 7 days", "7 天内"}, + "conversation_list.older": {"Older", "更早"}, + "conversation_list.untitled": {"New conversation", "新对话"}, + + "conversation_item.actions": {"Conversation actions", "对话操作"}, + "conversation_item.rename": {"Rename", "重命名"}, + "conversation_item.pin": {"Pin", "置顶"}, + "conversation_item.unpin": {"Unpin", "取消置顶"}, + "conversation_item.pinned": {"Pinned", "已置顶"}, + "conversation_item.export": {"Export", "导出"}, + "conversation_item.delete": {"Delete", "删除"}, + + "conversation_search.searching": {"Searching", "正在搜索"}, + "conversation_search.no_results": {"No conversations match", "没有匹配的对话"}, + "conversation_search.results": {"Search results", "搜索结果"}, + "conversation_search.retry": {"Retry", "重试"}, + + "project_list.expanded": {"expanded", "已展开"}, + "project_list.collapsed": {"collapsed", "已收起"}, + "project_list.expand": {"Show conversations in %s", "展开 %s 的对话"}, + "project_list.collapse": {"Hide conversations in %s", "收起 %s 的对话"}, + "project_list.move_to": {"Move %s", "移动 %s"}, + "project_list.move_group": {"Move to project", "移入项目"}, + + "project_knowledge_panel.title": {"Project knowledge", "项目知识"}, + "project_knowledge_panel.add": {"Add files", "添加文件"}, + "project_knowledge_panel.empty": {"No files yet", "暂无文件"}, + "project_knowledge_panel.tokens": {"%d tokens", "%d tokens"}, + "project_knowledge_panel.remove": {"Remove %s", "移除 %s"}, + "project_knowledge_panel.usage": {"%d of %d tokens (%d%%)", "已用 %d / %d tokens(%d%%)"}, + "project_knowledge_panel.near": {"Nearly full", "即将用满"}, + "project_knowledge_panel.over": {"Over capacity", "超出容量"}, + + "prompt_library.all": {"All", "全部"}, + "prompt_library.search": {"Search prompts", "搜索提示"}, + "prompt_library.no_results": {"No prompts match", "没有匹配的提示"}, + "prompt_library.pick": {"Choose a prompt to preview", "选择一个提示以预览"}, + "prompt_library.insert": {"Insert", "插入"}, + + "feedback_form.up.title": {"What did you like?", "哪里令你满意?"}, + "feedback_form.down.title": {"What went wrong?", "哪里出了问题?"}, + "feedback_form.up.accurate": {"Accurate", "准确"}, + "feedback_form.up.helpful": {"Helpful", "有帮助"}, + "feedback_form.up.clear": {"Clear", "清晰"}, + "feedback_form.down.wrong": {"Incorrect", "内容错误"}, + "feedback_form.down.unhelpful": {"Not helpful", "没有帮助"}, + "feedback_form.down.unsafe": {"Harmful or unsafe", "有害或不安全"}, + "feedback_form.down.style": {"Too long or unclear", "冗长或不清楚"}, + "feedback_form.comment": {"Tell us more (optional)", "补充说明(可选)"}, + "feedback_form.submit": {"Submit", "提交"}, + "feedback_form.cancel": {"Cancel", "取消"}, + + "date_separator.today": {"Today", "今天"}, + "date_separator.yesterday": {"Yesterday", "昨天"}, + "date_separator.short": {"%s %d", "%s%d日"}, + + "thinking_indicator.thinking": {"Thinking", "正在思考"}, + + "stop_generating_button.stop": {"Stop generating", "停止生成"}, + + "system_prompt_editor.title": {"System prompt", "系统提示"}, + "system_prompt_editor.unsaved": {"Unsaved changes", "未保存"}, + "system_prompt_editor.count": {"%d characters", "%d 字"}, + "system_prompt_editor.count_of": {"%d / %d characters", "%d / %d 字"}, + "system_prompt_editor.restore": {"Restore default", "恢复默认"}, + "system_prompt_editor.save": {"Save", "保存"}, + + "cost_estimator.kind": {"Kind", "类别"}, + "cost_estimator.tokens": {"Tokens", "Tokens"}, + "cost_estimator.cost": {"Cost", "费用"}, + "cost_estimator.input": {"Input", "输入"}, + "cost_estimator.output": {"Output", "输出"}, + "cost_estimator.total": {"Total", "合计"}, + "cost_estimator.total_label": {"Estimated cost %s", "预计费用 %s"}, + "cost_estimator.rates": {"Rates per million tokens: input %s, output %s", "每百万 tokens 单价:输入 %s,输出 %s"}, + + "shared_conversation_view.shared_by": {"Shared by %s", "分享者:%s"}, + "shared_conversation_view.someone": {"someone", "未知"}, + "shared_conversation_view.read_only": {"Read only", "只读"}, + "shared_conversation_view.copy_link": {"Copy link", "复制链接"}, + "shared_conversation_view.user": {"You", "你"}, + "shared_conversation_view.assistant": {"Assistant", "助手"}, + "shared_conversation_view.system": {"System", "系统"}, + + "conversation_export.format": {"Format", "格式"}, + "conversation_export.text": {"Plain text", "纯文本"}, + "conversation_export.range": {"Messages", "消息范围"}, + "conversation_export.all": {"All (%d)", "全部(%d)"}, + "conversation_export.last": {"Last", "最近"}, + "conversation_export.selected": {"Selected (%d)", "已选(%d)"}, + "conversation_export.preview": {"Preview", "预览"}, + "conversation_export.export": {"Export", "导出"}, + + "regenerate_menu.regenerate": {"Regenerate", "重新生成"}, + "regenerate_menu.again": {"Try again", "重试"}, + "regenerate_menu.model": {"Try another model", "换模型重试"}, + "regenerate_menu.variants": {"Rewrite", "改写"}, + "regenerate_menu.longer": {"Longer", "更长"}, + "regenerate_menu.shorter": {"Shorter", "更短"}, + "regenerate_menu.simpler": {"Simpler", "更简单"}, + "regenerate_menu.detailed": {"More detailed", "更详细"}, + + "artifact_card.code": {"Code", "代码"}, + "artifact_card.document": {"Document", "文档"}, + "artifact_card.web": {"Web page", "网页"}, + "artifact_card.open": {"Open", "打开"}, + "artifact_card.writing": {"Writing", "正在生成"}, + + "chat_empty_state.new.title": {"Start a conversation", "开始新对话"}, + "chat_empty_state.new.description": {"Ask a question or pick a suggestion.", "提出问题,或选择一个建议。"}, + "chat_empty_state.new.action": {"New conversation", "新建对话"}, + "chat_empty_state.no_results.action": {"Clear search", "清除搜索"}, + "chat_empty_state.offline.title": {"You are offline", "当前离线"}, + "chat_empty_state.offline.description": {"Messages will send when the connection returns.", "恢复连接后即可发送消息。"}, + "chat_empty_state.offline.action": {"Retry", "重试"}, + }) +} diff --git a/project_knowledge_panel.go b/project_knowledge_panel.go new file mode 100644 index 0000000..8c9208b --- /dev/null +++ b/project_knowledge_panel.go @@ -0,0 +1,122 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// KnowledgeFile is a file in a project's knowledge, sized in tokens by the caller. +type KnowledgeFile struct { + ID, Name string + Tokens int +} + +// ProjectKnowledgePanelOptions configure a ProjectKnowledgePanel. Capacity is required. +type ProjectKnowledgePanelOptions struct { + // Capacity is how many tokens the project's knowledge holds. + Capacity int + // Title replaces the built-in "Project knowledge". + Title string + Disabled bool +} + +// ProjectKnowledgePanelView is a built panel and what the user asked for. +type ProjectKnowledgePanelView struct { + Element *ui.Element + // Add asks the caller to pick files to add. + Add bool + // Removed is the ID of a file to remove, empty for none. + Removed string +} + +// ProjectKnowledgePanel lists a project's knowledge files with add, remove and how full it is. +func ProjectKnowledgePanel(c *ui.Context, files []KnowledgeFile, opts ProjectKnowledgePanelOptions) ProjectKnowledgePanelView { + if opts.Capacity <= 0 { + panic("mujica: ProjectKnowledgePanel needs a positive Capacity") + } + used := 0 + for _, f := range files { + if f.Tokens < 0 { + panic("mujica: KnowledgeFile with negative Tokens") + } + used += f.Tokens + } + k := Tokens(c) + d := Density(c) + col := ui.Column(c).Gap(d.Unit()*2).Padding(d.Unit()*3).Background(k.Surface).Border(theme.BorderWidth, k.Border). + Radius(theme.CardRadius).Disabled(opts.Disabled) + v := ProjectKnowledgePanelView{Element: col} + col.Children(func() { + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + title := opts.Title + if title == "" { + title = msg(c, "project_knowledge_panel.title") + } + ui.Text(c, title).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).TextColor(k.Text).Grow(1) + v.Add = Button(c, msg(c, "project_knowledge_panel.add"), ButtonOptions{Variant: Secondary, Icon: icons.Must("plus"), Disabled: opts.Disabled}).Clicked() + }) + ui.Box(c).FillWidth().Height(9).Draw(func(p *ui.Painter, r ui.Rect) { + internal.RuleDiamond(p, r, 6, 5, k.Ornament) + }) + projectKnowledgeMeter(c, k, used, opts.Capacity) + if len(files) == 0 { + ui.Text(c, msg(c, "project_knowledge_panel.empty")).TextColor(k.TextMuted).Padding(d.Unit()*2, 0) + return + } + ui.Column(c).Gap(2).FocusGroup(ui.Vertical).Children(func() { + for _, f := range files { + ui.Row(c).Key(f.ID).MinHeight(d.ControlHeight()).Gap(d.Unit()*2).AlignItems(ui.Center).Padding(0, d.Unit()).Children(func() { + ui.Icon(c, icons.Must("file-text")).Size(16, 16).TextColor(k.TextMuted) + ui.Text(c, f.Name).SingleLine().Grow(1).MinWidth(0) + ui.Text(c, fmt.Sprintf(msg(c, "project_knowledge_panel.tokens"), f.Tokens)). + FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + x := iconAction(c, icons.Must("x"), fmt.Sprintf(msg(c, "project_knowledge_panel.remove"), f.Name)) + if x.Clicked() && !x.IsDisabled() { + v.Removed = f.ID + } + }) + } + }) + }) + if v.Add || v.Removed != "" { + slog.Debug("mujica: project_knowledge_panel action", "add", v.Add, "remove", v.Removed) + } + return v +} + +// projectKnowledgeMeter shows used of capacity; near and over the limit add a word and an icon, not only color. +func projectKnowledgeMeter(c *ui.Context, k theme.Tokens, used, capacity int) { + d := Density(c) + frac := float64(used) / float64(capacity) + ink, note, icon := k.AccentText, "", "" + switch { + case used > capacity: + ink, note, icon = k.Danger, msg(c, "project_knowledge_panel.over"), "circle-alert" + case frac >= 0.8: + ink, note, icon = k.Warning, msg(c, "project_knowledge_panel.near"), "triangle-alert" + } + pct := int(frac * 100) + label := fmt.Sprintf(msg(c, "project_knowledge_panel.usage"), used, capacity, pct) + ui.Column(c).Gap(d.Unit()).Role(ui.RoleMeter).Label(label).Children(func() { + ui.Box(c).FillWidth().Height(6).Draw(func(p *ui.Painter, r ui.Rect) { + p.Fill(r, k.Border, 3) + p.Fill(ui.Rect{X: r.X, Y: r.Y, W: r.W * float32(min(frac, 1)), H: r.H}, ink, 3) + }) + ui.Row(c).Gap(d.Unit()).AlignItems(ui.Center).Children(func() { + if icon != "" { + ui.Icon(c, icons.Must(icon)).Size(14, 14).TextColor(ink) + } + t := ui.Text(c, label).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + if note != "" { + t.TextColor(ink) + ui.Text(c, note).FontSize(FontSize(c, theme.CaptionSize)).TextColor(ink).Role(ui.RoleStatus) + } + }) + }) +} diff --git a/project_list.go b/project_list.go new file mode 100644 index 0000000..06e7b56 --- /dev/null +++ b/project_list.go @@ -0,0 +1,212 @@ +package mujica + +import ( + "cmp" + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// ChatProject is a project that holds conversations; Folder groups projects, empty for none. +type ChatProject struct { + ID, Name, Folder string +} + +// ProjectListOptions configure a ProjectList. +type ProjectListOptions struct { + Label string + Disabled bool +} + +// ProjectListState is the chosen project and which folders and projects are open. +type ProjectListState struct { + // Selected is the chosen project's ID; empty for none. + Selected string + closed map[string]bool + open map[string]bool +} + +// ProjectListView is a built ProjectList and this frame's events. +type ProjectListView struct { + Element *ui.Element + // Changed reports a newly chosen project, in State.Selected. + Changed bool + // Opened is a conversation the user opened, empty for none. + Opened string + // Moved asks the caller to move conversation MoveID into project MoveTo. + Moved bool + MoveID, MoveTo string +} + +// ProjectList shows folders of projects and their conversations; drop a ConversationDrag on a project, or use Move to, to file it. +func ProjectList(c *ui.Context, s *ProjectListState, projects []ChatProject, conversations func(projectID string) []ChatConversation, opts ProjectListOptions) ProjectListView { + if s == nil || conversations == nil { + panic("mujica: ProjectList needs a state and conversations") + } + if s.closed == nil { + s.closed, s.open = map[string]bool{}, map[string]bool{} + } + d := Density(c) + col := ui.Column(c).Gap(2).FocusGroup(ui.Vertical).Role(ui.RoleTree).Label(opts.Label).Disabled(opts.Disabled) + v := ProjectListView{Element: col} + col.Children(func() { + seen := map[string]bool{} + for _, p := range projects { + if p.Folder == "" || seen[p.Folder] { + continue + } + seen[p.Folder] = true + open := !s.closed[p.Folder] + ui.Column(c).Key("folder:" + p.Folder).Children(func() { projectListFolder(c, p.Folder, &open) }) + s.closed[p.Folder] = !open + if !open { + continue + } + for _, q := range projects { + if q.Folder == p.Folder { + projectListProject(c, s, q, projects, conversations, d.Unit()*6, &v) + } + } + } + for _, p := range projects { + if p.Folder == "" { + projectListProject(c, s, p, projects, conversations, 0, &v) + } + } + }) + if col.IsDisabled() { + v.Changed, v.Opened, v.Moved = false, "", false + } + switch { + case v.Moved: + slog.Debug("mujica: project_list move", "conversation", v.MoveID, "project", v.MoveTo) + case v.Changed: + slog.Debug("mujica: project_list select", "project", s.Selected) + } + return v +} + +// projectListFolder is a folder heading on a CollapsibleBase trigger, which reports expanded. +func projectListFolder(c *ui.Context, title string, open *bool) *ui.Element { + k := Tokens(c) + d := Density(c) + parts := ui.CollapsibleBase(c, open) + tr := parts.Trigger.MinHeight(d.ControlHeight()).Padding(0, d.Unit()*2).Gap(d.Unit() * 2).AlignItems(ui.Center). + Radius(theme.ControlRadius).Label(title) + internal.Ring(tr, k.Focus, theme.ControlRadius) + if tr.Hovered() { + tr.Background(k.SurfaceHover) + } + chevron := "chevron-right" + if *open { + chevron = "chevron-down" + } + tr.Children(func() { + ui.Icon(c, icons.Must(chevron)).Size(14, 14).TextColor(k.TextMuted) + ui.Icon(c, icons.Must("folder")).Size(16, 16).TextColor(k.Ornament.Mix(k.Text, 0.3)) + ui.Text(c, title).Font(theme.SerifFont).SingleLine() + }) + return tr +} + +func projectListProject(c *ui.Context, s *ProjectListState, p ChatProject, all []ChatProject, conversations func(string) []ChatConversation, indent float32, v *ProjectListView) { + k := Tokens(c) + d := Density(c) + convs := conversations(p.ID) + chosen := s.Selected == p.ID + var b *ui.Element + line := ui.Row(c).Key("project:" + p.ID).AlignItems(ui.Center) + line.Children(func() { b = ui.ButtonBase(c).Grow(1).MinWidth(0).MinHeight(d.ControlHeight()) }) + b.Padding(0, d.Unit()*2, 0, d.Unit()*2+indent).Padding(0, d.Unit()*2, 0, d.Unit()*2+indent). + Gap(d.Unit() * 2).Justify(ui.Start).Radius(theme.ControlRadius).Role(ui.RoleTreeItem).Label(p.Name).Selected(chosen) + b.Background(ui.Transparent).TextColor(k.Text) + internal.Ring(b, k.Focus, theme.ControlRadius) + _, over := ui.DragOver[ConversationDrag](b) + switch { + case chosen: + b.Background(k.Selection).TextColor(k.AccentText) + case b.Hovered(): + b.Background(k.SurfaceHover) + } + if over { + b.DrawOver(func(pt *ui.Painter, r ui.Rect) { internal.Frame(pt, r, 1, 5, k.AccentText) }) + } + if drop, ok := ui.Drop[ConversationDrag](b); ok && !b.IsDisabled() { + v.Moved, v.MoveID, v.MoveTo = true, drop.ID, p.ID + } + if b.Clicked() && !chosen { + s.Selected, v.Changed = p.ID, true + } + open := s.open[p.ID] + if !b.IsDisabled() && len(convs) > 0 { + switch { + case b.Shortcut(0, ui.KeyRight): + s.open[p.ID] = true + case b.Shortcut(0, ui.KeyLeft): + s.open[p.ID] = false + } + } + if len(convs) > 0 { + b.Description(msg(c, map[bool]string{true: "project_list.expanded", false: "project_list.collapsed"}[open])) + } + b.Children(func() { + ui.Box(c).Size(8, 8).Shrink(0).Draw(func(pt *ui.Painter, r ui.Rect) { + if chosen { + pt.FillPath(internal.Diamond(r.X+4, r.Y+4, 8), k.AccentText) + } + }) + ui.Text(c, p.Name).SingleLine().Grow(1).MinWidth(0) + ui.Text(c, fmt.Sprint(len(convs))).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + }) + if len(convs) > 0 { + chevron := map[bool]string{true: "chevron-down", false: "chevron-right"}[open] + line.Children(func() { + t := iconAction(c, icons.Must(chevron), fmt.Sprintf(msg(c, map[bool]string{true: "project_list.collapse", false: "project_list.expand"}[open]), p.Name)) + if t.Clicked() && !t.IsDisabled() { + s.open[p.ID] = !open + } + }) + } + if !open { + return + } + for _, conv := range convs { + projectListConversation(c, conv, p, all, indent+d.Unit()*6, v) + } +} + +func projectListConversation(c *ui.Context, conv ChatConversation, home ChatProject, all []ChatProject, indent float32, v *ProjectListView) { + k := Tokens(c) + d := Density(c) + ui.Row(c).Key("conv:" + conv.ID).AlignItems(ui.Center).Children(func() { + b := ui.ButtonBase(c).Grow(1).MinWidth(0).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*2, 0, d.Unit()*2+indent). + Justify(ui.Start).Radius(theme.ControlRadius).Label(conv.Title).Drag(ConversationDrag{ID: conv.ID}) + internal.Ring(b, k.Focus, theme.ControlRadius) + if b.Dragging() { + b.Opacity(0.4) + } + if b.Hovered() { + b.Background(k.SurfaceHover) + } + b.Children(func() { + ui.Text(c, cmp.Or(conv.Title, msg(c, "conversation_list.untitled"))).SingleLine().TextColor(k.TextMuted) + }) + if b.Clicked() { + v.Opened = conv.ID + } + DropdownMenu(c, "", DropdownMenuOptions{Icon: icons.Must("ellipsis"), Label: fmt.Sprintf(msg(c, "project_list.move_to"), conv.Title)}, func(m *PopupMenu) { + m.Group(msg(c, "project_list.move_group"), func() { + for _, p := range all { + if p.ID != home.ID && m.Item(p.Name, PopupMenuItemOptions{}) { + v.Moved, v.MoveID, v.MoveTo = true, conv.ID, p.ID + } + } + }) + }).Shrink(0) + }) +} diff --git a/prompt_library.go b/prompt_library.go new file mode 100644 index 0000000..827f12c --- /dev/null +++ b/prompt_library.go @@ -0,0 +1,218 @@ +package mujica + +import ( + "log/slog" + "regexp" + "slices" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// PromptTemplate is a reusable prompt; {{name}} in Body is a variable to fill before inserting. +type PromptTemplate struct { + ID, Category, Title, Body string +} + +// PromptLibraryOptions configure a PromptLibrary. +type PromptLibraryOptions struct { + Label string + Disabled bool +} + +// PromptLibraryState is the library's category, search, chosen template and variable values. +type PromptLibraryState struct { + // Category filters templates; empty shows all. + Category string + Query string + Selected string + Values map[string]string + shown promptLibraryShown +} + +// promptLibraryShown caches the filtered templates until the data, query or category changes. +type promptLibraryShown struct { + src []PromptTemplate + query, category string + ids []int + cats []string + built bool +} + +// PromptLibraryView is a built PromptLibrary and the text inserted this frame. +type PromptLibraryView struct { + Element *ui.Element + // Inserted is the chosen template with its variables filled, empty for none. + Inserted string +} + +var promptLibraryVar = regexp.MustCompile(`\{\{\s*([A-Za-z0-9_.-]+)\s*\}\}`) + +// PromptLibraryVariables lists a body's {{name}} variables in order, once each. +func PromptLibraryVariables(body string) []string { + var out []string + for _, m := range promptLibraryVar.FindAllStringSubmatch(body, -1) { + if !slices.Contains(out, m[1]) { + out = append(out, m[1]) + } + } + return out +} + +// PromptLibraryFill replaces each {{name}} in body with values[name]. +func PromptLibraryFill(body string, values map[string]string) string { + return promptLibraryVar.ReplaceAllStringFunc(body, func(m string) string { + return values[promptLibraryVar.FindStringSubmatch(m)[1]] + }) +} + +// PromptLibrary browses templates by category and search, previews one, fills its variables and inserts it. +func PromptLibrary(c *ui.Context, s *PromptLibraryState, templates []PromptTemplate, opts PromptLibraryOptions) PromptLibraryView { + if s == nil { + panic("mujica: PromptLibrary needs a state") + } + if s.Values == nil { + s.Values = map[string]string{} + } + k := Tokens(c) + d := Density(c) + promptLibraryFilter(&s.shown, templates, s.Query, s.Category) + row := ui.Row(c).Gap(d.Unit() * 4).AlignItems(ui.Stretch).Role(ui.RoleGroup).Label(opts.Label).Disabled(opts.Disabled) + v := PromptLibraryView{Element: row} + row.Children(func() { + ui.Column(c).Width(150).Shrink(0).Gap(2).FocusGroup(ui.Vertical).Children(func() { + promptLibraryCategory(c, k, s, "", msg(c, "prompt_library.all")) + for _, cat := range s.shown.cats { + promptLibraryCategory(c, k, s, cat, cat) + } + }) + ui.Column(c).Width(240).Shrink(0).Gap(d.Unit() * 2).Children(func() { + SearchInput(c, &s.Query, SearchInputOptions{Placeholder: msg(c, "prompt_library.search"), Disabled: opts.Disabled}) + ui.Scroll(c).MaxHeight(320).Children(func() { + ui.Column(c).Gap(2).FocusGroup(ui.Vertical).Children(func() { + if len(s.shown.ids) == 0 { + ui.Text(c, msg(c, "prompt_library.no_results")).TextColor(k.TextMuted).Padding(d.Unit() * 2) + } + for _, i := range s.shown.ids { + t := templates[i] + if selectableRow(c, k, t.ID, t.Title, s.Selected == t.ID) && s.Selected != t.ID { + s.Selected = t.ID + slog.Debug("mujica: prompt_library select", "id", t.ID) + } + } + }) + }) + }) + ui.Column(c).Grow(1).MinWidth(200).Gap(d.Unit() * 2).Children(func() { + i := slices.IndexFunc(templates, func(t PromptTemplate) bool { return t.ID == s.Selected }) + if i < 0 { + ui.Text(c, msg(c, "prompt_library.pick")).TextColor(k.TextMuted) + return + } + v.Inserted = promptLibraryPreview(c, k, s, templates[i], opts.Disabled) + }) + }) + if v.Inserted != "" { + slog.Debug("mujica: prompt_library insert", "id", s.Selected) + } + return v +} + +func promptLibraryFilter(sh *promptLibraryShown, templates []PromptTemplate, query, category string) { + same := sh.built && sh.query == query && sh.category == category && len(sh.src) == len(templates) && + (len(templates) == 0 || &sh.src[0] == &templates[0]) + if same { + return + } + *sh = promptLibraryShown{src: templates, query: query, category: category, built: true} + q := strings.ToLower(strings.TrimSpace(query)) + for i, t := range templates { + if t.ID == "" || t.Title == "" { + panic("mujica: PromptTemplate needs an ID and a Title") + } + if t.Category != "" && !slices.Contains(sh.cats, t.Category) { + sh.cats = append(sh.cats, t.Category) + } + if category != "" && t.Category != category { + continue + } + if q == "" || strings.Contains(strings.ToLower(t.Title+"\n"+t.Body), q) { + sh.ids = append(sh.ids, i) + } + } +} + +func promptLibraryCategory(c *ui.Context, k theme.Tokens, s *PromptLibraryState, cat, label string) { + if selectableRow(c, k, "cat:"+cat, label, s.Category == cat) && s.Category != cat { + s.Category = cat + } +} + +// selectableRow is a focusable row chosen by click, Enter or Space, marked with Selection and a diamond. +func selectableRow(c *ui.Context, k theme.Tokens, key, label string, chosen bool) bool { + d := Density(c) + b := ui.ButtonBase(c).Key(key).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*2).Gap(d.Unit() * 2).Justify(ui.Start). + Radius(theme.ControlRadius).Label(label).Selected(chosen) + b.Background(ui.Transparent).TextColor(k.Text) + internal.Ring(b, k.Focus, theme.ControlRadius) + switch { + case chosen: + b.Background(k.Selection).TextColor(k.AccentText) + case b.Hovered(): + b.Background(k.SurfaceHover) + } + b.Children(func() { + ui.Box(c).Size(8, 8).Shrink(0).Draw(func(p *ui.Painter, r ui.Rect) { + if chosen { + p.FillPath(internal.Diamond(r.X+4, r.Y+4, 8), k.AccentText) + } + }) + ui.Text(c, label).SingleLine() + }) + return b.Clicked() && !b.IsDisabled() +} + +// promptLibraryPreview shows the filled body, a field per variable, and Insert once all are filled. +func promptLibraryPreview(c *ui.Context, k theme.Tokens, s *PromptLibraryState, t PromptTemplate, disabled bool) string { + d := Density(c) + vars := PromptLibraryVariables(t.Body) + ui.Text(c, t.Title).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).TextColor(k.Text) + missing := false + var spans []ui.Span + at := 0 + for _, m := range promptLibraryVar.FindAllStringSubmatchIndex(t.Body, -1) { + spans = append(spans, ui.Span{Text: t.Body[at:m[0]]}) + name := t.Body[m[2]:m[3]] + if val := s.Values[name]; val != "" { + spans = append(spans, ui.Span{Text: val, Weight: 600, Color: k.AccentText}) + } else { + missing = true + spans = append(spans, ui.Span{Text: "[" + name + "]", Background: k.Selection, Color: k.AccentText, Underline: true}) + } + at = m[1] + } + spans = append(spans, ui.Span{Text: t.Body[at:]}) + ui.Column(c).Padding(d.Unit()*3).Background(k.Background).Border(theme.BorderWidth, k.Border).Radius(theme.ControlRadius). + Children(func() { ui.RichText(c, spans...).Selectable() }) + for _, name := range vars { + val := s.Values[name] + ui.Column(c).Key("var:" + name).Children(func() { + FormField(c, name, FormFieldOptions{Required: true}, func() *ui.Element { + r := TextInput(c, &val, TextInputOptions{Label: name, Disabled: disabled}) + if r.Changed() { + s.Values[name] = val + } + return r.Element + }) + }) + } + insert := Button(c, msg(c, "prompt_library.insert"), ButtonOptions{Icon: icons.Must("plus"), Disabled: missing || disabled}).Clicked() + if insert && !missing { + return PromptLibraryFill(t.Body, s.Values) + } + return "" +} diff --git a/regenerate_menu.go b/regenerate_menu.go new file mode 100644 index 0000000..d122e0e --- /dev/null +++ b/regenerate_menu.go @@ -0,0 +1,90 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" +) + +// RegenerateKind is what a RegenerateMenu choice asks for. +type RegenerateKind int + +const ( + // RegenerateAgain retries with the same model. + RegenerateAgain RegenerateKind = iota + // RegenerateModel retries with Choice.Model. + RegenerateModel + // RegenerateVariant retries asking for Choice.Variant, such as longer or shorter. + RegenerateVariant +) + +// RegenerateChoice is the retry the user picked. +type RegenerateChoice struct { + Kind RegenerateKind + Model string + Variant string +} + +// RegenerateMenuOptions configure a RegenerateMenu. +type RegenerateMenuOptions struct { + // Models lists models to retry with; Current is marked and left out. + Models []string + Current string + // Variants replaces the built-in Longer, Shorter, Simpler and More detailed. + Variants []string + Disabled bool +} + +// RegenerateMenuView is a built menu and the retry chosen this frame. +type RegenerateMenuView struct { + Element *ui.Element + Chosen bool + Choice RegenerateChoice +} + +// RegenerateMenu offers regenerate, retry with another model, and variants such as longer or shorter. +func RegenerateMenu(c *ui.Context, opts RegenerateMenuOptions) RegenerateMenuView { + variants := opts.Variants + if variants == nil { + for _, key := range []string{"regenerate_menu.longer", "regenerate_menu.shorter", "regenerate_menu.simpler", "regenerate_menu.detailed"} { + variants = append(variants, msg(c, key)) + } + } + var v RegenerateMenuView + pick := func(ch RegenerateChoice) { v.Chosen, v.Choice = true, ch } + v.Element = DropdownMenu(c, msg(c, "regenerate_menu.regenerate"), DropdownMenuOptions{Icon: icons.Must("refresh-cw"), Disabled: opts.Disabled}, func(m *PopupMenu) { + if m.Item(msg(c, "regenerate_menu.again"), PopupMenuItemOptions{}) { + pick(RegenerateChoice{Kind: RegenerateAgain}) + } + others := 0 + for _, model := range opts.Models { + if model != opts.Current { + others++ + } + } + m.Submenu(msg(c, "regenerate_menu.model"), PopupMenuItemOptions{Disabled: others == 0}, func(m *PopupMenu) { + for _, model := range opts.Models { + if model != opts.Current && m.Item(model, PopupMenuItemOptions{}) { + pick(RegenerateChoice{Kind: RegenerateModel, Model: model}) + } + } + }) + m.Separator() + m.Group(msg(c, "regenerate_menu.variants"), func() { + for _, variant := range variants { + if m.Item(variant, PopupMenuItemOptions{}) { + pick(RegenerateChoice{Kind: RegenerateVariant, Variant: variant}) + } + } + }) + }) + if v.Element.IsDisabled() { + v.Chosen = false + } + if v.Chosen { + slog.Debug("mujica: regenerate_menu choose", "kind", v.Choice.Kind, "model", v.Choice.Model, "variant", v.Choice.Variant) + } + return v +} diff --git a/shared_conversation_view.go b/shared_conversation_view.go new file mode 100644 index 0000000..00676df --- /dev/null +++ b/shared_conversation_view.go @@ -0,0 +1,107 @@ +package mujica + +import ( + "cmp" + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// SessionRole is who wrote a message. The zero value is SessionUser. +type SessionRole int + +const ( + SessionUser SessionRole = iota + SessionAssistant + SessionSystem +) + +// SessionMessage is one message of a saved conversation, as plain text. +type SessionMessage struct { + Role SessionRole + // Author names the writer; empty uses the role's name. + Author string + Text string + Time time.Time +} + +// SharedConversationViewOptions configure a SharedConversationView. +type SharedConversationViewOptions struct { + Title string + SharedBy string + SharedAt time.Time + Disabled bool +} + +// SharedConversationView shows a shared conversation read-only, with who shared it and when; it reports Copy link. +func SharedConversationView(c *ui.Context, messages []SessionMessage, opts SharedConversationViewOptions) ChoiceResult { + if opts.Title == "" { + panic("mujica: SharedConversationView needs a Title") + } + k := Tokens(c) + d := Density(c) + col := ui.Column(c).Grow(1).MinHeight(0).Gap(d.Unit() * 3).Disabled(opts.Disabled) + rows := *ui.Local(col, sharedConversationKey{}, func() *ui.ListState { return &ui.ListState{} }) + copied := false + col.Children(func() { + ui.Row(c).Gap(d.Unit() * 3).AlignItems(ui.Center).Children(func() { + ui.Column(c).Grow(1).Gap(2).Children(func() { + ui.Text(c, opts.Title).Font(theme.SerifFont).FontSize(FontSize(c, theme.H2Size)).TextColor(k.Text) + by := fmt.Sprintf(msg(c, "shared_conversation_view.shared_by"), cmp.Or(opts.SharedBy, msg(c, "shared_conversation_view.someone"))) + if !opts.SharedAt.IsZero() { + by += " · " + dateSeparatorLabel(c, DateOf(opts.SharedAt), DateOf(c.Now())) + } + ui.Text(c, by).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + }) + ui.Row(c).Gap(d.Unit()).AlignItems(ui.Center).Children(func() { + ui.Icon(c, icons.Must("lock")).Size(14, 14).TextColor(k.TextMuted) + ui.Text(c, msg(c, "shared_conversation_view.read_only")).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + }) + copied = Button(c, msg(c, "shared_conversation_view.copy_link"), ButtonOptions{Variant: Secondary, Icon: icons.Must("copy"), + Disabled: opts.Disabled}).Clicked() + }) + ui.Box(c).FillWidth().Height(9).Draw(func(p *ui.Painter, r ui.Rect) { internal.RuleDiamond(p, r, 6, 5, k.Ornament) }) + rows.Key = func(i int) any { return i } + ui.List(c, rows, len(messages), func(i int) { sessionMessageView(c, k, messages[i]) }).Grow(1).MinHeight(0).Gap(d.Unit() * 3) + }) + if copied { + slog.Debug("mujica: shared_conversation_view copy_link") + } + return ChoiceResult{Element: col, changed: copied} +} + +type sharedConversationKey struct{} + +// sessionMessageView is one read-only message: author, time and selectable plain text. +func sessionMessageView(c *ui.Context, k theme.Tokens, m SessionMessage) { + d := Density(c) + if m.Role < SessionUser || m.Role > SessionSystem { + panic("mujica: SessionMessage Role out of range") + } + author := cmp.Or(m.Author, msg(c, sessionRoleKeys[m.Role])) + box := ui.Column(c).Gap(d.Unit()).Padding(d.Unit()*2, d.Unit()*3).Radius(theme.CardRadius) + if m.Role == SessionUser { + box.Background(k.Background).Border(theme.BorderWidth, k.Border) + } + box.Children(func() { + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, author).Bold().TextColor(k.Text) + if !m.Time.IsZero() { + ui.Text(c, m.Time.Format("15:04")).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + } + }) + // Plain text: Markdown is not rendered here. + Text(c, m.Text, TextOptions{Selectable: true}) + }) +} + +var sessionRoleKeys = map[SessionRole]string{ + SessionUser: "shared_conversation_view.user", SessionAssistant: "shared_conversation_view.assistant", + SessionSystem: "shared_conversation_view.system", +} diff --git a/stop_generating_button.go b/stop_generating_button.go new file mode 100644 index 0000000..c63739c --- /dev/null +++ b/stop_generating_button.go @@ -0,0 +1,56 @@ +package mujica + +import ( + "log/slog" + "runtime" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// StopGeneratingButtonOptions configure a StopGeneratingButton. +type StopGeneratingButtonOptions struct { + // Generating shows the button; it hides once generation ends. + Generating bool + Disabled bool +} + +// StopGeneratingButton asks to stop a reply while one is generating; Cmd+. (Ctrl+. elsewhere) does too. +func StopGeneratingButton(c *ui.Context, opts StopGeneratingButtonOptions) ChoiceResult { + if !opts.Generating { + return ChoiceResult{} + } + k := Tokens(c) + d := Density(c) + mods := ui.Ctrl + if runtime.GOOS == "darwin" { + mods = ui.Cmd + } + var b *ui.Element + wrap := ui.Row(c).Shrink(0).Disabled(opts.Disabled) + wrap.Children(func() { + b = ui.ButtonBase(c).MinHeight(max(theme.MinHitSize, d.ControlHeight()-4)).Padding(0, d.Unit()*3).Gap(d.Unit()*2). + Radius(theme.ControlRadius).Background(k.Surface).Border(theme.BorderWidth, k.ControlBorder).Label(msg(c, "stop_generating_button.stop")) + }) + internal.Ring(b, k.Focus, theme.ControlRadius) + if b.Hovered() { + b.Background(k.SurfaceHover) + } + b.Transition(colorFade) + b.Children(func() { + ui.Box(c).Size(10, 10).Shrink(0).Background(k.Text).Radius(1) + ui.Text(c, msg(c, "stop_generating_button.stop")).SingleLine() + Kbd(c, "Mod", ".") + }) + stop := b.Clicked() + if c.Shortcut(mods, ui.KeyPeriod) { + stop = true + } + stop = stop && !b.IsDisabled() + if stop { + slog.Debug("mujica: stop_generating_button stop") + } + return ChoiceResult{Element: b, changed: stop} +} diff --git a/suggestion_chips.go b/suggestion_chips.go new file mode 100644 index 0000000..0b4fcc7 --- /dev/null +++ b/suggestion_chips.go @@ -0,0 +1,76 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// SuggestionChipsOptions configure SuggestionChips. +type SuggestionChipsOptions struct { + // Send makes a click send the suggestion; by default it fills the input. + Send bool + // Label names the group, such as "Follow-up questions". + Label string + Disabled bool +} + +// SuggestionChipsView is built chips and the suggestion used this frame. +type SuggestionChipsView struct { + Element *ui.Element + // Chosen is the suggestion clicked, empty for none. + Chosen string + // Sent reports that Chosen should be sent now; otherwise it is already in the input. + Sent bool +} + +// SuggestionChips offers starter prompts or follow-ups; a click fills *input, or with Send asks to send. +func SuggestionChips(c *ui.Context, input *string, suggestions []string, opts SuggestionChipsOptions) SuggestionChipsView { + if input == nil { + panic("mujica: SuggestionChips needs an input") + } + k := Tokens(c) + d := Density(c) + row := ui.Row(c).Wrap().Gap(d.Unit() * 2).FocusGroup(ui.Horizontal).Role(ui.RoleGroup).Label(opts.Label).Disabled(opts.Disabled) + v := SuggestionChipsView{Element: row} + icon := icons.Must("chevron-right") + if opts.Send { + icon = icons.Must("arrow-up") + } + row.Children(func() { + for i, s := range suggestions { + if s == "" { + panic("mujica: SuggestionChips with an empty suggestion") + } + b := ui.ButtonBase(c).Key(i).MinHeight(max(theme.MinHitSize, d.ControlHeight()-4)).Padding(0, d.Unit()*3). + Gap(d.Unit()*2).Radius(theme.ControlRadius).Background(k.Surface).Border(theme.BorderWidth, k.ControlBorder).Label(s) + internal.Ring(b, k.Focus, theme.ControlRadius) + switch { + case b.Pressed(): + b.Background(k.Selection) + case b.Hovered(): + b.Background(k.SurfaceHover) + } + b.Transition(colorFade) + b.Children(func() { + ui.Text(c, s).SingleLine() + ui.Icon(c, icon).Size(14, 14).TextColor(k.TextMuted) + }) + if b.Clicked() && !b.IsDisabled() { + v.Chosen = s + } + } + }) + if v.Chosen != "" { + v.Sent = opts.Send + if !opts.Send { + *input = v.Chosen + } + slog.Debug("mujica: suggestion_chips choose", "send", v.Sent) + } + return v +} diff --git a/system_prompt_editor.go b/system_prompt_editor.go new file mode 100644 index 0000000..93a3919 --- /dev/null +++ b/system_prompt_editor.go @@ -0,0 +1,95 @@ +package mujica + +import ( + "fmt" + "log/slog" + "runtime" + "unicode/utf8" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// SystemPromptEditorOptions configure a SystemPromptEditor. +type SystemPromptEditorOptions struct { + // Default is what Restore default puts back. + Default string + // Saved is the text last saved; a different value shows as unsaved. + Saved string + // MaxLength caps the characters; zero is no cap. + MaxLength int + // Saving shows the caller's save in progress and blocks editing. + Saving bool + Disabled bool +} + +// SystemPromptEditorView is a built editor and what the user asked for. +type SystemPromptEditorView struct { + Element *ui.Element + // Save asks the caller to save *value; Restored reports the default was put back. + Save, Restored bool +} + +// SystemPromptEditor edits a system prompt with a character count, restore default, an unsaved mark and Mod+S to save. +func SystemPromptEditor(c *ui.Context, value *string, opts SystemPromptEditorOptions) SystemPromptEditorView { + if value == nil { + panic("mujica: SystemPromptEditor needs a value") + } + if opts.MaxLength < 0 { + panic("mujica: SystemPromptEditor MaxLength is negative") + } + k := Tokens(c) + d := Density(c) + blocked := opts.Disabled || opts.Saving + col := ui.Column(c).Gap(d.Unit() * 2).Disabled(blocked) + v := SystemPromptEditorView{Element: col} + dirty := *value != opts.Saved + col.Children(func() { + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, msg(c, "system_prompt_editor.title")).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).TextColor(k.Text).Grow(1) + if dirty { + ui.Row(c).Gap(d.Unit()).AlignItems(ui.Center).Role(ui.RoleStatus).Children(func() { + ui.Box(c).Size(8, 8).Draw(func(p *ui.Painter, r ui.Rect) { + p.FillPath(internal.Diamond(r.X+4, r.Y+4, 8), k.Warning) + }) + ui.Text(c, msg(c, "system_prompt_editor.unsaved")).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.Warning) + }) + } + }) + TextArea(c, value, TextAreaOptions{Label: msg(c, "system_prompt_editor.title"), MinHeight: 120, MaxHeight: 320, + MaxLength: opts.MaxLength, Disabled: blocked}) + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + n := utf8.RuneCountInString(*value) + count := fmt.Sprintf(msg(c, "system_prompt_editor.count"), n) + if opts.MaxLength > 0 { + count = fmt.Sprintf(msg(c, "system_prompt_editor.count_of"), n, opts.MaxLength) + } + ui.Text(c, count).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Grow(1) + if Button(c, msg(c, "system_prompt_editor.restore"), ButtonOptions{Variant: Ghost, Icon: icons.Must("refresh-cw"), + Disabled: blocked || *value == opts.Default}).Clicked() && !col.IsDisabled() { + *value, v.Restored = opts.Default, true + } + v.Save = Button(c, msg(c, "system_prompt_editor.save"), ButtonOptions{Loading: opts.Saving, Disabled: opts.Disabled || !dirty}).Clicked() + }) + }) + mods := ui.Ctrl + if runtime.GOOS == "darwin" { + mods = ui.Cmd + } + if col.Shortcut(mods, ui.KeyS) && dirty { + v.Save = true + } + if col.IsDisabled() { + v.Save = false + } + switch { + case v.Save: + slog.Debug("mujica: system_prompt_editor save", "len", len(*value)) + case v.Restored: + slog.Debug("mujica: system_prompt_editor restore") + } + return v +} diff --git a/thinking_indicator.go b/thinking_indicator.go new file mode 100644 index 0000000..df72017 --- /dev/null +++ b/thinking_indicator.go @@ -0,0 +1,55 @@ +package mujica + +import ( + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// ThinkingIndicatorOptions configure a ThinkingIndicator. +type ThinkingIndicatorOptions struct { + // Phase is the caller's stage text, such as "Searching the web"; empty uses "Thinking". + Phase string +} + +// ThinkingIndicator shows the assistant is working: three diamonds rising in turn and the phase; still under reduced motion. +func ThinkingIndicator(c *ui.Context, opts ThinkingIndicatorOptions) *ui.Element { + k := Tokens(c) + d := Density(c) + phase := opts.Phase + if phase == "" { + phase = msg(c, "thinking_indicator.thinking") + } + still := c.Preferences().ReduceMotion + row := ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).MinHeight(d.ControlHeight()).Role(ui.RoleStatus).Label(phase) + row.Children(func() { + ui.Box(c).Size(30, 14).Shrink(0).Draw(func(p *ui.Painter, r ui.Rect) { + t := 0.0 + if !still { + t = float64(p.Now().UnixMilli()%1200) / 1200 + p.AnimationFrame() + } + for i := range 3 { + lift := float32(0) + alpha := float32(1) + if !still { + phase := math.Mod(t-float64(i)*0.18+1, 1) + wave := float32(math.Max(0, math.Sin(phase*2*math.Pi))) + lift, alpha = wave*3, 0.45+0.55*wave + } + x := internal.Snap(p, r.X+5+float32(i)*10) + y := internal.Snap(p, r.Y+r.H/2-lift) + p.FillPath(internal.Diamond(x, y, 7), k.AccentText.Alpha(alpha)) + } + }) + text := phase + if still { + text += "…" + } + ui.Text(c, text).FontSize(FontSize(c, theme.BodySize)).TextColor(k.TextMuted).Italic() + }) + return row +} diff --git a/welcome_screen.go b/welcome_screen.go new file mode 100644 index 0000000..fca9d27 --- /dev/null +++ b/welcome_screen.go @@ -0,0 +1,49 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// WelcomeScreenOptions configure a WelcomeScreen. Greeting is required. +type WelcomeScreenOptions struct { + Greeting string + Subtitle string + Cards []CapabilityCard + // Prompts is the slot for starter prompts, such as SuggestionChips. + Prompts func() + Disabled bool +} + +// WelcomeScreen greets a new conversation with capability cards and a starter-prompt slot; it reports a chosen example. +func WelcomeScreen(c *ui.Context, opts WelcomeScreenOptions) CapabilityCardsView { + if opts.Greeting == "" { + panic("mujica: WelcomeScreen needs a Greeting") + } + k := Tokens(c) + d := Density(c) + var v CapabilityCardsView + col := ui.Column(c).FillWidth().MaxWidth(880).AlignSelf(ui.Center).AlignItems(ui.Center).Gap(d.Unit()*4). + Padding(d.Unit()*8, d.Unit()*4).Disabled(opts.Disabled) + col.Children(func() { + ui.Text(c, opts.Greeting).Font(theme.SerifFont).FontSize(FontSize(c, theme.H1Size)).TextColor(k.Text). + TextAlign(ui.Center).Role(ui.RoleText) + ui.Box(c).Width(220).Height(9).Draw(func(p *ui.Painter, r ui.Rect) { + internal.RuleDiamond(p, r, 8, 6, k.Ornament) + }) + if opts.Subtitle != "" { + ui.Text(c, opts.Subtitle).TextColor(k.TextMuted).TextAlign(ui.Center) + } + if len(opts.Cards) > 0 { + v = CapabilityCards(c, opts.Cards, CapabilityCardsOptions{Columns: min(3, len(opts.Cards)), Disabled: opts.Disabled}) + v.Element.FillWidth() + } + if opts.Prompts != nil { + ui.Column(c).FillWidth().AlignItems(ui.Center).Children(opts.Prompts) + } + }) + v.Element = col + return v +} From 85b41f6435a3ccfc862049887d2a223bb8e2cc03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 5 Oct 2026 14:24:42 -0400 Subject: [PATCH 03/13] wip chat sessions 2 --- artifact_card_test.go | 63 ++++ capability_cards_test.go | 73 ++++ chat_empty_state_test.go | 59 +++ chatsession_fixture_test.go | 38 ++ conversation_export_test.go | 95 +++++ conversation_item.go | 16 +- conversation_item_test.go | 118 ++++++ conversation_list.go | 2 +- conversation_list_test.go | 114 ++++++ conversation_search.go | 8 +- conversation_search_test.go | 133 +++++++ cost_estimator_test.go | 59 +++ date_separator_test.go | 65 ++++ docs/components/241-conversation-list.md | 56 +++ docs/components/242-conversation-item.md | 50 +++ docs/components/243-conversation-search.md | 53 +++ docs/components/244-project-list.md | 53 +++ .../components/245-project-knowledge-panel.md | 47 +++ docs/components/246-welcome-screen.md | 46 +++ docs/components/247-suggestion-chips.md | 42 +++ docs/components/248-prompt-library.md | 49 +++ docs/components/249-capability-cards.md | 45 +++ docs/components/250-feedback-form.md | 46 +++ docs/components/251-date-separator.md | 39 ++ docs/components/252-thinking-indicator.md | 39 ++ docs/components/253-stop-generating-button.md | 44 +++ docs/components/254-system-prompt-editor.md | 47 +++ docs/components/255-cost-estimator.md | 42 +++ .../256-shared-conversation-view.md | 48 +++ docs/components/257-conversation-export.md | 48 +++ docs/components/258-regenerate-menu.md | 44 +++ docs/components/259-artifact-card.md | 45 +++ docs/components/260-chat-empty-state.md | 44 +++ example_chatsession_test.go | 231 ++++++++++++ examples/gallery/pages_chatsession.go | 185 +++++++++- examples/gallery/pages_chatsession_demos.go | 249 +++++++++++++ examples/gallery/pages_chatsession_more.go | 341 ++++++++++++++++++ feedback_form_test.go | 75 ++++ messages_chatsession.go | 11 +- project_knowledge_panel_test.go | 110 ++++++ project_list.go | 4 +- project_list_test.go | 138 +++++++ prompt_library_test.go | 105 ++++++ regenerate_menu.go | 1 + regenerate_menu_test.go | 70 ++++ shared_conversation_view_test.go | 70 ++++ stop_generating_button_test.go | 65 ++++ suggestion_chips_test.go | 76 ++++ system_prompt_editor.go | 15 +- system_prompt_editor_test.go | 81 +++++ .../snapshots/darwin/artifact_card-dark.png | Bin 0 -> 16601 bytes .../snapshots/darwin/artifact_card-light.png | Bin 0 -> 16304 bytes .../darwin/capability_cards-dark.png | Bin 0 -> 22459 bytes .../darwin/capability_cards-light.png | Bin 0 -> 21680 bytes .../darwin/chat_empty_state-dark.png | Bin 0 -> 27233 bytes .../darwin/chat_empty_state-light.png | Bin 0 -> 26177 bytes .../darwin/conversation_export-dark.png | Bin 0 -> 39247 bytes .../darwin/conversation_export-light.png | Bin 0 -> 37271 bytes .../darwin/conversation_item-dark.png | Bin 0 -> 10094 bytes .../darwin/conversation_item-light.png | Bin 0 -> 9845 bytes .../darwin/conversation_list-dark.png | Bin 0 -> 2666 bytes .../darwin/conversation_list-light.png | Bin 0 -> 2668 bytes .../darwin/conversation_search-dark.png | Bin 0 -> 13790 bytes .../darwin/conversation_search-light.png | Bin 0 -> 13398 bytes .../snapshots/darwin/cost_estimator-dark.png | Bin 0 -> 15580 bytes .../snapshots/darwin/cost_estimator-light.png | Bin 0 -> 14880 bytes .../snapshots/darwin/date_separator-dark.png | Bin 0 -> 5045 bytes .../snapshots/darwin/date_separator-light.png | Bin 0 -> 4820 bytes .../snapshots/darwin/feedback_form-dark.png | Bin 0 -> 18504 bytes .../snapshots/darwin/feedback_form-light.png | Bin 0 -> 17872 bytes .../darwin/project_knowledge_panel-dark.png | Bin 0 -> 18329 bytes .../darwin/project_knowledge_panel-light.png | Bin 0 -> 17918 bytes .../snapshots/darwin/project_list-dark.png | Bin 0 -> 12889 bytes .../snapshots/darwin/project_list-light.png | Bin 0 -> 12229 bytes .../snapshots/darwin/prompt_library-dark.png | Bin 0 -> 27350 bytes .../snapshots/darwin/prompt_library-light.png | Bin 0 -> 26526 bytes .../snapshots/darwin/regenerate_menu-dark.png | Bin 0 -> 14887 bytes .../darwin/regenerate_menu-light.png | Bin 0 -> 16072 bytes .../darwin/shared_conversation_view-dark.png | Bin 0 -> 31145 bytes .../darwin/shared_conversation_view-light.png | Bin 0 -> 29902 bytes .../darwin/stop_generating_button-dark.png | Bin 0 -> 3385 bytes .../darwin/stop_generating_button-light.png | Bin 0 -> 3235 bytes .../darwin/suggestion_chips-dark.png | Bin 0 -> 8338 bytes .../darwin/suggestion_chips-light.png | Bin 0 -> 7922 bytes .../darwin/system_prompt_editor-dark.png | Bin 0 -> 15988 bytes .../darwin/system_prompt_editor-light.png | Bin 0 -> 15262 bytes .../darwin/thinking_indicator-dark.png | Bin 0 -> 4048 bytes .../darwin/thinking_indicator-light.png | Bin 0 -> 3832 bytes .../snapshots/darwin/welcome_screen-dark.png | Bin 0 -> 37202 bytes .../snapshots/darwin/welcome_screen-light.png | Bin 0 -> 35835 bytes thinking_indicator_test.go | 51 +++ welcome_screen_test.go | 66 ++++ 92 files changed, 3692 insertions(+), 22 deletions(-) create mode 100644 artifact_card_test.go create mode 100644 capability_cards_test.go create mode 100644 chat_empty_state_test.go create mode 100644 chatsession_fixture_test.go create mode 100644 conversation_export_test.go create mode 100644 conversation_item_test.go create mode 100644 conversation_list_test.go create mode 100644 conversation_search_test.go create mode 100644 cost_estimator_test.go create mode 100644 date_separator_test.go create mode 100644 docs/components/241-conversation-list.md create mode 100644 docs/components/242-conversation-item.md create mode 100644 docs/components/243-conversation-search.md create mode 100644 docs/components/244-project-list.md create mode 100644 docs/components/245-project-knowledge-panel.md create mode 100644 docs/components/246-welcome-screen.md create mode 100644 docs/components/247-suggestion-chips.md create mode 100644 docs/components/248-prompt-library.md create mode 100644 docs/components/249-capability-cards.md create mode 100644 docs/components/250-feedback-form.md create mode 100644 docs/components/251-date-separator.md create mode 100644 docs/components/252-thinking-indicator.md create mode 100644 docs/components/253-stop-generating-button.md create mode 100644 docs/components/254-system-prompt-editor.md create mode 100644 docs/components/255-cost-estimator.md create mode 100644 docs/components/256-shared-conversation-view.md create mode 100644 docs/components/257-conversation-export.md create mode 100644 docs/components/258-regenerate-menu.md create mode 100644 docs/components/259-artifact-card.md create mode 100644 docs/components/260-chat-empty-state.md create mode 100644 example_chatsession_test.go create mode 100644 examples/gallery/pages_chatsession_demos.go create mode 100644 examples/gallery/pages_chatsession_more.go create mode 100644 feedback_form_test.go create mode 100644 project_knowledge_panel_test.go create mode 100644 project_list_test.go create mode 100644 prompt_library_test.go create mode 100644 regenerate_menu_test.go create mode 100644 shared_conversation_view_test.go create mode 100644 stop_generating_button_test.go create mode 100644 suggestion_chips_test.go create mode 100644 system_prompt_editor_test.go create mode 100644 testdata/snapshots/darwin/artifact_card-dark.png create mode 100644 testdata/snapshots/darwin/artifact_card-light.png create mode 100644 testdata/snapshots/darwin/capability_cards-dark.png create mode 100644 testdata/snapshots/darwin/capability_cards-light.png create mode 100644 testdata/snapshots/darwin/chat_empty_state-dark.png create mode 100644 testdata/snapshots/darwin/chat_empty_state-light.png create mode 100644 testdata/snapshots/darwin/conversation_export-dark.png create mode 100644 testdata/snapshots/darwin/conversation_export-light.png create mode 100644 testdata/snapshots/darwin/conversation_item-dark.png create mode 100644 testdata/snapshots/darwin/conversation_item-light.png create mode 100644 testdata/snapshots/darwin/conversation_list-dark.png create mode 100644 testdata/snapshots/darwin/conversation_list-light.png create mode 100644 testdata/snapshots/darwin/conversation_search-dark.png create mode 100644 testdata/snapshots/darwin/conversation_search-light.png create mode 100644 testdata/snapshots/darwin/cost_estimator-dark.png create mode 100644 testdata/snapshots/darwin/cost_estimator-light.png create mode 100644 testdata/snapshots/darwin/date_separator-dark.png create mode 100644 testdata/snapshots/darwin/date_separator-light.png create mode 100644 testdata/snapshots/darwin/feedback_form-dark.png create mode 100644 testdata/snapshots/darwin/feedback_form-light.png create mode 100644 testdata/snapshots/darwin/project_knowledge_panel-dark.png create mode 100644 testdata/snapshots/darwin/project_knowledge_panel-light.png create mode 100644 testdata/snapshots/darwin/project_list-dark.png create mode 100644 testdata/snapshots/darwin/project_list-light.png create mode 100644 testdata/snapshots/darwin/prompt_library-dark.png create mode 100644 testdata/snapshots/darwin/prompt_library-light.png create mode 100644 testdata/snapshots/darwin/regenerate_menu-dark.png create mode 100644 testdata/snapshots/darwin/regenerate_menu-light.png create mode 100644 testdata/snapshots/darwin/shared_conversation_view-dark.png create mode 100644 testdata/snapshots/darwin/shared_conversation_view-light.png create mode 100644 testdata/snapshots/darwin/stop_generating_button-dark.png create mode 100644 testdata/snapshots/darwin/stop_generating_button-light.png create mode 100644 testdata/snapshots/darwin/suggestion_chips-dark.png create mode 100644 testdata/snapshots/darwin/suggestion_chips-light.png create mode 100644 testdata/snapshots/darwin/system_prompt_editor-dark.png create mode 100644 testdata/snapshots/darwin/system_prompt_editor-light.png create mode 100644 testdata/snapshots/darwin/thinking_indicator-dark.png create mode 100644 testdata/snapshots/darwin/thinking_indicator-light.png create mode 100644 testdata/snapshots/darwin/welcome_screen-dark.png create mode 100644 testdata/snapshots/darwin/welcome_screen-light.png create mode 100644 thinking_indicator_test.go create mode 100644 welcome_screen_test.go diff --git a/artifact_card_test.go b/artifact_card_test.go new file mode 100644 index 0000000..409109c --- /dev/null +++ b/artifact_card_test.go @@ -0,0 +1,63 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestArtifactCardOpens(t *testing.T) { + opens := 0 + tt := chatTester(480, 160, func(c *ui.Context) { + if ArtifactCard(c, ArtifactCardOptions{Kind: ArtifactDocument, Title: "Decree", Detail: "2 pages"}).Changed() { + opens++ + } + }) + if !tt.HasText("Document · 2 pages") { + t.Fatalf("texts %q", tt.Texts()) + } + _ = tt.Click("Decree") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if opens != 2 { + t.Fatalf("opens %d", opens) + } +} + +func TestArtifactCardStreamingDisabledAndChecks(t *testing.T) { + opens := 0 + tt := chatTester(480, 160, func(c *ui.Context) { + if ArtifactCard(c, ArtifactCardOptions{Kind: ArtifactWeb, Title: "Menu", Streaming: true, Disabled: true}).Changed() { + opens++ + } + }) + _ = tt.Click("Menu") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if opens != 0 || !tt.HasText("Web page") { + t.Fatalf("opens %d texts %q", opens, tt.Texts()) + } + for _, opts := range []ArtifactCardOptions{{}, {Title: "x", Kind: 7}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%+v: no panic", opts) + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + ArtifactCard(c, opts) + }, 100, 100, 1) + }() + } +} + +func TestArtifactCardSnapshot(t *testing.T) { + snapshot(t, "artifact_card", 460, 210, func(c *ui.Context) { + ui.Column(c).Padding(16).Gap(8).Children(func() { + ArtifactCard(c, ArtifactCardOptions{Kind: ArtifactCode, Title: "seating.go", Detail: "Go · 120 lines"}) + ArtifactCard(c, ArtifactCardOptions{Kind: ArtifactDocument, Title: "Royal decree", Streaming: true}) + ArtifactCard(c, ArtifactCardOptions{Kind: ArtifactWeb, Title: "Ball invitation", Disabled: true}) + }) + }) +} diff --git a/capability_cards_test.go b/capability_cards_test.go new file mode 100644 index 0000000..a80add7 --- /dev/null +++ b/capability_cards_test.go @@ -0,0 +1,73 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestCapabilityCardsExample(t *testing.T) { + got := "" + tt := chatTester(900, 400, func(c *ui.Context) { + if v := CapabilityCards(c, chatCards(), CapabilityCardsOptions{}); v.Example != "" { + got = v.Example + } + }) + if !tt.HasText("Banquets, seating and schedules.") { + t.Fatal("description missing") + } + if err := tt.Click("“Plan a ball for 200 guests”"); err != nil { + t.Fatal(err) + } + if got != "Plan a ball for 200 guests" { + t.Fatalf("example %q", got) + } + // Tab moves from the clicked example to the next card's. + got = "" + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if got != "Explain the minuet" { + t.Fatalf("keys chose %q", got) + } +} + +func TestCapabilityCardsColumnsAndDisabled(t *testing.T) { + got := "" + var g *ui.Element + tt := chatTester(900, 600, func(c *ui.Context) { + v := CapabilityCards(c, chatCards(), CapabilityCardsOptions{Columns: 1, Disabled: true}) + g = v.Element + if v.Example != "" { + got = v.Example + } + }) + _ = tt.Click("“Explain the minuet”") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if got != "" { + t.Fatalf("disabled cards chose %q", got) + } + a, _ := tt.Find("Write") + b, _ := tt.Find("Plan") + if b.Y <= a.Y || g == nil { + t.Fatalf("one column should stack cards: %v %v", a, b) + } +} + +func TestCapabilityCardsNeedTitles(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + CapabilityCards(c, []CapabilityCard{{}}, CapabilityCardsOptions{}) + }, 100, 100, 1) +} + +func TestCapabilityCardsSnapshot(t *testing.T) { + snapshot(t, "capability_cards", 860, 200, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { CapabilityCards(c, chatCards(), CapabilityCardsOptions{}) }) + }) +} diff --git a/chat_empty_state_test.go b/chat_empty_state_test.go new file mode 100644 index 0000000..c0eaa73 --- /dev/null +++ b/chat_empty_state_test.go @@ -0,0 +1,59 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestChatEmptyStateKinds(t *testing.T) { + for _, tc := range []struct { + opts ChatEmptyStateOptions + texts []string + action string + }{ + {ChatEmptyStateOptions{}, []string{"Start a conversation"}, "New conversation"}, + {ChatEmptyStateOptions{Kind: ChatEmptyNoResults, Query: "minuet"}, []string{"minuet"}, "Clear search"}, + {ChatEmptyStateOptions{Kind: ChatEmptyOffline}, []string{"You are offline"}, "Retry"}, + {ChatEmptyStateOptions{Kind: ChatEmptyOffline, Title: "Lost the court", Action: "Reconnect"}, []string{"Lost the court"}, "Reconnect"}, + } { + acted := 0 + tt := chatTester(420, 320, func(c *ui.Context) { + if ChatEmptyState(c, tc.opts).Action { + acted++ + } + }) + for _, s := range tc.texts { + if !tt.HasText(s) { + t.Errorf("%+v: %q missing from %q", tc.opts, s, tt.Texts()) + } + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if err := tt.Click(tc.action); err != nil || acted != 2 { + t.Errorf("%+v: action %q acted %d (%v)", tc.opts, tc.action, acted, err) + } + } +} + +func TestChatEmptyStateRejectsBadKind(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + ChatEmptyState(c, ChatEmptyStateOptions{Kind: 9}) + }, 100, 100, 1) +} + +func TestChatEmptyStateSnapshot(t *testing.T) { + snapshot(t, "chat_empty_state", 820, 240, func(c *ui.Context) { + ui.Row(c).Padding(16).Gap(8).Children(func() { + for _, k := range []ChatEmptyKind{ChatEmptyNew, ChatEmptyNoResults, ChatEmptyOffline} { + ui.Column(c).Width(260).Children(func() { ChatEmptyState(c, ChatEmptyStateOptions{Kind: k, Query: "minuet"}) }) + } + }) + }) +} diff --git a/chatsession_fixture_test.go b/chatsession_fixture_test.go new file mode 100644 index 0000000..4f2b199 --- /dev/null +++ b/chatsession_fixture_test.go @@ -0,0 +1,38 @@ +package mujica + +import ( + "time" + + "mujicaui/icons" +) + +// chatNow is the fixed clock of the chat session tests. +var chatNow = time.Date(2026, time.October, 5, 15, 30, 0, 0, time.UTC) + +func chatConversations() []ChatConversation { + h := time.Hour + return []ChatConversation{ + {ID: "a", Title: "Court etiquette notes", Updated: chatNow.Add(-2 * h)}, + {ID: "b", Title: "Ballroom seating plan", Updated: chatNow.Add(-26 * h)}, + {ID: "c", Title: "Harpsichord repair", Updated: chatNow.Add(-4 * 24 * h)}, + {ID: "d", Title: "Coronation menu", Updated: chatNow.Add(-40 * 24 * h)}, + {ID: "e", Title: "Royal letters", Updated: chatNow.Add(-90 * 24 * h), Pinned: true}, + {ID: "f", Title: "Garden maze", Updated: chatNow.Add(-1 * h)}, + } +} + +func chatMessages() []SessionMessage { + return []SessionMessage{ + {Role: SessionUser, Text: "How should guests be seated at the banquet?", Time: chatNow.Add(-10 * time.Minute)}, + {Role: SessionAssistant, Text: "Seat by rank: the host at the head, honored guests to the right.", Time: chatNow.Add(-9 * time.Minute)}, + {Role: SessionUser, Author: "Lady Ann", Text: "And the musicians?", Time: chatNow.Add(-5 * time.Minute)}, + } +} + +func chatCards() []CapabilityCard { + return []CapabilityCard{ + {Title: "Write", Description: "Letters, speeches and verse.", Icon: icons.Must("file-text"), Examples: []string{"Draft a royal decree"}}, + {Title: "Plan", Description: "Banquets, seating and schedules.", Icon: icons.Must("calendar"), Examples: []string{"Plan a ball for 200 guests"}}, + {Title: "Research", Description: "History, heraldry and music.", Icon: icons.Must("search"), Examples: []string{"Explain the minuet"}}, + } +} diff --git a/conversation_export_test.go b/conversation_export_test.go new file mode 100644 index 0000000..68c63aa --- /dev/null +++ b/conversation_export_test.go @@ -0,0 +1,95 @@ +package mujica + +import ( + "encoding/json" + "strings" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestExportConversationFormats(t *testing.T) { + msgs := chatMessages() + md := ExportConversation("Banquet", msgs, ExportMarkdown) + want := "# Banquet\n\n**User** · (2026-10-05 15:20)\n\nHow should guests be seated at the banquet?\n" + if !strings.HasPrefix(md, want) || !strings.Contains(md, "**Lady Ann**") { + t.Fatalf("markdown %q", md) + } + var doc struct { + Title string + Messages []struct{ Role, Author, Text, Time string } + } + if err := json.Unmarshal([]byte(ExportConversation("Banquet", msgs, ExportJSON)), &doc); err != nil { + t.Fatal(err) + } + if doc.Title != "Banquet" || len(doc.Messages) != 3 || doc.Messages[1].Role != "assistant" || doc.Messages[2].Author != "Lady Ann" || + doc.Messages[0].Time != "2026-10-05T15:20:00Z" { + t.Fatalf("json %+v", doc) + } + txt := ExportConversation("Banquet", msgs[:1], ExportText) + if txt != "Banquet\n\nUser (2026-10-05 15:20):\nHow should guests be seated at the banquet?\n" { + t.Fatalf("text %q", txt) + } + if got := ExportConversation("Empty", nil, ExportJSON); !strings.Contains(got, `"messages": []`) { + t.Fatalf("empty json %q", got) + } +} + +func TestConversationExportRangeAndExport(t *testing.T) { + var s ConversationExportState + var last ConversationExportView + selected := []int{2} + tt := chatTester(560, 600, func(c *ui.Context) { + if v := ConversationExport(c, &s, chatMessages(), ConversationExportOptions{Title: "Banquet", Selected: selected}); v.Exported { + last = v + } + }) + _ = tt.Click("JSON") + _ = tt.Click("Selected (1)") + _ = tt.Click("Export") + if !last.Exported || last.Format != ExportJSON || !strings.Contains(last.Content, "And the musicians?") || + strings.Contains(last.Content, "banquet?") { + t.Fatalf("export %+v", last) + } + _ = tt.Click("Plain text") + _ = tt.Click("Last") + s.Last = 2 + tt.Frame() + _ = tt.Click("Export") + if last.Format != ExportText || strings.Contains(last.Content, "banquet?") || !strings.Contains(last.Content, "Seat by rank") { + t.Fatalf("last-2 export %q", last.Content) + } +} + +func TestConversationExportDisabledAndChecks(t *testing.T) { + var s ConversationExportState + exported := false + tt := chatTester(560, 600, func(c *ui.Context) { + if ConversationExport(c, &s, chatMessages(), ConversationExportOptions{Title: "T", Disabled: true}).Exported { + exported = true + } + }) + _ = tt.Click("JSON") + _ = tt.Click("Export") + if exported || s.Format != ExportMarkdown { + t.Fatalf("disabled export acted: %v %v", exported, s.Format) + } + defer func() { + if recover() == nil { + t.Fatal("no panic for a bad selection") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + ConversationExport(c, &s, chatMessages(), ConversationExportOptions{Title: "T", Selected: []int{9}}) + }, 100, 100, 1) +} + +func TestConversationExportSnapshot(t *testing.T) { + snapshot(t, "conversation_export", 560, 470, func(c *ui.Context) { + s := &ConversationExportState{} + ui.Column(c).Padding(16).Children(func() { + ConversationExport(c, s, chatMessages(), ConversationExportOptions{Title: "Banquet seating", Selected: []int{0, 2}}) + }) + }) +} diff --git a/conversation_item.go b/conversation_item.go index c3eb5b2..9d04be3 100644 --- a/conversation_item.go +++ b/conversation_item.go @@ -94,7 +94,7 @@ func ConversationItem(c *ui.Context, conv *ChatConversation, opts ConversationIt v.Deleted = main.Shortcut(0, ui.KeyDelete) } } - menu := DropdownMenu(c, "", DropdownMenuOptions{Icon: icons.Must("ellipsis"), Label: msg(c, "conversation_item.actions"), Disabled: opts.Disabled}, func(m *PopupMenu) { + conversationItemMenu(c, msg(c, "conversation_item.actions"), func(m *PopupMenu) { rename = m.Item(msg(c, "conversation_item.rename"), PopupMenuItemOptions{}) || rename pin := msg(c, "conversation_item.pin") if conv.Pinned { @@ -105,7 +105,6 @@ func ConversationItem(c *ui.Context, conv *ChatConversation, opts ConversationIt m.Separator() v.Deleted = m.Item(msg(c, "conversation_item.delete"), PopupMenuItemOptions{}) || v.Deleted }) - menu.Shrink(0).MinWidth(theme.MinHitSize).MinHeight(theme.MinHitSize) }) if rename && !row.IsDisabled() { st.editing, st.fresh, st.draft = true, true, conv.Title @@ -142,3 +141,16 @@ func conversationItemEditor(c *ui.Context, k theme.Tokens, conv *ChatConversatio st.editing = false } } + +// conversationItemMenu is a borderless ellipsis button opening the menu build fills. +func conversationItemMenu(c *ui.Context, label string, build func(m *PopupMenu)) *ui.Element { + b := iconAction(c, icons.Must("ellipsis"), label).Role(ui.RoleMenuButton).Shrink(0) + open := ui.Local(b, conversationItemKey{}, func() bool { return false }) + if b.IsDisabled() { + *open = false + } else if b.Clicked() || b.Shortcut(0, ui.KeyDown) { + *open = true + } + popupMenuOpen(c, b, open, build) + return b +} diff --git a/conversation_item_test.go b/conversation_item_test.go new file mode 100644 index 0000000..1d358fa --- /dev/null +++ b/conversation_item_test.go @@ -0,0 +1,118 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func conversationItemTester(conv *ChatConversation, opts ConversationItemOptions, got *ConversationItemView) *ui.Tester { + return chatTester(420, 360, func(c *ui.Context) { + opts.Today = DateOf(chatNow) + v := ConversationItem(c, conv, opts) + if v.Opened || v.Deleted || v.Exported || v.PinToggled || v.Renamed { + *got = v + } + }) +} + +func TestConversationItemShowsTitleAndTime(t *testing.T) { + convs := chatConversations() + var got ConversationItemView + tt := conversationItemTester(&convs[0], ConversationItemOptions{}, &got) + if !tt.HasText("Court etiquette notes") || !tt.HasText("13:30") { + t.Fatalf("texts %q", tt.Texts()) + } + tt = conversationItemTester(&convs[1], ConversationItemOptions{}, &got) + if !tt.HasText("Yesterday") { + t.Fatalf("texts %q", tt.Texts()) + } + if err := tt.Click("Ballroom seating plan"); err != nil { + t.Fatal(err) + } + if !got.Opened { + t.Fatal("click did not open") + } +} + +func TestConversationItemMenuActions(t *testing.T) { + for _, tc := range []struct { + item string + want func(v ConversationItemView) bool + }{ + {"Pin", func(v ConversationItemView) bool { return v.PinToggled }}, + {"Export", func(v ConversationItemView) bool { return v.Exported }}, + {"Delete", func(v ConversationItemView) bool { return v.Deleted }}, + } { + conv := chatConversations()[0] + var got ConversationItemView + tt := conversationItemTester(&conv, ConversationItemOptions{}, &got) + if err := tt.Click("Conversation actions"); err != nil { + t.Fatal(err) + } + if err := tt.Click(tc.item); err != nil { + t.Fatal(err) + } + if !tc.want(got) { + t.Errorf("%s: %+v", tc.item, got) + } + } +} + +func TestConversationItemInlineRename(t *testing.T) { + conv := chatConversations()[0] + var got ConversationItemView + tt := conversationItemTester(&conv, ConversationItemOptions{}, &got) + _ = tt.Click("Conversation actions") + _ = tt.Click("Rename") + if !tt.Focused("Rename") { + t.Fatal("rename field not focused") + } + tt.Key(0, ui.KeyEnd) + tt.Type(" II") + tt.Key(0, ui.KeyEnter) + if conv.Title != "Court etiquette notes II" || !got.Renamed { + t.Fatalf("title %q renamed %v", conv.Title, got.Renamed) + } + // F2 starts a rename; Escape keeps the title; a blank title is refused. + _ = tt.Click("Court etiquette notes II") + tt.Key(0, ui.KeyF2) + tt.Type("xyz") + tt.Key(0, ui.KeyEscape) + if conv.Title != "Court etiquette notes II" { + t.Fatalf("Escape changed the title to %q", conv.Title) + } + tt.Key(0, ui.KeyF2) + tt.Key(ui.Cmd, ui.KeyA) + tt.Key(ui.Ctrl, ui.KeyA) + tt.Key(0, ui.KeyBackspace) + tt.Key(0, ui.KeyEnter) + if conv.Title != "Court etiquette notes II" { + t.Fatalf("blank rename gave %q", conv.Title) + } +} + +func TestConversationItemDisabled(t *testing.T) { + conv := chatConversations()[0] + var got ConversationItemView + tt := conversationItemTester(&conv, ConversationItemOptions{Disabled: true}, &got) + _ = tt.Click("Court etiquette notes") + _ = tt.Click("Conversation actions") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyF2) + tt.Key(0, ui.KeyDelete) + if got.Opened || got.Deleted || tt.HasText("Rename") { + t.Fatalf("disabled item acted: %+v", got) + } +} + +func TestConversationItemSnapshot(t *testing.T) { + snapshot(t, "conversation_item", 420, 140, func(c *ui.Context) { + convs := chatConversations() + ui.Column(c).Padding(16).Gap(4).Children(func() { + ConversationItem(c, &convs[0], ConversationItemOptions{Today: DateOf(chatNow), Selected: true}) + ConversationItem(c, &convs[4], ConversationItemOptions{Today: DateOf(chatNow)}) + ConversationItem(c, &convs[3], ConversationItemOptions{Today: DateOf(chatNow), Disabled: true}) + }) + }) +} diff --git a/conversation_list.go b/conversation_list.go index c6dae06..f2d1a0d 100644 --- a/conversation_list.go +++ b/conversation_list.go @@ -94,7 +94,7 @@ func ConversationList(c *ui.Context, s *ConversationListState, items []ChatConve s.rows.Label = func(i int) string { return conversationListTitle(c, items, rows[i]) } s.rows.Selected = cursor var list *ui.Element - wrap := ui.Column(c).Grow(1).MinHeight(0).Disabled(opts.Disabled) + wrap := ui.Column(c).MinHeight(0).Disabled(opts.Disabled) wrap.Children(func() { restore := dataSelectTheme(c, 0) list = ui.List(c, &s.rows, len(rows), func(i int) { diff --git a/conversation_list_test.go b/conversation_list_test.go new file mode 100644 index 0000000..3307cd6 --- /dev/null +++ b/conversation_list_test.go @@ -0,0 +1,114 @@ +package mujica + +import ( + "fmt" + "slices" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func chatTester(w, h int, view func(c *ui.Context)) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(10).Fill().Children(func() { view(c) }) + }, w, h) +} + +func TestConversationListGroups(t *testing.T) { + var s ConversationListState + items := chatConversations() + tt := chatTester(400, 600, func(c *ui.Context) { + ConversationList(c, &s, items, ConversationListOptions{Now: chatNow}, nil).Element.Height(560) + }) + want := []string{"Pinned", "Royal letters", "Today", "Garden maze", "Court etiquette notes", "Yesterday", + "Ballroom seating plan", "Previous 7 days", "Harpsichord repair", "Older", "Coronation menu"} + got := slices.Compact(slices.DeleteFunc(tt.Texts(), func(s string) bool { return !slices.Contains(want, s) })) + if !slices.Equal(got, want) { + t.Fatalf("rows %q", got) + } +} + +func TestConversationListSelectAndKeys(t *testing.T) { + var s ConversationListState + items := chatConversations() + changes, opened := 0, 0 + tt := chatTester(400, 600, func(c *ui.Context) { + v := ConversationList(c, &s, items, ConversationListOptions{Now: chatNow, Label: "History"}, nil) + v.Element.Height(560) + if v.Changed() { + changes++ + } + if v.Submitted() { + opened++ + } + }) + if err := tt.Click("Garden maze"); err != nil { + t.Fatal(err) + } + if s.Selected != "f" || changes != 1 { + t.Fatalf("selected %q changes %d", s.Selected, changes) + } + tt.Key(0, ui.KeyDown) + if s.Selected != "a" { + t.Fatalf("Down chose %q", s.Selected) + } + tt.Key(0, ui.KeyDown) + if s.Selected != "b" { + t.Fatalf("Down over a header chose %q", s.Selected) + } + tt.Key(0, ui.KeyEnter) + if opened != 1 { + t.Fatalf("Enter opened %d", opened) + } +} + +func TestConversationListDisabled(t *testing.T) { + var s ConversationListState + items := chatConversations() + tt := chatTester(400, 600, func(c *ui.Context) { + ConversationList(c, &s, items, ConversationListOptions{Now: chatNow, Disabled: true}, nil).Element.Height(560) + }) + _ = tt.Click("Garden maze") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyDown) + if s.Selected != "" { + t.Fatalf("disabled list chose %q", s.Selected) + } +} + +func TestConversationListVirtualizesAndGroupsOnce(t *testing.T) { + items := make([]ChatConversation, 100000) + for i := range items { + items[i] = ChatConversation{ID: fmt.Sprint(i), Title: fmt.Sprintf("Conversation %d", i), Updated: chatNow.Add(-time.Duration(i) * time.Minute)} + } + var s ConversationListState + tt := chatTester(400, 600, func(c *ui.Context) { + ConversationList(c, &s, items, ConversationListOptions{Now: chatNow}, nil).Element.Height(560) + }) + if n := len(tt.Texts()); n > 80 { + t.Fatalf("built %d texts for 100000 conversations", n) + } + // A marked plan survives frames that bring no new data. + s.plan.rows[1].item = -7 + tt.Frame() + if s.plan.rows[1].item != -7 { + t.Fatal("regrouped without a data change") + } + s.plan.rows[1].item = 0 + // Today, Yesterday, Previous 7 days and Older head the rows. + if len(s.plan.rows) != len(items)+4 { + t.Fatalf("%d rows", len(s.plan.rows)) + } +} + +func TestConversationListSnapshot(t *testing.T) { + items := chatConversations() + snapshot(t, "conversation_list", 360, 420, func(c *ui.Context) { + s := &ConversationListState{Selected: "b"} + ui.Column(c).Padding(16).Children(func() { + ConversationList(c, s, items, ConversationListOptions{Now: chatNow, Label: "History"}, nil).Element.Height(380) + }) + }) +} diff --git a/conversation_search.go b/conversation_search.go index 0fc7865..44bc501 100644 --- a/conversation_search.go +++ b/conversation_search.go @@ -97,10 +97,12 @@ func conversationSearchList(c *ui.Context, s *conversationSearchState, q string, s.rows.Key = func(i int) any { return hits[i].ID } s.rows.Label = func(i int) string { return hits[i].Title } s.rows.Selected = &s.cursor + // Rows have one height, so the list can size itself before measuring them. + rowH := d.ControlHeight() + FontSize(c, theme.CaptionSize)*theme.LineHeight + 2 restore := dataSelectTheme(c, 0) list := ui.List(c, &s.rows, len(hits), func(i int) { h := hits[i] - row := ui.Column(c).MinHeight(d.ControlHeight()).Padding(d.Unit(), d.Unit()*2).Gap(2).Justify(ui.Center) + row := ui.Column(c).Height(rowH).Padding(d.Unit(), d.Unit()*2).Gap(2).Justify(ui.Center).ClipY() if i == s.cursor { row.DrawOver(func(p *ui.Painter, r ui.Rect) { p.FillPath(internal.Diamond(r.X+3, r.Y+r.H/2, 6), k.AccentText) @@ -109,13 +111,13 @@ func conversationSearchList(c *ui.Context, s *conversationSearchState, q string, row.Children(func() { ui.RichText(c, conversationSearchSpans(h.Title, q, k)...).SingleLine() if h.Snippet != "" { - ui.RichText(c, conversationSearchSpans(h.Snippet, q, k)...).MaxLines(2).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)) + ui.RichText(c, conversationSearchSpans(h.Snippet, q, k)...).SingleLine().TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)) } }) if !row.IsDisabled() && row.Clicked() { chosen = h.ID } - }).MaxHeight(360).Padding(d.Unit()).Background(k.Surface).Border(theme.BorderWidth, k.Border). + }).Height(min(360, float32(len(hits))*rowH+2*d.Unit()+2)).Padding(d.Unit()).Background(k.Surface).Border(theme.BorderWidth, k.Border). Radius(theme.ControlRadius).Label(msg(c, "conversation_search.results")) restore() internal.Ring(list, k.Focus, theme.ControlRadius) diff --git a/conversation_search_test.go b/conversation_search_test.go new file mode 100644 index 0000000..2afb0f9 --- /dev/null +++ b/conversation_search_test.go @@ -0,0 +1,133 @@ +package mujica + +import ( + "slices" + "strings" + "testing" + + "github.com/egoist/mygo/ui" +) + +// chatSearchBackend answers queries one frame late, as an async caller does. +type chatSearchBackend struct { + query, asked string + hits []ConversationSearchHit + loading bool + queries []string + chosen string + err string + retries int +} + +func (b *chatSearchBackend) view(opts ConversationSearchOptions) func(c *ui.Context) { + return func(c *ui.Context) { + if b.loading && b.err == "" { + b.loading, b.hits = false, nil + for _, conv := range chatConversations() { + if strings.Contains(strings.ToLower(conv.Title), strings.ToLower(b.asked)) { + b.hits = append(b.hits, ConversationSearchHit{ID: conv.ID, Title: conv.Title, Snippet: "about " + conv.Title}) + } + } + } + opts.Loading, opts.Error = b.loading, b.err + v := ConversationSearch(c, &b.query, b.hits, opts) + if v.QueryChanged { + b.queries = append(b.queries, b.query) + b.asked, b.loading = b.query, true + c.Invalidate() + } + if v.Chosen != "" { + b.chosen = v.Chosen + } + if v.Retry { + b.retries++ + } + } +} + +func TestConversationSearchAsyncAndChoose(t *testing.T) { + b := &chatSearchBackend{} + tt := chatTester(420, 400, b.view(ConversationSearchOptions{Label: "Search conversations"})) + tt.Key(0, ui.KeyTab) + tt.Type("garden") + tt.Frame() + if len(b.queries) == 0 || b.queries[len(b.queries)-1] != "garden" { + t.Fatalf("queries %q", b.queries) + } + if !tt.HasText("Garden maze") { + t.Fatalf("results %q", tt.Texts()) + } + if err := tt.Click("Garden maze"); err != nil { + t.Fatal(err) + } + if b.chosen != "f" { + t.Fatalf("chose %q", b.chosen) + } +} + +func TestConversationSearchKeyboard(t *testing.T) { + b := &chatSearchBackend{} + tt := chatTester(420, 400, b.view(ConversationSearchOptions{Label: "Search conversations"})) + tt.Key(0, ui.KeyTab) + tt.Type("o") + tt.Frame() + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if b.chosen == "" || b.chosen != b.hits[1].ID { + t.Fatalf("keys chose %q of %v", b.chosen, b.hits) + } +} + +func TestConversationSearchStates(t *testing.T) { + b := &chatSearchBackend{query: "zzz", asked: "zzz"} + tt := chatTester(420, 400, b.view(ConversationSearchOptions{})) + if !tt.HasText("No conversations match") { + t.Fatalf("texts %q", tt.Texts()) + } + b.err = "Search is down" + tt.Frame() + if !tt.HasText("Search is down") { + t.Fatal("error missing") + } + _ = tt.Click("Retry") + if b.retries != 1 { + t.Fatalf("retries %d", b.retries) + } +} + +func TestConversationSearchHighlights(t *testing.T) { + got := conversationSearchMatches("Ballroom SEATING and seats", "seat") + if !slices.Equal(got, [][2]int{{9, 13}, {21, 25}}) { + t.Fatalf("matches %v", got) + } + if got := conversationSearchMatches("宫廷礼仪与宫廷音乐", "宫廷"); !slices.Equal(got, [][2]int{{0, 2}, {5, 7}}) { + t.Fatalf("CJK matches %v", got) + } + if conversationSearchMatches("abc", "") != nil { + t.Fatal("empty query matched") + } +} + +func TestConversationSearchDisabled(t *testing.T) { + b := &chatSearchBackend{query: "o", hits: []ConversationSearchHit{{ID: "x", Title: "Royal"}}} + tt := chatTester(420, 400, b.view(ConversationSearchOptions{Disabled: true})) + _ = tt.Click("Royal") + tt.Key(0, ui.KeyTab) + tt.Type("q") + if b.chosen != "" || b.query != "o" || len(b.queries) != 0 { + t.Fatalf("disabled search acted: %q %q %v", b.chosen, b.query, b.queries) + } +} + +func TestConversationSearchSnapshot(t *testing.T) { + snapshot(t, "conversation_search", 420, 260, func(c *ui.Context) { + q := "seat" + ui.Column(c).Padding(16).Children(func() { + ConversationSearch(c, &q, []ConversationSearchHit{ + {ID: "b", Title: "Ballroom seating plan", Snippet: "…where to seat the duke…"}, + {ID: "c", Title: "Theatre seats", Snippet: "Box seats for the opera"}, + }, ConversationSearchOptions{}) + }) + }) +} diff --git a/cost_estimator_test.go b/cost_estimator_test.go new file mode 100644 index 0000000..f1dfb2a --- /dev/null +++ b/cost_estimator_test.go @@ -0,0 +1,59 @@ +package mujica + +import ( + "math" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestCostEstimatorTable(t *testing.T) { + tt := chatTester(420, 260, func(c *ui.Context) { + CostEstimator(c, CostEstimatorOptions{InputTokens: 12000, OutputTokens: 3400, InputPrice: 3, OutputPrice: 15}) + }) + for _, s := range []string{"12000", "3400", "15400", "$0.0360", "$0.0510", "$0.0870", "input $3, output $15"} { + if !tt.HasText(s) { + t.Errorf("%q missing from %q", s, tt.Texts()) + } + } + tt = chatTester(420, 260, func(c *ui.Context) { + CostEstimator(c, CostEstimatorOptions{InputTokens: 1e6, InputPrice: 2.5, Currency: "¥", Digits: 2}) + }) + if !tt.HasText("¥2.50") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestEstimateCost(t *testing.T) { + got := EstimateCost(1_000_000, 500_000, 3, 15) + if got.Input != 3 || got.Output != 7.5 || got.Total != 10.5 { + t.Fatalf("estimate %+v", got) + } + if z := EstimateCost(0, 0, 3, 15); z.Total != 0 { + t.Fatalf("zero tokens cost %v", z.Total) + } +} + +func TestCostEstimatorRejectsBadInput(t *testing.T) { + for _, opts := range []CostEstimatorOptions{{InputTokens: -1}, {InputPrice: -1}, {OutputPrice: math.NaN()}, {Digits: -1}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%+v: no panic", opts) + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + CostEstimator(c, opts) + }, 100, 100, 1) + }() + } +} + +func TestCostEstimatorSnapshot(t *testing.T) { + snapshot(t, "cost_estimator", 420, 200, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + CostEstimator(c, CostEstimatorOptions{InputTokens: 12000, OutputTokens: 3400, InputPrice: 3, OutputPrice: 15}) + }) + }) +} diff --git a/date_separator_test.go b/date_separator_test.go new file mode 100644 index 0000000..bd68bc1 --- /dev/null +++ b/date_separator_test.go @@ -0,0 +1,65 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestDateSeparatorLabels(t *testing.T) { + today := DateOf(chatNow) + for _, tc := range []struct { + locale Locale + day Date + want string + }{ + {EnUS, today, "Today"}, + {EnUS, today.AddDays(-1), "Yesterday"}, + {EnUS, Date{2026, 9, 1}, "Tuesday, September 1, 2026"}, + {ZhCN, today, "今天"}, + {ZhCN, today.AddDays(-1), "昨天"}, + {ZhCN, Date{2026, 9, 1}, "2026年9月1日 星期二"}, + } { + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{Locale: tc.locale}) + DateSeparator(c, tc.day, DateSeparatorOptions{Today: today}) + }, 500, 80) + if !tt.HasText(tc.want) { + t.Errorf("%s %v: texts %q", tc.locale, tc.day, tt.Texts()) + } + } +} + +func TestDateSeparatorShortStamp(t *testing.T) { + var got []string + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + today := DateOf(chatNow) + got = []string{dateSeparatorWhen(c, chatNow, today), dateSeparatorWhen(c, chatNow.AddDate(0, 0, -1), today), + dateSeparatorWhen(c, chatNow.AddDate(0, -2, 0), today)} + }, 100, 100, 1) + if got[0] != "15:30" || got[1] != "Yesterday" || got[2] != "August 5" { + t.Fatalf("stamps %q", got) + } +} + +func TestDateSeparatorRejectsInvalid(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + DateSeparator(c, Date{2026, 2, 30}, DateSeparatorOptions{}) + }, 100, 100, 1) +} + +func TestDateSeparatorSnapshot(t *testing.T) { + snapshot(t, "date_separator", 520, 110, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + DateSeparator(c, DateOf(chatNow), DateSeparatorOptions{Today: DateOf(chatNow)}) + DateSeparator(c, Date{2026, 9, 1}, DateSeparatorOptions{Today: DateOf(chatNow)}) + }) + }) +} diff --git a/docs/components/241-conversation-list.md b/docs/components/241-conversation-list.md new file mode 100644 index 0000000..c2d1703 --- /dev/null +++ b/docs/components/241-conversation-list.md @@ -0,0 +1,56 @@ +# 241 ConversationList · 会话列表 + +## 用途 + +按“置顶、今天、昨天、7 天内、更早”分组显示历史会话,只构建可见行,适合十万条以上的会话历史。 + +## 最小示例 + +```go +var state mujica.ConversationListState +convs := []mujica.ChatConversation{ + {ID: "1", Title: "Court etiquette", Updated: time.Now()}, + {ID: "2", Title: "Royal letters", Updated: time.Now().AddDate(0, 0, -30), Pinned: true}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ConversationList(c, &state, convs, mujica.ConversationListOptions{Label: "History"}, nil).Changed() { + log.Println("open", state.Selected) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ConversationList(c *ui.Context, s *ConversationListState, items []ChatConversation, opts ConversationListOptions, row func(conv ChatConversation)) ConversationListView`。`row` 为 nil 时显示标题;传入时可放 `ConversationItem` 等自定义内容。 + +`ChatConversation`:`ID`(唯一)、`Title`、`Updated`、`Pinned`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Now` | `time.Time` | 零值(窗口时钟) | 分组用的当前时间。 | +| `Label` | `string` | "" | 列表的无障碍名称。 | +| `Disabled` | `bool` | false | 禁用:不能选择,退出 Tab 序列。 | + +`ConversationListState.Selected` 为当前会话 ID,调用方可直接设置。 + +## 状态 + +分组标题(衬线小字、旧金色)、普通行、悬停、选中(Selection 底色 + 左侧菱形)、聚焦(列表焦点环)、禁用。 + +## 事件 + +`Changed()`:选中了另一会话,ID 在 `State.Selected`。`Submitted()`:在选中行上按 Enter 或双击。 + +## 键盘操作 + +- Tab:聚焦列表。 +- ↑/↓、Home、End:在会话间移动并选择,跳过分组标题;输入首字母定位。 +- Enter:打开当前会话。 + +## 限制 + +- 分组与排序只在 `items` 切片(首元素地址或长度)或当天日期变化时重算。原地修改切片元素后,请传入新切片以触发重新分组。 +- 选中行由 MyGo 列表报告选中状态;分组标题由 `ListState.Header` 标记,不可选中。 +- 自定义 `row` 中若含按钮(如 `ConversationItem`),点击由按钮处理,不会改变列表选择;请在按钮事件里设置 `State.Selected`。 diff --git a/docs/components/242-conversation-item.md b/docs/components/242-conversation-item.md new file mode 100644 index 0000000..84246ff --- /dev/null +++ b/docs/components/242-conversation-item.md @@ -0,0 +1,50 @@ +# 242 ConversationItem · 会话条目 + +## 用途 + +一行会话:标题、时间、置顶标记,以及菜单中的重命名(行内编辑)、置顶、导出、删除。删除与导出只回调,由调用方执行。 + +## 最小示例 + +```go +conv := mujica.ChatConversation{ID: "1", Title: "Court etiquette", Updated: time.Now()} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + v := mujica.ConversationItem(c, &conv, mujica.ConversationItemOptions{}) + if v.Deleted { + log.Println("delete", conv.ID) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ConversationItem(c *ui.Context, conv *ChatConversation, opts ConversationItemOptions) ConversationItemView`。`conv` 不能为 nil,`ID` 不能为空。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Today` | `Date` | 零值(窗口时钟) | 决定时间显示为时刻、“昨天”或日期。 | +| `Selected` | `bool` | false | 显示为当前会话。 | +| `Disabled` | `bool` | false | 禁用全部操作。 | +| `Draggable` | `bool` | false | 允许拖到 `ProjectList` 的项目上,携带 `ConversationDrag`。 | + +## 状态 + +默认、悬停、选中(Selection 底色 + 酒红标题)、置顶(星形图标)、行内编辑(输入框酒红边框)、禁用。 + +## 事件 + +`ConversationItemView`:`Opened`(点击或 Enter)、`Renamed`(新标题已写入 `conv.Title`)、`PinToggled`、`Exported`、`Deleted`。 + +## 键盘操作 + +- Enter/Space:打开会话。 +- F2:行内重命名;输入框中 Enter 确认,Escape 取消;空白标题不会被接受。 +- Delete:请求删除。 +- 菜单按钮:Enter、Space 或 ↓ 打开,方向键移动,Escape 关闭。 + +## 限制 + +- 删除没有内置确认;需要确认时由调用方弹出 AlertDialog。 +- 菜单按钮不在条目的 Tab 位之外另设快捷键。 diff --git a/docs/components/243-conversation-search.md b/docs/components/243-conversation-search.md new file mode 100644 index 0000000..4195cdc --- /dev/null +++ b/docs/components/243-conversation-search.md @@ -0,0 +1,53 @@ +# 243 ConversationSearch · 会话搜索 + +## 用途 + +按标题与内容搜索会话。查询交给调用方异步执行,结果回传后高亮匹配文字。 + +## 最小示例 + +```go +query := "seat" +hits := []mujica.ConversationSearchHit{{ID: "1", Title: "Ballroom seating plan"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + v := mujica.ConversationSearch(c, &query, hits, mujica.ConversationSearchOptions{}) + if v.QueryChanged { + log.Println("search", query) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ConversationSearch(c *ui.Context, query *string, hits []ConversationSearchHit, opts ConversationSearchOptions) ConversationSearchView`。 + +`ConversationSearchHit`:`ID`、`Title`、`Snippet`(匹配的消息片段)。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Loading` | `bool` | false | 调用方正在搜索。 | +| `Error` | `string` | "" | 搜索失败的说明,附重试按钮。 | +| `Placeholder` | `string` | 内置“搜索” | 输入框占位。 | +| `Label` | `string` | "" | 无障碍名称。 | +| `Disabled` | `bool` | false | 禁用输入与选择。 | + +## 状态 + +空查询、搜索中(旋转标记)、有结果(匹配处加粗、下划线、Selection 底)、无结果、失败(错误文字 + 重试)、禁用。 + +## 事件 + +`QueryChanged`:查询变化,调用方据此发起搜索,结果到达后传入新的 `hits` 并调用 `c.Invalidate()`。`Chosen`:点击或 Enter 打开的会话 ID。`Retry`:点击重试。 + +## 键盘操作 + +- 输入框中 ↓:进入结果列表。 +- 列表中 ↑/↓ 移动,Enter 打开。 +- Escape:清空查询(SearchInput 行为)。 + +## 限制 + +- 匹配高亮为不区分大小写的逐字符匹配,不做分词、拼音或模糊匹配;排序完全由调用方决定。 +- 结果行固定高度(标题一行、片段一行),片段超长时截断。 diff --git a/docs/components/244-project-list.md b/docs/components/244-project-list.md new file mode 100644 index 0000000..a3ed67b --- /dev/null +++ b/docs/components/244-project-list.md @@ -0,0 +1,53 @@ +# 244 ProjectList · 项目列表 + +## 用途 + +按文件夹列出项目,展开项目可见其中的会话;把会话拖到项目上或用“移动”菜单即可改变归属。 + +## 最小示例 + +```go +var state mujica.ProjectListState +projects := []mujica.ChatProject{{ID: "p1", Name: "Coronation", Folder: "Court"}} +convs := func(id string) []mujica.ChatConversation { + return []mujica.ChatConversation{{ID: "1", Title: "Menu"}} +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.ProjectList(c, &state, projects, convs, mujica.ProjectListOptions{}); v.Moved { + log.Println("move", v.MoveID, "to", v.MoveTo) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ProjectList(c *ui.Context, s *ProjectListState, projects []ChatProject, conversations func(projectID string) []ChatConversation, opts ProjectListOptions) ProjectListView`。 + +`ChatProject`:`ID`、`Name`、`Folder`(文件夹名,空表示不在文件夹中)。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Label` | `string` | "" | 树的无障碍名称。 | +| `Disabled` | `bool` | false | 禁用选择、展开与移动。 | + +## 状态 + +文件夹(展开/收起)、项目行(悬停、选中:Selection 底 + 菱形)、拖入目标(角饰边框)、会话行(拖动时半透明)、禁用。 + +## 事件 + +`ProjectListView`:`Changed`(选中项目,ID 在 `State.Selected`)、`Opened`(打开的会话 ID)、`Moved` 与 `MoveID`/`MoveTo`(把会话移入项目,由调用方更新数据)。 + +## 键盘操作 + +- Tab:进入树;↑/↓ 在文件夹、项目、会话间移动。 +- 项目行上 →/← 展开/收起会话;Enter 选择项目。 +- 文件夹上 Enter/Space 展开或收起。 +- 会话行的菜单按钮:选择“移入项目”下的目标完成移动(拖放的键盘替代)。 + +## 限制 + +- 项目行通过 `Description` 读出“已展开/已收起”;MyGo 不向自定义元素公开 expanded 状态(ui/element.go:282),文件夹使用 `CollapsibleBase`,其展开状态可被辅助技术读到。 +- 列表未虚拟化,适合数百个项目以内。 diff --git a/docs/components/245-project-knowledge-panel.md b/docs/components/245-project-knowledge-panel.md new file mode 100644 index 0000000..158c9e5 --- /dev/null +++ b/docs/components/245-project-knowledge-panel.md @@ -0,0 +1,47 @@ +# 245 ProjectKnowledgePanel · 项目知识面板 + +## 用途 + +列出项目知识文件,提供添加、移除,并显示 token 用量与容量提示。选择与读取文件由调用方完成。 + +## 最小示例 + +```go +files := []mujica.KnowledgeFile{{ID: "1", Name: "etiquette.pdf", Tokens: 12000}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + v := mujica.ProjectKnowledgePanel(c, files, mujica.ProjectKnowledgePanelOptions{Capacity: 200000}) + if v.Add { + log.Println("pick files") + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ProjectKnowledgePanel(c *ui.Context, files []KnowledgeFile, opts ProjectKnowledgePanelOptions) ProjectKnowledgePanelView`。 + +`KnowledgeFile`:`ID`、`Name`、`Tokens`(不能为负)。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Capacity` | `int` | 必填 | 知识容量(tokens),必须为正,否则 panic。 | +| `Title` | `string` | 内置“项目知识” | 面板标题。 | +| `Disabled` | `bool` | false | 禁用添加与移除。 | + +## 状态 + +正常用量(酒红进度)、≥ 80%(警告色 + 三角图标 + “即将用满”)、超出容量(危险色 + 圆形警示图标 + “超出容量”)、空列表、禁用。 + +## 事件 + +`Add`:请调用方打开文件选择。`Removed`:要移除的文件 ID。 + +## 键盘操作 + +- Tab:添加按钮,再进入文件列表;↑/↓ 在移除按钮间移动;Enter/Space 移除。 + +## 限制 + +- token 数由调用方计算;面板只做求和与比例显示。 diff --git a/docs/components/246-welcome-screen.md b/docs/components/246-welcome-screen.md new file mode 100644 index 0000000..910f58f --- /dev/null +++ b/docs/components/246-welcome-screen.md @@ -0,0 +1,46 @@ +# 246 WelcomeScreen · 欢迎页 + +## 用途 + +新会话的欢迎页:衬线问候、菱形分隔、副标题、能力卡片,以及放置起始提示的插槽。 + +## 最小示例 + +```go +cards := []mujica.CapabilityCard{{Title: "Write", Examples: []string{"Draft a decree"}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.WelcomeScreen(c, mujica.WelcomeScreenOptions{Greeting: "Good evening", Cards: cards}); v.Example != "" { + log.Println("ask", v.Example) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func WelcomeScreen(c *ui.Context, opts WelcomeScreenOptions) CapabilityCardsView`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Greeting` | `string` | 必填 | 问候语,空时 panic。 | +| `Subtitle` | `string` | "" | 副标题。 | +| `Cards` | `[]CapabilityCard` | nil | 能力卡片,最多三列。 | +| `Prompts` | `func()` | nil | 起始提示插槽,例如 `SuggestionChips`。 | +| `Disabled` | `bool` | false | 禁用卡片示例与插槽内容。 | + +## 状态 + +默认、禁用(由 MyGo 置灰)。卡片与示例按钮的状态见 249 CapabilityCards。 + +## 事件 + +返回值的 `Example`:点击的示例提示。插槽内组件的事件由调用方自行读取。 + +## 键盘操作 + +- Tab 依次经过各卡片的示例与插槽内控件;卡片内 ↑/↓ 在示例间移动;Enter/Space 选择。 + +## 限制 + +- 问候语按纯文本显示,不解析 Markdown。 diff --git a/docs/components/247-suggestion-chips.md b/docs/components/247-suggestion-chips.md new file mode 100644 index 0000000..e8ae72f --- /dev/null +++ b/docs/components/247-suggestion-chips.md @@ -0,0 +1,42 @@ +# 247 SuggestionChips · 建议标签 + +## 用途 + +起始提示或追问建议。点击可填入输入框,或配置为直接发送。 + +## 最小示例 + +```go +input := "" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SuggestionChips(c, &input, []string{"Plan a ball", "Write a sonnet"}, mujica.SuggestionChipsOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func SuggestionChips(c *ui.Context, input *string, suggestions []string, opts SuggestionChipsOptions) SuggestionChipsView`。建议不能为空字符串。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Send` | `bool` | false | 点击即请求发送;默认把建议填入 `*input`。 | +| `Label` | `string` | "" | 组名称,如“追问建议”。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +默认(右箭头)、发送模式(上箭头)、悬停、按下、聚焦、禁用。 + +## 事件 + +`Chosen`:点击的建议。`Sent` 为 true 时调用方应立即发送 `Chosen`;否则建议已写入 `*input`。 + +## 键盘操作 + +- Tab 进入组;←/→ 在建议间移动;Enter/Space 选择。 + +## 限制 + +- 建议换行排列;数量很多时请调用方截取。 diff --git a/docs/components/248-prompt-library.md b/docs/components/248-prompt-library.md new file mode 100644 index 0000000..bd57cd9 --- /dev/null +++ b/docs/components/248-prompt-library.md @@ -0,0 +1,49 @@ +# 248 PromptLibrary · 提示模板库 + +## 用途 + +按分类与搜索浏览提示模板,预览模板,填写 `{{变量}}` 后插入。 + +## 最小示例 + +```go +var state mujica.PromptLibraryState +templates := []mujica.PromptTemplate{{ID: "1", Category: "Letters", Title: "Invitation", Body: "Invite {{guest}}."}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.PromptLibrary(c, &state, templates, mujica.PromptLibraryOptions{}); v.Inserted != "" { + log.Println("insert", v.Inserted) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func PromptLibrary(c *ui.Context, s *PromptLibraryState, templates []PromptTemplate, opts PromptLibraryOptions) PromptLibraryView`。另有 `PromptLibraryVariables(body)` 与 `PromptLibraryFill(body, values)`。 + +`PromptTemplate`:`ID`、`Category`、`Title`(ID 与 Title 必填)、`Body`(`{{name}}` 为变量,名称可含字母、数字、`_.-`)。 + +`PromptLibraryState`:`Category`(空为全部)、`Query`、`Selected`、`Values`(变量值)。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Label` | `string` | "" | 无障碍名称。 | +| `Disabled` | `bool` | false | 禁用全部操作。 | + +## 状态 + +分类与模板行(选中:Selection 底 + 菱形)、无匹配、未选模板、预览(未填变量以 [名称] 标出,已填值酒红加粗)、插入按钮(变量未填全时禁用)、禁用。 + +## 事件 + +`Inserted`:变量已填好的模板正文,非空时由调用方插入输入框。 + +## 键盘操作 + +- Tab 依次进入分类列、搜索框、模板列、变量输入框、插入按钮;列内 ↑/↓ 移动;Enter/Space 选择。 + +## 限制 + +- 过滤只在模板切片、查询或分类变化时重算。 +- 变量为简单占位替换,不支持条件或循环。 diff --git a/docs/components/249-capability-cards.md b/docs/components/249-capability-cards.md new file mode 100644 index 0000000..0c1c886 --- /dev/null +++ b/docs/components/249-capability-cards.md @@ -0,0 +1,45 @@ +# 249 CapabilityCards · 能力卡片 + +## 用途 + +用卡片说明助手能做什么,每张卡片附示例提示,点击示例交给调用方。 + +## 最小示例 + +```go +cards := []mujica.CapabilityCard{{Title: "Plan", Icon: icons.Must("calendar"), Examples: []string{"Plan a ball"}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.CapabilityCards(c, cards, mujica.CapabilityCardsOptions{}); v.Example != "" { + log.Println("ask", v.Example) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func CapabilityCards(c *ui.Context, cards []CapabilityCard, opts CapabilityCardsOptions) CapabilityCardsView`。 + +`CapabilityCard`:`Title`(必填)、`Description`、`Icon`、`Examples`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Columns` | `int` | 0 → 3 | 每行卡片数;负数 panic。 | +| `Disabled` | `bool` | false | 禁用示例按钮。 | + +## 状态 + +卡片(衬线标题、酒红图标)、示例按钮(悬停、按下、聚焦)、禁用。 + +## 事件 + +`Example`:点击的示例文字。 + +## 键盘操作 + +- Tab 在各卡片示例组间移动;组内 ↑/↓;Enter/Space 选择。 + +## 限制 + +- 卡片等宽分栏,不随窗口宽度自动减少列数;窄窗口时请调用方传入较小的 `Columns`。 diff --git a/docs/components/250-feedback-form.md b/docs/components/250-feedback-form.md new file mode 100644 index 0000000..3fa8600 --- /dev/null +++ b/docs/components/250-feedback-form.md @@ -0,0 +1,46 @@ +# 250 FeedbackForm · 反馈表单 + +## 用途 + +在点赞或点踩之后询问原因:原因标签多选与补充文字,然后提交或取消。 + +## 最小示例 + +```go +var value mujica.FeedbackValue +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.FeedbackForm(c, &value, mujica.FeedbackFormOptions{Rating: mujica.FeedbackDown}).Submitted { + log.Println("reasons", value.Reasons) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func FeedbackForm(c *ui.Context, value *FeedbackValue, opts FeedbackFormOptions) FeedbackFormView`。`FeedbackValue`:`Reasons`、`Comment`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Rating` | `FeedbackRating` | `FeedbackUp` | 赞(`FeedbackUp`)或踩(`FeedbackDown`),决定标题与内置原因。 | +| `Reasons` | `[]string` | nil(内置) | 替换内置原因。 | +| `Submitting` | `bool` | false | 调用方正在提交:提交按钮显示加载,表单不可编辑。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +原因标签(按下:Selection 底 + 下划条)、文字框、提交中、禁用。 + +## 事件 + +`Submitted`:提交;`Cancelled`:取消或 Escape。 + +## 键盘操作 + +- Tab 依次经过原因组、文字框、取消、提交;原因组内 ←/→;Space 切换原因。 +- Escape:取消。 + +## 限制 + +- 表单不发送任何数据;提交由调用方完成。 diff --git a/docs/components/251-date-separator.md b/docs/components/251-date-separator.md new file mode 100644 index 0000000..edd1bdc --- /dev/null +++ b/docs/components/251-date-separator.md @@ -0,0 +1,39 @@ +# 251 DateSeparator · 日期分隔 + +## 用途 + +在消息流中标出新的一天:今天、昨天,其余显示本地化的完整日期。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.DateSeparator(c, mujica.DateOf(time.Now()), mujica.DateSeparatorOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func DateSeparator(c *ui.Context, day Date, opts DateSeparatorOptions) *ui.Element`。`day` 必须是有效日期。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Today` | `Date` | 零值(窗口时钟) | 判断“今天/昨天”的当天。 | + +## 状态 + +细线 + 旧金色菱形 + 说明文字;无交互状态。 + +## 事件 + +无。 + +## 键盘操作 + +不获取焦点;辅助技术读出日期文字。 + +## 限制 + +- 日期格式沿用 Calendar 的文案(`calendar.day_label`),en-US 为“Tuesday, September 1, 2026”,zh-CN 为“2026年9月1日 星期二”。 diff --git a/docs/components/252-thinking-indicator.md b/docs/components/252-thinking-indicator.md new file mode 100644 index 0000000..355da7b --- /dev/null +++ b/docs/components/252-thinking-indicator.md @@ -0,0 +1,39 @@ +# 252 ThinkingIndicator · 思考指示 + +## 用途 + +显示助手正在思考:三个菱形依次起伏,旁边是阶段文字;减少动画时静止并加省略号。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ThinkingIndicator(c, mujica.ThinkingIndicatorOptions{Phase: "Searching the archives"}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ThinkingIndicator(c *ui.Context, opts ThinkingIndicatorOptions) *ui.Element`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Phase` | `string` | 内置“正在思考” | 阶段文字,如“正在检索资料”。 | + +## 状态 + +动画(1.2 秒一周)、减少动画(静止菱形 + “…”)。 + +## 事件 + +无。 + +## 键盘操作 + +不获取焦点;角色为 Status,辅助技术读出阶段文字。 + +## 限制 + +- 动画只在绘制时请求下一帧;组件隐藏后不再重绘。 diff --git a/docs/components/253-stop-generating-button.md b/docs/components/253-stop-generating-button.md new file mode 100644 index 0000000..33620d7 --- /dev/null +++ b/docs/components/253-stop-generating-button.md @@ -0,0 +1,44 @@ +# 253 StopGeneratingButton · 停止生成按钮 + +## 用途 + +生成回复时显示的停止按钮,并提供 Cmd+.(其他平台 Ctrl+.)快捷键;生成结束后不显示。 + +## 最小示例 + +```go +generating := true +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.StopGeneratingButton(c, mujica.StopGeneratingButtonOptions{Generating: generating}).Changed() { + generating = false + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func StopGeneratingButton(c *ui.Context, opts StopGeneratingButtonOptions) ChoiceResult`。不显示时返回的 `Element` 为 nil。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Generating` | `bool` | false | 正在生成时显示。 | +| `Disabled` | `bool` | false | 禁用按钮与快捷键。 | + +## 状态 + +默认(方块图标 + 文字 + 快捷键提示)、悬停、聚焦、禁用、隐藏。 + +## 事件 + +`Changed()`:请求停止。 + +## 键盘操作 + +- Enter/Space:停止。 +- Cmd+.(macOS)/ Ctrl+.(Windows、Linux):窗口级快捷键,焦点所在控件未占用该键时生效。 + +## 限制 + +- 快捷键用 MyGo 窗口快捷键注册,焦点控件若注册了同一组合键会优先获得。 diff --git a/docs/components/254-system-prompt-editor.md b/docs/components/254-system-prompt-editor.md new file mode 100644 index 0000000..27fdb0b --- /dev/null +++ b/docs/components/254-system-prompt-editor.md @@ -0,0 +1,47 @@ +# 254 SystemPromptEditor · 系统提示编辑器 + +## 用途 + +多行编辑系统提示,显示字数,可恢复默认,有未保存标记,Cmd/Ctrl+S 保存。 + +## 最小示例 + +```go +prompt, saved := "You are helpful.", "You are helpful." +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.SystemPromptEditor(c, &prompt, mujica.SystemPromptEditorOptions{Default: "You are helpful.", Saved: saved}).Save { + saved = prompt + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func SystemPromptEditor(c *ui.Context, value *string, opts SystemPromptEditorOptions) SystemPromptEditorView`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Default` | `string` | "" | 恢复默认时写回的文字。 | +| `Saved` | `string` | "" | 最近一次保存的文字;与当前值不同即显示“未保存”。 | +| `MaxLength` | `int` | 0 | 字数上限:显示 n / 上限,超出时提示并禁止保存。 | +| `Saving` | `bool` | false | 调用方正在保存,编辑被阻止。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +已保存、未保存(警告色菱形 + 文字)、超出上限(错误提示)、保存中、禁用。 + +## 事件 + +`Save`:请求保存当前值;`Restored`:已恢复默认。 + +## 键盘操作 + +- Tab:进入文本框,再到恢复默认与保存按钮。 +- Cmd+S(macOS)/ Ctrl+S:保存(有改动且未超限时)。 + +## 限制 + +- 超出上限不会截断文字,只阻止保存。 diff --git a/docs/components/255-cost-estimator.md b/docs/components/255-cost-estimator.md new file mode 100644 index 0000000..aa9bded --- /dev/null +++ b/docs/components/255-cost-estimator.md @@ -0,0 +1,42 @@ +# 255 CostEstimator · 费用估算 + +## 用途 + +显示输入、输出 token 数及按调用方单价估算的费用。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CostEstimator(c, mujica.CostEstimatorOptions{InputTokens: 12000, OutputTokens: 3400, InputPrice: 3, OutputPrice: 15}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func CostEstimator(c *ui.Context, opts CostEstimatorOptions) *ui.Element`。另有 `EstimateCost(inputTokens, outputTokens, inputPrice, outputPrice) CostEstimate`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `InputTokens`, `OutputTokens` | `int` | 0 | token 数,不能为负。 | +| `InputPrice`, `OutputPrice` | `float64` | 0 | 每百万 tokens 单价,须有限且不为负。 | +| `Currency` | `string` | "$" | 金额前缀。 | +| `Digits` | `int` | 0 → 4 | 金额小数位;负数 panic。 | + +## 状态 + +只读表格:输入、输出、合计(衬线标签、酒红加粗金额)与单价说明。 + +## 事件 + +无。 + +## 键盘操作 + +不获取焦点;整体读作“预计费用 金额”。 + +## 限制 + +- 估算按 tokens × 单价 / 1,000,000 的浮点运算;显示按 `Digits` 位小数四舍五入,不用于结算。 diff --git a/docs/components/256-shared-conversation-view.md b/docs/components/256-shared-conversation-view.md new file mode 100644 index 0000000..cda30ed --- /dev/null +++ b/docs/components/256-shared-conversation-view.md @@ -0,0 +1,48 @@ +# 256 SharedConversationView · 分享会话视图 + +## 用途 + +只读显示他人分享的会话,带分享者与时间,提供复制链接回调。 + +## 最小示例 + +```go +msgs := []mujica.SessionMessage{{Role: mujica.SessionUser, Text: "Hello"}, {Role: mujica.SessionAssistant, Text: "Good day."}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.SharedConversationView(c, msgs, mujica.SharedConversationViewOptions{Title: "Greeting", SharedBy: "Ann"}).Changed() { + c.WriteClipboard("https://example.com/share/1") + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func SharedConversationView(c *ui.Context, messages []SessionMessage, opts SharedConversationViewOptions) ChoiceResult`。 + +`SessionMessage`:`Role`(`SessionUser`、`SessionAssistant`、`SessionSystem`)、`Author`、`Text`、`Time`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Title` | `string` | 必填 | 会话标题。 | +| `SharedBy` | `string` | "" | 分享者,空显示“未知”。 | +| `SharedAt` | `time.Time` | 零值 | 分享时间,零值不显示。 | +| `Disabled` | `bool` | false | 禁用复制链接。 | + +## 状态 + +标题区、只读标记(锁形图标)、用户消息(描边气泡)、助手消息、禁用。 + +## 事件 + +`Changed()`:点击“复制链接”,由调用方生成链接并写入剪贴板。 + +## 键盘操作 + +- Tab:复制链接按钮,再到消息列表;消息文字可选择复制。 + +## 限制 + +- 消息以纯文本显示,不渲染 Markdown(Markdown 渲染属于 MarkdownView 组件)。 +- 消息列表虚拟化,只构建可见消息。 diff --git a/docs/components/257-conversation-export.md b/docs/components/257-conversation-export.md new file mode 100644 index 0000000..61a5f86 --- /dev/null +++ b/docs/components/257-conversation-export.md @@ -0,0 +1,48 @@ +# 257 ConversationExport · 会话导出 + +## 用途 + +选择格式(Markdown、JSON、纯文本)与范围,预览后生成导出文字;写文件由调用方完成。 + +## 最小示例 + +```go +var state mujica.ConversationExportState +msgs := []mujica.SessionMessage{{Role: mujica.SessionUser, Text: "Hello"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.ConversationExport(c, &state, msgs, mujica.ConversationExportOptions{Title: "Greeting"}); v.Exported { + log.Println(len(v.Content), "bytes to save") + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ConversationExport(c *ui.Context, s *ConversationExportState, messages []SessionMessage, opts ConversationExportOptions) ConversationExportView`。另有纯函数 `ExportConversation(title, messages, format) string`。 + +`ConversationExportState`:`Format`(`ExportMarkdown`、`ExportJSON`、`ExportText`)、`Range`(`ExportAll`、`ExportLast`、`ExportSelected`)、`Last`(0 → 10)。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Title` | `string` | 必填 | 会话标题,写入导出内容。 | +| `Selected` | `[]int` | nil | `ExportSelected` 使用的消息下标;越界 panic。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +格式单选、范围单选(无选中消息时“已选”不可选)、最近 N 条数字框、等宽字体预览、导出按钮、禁用。 + +## 事件 + +`Exported`:导出请求;`Content` 为生成的文字,`Format` 为格式。 + +## 键盘操作 + +- Tab 依次经过格式组、范围组、数字框、预览、导出按钮;单选组内方向键选择。 + +## 限制 + +- 导出不解析消息文字:Markdown 只加标题与作者行,原文原样写入。 +- 预览只在格式、范围或消息变化时重新生成。 diff --git a/docs/components/258-regenerate-menu.md b/docs/components/258-regenerate-menu.md new file mode 100644 index 0000000..c22739d --- /dev/null +++ b/docs/components/258-regenerate-menu.md @@ -0,0 +1,44 @@ +# 258 RegenerateMenu · 重新生成菜单 + +## 用途 + +重新生成回复:同模型重试、换模型重试,以及更长、更短等改写变体。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.RegenerateMenu(c, mujica.RegenerateMenuOptions{Models: []string{"Opus", "Sonnet"}, Current: "Opus"}); v.Chosen { + log.Println("retry", v.Choice.Kind, v.Choice.Model, v.Choice.Variant) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func RegenerateMenu(c *ui.Context, opts RegenerateMenuOptions) RegenerateMenuView`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Models` | `[]string` | nil | 可换用的模型;为空或只有当前模型时子菜单禁用。 | +| `Current` | `string` | "" | 当前模型,不出现在子菜单中。 | +| `Variants` | `[]string` | nil(内置) | 替换内置的更长、更短、更简单、更详细。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +触发按钮(刷新图标)、菜单打开、子菜单、分组标题、禁用项。 + +## 事件 + +`Chosen` 与 `Choice`:`Kind` 为 `RegenerateAgain`、`RegenerateModel`(`Model`)或 `RegenerateVariant`(`Variant`)。 + +## 键盘操作 + +- Enter、Space 或 ↓ 打开菜单;↑/↓ 移动;→ 打开子菜单,← 返回;Enter 选择;Escape 关闭。 + +## 限制 + +- 菜单在窗口内绘制(DropdownMenu),不使用系统菜单。 diff --git a/docs/components/259-artifact-card.md b/docs/components/259-artifact-card.md new file mode 100644 index 0000000..ed8601b --- /dev/null +++ b/docs/components/259-artifact-card.md @@ -0,0 +1,45 @@ +# 259 ArtifactCard · 产物卡片 + +## 用途 + +消息中的产物卡片(代码、文档、网页),点击打开产物面板。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ArtifactCard(c, mujica.ArtifactCardOptions{Title: "seating.go", Detail: "Go · 120 lines"}).Changed() { + log.Println("open artifact panel") + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ArtifactCard(c *ui.Context, opts ArtifactCardOptions) ChoiceResult`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Kind` | `ArtifactKind` | `ArtifactCode` | `ArtifactCode`、`ArtifactDocument`、`ArtifactWeb`;越界 panic。 | +| `Title` | `string` | 必填 | 产物标题。 | +| `Detail` | `string` | "" | 简短说明,如“Go · 120 行”。 | +| `Streaming` | `bool` | false | 仍在生成,显示旋转标记。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +默认、悬停、聚焦、生成中、禁用。种类同时用图标与文字表示。 + +## 事件 + +`Changed()`:请求打开产物面板。 + +## 键盘操作 + +- Tab 聚焦;Enter/Space 打开。 + +## 限制 + +- 卡片不渲染产物内容,面板由调用方实现。 diff --git a/docs/components/260-chat-empty-state.md b/docs/components/260-chat-empty-state.md new file mode 100644 index 0000000..3b3852e --- /dev/null +++ b/docs/components/260-chat-empty-state.md @@ -0,0 +1,44 @@ +# 260 ChatEmptyState · 会话空状态 + +## 用途 + +会话界面的三种空状态:新会话、无搜索结果、离线,并给出下一步操作。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ChatEmptyState(c, mujica.ChatEmptyStateOptions{Kind: mujica.ChatEmptyOffline}).Action { + log.Println("reconnect") + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ChatEmptyState(c *ui.Context, opts ChatEmptyStateOptions) EmptyStateResult`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Kind` | `ChatEmptyKind` | `ChatEmptyNew` | `ChatEmptyNew`、`ChatEmptyNoResults`、`ChatEmptyOffline`;越界 panic。 | +| `Query` | `string` | "" | 无结果时在说明中显示的查询。 | +| `Title`, `Description` | `string` | 内置 | 替换文案。 | +| `Action` | `string` | 内置 | 按钮文字:新建对话、清除搜索、重试。 | + +## 状态 + +新会话(星形图标)、无结果(搜索图标)、离线(断网图标)。 + +## 事件 + +返回值 `Action`:点击按钮。 + +## 键盘操作 + +- Tab 聚焦按钮;Enter/Space 触发。 + +## 限制 + +- 基于 EmptyState 组件,布局与其一致。 diff --git a/example_chatsession_test.go b/example_chatsession_test.go new file mode 100644 index 0000000..53a5849 --- /dev/null +++ b/example_chatsession_test.go @@ -0,0 +1,231 @@ +package mujica_test + +import ( + "log" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" + "mujicaui/icons" +) + +func ExampleConversationList() { + var state mujica.ConversationListState + convs := []mujica.ChatConversation{ + {ID: "1", Title: "Court etiquette", Updated: time.Now()}, + {ID: "2", Title: "Royal letters", Updated: time.Now().AddDate(0, 0, -30), Pinned: true}, + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ConversationList(c, &state, convs, mujica.ConversationListOptions{Label: "History"}, nil).Changed() { + log.Println("open", state.Selected) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleConversationItem() { + conv := mujica.ChatConversation{ID: "1", Title: "Court etiquette", Updated: time.Now()} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + v := mujica.ConversationItem(c, &conv, mujica.ConversationItemOptions{}) + if v.Deleted { + log.Println("delete", conv.ID) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleConversationSearch() { + query := "seat" + hits := []mujica.ConversationSearchHit{{ID: "1", Title: "Ballroom seating plan"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + v := mujica.ConversationSearch(c, &query, hits, mujica.ConversationSearchOptions{}) + if v.QueryChanged { + log.Println("search", query) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleProjectList() { + var state mujica.ProjectListState + projects := []mujica.ChatProject{{ID: "p1", Name: "Coronation", Folder: "Court"}} + convs := func(id string) []mujica.ChatConversation { + return []mujica.ChatConversation{{ID: "1", Title: "Menu"}} + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.ProjectList(c, &state, projects, convs, mujica.ProjectListOptions{}); v.Moved { + log.Println("move", v.MoveID, "to", v.MoveTo) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleProjectKnowledgePanel() { + files := []mujica.KnowledgeFile{{ID: "1", Name: "etiquette.pdf", Tokens: 12000}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + v := mujica.ProjectKnowledgePanel(c, files, mujica.ProjectKnowledgePanelOptions{Capacity: 200000}) + if v.Add { + log.Println("pick files") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleWelcomeScreen() { + cards := []mujica.CapabilityCard{{Title: "Write", Examples: []string{"Draft a decree"}}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.WelcomeScreen(c, mujica.WelcomeScreenOptions{Greeting: "Good evening", Cards: cards}); v.Example != "" { + log.Println("ask", v.Example) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleSuggestionChips() { + input := "" + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SuggestionChips(c, &input, []string{"Plan a ball", "Write a sonnet"}, mujica.SuggestionChipsOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExamplePromptLibrary() { + var state mujica.PromptLibraryState + templates := []mujica.PromptTemplate{{ID: "1", Category: "Letters", Title: "Invitation", Body: "Invite {{guest}}."}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.PromptLibrary(c, &state, templates, mujica.PromptLibraryOptions{}); v.Inserted != "" { + log.Println("insert", v.Inserted) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCapabilityCards() { + cards := []mujica.CapabilityCard{{Title: "Plan", Icon: icons.Must("calendar"), Examples: []string{"Plan a ball"}}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.CapabilityCards(c, cards, mujica.CapabilityCardsOptions{}); v.Example != "" { + log.Println("ask", v.Example) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleFeedbackForm() { + var value mujica.FeedbackValue + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.FeedbackForm(c, &value, mujica.FeedbackFormOptions{Rating: mujica.FeedbackDown}).Submitted { + log.Println("reasons", value.Reasons) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleDateSeparator() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.DateSeparator(c, mujica.DateOf(time.Now()), mujica.DateSeparatorOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleThinkingIndicator() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ThinkingIndicator(c, mujica.ThinkingIndicatorOptions{Phase: "Searching the archives"}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleStopGeneratingButton() { + generating := true + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.StopGeneratingButton(c, mujica.StopGeneratingButtonOptions{Generating: generating}).Changed() { + generating = false + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleSystemPromptEditor() { + prompt, saved := "You are helpful.", "You are helpful." + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.SystemPromptEditor(c, &prompt, mujica.SystemPromptEditorOptions{Default: "You are helpful.", Saved: saved}).Save { + saved = prompt + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCostEstimator() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CostEstimator(c, mujica.CostEstimatorOptions{InputTokens: 12000, OutputTokens: 3400, InputPrice: 3, OutputPrice: 15}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleSharedConversationView() { + msgs := []mujica.SessionMessage{{Role: mujica.SessionUser, Text: "Hello"}, {Role: mujica.SessionAssistant, Text: "Good day."}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.SharedConversationView(c, msgs, mujica.SharedConversationViewOptions{Title: "Greeting", SharedBy: "Ann"}).Changed() { + c.WriteClipboard("https://example.com/share/1") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleConversationExport() { + var state mujica.ConversationExportState + msgs := []mujica.SessionMessage{{Role: mujica.SessionUser, Text: "Hello"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.ConversationExport(c, &state, msgs, mujica.ConversationExportOptions{Title: "Greeting"}); v.Exported { + log.Println(len(v.Content), "bytes to save") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleRegenerateMenu() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.RegenerateMenu(c, mujica.RegenerateMenuOptions{Models: []string{"Opus", "Sonnet"}, Current: "Opus"}); v.Chosen { + log.Println("retry", v.Choice.Kind, v.Choice.Model, v.Choice.Variant) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleArtifactCard() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ArtifactCard(c, mujica.ArtifactCardOptions{Title: "seating.go", Detail: "Go · 120 lines"}).Changed() { + log.Println("open artifact panel") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleChatEmptyState() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ChatEmptyState(c, mujica.ChatEmptyStateOptions{Kind: mujica.ChatEmptyOffline}).Action { + log.Println("reconnect") + } + } + ui.Render(view, 400, 300, 1) +} diff --git a/examples/gallery/pages_chatsession.go b/examples/gallery/pages_chatsession.go index e315674..7cd7b79 100644 --- a/examples/gallery/pages_chatsession.go +++ b/examples/gallery/pages_chatsession.go @@ -1,3 +1,186 @@ package main -var chatsessionPages = []page{} +const chatsessionCategory = "Chat Sessions" + +var chatsessionPages = []page{ + {ID: "241", Name: "ConversationList", ZhName: "会话列表", Category: chatsessionCategory, Demo: chatDemoConversationList, + Keys: "Up/Down choose a conversation, skipping group headers; typing jumps; Enter opens.", Code: `var state mujica.ConversationListState +convs := []mujica.ChatConversation{ + {ID: "1", Title: "Court etiquette", Updated: time.Now()}, + {ID: "2", Title: "Royal letters", Updated: time.Now().AddDate(0, 0, -30), Pinned: true}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ConversationList(c, &state, convs, mujica.ConversationListOptions{Label: "History"}, nil).Changed() { + log.Println("open", state.Selected) + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "242", Name: "ConversationItem", ZhName: "会话条目", Category: chatsessionCategory, Demo: chatDemoConversationItem, + Keys: "Enter opens; F2 renames in place (Enter keeps, Escape cancels); Delete asks to delete; the ellipsis opens the menu.", Code: `conv := mujica.ChatConversation{ID: "1", Title: "Court etiquette", Updated: time.Now()} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + v := mujica.ConversationItem(c, &conv, mujica.ConversationItemOptions{}) + if v.Deleted { + log.Println("delete", conv.ID) + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "243", Name: "ConversationSearch", ZhName: "会话搜索", Category: chatsessionCategory, Demo: chatDemoConversationSearch, + Keys: "Type to search; Down moves into the results; Up/Down move; Enter opens; Escape clears.", Code: `query := "seat" +hits := []mujica.ConversationSearchHit{{ID: "1", Title: "Ballroom seating plan"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + v := mujica.ConversationSearch(c, &query, hits, mujica.ConversationSearchOptions{}) + if v.QueryChanged { + log.Println("search", query) + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "244", Name: "ProjectList", ZhName: "项目列表", Category: chatsessionCategory, Demo: chatDemoProjectList, + Keys: "Up/Down move through folders, projects and conversations; Right/Left show or hide a project's conversations; the ellipsis menu moves a conversation.", Code: `var state mujica.ProjectListState +projects := []mujica.ChatProject{{ID: "p1", Name: "Coronation", Folder: "Court"}} +convs := func(id string) []mujica.ChatConversation { + return []mujica.ChatConversation{{ID: "1", Title: "Menu"}} +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.ProjectList(c, &state, projects, convs, mujica.ProjectListOptions{}); v.Moved { + log.Println("move", v.MoveID, "to", v.MoveTo) + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "245", Name: "ProjectKnowledgePanel", ZhName: "项目知识面板", Category: chatsessionCategory, Demo: chatDemoProjectKnowledgePanel, + Keys: "Tab reaches Add files and the file list; Up/Down move between remove buttons; Enter removes.", Code: `files := []mujica.KnowledgeFile{{ID: "1", Name: "etiquette.pdf", Tokens: 12000}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + v := mujica.ProjectKnowledgePanel(c, files, mujica.ProjectKnowledgePanelOptions{Capacity: 200000}) + if v.Add { + log.Println("pick files") + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "246", Name: "WelcomeScreen", ZhName: "欢迎页", Category: chatsessionCategory, Demo: chatDemoWelcomeScreen, + Keys: "Tab moves through the cards' examples and the prompt slot; Enter picks.", Code: `cards := []mujica.CapabilityCard{{Title: "Write", Examples: []string{"Draft a decree"}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.WelcomeScreen(c, mujica.WelcomeScreenOptions{Greeting: "Good evening", Cards: cards}); v.Example != "" { + log.Println("ask", v.Example) + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "247", Name: "SuggestionChips", ZhName: "建议标签", Category: chatsessionCategory, Demo: chatDemoSuggestionChips, + Keys: "Tab enters the chips; Left/Right move; Enter or Space picks.", Code: `input := "" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SuggestionChips(c, &input, []string{"Plan a ball", "Write a sonnet"}, mujica.SuggestionChipsOptions{}) +} +ui.Render(view, 400, 300, 1)`}, + {ID: "248", Name: "PromptLibrary", ZhName: "提示模板库", Category: chatsessionCategory, Demo: chatDemoPromptLibrary, + Keys: "Tab moves between categories, search, templates and fields; Up/Down move in a column; Enter picks.", Code: `var state mujica.PromptLibraryState +templates := []mujica.PromptTemplate{{ID: "1", Category: "Letters", Title: "Invitation", Body: "Invite {{guest}}."}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.PromptLibrary(c, &state, templates, mujica.PromptLibraryOptions{}); v.Inserted != "" { + log.Println("insert", v.Inserted) + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "249", Name: "CapabilityCards", ZhName: "能力卡片", Category: chatsessionCategory, Demo: chatDemoCapabilityCards, + Keys: "Tab moves between cards; Up/Down move among a card's examples; Enter picks.", Code: `cards := []mujica.CapabilityCard{{Title: "Plan", Icon: icons.Must("calendar"), Examples: []string{"Plan a ball"}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.CapabilityCards(c, cards, mujica.CapabilityCardsOptions{}); v.Example != "" { + log.Println("ask", v.Example) + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "250", Name: "FeedbackForm", ZhName: "反馈表单", Category: chatsessionCategory, Demo: chatDemoFeedbackForm, + Keys: "Left/Right move among reasons, Space toggles; Escape cancels.", Code: `var value mujica.FeedbackValue +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.FeedbackForm(c, &value, mujica.FeedbackFormOptions{Rating: mujica.FeedbackDown}).Submitted { + log.Println("reasons", value.Reasons) + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "251", Name: "DateSeparator", ZhName: "日期分隔", Category: chatsessionCategory, Demo: chatDemoDateSeparator, + Keys: "Not focusable; read as the date.", Code: `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.DateSeparator(c, mujica.DateOf(time.Now()), mujica.DateSeparatorOptions{}) +} +ui.Render(view, 400, 300, 1)`}, + {ID: "252", Name: "ThinkingIndicator", ZhName: "思考指示", Category: chatsessionCategory, Demo: chatDemoThinkingIndicator, + Keys: "Not focusable; read as a status.", Code: `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ThinkingIndicator(c, mujica.ThinkingIndicatorOptions{Phase: "Searching the archives"}) +} +ui.Render(view, 400, 300, 1)`}, + {ID: "253", Name: "StopGeneratingButton", ZhName: "停止生成按钮", Category: chatsessionCategory, Demo: chatDemoStopGeneratingButton, + Keys: "Enter or Space stops; Cmd+. (Ctrl+. elsewhere) stops from anywhere.", Code: `generating := true +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.StopGeneratingButton(c, mujica.StopGeneratingButtonOptions{Generating: generating}).Changed() { + generating = false + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "254", Name: "SystemPromptEditor", ZhName: "系统提示编辑器", Category: chatsessionCategory, Demo: chatDemoSystemPromptEditor, + Keys: "Cmd+S (Ctrl+S elsewhere) saves.", Code: `prompt, saved := "You are helpful.", "You are helpful." +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.SystemPromptEditor(c, &prompt, mujica.SystemPromptEditorOptions{Default: "You are helpful.", Saved: saved}).Save { + saved = prompt + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "255", Name: "CostEstimator", ZhName: "费用估算", Category: chatsessionCategory, Demo: chatDemoCostEstimator, + Keys: "Not focusable; read as the estimated cost.", Code: `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CostEstimator(c, mujica.CostEstimatorOptions{InputTokens: 12000, OutputTokens: 3400, InputPrice: 3, OutputPrice: 15}) +} +ui.Render(view, 400, 300, 1)`}, + {ID: "256", Name: "SharedConversationView", ZhName: "分享会话视图", Category: chatsessionCategory, Demo: chatDemoSharedConversationView, + Keys: "Tab reaches Copy link and the messages; message text is selectable.", Code: `msgs := []mujica.SessionMessage{{Role: mujica.SessionUser, Text: "Hello"}, {Role: mujica.SessionAssistant, Text: "Good day."}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.SharedConversationView(c, msgs, mujica.SharedConversationViewOptions{Title: "Greeting", SharedBy: "Ann"}).Changed() { + c.WriteClipboard("https://example.com/share/1") + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "257", Name: "ConversationExport", ZhName: "会话导出", Category: chatsessionCategory, Demo: chatDemoConversationExport, + Keys: "Arrows choose a format and range; Tab reaches Export.", Code: `var state mujica.ConversationExportState +msgs := []mujica.SessionMessage{{Role: mujica.SessionUser, Text: "Hello"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.ConversationExport(c, &state, msgs, mujica.ConversationExportOptions{Title: "Greeting"}); v.Exported { + log.Println(len(v.Content), "bytes to save") + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "258", Name: "RegenerateMenu", ZhName: "重新生成菜单", Category: chatsessionCategory, Demo: chatDemoRegenerateMenu, + Keys: "Enter, Space or Down open; Up/Down move; Right opens the model list; Escape closes.", Code: `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if v := mujica.RegenerateMenu(c, mujica.RegenerateMenuOptions{Models: []string{"Opus", "Sonnet"}, Current: "Opus"}); v.Chosen { + log.Println("retry", v.Choice.Kind, v.Choice.Model, v.Choice.Variant) + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "259", Name: "ArtifactCard", ZhName: "产物卡片", Category: chatsessionCategory, Demo: chatDemoArtifactCard, + Keys: "Enter or Space opens the artifact panel.", Code: `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ArtifactCard(c, mujica.ArtifactCardOptions{Title: "seating.go", Detail: "Go · 120 lines"}).Changed() { + log.Println("open artifact panel") + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "260", Name: "ChatEmptyState", ZhName: "会话空状态", Category: chatsessionCategory, Demo: chatDemoChatEmptyState, + Keys: "Tab reaches the action; Enter runs it.", Code: `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ChatEmptyState(c, mujica.ChatEmptyStateOptions{Kind: mujica.ChatEmptyOffline}).Action { + log.Println("reconnect") + } +} +ui.Render(view, 400, 300, 1)`}, +} diff --git a/examples/gallery/pages_chatsession_demos.go b/examples/gallery/pages_chatsession_demos.go new file mode 100644 index 0000000..8594e36 --- /dev/null +++ b/examples/gallery/pages_chatsession_demos.go @@ -0,0 +1,249 @@ +package main + +import ( + "fmt" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" + "mujicaui/icons" +) + +// chatHistory is the gallery's sample conversations, dated from now. +func chatHistory(now time.Time) []mujica.ChatConversation { + day := 24 * time.Hour + return []mujica.ChatConversation{ + {ID: "a", Title: "Court etiquette notes", Updated: now.Add(-2 * time.Hour)}, + {ID: "b", Title: "Ballroom seating plan", Updated: now.Add(-day)}, + {ID: "c", Title: "Harpsichord repair", Updated: now.Add(-4 * day)}, + {ID: "d", Title: "Coronation menu", Updated: now.Add(-40 * day)}, + {ID: "e", Title: "Royal letters", Updated: now.Add(-90 * day), Pinned: true}, + {ID: "f", Title: "Garden maze", Updated: now.Add(-time.Hour)}, + } +} + +func chatSampleMessages(now time.Time) []mujica.SessionMessage { + return []mujica.SessionMessage{ + {Role: mujica.SessionUser, Text: "How should guests be seated at the banquet?", Time: now.Add(-10 * time.Minute)}, + {Role: mujica.SessionAssistant, Text: "Seat by rank: the host at the head, honored guests to the right.", Time: now.Add(-9 * time.Minute)}, + {Role: mujica.SessionUser, Author: "Lady Ann", Text: "And the musicians?", Time: now.Add(-5 * time.Minute)}, + {Role: mujica.SessionAssistant, Text: "Place the quartet behind a screen near the gallery.", Time: now.Add(-4 * time.Minute)}, + } +} + +func chatSampleCards() []mujica.CapabilityCard { + return []mujica.CapabilityCard{ + {Title: "Write", Description: "Letters, speeches and verse.", Icon: icons.Must("file-text"), Examples: []string{"Draft a royal decree", "Write a sonnet"}}, + {Title: "Plan", Description: "Banquets, seating and schedules.", Icon: icons.Must("calendar"), Examples: []string{"Plan a ball for 200 guests"}}, + {Title: "Research", Description: "History, heraldry and music.", Icon: icons.Must("search"), Examples: []string{"Explain the minuet"}}, + } +} + +func chatDemoConversationList(c *ui.Context, log func(string)) { + type state struct { + list mujica.ConversationListState + items []mujica.ChatConversation + many, rich bool + disabled bool + } + s := *ui.Local(c.Root(), "241", func() *state { return &state{items: chatHistory(time.Now())} }) + choiceDemo(c, func() { + if mujica.Switch(c, &s.many, "100,000 conversations", mujica.SwitchOptions{}).Changed() { + s.items = chatHistory(time.Now()) + if s.many { + now := time.Now() + for i := range 100000 { + s.items = append(s.items, mujica.ChatConversation{ID: fmt.Sprint("n", i), Title: fmt.Sprintf("Archive %d", i), Updated: now.Add(-time.Duration(i) * 7 * time.Minute)}) + } + } + log(fmt.Sprintf("conversations = %d", len(s.items))) + } + choiceFlag(c, &s.rich, "ConversationItem rows", log) + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + var row func(conv mujica.ChatConversation) + if s.rich { + row = func(conv mujica.ChatConversation) { + v := mujica.ConversationItem(c, &conv, mujica.ConversationItemOptions{Selected: conv.ID == s.list.Selected}) + if v.Opened { + s.list.Selected = conv.ID + log("open " + conv.Title) + } + } + } + v := mujica.ConversationList(c, &s.list, s.items, mujica.ConversationListOptions{Label: "History", Disabled: s.disabled}, row) + v.Element.Width(380).Height(380) + if v.Changed() { + log("select " + s.list.Selected) + } + if v.Submitted() { + log("open " + s.list.Selected) + } + }) +} + +func chatDemoConversationItem(c *ui.Context, log func(string)) { + type state struct { + convs []mujica.ChatConversation + selected, disabled bool + } + s := *ui.Local(c.Root(), "242", func() *state { return &state{convs: chatHistory(time.Now())[:3]} }) + choiceDemo(c, func() { + choiceFlag(c, &s.selected, "Selected", log) + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + ui.Column(c).Width(420).Gap(4).Children(func() { + for i := range s.convs { + conv := &s.convs[i] + ui.Row(c).Key(conv.ID).Children(func() { + v := mujica.ConversationItem(c, conv, mujica.ConversationItemOptions{Selected: s.selected && i == 0, Disabled: s.disabled}) + switch { + case v.Opened: + log("open " + conv.Title) + case v.Renamed: + log("rename to " + conv.Title) + case v.PinToggled: + conv.Pinned = !conv.Pinned + log(fmt.Sprintf("pinned %s = %v", conv.Title, conv.Pinned)) + case v.Exported: + log("export " + conv.Title) + case v.Deleted: + log("delete " + conv.Title) + } + }) + } + }) + }) +} + +func chatDemoConversationSearch(c *ui.Context, log func(string)) { + type state struct { + query, asked string + at time.Time + hits []mujica.ConversationSearchHit + fail, slow bool + disabled bool + } + s := *ui.Local(c.Root(), "243", func() *state { return &state{} }) + choiceDemo(c, func() { + choiceFlag(c, &s.slow, "Slow server", log) + choiceFlag(c, &s.fail, "Fail searches", log) + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + loading := s.asked != s.query + if loading && (!s.slow || choiceDue(c, s.at)) { + s.asked, s.hits, loading = s.query, nil, false + for _, conv := range chatHistory(time.Now()) { + if q := strings.ToLower(s.query); q != "" && strings.Contains(strings.ToLower(conv.Title), q) { + s.hits = append(s.hits, mujica.ConversationSearchHit{ID: conv.ID, Title: conv.Title, Snippet: "…mentions " + strings.ToLower(conv.Title) + "…"}) + } + } + log(fmt.Sprintf("results for %q: %d", s.query, len(s.hits))) + } + errText := "" + if s.fail && s.query != "" { + errText = "The archive did not answer." + } + ui.Column(c).Width(420).Children(func() { + v := mujica.ConversationSearch(c, &s.query, s.hits, mujica.ConversationSearchOptions{Loading: loading, Error: errText, Disabled: s.disabled, Label: "Search conversations"}) + if v.QueryChanged { + s.at = c.Now() + log(fmt.Sprintf("query %q", s.query)) + } + if v.Chosen != "" { + log("open " + v.Chosen) + } + if v.Retry { + s.fail, s.asked = false, "" + log("retry") + } + }) + }) +} + +func chatDemoProjectList(c *ui.Context, log func(string)) { + type state struct { + list mujica.ProjectListState + owner map[string]string + disabled bool + } + s := *ui.Local(c.Root(), "244", func() *state { + return &state{owner: map[string]string{"a": "p1", "b": "p1", "c": "p3", "f": "p2"}} + }) + projects := []mujica.ChatProject{{ID: "p1", Name: "Coronation", Folder: "Court"}, {ID: "p2", Name: "Gardens", Folder: "Court"}, {ID: "p3", Name: "Music"}} + choiceDemo(c, func() { + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + ui.Row(c).Gap(24).AlignItems(ui.Start).Children(func() { + ui.Column(c).Width(380).Children(func() { + convs := func(id string) []mujica.ChatConversation { + var out []mujica.ChatConversation + for _, conv := range chatHistory(time.Now()) { + if s.owner[conv.ID] == id { + out = append(out, conv) + } + } + return out + } + v := mujica.ProjectList(c, &s.list, projects, convs, mujica.ProjectListOptions{Label: "Projects", Disabled: s.disabled}) + switch { + case v.Moved: + s.owner[v.MoveID] = v.MoveTo + log(fmt.Sprintf("move %s to %s", v.MoveID, v.MoveTo)) + case v.Changed: + log("project " + s.list.Selected) + case v.Opened != "": + log("open " + v.Opened) + } + }) + choiceLabeled(c, "Drag onto a project", func() { + conv := chatHistory(time.Now())[3] + v := mujica.ConversationItem(c, &conv, mujica.ConversationItemOptions{Draggable: true}) + v.Element.Width(300) + if v.Opened { + log("open " + conv.Title) + } + }) + }) + }) +} + +func chatDemoProjectKnowledgePanel(c *ui.Context, log func(string)) { + type state struct { + files []mujica.KnowledgeFile + next int + small bool + disabled bool + } + s := *ui.Local(c.Root(), "245", func() *state { + return &state{files: []mujica.KnowledgeFile{{ID: "1", Name: "etiquette.pdf", Tokens: 120000}, {ID: "2", Name: "menu.md", Tokens: 30000}}} + }) + choiceDemo(c, func() { + choiceFlag(c, &s.small, "Capacity 150,000", log) + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + capacity := 400000 + if s.small { + capacity = 150000 + } + ui.Column(c).Width(440).Children(func() { + v := mujica.ProjectKnowledgePanel(c, s.files, mujica.ProjectKnowledgePanelOptions{Capacity: capacity, Disabled: s.disabled}) + if v.Add { + s.next++ + s.files = append(s.files, mujica.KnowledgeFile{ID: fmt.Sprint("n", s.next), Name: fmt.Sprintf("notes-%d.txt", s.next), Tokens: 15000}) + log("add (the demo invents a file)") + } + if v.Removed != "" { + for i, f := range s.files { + if f.ID == v.Removed { + s.files = append(s.files[:i:i], s.files[i+1:]...) + log("remove " + f.Name) + break + } + } + } + }) + }) +} diff --git a/examples/gallery/pages_chatsession_more.go b/examples/gallery/pages_chatsession_more.go new file mode 100644 index 0000000..b6fd37d --- /dev/null +++ b/examples/gallery/pages_chatsession_more.go @@ -0,0 +1,341 @@ +package main + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func chatDemoWelcomeScreen(c *ui.Context, log func(string)) { + type state struct { + input string + cards, disabled bool + } + s := *ui.Local(c.Root(), "246", func() *state { return &state{cards: true} }) + choiceDemo(c, func() { + choiceFlag(c, &s.cards, "Capability cards", log) + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + var cards []mujica.CapabilityCard + if s.cards { + cards = chatSampleCards() + } + ui.Column(c).Width(860).Children(func() { + v := mujica.WelcomeScreen(c, mujica.WelcomeScreenOptions{Greeting: "Good afternoon", Subtitle: "How may I serve the court?", Cards: cards, Disabled: s.disabled, + Prompts: func() { + if mujica.SuggestionChips(c, &s.input, []string{"Plan a ball", "Write a sonnet"}, mujica.SuggestionChipsOptions{Disabled: s.disabled}).Chosen != "" { + log(fmt.Sprintf("fill %q", s.input)) + } + }}) + if v.Example != "" { + log(fmt.Sprintf("ask %q", v.Example)) + } + }) + }) +} + +func chatDemoSuggestionChips(c *ui.Context, log func(string)) { + type state struct { + input string + send, disabled bool + } + s := *ui.Local(c.Root(), "247", func() *state { return &state{} }) + choiceDemo(c, func() { + choiceFlag(c, &s.send, "Send directly", log) + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + v := mujica.SuggestionChips(c, &s.input, []string{"Plan a ball", "Write a sonnet", "Explain the minuet"}, + mujica.SuggestionChipsOptions{Send: s.send, Label: "Suggestions", Disabled: s.disabled}) + switch { + case v.Sent: + log(fmt.Sprintf("send %q", v.Chosen)) + case v.Chosen != "": + log(fmt.Sprintf("fill %q", v.Chosen)) + } + ui.Column(c).Width(420).Children(func() { + mujica.TextInput(c, &s.input, mujica.TextInputOptions{Label: "Message", Placeholder: "Message"}) + }) + }) +} + +func chatDemoPromptLibrary(c *ui.Context, log func(string)) { + type state struct { + lib mujica.PromptLibraryState + disabled bool + } + s := *ui.Local(c.Root(), "248", func() *state { return &state{} }) + templates := []mujica.PromptTemplate{ + {ID: "t1", Category: "Letters", Title: "Invitation", Body: "Write an invitation to {{guest}} for the {{event}}."}, + {ID: "t2", Category: "Letters", Title: "Thank-you note", Body: "Thank {{host}} for the evening."}, + {ID: "t3", Category: "Music", Title: "Recital program", Body: "List pieces for a {{instrument}} recital."}, + {ID: "t4", Category: "Planning", Title: "Seating chart", Body: "Seat {{count}} guests by rank."}, + } + choiceDemo(c, func() { + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + before := s.lib.Selected + v := mujica.PromptLibrary(c, &s.lib, templates, mujica.PromptLibraryOptions{Label: "Prompt library", Disabled: s.disabled}) + if s.lib.Selected != before { + log("preview " + s.lib.Selected) + } + if v.Inserted != "" { + log(fmt.Sprintf("insert %q", v.Inserted)) + } + }) +} + +func chatDemoCapabilityCards(c *ui.Context, log func(string)) { + type state struct { + one, disabled bool + } + s := *ui.Local(c.Root(), "249", func() *state { return &state{} }) + choiceDemo(c, func() { + choiceFlag(c, &s.one, "One column", log) + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + cols := 0 + if s.one { + cols = 1 + } + ui.Column(c).Width(860).Children(func() { + if v := mujica.CapabilityCards(c, chatSampleCards(), mujica.CapabilityCardsOptions{Columns: cols, Disabled: s.disabled}); v.Example != "" { + log(fmt.Sprintf("ask %q", v.Example)) + } + }) + }) +} + +func chatDemoFeedbackForm(c *ui.Context, log func(string)) { + type state struct { + value mujica.FeedbackValue + down, submitting bool + disabled bool + at time.Time + } + s := *ui.Local(c.Root(), "250", func() *state { return &state{down: true} }) + choiceDemo(c, func() { + choiceFlag(c, &s.down, "Thumbs down", log) + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + rating := mujica.FeedbackUp + if s.down { + rating = mujica.FeedbackDown + } + if s.submitting && choiceDue(c, s.at) { + s.submitting, s.value = false, mujica.FeedbackValue{} + log("feedback sent") + } + ui.Column(c).Width(480).Children(func() { + v := mujica.FeedbackForm(c, &s.value, mujica.FeedbackFormOptions{Rating: rating, Submitting: s.submitting, Disabled: s.disabled}) + if v.Submitted { + s.submitting, s.at = true, c.Now() + log(fmt.Sprintf("submit reasons %q, %d characters", s.value.Reasons, len(s.value.Comment))) + } + if v.Cancelled { + s.value = mujica.FeedbackValue{} + log("cancel") + } + }) + }) +} + +func chatDemoDateSeparator(c *ui.Context, log func(string)) { + today := mujica.DateOf(time.Now()) + choiceDemo(c, func() { + ui.Text(c, "No parameters; the language follows the window.") + }, func() { + ui.Column(c).Width(520).Children(func() { + for _, d := range []int{0, -1, -12} { + mujica.DateSeparator(c, today.AddDays(d), mujica.DateSeparatorOptions{}) + } + }) + }) +} + +func chatDemoThinkingIndicator(c *ui.Context, log func(string)) { + type state struct{ phase int } + s := *ui.Local(c.Root(), "252", func() *state { return &state{} }) + phases := []string{"", "Searching the archives", "Reading 3 letters", "Composing a reply"} + choiceDemo(c, func() { + if mujica.Button(c, "Next phase", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.phase = (s.phase + 1) % len(phases) + log(fmt.Sprintf("phase %q", phases[s.phase])) + } + }, func() { + mujica.ThinkingIndicator(c, mujica.ThinkingIndicatorOptions{Phase: phases[s.phase]}) + }) +} + +func chatDemoStopGeneratingButton(c *ui.Context, log func(string)) { + type state struct { + generating, disabled bool + at time.Time + } + s := *ui.Local(c.Root(), "253", func() *state { return &state{} }) + choiceDemo(c, func() { + if mujica.Button(c, "Generate", mujica.ButtonOptions{Disabled: s.generating}).Clicked() { + s.generating, s.at = true, c.Now() + log("generate") + } + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + if s.generating && c.Now().Sub(s.at) > 8*time.Second { + s.generating = false + log("finished") + } else if s.generating { + c.After(time.Second) + } + if mujica.StopGeneratingButton(c, mujica.StopGeneratingButtonOptions{Generating: s.generating, Disabled: s.disabled}).Changed() { + s.generating = false + log("stop") + } + if !s.generating { + ui.Text(c, "Idle: the button is hidden.").TextColor(mujica.Tokens(c).TextMuted) + } + }) +} + +func chatDemoSystemPromptEditor(c *ui.Context, log func(string)) { + type state struct { + value, saved string + limit, disabled bool + saving bool + at time.Time + } + s := *ui.Local(c.Root(), "254", func() *state { + return &state{value: "You are a courtly assistant.", saved: "You are a courtly assistant."} + }) + choiceDemo(c, func() { + choiceFlag(c, &s.limit, "Limit 60", log) + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + if s.saving && choiceDue(c, s.at) { + s.saving, s.saved = false, s.value + log("saved") + } + limit := 0 + if s.limit { + limit = 60 + } + ui.Column(c).Width(520).Children(func() { + v := mujica.SystemPromptEditor(c, &s.value, mujica.SystemPromptEditorOptions{Default: "You are helpful.", Saved: s.saved, + MaxLength: limit, Saving: s.saving, Disabled: s.disabled}) + if v.Save { + s.saving, s.at = true, c.Now() + log(fmt.Sprintf("save %d characters", len(s.value))) + } + if v.Restored { + log("restore default") + } + }) + }) +} + +func chatDemoCostEstimator(c *ui.Context, log func(string)) { + type state struct{ in, out, inPrice, outPrice float64 } + s := *ui.Local(c.Root(), "255", func() *state { return &state{in: 12000, out: 3400, inPrice: 3, outPrice: 15} }) + choiceDemo(c, func() { + for _, f := range []struct { + v *float64 + label string + }{{&s.in, "Input tokens"}, {&s.out, "Output tokens"}, {&s.inPrice, "Input $/M"}, {&s.outPrice, "Output $/M"}} { + choiceLabeled(c, f.label, func() { + r := mujica.NumberInput(c, f.v, mujica.NumberInputOptions{Min: 0, Max: 1e7, Step: 100, Label: f.label}) + r.Element.Width(150) + if r.Changed() { + log(fmt.Sprintf("%s = %v", f.label, *f.v)) + } + }) + } + }, func() { + ui.Column(c).Width(420).Children(func() { + mujica.CostEstimator(c, mujica.CostEstimatorOptions{InputTokens: int(s.in), OutputTokens: int(s.out), InputPrice: s.inPrice, OutputPrice: s.outPrice}) + }) + }) +} + +func chatDemoSharedConversationView(c *ui.Context, log func(string)) { + type state struct{ disabled bool } + s := *ui.Local(c.Root(), "256", func() *state { return &state{} }) + choiceDemo(c, func() { + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + ui.Column(c).Width(600).Height(420).Children(func() { + if mujica.SharedConversationView(c, chatSampleMessages(time.Now()), mujica.SharedConversationViewOptions{Title: "Banquet seating", + SharedBy: "Lady Ann", SharedAt: time.Now(), Disabled: s.disabled}).Changed() { + c.WriteClipboard("https://example.com/share/banquet") + log("copy link") + } + }) + }) +} + +func chatDemoConversationExport(c *ui.Context, log func(string)) { + type state struct { + export mujica.ConversationExportState + disabled bool + } + s := *ui.Local(c.Root(), "257", func() *state { return &state{} }) + choiceDemo(c, func() { + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + ui.Column(c).Width(580).Children(func() { + v := mujica.ConversationExport(c, &s.export, chatSampleMessages(time.Now()), mujica.ConversationExportOptions{Title: "Banquet seating", + Selected: []int{1, 3}, Disabled: s.disabled}) + if v.Exported { + log(fmt.Sprintf("export %d bytes as format %d (the caller writes the file)", len(v.Content), v.Format)) + } + }) + }) +} + +func chatDemoRegenerateMenu(c *ui.Context, log func(string)) { + type state struct{ disabled bool } + s := *ui.Local(c.Root(), "258", func() *state { return &state{} }) + choiceDemo(c, func() { + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + v := mujica.RegenerateMenu(c, mujica.RegenerateMenuOptions{Models: []string{"Opus", "Sonnet", "Haiku"}, Current: "Opus", Disabled: s.disabled}) + if v.Chosen { + log(fmt.Sprintf("retry kind %d model %q variant %q", v.Choice.Kind, v.Choice.Model, v.Choice.Variant)) + } + }) +} + +func chatDemoArtifactCard(c *ui.Context, log func(string)) { + type state struct{ streaming, disabled bool } + s := *ui.Local(c.Root(), "259", func() *state { return &state{} }) + choiceDemo(c, func() { + choiceFlag(c, &s.streaming, "Streaming", log) + choiceFlag(c, &s.disabled, "Disabled", log) + }, func() { + for _, a := range []mujica.ArtifactCardOptions{ + {Kind: mujica.ArtifactCode, Title: "seating.go", Detail: "Go · 120 lines"}, + {Kind: mujica.ArtifactDocument, Title: "Royal decree", Detail: "2 pages"}, + {Kind: mujica.ArtifactWeb, Title: "Ball invitation"}, + } { + a.Streaming, a.Disabled = s.streaming, s.disabled + if mujica.ArtifactCard(c, a).Changed() { + log("open " + a.Title) + } + } + }) +} + +func chatDemoChatEmptyState(c *ui.Context, log func(string)) { + type state struct{ kind int } + s := *ui.Local(c.Root(), "260", func() *state { return &state{} }) + choiceDemo(c, func() { + mujica.RadioGroup(c, &s.kind, []mujica.RadioItem[int]{{Value: 0, Label: "New"}, {Value: 1, Label: "No results"}, {Value: 2, Label: "Offline"}}, + mujica.RadioGroupOptions{Horizontal: true, Label: "Kind"}) + }, func() { + ui.Column(c).Width(420).Children(func() { + if mujica.ChatEmptyState(c, mujica.ChatEmptyStateOptions{Kind: mujica.ChatEmptyKind(s.kind), Query: "minuet"}).Action { + log(fmt.Sprintf("action for kind %d", s.kind)) + } + }) + }) +} diff --git a/feedback_form_test.go b/feedback_form_test.go new file mode 100644 index 0000000..8cb86e0 --- /dev/null +++ b/feedback_form_test.go @@ -0,0 +1,75 @@ +package mujica + +import ( + "slices" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestFeedbackFormReasonsAndSubmit(t *testing.T) { + var v FeedbackValue + var last FeedbackFormView + tt := chatTester(480, 420, func(c *ui.Context) { + if r := FeedbackForm(c, &v, FeedbackFormOptions{Rating: FeedbackDown}); r.Submitted || r.Cancelled { + last = r + } + }) + if !tt.HasText("What went wrong?") || !tt.HasText("Harmful or unsafe") { + t.Fatalf("texts %q", tt.Texts()) + } + _ = tt.Click("Incorrect") + _ = tt.Click("Not helpful") + _ = tt.Click("Incorrect") + if !slices.Equal(v.Reasons, []string{"Not helpful"}) { + t.Fatalf("reasons %q", v.Reasons) + } + _ = tt.Click("Tell us more (optional)") + tt.Type("Wrong date") + _ = tt.Click("Submit") + if !last.Submitted || v.Comment != "Wrong date" { + t.Fatalf("submit %+v comment %q", last, v.Comment) + } +} + +func TestFeedbackFormCancelAndUpReasons(t *testing.T) { + var v FeedbackValue + var last FeedbackFormView + tt := chatTester(480, 420, func(c *ui.Context) { + if r := FeedbackForm(c, &v, FeedbackFormOptions{Reasons: []string{"Elegant"}}); r.Submitted || r.Cancelled { + last = r + } + }) + if !tt.HasText("What did you like?") || !tt.HasText("Elegant") { + t.Fatalf("texts %q", tt.Texts()) + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEscape) + if !last.Cancelled { + t.Fatal("Escape did not cancel") + } +} + +func TestFeedbackFormBlocked(t *testing.T) { + for _, opts := range []FeedbackFormOptions{{Disabled: true}, {Submitting: true}} { + var v FeedbackValue + submitted := false + tt := chatTester(480, 420, func(c *ui.Context) { + if FeedbackForm(c, &v, opts).Submitted { + submitted = true + } + }) + _ = tt.Click("Accurate") + _ = tt.Click("Submit") + if submitted || len(v.Reasons) != 0 { + t.Fatalf("%+v: blocked form acted", opts) + } + } +} + +func TestFeedbackFormSnapshot(t *testing.T) { + snapshot(t, "feedback_form", 480, 300, func(c *ui.Context) { + v := FeedbackValue{Reasons: []string{"Incorrect"}} + ui.Column(c).Padding(16).Children(func() { FeedbackForm(c, &v, FeedbackFormOptions{Rating: FeedbackDown}) }) + }) +} diff --git a/messages_chatsession.go b/messages_chatsession.go index 6151bf6..94f4957 100644 --- a/messages_chatsession.go +++ b/messages_chatsession.go @@ -65,12 +65,11 @@ func init() { "stop_generating_button.stop": {"Stop generating", "停止生成"}, - "system_prompt_editor.title": {"System prompt", "系统提示"}, - "system_prompt_editor.unsaved": {"Unsaved changes", "未保存"}, - "system_prompt_editor.count": {"%d characters", "%d 字"}, - "system_prompt_editor.count_of": {"%d / %d characters", "%d / %d 字"}, - "system_prompt_editor.restore": {"Restore default", "恢复默认"}, - "system_prompt_editor.save": {"Save", "保存"}, + "system_prompt_editor.title": {"System prompt", "系统提示"}, + "system_prompt_editor.unsaved": {"Unsaved changes", "未保存"}, + "system_prompt_editor.count": {"%d characters", "%d 字"}, + "system_prompt_editor.restore": {"Restore default", "恢复默认"}, + "system_prompt_editor.save": {"Save", "保存"}, "cost_estimator.kind": {"Kind", "类别"}, "cost_estimator.tokens": {"Tokens", "Tokens"}, diff --git a/project_knowledge_panel_test.go b/project_knowledge_panel_test.go new file mode 100644 index 0000000..1b6ac0f --- /dev/null +++ b/project_knowledge_panel_test.go @@ -0,0 +1,110 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func knowledgeFiles() []KnowledgeFile { + return []KnowledgeFile{{ID: "1", Name: "etiquette.pdf", Tokens: 120000}, {ID: "2", Name: "menu.md", Tokens: 50000}} +} + +func TestProjectKnowledgePanelAddRemove(t *testing.T) { + files := knowledgeFiles() + adds := 0 + tt := chatTester(420, 400, func(c *ui.Context) { + v := ProjectKnowledgePanel(c, files, ProjectKnowledgePanelOptions{Capacity: 400000}) + if v.Add { + adds++ + } + if v.Removed != "" { + for i, f := range files { + if f.ID == v.Removed { + files = append(files[:i:i], files[i+1:]...) + break + } + } + } + }) + if !tt.HasText("170000 of 400000 tokens (42%)") { + t.Fatalf("texts %q", tt.Texts()) + } + _ = tt.Click("Add files") + if adds != 1 { + t.Fatalf("adds %d", adds) + } + if err := tt.Click("Remove menu.md"); err != nil { + t.Fatal(err) + } + if len(files) != 1 || files[0].ID != "1" || !tt.HasText("120000 of 400000 tokens (30%)") { + t.Fatalf("files %v texts %q", files, tt.Texts()) + } +} + +func TestProjectKnowledgePanelCapacityStates(t *testing.T) { + for _, tc := range []struct { + capacity int + note string + }{{200000, "Nearly full"}, {150000, "Over capacity"}} { + tt := chatTester(420, 400, func(c *ui.Context) { + ProjectKnowledgePanel(c, knowledgeFiles(), ProjectKnowledgePanelOptions{Capacity: tc.capacity}) + }) + if !tt.HasText(tc.note) { + t.Errorf("%d: texts %q", tc.capacity, tt.Texts()) + } + } + tt := chatTester(420, 400, func(c *ui.Context) { + ProjectKnowledgePanel(c, nil, ProjectKnowledgePanelOptions{Capacity: 10}) + }) + if !tt.HasText("No files yet") { + t.Fatal("empty state missing") + } +} + +func TestProjectKnowledgePanelDisabledAndKeys(t *testing.T) { + removed := "" + tt := chatTester(420, 400, func(c *ui.Context) { + if v := ProjectKnowledgePanel(c, knowledgeFiles(), ProjectKnowledgePanelOptions{Capacity: 400000, Disabled: true}); v.Removed != "" { + removed = v.Removed + } + }) + _ = tt.Click("Remove menu.md") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if removed != "" { + t.Fatalf("disabled panel removed %q", removed) + } + tt = chatTester(420, 400, func(c *ui.Context) { + if v := ProjectKnowledgePanel(c, knowledgeFiles(), ProjectKnowledgePanelOptions{Capacity: 400000}); v.Removed != "" { + removed = v.Removed + } + }) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if removed != "2" { + t.Fatalf("keys removed %q", removed) + } +} + +func TestProjectKnowledgePanelRejectsBadCapacity(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + ProjectKnowledgePanel(c, nil, ProjectKnowledgePanelOptions{}) + }, 100, 100, 1) +} + +func TestProjectKnowledgePanelSnapshot(t *testing.T) { + snapshot(t, "project_knowledge_panel", 420, 240, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + ProjectKnowledgePanel(c, knowledgeFiles(), ProjectKnowledgePanelOptions{Capacity: 200000}) + }) + }) +} diff --git a/project_list.go b/project_list.go index 06e7b56..4c21553 100644 --- a/project_list.go +++ b/project_list.go @@ -199,7 +199,7 @@ func projectListConversation(c *ui.Context, conv ChatConversation, home ChatProj if b.Clicked() { v.Opened = conv.ID } - DropdownMenu(c, "", DropdownMenuOptions{Icon: icons.Must("ellipsis"), Label: fmt.Sprintf(msg(c, "project_list.move_to"), conv.Title)}, func(m *PopupMenu) { + conversationItemMenu(c, fmt.Sprintf(msg(c, "project_list.move_to"), conv.Title), func(m *PopupMenu) { m.Group(msg(c, "project_list.move_group"), func() { for _, p := range all { if p.ID != home.ID && m.Item(p.Name, PopupMenuItemOptions{}) { @@ -207,6 +207,6 @@ func projectListConversation(c *ui.Context, conv ChatConversation, home ChatProj } } }) - }).Shrink(0) + }) }) } diff --git a/project_list_test.go b/project_list_test.go new file mode 100644 index 0000000..4042954 --- /dev/null +++ b/project_list_test.go @@ -0,0 +1,138 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +type projectFixture struct { + s ProjectListState + projects []ChatProject + owner map[string]string + last ProjectListView + moves int +} + +func newProjectFixture() *projectFixture { + return &projectFixture{ + projects: []ChatProject{{ID: "p1", Name: "Coronation", Folder: "Court"}, {ID: "p2", Name: "Gardens", Folder: "Court"}, {ID: "p3", Name: "Music"}}, + owner: map[string]string{"a": "p1", "b": "p1", "c": "p3"}, + } +} + +func (f *projectFixture) view(opts ProjectListOptions) func(c *ui.Context) { + return func(c *ui.Context) { + convs := func(id string) []ChatConversation { + var out []ChatConversation + for _, conv := range chatConversations() { + if f.owner[conv.ID] == id { + out = append(out, conv) + } + } + return out + } + v := ProjectList(c, &f.s, f.projects, convs, opts) + if v.Moved { + f.owner[v.MoveID] = v.MoveTo + f.moves++ + } + if v.Changed || v.Opened != "" || v.Moved { + f.last = v + } + } +} + +func TestProjectListSelectAndExpand(t *testing.T) { + f := newProjectFixture() + tt := chatTester(420, 500, f.view(ProjectListOptions{Label: "Projects"})) + if err := tt.Click("Gardens"); err != nil { + t.Fatal(err) + } + if f.s.Selected != "p2" || !f.last.Changed { + t.Fatalf("selected %q", f.s.Selected) + } + if tt.HasText("Court etiquette notes") { + t.Fatal("conversations shown before expanding") + } + _ = tt.Click("Show conversations in Coronation") + if !tt.HasText("Court etiquette notes") || !tt.HasText("Ballroom seating plan") { + t.Fatalf("texts %q", tt.Texts()) + } + _ = tt.Click("Court etiquette notes") + if f.last.Opened != "a" { + t.Fatalf("opened %q", f.last.Opened) + } + // The folder collapses its projects. + _ = tt.Click("Court") + if tt.HasText("Gardens") { + t.Fatal("folder did not collapse") + } +} + +func TestProjectListKeyboard(t *testing.T) { + f := newProjectFixture() + tt := chatTester(420, 500, f.view(ProjectListOptions{})) + tt.Key(0, ui.KeyTab) + if !tt.Focused("Court") { + t.Fatal("Tab did not enter at the folder") + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyRight) + if !tt.HasText("Court etiquette notes") { + t.Fatal("Right did not expand") + } + tt.Key(0, ui.KeyEnter) + if f.s.Selected != "p1" { + t.Fatalf("Enter chose %q", f.s.Selected) + } + tt.Key(0, ui.KeyLeft) + if tt.HasText("Court etiquette notes") { + t.Fatal("Left did not collapse") + } +} + +func TestProjectListMoveByMenuAndDrag(t *testing.T) { + f := newProjectFixture() + tt := chatTester(420, 500, f.view(ProjectListOptions{})) + _ = tt.Click("Show conversations in Coronation") + if err := tt.Click("Move Court etiquette notes"); err != nil { + t.Fatal(err) + } + // The menu opens on Gardens; Down reaches Music. + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if f.owner["a"] != "p3" || f.moves != 1 { + t.Fatalf("menu move: owner %q moves %d", f.owner["a"], f.moves) + } + from, _ := tt.Find("Ballroom seating plan") + to, _ := tt.Find("Gardens") + tt.Press(from.X+5, from.Y+from.H/2) + tt.Move(from.X+20, from.Y+from.H/2+5) + tt.Move(to.X+10, to.Y+to.H/2) + tt.Release(to.X+10, to.Y+to.H/2) + if f.owner["b"] != "p2" || f.last.MoveTo != "p2" { + t.Fatalf("drag move: owner %q", f.owner["b"]) + } +} + +func TestProjectListDisabled(t *testing.T) { + f := newProjectFixture() + tt := chatTester(420, 500, f.view(ProjectListOptions{Disabled: true})) + _ = tt.Click("Gardens") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if f.s.Selected != "" || f.moves != 0 { + t.Fatalf("disabled list acted: %q", f.s.Selected) + } +} + +func TestProjectListSnapshot(t *testing.T) { + snapshot(t, "project_list", 380, 280, func(c *ui.Context) { + f := newProjectFixture() + f.s.Selected = "p1" + f.s.open = map[string]bool{"p1": true} + f.s.closed = map[string]bool{} + ui.Column(c).Padding(16).Children(func() { f.view(ProjectListOptions{})(c) }) + }) +} diff --git a/prompt_library_test.go b/prompt_library_test.go new file mode 100644 index 0000000..63f56e7 --- /dev/null +++ b/prompt_library_test.go @@ -0,0 +1,105 @@ +package mujica + +import ( + "slices" + "testing" + + "github.com/egoist/mygo/ui" +) + +func promptTemplates() []PromptTemplate { + return []PromptTemplate{ + {ID: "t1", Category: "Letters", Title: "Invitation", Body: "Write an invitation to {{guest}} for the {{event}}."}, + {ID: "t2", Category: "Music", Title: "Recital program", Body: "List pieces for a {{ instrument }} recital, then thank {{guest}}."}, + {ID: "t3", Category: "Letters", Title: "Thank-you note", Body: "Thank the hosts."}, + } +} + +func TestPromptLibraryVariables(t *testing.T) { + if got := PromptLibraryVariables("{{a}} and {{ b }} and {{a}}"); !slices.Equal(got, []string{"a", "b"}) { + t.Fatalf("variables %q", got) + } + if got := PromptLibraryFill("Hi {{ name }}, {{x}}!", map[string]string{"name": "Ann"}); got != "Hi Ann, !" { + t.Fatalf("fill %q", got) + } +} + +func TestPromptLibraryBrowseFillInsert(t *testing.T) { + var s PromptLibraryState + templates := promptTemplates() + inserted := "" + tt := chatTester(940, 520, func(c *ui.Context) { + if v := PromptLibrary(c, &s, templates, PromptLibraryOptions{Label: "Prompts"}); v.Inserted != "" { + inserted = v.Inserted + } + }) + _ = tt.Click("Music") + if tt.HasText("Invitation") || !tt.HasText("Recital program") { + t.Fatalf("category filter: %q", tt.Texts()) + } + _ = tt.Click("All") + _ = tt.Click("Search prompts") + tt.Type("thank") + if tt.HasText("Invitation") || !tt.HasText("Thank-you note") || !tt.HasText("Recital program") { + t.Fatalf("search covers titles and bodies: %q", tt.Texts()) + } + _ = tt.Click("Recital program") + if !tt.HasText("[instrument]") { + t.Fatal("placeholder not previewed") + } + _ = tt.Click("Insert") + if inserted != "" { + t.Fatal("inserted with empty variables") + } + // Each variable's field sits under its label. + for _, f := range [][2]string{{"instrument", "harp"}, {"guest", "the duke"}} { + r, _ := tt.Find(f[0]) + tt.ClickAt(r.X+20, r.Y+r.H+18) + tt.Type(f[1]) + } + _ = tt.Click("Insert") + if inserted != "List pieces for a harp recital, then thank the duke." { + t.Fatalf("inserted %q", inserted) + } +} + +func TestPromptLibraryKeyboardAndDisabled(t *testing.T) { + var s PromptLibraryState + tt := chatTester(940, 520, func(c *ui.Context) { PromptLibrary(c, &s, promptTemplates(), PromptLibraryOptions{}) }) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if s.Category != "Letters" { + t.Fatalf("keys chose category %q", s.Category) + } + var d PromptLibraryState + tt = chatTester(940, 520, func(c *ui.Context) { PromptLibrary(c, &d, promptTemplates(), PromptLibraryOptions{Disabled: true}) }) + _ = tt.Click("Invitation") + _ = tt.Click("Music") + if d.Selected != "" || d.Category != "" { + t.Fatalf("disabled library chose %q %q", d.Selected, d.Category) + } +} + +func TestPromptLibraryFiltersOnlyOnChange(t *testing.T) { + var s PromptLibraryState + templates := promptTemplates() + tt := chatTester(940, 520, func(c *ui.Context) { PromptLibrary(c, &s, templates, PromptLibraryOptions{}) }) + s.shown.cats = append(s.shown.cats, "Marker") + tt.Frame() + if !slices.Contains(s.shown.cats, "Marker") { + t.Fatal("refiltered without a change") + } + s.Query = "invit" + tt.Frame() + if !slices.Equal(s.shown.ids, []int{0}) { + t.Fatalf("ids %v", s.shown.ids) + } +} + +func TestPromptLibrarySnapshot(t *testing.T) { + snapshot(t, "prompt_library", 900, 360, func(c *ui.Context) { + s := &PromptLibraryState{Selected: "t1", Values: map[string]string{"guest": "Lady Ann"}} + ui.Column(c).Padding(16).Children(func() { PromptLibrary(c, s, promptTemplates(), PromptLibraryOptions{}) }) + }) +} diff --git a/regenerate_menu.go b/regenerate_menu.go index d122e0e..b224406 100644 --- a/regenerate_menu.go +++ b/regenerate_menu.go @@ -80,6 +80,7 @@ func RegenerateMenu(c *ui.Context, opts RegenerateMenuOptions) RegenerateMenuVie } }) }) + v.Element.AlignSelf(ui.Start) if v.Element.IsDisabled() { v.Chosen = false } diff --git a/regenerate_menu_test.go b/regenerate_menu_test.go new file mode 100644 index 0000000..1f44c46 --- /dev/null +++ b/regenerate_menu_test.go @@ -0,0 +1,70 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func regenerateTester(opts RegenerateMenuOptions, got *[]RegenerateChoice) *ui.Tester { + return chatTester(500, 420, func(c *ui.Context) { + if v := RegenerateMenu(c, opts); v.Chosen { + *got = append(*got, v.Choice) + } + }) +} + +func TestRegenerateMenuChoices(t *testing.T) { + var got []RegenerateChoice + opts := RegenerateMenuOptions{Models: []string{"Opus", "Sonnet"}, Current: "Opus"} + tt := regenerateTester(opts, &got) + _ = tt.Click("Regenerate") + _ = tt.Click("Try again") + _ = tt.Click("Regenerate") + _ = tt.Click("Shorter") + if len(got) != 2 || got[0].Kind != RegenerateAgain || got[1] != (RegenerateChoice{Kind: RegenerateVariant, Variant: "Shorter"}) { + t.Fatalf("choices %+v", got) + } + _ = tt.Click("Regenerate") + _ = tt.Click("Try another model") + if tt.HasText("Opus") || !tt.HasText("Sonnet") { + t.Fatalf("model submenu %q", tt.Texts()) + } + _ = tt.Click("Sonnet") + if len(got) != 3 || got[2] != (RegenerateChoice{Kind: RegenerateModel, Model: "Sonnet"}) { + t.Fatalf("choices %+v", got) + } +} + +func TestRegenerateMenuKeyboardAndVariants(t *testing.T) { + var got []RegenerateChoice + tt := regenerateTester(RegenerateMenuOptions{Variants: []string{"In verse"}}, &got) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if len(got) != 1 || got[0].Kind != RegenerateAgain { + t.Fatalf("keys chose %+v", got) + } + _ = tt.Click("Regenerate") + if !tt.HasText("In verse") || tt.HasText("Longer") { + t.Fatalf("variants %q", tt.Texts()) + } +} + +func TestRegenerateMenuDisabled(t *testing.T) { + var got []RegenerateChoice + tt := regenerateTester(RegenerateMenuOptions{Disabled: true}, &got) + _ = tt.Click("Regenerate") + _ = tt.Click("Try again") + if len(got) != 0 || tt.HasText("Try again") { + t.Fatalf("disabled menu chose %+v", got) + } +} + +func TestRegenerateMenuSnapshot(t *testing.T) { + snapshotAfter(t, "regenerate_menu", 360, 330, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + RegenerateMenu(c, RegenerateMenuOptions{Models: []string{"Opus", "Sonnet"}, Current: "Opus"}) + }) + }, func(tt *ui.Tester) { _ = tt.Click("Regenerate") }) +} diff --git a/shared_conversation_view_test.go b/shared_conversation_view_test.go new file mode 100644 index 0000000..43fae0e --- /dev/null +++ b/shared_conversation_view_test.go @@ -0,0 +1,70 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestSharedConversationViewShowsAndCopies(t *testing.T) { + copies := 0 + tt := chatTester(560, 460, func(c *ui.Context) { + if SharedConversationView(c, chatMessages(), SharedConversationViewOptions{Title: "Banquet seating", SharedBy: "Lady Ann", SharedAt: chatNow}).Changed() { + copies++ + } + }) + for _, s := range []string{"Banquet seating", "Shared by Lady Ann", "Read only", "You", "Assistant", "Lady Ann", "And the musicians?"} { + if !tt.HasText(s) { + t.Errorf("%q missing from %q", s, tt.Texts()) + } + } + _ = tt.Click("Copy link") + tt.Key(0, ui.KeyEnter) + if copies != 2 { + t.Fatalf("copies %d", copies) + } +} + +func TestSharedConversationViewVirtualizes(t *testing.T) { + msgs := make([]SessionMessage, 100000) + for i := range msgs { + msgs[i] = SessionMessage{Role: SessionRole(i % 2), Text: fmt.Sprintf("Message %d", i)} + } + tt := chatTester(560, 460, func(c *ui.Context) { + SharedConversationView(c, msgs, SharedConversationViewOptions{Title: "Long"}) + }) + if n := len(tt.Texts()); n > 80 { + t.Fatalf("built %d texts for 100000 messages", n) + } +} + +func TestSharedConversationViewDisabledAndChecks(t *testing.T) { + copies := 0 + tt := chatTester(560, 460, func(c *ui.Context) { + if SharedConversationView(c, chatMessages(), SharedConversationViewOptions{Title: "T", Disabled: true}).Changed() { + copies++ + } + }) + _ = tt.Click("Copy link") + if copies != 0 || !tt.HasText("Shared by someone") { + t.Fatalf("copies %d texts %q", copies, tt.Texts()) + } + defer func() { + if recover() == nil { + t.Fatal("no panic for a missing title") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + SharedConversationView(c, nil, SharedConversationViewOptions{}) + }, 100, 100, 1) +} + +func TestSharedConversationViewSnapshot(t *testing.T) { + snapshot(t, "shared_conversation_view", 560, 380, func(c *ui.Context) { + ui.Column(c).Padding(16).Height(380).Children(func() { + SharedConversationView(c, chatMessages(), SharedConversationViewOptions{Title: "Banquet seating", SharedBy: "Lady Ann", SharedAt: chatNow}) + }) + }) +} diff --git a/stop_generating_button_test.go b/stop_generating_button_test.go new file mode 100644 index 0000000..c6663b4 --- /dev/null +++ b/stop_generating_button_test.go @@ -0,0 +1,65 @@ +package mujica + +import ( + "runtime" + "testing" + + "github.com/egoist/mygo/ui" +) + +func chatMod() ui.Modifiers { + if runtime.GOOS == "darwin" { + return ui.Cmd + } + return ui.Ctrl +} + +func TestStopGeneratingButtonClickAndShortcut(t *testing.T) { + generating, stops := true, 0 + tt := chatTester(400, 120, func(c *ui.Context) { + if StopGeneratingButton(c, StopGeneratingButtonOptions{Generating: generating}).Changed() { + stops++ + generating = false + } + }) + if err := tt.Click("Stop generating"); err != nil { + t.Fatal(err) + } + if stops != 1 || tt.HasText("Stop generating") { + t.Fatalf("stops %d, still shown %v", stops, tt.HasText("Stop generating")) + } + generating = true + tt.Frame() + tt.Key(chatMod(), ui.KeyPeriod) + if stops != 2 { + t.Fatalf("shortcut stops %d", stops) + } + tt.Key(chatMod(), ui.KeyPeriod) + if stops != 2 { + t.Fatal("shortcut acted while hidden") + } +} + +func TestStopGeneratingButtonDisabled(t *testing.T) { + stops := 0 + tt := chatTester(400, 120, func(c *ui.Context) { + if StopGeneratingButton(c, StopGeneratingButtonOptions{Generating: true, Disabled: true}).Changed() { + stops++ + } + }) + _ = tt.Click("Stop generating") + tt.Key(chatMod(), ui.KeyPeriod) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if stops != 0 { + t.Fatalf("disabled button stopped %d times", stops) + } +} + +func TestStopGeneratingButtonSnapshot(t *testing.T) { + snapshot(t, "stop_generating_button", 300, 70, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + StopGeneratingButton(c, StopGeneratingButtonOptions{Generating: true}) + }) + }) +} diff --git a/suggestion_chips_test.go b/suggestion_chips_test.go new file mode 100644 index 0000000..87eb259 --- /dev/null +++ b/suggestion_chips_test.go @@ -0,0 +1,76 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +var chipTexts = []string{"Plan a ball", "Write a sonnet", "Explain the minuet"} + +func TestSuggestionChipsFill(t *testing.T) { + input := "draft" + var last SuggestionChipsView + tt := chatTester(500, 200, func(c *ui.Context) { + if v := SuggestionChips(c, &input, chipTexts, SuggestionChipsOptions{Label: "Suggestions"}); v.Chosen != "" { + last = v + } + }) + _ = tt.Click("Write a sonnet") + if input != "Write a sonnet" || last.Sent { + t.Fatalf("input %q sent %v", input, last.Sent) + } +} + +func TestSuggestionChipsSendAndKeys(t *testing.T) { + input := "draft" + var last SuggestionChipsView + tt := chatTester(500, 200, func(c *ui.Context) { + if v := SuggestionChips(c, &input, chipTexts, SuggestionChipsOptions{Send: true}); v.Chosen != "" { + last = v + } + }) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyEnter) + if last.Chosen != "Explain the minuet" || !last.Sent || input != "draft" { + t.Fatalf("chose %+v input %q", last, input) + } +} + +func TestSuggestionChipsDisabled(t *testing.T) { + input := "" + tt := chatTester(500, 200, func(c *ui.Context) { + SuggestionChips(c, &input, chipTexts, SuggestionChipsOptions{Disabled: true}) + }) + _ = tt.Click("Plan a ball") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if input != "" { + t.Fatalf("disabled chips filled %q", input) + } +} + +func TestSuggestionChipsRejectEmpty(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + in := "" + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + SuggestionChips(c, &in, []string{""}, SuggestionChipsOptions{}) + }, 100, 100, 1) +} + +func TestSuggestionChipsSnapshot(t *testing.T) { + snapshot(t, "suggestion_chips", 520, 120, func(c *ui.Context) { + in := "" + ui.Column(c).Padding(16).Gap(8).Children(func() { + SuggestionChips(c, &in, chipTexts, SuggestionChipsOptions{}) + SuggestionChips(c, &in, chipTexts[:2], SuggestionChipsOptions{Send: true, Disabled: true}) + }) + }) +} diff --git a/system_prompt_editor.go b/system_prompt_editor.go index 93a3919..7fcba8d 100644 --- a/system_prompt_editor.go +++ b/system_prompt_editor.go @@ -19,7 +19,7 @@ type SystemPromptEditorOptions struct { Default string // Saved is the text last saved; a different value shows as unsaved. Saved string - // MaxLength caps the characters; zero is no cap. + // MaxLength is the character limit; over it, Save is blocked. Zero is none. MaxLength int // Saving shows the caller's save in progress and blocks editing. Saving bool @@ -47,6 +47,7 @@ func SystemPromptEditor(c *ui.Context, value *string, opts SystemPromptEditorOpt col := ui.Column(c).Gap(d.Unit() * 2).Disabled(blocked) v := SystemPromptEditorView{Element: col} dirty := *value != opts.Saved + over := opts.MaxLength > 0 && utf8.RuneCountInString(*value) > opts.MaxLength col.Children(func() { ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { ui.Text(c, msg(c, "system_prompt_editor.title")).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).TextColor(k.Text).Grow(1) @@ -62,24 +63,24 @@ func SystemPromptEditor(c *ui.Context, value *string, opts SystemPromptEditorOpt TextArea(c, value, TextAreaOptions{Label: msg(c, "system_prompt_editor.title"), MinHeight: 120, MaxHeight: 320, MaxLength: opts.MaxLength, Disabled: blocked}) ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { - n := utf8.RuneCountInString(*value) - count := fmt.Sprintf(msg(c, "system_prompt_editor.count"), n) - if opts.MaxLength > 0 { - count = fmt.Sprintf(msg(c, "system_prompt_editor.count_of"), n, opts.MaxLength) + // With MaxLength the TextArea shows "n / max" itself. + count := "" + if opts.MaxLength == 0 { + count = fmt.Sprintf(msg(c, "system_prompt_editor.count"), utf8.RuneCountInString(*value)) } ui.Text(c, count).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Grow(1) if Button(c, msg(c, "system_prompt_editor.restore"), ButtonOptions{Variant: Ghost, Icon: icons.Must("refresh-cw"), Disabled: blocked || *value == opts.Default}).Clicked() && !col.IsDisabled() { *value, v.Restored = opts.Default, true } - v.Save = Button(c, msg(c, "system_prompt_editor.save"), ButtonOptions{Loading: opts.Saving, Disabled: opts.Disabled || !dirty}).Clicked() + v.Save = Button(c, msg(c, "system_prompt_editor.save"), ButtonOptions{Loading: opts.Saving, Disabled: opts.Disabled || !dirty || over}).Clicked() }) }) mods := ui.Ctrl if runtime.GOOS == "darwin" { mods = ui.Cmd } - if col.Shortcut(mods, ui.KeyS) && dirty { + if col.Shortcut(mods, ui.KeyS) && dirty && !over { v.Save = true } if col.IsDisabled() { diff --git a/system_prompt_editor_test.go b/system_prompt_editor_test.go new file mode 100644 index 0000000..ace4f4b --- /dev/null +++ b/system_prompt_editor_test.go @@ -0,0 +1,81 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestSystemPromptEditorEditSaveRestore(t *testing.T) { + value, saved := "Be brief.", "Be brief." + saves, restores := 0, 0 + tt := chatTester(520, 360, func(c *ui.Context) { + v := SystemPromptEditor(c, &value, SystemPromptEditorOptions{Default: "You are helpful.", Saved: saved}) + if v.Save { + saves++ + saved = value + } + if v.Restored { + restores++ + } + }) + if tt.HasText("Unsaved changes") || !tt.HasText("9 characters") { + t.Fatalf("texts %q", tt.Texts()) + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnd) + tt.Type(" Be kind.") + if !tt.HasText("Unsaved changes") || !tt.HasText("18 characters") { + t.Fatalf("texts %q", tt.Texts()) + } + tt.Key(chatMod(), ui.KeyS) + if saves != 1 || saved != "Be brief. Be kind." || tt.HasText("Unsaved changes") { + t.Fatalf("saves %d saved %q", saves, saved) + } + _ = tt.Click("Restore default") + if value != "You are helpful." || restores != 1 || !tt.HasText("Unsaved changes") { + t.Fatalf("restore gave %q", value) + } + _ = tt.Click("Save") + if saves != 2 { + t.Fatalf("saves %d", saves) + } +} + +func TestSystemPromptEditorLimitAndDisabled(t *testing.T) { + value, saves := "abc", 0 + tt := chatTester(520, 360, func(c *ui.Context) { + if SystemPromptEditor(c, &value, SystemPromptEditorOptions{MaxLength: 5}).Save { + saves++ + } + }) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnd) + tt.Type("defgh") + tt.Key(chatMod(), ui.KeyS) + _ = tt.Click("Save") + if saves != 0 || !tt.HasText("3 characters over the limit") { + t.Fatalf("over the limit: saves %d, texts %q", saves, tt.Texts()) + } + value = "abcde" + tt = chatTester(520, 360, func(c *ui.Context) { + if SystemPromptEditor(c, &value, SystemPromptEditorOptions{Saved: "x", Disabled: true}).Save { + saves++ + } + }) + _ = tt.Click("Save") + tt.Key(chatMod(), ui.KeyS) + _ = tt.Click("Restore default") + if saves != 0 || value != "abcde" { + t.Fatalf("disabled editor acted: %d %q", saves, value) + } +} + +func TestSystemPromptEditorSnapshot(t *testing.T) { + snapshot(t, "system_prompt_editor", 520, 280, func(c *ui.Context) { + v := "You are a courtly assistant." + ui.Column(c).Padding(16).Children(func() { + SystemPromptEditor(c, &v, SystemPromptEditorOptions{Default: "You are helpful.", Saved: "x", MaxLength: 2000}) + }) + }) +} diff --git a/testdata/snapshots/darwin/artifact_card-dark.png b/testdata/snapshots/darwin/artifact_card-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..375162b77623d8393971662de496661300befe13 GIT binary patch literal 16601 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/artifact_card-light.png b/testdata/snapshots/darwin/artifact_card-light.png new file mode 100644 index 0000000000000000000000000000000000000000..693b53729334dcbf950913d5684084ba50ac787a GIT binary patch literal 16304 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/capability_cards-dark.png b/testdata/snapshots/darwin/capability_cards-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..3d1e0148c8cd0903cec513426283c750aa859462 GIT binary patch literal 22459 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 NZ>Vdk)1d8|^k2QA4I%&l literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/capability_cards-light.png b/testdata/snapshots/darwin/capability_cards-light.png new file mode 100644 index 0000000000000000000000000000000000000000..35b9a9713d3834dc797b8e626dd87093607dadf0 GIT binary patch literal 21680 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

L6S_zImDo@DA`ZQGqtDyPNjqGu=ZQm+T6@E-2PJ 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�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%0AG?XBf<~z!5*xBo_kd9 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/regenerate_menu-light.png b/testdata/snapshots/darwin/regenerate_menu-light.png new file mode 100644 index 0000000000000000000000000000000000000000..9cea599caf0e0f1381011778ba9c1eaaecb88658 GIT binary patch literal 16072 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⋙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 kQOa%b=!UO<-`N4bv9WmI&tOo$RoutKt z)x5ILH=y-YmkFV-UD04@VIfd(QpQl3o{43IgoGe5vc+}r-4_H5%B$_E`ARTtscm}O zJ(YQ}3rV?j&=aV%29?W6eMiD&v{lgiq@=c}+PJ^oVF&LuG=FaI-i=PS-MQYo_H4LL ziH`~?5(yKdz(Cv79tKz__hlv zZfa(B{Sa&qA#T7DEHtyQ;P*DwHNYxOPhZ`N%aVBGZ`vIeRvs2+y)nwF{dDKV4)Fy? z0pETVsd-7RohM8L$BK6ZWu6TEP$!Qp0l^`-UlC5RjaMrNF*Ofjplq9O#P;;nl3 zaoW>8Ebp&@gCZyc*rCdVQ`rR}V&+yeH}xXcjz=YW3bhqA zH<|1NByM*a7BlTLtx1-Ql!h7m7v-g;V@5OTi)!<=TYr2z&2TJ@J)8o+XPy1c-Uxv% z!DxL|bVht?xDzKu_awbpdsuHp`Vx%5%BpwHXt^=CO-z=tM0KG`U{`Btu@4u{+ouObcOIP0iBU>+=+&c1j9+v7%dhcx-GlWm2yh3odTf*ceSVrR(Ix z(Cy26Rn@2KRdqGq4c$vraWNa8Q3||2 zR{lGZS`+)2u8A<}ARR0eQ#Btfdt^l8_08($K}znj_Wqf>kD0;N4E zW6;D}J3Z@Xj}!;|Dtdw!B`gshH;-KO3a*LOuQ=KPg&FqZq6EiIfvdY1;Y1rX)wdbf zCA=C{d@^MF;q^k#ZQZ<&q(-b+%V19}E2fx7w?duUlE!%XU7oe71=*Wcq%b=em{pV@ z6u1w!@wU6sRvo?Mj)`5d@%v~F{ zd0%IB_v$@FE|2r{&^OYF$)P=Pz8E25qxJTE$A6Si->qbxmNlC>KfnH)bhEFgeeO9I zEQ#B`#o_MAx7&z^ar(Ua)l|jYM(*~B+|ylE4FhQuF{M8p?d?1;1tUeXun}{-rQm6- zKKH+l)4fnxLx@wK8U9cSBk3tDw7el8K14;zb{#ReI%j$A?gb*;KVT!gCN*<>SJKfL zs^K?;4-@Hx9&68QIRrkeaznO?WJ2C`k#=uL6;TH^?Gyhv!@;GL7+<%2m9z!o;$?YW ze!RN%#U&ytj~(3ezr~)fdXm%9VqMWsR$z2rIw(xW>G-96oIMN%P^Zn0X268zn#@?7 zT;WdTDI%?+GjRGV-#~5j_*S;9uB4_eWo$)#z9fuREhSLjGGD-?N0W zO>Q3eyuR$u{utp#0?F%_FPyhG_)Mxvnxm4bOH0GMYx{ade^&uya ze0Yd~_tS8QS?O3~+%eEV60r)2X^Q2DVsn&Tp@I;0^SlGTgOAfzWM&doZ~x9Xw>sT% zC;c8!>G+cmS5-+Xq!zxZSwNw~XFuy|?=KHf;A4b{L`_Zab<)$B&tN!0_2^ReFqlsJ ze17tXh#S-O68fZnCgnc5KSB8iSy4rW?G0FQ2HOo0Ou>0}2x#5t>~qiizPQYp*yRD9 z7a~)Fv_VIZljCn7s$gI&Vxlr}GyjYlzlUg*4^kbJ4%dHWH9?)QI=uTmtjX8I-^;8$ z9H*BdoBhW?F)~YmR0v5{UyHq<6E%fAIV!gkw{>|$gVXkAf+@52i#QfTX=D#Exo=KV zG8DS9^4@kbpXe&(OsB)tPD|e{Fm+2xUYru$_-lz86t*n0W@;bwY zphSr2`SOn9s@>+}{||{w3|;6bF0tI`OgT9pP*+j8y?2^q{MP)N2@!a{4Ik;lhUfl-bxT}^R|qOegE{&j3LugM$aY+pqvC?dCV0y~{nN2ETxJT)tS z&5SU#%Hx6a^Xq{`6N7v3CtK8>_&4;+4S%mYtX_~p*;B*^nJ;enW=R?gss@jN+RcP}8oD2qiM@f_?ZpOE)DIbjnegvhamI@KWZ2hJ< zF{x-kOY6LQgbDM%+SW7!%Iajw>2XdhEV4@pC~JE!uHKCT9XPe>>e&Qyu1!Tu<~F!l z52temEp$o0XXmtDI!u8kbaAG+R9kZ5<;B77S}5o?OZm}9}Dtoa(;#SIG?t)#$6&L2LtPfnwBIZQkM(6nmNu z1g+U^4JDr5`UDrsiEaB`va0iBw=I12oO0q}lz4-)bEty)n_X%0w}*cY==ArxUpd_`vJ73T+hKEHLPiGOiT2l#fB@5W@)QGBQ12QU;Sm`@ z;d!?&bCK3f>obmoBt8-Hm_aN z`7gEV>$YCnRC*zmJ~npAR+b#P3Hc+*a5`=D*?GvduBRtjO~>U$PP(56gC=zxOJo-p zRcVYd$rt2Jb%fFdN<7}3FLxq(83-^T2#ELJMU1t*OSZXcN3K_Sc-Ev$?e#^)DLSe; zU37NDzR#Us*h_S@ReheS63}dv6$HCpcCy`zmDrH9q;vHyZ%q6hXB4PwXgF#6!p*%} zjsinnPRG$fX_QEW8TCMLwtKQW=H{&PG)NVT)O<8$DBi5d&e=kz$AlF(yuPO85vm9Hb? z6E}(Q>MA2t#u(T+IEN=?|H_Qh_O77MRDR!HVqLCjrmpVT-$y`6ckS5KK3-bL(9&41L2g zvTzi!uUwC>skI@dH)D+L&5a!_>>MnrDr7iV<~TW7OXuBi@!H^MJ4Yt^`tJX1Rii*P zm>%`!bQC73Y9T#x^s-V?QCN1y)K6g^Qtku07!6}+8K`@F*e`3LBkHjXy|dVy>C|=4 z?pMcwYuhlU*v)Y&xdoPvKjN$C=ske1{#Ov@;Qs9m4WS7IU>)t0)ZG62hxW@g+rp{O zOxOr21khXY-+SM;HFZbK5+mvg+S@aeiu7%5*KbSi%&%@i(>-uVaHGSwvI;-6n^0a? zc7N@GS6zLPy1Z)klHv3eT@|fJxmhDc-7Z0?xI*Sq{vR*^;%<2O>)4pgk_IMywY{Y& z1FJrMM+c<7zCJGQDHg-#H`-di%;d{+yV?Tg5QSxsAg->?;`r{aDXu>fe-$iHDlQcH z-BhQhp;0*RHflDvPesk$=D+1rcsPCFl&LmqMs&qI4^FkJ6*s~7O{c*F4Yd~U8M8Jg zRn?NAvBh&F@Q3_%O$sCiBI5lBc_B!44u+!)c!NDZ{dO)6Kq69HDq(GF>uC4a4ITpY znp$+2al^dau{_?dUtY}spUO=5=gwT`^9yMy5*Kz=&-$C*E)=!IFf8mG^>w&y2g{qV z5u=mU)nNO>yEo6-e2@zLMia~9MK#^VR^QF69W2c9KNY{CCj4?aecrnMy#u@N{|d}P z-8nis^9By(fjiC34Sq!k-)#R}cj3JZkd?Ld_EvX+qcvM%!@%e>eA=aogvo1jn2cn% z)$sCd+jZh1mp*-)JhOm+WXg!m;;hNwr5agS_(qX3XtYAK@##wTLs#XCWKd%hyQ#vb z1Sy(!m7TYUjkPszfL)8yw~5iw&w#u3j9%4FzRhlfPiwOQI)DGQq=AKi?~SKP;@fu5 zRb54<*Vcxjl;nPS4Z=YWbmKP3R6dWm=e$n$*9oezNJTcbX9>&K9XH7CZjG>GV=*y$ zgn6Gm{6A*9Rk+%|J!+}W=f-3)jsFR%k)e#DNDK+ti>i}+t$w|J(T_?EaImuzDm!_6 z@1aJEqJT#F2)4sZ41S=aC1%po*O!-+)FnqBUHWDA*uy^yT@-Z+ooOp!F&F@=%CyY~+U;Z8SP*|_2VIkt2h9&SQpxD)Cx~HGlu76!)6ba3O4~{vrn;b?i2Cv1Cgr2CzW>0T zvCb|%j9PY}EHVGHzGZJOVhM3NYpu=A=p&hBp3c%cy*w_eACsu5)CV zp@H(fj*W9XAi?wF6wyPzn$D>U*x^{S*`0OGhQqLdfz32G;r5mber)6jKZW2spZh@m z0+U-Eb5M@vn}hQ>vh5l6yPoC9B?}ETaTdz!B%{8R^+0R?qdG+DUlbnZnH{>&Mql@Zsh8KS8;9 zjPwj^)7M;82?gDyLoi;;e$!SUf(u^p-#)q_=kU`rTz)hdWPZ)_!*61;nJS@eaomWO zT;C$S7Jc8ypIuzcNgPv2kKlx;tf&x1#tT zW)>}M<{$dHx=L#GZo*=^x^KZnRD7H1<3)!h{Jsj52^tJBH1xI60v=<-rj5ab{1jc& zj>c^B+;&URwk=onwlX>;Sc^zBC=pLO9?oUW&!jMVK7p*-bRULNm{k1deBn=iiq2&G}E)2cUH zU2AU-k0Nu-<#nA|UKW**8c!9YGr;!v=!?l~xf1;%_30zx<69~d-T>a%$nM0o0q9jS za(_TfO+5r@TWXaLt+7!{?P$R7D ziUVK9?2GYP)7Gc~H8Av8715>gL29XIi=t}gajd8oPj z2UkDz&YOfkYG`RzM-tVIjjbgm%bJ@@*^I@0w41!VV==-7t~Fy_z{5y?C4p4PK*8r5 z92h_eAre8fIk$2>2Q-!AsO?4d?Ug`JjzkI)#K_;f`7rXDEt22E zXc4K{IL26{O4d@exk14yg~uYdUuziZcG_%?D~K;^%^a!Vl9EuNA@3%ho=}8wS6x$P zCU!Hkqi3h5A{Cy6lkq~t1G`Sx2+es$Y^YmGDt&^|a`vEL=+hl##V@0}m8_P_0)2zf zt%pUQ?XOXTY@97CE794gJAr49Mv`xgsEMViP!YdEl2OEEnWBYcm;gyFf0Ltw{`@Xi zrPR{Su(h^9f%y(PlDXC{2`jCbH21+C2X-w`P^pXJ3t1zrSat#x{p6dRzOk@DhZ*%G zLFAuHCNGTA0>va}C)rFe15GgabZOjFb+ulDqITt|g&Ar9_?t z8Xu`e5t$n%tWQm&G%6{SL7kV`T&bXut7b_ z^PGn~Ma$Kl$IWQHWV|I{rM;uHG{v!TZ09dmMQba9vyYp5BmIPYWaKVf2BGQB zBu!XYiAcfq)aDP?5K3#CUuh}oAO77{j#kln*C!cCZ#}@*hP}P|_mI8iz{4JCDJq4b z5ZpyawW9X+(o2x}^v?tU!oiPfw^r^Cjc_=a0qVo{e8p-iRejoN3Wo-O=2(md76C)E9HP!H07;37T+Y7g^ z^~MpS*0!1q!}~WKNcb8Xrd-j(`;rV==A2^{zkVf`%KDr42(OIJV*!V}#lKG%t2E_O zmYki<9*R$(Mu=JZBv$WVZWv;-TOQSB5eiBZTwTeRoeks$W-K+@4j-nk*p`+`pbfnh zTk<(xQdfH1X}o98oG2)GydmR@@*)wKB(xR;-yOUX6$Y+ja+=LqB1r%hJ=*;{*BrC^J-XwUboS_p9cY|e{AgIY!;0$ zFYwcOFMH?2xWVFg{SLZWgqX_qjMx2rTU+n^u(x-zy4upxV$|#`%G;grmz>fLF9Yo0 zd_86Lt}`LFci}p%C3(73;^D5I(WsC<1;X0Wn&A0`vexV0cyYsu^5bID;jvQ+Tc?a1 z0S(3vT6wc*RMFz8t{j0aMa7L@Lh^wUxb)qe}N}mJ_d~h+rF&$&ElK4+;PX`b6!sgochLN;6cW>uJD<8r0EF-;V7G zJnX}>i&xW73E6pwOIxiTlesQ!*^*%%F#$nJQbrsyaHOa~+FipG3R+})`bqmN4t!o; z!qFx?gl>JDrn}=A&RuVx*2_&`KfrpsQsB)ZsL?TlnwAz1=hV4X9*EABpsiB$>(N6V ziRe{aJp~{0rY$;>C0`N{09S3w)VE574O&ZIx}IMV0!)r6X}P+ z7oQdAD>~LU|EfnsP!13PVCn??=Pq&~si1fO37E*2|9K!VDV_;CI<+*s3LgeScqtWA zRAbeL42*$-f`YO?A&6$7i@&o0udC(M5;OzA9~tbwNh20zOeyacn4#)j{w|E{db%cR za(~!uuqd{)(C>0D3%u&FtU-`e^jt>N4UoVic85D?IEeamyo+0Ga<^JPtMfRBd>tA> zV|M&~v?K4>crrdsjlS5l?I4U7j;4Wmh__TFGF{y2ayE5<*D}jGn9ge}VWBZ~kmYOz zPW+!C_<#E@Mv9syDK4NO)8@h&E26C5Ol)H8b*$L&Sg^dUYE-9%k6F3X$CSa4Vqs#oms^1gN31UC=U2R=+nO;V)U>sH zZs+7G?p_{B`EfrwPzgV|q%$YE8Qn@thko+^i0#wKkO;37)Op>H-2}>@`?j*KF0#|x zU*ulOeUG>5aB3yV3%1}~_r>?lTH_%?UGFm`n+5^IbB z>)H^HGd~fHNW03O=D0OAG3B4~sx6q)_}6Vou+SO`Vdc$~v<^G8cO()S3{Rrph)Hw> z?Quv!RNYp&BBY%jdv9& zmWh9#kW(0c1`cF=J+*PQ=xcezy}(3gVkTjJxqlhIlsl=0kCM$HAV3kvr0lQLC5~rI zzuFy=ld+^IYuM1wcILwGTw1&<#w?{Ap3Zf&afrxfg^wDfu@f7P7l|viwKR>%MTCG8 zcYlzS6&Kkp*e}b<%+jRSFP1H-s4TD6!(E&mjS}#Xk(M3>ECTe~i3_8)-FJ>7XgnTn ze|dA^Bh9iUVG282rY39N;}8ILL?vBqJ4kYP5WvCiA)!K<3(weEntSSpoxG*K1n-pT zzlm7NWpUffNGTcF>jM*1E$`rV$NnlNs_ql@Wi_WGNc!`P$&%3W(X2w|vKpLR9-`$I{%sKcgi|i@qHjT9=YRgOXy1){lZ~4C}EDry! z>GYMOfxw*Em=OqZBvB|kdG{WzhB$!r_cDNbPul%f3p95yk()1|EHiKP^k7KmUGH6j zDkp;#o{4b90!`P-3fq9S)~$gNA!3v<&an*wYS#(m7A98Uaa8S^uX?$PRqCMyIjXbb z{j35ZBN?mhRWp5275(}eFM37Z=vgrkk9`sZSH7NTzkCo*omP;)Jc$JLfG22eY^>$x zro?e{vWtjh7w141s>487O1^2&mj$%j-3*^`2%#(l*`zLTvXL5uWYo>>jWF?N)4^cs!{Wr-AsA zw40v(>LZMfn$Su|(+3)0+z%=+>4f}~W3z+qW6vmuVB!mH%K6c{U&V59rL=;rKk!t^ zF{j~k!e-Kc@Ty8k#o!}VQ7r++lW2ESP()6be-N9R9AT%Hw>;KYa`Om)9iW(tg@TJkYzX|H4-#Kfk$NUp^Od-ErwhuSN?K+L z#JFLQ9~x`6F-qp=;bg1(wsl<8^nj?_qplQ`+HY^NygN)I=i&+t@4*x zW8`eNe|~jIgxk#0!j6+MsbB70$o3+?adwl{2IAq1cia+8L2~y#^$E+$~@`?X~aTxG?ks3kfE-jjDgE1FRBlGGxSJF z)|^0s`|FhTOU)jcv$U`3EIwZd=|^Qr$;s}a&jDukJRL~IvuJ@Lr&uY;qs6hlS-4>) z4kidh!b-Znyo7OSKPfHAi}OuL4N%~9^)qeMf?;w*TUmpCV2b7KS0$41AG?p{=> zUWX0Zf}5p{Elo>mB)DBaTB72Q6ClDh#JhyEd z*J0e7upq_x1Pl#;2yy-6XT@Et@~r>0#YUe_zqFd;~U z{5L1JgWHZ;%d@K)S%&#FrQut8JX{dMDd(qGOSK?ecaovac{$LJMSN^+14?XLnpAvw zk|IrD!ikj&FIrGnw9JX^V#_>v2iY#ExlA5NOwy>1r#~w*M&4@VNI&F9y)1s!{x}W- z0U(eKd9K?UwZ`!u3M1yUEW4HA=#xN!X!3OXdx+7>%}aumeebPIQMVPxXe%a(i|#WG z3J&`2j6__=2#eqQ3@Agcu7GUhgbNUF-I?DtY&JLK+E2X&IOhflsgU zhEV_Wl(SGvGOcE@%kGgq8OF>|wb8#hf({|X$7MObphv*pDi$aKtMU}q{;|0K^!+dR z+J8>c^`lg_1TL(v<*QGhah;DFF7%}3n^C?*LA>;UXO%V7zn~%rF%b!n{6iPOdu1?W z63=@Q+<#B}pU~j{%?C~%zTbbIZwfo0Dg%ahz3KbE$gmn0dR&b`4qGArne#$a++~j* zClrdC71z|qFr#B8{kaZ&>IHYJ4X239w`NrrIsP%lpmv z#qsv^AgW2C|E~98a`R!b+AtE-#)cRNBkB~Q-A&E~6r%MRi^ml;|Mg}U?j+vc-oRHK zGBGmT*<)(lf4%YjLfBtwUd2`Ku_;xL-1@uZ&7Rw2g7_c^a$+!8sec~&|G>`=IH?YN z!GxUbL+zgBlV)9OEzF(-assP|dJ}=bXAZp0xGT%~XL(a%bE-1Sm%CBB*Oy0G?NoLB zVMlUl=uKr9>&!>rRqYQt=|p?^HQZvpGewK}+M6hmxBL=6Dg9OT0G6zugIM694>Y zYJQA3~s$ayBXz$wa%zU{*@gk;9;SiQm z|JmFNGK;pm9UOLY&r^^Oa60OAusMN4g|2p5(*yELnl6?u-mJ<4X(5D5ecGn)Zz2_> zUa4p>0l$sa^Ghek2Wa}dpNAQ+;P8L>0{fqKq6?+s>Uy^78tC|H-4xpOFaY~_d+P$SbbugJs;P(j zdxm>ZRbrl*RsQnK%KQ21coCI|RPm)cEvDkbgP;2IVaxUt0N`=4VrOnGA?M?DdoR9l z>f2|;)Z?gETU{<(pi-x0_qm^GR&0uz_qFXQ$X1cKH2bxuEHr9jLYIXVz~Eg~WutD6 zorx;DySw#&#B#PE%)kJMMTwtVI}CW-*`7xN0()>a44*pu_8%Ype}DnxC+U0BJ}xg$ zj73L=-~dWG2Cx7nbq$8vszYqRL5jLp=dbK41RK=<$#gtuQ~)va$?W{O-{sp%>)+0I zthKdF7M3|c(2T8Td%KjTX#Y2K8o(dBcdq+wD3%=^?7JfTKee^Fr3l zmt3~R#njhn`G91D<(Z$vKcm@#K_ye8VEWmdC{q7zhS*Z1pFM|Qt$q)wIrQt`9xtc# zk9R<^x2NXW4x<^M%4F>RfssGuheZ`DjSy^6QT2sR_ zWkqMRZ%RQ+W^Zm0DN3X&RiNaIUr`OO<74*J{L!^(@+`ky3nDl_j!VM0$mJIF<}6Qk zi;!b9QkclaIqquF&MpG%RQ%4rHz&4vB(OhwjRby1<_UTZ-CG+>O?lk9)B}PtGha8} zk67x@%V9C2D26tTSu*mNL{Cpna*nMS85jsXK7(VMQ>#k`Lt7yLLekpaj*Px|oS327 zJtl4SiG8c%1vWJ27YOzQ1R!*Zv)U#c1+1o@SX*1~+AK3OJIbddi6{O~`_K#;a7|`@ zeJvyFc*2JSczL&e8yTNHxyNFR3Rtbr5<88JC23d8I6mEr?lr2YusLyS@BYBv+U;E7QX^yPM2oD)aGx66>T@CXp5V}=BvO z>>3%y(GGuYKl_qqQkTA$Sik;6s=TiB&tfR`Gqb)zXzse6vu?sC<zNKIr)J2Z&H17)Jy;*XnBZuh0uEM znT`*K14Y{pfCTFsLZt4Wvc#Y{HFS8W2>7yG4gIeR^I-16PJ=`KS#UM}E1Caq+3OMG z;NeBjEulYi+tZHUK!l)YUcaz!xowP^2HIHtDuB(~o&s5ir}J0D82^}8z0m8hCdcWk z2B6>U%F%3MkhgBj`_CZ>VhG__!mX3Di&#p(7*dpC{PXJJtl0itrz>+IVqs8&1)Pk9 zp=EK@2%DZ8nOl3@t!aaFBirtstgP(j_`JHZFp~W9yT`<&d?%m&%nH`rWlqoYbXM?? zK-Z0-#H&wH9O0I=*{?WCzvS*awn+K2O z1vN>u?u{V7;EJAbWl%la%Hx}2ZPXTnPQAm~BXAC)Z;2jnCgk62BZEKU-pu_61U0`xfB~K-Zz+bh>za%W!wwG2BW^q~pQlCQETF|9U*@Tv z_`UH{QV4xX{{F(;X197}t6lkp*QO1-T$8(7qN^P%h~@WulC<(YeVw<(5fck-|8*O6 zzpuEMoLl@4qhM`^JCM$%)DR}bPKyW~%b%5#mW2E{zCQ6wCM$>y0c*c$I8G(D<_F?; zM14ISVUatyI{o2Y=RtqDGj5PCfn6RC^&ivVq1r7L+9DGdmfX?_PoIxYS>%k2S=d;V z3=D@Xs}b0NmYpZ9z2-9-om8GJ(l@g$w+#_#jM+O#WS%P^X`rWIes`7`NC@Rc$M`$D z2gDs~omnDj4LNIIO!JErl7=sB38O1(+-S(e5gb0m*)NNXf_`5TZ0z#aFaVS8q3*wNS;85|xRa zZ*=2CT?ih5V@@L?ccf>fIKA}2T1x6J4EfH@D0R5phy`#kp9WYd?erP@&{I%kU}H7g zpAG%aI?6jBrx@6HymdQpzgyYW-*BkWZJ^^j-&4fXh`HZDInFFD9>}>Kx!^@U_>1}d z6HQ-7gV`n-bIs=82Gm%nZ`WxKf_f|O`**IZil^mrU_gW4b{DOzw7loZDVm5G^e%y-a60pN}vwoPxl@o)Zw6Mon26 z_k9par`ze`)I3^1!ptosxVxqyi6E0T|KaS5W-UVg{2M9h{)7AQ#N*u}P6>Oozde17 zYwr)bNqJL~q+e=l;Sa*JU$DRcew~{E&jP=iYj)>SvJz1fsbVh@5>jI$C>|dk7MIw? zhEa5NbfD9eRn;Z%Sn@G~qioJj_xDsmb#os)O@^YPh@rjNT`uaVoX~f_fknmouxVK)rGXspwXH3XMfg2lN8W)w6wkyQ8qWm4&6g{48Zho??7$V!d+ejN;JXzeB%X2GV6o4%) zD{f3~4iJI;&j%i-gPpwmW?jDwoGu5sZak?1m6%;kGsx@y04f~IfrK? z^6@&D_ofmSNPwM%8-5U_X=r4QzxG>SW?Q?vBYs3J$4hOd)oetz6Ga{(SUu8hkByza zz-uOqCc9#Z6p_^!Gxhfdys|Ok;8=f(+ur7Np*RgU z)xSE*aR0j5^`-~_*qq@mRq2>mKOJwSYgxJuFSBLm8<<}&_lao`J>f})~o%Afw%R?#HoiG4Y=H?u*}u|C&x#*K4+h%}!(ueN(~O}E{gWctMN6%zsveN;x4khz4tgmH zFjrdIN+4D>WfHY#e-Y_N8_(kK{z?SO{m+1==B77Bo%yw;nqS03z@1l+{ksa6guQrJ z_bdSfy<0M-LIOuXC87&Z)%sm_o#kI+B#y2uJ{quyHomehw2?I0zI|-$agIM7R2FXf z#uZur+iLU$sl7M<-2!T{LAklRA5P^Cb({`T6+0ygtK9B)cMG7I_E#1d%gfU*X;^^r zeyFH>M~nu#IE`A;(!FbIe4nfEEC*fV4n97Qc7ofD3(zogMyt*ZkAC0ctNxNU?rq@{&rWNxJ;rsjgYIYmP6 zZu80ny>Y+dY_G0{5iZomQG)}1#>($?hKTKvL4_KF{I$6?D8TQArdF4PNhoe^Z9q^$ zf`DNBcU+>1CdWuw(D(y@FTU*V7}`^aU?7CAbDCCHS1==!fk1f_dhBQ>r#ELr3~~T5 zF)`o#jvo78iE*q$va95Xx{xQ|wVImTJ87w*0iY22;vzc=j0%WWMedF3Yips3L;!r| zj0tCn*DHb{SZ!_ZYWoX7Q0h`MC=D%*M!<|c!PFIy35*^z0R!CL8UO&v$>=4pD({=o zu_PaDcbW_DBU6ZMfkITBdQ?yqb@1LvzFI`Xlgw0@?@9A zIV3c#?5qlBYdqwY^I4@_4df!sTAgD7#KfK1x*h4B*2mZBq6Up1x30-aNkfQXYRk_p z=HKjZzhuZ6Go?dx%Z4|yf%(&JbYl~4FE48vZjZzQ{`mKs)XmK`ykk}0WS#8)wQ9H- zUKAe3n#yeGY%fJ>8bBga4PTa=x@N&fphWtC*1r!1n4GMRiJ3fyck|yrTOM3oB;pWI zv+XhL@B_C00gN?EvQoA46&oy;R zE;?5X8GUVZ1?M*rGV$`$)g2D~<@Mnq@^8!tJ*VWOe~$^+`D>Nc?+iMd5fQQ57IC7O zJC(W1ZyWBZ`e3Hv@ZRWmeX;j1hA^=krXMp|2k zWRx>!t}?=f>8R)&9-R2lo(J^ai7+Z^g0M0_f7b?G!J{Eom;3J)0nZyBb945Npn~qs zPCG?KMo-{*904>J?Gb$7R_oB}=%a=f$c+-I4}^3`XL&acX#n<1;+$7cFJTrIw(hl1 zYrHA33e&nH{8Oh4T?xJSc^&$Ad4C2P-CZ)T30%hCO`Po@RQ{8peNq;gIO||yM)@cE<-tK6_u<9&2Dj)?v$=VA zEG}|B-ak65d&l=0k;1U_uEs(GK8#H585k%fN|go%2dd~MLEm>`BMe=4VJdyT9GVU5 zYr1+g9$ZvlpR_Tz+Nv)$1-Pbhg2EKA|AE8MDmUwMiF1)D!coqoq@a)q2>B&YCnqns zJ%&hHASI203Y7hlQ$dbjcIs#sG*+uaWaOSg-U>(>>d;8g;oKWzJyca?HL+kPvD8SJ z-ADJhL6};v!&y^Qe=+c5BCR$O^kr4lcD?>*&qt?%WpZg-TSRUR(z1Ae?eq6!3b4Bn zMIun&+>6Vq1_r5T-TTX1Kq^KG+> z;wDljWq0|Ut9$YBGUl^1CFGx`Yrs(2^M^ zI(+D`1nka=%}3@mss46su0E2e8#ysK`B$~Q7AlixW9(z2w(K*1fJh8hmp4^o6UY>U zLRx1_bhh^Px(zn4HsER+O8`JBUGDg?DLD!eTy^8|WXD)VCg?%Gwd6E4J$G0@Uu}Yc z5ZLeK3Cu}l4UPK;4^0)7!azU_dIiXzhptNMHs)1;6uSh?Kp#1!n4tFuev z^AGoiX;8>T;o)m-4L{H#koh;LK#_%Pgt#vNghkteJr7o^7ZEzB`Bib9Znyj_GJZ}d z&q??C`PCjIe!t{8o9g@)G`Le;^i*Q*`fd3cHH}K^3amtCPyywursnbu99vr3SRURSakA6!_y{NZBu=7cZ+eJ~yp2U#Vo1sXC0*3jV_MT!QhFTk)<^v^ z%c`rHjYELw%dngLT@)n;F7@?TjN3x%eMn7B57gzLs2M#w`vWMWKM=Lc&c4W~*C~(; z1hI9j0vE*Za)C>a=G0oaC{Bm1t=U<1EiF5%{3GBdI*}tMw{}L)ltFB)v7wJoyRW=_ z4BsY|CI4iUq7;TsI96*+57t*+*Y>C42qXf69N$NR>4`COmW=W^7P)A|uC7u!=bS%A zETG!D?2L>k!eJy4yqTF9^2VksnXw%FD$qQa&peKQWfE1?q++ENq-x1;XpmJGU!8O5 zY$&>TiCX@yF=oWX(%=Frx&!f*mwOE*iO}{}B_>9ilchV5HK-z!xu}Us-pwV8B|)SB zL|g#CVXK>wiTM3e=A(j9zwP9NSzB26W9^~ioDcARG;Mcv934Sn!9S@QpO(eeyR~i` z85^syvN-~Zzuvqde1*_%uo+E?wxg$y0Wr*_o&^M;C1W8QwCD=D0zL|z#CQ6raJXNl zS1KiG#$-TIfucfGSsB{a&HMZG^JAl=7dAz8@wVbdK5h#8;-he(WdI;E6IWpCvZUmo z?q<}gzaYOG)1QydOJpHgefEin!WV74O7q3)d|O5iA&wX(L+(YWtpHRnG-^`kg%pDf zB`pmLvOqnQ138WnQBj`m3EzEA+XB5hzZs}C+RkkJY=PES)U+HYdZVGKkdH=m+=lU1 zf42DOTO?{^q^9oe?(E(UU}okcj63SNIii=k)_@PE>1V`8q9P#?XpL@7$3~)JQ8Nr@ zW@u~z#X^!s(WT7tbhG8B{r&y>HE9?a!h4ONh^CT2&WVDUm+cF*S$f3}IBWz7iEts( z2LwYEolGH+Z$g7xu`DXBp#i!Y1i?YB{lMR0-R4VRqpPTs+Tb9_1=~5`{PycpFAos) zIb=SJwjA@}IB>V?XNKYfSuhLnm0e4XCPtMn~`47xK+mQ!G; zd*)H;n_2-`f1o^m1wzlUn~!B#yw525*!2@Y6bBSg?M0H?Dz*QB2P&lmTzh<%D~;cl zMG+wGSL0VRV#&C;$g#4Mf^~;PUOX#Um?h~fOvuFxDS9oK4YieWLWHd$@i#&|31l1? zEK^fcQ*>(9R7tL_sh%DgVW6%SVlBvray$RaeW`%??b|mnVPbzmV&^nau%uJeR7t7N z{cef>o*sRHv-H#S>e3{O2AnIp=cv&<~ z#$tvwW)JBpBJ0oqTg-Rt46C0}WX}olS_c+e`5NNdLnBhHy#QA$t<1%G5A?M;Q=U6i zecR&6cBx0cPx!SKB3R9y?5Ld7*Wk?0bmk%KtaUI{;{WA37lWvBX()^G_3Pv>7`jL> zY4zk!FErEWI&VI8<-;$l&jIqLt2+(n8`pOG^Pxs3fwjr8Rn*u>Hp;z{x632 z|EW`xNKzWMtMVF^eo#_D5dT`$(4{DoY*@-83r9lxDqM~W$a-fudnuwEQ!W2<1%wo2 z$il9@AUi4#JL+pbC-F2KC}S~YG0#?ASYTYvH$IP+TiqRdp>X8lt>lED&9U z@o62pRN08}GR3?E%diJ6TiLVHhheB6(A@&0)3--DC+GJ*HRMUWzFVjwt$0^w_db84 z_KtUE-iRK?Emyhk$FMqbYicVoMBZHUlmc!{Mo=YiqisXo2{G&bRiT9axMCJojVE1{d9LHR_Mz&2@F# zp+BGnE=|z4L1>)io5ZLOuDn7Y(n~$HeYO-2R#a?bTT)jJDy*^$sXEoG& zxcjVgIQsczDbCXv_GH7XZ>m-$d0n-U>4H-`&H}O873)t z!b_Zg-NuINu^vwtJ(YRV{!-C+v(fks>EjVpK3CgE4!JsiW6svL^5H?06f;a%ZyBxI zW8*64;vz(_wUx}u?tXiMuz6iv0w%hzd<{XUC_X-h`i5$h$X-@x@G=e(MQUis?BZnX zwa6AnS-14XYuGVGC=gO|a$9}kl!(k{NKRBEwiGFGzUE)AU3QBV_*?4De&hUdcq4-8 z4ZVWw8=S6nK0)fe#{A>s&(8L)4taGjo!=3TrCV9Y;7;X-IQtnK0=bxn>+Fn-$k5P? zXxOhEW*&ssCnUmO`GO`FZ#N1$Iv^b#cFyXTmt9n(wu&H-qK1T$((cG01!ua(`UC?L z6X%%6O!EinUBRX;fHQ}m|1F0jG3b}Y>0Fum2nfUw3G{maZ%(3Y|92t)CYT2)o~i_l zQnl}4OVcf$E4QYjBL^rTys8SI3h^7o1q`ZKzw+SlkhT)%F;AQ`&IOsOrMi%FMD;QGkb<87w_}XIJAhyjZX>xFa+^)}*6At8k^TP3! zWzJI5bu_t@Xk0TBU0T<4Z4@3v6h|tn@#<%}wT*?~YeZ5ckc>=t9O;KH$3b=uM_Ew7 zQNQw4SSHY+Pw(Qr*|Ufmm%EMao+cA6Us}#Uj(*1PxL`jlz%Gk|0{Xai2_8q+8(PIMgwG7KSt z7Ti>4F27OPs9IO`b$g$a%zHO9G-M0=zm}X#m4pKB5*sS{S}V8l7){K8w3=_s;ewgSUkHwu0DEuC+ z1sxiblyF^z^YqlgGjm>e2Lgq4??Wo%s2C}g3MQZ1JZNDvI<%6n$IaLz#t46?43zup zEG;diq@{=ziUGVyAAR~7b!%#=V?R{rU7{u+9@$iayOnZq9 zio97pqa!0zT3d_z(kN)Ce^Mi%DQk7}TfF_@6*UbJed#lZbvU zEoi?%J6RYs)9UNb!^6X|G@hcQLD;#ljSc5hSFbe)#I0#&%Zkp-d8GD` zbQHJ!N#*3;Z2RSK5}BDY&{I#lqU@m|qKFO9Or>Ee9~yX10n>I> zWL3rZ=YGFo<3z`Q4u&05)2Js^ze19O2f+t*P1~&>FIi#_w-74RB^}#T?wFdHE93&X z_8PL?JxddRehmWybxng>uN_Vfj-?B;DAYGmKqvtR;%_!Os$pOnvR|zu2L1Ug+FF|w zaa!|7U>r44is&tivmRHk)6^G>amc$r?w_T-y^%VcZZ(D2S!yz^DvN(+JyC2Bj>jy< z<>K%g1x6<3N1Ug18`GyL%;_&%?Iha^?!j6@L;tcziul;TgR~Vm>+5rzgxTQC@^p!V z1ky)_e)>7k{PQ>n|Jsp#sI*Mdr~(M&BCz!wWOGCou$%Jf5#Qd9$GFpe;yBtH`CD2B z(eUtahsWL5kon^4YYZs29y1dYP_{Ng7h_S&&s%^S`%XBfrb?I+1VWWmpXS6w$_2V4 zr%CcZtT^n2VJZr`KkV!f!h^tIW#O?wYisM&)Ks7nkZ;ewupmgp;Rj6&UB&}~;IEid z){O^oh20W?bBVTy%t;hk#dUdFz)r^V<7yFzdjbNr{v~+ z>o;)TzyO+!m6fgiDaF)#Y(hd@Y-~GA%bszuv*2jhM~pvbk0109#P|#}#ORWGdU^o; zuxQh9b%uu%F|$qu3J6TpmblF;E0Y#L0A3R0=TK}MJO&luzjUz{+H3Rvqh8|UDJaFj z-~Ow<`M>QCGs@t^1TsrwyOx>R$*vW=7tca}tkCXIGLh}d{QQ~IM1N&01eCL7GeKXb zgtJ%QpD-@mTW(^CrvPQv-pY&Xz7AdOL?O-o9fs*?ZEb~x@*?&almhhPNAQs_E$Fk2 zVJtUP(4J6GJ}Ki&nbxAnHd4if-r6ngxpMXJGKx&ObZJx7lBe-ngpPOE_N-czmN71C z>kSN{(cpC8Vj)y#i_HG|jGSG#Q9ny-5%FeH&7(V45FlJRq9J=yu4K}Nu%vC904FaCLxETG;C17 zI!}c{WG4+J+uV~uN|u9;kx?oGTu+ZBu<|$F_RWr03WiEcKg7NYW%kWB*gtSzbe+>L zGDbM2+ElQH3y6q;!H-A#e{R!|X(c^fxs!_^v5AQ|5_EL67K+QK?f9T7>xcVc!tQDs z(9Em`)mZ4Rh+J&D(O{0taEb zV7g_UmolezIg`_t&`R1q+a||jX;ukK$8fdbVW(s#rzN-RUG^Jfy>;qK;SF`B@ncl$Ox_*RyLlr#!fJJ6t9!7f_YSOZp_Gn*;=1kP@sv zHLpjupYbtsu)uz_W&MDf|2~c-w(?+^Io)W#?P-#4b+f_4CO`x!FcQ%%szr*OrayU^KNILqyK=Su?QCe12gty^f|=aqesgnE0Go!A`6rcu2n+$B>wiak?{|V!_vWTLQS=yad;W$Eg~O~o zBU#4D58FCUPWM;_*=JQC1hJF#aX)pP-VKK@TZxys_}6Yxxv8vWKmFX9DQ$xjekV|n z!x8R5#6wuG_ zDLdE*ND&Jw9Tjq7S{9_D!sGM$>5$x;+tB`oQELV~ITxG!6XhWBZ$2(Ah`6&pQl~XE zIQug3<893iP{ZV+)eb?wl|A68%xGT|D{=v=ZD`2zxP3Q|pA2|tq=aMmpOpc-Tdg8m z`I{IpQF3y_7GqUQO@6fF&;A8@taZ7UTu_Ra#VC$~7!0z7*k-y2JfbR#-;e3zsD>gw z-vv$XzfWKpai-hYnsqon$srb8%4u*VgV$=T>dzMvK%kqVC}H6h6@th`73txbp0rXu zEU!kOLW_*xfY+&~s%IP4s5u*pQHyzZiU^XCm38xVWARCQ+U_0J>NAlR5L`r^INh)s z9UT=4D=7HDcNTvWPbmPny5u4}&3uBe6WU}sVXy5!TqIFhE05756-AJ!(1Rx$c6ubB zd`?qM_4$z`GlTfR$*Bf@UmnaAz4bAzA+g`J9h@0nK=DItXj7;0=)Rfl;y7Pmb zB!IO(V#CBmfSQ|CT}>^&Uju{p z-O{pixGu;3xyHdB+U|a!#hBCuGbeDk{6;;*jImXx>2L4D{?xwr&#@&}th2dm(V~SW zYc1o35fVq0F+eLvX5THckPj@ld*d@SIm-tGdOk)0 zX}`Cpi;xh&BMPm>{v>;iD@1h9{ag@vLGK$VSOg$xL2YxMp0fjd(9k1zoAAtaNs($>nl)FR$IJEln zkr5P-lcO{MiX?5{zvCCS%*i03VdYOs%xWaFOG`G^)qOeAygIQm4BU7xobT1K zw|b%?yt=zf@Xr&Uqgc&-+HK0_c&bpo=Wo8NwJ>hYe1ripW#6&YV`u@e>i~Jn$&>W0 zg_sZct39}jcP%M#8pU2&`o{h=uNxiCywm$;^3k&)z0n?!x9r4}^t71|d<=e?bL`_A ze*-1_L|MkiCE8K;*V@B+%yJcG7H-cq2dzQB09yg1>Nk55MS5O%eVD=Up!Y=CC=o#U zf)x@5A`;Tc2W}2B^B?p=pFvT*UN?{i`PY94-(ma(_i&KfjsiwYQj!+=8|++$A?c10 zW?ZX^XQtkIU24}yGg4E_!TX`QCPQEIijAJPQ<@P3in_Y9_1^Fy>MVYX)>je*fv(!^ zADKGwz0>*|GRYBf`gIL=&=)?tv^Hr^C|Qm+L57vpcGbMukGkW?^|dNkMJEqJ=^hqf z!;{$yF4K^cM)G|IyFc8yCDFwi)j6De>GuSJ9)lL2pwcpWKyBlBZt#V54-SqpGkX`5 zmi`jo*Tbk>p2-d_3qe8y0nQXRP;g-kO?0mh36V@ro;A#o2YkFw>l0~7Nm_b(VfMU0 zhaG}gllX?xE}?p#vR5NBjl}VZe`DMRq*qu{y-!WcM$X5gAM8z-9EU)Kg5s#+#+pyOjw z#SowfJC4NnsOK&+Qtq);N|zWl(WQ+@;LmB5F?6)kW$ekZ|@ESFwMC zV<>Hs8bDnndua{U3;9pi=LHwWyBdnS$2TZ3L;<=+6w8cU{n*Gc-$ZhvKcqe$FH|M? zx6=%CQb3-RTB9SNv=rHK@Rg$C=&5b5l6kx?9anw;w_F2}5RtSgJSD}a%7 zz|=|Vz!mW`tmtLk%MysULrMDy)=kX{!`|+-voI~Tcq%$ON2T|^BZ%U58wvLWxC(iI z!%V{KMiT-CjyF(o(jB&s%YB6z!fvQYBr0`7Z@ZFxwgqB0!~+cXjePFF%a8*A9RbTG zETQ#ahCR0e>_<3GZop5G;E0e>Cj8wt-ZKY|mav8mu-lM)gg6v*!rK5w{v zhKqYoQ%If`UqiMtwI6+~=dY=y&dSC{$|28RV3Hy4}4hbc*e2XUdf!=@q#B+zIYJ|KUuGMKB|SUj~w;N;P_yMa`s zynO{=$(*lv5KhqM`c;&_$qM?_J4j}hcaBmf;iTNtU(&>`_YTK};@GWtKN#TOBlsAo=O;tl5D8A@eS&fj(Zh_rwYc<>1t|jZQ4M~^6Yr$i&|RD z!y(s0_;%>%G0c9Blrv)BFBws_|EPGubWHOlU7$*NW7z%c&mpAi7c!DupYthKuohNg zqJ1kLD>Ax>1KVa~WKI577eC;oc&O`0Zr^Bj_LB!)k|;UJg-&n2mi|_?sjEvY^wQLn zpMNo4n*c=5I__I(EClHieOh*{?|zszZA^&!wUV0(yE!%x+FVES+6TS5p+t6Kcpt4~ z0VLf!{f*XFR=R|fftCxv_tR@?56?xyX%ULVvhvM7FD^C*hp;20h37iN3Gj%duT!I; z?1#}80)P&^7CR75bv_==B!d7ydERybFptx1-_{#EpoaS$uG3!;#Bz4=ZI%vJ=jJ-* z=^dsKp+IdNfQznrodwOm zYgv*8U5q+T{sfY;ja}otDJracyvar~Om1UiEk_ph^c&o~^S?a>4yaY*X=rc`-sf?E zTc@XRS)FB+E+f`k^Wq-x(D68%rC+>prbM~8RvK1|rBuIs?Q;d45ip;E zz)ENzCTgpBa?MQ=JbC2}6knTF-==5xez9F?vjAdCAO=PNwfQ}nFJq7cJ0P4)Xa2#{ z3!~A&d-6KFLr6G&Vn=oRq+R+c!!aLY!keIpT)~fS^ID+-IkHBjF6>o*AN{3wFl7fl zfT;E6SiNM)$jc874Ym0jy_}oiCS0Qcklh%P1UyBOET9R28nSj#+q0cNCnm@%;373i zNl7ms@zG4{)^+b;h_D|a^&Q05IVzy|fz6b2J&qGWY`~QBM*TM~4UVjuT3b=kad}3& zq_zj>8wDw;5lhboJ|KMV_6;ZvCE?-klfhPYR!>>5`e*;Jya;4e^)g{^S~j*m^V;So zq*S<9!9XvnBlAm}&0wgJR$AI3z}O5N3HTVgAydwWj-3f<-<^FzA29^OB`e>e3= z^S9FJjWt-1Z7{Qonu8dgY>~|PCMs%Z1cT{rAW6B4y*-xiFiOI%no1IL|017J<&ZHn z$@nYMfQ-1YMK{Rm1Eh&?ru+lrpYio0`FH>jwAHr&qoPt^91l zAN&~jw;R2IC_#ZPDI_1TjypTaN_K{TDa5^d+4==iglXc6f$s^C_W_W?ML_sKmj%{K zK1|q&T~Rp#l-7OKrAs&yhZl=4OG!dQ11K8RtaLo(4zm4TW4)ll|NGl0Z~nn1AH%^1 z>7f5ee*AaA$f*|s$|rK~zhu)hcl{go^6a5bO7cfl08^#00cl?vo7DtFx<@_K8% z*xBG;Ecc#DV6U~Ctm|?5@dqbeJe)TuA;DlUWnR3B3O0D+%j(ld(K6%lFxtw8?hLJKpHGfYPEHJK(*Y6* zkVi508-y>_+JlVxn$!`NKa_~8;x*pvw9oAdUe(+D(_URQVa?2yf10nKtZbV57l#)Xt59UAaNOP9Yk@XD&<|0mBvpVUw$>Oo@gv2r4(#ig zD*Iqx>LU{4^??R^*hjC?U9rc`<)T{=ZYo_uS zXrWbsa1^P|lTm~c?1t}$MnhtR38Y1pnVDIcm|1oCUL<+0b3alM2nv>+X>*V<_nGv1 zR1n4Ciyl>P8ne&{3buB>h@^KlhJqjt#FPzG}7ae~ozGP*=CJn{Adl zoici={N@5$`SgKJWYRnX|GZiPua+jSxhUDdjDJ^hj55EW!7Y8nkk@Q#AmL|Aix(B~ z7KecAsTY-f($h;(JDlBh!QR zb;{E@jHumiRxsN@Di5D(lV6De&u+QCvAw$CF6LCtxG z)#-zRZPoXzT&~I<7d5GvPLq21^(rmqaQ;z#wz;`UzeBf%nl>3dK5NU%%X`>v?PrI& zx@r-0MoTZ42Ct>HnV*r=*4wJ&5>?*+8JMDRwVC`Sxu8ITsyZ$D?=W*Y46&R1{veXc zSK5N!TmC;J-|9A`P(xsM7oSYfkI7~%|E~r6(a{lAe*B+bjFe(zCk5dQTN9J1gdK*D z-P~?SJKK0^m5Ut08uU03In#=C`46~5Znt+zXD}E={o1qA)&Pa3RqeQFuM zrlGf8#NwNrzn?uUzTvUCWBQARZSdH^$J}av?(lWM^vO18(y}g{#YsuqOU~(FEUtiX zwEr5XA+@SK__)Zz$9rEEwX8-h*OhbLl8e@M+2w3Hn<}A5QYtz=b~=_eAE^p?M{&f;=y+}@mRQnIjv5&QccB@RHS)MCiQUL076e~^r*RxFG!esyIxK;ghZmu%g zUwyyybJ7b1r%y^J^d`ZCK3s+=S*9qFt$@*L{P{!3y2MBhzqJ%YD;B`Bli0Z+c-ce; zVU1l^z!`wgSC%NNVc3K)Xnz!Yt&bJi8rK^+<7>stcEwmDYg;|5>-!a7@)4%0XQm#E z<%X>y!7~Y86OL8NpsVUuqi`XTG*}qG2oLpjJF1C3p3;YIxDXFj%SXl~z`Rq5{U=>H% z^p7eJ@*k?rgZKq--~=$je4mfl84;th2_7G|JrB?lhJ}E^I~pNiTU%SELvNFt$jDb1 z{suar?g`98EQd;iIx^pXao1-OuR!5NpZR_$kITI80-BCfehB+G^dAg)?qo{e- z#QsBFy=5WyyU5-z!4r`?N`Xl2u&YpI?sNvcNR>uZKf!`&j#RTKqmHjEY^?5C_T>=B zCtX!WoG5=5#!3j~N|Uj;tDEhzhNgO^mdE(OM1ah+hyMK15|4K=ZRRLOtJkQC(fEqX zQvGcY?+C(2cnY|9kPN8s84ji2(QGc@i@F}8A8m%ctu2SeTy#R{eJ`z_lt#mMGf8>^G|Oz=({8#o81u!WHVFq zBrY&=(P|T8vK$9mZMq45zcQVbL~Q65UqUV`p$;{{){uAc^nMepM4BhbEcEH-g!n2JPk5QV`5*R}=53nv zV*%>#2t0jC%xNq2Ip045{%h}oCm_Plj*lmlt&ME1uJvL-TGY>vGWmLgKFX3SBeucK z#2Gi;78yS9qyO8hR|K5}VKYHjXJd-i)_RTZc6%;IQ@tOy1$p_K-3J>jUo3InNIrSg zYSJYooZtb&gaV1|oiEnX6+-hNXTe}qtHtgC<~EULiqHSN{0Sa#L9$HACpW?p*}$+X ztUV~Bf+XobU;Fst{-1Y=2807b3HbM>{crpgUgqmpg%8t=)KYtD_`WKCEFQEV4*6pm z!zM9Njq?}>N37N_YsdX@WJe9@>bU~2SuSpFb8V$uPEYux!J{eAzvasAqwf3h-LTU! zAKz{DpZSv}Wz zGUB0VIsDy1tWN}D#l1ZkRmha+=yqy8Y0w);75UiesG@9iYum({(%LtGKReF%%IXu{ z>23_scpPuXi7YV70?Wfe6ucL3dU7WJI}$zV{ZVazZ{w5+Cq$b3Y+1a7S!9OT{qI24 zrRQP<;kP)wajud+mGHJ0(2KBE7yHVn;++VrZty$GZ!zi1Q<@?=DX$7gN_TQ)C1iJ( zH0DltV5k%weXw%Y`;-Omp)Qt9CkHX5i>tx`-p;g95;UwCW}wtq~A zIoE7L=_UOLs^Uh?T~9t1O!8Fd;g3J$y=UiU+kL>CYl1zR8s^3h?*vQt-IDTUWoi+< z?Jf7wu>Jf)+L!O&!shyV>I=QM0I47@?701bHi~dDDZrTXE#f`(C#de^+FDLx28YW6 z)~Rm}7jcYINiN@Yb3yk?S66Oe0W_}`1+kXi!J5C$mDYq}iY1bZv-l9pNu{$26sg@|cq=67tVxbIvvq@@M z{8M}it7GX?*~!`y4w>kpcWwzF&DYsJPNIe1T5sm<7ATVjg~;s}8qAKr4{k|Po!6Bm zQ5ATs`SqMg128(=vv+9%UdxM#tc${)ulRwhVCnHr#G3e_Fr9% zN68O$+)w#OSF7$&!_8JlNs+w$S;mo+XqUzRKrS_KbILzfUQtm@jG|XF;P(qO8l&fC zVQNkt43Fvc_H9g0mC>0IkgVGR(pq110o1jAp{MjL-b$T5Sxe)m4<~XSSuv{6Uj3Km z={QMDk*7x@O{9No0i}-_@BN~y&r9oIdJWDM0!tCX!>MeJD)9SCV+Mde#2Om!WXC+Q z!kn1-hxiJS*yDQ9PeXJ-KVyaj6XD-vSE9Fe;ar_@fA zt(aDQy2eNNFK)pT(~?>*?@!@?^)x zUIW&+vBrtlewmses%(SO6p2z0c~NWt1MHR!c9SQ>-A4nS?VA$02+>Cm%Iizp@2Y%x zDy0nJ5*lbRpa7Y|+fM)+T)Y0`>5ot~L!jZ11I^mb&iA4)M+hQynapxz!xyVANmCN= zrocqI5$x^VFE@`)--%*n^VM*t({+e zML5!!*W#k3b0;1gU!VLsad>Gc-#NNGlkXjmrbb?0UvUflRV9F5B6X~sdJin0MgJ3;O0md(~%u&UU+S*T-q`L8G=xT$({(H>{eV zc+%h_3eys_#nFa_caL#mFDU515!}IN5TY^%+$?!Q_K^V%^iW_H;;q?%fr z(5A?g!r|e}JmO)$wYIlEJgyJwSMGDvpDK$(=%>A4See`s(`W0SG=^lyBuh{=;}MX$ zuzf#}B#M=9T|s119Shl#2z)m;O#lAu$NbzV*_Y~DH@D{_ofI6DoYY+0cTSF156ply zD+9ip<90c-kF|+Y9UMIaj6*zG+v;@g-}U#s$kSjN9`5|R^W^y#qhBfO1F>0^?JyE@ z9-m)iH(0Qm=+sYsCaF2O$V-5#ijflX&4aY(kirn@yhYTz4TDl*diJeUvN!FpZ1JMx z>zTz$ldy9@qNtrxg_nK99 zO6$Atnfw1ClD+>arn>(l^nd?DcLsB&XsYt%S~{LhNXN-9Y}z@NYUCsaW*z5oCK literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/shared_conversation_view-light.png b/testdata/snapshots/darwin/shared_conversation_view-light.png new file mode 100644 index 0000000000000000000000000000000000000000..09fa005d2cbe409eb404c3e660a0f167fcdcf1e0 GIT binary patch literal 29902 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

3w~B>0{Qnw-4Gp9ODyUflZ=dfYwE5d+Cl9 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 Z0Lo-dj|2p>UOpcHeH~-%YM4{(e*n;?`y>DW literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/suggestion_chips-dark.png b/testdata/snapshots/darwin/suggestion_chips-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..8d625526d19628b0a67ad35d7089443c9086848c GIT binary patch literal 8338 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/suggestion_chips-light.png b/testdata/snapshots/darwin/suggestion_chips-light.png new file mode 100644 index 0000000000000000000000000000000000000000..5d1b6fe6f1f1c9c718ea301e7b75038de53491d4 GIT binary patch literal 7922 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 P093?;Bn8WVX#4yh*#j`s literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/system_prompt_editor-light.png b/testdata/snapshots/darwin/system_prompt_editor-light.png new file mode 100644 index 0000000000000000000000000000000000000000..6dced57a6ce4ce0899724363754a5255a43e9312 GIT binary patch literal 15262 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/thinking_indicator-dark.png b/testdata/snapshots/darwin/thinking_indicator-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..36e4f4589ac120c9b9145290cfb324bb2bb7683a GIT binary patch literal 4048 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 k(~{~Na0~TgJW;!}L79&GF3p%<> z&uD!p<7HawYmM}$qhlo)>FHX9qBo}_%&crMpxv>#21jL+gVn^Sz4hJF5|YpOS)pj2 zUiWb_GAV1*-5qw@YjAsVb6|YZwDfsJRX*}TbxSYEyzDzt|AAQHYrWkOF*cTKT>2dJ z-j|qy$t9krbBA%IpCT$-XItn++1#*G$LE-6-+~|tIwB7&Jaj&vtZu@_PESw&oyY_Z zqw}W|pkw%U>3Ee1dYlPY8FT>{?Wxz8U_#*rLu~!3wgDT}H$5&z~M<#y6cYnGETitZ_`Dw=&-JB;E9itOs}|nhNTW z0-M+&#@sa&uhJjz^%>!q=?GwHyxyJ6^Fj+e?h=Y+HToVF^ zyD{oR;(vT}-yKbO=tW(y$DZ>ik-D}v*1SBudu0ZaIl3}l(5}A@;tv9pT1H&3h}IwU z%o`A?S@qg{*2(y@VbayktHU{(!%hmm4g@=!r` zAO9s>D21J=#M+*)#`Ui3100)>*iRW9D{_I0d-gdg6!P}MRug4leh;f4Lkj3i#;t^r=R}&hEcq0lz`0W2vc1paEmCQ}Lpm8*?*Sf!fay+!vmyosffkyV)UzA+8FFBaY^gAz1>L!SO8p@nR^m}wVwMp33ztPf+--j zd#POAe9VlvyO#aPB&+m&J=e83T?eUU5N2PXyF-8hzi)H46eyvkl;7@zt^%ol<^@DT zKl__F+e7m@wn2x8`<6rHax)FZrDdw)Du7wRe;ARHCfyf-vZ{AOy7@I+mRvTxHdvOf z#s66C`P};~4_I&~tO>pqN$V84#OMwpJJuL*`A{HATNP4uoV z6WJ3&=?tREnjnF$>-QN`BURn;wv-48(a%;s+vo|(91LT(D9)QVC9?V*rjC-NZAb-skARYi%J-!_r8d-RguA$j^5xN7C*v60E$Tj~Lu^e@;(XXa!+BsH`(Kh7)!IYzhP>r}*Lik3@mWQ|x| ztn51}G|n~(HF#{|6lwhN3Bf(V>o{HBhEm843~}w)4!1T> zVaTfSATJEzN4+@8A&>(d{Tzc_mBNth3+>-7UM8OBCGdC6;XQ0-lxx78bt2u~o zi`(DDI{}Y|bXq&yaREG;v1FIXA;lqLDSH zuejxCvvBObOIrh3tK`ASAGU>ClR-X@tEap_^xT?O^l@;WPs`U}hnOpx(@0La=K4;I ziMTjbiM@|qJv1LNr!D_iL0027g-keUy`*+a<{fI>M1Po@!_kUV5k*EVFu5jpv!c)j zpJ}q(WA+j!}GF#UKLy1d^CD`HIt@B{f<;@LrVkg!L7xNszo2WoB9rA zxW9oG<2*2>1;?OBj@Ae{L&hUDk0j zo45j5(0kMA!ZBrrm{TO7`{ery2ssgr3u)|nwgaC~JYlh#_09FCv4xk#G+sN~Dgc+S zA47`*`qc66b9q0A>@Gn+UCNI~lq-lEc>5|n9lb(Pv@qraQk6>nrr@$dm>uVa!r{g4 z|BOve{|SgN&MN)9dI!(}O@y*T!Vd(QOCHAf_z|sKN#J`v{XkB5U;&#Cubd>anE3Cdi=TKlO!T{ z?U18M(MV6o>np!P8N2`eOMu577}*m7l@O7#G24 zP;?Zi`mVMp#@;*=tr2*p>PcrH^Oy=x1;k)g&cdw8kie5(= zoW$qbix7X9#-CTqT~=cPlo82;RP)48m zW;^Me5ZD&z#hI0j2T_B1%&N{sD@`)|%{HQ&3@RRtHs8sUSA7ZF3Z;#tHI!${+pdis%?##JzU{h4!*#bzqVg{jvnHoPmor3^%*0rjxuef-4%f0)fi|I zM}J)7xh~^Wbx4iudk(aM@lT(llq$ehuBz(Y4?vlER(yC^EE-z0hCc-b2xRpN2nj$L z%_|?)j^Wh3KN%W&`#=q#*%d!RT3ae-R7iz%h0HY_P0q0A&Kq69G{+u~5W6;OW(#Ya z9q-YGl;Db#q`~Vvgww03(1Y++xg7g94@Wl+$MFfJy-PPv1f@L&(tka481vXaV{cC+!YSuGug zJG`HbSzaB(2$VoXI3nBoqTfv>)PbY%#HH%vT4or6MowC#U|e3iv72Nn)UsHbR-gb5 zSysD(vq{;MsFvZaKu)iyQ2(DUUz8oag;x1LT8~3Geslhw@(wv)3!lr~_8p!RXGlAo z-4?ap|97H>xL!_O{!T+ooSx(RLGlUbGM3$F5Bqubb7FI1ze&!7$3)p9OzGH~1@ir- zXIrQy#*VtV+Ot{}J*h&%+WCxw)%a3yI2@LKD$ueBEPCYVoAX4YLgiOt-+mwO0^kKd ze)rVU!g4_JpfiXkKx;m;Ov)3-I6W&teHoZ@R~iGCWJPE zmEfquP!V?aqurc?uHwG`mdf3*b7X{V!+_%#`Td65ZUg2V2^znYq{GJ+b~c ztIH^*>6m9ozHet|OJ2+D^uY0a))$9Rm52K^3Uw=_9DB4a{|7X;j%0qQ4!_pfqO&T> zq}UK1i0mf?g3;rBx8Jp8b@d*7Ig%N)3DuncA~`gpvy! z)AW?w&PB79O?e-M6V`}uQESy_rejz3k7tBbD+hPT*YzP{Ek+5^UBZm?+*)6A_Xg?X z+V!&^ayQHjk^*`Do&ZVHWyIg#1N7EMHul=6^AxYi>Z!v%N$h!$;zmK__D3xPXS>sntq=qPQ9I7hDb#=%be89PIjN(eq;y}iu5?~mG|G0}X+-fowdg9P z;&#+^=4>8Yt6W*huw$Ke7o0XZ?Bv&8sN>pK`Q(vI^S^d~^ImxU^bXm{cTh#OE_SlO zmwq2hKbKX*C+OZ1Y*T)wJk4AY!*2ii%1t2W6J>ekHwhN9nu&r8o1lwz8YW>#6w1rX zho4vI(}?F9@7jZG3w9|Heo>J&%S--MKmoIlnpz30(Y-r8jyHbMf#_IiD*xXMX=VRE gTUrCss6uqP!*#Z`pF}ljKUz8?eN(*}h*RwU0eXuuQ2+n{ literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/welcome_screen-dark.png b/testdata/snapshots/darwin/welcome_screen-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..dc49fa827d9bb3b717d4f3e71f618dc16e1977fe GIT binary patch literal 37202 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/welcome_screen-light.png b/testdata/snapshots/darwin/welcome_screen-light.png new file mode 100644 index 0000000000000000000000000000000000000000..49286a001a3fdaa9b6dedc782ae8ea350524f8e1 GIT binary patch literal 35835 zcmeFZ1x#dbvp3klAOnNVFu1$BI}C&S;0}YkyX)XKxVty*?(XjHPUE`$zxUnbzBij} z@@4bwZgNjm4(I8nAD*Y=S9PlE5GpS#h6s-h4*&oVCB#J(0RX5#001H%4ifyz0fDCj z0N@Ld5D`*xO+Q;;LIp6wb#>`fzT>Gt;J_zO0eVfs0)4PP#N$XMzOCb91}Xdx|8J6j zw(qpT=7sPobuS=F0C$I6bYY(SrKwoTICi-O-a&D6;9?$u16n8qoua&kCc_^CNo4N$ zz!vBFx4K9ox?`CVo^+sV^{C``s>qcUcC#ubrB%{|%m-2m3O;cGonmMKjrfM04 z2~eiiZQ(1SR~IEFbeG=|w5}0L-WYY?3 zQe8MMmS@W+Y1HYHq6c9`zvdw}LO)!zkDlJ0eEWAXwoqf%Tk)ig+br*ZTo?Lv-ke^6ybn*=XV>8~aV3 zr*LefspzQ|A4ag)Fuzd5{Q_M)`PzZcPw#wA&C}}VGmt_$Tx)hLV4_7s zQ5FfRQ-WM2prUmx9~j ztv%)ofwqXwOU>=MhbB}!ADBuw_l-h!3BA$!V==^LW5nD_IRcM|`*m`0<^e44{ z_S&44S;-)F!FVWaGzPk23KTBVVFGG*>-z(Xjg6eANk(ZgikHKdse)aKaE=Jv^;3h8 zA4J*jMA>ANVC^x7jrK#|{&)x|D5z6?6+2CXRzzPxLU{}}cJ>V31oM@j4u`L7kNaIf z6OW}WBAs_{{@(vSbG3&?%uj1vHWg8!_yX2ryFFi1CsBlRaw;PTIAB^Ih~h{a2l^?p zq_?jv8+;n^B?_D<)Gn@wFaCTNU!*h^O)8P0BUii% z=cK8r$)is!o*^ri!Hk{7J3m#l@qEfkK_M16HT72B8A_pwBj6)Ao;dx1C308PN^IyTK0WuHLEk``ZR+#L)L^9n=Ec1CMIchb(MgZ zwz#Ck#>OXi@zlxvhj0&3f$;v>nTQy1TB?z{x*Gz<#I`Nx<2$941Ye`u=!Ci5`JZhe z8ddrfRIHqN)5{HyWV_>F;hZnX1grC%Srb7&3le2uK0*4qhyNHVz2b-a1bH`iuIpg1 z=oKc-?QXbPy9{g;kBfM}+I@W$rcd%iGb$P$o&)f%@K zg{#L z@H1K9)V&qLaN^@E`7N=ulXBDeEJlvGn@9w&|))ExSPZEyj-&oA%I<>4>2}5Yl688QPcq z8#ggT8y}o4o3pdK;Mwu;@cjKD$s>FaiT1V#G4a0|+6%2V42UvlbNUYM+Bc)3#`owT z82wQv9nkf6|1sl0z@JHjp+QQ7gWd) z^4cKUHW(#Q%nQPf-o!eAG7@}~`SG%8Gv~~K#Kg(T%ad4(S3CwR>2g`JELPL6ZZ^Le zMDOq4&d~&n$A++CQNcc}QE&el|3_35B)N&;h@roRC0FwY5dD`3kM(OZkfGel%IY}x zlSW12I7fX=4YQTP7NY=#7;NAa*n`(Q65e;0cde~~5z%bBpp&x7E#y4Qnf%XlFgb~d zD!jq=4wtj2JKID;miN@*ar%|*k_@XY2`N^3oZZ*49r6R>s#=S_S_WV zcV~v`<&Ag4oxM!jA;3s6YLP6t%I?qWNL~ZRPO|+ zpT5kRVga=4Oy5IBHwJqd#LpUWB7;p{GfB-FSTHd$mmF9xKu?&Aj8z|syC5s5*A)IN z3uj8A!RIdo}@Q{gs$sdt2*zw@sB(vqD#46Uzc)8xn;&orz6 zs`%?dw8DS7H|BC^*2>D+kpBEU_;YF05|8J--7I{kVZhyu>5J7A4sEc)y@sM1zK{x^Ew(PO2hb;Q@H_9lLkw#vv~ zHKT1g;rYJ8>a4i9H|&#Ba{3&(>KZX!Fv_u{@r=$DlGbo^wv4c@^+FdZIy*(!FC?IC{PMX(i7BQ0cJp+57Z~id(MV?r6J^})- zyVjU-<&2NH6AmANhexZ~EP2}h)#A{I>h!h0tgk4L$1|uuD=64u@%M_C%{Ndd6U%eI zrs5FQ+4mbf_ka!739)(D@Fx5t*T0;eeqvfGkJeTP9dF-QLs&;iE3xVl<^HE+L0JFn zNa+OfF&%#NV8`j?h_SfB#!SoQY46wr`)DhNj?YRSHx-RD*X!MBqk3Y&vDI8wOrVpQaDNxlhI-Hy0N$Ix^>-k8n7@ zci1(#W_Gj4jE5UVm?n{-a8&$1fHWJAvJNW9IeQ8TZN*QRN8S_`{#=mG40gnRm8X{E zJG`=lS&(R6v*$iWY_VvLyoS1_s&c5!M%%ZC<0MCe+{noBGj*0F;e>^Sg>DAq(YB2B zg@w!nuf@^P+5Y8{;wDE>;v^1sJ~(4(b+Iy;MH#nmsIJE1p5tL*8PsFsbyxB{l(qKq z>IDPy139j_xp^Uo-@^QahWh9D_>BTd$gbuwT1YPyJ$>G(??(GWRaNocK;-J@m$)_9 z<`OvJ%EiTbiPTg>neiHZhz>V5WZ87-l1iIwl2rI0$;BK8C#M{{h2`Z?YY7G`bJYRJnY*`0|zJM%CyN)ULxnr!z#E`{4UiuLmL{=tSV zV}0@Vjp7$+oT&M>>hEtt#XOEJNo!ii-uY;1sw%o2_Mn~qQJ4T!qT8k_B|V$N<71)X z)tj3O3W}n-?gcAzzVRN)^>Tia}LrC(%UlMx)lcd=QeDV;`@ig zXXn#%S&Gd=HTwI|_NNvO#l_4N%anPiYNnhVB{TOpQaLY|`w$j^VLK~@QhO8IEpX-~ z8jT-{@-?*2;o#>3a4p4i2cRis0ZPnhuf>ohqga?*`0zT!=j}4>zv(BaRQHRX>i5x> zS#l}15L6|s(rt8BUNkN;=K4q(21G#q8)+crS*jQ*Cp6X72^TGTxVyszU1SQotO}GS zNuZp>&4dlWltfR)bP0Z#BpEV~s#9Ch)0J(3o=9{*Z-cBNMe}4U3A%RgwpXM`B@&ZV zB}gL!U_G8*UaI!fGkM)K)RnDlYz|LZ^0VeIPfu}35f%NqHddvMrc`O=>1|4iQI79| zy93%iJz+YB)Uu~d(H7?t5>>8T+p@C(HVoS=)+4kgj9|DIFazZMCmHurf&&3K6o8oN zc^S9-AdtVf>fJv0LHrvQ{yQ@MzdL#s*1P>!uKk@B>__>fOEkAy%N278pav<|^GVu( z+%^Q(c6WyCn>^mku?Cv@AvYJ90-Dby+oZkAe9=e9|CBBNZzVA8F=!e_)F0EShbF53 zU$`=88m*W29<&6ajJ^T0X|>qD-md$US0=J(_*cyBKRBH4IT`u)SjWN3DNEKtv75)o z(4l^k*%BbtK&^25sQ}bt;;CsKiW-#m9wJQCe!fQnU!PUU~f` zQ(34wTXsBuYwph0o~i>Lb{fibLi`nx_zw;zbN3iN5@>af2w+5kg1Gv~${mUp4=IQ= zV?;y@BeoN-U3>(}u!JodGN-(oyMJJ1z-B1?H=1VP&YK{E{lSFx56iL4rEdI--d|I7 zL`3L6NAyts5C5-A02nb%I%qd`o3Dm0sGEdGlc$4PGJC@RbQRyR!C$()9Eq@x!T+*qGFMiF zt9lA_E@`>IC2rU8x#^RL9~NnU8jF-Kn)j;TEwdu9S-rn*2=GACphZ8S?V{8}V}!?q zj(`+}$n%}X>Z9DVN%(F;V+$?Y?p`Q%WXtLOdOw)0E|k`2J+T>6d7+eqmLzW?Bq%7z zYv-y6ivm76y;v7G7PNu0W{&!(`o}59cAxFIE37w>U)aA}!W+Y`p5HTkTpO8-nlHqG zYYCw{-`LBn)@e?QH;VHr@|vnRDL9I5v9taijCnqnvJLZarie{UCzeH81{dP(^xgz)c)m_LlUR+Udu6S3F#$h8m z5vldD;tmt5gVx8?D%uF(#T;+N>>dVhd?Uo zLut6AA(6dy7`H!KgI=4T#uZ)o=x967`-{M_Io0&HoXd`9Sz6R0qx=MX8n$(E$=Y#O zQ0a%d)BT+KBAl)VsD7<&ZRt^sJf6$sB7NX_0Ad|*w=ItqG(xE)n!^mApimqkY=lOg z$D)bll>3qxveBwhhh;<0t%inzLa0r0cYViI_Yk8|a1dxe5V?CI%O+f`xz5MRnQy5m zo9UC6g4a{%{>`jjP3)FrK4D%;M~yg@f%})c@#F;`ShsFvAV&@DWjli)L0uc&>F(Ss zuI;kL3ZyUauSOpXVBN`e&E8vR&yFnORI*@3491!!l}f3QhD-e!-Auk5yjpGbs2n%{ z0hfT5G&f>FW)}A|9D@o-6NSsYgT3)|1BzoEcEFmv{=_SjRj9cxqXm~!I6xi|q>p*f zP)TFPx)PQ^lZ?p{Mo@3C4<8YwCw8^K(r{x{bzP`Rq z?ya?KCw7}MDz;A_9Z{Oe=XEcsZE`a6)|~Ylp~j*M&_wrml<|E!&$bdlA;5JN)eWgabkqmWa!@arSm-KCnk)2&33?Drq4# zi;HTAy83gKd4XTnZ_b<|Dkcg|3^D&=U9R2fY(2NO_jeCx(Wb9|aDVTBFfbS<_%8=s z|MSaBCuoBQlzT93T9@3EeD1TnQE?$FD*;yR6?rl;rC4yG+>fGJmRc4p zX&Buu3XDz-+C&Yv^A^%vlne+4wAsPDWUqZY6k zHw#nljk<^*r1tnM|%abO*tb7&z4Yydr6{bB=CF+J} zR)&s-zfovcjcUblaUuLD0tL3Aw?Pw;qI{-T)+ILH*5qMEH~E`ItLjoZZp;!t`~?9y z59r9zq_1UwA0qp32Xab~WkNS@T>TsY^N52uFak;-=_T1KBuI-aHVVTCv)HdMTL3CL z6-$%`{3$9XdiY+67ldoC&nBjo3jZ$*Dp z0!4$xM8(8PW+{HmmJMsgNdUiP&mJ>$J~Io8uS-PeQhwdw3W_n(lg}nP ze=;jjeoaJ6`htx3@Ng$KDB@Dmva-5@=L{>5Do1TD*<|HN2JAw<;KJnQakQS(lBFzq z5(VWWV1$jzB|hBUZ_9A%4*8^Wx#xbu#ICv9t+=bdvl_PopVw@yyI-K$5tu9^f}WnA zhy#-`9qc9y$OlNXIvg*r`i6IIYV0dS!)a{&#C`RX3srX;80L3#w*9kVy>7b9>%pMi z`rJ}Myo%>6H(A2rd}H!()AG`Ib$d&S6YAKaYsB<6XUGm@TLk=+ySqeLH z0P*nN@j)K3xUqvh#5P3W^qE?PoZ8qsDU2QyI%IIB0Vka<{kHGrDSFYdf_+ z>aiFtDt$rLIpn$(a){g=Wl5T-7DjB`vuc zWz(5FUcmNxJ|;7Jpcds<9g8ON2qN+*XyNXyu51<1QHn+5@Qumwox5^~uJoRU={9GY7s!0Y{QdeOdp~R30 z)~mf>o2L)E!A%(RN(;&32ThNh_O8*hNq9ZhHddD^E^}I^S=~#?5=xFm;C*sOZg<8}6MS@HbqRqPNA~SJoJT z4Z0pby^Z8KC~4wkK*zsCIdch~99N4lCUx^SLjHR|l*h`r9yz*YX$EI0q5;*Vxus{W z>VkT{j`ef(w!a9!vTB+Ai3$~kdt!PeCME&L#yyABi|}K50jzKb^asbgvyJ*R*&-9V z@e>uN*<$NZiBNF1umoM*(b0i?%*R%fXoz?M^YB(>V_@JvYzQ3JmEwmq>(#`8f55o- zFzXyQMo9f$XE!Tqu-e+XP4?%TWSG=W|Mdoc{G^Tj=EM8Y&goeh_ypTvP+Y;&J4$&uGd(Niww1q{zbSv|-FVwtry>ss1RtKx zGax&;f39AC6oeFsxf{Eii&BfDk-~q44)qtwQV;!)%;%rzd*owjg!UDD+#ts~HjQ^# z!C14{ragJtu>3cC`2XqfNLue!_iT0DJY5hVcD>YREqrENOLSX!`Jv+F?>$`F1S~+; zgpovj9s1${dO0+XT!fv#6*W@AQWi~6_}}}ZF>$)}ie#mw!K(CTZO&_R{mX6-4hv4w z+p=~?s}C){0IoAK@-|{q7c}tPmIy(8NK$A)b4#P?>~`Pb5l>%xHPhRZCNt{gaB-D) zl6ha*O<9LxBZ>Xt^wkXV<)ugfgm-uRU9a?ZB&G;Ur$ z1g)(wD2$qzpmH?B3jb4c=9PzatIQAzmNfNuZw{SbP#8^J-@nrvf)`9RqyfD+Z+L5r zsnuk+JrI;OjKC4^L&DGtpttp-q1PG`Mz2wfsYe3#hf8Niqj&`#k@S7=3rGC?k3B2@ zYtJh1=D4tUU`oP=9UmK`eIBC3BFi)U8xg0#EGatt|JlKFbi}*yrF3>`Q-{ENP0T0t zytA+D-)ZFgDbXN=P`{&=<^E~fx^bYP&lZ?6I1SdQ*Ep3$g%HZu5V80KE%F5gHJmc{ zC%O>(a!+DRAlvYVbgKkQs_4*&+S$*RAKve~~l2r|Kg z_m(FgAq>7a!k`lEC%(>rGGPX8d=2kQzNB-7?B4K*>>mmGXO3IH(zTwIMWgYxfunW` znGBPtI`-ZPU)A#4u~R!)4?e0e_}<(4c`+P46MpJL?S=T%^S}c+)AEj5n{46lbOr85N`h09Z1| z;kb0FtucGSdL2SiYD@bpMNpi$NchnnDeD^5%6$=auz7gqrWLSWwe6)&+%D8`LeL|__P5pK7odvlx zZnXB&rLBuDx5L4$nRC?n`FS$(KY3fB-*OizdRPpc(%)X(OF`0M+E!cF$EC`+x8C^4 zAQzrhL`1~9xscFe)dyYAhjzH(HajJtb&cy3uAPT6eC z(LyBJK;Us4gQYf};_0q_zSM`TCXdgsTq49X`_hB7{kk)W6z!p@nZP9@-XIC{^ zpl@LC_dVIj%!~*%CN5oHN3Ux8lUU*FH2dLa%uN0~i{e9Q4d?ZVnojh5+>SQ|R#v z62}@E8uGTYe}(%rwwQ5;vv3A_i4`Gs+LLUK?C&SjLc-ud_Pcd4Oh6-J@VMDPCXU1_ zGO+H8z$)gL;-Yge^aWAOppzJt)g&q}pw|%~DAGruHrKQ4#>w;Xb8I3{a_+8N zw-H?s7vH4b`FbtOvnk;$*^7ed0hSQu3WnsinnaJ&eaomrOA#6w|&`SKO0*; zHTBTqCz^dB2L~1a;kNb8#d^n)Yf8eMXD*hu(Dp1^K$r+IZ^!1ThpBE{=ucsQpt>>p zK@5yL)^jYs{!Kko0O~It9Y3y(0C`H`(cgqI-9jt-C=jy3gS>oCUWs=fnhJ>i&V?PHo*G2CG&xZ4 zGcxA4l(tk?$I231Hu_*h7Ou1HAmOil!}Sd9mn1{E0{3Y>tRI6W4vAvkVH@M#$Y};` z!-8&&rpJ;d8HQbB(~`}r4ImCqalU{5^QGX}^f!{cs;bZ9R5dIzenUe;B(BlcZf$}r z$4|1Y>O6|v+;=p%Puwls$_dJ`u}OEgP6ZM2cXx<`QJLa0GP|}-@bEX_9x%=N6+8gS z)8L)vbYnB_1*sH*wzh_?JY}c|d@CBOBW1$mApws&F&SBXd;9uQpXq$*zUc{UeG-F1 z6fXb!-taGV^<|kfc3Kx*{|r9^w6JLiGSTmBO6v^xKUwm^uuA~|YMEK{^Bv%uwBeJ^ z9fgLv%*Z5zxU9i=DqCJf1szi?7B=<}5U9@_zq|WYT4oSFsOR=J;+!XDLmxh9XS>?^ ztz{gHRjUmb$?R6tA-($K1+P^Otwlw0KYl>1#B3il9Bs6}JUu}>wj9ruup7eHJe!FR z75osuySu-(chMb@blckAR#w$~08IxhfqPN15bG7(0f6xD2z4@%jJnZ(jf{(eL~{s^ z`5^ta1`rLYBCuG_m^L*P6&3j!T^Y1bT1+mH!B#_~TE2SRdZ_3szxW4qztOzr6`D}r zUlM;PEKJ`_Ymd)m|H&B&E?+=V)!&fp3+?f`T$=^A<2Mn0^duM1L-76m{nl31$O!fK z1bu7kaBdOCMmxXSwA@^StssZzXLs=Q+AW6j=R6#@cXx_$1c8BCVJ-MMWo6&cvF%CU-6&NO&ylOw1fvoL<4&_oL~f+p6F$yz+8daZ*K{ zjWP->xr%ZMI$NEYxj9EFUU5y2M^+xO%}bZT0j4PlQVIxj&;!hC)>MsIw)xr|BK65gm$R#s+$L(``qll6dKPq0V zuC4X@bq`Z@yS&G%fAF=4No;3a{s5F%Zbl z&+j*R*xF3DQs)MxVF?3(<0W`KkZCSD6eY>41OTKGTll@6&qfj~IyyGM75w;NLno&@ zq94JQkJd7hBTzZ=lwN@bwHB0U%(3EsV`EczCaLJoE6d9^_f5E;#0q9+SkFcfeqU5{ct6rai0Pais_W{GR_5mt+(3uPDRSV%#?sVOkI{e= z*ZSA5Unccf*mmH461;V#f!{IQ5YC9Mm+jd?ryQbqQLNFm2w_ZvFC`;%g7ga)n%%|z zx&HqCo>o?PeuBw7lb;h@ikaeL*w?@)v+v2B_V12+|ig-aD1*H*)Z{0qZ|;q66{*e}258A5Y;Yx5mE zGS<|fvDAL1RWaY;GZq#$P+Nj_G!j8Ta6qSFqv!W?6X-W-#c+NSQzV!8OHD;HGVD|? z1^#k@86db=i412bU*j=3k;#qO5|@_NY4Y&Cw)WcWkg>NH4EM=DlRpTm>KKBZ?>6Un zn`K2_o6apE=Vvr?Ke3%0qBOvFtuI8ppJF{9Y@NxNIBxD%mRq*(P1yVU#}4tR5(U&Q zwE5Z!&;WS_FwnqAJq(D3n3;SqEt)y2(ee}@0;eUx$LqGZN&BR!m3+++x!za?KhhN z{SN*ruqmof>g?_9JwKj(`NA81U-T=4+JQ4&z1G;&0(p@B%y-;4i|@rkfBW=E(*>v% zDlIMjeBOu<9GvHlozt{7@C4EVH;lac@R(Uy4eRx3b$Z7W)=P@1t5@gb5RvSbBrXin zA_4qvMLKc52U?vszR7B@wsfveT6O;FY2d%S@SW%Zx$-(j;nyFt6r#dC-rT_B;8^So zS`(~A%mY%AF?X*YUqXjvWNga(f!eJK^74Q1z+0wQtt8fd&D6m$BI|bmr{jtXw?Qyg zfRuf6jPFn@?Ylyg)_uP_8t2dwpM6?kLI%fI>OXtVaf=x;KP`R}1H-oc*HceHv4oYT zYF#LR^=4Er5Yp0F1{{(Bdhfi8adC=JP;YdZ_z{|mlxR1nJ;YQbN|HALBO|55@pRyT z%5$oFt%%`@%>q-x_q$q=33h1IBWU9C$3HNU{WXs+^7U+K@8P|U^=7lV4&&(bblP+% z3{zINmXRP^F=3o^{p?N`Z4)P4Thw! zq~v%y?=})&=jO&nY^o5+AQ8nB z(Ltby6^BKB#r=L~VqrlOE1o|q^FXjvQMuW8XGf?@%Rs<#*MYq{{#4>m!^8fxvha4~ zoSj@L#tal4JmYJ=TGUq5xNQG8#rftSM!DRXBuFToY3am&^~L$Cl4`9sI{i;o(ZBKW zt+v}*78YgElM^TA?0$l3X9u~ZrS>;{>b&?qTU(hiTa2tb;-oW~d^}R4Bf|a+ITpps zt8#pYo2yl z6ij?>bB%2`-*;Dn%$11WiUIuIWfIOAva0qlHb!3oq2RdGHWjz9M}^z|MOe4{r+kXvfMv!?(?|F}cQVF_B@&2`IRoIF3jj>g8rB|BXPt*ZQ* zufvN&!^2N6SrLDl!Zy&O2P<{XJG=(j&ng4E?~I@qyT0WOzi*HI$|Ltz2+^-jV$DCdd3g719q^Ft@bcLm>@Lra|c_pQdqm8@j2*FTkf>)#d;-ge6R z(LR^w#mwGXnB&I+e`+W;NJt#3rn}h%G>&G*UA98b&lD{_F?ZI~#NiGgLL=6`Pfa}` z(89ePPqVL9d;K_7(YNj1I>FY0s`QhXHASmozf@$XCEG;G>G1K_l%JG{)^pTZlOmm| zYUR$CANmjpb(ZCKW+RSWS|));)DU30n}%`37^H}8RLFS}I--xtQVEs(TI}kG)ibd^ zU8M`Y;e|{neA?hky!zx1QqVPIf0g~Z-aoB31B*U<*L^u{O^2cc?teV>vJou? zRt9~7)RB{e`T+(0^i~cgZ_`W9zu5mD|$@59N*v+xvyc}O5A+BUsy%UStxu)-4j63U;VK3Jw zU-D5FBjr){SVe9%h-SHI=0TX8cYYXP{*pQ{(N=g#m&Nk<7b8B_wej&!s6_+@E8llCBzWB05=9m;7g>;6z%gO}L&t`66 z+P#Rn%NTu6eQq}#feCu1N$`DtoE2v)%BAciB&3wL_)4u*ygR?tw->bd{uyv|c|JNh z5&CxDiX4U8P*o!``7up=bSV|qX*j7SNE$o!+o#wtzp%Nfbs7&7;Oko;ByD2C0&+W& zpp^HQns8>fH0<4s(xKvG3VvQ`oukw$AEu5&cf;^SV;)OY)4-hF$6??uA&@m$TEVphwRj20?ZcW;jlhd&m}C!{B{ zjA6o$t@3g>0EKA5Zc=q*sSB0kX^TNa(l< zfQ1WVJ!=BsK4;eyB$7c32_b!BcXx&?fyp&uR?Eo7ECK)_)%(oQRaJMn`k6<8E3dc2 zRSnzeB2^^}Aq7hrAw^^Kq>Hl)xRfANixm%?m>_unsLt@n%wzc*&>}+ow6jZ6*4yiu zM7v=DFKY!4CnUfjCf#_ZJJnPp~R)HbLN6?}E2><>cf7DEmpY-Z?Z6 z76~Spw$iY=nU2n3{J?spBeL5N63}O0H`D)kG9t-~)amZ!>P9s>+|OlrS9&v3b1I>_ zA#hV&0|&4!ST`*%^Ld|Ft!ps;UPS!9#sv^OyS^-Dufx#wks(Ic?XbP}R!%T*bo3)} z0I{r6xUkpPH8yB>*ycp8nhUdjhJ%OK1}E9Q`fiCLw6e0|KW_fSDTT{F013|uqr279%ICb!De0& z9@VpLi%o(NaIBV|^|8>2ymdVi%~wi8{nfjp>2lpgyfFFFX)zA?7Y%Lansd|F_o`SN zk0e&~kMqNA`dY!XmR}T;0Svo^6S(t&^4j3_ZA20msgv0fF?IYCm;2UM+?LV4kr7^n zl_TsxqKS)6^I!R2%0EeCdx+UxpPnQOX5^5)o9>n~qz{Asv}U{>JeJvXvMr8Dmz_r1 zOo7d6jz;yAfR~k()e&^7*2#ojf~QsZG0QM(F`rs`0;(<=qoXC^u)#({On-cCk|(_V zeC6V3&&3?lqh7j`Wrung4P+(UyN%_(uGIn_^(do@cNXcmH zX4~7_B6T>yaC75%|Fj+~DoPRMMG`AMWxxh~YJeZ@a;NB@6RUsQPythGoWX}0UOr*U zra5@6J2AL#yncNH(rl-1E34f-Wq1#;A}`Kza&rA+8bi;*DdNUH zsCZx8-e~BE7NF^Ic6laur)z6#s@}r7uy9_$laaM}&4`nkxo7u!YNl(eOVCG`Kt;D; zrnoytG6Df!J?ctJ(m>IOi^ASPT0~m*Y$nu8Q$Hz2X~PT zSlZhfkoRd%4atZZmC;a7WJHj~N#`|MlYf<{9_+NRwp3b&V4h{69o}=AR$wk+y?=C3 zEJ35eKVcN4MEMg)%nI%PaQEeLtoXov_^6>Ge>6qXaFv$adUgO*fPm+n zlZl6zt5RTV(qV>XV&h)Z^Q?wADi^xQF&QL$)Jn&HEz;XX%lvGwS zl5WYUay|u_GbR!U*^R@{_DLzXva)lRz=wmCb#9%^6CJiZJWBB%@kejdtVtjwgr6WK z4SncxwbyYN3ZToA`%OTMUr1_-Uag{eYMzX1n|ao4+tb6NuhX=lVThM+-7jaCB^3gU zF^dEZ`T@0RWndm9b}`H$7~O4qdwYdSQd6J=0Qew@-p{y7L{5%R~s2+^Wy_m7zViMwM&M?}%Z*?7%=yJsf^NX~?|19S- z*;AQ7P@>6Vg?Af9MMbG3ILslaYbeXfUG^{PvN1AVeTH+rtoM?+L$t=nS9{Mz&8>Gf z^MdkXwaNB~aHUOi`dh$;UM)G$PwesXf&Yd!Zst#`gI&jLSyA)3Y0Vtzkbt56&)_Z{ zE!~I5?JO_~NeUjT-Btrwv;dD@)>(Pk727*>pV@3FC{Mq-v&tq7l&0f55r+77>N3Rt8jH&@Qq z=4N-=nc3MNpeZyw3( znzN{&BzALO1abdnV`tj9>j8~$Rdna1mX_91$Wo)h+xQ6JX$!AkTOQxT2jx~as+OM6 z$LCPIqckGE9(r<5XcYX8l zL&vp>cOq4^Os_ip<|YVINY14ZT)P?>5ap!J(6aj!g_`;aAYZIB+w3qkN)WnG!wRZv zWKi^STi#eP|Cv+lvP=7al=sy^k$p>=(9l4m-MCxh?kJn4NeLTU8NM!7c8QJb5znWPYEcQ}U>vYWyBcLqM5&C>sfGl*sQ- z)PvGmze}1R)teB@uWUIWxU6fWG5j*botz!+5Ik?2_-QkJP`nt-)5l}YthUtU$Q&k7 z^*Cr-GaU14+O!OI`5UQuIZbx%tpL{{C^)F~wYF8EcrJ{eo{sKEQJk?w_~?l46QE=> zro9}azC{_;{HiX95V|?K7Zw&al}74a?l-1_z{HwhWED}Kj%HO&mJHJVTyW%WzExlQ zo80hD_$F&_xnb#tmnN~K=-WgH&}UI1;eO#`dYh|h{1P}g?n*5peIr)l7}3Gis4vlt z`eWvVp@RqHh1=g6(O6-Q7T{GT51`SaDA74$mp{D&42Gh&5TVhB>iPU97H(oSLFp zMb(k=tiR;)&mC6oRBX!ib?VD-m;}Y*X^K>2sWzFqQ!5;Mo3bP^G;PD33Taf+0t>hS<{%*QY9zT3Lz|HODwICq#DOpk&-<0;-aOF3@ecunbzAalttW>xC{peJKNoqEJr_5Lx&vH4^;u2N@ zRs;kz7gob3F|w~;#faW}xrw)>ACeJ4hlmLG>W5l? zpVOh0E1GRUc*7zm-f^dJ7Y^UFWrL0{Sr0ELISLTXQ^xc8*nWM@?jkTzQQ5si9_c>f znloF6xmzd_B}-wpnBQ^!VnKm&1TpBS?qfq+-GC0FtE-EjIP}QPJ;(~#)>?HWvsO-? z80nSB!A7S$p}M)5r`i4TG%CZcrl$H=3?d&f)Mqp1XI3X@^x=n>XCoPF)VQwc9aXWQ zy0RiRDn=Crm*i8vkn((6Hz5-#-CL!8F$;?;7Z2&l_`ZoV2uRq?jYtr)o}!CdY+s77 zQDQ<^pMD+zNhSMXg{6R&*5I*{!G|6_>B8!COqZkJMJm4Pm25ERGX#Vdj={&FI7PJd zJAx))arvmtT^Y{4{Wdq~X?`dYO2JA6Ds-76Ny_G5eKc;Us7_HQ*^P{_Stz*}?7N%H zpyovbGBT|bGv3kZ^T(pjctokpO>brUa#j0~0 zT-^8TOVU{096tt}=%Kuif%PU~A-i=SPZO6#6xE1#IT}o%5BA7mC0K}7q|bd!_2%J6 z5!6Ur<221pem!!h z>Mf0P)!z;IBJ=if)cRU7Jlvd;VgPC1WP@y=`9R6Tq2XD&wV#+sTQdKznxL#q<_+J@eY}@GiDS6QLS^^v`` zKNeHd=fnNZ^8pd$@q1Yy6gtA~dPoBfE;BJ6XvB?7hU12iHZxyTlY`np*f|Ctu5f=p z8F?5tVZ2I3#@kBqVXCEuH)EtBYUtNHn1_5ca_Spw0(BFc1tHV$ z_KLZaD7?}5Ik00?@q7kLNmn5^H>da;GEdh6)n)hA9DRMW_~SSKrj3OKAFn&!CXa`? zqx6MXrTBOot8t7)zVIo==S}Wh#l85_w&0!dVQp5EcL(Fxqu7|3ZqM}0Wt*<;+TNw{ zLWi8~?TieDC;!|5`AnU(`x;`up}CV98Eg(u*N=A^jfIa$XzeyVugS};xEz^k5?V=S zOl!R57NEKd+`O*C{V9J_E;o%9QuFn(xG>NQHZK_ky010vbLK})nW#z@9JKm%_}(cx zWuAHLuu6r7$Ms~i!39q3l4Y)dze7_(U#0e|2?DxMQ=H#=0T8vAm(7 z@I1wlcy$%Nm7JH=Sw?zGocP|W5RAngGcvLJ_goVOcIN#2rl!2cMp2co^mh8&r)oK9 z?J^PQSFvKT*0T#D1AR@DaWPN?MN!$W3=sh-`=!`IOTVVd1>*MZFUfHpjQ%_izw$CUVH}8BZs#JEZkitJuiMadh8{Z!gf&Q@2t& z=yV>=?{O+SqGvo}#jrBcQV@BZEuEC&<@1LJ)tf$|F6H0>Mh}B%@xoJ(Hl$hcKhcP}nJy049*>FGV0-BHh{ zaajmB>t$F!%(Kp!-|ZF^jn0)mr+soK_jd0F7JE{$!cqpiT#fDBi=N$qNf_Z%zRde? zg_IBFZES+Var@KndSVsS%OiB7fV3nyhx_FO@Q!$G&bmM>D7qW>Px0a{cD&%!2{Rgu zTat>%BM-U1f*N@_a?sj5%v*`)+lxCgy=-p+4NHxP93TGihG^8RAn-cvF{jhPLQIgH z>dwZHD(S0Uu8U0@+{4#I#9`L3!pX_8?ZcTBpv88F`D#hzYyGx>x4r#J%zv z-wO3hXhvwOlv(lt6kqyF1C1|78IE|o{BPeksG240uU|VGgmB9Tg6H(F6iPkt+Oxef zjx(Ef!%G8B0z3vFGAVM1#D~Gda@-r<{W7f> zSV#&BY!&#Um3Pmn!g2)9NUr9y@HJH$XNP)3cqrTQa*jCKyk7&pMAJ{5*NB&eBTrk$ zudA|;xLX2akb^-Im0`I&ViV{5keB_Lj`cYsK|X< zbv6zn#oh4WY!k#xqYb{>&(vDcJnR(J(mFE$ke9=G+M?N2n~rBt7M?;nUB}lK40SePIhb&ClLiiUv0(|)9 zur5s!%)Yy~f3cYTT!Nzb4&^V11gu4IXY_jpu+S z7(#C2nC}X<|1(Q4?E&NHX9qZpf86)`6W1jj^xsAmoV))2-LT@AqQBvJsC+_Ic<7&~ zEv%KQR*{ck4j`iVLaj(7p8u7fFdHS_(yBfLDl?ymB427nMV@R~C0{Z;->cHh_{m*G-0eg3jmN>&s>e9D#D43++u8&70W4AO?+AVd=pnNImN(A}(NnFjgdjg09AGMP zph12RAzqP9ig<$qx#QmNGS<)QB1qn7o=@@)FTZ>MsLPZecwJpv7|HC1YqXzmqkJ$i zmnJ7w-;Nv%6|tj51s(9;xsZ{Ozi;5@=!5(`KeuikW*($}x>ZK90)Sj+viVzCCXc5I0x1 zwgzH$P;lWTrKKXV1VNBY#xTiTW<29!Tu2$>>g7K58e(ABlkF{$;jt>4m%a2gebeYS$S@oS!=Obco-Wi z&e)C4Z<$ez;vheiowaRk*-~!sa&vNqZ(3b|K>`M#;ry}9^9iEuMQD(g%$d!3zkkdF z6qG=uJe`5Tn;9zzohC1@wW^jwS!d&L-)`^uj`OGA*fVGGaDF5INdLW|gv80_!0yCI zorTNv48vp#0T&)x=I+4*xYTm6va{_wXCt2}jmFr`}3Rh!0QlZ*KVLl$ae_&941=#dCIX$z|_=@=u;jOIw3i zT}DGoT;@!>Z+9+~!R?*M?pS)3y^k(Yo1G|>(V0Z-F~)g)#ocIR2S<=FRh?~dSrTC2 z=A{xiTXC71Ty(tf*0r*lD4p&3x!EIv<6sYioxVl|znmk(_u8(@N9*lUTU#qE*xSqH zgZ;+EC#a|@;DwU)Gb(YQrzctP6Od}d&i>hCLTh+<*x^rup|P=WxHsfnCQoAGPAg4j zyiPMZ$nUtgXC@|j2?@Bd;H)S$#=^=4Wk?Won>B2tRMAhD11TS~coyv*7txV*p8;f5 zTU%GlQC7^tYWc2CT?5v3PD;*+54}lm7>$iow8>FkgyPES**RqncJQXbB2pSw>An z)H})fv+p`Lu?Ip1!NijlwC#n*dbPE|GkLYut!66V<9pC@!^QSUVr7MOV*bIn;5%tU z@*!{36B>x^XxDK6JcbvvyKuJ2Z6S9qo?U#T)YyX8c|!aaB9cN8t!7J(aqMODZ5c=leLK__Qo6 zcBS-7ENmQ2)+^R_&!eAtKS*`jXN$}ZpPptoRG!faL8Zdi*4C`gwU@CXR4S&~&CdeB zAp!K*ycRP~=A!glLM5+qZz(G+508N(Mzr}ND|uPX28)O6FwkwU!NT(Lw}9NzVe|C4 zlIC{=|Dq$1pO+y?Rx8xVaZJ?ki+8{5gG72QH}nWPGnk%=2j^t7VMI%%yfl5B^lBeT9b`-(^Bsd} zSe2utd3NC#4Y@TcQbK-al9Gldzckg66t2Y41?m2LsiLekEj(O8%&s^tP7u&kAX#On z2I}fTcXHuwH^vgusmJ!y^{voyP&xu5+W&ZDa24T30bfkg&LNuCl1e8xgsnAX`LB`jTO<4iGr#u#@|n$MFXZ1A~L8;52Np+0+CQGRo#}+$FMny*-EhQFQJUtg$07x2L|-(^EHOuZr?=1YkX=$Qch)=;pRU@;PhZ1KZ}Z7wKJytR6#E+8vOlw?(XIkr`l{>RhB#pMm8)jWu|bsb$5ZaU}0iDXeMM7OJ2A8hdv>WV49083Uv{Zf0_AD%pj)-uSlM9_-MgWQ_YhAwjpx@rH zgoK8Mh0DlkS6RM3R+-x4eT6bagOTd=JG3gP;m#0|e?>-&Xdd^=FFK&$ zkp1kB@m&}UTIB#K(TpU3fNjLt;!0Mj>b%^S5gfd-+Fg*Fn_E*8p6W3RBrWajHI@sf zCQ_+|IKu&JM6@Q*Q@NPz`ue)D(e-O+uZXYAM%xH*U=uMq4eSykQTsghi=MM&(pW38 zgBo8^1PSdvyi=c_AtXk)kIgASqxj#Ous}eHN=qw?i*X`=I3qfYgMznr`_s+AUjuV_ z6RiN+c{nq zndu}EdTx1f3V`JOE5{4F`WMZcAF*a#y}d*{N=zMD=(70uojz+TI9p;m9rLTrZg%Uf zOX#r1$*pBE)y~Sw6+zD>M%UHAjv!%Zl$Tck3Q`aT6qKTtX}5hUuZH9|`12MHBa;!b z50-)o0HF);6P87tZ?uYGf&4Mu@+`j-2CAxthe!GfLVEj&0Zohq70{c9JcAPi0>V5O zpOR9duOK*huC1(m5PP1Uo^D$1HMzKmjDlj~HOp_q*tD<4m=7Bcjlfy$AA z-+@U{samhD1Z4E~38yzAb)@Z1)ThCLGUt2UJq_m|I=e$OJ z%FJMMMh`uV{ML)hb8NaWne_Yj>yw1k?%BwvPp`N)`R>I=hUEhhS+^_5re1%<~x8 zg%zMfAc1p2@$z2-b}Az@+N>2aPEJns5cs5|B;|7X>n1xHNlC-IV-#4&SmWs|NxAlKFcyQ12K%=wg!VE5?@Qh&A?J_}7%Ztl#H+C z;OMC5+5sL@EIh=t!YALyJ&Cb%t^R8Xv=LgZvOk_*P$}uWUl-SrQZhe~jE(oHHCV2% zt_KH2zegiUOT(86cz}Y0B*I%k>Z5mdT3RtL1$XI^CF)-9hGr8y04+_E#$GGym^tWQ z^LPLo84b0gp|c+x1yLUiop1;s-bb=aRLgjGPk-aNf^zs%y}4x_X9#LZCRgh%L6f# zD7YCzP>3`Ni!@G0wydmGQ^{#>hcsIxDycBvgoU-CsDgm9BOpMPpWj|oR8UF^2OfYc zMFe2JC)HoF8XJ*8{wP)y?l0BkySfVJdgN@t=zqrkm7cx4>DT?RJ0|=j6a;}4-4vCa zjGKnN}cSx(kmVWH^4)J zkJ!@E^5p7f{g@`=;NGb_Ii5za#Mo&p_W5)0M-t1>@G!o$5HOuWFb5y0kM>!@7_oAg zbdypkV*V9r+%89FD^wd;2ThH_pdgJ+!cNZ4Kr%)NWNmqQdU!YtNN3;J-2BOfd7-7} zenDK0xZak>mr(LqVtQ>nfdHz`k^fdqVtqpTs!$;z;>bv;{QSM{?%2su8{M)PM|v=728#sb>PCy- z`#*q%B#7hsG+3_+eijA7tAmF7!RY0GZ<@E98_j}LS6i#Bs63JN$Oa06UXY<8GmN`} zrW_n4gMt*FkU>mBa&4mzox(^4Tg_J2Hx6H|WNcs{-~htOsR0R~B^Q*OI_()-YwKxh zPV-}!@$pf)rQcoEM9bO1pos(jf;d_+sjc9tTUwETkUlwM0ov%Jcm5P^@b?Mjj&5bqlG7)~~!uopGP?vOh?D5w?hHay( z?avm>gPflSB9T%6IAEW!e%;CH>ibb@#|A`r`Bc+cNV^tzZ3T!=U~75FOwS|bE8f8N zu{xgq1Dg&6L~lz>kZ_5T{nz#*QM4!kJN4}wiHBQYASnup_YT}(m<(o4XJ6mk^79!8 zj$s`L3K3%HzCJ$pXAsSnV^jcX7Q0ucD)EtD$u$)fw-AIGJUZnR!Yv%mI|wjW=25E8t8ZI?bt+A| zMvp$4*2FkfYXjv0P_^(7cYZ)r>-HV=b29~_I?8xqd0ye76%!?YHa^(>PEwLx^(DA8 zCMFI9L^6d*?>sHJsw&j(O3Y)dK04XL#6-~W6qhmfY^5F_x7cKB;z%*9f=fW!lFz)N z;yr?@y-SyFra&s4&8~H?E29WFLE>fzmr6wTNsKlyT)Zj4L4LKo-W6kjc@Eh94Nplv zOshc>-b>iwUEZhv1Q=C2+W=Tj3s`nddAU^xdjR@X5+OxdMS6n^A6 z-2?>R=H@b^;~T50!~n5j{^iS&S@6UQ>;Cq9mLqf%DoA)IO99wq#>U2mXXN(Qga+Ja zK&<)jaCTO4Zd$&y(q?k4^*b36b~fkim-4#0$V3+)kQ>WwOmg*Q2oip|%_EUIxL+0j z-C=fqKGUJCtUMnV6ZP&|NqGV>80UBmwg)^`T=+O3Ty3UMXJ;vd0XfGb9+LV=H)HI>`6(dwom zFP{(>H_RqYN<_rwGCm4?Q-`QycyJJKPzAk$wQJPbnW&!E-#P&w5RdnZf?D|v7YX2l zRa5}gh>kn^Z8_VBfH5w^)?D8(lVL2mv`)XU7iR*j0AgYz_Q!vGMy#FI6 zA;av#R$bfs>ha28$U)j1vl>oLRMZwQ?=rC-wA(#nljBdej@n$OJPoh%>k}|hM=m_4 z+iGj6cFhbIYYw?vq$Z!;vzmq7GHy@3_UBv1%9!e4i?N!Ll9T&-1^Ih&0B?nX!M?(E zL%*yLkH=F{cDmJd=wKu}-)AR)zG&5r?b#h=$dHVS|G`K@jX-9%-wwRo*0thGdRXtXxm!k2-7aIL0U zo@v3W;SB6t#l&nU(xeF!UL(&JIga1O#KdqRA_1WH&h?P#X>0Q*=rB;1rKP2SjQ%K( zEKna7MjH4&FTMX_1p@Nyeu9;n^4sK=#bRM@Zms#QbMA}**yls5G7?DKSf_*TFo9Ys z?{~gLnvKo<{bd{LW=ZY(kB#%Kb4!Z@`^o9-ni_}h0J{ua(kfMNs)UW6wV|;!37-)f z#L!wn<^8-^X7x|{y`RA7ZW$-(*(bB|F%*;D#r$VTKsxuO)a~rV))%aAuCFaO>V+KE zFt2$ce3=8)#XeBYgkOF%i#6b1e}VN38`wcYQb3#%`pnPoH<9}Z6a*6Cw4&^}cHtF3 zZ%E;mIDV|^F@^GutI4e!F_Sri>&M2%R!=FxVkyfnP74g&o95c^aDKXy*gAH`Xe08;`Hr`@yF1WN^1R;K+1*|3k!WYA2+*({ z(5ATnJGAB07f5xI32AdjWg07+VUz0hZ4HXa!krON+B%y?qA{ zh;b=8UPBYR89KcE!1-&c%xjOXV*jM2y$(cK-xVWo%YYOdS$uKlh9#pMjERxUi>0T# zoi_jO&`ihbadKUSzakl?JSyJ zUF{woX2|P!qmBE>gnrE!W}fAH0b8D(oE+?7Y<79$ojG)Ix(Uv2ZwHOKKt)6pL~74& z#b$LrMQ`>2f;?uMJCjnWwZC0|9k|)>c94pNX3tWq0XPI)T)8h7OqilFC&$NbZf>UY z>vtKGK%*rjD0$sI5oXIa6l#iotL1I$`iMHLrT7}(Wf(DPX`P+nybbioPR#}4nfiBC zvO)skJ}IfOw}x%FSx_L?3IFS6eQUP$$P13*X64JcDXJwL5g2tYuHn^sw>YS~NWzFV zE1)M#M5Q#^J->`eZ2k5Q23x95-*JK959mA3*0-vByy1iKbatC{?3DCC*?0RYI@WY%2aY!`sF3JSqQW0w z49zpMAuL~@k%3G#06w~GL0RMiAOHDh*OyD#tO#^H%peZ@e|vaC{dXR}{GZ1-&mW|@ zm#*JkTc<=h)(;ynCuEzl>?6_l{8BzMTY#I+e=N56tkq_-{mNxyU@PY%&X1oazxa^F z;Z(HxN>Kl}6QUt^L=#OYd0C!*>*)i-B9Rc~Sb$%VxP6S5`;@mhujI+#(X%qE#6zCZ zfs)wR>!hYRET2#G<0vcYj)G z3a`X8w-HrX?SLzW#pUMJ?CLtWybq1{EZeo$qJ(pgJn1u#)#mA)(>?Iey0e$8N`sBs zw8!@|cP#$8J6a#mGIB~GwaW0)x9Ypfiz^4#6)Tpz9div8sT!=noo!ZQXU%(;r^ZH_ z!o5?4t1W|9Vc>=fC;!@PiNBf+Oad?yb*+?MhXQ!C_n`lZP5*Bo_5b-d&lB{|!EG&O zp%lLn}1E*^E z=g}4vj5jel+OJezy;dpNP7x6)74Q`mtpiAFsVFP!jr9SLbeMUJVDtuPaM$}{Zlp=G;^4GN-;M|O+}^v&g+^B@!3x`FpCyO{sViAt?DMZ^)9!vV zELU+M3`9t{Pl8DP;Cw%R;XeME6}&z{imbhq5bx{mR>%fQv=rfs&0K%{==_00_d{Pp z>-4RHKEoHxE;;S>{9|L}#OwUUP4~jVL+ky%ed4D5&FL~Fddd;rLuH%PUzAa^0s!a# z8vD@XaPY-%aDukeO;J^~dvAGDxv)P1Bi7?y(R2|2NZ9m1sJE0Z!g>F3k4(ydOab*D z7;%41DBYN`T_KVxgF>+2bfLL{+9={)|i&=N#3kB`(f#vH0@%Pt~H!B6AG#gGX! zcRPRFKKZWng$ua~CNePmf&sTi-Pb%2l89?q@F*#6Vke`E=-F>-X?uBl5c!x_g_9zT z*5qENZ`g$;9HT>r1;Bq%BK8l^RR4_OaeZBDR-3o`e7iN4+VJREVXyyizSdw^^^iJK zwz9meTmd^eIyyY|wlrab!f!eUNiYnyH>X_blBl7vPh+Q^>vt0`-O(u@glCY^3IKnteM22Ap2PujLQySkCxN;O0D&B$I zZ0lj61!>%a-H);r0Yee=p7wwJS-#?SzErFsuYQ#+!^-Ma;zOp zEQkYX*35}Bzp2(6iG)UmKEJ4~GZX&UakV zdWw8>=vm;1>-SU;CpMt4J|3 zUqBF$wt*TDL~)Kk<8&w|cOpdi&A+R2XYvtk0FUbyCDlrrFxq&mx}hq=?PwZBpht{t zgPdfBjob_}nX7wAZFB!P+4+!@WEQgUsjwiAM0ldk_iIdTWI444y@l?k@!u|0Uoc@ z10xd{Ztld*Z=y7bHcObiZq-+dRn1V@IzDaB5<^C5r;27rcjO9^pZz{V5x@`R6z_;1 zEEETqm9d3pS_(l?+oLwNxZ!fyCiPSuqWf;MmaEW^7Lio~5hu0x_344Wn(Fb@4j%zlf8k)fLC8hG4Jk-bBMbn*-a-Y#w9tn1lQ;9a zNk~Q+m)J$78IMn}0Pw^;`zFcxFS!b11!V5{OlMMze)vFTH}9w19Si_T(BmObQDwu* z%#1JOw|G9=5;4s}kfbtKi@zkv%Az_?X0>jBv_K| z%O4UNsr|;OXsD&4X#2Lu6&*bWTIRLJ`Y@5-2nh#{Og-@a%35f8(M3KirCl3tjZ zQK*PfZ|#lj)8B6G*0+l-4G&hN*t=<>#Xw&zF6&OFq1MZ@=m}HPfi1-;5N8sz=$2abs7?z>I=;acb!M$Re2~1}caQ`ka8*y6tuTZz1 zVnE`>6rsqfe4-)+r`>De@83%Apx#i~U>kWjoX&`(nOPALNRs=zxdZJ&P|QqBB&0sR zj8TWzdo;~$_D?0DUleYtFq^AeU+wLNWH-@qH|}lKpWA@LBd|A=5!~8ZOUp86VlQbD z1uE*LMirgslZlQv7&5g2655Vec}2w}!Z2AcF9DY_5vX+9Mp+FF7mkzOQXDkFO3kJ) zMlHnfR4S^1l||LMhK7M&ORh^Pbyruqk+`L{n@W|6wkrsjhW8-J4Z5Lm)Sw^;GXNnr z;QetYs-7iuITW@9y8G`02mfF_D8^%@yJLzh5Gp(Y61)|al`~RbZqC;{Z1;!s>258| z&$U}s9p9cKiw2#*`8G$t4^QxB)-pcrM`{2H9tN6*jVh`1Nfqv{xyo*}zFff9;L&sC z_!x5!2^QHZ;PlL`!6vbWegC_N`Hptm$R;ruMZEj2XwWrgVdoTpO7^It>h9hhz!Pk(IM>!XYg5r-6omQ$ z4&%d>+(c{CQB4N;v@VXCSuCohu8xDIFPN5EcOL6adDed3WZcv*t~cT(2B zQ?r6}lZj>f^i_5^pRo=E($G&~rE^qd$A}WmZIt{93n^K<8nD^37wA#(Y*lG&cKxGD zLfd-zNvtirTYDY1ux6Z%y{WJO_ZHz2;C(#zu${N8tS+lG>*xP9(ooQCj%NNE7`5B>tCRuMa7mb zc6T!}-US>T8*@9e8xRUO4!NyO*~}KsaZuu2RyDc3T2;`|C07$J^(K%ov{Ar)e}GZR zhZkYv`Txk$%UxSxt&IEtZ^-b4^84H22G&b&T?F^q>S|7Y{$1~gx4s=xy0pr<;d6@t zCWaN2>~)`i=1QJf?So!J~2 z-cg*&TK>HEBiP)`O*CJA?s)M=5Teu%|EnokI73zk9QY?VB>=I@ZYRV3<2s4n(Q`4; zJrEae;9VyfNU8zV+{n*%f@*M2{55Xs`M8_I6?o`~ciijDC^LdPOwRJ%P=OaU~%CdMy1zbd5a@(tVN2M9-#d~qJHHlFrHte7u zk_(Y2INseBs;O>+j5_m<-)AX)UGD_9(e-1c>%vOfgp<64AaMnoVe|$=D#Hk5&i!MI zJRi}WBKJ2yIlVEmzx~p`-WXZ;|JAehL-*F_bg>HrczmMwIlT8^Zsbkt2sjj;Hg!uz 0 { + time.Sleep(at) + tt.Frame() + } + return encode(t, tt.Image()) + } + if !bytes.Equal(frame(true, 0), frame(true, 300*time.Millisecond)) { + t.Fatal("reduced motion still moves") + } + tt := chatTester(200, 60, func(c *ui.Context) { ThinkingIndicator(c, ThinkingIndicatorOptions{}) }) + tt.SetPreferences(ui.Preferences{ReduceMotion: true, TextScale: 1}) + if !tt.HasText("Thinking…") { + t.Fatalf("static label missing: %q", tt.Texts()) + } +} + +func TestThinkingIndicatorSnapshot(t *testing.T) { + snapshot(t, "thinking_indicator", 360, 70, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + ThinkingIndicator(c, ThinkingIndicatorOptions{Phase: "Searching the archives"}) + }) + }) +} diff --git a/welcome_screen_test.go b/welcome_screen_test.go new file mode 100644 index 0000000..febf2ae --- /dev/null +++ b/welcome_screen_test.go @@ -0,0 +1,66 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestWelcomeScreenGreetsAndChooses(t *testing.T) { + input, got := "", "" + tt := chatTester(900, 600, func(c *ui.Context) { + v := WelcomeScreen(c, WelcomeScreenOptions{Greeting: "Good evening", Subtitle: "How may I serve?", Cards: chatCards(), + Prompts: func() { SuggestionChips(c, &input, []string{"Plan a ball"}, SuggestionChipsOptions{}) }}) + if v.Example != "" { + got = v.Example + } + }) + for _, s := range []string{"Good evening", "How may I serve?", "Research"} { + if !tt.HasText(s) { + t.Fatalf("%q missing from %q", s, tt.Texts()) + } + } + _ = tt.Click("“Explain the minuet”") + if got != "Explain the minuet" { + t.Fatalf("example %q", got) + } + _ = tt.Click("Plan a ball") + if input != "Plan a ball" { + t.Fatalf("slot prompt left %q", input) + } +} + +func TestWelcomeScreenDisabled(t *testing.T) { + got := "" + tt := chatTester(900, 600, func(c *ui.Context) { + if v := WelcomeScreen(c, WelcomeScreenOptions{Greeting: "Hello", Cards: chatCards(), Disabled: true}); v.Example != "" { + got = v.Example + } + }) + _ = tt.Click("“Explain the minuet”") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if got != "" { + t.Fatalf("disabled screen chose %q", got) + } +} + +func TestWelcomeScreenNeedsGreeting(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + WelcomeScreen(c, WelcomeScreenOptions{}) + }, 100, 100, 1) +} + +func TestWelcomeScreenSnapshot(t *testing.T) { + snapshot(t, "welcome_screen", 900, 420, func(c *ui.Context) { + in := "" + WelcomeScreen(c, WelcomeScreenOptions{Greeting: "Good afternoon", Subtitle: "How may I serve the court?", Cards: chatCards(), + Prompts: func() { SuggestionChips(c, &in, []string{"Plan a ball", "Write a sonnet"}, SuggestionChipsOptions{}) }}) + }) +} From 9677fad17c39c2ed27a2be51ac92ac1c0ac813b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 5 Oct 2026 14:25:10 -0400 Subject: [PATCH 04/13] Chat Messages: components 201-220 --- audio_message.go | 112 +++++++ audio_message_test.go | 92 ++++++ branch_navigator.go | 52 +++ branch_navigator_test.go | 64 ++++ chat_container.go | 48 +++ chat_container_test.go | 64 ++++ code_block.go | 158 +++++++++ code_block_test.go | 79 +++++ docs/components/201-chat-container.md | 43 +++ docs/components/202-message-list.md | 42 +++ docs/components/203-message-bubble.md | 41 +++ docs/components/204-message-header.md | 37 +++ docs/components/205-streaming-text.md | 38 +++ docs/components/206-markdown-view.md | 39 +++ docs/components/207-code-block.md | 39 +++ docs/components/208-table-block.md | 39 +++ docs/components/209-image-grid.md | 40 +++ docs/components/210-file-message.md | 40 +++ docs/components/211-audio-message.md | 41 +++ docs/components/212-link-preview-card.md | 42 +++ docs/components/213-quote-reply.md | 38 +++ docs/components/214-message-actions.md | 38 +++ docs/components/215-message-editor.md | 38 +++ docs/components/216-branch-navigator.md | 38 +++ docs/components/217-error-message.md | 40 +++ docs/components/218-thinking-block.md | 40 +++ .../components/219-scroll-to-bottom-button.md | 40 +++ docs/components/220-typing-indicator.md | 35 ++ error_message.go | 72 +++++ error_message_test.go | 69 ++++ example_chatmsg_test.go | 222 +++++++++++++ examples/gallery/pages_chatmsg.go | 260 ++++++++++++++- examples/gallery/pages_chatmsg_actions.go | 292 +++++++++++++++++ examples/gallery/pages_chatmsg_blocks.go | 198 ++++++++++++ examples/gallery/pages_chatmsg_test.go | 72 +++++ file_message.go | 123 +++++++ file_message_test.go | 82 +++++ icons/svg/brain.svg | 21 ++ icons/svg/download.svg | 16 + icons/svg/file-archive.svg | 19 ++ icons/svg/file-code.svg | 17 + icons/svg/pause.svg | 15 + icons/svg/pencil.svg | 15 + icons/svg/play.svg | 14 + icons/svg/share-2.svg | 18 ++ icons/svg/thumbs-down.svg | 15 + icons/svg/thumbs-up.svg | 15 + icons/svg/volume-2.svg | 16 + icons/svg/wrap-text.svg | 17 + image_grid.go | 103 ++++++ image_grid_test.go | 95 ++++++ internal/markdown.go | 305 ++++++++++++++++++ internal/markdown_inline.go | 128 ++++++++ internal/markdown_test.go | 108 +++++++ link_preview_card.go | 49 +++ link_preview_card_test.go | 62 ++++ markdown_view.go | 126 ++++++++ markdown_view_test.go | 64 ++++ message_actions.go | 111 +++++++ message_actions_test.go | 93 ++++++ message_bubble.go | 115 +++++++ message_bubble_test.go | 60 ++++ message_editor.go | 57 ++++ message_editor_test.go | 62 ++++ message_header.go | 70 ++++ message_header_test.go | 55 ++++ message_list.go | 108 +++++++ message_list_test.go | 127 ++++++++ messages_chatmsg.go | 57 ++++ quote_reply.go | 33 ++ quote_reply_test.go | 53 +++ scroll_to_bottom_button.go | 47 +++ scroll_to_bottom_button_test.go | 51 +++ streaming_text.go | 77 +++++ streaming_text_test.go | 80 +++++ table_block.go | 125 +++++++ table_block_test.go | 58 ++++ .../snapshots/darwin/audio_message-dark.png | Bin 0 -> 2809 bytes .../snapshots/darwin/audio_message-light.png | Bin 0 -> 2802 bytes .../darwin/branch_navigator-dark.png | Bin 0 -> 1179 bytes .../darwin/branch_navigator-light.png | Bin 0 -> 1124 bytes .../snapshots/darwin/chat_container-dark.png | Bin 0 -> 11397 bytes .../snapshots/darwin/chat_container-light.png | Bin 0 -> 10862 bytes testdata/snapshots/darwin/code_block-dark.png | Bin 0 -> 11803 bytes .../snapshots/darwin/code_block-light.png | Bin 0 -> 11234 bytes .../snapshots/darwin/error_message-dark.png | Bin 0 -> 13200 bytes .../snapshots/darwin/error_message-light.png | Bin 0 -> 12731 bytes .../snapshots/darwin/file_message-dark.png | Bin 0 -> 8517 bytes .../snapshots/darwin/file_message-light.png | Bin 0 -> 8395 bytes testdata/snapshots/darwin/image_grid-dark.png | Bin 0 -> 3862 bytes .../snapshots/darwin/image_grid-light.png | Bin 0 -> 3925 bytes .../darwin/link_preview_card-dark.png | Bin 0 -> 10676 bytes .../darwin/link_preview_card-light.png | Bin 0 -> 10454 bytes .../snapshots/darwin/markdown_view-dark.png | Bin 0 -> 29310 bytes .../snapshots/darwin/markdown_view-light.png | Bin 0 -> 28190 bytes .../snapshots/darwin/message_actions-dark.png | Bin 0 -> 2824 bytes .../darwin/message_actions-light.png | Bin 0 -> 2783 bytes .../snapshots/darwin/message_bubble-dark.png | Bin 0 -> 17251 bytes .../snapshots/darwin/message_bubble-light.png | Bin 0 -> 16414 bytes .../snapshots/darwin/message_editor-dark.png | Bin 0 -> 8615 bytes .../snapshots/darwin/message_editor-light.png | Bin 0 -> 8260 bytes .../snapshots/darwin/message_header-dark.png | Bin 0 -> 7421 bytes .../snapshots/darwin/message_header-light.png | Bin 0 -> 7437 bytes .../snapshots/darwin/message_list-dark.png | Bin 0 -> 12244 bytes .../snapshots/darwin/message_list-light.png | Bin 0 -> 11756 bytes .../snapshots/darwin/quote_reply-dark.png | Bin 0 -> 5002 bytes .../snapshots/darwin/quote_reply-light.png | Bin 0 -> 4881 bytes .../darwin/scroll_to_bottom_button-dark.png | Bin 0 -> 2053 bytes .../darwin/scroll_to_bottom_button-light.png | Bin 0 -> 2677 bytes .../snapshots/darwin/streaming_text-dark.png | Bin 0 -> 4383 bytes .../snapshots/darwin/streaming_text-light.png | Bin 0 -> 4207 bytes .../snapshots/darwin/table_block-dark.png | Bin 0 -> 11282 bytes .../snapshots/darwin/table_block-light.png | Bin 0 -> 10722 bytes .../snapshots/darwin/thinking_block-dark.png | Bin 0 -> 9981 bytes .../snapshots/darwin/thinking_block-light.png | Bin 0 -> 9494 bytes .../darwin/typing_indicator-dark.png | Bin 0 -> 2445 bytes .../darwin/typing_indicator-light.png | Bin 0 -> 2381 bytes thinking_block.go | 50 +++ thinking_block_test.go | 71 ++++ typing_indicator.go | 44 +++ typing_indicator_test.go | 49 +++ 121 files changed, 5737 insertions(+), 1 deletion(-) create mode 100644 audio_message.go create mode 100644 audio_message_test.go create mode 100644 branch_navigator.go create mode 100644 branch_navigator_test.go create mode 100644 chat_container.go create mode 100644 chat_container_test.go create mode 100644 code_block.go create mode 100644 code_block_test.go create mode 100644 docs/components/201-chat-container.md create mode 100644 docs/components/202-message-list.md create mode 100644 docs/components/203-message-bubble.md create mode 100644 docs/components/204-message-header.md create mode 100644 docs/components/205-streaming-text.md create mode 100644 docs/components/206-markdown-view.md create mode 100644 docs/components/207-code-block.md create mode 100644 docs/components/208-table-block.md create mode 100644 docs/components/209-image-grid.md create mode 100644 docs/components/210-file-message.md create mode 100644 docs/components/211-audio-message.md create mode 100644 docs/components/212-link-preview-card.md create mode 100644 docs/components/213-quote-reply.md create mode 100644 docs/components/214-message-actions.md create mode 100644 docs/components/215-message-editor.md create mode 100644 docs/components/216-branch-navigator.md create mode 100644 docs/components/217-error-message.md create mode 100644 docs/components/218-thinking-block.md create mode 100644 docs/components/219-scroll-to-bottom-button.md create mode 100644 docs/components/220-typing-indicator.md create mode 100644 error_message.go create mode 100644 error_message_test.go create mode 100644 example_chatmsg_test.go create mode 100644 examples/gallery/pages_chatmsg_actions.go create mode 100644 examples/gallery/pages_chatmsg_blocks.go create mode 100644 examples/gallery/pages_chatmsg_test.go create mode 100644 file_message.go create mode 100644 file_message_test.go create mode 100644 icons/svg/brain.svg create mode 100644 icons/svg/download.svg create mode 100644 icons/svg/file-archive.svg create mode 100644 icons/svg/file-code.svg create mode 100644 icons/svg/pause.svg create mode 100644 icons/svg/pencil.svg create mode 100644 icons/svg/play.svg create mode 100644 icons/svg/share-2.svg create mode 100644 icons/svg/thumbs-down.svg create mode 100644 icons/svg/thumbs-up.svg create mode 100644 icons/svg/volume-2.svg create mode 100644 icons/svg/wrap-text.svg create mode 100644 image_grid.go create mode 100644 image_grid_test.go create mode 100644 internal/markdown.go create mode 100644 internal/markdown_inline.go create mode 100644 internal/markdown_test.go create mode 100644 link_preview_card.go create mode 100644 link_preview_card_test.go create mode 100644 markdown_view.go create mode 100644 markdown_view_test.go create mode 100644 message_actions.go create mode 100644 message_actions_test.go create mode 100644 message_bubble.go create mode 100644 message_bubble_test.go create mode 100644 message_editor.go create mode 100644 message_editor_test.go create mode 100644 message_header.go create mode 100644 message_header_test.go create mode 100644 message_list.go create mode 100644 message_list_test.go create mode 100644 messages_chatmsg.go create mode 100644 quote_reply.go create mode 100644 quote_reply_test.go create mode 100644 scroll_to_bottom_button.go create mode 100644 scroll_to_bottom_button_test.go create mode 100644 streaming_text.go create mode 100644 streaming_text_test.go create mode 100644 table_block.go create mode 100644 table_block_test.go create mode 100644 testdata/snapshots/darwin/audio_message-dark.png create mode 100644 testdata/snapshots/darwin/audio_message-light.png create mode 100644 testdata/snapshots/darwin/branch_navigator-dark.png create mode 100644 testdata/snapshots/darwin/branch_navigator-light.png create mode 100644 testdata/snapshots/darwin/chat_container-dark.png create mode 100644 testdata/snapshots/darwin/chat_container-light.png create mode 100644 testdata/snapshots/darwin/code_block-dark.png create mode 100644 testdata/snapshots/darwin/code_block-light.png create mode 100644 testdata/snapshots/darwin/error_message-dark.png create mode 100644 testdata/snapshots/darwin/error_message-light.png create mode 100644 testdata/snapshots/darwin/file_message-dark.png create mode 100644 testdata/snapshots/darwin/file_message-light.png create mode 100644 testdata/snapshots/darwin/image_grid-dark.png create mode 100644 testdata/snapshots/darwin/image_grid-light.png create mode 100644 testdata/snapshots/darwin/link_preview_card-dark.png create mode 100644 testdata/snapshots/darwin/link_preview_card-light.png create mode 100644 testdata/snapshots/darwin/markdown_view-dark.png create mode 100644 testdata/snapshots/darwin/markdown_view-light.png create mode 100644 testdata/snapshots/darwin/message_actions-dark.png create mode 100644 testdata/snapshots/darwin/message_actions-light.png create mode 100644 testdata/snapshots/darwin/message_bubble-dark.png create mode 100644 testdata/snapshots/darwin/message_bubble-light.png create mode 100644 testdata/snapshots/darwin/message_editor-dark.png create mode 100644 testdata/snapshots/darwin/message_editor-light.png create mode 100644 testdata/snapshots/darwin/message_header-dark.png create mode 100644 testdata/snapshots/darwin/message_header-light.png create mode 100644 testdata/snapshots/darwin/message_list-dark.png create mode 100644 testdata/snapshots/darwin/message_list-light.png create mode 100644 testdata/snapshots/darwin/quote_reply-dark.png create mode 100644 testdata/snapshots/darwin/quote_reply-light.png create mode 100644 testdata/snapshots/darwin/scroll_to_bottom_button-dark.png create mode 100644 testdata/snapshots/darwin/scroll_to_bottom_button-light.png create mode 100644 testdata/snapshots/darwin/streaming_text-dark.png create mode 100644 testdata/snapshots/darwin/streaming_text-light.png create mode 100644 testdata/snapshots/darwin/table_block-dark.png create mode 100644 testdata/snapshots/darwin/table_block-light.png create mode 100644 testdata/snapshots/darwin/thinking_block-dark.png create mode 100644 testdata/snapshots/darwin/thinking_block-light.png create mode 100644 testdata/snapshots/darwin/typing_indicator-dark.png create mode 100644 testdata/snapshots/darwin/typing_indicator-light.png create mode 100644 thinking_block.go create mode 100644 thinking_block_test.go create mode 100644 typing_indicator.go create mode 100644 typing_indicator_test.go diff --git a/audio_message.go b/audio_message.go new file mode 100644 index 0000000..a97bb08 --- /dev/null +++ b/audio_message.go @@ -0,0 +1,112 @@ +package mujica + +import ( + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// AudioMessageOptions describe a voice message the caller plays. +type AudioMessageOptions struct { + // Duration is the length; required. + Duration time.Duration + // Position is how far playback has gone, 0 to Duration. + Position time.Duration + Playing bool + // Waveform holds loudness samples from 0 to 1; empty draws a flat line. + Waveform []float32 +} + +// AudioMessageResult is an AudioMessage's element and the user's requests this frame. +type AudioMessageResult struct { + Element *ui.Element + toggled bool + seek time.Duration + seeked bool +} + +// Toggled reports a press of play or pause. +func (r AudioMessageResult) Toggled() bool { return r.toggled } + +// Seek returns the position the user moved to by click, drag or keys. +func (r AudioMessageResult) Seek() (time.Duration, bool) { return r.seek, r.seeked } + +// audioBarWidth and audioBarGap space the waveform's bars. +const audioBarWidth, audioBarGap float32 = 2, 2 + +// AudioMessage shows a voice bar: play button, waveform with progress, and times. +func AudioMessage(c *ui.Context, opts AudioMessageOptions) AudioMessageResult { + if opts.Duration <= 0 || opts.Position < 0 || opts.Position > opts.Duration { + panic("mujica: AudioMessage needs 0 <= Position <= Duration and Duration > 0") + } + for _, v := range opts.Waveform { + if !(v >= 0 && v <= 1) { + panic("mujica: AudioMessage Waveform samples must be from 0 to 1") + } + } + k := Tokens(c) + u := Density(c).Unit() + var r AudioMessageResult + r.Element = ui.Row(c).Gap(u*2).AlignItems(ui.Center).Padding(u, u*3, u, u).Width(300). + Radius(theme.CardRadius).Background(k.Surface).Border(theme.BorderWidth, k.Border) + disabled := r.Element.IsDisabled() + r.Element.Children(func() { + icon, name := "play", msg(c, "audio_message.play") + if opts.Playing { + icon, name = "pause", msg(c, "audio_message.pause") + } + if iconAction(c, icons.Must(icon), name).Clicked() && !disabled { + r.toggled = true + slog.Debug("mujica: audio_message toggle", "playing", !opts.Playing) + } + pos := opts.Position.Seconds() + s := ui.SliderBase(c, &pos, 0, opts.Duration.Seconds()).Grow(1).Height(theme.MinHitSize). + Label(msg(c, "audio_message.seek")).Description(audioClock(opts.Position) + " / " + audioClock(opts.Duration)) + internal.Ring(s, k.Focus, theme.ControlRadius) + if s.Changed() && !disabled { + r.seek, r.seeked = time.Duration(pos*float64(time.Second)), true + slog.Debug("mujica: audio_message seek", "at", r.seek) + } + frac := float32(opts.Position.Seconds() / opts.Duration.Seconds()) + s.Draw(func(p *ui.Painter, b ui.Rect) { audioWave(p, b, opts.Waveform, frac, k) }) + ui.Text(c, audioClock(opts.Position)+" / "+audioClock(opts.Duration)).FontFeatures("tnum"). + FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine().Shrink(0) + }) + return r +} + +// audioWave draws bars, played ones in AccentText, with a position line so progress is not color alone. +func audioWave(p *ui.Painter, b ui.Rect, wave []float32, frac float32, k theme.Tokens) { + n := int((b.W + audioBarGap) / (audioBarWidth + audioBarGap)) + if n <= 0 { + return + } + cy := b.Y + b.H/2 + for i := range n { + v := float32(0.12) + if len(wave) > 0 { + v = max(v, wave[i*len(wave)/n]) + } + h := max(2, v*(b.H-8)) + x := b.X + float32(i)*(audioBarWidth+audioBarGap) + col := k.TextMuted.Alpha(0.55) + if (x-b.X)/b.W < frac { + col = k.AccentText + } + p.Fill(ui.Rect{X: x, Y: cy - h/2, W: audioBarWidth, H: h}, col, 1) + } + at := internal.Snap(p, b.X+b.W*frac) + p.Fill(ui.Rect{X: at - 1, Y: b.Y + 2, W: 2, H: b.H - 4}, k.Text, 1) +} + +// audioClock formats d as m:ss. +func audioClock(d time.Duration) string { + s := int(d.Round(time.Second).Seconds()) + return fmt.Sprintf("%d:%02d", s/60, s%60) +} diff --git a/audio_message_test.go b/audio_message_test.go new file mode 100644 index 0000000..682e821 --- /dev/null +++ b/audio_message_test.go @@ -0,0 +1,92 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +var audioMessageWave = []float32{0.2, 0.5, 0.9, 0.4, 0.7, 0.3, 0.8, 0.6, 0.2, 0.5} + +func TestAudioMessagePlaySeekAndKeys(t *testing.T) { + playing, pos := false, 10*time.Second + var seeks []time.Duration + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := AudioMessage(c, AudioMessageOptions{Duration: time.Minute, Position: pos, Playing: playing, Waveform: audioMessageWave}) + if r.Toggled() { + playing = !playing + } + if d, ok := r.Seek(); ok { + pos = d + seeks = append(seeks, d) + } + }, 400, 200) + if !tt.HasText("0:10 / 1:00") { + t.Fatalf("times %q", tt.Texts()) + } + _ = tt.Click("Play") + if !playing { + t.Fatal("play not reported") + } + if _, ok := tt.Find("Pause"); !ok { + t.Fatal("button did not turn to pause") + } + r, _ := tt.Find("Playback position") + tt.ClickAt(r.X+r.W*0.75, r.Y+r.H/2) + if len(seeks) == 0 || pos < 40*time.Second || pos > 50*time.Second { + t.Fatalf("click at 3/4 seeked to %v", pos) + } + tt.Key(0, ui.KeyHome) + if pos != 0 { + t.Fatalf("Home gave %v", pos) + } + tt.Key(0, ui.KeyEnd) + if pos != time.Minute { + t.Fatalf("End gave %v", pos) + } +} + +func TestAudioMessageDisabled(t *testing.T) { + events := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Disabled(true).Children(func() { + r := AudioMessage(c, AudioMessageOptions{Duration: time.Minute}) + if _, ok := r.Seek(); ok || r.Toggled() { + events++ + } + }) + }, 400, 200) + _ = tt.Click("Play") + r, _ := tt.Find("Playback position") + tt.ClickAt(r.X+r.W/2, r.Y+r.H/2) + if events != 0 { + t.Fatalf("disabled audio reported %d events", events) + } +} + +func TestAudioMessageBadOptions(t *testing.T) { + for _, o := range []AudioMessageOptions{{}, {Duration: time.Second, Position: 2 * time.Second}, {Duration: time.Second, Waveform: []float32{2}}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%+v: no panic", o) + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + AudioMessage(c, o) + }, 100, 100) + }() + } +} + +func TestAudioMessageSnapshot(t *testing.T) { + snapshot(t, "audio_message", 340, 80, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + AudioMessage(c, AudioMessageOptions{Duration: 47 * time.Second, Position: 18 * time.Second, Playing: true, Waveform: audioMessageWave}) + }) + }) +} diff --git a/branch_navigator.go b/branch_navigator.go new file mode 100644 index 0000000..b08f1b3 --- /dev/null +++ b/branch_navigator.go @@ -0,0 +1,52 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// BranchNavigator switches among count branches of a message, showing "< 2 / 3 >"; Left and Right step. +func BranchNavigator(c *ui.Context, index *int, count int) ChoiceResult { + if count < 1 || *index < 0 || *index >= count { + panic("mujica: BranchNavigator needs 0 <= index < count") + } + k := Tokens(c) + label := fmt.Sprintf(msg(c, "branch_navigator.label"), *index+1, count) + var r ChoiceResult + r.Element = ui.Row(c).Focusable().AlignItems(ui.Center).Radius(theme.ControlRadius).Role(ui.RoleGroup).Label(label) + internal.Ring(r.Element, k.Focus, theme.ControlRadius) + disabled := r.Element.IsDisabled() + step := func(d int) { + if i := *index + d; i >= 0 && i < count && !disabled { + *index, r.changed = i, true + c.Announce(fmt.Sprintf(msg(c, "branch_navigator.label"), i+1, count)) + slog.Debug("mujica: branch_navigator change", "index", i) + } + } + switch { + case r.Element.Shortcut(0, ui.KeyLeft): + step(-1) + case r.Element.Shortcut(0, ui.KeyRight): + step(1) + case r.Element.Shortcut(0, ui.KeyHome): + step(-*index) + case r.Element.Shortcut(0, ui.KeyEnd): + step(count - 1 - *index) + } + r.Element.Children(func() { + if numberInputButton(c, "chevron-left", msg(c, "branch_navigator.previous"), *index > 0) { + step(-1) + } + ui.Text(c, fmt.Sprintf("%d / %d", *index+1, count)).FontFeatures("tnum").FontSize(FontSize(c, theme.CaptionSize)). + TextColor(k.TextMuted).SingleLine() + if numberInputButton(c, "chevron-right", msg(c, "branch_navigator.next"), *index < count-1) { + step(1) + } + }) + return r +} diff --git a/branch_navigator_test.go b/branch_navigator_test.go new file mode 100644 index 0000000..eee74eb --- /dev/null +++ b/branch_navigator_test.go @@ -0,0 +1,64 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestBranchNavigatorButtonsAndKeys(t *testing.T) { + i, changes, off := 1, 0, false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Disabled(off).Children(func() { + if BranchNavigator(c, &i, 3).Changed() { + changes++ + } + }) + }, 300, 100) + if !tt.HasText("2 / 3") { + t.Fatalf("texts %q", tt.Texts()) + } + _ = tt.Click("Next branch") + _ = tt.Click("Next branch") + if i != 2 || changes != 1 { + t.Fatalf("index %d changes %d at the end", i, changes) + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyLeft) + tt.Key(0, ui.KeyHome) + tt.Key(0, ui.KeyLeft) + if i != 0 || changes != 3 { + t.Fatalf("keys: index %d changes %d", i, changes) + } + tt.Key(0, ui.KeyEnd) + if i != 2 { + t.Fatalf("End gave %d", i) + } + off = true + tt.Key(0, ui.KeyLeft) + _ = tt.Click("Previous branch") + if i != 2 { + t.Fatalf("disabled navigator moved to %d", i) + } +} + +func TestBranchNavigatorBounds(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic for an index past count") + } + }() + i := 3 + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + BranchNavigator(c, &i, 3) + }, 100, 100) +} + +func TestBranchNavigatorSnapshot(t *testing.T) { + i := 1 + snapshot(t, "branch_navigator", 200, 60, func(c *ui.Context) { + ui.Column(c).Padding(12).Children(func() { BranchNavigator(c, &i, 3) }) + }) +} diff --git a/chat_container.go b/chat_container.go new file mode 100644 index 0000000..a3ad762 --- /dev/null +++ b/chat_container.go @@ -0,0 +1,48 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// ChatContainerOptions configure a ChatContainer. +type ChatContainerOptions struct { + // List configures the message area; its ID is required. + List MessageListOptions + // Input builds the input area under the messages. + Input func() + // Sidebar builds a side column, as a session list; nil shows none. + Sidebar func() + // SidebarWidth is the side column's width in DIPs; zero means 260. + SidebarWidth float32 +} + +// ChatContainer lays out a chat: sidebar, messages that follow the newest, and the input. +func ChatContainer(c *ui.Context, s *MessageListState, n int, opts ChatContainerOptions, row func(i int)) MessageListResult { + if opts.SidebarWidth < 0 { + panic("mujica: ChatContainer SidebarWidth must not be negative") + } + w := opts.SidebarWidth + if w == 0 { + w = 260 + } + k := Tokens(c) + u := Density(c).Unit() + var r MessageListResult + shell := ui.Row(c).Fill().AlignItems(ui.Stretch).Background(k.Background) + shell.Children(func() { + if opts.Sidebar != nil { + ui.Column(c).Width(w).Shrink(0).MinHeight(0).Background(k.Surface). + BorderWidth(0, theme.BorderWidth, 0, 0).BorderColor(k.Border).Children(opts.Sidebar) + } + ui.Column(c).Grow(1).MinWidth(0).MinHeight(0).Children(func() { + r = MessageList(c, s, n, opts.List, row) + if opts.Input != nil { + ui.Column(c).Shrink(0).Padding(u*3, u*4).BorderWidth(theme.BorderWidth, 0, 0, 0).BorderColor(k.Border).Children(opts.Input) + } + }) + }) + r.Element = shell + return r +} diff --git a/chat_container_test.go b/chat_container_test.go new file mode 100644 index 0000000..ac9f9ca --- /dev/null +++ b/chat_container_test.go @@ -0,0 +1,64 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +// chatContainerApp is a chat with a sidebar and an input. +type chatContainerApp struct { + msgs []string + state MessageListState + draft string +} + +func (a *chatContainerApp) view(c *ui.Context) { + Use(c, Settings{}) + ChatContainer(c, &a.state, len(a.msgs), ChatContainerOptions{ + List: MessageListOptions{ID: func(i int) string { return a.msgs[i] }}, + Sidebar: func() { ui.Text(c, "Sessions").Padding(12) }, + Input: func() { TextInput(c, &a.draft, TextInputOptions{Label: "Prompt"}) }, + }, func(i int) { + MessageBubble(c, MessageAssistant, MessageBubbleOptions{}, func() { ui.Text(c, a.msgs[i]) }) + }) +} + +func TestChatContainerSlotsAndFollow(t *testing.T) { + a := &chatContainerApp{} + for i := range 40 { + a.msgs = append(a.msgs, "reply "+string(rune('A'+i%26))+string(rune('a'+i/26))) + } + tt := ui.NewTester(a.view, 600, 400) + tt.Frame() + if !tt.HasText("Sessions") || !tt.HasText("reply Nb") { + t.Fatalf("slots or newest message missing: %q", tt.Texts()) + } + _ = tt.Click("Prompt") + tt.Type("hi") + if a.draft != "hi" { + t.Fatalf("input slot draft %q", a.draft) + } + a.msgs = append(a.msgs, "fresh") + tt.Frame() + tt.Frame() + if !tt.HasText("fresh") { + t.Fatal("new message not followed") + } + tt.Scroll(400, 150, 0, -3000) + tt.Frame() + a.msgs = append(a.msgs, "later") + tt.Frame() + if tt.HasText("later") { + t.Fatal("followed after the user scrolled up") + } +} + +func TestChatContainerSnapshot(t *testing.T) { + snapshot(t, "chat_container", 560, 300, func(c *ui.Context) { + a := ui.Local(c.Root(), "app", func() *chatContainerApp { + return &chatContainerApp{msgs: []string{"Bonjour, Madame.", "How may I serve the court today?"}} + }) + (*a).view(c) + }) +} diff --git a/code_block.go b/code_block.go new file mode 100644 index 0000000..3143923 --- /dev/null +++ b/code_block.go @@ -0,0 +1,158 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// CopyResult is a block's element and whether its copy action ran this frame. +type CopyResult struct { + Element *ui.Element + copied bool +} + +// Copied reports that the block wrote its content to the clipboard this frame. +func (r CopyResult) Copied() bool { return r.copied } + +// CodeBlockOptions configure a CodeBlock. +type CodeBlockOptions struct { + // Language picks the highlighting: go, javascript, typescript, python, json, shell, sql. + Language string + LineNumbers bool + // Wrap and Collapsed set the toggles' first state. + Wrap, Collapsed bool +} + +// codeBlockState holds the user's toggles and the copy confirmation. +type codeBlockState struct { + wrap, collapsed bool + copiedAt time.Time +} + +// codeBlockCopiedFor is how long the copy button shows its check. +const codeBlockCopiedFor = 2 * time.Second + +// CodeBlock shows code with a language label, highlighting, copy, collapse and wrap toggles. +func CodeBlock(c *ui.Context, code string, opts CodeBlockOptions) CopyResult { + k := Tokens(c) + u := Density(c).Unit() + var r CopyResult + r.Element = ui.Column(c).Radius(theme.CardRadius).Border(theme.BorderWidth, k.Border).Background(k.Surface).Clip().MinWidth(0) + st := ui.Local(r.Element, "code", func() codeBlockState { return codeBlockState{wrap: opts.Wrap, collapsed: opts.Collapsed} }) + disabled := r.Element.IsDisabled() + lines := strings.Split(strings.TrimSuffix(code, "\n"), "\n") + r.Element.Children(func() { + ui.Row(c).Padding(0, u, 0, u*3).Gap(u).AlignItems(ui.Center).Background(k.SurfaceHover).Children(func() { + lang := opts.Language + if lang == "" { + lang = msg(c, "code_block.plain") + } + ui.Text(c, lang).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine().Grow(1) + if codeBlockToggle(c, "wrap-text", msg(c, "code_block.wrap"), &st.wrap) { + slog.Debug("mujica: code_block wrap", "on", st.wrap) + } + icon, name := "copy", msg(c, "code_block.copy") + if left := codeBlockCopiedFor - c.Now().Sub(st.copiedAt); left > 0 { + icon, name = "check", msg(c, "code_block.copied") + c.After(left) + } + if iconAction(c, icons.Must(icon), name).Clicked() && !disabled { + c.WriteClipboard(code) + st.copiedAt, r.copied = c.Now(), true + c.Announce(msg(c, "code_block.copied")) + slog.Debug("mujica: code_block copy", "lines", len(lines)) + } + fold, foldName := "chevron-up", msg(c, "code_block.collapse") + if st.collapsed { + fold, foldName = "chevron-down", fmt.Sprintf(msg(c, "code_block.expand"), len(lines)) + } + if iconAction(c, icons.Must(fold), foldName).Clicked() && !disabled { + st.collapsed = !st.collapsed + slog.Debug("mujica: code_block collapse", "on", st.collapsed) + } + }) + if st.collapsed { + return + } + var body *ui.Element + if st.wrap { + body = ui.Column(c).Padding(u*2, u*3).MinWidth(0) + } else { + body = ui.ScrollHorizontal(c).Padding(u*2, u*3).AlignItems(ui.Start) + } + body.Font(theme.MonoFont).FontSize(FontSize(c, 13)).Children(func() { + ui.Column(c).MinWidth(0).Grow(1).Children(func() { codeBlockLines(c, lines, opts, st.wrap) }) + }) + }) + return r +} + +// codeBlockLines builds numbered, highlighted lines. +func codeBlockLines(c *ui.Context, lines []string, opts CodeBlockOptions, wrap bool) { + k := Tokens(c) + u := Density(c).Unit() + digits := len(fmt.Sprint(len(lines))) + inBlock := false + for i, line := range lines { + var toks []internal.Token + toks, inBlock = internal.Highlight(opts.Language, line, inBlock) + ui.Row(c).Gap(u * 3).AlignItems(ui.Start).Children(func() { + if opts.LineNumbers { + ui.Text(c, fmt.Sprintf("%*d", digits, i+1)).TextColor(k.TextMuted).Shrink(0).NoWrap() + } + spans := make([]ui.Span, len(toks)) + for j, t := range toks { + spans[j] = ui.Span{Text: t.Text, Color: codeBlockColor(k, t.Kind), Italic: t.Kind == internal.TokComment} + } + if len(spans) == 0 { + spans = []ui.Span{{Text: " "}} + } + t := ui.RichText(c, spans...).MinWidth(0) + if wrap { + t.Grow(1) + } else { + t.NoWrap() + } + }) + } +} + +// codeBlockColor colors a token from the theme; comments are also italic. +func codeBlockColor(k theme.Tokens, kind internal.TokenKind) ui.Color { + switch kind { + case internal.TokKeyword: + return k.AccentText + case internal.TokString: + return k.Success + case internal.TokNumber: + return k.Warning + case internal.TokComment, internal.TokPunct: + return k.TextMuted + case internal.TokType: + return k.Info + } + return k.Text +} + +// codeBlockToggle is a pressed-state icon button; on shows a Selection face and frame. +func codeBlockToggle(c *ui.Context, icon, label string, on *bool) bool { + k := Tokens(c) + b := ui.ToggleBase(c, on).Size(theme.MinHitSize, theme.MinHitSize).Radius(theme.ControlRadius).Label(label).TextColor(k.TextMuted) + internal.Ring(b, k.Focus, theme.ControlRadius) + switch { + case *on: + b.Background(k.Selection).Border(theme.BorderWidth, k.AccentText).TextColor(k.AccentText) + case b.Hovered(): + b.Background(k.SurfaceHover).TextColor(k.Text) + } + b.Children(func() { ui.Icon(c, icons.Must(icon)).Size(16, 16) }) + return b.Changed() +} diff --git a/code_block_test.go b/code_block_test.go new file mode 100644 index 0000000..59d1995 --- /dev/null +++ b/code_block_test.go @@ -0,0 +1,79 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +const codeBlockSample = "// greet the court\nfunc greet(name string) int {\n\treturn len(\"hi \" + name) + 42\n}" + +func codeBlockTester(opts CodeBlockOptions, copies *int, disabled *bool) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Width(360).Disabled(*disabled).Children(func() { + if CodeBlock(c, codeBlockSample, opts).Copied() { + *copies++ + } + }) + }, 400, 300) +} + +func TestCodeBlockLabelNumbersAndCopy(t *testing.T) { + copies, off := 0, false + tt := codeBlockTester(CodeBlockOptions{Language: "go", LineNumbers: true}, &copies, &off) + for _, s := range []string{"go", "1", "4", "func", "greet", "42"} { + if !tt.HasText(s) { + t.Errorf("missing %q in %q", s, tt.Texts()) + } + } + if err := tt.Click("Copy code"); err != nil { + t.Fatal(err) + } + if tt.Clipboard() != codeBlockSample || copies != 1 { + t.Fatalf("copied %d, clipboard matches %v", copies, tt.Clipboard() == codeBlockSample) + } + if _, ok := tt.Find("Copied"); !ok { + t.Fatal("no copied confirmation") + } +} + +func TestCodeBlockCollapseAndWrapByKeyboard(t *testing.T) { + copies, off := 0, false + tt := codeBlockTester(CodeBlockOptions{Language: "go"}, &copies, &off) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeySpace) + if !tt.Focused("Wrap lines") { + t.Fatal("Tab did not reach the wrap toggle") + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if tt.HasText("greet") { + t.Fatal("collapse left the code built") + } + if err := tt.Click("Show 4 lines"); err != nil { + t.Fatal(err) + } + if !tt.HasText("greet") { + t.Fatal("expand did not show the code") + } +} + +func TestCodeBlockDisabledBlocksActions(t *testing.T) { + copies, off := 0, true + tt := codeBlockTester(CodeBlockOptions{Collapsed: true}, &copies, &off) + _ = tt.Click("Copy code") + _ = tt.Click("Show 4 lines") + if copies != 0 || tt.Clipboard() != "" || tt.HasText("greet") { + t.Fatalf("disabled block acted: copies %d", copies) + } +} + +func TestCodeBlockSnapshot(t *testing.T) { + snapshot(t, "code_block", 440, 200, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + CodeBlock(c, codeBlockSample, CodeBlockOptions{Language: "go", LineNumbers: true}) + }) + }) +} diff --git a/docs/components/201-chat-container.md b/docs/components/201-chat-container.md new file mode 100644 index 0000000..2c5b04d --- /dev/null +++ b/docs/components/201-chat-container.md @@ -0,0 +1,43 @@ +# 201 ChatContainer 对话容器 + +## 用途 + +整页对话布局:左侧可选侧栏插槽,右侧为消息区与底部输入区。消息区就是 MessageList:新消息到来时自动滚到底部,用户向上翻看时停止跟随,并在底部显示回到最新按钮。 + +## 最小示例 + +```go +mujica.ChatContainer(c, &chat, len(msgs), mujica.ChatContainerOptions{ + List: mujica.MessageListOptions{ID: func(i int) string { return msgs[i] }}, + Input: func() { ui.Text(c, "Composer goes here") }, +}, func(i int) { ui.Text(c, msgs[i]) }) +``` + +签名:`func ChatContainer(c *ui.Context, s *MessageListState, n int, opts ChatContainerOptions, row func(i int)) MessageListResult` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `s` | `*MessageListState` | 必填 | 消息区的位置与已读状态,由调用方持有。 | +| `n / row` | `int / func(i int)` | 必填 | 消息数量与第 i 条消息的构建函数;只构建可见消息。 | +| `List` | `MessageListOptions` | `ID` 必填 | 传给消息列表的选项,见 202。 | +| `Input` | `func()` | nil | 输入区插槽,位于消息区下方,带上边线。 | +| `Sidebar` | `func()` | nil | 侧栏插槽;nil 时不显示侧栏。 | +| `SidebarWidth` | `float32` | 260 | 侧栏宽度 DIP;负数 panic。 | + +## 状态 + +消息区跟随底部 / 用户上翻后停止跟随;离开底部时出现带未读数的回到最新按钮。 + +## 事件 + +返回的 `MessageListResult.Unread()` 给出离开底部后新到的消息数。 + +## 键盘操作 + +Tab 在侧栏、消息与输入区之间移动;消息区获得焦点后滚轮与 PageUp/PageDown(Linux、Windows)滚动。 + +## 限制 + +- 侧栏宽度固定,不提供拖动调整;需要时用 SplitPane(008)包裹。 diff --git a/docs/components/202-message-list.md b/docs/components/202-message-list.md new file mode 100644 index 0000000..0e2bc60 --- /dev/null +++ b/docs/components/202-message-list.md @@ -0,0 +1,42 @@ +# 202 MessageList 消息列表 + +## 用途 + +虚拟化的消息列表,基于 MyGo `ui.List`:只构建可见消息,以稳定消息 ID 保持位置;从底部开始并跟随新消息,用户上翻后停止跟随,并显示新消息提示;可按日期插入分隔。 + +## 最小示例 + +```go +r := mujica.MessageList(c, &list, len(ids), mujica.MessageListOptions{ + ID: func(i int) string { return ids[i] }, +}, func(i int) { ui.Text(c, "Message "+ids[i]) }) +fmt.Println("unread", r.Unread()) +``` + +签名:`func MessageList(c *ui.Context, s *MessageListState, n int, opts MessageListOptions, row func(i int)) MessageListResult` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `ID` | `func(i int) string` | 必填 | 消息的稳定 ID;在上方插入旧消息时视野中的消息保持不动。ID 须唯一。 | +| `Date` | `func(i int) time.Time` | nil | 设置后在每个新日期的第一条消息前显示“今天 / 昨天 / 日期”分隔。 | +| `Label` | `func(i int) string` | nil | 消息的无障碍名称,也用于键入定位。 | +| `n` | `int` | 必填 | 消息数;负数 panic。 | + +## 状态 + +跟随底部;离开底部时底部居中出现 ScrollToBottomButton(含未读数);点击后回到底部并清零。 + +## 事件 + +`Unread()`:离开底部后新增的消息数。`MessageListState.ScrollToEnd()` 与 `AtEnd()` 供调用方控制。 + +## 键盘操作 + +列表获得焦点后,滚轮、方向键与 PageUp/PageDown 滚动;回到最新按钮可用 Tab 聚焦,Enter 或 Space 触发。 + +## 限制 + +- 不检查 ID 是否重复(逐帧检查 10 万条代价过高);重复 ID 会让两条消息共享状态。 +- 消息高度由 MyGo 在显示时测量,未显示消息按已测高度估算,长距离跳转时滚动条可能微调。 diff --git a/docs/components/203-message-bubble.md b/docs/components/203-message-bubble.md new file mode 100644 index 0000000..96349f0 --- /dev/null +++ b/docs/components/203-message-bubble.md @@ -0,0 +1,41 @@ +# 203 MessageBubble 消息气泡 + +## 用途 + +按角色框住一条消息:用户靠右、Selection 底色;助手靠左、Surface 底与细边;系统居中、灰色小字;错误带 Danger 边框与警示图标。头像与名称为插槽,宽度可限制。 + +## 最小示例 + +```go +mujica.MessageBubble(c, mujica.MessageAssistant, mujica.MessageBubbleOptions{Name: "Herald"}, func() { + ui.Text(c, "The ball begins at nine.") +}) +``` + +签名:`func MessageBubble(c *ui.Context, role MessageRole, opts MessageBubbleOptions, content func()) *ui.Element` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `role` | `MessageRole` | 必填 | `MessageUser`、`MessageAssistant`、`MessageSystem`、`MessageError`。 | +| `Name` | `string` | "" | 显示在气泡上方的名称。 | +| `Avatar` | `func()` | nil | 头像插槽,用户在右侧、其他角色在左侧;系统消息不显示。 | +| `MaxWidth` | `float32` | 560 | 气泡最大宽度 DIP;负数 panic。 | +| `content` | `func()` | 必填 | 气泡内容,如 MarkdownView 或 StreamingText。 | + +## 状态 + +四种角色外观;错误角色同时使用图标、边框与文字,不只依赖颜色。 + +## 事件 + +无;交互由内容与 MessageActions 提供。 + +## 键盘操作 + +气泡本身不获取焦点;内容中的链接、按钮按 Tab 顺序访问。辅助技术读到“角色,名称”分组。 + +## 限制 + +- 气泡不自带操作栏;把 MessageActions 放在 content 中或气泡下方。 diff --git a/docs/components/204-message-header.md b/docs/components/204-message-header.md new file mode 100644 index 0000000..f545f94 --- /dev/null +++ b/docs/components/204-message-header.md @@ -0,0 +1,37 @@ +# 204 MessageHeader 消息头 + +## 用途 + +在消息上方显示模型名、时间与状态(发送中、生成中、已发送、失败),状态同时用图标和文字表达。 + +## 最小示例 + +```go +mujica.MessageHeader(c, mujica.MessageHeaderOptions{Model: "herald-2", Time: time.Now(), Status: mujica.MessageSent}) +``` + +签名:`func MessageHeader(c *ui.Context, opts MessageHeaderOptions) *ui.Element` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Model` | `string` | "" | 模型名,加粗;空则不显示。 | +| `Time` | `time.Time` | 零值 | 时间,按 `15:04` 显示;零值不显示。 | +| `Status` | `MessageStatus` | `MessageNoStatus` | `MessageSending`、`MessageStreaming`、`MessageSent`、`MessageFailed`;未知值 panic。 | + +## 状态 + +生成中显示菱形加载标记(减少动画时静止);失败用 Danger 色并带警示图标。 + +## 事件 + +无。 + +## 键盘操作 + +不获取焦点。 + +## 限制 + +- 时间格式固定为 24 小时制时分,日期由 MessageList 的日期分隔显示。 diff --git a/docs/components/205-streaming-text.md b/docs/components/205-streaming-text.md new file mode 100644 index 0000000..552c2cf --- /dev/null +++ b/docs/components/205-streaming-text.md @@ -0,0 +1,38 @@ +# 205 StreamingText 流式文本 + +## 用途 + +显示随流式输出不断增长的文本。可平滑出字(按速率逐字显示),可显示流式光标;减少动画时直接显示全部文本。文本被替换为不以旧文本开头的内容时,从共同前缀继续。 + +## 最小示例 + +```go +mujica.StreamingText(c, reply, mujica.StreamingTextOptions{Streaming: true, Smooth: true}) +``` + +签名:`func StreamingText(c *ui.Context, text string, opts StreamingTextOptions) *ui.Element` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `text` | `string` | 必填 | 当前收到的全部文本。 | +| `Streaming` | `bool` | false | 在文本末尾显示 AccentText 色的静态光标 ▍。 | +| `Smooth` | `bool` | false | 新到的文本按 Rate 逐字显示;关闭时立即显示。 | +| `Rate` | `float64` | 80 | 平滑出字速度,字符/秒;负数 panic。 | + +## 状态 + +出字中 / 完成;减少动画时始终为完成。光标不闪烁,避免装饰性循环。 + +## 事件 + +无。 + +## 键盘操作 + +不获取焦点。辅助技术读到的名称始终是完整文本。 + +## 限制 + +- 只渲染纯文本;Markdown 内容请交给 MarkdownView(206),它的增量解析同样适合流式输出。 diff --git a/docs/components/206-markdown-view.md b/docs/components/206-markdown-view.md new file mode 100644 index 0000000..e1b35b0 --- /dev/null +++ b/docs/components/206-markdown-view.md @@ -0,0 +1,39 @@ +# 206 MarkdownView Markdown 视图 + +## 用途 + +渲染 Markdown 子集:标题、段落、粗体、斜体、删除线、行内代码、有序与无序列表(含缩进层级)、引用、链接、围栏代码块(交给 CodeBlock)、表格(交给 TableBlock)与分隔线(菱形饰线)。解析器在 `internal/markdown.go`,按块增量解析:新文本只是在旧文本后追加时,只重新解析最后一块,已完成的块保持不变。 + +## 最小示例 + +```go +if url, ok := mujica.MarkdownView(c, "# Decree\n\nSee **the guide** at [the court](https://example.com).").Link(); ok { + fmt.Println("open", url) +} +``` + +签名:`func MarkdownView(c *ui.Context, src string) MarkdownResult` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `src` | `string` | 必填 | Markdown 源文本;流式输出时每帧传入增长后的全文即可。 | + +## 状态 + +围栏未闭合的代码块按已收到的内容显示;未闭合的强调标记按字面显示,闭合后再加样式。 + +## 事件 + +`Link()` 返回本帧被点击或用 Enter 激活的链接地址;打开链接由调用方决定。 + +## 键盘操作 + +链接可用 Tab 聚焦,Enter 激活;代码块与表格的按钮按 Tab 顺序访问。 + +## 限制 + +- 只支持上述子集:不支持 HTML、图片、脚注、任务列表、Setext 标题、链接引用定义,列表项内不支持多段落。 +- 表格单元格按纯文本显示,不解析行内样式。 +- 源文本被整体替换(不是在末尾追加)时重新解析全部块。 diff --git a/docs/components/207-code-block.md b/docs/components/207-code-block.md new file mode 100644 index 0000000..87b6375 --- /dev/null +++ b/docs/components/207-code-block.md @@ -0,0 +1,39 @@ +# 207 CodeBlock 代码块 + +## 用途 + +显示代码:语言标签、可选行号、基础语法着色(`internal.Highlight`,支持 go、javascript、typescript、python、json、shell、sql),复制、折叠与自动换行切换。 + +## 最小示例 + +```go +mujica.CodeBlock(c, "func bow() {}", mujica.CodeBlockOptions{Language: "go", LineNumbers: true}) +``` + +签名:`func CodeBlock(c *ui.Context, code string, opts CodeBlockOptions) CopyResult` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Language` | `string` | ""(显示“文本”) | 着色语言;未知语言按纯文本显示。 | +| `LineNumbers` | `bool` | false | 显示右对齐的行号。 | +| `Wrap` | `bool` | false | 自动换行的初始状态;关闭时横向滚动。 | +| `Collapsed` | `bool` | false | 折叠的初始状态。 | + +## 状态 + +换行开关以 Selection 底色加边框表示开启;复制后按钮在 2 秒内显示对勾“已复制”;折叠时只显示标题栏,展开按钮写明行数。关键字、字符串、数字、类型使用不同颜色,注释同时使用斜体。 + +## 事件 + +`Copied()`:本帧把代码写入了剪贴板。 + +## 键盘操作 + +Tab 依次到换行开关、复制、折叠按钮;Space 或 Enter 触发。 + +## 限制 + +- 着色是逐行的词法着色,不做语法分析;块注释可跨行。 +- 不做虚拟化,适合消息中的代码片段,不适合上万行文件。 diff --git a/docs/components/208-table-block.md b/docs/components/208-table-block.md new file mode 100644 index 0000000..5891e29 --- /dev/null +++ b/docs/components/208-table-block.md @@ -0,0 +1,39 @@ +# 208 TableBlock 表格块 + +## 用途 + +在消息中显示小型表格:表头加粗,列按内容宽度排列并铺满消息宽度,过宽时横向滚动;可复制为 TSV。 + +## 最小示例 + +```go +if mujica.TableBlock(c, []string{"Guest", "Seat"}, [][]string{{"Marie", "1"}}, mujica.TableBlockOptions{}).Copied() { + fmt.Println("copied as TSV") +} +``` + +签名:`func TableBlock(c *ui.Context, header []string, rows [][]string, opts TableBlockOptions) CopyResult` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `header` | `[]string` | 必填 | 表头;为空 panic。 | +| `rows` | `[][]string` | nil | 数据行;每行列数必须与表头相同,否则 panic。 | +| `Align` | `[]ui.Align` | 全部 `ui.Start` | 各列对齐:`ui.Start`、`ui.Center`、`ui.End`;多于列数 panic。 | + +## 状态 + +复制后按钮 2 秒内显示对勾。 + +## 事件 + +`Copied()`:本帧写入了 TSV(制表符分列、换行分行;单元格内的制表符与换行替换为空格)。 + +## 键盘操作 + +Tab 到复制按钮,Enter 或 Space 复制。 + +## 限制 + +- 不排序、不选择;需要这些功能请使用 DataTable(069 起)。 diff --git a/docs/components/209-image-grid.md b/docs/components/209-image-grid.md new file mode 100644 index 0000000..ae3ffa4 --- /dev/null +++ b/docs/components/209-image-grid.md @@ -0,0 +1,40 @@ +# 209 ImageGrid 图片网格 + +## 用途 + +在消息中排列 1 至 9 张图片:1 张大图,2 与 4 张两列,其余三列。点击已加载的图片打开 ImageViewer;加载中与失败状态复用 Image 组件,失败时可重试。 + +## 最小示例 + +```go +if i, ok := mujica.ImageGrid(c, []mujica.GridImage{{Source: pic, Alt: "Portrait"}}).Retried(); ok { + fmt.Println("reload", i) +} +``` + +签名:`func ImageGrid(c *ui.Context, images []GridImage) ImageGridResult` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `images` | `[]GridImage` | 必填 | 1 至 9 张,否则 panic。 | +| `Source` | `ui.ImageSource` | nil | 已加载的位图或 SVG。 | +| `Alt` | `string` | "" | 替代说明,也是按钮名称与查看器标题。 | +| `Loading / Err` | `bool / error` | false / nil | 调用方的加载中与失败状态。 | + +## 状态 + +已加载、加载中(菱形加载标记)、失败(重试按钮);只有已加载的图片可点击。 + +## 事件 + +`Retried()` 返回本帧点击了重试的图片下标。查看器在组件内部打开与关闭。 + +## 键盘操作 + +Tab 聚焦图片,Enter 或 Space 打开查看器;查看器内的键盘操作见 ImageViewer。 + +## 限制 + +- 查看器只包含已加载的图片,序号按已加载图片计算。 diff --git a/docs/components/210-file-message.md b/docs/components/210-file-message.md new file mode 100644 index 0000000..5bfc0f5 --- /dev/null +++ b/docs/components/210-file-message.md @@ -0,0 +1,40 @@ +# 210 FileMessage 文件消息 + +## 用途 + +显示消息中的文件:按类型的图标、文件名、大小,以及打开与下载回调。 + +## 最小示例 + +```go +r := mujica.FileMessage(c, mujica.FileMessageOptions{Name: "treaty.pdf", Size: 2621440}) +if r.Downloaded() { + fmt.Println("save treaty.pdf") +} +``` + +签名:`func FileMessage(c *ui.Context, opts FileMessageOptions) FileMessageResult` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Name` | `string` | 必填 | 文件名;为空 panic。 | +| `Size` | `int64` | 0 | 字节数,按 B、KB、MB、GB 显示(1024 进制);负数 panic。 | +| `Type` | `string` | "" | MIME 类型;为空时按扩展名选择图标。 | + +## 状态 + +悬停时文件区域加深;禁用时两个操作都不响应。 + +## 事件 + +`Opened()`:点击或在文件区按 Enter。`Downloaded()`:点击下载按钮。 + +## 键盘操作 + +Tab 依次到文件区与下载按钮,Enter 或 Space 触发。 + +## 限制 + +- 组件不读取文件、不下载:打开与下载由调用方完成。 diff --git a/docs/components/211-audio-message.md b/docs/components/211-audio-message.md new file mode 100644 index 0000000..f8c8879 --- /dev/null +++ b/docs/components/211-audio-message.md @@ -0,0 +1,41 @@ +# 211 AudioMessage 语音消息 + +## 用途 + +语音条:播放/暂停按钮、波形、播放进度与时长。播放由调用方驱动:组件只报告播放切换与跳转请求,调用方更新 Position 与 Playing。波形基于 MyGo `ui.SliderBase`,可拖动与键盘跳转。 + +## 最小示例 + +```go +r := mujica.AudioMessage(c, mujica.AudioMessageOptions{Duration: time.Minute, Position: pos}) +if d, ok := r.Seek(); ok { + pos = d +} +``` + +签名:`func AudioMessage(c *ui.Context, opts AudioMessageOptions) AudioMessageResult` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Duration` | `time.Duration` | 必填 | 时长,必须大于 0。 | +| `Position` | `time.Duration` | 0 | 当前进度,0 到 Duration 之间,否则 panic。 | +| `Playing` | `bool` | false | 按钮显示暂停(播放中)或播放。 | +| `Waveform` | `[]float32` | nil | 0 到 1 的响度采样,按宽度重采样为竖条;为空画平线;越界 panic。 | + +## 状态 + +已播放的竖条为 AccentText,未播放为半透明 TextMuted,当前位置另有一条竖线,进度不只靠颜色表达;右侧显示 `m:ss / m:ss`。 + +## 事件 + +`Toggled()`:按下播放或暂停。`Seek()`:点击、拖动或按键请求的新位置。 + +## 键盘操作 + +Tab 到播放按钮(Enter 或 Space)与波形;波形上 Left/Right(Up/Down)按时长的 1% 移动,Home、End 到开头与结尾。 + +## 限制 + +- 不解码音频、不生成波形:采样由调用方提供。 diff --git a/docs/components/212-link-preview-card.md b/docs/components/212-link-preview-card.md new file mode 100644 index 0000000..c96bc48 --- /dev/null +++ b/docs/components/212-link-preview-card.md @@ -0,0 +1,42 @@ +# 212 LinkPreviewCard 链接预览卡片 + +## 用途 + +显示链接的站点、标题、描述与缩略图;元数据由调用方获取。整张卡片是一个按钮,悬停显示完整地址。 + +## 最小示例 + +```go +p := mujica.LinkPreview{URL: "https://example.com", Title: "The Palace", Site: "example.com"} +if mujica.LinkPreviewCard(c, p).Clicked() { + fmt.Println("open", p.URL) +} +``` + +签名:`func LinkPreviewCard(c *ui.Context, p LinkPreview) *ui.Element` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `URL` | `string` | 必填 | 链接地址,作为悬停提示。 | +| `Title` | `string` | 必填 | 标题,最多两行,AccentText 色。 | +| `Description` | `string` | "" | 描述,最多两行。 | +| `Site` | `string` | URL | 站点名;为空时显示 URL。 | +| `Thumbnail` | `ui.ImageSource` | nil | 缩略图,64×64 裁切显示。 | + +## 状态 + +悬停时底色加深;聚焦时显示焦点环。 + +## 事件 + +`Clicked()`:点击或 Enter、Space;打开链接由调用方完成。 + +## 键盘操作 + +Tab 聚焦,Enter 或 Space 触发。 + +## 限制 + +- 组件不联网:标题、描述与缩略图都由调用方提供。 diff --git a/docs/components/213-quote-reply.md b/docs/components/213-quote-reply.md new file mode 100644 index 0000000..6f7857b --- /dev/null +++ b/docs/components/213-quote-reply.md @@ -0,0 +1,38 @@ +# 213 QuoteReply 引用回复 + +## 用途 + +显示被引用消息的作者与单行摘要(多余空白折叠,过长省略);点击跳转到原消息。 + +## 最小示例 + +```go +if mujica.QuoteReply(c, "Marie", "Let them eat cake.").Clicked() { + fmt.Println("jump to the quoted message") +} +``` + +签名:`func QuoteReply(c *ui.Context, author, excerpt string) *ui.Element` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `author` | `string` | 必填 | 原消息作者;为空 panic。 | +| `excerpt` | `string` | "" | 原消息摘要;换行与连续空白合并为一个空格。 | + +## 状态 + +左侧 3 DIP AccentText 竖线标明引用;悬停时底色变为 Selection。 + +## 事件 + +`Clicked()`:点击或 Enter、Space;跳转由调用方完成(如 MessageList 的 ScrollTo)。 + +## 键盘操作 + +Tab 聚焦,Enter 或 Space 触发。辅助技术读到“回复 作者:摘要”。 + +## 限制 + +- 只显示一行摘要,不渲染原消息的格式。 diff --git a/docs/components/214-message-actions.md b/docs/components/214-message-actions.md new file mode 100644 index 0000000..6828031 --- /dev/null +++ b/docs/components/214-message-actions.md @@ -0,0 +1,38 @@ +# 214 MessageActions 消息操作 + +## 用途 + +消息下方的操作工具栏:复制、重新生成、编辑、赞、踩、朗读、分享,按角色显示:用户消息为复制、编辑;助手消息为复制、重新生成、赞、踩、朗读、分享;系统消息为复制;错误消息为复制、重新生成。 + +## 最小示例 + +```go +if a, ok := mujica.MessageActions(c, mujica.MessageAssistant, mujica.MessageActionsOptions{Feedback: &rating}).Action(); ok { + fmt.Println("action", a) +} +``` + +签名:`func MessageActions(c *ui.Context, role MessageRole, opts MessageActionsOptions) MessageActionsResult` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `role` | `MessageRole` | 必填 | 决定显示哪些操作。 | +| `Feedback` | `*MessageFeedback` | nil | 赞踩状态;nil 时不显示赞与踩。再次点击已选的赞或踩会取消。 | + +## 状态 + +赞或踩选中时为按下状态:Selection 底色、AccentText 边框与图标;辅助技术读到切换按钮的按下状态。 + +## 事件 + +`Action()` 返回本帧的操作:`ActionCopy`、`ActionRegenerate`、`ActionEdit`、`ActionLike`、`ActionDislike`、`ActionSpeak`、`ActionShare`。复制、朗读与分享由调用方执行。 + +## 键盘操作 + +整个工具栏是一个 Tab 停靠点,Left/Right 在操作间移动,Home、End 到首末;Enter 或 Space 触发。 + +## 限制 + +- 不内置复制内容与朗读:调用方收到操作后自行处理。 diff --git a/docs/components/215-message-editor.md b/docs/components/215-message-editor.md new file mode 100644 index 0000000..5d6b0d1 --- /dev/null +++ b/docs/components/215-message-editor.md @@ -0,0 +1,38 @@ +# 215 MessageEditor 消息编辑器 + +## 用途 + +编辑已发送的消息:多行文本框加取消与保存。保存时调用方据草稿产生新分支(配合 BranchNavigator)。 + +## 最小示例 + +```go +if mujica.MessageEditor(c, &draft, mujica.MessageEditorOptions{Original: "Hello"}).Saved() { + fmt.Println("new branch from", draft) +} +``` + +签名:`func MessageEditor(c *ui.Context, draft *string, opts MessageEditorOptions) MessageEditorResult` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `draft` | `*string` | 必填 | 正在编辑的文本。 | +| `Original` | `string` | "" | 原文;草稿与原文相同或只有空白时不能保存。 | + +## 状态 + +保存按钮在内容无效时禁用;文本框保留输入法、撤销与剪贴板行为。 + +## 事件 + +`Saved()`:点击保存或 Cmd/Ctrl+Enter。`Canceled()`:点击取消或在文本框中按 Escape。 + +## 键盘操作 + +Cmd/Ctrl+Enter 保存,Escape 取消;Tab 依次到文本框、取消、保存。 + +## 限制 + +- 不保存历史:分支与原文由调用方保存。 diff --git a/docs/components/216-branch-navigator.md b/docs/components/216-branch-navigator.md new file mode 100644 index 0000000..8ab7bcc --- /dev/null +++ b/docs/components/216-branch-navigator.md @@ -0,0 +1,38 @@ +# 216 BranchNavigator 分支切换 + +## 用途 + +在一条消息的多个分支间切换,显示“< 2 / 3 >”。 + +## 最小示例 + +```go +if mujica.BranchNavigator(c, &branch, 3).Changed() { + fmt.Println("show branch", branch) +} +``` + +签名:`func BranchNavigator(c *ui.Context, index *int, count int) ChoiceResult` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `index` | `*int` | 必填 | 当前分支,0 起;不在 0 到 count−1 之间时 panic。 | +| `count` | `int` | 必填 | 分支数,至少 1。 | + +## 状态 + +首末分支时对应箭头禁用;切换时向辅助技术播报“第 n 个分支,共 m 个”。 + +## 事件 + +`Changed()`:分支改变。 + +## 键盘操作 + +整个控件是一个 Tab 停靠点:Left/Right 切换,Home、End 到第一个与最后一个;箭头按钮只响应指针。 + +## 限制 + +- 箭头按钮不进入 Tab 序列,避免到达首末分支时焦点停在禁用按钮上。 diff --git a/docs/components/217-error-message.md b/docs/components/217-error-message.md new file mode 100644 index 0000000..441891c --- /dev/null +++ b/docs/components/217-error-message.md @@ -0,0 +1,40 @@ +# 217 ErrorMessage 错误消息 + +## 用途 + +显示失败的回复:标题、原始错误文本(等宽、可选择复制,不改写、不截断)与重试按钮;限流时显示倒计时,倒计时结束前不能重试。 + +## 最小示例 + +```go +opts := mujica.ErrorMessageOptions{RetryAt: time.Now().Add(30 * time.Second)} +if mujica.ErrorMessage(c, "429 Too Many Requests", opts).Retried() { + fmt.Println("send again") +} +``` + +签名:`func ErrorMessage(c *ui.Context, text string, opts ErrorMessageOptions) ErrorMessageResult` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `text` | `string` | 必填 | 原始错误文本,原样显示;为空 panic。 | +| `Title` | `string` | “出错了” | 概括失败原因。 | +| `RetryAt` | `time.Time` | 零值 | 限流解除时间;之前重试按钮禁用并显示“n 秒后重试”与“已限流”。 | + +## 状态 + +可重试 / 限流倒计时;Danger 边框、图标与标题文字共同表示错误。倒计时只在秒数变化时重绘。 + +## 事件 + +`Retried()`:按下重试。 + +## 键盘操作 + +Tab 到错误文本(可用 Shift+方向键选择、Cmd/Ctrl+C 复制)与重试按钮。 + +## 限制 + +- 倒计时依据窗口时钟;调用方的 RetryAt 应来自服务端的 Retry-After。 diff --git a/docs/components/218-thinking-block.md b/docs/components/218-thinking-block.md new file mode 100644 index 0000000..fb2ca98 --- /dev/null +++ b/docs/components/218-thinking-block.md @@ -0,0 +1,40 @@ +# 218 ThinkingBlock 思考过程 + +## 用途 + +可折叠的思考过程:思考中显示加载标记与实时秒数,结束后显示“思考了 n 秒”。默认折叠或展开由调用方传入的 `*open` 初值决定。基于 Collapsible。 + +## 最小示例 + +```go +mujica.ThinkingBlock(c, &open, mujica.ThinkingBlockOptions{Elapsed: 12 * time.Second}, func() { + ui.Text(c, "Weigh the guest list.") +}) +``` + +签名:`func ThinkingBlock(c *ui.Context, open *bool, opts ThinkingBlockOptions, content func()) ChoiceResult` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `open` | `*bool` | 必填 | 是否展开;其初值即默认状态。 | +| `Thinking` | `bool` | false | 思考中:显示加载标记与从 Started 起的秒数。 | +| `Started` | `time.Time` | 零值 | 思考开始时间;Thinking 时必填,否则 panic。 | +| `Elapsed` | `time.Duration` | 0 | 思考结束后的总耗时;负数 panic。 | + +## 状态 + +思考中 / 已完成;展开时内容带左侧细线、TextMuted 色。减少动画时加载标记静止,秒数仍每秒更新。 + +## 事件 + +`Changed()`:展开状态改变。 + +## 键盘操作 + +Tab 聚焦标题,Enter 或 Space 展开与折叠。 + +## 限制 + +- 思考中每秒重绘一次以更新秒数;折叠且完成后不再重绘。 diff --git a/docs/components/219-scroll-to-bottom-button.md b/docs/components/219-scroll-to-bottom-button.md new file mode 100644 index 0000000..1cd7550 --- /dev/null +++ b/docs/components/219-scroll-to-bottom-button.md @@ -0,0 +1,40 @@ +# 219 ScrollToBottomButton 回到底部按钮 + +## 用途 + +离开底部时出现在容器底部居中的圆角按钮,带未读计数;点击回到底部。MessageList 已内置,也可单独用于其他滚动区域。 + +## 最小示例 + +```go +ui.Box(c).Fill().Children(func() { + if mujica.ScrollToBottomButton(c, !list.AtEnd(), 3).Clicked() { + list.ScrollToEnd() + } +}) +``` + +签名:`func ScrollToBottomButton(c *ui.Context, away bool, unread int) *ui.Element` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `away` | `bool` | 必填 | 是否已离开底部;false 时返回不可见的空元素,其 Clicked 为 false。 | +| `unread` | `int` | 0 | 未读数,大于 0 时显示;负数 panic。 | + +## 状态 + +出现时 160 毫秒淡入(减少动画时直接显示);悬停时底色加深。 + +## 事件 + +`Clicked()`:点击或 Enter、Space;滚动由调用方完成。 + +## 键盘操作 + +Tab 聚焦,Enter 或 Space 触发。辅助技术读到“回到最新,n 条新消息”。 + +## 限制 + +- 按钮以绝对定位贴在父元素底部,父元素需要占满滚动区域。 diff --git a/docs/components/220-typing-indicator.md b/docs/components/220-typing-indicator.md new file mode 100644 index 0000000..b0094d6 --- /dev/null +++ b/docs/components/220-typing-indicator.md @@ -0,0 +1,35 @@ +# 220 TypingIndicator 正在输入 + +## 用途 + +对方正在输入的提示:三个依次明暗变化的圆点;减少动画时改为静态文字“某某 正在输入…”。 + +## 最小示例 + +```go +mujica.TypingIndicator(c, "Herald") +``` + +签名:`func TypingIndicator(c *ui.Context, name string) *ui.Element` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `name` | `string` | 必填 | 正在输入的一方;为空 panic。 | + +## 状态 + +动画 / 静态文字;状态角色,辅助技术读到“某某 正在输入…”。 + +## 事件 + +无。 + +## 键盘操作 + +不获取焦点。 + +## 限制 + +- 动画只在显示时请求下一帧,移出界面后停止重绘。 diff --git a/error_message.go b/error_message.go new file mode 100644 index 0000000..64847d3 --- /dev/null +++ b/error_message.go @@ -0,0 +1,72 @@ +package mujica + +import ( + "fmt" + "log/slog" + "math" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// ErrorMessageOptions configure an ErrorMessage. +type ErrorMessageOptions struct { + // Title sums the failure up; empty uses the built-in "Something went wrong". + Title string + // RetryAt is when a rate limit lifts; until then retry waits with a countdown. + RetryAt time.Time +} + +// ErrorMessageResult is the error's element and a retry the user asked for. +type ErrorMessageResult struct { + Element *ui.Element + retried bool +} + +// Retried reports a press of retry. +func (r ErrorMessageResult) Retried() bool { return r.retried } + +// ErrorMessage shows a failed reply with the original error text, selectable, and retry. +func ErrorMessage(c *ui.Context, text string, opts ErrorMessageOptions) ErrorMessageResult { + if text == "" { + panic("mujica: ErrorMessage needs the error text") + } + k := Tokens(c) + u := Density(c).Unit() + title := opts.Title + if title == "" { + title = msg(c, "error_message.title") + } + wait := opts.RetryAt.Sub(c.Now()) + var r ErrorMessageResult + r.Element = ui.Column(c).Gap(u*2).Padding(u*3, u*4).MaxWidth(560).Radius(theme.CardRadius). + Background(k.Surface).Border(theme.BorderWidth, k.Danger).Role(ui.RoleGroup).Label(title) + disabled := r.Element.IsDisabled() + r.Element.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ui.Icon(c, icons.Must("circle-alert")).Size(16, 16).Shrink(0).TextColor(k.Danger) + ui.Text(c, title).FontWeight(600).TextColor(k.Danger) + }) + ui.Text(c, text).Selectable().Font(theme.MonoFont).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.Text) + ui.Row(c).Gap(u * 3).AlignItems(ui.Center).Children(func() { + label := msg(c, "error_message.retry") + if wait > 0 { + secs := int(math.Ceil(wait.Seconds())) + label = fmt.Sprintf(msg(c, "error_message.wait"), secs) + // Wake when the shown second changes. + c.After(wait - time.Duration(secs-1)*time.Second) + } + if Button(c, label, ButtonOptions{Variant: Secondary, Icon: icons.Must("refresh-cw"), Disabled: wait > 0}).Clicked() && !disabled { + r.retried = true + slog.Debug("mujica: error_message retry") + } + if wait > 0 { + ui.Text(c, msg(c, "error_message.limited")).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + } + }) + }) + return r +} diff --git a/error_message_test.go b/error_message_test.go new file mode 100644 index 0000000..08afeac --- /dev/null +++ b/error_message_test.go @@ -0,0 +1,69 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +const errorMessageText = `429 Too Many Requests: {"error":"rate_limit","retry_after":30}` + +func TestErrorMessageKeepsTextAndRetries(t *testing.T) { + retries := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if ErrorMessage(c, errorMessageText, ErrorMessageOptions{}).Retried() { + retries++ + } + }, 500, 200) + if !tt.HasText(errorMessageText) || !tt.HasText("Something went wrong") { + t.Fatalf("texts %q", tt.Texts()) + } + _ = tt.Click("Retry") + if retries != 1 { + t.Fatalf("retries %d", retries) + } +} + +func TestErrorMessageRateLimitCountdown(t *testing.T) { + retries := 0 + until := time.Now().Add(2500 * time.Millisecond) + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if ErrorMessage(c, errorMessageText, ErrorMessageOptions{Title: "Rate limited by the API", RetryAt: until}).Retried() { + retries++ + } + }, 500, 200) + if !tt.HasText("Retry in 3 s") { + t.Fatalf("countdown missing: %q", tt.Texts()) + } + _ = tt.Click("Retry in 3 s") + if retries != 0 { + t.Fatal("retried during the rate limit") + } + until = time.Now().Add(-time.Second) + tt.Frame() + _ = tt.Click("Retry") + if retries != 1 { + t.Fatalf("retries %d after the limit lifted", retries) + } +} + +func TestErrorMessageNeedsText(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic without error text") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ErrorMessage(c, "", ErrorMessageOptions{}) + }, 100, 100) +} + +func TestErrorMessageSnapshot(t *testing.T) { + snapshot(t, "error_message", 520, 150, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { ErrorMessage(c, errorMessageText, ErrorMessageOptions{}) }) + }) +} diff --git a/example_chatmsg_test.go b/example_chatmsg_test.go new file mode 100644 index 0000000..63b8ed2 --- /dev/null +++ b/example_chatmsg_test.go @@ -0,0 +1,222 @@ +package mujica_test + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func ExampleChatContainer() { + var chat mujica.MessageListState + msgs := []string{"Hello", "Bonjour"} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ChatContainer(c, &chat, len(msgs), mujica.ChatContainerOptions{ + List: mujica.MessageListOptions{ID: func(i int) string { return msgs[i] }}, + Input: func() { ui.Text(c, "Composer goes here") }, + }, func(i int) { ui.Text(c, msgs[i]) }) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMessageList() { + var list mujica.MessageListState + ids := []string{"m1", "m2", "m3"} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.MessageList(c, &list, len(ids), mujica.MessageListOptions{ + ID: func(i int) string { return ids[i] }, + }, func(i int) { ui.Text(c, "Message "+ids[i]) }) + fmt.Println("unread", r.Unread()) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMessageBubble() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.MessageBubble(c, mujica.MessageAssistant, mujica.MessageBubbleOptions{Name: "Herald"}, func() { + ui.Text(c, "The ball begins at nine.") + }) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMessageHeader() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.MessageHeader(c, mujica.MessageHeaderOptions{Model: "herald-2", Time: time.Now(), Status: mujica.MessageSent}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleStreamingText() { + reply := "The decree reads" + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.StreamingText(c, reply, mujica.StreamingTextOptions{Streaming: true, Smooth: true}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMarkdownView() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if url, ok := mujica.MarkdownView(c, "# Decree\n\nSee **the guide** at [the court](https://example.com).").Link(); ok { + fmt.Println("open", url) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCodeBlock() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CodeBlock(c, "func bow() {}", mujica.CodeBlockOptions{Language: "go", LineNumbers: true}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleTableBlock() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.TableBlock(c, []string{"Guest", "Seat"}, [][]string{{"Marie", "1"}}, mujica.TableBlockOptions{}).Copied() { + fmt.Println("copied as TSV") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleImageGrid() { + pic := ui.MustParseSVG([]byte(``)) + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if i, ok := mujica.ImageGrid(c, []mujica.GridImage{{Source: pic, Alt: "Portrait"}}).Retried(); ok { + fmt.Println("reload", i) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleFileMessage() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.FileMessage(c, mujica.FileMessageOptions{Name: "treaty.pdf", Size: 2621440}) + if r.Downloaded() { + fmt.Println("save treaty.pdf") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleAudioMessage() { + pos := 5 * time.Second + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.AudioMessage(c, mujica.AudioMessageOptions{Duration: time.Minute, Position: pos}) + if d, ok := r.Seek(); ok { + pos = d + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleLinkPreviewCard() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + p := mujica.LinkPreview{URL: "https://example.com", Title: "The Palace", Site: "example.com"} + if mujica.LinkPreviewCard(c, p).Clicked() { + fmt.Println("open", p.URL) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleQuoteReply() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.QuoteReply(c, "Marie", "Let them eat cake.").Clicked() { + fmt.Println("jump to the quoted message") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMessageActions() { + rating := mujica.FeedbackNone + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if a, ok := mujica.MessageActions(c, mujica.MessageAssistant, mujica.MessageActionsOptions{Feedback: &rating}).Action(); ok { + fmt.Println("action", a) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMessageEditor() { + draft := "Hello" + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.MessageEditor(c, &draft, mujica.MessageEditorOptions{Original: "Hello"}).Saved() { + fmt.Println("new branch from", draft) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleBranchNavigator() { + branch := 1 + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.BranchNavigator(c, &branch, 3).Changed() { + fmt.Println("show branch", branch) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleErrorMessage() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + opts := mujica.ErrorMessageOptions{RetryAt: time.Now().Add(30 * time.Second)} + if mujica.ErrorMessage(c, "429 Too Many Requests", opts).Retried() { + fmt.Println("send again") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleThinkingBlock() { + open := false + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ThinkingBlock(c, &open, mujica.ThinkingBlockOptions{Elapsed: 12 * time.Second}, func() { + ui.Text(c, "Weigh the guest list.") + }) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleScrollToBottomButton() { + var list mujica.MessageListState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + ui.Box(c).Fill().Children(func() { + if mujica.ScrollToBottomButton(c, !list.AtEnd(), 3).Clicked() { + list.ScrollToEnd() + } + }) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleTypingIndicator() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.TypingIndicator(c, "Herald") + } + ui.Render(view, 400, 300, 1) +} diff --git a/examples/gallery/pages_chatmsg.go b/examples/gallery/pages_chatmsg.go index 0172452..10d6b85 100644 --- a/examples/gallery/pages_chatmsg.go +++ b/examples/gallery/pages_chatmsg.go @@ -1,3 +1,261 @@ package main -var chatmsgPages = []page{} +import ( + "fmt" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +const chatmsgCategory = "Chat Messages" + +var chatmsgPages = append(append(chatmsgListPages, chatmsgBlockPages...), chatmsgActionPages...) + +// chatmsgReplies are the lines the demo assistant sends. +var chatmsgReplies = []string{ + "The ball begins at nine, in the Hall of Mirrors.", + "Guests arrive by the **east door**; carriages wait in the *lower court*.", + "Seating follows rank: dukes nearest the throne, then the envoys.", + "Shall I send the invitations tonight?", +} + +// chatmsgDemo is a chat whose messages the demo adds. +type chatmsgDemo struct { + ids []string + texts []string + list mujica.MessageListState + next int + sidebar bool + dated bool +} + +func newChatmsgDemo(n int) *chatmsgDemo { + d := &chatmsgDemo{sidebar: true, dated: true} + for range n { + d.add() + } + return d +} + +func (d *chatmsgDemo) add() { + d.ids = append(d.ids, fmt.Sprintf("msg-%d", d.next)) + d.texts = append(d.texts, chatmsgReplies[d.next%len(chatmsgReplies)]) + d.next++ +} + +// day puts three messages on each day, ending today. +func (d *chatmsgDemo) day(i int) time.Time { + last := (len(d.ids) - 1) / 3 + return time.Now().AddDate(0, 0, i/3-last) +} + +// row shows message i as a bubble, users and the assistant taking turns. +func (d *chatmsgDemo) row(c *ui.Context, i int) { + role := mujica.MessageAssistant + if i%2 == 0 { + role = mujica.MessageUser + } + mujica.MessageBubble(c, role, mujica.MessageBubbleOptions{}, func() { mujica.MarkdownView(c, d.texts[i]) }) +} + +// chatmsgControls adds messages to a demo chat and logs it. +func chatmsgControls(c *ui.Context, log func(string), d *chatmsgDemo) { + ui.Row(c).Gap(8).Children(func() { + if mujica.Button(c, "Add message", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + d.add() + log(fmt.Sprintf("message %s added", d.ids[len(d.ids)-1])) + } + if mujica.Button(c, "Add 10", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + for range 10 { + d.add() + } + log(fmt.Sprintf("10 messages added, %d in all", len(d.ids))) + } + if mujica.Button(c, "Jump to latest", mujica.ButtonOptions{Variant: mujica.Ghost}).Clicked() { + d.list.ScrollToEnd() + log("scrolled to end") + } + }) +} + +var chatmsgListPages = []page{ + {ID: "201", Name: "ChatContainer", ZhName: "对话容器", Category: chatmsgCategory, + Keys: "Tab 在侧栏、消息与输入区之间移动;消息区滚轮与 PageUp/PageDown 滚动;上翻后出现回到最新按钮。", + Code: `mujica.ChatContainer(c, &chat, len(msgs), mujica.ChatContainerOptions{ + List: mujica.MessageListOptions{ID: func(i int) string { return msgs[i] }}, + Input: func() { ui.Text(c, "Composer goes here") }, +}, func(i int) { ui.Text(c, msgs[i]) })`, + Demo: func(c *ui.Context, log func(string)) { + d := *ui.Local(c.Root(), "201", func() *chatmsgDemo { return newChatmsgDemo(6) }) + draft := ui.Local(c.Root(), "201.draft", func() string { return "" }) + inputSection(c, "Parameters", func() { + inputFlags(c, log, map[string]*bool{"Sidebar": &d.sidebar}, "Sidebar") + chatmsgControls(c, log, d) + }) + inputSection(c, "Live", func() { + ui.Box(c).Height(420).Border(1, mujica.Tokens(c).Border).Clip().Children(func() { + opts := mujica.ChatContainerOptions{ + List: mujica.MessageListOptions{ID: func(i int) string { return d.ids[i] }}, + Input: func() { + r := mujica.TextInput(c, draft, mujica.TextInputOptions{Label: "Message", Placeholder: "Write to the herald"}) + if r.Submitted() && strings.TrimSpace(*draft) != "" { + d.add() + d.texts[len(d.texts)-1] = *draft + log("sent a message") + *draft = "" + } + }, + } + if d.sidebar { + opts.Sidebar = func() { + ui.Column(c).Padding(12).Gap(8).Children(func() { + for _, s := range []string{"The ball", "Seating", "Envoys"} { + ui.Text(c, s) + } + }) + } + } + r := mujica.ChatContainer(c, &d.list, len(d.ids), opts, func(i int) { d.row(c, i) }) + if r.Unread() > 0 { + ui.Text(c, fmt.Sprintf("%d unread", r.Unread())).Absolute().Top(8).Right(12) + } + }) + }) + }}, + {ID: "202", Name: "MessageList", ZhName: "消息列表", Category: chatmsgCategory, + Keys: "滚轮与方向键滚动;上翻后停止跟随;Tab 到回到最新按钮,Enter 回到底部。", + Code: `r := mujica.MessageList(c, &list, len(ids), mujica.MessageListOptions{ + ID: func(i int) string { return ids[i] }, +}, func(i int) { ui.Text(c, "Message "+ids[i]) }) +fmt.Println("unread", r.Unread())`, + Demo: func(c *ui.Context, log func(string)) { + d := *ui.Local(c.Root(), "202", func() *chatmsgDemo { return newChatmsgDemo(30) }) + inputSection(c, "Parameters", func() { + inputFlags(c, log, map[string]*bool{"Date separators": &d.dated}, "Date separators") + chatmsgControls(c, log, d) + ui.Row(c).Children(func() { + if mujica.Button(c, "Load 100,000", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + for len(d.ids) < 100000 { + d.add() + } + log("100,000 messages loaded") + } + }) + }) + inputSection(c, "Live", func() { + opts := mujica.MessageListOptions{ID: func(i int) string { return d.ids[i] }, Label: func(i int) string { return d.texts[i] }} + if d.dated { + opts.Date = d.day + } + ui.Column(c).Height(360).Border(1, mujica.Tokens(c).Border).Children(func() { + r := mujica.MessageList(c, &d.list, len(d.ids), opts, func(i int) { d.row(c, i) }) + ui.Text(c, fmt.Sprintf("%d messages, %d unread, at end %v", len(d.ids), r.Unread(), d.list.AtEnd())).Padding(8) + }) + }) + }}, + {ID: "203", Name: "MessageBubble", ZhName: "消息气泡", Category: chatmsgCategory, + Keys: "气泡不获取焦点;内容中的链接与按钮按 Tab 顺序访问。", + Code: `mujica.MessageBubble(c, mujica.MessageAssistant, mujica.MessageBubbleOptions{Name: "Herald"}, func() { + ui.Text(c, "The ball begins at nine.") +})`, + Demo: func(c *ui.Context, log func(string)) { + type state struct { + role mujica.MessageRole + avatar, named bool + width float64 + } + s := ui.Local(c.Root(), "203", func() state { return state{role: mujica.MessageAssistant, avatar: true, named: true, width: 360} }) + roles := []mujica.RadioItem[mujica.MessageRole]{{Value: mujica.MessageUser, Label: "User"}, {Value: mujica.MessageAssistant, Label: "Assistant"}, + {Value: mujica.MessageSystem, Label: "System"}, {Value: mujica.MessageError, Label: "Error"}} + inputSection(c, "Parameters", func() { + if mujica.RadioGroup(c, &s.role, roles, mujica.RadioGroupOptions{Horizontal: true, Label: "Role"}).Changed() { + log(fmt.Sprintf("role %d", s.role)) + } + inputFlags(c, log, map[string]*bool{"Avatar": &s.avatar, "Name": &s.named}, "Avatar", "Name") + if mujica.NumberInput(c, &s.width, mujica.NumberInputOptions{Min: 160, Max: 640, Step: 40, Label: "MaxWidth"}).Changed() { + log(fmt.Sprintf("MaxWidth %v", s.width)) + } + }) + inputSection(c, "Live", func() { + opts := mujica.MessageBubbleOptions{MaxWidth: float32(s.width)} + if s.named { + opts.Name = "Herald" + } + if s.avatar { + opts.Avatar = func() { mujica.Avatar(c, "Herald", mujica.AvatarOptions{}) } + } + mujica.MessageBubble(c, s.role, opts, func() { ui.Text(c, chatmsgReplies[0]+" "+chatmsgReplies[2]) }) + }) + inputSection(c, "States", func() { + for _, r := range roles { + mujica.MessageBubble(c, r.Value, mujica.MessageBubbleOptions{Name: r.Label}, func() { ui.Text(c, r.Label+" message") }) + } + }) + }}, + {ID: "204", Name: "MessageHeader", ZhName: "消息头", Category: chatmsgCategory, Keys: "不获取焦点。", + Code: `mujica.MessageHeader(c, mujica.MessageHeaderOptions{Model: "herald-2", Time: time.Now(), Status: mujica.MessageSent})`, + Demo: func(c *ui.Context, log func(string)) { + status := ui.Local(c.Root(), "204", func() mujica.MessageStatus { return mujica.MessageSent }) + items := []mujica.RadioItem[mujica.MessageStatus]{{Value: mujica.MessageNoStatus, Label: "None"}, {Value: mujica.MessageSending, Label: "Sending"}, + {Value: mujica.MessageStreaming, Label: "Streaming"}, {Value: mujica.MessageSent, Label: "Sent"}, {Value: mujica.MessageFailed, Label: "Failed"}} + inputSection(c, "Parameters", func() { + if mujica.RadioGroup(c, status, items, mujica.RadioGroupOptions{Horizontal: true, Label: "Status"}).Changed() { + log(fmt.Sprintf("status %d", *status)) + } + }) + inputSection(c, "Live", func() { + mujica.MessageHeader(c, mujica.MessageHeaderOptions{Model: "herald-2", Time: time.Now(), Status: *status}) + }) + inputSection(c, "States", func() { + for _, it := range items[1:] { + mujica.MessageHeader(c, mujica.MessageHeaderOptions{Model: "herald-2", Time: time.Now(), Status: it.Value}) + } + }) + }}, + {ID: "205", Name: "StreamingText", ZhName: "流式文本", Category: chatmsgCategory, Keys: "不获取焦点;减少动画时直接显示全部文本。", + Code: `mujica.StreamingText(c, reply, mujica.StreamingTextOptions{Streaming: true, Smooth: true})`, + Demo: func(c *ui.Context, log func(string)) { + type state struct { + text string + smooth, streaming, auto bool + rate float64 + at time.Time + } + s := ui.Local(c.Root(), "205", func() state { return state{smooth: true, streaming: true, rate: 80} }) + const full = "By order of the Queen, the ball begins at nine. Guests arrive by the east door, and carriages wait in the lower court until midnight." + inputSection(c, "Parameters", func() { + inputFlags(c, log, map[string]*bool{"Smooth": &s.smooth, "Streaming cursor": &s.streaming, "Stream": &s.auto}, "Smooth", "Streaming cursor", "Stream") + if mujica.NumberInput(c, &s.rate, mujica.NumberInputOptions{Min: 10, Max: 400, Step: 10, Label: "Rate"}).Changed() { + log(fmt.Sprintf("Rate %v", s.rate)) + } + ui.Row(c).Children(func() { + if mujica.Button(c, "Restart", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.text = "" + log("stream restarted") + } + }) + }) + // The demo's own source appends a word every 150 ms while streaming. + if s.auto && len(s.text) < len(full) && c.Now().Sub(s.at) > 150*time.Millisecond { + rest := full[len(s.text):] + n := strings.IndexByte(rest[1:], ' ') + 2 + if n <= 1 { + n = len(rest) + } + s.text += rest[:n] + s.at = c.Now() + if len(s.text) == len(full) { + log("stream finished") + } + } + if s.auto && len(s.text) < len(full) { + c.After(150 * time.Millisecond) + } + inputSection(c, "Live", func() { + mujica.StreamingText(c, s.text, mujica.StreamingTextOptions{Streaming: s.streaming && len(s.text) < len(full), Smooth: s.smooth, Rate: s.rate}) + }) + }}, +} diff --git a/examples/gallery/pages_chatmsg_actions.go b/examples/gallery/pages_chatmsg_actions.go new file mode 100644 index 0000000..4d84d48 --- /dev/null +++ b/examples/gallery/pages_chatmsg_actions.go @@ -0,0 +1,292 @@ +package main + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +var chatmsgActionPages = []page{ + {ID: "211", Name: "AudioMessage", ZhName: "语音消息", Category: chatmsgCategory, Keys: "Tab 到播放按钮与波形;波形上 Left/Right 跳转,Home、End 到首尾。", + Code: `r := mujica.AudioMessage(c, mujica.AudioMessageOptions{Duration: time.Minute, Position: pos}) +if d, ok := r.Seek(); ok { + pos = d +}`, + Demo: func(c *ui.Context, log func(string)) { + type state struct { + pos time.Duration + playing bool + at time.Time + } + s := ui.Local(c.Root(), "211", func() state { return state{pos: 12 * time.Second} }) + const length = 47 * time.Second + // The demo plays: it moves the position while playing. + if s.playing { + s.pos += c.Now().Sub(s.at) + if s.pos >= length { + s.pos, s.playing = length, false + log("playback ended") + } + c.After(100 * time.Millisecond) + } + s.at = c.Now() + inputSection(c, "Live", func() { + r := mujica.AudioMessage(c, mujica.AudioMessageOptions{Duration: length, Position: s.pos, Playing: s.playing, Waveform: chatmsgWave}) + if r.Toggled() { + s.playing = !s.playing + if s.pos >= length { + s.pos = 0 + } + log(fmt.Sprintf("playing %v", s.playing)) + } + if d, ok := r.Seek(); ok { + s.pos = d + log(fmt.Sprintf("seek to %v", d.Round(time.Second))) + } + }) + inputSection(c, "States", func() { + ui.Column(c).Disabled(true).Children(func() { + mujica.AudioMessage(c, mujica.AudioMessageOptions{Duration: length, Waveform: chatmsgWave}) + }) + }) + }}, + {ID: "212", Name: "LinkPreviewCard", ZhName: "链接预览卡片", Category: chatmsgCategory, Keys: "Tab 聚焦卡片,Enter 或 Space 打开。", + Code: `p := mujica.LinkPreview{URL: "https://example.com", Title: "The Palace", Site: "example.com"} +if mujica.LinkPreviewCard(c, p).Clicked() { + fmt.Println("open", p.URL) +}`, + Demo: func(c *ui.Context, log func(string)) { + thumb := ui.Local(c.Root(), "212", func() bool { return true }) + inputSection(c, "Parameters", func() { + inputFlags(c, log, map[string]*bool{"Thumbnail": thumb}, "Thumbnail") + }) + p := mujica.LinkPreview{URL: "https://example.com/versailles", Title: "The Palace of Versailles", Site: "example.com", + Description: "A royal château in the Île-de-France region, seat of the French court from 1682 until the Revolution."} + if *thumb { + p.Thumbnail = chatmsgPicture("#AD9164") + } + inputSection(c, "Live", func() { + if mujica.LinkPreviewCard(c, p).Clicked() { + log("open " + p.URL) + } + if mujica.LinkPreviewCard(c, mujica.LinkPreview{URL: "https://example.com/hall", Title: "Hall of Mirrors"}).Clicked() { + log("open https://example.com/hall") + } + }) + }}, + {ID: "213", Name: "QuoteReply", ZhName: "引用回复", Category: chatmsgCategory, Keys: "Tab 聚焦,Enter 或 Space 跳转。", + Code: `if mujica.QuoteReply(c, "Marie", "Let them eat cake.").Clicked() { + fmt.Println("jump to the quoted message") +}`, + Demo: func(c *ui.Context, log func(string)) { + inputSection(c, "Live", func() { + for _, q := range [][2]string{{"Marie", "Let them eat cake."}, {"Herald", chatmsgMarkdown}} { + if mujica.QuoteReply(c, q[0], q[1]).Clicked() { + log("jump to " + q[0] + ": " + chatmsgSnippet(q[1], 24)) + } + } + }) + }}, + {ID: "214", Name: "MessageActions", ZhName: "消息操作", Category: chatmsgCategory, Keys: "Tab 进入工具栏,Left/Right 移动,Enter 或 Space 触发。", + Code: `if a, ok := mujica.MessageActions(c, mujica.MessageAssistant, mujica.MessageActionsOptions{Feedback: &rating}).Action(); ok { + fmt.Println("action", a) +}`, + Demo: func(c *ui.Context, log func(string)) { + type state struct { + role mujica.MessageRole + rating mujica.MessageFeedback + rated bool + } + s := ui.Local(c.Root(), "214", func() state { return state{role: mujica.MessageAssistant, rated: true} }) + names := map[mujica.MessageAction]string{mujica.ActionCopy: "copy", mujica.ActionRegenerate: "regenerate", mujica.ActionEdit: "edit", + mujica.ActionLike: "like", mujica.ActionDislike: "dislike", mujica.ActionSpeak: "speak", mujica.ActionShare: "share"} + inputSection(c, "Parameters", func() { + roles := []mujica.RadioItem[mujica.MessageRole]{{Value: mujica.MessageUser, Label: "User"}, {Value: mujica.MessageAssistant, Label: "Assistant"}, + {Value: mujica.MessageSystem, Label: "System"}, {Value: mujica.MessageError, Label: "Error"}} + if mujica.RadioGroup(c, &s.role, roles, mujica.RadioGroupOptions{Horizontal: true, Label: "Role"}).Changed() { + log(fmt.Sprintf("role %d", s.role)) + } + inputFlags(c, log, map[string]*bool{"Rating": &s.rated}, "Rating") + }) + inputSection(c, "Live", func() { + opts := mujica.MessageActionsOptions{} + if s.rated { + opts.Feedback = &s.rating + } + if a, ok := mujica.MessageActions(c, s.role, opts).Action(); ok { + log(fmt.Sprintf("action %s, rating %d", names[a], s.rating)) + } + }) + }}, + {ID: "215", Name: "MessageEditor", ZhName: "消息编辑器", Category: chatmsgCategory, Keys: "Cmd/Ctrl+Enter 保存,Escape 取消。", + Code: `if mujica.MessageEditor(c, &draft, mujica.MessageEditorOptions{Original: "Hello"}).Saved() { + fmt.Println("new branch from", draft) +}`, + Demo: func(c *ui.Context, log func(string)) { + type state struct { + original, draft string + editing bool + branches []string + index int + } + s := ui.Local(c.Root(), "215", func() state { + return state{original: "Seat the ambassador.", branches: []string{"Seat the ambassador."}} + }) + inputSection(c, "Live", func() { + if !s.editing { + mujica.MessageBubble(c, mujica.MessageUser, mujica.MessageBubbleOptions{}, func() { ui.Text(c, s.branches[s.index]) }) + ui.Row(c).Gap(8).Justify(ui.End).Children(func() { + if mujica.BranchNavigator(c, &s.index, len(s.branches)).Changed() { + log(fmt.Sprintf("branch %d", s.index+1)) + } + if mujica.Button(c, "Edit", mujica.ButtonOptions{Variant: mujica.Ghost}).Clicked() { + s.editing, s.draft = true, s.branches[s.index] + log("editing") + } + }) + return + } + r := mujica.MessageEditor(c, &s.draft, mujica.MessageEditorOptions{Original: s.branches[s.index]}) + if r.Saved() { + s.branches = append(s.branches, s.draft) + s.index, s.editing = len(s.branches)-1, false + log(fmt.Sprintf("saved as branch %d", len(s.branches))) + } + if r.Canceled() { + s.editing = false + log("edit canceled") + } + }) + }}, + {ID: "216", Name: "BranchNavigator", ZhName: "分支切换", Category: chatmsgCategory, Keys: "Tab 聚焦,Left/Right 切换,Home、End 到首末。", + Code: `if mujica.BranchNavigator(c, &branch, 3).Changed() { + fmt.Println("show branch", branch) +}`, + Demo: func(c *ui.Context, log func(string)) { + type state struct { + index int + count float64 + disabled bool + } + s := ui.Local(c.Root(), "216", func() state { return state{index: 1, count: 3} }) + inputSection(c, "Parameters", func() { + if mujica.NumberInput(c, &s.count, mujica.NumberInputOptions{Min: 1, Max: 9, StepperOnly: true, Label: "Branches"}).Changed() { + s.index = min(s.index, int(s.count)-1) + log(fmt.Sprintf("%v branches", s.count)) + } + inputFlags(c, log, map[string]*bool{"Disabled": &s.disabled}, "Disabled") + }) + inputSection(c, "Live", func() { + ui.Row(c).Disabled(s.disabled).Children(func() { + if mujica.BranchNavigator(c, &s.index, int(s.count)).Changed() { + log(fmt.Sprintf("branch %d of %v", s.index+1, s.count)) + } + }) + }) + }}, + {ID: "217", Name: "ErrorMessage", ZhName: "错误消息", Category: chatmsgCategory, Keys: "Tab 到错误文本(可选择复制)与重试按钮。", + Code: `opts := mujica.ErrorMessageOptions{RetryAt: time.Now().Add(30 * time.Second)} +if mujica.ErrorMessage(c, "429 Too Many Requests", opts).Retried() { + fmt.Println("send again") +}`, + Demo: func(c *ui.Context, log func(string)) { + until := ui.Local(c.Root(), "217", func() time.Time { return time.Time{} }) + inputSection(c, "Parameters", func() { + ui.Row(c).Children(func() { + if mujica.Button(c, "Rate limit for 10 s", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + *until = c.Now().Add(10 * time.Second) + log("rate limited for 10 s") + } + }) + }) + inputSection(c, "Live", func() { + opts := mujica.ErrorMessageOptions{RetryAt: *until} + if mujica.ErrorMessage(c, `429 Too Many Requests: {"type":"rate_limit_error","message":"Number of requests exceeded"}`, opts).Retried() { + log("retry") + } + if mujica.ErrorMessage(c, "dial tcp 10.0.0.7:443: connection refused", mujica.ErrorMessageOptions{Title: "Could not reach the server"}).Retried() { + log("retry connection") + } + }) + }}, + {ID: "218", Name: "ThinkingBlock", ZhName: "思考过程", Category: chatmsgCategory, Keys: "Tab 聚焦标题,Enter 或 Space 展开与折叠。", + Code: `mujica.ThinkingBlock(c, &open, mujica.ThinkingBlockOptions{Elapsed: 12 * time.Second}, func() { + ui.Text(c, "Weigh the guest list.") +})`, + Demo: func(c *ui.Context, log func(string)) { + type state struct { + open, thinking bool + started time.Time + elapsed time.Duration + } + s := ui.Local(c.Root(), "218", func() state { return state{elapsed: 14 * time.Second} }) + inputSection(c, "Parameters", func() { + label := "Start thinking" + if s.thinking { + label = "Finish thinking" + } + ui.Row(c).Children(func() { + if mujica.Button(c, label, mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + if s.thinking { + s.elapsed = c.Now().Sub(s.started) + } else { + s.started = c.Now() + } + s.thinking = !s.thinking + log(fmt.Sprintf("thinking %v", s.thinking)) + } + }) + }) + inputSection(c, "Live", func() { + opts := mujica.ThinkingBlockOptions{Thinking: s.thinking, Started: s.started, Elapsed: s.elapsed} + if mujica.ThinkingBlock(c, &s.open, opts, func() { + ui.Text(c, "Forty guests, thirty-six seats. The envoys outrank the counts; four counts dine in the antechamber.") + }).Changed() { + log(fmt.Sprintf("open %v", s.open)) + } + }) + }}, + {ID: "219", Name: "ScrollToBottomButton", ZhName: "回到底部按钮", Category: chatmsgCategory, Keys: "Tab 聚焦,Enter 或 Space 回到底部。", + Code: `ui.Box(c).Fill().Children(func() { + if mujica.ScrollToBottomButton(c, !list.AtEnd(), 3).Clicked() { + list.ScrollToEnd() + } +})`, + Demo: func(c *ui.Context, log func(string)) { + type state struct { + away bool + unread float64 + } + s := ui.Local(c.Root(), "219", func() state { return state{away: true, unread: 3} }) + inputSection(c, "Parameters", func() { + inputFlags(c, log, map[string]*bool{"Away from bottom": &s.away}, "Away from bottom") + if mujica.NumberInput(c, &s.unread, mujica.NumberInputOptions{Min: 0, Max: 99, Label: "Unread"}).Changed() { + log(fmt.Sprintf("unread %v", s.unread)) + } + }) + inputSection(c, "Live", func() { + ui.Box(c).Height(120).Background(mujica.Tokens(c).Surface).Border(1, mujica.Tokens(c).Border).Children(func() { + if mujica.ScrollToBottomButton(c, s.away, int(s.unread)).Clicked() { + s.away, s.unread = false, 0 + log("back to the bottom") + } + }) + }) + }}, + {ID: "220", Name: "TypingIndicator", ZhName: "正在输入", Category: chatmsgCategory, Keys: "不获取焦点;减少动画时显示静态文字。", + Code: `mujica.TypingIndicator(c, "Herald")`, + Demo: func(c *ui.Context, log func(string)) { + typing := ui.Local(c.Root(), "220", func() bool { return true }) + inputSection(c, "Parameters", func() { + inputFlags(c, log, map[string]*bool{"Typing": typing}, "Typing") + }) + inputSection(c, "Live", func() { + if *typing { + mujica.TypingIndicator(c, "Herald") + } + }) + }}, +} diff --git a/examples/gallery/pages_chatmsg_blocks.go b/examples/gallery/pages_chatmsg_blocks.go new file mode 100644 index 0000000..3356e64 --- /dev/null +++ b/examples/gallery/pages_chatmsg_blocks.go @@ -0,0 +1,198 @@ +package main + +import ( + "errors" + "fmt" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +const chatmsgMarkdown = "## The Decree\n\nBy order of **the Queen**, *all* guests use `the east door`. See [the protocol](https://example.com/protocol).\n\n" + + "1. Arrive at nine\n2. Bow to the throne\n - dukes first\n\n> Silence in the Hall of Mirrors.\n\n" + + "```python\ndef bow(guest):\n return f\"{guest} bows\" # deeply\n```\n\n| Guest | Seat |\n|---|--:|\n| Marie | 1 |\n| Axel | 14 |\n\n---\n\nVive la reine." + +// chatmsgPicture is a flat colored picture for image demos. +func chatmsgPicture(color string) ui.ImageSource { + return ui.MustParseSVG([]byte(fmt.Sprintf(``, color))) +} + +var chatmsgColors = []string{"#7D2034", "#AD9164", "#355E80", "#326247", "#805714", "#6A5B55", "#9C3C53", "#D2C3AF", "#211C1D"} + +var chatmsgBlockPages = []page{ + {ID: "206", Name: "MarkdownView", ZhName: "Markdown 视图", Category: chatmsgCategory, Keys: "Tab 到链接,Enter 激活;代码块与表格按钮按 Tab 顺序访问。", + Code: `if url, ok := mujica.MarkdownView(c, "# Decree\n\nSee **the guide** at [the court](https://example.com).").Link(); ok { + fmt.Println("open", url) +}`, + Demo: func(c *ui.Context, log func(string)) { + type state struct { + src string + stream bool + at time.Time + } + s := ui.Local(c.Root(), "206", func() state { return state{src: chatmsgMarkdown} }) + inputSection(c, "Parameters", func() { + ui.Row(c).Children(func() { + if mujica.Button(c, "Stream it again", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.src, s.stream = "", true + log("streaming started") + } + }) + mujica.TextArea(c, &s.src, mujica.TextAreaOptions{Label: "Markdown source", MaxHeight: 160}) + }) + if s.stream && len(s.src) < len(chatmsgMarkdown) && c.Now().Sub(s.at) > 40*time.Millisecond { + s.src = chatmsgMarkdown[:min(len(chatmsgMarkdown), len(s.src)+6)] + s.at = c.Now() + if len(s.src) == len(chatmsgMarkdown) { + s.stream = false + log("streaming finished; finished blocks were never parsed again") + } + } + if s.stream { + c.After(40 * time.Millisecond) + } + inputSection(c, "Live", func() { + if url, ok := mujica.MarkdownView(c, s.src).Link(); ok { + log("link " + url) + } + }) + }}, + {ID: "207", Name: "CodeBlock", ZhName: "代码块", Category: chatmsgCategory, Keys: "Tab 到换行、复制、折叠按钮;Space 或 Enter 触发。", + Code: `mujica.CodeBlock(c, "func bow() {}", mujica.CodeBlockOptions{Language: "go", LineNumbers: true})`, + Demo: func(c *ui.Context, log func(string)) { + type state struct { + lang string + numbers, wrap bool + } + s := ui.Local(c.Root(), "207", func() state { return state{lang: "go", numbers: true} }) + samples := map[string]string{ + "go": "// greet the court\nfunc greet(name string) int {\n\treturn len(\"Your Majesty, \" + name + \", the ball awaits you in the Hall of Mirrors\") + 42\n}", + "python": "def bow(guest):\n # deeply, always\n return f\"{guest} bows\" * 3", + "sql": "SELECT name, seat FROM guests WHERE rank > 2 ORDER BY seat LIMIT 10; -- the envoys", + } + inputSection(c, "Parameters", func() { + langs := []mujica.RadioItem[string]{{Value: "go", Label: "Go"}, {Value: "python", Label: "Python"}, {Value: "sql", Label: "SQL"}} + if mujica.RadioGroup(c, &s.lang, langs, mujica.RadioGroupOptions{Horizontal: true, Label: "Language"}).Changed() { + log("language " + s.lang) + } + inputFlags(c, log, map[string]*bool{"LineNumbers": &s.numbers, "Wrap at first": &s.wrap}, "LineNumbers", "Wrap at first") + }) + inputSection(c, "Live", func() { + ui.Column(c).Key(s.lang + fmt.Sprint(s.wrap)).Children(func() { + if mujica.CodeBlock(c, samples[s.lang], mujica.CodeBlockOptions{Language: s.lang, LineNumbers: s.numbers, Wrap: s.wrap}).Copied() { + log("code copied") + } + }) + }) + inputSection(c, "States", func() { + mujica.CodeBlock(c, samples["go"], mujica.CodeBlockOptions{Language: "go", Collapsed: true}) + }) + }}, + {ID: "208", Name: "TableBlock", ZhName: "表格块", Category: chatmsgCategory, Keys: "Tab 到复制按钮,Enter 或 Space 复制为 TSV。", + Code: `if mujica.TableBlock(c, []string{"Guest", "Seat"}, [][]string{{"Marie", "1"}}, mujica.TableBlockOptions{}).Copied() { + fmt.Println("copied as TSV") +}`, + Demo: func(c *ui.Context, log func(string)) { + wide := ui.Local(c.Root(), "208", func() bool { return false }) + inputSection(c, "Parameters", func() { + inputFlags(c, log, map[string]*bool{"Wide table": wide}, "Wide table") + }) + header := []string{"Guest", "Title", "Seat"} + rows := [][]string{{"Marie", "Queen of France", "1"}, {"Axel", "Count of Fersen", "14"}} + if *wide { + header = append(header, "Arrival", "Carriage", "Retinue", "Notes") + for i := range rows { + rows[i] = append(rows[i], "21:00", "Gilded coach", "Twelve", "Seated near the orchestra, away from the draughts") + } + } + inputSection(c, "Live", func() { + ui.Column(c).MaxWidth(520).Children(func() { + if mujica.TableBlock(c, header, rows, mujica.TableBlockOptions{Align: []ui.Align{ui.Start, ui.Start, ui.End}}).Copied() { + log("table copied as TSV") + } + }) + }) + }}, + {ID: "209", Name: "ImageGrid", ZhName: "图片网格", Category: chatmsgCategory, Keys: "Tab 聚焦图片,Enter 打开查看器;查看器内 Left/Right 切换,Escape 关闭。", + Code: `if i, ok := mujica.ImageGrid(c, []mujica.GridImage{{Source: pic, Alt: "Portrait"}}).Retried(); ok { + fmt.Println("reload", i) +}`, + Demo: func(c *ui.Context, log func(string)) { + type state struct { + n float64 + loading, fail bool + } + s := ui.Local(c.Root(), "209", func() state { return state{n: 5} }) + inputSection(c, "Parameters", func() { + if mujica.NumberInput(c, &s.n, mujica.NumberInputOptions{Min: 1, Max: 9, Label: "Images", StepperOnly: true}).Changed() { + log(fmt.Sprintf("%v images", s.n)) + } + inputFlags(c, log, map[string]*bool{"Last loading": &s.loading, "Second failed": &s.fail}, "Last loading", "Second failed") + }) + imgs := make([]mujica.GridImage, int(s.n)) + for i := range imgs { + imgs[i] = mujica.GridImage{Source: chatmsgPicture(chatmsgColors[i]), Alt: fmt.Sprintf("Portrait %d", i+1)} + } + if s.loading { + imgs[len(imgs)-1] = mujica.GridImage{Alt: "Loading portrait", Loading: true} + } + if s.fail && len(imgs) > 1 { + imgs[1] = mujica.GridImage{Alt: "Lost portrait", Err: errors.New("404")} + } + inputSection(c, "Live", func() { + if i, ok := mujica.ImageGrid(c, imgs).Retried(); ok { + s.fail = false + log(fmt.Sprintf("retry image %d", i)) + } + }) + }}, + {ID: "210", Name: "FileMessage", ZhName: "文件消息", Category: chatmsgCategory, Keys: "Tab 到文件与下载按钮,Enter 或 Space 触发。", + Code: `r := mujica.FileMessage(c, mujica.FileMessageOptions{Name: "treaty.pdf", Size: 2621440}) +if r.Downloaded() { + fmt.Println("save treaty.pdf") +}`, + Demo: func(c *ui.Context, log func(string)) { + disabled := ui.Local(c.Root(), "210", func() bool { return false }) + inputSection(c, "Parameters", func() { + inputFlags(c, log, map[string]*bool{"Disabled": disabled}, "Disabled") + }) + inputSection(c, "Live", func() { + ui.Column(c).Gap(8).Disabled(*disabled).Children(func() { + for _, f := range []mujica.FileMessageOptions{{Name: "treaty.pdf", Size: 2621440}, {Name: "portrait.png", Size: 812000}, + {Name: "ledger.zip", Size: 73400320}, {Name: "decree.go", Size: 1840}, {Name: "notes", Size: 12}} { + r := mujica.FileMessage(c, f) + if r.Opened() { + log("open " + f.Name) + } + if r.Downloaded() { + log("download " + f.Name) + } + } + }) + }) + }}, +} + +// chatmsgWave is a fixed waveform for the voice demo. +var chatmsgWave = func() []float32 { + w := make([]float32, 48) + for i := range w { + w[i] = float32(0.25 + 0.7*float64((i*37)%11)/10) + if w[i] > 1 { + w[i] = 1 + } + } + return w +}() + +// chatmsgSnippet trims s to n runes for logs. +func chatmsgSnippet(s string, n int) string { + r := []rune(strings.TrimSpace(s)) + if len(r) > n { + return string(r[:n]) + "…" + } + return string(r) +} diff --git a/examples/gallery/pages_chatmsg_test.go b/examples/gallery/pages_chatmsg_test.go new file mode 100644 index 0000000..7a2bf62 --- /dev/null +++ b/examples/gallery/pages_chatmsg_test.go @@ -0,0 +1,72 @@ +package main + +import ( + "image/png" + "os" + "path/filepath" + "slices" + "testing" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +// chatmsgDemoTester runs the demo of page id and returns its tester and event log. +func chatmsgDemoTester(t *testing.T, id string, mode mujica.Mode) (*ui.Tester, *[]string) { + t.Helper() + i := slices.IndexFunc(chatmsgPages, func(p page) bool { return p.ID == id }) + if i < 0 { + t.Fatalf("no page %s", id) + } + events := &[]string{} + tt := ui.NewTester(func(c *ui.Context) { + mujica.Use(c, mujica.Settings{Mode: mode}) + ui.Scroll(c).Fill().Padding(24).Gap(16).Children(func() { + chatmsgPages[i].Demo(c, func(s string) { *events = append(*events, s) }) + }) + }, 900, 800) + tt.SetPreferences(ui.Preferences{ReduceMotion: true, TextScale: 1}) + tt.Frame() + return tt, events +} + +func TestChatmsgDemosRender(t *testing.T) { + if len(chatmsgPages) != 20 { + t.Fatalf("%d chat message pages, want 20", len(chatmsgPages)) + } + dir := os.Getenv("CHATMSG_DEMO_DIR") + for _, p := range chatmsgPages { + for _, m := range []mujica.Mode{mujica.Light, mujica.Dark} { + tt, _ := chatmsgDemoTester(t, p.ID, m) + if len(tt.Texts()) == 0 { + t.Errorf("%s: demo shows nothing", p.ID) + } + if dir == "" { + continue + } + f, err := os.Create(filepath.Join(dir, p.ID+"-"+m.String()+".png")) + if err != nil { + t.Fatal(err) + } + if err := png.Encode(f, tt.Image()); err != nil { + t.Fatal(err) + } + f.Close() + } + } +} + +func TestChatmsgDemosLogEvents(t *testing.T) { + for id, click := range map[string]string{ + "202": "Add message", "207": "Copy code", "214": "Regenerate", "216": "Next branch", "217": "Retry", + } { + tt, events := chatmsgDemoTester(t, id, mujica.Light) + if err := tt.Click(click); err != nil { + t.Fatalf("%s: %v", id, err) + } + if len(*events) == 0 { + t.Errorf("%s: clicking %q logged nothing", id, click) + } + } +} diff --git a/file_message.go b/file_message.go new file mode 100644 index 0000000..451d76c --- /dev/null +++ b/file_message.go @@ -0,0 +1,123 @@ +package mujica + +import ( + "fmt" + "log/slog" + "path" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// FileMessageOptions describe a file sent in a chat. +type FileMessageOptions struct { + // Name is the file name; required. + Name string + // Size is the length in bytes. + Size int64 + // Type is the MIME type; empty guesses from the name's extension. + Type string +} + +// FileMessageResult is a FileMessage's element and this frame's actions. +type FileMessageResult struct { + Element *ui.Element + opened, downloaded bool +} + +// Opened reports a click or Enter on the file. +func (r FileMessageResult) Opened() bool { return r.opened } + +// Downloaded reports a click on the download button. +func (r FileMessageResult) Downloaded() bool { return r.downloaded } + +// FileMessage shows a file's type icon, name and size, with open and download actions. +func FileMessage(c *ui.Context, opts FileMessageOptions) FileMessageResult { + if opts.Name == "" { + panic("mujica: FileMessage needs a Name") + } + if opts.Size < 0 { + panic("mujica: FileMessage Size must not be negative") + } + k := Tokens(c) + u := Density(c).Unit() + size := fileMessageSize(c, opts.Size) + var r FileMessageResult + r.Element = ui.Row(c).Gap(u).AlignItems(ui.Center).Padding(u, u, u, u*2).MaxWidth(360). + Radius(theme.CardRadius).Background(k.Surface).Border(theme.BorderWidth, k.Border) + disabled := r.Element.IsDisabled() + r.Element.Children(func() { + open := ui.ButtonBase(c).Grow(1).MinWidth(0).Gap(u * 3).Padding(u).Justify(ui.Start).Radius(theme.ControlRadius). + Label(fmt.Sprintf(msg(c, "file_message.open"), opts.Name, size)) + internal.Ring(open, k.Focus, theme.ControlRadius) + if open.Hovered() { + open.Background(k.SurfaceHover) + } + open.Children(func() { + ui.Icon(c, icons.Must(fileMessageIcon(opts.Name, opts.Type))).Size(24, 24).Shrink(0).TextColor(k.AccentText) + ui.Column(c).MinWidth(0).Grow(1).Children(func() { + ui.Text(c, opts.Name).SingleLine().FontWeight(600) + ui.Text(c, size).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine() + }) + }) + if open.Clicked() && !disabled { + r.opened = true + slog.Debug("mujica: file_message open") + } + if iconAction(c, icons.Must("download"), fmt.Sprintf(msg(c, "file_message.download"), opts.Name)).Clicked() && !disabled { + r.downloaded = true + slog.Debug("mujica: file_message download") + } + }) + return r +} + +// fileMessageSize formats n bytes in binary units. +func fileMessageSize(c *ui.Context, n int64) string { + units := []string{"B", "KB", "MB", "GB", "TB"} + v, i := float64(n), 0 + for v >= 1024 && i < len(units)-1 { + v /= 1024 + i++ + } + if i == 0 { + return fmt.Sprintf(msg(c, "file_message.bytes"), n) + } + return fmt.Sprintf("%.1f %s", v, units[i]) +} + +// fileMessageKinds maps extensions to type icons. +var fileMessageKinds = func() map[string]string { + m := map[string]string{} + for icon, exts := range map[string]string{ + "image": ".png .jpg .jpeg .gif .webp .svg", + "file-archive": ".zip .tar .gz .tgz .7z .rar", + "file-code": ".go .js .ts .py .json .sh .sql .html .css .rs .java .c .h", + "file-text": ".txt .md .pdf .doc .docx .rtf", + } { + for _, e := range strings.Fields(exts) { + m[e] = icon + } + } + return m +}() + +// fileMessageIcon picks a type icon from the MIME type, else the extension. +func fileMessageIcon(name, mime string) string { + switch { + case strings.HasPrefix(mime, "image/"): + return "image" + case strings.Contains(mime, "zip"): + return "file-archive" + case strings.HasPrefix(mime, "text/"): + return "file-text" + } + if icon, ok := fileMessageKinds[strings.ToLower(path.Ext(name))]; ok { + return icon + } + return "file" +} diff --git a/file_message_test.go b/file_message_test.go new file mode 100644 index 0000000..3ec84cf --- /dev/null +++ b/file_message_test.go @@ -0,0 +1,82 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestFileMessageOpenDownloadAndSize(t *testing.T) { + opened, downloaded, off := 0, 0, false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Disabled(off).Children(func() { + r := FileMessage(c, FileMessageOptions{Name: "treaty.pdf", Size: 2_621_440}) + if r.Opened() { + opened++ + } + if r.Downloaded() { + downloaded++ + } + }) + }, 400, 200) + if !tt.HasText("2.5 MB") || !tt.HasText("treaty.pdf") { + t.Fatalf("texts %q", tt.Texts()) + } + _ = tt.Click("Open treaty.pdf, 2.5 MB") + _ = tt.Click("Download treaty.pdf") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if opened != 2 || downloaded != 1 { + t.Fatalf("opened %d downloaded %d", opened, downloaded) + } + off = true + _ = tt.Click("Open treaty.pdf, 2.5 MB") + _ = tt.Click("Download treaty.pdf") + if opened != 2 || downloaded != 1 { + t.Fatalf("disabled file acted: opened %d downloaded %d", opened, downloaded) + } +} + +func TestFileMessageIconsAndSizes(t *testing.T) { + for name, want := range map[string]string{"a.png": "image", "b.zip": "file-archive", "c.go": "file-code", "d.md": "file-text", "e.bin": "file", "f.c": "file-code", "g.s": "file"} { + if got := fileMessageIcon(name, ""); got != want { + t.Errorf("%s: icon %s, want %s", name, got, want) + } + } + if fileMessageIcon("x", "image/heic") != "image" { + t.Error("MIME type ignored") + } + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + for _, n := range []int64{0, 1023, 1024, 5 << 30} { + ui.Text(c, fileMessageSize(c, n)) + } + }, 200, 200) + for _, s := range []string{"0 B", "1023 B", "1.0 KB", "5.0 GB"} { + if !tt.HasText(s) { + t.Errorf("missing size %q in %q", s, tt.Texts()) + } + } +} + +func TestFileMessageNeedsName(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic without a name") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + FileMessage(c, FileMessageOptions{}) + }, 100, 100) +} + +func TestFileMessageSnapshot(t *testing.T) { + snapshot(t, "file_message", 400, 160, func(c *ui.Context) { + ui.Column(c).Padding(16).Gap(8).Children(func() { + FileMessage(c, FileMessageOptions{Name: "seating-plan.xlsx", Size: 48_213}) + FileMessage(c, FileMessageOptions{Name: "portrait.png", Size: 3_400_000}) + }) + }) +} diff --git a/icons/svg/brain.svg b/icons/svg/brain.svg new file mode 100644 index 0000000..5a030d0 --- /dev/null +++ b/icons/svg/brain.svg @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/icons/svg/download.svg b/icons/svg/download.svg new file mode 100644 index 0000000..4da2f2a --- /dev/null +++ b/icons/svg/download.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/icons/svg/file-archive.svg b/icons/svg/file-archive.svg new file mode 100644 index 0000000..c9ea9ef --- /dev/null +++ b/icons/svg/file-archive.svg @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/icons/svg/file-code.svg b/icons/svg/file-code.svg new file mode 100644 index 0000000..34c065e --- /dev/null +++ b/icons/svg/file-code.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/icons/svg/pause.svg b/icons/svg/pause.svg new file mode 100644 index 0000000..12b6f06 --- /dev/null +++ b/icons/svg/pause.svg @@ -0,0 +1,15 @@ + + + + diff --git a/icons/svg/pencil.svg b/icons/svg/pencil.svg new file mode 100644 index 0000000..f0e3f38 --- /dev/null +++ b/icons/svg/pencil.svg @@ -0,0 +1,15 @@ + + + + diff --git a/icons/svg/play.svg b/icons/svg/play.svg new file mode 100644 index 0000000..6eb03bb --- /dev/null +++ b/icons/svg/play.svg @@ -0,0 +1,14 @@ + + + diff --git a/icons/svg/share-2.svg b/icons/svg/share-2.svg new file mode 100644 index 0000000..7825a02 --- /dev/null +++ b/icons/svg/share-2.svg @@ -0,0 +1,18 @@ + + + + + + + diff --git a/icons/svg/thumbs-down.svg b/icons/svg/thumbs-down.svg new file mode 100644 index 0000000..6e74b23 --- /dev/null +++ b/icons/svg/thumbs-down.svg @@ -0,0 +1,15 @@ + + + + diff --git a/icons/svg/thumbs-up.svg b/icons/svg/thumbs-up.svg new file mode 100644 index 0000000..30dca62 --- /dev/null +++ b/icons/svg/thumbs-up.svg @@ -0,0 +1,15 @@ + + + + diff --git a/icons/svg/volume-2.svg b/icons/svg/volume-2.svg new file mode 100644 index 0000000..d403d95 --- /dev/null +++ b/icons/svg/volume-2.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/icons/svg/wrap-text.svg b/icons/svg/wrap-text.svg new file mode 100644 index 0000000..d5ce615 --- /dev/null +++ b/icons/svg/wrap-text.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/image_grid.go b/image_grid.go new file mode 100644 index 0000000..8161285 --- /dev/null +++ b/image_grid.go @@ -0,0 +1,103 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// GridImage is one picture of an ImageGrid; the caller loads it. +type GridImage struct { + Source ui.ImageSource + Alt string + // Loading and Err show the caller's load in progress or failure. + Loading bool + Err error +} + +// ImageGridResult is an ImageGrid's element and a retry the user asked for. +type ImageGridResult struct { + Element *ui.Element + retry int +} + +// Retried returns the index of the failed picture whose retry was pressed this frame. +func (r ImageGridResult) Retried() (int, bool) { return r.retry, r.retry >= 0 } + +// imageGridState is the viewer opened from the grid. +type imageGridState struct { + open bool + index int +} + +// ImageGrid lays out 1 to 9 pictures; a click on a loaded one opens the ImageViewer. +func ImageGrid(c *ui.Context, images []GridImage) ImageGridResult { + n := len(images) + if n < 1 || n > 9 { + panic("mujica: ImageGrid shows 1 to 9 images") + } + k := Tokens(c) + u := Density(c).Unit() + cols := 3 + switch n { + case 1: + cols = 1 + case 2, 4: + cols = 2 + } + cell := float32(120) + if n == 1 { + cell = 280 + } + r := ImageGridResult{retry: -1} + r.Element = ui.Grid(c).Columns(cols).Gap(u).AlignSelf(ui.Start) + st := ui.Local(r.Element, "viewer", func() imageGridState { return imageGridState{} }) + var viewable []ViewerImage + var at []int + for i, im := range images { + if im.Source != nil && !im.Loading && im.Err == nil { + at = append(at, i) + viewable = append(viewable, ViewerImage{Source: im.Source, Alt: im.Alt}) + } + } + disabled := r.Element.IsDisabled() + r.Element.Children(func() { + for i, im := range images { + loaded := im.Source != nil && !im.Loading && im.Err == nil + // Only a loaded picture is a button; a failed one keeps its retry. + var b *ui.Element + if loaded { + b = ui.ButtonBase(c).Label(im.Alt) + internal.Ring(b, k.Focus, theme.ControlRadius) + } else { + b = ui.Box(c) + } + b.Size(cell, cell).Radius(theme.ControlRadius).Clip().Children(func() { + v := Image(c, im.Source, ImageOptions{Width: cell, Height: cell, Crop: true, Alt: im.Alt, Loading: im.Loading, Err: im.Err}) + if v.Retry && !disabled { + r.retry = i + slog.Debug("mujica: image_grid retry", "index", i) + } + }) + if loaded && b.Clicked() && !disabled { + for vi, ii := range at { + if ii == i { + st.open, st.index = true, vi + } + } + slog.Debug("mujica: image_grid open", "index", i) + } + } + }) + if disabled { + st.open = false + } + if st.open && len(viewable) > 0 { + st.index = min(st.index, len(viewable)-1) + ImageViewer(c, &st.open, &st.index, viewable) + } + return r +} diff --git a/image_grid_test.go b/image_grid_test.go new file mode 100644 index 0000000..e5e65fd --- /dev/null +++ b/image_grid_test.go @@ -0,0 +1,95 @@ +package mujica + +import ( + "errors" + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +// imageGridPicture is a plain colored picture standing in for a photo. +func imageGridPicture(color string) ui.ImageSource { + return ui.MustParseSVG([]byte(fmt.Sprintf(``, color))) +} + +func imageGridSet(n int) []GridImage { + colors := []string{"#7D2034", "#AD9164", "#355E80", "#326247", "#805714", "#6A5B55", "#9C3C53", "#D2C3AF", "#211C1D"} + out := make([]GridImage, n) + for i := range out { + out[i] = GridImage{Source: imageGridPicture(colors[i]), Alt: fmt.Sprintf("Photo %d", i+1)} + } + return out +} + +func TestImageGridLayoutsByCount(t *testing.T) { + for n, cols := range map[int]int{1: 1, 2: 2, 3: 3, 4: 2, 5: 3, 9: 3} { + var xs map[float32]bool + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ImageGrid(c, imageGridSet(n)) + }, 900, 900) + tt.Frame() + xs = map[float32]bool{} + for i := range n { + r, ok := tt.Find(fmt.Sprintf("Photo %d", i+1)) + if !ok { + t.Fatalf("%d images: Photo %d missing", n, i+1) + } + xs[r.X] = true + } + if len(xs) != cols { + t.Errorf("%d images in %d columns, want %d", n, len(xs), cols) + } + } +} + +func TestImageGridOpensViewerAndRetries(t *testing.T) { + imgs := imageGridSet(3) + imgs[1] = GridImage{Alt: "Lost", Err: errors.New("404")} + retried := -1 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if i, ok := ImageGrid(c, imgs).Retried(); ok { + retried = i + } + }, 800, 600) + if err := tt.Click("Photo 3"); err != nil { + t.Fatal(err) + } + if !tt.HasText("Image 2 of 2") { + t.Fatalf("viewer not at the third picture (second viewable): %q", tt.Texts()) + } + tt.Key(0, ui.KeyEscape) + if err := tt.Click("Retry"); err != nil { + t.Fatal(err) + } + if retried != 1 { + t.Fatalf("retried %d, want 1", retried) + } +} + +func TestImageGridCountLimits(t *testing.T) { + for _, n := range []int{0, 10} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%d images: no panic", n) + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ImageGrid(c, make([]GridImage, n)) + }, 100, 100) + }() + } +} + +func TestImageGridSnapshot(t *testing.T) { + imgs := imageGridSet(5) + imgs[3] = GridImage{Alt: "Loading", Loading: true} + imgs[4] = GridImage{Alt: "Lost", Err: errors.New("404")} + snapshot(t, "image_grid", 420, 300, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { ImageGrid(c, imgs) }) + }) +} diff --git a/internal/markdown.go b/internal/markdown.go new file mode 100644 index 0000000..8608cac --- /dev/null +++ b/internal/markdown.go @@ -0,0 +1,305 @@ +package internal + +import ( + "strconv" + "strings" +) + +// BlockKind is the kind of a Markdown block. +type BlockKind uint8 + +const ( + BlockParagraph BlockKind = iota + BlockHeading + BlockList + BlockQuote + BlockCode + BlockTable + BlockRule +) + +// MdSpan is a run of inline text with one style. +type MdSpan struct { + Text string + // URL is set for a link. + URL string + Strong, Em, Code, Strike bool +} + +// MdItem is one list item. +type MdItem struct { + // Number is the ordinal of an ordered item, 0 for a bullet. + Number int + Depth int + Spans []MdSpan +} + +// TableAlign is a table column's alignment. +type TableAlign uint8 + +const ( + AlignLeft TableAlign = iota + AlignCenter + AlignRight +) + +// MdBlock is one parsed block. +type MdBlock struct { + Kind BlockKind + // Level is a heading's level, 1 to 6. + Level int + // Spans hold a paragraph's, heading's or quote's text. + Spans []MdSpan + Items []MdItem + // Lang and Code hold a fenced code block; Open is true until its fence closes. + Lang, Code string + Open bool + Header []string + Align []TableAlign + Rows [][]string +} + +// Markdown is a document parsed incrementally as its source grows. +type Markdown struct { + src string + Blocks []MdBlock + starts []int +} + +// Update parses src and returns the index of the first block parsed anew. +// When src extends the last source, blocks before the last stay as they are. +func (m *Markdown) Update(src string) int { + if src == m.src && m.starts != nil { + return len(m.Blocks) + } + from := 0 + if len(m.Blocks) > 0 && strings.HasPrefix(src, m.src) { + from = len(m.Blocks) - 1 + } + off := 0 + if from > 0 { + off = m.starts[from] + } + m.Blocks, m.starts = m.Blocks[:from], m.starts[:from] + m.src = src + parseBlocks(m, src, off) + return from +} + +// mdLine is one source line and its byte offset. +type mdLine struct { + text string + off int +} + +func parseBlocks(m *Markdown, src string, off int) { + var lines []mdLine + for off < len(src) { + end := strings.IndexByte(src[off:], '\n') + if end < 0 { + lines = append(lines, mdLine{src[off:], off}) + break + } + lines = append(lines, mdLine{strings.TrimRight(src[off:off+end], "\r"), off}) + off += end + 1 + } + for i := 0; i < len(lines); { + l := lines[i].text + if strings.TrimSpace(l) == "" { + i++ + continue + } + start := lines[i].off + var b MdBlock + switch { + case mdFence(l) != "": + b, i = parseFenced(lines, i) + case mdHeadingLevel(l) > 0: + lv := mdHeadingLevel(l) + b = MdBlock{Kind: BlockHeading, Level: lv, Spans: ParseInline(strings.TrimSpace(strings.TrimRight(l[lv:], "# ")))} + i++ + case mdIsRule(l): + b = MdBlock{Kind: BlockRule} + i++ + case strings.HasPrefix(strings.TrimLeft(l, " "), ">"): + b, i = parseQuote(lines, i) + case mdListMarker(l) != nil: + b, i = parseList(lines, i) + case i+1 < len(lines) && strings.Contains(l, "|") && mdDelimiter(lines[i+1].text) != nil: + b, i = parseTable(lines, i) + default: + b, i = parseParagraph(lines, i) + } + m.Blocks = append(m.Blocks, b) + m.starts = append(m.starts, start) + } +} + +// mdStarts reports whether line l begins a block other than a paragraph. +func mdStarts(lines []mdLine, i int) bool { + l := lines[i].text + return strings.TrimSpace(l) == "" || mdFence(l) != "" || mdHeadingLevel(l) > 0 || mdIsRule(l) || + strings.HasPrefix(strings.TrimLeft(l, " "), ">") || mdListMarker(l) != nil || + i+1 < len(lines) && strings.Contains(l, "|") && mdDelimiter(lines[i+1].text) != nil +} + +func parseParagraph(lines []mdLine, i int) (MdBlock, int) { + var parts []string + for ; i < len(lines) && (len(parts) == 0 || !mdStarts(lines, i)); i++ { + parts = append(parts, strings.TrimSpace(lines[i].text)) + } + return MdBlock{Kind: BlockParagraph, Spans: ParseInline(strings.Join(parts, " "))}, i +} + +// mdFence returns the fence a line opens, "```" or "~~~", or "". +func mdFence(l string) string { + t := strings.TrimLeft(l, " ") + for _, f := range []string{"```", "~~~"} { + if strings.HasPrefix(t, f) { + return f + } + } + return "" +} + +func parseFenced(lines []mdLine, i int) (MdBlock, int) { + fence := mdFence(lines[i].text) + b := MdBlock{Kind: BlockCode, Open: true, Lang: strings.ToLower(strings.TrimSpace(strings.TrimLeft(strings.TrimSpace(lines[i].text), fence[:1])))} + var code []string + for i++; i < len(lines); i++ { + if strings.HasPrefix(strings.TrimSpace(lines[i].text), fence) && strings.Trim(strings.TrimSpace(lines[i].text), fence[:1]) == "" { + b.Open = false + i++ + break + } + code = append(code, lines[i].text) + } + b.Code = strings.Join(code, "\n") + return b, i +} + +func mdHeadingLevel(l string) int { + n := 0 + for n < len(l) && l[n] == '#' { + n++ + } + if n == 0 || n > 6 || n < len(l) && l[n] != ' ' { + return 0 + } + return n +} + +func mdIsRule(l string) bool { + t := strings.ReplaceAll(strings.TrimSpace(l), " ", "") + if len(t) < 3 { + return false + } + return strings.Count(t, t[:1]) == len(t) && strings.ContainsAny(t[:1], "-*_") +} + +func parseQuote(lines []mdLine, i int) (MdBlock, int) { + var parts []string + for ; i < len(lines); i++ { + t := strings.TrimLeft(lines[i].text, " ") + if !strings.HasPrefix(t, ">") { + break + } + parts = append(parts, strings.TrimSpace(t[1:])) + } + return MdBlock{Kind: BlockQuote, Spans: ParseInline(strings.Join(parts, " "))}, i +} + +// mdMarker is a list item's marker. +type mdMarker struct { + number, depth, width int +} + +func mdListMarker(l string) *mdMarker { + indent := len(l) - len(strings.TrimLeft(l, " ")) + t := l[indent:] + if len(t) >= 2 && strings.ContainsRune("-*+", rune(t[0])) && t[1] == ' ' { + return &mdMarker{depth: indent / 2, width: indent + 2} + } + d := 0 + for d < len(t) && t[d] >= '0' && t[d] <= '9' { + d++ + } + if d == 0 || d > 9 || d+1 >= len(t) || !strings.ContainsRune(".)", rune(t[d])) || t[d+1] != ' ' { + return nil + } + n, _ := strconv.Atoi(t[:d]) + return &mdMarker{number: max(n, 1), depth: indent / 2, width: indent + d + 2} +} + +func parseList(lines []mdLine, i int) (MdBlock, int) { + b := MdBlock{Kind: BlockList} + var texts []string + for ; i < len(lines); i++ { + l := lines[i].text + if mk := mdListMarker(l); mk != nil { + b.Items = append(b.Items, MdItem{Number: mk.number, Depth: mk.depth}) + texts = append(texts, strings.TrimSpace(l[mk.width:])) + continue + } + if mdStarts(lines, i) { + break + } + // A lazy line continues the item above. + texts[len(texts)-1] += " " + strings.TrimSpace(l) + } + for j := range b.Items { + b.Items[j].Spans = ParseInline(texts[j]) + } + return b, i +} + +// mdCells splits a table row into trimmed cells. +func mdCells(l string) []string { + t := strings.TrimSpace(l) + t = strings.TrimSuffix(strings.TrimPrefix(t, "|"), "|") + cells := strings.Split(t, "|") + for i := range cells { + cells[i] = strings.TrimSpace(cells[i]) + } + return cells +} + +// mdDelimiter parses a table's delimiter row, or returns nil. +func mdDelimiter(l string) []TableAlign { + if !strings.Contains(l, "-") { + return nil + } + var out []TableAlign + for _, c := range mdCells(l) { + left, right := strings.HasPrefix(c, ":"), strings.HasSuffix(c, ":") + if strings.Trim(c, ":") == "" || strings.Trim(c, ":-") != "" { + return nil + } + switch { + case left && right: + out = append(out, AlignCenter) + case right: + out = append(out, AlignRight) + default: + out = append(out, AlignLeft) + } + } + return out +} + +func parseTable(lines []mdLine, i int) (MdBlock, int) { + b := MdBlock{Kind: BlockTable, Header: mdCells(lines[i].text), Align: mdDelimiter(lines[i+1].text)} + n := len(b.Header) + for len(b.Align) < n { + b.Align = append(b.Align, AlignLeft) + } + b.Align = b.Align[:n] + for i += 2; i < len(lines) && strings.Contains(lines[i].text, "|") && strings.TrimSpace(lines[i].text) != ""; i++ { + row := mdCells(lines[i].text) + for len(row) < n { + row = append(row, "") + } + b.Rows = append(b.Rows, row[:n]) + } + return b, i +} diff --git a/internal/markdown_inline.go b/internal/markdown_inline.go new file mode 100644 index 0000000..db9e160 --- /dev/null +++ b/internal/markdown_inline.go @@ -0,0 +1,128 @@ +package internal + +import "strings" + +// mdStyle is the inline style in effect. +type mdStyle struct{ strong, em, strike bool } + +// ParseInline splits text into styled spans: emphasis, code, strikethrough and links. +// An opener without its closer stays literal, as while a message streams in. +func ParseInline(s string) []MdSpan { + var out []MdSpan + parseInline(s, mdStyle{}, &out) + return out +} + +func mdEmit(out *[]MdSpan, sp MdSpan) { + if sp.Text == "" { + return + } + if n := len(*out); n > 0 { + last := &(*out)[n-1] + if sp.URL == "" && last.URL == "" && last.Strong == sp.Strong && last.Em == sp.Em && last.Code == sp.Code && last.Strike == sp.Strike { + last.Text += sp.Text + return + } + } + *out = append(*out, sp) +} + +func parseInline(s string, st mdStyle, out *[]MdSpan) { + plain := func(t string) { + mdEmit(out, MdSpan{Text: t, Strong: st.strong, Em: st.em, Strike: st.strike}) + } + for i := 0; i < len(s); { + switch c := s[i]; { + case c == '\\' && i+1 < len(s) && strings.IndexByte("\\`*_~[]()#!>-|", s[i+1]) >= 0: + plain(s[i+1 : i+2]) + i += 2 + continue + case c == '`': + if end := strings.IndexByte(s[i+1:], '`'); end >= 0 { + mdEmit(out, MdSpan{Text: s[i+1 : i+1+end], Code: true, Strong: st.strong, Em: st.em, Strike: st.strike}) + i += end + 2 + continue + } + case c == '[': + if text, url, n := mdLink(s[i:]); n > 0 { + mdEmit(out, MdSpan{Text: text, URL: url, Strong: st.strong, Em: st.em, Strike: st.strike}) + i += n + continue + } + case c == '*' || c == '_' || c == '~': + if n := mdDelimited(s, i, st, out); n > 0 { + i += n + continue + } + } + j := i + 1 + for j < len(s) && strings.IndexByte("\\`[*_~", s[j]) < 0 { + j++ + } + plain(s[i:j]) + i = j + } +} + +// mdDelimited parses emphasis or strikethrough opening at i and returns its length, or 0. +func mdDelimited(s string, i int, st mdStyle, out *[]MdSpan) int { + c := s[i] + n := 1 + if i+1 < len(s) && s[i+1] == c { + n = 2 + } + if c == '~' && n != 2 { + return 0 + } + // Intraword underscores stay literal, as in snake_case. + if c == '_' && i > 0 && mdWord(s[i-1]) { + return 0 + } + marker := s[i : i+n] + body := i + n + if body >= len(s) || s[body] == ' ' { + return 0 + } + end := -1 + for j := body + 1; j+n <= len(s); j++ { + if s[j:j+n] == marker && s[j-1] != ' ' && (n == 2 || j+1 >= len(s) || s[j+1] != c) { + end = j + break + } + } + if end < 0 { + return 0 + } + inner := st + switch { + case c == '~': + inner.strike = true + case n == 2: + inner.strong = true + default: + inner.em = true + } + parseInline(s[body:end], inner, out) + return end + n - i +} + +func mdWord(b byte) bool { + return b >= 'a' && b <= 'z' || b >= 'A' && b <= 'Z' || b >= '0' && b <= '9' +} + +// mdLink parses [text](url) at the start of s and returns its length, or 0. +func mdLink(s string) (text, url string, n int) { + close := strings.Index(s, "](") + if close < 1 || strings.IndexByte(s[1:close], '[') >= 0 { + return "", "", 0 + } + end := strings.IndexByte(s[close+2:], ')') + if end < 0 { + return "", "", 0 + } + url = strings.TrimSpace(s[close+2 : close+2+end]) + if url == "" || strings.ContainsAny(url, " \n") { + return "", "", 0 + } + return s[1:close], url, close + 3 + end +} diff --git a/internal/markdown_test.go b/internal/markdown_test.go new file mode 100644 index 0000000..373baeb --- /dev/null +++ b/internal/markdown_test.go @@ -0,0 +1,108 @@ +package internal + +import ( + "reflect" + "strings" + "testing" +) + +const mdSample = "# Title\n\nSome **bold** and *em* text with `code`\nand a [link](https://x.io).\n\n" + + "- one\n- two\n - nested\n3. three\n\n> quoted *line*\n\n```go\nfunc f() {}\n```\n\n" + + "| a | b |\n|:--|--:|\n| 1 | 2 |\n| 3 |\n\n---\n\nend ~~old~~ new" + +func TestMarkdownBlocks(t *testing.T) { + var m Markdown + m.Update(mdSample) + var kinds []BlockKind + for _, b := range m.Blocks { + kinds = append(kinds, b.Kind) + } + want := []BlockKind{BlockHeading, BlockParagraph, BlockList, BlockQuote, BlockCode, BlockTable, BlockRule, BlockParagraph} + if !reflect.DeepEqual(kinds, want) { + t.Fatalf("kinds %v, want %v", kinds, want) + } + b := m.Blocks + if b[0].Level != 1 || b[0].Spans[0].Text != "Title" { + t.Errorf("heading %+v", b[0]) + } + p := b[1].Spans + if p[1] != (MdSpan{Text: "bold", Strong: true}) || p[3] != (MdSpan{Text: "em", Em: true}) || p[5] != (MdSpan{Text: "code", Code: true}) { + t.Errorf("paragraph spans %+v", p) + } + if p[7] != (MdSpan{Text: "link", URL: "https://x.io"}) { + t.Errorf("link %+v", p[7]) + } + it := b[2].Items + if len(it) != 4 || it[2].Depth != 1 || it[2].Spans[0].Text != "nested" || it[3].Number != 3 { + t.Errorf("list items %+v", it) + } + if b[3].Spans[1] != (MdSpan{Text: "line", Em: true}) { + t.Errorf("quote %+v", b[3].Spans) + } + if b[4].Lang != "go" || b[4].Code != "func f() {}" || b[4].Open { + t.Errorf("code %+v", b[4]) + } + tb := b[5] + if !reflect.DeepEqual(tb.Header, []string{"a", "b"}) || !reflect.DeepEqual(tb.Align, []TableAlign{AlignLeft, AlignRight}) || + !reflect.DeepEqual(tb.Rows, [][]string{{"1", "2"}, {"3", ""}}) { + t.Errorf("table %+v", tb) + } + if b[7].Spans[1] != (MdSpan{Text: "old", Strike: true}) { + t.Errorf("strike %+v", b[7].Spans) + } +} + +func TestMarkdownInlineLiterals(t *testing.T) { + for in, want := range map[string]string{ + "2 * 3 * 4": "2 * 3 * 4", + "snake_case_name": "snake_case_name", + "**unclosed": "**unclosed", + `\*not em\*`: "*not em*", + "[no link]": "[no link]", + } { + sp := ParseInline(in) + if len(sp) != 1 || sp[0].Text != want || sp[0].Em || sp[0].Strong { + t.Errorf("%q gave %+v", in, sp) + } + } +} + +// TestMarkdownIncremental streams the sample byte by byte and checks finished blocks are kept. +func TestMarkdownIncremental(t *testing.T) { + var m Markdown + for i := 1; i <= len(mdSample); i++ { + before := append([]MdBlock(nil), m.Blocks...) + from := m.Update(mdSample[:i]) + if from < len(before)-1 { + t.Fatalf("at %d reparsed from %d of %d blocks", i, from, len(before)) + } + for j := 0; j < from; j++ { + if !reflect.DeepEqual(m.Blocks[j], before[j]) { + t.Fatalf("at %d finished block %d changed", i, j) + } + } + } + var whole Markdown + whole.Update(mdSample) + if !reflect.DeepEqual(m.Blocks, whole.Blocks) { + t.Fatal("streamed parse differs from a whole parse") + } + if m.Update(mdSample) != len(m.Blocks) { + t.Fatal("an unchanged source parsed again") + } + if m.Update("# Other") != 0 || len(m.Blocks) != 1 { + t.Fatal("a replaced source kept old blocks") + } +} + +func TestMarkdownOpenFence(t *testing.T) { + var m Markdown + m.Update("```py\nprint(1)\n") + if len(m.Blocks) != 1 || !m.Blocks[0].Open || m.Blocks[0].Code != "print(1)" { + t.Fatalf("open fence %+v", m.Blocks) + } + m.Update("```py\nprint(1)\n```\nafter") + if len(m.Blocks) != 2 || m.Blocks[0].Open || !strings.Contains(m.Blocks[1].Spans[0].Text, "after") { + t.Fatalf("closed fence %+v", m.Blocks) + } +} diff --git a/link_preview_card.go b/link_preview_card.go new file mode 100644 index 0000000..697ace7 --- /dev/null +++ b/link_preview_card.go @@ -0,0 +1,49 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// LinkPreview is a link's metadata, fetched by the caller. +type LinkPreview struct { + // URL is the link; required. + URL string + // Title is required; Description, Site and Thumbnail may be empty. + Title, Description, Site string + Thumbnail ui.ImageSource +} + +// LinkPreviewCard shows a link's site, title, description and thumbnail; Clicked opens it. +func LinkPreviewCard(c *ui.Context, p LinkPreview) *ui.Element { + if p.URL == "" || p.Title == "" { + panic("mujica: LinkPreviewCard needs URL and Title") + } + k := Tokens(c) + u := Density(c).Unit() + b := ui.ButtonBase(c).MaxWidth(420).Gap(u*3).Padding(u*2).AlignItems(ui.Start).Justify(ui.Start). + Radius(theme.CardRadius).Background(k.Surface).Border(theme.BorderWidth, k.Border).Label(p.Title).Tooltip(p.URL).Transition(colorFade) + internal.Ring(b, k.Focus, theme.CardRadius) + if b.Hovered() { + b.Background(k.SurfaceHover) + } + b.Children(func() { + ui.Column(c).Grow(1).MinWidth(0).Gap(u).Children(func() { + site := p.Site + if site == "" { + site = p.URL + } + ui.Text(c, site).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine() + ui.Text(c, p.Title).FontWeight(600).TextColor(k.AccentText).MaxLines(2) + if p.Description != "" { + ui.Text(c, p.Description).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).MaxLines(2) + } + }) + if p.Thumbnail != nil { + ui.Image(c, p.Thumbnail).Fit(ui.Cover).Size(64, 64).Radius(theme.ControlRadius).Shrink(0) + } + }) + return b +} diff --git a/link_preview_card_test.go b/link_preview_card_test.go new file mode 100644 index 0000000..527f4e9 --- /dev/null +++ b/link_preview_card_test.go @@ -0,0 +1,62 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +var linkPreviewSample = LinkPreview{ + URL: "https://example.com/versailles", Title: "The Palace of Versailles", + Description: "A royal château in the Île-de-France region, seat of the court from 1682.", Site: "example.com", +} + +func TestLinkPreviewCardShowsMetadataAndOpens(t *testing.T) { + opened := 0 + p := linkPreviewSample + p.Thumbnail = imageGridPicture("#7D2034") + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if LinkPreviewCard(c, p).Clicked() { + opened++ + } + }, 500, 200) + for _, s := range []string{"example.com", "The Palace of Versailles", "A royal château"} { + if !tt.HasText(s) { + t.Errorf("missing %q in %q", s, tt.Texts()) + } + } + _ = tt.Click("The Palace of Versailles") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if opened != 2 { + t.Fatalf("opened %d", opened) + } +} + +func TestLinkPreviewCardSiteFallsBackToURL(t *testing.T) { + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + LinkPreviewCard(c, LinkPreview{URL: "https://a.io/x", Title: "X"}) + }, 400, 200) + if !tt.HasText("https://a.io/x") { + t.Fatalf("texts %q", tt.Texts()) + } + defer func() { + if recover() == nil { + t.Fatal("no panic without a title") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + LinkPreviewCard(c, LinkPreview{URL: "https://a.io"}) + }, 100, 100) +} + +func TestLinkPreviewCardSnapshot(t *testing.T) { + p := linkPreviewSample + p.Thumbnail = imageGridPicture("#AD9164") + snapshot(t, "link_preview_card", 460, 130, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { LinkPreviewCard(c, p) }) + }) +} diff --git a/markdown_view.go b/markdown_view.go new file mode 100644 index 0000000..d06a6e7 --- /dev/null +++ b/markdown_view.go @@ -0,0 +1,126 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// MarkdownResult is a MarkdownView's element and the link the user opened this frame. +type MarkdownResult struct { + Element *ui.Element + link string +} + +// Link returns the URL of the link clicked or activated this frame. +func (r MarkdownResult) Link() (string, bool) { return r.link, r.link != "" } + +// MarkdownView renders a Markdown subset; a growing src parses only its last block again. +func MarkdownView(c *ui.Context, src string) MarkdownResult { + u := Density(c).Unit() + var r MarkdownResult + r.Element = ui.Column(c).Gap(u * 3).MinWidth(0) + doc := ui.Local(r.Element, "doc", func() *internal.Markdown { return &internal.Markdown{} }) + if from := (*doc).Update(src); from < len((*doc).Blocks) { + slog.Debug("mujica: markdown_view parse", "from", from, "blocks", len((*doc).Blocks)) + } + r.Element.Children(func() { + for i := range (*doc).Blocks { + b := &(*doc).Blocks[i] + ui.Column(c).Key(i).MinWidth(0).Children(func() { + if url := markdownBlock(c, b); url != "" { + r.link = url + } + }) + } + }) + if r.link != "" { + slog.Debug("mujica: markdown_view link") + } + return r +} + +// markdownBlock builds one block and returns a link opened in it. +func markdownBlock(c *ui.Context, b *internal.MdBlock) string { + k := Tokens(c) + u := Density(c).Unit() + switch b.Kind { + case internal.BlockHeading: + size := []float32{theme.H1Size, theme.H2Size, theme.H3Size}[min(b.Level, 3)-1] + t := ui.RichText(c).Font(theme.SerifFont).FontSize(FontSize(c, size)).FontWeight(600).Role(ui.RoleText) + return markdownSpans(c, t, b.Spans) + case internal.BlockParagraph: + return markdownSpans(c, ui.RichText(c), b.Spans) + case internal.BlockQuote: + var link string + ui.Row(c).Padding(0, 0, 0, u*3).BorderWidth(0, 0, 0, 3).BorderColor(k.Border).Children(func() { + link = markdownSpans(c, ui.RichText(c).TextColor(k.TextMuted).Grow(1), b.Spans) + }) + return link + case internal.BlockList: + var link string + ui.Column(c).Gap(u).Role(ui.RoleList).Children(func() { + for _, it := range b.Items { + ui.Row(c).Gap(u*2).AlignItems(ui.Start).Padding(0, 0, 0, float32(it.Depth)*u*5).Role(ui.RoleListItem).Children(func() { + mark := "•" + if it.Number > 0 { + mark = fmt.Sprintf("%d.", it.Number) + } + ui.Text(c, mark).TextColor(k.TextMuted).FontFeatures("tnum").MinWidth(u * 4).Shrink(0) + if l := markdownSpans(c, ui.RichText(c).Grow(1).MinWidth(0), it.Spans); l != "" { + link = l + } + }) + } + }) + return link + case internal.BlockCode: + CodeBlock(c, b.Code, CodeBlockOptions{Language: b.Lang}) + case internal.BlockTable: + align := make([]ui.Align, len(b.Align)) + for i, a := range b.Align { + align[i] = []ui.Align{ui.Start, ui.Center, ui.End}[a] + } + TableBlock(c, b.Header, b.Rows, TableBlockOptions{Align: align}) + case internal.BlockRule: + ui.Box(c).Height(u * 4).Draw(func(p *ui.Painter, r ui.Rect) { + internal.RuleDiamond(p, r, u*2, 5, k.Ornament) + }) + } + return "" +} + +// markdownSpans fills paragraph t with styled spans; links are focusable and return their URL when used. +func markdownSpans(c *ui.Context, t *ui.Element, spans []internal.MdSpan) string { + k := Tokens(c) + var link string + t.MinWidth(0).Children(func() { + for _, sp := range spans { + e := ui.Text(c, sp.Text) + if sp.Strong { + e.FontWeight(700) + } + if sp.Em { + e.Italic() + } + if sp.Strike { + e.Strikethrough() + } + if sp.Code { + e.Font(theme.MonoFont).TextBackground(k.SurfaceHover) + } + if sp.URL == "" { + continue + } + e.TextColor(k.AccentText).Underline().Focusable().Role(ui.RoleLink).Cursor(ui.CursorPointer).Tooltip(sp.URL) + if e.Clicked() && !e.IsDisabled() { + link = sp.URL + } + } + }) + return link +} diff --git a/markdown_view_test.go b/markdown_view_test.go new file mode 100644 index 0000000..9f39b2f --- /dev/null +++ b/markdown_view_test.go @@ -0,0 +1,64 @@ +package mujica + +import ( + "strings" + "testing" + + "github.com/egoist/mygo/ui" +) + +const markdownViewSample = "# Decree\n\nBy order of **the Queen**, *all* guests use `the east door`.\n\n" + + "- Arrive at nine\n- Wear [court dress](https://example.com/dress)\n\n> Silence in the hall.\n\n" + + "```go\nfunc bow() {}\n```\n\n| Room | Floor |\n|---|--:|\n| Hall | 1 |\n\n---\n\nEnd." + +func TestMarkdownViewRendersSubset(t *testing.T) { + src := markdownViewSample + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Scroll(c).Fill().Children(func() { MarkdownView(c, src) }) + }, 600, 900) + for _, s := range []string{"Decree", "the Queen", "all", "the east door", "Arrive at nine", "court dress", + "Silence in the hall.", "func", "bow", "Room", "Hall", "End."} { + if !tt.HasText(s) { + t.Errorf("missing %q in %q", s, tt.Texts()) + } + } +} + +func TestMarkdownViewLinkByClickAndKeyboard(t *testing.T) { + var got []string + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if url, ok := MarkdownView(c, "See [the guide](https://x.io/guide).").Link(); ok { + got = append(got, url) + } + }, 400, 200) + if err := tt.Click("the guide"); err != nil { + t.Fatal(err) + } + tt.Key(0, ui.KeyEnter) + if len(got) != 2 || got[0] != "https://x.io/guide" || got[1] != got[0] { + t.Fatalf("links %q", got) + } +} + +func TestMarkdownViewStreamsWithoutReparsingFinishedBlocks(t *testing.T) { + src := "" + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Scroll(c).Fill().Children(func() { MarkdownView(c, src) }) + }, 600, 900) + for _, chunk := range strings.SplitAfter(markdownViewSample, " ") { + src += chunk + tt.Frame() + } + if !tt.HasText("End.") || !tt.HasText("Decree") { + t.Fatalf("streamed render incomplete: %q", tt.Texts()) + } +} + +func TestMarkdownViewSnapshot(t *testing.T) { + snapshot(t, "markdown_view", 560, 720, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { MarkdownView(c, markdownViewSample) }) + }) +} diff --git a/message_actions.go b/message_actions.go new file mode 100644 index 0000000..ba28375 --- /dev/null +++ b/message_actions.go @@ -0,0 +1,111 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" +) + +// MessageAction is one action on a chat message. +type MessageAction int + +const ( + ActionCopy MessageAction = iota + 1 + ActionRegenerate + ActionEdit + ActionLike + ActionDislike + ActionSpeak + ActionShare +) + +// MessageFeedback is the user's rating of an assistant message. +type MessageFeedback int + +const ( + FeedbackNone MessageFeedback = iota + FeedbackLiked + FeedbackDisliked +) + +// MessageActionsOptions configure MessageActions. +type MessageActionsOptions struct { + // Feedback holds the rating; nil hides like and dislike. + Feedback *MessageFeedback +} + +// MessageActionsResult is the toolbar's element and the action chosen this frame. +type MessageActionsResult struct { + Element *ui.Element + action MessageAction +} + +// Action returns the action the user chose this frame. +func (r MessageActionsResult) Action() (MessageAction, bool) { return r.action, r.action != 0 } + +// messageActionIcons names each action's icon and copy key. +var messageActionIcons = map[MessageAction][2]string{ + ActionCopy: {"copy", "message_actions.copy"}, + ActionRegenerate: {"refresh-cw", "message_actions.regenerate"}, + ActionEdit: {"pencil", "message_actions.edit"}, + ActionLike: {"thumbs-up", "message_actions.like"}, + ActionDislike: {"thumbs-down", "message_actions.dislike"}, + ActionSpeak: {"volume-2", "message_actions.speak"}, + ActionShare: {"share-2", "message_actions.share"}, +} + +// messageActionsFor lists the actions a role's messages offer. +func messageActionsFor(role MessageRole, rated bool) []MessageAction { + switch role { + case MessageUser: + return []MessageAction{ActionCopy, ActionEdit} + case MessageAssistant: + if rated { + return []MessageAction{ActionCopy, ActionRegenerate, ActionLike, ActionDislike, ActionSpeak, ActionShare} + } + return []MessageAction{ActionCopy, ActionRegenerate, ActionSpeak, ActionShare} + case MessageSystem: + return []MessageAction{ActionCopy} + case MessageError: + return []MessageAction{ActionCopy, ActionRegenerate} + } + panic("mujica: unknown MessageRole") +} + +// MessageActions is a toolbar of the actions a role's message offers; arrows move between them. +func MessageActions(c *ui.Context, role MessageRole, opts MessageActionsOptions) MessageActionsResult { + var r MessageActionsResult + r.Element = ui.Row(c).Gap(Density(c).Unit()).AlignItems(ui.Center).FocusGroup(ui.Horizontal). + Role(ui.RoleToolbar).Label(msg(c, "message_actions.label")) + disabled := r.Element.IsDisabled() + r.Element.Children(func() { + for _, a := range messageActionsFor(role, opts.Feedback != nil) { + ic := messageActionIcons[a] + hit := false + if a == ActionLike || a == ActionDislike { + want := FeedbackLiked + if a == ActionDislike { + want = FeedbackDisliked + } + on := *opts.Feedback == want + if codeBlockToggle(c, ic[0], msg(c, ic[1]), &on) && !disabled { + hit = true + if on { + *opts.Feedback = want + } else { + *opts.Feedback = FeedbackNone + } + } + } else { + hit = iconAction(c, icons.Must(ic[0]), msg(c, ic[1])).Tooltip(msg(c, ic[1])).Clicked() && !disabled + } + if hit { + r.action = a + slog.Debug("mujica: message_actions action", "action", a) + } + } + }) + return r +} diff --git a/message_actions_test.go b/message_actions_test.go new file mode 100644 index 0000000..6c41739 --- /dev/null +++ b/message_actions_test.go @@ -0,0 +1,93 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestMessageActionsByRole(t *testing.T) { + for role, want := range map[MessageRole][]string{ + MessageUser: {"Copy", "Edit"}, + MessageAssistant: {"Copy", "Regenerate", "Good response", "Bad response", "Read aloud", "Share"}, + MessageSystem: {"Copy"}, + MessageError: {"Copy", "Regenerate"}, + } { + fb := FeedbackNone + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + MessageActions(c, role, MessageActionsOptions{Feedback: &fb}) + }, 400, 100) + for _, name := range want { + if _, ok := tt.Find(name); !ok { + t.Errorf("role %v: missing %q", role, name) + } + } + if _, ok := tt.Find("Edit"); ok != (role == MessageUser) { + t.Errorf("role %v: edit shown %v", role, ok) + } + } +} + +func TestMessageActionsChooseAndRate(t *testing.T) { + fb := FeedbackNone + var got []MessageAction + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if a, ok := MessageActions(c, MessageAssistant, MessageActionsOptions{Feedback: &fb}).Action(); ok { + got = append(got, a) + } + }, 400, 100) + _ = tt.Click("Regenerate") + _ = tt.Click("Good response") + if fb != FeedbackLiked { + t.Fatalf("feedback %v after like", fb) + } + _ = tt.Click("Bad response") + if fb != FeedbackDisliked { + t.Fatalf("feedback %v after dislike", fb) + } + _ = tt.Click("Bad response") + if fb != FeedbackNone { + t.Fatalf("feedback %v after undoing dislike", fb) + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyEnter) + // Tab returns to the last focused action, Dislike; Right moves to Read aloud. + want := []MessageAction{ActionRegenerate, ActionLike, ActionDislike, ActionDislike, ActionSpeak} + if len(got) != len(want) { + t.Fatalf("actions %v, want %v", got, want) + } + for i := range want { + if got[i] != want[i] { + t.Fatalf("actions %v, want %v", got, want) + } + } +} + +func TestMessageActionsHideRatingAndDisable(t *testing.T) { + n := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Disabled(true).Children(func() { + if _, ok := MessageActions(c, MessageAssistant, MessageActionsOptions{}).Action(); ok { + n++ + } + }) + }, 400, 100) + if _, ok := tt.Find("Good response"); ok { + t.Fatal("rating shown without Feedback") + } + _ = tt.Click("Copy") + if n != 0 { + t.Fatal("disabled actions fired") + } +} + +func TestMessageActionsSnapshot(t *testing.T) { + fb := FeedbackLiked + snapshot(t, "message_actions", 300, 70, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { MessageActions(c, MessageAssistant, MessageActionsOptions{Feedback: &fb}) }) + }) +} diff --git a/message_bubble.go b/message_bubble.go new file mode 100644 index 0000000..a4377ae --- /dev/null +++ b/message_bubble.go @@ -0,0 +1,115 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// MessageRole is who a chat message comes from. +type MessageRole int + +const ( + MessageUser MessageRole = iota + MessageAssistant + MessageSystem + MessageError +) + +func (r MessageRole) key() string { + switch r { + case MessageUser: + return "message_bubble.user" + case MessageAssistant: + return "message_bubble.assistant" + case MessageSystem: + return "message_bubble.system" + case MessageError: + return "message_bubble.error" + } + panic("mujica: unknown MessageRole") +} + +// MessageBubbleOptions configure a MessageBubble. +type MessageBubbleOptions struct { + // Name shows above the bubble; empty shows none. + Name string + // Avatar builds the picture beside the bubble. + Avatar func() + // MaxWidth caps the bubble in DIPs; zero means 560. + MaxWidth float32 +} + +// MessageBubble frames one chat message by role: users right, others left, system centered. +func MessageBubble(c *ui.Context, role MessageRole, opts MessageBubbleOptions, content func()) *ui.Element { + if opts.MaxWidth < 0 { + panic("mujica: MessageBubble MaxWidth must not be negative") + } + if content == nil { + panic("mujica: MessageBubble needs content") + } + maxW := opts.MaxWidth + if maxW == 0 { + maxW = 560 + } + k := Tokens(c) + u := Density(c).Unit() + label := msg(c, role.key()) + if opts.Name != "" { + label += ", " + opts.Name + } + row := ui.Row(c).Gap(u * 2).AlignItems(ui.Start).Role(ui.RoleGroup).Label(label) + switch role { + case MessageUser: + row.Justify(ui.End) + case MessageSystem: + row.Justify(ui.Center) + } + row.Children(func() { + if role == MessageSystem { + ui.Row(c).MaxWidth(maxW).Padding(u, u*3).Gap(u * 2).Radius(theme.ControlRadius). + Background(k.SurfaceHover).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)). + Children(content) + return + } + if opts.Avatar != nil && role != MessageUser { + opts.Avatar() + } + ui.Column(c).Gap(u).MaxWidth(maxW).Shrink(1).MinWidth(0).AlignItems(messageBubbleAlign(role)).Children(func() { + if opts.Name != "" { + ui.Text(c, opts.Name).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine() + } + b := ui.Column(c).Padding(u*2, u*3).Gap(u * 2).Radius(theme.CardRadius).MinWidth(0) + switch role { + case MessageUser: + b.Background(k.Selection) + case MessageError: + b.Background(k.Surface).Border(theme.BorderWidth, k.Danger) + default: + b.Background(k.Surface).Border(theme.BorderWidth, k.Border) + } + b.Children(func() { + if role != MessageError { + content() + return + } + ui.Row(c).Gap(u * 2).AlignItems(ui.Start).Children(func() { + ui.Icon(c, icons.Must("circle-alert")).Size(16, 16).Shrink(0).TextColor(k.Danger) + ui.Column(c).Gap(u * 2).Grow(1).MinWidth(0).Children(content) + }) + }) + }) + if opts.Avatar != nil && role == MessageUser { + opts.Avatar() + } + }) + return row +} + +func messageBubbleAlign(r MessageRole) ui.Align { + if r == MessageUser { + return ui.End + } + return ui.Start +} diff --git a/message_bubble_test.go b/message_bubble_test.go new file mode 100644 index 0000000..df5676c --- /dev/null +++ b/message_bubble_test.go @@ -0,0 +1,60 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestMessageBubbleRolesAlignAndLimit(t *testing.T) { + var user, bot, sys ui.Rect + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Width(600).Children(func() { + MessageBubble(c, MessageUser, MessageBubbleOptions{Name: "Ada", MaxWidth: 200}, func() { + user = ui.Text(c, "A long user message that must wrap inside the bubble's width limit.").Bounds() + }) + MessageBubble(c, MessageAssistant, MessageBubbleOptions{Avatar: func() { Avatar(c, "Bot", AvatarOptions{}) }}, func() { + bot = ui.Text(c, "Hello").Bounds() + }) + MessageBubble(c, MessageSystem, MessageBubbleOptions{}, func() { sys = ui.Text(c, "Joined").Bounds() }) + MessageBubble(c, MessageError, MessageBubbleOptions{}, func() { ui.Text(c, "Timeout") }) + }) + }, 600, 400) + tt.Frame() + if user.W > 200 || user.X < 300 { + t.Errorf("user bubble %+v not right-aligned within 200", user) + } + if bot.X > 100 || sys.X < 200 || sys.X > 300 { + t.Errorf("assistant at %v, system at %v", bot.X, sys.X) + } + for _, s := range []string{"Ada", "Bot", "Error"} { + if !tt.HasText(s) { + t.Errorf("missing %q", s) + } + } +} + +func TestMessageBubbleBadOptions(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic for a negative MaxWidth") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + MessageBubble(c, MessageUser, MessageBubbleOptions{MaxWidth: -1}, func() {}) + }, 100, 100) +} + +func TestMessageBubbleSnapshot(t *testing.T) { + snapshot(t, "message_bubble", 520, 300, func(c *ui.Context) { + ui.Column(c).Padding(16).Gap(12).Children(func() { + MessageBubble(c, MessageUser, MessageBubbleOptions{Name: "Marie"}, func() { ui.Text(c, "Is the ball tonight?") }) + MessageBubble(c, MessageAssistant, MessageBubbleOptions{Name: "Herald", Avatar: func() { Avatar(c, "Herald", AvatarOptions{}) }}, + func() { ui.Text(c, "Yes, at nine, in the Hall of Mirrors.") }) + MessageBubble(c, MessageSystem, MessageBubbleOptions{}, func() { ui.Text(c, "Herald joined the chat") }) + MessageBubble(c, MessageError, MessageBubbleOptions{}, func() { ui.Text(c, "The messenger did not return.") }) + }) + }) +} diff --git a/message_editor.go b/message_editor.go new file mode 100644 index 0000000..06439b5 --- /dev/null +++ b/message_editor.go @@ -0,0 +1,57 @@ +package mujica + +import ( + "log/slog" + "strings" + + "github.com/egoist/mygo/ui" +) + +// MessageEditorOptions configure a MessageEditor. +type MessageEditorOptions struct { + // Original is the sent text; saving it unchanged is not allowed. + Original string +} + +// MessageEditorResult is the editor's element and its outcome this frame. +type MessageEditorResult struct { + Element *ui.Element + saved, canceled bool +} + +// Saved reports a save; the caller makes a new branch from the draft. +func (r MessageEditorResult) Saved() bool { return r.saved } + +// Canceled reports Cancel or Escape. +func (r MessageEditorResult) Canceled() bool { return r.canceled } + +// MessageEditor edits a sent message in *draft; Cmd+Enter saves, Escape cancels. +func MessageEditor(c *ui.Context, draft *string, opts MessageEditorOptions) MessageEditorResult { + if draft == nil { + panic("mujica: MessageEditor needs a draft") + } + u := Density(c).Unit() + var r MessageEditorResult + r.Element = ui.Column(c).Gap(u * 2).MinWidth(0) + disabled := r.Element.IsDisabled() + r.Element.Children(func() { + area := TextArea(c, draft, TextAreaOptions{Label: msg(c, "message_editor.label"), MaxHeight: 240}) + ok := strings.TrimSpace(*draft) != "" && *draft != opts.Original + escape := area.Input.Shortcut(0, ui.KeyEscape) + ui.Row(c).Gap(u * 2).Justify(ui.End).Children(func() { + if Button(c, msg(c, "message_editor.cancel"), ButtonOptions{Variant: Secondary}).Clicked() || escape { + r.canceled = !disabled + } + if Button(c, msg(c, "message_editor.save"), ButtonOptions{Disabled: !ok}).Clicked() || area.Submitted() && ok { + r.saved = !disabled + } + }) + }) + if r.saved { + slog.Debug("mujica: message_editor save", "chars", len(*draft)) + } + if r.canceled { + slog.Debug("mujica: message_editor cancel") + } + return r +} diff --git a/message_editor_test.go b/message_editor_test.go new file mode 100644 index 0000000..1a75412 --- /dev/null +++ b/message_editor_test.go @@ -0,0 +1,62 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func messageEditorTester(draft *string, saves, cancels *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := MessageEditor(c, draft, MessageEditorOptions{Original: "Hello"}) + if r.Saved() { + *saves++ + } + if r.Canceled() { + *cancels++ + } + }, 400, 300) +} + +func TestMessageEditorSaveRules(t *testing.T) { + draft, saves, cancels := "Hello", 0, 0 + tt := messageEditorTester(&draft, &saves, &cancels) + _ = tt.Click("Save") + _ = tt.Click("Edit message") + tt.Key(ui.Cmd, ui.KeyEnter) + if saves != 0 { + t.Fatal("saved unchanged text") + } + tt.Type(" there") + tt.Key(ui.Cmd, ui.KeyEnter) + _ = tt.Click("Save") + if saves != 2 || draft != "Hello there" { + t.Fatalf("saves %d draft %q", saves, draft) + } + _ = tt.Click("Edit message") + tt.Command("selectAll") + tt.Type(" ") + _ = tt.Click("Save") + if saves != 2 { + t.Fatal("saved blank text") + } +} + +func TestMessageEditorCancel(t *testing.T) { + draft, saves, cancels := "Hello", 0, 0 + tt := messageEditorTester(&draft, &saves, &cancels) + _ = tt.Click("Cancel") + _ = tt.Click("Edit message") + tt.Key(0, ui.KeyEscape) + if cancels != 2 || saves != 0 { + t.Fatalf("cancels %d saves %d", cancels, saves) + } +} + +func TestMessageEditorSnapshot(t *testing.T) { + draft := "Could you seat the ambassador nearer the throne?" + snapshot(t, "message_editor", 420, 200, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { MessageEditor(c, &draft, MessageEditorOptions{Original: "Seat the ambassador."}) }) + }) +} diff --git a/message_header.go b/message_header.go new file mode 100644 index 0000000..f45adde --- /dev/null +++ b/message_header.go @@ -0,0 +1,70 @@ +package mujica + +import ( + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// MessageStatus is where a chat message is in its delivery. +type MessageStatus int + +const ( + // MessageNoStatus shows no status. + MessageNoStatus MessageStatus = iota + MessageSending + MessageStreaming + MessageSent + MessageFailed +) + +// MessageHeaderOptions configure a MessageHeader; zero fields are hidden. +type MessageHeaderOptions struct { + Model string + Time time.Time + Status MessageStatus +} + +// MessageHeader shows a message's model, time and status as icon and text. +func MessageHeader(c *ui.Context, opts MessageHeaderOptions) *ui.Element { + k := Tokens(c) + u := Density(c).Unit() + small := FontSize(c, theme.CaptionSize) + row := ui.Row(c).Gap(u * 2).AlignItems(ui.Center).FontSize(small).TextColor(k.TextMuted) + row.Children(func() { + if opts.Model != "" { + ui.Text(c, opts.Model).FontWeight(600).TextColor(k.Text).SingleLine() + } + if !opts.Time.IsZero() { + ui.Text(c, opts.Time.Format(msg(c, "message_header.time"))).FontFeatures("tnum").SingleLine() + } + if opts.Status == MessageNoStatus { + return + } + key, icon, color := "", "", k.TextMuted + switch opts.Status { + case MessageSending: + key, icon = "message_header.sending", "clock" + case MessageStreaming: + key = "message_header.streaming" + case MessageSent: + key, icon = "message_header.sent", "check" + case MessageFailed: + key, icon, color = "message_header.failed", "circle-alert", k.Danger + default: + panic("mujica: unknown MessageStatus") + } + ui.Row(c).Gap(u).AlignItems(ui.Center).TextColor(color).Children(func() { + if icon == "" { + Spinner(c, SpinnerOptions{Size: 12, Label: msg(c, key)}) + } else { + ui.Icon(c, icons.Must(icon)).Size(12, 12) + } + ui.Text(c, msg(c, key)).SingleLine() + }) + }) + return row +} diff --git a/message_header_test.go b/message_header_test.go new file mode 100644 index 0000000..61f95b6 --- /dev/null +++ b/message_header_test.go @@ -0,0 +1,55 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func TestMessageHeaderFieldsAndStatus(t *testing.T) { + at := time.Date(2026, 3, 1, 14, 5, 0, 0, time.UTC) + for status, want := range map[MessageStatus]string{ + MessageSending: "Sending", MessageStreaming: "Generating", MessageSent: "Sent", MessageFailed: "Failed", + } { + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{Locale: EnUS}) + MessageHeader(c, MessageHeaderOptions{Model: "claude", Time: at, Status: status}) + }, 400, 100) + for _, s := range []string{"claude", "14:05", want} { + if !tt.HasText(s) { + t.Errorf("status %v: missing %q in %q", status, s, tt.Texts()) + } + } + } + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + MessageHeader(c, MessageHeaderOptions{}) + }, 400, 100) + if len(tt.Texts()) != 0 { + t.Fatalf("zero header shows %q", tt.Texts()) + } +} + +func TestMessageHeaderUnknownStatus(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic for an unknown status") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + MessageHeader(c, MessageHeaderOptions{Status: 99}) + }, 100, 100) +} + +func TestMessageHeaderSnapshot(t *testing.T) { + at := time.Date(2026, 3, 1, 21, 30, 0, 0, time.UTC) + snapshot(t, "message_header", 360, 150, func(c *ui.Context) { + ui.Column(c).Padding(16).Gap(12).Children(func() { + for _, s := range []MessageStatus{MessageSending, MessageStreaming, MessageSent, MessageFailed} { + MessageHeader(c, MessageHeaderOptions{Model: "herald-2", Time: at, Status: s}) + } + }) + }) +} diff --git a/message_list.go b/message_list.go new file mode 100644 index 0000000..fc5bf1c --- /dev/null +++ b/message_list.go @@ -0,0 +1,108 @@ +package mujica + +import ( + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// MessageListState keeps a MessageList's place and what the user has seen. +type MessageListState struct { + list ui.ListState + seen int + started bool +} + +// ScrollToEnd shows the newest message and follows new ones again. +func (s *MessageListState) ScrollToEnd() { s.list.ScrollToEnd() } + +// AtEnd reports whether the newest message is in view. +func (s *MessageListState) AtEnd() bool { return s.list.AtEnd() } + +// MessageListOptions configure a MessageList. +type MessageListOptions struct { + // ID returns message i's stable identity; required. + ID func(i int) string + // Date returns message i's time; set, a separator heads each new day. + Date func(i int) time.Time + // Label returns message i's text for assistive technology and typing to find. + Label func(i int) string +} + +// MessageListResult is a MessageList's element and its unread count. +type MessageListResult struct { + Element *ui.Element + unread int +} + +// Unread returns how many messages arrived since the user scrolled away from the end. +func (r MessageListResult) Unread() int { return r.unread } + +// MessageList shows n messages, building only those in view, and follows the end until the user scrolls up. +func MessageList(c *ui.Context, s *MessageListState, n int, opts MessageListOptions, row func(i int)) MessageListResult { + if opts.ID == nil || row == nil { + panic("mujica: MessageList needs ID and row") + } + if n < 0 { + panic("mujica: MessageList with negative message count") + } + u := Density(c).Unit() + s.list.Key = func(i int) any { return opts.ID(i) } + s.list.Label = opts.Label + s.list.FollowEnd = true + at := !s.started || s.list.AtEnd() + if at || n < s.seen { + s.seen = n + } + s.started = true + r := MessageListResult{unread: n - s.seen} + r.Element = ui.Box(c).Grow(1).MinHeight(0) + r.Element.Children(func() { + ui.List(c, &s.list, n, func(i int) { + ui.Column(c).Padding(u*2, u*4).Gap(u * 2).Children(func() { + if opts.Date != nil && (i == 0 || !messageListSameDay(opts.Date(i-1), opts.Date(i))) { + messageListDay(c, opts.Date(i)) + } + row(i) + }) + }).Fill().Justify(ui.End).Label(msg(c, "message_list.label")) + jump := ScrollToBottomButton(c, !at, r.unread) + if jump.Clicked() && !r.Element.IsDisabled() { + s.list.ScrollToEnd() + s.seen = n + slog.Debug("mujica: message_list jump", "unread", r.unread) + } + }) + return r +} + +func messageListSameDay(a, b time.Time) bool { + ay, am, ad := a.Date() + by, bm, bd := b.Date() + return ay == by && am == bm && ad == bd +} + +// messageListDay is a separator naming the day: today, yesterday or the date. +func messageListDay(c *ui.Context, t time.Time) { + k := Tokens(c) + u := Density(c).Unit() + label := t.Format(msg(c, "message_list.date")) + now := c.Now().In(t.Location()) + switch { + case messageListSameDay(t, now): + label = msg(c, "message_list.today") + case messageListSameDay(t, now.AddDate(0, 0, -1)): + label = msg(c, "message_list.yesterday") + } + ui.Row(c).Gap(u*3).AlignItems(ui.Center).Padding(u*2, 0).Role(ui.RoleText).Label(label).Children(func() { + rule := func() { + ui.Box(c).Grow(1).Height(theme.BorderWidth).Background(k.Border) + } + rule() + ui.Text(c, label).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine() + rule() + }) +} diff --git a/message_list_test.go b/message_list_test.go new file mode 100644 index 0000000..5aaf0a4 --- /dev/null +++ b/message_list_test.go @@ -0,0 +1,127 @@ +package mujica + +import ( + "fmt" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +// messageListApp is a chat of n messages with stable IDs. +type messageListApp struct { + ids []string + state MessageListState + built int + res MessageListResult +} + +func newMessageListApp(n int) *messageListApp { + a := &messageListApp{} + for i := range n { + a.ids = append(a.ids, fmt.Sprintf("m%d", i)) + } + return a +} + +func (a *messageListApp) view(c *ui.Context) { + Use(c, Settings{}) + a.built = 0 + day := time.Date(2026, 3, 1, 9, 0, 0, 0, time.UTC) + a.res = MessageList(c, &a.state, len(a.ids), MessageListOptions{ + ID: func(i int) string { return a.ids[i] }, + Date: func(i int) time.Time { return day.Add(time.Duration(i/3) * 24 * time.Hour) }, + }, func(i int) { + a.built++ + ui.Text(c, "Message "+a.ids[i]).Padding(8) + }) +} + +func TestMessageListVirtualizedAndFollowsEnd(t *testing.T) { + a := newMessageListApp(100000) + tt := ui.NewTester(a.view, 400, 300) + tt.Frame() + if a.built == 0 || a.built > 60 { + t.Fatalf("built %d rows of 100000", a.built) + } + if !tt.HasText("Message m99999") || !a.state.AtEnd() { + t.Fatal("list did not start at the newest message") + } + a.ids = append(a.ids, "m100000") + tt.Frame() + tt.Frame() + if !tt.HasText("Message m100000") || a.res.Unread() != 0 { + t.Fatalf("new message not followed, unread %d", a.res.Unread()) + } +} + +func TestMessageListStopsFollowingAndCountsUnread(t *testing.T) { + a := newMessageListApp(50) + tt := ui.NewTester(a.view, 400, 300) + tt.Frame() + tt.Scroll(200, 150, 0, -2000) + tt.Frame() + if a.state.AtEnd() { + t.Fatal("still at end after scrolling up") + } + a.ids = append(a.ids, "n1", "n2") + tt.Frame() + tt.Frame() + if tt.HasText("Message n2") || a.res.Unread() != 2 { + t.Fatalf("followed while scrolled up, unread %d", a.res.Unread()) + } + if err := tt.Click("Scroll to latest, 2 new"); err != nil { + t.Fatal(err) + } + tt.Frame() + tt.Frame() + if !tt.HasText("Message n2") || a.res.Unread() != 0 { + t.Fatalf("jump did not reach the end, unread %d", a.res.Unread()) + } +} + +func TestMessageListKeepsPlaceByID(t *testing.T) { + a := newMessageListApp(50) + tt := ui.NewTester(a.view, 400, 300) + tt.Frame() + tt.Scroll(200, 150, 0, -600) + tt.Frame() + r, _ := tt.Find("Message m40") + // Older messages load above; the one in view stays put. + a.ids = append([]string{"old1", "old2", "old3"}, a.ids...) + tt.Frame() + r2, ok := tt.Find("Message m40") + if !ok || r2.Y != r.Y { + t.Fatalf("m40 moved from %v to %v (found %v)", r.Y, r2.Y, ok) + } +} + +func TestMessageListDaySeparators(t *testing.T) { + a := newMessageListApp(6) + tt := ui.NewTester(a.view, 400, 600) + tt.Frame() + for _, d := range []string{"Mar 1, 2026", "Mar 2, 2026"} { + if !tt.HasText(d) { + t.Errorf("missing separator %q in %q", d, tt.Texts()) + } + } +} + +func TestMessageListNeedsID(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic without ID") + } + }() + var s MessageListState + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + MessageList(c, &s, 1, MessageListOptions{}, func(int) {}) + }, 200, 100) +} + +func TestMessageListSnapshot(t *testing.T) { + snapshot(t, "message_list", 420, 320, func(c *ui.Context) { + (*ui.Local(c.Root(), "app", func() *messageListApp { return newMessageListApp(6) })).view(c) + }) +} diff --git a/messages_chatmsg.go b/messages_chatmsg.go new file mode 100644 index 0000000..2ebff69 --- /dev/null +++ b/messages_chatmsg.go @@ -0,0 +1,57 @@ +package mujica + +func init() { + addMessages(map[string][2]string{ + "message_bubble.user": {"You", "你"}, + "message_bubble.assistant": {"Assistant", "助手"}, + "message_bubble.system": {"System", "系统"}, + "message_bubble.error": {"Error", "错误"}, + "message_header.time": {"15:04", "15:04"}, + "message_header.sending": {"Sending", "发送中"}, + "message_header.streaming": {"Generating", "生成中"}, + "message_header.sent": {"Sent", "已发送"}, + "message_header.failed": {"Failed", "失败"}, + "message_list.label": {"Messages", "消息"}, + "message_list.date": {"Jan 2, 2006", "2006年1月2日"}, + "message_list.today": {"Today", "今天"}, + "message_list.yesterday": {"Yesterday", "昨天"}, + "scroll_to_bottom_button.label": {"Scroll to latest", "回到最新"}, + "scroll_to_bottom_button.unread": {"Scroll to latest, %d new", "回到最新,%d 条新消息"}, + "code_block.plain": {"text", "文本"}, + "code_block.wrap": {"Wrap lines", "自动换行"}, + "code_block.copy": {"Copy code", "复制代码"}, + "code_block.copied": {"Copied", "已复制"}, + "code_block.collapse": {"Collapse", "折叠"}, + "code_block.expand": {"Show %d lines", "展开 %d 行"}, + "table_block.title": {"Table", "表格"}, + "table_block.copy": {"Copy as TSV", "复制为 TSV"}, + "file_message.open": {"Open %s, %s", "打开 %s,%s"}, + "file_message.download": {"Download %s", "下载 %s"}, + "file_message.bytes": {"%d B", "%d 字节"}, + "audio_message.play": {"Play", "播放"}, + "audio_message.pause": {"Pause", "暂停"}, + "audio_message.seek": {"Playback position", "播放位置"}, + "quote_reply.label": {"Reply to %s: %s", "回复 %s:%s"}, + "message_actions.label": {"Message actions", "消息操作"}, + "message_actions.copy": {"Copy", "复制"}, + "message_actions.regenerate": {"Regenerate", "重新生成"}, + "message_actions.edit": {"Edit", "编辑"}, + "message_actions.like": {"Good response", "赞"}, + "message_actions.dislike": {"Bad response", "踩"}, + "message_actions.speak": {"Read aloud", "朗读"}, + "message_actions.share": {"Share", "分享"}, + "message_editor.label": {"Edit message", "编辑消息"}, + "message_editor.cancel": {"Cancel", "取消"}, + "message_editor.save": {"Save", "保存"}, + "branch_navigator.label": {"Branch %d of %d", "第 %d 个分支,共 %d 个"}, + "branch_navigator.previous": {"Previous branch", "上一个分支"}, + "branch_navigator.next": {"Next branch", "下一个分支"}, + "error_message.title": {"Something went wrong", "出错了"}, + "error_message.retry": {"Retry", "重试"}, + "error_message.wait": {"Retry in %d s", "%d 秒后重试"}, + "error_message.limited": {"Rate limited", "已限流"}, + "thinking_block.done": {"Thought for %d s", "思考了 %d 秒"}, + "thinking_block.thinking": {"Thinking… %d s", "思考中… %d 秒"}, + "typing_indicator.label": {"%s is typing…", "%s 正在输入…"}, + }) +} diff --git a/quote_reply.go b/quote_reply.go new file mode 100644 index 0000000..ad82de1 --- /dev/null +++ b/quote_reply.go @@ -0,0 +1,33 @@ +package mujica + +import ( + "fmt" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// QuoteReply shows the author and a one-line excerpt of a quoted message; Clicked jumps to it. +func QuoteReply(c *ui.Context, author, excerpt string) *ui.Element { + if author == "" { + panic("mujica: QuoteReply needs an author") + } + k := Tokens(c) + u := Density(c).Unit() + line := strings.Join(strings.Fields(excerpt), " ") + b := ui.ButtonBase(c).MinHeight(theme.MinHitSize).MaxWidth(420).Gap(u*2).Padding(u, u*3, u, u*2).Justify(ui.Start). + Radius(theme.ControlRadius).Background(k.SurfaceHover).BorderWidth(0, 0, 0, 3).BorderColor(k.AccentText). + Label(fmt.Sprintf(msg(c, "quote_reply.label"), author, line)).Transition(colorFade) + internal.Ring(b, k.Focus, theme.ControlRadius) + if b.Hovered() { + b.Background(k.Selection) + } + b.Children(func() { + ui.Text(c, author).FontWeight(600).FontSize(FontSize(c, theme.CaptionSize)).SingleLine().Shrink(0) + ui.Text(c, line).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine().MinWidth(0).Shrink(1) + }) + return b +} diff --git a/quote_reply_test.go b/quote_reply_test.go new file mode 100644 index 0000000..b9aa5b5 --- /dev/null +++ b/quote_reply_test.go @@ -0,0 +1,53 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestQuoteReplyJumpsAndFlattensExcerpt(t *testing.T) { + jumps, off := 0, false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Disabled(off).Children(func() { + if QuoteReply(c, "Marie", "Let them\n eat cake.").Clicked() { + jumps++ + } + }) + }, 400, 200) + if !tt.HasText("Let them eat cake.") { + t.Fatalf("excerpt %q", tt.Texts()) + } + _ = tt.Click("Reply to Marie: Let them eat cake.") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeySpace) + if jumps != 2 { + t.Fatalf("jumps %d", jumps) + } + off = true + _ = tt.Click("Reply to Marie: Let them eat cake.") + if jumps != 2 { + t.Fatal("disabled quote jumped") + } +} + +func TestQuoteReplyNeedsAuthor(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic without an author") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + QuoteReply(c, "", "x") + }, 100, 100) +} + +func TestQuoteReplySnapshot(t *testing.T) { + snapshot(t, "quote_reply", 420, 70, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + QuoteReply(c, "Herald", "The ball begins at nine in the Hall of Mirrors, and every guest must arrive by the east door.") + }) + }) +} diff --git a/scroll_to_bottom_button.go b/scroll_to_bottom_button.go new file mode 100644 index 0000000..19ac548 --- /dev/null +++ b/scroll_to_bottom_button.go @@ -0,0 +1,47 @@ +package mujica + +import ( + "fmt" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// ScrollToBottomButton shows while away is true, with the unread count; click it to return to the end. +// While hidden it returns an empty element whose Clicked is false. +func ScrollToBottomButton(c *ui.Context, away bool, unread int) *ui.Element { + if unread < 0 { + panic("mujica: ScrollToBottomButton unread must not be negative") + } + if !away { + return ui.Box(c).Absolute().Invisible() + } + k := Tokens(c) + u := Density(c).Unit() + label := msg(c, "scroll_to_bottom_button.label") + if unread > 0 { + label = fmt.Sprintf(msg(c, "scroll_to_bottom_button.unread"), unread) + } + wrap := ui.Row(c).Absolute().Left(0).Right(0).Bottom(u * 3).Justify(ui.Center).PassThrough() + var b *ui.Element + wrap.Children(func() { + b = ui.ButtonBase(c).MinHeight(theme.MinHitSize).MinWidth(theme.MinHitSize).Padding(0, u*3).Gap(u*2). + Radius(theme.MinHitSize/2).Label(label).Background(k.Surface).Border(theme.BorderWidth, k.ControlBorder). + TextColor(k.Text).Shadow(0, 2, 8, 0, ui.RGBA(0, 0, 0, 0.14)).Transition(colorFade) + b.Opacity(overlayEnter(c, b)) + internal.Ring(b, k.Focus, theme.MinHitSize/2) + if b.Hovered() { + b.Background(k.SurfaceHover) + } + b.Children(func() { + ui.Icon(c, icons.Must("arrow-down")).Size(16, 16) + if unread > 0 { + ui.Text(c, fmt.Sprint(unread)).FontFeatures("tnum").FontWeight(600).TextColor(k.AccentText).SingleLine() + } + }) + }) + return b +} diff --git a/scroll_to_bottom_button_test.go b/scroll_to_bottom_button_test.go new file mode 100644 index 0000000..2ea4271 --- /dev/null +++ b/scroll_to_bottom_button_test.go @@ -0,0 +1,51 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestScrollToBottomButtonShowsWhenAway(t *testing.T) { + away, unread, clicks := false, 0, 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Box(c).Fill().Children(func() { + if ScrollToBottomButton(c, away, unread).Clicked() { + clicks++ + } + }) + }, 300, 200) + if _, ok := tt.Find("Scroll to latest"); ok { + t.Fatal("shown while at the bottom") + } + away, unread = true, 4 + tt.Frame() + if !tt.HasText("4") { + t.Fatalf("unread count missing: %q", tt.Texts()) + } + _ = tt.Click("Scroll to latest, 4 new") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if clicks != 2 { + t.Fatalf("clicks %d", clicks) + } +} + +func TestScrollToBottomButtonNegativeUnread(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic for negative unread") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ScrollToBottomButton(c, true, -1) + }, 100, 100) +} + +func TestScrollToBottomButtonSnapshot(t *testing.T) { + snapshot(t, "scroll_to_bottom_button", 240, 80, func(c *ui.Context) { + ui.Box(c).Fill().Children(func() { ScrollToBottomButton(c, true, 12) }) + }) +} diff --git a/streaming_text.go b/streaming_text.go new file mode 100644 index 0000000..8c658f4 --- /dev/null +++ b/streaming_text.go @@ -0,0 +1,77 @@ +package mujica + +import ( + "strings" + "time" + "unicode/utf8" + + "github.com/egoist/mygo/ui" +) + +// StreamingTextOptions configure a StreamingText. +type StreamingTextOptions struct { + // Streaming shows the cursor after the text while more is coming. + Streaming bool + // Smooth reveals new text gradually instead of at once. + Smooth bool + // Rate is the smooth reveal speed in characters per second; zero means 80. + Rate float64 +} + +// streamingState is how much of the text shows, and since when. +type streamingState struct { + text string + shown float64 + at time.Time +} + +// StreamingText shows text that grows as it streams; reduced motion shows it at once. +func StreamingText(c *ui.Context, text string, opts StreamingTextOptions) *ui.Element { + if opts.Rate < 0 { + panic("mujica: StreamingText Rate must not be negative") + } + rate := opts.Rate + if rate == 0 { + rate = 80 + } + k := Tokens(c) + e := ui.Box(c).Label(text) + st := ui.Local(e, "stream", func() streamingState { + return streamingState{text: text, shown: float64(utf8.RuneCountInString(text)), at: c.Now()} + }) + total := float64(utf8.RuneCountInString(text)) + if !strings.HasPrefix(text, st.text) { + // Replaced text starts over from what it shares. + st.shown = min(st.shown, float64(utf8.RuneCountInString(streamingCommon(st.text, text)))) + } + st.text = text + now := c.Now() + if !opts.Smooth || Motion(c, time.Second) == 0 { + st.shown = total + } else if st.shown < total { + st.shown = min(total, st.shown+now.Sub(st.at).Seconds()*rate) + c.AnimationFrame() + } + st.at = now + shown := text + if n := int(st.shown); n < int(total) { + shown = string([]rune(text)[:n]) + } + spans := []ui.Span{{Text: shown}} + if opts.Streaming { + spans = append(spans, ui.Span{Text: "▍", Color: k.AccentText}) + } + return e.Children(func() { ui.RichText(c, spans...) }) +} + +// streamingCommon returns the longest common prefix of a and b, on rune boundaries. +func streamingCommon(a, b string) string { + n := 0 + for n < len(a) && n < len(b) && a[n] == b[n] { + n++ + } + for n > 0 && n < len(a) && !utf8.RuneStart(a[n]) { + n-- + } + return a[:n] +} diff --git a/streaming_text_test.go b/streaming_text_test.go new file mode 100644 index 0000000..a8499d3 --- /dev/null +++ b/streaming_text_test.go @@ -0,0 +1,80 @@ +package mujica + +import ( + "strings" + "testing" + + "github.com/egoist/mygo/ui" +) + +func streamingTester(text *string, opts StreamingTextOptions, reduce bool) *ui.Tester { + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + StreamingText(c, *text, opts) + }, 400, 200) + tt.SetPreferences(ui.Preferences{ReduceMotion: reduce, TextScale: 1}) + tt.Frame() + return tt +} + +// streamingShown returns the visible text of the stream. +func streamingShown(tt *ui.Tester) string { + texts := tt.Texts() + return texts[len(texts)-1] +} + +func TestStreamingTextSmoothReveal(t *testing.T) { + text := "Hello" + tt := streamingTester(&text, StreamingTextOptions{Smooth: true, Streaming: true, Rate: 1}, false) + if !strings.HasPrefix(streamingShown(tt), "Hello") || !strings.HasSuffix(streamingShown(tt), "▍") { + t.Fatalf("first text %q", streamingShown(tt)) + } + text += ", court" + tt.Frame() + if s := streamingShown(tt); strings.Contains(s, "court") { + t.Fatalf("1 char/s revealed %q at once", s) + } +} + +func TestStreamingTextInstantAndReducedMotion(t *testing.T) { + for _, tc := range []struct { + opts StreamingTextOptions + reduce bool + }{{StreamingTextOptions{}, false}, {StreamingTextOptions{Smooth: true, Rate: 1}, true}} { + text := "Hello" + tt := streamingTester(&text, tc.opts, tc.reduce) + text += ", court" + tt.Frame() + if s := streamingShown(tt); s != "Hello, court" { + t.Errorf("%+v reduce %v: shows %q", tc.opts, tc.reduce, s) + } + } +} + +func TestStreamingTextReplacedRestarts(t *testing.T) { + text := "abcdef" + tt := streamingTester(&text, StreamingTextOptions{Smooth: true, Rate: 1}, false) + text = "abXYZ" + tt.Frame() + if s := streamingShown(tt); s != "ab" { + t.Fatalf("replaced text shows %q, want the shared prefix", s) + } +} + +func TestStreamingTextNegativeRate(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic for a negative rate") + } + }() + text := "" + streamingTester(&text, StreamingTextOptions{Rate: -1}, false) +} + +func TestStreamingTextSnapshot(t *testing.T) { + snapshot(t, "streaming_text", 360, 90, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + StreamingText(c, "The herald reads the decree, word by word", StreamingTextOptions{Streaming: true, Smooth: true}) + }) + }) +} diff --git a/table_block.go b/table_block.go new file mode 100644 index 0000000..55ccfc7 --- /dev/null +++ b/table_block.go @@ -0,0 +1,125 @@ +package mujica + +import ( + "log/slog" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// TableBlockOptions configure a TableBlock. +type TableBlockOptions struct { + // Align sets each column's alignment: ui.Start, ui.Center or ui.End; missing columns start. + Align []ui.Align +} + +// TableBlock shows a small table inside a message; it scrolls sideways and copies as TSV. +func TableBlock(c *ui.Context, header []string, rows [][]string, opts TableBlockOptions) CopyResult { + n := len(header) + if n == 0 { + panic("mujica: TableBlock needs a header") + } + if len(opts.Align) > n { + panic("mujica: TableBlock has more alignments than columns") + } + for _, row := range rows { + if len(row) != n { + panic("mujica: TableBlock row width differs from the header") + } + } + k := Tokens(c) + u := Density(c).Unit() + var r CopyResult + r.Element = ui.Column(c).Radius(theme.CardRadius).Border(theme.BorderWidth, k.Border).Background(k.Surface).Clip().MinWidth(0) + copiedAt := ui.Local(r.Element, "copied", func() time.Time { return time.Time{} }) + r.Element.Children(func() { + ui.Row(c).Padding(0, u, 0, u*3).AlignItems(ui.Center).Background(k.SurfaceHover).Children(func() { + ui.Text(c, msg(c, "table_block.title")).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Grow(1) + icon, name := "copy", msg(c, "table_block.copy") + if left := codeBlockCopiedFor - c.Now().Sub(*copiedAt); left > 0 { + icon, name = "check", msg(c, "code_block.copied") + c.After(left) + } + if iconAction(c, icons.Must(icon), name).Clicked() && !r.Element.IsDisabled() { + c.WriteClipboard(tableBlockTSV(header, rows)) + *copiedAt, r.copied = c.Now(), true + c.Announce(msg(c, "code_block.copied")) + slog.Debug("mujica: table_block copy", "rows", len(rows)) + } + }) + tracks := make([]ui.Track, n) + for i := range tracks { + tracks[i] = ui.FitContent() + } + sc := ui.ScrollHorizontal(c).AlignItems(ui.Start) + // Rows span the block: the grid is at least last frame's scroll width. + w := sc.Bounds().W + internal.Remeasure(c, sc, w, sc.Bounds().H) + sc.Children(func() { + ui.Grid(c).ColumnTracks(tracks...).MinWidth(w).Children(func() { + for i, h := range header { + tableBlockCell(c, h, tableBlockAlign(opts.Align, i), true, false) + } + for ri, row := range rows { + for i, cell := range row { + tableBlockCell(c, cell, tableBlockAlign(opts.Align, i), false, ri == len(rows)-1) + } + } + }) + }) + }) + return r +} + +func tableBlockAlign(a []ui.Align, i int) ui.Align { + if i < len(a) { + return a[i] + } + return ui.Start +} + +func tableBlockCell(c *ui.Context, s string, align ui.Align, head, last bool) { + k := Tokens(c) + u := Density(c).Unit() + cell := ui.Box(c).Padding(u*2, u*3).Role(ui.RoleCell) + if !last { + cell.BorderWidth(0, 0, theme.BorderWidth, 0).BorderColor(k.Border) + } + if head { + cell.Role(ui.RoleColumnHeader) + } + cell.Children(func() { + t := ui.Text(c, tableBlockClean.Replace(s)).NoWrap().TextAlign(align) + if head { + t.FontWeight(600) + } + }) +} + +// tableBlockClean turns a cell's tabs and newlines into spaces. +var tableBlockClean = strings.NewReplacer("\t", " ", "\r\n", " ", "\n", " ") + +// tableBlockTSV joins cells with tabs and rows with newlines. +func tableBlockTSV(header []string, rows [][]string) string { + clean := tableBlockClean + var b strings.Builder + line := func(cells []string) { + for i, s := range cells { + if i > 0 { + b.WriteByte('\t') + } + b.WriteString(clean.Replace(s)) + } + b.WriteByte('\n') + } + line(header) + for _, row := range rows { + line(row) + } + return b.String() +} diff --git a/table_block_test.go b/table_block_test.go new file mode 100644 index 0000000..c5bc804 --- /dev/null +++ b/table_block_test.go @@ -0,0 +1,58 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +var ( + tableBlockHeader = []string{"Guest", "Title", "Seat"} + tableBlockRows = [][]string{{"Marie", "Queen", "1"}, {"Louis", "King", "2"}, {"Axel", "Count\tof Fersen", "14"}} +) + +func TestTableBlockCopiesTSVAndScrolls(t *testing.T) { + copies := 0 + var w float32 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Width(160).Children(func() { + r := TableBlock(c, tableBlockHeader, tableBlockRows, TableBlockOptions{Align: []ui.Align{ui.Start, ui.Start, ui.End}}) + w = r.Element.Bounds().W + if r.Copied() { + copies++ + } + }) + }, 400, 300) + tt.Frame() + if w > 160 { + t.Fatalf("table widened its message to %v", w) + } + if err := tt.Click("Copy as TSV"); err != nil { + t.Fatal(err) + } + want := "Guest\tTitle\tSeat\nMarie\tQueen\t1\nLouis\tKing\t2\nAxel\tCount of Fersen\t14\n" + if tt.Clipboard() != want || copies != 1 { + t.Fatalf("copies %d clipboard %q", copies, tt.Clipboard()) + } +} + +func TestTableBlockBadRows(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic for a short row") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + TableBlock(c, []string{"a", "b"}, [][]string{{"1"}}, TableBlockOptions{}) + }, 100, 100) +} + +func TestTableBlockSnapshot(t *testing.T) { + snapshot(t, "table_block", 400, 220, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + TableBlock(c, tableBlockHeader, tableBlockRows, TableBlockOptions{Align: []ui.Align{ui.Start, ui.Start, ui.End}}) + }) + }) +} diff --git a/testdata/snapshots/darwin/audio_message-dark.png b/testdata/snapshots/darwin/audio_message-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..f9872223db295fba05b9341ce16d1bc030039c41 GIT binary patch literal 2809 zcmc&$`8U*!8vj~ujY=a#DQmWDg=C4D67SdsL)o{+p6t6aLo`Zut2ANS_ zZe@nDR3suhV=QA|X0G@B6Ye?p+;g7uJfB~l^XyBiwIz)InAkA@0QgN!jBEga>((K* z25}$qPaQ==QVVhR|A$E}68#6O_#gWWzD=#2B8nuzh2pkBz7t=u@}b!E_A zs|L9^NY}Xv*DU;DI#T+nvFb_5{G6ZAhd2I#gQ;RAeM+fc{EE3wmm#cqjmE&Z`(ai? z*WQGyC@;QOzki;wx*dCU~!h&(Kw;5Y9w$YV>Km#PZ8RUTPxZBUkh-` zzKr~Kf=%rsJj~4SW|xdQ*L4A27U-eW%@f85VPIaiCW`p2^gA(~exZ$4m#vJHxo!8> z)pJnSwU()!oRp-MZY+RxP{f;dcxEdBXOuYc5C#qpb6Se3`E*^c&<~Q2n*oz|)~9~W z%QnelzTUy%l?g#()4AB>{8v8ZNm3wmR7Z4oP8S{)vUw<+aHlklLlmAM8JCmRJ{Gcx3EJW2P|&X!asi+~Rm0Yci6J zh%A((73FU+?#auTNSzu7LoP#OvL&ZsJFxQox8Y<)_ozm5x>O0bK4Y2lCxZIW*x0qjiLQQ__V&+fLcEz2uRA}DwnVwEYLRD7yKn1%r!CB6QN z^urQCXizOJU4{Gpf$Ee(tx%nOGXN!~6Q3*~CnmmmRTZK0-shKnf(| zBBSoCVv(X?Ra)lPs8={PUT=>ztkpg-JiGJ@0UkRdthaSw4D)L~p~ztH zdt;G{Gf%P<;EcJswwSV&^_JuG3zU!EuYYcko)_R-!PeJ2LpsqbJ>2F&+c703*W*$*3i`rNz(+ z=Gm6y;In7;vX;*q-><4?O4dyE9c2RmBt@n??yq`tZa};_Fe~5uz+8&!Bz^UL8EOi zr|cXNp{Ad+6iBnstyiNH0-!kN=Mf5Lyd<~R?X{FN3QwEvFpqb;v=Q1upHaoh-RjE} zx`n{d9^eU??2fjUpR5e2Oe`D@hs3iD!)brfjK3?B0-h7J#DNaEJ3^ic*koRwccnvl zb?ubat#>fGB@<8cR?8(-Hg^t=xy2mF1BzZ6Gw&sAvc9U;h>?1FBi=PClA@g=NygPpkoY5W##O?4r-`IR~45yX$2M*$^v;mddj03 zl=Q0CgSv>zOyt$Xq)YTHns-HSe0?PAkMg?QSH{Ox?34|DzSwu0UM{Y@;rj{@p7xYD zCLFdE5m@gqKmP++A7{d>G3j^wHKZS~Yiqi|TW_)spU}cpC=iorX z_-xS(qS_7Pa*>r#pcf0Fn^Nn4J^oifU98LRBiEsk#T>Oyeyra zZfvEeuV;*Vz+fpFhSFJPT26r>AzymQ=t4RDtvc(kZ-jwvzv#b z&v3KNpw0M}N?zM2O0d`~u|T2I9%uZ$4W2^g+Jt>}FUpE$woRYnpY~*eiK7TRw|eC8 zZ;>bRs*W|5kDyt(U_g&TZCj((k1o2uAXNo8Ja5uD9Qf*m{Igb2-5aOlspEq8O9rQm zaQ>2j+47k4LH}zl-Cki9viRE6DhEyr(AcAYv-UBt(D`%G~{W*ov_` zq6A}h(vpukBBA^sRF?D3aI=R!zBGsFHFtN{&Pnp}mAnIf-dIQp#Evh-44 zgL?iC9BOx`^%+f5vw!2r zk%M-fNkb*G+uC)X1XHdkzUjt^_Ij!k>coKh2vJ6y;T0xe#_XVS}~qn96B zf2_GW0x0Y(`Ov<(vvd5pOz|8@)Y?j_?YcNhf)w9}$P6PiF4Mt4mmE0=WnZ0cJ-2=Y zN728#Ma5X~HgxSSY?AZ74dFR%w>JoF4|XvIHWBx9wM-BSd8&4CJ1;J|y1Gh`d7h++sqI`$(o0Ohbq7yVL4qa^*d~{Hopb`8U>yT~YGAo{)u1R((SOK3 zfm;7q3Z#^v37wbiGSqh*-}B-+JNtzOFe)f##{{13spqwW9z literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/audio_message-light.png b/testdata/snapshots/darwin/audio_message-light.png new file mode 100644 index 0000000000000000000000000000000000000000..8c92e8e54d205eece0f09e384f22c7de7904f282 GIT binary patch literal 2802 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 C*BDO# literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/chat_container-dark.png b/testdata/snapshots/darwin/chat_container-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..850e4c245b1f2f211c747904955d1ae88af4a189 GIT binary patch literal 11397 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 JyR`Yoe*>m2$I<`* literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/chat_container-light.png b/testdata/snapshots/darwin/chat_container-light.png new file mode 100644 index 0000000000000000000000000000000000000000..503f7a37e5c1ac63c25f77da169b4806a67f15d3 GIT binary patch literal 10862 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 WmpTdpm+e0e+{j8QNmPlM1pf!KMwUMS literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/code_block-dark.png b/testdata/snapshots/darwin/code_block-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..6c41a3580c96c9e2cd87fd4303913d9c9dfd642d GIT binary patch literal 11803 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 bZ2~aWY{Igd7@c{I20%_)S*ljTB=|o7NsSzf literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/error_message-dark.png b/testdata/snapshots/darwin/error_message-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..ba389db18399f1225a960d4b52f09eb1c7263dce GIT binary patch literal 13200 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/error_message-light.png b/testdata/snapshots/darwin/error_message-light.png new file mode 100644 index 0000000000000000000000000000000000000000..04a134487a8d32625cc5e62ebdfee0c24ec64c2a GIT binary patch literal 12731 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/file_message-dark.png b/testdata/snapshots/darwin/file_message-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..f3438b91e8045c965f48e2d53fbc2e9a9cc9df47 GIT binary patch literal 8517 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/image_grid-light.png b/testdata/snapshots/darwin/image_grid-light.png new file mode 100644 index 0000000000000000000000000000000000000000..a622891c7be75cd669f8f644c8a4b95e497502c2 GIT binary patch literal 3925 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 IGL{kl3mO=^NB{r; literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/link_preview_card-light.png b/testdata/snapshots/darwin/link_preview_card-light.png new file mode 100644 index 0000000000000000000000000000000000000000..b1e45ba7eb9c4239d60348e895c9c3c7747bc206 GIT binary patch literal 10454 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 U;<+e5zgGlEiOGvriWmm|2T;$E2mk;8 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/markdown_view-dark.png b/testdata/snapshots/darwin/markdown_view-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a4d43d3231741947b12b635c6c477d034c93a2d3 GIT binary patch literal 29310 zcmeEu1#leAw%*E;EoNr07%gU&#b7a`#mo#AGc&VfF*8}r%*iME!yBiVLj(~0wrCpAc|;Oae@N(TXDa5St_O*_*m6-EqsTcJ zOBe0v+bIH*%!byO{2YQK4iR?1cydvT^*CJh(vb@58|(i7sD5x&kAioUInw5)i}JsI zEJB_GkF`&lbkBjE5axklNDzWZdv?Kt7yxJ@Fw$QTF#r^SPvZZ71Jnmc$o`~y;qS)J z^#zD7Hb!z@1!X5$4V4>~l^s7zJG7MSN!d58FZ2jWp!|r$H@8O%nHtYkh5YrszuWj&ziAmp57y*N>e9G%$pa=;-)5~eDm2j{RMDya*7;Z7`gw)=^-Ybb1>+d z9>@)nv6**vBCc2#KcvFx*u1HcOA^9TQetTobf?X~E(gz9H!-+7DVr@jE&RbpIghao z4&WwTBi=?h(qAJ^wWuhT%{GziP_U>W;I}h=mm2lybPT)`r$srNT)QKZ|F>bC5e9^Y zaB<;TE{j<j7mV445<0Um_&ZSGg@7dY0}@Z6wxRTC4F zdtV#&qADYJ7zBis#{G)GaMju%8v7Q@W?5A9Li_?14O%Dnj%^hu8K(wcuXAi&U0s>I zm~Ac@!@ZcwN)HSRZRPp19U3Fq;`r9DD9}a4*F%h@QWV_(HO|7tW9xAe092!f(>O0CC`qVsuJH15OZ660wo z9>U=JBtk8PDi=35MPGjqB7zb8_0<(4*11-Pil7MNPf`4_4R-6(LxRZ8=V#jmUz?rX zflv`4lCTh{^yD~Ck`GJ8+4b`(1(Ck3(@Fj`&RsL#UveT&PVi>9jZI4$Vj?FYrUJh{ zZp|dzC}8*Om#g)K$qX1@WGd0ZwwCLPo}Qj+zrbT5>3vJ1rnbIzZ9mhTU8wTt7^E(1 z;G=uf4(?^tDkdh$onoM36wHO<)BJJBhvn8l=px=M-19GCyEVOtdB(0=?n$crtt3ej zC*DVRI%1psO>(r-$a2-|cB!NzRo(JyXn)@LMY+T9Fz{kIHFws0&7NMnlm5c6+aD6S zM*Q}pFJMfrHajg%LES06p#=s9YiVxo^a{szZite^UH`pqay+%$J)u$GL+5?@R)+f+ z*V}|Q?d6rWsdM8T@-O3bEAq>b>A@W+Dk4c1Je8Ix1zD0ihpF(rkYLlMj_7QV7+4n@h=N`Bmq{^u|APh3H7)}+JCxt zRNkF9ZHfZ()@LxSOYw;$SoAhSUd_ME&w*Zp9u1?0Kot{);o+$*Ib8DAU3g+!>mjtX zWBvW7^+p0!JXzce!$X9Nv?re~DT-ua+`xeG!hyNzgHP}3+ka5SAPR%uxj=1f%~l1~ zO(dMs`-kMZFRH088zxedzvo6`Vu%Wv0$7`CHBMUiMRYw=XBQUO>~>s(dtt^t{p>Sq$2HU5nUleuT*A7axpBQ~UEm56Yx53HJuh%&f%l$!_Aoe!A z(ILj_wqXbGiNhrI&1r@qhNe^v#iXoL^MGJ0ET*V|geOW7pt3)@O;B4vAxZT2uWi6B zPM)oErqTAusAa}4D?76+o{&AD2iDt%iDmwPOwerptcDG}_-k1r97}&dP7erZqX@-Xmxagt44?{YSPHU`r+j`Ctw0QGd*qPW!cTA8?m$! zdt^3S()u7f-yt^nnq1%L1X`xB_20<9_+J^%(s5}b(fCGH{w*+j^hAN1cKfC8*ScpH z1nOer=@j%@TJ7^h0i>2bF$62MD>mr7?Pb#G80{OYn^j#mtR-#g(H`Q>!2y3&)^>*E zawTN~@9Qn^AiFJ}(!x6jcT;RWzKu3R2}d@<`Obv$F&2d2-9vW`z+XDC#}uQM>D$!Q z^kz{UfYd@;Lc|b1G1S+$=PP8z;6-<|&P+JNoP>0o;BJCESa@<_chQR!|Aw(XW<>z?L~P~ z*_394Rdd$>Ut7*%sRWFhRj>HV>D;eO9IZM<|K!Cm;lQW7KL8CPE&9R1^pC4VQH0<+ zL7ddsPN2trzk_KcP6UqCcj4aGd%H+g8_N5k&z}f2h@h`ldxRFe$s-%>1^Aa-??l~KtoeL8X~IG`C?msC7{^ITd6Ww1#g%!?-83%7Q5PtBW@qEh zvO|7i9o)8ooR-b3AKgGr&2ULcUw~D;fJ)W|>i&+#p%MW{O$2tAPR!xQGA|Pq7N-&vET-*wW}(Ny=-1j`?!lIQG~K6U8Oa(#3!rc zlVZCL{Z|kzL#Y@%L~+o&_vxD>mNzz>P9IBjv)}3HX#ZWdDg5{HkSXCppb*vD=uOSd zpGW1s*H^RgRTFB_vvY{!5fJR`H}v>l9Ud>dogGvxFRQzIA8lW?g9aJo*&i!3N){2F zPTbS^EowIDFX$J+|3abmE-@f*8dK%g96tB|G$=iHi{Uv0^CL+i{D8 zkHSUjD1I0-MVu=v6dZsse8&AhK<9CqzI~6+P={9^X)@_~3ty!ANOILkZ|~3}A|lep zjooL+8P7F4|xq_>2lS*RRgb=&a7Z_{S#U zM->+X-x$-|pI#Y6-z6;0(?L2=NOpX1kaTqws;c7|H3;-_E=$aMr8X&yX5ck68BIDo zTis1d*EHRxN!-$_A^E;AUy`1Yk;e+``(~UI{Ey~vwh2E!X;x*u_Tw&O*O{2}zwJHL ziaAfk(@R*M8n;+dWOC9?s`8et6zgG~FD+qJs0WFVxRdag5iyL;&c-9v&Zx$eNRBHN zO7{6WhW!uGwOodwi@|jxL@}vK5v?#h*xgy^8V9?OrIgjhsWhrx@;3hopj?3^4Jj& z5FQW@f9A2H2vu&HY8b{^kf1=v6MB(SnsO3$ZPdGUNETjRYY4(Vi0-vHlk;W>m_XHz zJz;tP!7%#g-#)n8q%@xuAPOE@ZxIywKN*PqK!&~VL&;}k6qS)jW>tZ}b@ta25h##A zb}W>*kSUqTtJfLr5&gKMeWIpjf<15$@R#g9v z5GJpU?QC16rJ@>cuuy4k?4*$qP9;Qd;dSpro|7>ZPlpkroC8 zi;0$`1qTmI_=5kYqakYUX}LDjLwb8XZn6E~;#s4Aj;D%kR?@!s-BXcXNk%4u&E}e& zovcY=6*YcFSg02aa06^P+i2n3g4xJ>)H<-o*G`Dh` zZax(5NIxB?J@@i|SzPD<1Ei$JEmqvI65~chL}6egWpTQ+B(6lAVK*=|+59lb)_m}K zQIxhM;pg8B{Rs)2u+!e!zv5tHWImbCOvfZ6?Gx^`9_Xh)4HZH>*Zu-!fBEBwpnhn| z?;+K;CXE!_cyW}%!o)7#5Lp@Fn{#qD?T@hHhYf4gR-3%onV7gz z1@7;%xEH@GD74q+v2i>qxVSJ-__jNy0#BFg(9n$M7TNhiLcE@s5KpfCXV|B7+7`q# zH9LxnFZRRREf&umYBybZyc<3g#KdTjk+)x8cbb>bth0VdO4^U78DS(1xbnQ;oy?pp zp1U~R0RWxLUD~RuiaOq3;)mh7u4vrh<+ZL(jz*U%T}S)oz7grQw6@wSDq2{Lr<-kW z%@}3j;85e^YbPW>ZEquI)DT0}>icImM3$77J8GY$5B;VSe zS^=H3vU04h&KZoD+0z<;j1m#^&Ww!0&!1gT&>U8~6Zie*?5v`+)PkFD^6C>G|&HKKsvUTq#1%OjMkw6y2BdRk4~aGKm=v^^6501a&q@3eeK)Ezq1 zjI1!x_e9ldwKhu7q_2hxhU}c4` z<^#23k?vXL{E|MdE%aD5)Lt zJ`6O}?d%w+!OlfQ!h-=yju;3ANvqY$Yih1+y7(oFXQ!14YQO*jno`EtX9{|z>1cZmb8q_ z)0RscKT10c42)LSYZ>D*5f^!GbHUp9yxnG&)v5PfU;qTCd@SQ~PHU03q2smV81`Oa zIK{!Z)3}dzM(mUM+e#uxnQEC#OU2~nz0D02Wt7!LMbnsJUG+X>Kl%Rh&RIFeoWP%* zQNY9?*Ma6GqoMKIU&#y_C~^Yp^zM{8KEZXchXnxKp1w;AoAI3Jt>=>yQRbAhD1I8H z3=0dRq!~xUAou=FJQ=H(nJa2#Rs7?6v)$|qVDA7!f$|9?S*WPD!`S4EvGBOBIJoJW znyVG%GQe>cqc-2-IIJ%^d>(zsRHxK10wJPk*6I@Pvdc>v(Cj7i%`ZLy=>6xMcz9#KGxu6fS#(PzN9( zNkyLW$=_d?MT4KqSkk+{Z4v20N+a#|X7VK>!ZAE-bH^hQ(w4+L^t(P7`kb+^&(1mqg<%!P9 zEcdx`gNcKK^m|-{ho?#6X53P9K^?HF{8n2_UftpT6}_C^e9>mj#@d?KO2dT$-1+$1<9Pn*ari z$~vbE0FaTPFA@B?ycGBH%5Q88ip?cB*d=CGtWBlD22^|RR-R_~jV8;ktg2UPv?RzD z-`tvX3>i0pS5#P~H=a4UIIT7Oj894Vomfbm}xjo9XM`IVWa<+Wyq zk)a_A6E)lOcI4+Qf=PvJ(2$Xl73#vYNi;hzI&^wyucyz{jvS^GXWgvt?kL77GDQqO zUo3XJzooFSD!H-kaiXx?M3m&^73Jj_2UazOhIWtR#?B_y5J92fc~Ws6arzO-BUUY~ zs;{-YApy2dExDPPTFrJhLPJ9f3L;{p2FokP%`N!Zl%%9k_4RkUFXY-?V_^Z0bUShR z`K-lF&p}PV3GMJm3FB{AO6G$}bnnN|>$6BLy zNI(}75EGL!;{916i??|8DCkS;A?&^2P;PAXH+c#9Z9yeCpw`rk5FIV`SKQoUad2>a zjPSet`#V!`04W)np<#iDNB{__wEvkH(n1au%D6e&B5JkFZ7XJHuhLtf)dVq#hDCrr^|%P@I)S*k(*>)W{0a4ZnIp2o{ak*d^hT zk`>FH({pCp-4dw`35(>#q?Ovs$=M7&?XJBYpO|UGv`uepviMZRmneffIB`ONyWMhyg^xVX}OV*-?w$-em8Jq{5#lLNp2 zze}m~BVDDwD`%M!4rPS&*uC@3o)A0F-$u&dE7gqN@NOC3PN zz-(Q)Vq=&59^yc-q^7X|bwf+Ww;%_$C$2^eFa zGD&@)6smieZjdU)BkT^Iv zh`h!vHVY!<%!VnnSp@vq#-V2Meb&)T^2A`{Wj>FTy+%b6 zJXRb<5t>ov?d>17eyuV9;`6x7Fi6dNYF>lv`Oev%X$ucA~?T zd45v&LqUOrp$m#etfIPFNmp*QXU%mG(-$gOFLSdJ zhb@u(J5an992AU5fMD<~1UhAb<;Dk`2D${xS~)YM_u*UYuL=z3>UKElFZXAwMQ@jj?j#gRZI z8=TZhdH)Z5nJv_WfbQzXL|DH;p-KB5ser*w+^5C-o9qnc6(wcm#rcJfWwgUdF{0bs z`wHzk14GAzIv&e36ck19g>ooPpI0|>Bi}_l6bU~E9dSun#LI^k9OvWvbxKD0*hpLz zcGf0$IxXIgH?;6@xec^KLi=~u0f&(_PI?#^dzTCT3>6blTBj65lp+L&H)CRWGw+;t zP?j6E8W^B<@bJRHJI13DL_|iFl;*X-p8HWwbk$*2YG|gL{VucKY_+C_y4dg;O6{mB zFHcM-w)kn4b;G28%(V*&&}GIeB*S20yR<7REWS-Gc5mBGM`yo#p2Ep}7D>H}4M_7=WC24le$<@#1mGTDGY(}(hCinOu1TVk#+JwY@LwWz9mT;#3fD0Oim zJ1%az^+p(!THTKFLOe7Vesr(HrmC`21*7_h<0bM)S^FgLaweXp_AE20`ti($1A)1~N>heK<3cLOtEX%2RVPQis z|86q%Y;Ag)m5r^@d!6(m67J3wglFQ+ygmUoY6maJ-_NM1Qic6{LG?wpVR4wyFd~$i z_fDU0LV`4^qOgn0U^r&aW~Wv6h#MtE+qZAF`{(Pp`T3|wzsfbc@@i`-uIW4$qmj%d>E>%~#lL^+*;tsFSTH&idCFMz*5o)~PwLvA&rPka0^1DaCCvKw zX_{&<;tiNm&CJw67{&qEoU=G&g%64Nxr3e(4B+bFc6oEd8!iK_aN7m zH9p}+M@4mhsK-0l`~8Rb<#|Uirch6fvI7kcPI^|Mv4Il>>o<;o!QH|_i98Y#kVG<2 zwPaM2Gf^k4EYLGhv>Db=0Je@B+7jm*Y&IKBEzBsXsKv!Y9`2^2Aaz5$;sWkiQl&kT z(h4h!NNB!}Z^Qd{_ie`&^ea}lfR>>r;JQBw;MZN)1x&CM$zLAc#Mnps&1o4Y6Z zc1HQV!rj~JsI0{o^zvuo;ouw`WvAp+-D-pAu&cPZ$xy*2EA{Z+Z4{JQ^OFq-NPKgP zlMs)%h)7sax@CUh(% zNxxt^qtiJ;M^|xrc1A->jmYO@7yHm&TDmfKTRu}Osfi1VYvG`Z8C+W{`S}UEzuzd8 zp;p%jC>2YZiDz{%>7=Nv92OG6=|z5ewrUKL1a@|@s;9bf>Bt#o9RhAUYe&Zj(UWA5 zb{mU2SJ!d9&Psq(hrUn|EdHA8NlD-ST1jq2g|M{N z+>rR>@bE%+H#G@KkgQ3HW(+Iq{Q0^^U*u0iL-8(t5!DAJl{s;#Sj#h7JiPLR1hk!9 z#fvq!A-#6+YqN#b)y3&)BNG#S6B9FIYmh;7Avq)g!me#Bl;oFjnncxQWnl!yRTUNC zVWzLm&-WVC9G~Dc)X!tkrda*_siHV*%Xw-I$vw6GT2^K;x1iEg&*E%f8ykbd+QRUao{_|{2QZM zTd+BasVX`vBJ9%G!UcQAK9vP*8&>{%Q-Hk*QgJ8<% z$EO#!ed&O}(AgpfK5HnykkHT>)3@1I!bPzKK51q~MtN`V_w)0tXf3hbD_2(K!s!}D z5I2guIDriH_-EXs`DBxntY4jWYVf2|$j|Q+h;;#FZBS8Bvv+(p(a`s^$wc2gZx>fx zip4xUJw1DRL~za+);=VJgkB{Nhg+Wq2odtj$k@v@TPy~PehLDu^`!7ZMTkEUe7r*j z_ip#~e~0`M)O-`D1>D-YtatGxf+C0p&b|J?uLOk=n3%W(1X)}+SFu4nVoaR#ALlnQ zP!ON|yC3`b5qy79#FB!LaB)zN4>gD!j*XR<6|yV^HMO_b^chw##teLGk9pJP`aSzx zk(8R6hl6A6hBquU6af)&)@^KJComv@k1>0BW;$%}16fprY<&CN%dfiO^?Wgqg#xV9`VD+`#9P=kK;!h5be_PiiPQxip+0{i2CAGVGZb2W# zG(dnN{i_sws1vz0b8ohJfd(u(Wp}bLH`hSl8bqfAa=tT~nU!Y3@Rb*rfi^^hgoGAU zjGv!ZQoun}AIvfH_djg!taKV2m;gQL1yw~wYg5}7o1EC&`0;soNZg1g+&k;Lon0+rhv&&+ zojw2nqH;FBRsr|Xk55j1mr#2!Krc0N3jD`Z#Xu9?OXo%>pKWsXg#kO}U?B|~90CFu zz%$9s22QKv=c4Zc#xc9DkG_e8AQ6(iJ#17q$L9RH{~0PPgdkh_jb>|~l#aEil!d0D z(paP>ayZ7si~EBLD2lACJWpD12J!1^cf-U+#zwd}hvpU~E{=|G?&tPG2BkSU0%I5K zHtV774j1}U(-#t?5*j{T9Tn*D!{U+?k5|dFv>5*_sb8MVsW$k{2vX7cuj*klw)W;e z&3|y0K5&DQn*KrO8>Ao-06<76_+8!Z2!-K`Kk}W2mM)=;px{LJM3`kka!iVff(D2{ zE(H;sKg6qROI4JWhx>;KU>grYL&N6g*|RwBcCU?KK^U&iLC0gl1+fJQrch~SM`ER#SI~-LZ@3^nRoqYW*~3IdGL-$r^8WI($es|nTMY5>Cby6 zNXn{eZ@@G`*zs-A+T>fxFS;-OHES+EX&UeWIRyoPB}v&~ECPb7OWP=~IMT0Qjm!-m zHAU)c@s$zBJ?J%o!t~Uo~55Z9&QvweM2a5PTAGgv< zLiG>#HK!Tnc!6z${l%okhI&pPQzw2qPQGm*UST5XkCo;^Y~(EnH0TBXW=tKM2V4DZ zh2O>Nig$BZ)Rw*rIurzfBO_(J%bGw*Tv5?}QU3OtKeM~HsXxk*AyED*Gr&(0$`W=_ zWy}D*BflpfNO4f;uc2{lhRvXraVjPzx_l#X(=3qJKC(Ll1^BUfnIxQFf`g4MBPpBB zJ*X@$Zrj*~iV*C9m#(Lm0}`r6Cit$fPZA0Wp8z?<#jNP!iOLN)IHjAOZ-MPSaL{&) zfM34={3?%vMnE)M1>2{m{!`EVTNWY^z*b!40sxff8$hgcEz`_@Bz?3@k50Uf^PvCT zG(>}yL@)3&GIkFRF0RjpKkfG(aYYiWvpf_Pl$PQ4R1g=a^aT^?UF4L43g7p zaM*yzA}z$^fq|l)JSKcAnSWBz9v&2cUy@b~3{~dl=KUHu_x+7`y4IUh^Xu{1x^o*F zW~MnWV#~px%VTR{z=r~+O}=>^(CejofVtDx`U5Yqx<&@>;fy$ z!8r^5Ns(wwjh2+4-`PdWLvXRb58}kSynrs2kSS*e%`TJ9(aRH)%v5R>{EKC$uOJ$r z3q726Oom>k6#+n5_4^-r0Q4Z8&d-3DBob`wV`Y_j1G*pSXXkU9{9AjiDYC_y>S^@a zr=f{CqNFhT={~9~8a^})UZ$>(TiZlm{6mRC^8HycWv6lk{qH|~-}vv(c}hzxHo+em zzWRO(5)29;^3x}PAc3LW0)%PIVVwNR+gV$=Z}1vDo|&J2c=l|#Ynbm;$!_p>`YmaN zUI4>0nnIbMLzF*~fP~C6oRYCui4>JgeXr8-5VpAKax=);HNMRG;kCf`a_W>tCJvY) zk8PC5I<7b|i`{O-OTUQDu(Y3M8kdi(Hb&b`7|jwT`&heGiSAmaTjF1KmiCkiGY zYK))`NPO1u?%q#1gh~nx)u~!EhXzG;k5NRTSvXP9*Mt*Ay5ib(<>l=o&CC+{(*@S9 z9+T&p779r-N4IU->lfB9Ih~!M?JHA!>kmGtYftIyMSwp~V;P)RH8_#_^#@6fvt~zj zc8uH`9uB195V^Q+QV%u)>}b13;Or7e0nUex7bcKPmUS%-peqtHZCF92@L`l)w^*?!Z$z^=l-jC7mQlwOe2d@5vufUyk_<0WByLgG35pX8DV> zQws*5pW93HT~zuDfM1t^hGsMuF+HYC?7<6&Rn5v12 z0nOV^J2rN_qWJ+_JJNLF0{lq^Hgd7?{TbJ`lk+Ofb@n-!^w&6RpSo;dKA>HG$@bTP z2UtewBK>jMbiJ%I?aE;X(v7rg;1J@GC%Q=OuTOXS(tg=Zwj#`+!|?Jr>KVGYgXZl} zFxc^I_6&WsKEIQ!h2z%InP6<1LJ~;{-rDMqP|REF-vAGIe?8a5n~$^z)YG!%=-=}QMDM}N9GIGNlq?p zVL_uy*j_P}L`iJE)*%sl}>diLj+hR zM$F?B0$XFes+cLw`+IJK`!R4C{aW0}}kTNWmR zxe6tmAK8;GPN5-4I9dLIpQ+GB(s1uU=C84~R;$%O(d|13&pjUPZ5OCw;Bk50YKf{0 zJe`(j@Bm_Hlu9g;TCTN}%vk{miK=A9mc&r_PuxKVJvHIiSNuA*N3*vq0Hnpm^3cfa ztwX#6;%fc$sZ#mQD?>j%gM{nO8Uy#$6B-dN<-L@nV%}Dk0zrDQF zfeT-k(u}8&FDDume|Iz6c`YBQZESPVIy)t#j}s>Omu>2BC2F~9wyT*2rDNXLior|z z^yExq!t3%S3oBbyGF6GPSRGo6i#>)4{`BX2*&iSL)IVjCmFCKVe7A+=(#x zqJS7x?NrJLBo2q+6Hz&JMR2#rAy+Pkf9@N|CV*B@4DS1loGE%^Yk#g#c28Qx?g&8Q z658r{;bSkWC}VaySfjN07=>r2Przh%7C&TJ>HTgm{x8E*fQd*Ns8Bd<3YvbS+LTew zE5T*xl4iYu5%f9Q#et5pT?nbw?^AD{{PD3-62`&z9Rq+~YKm!tMv0PfGvJRasEyHt z+=oYuosE?>m6fqVxy^8?hOe{c4G+;5>|Bvw0606{^yHa*9C;iZj&$*SuS{HlOt0ec zk_2n){yd(BDfRNA-mVZ_iK6*4b6#GV)PZ&ZwK*R#P7weZPODe@p95l1 zJMKkk0{o0Kz}3rohe|%H>%^5`l|5e#v3UO+|4U>i=X+sL&X2eUu6MA_>XKln&uH|)y3_*G2q;r6ydv#niR zNkK>c`+JY=E#QfDvAwz7EmzSP0^-5qi%aHXWsUGmp$e-c+4iUG!1%A=kLUf74Hx*_ zJUP=tX!cTyb!L2EAbVj+N1JY_z>FGC2XdikH%axWr%l)lgP_iiI#dba7M0lsQ ztMa!~X#!IrPtT~0j_IR_iM4ylQt;qMVY7Hq!XyHW(bUlqnZa(DMt_AUtYRJZdpB%P zk*woE7REmQ2p_}Id7c90RdM+^m31$M#C!(wTD#<=kbJa6{sB_{ zfmPlmh!Rs9<~3%G0=iI=|uY9u;7d%g1IE&{{?RTZQnnk z&j0o;0^EYGY8QF|8ErE>{uW|+D5M`DLV|EaL?B8xIi!(Fqk$wLnFLLx+T2d#)Y+`* zY+>E5t+LLd&8h*PyK&WOy|by2+cFV-&y0#oZA6$(K~M)w2?d;Zsr`Hco>N|pIv3Go z@%43t%}k<*E51YD9LCt*Y!);=Nv(VdhWPIm zM==gk0JOlT7{GtB@^%(Lfe8fj?zCf+zj-YX^8K?W`svjRw$Ub)vo{gxdMjwIA6D4( z`Rqr}aiaRs@U5l!_4VyiMvLI-sWfg;PIJm{$a7tpN%G{o_|#*8zyHsSC+4-#A^YR4 z(gfDUdVF|I`Ee=R`9t)WIT&f@WcMp9tdmQ+1XS!`|MSyC;aBV69!$E3B)VLacp6qa z?fNkV9ZEZw_`!ZIZqAtrDoR6dJ?VmoEE)O}3g&rV$`{dP_K{BcdoN(Jmz?sG8>eWz z-KMX9rZ%raHfK6B`{`1gV)IGM?tY>P4o;O8eoknU^2L0n?t>hmTRVexuqh1_pWIZ_eY5-NliB2TZ>7Sts~m^AO-}Ol!t4Js`PY;1X><` zkm3C9SyJ~hrFjv75c@nPp;bq1o3%L)W@M%PW-=&s#KPXUdu7j7M5m5t&XhLcIsf<& z9aT+BV{bboEro!P#xBEAp*j6>|3c_=M|lWUPOJ|PZ6U5E+=DZNs3VMnGoz(Uy>C|& zYM~-ACI{>^vtZzp2PrK6=^2?d^V#VDlAT$BJ|Fn{ZoBciQ@I-LaSW+`HoZQZN zQnmX&YeQ@6LBi5970r0xi<=@>?>92^dC#EbwD<-}(iEgxFNa1?x6|b+h72=P z4V;#}X{#2V4J>|^-hLy;r;+Y%!5ub-w>0IuNEskQJv|gmyGuV)T7Te14!^vULh&rk z^Rt|iimoD}T}8lJm%@hQ`N_cz-3|C_lc9;NLu)Hf=g;&Dt?b&;$zYbW$l;USi>UnB zwJFO`kD=E;rD=-7IOEh$Vdyo}0Wo9sdq&g9@G>T4=H{S;F~Md{WKl11_h01=3n3Kg z`r5+B>vTI<0d=vEyt1uSX(6MOTScP?dtv6CQ3KycPE2)j0}~M|a-cMA#j7nlGAiOk*H+cAZ=(~Rkn^vJA%)pow5uavEjpPpj3|#|7(57J(7R7Ykh&` zdg-He;Et&TwiP*{w}xYRLR*b4=ILd!Bs4K2GE+_6tYX{8QpKSW*1>X5=5_PZOqe-W z4@r{IL+9IG$5m6CZ!q`xiL zt-tTw#&pZg(I!0{!cNluSHqLVav05Ky~Qm4*>~KXo2QMetmE!(KP$IB+Wcvj#nteX z`RnoT1}YYsxWs+mY0u9t93`hD8~yj z1FS6BFI(|>_?q6tu&{Uct>MlaNZF|Q_}DdE{-q4&9%vm&VkYjq4YWxYEi!RK#w(N$m? z>F3t_L^yJ3+kEU3M;?s3@O@)P;xC!piV3=pPL{2@I6FZ^fCJ6aq8+_{dQAvuIK$UY zZf%7o9tUbl(zFa3-Om<#c(^&=-%i@? zdg!kTO`gqyW*J?7+k*8VT#J#!-HQ3USlWuacX&_2zT7y}G0zfwV~?pM==T-2sioz9 z_VFC0aT&n(d{(a+>h?A>?7J?U2Hjlgs%~UwhMhgh4y;Sc1Kfa(+E;z=CnJFj-e;7b zuDv{2?4qNlFX7Z4tUc{~gKPpC7gJO;)$Nwe9jk7*mR($#PJ-3mgD#f<|m!zAxVMJFNWpdPo6>BjGwyYUJyYk5674Oo0zep zLH_LvV$LuTW-aXm>Uo#>#dTUxs`HR?2Eihde6|n!Xa9aU9!sxAlF=ZKA*wCTf~@y< z+`CP57}SyOjSWL4?T>rS6}@;%pGD80nyYwUVZXmhEeENEX;AQ>l}yL?YFciVf*Pv% zw5n7+`%E31QIx2&+CWjQj?Ez`-V8s`$vMcT5IDY~E(DR@*Q}%vph;symT-S7}e22Fc|L+%#4)C*A^V15EZS>DZ2rKeB(AKlljFKzU=o z_lrBi`}4cv67Hzo$0`nlf z3CY{lc=%Q4=^jrmkT=BJfsJ@u+?9i4=j!3%#p@P(T43ZyNgWHUkp9Bi&9o0d2r8FT zheh2|Ktex-cKnmjP;c7p6ydU&a@vm+_#h!Xc7(_rWEMZsDJYyPoU2Vw-U++zACzdu z4W)3cbU5PI_4V>>v74|_NJ6Gb=mx#l^^WeOIO4;Tq^N$~Q2xkYzQT!OMSR1OffIe8 zkFsT?75O58fje@DECfZ&!W*?~cw3V~w4KJKr5J2+Y%7CbS(1LUI2Y<07&F=lI)*nE zi@b$sa_Ae}dP<0qdir{|L> znWHY8j**EbNXc&-1R_r5yV49XA2T&HIC->P+)sCe!f`&Q9aI05bxt0aefaxM%5nXe zk%e;i5>I$ucRk=((oYK9Bl-5L?78(a_Z7Nkh{udI{9k=QdrZ{6X`e{FdpVQB9q;E zn%6fmIkB^|#SbYiZX_kW+)>k%Eqe=2x;>H@In=Wl4$DzCReC+Mi9tE?{XxsdTduofhIXR%IPs@%cXgC z=a*mCDkvKDgQibI6Bmt8N*SalkY0LyEcWpHRG4XhgG6j1wBC_L}x3dWc>08oJTfxC}og4reuEXR z(+P%5J$51`N}hN96elW}+2$;>COeTv>hGv6F9@R0T4iA{6s%!Z(qp1UBVk)ZrVdgx zUb!OVq{*vgDpU<=hi8M#S;{wvUp&DI4c^<`rfa0hznUlZ0AZnCVUdKyxr~mSbk8@8 zSPUUQ`CCV;R;b8&2=XkSA|$UWDrzTMj72^0`YkLys=aLonGsHfA9tJs* z7tp7#@1A`;_MR=aSxR9XprUkuZ{QDV3mIxkr;lNl_kRzB>3`L1x|nhy3Ya>jm8x1* zZ|EqVJaTlC3{y2UXEhnec-|B4tKD8{^%}@Hd`FFsMIP%EGFHsB&8S6MS6Mb z^e1CLGjG7A_;_@9YyB_nJO@xz%a#~PDli}@Ajts)hM?pi2n;wNIcE?h3|Z2U2azC> z(;z`c@&g0}B!`g9o&-#+)8KHYu# zoD(}5xG1HDZ25GQFvKbc95;qU(rqw}A9bNMxRjl8Y>6i~X zn(?VmA$LAf^xn02i5b%uf_(SBFL4_fK1Om*fNPxQw+s}OX+>2j={SM!SrW~ zqy!pNV6@b%v*+~GFfk7E^3*@LPR$<^guVRwo=cz;Ca=5i#EV5Im!^x573bD`-H zTn6+>JO9dnXosvt`?K@Yt$C_#8D53q;?C{?1Rsi`TsjLThHmxZP)nDNZy znyR+K{J96@_uq#@>YuFUKX?B#C=GH>c;`qY{J#16s?#O0Nq>if8UGs(73JSCP=eUN zO0c)le9TW}ViyDdcU=h$_(~rq*1KGI1L&w8RwqtbB)Tz5SWr-q2Yi-!r1j|XTG(-h zWKL*Fzfy+%kUL0_ZM;n-_USzIS#ldyico|m`@5EJ-^OExb-_C7%s+L#4-WVOyIvIS?a_b&%Z2won;y? zd+ek(`z@N|(+Vd8i#qgB%i?*<=QFG-XJ){wi~7`r3EYXbPRj=L~maKQ4o7AdSGSH9|k^)pO zB*030dk$FZ%=(b`GUm4}`&5Tj54L-_>;2^2v1)z%FvBQ98T zN#)T6bLkj^scLhDtIFZw#g&PPxe_ORA?|pg6p`N?t&e-K2p3)>z|c2)>mq@Fd*b%Z zShNy$4tw4|7Kh~R5ckXe+`9AH;?{T_X)_<0SozZOvV02SseZ6Uh{t&}Gl)bJWVJ|h z)38t{xh$l|vR2E(LPsX`c|gH_c5SUc`9StiKUB)VzS4yV$2=zqo(u^*iFRTfxHJ>8 zXik6J>Yo1jTy^unq5!K035@=biPo+ZVx0W6x!Z+5DqW;y26J;RTkTR8c1=Gf60L$8 znrQ2rAAWMe`*XPo5@N)R2Zv>dC~8S7d5n`l6s<2Nm)71yxu}+}f7*Kz%qAu_-!Uf@ z9ITS}+lR3-;o6MSWO9}`Mfds&R*o0I9zIBJ1c9kH&Fnw-!y5_;?lV4ToIE+;dFhX_ zKS`lOHaK|sbhq`06EUAt`s$+qNk|r1!xIJ1A&>yKWIdnyjb{J>E=IM7MTG%|acF}*-0qS{QDOZn$wQvCiFedta&s$BD4SWxe>BUyqTx-Qm>Mh? zyxuVJF)v#gOvQ6DciI_u(fYO~__^_YiJ+ zJ<^rqN(wAqKg#~bHux~)z9ylB|UkMuIS=6%6W$Xj~BX?jyK3i;SLTF zQJQ}4hodja$i{HaA2)*cZ5N%B^0QbTa*KjRI;M=xO7xnWWt(z>>5msXK0C+vKQA4# z+iS$V7rvFHLA-gr>)R{`a3VLdejUx&b>9&3D!9OQeP@T1hWAjqZSorpqCtA_w`euy zbQzhTKoa-{XO_C!^tV|L*1}|!3w@I9azw;C+g!FAeYybsan&i!NJ4bOp4=(U8tsq% z0!}k=Mp*!|uo5fcYG-XZqV4Sitvt>a^Qa)w!2*X#2p1+M4Yjevs+*uSIs=7SCF+2w zZd6mZ@`VE$Laq^fp4Rvz$6>4bGE7d1%N0-w@K%vSUq)gVuZLAA@^gdI8&C@eij`MrR$CfrFmpV}P!1PxfZB4DWNMu<0 z(c8DMli-WSh|M0yy{ij5-PaQGjkGlyB={G4@3?4dN4UsJPZYWbKMlAT@>YpdO=+>Z zx_sIuH}q+VL1AI#cwZU@d_b4AMs7~nGM`1rFIQO4#4Lo3s76M5 zb=wkz1rHT1ZkG(gz4V-)6hBN6b8PKiY@1k1L_xN`!g;k&{f+5Kaj{kK1s5B)mE#q3 zKV7(BxtnEKc7DG5&>L2p@;1vd$+LxSK(TeAQZNuu=*@4@-_DOEiOX|rCbcap_|mg{ z9$H@EUOsK6r1ZMj(K@3K%g(_({d~B5BC zdrPEG+8ge54ASn^j!58*jsuFnXbXwiEZOPQ7(83ByMz{dQMfAqWEaKCbx?Q$w^GHu z92DJCkOeH%Fgy^GGp*$!Q%p-~cY%0mYJjJOmClnV6OpQ{62Lj2on+fZhY5(CHr!!$t8q2Q&xftoexPIV@luyU`5n-SqKCNq5< z#|Ql_L?Xi;5?<6`~hsfmcu#m3BVq>3K_xcriH_uuFfy>yKY?=RdZcPVNN% zo)xj6YJQ-_1PL%)UgyA~#^R(XCPFqL6VV4-S0?IFLiv+dEeh{X$?$e$GlUdV5 zI+=h((d}iUA14-5kuO}_be1FLO;E;-P5WnPxKA*|K?z)?qCz#03tr_a?V zih3GNu^?3Z$E>}#yd0vac#(FYt7WY~yAE)%)Y4ls&Ds}$u5J6@Sz7t;!u&t++_6cZ zKype%-E(Kgq)I(-(_FrY(an&8c_(f9qT?ToMaQNGy;$Klr4h}24u~A?uMSV2Jb@=x z_=F@bDywCHBPgzrP?5GW(FzV<(o`lPO!HVon`PugQ)Rql1CG0)@%M;qu9zQ@tCgtP ztdCQtPuSx!)5ZBWijt;$Z4AF=_1xH7sPSVL$GN7Y8CS0~i1)ohR@MXU8Nlr_;J^a|0kDEC#I*(FWILAsQP8UV2@Zz4#*IWI+ zE>^lsZ%WFNDhPx+mU}wBlM6smOpAHReY@HS6BxZ-@5`k>BgrK)NTm$*GyRjR1pW%4 z`JCCU4%*rl%%Mf=n`t+u=C51~42&iR$;iNnI;mpwIm-o$7khdWf}Xm1d#|nG4A;Q_ za9;ynBJSw!V0_llTVz;@%KFVo#a_9*)(N|{$)Nw_;lX`BUb!mECCEK)lrEkR^W3D! z_M7-dAh}FiYD-*=w|)FQ?DWLfem6~OHm#7o?qI4h#+z zCaeQ10LHZ~Dc^&p>afJ6I|KwD-yBMG?lbOY4VdHh>Fi5|E?B`P@;L>Jr4Bp$4J&Ia zwe6in2D%d$sx5&Zz1XQ7-#2_yg<>wh_iER6+EiWor{~iv?JA!pt&8&^yc|5Sh@ZfQ zdJZ%vv0p#`+_D;tePZk@3w9R1d$*Y{e5ni7-Q7tc17+#IL?}f^6jEINss3!Z_lOny zM7M~|9$v|7ShG4hGE-6EX)qxXMvdap|1?XcntSR?K)~ne@m_}0aNl|?KVdM(;>MYj z36e>K{093~3tvC{*QJ^yQI(Kpb^VfxQuEDOmbyA(0)jl~$bJj36&I3^Q-q23Zn&vR zz1XScmrBFL3qCvU6*h@Tlye^r|0LiI29;0PkLl~5KT`9Py)2t`57ZC+U5@oxr7~ zy?;8!x<%AnHPP?s(z8}7iF~9Uzfz$iU|conQKK+TNZ=ozzAkTk=7*S@G_0%-y}s4S z2HsT~I~4T;RNGx>c#BO>7Tb1)Lbb(q`g=WIurY{vE<@Pp?6kYk=)`H8>6Mqx_a}u#f^m_zBJ9U)C1yMTQQ8SxsMyfyf)}k zdeS^JI0Anh9Quj4s1U`(#1z4gXB(+&4>nYbq6h3}6wcZP zu7-ze+;vX69q8PfYPsB<{!*l^gLVG2LAE26Q1qG4wvWV$r`b;d;lFbRT+hX%JZJc} zAfB`p6uQZA{rYuyc}<=NnLEI}GCQARnVCuEI?{Ab_&6VAFyVKD4V94)DYk3klrW@- z9$SK9&|ULeIcv{19V<7>^hBOsV-EcKoVxbj8e&42`0>FTzmlP5*$S}A)QIqGmM-jc zL8<3TWxJ4yh>=5O^Hjj>zfKbs%}Xr#6zU!9x|9dMm4WDS?b( zHPqUBtgR)`kvCLRS4*esId+`{V^SwFZWW2JwKW{d8?V{bwMVAzIP)iFgM+z^-Vfe( z5Skn-!|`>MqAhX?Asse$cIx*ovS`m42eY$c#u8A;@v*7E{(;A+t|8l%x2v?tmL)J+ z6Nk?26FPUEs1l@_%WF+PI0%oxxkR ze_tzWdIFHE^V`fMArTSlz9Lg^kB(!)a4gn=qmwu$|A)4z@8ICzy42PsKTw69NMWAc}2!&?!u!;+Ei~- zw!T6#N$J1IInZBh|q zz+zK1^qkL?GUh>(-+Ea|N$c|mm6iCgr?*&YUMvVvOx4b)KtY{*#%ll_8m2*64t96T zkv@FOg)K9p!;}n&c`dWZ?ec$YHu1>M=wQFyUjE!SKQfwKsv+n^D4Hg^Q zt<*&fApI7#z1mFq7-)LTMqs9-hLxJ#2X}YfV`8u8^Pp?)`sega0EN@I?cS~)3HQ_D z?^wxZqEWKXT8l;$P5@?AGau z{C?tdRBxX1j!DjOfm8ui%ADkPI+o!a;t~Tzl6E)W9j4%GY1hsSBy8W z^B8{&4ip6cgR%=~IQk!pnrMF>?tp(aLCo~;rh|Vb(ibjIP!i7F)ZkiGte{-_K>k!+jaT}RTzVPsv7uIK*kV48PK?M4S<3^pkOXkE zgfop^3{zn5iT$C<+*^dej!%jUPtJ{?(>nx<`O8ku7`}S<-Z4GnJKcjYT>$+V1leHq z^#v$yL(W=KF4~AucTR?=PHDHi@&YuYr!#y6RJi}6mp%9a+*1|`Er%o-*-hlZvgB^i zl4R+cGI(zE+n3gU+@Kq=Y?mL|pKw+)Mj%G+R65$2ep0g)j8`z7sa2dNr%>;y*_sx| zHS8L=+X*BX+_l=@USNOy+WK7JxM}cvoClv_~yTY)0EiH|6 zF;go235igs7VrMdByNCfOp_fscC@kJJnYY;k4l2ISmb8(cXV%YQioy3_LZvX>+p?- zZ*J;3-c}S>d2v|%a7UVjB|i~cbCNFe^g)@Y+6`LDEal1%_`L;$1uikbYy?|k#Dkwo z-zpzIIcS(38R6P`{ra~^PAaygk{IbPE6CAG{N1s~t|{}HmtA01bgzc4e_j4StT*Cdq05AcPP;V^l!yGp8t;zK9= zaBr`iY*J%nZb9zrDrDk6`$}m9Je4p)aEOP7QBEQnYa)hWX5@NSr&$sOZa5{@oTQ5t`m!8g}?9r6qXeX)-4O* zPcsCEL886~y0}xU)DMFb4<$rZR2JDH~x>JH|Z(eme4Ue4kt{!w-&?Ubj z$CyDm)TW$r?YiN($|Ou?j%DIjg4*Q-DCsk6ZFLHYz({Vu?w^|VWpb|ot@-LeRPcKP zV)=&q0~9nt0ir%s_wRx zb>%0SxYm<--=i+vQd3+_NjA46*YEGo=gms$6aJ$YcsR3Yq|13KGxRQP|8LY0e-xGj zG7ND;_lga>v9Z!J3mkH+^b#oAA9&vdV%VdLf5pF9m`faY7|$DBT_-({2C_X0QqRts zUo|_|8T0XC4mZ5g1>T_}7zzFaPwOUZtL_L8y_N$N5i=)F^9e>kOQAEG>f zN=8qgd(i~RHQh8lE$t)FcI#Pw5~uX>QKG3XhP%yh>G=a)tDNa`FL-s?LXo%wrrhWp z{s7l@YGoQs4tT6h^IQupDmqc|lS=x6OjXRDPlO2S*?jzFme;89Dm!=_1?Yo*S6W^h zQw4PGWMz+0DUP)C9*e81*4tsl1{2BcXa?nMjs5-o>dr(4toKK~Nuy)SrT+AnT)I5% z$jo1KHlzcaBAdii)R8;RmBf^6Db9qD50hr6&#}jWZ%@%Nc>1hj?M}A09dXlxqVLdm zkPa+?Y7mEpAE$b!48OpA`RS}#}dMwb=8n-|AlNmHB<_G5LsEPH9F-#T7n z+OO|0TC-@~(r*siOo$_Np)n8VHEEDUxK}9WoutKUDmHKTD%ck8OKx3ikEG{bsW0s8 ze09IAr)O&^V?96Lxpxl7MXVqb8w~~n$y!qMd0}ORU;Khf|7&@H42p<@YI%&nF(aAa zz3g}mUy{G*82y*9m(7PivHd5~|3CTbe2@W2RTu{JSDb(TCA9sM5B(DpH5~nFkMyt7 z*}vjqWI&SeJI((y=>NUNWR~xZ0p6dBmcQm=_5b+zJE6}q{p;=o{*Qm$-zoM$6o&Z= gP%a$UG`kS=m>hIguM!#n`Vs^Raw^aw8MA79_Z9f;++8-Q6`nAh<(tcXzko?(XisaoMxKbG~zaGj-3* zRLvi^?$q6H)78+`-MiPj-e*0_2>mW6{t*Em0RRAel#~!r1OOnJz&}%Pkl?>SEUvc# z05CwW zJCO0nO321zzY;<-iNi`Y$z~maLSq~fRVB6m9;CBp+x_Q)Z1jRda4GPJD}w7)oVZBt$KBn>5(~VWFc5P;b51!7?eiv33CXn160m$P^*M>hwt`C*rDQD)$MBW%Itinj!1cGb>bH zf5y)-n5Pvs*P9u*+>_4Ggy2Z+eudZUhH6KXcXaqj^17+1styOkA!oV>JVc=8mX&Ee zWIr<=-bhJbjwX|lkQhbd!U_tiPGp%pXE=IcG=C*48^|;;JlM*>3ucV}9Pghhp(7@jQd*h&#d~{8_keY_Z z{Ms7N{qm?~LzH#(>N!|eu5CJ<-u$L@q7T`c58174ZQ}O>Bkm8ZbKT#egg+v&GtDtE z3xC`l*%3t);N4}tlP53{etjbbtzdTb^!JN$^sUF;l$Q%G3V5z9n&Df*B}!qj`Dhv% zzK;C<+;VCHd@eK^oa8GnwXiyk;m?_NuhO|~sDO7MBD(OvVZg!E=1dtc6i~_nkUb9>YcIAhZ(%6p)u-U|=96)r*mrV&`l+ah@NMf(tJIZEbH-*}iCK zv{Y72*1rvE$$ffpnF3mHq@7y?`aUosU&w5*-e@oefhFTNB=Asir&WoA-O%7Nmd;JS z>n84(+HT_>NA?okBFXD(+n_mb>Ea}9Wn+_(Q_@ma=B58N1=joZ@%W(=l=m87#m_HB zDq?nc8!>h^Al7?j*XdTZlXl9PH9Br(%{KPB7BLnvH=f3UKpHWyL8peeSRUEt)Fktc zby-XN_uOux_ zX19s6?Bm(sB*Ts3Ivp#km!IJvyv|enMc=QG6n|~c-@o46028Fm#!N@A9K<;i5D*-F z%jGlqJb*ca=4UoGRyacGJQ=K>O9mDqOIOvxM*)n(nTq5e$Wc(-mX&C4=%m^3FMt0o zj_nlN?ck%$t*tFBFIT)k|Mo2_NqYOTEK$1P(v{z1wHQajO=8x2Y%Cgh zA=5B0r0faMQ1LjP%mG^VKVH8lEcUmj6NonH=;)~Vkq@k|zjd)k?@1So&^ZfANHngV zH-6I+KXh7Fm9lfE3c|hg1;bI*KIm-S>$~zI;fJfy+Uo9^?g&NwRD0XcU`=vWw4DT^snoVptUFdMfz|QA$6SzItjTj?TxGq`0 z1b$guNUHU@DO+E&(|Z$- zt=r~ z+h|p~Ao9Dvc1_-&n}Di5MP+3TdloOueG$IkSX-QYxMNQ7>!=N8J5=;5$|);bG(OU} zet002ZA{f#iI`l)CyN~dzWl-AB_@HO`0K_qApHDLk3n0u)SQT2?qDNMtHsJ;zSx7a zu|?vx(3RR0ZG%%OkAiDAI$&a^gXiK!e)$=ntKOq&d=tmq!bUSl|K7jiy{e#rpZWN< z`BDBO`J@uTg5Tz>(MA3o5a_J??lF@lD_^zO8+~uP-e_em(YEwtjP$Rk*Z!DWG^-6S zFH*a?+9sdL^Yo-7K9^y$hOl?iO7nP)xvucma#ofY;+e^F=2?&W9n>|yj!!^PWYL;) z?R(Nw{~CZ;$x!8eLpgG8?dxy| ze%mo-&_dW>6B=*+L`dk{Bp3=@qGf1#ePKktyOYEVJ|@O(2OgHS?Z&B;zCYxVX>03h zoO!b#ZVLZ-h`HjY@J4~(6s`q6#K3--U#wJd32Pe#DO%i1DS3Id5!bI}XXggzltTaF$~O>GSgT|H%)jPR55WGETm z4}TLE4+(|Ocvrt@JSu+6qIBd+FBtzI0f7HY!p0sknwqO_eSPs8kPa>`*Ectq2r#;k z(TjR0%fNVIye^L(dRA7}+`57%7@RTP#PLJk4xFcp%pi3&H5`_KBwI%oPBrKEKLrZ2 zIK*DvKZN>+nxTKKWs(?G4h*!cX>Kbk3pwn*1p?u8A84~KMHo^;3~*b7Xt3SrFlo)q zI-{GIK7Zb#Ipg<}m6g2%O7QgSST=y+XM9!b=<=|xyS-rI-!FJhLJAi^!sx-(?65Ns zNU)C?ehxyqUO~f}p}@^-wdv=uHZx!aHOl)*!d~cbT{hj z8}%xRsX9PSpH<#+olJHyFpL2t5c%_fnR~*nr=DjwpdUdm8M=U6>@e2ePVL@71ux9c z{(Q3<hlJpp`&B?kSN`Fh2QI~$N?TvG$$Y5&3uk?iSqp!Xh5g{Zzhvpje{wh3W_c! z3ir!68dk zWpR9L%D_O-`@C)QIDV+M_O??XU9wQ!C^c2Hix5-a&TesSW`Ie?+?=VU_Dq3RB_!H- z#MqIg8q#BJUdwU1^jxF*|Y%?<@yl$-1Wg$v);U?Vikp0z*AFAP0+0I`Zsf&`iJcH+?%oG(Uz91foQdAEyMGz>Y%`+ zhYu()UY_O6j{A+R&wW!$AvGtz_aB%S%7Q#JvOrz{3NE*OdrNoMsjmxt;afB9PGV z)ummlU09xdM{*VH)dIfnIMzTKVjJG-z=f8ATUuHHefO_=*#;L1_Pmr+-{ z@rer)8nCp}B`&S>g=OdQ!Ns2I69=k4(FlKA6aHj+lC2k`n{BwB6h__k`(yV%ZrulF_`t7>L;R?aiU_ssowYN=GWYSuy0f>%v6cf~g^uaK(CiPF+k@H#p< zwj}2J6bED>1Wc{VR#jH=<2cPvObkprY?X^a)OlShczCqzlbIP!jFJ4_ca3V35D6B_>c=ZN7A6GX6Jb&|8zg|5eR)Z`Rx7 zGcxLL!bY;UK3kLU^_kW+J)Y-&FNJKhwRf(L^h>@4P zXN1J*7V=hA>vfFmgC9UFc+k{9x`-hgsch-Qs){%_ztH5Qn&arWalYasB59GniCwj@ z&^X@7n^rt-&EeHMuzBt6Js5RSqiIfr?aRP^o){clS{4pTJ{{DVpZjKq(=O5Z$&f2G}oWQq6csRjvu)BL}?*_DYb9T}R#tK+zeWqKy_)`CB z(pWORU*i1b)(!$%n3nzXUY0bB~#A3^7iw3{Ks%|s0u+Vff(h8~YNK`~e zN{O##3kPi*$=Y+bKwqM`aXA|NIyiN}rO_g4}C0GSY;nT?Ih(H#dlq^_35 z&0agQ{sRdmWnE{^asNJ?g$0fAvsLa!%Zqu>tH%-0?Qv@YkG0UCYN0BviC88}V1LMf zqNLe9wjexhaosDrNH)#d!UEgry|wft=qKWMP3y0ewDF|mWETe=c@osj{!RRJk1Kn< zi}QVtgR^}nW;H=S1^}S1pL%YQbAlxU4bP#yscF%oeYv!a5CL&CSksFIgw6bovcmww)3ZXjoV+ZifNw?bh}~DP@ZneD0{1CnrO*T|Q}y zMTEcEB&nZerb19WP8VL1la)$Ktr9T@4LXp~!uwZR=fy=u;X7=H#^2O6HIV_2it1yA zHB)Rl0>`6{)V$>|hO)AA5fSNcFTPE6br1ktIZpM1W(2yuin7Ja)KuJakP!i(`;Yg8 zkX6y#9KBN=H+ZS(p7NVbrgD2NjCnZ8{t~f(f#FtC%2UcQla2Uzcjr<(mvnim-w{=K zaG;v`(IcvF+FxzP zqR3S4yXsooC<;KITBeQ^yXtIJM6{VD$s*k(;_z0qPMSeJkKoH$QYqJj7&mPu4p zl;#9DU6O9DE~IV!Qb~S(PKb^^w8{JU$gC%<%8QUGn;C18)X@CYJ1IrUje zS;iT-xL=xI-=0%L^Vlb#gdq$75Jh(p5Dd~lEH7Uk0W+^+0u2pw8@m{+ZEa;`q?+Db zNC70wG&aH0b3R_L5CGF#(`9;xQIEHc9^crQn5{89B|%>@N=mcGr}u-sE4q6gR0&iG zkSPgRMO+r)VUUv2N*@c*;@oLS+u9h#G3WyzA%ka&ymtWE#mxy>Ss-O|Hn)+= zGJ+-f9;b}F;$r85G$TL0UqKE^tSogQbB`7p4399;gId2QxpABtBI|aeM1<}$V@GK& zhy;cl6{HDv=y4$_NJ)DdIVkFaxKU4!zd@3al71WO5jH=Rp`s%}9S*8@P)vQw&y9Um z=he66NXyFd8;Gz#N8bSp+ofSs3=*A~I15SPc{m;i21Zn8eLX+GP<(<`#*)%G4wYUOBlv7>ZPPfvF1zR+BjR#sIn3sZiUGT#kZQkZdU=jME^%*_pJ z)OB>$KgX0;j6GZkwygDA-IwEq+Z zuwtZ}>4Q=D=jdBo*vJs3E!B5LMQuI#vhs4sQ*`D}$Y$@O^k;a`=+HA=#1aSyH&g>d zDp-dBZWny4s|j;5hgkO<3)ry=I0&7XMft|~c=*|6^xAh*Ufg&d5MvO~Ffd2yC3sIn zyDvDfOV+N8fu#ODp-L5gI~Ny)h=}k~l6QC6s$j|YICoH9x4yA4B^4JdnIwgizvG88 zE|_FQYgT6fohM+m!EilvajEyT^n6tGdeI>id0X^imD8>IaS+x!cg>PDAJO38;0G=; zR9I6es_=gP<0+@4G-`bxwZ6Wv?`g%k6y&!`3iNE|y%B!RyOUa0Rs?C|rYy0H1-U!T zH1T(F@vMr9tUm2(C?y~Ku@5a7vXp;KR9D!XtEe>aXyOagI#gEA%~Ku3!rFQdkAnW3 zlTxx<f!Ju6L4^W#=REJG{ut;B5qhrJ%>RygNpJczAeK zWo5^_ug<3&o|psC#HW{wU7fN8jc^DEU^i|0n7^@c!PS-H%a;l{x&;C6*9b%cSSXDS zf(~Ree9EiqYlY8m+i(v_wXyg&pWqjk{q5a9#Sa@Z;jR_?IL9YaaL>u#zZmvQ#9^Dj`d)8G2Rx9k?`WC zBJ*9<`|ZBBDm=DIoHHXcS5}W$ z;O;aV8=!l|^ZlGRT2pKFU^0udoHF*ai80$<-|%dTMitoJH`xh-fmOiifGu;lrmt@f zY|Jr}V*-V8JH2Tx9BnCRVC-BkZ>sBYfS9FWlzOO1np(*5Y#}&Z#BSwdG@*xqN|Jrd>nF%4Dn})&r1TMBfBwwR>2}%B^<;4F-?}2g zuk(erp}%+baOv89F>yod)zzfKlQoXmYEY}DM!wli)c}H0S3;sVKS(A=xuCEE0U;_O zA>q67C-H*DIiIq_3-jM>780Gv84j;+?U!pld-aCrrR-_)KQj~K@Ow>E6dW|p-kNV5 zM|y-wwVO4+)c*>XZ}%l{47j;_4}63{Bm^^X6=m-XGgAUz9x(e0)z)2}pO2jI+#R4r zg$ojw&jhC%Bb7tw1Ox?;aakBRCT`-6oGZK0JMnz`7=lkHj6Yi?B)iMU(GJ`*9md^ z&ST9}zR(=8%RRyZWX&!$Ip@#)l9QCc;ZCbGJ-pQpbjKmtkimLd;=-wosxn}xZ_|wKYm^t{I^?Bni2r|nE zroeoWwqbuHk++A`3=?y&@!3nupbb~dl9G(9-C}n|JUTNmNkv&z)#$=^yZbBamoIly zF@fJm6&T}Lm#iDp(`B|)i8FFmf5E^&{}DpD6tuq?UqulWEs&6s{a#&E6w-#hbH4v{ z%vw@j9w0({15|goT?ov~B>IFLGPs*ZCV#f(!Ug6@JLoJwzS`>=T%PZ9$N6m$e)KUq zGV^*9I|Cjo1w+sDeKb*`8Z@{fiw2cCX zZMeBFAD^C3E;cVZNUK5JEj;Z$FWXbws2pivt3-*900l@_qqniO?Q}jq7|w?K_N_-H zbHcTegX@!RS=YnzQ5g>7IwmG+bv>J~TidVDP|s$@E)Yqk2yMIHCHf>!pv{9EsN%;< zdplIn&!1<>429oI?YYu}gJ~!K(#$(H5*PNw`AoXZK1#4vqNSor1%A@_*0XIN7%gz9 zeB@_o#NQR5=yE>r7M^T}2oK-d#yyr{6ri&E1rP7|?FCW}TD;;Gxo_7&EEqP8v$ChN zz7Z>-)Meubn3YY8p641>I>^U-Nn3>ZnXb{WfC5;nFNt3$cN};Ywr<&ti&J!*Dydsv zcW$FpU4`_iMkk`8qVn9^iZY@mcRdrJrKCJ=UyDK%B(#a_XnW1gt)l1{L&d_;OyJ1?~#7vRVIB2Flo7?udm0{krXU2`#&>c8hW@0;?kv!c=i8whr zqCkE885Gq0U_!2LWwpBXlHw~ykB!(-bP@tSd3J7s8k$$pRHt5kb0Y>*X);Ykg*j%k6Y>JeOEX^Qgw0)4+`RHdOymDW{bP@Ln*1MijI!9TY{OD7%;3!P17nUDCpFi_$2z} ziwzmspG`AlULKzQJ`o45Pif;s9R9XEgdgnljA34$pF2UH#n9alHy;*O78pnw-rrUY zYShmOGXzsUW20f1v83dE;)SDt%lAW!AtPh#8>E(!j&5;yJCo1soqC75zq4vMS9}-) za%FbEAYy-VJa~@uil;ul!FUA2qJ>4tph(E;6#~@zSK`+n0*_EWS0A3mo_=)tF~>~w zYwsT(x;d+}oK<0ceKD)3tQ7e2mUxTsLb}mabav*JB@plF<;BiEPfvf~*mVDmg0WLpQp}#KtzkNKneKlml1?#5Qz0v&KoT!NI(aFicC(v&&bqBW4=^;oneE_=x z{~R+Q`j{c(u1(nWRR&{O5vP6mlaD!v!{xJ z&JxFpE7fm*T&WBknh1#hs+T2%mJf14}u z^z_17ORrmbz-v@SNT=$&xp{GGD;EHe#Jik}0$T=tEE}8Wh;hfqjk2S4;MCR8J50q2 zk0$j;fIkw8Kuv3_>+C=S{z)m=QS9=u0s!{*+E*K1e#Omjb$!vTsIW=%apO=(tI^HL z27jLKa4=+#hmZI7ZeUaqF%z+vH}w>>y?5#@;!R9Uz>(+=&=+}%TE9d}-hcH?m_9K0 zm6QEDR+f#l_2}Q&7<|$P4-Tv-70H2pg3+O|<)gY_vC~$Zm%ZqYA7B;_0BGPDZZ*EO zX|4`L#P;z(Io9?`vNT*Gm+Y=Ih3 z08|{D)w&0DB@7j@;9po|R5Uccw0k5!zN$0%U8H+R&&=pmsCNQS?%E2e#9ly4uz+f& zth%Wc8g};4X#@BLI7s-v$8i;8NkhS%$C{IIG+ubeiWU38`)uxXYn&2`PWrjD)bNcX z3)tT=o7AgxcG|-Xkn~(p7wxNOoBxjgF+OtqRU8~VynFC{xi@m-^vNmEaB#p&8<&&y zx_cKU0%XSr2Qh-95Cg15Mv?yI+`MqQJjRPXLJ_-^WmziR_&c>mtL5YX_V zDWDmk82|tZ!CZy~S=IT;$Id)&I|XS`a#q@F?VetE;Ph9ukbf@<9szQ6FA;KVL!zjQ zi;W}=HzoV5`++kU(QSDGu*nppq@)zVo1{Z}$cv-JF|#^ipQ2(N_#V3L5~Qe)Dk{`q zH_L!BFI2iO_T&}=7BD$k5||w&mmGsC{DGX3(xS_Gnk`UL{mXxc&oi69VxXa+IX+mw zt3JpIOGDkhVfFV@|4zjx`H;_i}PE6|G`1h@7u)|(e#(x=jsqYHLg!` zN=i1bk2UYU8~)^Ad;9(Smb^0r3=GWOW`!S%5F|iCQu_Gl_%)+r!o}t8a??-OxXxc9 zK?w9$1U3#I11I^H%9FrlP=158n1gIt@gfx ziVCQ*sNYBmt*xyLoDWJ44$ELaYuTD(2S$HQ9R~8p)zR?nh~K)boGRj%ogEA?9#>?0 zcYsKIdxS#rlP%Oq{|n1Ep=LH0>kb)V;GpaDOpTDc2M5hswvx>z)2?Lpu&tdN%*AkZ4*-=V(l`;iC|nbRHc2D5ezBtS+3bbIvAG+1df>a1ER{|97#OUoP@EajOJqO~Mu6eLlfunOq6qHPZ_6<#L;6z$b zQ1E6hI4zPQbI|pwtM(73gC0E?tq%2Hs|`dEll?6a_TvgDW_$Y+{GkMw_#bZciCFT9 z*uP?&|KA!Qlds^Q9ypQY6^t9$qhF)G#7czqUR2T6uzTJ>y>3HDzTp3F#_=rf4}A5g z1smhLyU292?1F-M^TK`N7kT}Cup4BV(|~b*)}_|)RPZFPSYt+BT318K{|Xzq63k5! z^RMyF>(2&u=>cCaUgST=IO-nOE}xyHYnOkbVac@k#s6}t;&DHyc6ebh`4>uOzvn)J zzI40?85{osdm%?vzo7t*j*cIZfMAlAn3QB?UhL}ZoRpMQw;6>?eIxb5yc&+rQjcW*A?0qK^CRK(P^9RXN zG&Hze>V~#4o+q>&8L$8nvrf*AlqASsbq7RHESo6EoRw7GxpJfb9*eS~V*miE0kM`#K_{Ysvvjw6X`He$`LPL)4*+nO zKdav`1(%?)$?fs^qP(bcyEsc|VI#NT(> znDvQO47<7IXme?56kPHQ5VL`?c0D`D;}UqS3gNI~WE=n0u9BKLx(ZKD@wb>jg5nbY zqv_8|3a#0mw{lA@9v>h70#5U26p9%;in`uwp*-w^1zA!ipAbtb;0Y}McP#Ud2wy3G3_qHuf-Qc1#=Ih`=2JnyWPWIXEX_sYC=iSh(-xOaiCKeQ7FKA^n zK8Gn(H|Ua5+MHSCU1uN^+GWCyPxK-uqJt)zL6?j5dW4e*N=5h9=y$K3*R=y%3`Q|C zoR@^cj#;L(>E$K9Q_hgkLRbvhk8`H-7>P;w4fTGPeXT)%FYRX#ibTbiipkwfD8Lf^ zy=B$>?-zNiXW%e6dvfU{IPYUMHKQCKOFEIte!Fn~fuElrER(d~xDbG_FllhkK>nwg zlcs;^$x15^h5hu@cUft#yT|KWFmEg^#m5expPdbdw1~^(xJQ60Wvm2PHH?nlOQLH6i4sHD`1RCVW!lfNqg^n!q0v zWy}x-XlB-!3b}i?ZwhZ+w38urpL1~OwU~UvRA*`sDNF3AQ)Q-W(kcHKpvY6pEcYZ3 z{&jraq5|lb_D~22bb^WdpFijrM#kd8 zZk#&m65pky(BI7XoSqeVDf*V%E*~#fQ4$j33i2tyQ1bBtKjiSb@OOt#I>4OE|Haeu z2?lh@MPivte;#^%hp)P`xZ3V#4g%dEN1y0fRe{Nydp zFhRRog~mAopxNhed)7=+J-MB-r~ndB{G?6Ktcneo>euL>*5HzsQ!04eKiyzx_5X!h z`!OdQDP(Ze@^h1)l`+e+rq#({MDhnf{XCmK|21m(H0N00*~)h{207o}^A?USXgWOF zPjae80ef66dfw~JbTY4y(5l3B(Hp$Si+WUFm`^P&x^`N>fFw`U`R^_>c8kmne85SQ zZ*M4wf`-GzadAmA)3e)$AUZw*dL@j!(i2U{ANow9DE4fl&SD!0qNffB)@XJm%Nruf ztcGg_NnhE5IT3pGG&GO0x|$SCh4G_8X`1N$} zg2Qs~!9_&m%jMVq9A!ifS#6lT?Cv4)`XCQxw&2u*cAG0si13Vgp7jr1$GOYnjbF_f zIY^$-2{TItJwILpAdN8h&*iLTxn1^C2jw6Pz9pu_+uYkh10>2KICW01?pNXi%0?xM!(xj|BzY7nWuxoHL*fV8N%CKP~+xa(zpELEdKGVdb}B&9mLL z=X?HrU_3v+c7HIkn-D_>ej4jqvW%u7tbMbdx0-2Iw2#w1a~I&7)sJE2!Jm+1LYurb zw*N5iO+T&dD2$>(W%JY1k|bAo1{jTxe{5}S!MV)7TTM26Nf|Lc;tuie+L%tjvZA_h z68c|+@y&7wH1Qlf21h)LdU!TMuNu>BT?Pu^QISEU|(e{C|#okRi!m^bH)TaqI;hWB=Es z|L+~~`2#^qZJ^&&mwhN(Sw&wWW>g1J!V5^?fQW%`fp&Pm0%c*)m^0JjdDobVY*{mh z&kY^@*4~_&jF(ez?OMi+lh^vkNz;Gjk|E=5F~$%F$XKt;=e`Dqef{xXU5^56Nhp$6 zF;+}x;P&Yf9Cm+xwHzh(+FzgifcSqWD+ULUJwz{-2aK%ze z7r!1o+UCM~=XW1c1_3!D+Nz4uarJmoltd>S{s*=>c3iQK!zIIOQ64i3GY7<5#6)Ov zaCn4-Z^YV9q%nPNUl>zj*NF$vx0zo{=a$AlQ6|9&$zg8V!^;*9k4SMy8p zZ_*=&xj28YXhI@Eg#IHL30Q@o2J)cr$q}GQn zR9I9rsg}N2+5oOF4l@_MIMBAc6ki$pd4folM|1hszS_EKLTREwP|Gl{%_4`JEKa`} z*Ck4U?m&$mY=G?Ts&D9>TTmnFqtszFS(&mfQZ&!Lz#bJH&4{R#^x&IWHI$6%Xm_ML z{**cqCD#QIGznv&{PMGHoV4Wbs;$d+ zQLsCUm(WS#xA31&=m#-OA;7xB7SBmC?w%NbK;Rs5^(351MOMn4;4hD@>N) zy2!PbiRqkkE?s9n5+)KerKo;G?wd<;s=Q(DZ8pPVJ}o?KqNJ2~$yw+9WhvJ`$4LjO z!_(+BBI#}1YV_DRL=0!A=j1`@UwBv7rpjd$Do4}{EY%XRlN~3w!uqY5<#035m(GF} zgk?=+H9b>VL`!B*Ry0?d>(T>ri|+^)!~1ggV@DV5v>B6rWq84taO=glvv5;>DY%t0 z^U&ZX?epC9+|v^m3lXp5Gz|#~PUrEJny=iky(NM2f#TQU*WlK;K|M4}#7_+F(6Vx} z()83+m0S32P=1s~cHzuM@%P9#n~s4aeOkSZCKB*G=u5eY-)Cu|mrO}$rB&Htf4E)H zDOD1o+ZgqWMn%UVZUR-ku+z$p(3(w3C{k67>WIUkA^a@pFQCektd&soD-hr#f3S$Mns#>ybvJZFNBZPJuNLxd@@HX7iy)ATNthx&g^O<(Eowqy!Zh3Y{(isC zzxn`<%>wHm=li`L&gW5%Tr}73l1{OT=y;q7c?C9l2>mF)`W`2W?v}HC?H&jf$eKn$ z!PfT_7&B#(gVY-l9W9M53Ht)O>HQ)bmb(b4w6cg)vJ})O zh>rD+HJZQLFQlQJE`7y}Bm|XTZLSw=w3dB^6_iDkMP}y;nC4>|Hah+l2;mNzjV8){uDfHZdq(q%%iryyBpuZ%*z9w;+vic6e$F01QeVZ zw)4YFwd%61>)^fC!*YU2Um~@cnORynHSfFVs{1#KP4eV6-7qI!5~gf@vv2(+VZwfb zeM}K#nz2n^CS4|WCr5v#4j)vcjY^GlE`ffk)5|GSfl(ptF3myDylGkdA`%w~cF_O{ z2`K`{KLBhr@@`%YZ3cky8C)gOxLh)+GJA%s{cD$SHyxP9eLXjn4&~sftMPxGXUQ z6ai?k5ls3)5adX>2EXsfksS4zjbfOTLQ;6f<_rpvSzUgY#6yM440NJFe~WpEYsMtD zZ=saTC0OjOwf;F?YN+B&P7Ur+|3_~W4d>S|>Fb3Kn;w4&&cYy02VS>^y?V)i;cG4I z%#p;<>GjNfJ=zFNpn|;Gv1#`{GHhQ)n-;wg-g+BRmRq%peA?n}or>xd|G(Na>u~cg zDlc{id5$etxQMLG*P4G+&dA=xx2Ca6**3P{7N(_cxx zt8_fBbS+}jmuq+axgfrAtLNOviW>O%Z}7*?=7kGR{Dqgr!!;k+B=`c zO>kRDkl6V|VG%w&Dd9PM(jJE-LkwSXM-Zu2Dkm#~7%IJ=_G3IM%Mn4CXu&~+7N*os z5;&X*J?AzCHAWqwO)!Ivn+z4p6(r_&&Ar{Tvb$*YiZ>p2iR9pvBXdTPi9^hvGMA`Y zWDN@~+FP5(ULo{0S7G>3=3q3Qo zY_Ur7Y!`Hu4pRzEIwN81jr^yxt(Vykw( zFO=1o%Ty@LdVy!+hQj5}1-l1~6`yh7go!kC+;$diz0PYzRS>y5gE+5&cVkXzw-i}! z_BXKp2>{6o)l=tI@Hz!ons3{?dsM7*fc)nF3GJUjY^hu{i<_@8t+HCF5&gkYu7@M7 zSQ^uxJu>^QLvJZsnJGU_sw|Z|C$bs{^+*GGDw-!AQb!JF=LyjxMa0F#!owp`;UK?} zz$GL@7U&T*HH|5j(tjU$ILiKTQuG-z(^qT0_Cv0)RFYU3&AjCi!Z%do`@%KasnIi$ z{?dzg4I~t0%$xVy&zJ~5g$lsc7=O1m|4+Lw|7Cp&0uqK3bR;b{eC2WfQXGvE|Dr72 zTw$S*AY^z#bRG(43GVs-T`T9mZuTF{$p7{WfUj|uj(In_oCr*7o#62AV!;+lqeNsR zVfr!2EG$4E$&oKfDhy@QjVU8+y~}2Ty8>?`yi%RCPH+0r08y)u#sV%VA42MPK*$#k zFD>jqdkBMWYgl?CtK@;)Nq4lMB8qK5IdL_`Q}<|ApNKP{*U2GM%n6Suv?=G+#tN+xD&)j2+LK(b8$j zbiTdZi;52W&7BUGqZQ93>qUiz(=9cmu@ey&^*Zd&?AIt!`!OBM_Z4MmX0+++KF36` ziWV(>Zuf<(%IZF)zIujl_sylL$};y}o4}uKNV~Mv$dfxB@swBc7SQXtShq7ZLxhH0 zKrDQae}1*;9e5A?AS%XjVs}*PfELTblgb{TAV#Od&TfsuN--A0B>V>no;9CoEJk4T zX}8GkE%R4n#IRO|fTPQ^#Oyo^nWmt(w&Zr#BdM}yy}8c)%a1ReewI$}&)d5=ceu4K z|E-h9Dpy zIgBKUL(Xwq*Jtfk-F@%Ax4TulRkypVyH9tY^qv1d{h#!$PkHzS<&9vv5WCyahB~T7 zJu_ksZdF~~O(3&k!$#?Q9<}PHt8lW-nOZVQ5)?95Bl%o+6LGLHY&)2>!UL6sTWZ0I zj2NFOB+G2JB_bVyme)!|G^k_(E{XV|+IBoVceGLJo-$oDYDF~%;bp!;3=|P4ilg_q zv{4_{_RFn*fsSR_d3HnLn+9vfm7$p)-KgX$W@vi&(q-Y3mBm~F@PZRC3rym$8q?8@ zT`26>znsu$|8#h`+{dSk`|} zX5tdcAQitk@M)@H9;MOOnaU6A3!M{yv1=sBfiV;9YZ?ephQix$260D!_}8A^Wt?ggBSoir^DAWA|G~X z*e-#V_YCxK1dF*_UpVvZ?2fRc89zS`QBT)`$VyG-g|V<+MrIr?F&%@z!TH{v$kn?O z7>C{4(~WCGD}wdT7$@;mI#kdE{2|+Jd$j6i7(;t;Nrg(5rt^prOO%TB2ufqL+jiPe z+}8W8e|R&USjNSmk-n$rNXbmsrL#v%@wA)j?FwOY$nPMNK!0j-a|pMH!pjF=x|Gk@ zIlkB#h8xW@7u32|`Q^|yD-YbjT>8i|0x1-nxOov%sjK#t(>f$ze(GtV5VxAgCMTv+ z&_GQstj%O}way5b1@I)wun}D9Un^@Bb8m# zho-Vs#o5_xjvQ0_mrOCnHgR#*(|g)|@L8=L^9lxFQTBJ`&tku-$z_r?WHu|3U$BSs zYBU0IlxMj7=&^mk(U)gdBKu3@Zz4I6ueV#m^6nxbUv$}Gs0mvNYlxP3;b7*(hdGb# zl9P+upqp5Pw3CwxdeKPLY|Zxe_MObU#yY8`IR@knj@l0v6%zE}u1=?Q>UrdN*B%Gw zNuQr26%>eue^1xUU9I+y%kF!T5Z3p&KaI$hpf_I@hre8|-_2|AEZXbr($d?}kucN5 z*_TRgZr-zq!Z^2A-yl%;+$V8nHLJEoBYiGg9F_=QjhrD(QN(3sWn^SzB@KfPZIsEu zA^m9*u%olxFe#6m>3Ui9go5#!l1C`Nn`56X$1EZFnu>)_a@A9e!%oG#=KLj97$|5@ zABi|_cqKH?5O!_u3hjvhvO{}u^Dmko!t<6UsiTVYe4_8aRNCM-Fc%-dHeKx?@Rb3_ zN^b2tPm_y;CDn<0nfddTqsNSJQT}&-ljVDDd`UgD8`zX+D){uhepRgPP^+RFe)b$D zg-j=L6AsRZh`)#D8007(hThar_vYZ>$k#4>I)N+8oMB`JV>sK8=-dDN3FwTwxiOs( zl}JrCFeYOhD^FJYe9kN?XqrV^Pw!QOSN%uhM|W@a)++&j&h)fw@-Z&eapz2XjQqB$ zlo8CMH=^eoDc1ssWHcnf;dFDxn%layF1~Fxw&#TvFBPRmNG(Ura$O^o8x0 z=?ssB4=ok$=bIg#pWoG{7Z@L=WtgG@=*+a6_+*_`9vD&emEa`HK6{$RmEP~+_|q|6R#L%4!5@X+t=$46LUc^d+yTwb3>q;(d2=54tuLuO6uMZ+uZIxDFW{!Gxk33|Y z0m!Itr7ZJ@tIx0qjIZ2#6L5O(U&;2rWP@ZeN<(_x;^`TRgWnd;%@(-UaxxU3+?3Ma zZ(dIYC?6JSQJc;ZFqpxZie*h%w6)|}M;i$a`D3|O0>veWNZa_Wf9W*m(2Lk) zQySUll* zcldQ$1BJ|ndSPRIsAat!=H#*u&U}oFlG7fpJJD6tUI^r2V)gfrBqf)Zhj4(}Gs>(H zHLg>J$op7&*;Q^83Q%^?e|Qggcb%H~#vM*`YKBZmA9Zq=9J!rPQRA(fI@Kf7F?-Q= zwqS^EOxvKf-zVu~fTE{UU}HBx{)7@M>`oCAcNuX3 zXhV73I;$?N5H0cX?H6ke$GbF$-?{wx5+Ck}V_}6FJ|7sP)YEH7OFvb9n(Q5GD5Vaf8=)w?&OS)Bvz_cUsvp~V@hbr8L@ z>qo2m%|mAgd(=Zs=nA8~=7EKVSrxYEwHX6F1Fb69(#)f~thO49xr`A9b?)eArzfq7 z1P2(YuT6_l(C@j-K!9a}yazk?Vi>0QggLW7mJ_8s2ITn#gU$yDvX=?rf@*rm6K&I| z0h`&4wCD)29F&m)l)?sCOzt( zad>Yrl(av;e>)pr$ZvqpGI}xmFx;YZiV;7+x5aqvz#y@T)I3Dz;u_W)&x`{f(R!eq zJ6kREZ*b5AZJ<52+M)5h&qQU&gFJTzV2Nc!2#pzLPiY@FMWlX^X3-Pv;T$5{;j#Tx zAs_%i%Jj0G04YJ`?Aw>TyIK79CScKZeFXP>%*e>7$emcI#yi4>Y1FjOZyQZ|@1CAx zf14u8uz88;M`-{(c(P2T^MxZJ&6l8(D_FA9kDp|_Rb+OR6&Dm}ZiLm~b2#V* z8qamHMqBey(NKPhfhz7Vta2rk&`H^UdSb3y<=)pErN|aXxstT zo5I4l1ccf2_=)1E?R~R|mZg>0=1U3#pR|$`e(hp=HiigxiY}$x(YD#rry1vya;jw( z?=SNXTBVGyVY#LtCkBptMbG&Wx>ve<2pY&t|H+ zm%E>6iamF;8id{)id;%LNNF=_Ch0$p()wH5;Je|+`Zq@jKE(9s);G2oOJm~?{C8++ zla*uMFm7Rce;_#u6Z1YlKesv&WRA+qR@BnWh`xTreM9%7vj%IVJTwqpe^_*jRZnkb za`Khld(ZK5rUPlE zHK7D$Efbf(5_5cc#DfED9eE^BXhLM!Cb00z9EzW0Ydbw|`A9r-*=u}KWukixBGi(_> z3DO!W;s@ycwc=59UQv;YgNv$)xNACC``I&A@}Q9-0(99fk+U4owHd_V;!-2Ex%phL zwbtvDIGI?_G6<4ssiv%4Qc~Zt+W^cZeRbH!p_Kx^D=nQ~og*zS&fom?)0^@4oLuHG z8pP!nz95R?_KAe!!qHA7n{|ldJH#DcZ`yf;B@mLE2*pBUNLQkA3xQ18u8% zvTX5E1&3^p*Vwc)109|AVn4v72#uZP zEK<*%B(ExZs0}Q+MAOsL2M4Px?1*NTCBPXfr9NBeQjilnxj5C=)s+i`i9||saPe{= zUAJWC^0gQ#9)BKe*Tu9A4)Oz74~D>Q1@C#C9#Dlf9=qiRLG1JaeoTQ1P5uha{xq)A zii(~tG2lr61sO2ZbQ>Y#kX{+NbQ~V8B!*1v238u~d6HQdWIzh^-elya%bhn9MU9Mx zWBlS(Sf1#{6*LrK)nklYoa;)1N zvoQ&MWLe}h{x&d>lniCZr2u_)F?AVCukva%ux#aM9kfWf5Zpdjv{T!s-uU*d1lj%p zK7ni+<;FBw)R;X*3BYr~nuS=pY$d*vwiHlvkKn($>wsN22<|Uxh0QuN|4Ao7V+? zVxYzK#44!2U*oYRPS6=S63kXy6Mv>)P2`nVZFM>)3X7eAVd@xUc0bm z)~#T>x81hzdy$=qNg*d^v6G{uZlimg(+!}T*f&%qu&}bFrKh68erT|~X>)yjV?)|V zU)<}&Xo(k(&T&iB0Hm{7pyQ1f#&|r!4R&0BaH8x`w=7kCZvzX3a&lpl6BFL0KDH3} z>k3Vth~SWr`&90lS^^tWNLq#qgx}kP%N-ngl+(crc}NPQ^J`ggav48E4xTvqxqQ&9-q!?{l&7Y;!ZLyvvEU2G7yjBlprj?M8sGe6G)c0xcRqd|6fYhu9 zhC*0rG+CIFgso|knE`A~qXGTO%*0N<$Y~+Jrb>EGuJl?9x!L=8rp^-lpN-~Ub?1Mo zNdG4t?uL0 z1trX49ILPST)is#X8w{TC>MECAXSuY><#@gjx-e_tFHAO-|I)*?FGEP#t2Vx@OTV< zvi4XHb5CiWRU|G#(ehRSFQ*W<_0Y&((w7lPW2LgY@?cCFi{*Kh(6hWM7;^9QJS++= zwv=wmXg?Tp^%v8%rjzdzU|c{%ZTzB-kFclQjLX_?yJllU16U3lr#ZU?%gmg&4}`Iw_N3hQZ-^ zR$&iNJW@l>8&*sV8l7bYSA$Hb0`q^nfun%I@QS6Xi#<~IAz6VWB_?_urXF^nObttx zJa@Gcc$wIR%|dBXHnM4*YWh}(LqtERefTP+v4gZtWPja zbXH3xEEJ538@RwqMn;cXzrM1vt7dIoRGz=U+f`irs{QZN!QeBcMms zEtiq{*CB7N{Wu)IFdfs<@EBS}si~N|6N)&knV}*gQCcJfq8{qreT8NR=32*|?1ZF&J$W26>k&&~t~2nT zC(f^KnMv1`hXmbpbeXnXm6T5R*FEu{}!QgD2 zcsF)gd(r*Yj=&#o>f@BQ{2p^!h!ex6$|}h?91d5}Q{x?WYbYN-7?w+OH)7k*)$CrY z?{}*yw!BOf3^bw2VMCQaWI+I*6}^aG^*Zb}nQYRpI?B!)U!PFntf_uU<@VxMi~tzy z_;9Eih)Xr@_$F3$j}|jRGRVb-FgPxhGzFc zhs{*)w=nmL*|88aeQd%I@C}8Ws zYTFSN5WwI(?n>wKr5#5(W=H3wr1n$)e$SGKP*VRx8H6haNolm-cx33wdw6bGodUDb z@9n4x1e%bL0FkUwtzMdFz#%mdXcmg}5GKnY3$u6<`ryaITa%Gf>oM;^44rmw-U~ ztZg12tkq63dnk2C+aA}ZOH(sq{VcC1q!5t5hRpHZ)C>NNRxWK`R5lzA0dbIKf#(8T z(D@Pd5|*3GE9+Jg-p|dQ5AXoQ2%sI7$Ls0glE8K8Pm$Et)Epe0q`#b|juv2r zLHZ(7Kw=7<8-y!zKo9ib=g+UtC!J&t4i}%=E7S+JJ-9fx-TFM6nQBzE?>$;&YvyTU za=$4ZD8?UUWeI5)${Hv;H=W0w;|Yz}$S?L5@c%q9v9qgzeoNZjgE&7$(5tGB0#wFq z>=8s~$FE$VN_Ze0=&qWEk0;4bDFo#0rHy-Y<9SFefwnfU^;zJ=M9q#2h&4uNZEYBwZF&bVobf)2Tx7{09u6HY1X2rT&oLi3{KvJZ^;I1YKG$StEi)Y?Sst-(7A8|uR$oh z->7M%UQ|?6Tv}S0SBRBJSz$0zkd?@?DbUf?bp+~6j!QDaZ}dv6NHI*$@`1A1oSUQd-H{ojyDl|I}gc8y1Uw%&O7^> zp9!uCHuF}CFv_?&U$zXvYdw~pHWwuA8g82TTzWJY3?jf_Gq)J+MqA6qF+v6+9_7ga{^S29bpN=%_&=_D zf3nv5XL6C%?)SYa`>6weUH*R|!R@B-lIBnS3I7?H`0LwWie}j*_wtwH@7o%Gq4uu; z#VrOQ`nx9FU$Fiwu>P`(v+m&L|8o3=<$nvyKZLJxfl25eHADW;<6qXupVRwzx-6Xk f2LQ%XWFfGzDqP(ic{qgpv4BlkQ5{??Z|wVT^Ap~q literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/message_actions-dark.png b/testdata/snapshots/darwin/message_actions-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..878585a0fe6739a9f6f57e92bcdeca5d859e9573 GIT binary patch literal 2824 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 W&c@He{89>=Z~^o+459+=^yq&r=t3R< literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/message_actions-light.png b/testdata/snapshots/darwin/message_actions-light.png new file mode 100644 index 0000000000000000000000000000000000000000..f31f9f05d62f696a320be5044b89ee3cd307fb31 GIT binary patch literal 2783 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/message_bubble-dark.png b/testdata/snapshots/darwin/message_bubble-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..71d3f9ad370deb99ba520dde4404e753a4c0f8dc GIT binary patch literal 17251 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/message_bubble-light.png b/testdata/snapshots/darwin/message_bubble-light.png new file mode 100644 index 0000000000000000000000000000000000000000..fd189ccd2b7e84628deddf41a32e3f7c516e9c0a GIT binary patch literal 16414 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/message_editor-dark.png b/testdata/snapshots/darwin/message_editor-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..b61c1ac98c724f3b5087b66999863e20dc5e7f0c GIT binary patch literal 8615 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/message_editor-light.png b/testdata/snapshots/darwin/message_editor-light.png new file mode 100644 index 0000000000000000000000000000000000000000..e6090721e8dbaf92a66e5d421b1295d02c0ea008 GIT binary patch literal 8260 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/message_header-dark.png b/testdata/snapshots/darwin/message_header-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..547af066146855f64c3c1af80f860a3e9b7ec365 GIT binary patch literal 7421 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 tb|Ss{FqFY)lKy0pk1UH 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 RB|}3U$_i@owLtT*{{Wjn1+xGE literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/message_list-dark.png b/testdata/snapshots/darwin/message_list-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..085017048b4e0e184098b36a471d8c6eae589c0f GIT binary patch literal 12244 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 a$hut;<&wN^!FTK5ke5*bmAw7%@xKA{4=XYN literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/message_list-light.png b/testdata/snapshots/darwin/message_list-light.png new file mode 100644 index 0000000000000000000000000000000000000000..1853340664c715219d6e27063479003b214ad6a8 GIT binary patch literal 11756 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 CFGyzq literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/quote_reply-dark.png b/testdata/snapshots/darwin/quote_reply-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..dae6d61ef603aac45e7bb12434a47e28c55dd75e GIT binary patch literal 5002 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/quote_reply-light.png b/testdata/snapshots/darwin/quote_reply-light.png new file mode 100644 index 0000000000000000000000000000000000000000..9c4e5431a285d5c6ab269a5ab5661a0313aaa2f6 GIT binary patch literal 4881 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 W{#UeYatQ@>Q5oo%fU2|{V*UvohlgSS literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/scroll_to_bottom_button-dark.png b/testdata/snapshots/darwin/scroll_to_bottom_button-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..2213efe07e4ed8f6ab1a21ad0d472d90c13fce2c GIT binary patch literal 2053 zcmd5-`#%#3A6`efom^fO*}{=&4rSdeBpkEi65qzF_5002sGM_adD zUELiQ`CoSViBY5x03bIExBbH-o-CZfp+SN@a;t*&{1s<6EGz4ZZ}+=G!=b|9Bak`Q z%^;mk-Di#Xt;U{Lg}57M>C6Xehl6xvf8_?wG>$6Uzk8gFdE3Kj7&|2!y#KVfW`si2 zmwtvsT|XL(C_KS!2!+R89-#;l-9jLW5l02moq<Xx9o7%AvI9!rQ>Sf9F zHz;)KBUDgBV}737Y?4!R8XVEdl*YY?B9Hf+*HVTbv@ou1A6yo}wvuL9G|9T8gyi1j z`@_O~i8=x-8!BV%2)fGY^F2?fR~zoUl$3;&dxvD7wcXpJX+Ep1@cKx#&J3Ac`Y?F! z6|J<@i=}#44xbpy>P_FK{M1|PtKLbn$Qz*>QeUfI{o5d`<9Q=Yg9*ueVGRbGmSiI| zi(nVIN1By6R5Rd8X%VWZsGWvE$}mGKFv!y-o*o;vmsD$LH8^FY94_~)^M=E*8jUNh z2e9^)kj@VJlP}hnPBQ(yQLJfl^BsAC%`++go?Ve-P+96-Z<6yVmbk|nI z>C19uI7JTc`=4X?E2xX^F?I7NLlZI1u9M~HDoizigD=bJxoaRlcKz)H&)=^0mWE5A zOyiNj7RmuTR|~`OVApqxqM1B6p5Qa&pD3VBPh8lHX{o#l&Ktgg zZ%#5l6F_&*(&nHpG#BHU&|;sU7D!(G{{3Ah2|c5J1((^0w15=}xcmB#ba6eK{gc#X zl`s#&@{{3VUYu=9uck=sZn85AIOHI$iIe~8vrC(cq4XQ{tMNxKA78USXUZ!o{1U#F zFjFKu?-N(GbwAjKpCh#gcttOrm_6ntgC?aha-lrqsNk6FNo_SBWxx34=itn`pmPK; zDt=i~Dbz!C#)`I>OiBIP(ykqzBK}$Y&kne&M#n>2xL?giy=iFooauMG=+2i!Bl%Ib z<)^F@D0V-zzzNzF&(AS>O#KT%_}*WD*j;Np3>z31L}OTNXmI)@2EtQ6DGQ3+5x=ja z<;GGYX@H-r>9ee`)l%rg9tk--ni>v53O;#$`CG6D*MDsU!|jZ z@D$M2voHr~pxFW*$8Yt?QC%N}EtSU&IYrD|W`Bw?hlLZTpgH`T?xGt)fHUhmiI}q0 zC2}AUcg{pDvQi`kCRX5XNH-+47q5hWms=2WjLVNKW|HdAGw1Gpw(?6VF?p2!h9`^; zuoOF$^~EhuL74G7GY(99D(gLAIK)S(3@1ke%-tD`tsLKydbie6>e}_~A^OXRO>&Ywo^v<8Yg> zg-pSv68X5;;fb4}Z*E{$3i5P72kL0uhqaz<&>si0P>Xa85icv*b*I<)eMYCbsZ;oZ zLT3y^q-8WE{f?l>b$(!^pg^}C44IWC%-@tg4baYo)>uAI&Tp9(o4b*|9{h6tPR1ip z{;ASM=gkYP0yQOaev)pfAmXonZyDp&R>3}Lp=F(m;UUGoG)G6*N#U0ub1zke*Libm z4Qqq9K8I#Wr$@?YB(fU8$Nx~ti_FqF-P2kMuVwP)J_wiBY7gtf#MpR7jEes>+}-9t zZL`6r8h=93ARqXHVI#*@*|?|IvzXu1I?!)LQ^kglFtnpB;tf*Y^m!z7x(HR`?sc9w zs9pm3=HM4w4NPx!d=y-=V~&2%1Tjr4&D|YTG?d1m7?(ez+xfT^&mNy zA~JZ!N{k2=xCSDMI|r-3{Z{)WWxwg}OWTu>GOh$f)2pXPDBVUC|Cm-yV2}bE&}W|x zKB#47&?crjEY&z2R_i@5{?UHw5Hif;xX4Tcxt60EI14&s?Q2ak-2`GsiTOFORRB7b zaT}IrVM>jtEAwUGhX7qF=>CpG&ORM@+QX`NbxT48|0J+_?bmw&{VPzJkEmmTnVx`@hPm^;G}> literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/scroll_to_bottom_button-light.png b/testdata/snapshots/darwin/scroll_to_bottom_button-light.png new file mode 100644 index 0000000000000000000000000000000000000000..31fd1d73983b5b7dece7926966ab12f0c4c7a305 GIT binary patch literal 2677 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/streaming_text-light.png b/testdata/snapshots/darwin/streaming_text-light.png new file mode 100644 index 0000000000000000000000000000000000000000..cadc899c637756e4bb0705e84dda4d263e185e42 GIT binary patch literal 4207 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 R)Bl6zM_Hf@Sjsf$KLE-LrrZDk literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/thinking_block-light.png b/testdata/snapshots/darwin/thinking_block-light.png new file mode 100644 index 0000000000000000000000000000000000000000..4f62d55190ce52ef266934729d48319dc397d0b6 GIT binary patch literal 9494 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/typing_indicator-dark.png b/testdata/snapshots/darwin/typing_indicator-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..50032a90610deb4f3530444ce8da0661ce5766af GIT binary patch literal 2445 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 Date: Mon, 5 Oct 2026 14:27:37 -0400 Subject: [PATCH 05/13] Chat Sessions: components 241-260 --- artifact_card.go | 6 +++--- capability_cards.go | 6 +++--- chat_empty_state.go | 8 ++++---- conversation_export.go | 10 +++++----- conversation_item.go | 14 +++++++------- conversation_list.go | 10 +++++----- conversation_search.go | 16 ++++++++-------- cost_estimator.go | 11 ++++------- date_separator.go | 8 +++----- feedback_form.go | 8 ++++---- project_knowledge_panel.go | 10 +++++----- project_list.go | 10 +++++----- prompt_library.go | 16 ++++++++-------- regenerate_menu.go | 6 +++--- shared_conversation_view.go | 8 ++++---- stop_generating_button.go | 2 +- suggestion_chips.go | 6 +++--- system_prompt_editor.go | 10 +++++----- .../darwin/conversation_list-dark.png | Bin 2666 -> 19901 bytes .../darwin/conversation_list-light.png | Bin 2668 -> 19233 bytes thinking_indicator.go | 4 ++-- welcome_screen.go | 2 +- 22 files changed, 83 insertions(+), 88 deletions(-) diff --git a/artifact_card.go b/artifact_card.go index 478888f..1bf76d4 100644 --- a/artifact_card.go +++ b/artifact_card.go @@ -10,7 +10,7 @@ import ( "mujicaui/theme" ) -// ArtifactKind is what an artifact holds. The zero value is ArtifactCode. +// ArtifactKind is what an artifact holds; zero is ArtifactCode. type ArtifactKind int const ( @@ -23,7 +23,7 @@ const ( type ArtifactCardOptions struct { Kind ArtifactKind Title string - // Detail is a short fact, such as "Go · 120 lines". + // Detail is a short fact, such as "Go, 120 lines". Detail string // Streaming shows the artifact is still being written. Streaming bool @@ -34,7 +34,7 @@ var artifactKinds = [3]struct{ icon, name string }{ {"file", "artifact_card.code"}, {"file-text", "artifact_card.document"}, {"layout-grid", "artifact_card.web"}, } -// ArtifactCard stands for an artifact inside a message; a click or Enter asks to open the artifact panel. +// ArtifactCard stands for an artifact; activating asks to open it. func ArtifactCard(c *ui.Context, opts ArtifactCardOptions) ChoiceResult { if opts.Title == "" { panic("mujica: ArtifactCard needs a Title") diff --git a/capability_cards.go b/capability_cards.go index da12989..fb977cf 100644 --- a/capability_cards.go +++ b/capability_cards.go @@ -9,7 +9,7 @@ import ( "mujicaui/theme" ) -// CapabilityCard explains one thing the assistant can do, with example prompts. +// CapabilityCard explains one assistant capability with example prompts. type CapabilityCard struct { Title, Description string Icon *ui.SVG @@ -30,7 +30,7 @@ type CapabilityCardsView struct { Example string } -// CapabilityCards shows what the assistant can do; clicking an example hands it to the caller. +// CapabilityCards shows capabilities; a clicked example goes to the caller. func CapabilityCards(c *ui.Context, cards []CapabilityCard, opts CapabilityCardsOptions) CapabilityCardsView { if opts.Columns < 0 { panic("mujica: CapabilityCards Columns is negative") @@ -76,7 +76,7 @@ func CapabilityCards(c *ui.Context, cards []CapabilityCard, opts CapabilityCards return v } -// capabilityExample is a quoted example prompt button; it reports a click. +// capabilityExample is a quoted example button reporting a click. func capabilityExample(c *ui.Context, k theme.Tokens, text string) bool { d := Density(c) b := ui.ButtonBase(c).MinHeight(d.ControlHeight()).Padding(d.Unit(), d.Unit()*3).Justify(ui.Start). diff --git a/chat_empty_state.go b/chat_empty_state.go index 38628f9..a386f0a 100644 --- a/chat_empty_state.go +++ b/chat_empty_state.go @@ -8,7 +8,7 @@ import ( "mujicaui/icons" ) -// ChatEmptyKind is why a chat view is empty. The zero value is ChatEmptyNew. +// ChatEmptyKind is why a chat is empty; zero is ChatEmptyNew. type ChatEmptyKind int const ( @@ -20,18 +20,18 @@ const ( ChatEmptyOffline ) -// ChatEmptyStateOptions configure a ChatEmptyState; empty texts use the kind's built-in copy. +// ChatEmptyStateOptions configure a ChatEmptyState; empty texts use built-in copy. type ChatEmptyStateOptions struct { Kind ChatEmptyKind // Query, for ChatEmptyNoResults, is named in the description. Query string Title string Description string - // Action replaces the kind's button text: Start, Clear search or Retry. + // Action replaces the kind's built-in button text. Action string } -// ChatEmptyState explains an empty chat (new, no results, offline) and offers the next step. +// ChatEmptyState explains an empty chat and offers the next step. func ChatEmptyState(c *ui.Context, opts ChatEmptyStateOptions) EmptyStateResult { switch opts.Kind { case ChatEmptyNew: diff --git a/conversation_export.go b/conversation_export.go index e9c6f40..3acf073 100644 --- a/conversation_export.go +++ b/conversation_export.go @@ -13,7 +13,7 @@ import ( "mujicaui/theme" ) -// ExportFormat is the text form of an export. The zero value is ExportMarkdown. +// ExportFormat is an export's text form; zero is ExportMarkdown. type ExportFormat int const ( @@ -22,7 +22,7 @@ const ( ExportText ) -// ExportRange is which messages an export holds. The zero value is ExportAll. +// ExportRange is which messages an export holds; zero is ExportAll. type ExportRange int const ( @@ -35,7 +35,7 @@ const ( var exportRoles = map[SessionRole]string{SessionUser: "user", SessionAssistant: "assistant", SessionSystem: "system"} -// ExportConversation writes messages as Markdown, JSON or plain text; it does not parse their text. +// ExportConversation writes messages as Markdown, JSON or plain text. func ExportConversation(title string, messages []SessionMessage, format ExportFormat) string { var b strings.Builder switch format { @@ -145,13 +145,13 @@ type ConversationExportOptions struct { // ConversationExportView is a built ConversationExport and the export asked for. type ConversationExportView struct { Element *ui.Element - // Exported reports Content is ready for the caller to write, as Format. + // Exported reports Content is ready for the caller to write. Exported bool Content string Format ExportFormat } -// ConversationExport picks a format and range, previews the result and hands the text to the caller to save. +// ConversationExport picks format and range, previews, and hands over text. func ConversationExport(c *ui.Context, s *ConversationExportState, messages []SessionMessage, opts ConversationExportOptions) ConversationExportView { if s == nil || opts.Title == "" { panic("mujica: ConversationExport needs a state and a Title") diff --git a/conversation_item.go b/conversation_item.go index 9d04be3..2846c97 100644 --- a/conversation_item.go +++ b/conversation_item.go @@ -14,21 +14,21 @@ import ( // ConversationItemOptions configure a ConversationItem. type ConversationItemOptions struct { - // Today decides the time stamp's form; zero uses the window clock. + // Today decides the time stamp; zero uses the clock. Today Date Selected bool Disabled bool - // Draggable lets the row be dragged onto a ProjectList as a ConversationDrag. + // Draggable lets the row be dropped on a ProjectList. Draggable bool } // ConversationDrag is the value a dragged conversation carries. type ConversationDrag struct{ ID string } -// ConversationItemView is a built ConversationItem and what the user asked for this frame. +// ConversationItemView is a built ConversationItem and its requests. type ConversationItemView struct { Element *ui.Element - // Opened, Deleted, Exported and PinToggled are requests for the caller to carry out. + // Opened, Deleted, Exported and PinToggled are requests for the caller. Opened, Deleted, Exported, PinToggled bool // Renamed reports a confirmed new title, already in conv.Title. Renamed bool @@ -41,7 +41,7 @@ type conversationItemState struct { type conversationItemKey struct{} -// ConversationItem is a conversation row: title, time, and a menu to rename in place, pin, export or delete. +// ConversationItem is a conversation row with rename, pin, export, delete. func ConversationItem(c *ui.Context, conv *ChatConversation, opts ConversationItemOptions) ConversationItemView { if conv == nil || conv.ID == "" { panic("mujica: ConversationItem needs a conversation with an ID") @@ -118,7 +118,7 @@ func ConversationItem(c *ui.Context, conv *ChatConversation, opts ConversationIt return v } -// conversationItemEditor is the in-place title field: Enter keeps a non-blank title, Escape cancels. +// conversationItemEditor edits the title in place; Escape cancels. func conversationItemEditor(c *ui.Context, k theme.Tokens, conv *ChatConversation, st *conversationItemState, v *ConversationItemView) { d := Density(c) in := ui.TextInputBase(c, &st.draft).Grow(1).MinHeight(d.ControlHeight()-4).Padding(0, d.Unit()*2). @@ -142,7 +142,7 @@ func conversationItemEditor(c *ui.Context, k theme.Tokens, conv *ChatConversatio } } -// conversationItemMenu is a borderless ellipsis button opening the menu build fills. +// conversationItemMenu is a borderless ellipsis button opening a menu. func conversationItemMenu(c *ui.Context, label string, build func(m *PopupMenu)) *ui.Element { b := iconAction(c, icons.Must("ellipsis"), label).Role(ui.RoleMenuButton).Shrink(0) open := ui.Local(b, conversationItemKey{}, func() bool { return false }) diff --git a/conversation_list.go b/conversation_list.go index f2d1a0d..9700a1b 100644 --- a/conversation_list.go +++ b/conversation_list.go @@ -37,7 +37,7 @@ type ConversationListState struct { plan conversationListPlan } -// conversationListPlan is the grouped rows, rebuilt only when the data or day changes. +// conversationListPlan holds grouped rows, rebuilt on new data or day. type conversationListPlan struct { src []ChatConversation day Date @@ -45,7 +45,7 @@ type conversationListPlan struct { built bool } -// conversationListRow is group header g (item < 0) or an index into the items. +// conversationListRow is a header (item < 0) or item index. type conversationListRow struct { group, item int } @@ -60,10 +60,10 @@ type ConversationListView struct { // Changed reports a newly chosen conversation, in State.Selected. func (v ConversationListView) Changed() bool { return v.changed } -// Submitted reports Enter or a double click on the chosen conversation. +// Submitted reports Enter or a double click on the choice. func (v ConversationListView) Submitted() bool { return v.submitted } -// ConversationList groups conversations into pinned, today, yesterday, past 7 days and older, building only rows in view. +// ConversationList groups conversations by recency, building only visible rows. func ConversationList(c *ui.Context, s *ConversationListState, items []ChatConversation, opts ConversationListOptions, row func(conv ChatConversation)) ConversationListView { if s == nil { panic("mujica: ConversationList needs a state") @@ -181,7 +181,7 @@ var conversationListGroups = [5]string{ "conversation_list.week", "conversation_list.older", } -// conversationListGroup is the group index of conv: pinned, today, yesterday, 7 days, older. +// conversationListGroup returns the recency group index of conv. func conversationListGroup(conv ChatConversation, today Date) int { day := DateOf(conv.Updated) switch { diff --git a/conversation_search.go b/conversation_search.go index 44bc501..f711f30 100644 --- a/conversation_search.go +++ b/conversation_search.go @@ -20,9 +20,9 @@ type ConversationSearchHit struct { // ConversationSearchOptions configure a ConversationSearch. type ConversationSearchOptions struct { - // Loading shows the caller's search for the query is under way. + // Loading shows the caller's search is under way. Loading bool - // Error is the caller's failed search; it shows with a retry button. + // Error describes a failed search, shown with a retry button. Error string Placeholder string Label string @@ -32,9 +32,9 @@ type ConversationSearchOptions struct { // ConversationSearchView is a built ConversationSearch and this frame's events. type ConversationSearchView struct { Element *ui.Element - // QueryChanged asks the caller to search again for the new query. + // QueryChanged asks the caller to search for the new query. QueryChanged bool - // Chosen is the hit opened by a click or Enter, empty for none. + // Chosen is the hit opened this frame, or empty. Chosen string Retry bool } @@ -47,7 +47,7 @@ type conversationSearchState struct { type conversationSearchKey struct{} -// ConversationSearch searches titles and content; the caller supplies hits for the query and the matches are highlighted. +// ConversationSearch shows caller-supplied hits for a query, highlighting matches. func ConversationSearch(c *ui.Context, query *string, hits []ConversationSearchHit, opts ConversationSearchOptions) ConversationSearchView { if query == nil { panic("mujica: ConversationSearch needs a query") @@ -97,7 +97,7 @@ func conversationSearchList(c *ui.Context, s *conversationSearchState, q string, s.rows.Key = func(i int) any { return hits[i].ID } s.rows.Label = func(i int) string { return hits[i].Title } s.rows.Selected = &s.cursor - // Rows have one height, so the list can size itself before measuring them. + // Rows share one height, so the list sizes itself early. rowH := d.ControlHeight() + FontSize(c, theme.CaptionSize)*theme.LineHeight + 2 restore := dataSelectTheme(c, 0) list := ui.List(c, &s.rows, len(hits), func(i int) { @@ -134,7 +134,7 @@ func conversationSearchList(c *ui.Context, s *conversationSearchState, q string, return chosen } -// conversationSearchSpans splits text into spans, marking each case-insensitive match of q. +// conversationSearchSpans marks each case-insensitive match of q in text. func conversationSearchSpans(text, q string, k theme.Tokens) []ui.Span { r := []rune(text) var spans []ui.Span @@ -152,7 +152,7 @@ func conversationSearchSpans(text, q string, k theme.Tokens) []ui.Span { return spans } -// conversationSearchMatches returns rune ranges of case-insensitive matches of q in text. +// conversationSearchMatches returns rune ranges where q matches, ignoring case. func conversationSearchMatches(text, q string) [][2]int { t, p := []rune(text), []rune(q) if len(p) == 0 { diff --git a/cost_estimator.go b/cost_estimator.go index 553aa80..b70e411 100644 --- a/cost_estimator.go +++ b/cost_estimator.go @@ -7,11 +7,10 @@ import ( "github.com/egoist/mygo/ui" - "mujicaui/internal" "mujicaui/theme" ) -// CostEstimatorOptions configure a CostEstimator. Prices are per million tokens, from the caller. +// CostEstimatorOptions configure a CostEstimator; prices are per million tokens. type CostEstimatorOptions struct { InputTokens, OutputTokens int InputPrice, OutputPrice float64 @@ -21,7 +20,7 @@ type CostEstimatorOptions struct { Digits int } -// CostEstimate is the cost of the input, the output and both. +// CostEstimate is the input, output and total cost. type CostEstimate struct{ Input, Output, Total float64 } // EstimateCost prices token counts at per-million rates. @@ -31,7 +30,7 @@ func EstimateCost(inputTokens, outputTokens int, inputPrice, outputPrice float64 return CostEstimate{in, out, in + out} } -// CostEstimator shows input and output tokens and their estimated cost at the caller's prices. +// CostEstimator shows token counts and cost at caller prices. func CostEstimator(c *ui.Context, opts CostEstimatorOptions) *ui.Element { if opts.InputTokens < 0 || opts.OutputTokens < 0 { panic("mujica: CostEstimator token counts must not be negative") @@ -76,9 +75,7 @@ func CostEstimator(c *ui.Context, opts CostEstimatorOptions) *ui.Element { cell(msg(c, "cost_estimator.output"), k.Text, false) cell(strconv.Itoa(opts.OutputTokens), k.Text, true) cell(money(est.Output), k.Text, true) - ui.Box(c).ColumnSpan(3).Height(9).Draw(func(p *ui.Painter, r ui.Rect) { - internal.Rule(p, r.X, r.X+r.W, r.Y+r.H/2, k.Ornament) - }) + ui.Box(c).ColumnSpan(3).Height(theme.BorderWidth).MarginY(d.Unit()).Background(k.Ornament) ui.Text(c, msg(c, "cost_estimator.total")).Font(theme.SerifFont).TextColor(k.Text) cell(strconv.Itoa(opts.InputTokens+opts.OutputTokens), k.Text, true) ui.Text(c, money(est.Total)).Bold().TextColor(k.AccentText).JustifySelf(ui.End).FontFeatures("tnum") diff --git a/date_separator.go b/date_separator.go index 1d73c87..7e03af2 100644 --- a/date_separator.go +++ b/date_separator.go @@ -16,7 +16,7 @@ type DateSeparatorOptions struct { Today Date } -// DateSeparator marks where a day's messages begin: Today, Yesterday, or the full date in the window's language. +// DateSeparator marks where a day's messages begin, localized. func DateSeparator(c *ui.Context, day Date, opts DateSeparatorOptions) *ui.Element { if !day.Valid() { panic("mujica: DateSeparator needs a valid date") @@ -30,9 +30,7 @@ func DateSeparator(c *ui.Context, day Date, opts DateSeparatorOptions) *ui.Eleme label := dateSeparatorLabel(c, day, today) row := ui.Row(c).FillWidth().Gap(u*3).AlignItems(ui.Center).Padding(u*2, 0).Role(ui.RoleText).Label(label) line := func() { - ui.Box(c).Grow(1).Height(9).Draw(func(p *ui.Painter, r ui.Rect) { - internal.Rule(p, r.X, r.X+r.W, r.Y+r.H/2, k.Border) - }) + ui.Box(c).Grow(1).Height(theme.BorderWidth).Background(k.Border) } row.Children(func() { line() @@ -59,7 +57,7 @@ func dateSeparatorLabel(c *ui.Context, day, today Date) string { msg(c, fmt.Sprintf("calendar.month_%d", day.Month)), day.Day, day.Year) } -// dateSeparatorWhen is a short time stamp: the clock today, else the relative day or date. +// dateSeparatorWhen is a short stamp: time, day or date. func dateSeparatorWhen(c *ui.Context, t time.Time, today Date) string { day := DateOf(t) if day == today { diff --git a/feedback_form.go b/feedback_form.go index 4edcd75..0b7e0b5 100644 --- a/feedback_form.go +++ b/feedback_form.go @@ -10,7 +10,7 @@ import ( "mujicaui/theme" ) -// FeedbackRating is the thumb the user gave. The zero value is FeedbackUp. +// FeedbackRating is the thumb given; zero is FeedbackUp. type FeedbackRating int const ( @@ -18,7 +18,7 @@ const ( FeedbackDown ) -// FeedbackValue is what the user wrote: chosen reasons and a comment. +// FeedbackValue is the chosen reasons and a comment. type FeedbackValue struct { Reasons []string Comment string @@ -29,7 +29,7 @@ type FeedbackFormOptions struct { Rating FeedbackRating // Reasons replaces the built-in reasons for the rating. Reasons []string - // Submitting shows the caller sending the feedback and blocks the form. + // Submitting shows the caller sending; it blocks the form. Submitting bool Disabled bool } @@ -45,7 +45,7 @@ var feedbackReasons = [2][]string{ {"feedback_form.down.wrong", "feedback_form.down.unhelpful", "feedback_form.down.unsafe", "feedback_form.down.style"}, } -// FeedbackForm asks why after a thumbs up or down: reason chips and a comment, then Submit or Cancel. +// FeedbackForm asks for reasons and a comment after a rating. func FeedbackForm(c *ui.Context, value *FeedbackValue, opts FeedbackFormOptions) FeedbackFormView { if value == nil { panic("mujica: FeedbackForm needs a value") diff --git a/project_knowledge_panel.go b/project_knowledge_panel.go index 8c9208b..4a2cce1 100644 --- a/project_knowledge_panel.go +++ b/project_knowledge_panel.go @@ -11,7 +11,7 @@ import ( "mujicaui/theme" ) -// KnowledgeFile is a file in a project's knowledge, sized in tokens by the caller. +// KnowledgeFile is a project knowledge file, sized in tokens. type KnowledgeFile struct { ID, Name string Tokens int @@ -26,16 +26,16 @@ type ProjectKnowledgePanelOptions struct { Disabled bool } -// ProjectKnowledgePanelView is a built panel and what the user asked for. +// ProjectKnowledgePanelView is a built panel and its requests. type ProjectKnowledgePanelView struct { Element *ui.Element // Add asks the caller to pick files to add. Add bool - // Removed is the ID of a file to remove, empty for none. + // Removed is the ID of a file to remove. Removed string } -// ProjectKnowledgePanel lists a project's knowledge files with add, remove and how full it is. +// ProjectKnowledgePanel lists knowledge files with add, remove and usage. func ProjectKnowledgePanel(c *ui.Context, files []KnowledgeFile, opts ProjectKnowledgePanelOptions) ProjectKnowledgePanelView { if opts.Capacity <= 0 { panic("mujica: ProjectKnowledgePanel needs a positive Capacity") @@ -90,7 +90,7 @@ func ProjectKnowledgePanel(c *ui.Context, files []KnowledgeFile, opts ProjectKno return v } -// projectKnowledgeMeter shows used of capacity; near and over the limit add a word and an icon, not only color. +// projectKnowledgeMeter shows usage; limits get words and icons. func projectKnowledgeMeter(c *ui.Context, k theme.Tokens, used, capacity int) { d := Density(c) frac := float64(used) / float64(capacity) diff --git a/project_list.go b/project_list.go index 4c21553..6c73018 100644 --- a/project_list.go +++ b/project_list.go @@ -12,7 +12,7 @@ import ( "mujicaui/theme" ) -// ChatProject is a project that holds conversations; Folder groups projects, empty for none. +// ChatProject holds conversations; Folder groups projects, empty for none. type ChatProject struct { ID, Name, Folder string } @@ -23,7 +23,7 @@ type ProjectListOptions struct { Disabled bool } -// ProjectListState is the chosen project and which folders and projects are open. +// ProjectListState is the chosen project and open folders and projects. type ProjectListState struct { // Selected is the chosen project's ID; empty for none. Selected string @@ -38,12 +38,12 @@ type ProjectListView struct { Changed bool // Opened is a conversation the user opened, empty for none. Opened string - // Moved asks the caller to move conversation MoveID into project MoveTo. + // Moved asks the caller to move MoveID into MoveTo. Moved bool MoveID, MoveTo string } -// ProjectList shows folders of projects and their conversations; drop a ConversationDrag on a project, or use Move to, to file it. +// ProjectList shows project folders and conversations; drops move them. func ProjectList(c *ui.Context, s *ProjectListState, projects []ChatProject, conversations func(projectID string) []ChatConversation, opts ProjectListOptions) ProjectListView { if s == nil || conversations == nil { panic("mujica: ProjectList needs a state and conversations") @@ -91,7 +91,7 @@ func ProjectList(c *ui.Context, s *ProjectListState, projects []ChatProject, con return v } -// projectListFolder is a folder heading on a CollapsibleBase trigger, which reports expanded. +// projectListFolder is a folder heading on a CollapsibleBase trigger. func projectListFolder(c *ui.Context, title string, open *bool) *ui.Element { k := Tokens(c) d := Density(c) diff --git a/prompt_library.go b/prompt_library.go index 827f12c..738566e 100644 --- a/prompt_library.go +++ b/prompt_library.go @@ -13,7 +13,7 @@ import ( "mujicaui/theme" ) -// PromptTemplate is a reusable prompt; {{name}} in Body is a variable to fill before inserting. +// PromptTemplate is a reusable prompt; {{name}} marks a variable. type PromptTemplate struct { ID, Category, Title, Body string } @@ -24,7 +24,7 @@ type PromptLibraryOptions struct { Disabled bool } -// PromptLibraryState is the library's category, search, chosen template and variable values. +// PromptLibraryState holds category, query, chosen template and variable values. type PromptLibraryState struct { // Category filters templates; empty shows all. Category string @@ -34,7 +34,7 @@ type PromptLibraryState struct { shown promptLibraryShown } -// promptLibraryShown caches the filtered templates until the data, query or category changes. +// promptLibraryShown caches filtered templates until data, query or category change. type promptLibraryShown struct { src []PromptTemplate query, category string @@ -43,10 +43,10 @@ type promptLibraryShown struct { built bool } -// PromptLibraryView is a built PromptLibrary and the text inserted this frame. +// PromptLibraryView is a built PromptLibrary and inserted text. type PromptLibraryView struct { Element *ui.Element - // Inserted is the chosen template with its variables filled, empty for none. + // Inserted is the filled template, or empty. Inserted string } @@ -70,7 +70,7 @@ func PromptLibraryFill(body string, values map[string]string) string { }) } -// PromptLibrary browses templates by category and search, previews one, fills its variables and inserts it. +// PromptLibrary browses, previews, fills and inserts prompt templates. func PromptLibrary(c *ui.Context, s *PromptLibraryState, templates []PromptTemplate, opts PromptLibraryOptions) PromptLibraryView { if s == nil { panic("mujica: PromptLibrary needs a state") @@ -152,7 +152,7 @@ func promptLibraryCategory(c *ui.Context, k theme.Tokens, s *PromptLibraryState, } } -// selectableRow is a focusable row chosen by click, Enter or Space, marked with Selection and a diamond. +// selectableRow is a focusable row marked chosen with a diamond. func selectableRow(c *ui.Context, k theme.Tokens, key, label string, chosen bool) bool { d := Density(c) b := ui.ButtonBase(c).Key(key).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*2).Gap(d.Unit() * 2).Justify(ui.Start). @@ -176,7 +176,7 @@ func selectableRow(c *ui.Context, k theme.Tokens, key, label string, chosen bool return b.Clicked() && !b.IsDisabled() } -// promptLibraryPreview shows the filled body, a field per variable, and Insert once all are filled. +// promptLibraryPreview shows the body, variable fields and Insert. func promptLibraryPreview(c *ui.Context, k theme.Tokens, s *PromptLibraryState, t PromptTemplate, disabled bool) string { d := Density(c) vars := PromptLibraryVariables(t.Body) diff --git a/regenerate_menu.go b/regenerate_menu.go index b224406..95fe6c4 100644 --- a/regenerate_menu.go +++ b/regenerate_menu.go @@ -29,7 +29,7 @@ type RegenerateChoice struct { // RegenerateMenuOptions configure a RegenerateMenu. type RegenerateMenuOptions struct { - // Models lists models to retry with; Current is marked and left out. + // Models lists models to retry with; Current is left out. Models []string Current string // Variants replaces the built-in Longer, Shorter, Simpler and More detailed. @@ -37,14 +37,14 @@ type RegenerateMenuOptions struct { Disabled bool } -// RegenerateMenuView is a built menu and the retry chosen this frame. +// RegenerateMenuView is a built menu and the chosen retry. type RegenerateMenuView struct { Element *ui.Element Chosen bool Choice RegenerateChoice } -// RegenerateMenu offers regenerate, retry with another model, and variants such as longer or shorter. +// RegenerateMenu offers retry, another model, and rewrite variants. func RegenerateMenu(c *ui.Context, opts RegenerateMenuOptions) RegenerateMenuView { variants := opts.Variants if variants == nil { diff --git a/shared_conversation_view.go b/shared_conversation_view.go index 00676df..cda049f 100644 --- a/shared_conversation_view.go +++ b/shared_conversation_view.go @@ -13,7 +13,7 @@ import ( "mujicaui/theme" ) -// SessionRole is who wrote a message. The zero value is SessionUser. +// SessionRole is who wrote a message; zero is SessionUser. type SessionRole int const ( @@ -22,7 +22,7 @@ const ( SessionSystem ) -// SessionMessage is one message of a saved conversation, as plain text. +// SessionMessage is one saved message, as plain text. type SessionMessage struct { Role SessionRole // Author names the writer; empty uses the role's name. @@ -39,7 +39,7 @@ type SharedConversationViewOptions struct { Disabled bool } -// SharedConversationView shows a shared conversation read-only, with who shared it and when; it reports Copy link. +// SharedConversationView shows a shared conversation read-only with Copy link. func SharedConversationView(c *ui.Context, messages []SessionMessage, opts SharedConversationViewOptions) ChoiceResult { if opts.Title == "" { panic("mujica: SharedConversationView needs a Title") @@ -78,7 +78,7 @@ func SharedConversationView(c *ui.Context, messages []SessionMessage, opts Share type sharedConversationKey struct{} -// sessionMessageView is one read-only message: author, time and selectable plain text. +// sessionMessageView shows one read-only message with author and time. func sessionMessageView(c *ui.Context, k theme.Tokens, m SessionMessage) { d := Density(c) if m.Role < SessionUser || m.Role > SessionSystem { diff --git a/stop_generating_button.go b/stop_generating_button.go index c63739c..0d5fe29 100644 --- a/stop_generating_button.go +++ b/stop_generating_button.go @@ -17,7 +17,7 @@ type StopGeneratingButtonOptions struct { Disabled bool } -// StopGeneratingButton asks to stop a reply while one is generating; Cmd+. (Ctrl+. elsewhere) does too. +// StopGeneratingButton asks to stop generating; Mod+. does too. func StopGeneratingButton(c *ui.Context, opts StopGeneratingButtonOptions) ChoiceResult { if !opts.Generating { return ChoiceResult{} diff --git a/suggestion_chips.go b/suggestion_chips.go index 0b4fcc7..c11de04 100644 --- a/suggestion_chips.go +++ b/suggestion_chips.go @@ -12,7 +12,7 @@ import ( // SuggestionChipsOptions configure SuggestionChips. type SuggestionChipsOptions struct { - // Send makes a click send the suggestion; by default it fills the input. + // Send makes a click send instead of filling the input. Send bool // Label names the group, such as "Follow-up questions". Label string @@ -24,11 +24,11 @@ type SuggestionChipsView struct { Element *ui.Element // Chosen is the suggestion clicked, empty for none. Chosen string - // Sent reports that Chosen should be sent now; otherwise it is already in the input. + // Sent asks to send Chosen now instead of filling. Sent bool } -// SuggestionChips offers starter prompts or follow-ups; a click fills *input, or with Send asks to send. +// SuggestionChips offers prompts that fill *input or ask to send. func SuggestionChips(c *ui.Context, input *string, suggestions []string, opts SuggestionChipsOptions) SuggestionChipsView { if input == nil { panic("mujica: SuggestionChips needs an input") diff --git a/system_prompt_editor.go b/system_prompt_editor.go index 7fcba8d..ffb0792 100644 --- a/system_prompt_editor.go +++ b/system_prompt_editor.go @@ -17,23 +17,23 @@ import ( type SystemPromptEditorOptions struct { // Default is what Restore default puts back. Default string - // Saved is the text last saved; a different value shows as unsaved. + // Saved is the text last saved; differences show as unsaved. Saved string - // MaxLength is the character limit; over it, Save is blocked. Zero is none. + // MaxLength limits characters, blocking Save beyond it; zero is none. MaxLength int // Saving shows the caller's save in progress and blocks editing. Saving bool Disabled bool } -// SystemPromptEditorView is a built editor and what the user asked for. +// SystemPromptEditorView is a built editor and its requests. type SystemPromptEditorView struct { Element *ui.Element - // Save asks the caller to save *value; Restored reports the default was put back. + // Save asks to save *value; Restored reports the default returned. Save, Restored bool } -// SystemPromptEditor edits a system prompt with a character count, restore default, an unsaved mark and Mod+S to save. +// SystemPromptEditor edits a system prompt with count, restore and save. func SystemPromptEditor(c *ui.Context, value *string, opts SystemPromptEditorOptions) SystemPromptEditorView { if value == nil { panic("mujica: SystemPromptEditor needs a value") diff --git a/testdata/snapshots/darwin/conversation_list-dark.png b/testdata/snapshots/darwin/conversation_list-dark.png index 493b24742e87ace160c3ca37309af0251b1b537a..775de36e4bcff8fd52fe6f1cab0d69fa44d808d9 100644 GIT binary patch literal 19901 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 literal 2666 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⋙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 Date: Mon, 5 Oct 2026 14:28:19 -0400 Subject: [PATCH 06/13] Trading: components 161-180 --- bid_ask_bar.go | 60 ++++ bid_ask_bar_test.go | 34 +++ depth_ladder.go | 178 +++++++++++ depth_ladder_test.go | 113 +++++++ docs/components/161-ticker-tape.md | 46 +++ docs/components/162-quote-card.md | 43 +++ docs/components/163-price-text.md | 46 +++ docs/components/164-price-change-badge.md | 42 +++ docs/components/165-order-book.md | 52 ++++ docs/components/166-level2-quotes.md | 46 +++ docs/components/167-time-and-sales.md | 48 +++ docs/components/168-depth-ladder.md | 50 +++ docs/components/169-spread-indicator.md | 41 +++ docs/components/170-bid-ask-bar.md | 41 +++ docs/components/171-order-entry.md | 52 ++++ docs/components/172-quick-trade-buttons.md | 47 +++ docs/components/173-position-table.md | 49 +++ docs/components/174-order-table.md | 48 +++ docs/components/175-trade-history-table.md | 49 +++ docs/components/176-pnl-display.md | 44 +++ docs/components/177-leverage-slider.md | 46 +++ docs/components/178-margin-indicator.md | 41 +++ docs/components/179-risk-meter.md | 41 +++ docs/components/180-order-confirm-dialog.md | 52 ++++ example_trading_test.go | 221 ++++++++++++++ examples/gallery/pages_trading.go | 275 ++++++++++++++++- examples/gallery/pages_trading_code.go | 156 ++++++++++ examples/gallery/pages_trading_orders.go | 286 ++++++++++++++++++ level2_quotes.go | 123 ++++++++ level2_quotes_test.go | 63 ++++ leverage_slider.go | 159 ++++++++++ leverage_slider_test.go | 94 ++++++ margin_indicator.go | 71 +++++ margin_indicator_test.go | 39 +++ messages_trading.go | 161 ++++++++++ order_book.go | 260 ++++++++++++++++ order_book_test.go | 123 ++++++++ order_confirm_dialog.go | 88 ++++++ order_confirm_dialog_test.go | 78 +++++ order_entry.go | 222 ++++++++++++++ order_entry_test.go | 137 +++++++++ order_table.go | 194 ++++++++++++ order_table_test.go | 118 ++++++++ pnl_display.go | 82 +++++ pnl_display_test.go | 43 +++ position_table.go | 107 +++++++ position_table_test.go | 84 +++++ price_change_badge.go | 37 +++ price_change_badge_test.go | 35 +++ price_text.go | 171 +++++++++++ price_text_test.go | 106 +++++++ quick_trade_buttons.go | 127 ++++++++ quick_trade_buttons_test.go | 86 ++++++ quote_card.go | 52 ++++ quote_card_test.go | 43 +++ risk_meter.go | 84 +++++ risk_meter_test.go | 42 +++ spread_indicator.go | 53 ++++ spread_indicator_test.go | 42 +++ .../snapshots/darwin/bid_ask_bar-dark.png | Bin 0 -> 5801 bytes .../snapshots/darwin/bid_ask_bar-light.png | Bin 0 -> 5715 bytes .../snapshots/darwin/depth_ladder-dark.png | Bin 0 -> 11744 bytes .../snapshots/darwin/depth_ladder-light.png | Bin 0 -> 11140 bytes .../snapshots/darwin/level2_quotes-dark.png | Bin 0 -> 15272 bytes .../snapshots/darwin/level2_quotes-light.png | Bin 0 -> 14620 bytes .../snapshots/darwin/leverage_slider-dark.png | Bin 0 -> 8567 bytes .../darwin/leverage_slider-light.png | Bin 0 -> 8234 bytes .../darwin/margin_indicator-dark.png | Bin 0 -> 8169 bytes .../darwin/margin_indicator-light.png | Bin 0 -> 7925 bytes testdata/snapshots/darwin/order_book-dark.png | Bin 0 -> 18445 bytes .../snapshots/darwin/order_book-light.png | Bin 0 -> 17683 bytes .../darwin/order_confirm_dialog-dark.png | Bin 0 -> 27098 bytes .../darwin/order_confirm_dialog-light.png | Bin 0 -> 27676 bytes .../snapshots/darwin/order_entry-dark.png | Bin 0 -> 25738 bytes .../snapshots/darwin/order_entry-light.png | Bin 0 -> 24671 bytes .../snapshots/darwin/order_table-dark.png | Bin 0 -> 33166 bytes .../snapshots/darwin/order_table-light.png | Bin 0 -> 31963 bytes .../snapshots/darwin/pnl_display-dark.png | Bin 0 -> 9651 bytes .../snapshots/darwin/pnl_display-light.png | Bin 0 -> 9489 bytes .../snapshots/darwin/position_table-dark.png | Bin 0 -> 27714 bytes .../snapshots/darwin/position_table-light.png | Bin 0 -> 27071 bytes .../darwin/price_change_badge-dark.png | Bin 0 -> 5715 bytes .../darwin/price_change_badge-light.png | Bin 0 -> 5632 bytes testdata/snapshots/darwin/price_text-dark.png | Bin 0 -> 6387 bytes .../snapshots/darwin/price_text-light.png | Bin 0 -> 6279 bytes .../darwin/quick_trade_buttons-dark.png | Bin 0 -> 5194 bytes .../darwin/quick_trade_buttons-light.png | Bin 0 -> 5097 bytes testdata/snapshots/darwin/quote_card-dark.png | Bin 0 -> 9126 bytes .../snapshots/darwin/quote_card-light.png | Bin 0 -> 8893 bytes testdata/snapshots/darwin/risk_meter-dark.png | Bin 0 -> 5465 bytes .../snapshots/darwin/risk_meter-light.png | Bin 0 -> 5229 bytes .../darwin/spread_indicator-dark.png | Bin 0 -> 7438 bytes .../darwin/spread_indicator-light.png | Bin 0 -> 7308 bytes .../snapshots/darwin/ticker_tape-dark.png | Bin 0 -> 8071 bytes .../snapshots/darwin/ticker_tape-light.png | Bin 0 -> 7578 bytes .../snapshots/darwin/time_and_sales-dark.png | Bin 0 -> 28841 bytes .../snapshots/darwin/time_and_sales-light.png | Bin 0 -> 27613 bytes .../darwin/trade_history_table-dark.png | Bin 0 -> 23321 bytes .../darwin/trade_history_table-light.png | Bin 0 -> 22690 bytes ticker_tape.go | 155 ++++++++++ ticker_tape_test.go | 93 ++++++ time_and_sales.go | 137 +++++++++ time_and_sales_test.go | 90 ++++++ trade_history_table.go | 110 +++++++ trade_history_table_test.go | 87 ++++++ 105 files changed, 6042 insertions(+), 1 deletion(-) create mode 100644 bid_ask_bar.go create mode 100644 bid_ask_bar_test.go create mode 100644 depth_ladder.go create mode 100644 depth_ladder_test.go create mode 100644 docs/components/161-ticker-tape.md create mode 100644 docs/components/162-quote-card.md create mode 100644 docs/components/163-price-text.md create mode 100644 docs/components/164-price-change-badge.md create mode 100644 docs/components/165-order-book.md create mode 100644 docs/components/166-level2-quotes.md create mode 100644 docs/components/167-time-and-sales.md create mode 100644 docs/components/168-depth-ladder.md create mode 100644 docs/components/169-spread-indicator.md create mode 100644 docs/components/170-bid-ask-bar.md create mode 100644 docs/components/171-order-entry.md create mode 100644 docs/components/172-quick-trade-buttons.md create mode 100644 docs/components/173-position-table.md create mode 100644 docs/components/174-order-table.md create mode 100644 docs/components/175-trade-history-table.md create mode 100644 docs/components/176-pnl-display.md create mode 100644 docs/components/177-leverage-slider.md create mode 100644 docs/components/178-margin-indicator.md create mode 100644 docs/components/179-risk-meter.md create mode 100644 docs/components/180-order-confirm-dialog.md create mode 100644 example_trading_test.go create mode 100644 examples/gallery/pages_trading_code.go create mode 100644 examples/gallery/pages_trading_orders.go create mode 100644 level2_quotes.go create mode 100644 level2_quotes_test.go create mode 100644 leverage_slider.go create mode 100644 leverage_slider_test.go create mode 100644 margin_indicator.go create mode 100644 margin_indicator_test.go create mode 100644 messages_trading.go create mode 100644 order_book.go create mode 100644 order_book_test.go create mode 100644 order_confirm_dialog.go create mode 100644 order_confirm_dialog_test.go create mode 100644 order_entry.go create mode 100644 order_entry_test.go create mode 100644 order_table.go create mode 100644 order_table_test.go create mode 100644 pnl_display.go create mode 100644 pnl_display_test.go create mode 100644 position_table.go create mode 100644 position_table_test.go create mode 100644 price_change_badge.go create mode 100644 price_change_badge_test.go create mode 100644 price_text.go create mode 100644 price_text_test.go create mode 100644 quick_trade_buttons.go create mode 100644 quick_trade_buttons_test.go create mode 100644 quote_card.go create mode 100644 quote_card_test.go create mode 100644 risk_meter.go create mode 100644 risk_meter_test.go create mode 100644 spread_indicator.go create mode 100644 spread_indicator_test.go create mode 100644 testdata/snapshots/darwin/bid_ask_bar-dark.png create mode 100644 testdata/snapshots/darwin/bid_ask_bar-light.png create mode 100644 testdata/snapshots/darwin/depth_ladder-dark.png create mode 100644 testdata/snapshots/darwin/depth_ladder-light.png create mode 100644 testdata/snapshots/darwin/level2_quotes-dark.png create mode 100644 testdata/snapshots/darwin/level2_quotes-light.png create mode 100644 testdata/snapshots/darwin/leverage_slider-dark.png create mode 100644 testdata/snapshots/darwin/leverage_slider-light.png create mode 100644 testdata/snapshots/darwin/margin_indicator-dark.png create mode 100644 testdata/snapshots/darwin/margin_indicator-light.png create mode 100644 testdata/snapshots/darwin/order_book-dark.png create mode 100644 testdata/snapshots/darwin/order_book-light.png create mode 100644 testdata/snapshots/darwin/order_confirm_dialog-dark.png create mode 100644 testdata/snapshots/darwin/order_confirm_dialog-light.png create mode 100644 testdata/snapshots/darwin/order_entry-dark.png create mode 100644 testdata/snapshots/darwin/order_entry-light.png create mode 100644 testdata/snapshots/darwin/order_table-dark.png create mode 100644 testdata/snapshots/darwin/order_table-light.png create mode 100644 testdata/snapshots/darwin/pnl_display-dark.png create mode 100644 testdata/snapshots/darwin/pnl_display-light.png create mode 100644 testdata/snapshots/darwin/position_table-dark.png create mode 100644 testdata/snapshots/darwin/position_table-light.png create mode 100644 testdata/snapshots/darwin/price_change_badge-dark.png create mode 100644 testdata/snapshots/darwin/price_change_badge-light.png create mode 100644 testdata/snapshots/darwin/price_text-dark.png create mode 100644 testdata/snapshots/darwin/price_text-light.png create mode 100644 testdata/snapshots/darwin/quick_trade_buttons-dark.png create mode 100644 testdata/snapshots/darwin/quick_trade_buttons-light.png create mode 100644 testdata/snapshots/darwin/quote_card-dark.png create mode 100644 testdata/snapshots/darwin/quote_card-light.png create mode 100644 testdata/snapshots/darwin/risk_meter-dark.png create mode 100644 testdata/snapshots/darwin/risk_meter-light.png create mode 100644 testdata/snapshots/darwin/spread_indicator-dark.png create mode 100644 testdata/snapshots/darwin/spread_indicator-light.png create mode 100644 testdata/snapshots/darwin/ticker_tape-dark.png create mode 100644 testdata/snapshots/darwin/ticker_tape-light.png create mode 100644 testdata/snapshots/darwin/time_and_sales-dark.png create mode 100644 testdata/snapshots/darwin/time_and_sales-light.png create mode 100644 testdata/snapshots/darwin/trade_history_table-dark.png create mode 100644 testdata/snapshots/darwin/trade_history_table-light.png create mode 100644 ticker_tape.go create mode 100644 ticker_tape_test.go create mode 100644 time_and_sales.go create mode 100644 time_and_sales_test.go create mode 100644 trade_history_table.go create mode 100644 trade_history_table_test.go diff --git a/bid_ask_bar.go b/bid_ask_bar.go new file mode 100644 index 0000000..b8d23ec --- /dev/null +++ b/bid_ask_bar.go @@ -0,0 +1,60 @@ +package mujica + +import ( + "fmt" + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// BidAskBarOptions configure a BidAskBar. +type BidAskBarOptions struct { + // Decimals of the volumes shown; zero shows whole numbers. + Decimals int + // Label names the bar; empty uses the built-in name. + Label string +} + +// BidAskBar compares buy and sell volume in a split bar. +func BidAskBar(c *ui.Context, bid, ask float64, opts BidAskBarOptions) *ui.Element { + if bid < 0 || ask < 0 || math.IsNaN(bid+ask) { + panic("mujica: BidAskBar volumes must be zero or more") + } + if opts.Decimals < 0 { + panic("mujica: BidAskBar with negative Decimals") + } + k := Tokens(c) + u := Density(c).Unit() + total := bid + ask + share := 0.5 + if total > 0 { + share = bid / total + } + label := opts.Label + if label == "" { + label = msg(c, "bid_ask_bar.label") + } + buy := fmt.Sprintf(msg(c, "bid_ask_bar.buy"), statisticFormat(share*100, 1), statisticFormat(bid, opts.Decimals)) + sell := fmt.Sprintf(msg(c, "bid_ask_bar.sell"), statisticFormat(ask, opts.Decimals), statisticFormat((1-share)*100, 1)) + up, down := trendColor(c, 1), trendColor(c, -1) + upText, downText := up, down + if total == 0 { + up, down, upText, downText = k.Border, k.Border, k.TextMuted, k.TextMuted + } + e := ui.Column(c).Gap(u).MinWidth(160).Role(ui.RoleMeter).Label(label).Description(buy + ", " + sell) + e.Children(func() { + ui.Row(c).Justify(ui.SpaceBetween).Gap(u * 2).Children(func() { + ui.Text(c, buy).TextColor(upText).FontSize(FontSize(c, theme.CaptionSize)).FontFeatures("tnum").FontWeight(600).SingleLine() + ui.Text(c, sell).TextColor(downText).FontSize(FontSize(c, theme.CaptionSize)).FontFeatures("tnum").FontWeight(600).SingleLine() + }) + ui.Box(c).Height(8).FillWidth().Draw(func(p *ui.Painter, r ui.Rect) { + split := r.X + r.W*float32(share) + const gap = 2 + p.Fill(ui.Rect{X: r.X, Y: r.Y, W: max(0, split-r.X-gap/2), H: r.H}, up, theme.ControlRadius) + p.Fill(ui.Rect{X: split + gap/2, Y: r.Y, W: max(0, r.X+r.W-split-gap/2), H: r.H}, down, theme.ControlRadius) + }) + }) + return e +} diff --git a/bid_ask_bar_test.go b/bid_ask_bar_test.go new file mode 100644 index 0000000..89084d8 --- /dev/null +++ b/bid_ask_bar_test.go @@ -0,0 +1,34 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestBidAskBarShares(t *testing.T) { + bid, ask := 620.0, 380.0 + tt := tradingTester(GreenUp, 400, 100, func(c *ui.Context) { + ui.Box(c).Width(300).Children(func() { BidAskBar(c, bid, ask, BidAskBarOptions{}) }) + }) + if !tt.HasText("Buy 62.0% · 620") || !tt.HasText("380 · Sell 38.0%") { + t.Fatalf("texts %q", tt.Texts()) + } + bid, ask = 0, 0 + tt.Frame() + if !tt.HasText("Buy 50.0% · 0") { + t.Fatalf("empty: %q", tt.Texts()) + } + defer func() { + if recover() == nil { + t.Fatal("negative volume accepted") + } + }() + tradingTester(GreenUp, 100, 100, func(c *ui.Context) { BidAskBar(c, -1, 2, BidAskBarOptions{}) }) +} + +func TestBidAskBarSnapshot(t *testing.T) { + snapshot(t, "bid_ask_bar", 340, 80, func(c *ui.Context) { + ui.Column(c).Padding(20).Children(func() { BidAskBar(c, 6234, 3820, BidAskBarOptions{}) }) + }) +} diff --git a/depth_ladder.go b/depth_ladder.go new file mode 100644 index 0000000..6b76af6 --- /dev/null +++ b/depth_ladder.go @@ -0,0 +1,178 @@ +package mujica + +import ( + "fmt" + "log/slog" + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// DepthLadderOptions configure a DepthLadder. TickSize is required. +type DepthLadderOptions struct { + TickSize float64 + // Decimals of prices and sizes; zero means 2 and 0. + Decimals, SizeDecimals int + // Rows shown; zero means 15. + Rows int + Disabled bool +} + +// DepthLadderState is the ladder's scroll from last price, in ticks. +type DepthLadderState struct { + Offset int + cache depthLadderCache +} + +type depthLadderCache struct { + key bookKey + bids, asks map[int64]float64 +} + +// DepthLadderResult is a built DepthLadder and its clicked cell. +type DepthLadderResult struct { + Element *ui.Element + price float64 + side OrderSide +} + +// Clicked returns the clicked cell's price and side. +func (r DepthLadderResult) Clicked() (price float64, side OrderSide, ok bool) { + return r.price, r.side, r.side != 0 +} + +// DepthLadder is a price ladder around last; cell clicks order. +func DepthLadder(c *ui.Context, s *DepthLadderState, last float64, book OrderBookData, opts DepthLadderOptions) DepthLadderResult { + dec := priceDecimals("DepthLadder", opts.Decimals) + if opts.SizeDecimals < 0 || opts.Rows < 0 { + panic("mujica: DepthLadder SizeDecimals and Rows cannot be negative") + } + scale := math.Pow(10, float64(dec)) + tick := int64(math.Round(opts.TickSize * scale)) + if tick < 1 || math.Abs(opts.TickSize*scale-float64(tick)) > 1e-6 { + panic(fmt.Sprintf("mujica: DepthLadder TickSize %v is not a whole number of %d-decimal units", opts.TickSize, dec)) + } + rows := opts.Rows + if rows == 0 { + rows = 15 + } + depthLadderRefresh(s, book, scale, tick) + center := int64(math.Round(last*scale/float64(tick))) * tick + k := Tokens(c) + d := Density(c) + var r DepthLadderResult + r.Element = ui.Column(c).Gap(d.Unit()).Disabled(opts.Disabled).Role(ui.RoleTable).Label(msg(c, "depth_ladder.label")) + disabled := r.Element.IsDisabled() + move := func(by int) { + if !disabled && by != 0 { + s.Offset += by + slog.Debug("mujica: depth_ladder scrolled", "offset", s.Offset) + } + } + if r.Element.Shortcut(0, ui.KeyPageUp) { + move(rows / 2) + } + if r.Element.Shortcut(0, ui.KeyPageDown) { + move(-rows / 2) + } + r.Element.Children(func() { + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, msg(c, "depth_ladder.bid")).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)).Grow(1).Basis(0).TextAlign(ui.End) + ui.Text(c, msg(c, "depth_ladder.price")).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)).Grow(1).Basis(0).TextAlign(ui.Center) + ui.Text(c, msg(c, "depth_ladder.ask")).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)).Grow(1).Basis(0) + }) + grid := ui.Column(c).FocusGroup(ui.Vertical | ui.Horizontal) + grid.HandleInput(func(ev ui.InputEvent) bool { + if ev.Kind != ui.InputScroll || disabled || ev.DY == 0 { + return false + } + move(int(math.Copysign(1, float64(-ev.DY)))) + return true + }) + grid.Children(func() { + top := center + int64(s.Offset+rows/2)*tick + for i := range rows { + t := top - int64(i)*tick + depthLadderRow(c, &r, s, t, t == center, scale, dec, opts.SizeDecimals) + } + }) + if s.Offset != 0 { + if Button(c, msg(c, "depth_ladder.recenter"), ButtonOptions{Variant: Ghost, Icon: icons.Must("refresh-cw"), Disabled: disabled}).Clicked() { + s.Offset = 0 + } + } + }) + return r +} + +// depthLadderRow is a buy cell, the price, a sell cell. +func depthLadderRow(c *ui.Context, r *DepthLadderResult, s *DepthLadderState, t int64, current bool, scale float64, dec, sizeDec int) { + k := Tokens(c) + d := Density(c) + price := float64(t) / scale + text := statisticFormat(price, dec) + ui.Row(c).Key(t).MinHeight(d.ControlHeight()).AlignItems(ui.Stretch).BorderWidth(0, 0, theme.BorderWidth, 0).BorderColor(k.Border).Children(func() { + cell := func(side OrderSide, size float64) { + label := fmt.Sprintf(msg(c, fmt.Sprintf("depth_ladder.order%d", side)), text) + b := ui.ButtonBase(c).Grow(1).Basis(0).Padding(0, d.Unit()*2).Label(label) + if side == SideBuy { + b.Justify(ui.End) + } else { + b.Justify(ui.Start) + } + internal.Ring(b, k.Focus, 0) + if b.Hovered() { + b.Background(trendColor(c, side.sign()).Alpha(0.14)) + } + b.Children(func() { + if size > 0 { + ui.Text(c, statisticFormat(size, sizeDec)).TextColor(trendColor(c, side.sign())).FontFeatures("tnum").FontWeight(600).SingleLine() + } + }) + if b.Clicked() && !b.IsDisabled() { + r.price, r.side = price, side + slog.Debug("mujica: depth_ladder order", "side", side) + } + } + cell(SideBuy, s.cache.bids[t]) + mid := ui.Row(c).Grow(1).Basis(0).Justify(ui.Center).AlignItems(ui.Center).Gap(d.Unit()).Background(k.Background) + if current { + mid.Background(k.Selection).Label(msg(c, "depth_ladder.last") + " " + text) + mid.DrawOver(func(p *ui.Painter, rect ui.Rect) { + internal.Frame(p, rect, 2, 4, k.AccentText) + }) + } + mid.Children(func() { + if current { + ui.Box(c).Size(8, 8).Draw(func(p *ui.Painter, rect ui.Rect) { + p.FillPath(internal.Diamond(rect.X+4, rect.Y+4, 8), k.AccentText) + }) + } + t := ui.Text(c, text).FontFeatures("tnum").SingleLine() + if current { + t.FontWeight(700) + } + }) + cell(SideSell, s.cache.asks[t]) + }) +} + +// depthLadderRefresh indexes sizes by tick when the book changed. +func depthLadderRefresh(s *DepthLadderState, book OrderBookData, scale float64, tick int64) { + key := bookKeyOf(book, float64(tick)/scale) + if s.cache.bids != nil && s.cache.key == key { + return + } + index := func(ls []BookLevel) map[int64]float64 { + m := make(map[int64]float64, len(ls)) + for _, l := range ls { + m[int64(math.Round(l.Price*scale/float64(tick)))*tick] += l.Size + } + return m + } + s.cache = depthLadderCache{key: key, bids: index(book.Bids), asks: index(book.Asks)} +} diff --git a/depth_ladder_test.go b/depth_ladder_test.go new file mode 100644 index 0000000..6af2c74 --- /dev/null +++ b/depth_ladder_test.go @@ -0,0 +1,113 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func depthLadderBook() OrderBookData { + return OrderBookData{Bids: []BookLevel{{100.00, 5}, {99.99, 3}}, Asks: []BookLevel{{100.01, 2}, {100.03, 7}}} +} + +func TestDepthLadderCentersAndOrders(t *testing.T) { + var s DepthLadderState + var price float64 + var side OrderSide + tt := tradingTester(GreenUp, 400, 600, func(c *ui.Context) { + if p, sd, ok := DepthLadder(c, &s, 100.004, depthLadderBook(), DepthLadderOptions{TickSize: 0.01, Rows: 7}).Clicked(); ok { + price, side = p, sd + } + }) + top, _ := tt.Find("100.03") + mid, _ := tt.Find("Last price 100.00") + bottom, _ := tt.Find("99.97") + if !(top.Y < mid.Y && mid.Y < bottom.Y) || tt.HasText("100.04") { + t.Fatalf("not centered: %v %v %v %q", top, mid, bottom, tt.Texts()) + } + if err := tt.Click("Sell at 100.03"); err != nil { + t.Fatal(err) + } + if price != 100.03 || side != SideSell { + t.Fatalf("clicked %v %v", price, side) + } + tt.Key(0, ui.KeyLeft) + tt.Key(0, ui.KeyEnter) + if price != 100.03 || side != SideBuy { + t.Fatalf("keyboard %v %v", price, side) + } + if !tt.HasText("7") || !tt.HasText("5") { + t.Fatalf("sizes: %q", tt.Texts()) + } +} + +func TestDepthLadderScrollsAndRecenters(t *testing.T) { + var s DepthLadderState + tt := tradingTester(GreenUp, 400, 600, func(c *ui.Context) { + DepthLadder(c, &s, 100, depthLadderBook(), DepthLadderOptions{TickSize: 0.01, Rows: 7}) + }) + _ = tt.Click("Buy at 100.00") + tt.Key(0, ui.KeyPageUp) + if s.Offset != 3 || !tt.HasText("100.06") { + t.Fatalf("page up: offset %d %q", s.Offset, tt.Texts()) + } + tt.Scroll(100, 200, 0, 40) + if s.Offset != 2 { + t.Fatalf("wheel: offset %d", s.Offset) + } + if err := tt.Click("Center on last price"); err != nil { + t.Fatal(err) + } + if s.Offset != 0 || tt.HasText("Center on last price") { + t.Fatalf("recenter: %d", s.Offset) + } +} + +// Only the visible rows are built, whatever the book's size. +func TestDepthLadderLargeBook(t *testing.T) { + var s DepthLadderState + book := OrderBookData{} + for i := range 100_000 { + book.Bids = append(book.Bids, BookLevel{Price: 100 - float64(i)/100, Size: 1}) + } + tt := tradingTester(GreenUp, 400, 600, func(c *ui.Context) { + DepthLadder(c, &s, 100, book, DepthLadderOptions{TickSize: 0.01, Rows: 9}) + }) + if n := len(tt.Texts()); n > 60 { + t.Fatalf("built %d texts", n) + } + // A sentinel survives only if the index is kept. + s.cache.bids[-1] = 42 + tt.Frame() + if s.cache.bids[-1] != 42 { + t.Fatal("index rebuilt without a change") + } +} + +func TestDepthLadderDisabledAndBadTick(t *testing.T) { + var s DepthLadderState + clicked := false + tt := tradingTester(GreenUp, 400, 600, func(c *ui.Context) { + _, _, clicked = DepthLadder(c, &s, 100, depthLadderBook(), DepthLadderOptions{TickSize: 0.01, Disabled: true}).Clicked() + }) + _ = tt.Click("Buy at 100.00") + tt.Scroll(100, 200, 0, 40) + if clicked || s.Offset != 0 { + t.Fatal("disabled ladder acted") + } + defer func() { + if recover() == nil { + t.Fatal("zero tick accepted") + } + }() + tradingTester(GreenUp, 100, 100, func(c *ui.Context) { DepthLadder(c, &s, 100, depthLadderBook(), DepthLadderOptions{}) }) +} + +func TestDepthLadderSnapshot(t *testing.T) { + snapshot(t, "depth_ladder", 340, 340, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + s := ui.Local(c.Root(), "snap", func() DepthLadderState { return DepthLadderState{} }) + DepthLadder(c, s, 100, depthLadderBook(), DepthLadderOptions{TickSize: 0.01, Rows: 7}) + }) + }) +} diff --git a/docs/components/161-ticker-tape.md b/docs/components/161-ticker-tape.md new file mode 100644 index 0000000..e97ec6a --- /dev/null +++ b/docs/components/161-ticker-tape.md @@ -0,0 +1,46 @@ +# 161 TickerTape + +行情滚动条。 + +## 用途 + +横向循环滚动的行情条,显示代码、价格与涨跌幅。指针悬停或键盘聚焦时暂停;减少动画时改为静态分页。 + +## 最小示例 + +```go +items := []mujica.TickerItem{{Symbol: "MUJC", Price: 412.08, ChangePercent: -1.35}, {Symbol: "AVE", Price: 88.2, ChangePercent: 2.1}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.TickerTape(c, items, mujica.TickerTapeOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `items` | `[]TickerItem` | 必填 | 代码、价格、涨跌幅(%)。 | +| `Decimals` | `int` | 2 | 价格小数位,0 表示 2,负数 panic。 | +| `Speed` | `float32` | 40 | 每秒滚动的 DIP。 | +| `PerPage` | `int` | 4 | 减少动画时每页条数。 | +| `Label` | `string` | 内置“Market ticker” | 无障碍名称。 | + +## 状态 + +滚动、暂停(悬停或聚焦)、静态分页(减少动画)、空列表。 + +## 事件 + +无业务事件。 + +## 键盘操作 + +Tab 聚焦滚动条即暂停;减少动画时 ←/→ 翻页,也可用上一页、下一页按钮。 + +## 限制 + +- 滚动以四分之一 DIP 取整,暂停时停止请求重绘。 +- 第二份副本用于无缝循环,屏幕阅读器可能读到重复内容。 +- 涨跌颜色由 `UseTrend(c, GreenUp|RedUp)` 按窗口设置,默认绿涨红跌;方向同时用箭头与正负号表达,不只靠颜色。 diff --git a/docs/components/162-quote-card.md b/docs/components/162-quote-card.md new file mode 100644 index 0000000..6df9188 --- /dev/null +++ b/docs/components/162-quote-card.md @@ -0,0 +1,43 @@ +# 162 QuoteCard + +报价卡片。 + +## 用途 + +显示代码、名称、现价、涨跌额与涨跌幅,并提供迷你图插槽。 + +## 最小示例 + +```go +quote := mujica.Quote{Symbol: "MUJC", Name: "Ave Mujica Holdings", Price: 412.08, Change: -5.62, ChangePercent: -1.35} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.QuoteCard(c, quote, mujica.QuoteCardOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `q` | `Quote` | 必填 | Symbol 必填,空值 panic;Name、Price、Change、ChangePercent。 | +| `Decimals` | `int` | 2 | 价格与涨跌额小数位。 | +| `Chart` | `func()` | nil | 迷你图插槽,高 40 DIP,例如 Sparkline。 | + +## 状态 + +默认;涨、跌、平三种方向。 + +## 事件 + +无。 + +## 键盘操作 + +卡片本身不获取焦点;插槽内控件自行处理键盘。 + +## 限制 + +- 不计算涨跌,数值由调用方提供。 +- 涨跌颜色由 `UseTrend(c, GreenUp|RedUp)` 按窗口设置,默认绿涨红跌;方向同时用箭头与正负号表达,不只靠颜色。 diff --git a/docs/components/163-price-text.md b/docs/components/163-price-text.md new file mode 100644 index 0000000..a13c7a7 --- /dev/null +++ b/docs/components/163-price-text.md @@ -0,0 +1,46 @@ +# 163 PriceText + +价格文本。 + +## 用途 + +按固定小数位与千分位显示价格;可与参考价比较着色并加箭头;价格变化时闪烁一次。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.UseTrend(c, mujica.RedUp) + mujica.PriceText(c, 18234.5, mujica.PriceTextOptions{Compare: true, Reference: 18000}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `value` | `float64` | 必填 | 价格。 | +| `Decimals` | `int` | 2 | 小数位,0 表示 2,负数 panic。 | +| `NoGrouping` | `bool` | false | 不显示千分位。 | +| `Compare / Reference` | `bool / float64` | false / 0 | 按相对 Reference 的方向着色并加箭头。 | +| `NoFlash` | `bool` | false | 变化时不闪烁。 | +| `Size` | `float32` | 正文字号 | 字号(DIP),随系统文字缩放。 | + +## 状态 + +默认;上涨、下跌、持平;变化闪烁(360 ms 淡出)。 + +## 事件 + +无。 + +## 键盘操作 + +不获取焦点。 + +## 限制 + +- 闪烁由帧间比较值得出:同一元素的值改变才会闪烁。减少动画时不闪烁,结束后不再请求重绘。 +- 涨跌颜色由 `UseTrend(c, GreenUp|RedUp)` 按窗口设置,默认绿涨红跌;方向同时用箭头与正负号表达,不只靠颜色。 diff --git a/docs/components/164-price-change-badge.md b/docs/components/164-price-change-badge.md new file mode 100644 index 0000000..af8f3d3 --- /dev/null +++ b/docs/components/164-price-change-badge.md @@ -0,0 +1,42 @@ +# 164 PriceChangeBadge + +涨跌徽标。 + +## 用途 + +显示涨跌额与涨跌幅,带箭头、正负号与语义底色。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.PriceChangeBadge(c, -5.62, -1.35, mujica.PriceChangeBadgeOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `change` | `float64` | 必填 | 涨跌额。 | +| `percent` | `float64` | 必填 | 涨跌幅(%),固定 2 位小数。 | +| `Decimals` | `int` | 2 | 涨跌额小数位。 | +| `HidePercent` | `bool` | false | 只显示涨跌额。 | + +## 状态 + +上涨、下跌、持平。 + +## 事件 + +无。 + +## 键盘操作 + +不获取焦点;无障碍名称含方向词与数值。 + +## 限制 + +- 涨跌颜色由 `UseTrend(c, GreenUp|RedUp)` 按窗口设置,默认绿涨红跌;方向同时用箭头与正负号表达,不只靠颜色。 diff --git a/docs/components/165-order-book.md b/docs/components/165-order-book.md new file mode 100644 index 0000000..a06c386 --- /dev/null +++ b/docs/components/165-order-book.md @@ -0,0 +1,52 @@ +# 165 OrderBook + +盘口。 + +## 用途 + +按价格显示卖档(上)与买档(下),带累计深度条与价差;可按价格步长合并档位;点击档位回传价格。 + +## 最小示例 + +```go +var state mujica.OrderBookState +book := mujica.OrderBookData{ + Bids: []mujica.BookLevel{{Price: 100.00, Size: 5}, {Price: 99.99, Size: 3}}, + Asks: []mujica.BookLevel{{Price: 100.01, Size: 1}, {Price: 100.02, Size: 2}}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if price, side, ok := mujica.OrderBook(c, &state, book, mujica.OrderBookOptions{Groups: []float64{0.01, 0.05}}).Clicked(); ok { + fmt.Println("order at", price, side) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `s` | `*OrderBookState` | 必填 | Group 为合并步长,0 取 Groups 第一项;不在 Groups 中 panic。 | +| `book` | `OrderBookData` | 必填 | Bids、Asks 与 Version(原地修改时递增)。 | +| `Decimals / SizeDecimals` | `int` | 2 / 0 | 价格与数量小数位。 | +| `Depth` | `int` | 8 | 每侧档数。 | +| `Groups` | `[]float64` | nil | 可选合并步长,须为价格精度的整数倍,否则 panic。 | +| `Disabled` | `bool` | false | 禁用点击与合并选择。 | + +## 状态 + +默认、悬停、聚焦、禁用;空盘口时只显示表头。 + +## 事件 + +`OrderBookResult.Clicked()` 返回被点击档位的价格与方向。 + +## 键盘操作 + +Tab 进入档位列表,↑/↓ 在档位间移动,Enter/Space 选中价格。 + +## 限制 + +- 合并以整数价格单位计算:买档向下取整、卖档向上取整。只在数据或步长变化时重新聚合。 +- 涨跌颜色由 `UseTrend(c, GreenUp|RedUp)` 按窗口设置,默认绿涨红跌;方向同时用箭头与正负号表达,不只靠颜色。 diff --git a/docs/components/166-level2-quotes.md b/docs/components/166-level2-quotes.md new file mode 100644 index 0000000..1b4d9bf --- /dev/null +++ b/docs/components/166-level2-quotes.md @@ -0,0 +1,46 @@ +# 166 Level2Quotes + +多档行情。 + +## 用途 + +并排显示买卖各 N 档的价格、数量与委托笔数;档位变化时高亮一次,并以箭头标出数量增减。 + +## 最小示例 + +```go +data := mujica.Level2Data{ + Bids: []mujica.L2Level{{Price: 100.00, Size: 500, Orders: 12}}, + Asks: []mujica.L2Level{{Price: 100.01, Size: 200, Orders: 3}}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Level2Quotes(c, data, mujica.Level2QuotesOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `data` | `Level2Data` | 必填 | Bids、Asks,最优价在前。 | +| `Decimals / SizeDecimals` | `int` | 2 / 0 | 价格与数量小数位。 | +| `Levels` | `int` | 5 | 每侧档数;不足的档位显示“—”。 | + +## 状态 + +默认、档位变化高亮(减少动画时只显示箭头)、空档。 + +## 事件 + +无。 + +## 键盘操作 + +不获取焦点;每行有包含档位、价格、数量和笔数的无障碍名称。 + +## 限制 + +- 价格变化视为新档位,不标增减箭头。 +- 涨跌颜色由 `UseTrend(c, GreenUp|RedUp)` 按窗口设置,默认绿涨红跌;方向同时用箭头与正负号表达,不只靠颜色。 diff --git a/docs/components/167-time-and-sales.md b/docs/components/167-time-and-sales.md new file mode 100644 index 0000000..d68511f --- /dev/null +++ b/docs/components/167-time-and-sales.md @@ -0,0 +1,48 @@ +# 167 TimeAndSales + +逐笔成交。 + +## 用途 + +逐笔成交列表,最新在上,只构建可见行;大单以菱形与粗体标记;可暂停跟随。 + +## 最小示例 + +```go +var state mujica.TimeAndSalesState +trades := []mujica.TradePrint{{ID: "1", Time: time.Now(), Price: 100.01, Size: 300, Side: mujica.SideBuy}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.TimeAndSales(c, &state, trades, mujica.TimeAndSalesOptions{LargeSize: 1000}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `s` | `*TimeAndSalesState` | 必填 | Paused 暂停跟随。 | +| `trades` | `[]TradePrint` | 必填 | 按时间先后追加;ID 唯一。 | +| `Decimals / SizeDecimals` | `int` | 2 / 0 | 价格与数量小数位。 | +| `LargeSize` | `float64` | 0 | 数量达到即标记为大单。 | +| `Height` | `float32` | 320 | 高度(DIP)。 | +| `Status / Error` | `DataStatus / string` | Ready | 加载、失败等状态。 | + +## 状态 + +跟随、暂停(显示新成交数量)、加载、失败、空列表。 + +## 事件 + +`ChoiceResult.Changed()` 在暂停或继续时为 true。 + +## 键盘操作 + +Tab 到达暂停按钮(Enter/Space 切换)与列表;列表内 ↑/↓ 移动。 + +## 限制 + +- 基于 List 虚拟化,100,000 条成交只构建可见行。 +- 暂停时冻结显示的条数,新成交不打断阅读。 +- 涨跌颜色由 `UseTrend(c, GreenUp|RedUp)` 按窗口设置,默认绿涨红跌;方向同时用箭头与正负号表达,不只靠颜色。 diff --git a/docs/components/168-depth-ladder.md b/docs/components/168-depth-ladder.md new file mode 100644 index 0000000..2421ee9 --- /dev/null +++ b/docs/components/168-depth-ladder.md @@ -0,0 +1,50 @@ +# 168 DepthLadder + +价格阶梯。 + +## 用途 + +按最小变动价位排列的价格阶梯(DOM):买量、价格、卖量三列,最新价居中并加框;点击买量或卖量单元格回调下单。 + +## 最小示例 + +```go +var state mujica.DepthLadderState +book := mujica.OrderBookData{Bids: []mujica.BookLevel{{Price: 100, Size: 5}}, Asks: []mujica.BookLevel{{Price: 100.01, Size: 2}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if price, side, ok := mujica.DepthLadder(c, &state, 100, book, mujica.DepthLadderOptions{TickSize: 0.01}).Clicked(); ok { + fmt.Println("place", side, "at", price) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `s` | `*DepthLadderState` | 必填 | Offset 为相对最新价滚动的档数。 | +| `last` | `float64` | 必填 | 最新价。 | +| `book` | `OrderBookData` | 必填 | 盘口数据。 | +| `TickSize` | `float64` | 必填 | 最小变动价位,须为价格精度的整数倍,否则 panic。 | +| `Decimals / SizeDecimals` | `int` | 2 / 0 | 小数位。 | +| `Rows` | `int` | 15 | 显示的行数。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +默认、悬停、聚焦、最新价行(底色、框线与菱形)、已滚动(显示回到最新价按钮)、禁用。 + +## 事件 + +`DepthLadderResult.Clicked()` 返回价格与方向(买量列为买入,卖量列为卖出)。 + +## 键盘操作 + +Tab 进入阶梯,方向键在单元格间移动,Enter/Space 下单;PageUp/PageDown 滚动半屏;滚轮逐档滚动。 + +## 限制 + +- 只构建可见行;按价位建立的数量索引只在数据变化时重建。 +- 涨跌颜色由 `UseTrend(c, GreenUp|RedUp)` 按窗口设置,默认绿涨红跌;方向同时用箭头与正负号表达,不只靠颜色。 diff --git a/docs/components/169-spread-indicator.md b/docs/components/169-spread-indicator.md new file mode 100644 index 0000000..f071535 --- /dev/null +++ b/docs/components/169-spread-indicator.md @@ -0,0 +1,41 @@ +# 169 SpreadIndicator + +价差指示。 + +## 用途 + +显示卖一减买一的价差与占中间价的百分比;超过阈值或买卖倒挂时给出带图标的文字提示。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SpreadIndicator(c, 99.95, 100.05, mujica.SpreadIndicatorOptions{WarnPercent: 0.5}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `bid / ask` | `float64` | 必填 | 买一价与卖一价。 | +| `Decimals` | `int` | 2 | 价差小数位。 | +| `WarnPercent` | `float64` | 0 | 价差百分比达到即提示;0 不提示,负数 panic。 | + +## 状态 + +正常、价差过大、倒挂。 + +## 事件 + +无。 + +## 键盘操作 + +不获取焦点;以状态角色读出。 + +## 限制 + +- 无。 diff --git a/docs/components/170-bid-ask-bar.md b/docs/components/170-bid-ask-bar.md new file mode 100644 index 0000000..6ef8828 --- /dev/null +++ b/docs/components/170-bid-ask-bar.md @@ -0,0 +1,41 @@ +# 170 BidAskBar + +买卖力量条。 + +## 用途 + +以分段条对比买卖成交量,两端标出占比与数量。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BidAskBar(c, 6234, 3820, mujica.BidAskBarOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `bid / ask` | `float64` | 必填 | 买量与卖量,负数或 NaN panic。 | +| `Decimals` | `int` | 0 | 数量小数位。 | +| `Label` | `string` | 内置“Bid and ask volume” | 无障碍名称。 | + +## 状态 + +默认;两者都为 0 时显示中性灰条与 50%。 + +## 事件 + +无。 + +## 键盘操作 + +不获取焦点;以计量角色读出买卖占比。 + +## 限制 + +- 涨跌颜色由 `UseTrend(c, GreenUp|RedUp)` 按窗口设置,默认绿涨红跌;方向同时用箭头与正负号表达,不只靠颜色。 diff --git a/docs/components/171-order-entry.md b/docs/components/171-order-entry.md new file mode 100644 index 0000000..fdbceb3 --- /dev/null +++ b/docs/components/171-order-entry.md @@ -0,0 +1,52 @@ +# 171 OrderEntry + +下单面板。 + +## 用途 + +限价、市价、止损与条件限价单的录入:方向、类型、数量、价格、触发价与有效期;同步与调用方异步校验;预估金额;提交防重入。建立在 Form 之上。 + +## 最小示例 + +```go +var state mujica.OrderEntryState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if order, ok := mujica.OrderEntry(c, &state, mujica.OrderEntryOptions{Symbol: "MUJC", Last: 100.2}).Submitted(); ok { + fmt.Println("place", order.Quantity) + state.EndSubmit("") + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `s` | `*OrderEntryState` | 必填 | Draft 为当前订单,Form 为表单状态。 | +| `Symbol` | `string` | 必填 | 代码,空值 panic。 | +| `Last` | `float64` | 0 | 最新价,用于市价预估和止损方向检查。 | +| `TickSize / LotSize` | `float64` | 0.01 / 1 | 价格与数量步长。 | +| `MaxQuantity` | `float64` | 0 | 数量上限,0 不限。 | +| `Initial` | `OrderDraft` | 买入限价 | 重置恢复的订单。 | +| `Validate` | `func(OrderDraft) string` | nil | 调用方同步规则。 | +| `Check` | `func(OrderDraft, uint64)` | nil | 异步检查(如可用资金),以 `s.Resolve(version, msg)` 回传;旧版本结果被丢弃。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +默认、字段错误(失焦或提交后)、异步检查中、提交中(按钮加载)、表单错误、禁用。 + +## 事件 + +`OrderEntryResult.Submitted()` 返回通过全部校验的订单;处理完毕后调用 `s.EndSubmit(err)`。 + +## 键盘操作 + +Tab 依次经过方向、类型、各字段与按钮;数量与价格字段 ↑/↓ 按步长调整;提交失败聚焦第一个错误字段。 + +## 限制 + +- 止损单检查:买入触发价须高于最新价,卖出须低于。 +- 数量字段的异步检查覆盖整张订单:任一字段变化都会让旧结果失效。 diff --git a/docs/components/172-quick-trade-buttons.md b/docs/components/172-quick-trade-buttons.md new file mode 100644 index 0000000..a5e2a07 --- /dev/null +++ b/docs/components/172-quick-trade-buttons.md @@ -0,0 +1,47 @@ +# 172 QuickTradeButtons + +快速交易按钮。 + +## 用途 + +以预设数量一键市价买入或卖出;可配置在发送前就近确认。 + +## 最小示例 + +```go +quantity := 10.0 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if side, q, ok := mujica.QuickTradeButtons(c, &quantity, mujica.QuickTradeButtonsOptions{Symbol: "MUJC", Confirm: true}).Traded(); ok { + fmt.Println(side, q) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `quantity` | `*float64` | 必填 | 当前数量,须为 Presets 之一,0 取第一项。 | +| `Symbol` | `string` | 必填 | 代码。 | +| `Presets` | `[]float64` | 1, 10, 100 | 数量预设。 | +| `Decimals` | `int` | 0 | 数量小数位。 | +| `Confirm` | `bool` | false | 发送前弹出确认,默认聚焦取消。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +默认、悬停、按下、聚焦、确认中、禁用。 + +## 事件 + +`QuickTradeResult.Traded()` 返回方向与数量。 + +## 键盘操作 + +Tab 到达数量分段与买卖按钮;Enter/Space 触发;确认浮层中 Enter 默认取消,Escape 关闭。 + +## 限制 + +- 涨跌颜色由 `UseTrend(c, GreenUp|RedUp)` 按窗口设置,默认绿涨红跌;方向同时用箭头与正负号表达,不只靠颜色。 diff --git a/docs/components/173-position-table.md b/docs/components/173-position-table.md new file mode 100644 index 0000000..95443d8 --- /dev/null +++ b/docs/components/173-position-table.md @@ -0,0 +1,49 @@ +# 173 PositionTable + +持仓表。 + +## 用途 + +持仓列表:数量、成本、现价、市值、浮动盈亏与比例,每行提供平仓操作。基于 DataTable,以稳定行 ID 保存选择与排序。 + +## 最小示例 + +```go +var state mujica.DataTableState[string] +rows := []mujica.PositionRow{{ID: "p1", Symbol: "MUJC", Quantity: 100, AvgCost: 400, Price: 412.08}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if id, ok := mujica.PositionTable(c, &state, rows, mujica.PositionTableOptions{}).Acted(); ok { + fmt.Println("close", id) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `s` | `*DataTableState[string]` | 必填 | 表格状态。 | +| `rows` | `[]PositionRow` | 必填 | ID 必须稳定。 | +| `Decimals` | `int` | 2 | 小数位。 | +| `Version` | `int` | 0 | 原地修改行时递增。 | +| `Status / Error` | `DataStatus / string` | Ready | 加载与失败状态。 | +| `Disabled` | `bool` | false | 禁用平仓。 | + +## 状态 + +默认、排序、选中、加载、失败、空、禁用。 + +## 事件 + +`TableActionResult.Acted()` 返回要平仓的行 ID;`Table` 为 DataTable 事件。 + +## 键盘操作 + +沿用 DataTable 的键盘操作;Tab 到达各行的平仓按钮。 + +## 限制 + +- 只构建可见行。 +- 涨跌颜色由 `UseTrend(c, GreenUp|RedUp)` 按窗口设置,默认绿涨红跌;方向同时用箭头与正负号表达,不只靠颜色。 diff --git a/docs/components/174-order-table.md b/docs/components/174-order-table.md new file mode 100644 index 0000000..aa1d93d --- /dev/null +++ b/docs/components/174-order-table.md @@ -0,0 +1,48 @@ +# 174 OrderTable + +委托表。 + +## 用途 + +委托列表:方向、类型、价格、成交进度与状态,按状态筛选;进行中的委托提供撤单。基于 DataTable。 + +## 最小示例 + +```go +var state mujica.OrderTableState +rows := []mujica.OrderRow{{ID: "o1", Symbol: "MUJC", Side: mujica.SideBuy, Price: 99.5, Quantity: 100, Filled: 40, Status: mujica.OrderPartial}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if id, ok := mujica.OrderTable(c, &state, rows, mujica.OrderTableOptions{}).Acted(); ok { + fmt.Println("cancel", id) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `s` | `*OrderTableState` | 必填 | Filter 为状态筛选,Table 为表格状态。 | +| `rows` | `[]OrderRow` | 必填 | Filled 不得超过 Quantity,否则 panic。 | +| `Decimals / QuantityDecimals` | `int` | 2 / 0 | 小数位。 | +| `Version` | `int` | 0 | 原地修改行时递增。 | +| `Status / Error` | `DataStatus / string` | Ready | 加载与失败状态。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +全部、进行中、已成交、已关闭四种筛选;部分成交进度条;禁用。 + +## 事件 + +`TableActionResult.Acted()` 返回要撤销的委托 ID。 + +## 键盘操作 + +筛选分段用方向键切换;表格沿用 DataTable 键盘操作;Tab 到达撤单按钮。 + +## 限制 + +- 筛选只在数据或条件变化时执行。 diff --git a/docs/components/175-trade-history-table.md b/docs/components/175-trade-history-table.md new file mode 100644 index 0000000..429704f --- /dev/null +++ b/docs/components/175-trade-history-table.md @@ -0,0 +1,49 @@ +# 175 TradeHistoryTable + +成交记录表。 + +## 用途 + +成交记录:时间、代码、方向、价格、数量与手续费;按日期范围筛选;导出当前范围的记录交给调用方。 + +## 最小示例 + +```go +var state mujica.TradeHistoryTableState +rows := []mujica.FillRow{{ID: "f1", Time: time.Now(), Symbol: "MUJC", Side: mujica.SideBuy, Price: 400, Quantity: 10, Fee: 1.2}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if fills, ok := mujica.TradeHistoryTable(c, &state, rows, mujica.TradeHistoryTableOptions{}).Exported(); ok { + fmt.Println("export", len(fills)) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `s` | `*TradeHistoryTableState` | 必填 | Range 为日期范围,零值不筛选。 | +| `rows` | `[]FillRow` | 必填 | 成交记录。 | +| `Decimals / QuantityDecimals` | `int` | 2 / 0 | 小数位。 | +| `Version` | `int` | 0 | 原地修改行时递增。 | +| `Status / Error` | `DataStatus / string` | Ready | 加载与失败状态。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +全部日期、指定范围、空范围、加载、失败、禁用。 + +## 事件 + +`TradeHistoryResult.Exported()` 返回导出请求时当前范围内的记录。 + +## 键盘操作 + +日期范围选择器与按钮按 Tab 顺序;表格沿用 DataTable 键盘操作。 + +## 限制 + +- 只回传数据,不生成文件:导出格式与写入由调用方负责。 +- 日期按每条记录自身时区的日期比较。 diff --git a/docs/components/176-pnl-display.md b/docs/components/176-pnl-display.md new file mode 100644 index 0000000..947e0b6 --- /dev/null +++ b/docs/components/176-pnl-display.md @@ -0,0 +1,44 @@ +# 176 PnLDisplay + +盈亏显示。 + +## 用途 + +并列显示已实现、未实现与当日盈亏,带正负号、箭头与语义色;可切换隐私遮蔽。 + +## 最小示例 + +```go +hidden := false +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.PnLDisplay(c, mujica.PnL{Realized: 1200.5, Unrealized: -340.2, Today: 88}, &hidden, mujica.PnLDisplayOptions{Currency: "$"}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `pnl` | `PnL` | 必填 | Realized、Unrealized、Today。 | +| `hidden` | `*bool` | 必填 | 为 true 时以“••••”遮蔽。 | +| `Decimals` | `int` | 2 | 小数位。 | +| `Currency` | `string` | "" | 金额前缀,例如 "$"。 | + +## 状态 + +正、负、零;已遮蔽。 + +## 事件 + +`ChoiceResult.Changed()` 在遮蔽切换时为 true。 + +## 键盘操作 + +Tab 到达遮蔽按钮,Enter/Space 切换。 + +## 限制 + +- 遮蔽时无障碍名称只读出“已隐藏”,不读出金额。 +- 涨跌颜色由 `UseTrend(c, GreenUp|RedUp)` 按窗口设置,默认绿涨红跌;方向同时用箭头与正负号表达,不只靠颜色。 diff --git a/docs/components/177-leverage-slider.md b/docs/components/177-leverage-slider.md new file mode 100644 index 0000000..31ecb1e --- /dev/null +++ b/docs/components/177-leverage-slider.md @@ -0,0 +1,46 @@ +# 177 LeverageSlider + +杠杆滑块。 + +## 用途 + +在预设杠杆档位间选择草稿值,显示高风险与极高风险区间提示,按“确认”后才写入值。 + +## 最小示例 + +```go +leverage := 5.0 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.LeverageSlider(c, &leverage, mujica.LeverageSliderOptions{Warning: 10, Danger: 50}).Changed() { + fmt.Println("leverage", leverage) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `value` | `*float64` | 必填 | 当前杠杆,须为 Levels 之一。 | +| `Levels` | `[]float64` | 1–100 八档 | 递增档位,至少两档。 | +| `Warning / Danger` | `float64` | 0 | 高风险与极高风险起点;Danger 须大于 Warning。 | +| `Label` | `string` | 内置“Leverage” | 名称。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +默认、聚焦、拖动、高风险、极高风险、草稿未确认、禁用。 + +## 事件 + +`ChoiceResult.Changed()` 在确认写入时为 true。 + +## 键盘操作 + +Tab 聚焦滑块:←/↓ 与 →/↑ 逐档、Home/End 到两端;Tab 到达确认按钮。 + +## 限制 + +- 滑块命中区高 44 DIP;风险区间以色带、图标和文字共同表达。 diff --git a/docs/components/178-margin-indicator.md b/docs/components/178-margin-indicator.md new file mode 100644 index 0000000..e3d3332 --- /dev/null +++ b/docs/components/178-margin-indicator.md @@ -0,0 +1,41 @@ +# 178 MarginIndicator + +保证金率指示。 + +## 用途 + +显示保证金率(维持保证金 / 权益)及其与警戒线、强平线的关系。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.MarginIndicator(c, 0.86, mujica.MarginIndicatorOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `ratio` | `float64` | 必填 | 保证金率,0 以上。 | +| `Warning / Liquidation` | `float64` | 0.8 / 1 | 警戒与强平线;须 0 < Warning < Liquidation。 | +| `Label` | `string` | 内置“Margin ratio” | 名称。 | + +## 状态 + +安全、追加保证金、强制平仓。 + +## 事件 + +无。 + +## 键盘操作 + +不获取焦点;以计量角色读出比率、状态与两条线。 + +## 限制 + +- 状态同时用图标、文字与颜色表达;两条线粗细不同,并在下方以文字标注。 diff --git a/docs/components/179-risk-meter.md b/docs/components/179-risk-meter.md new file mode 100644 index 0000000..208b797 --- /dev/null +++ b/docs/components/179-risk-meter.md @@ -0,0 +1,41 @@ +# 179 RiskMeter + +风险等级。 + +## 用途 + +分段刻度显示风险等级,当前段上方有菱形标记,并显示等级名称与说明。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.RiskMeter(c, 4, mujica.RiskMeterOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `level` | `int` | 必填 | 从 1 开始,超出范围 panic。 | +| `Levels` | `[]RiskLevel` | 内置五级 | 各级名称与说明,至少两级。 | +| `Label` | `string` | 内置“Risk level” | 名称。 | + +## 状态 + +各等级。 + +## 事件 + +无。 + +## 键盘操作 + +不获取焦点;以计量角色读出“第 n 级,共 N 级”和名称。 + +## 限制 + +- 颜色只辅助:位置标记与等级文字同时表达等级。 diff --git a/docs/components/180-order-confirm-dialog.md b/docs/components/180-order-confirm-dialog.md new file mode 100644 index 0000000..00225c1 --- /dev/null +++ b/docs/components/180-order-confirm-dialog.md @@ -0,0 +1,52 @@ +# 180 OrderConfirmDialog + +下单确认对话框。 + +## 用途 + +以模态对话框展示下单摘要与风险提示,默认聚焦取消;可要求勾选确认后才能下单。 + +## 最小示例 + +```go +open := true +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.OrderConfirmDialog(c, &open, mujica.OrderConfirmDialogOptions{ + Lines: []mujica.OrderSummaryLine{{Label: "Symbol", Value: "MUJC"}, {Label: "Quantity", Value: "100"}}, + Risk: "Leveraged products can lose more than the deposit.", + Acknowledge: "I understand the risk", + }) + if r.Confirmed { + fmt.Println("send order") + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `open` | `*bool` | 必填 | 是否显示。 | +| `Lines` | `[]OrderSummaryLine` | 必填 | 摘要行,空值 panic。 | +| `Title` | `string` | 内置“Confirm order” | 标题。 | +| `Risk` | `string` | "" | 风险提示。 | +| `Acknowledge` | `string` | "" | 二次确认复选框文字;设置后须勾选才能下单。 | +| `ConfirmLabel` | `string` | 内置“Place order” | 确认按钮文字。 | + +## 状态 + +打开、未勾选(下单按钮禁用)、已勾选。 + +## 事件 + +`AlertDialogResult.Confirmed` / `Canceled`;Escape 视为取消。 + +## 键盘操作 + +打开时焦点在取消上;Tab 在复选框与按钮间移动;Escape 取消。点击遮罩不关闭。 + +## 限制 + +- 每次打开都需重新勾选。 diff --git a/example_trading_test.go b/example_trading_test.go new file mode 100644 index 0000000..6c32d4f --- /dev/null +++ b/example_trading_test.go @@ -0,0 +1,221 @@ +package mujica_test + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func ExampleTickerTape() { + items := []mujica.TickerItem{{Symbol: "MUJC", Price: 412.08, ChangePercent: -1.35}, {Symbol: "AVE", Price: 88.2, ChangePercent: 2.1}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.TickerTape(c, items, mujica.TickerTapeOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleQuoteCard() { + quote := mujica.Quote{Symbol: "MUJC", Name: "Ave Mujica Holdings", Price: 412.08, Change: -5.62, ChangePercent: -1.35} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.QuoteCard(c, quote, mujica.QuoteCardOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExamplePriceText() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.UseTrend(c, mujica.RedUp) + mujica.PriceText(c, 18234.5, mujica.PriceTextOptions{Compare: true, Reference: 18000}) + } + ui.Render(view, 400, 300, 1) +} + +func ExamplePriceChangeBadge() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.PriceChangeBadge(c, -5.62, -1.35, mujica.PriceChangeBadgeOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleOrderBook() { + var state mujica.OrderBookState + book := mujica.OrderBookData{ + Bids: []mujica.BookLevel{{Price: 100.00, Size: 5}, {Price: 99.99, Size: 3}}, + Asks: []mujica.BookLevel{{Price: 100.01, Size: 1}, {Price: 100.02, Size: 2}}, + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if price, side, ok := mujica.OrderBook(c, &state, book, mujica.OrderBookOptions{Groups: []float64{0.01, 0.05}}).Clicked(); ok { + fmt.Println("order at", price, side) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleLevel2Quotes() { + data := mujica.Level2Data{ + Bids: []mujica.L2Level{{Price: 100.00, Size: 500, Orders: 12}}, + Asks: []mujica.L2Level{{Price: 100.01, Size: 200, Orders: 3}}, + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Level2Quotes(c, data, mujica.Level2QuotesOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleTimeAndSales() { + var state mujica.TimeAndSalesState + trades := []mujica.TradePrint{{ID: "1", Time: time.Now(), Price: 100.01, Size: 300, Side: mujica.SideBuy}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.TimeAndSales(c, &state, trades, mujica.TimeAndSalesOptions{LargeSize: 1000}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleDepthLadder() { + var state mujica.DepthLadderState + book := mujica.OrderBookData{Bids: []mujica.BookLevel{{Price: 100, Size: 5}}, Asks: []mujica.BookLevel{{Price: 100.01, Size: 2}}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if price, side, ok := mujica.DepthLadder(c, &state, 100, book, mujica.DepthLadderOptions{TickSize: 0.01}).Clicked(); ok { + fmt.Println("place", side, "at", price) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleSpreadIndicator() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SpreadIndicator(c, 99.95, 100.05, mujica.SpreadIndicatorOptions{WarnPercent: 0.5}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleBidAskBar() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BidAskBar(c, 6234, 3820, mujica.BidAskBarOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleOrderEntry() { + var state mujica.OrderEntryState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if order, ok := mujica.OrderEntry(c, &state, mujica.OrderEntryOptions{Symbol: "MUJC", Last: 100.2}).Submitted(); ok { + fmt.Println("place", order.Quantity) + state.EndSubmit("") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleQuickTradeButtons() { + quantity := 10.0 + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if side, q, ok := mujica.QuickTradeButtons(c, &quantity, mujica.QuickTradeButtonsOptions{Symbol: "MUJC", Confirm: true}).Traded(); ok { + fmt.Println(side, q) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExamplePositionTable() { + var state mujica.DataTableState[string] + rows := []mujica.PositionRow{{ID: "p1", Symbol: "MUJC", Quantity: 100, AvgCost: 400, Price: 412.08}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if id, ok := mujica.PositionTable(c, &state, rows, mujica.PositionTableOptions{}).Acted(); ok { + fmt.Println("close", id) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleOrderTable() { + var state mujica.OrderTableState + rows := []mujica.OrderRow{{ID: "o1", Symbol: "MUJC", Side: mujica.SideBuy, Price: 99.5, Quantity: 100, Filled: 40, Status: mujica.OrderPartial}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if id, ok := mujica.OrderTable(c, &state, rows, mujica.OrderTableOptions{}).Acted(); ok { + fmt.Println("cancel", id) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleTradeHistoryTable() { + var state mujica.TradeHistoryTableState + rows := []mujica.FillRow{{ID: "f1", Time: time.Now(), Symbol: "MUJC", Side: mujica.SideBuy, Price: 400, Quantity: 10, Fee: 1.2}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if fills, ok := mujica.TradeHistoryTable(c, &state, rows, mujica.TradeHistoryTableOptions{}).Exported(); ok { + fmt.Println("export", len(fills)) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExamplePnLDisplay() { + hidden := false + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.PnLDisplay(c, mujica.PnL{Realized: 1200.5, Unrealized: -340.2, Today: 88}, &hidden, mujica.PnLDisplayOptions{Currency: "$"}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleLeverageSlider() { + leverage := 5.0 + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.LeverageSlider(c, &leverage, mujica.LeverageSliderOptions{Warning: 10, Danger: 50}).Changed() { + fmt.Println("leverage", leverage) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMarginIndicator() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.MarginIndicator(c, 0.86, mujica.MarginIndicatorOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleRiskMeter() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.RiskMeter(c, 4, mujica.RiskMeterOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleOrderConfirmDialog() { + open := true + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.OrderConfirmDialog(c, &open, mujica.OrderConfirmDialogOptions{ + Lines: []mujica.OrderSummaryLine{{Label: "Symbol", Value: "MUJC"}, {Label: "Quantity", Value: "100"}}, + Risk: "Leveraged products can lose more than the deposit.", + Acknowledge: "I understand the risk", + }) + if r.Confirmed { + fmt.Println("send order") + } + } + ui.Render(view, 400, 300, 1) +} diff --git a/examples/gallery/pages_trading.go b/examples/gallery/pages_trading.go index e79ef71..5a65056 100644 --- a/examples/gallery/pages_trading.go +++ b/examples/gallery/pages_trading.go @@ -1,3 +1,276 @@ package main -var tradingPages = []page{} +import ( + "fmt" + "math" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +const tradingCategory = "Trading" + +// tradingTrend shows and applies the rise-color switch. +func tradingTrend(c *ui.Context, redUp *bool, log func(string)) { + if mujica.Checkbox(c, redUp, "Red means up (China)", mujica.CheckboxOptions{}).Changed() { + log(fmt.Sprintf("red up %v", *redUp)) + } + t := mujica.GreenUp + if *redUp { + t = mujica.RedUp + } + mujica.UseTrend(c, t) +} + +// tradingAction is a demo button at its natural width. +func tradingAction(c *ui.Context, label string) bool { + clicked := false + ui.Row(c).Children(func() { + clicked = mujica.Button(c, label, mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() + }) + return clicked +} + +// tradingBook is a deterministic book around mid, moved by step. +func tradingBook(mid float64, step int) mujica.OrderBookData { + var b mujica.OrderBookData + for i := range 12 { + w := float64((i*7+step*3)%11 + 1) + b.Bids = append(b.Bids, mujica.BookLevel{Price: math.Round((mid-0.01*float64(i+1))*100) / 100, Size: w * 10}) + b.Asks = append(b.Asks, mujica.BookLevel{Price: math.Round((mid+0.01*float64(i))*100) / 100, Size: float64((i*5+step)%9+1) * 10}) + } + b.Version = step + return b +} + +var tradingPages = []page{ + {ID: "161", Name: "TickerTape", ZhName: "行情滚动条", Category: tradingCategory, Code: tradingCode["TickerTape"], Demo: tradingTickerDemo, + Keys: "Tab focuses the tape, which pauses it. With reduced motion, Left and Right turn pages."}, + {ID: "162", Name: "QuoteCard", ZhName: "报价卡片", Category: tradingCategory, Code: tradingCode["QuoteCard"], Demo: tradingQuoteDemo, + Keys: "The card takes no focus; controls in its chart slot do."}, + {ID: "163", Name: "PriceText", ZhName: "价格文本", Category: tradingCategory, Code: tradingCode["PriceText"], Demo: tradingPriceDemo, + Keys: "Display only."}, + {ID: "164", Name: "PriceChangeBadge", ZhName: "涨跌徽标", Category: tradingCategory, Code: tradingCode["PriceChangeBadge"], Demo: tradingBadgeDemo, + Keys: "Display only; the name reads the direction and values."}, + {ID: "165", Name: "OrderBook", ZhName: "盘口", Category: tradingCategory, Code: tradingCode["OrderBook"], Demo: tradingBookDemo, + Keys: "Tab into the levels, Up and Down move, Enter picks a price."}, + {ID: "166", Name: "Level2Quotes", ZhName: "多档行情", Category: tradingCategory, Code: tradingCode["Level2Quotes"], Demo: tradingLevel2Demo, + Keys: "Display only; each row reads its level, price, size and orders."}, + {ID: "167", Name: "TimeAndSales", ZhName: "逐笔成交", Category: tradingCategory, Code: tradingCode["TimeAndSales"], Demo: tradingTapeDemo, + Keys: "Tab to Pause and the list; Up and Down move in the list."}, + {ID: "168", Name: "DepthLadder", ZhName: "价格阶梯", Category: tradingCategory, Code: tradingCode["DepthLadder"], Demo: tradingLadderDemo, + Keys: "Arrows move between cells, Enter orders, Page Up and Page Down scroll, the wheel steps a tick."}, + {ID: "169", Name: "SpreadIndicator", ZhName: "价差指示", Category: tradingCategory, Code: tradingCode["SpreadIndicator"], Demo: tradingSpreadDemo, + Keys: "Display only."}, + {ID: "170", Name: "BidAskBar", ZhName: "买卖力量条", Category: tradingCategory, Code: tradingCode["BidAskBar"], Demo: tradingBarDemo, + Keys: "Display only; read as a meter."}, + {ID: "171", Name: "OrderEntry", ZhName: "下单面板", Category: tradingCategory, Code: tradingCode["OrderEntry"], Demo: tradingEntryDemo, + Keys: "Tab through side, type and fields; Up and Down step numbers; a failed submit focuses the first error."}, + {ID: "172", Name: "QuickTradeButtons", ZhName: "快速交易按钮", Category: tradingCategory, Code: tradingCode["QuickTradeButtons"], Demo: tradingQuickDemo, + Keys: "Enter or Space trades; with Confirm, Enter in the popup cancels and Escape closes it."}, + {ID: "173", Name: "PositionTable", ZhName: "持仓表", Category: tradingCategory, Code: tradingCode["PositionTable"], Demo: tradingPositionsDemo, + Keys: "DataTable keys; Tab reaches each Close button."}, + {ID: "174", Name: "OrderTable", ZhName: "委托表", Category: tradingCategory, Code: tradingCode["OrderTable"], Demo: tradingOrdersDemo, + Keys: "Arrows switch the status filter; DataTable keys; Tab reaches Cancel."}, + {ID: "175", Name: "TradeHistoryTable", ZhName: "成交记录表", Category: tradingCategory, Code: tradingCode["TradeHistoryTable"], Demo: tradingHistoryDemo, + Keys: "Tab to the range picker, Export and the table."}, + {ID: "176", Name: "PnLDisplay", ZhName: "盈亏显示", Category: tradingCategory, Code: tradingCode["PnLDisplay"], Demo: tradingPnLDemo, + Keys: "Tab to the eye button; Enter or Space masks the amounts."}, + {ID: "177", Name: "LeverageSlider", ZhName: "杠杆滑块", Category: tradingCategory, Code: tradingCode["LeverageSlider"], Demo: tradingLeverageDemo, + Keys: "Arrows step levels, Home and End jump; Apply sets the value."}, + {ID: "178", Name: "MarginIndicator", ZhName: "保证金率指示", Category: tradingCategory, Code: tradingCode["MarginIndicator"], Demo: tradingMarginDemo, + Keys: "Display only; read as a meter with its lines."}, + {ID: "179", Name: "RiskMeter", ZhName: "风险等级", Category: tradingCategory, Code: tradingCode["RiskMeter"], Demo: tradingRiskDemo, + Keys: "Display only."}, + {ID: "180", Name: "OrderConfirmDialog", ZhName: "下单确认对话框", Category: tradingCategory, Code: tradingCode["OrderConfirmDialog"], Demo: tradingConfirmDemo, + Keys: "Cancel has the focus; Escape cancels; the backdrop does not close it."}, +} + +type tradingTickerState struct { + redUp bool + items []mujica.TickerItem +} + +func tradingTickerDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "161", func() tradingTickerState { + return tradingTickerState{items: []mujica.TickerItem{{Symbol: "MUJC", Price: 412.08, ChangePercent: -1.35}, {Symbol: "AVE", Price: 88.2, ChangePercent: 2.1}, {Symbol: "OBLV", Price: 1204.5, ChangePercent: 0.4}, + {Symbol: "DOLO", Price: 7.25, ChangePercent: -0.8}, {Symbol: "MORT", Price: 33.1, ChangePercent: 1.2}, {Symbol: "TIMR", Price: 61.9, ChangePercent: -2.3}}} + }) + tradingTrend(c, &d.redUp, log) + if tradingAction(c, "Move prices") { + for i := range d.items { + d.items[i].ChangePercent = -d.items[i].ChangePercent + } + log("prices moved") + } + ui.Box(c).Width(560).Children(func() { mujica.TickerTape(c, d.items, mujica.TickerTapeOptions{}) }) + formStates(c, func() { + ui.Box(c).Width(280).Children(func() { mujica.TickerTape(c, d.items[:2], mujica.TickerTapeOptions{Speed: 15}) }) + }) +} + +type tradingQuoteState struct { + redUp bool + price float64 +} + +func tradingQuoteDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "162", func() tradingQuoteState { return tradingQuoteState{price: 412.08} }) + tradingTrend(c, &d.redUp, log) + if mujica.Slider(c, &d.price, mujica.SliderOptions{Min: 380, Max: 440, Step: 0.01, Label: "Price", ShowValue: true}).Changed() { + log(fmt.Sprintf("price %.2f", d.price)) + } + change := d.price - 417.7 + ui.Row(c).Gap(16).Wrap().Children(func() { + mujica.QuoteCard(c, mujica.Quote{Symbol: "MUJC", Name: "Ave Mujica Holdings", Price: d.price, Change: change, ChangePercent: change / 417.7 * 100}, + mujica.QuoteCardOptions{Chart: func() { + k := mujica.Tokens(c) + ui.Box(c).Fill().Draw(func(p *ui.Painter, r ui.Rect) { + p.Line(r.X, r.Y+r.H*0.7, r.X+r.W/2, r.Y+r.H*0.3, 1.5, k.Info) + p.Line(r.X+r.W/2, r.Y+r.H*0.3, r.X+r.W, r.Y+r.H*(0.5-float32(change)/40), 1.5, k.Info) + }) + }}) + mujica.QuoteCard(c, mujica.Quote{Symbol: "AVE", Price: 88.2}, mujica.QuoteCardOptions{}) + }) +} + +type tradingPriceState struct { + redUp, noFlash, grouping bool + price float64 +} + +func tradingPriceDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "163", func() tradingPriceState { return tradingPriceState{price: 18234.5, grouping: true} }) + tradingTrend(c, &d.redUp, log) + formToggles(c, []string{"Thousands separators", "No flash"}, &d.grouping, &d.noFlash) + ui.Row(c).Gap(8).Children(func() { + if mujica.Button(c, "Tick up", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + d.price += 12.5 + log(fmt.Sprintf("price %.2f", d.price)) + } + if mujica.Button(c, "Tick down", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + d.price -= 12.5 + log(fmt.Sprintf("price %.2f", d.price)) + } + }) + mujica.PriceText(c, d.price, mujica.PriceTextOptions{Size: 28, Compare: true, Reference: 18234.5, NoFlash: d.noFlash, NoGrouping: !d.grouping}) + formStates(c, func() { + mujica.PriceText(c, 0.004521, mujica.PriceTextOptions{Decimals: 6}) + mujica.PriceText(c, 100, mujica.PriceTextOptions{Compare: true, Reference: 100}) + }) +} + +type tradingBadgeState struct { + redUp, hidePercent bool + change float64 +} + +func tradingBadgeDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "164", func() tradingBadgeState { return tradingBadgeState{change: 1.25} }) + tradingTrend(c, &d.redUp, log) + formToggles(c, []string{"Hide percent"}, &d.hidePercent) + if mujica.Slider(c, &d.change, mujica.SliderOptions{Min: -5, Max: 5, Step: 0.05, Label: "Change", ShowValue: true}).Changed() { + log(fmt.Sprintf("change %.2f", d.change)) + } + mujica.PriceChangeBadge(c, d.change, d.change/1.47, mujica.PriceChangeBadgeOptions{HidePercent: d.hidePercent}) + formStates(c, func() { + mujica.PriceChangeBadge(c, 2.4, 1.2, mujica.PriceChangeBadgeOptions{}) + mujica.PriceChangeBadge(c, -2.4, -1.2, mujica.PriceChangeBadgeOptions{}) + mujica.PriceChangeBadge(c, 0, 0, mujica.PriceChangeBadgeOptions{}) + }) +} + +type tradingBookState struct { + redUp, disabled bool + step int + book mujica.OrderBookState +} + +func tradingBookDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "165", func() tradingBookState { return tradingBookState{} }) + tradingTrend(c, &d.redUp, log) + formToggles(c, []string{"Disabled"}, &d.disabled) + if tradingAction(c, "Next update") { + d.step++ + log(fmt.Sprintf("book update %d", d.step)) + } + ui.Box(c).Width(320).Children(func() { + r := mujica.OrderBook(c, &d.book, tradingBook(100, d.step), mujica.OrderBookOptions{Depth: 6, Groups: []float64{0.01, 0.05, 0.1}, Disabled: d.disabled}) + if price, side, ok := r.Clicked(); ok { + log(fmt.Sprintf("level %v at %.2f", side, price)) + } + }) +} + +type tradingLevel2State struct { + redUp bool + step int +} + +func tradingLevel2Demo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "166", func() tradingLevel2State { return tradingLevel2State{} }) + tradingTrend(c, &d.redUp, log) + if tradingAction(c, "Next update") { + d.step++ + log(fmt.Sprintf("level 2 update %d", d.step)) + } + book := tradingBook(100, d.step) + var data mujica.Level2Data + for i := range 5 { + data.Bids = append(data.Bids, mujica.L2Level{Price: book.Bids[i].Price, Size: book.Bids[i].Size, Orders: int(book.Bids[i].Size / 10)}) + data.Asks = append(data.Asks, mujica.L2Level{Price: book.Asks[i].Price, Size: book.Asks[i].Size, Orders: int(book.Asks[i].Size / 10)}) + } + ui.Box(c).Width(620).Children(func() { mujica.Level2Quotes(c, data, mujica.Level2QuotesOptions{}) }) +} + +type tradingTapeState struct { + redUp bool + trades []mujica.TradePrint + tape mujica.TimeAndSalesState +} + +func tradingTapeDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "167", func() tradingTapeState { return tradingTapeState{} }) + tradingTrend(c, &d.redUp, log) + if tradingAction(c, "Add 20 trades") { + at := time.Date(2026, 10, 5, 9, 30, 0, 0, time.Local) + for range 20 { + n := len(d.trades) + side := mujica.SideBuy + if n%3 == 1 { + side = mujica.SideSell + } + d.trades = append(d.trades, mujica.TradePrint{ID: fmt.Sprint(n), Time: at.Add(time.Duration(n) * time.Second), + Price: 100 + float64(n%17)/100, Size: float64((n*37)%1500 + 1), Side: side}) + } + log(fmt.Sprintf("%d trades", len(d.trades))) + } + ui.Box(c).Width(460).Children(func() { + if mujica.TimeAndSales(c, &d.tape, d.trades, mujica.TimeAndSalesOptions{LargeSize: 1000}).Changed() { + log(fmt.Sprintf("paused %v", d.tape.Paused)) + } + }) +} + +type tradingLadderState struct { + redUp, disabled bool + last float64 + ladder mujica.DepthLadderState +} + +func tradingLadderDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "168", func() tradingLadderState { return tradingLadderState{last: 100} }) + tradingTrend(c, &d.redUp, log) + formToggles(c, []string{"Disabled"}, &d.disabled) + if mujica.Slider(c, &d.last, mujica.SliderOptions{Min: 99.9, Max: 100.1, Step: 0.01, Label: "Last price", ShowValue: true}).Changed() { + log(fmt.Sprintf("last %.2f", d.last)) + } + ui.Box(c).Width(360).Children(func() { + r := mujica.DepthLadder(c, &d.ladder, d.last, tradingBook(100, 0), mujica.DepthLadderOptions{TickSize: 0.01, Rows: 11, Disabled: d.disabled}) + if price, side, ok := r.Clicked(); ok { + log(fmt.Sprintf("order %v at %.2f", side, price)) + } + }) +} diff --git a/examples/gallery/pages_trading_code.go b/examples/gallery/pages_trading_code.go new file mode 100644 index 0000000..b5fdbc7 --- /dev/null +++ b/examples/gallery/pages_trading_code.go @@ -0,0 +1,156 @@ +package main + +// tradingCode holds each page's copyable snippet, the same as its doc and Example. +var tradingCode = map[string]string{ + "TickerTape": `items := []mujica.TickerItem{{Symbol: "MUJC", Price: 412.08, ChangePercent: -1.35}, {Symbol: "AVE", Price: 88.2, ChangePercent: 2.1}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.TickerTape(c, items, mujica.TickerTapeOptions{}) +} +ui.Render(view, 400, 300, 1)`, + "QuoteCard": `quote := mujica.Quote{Symbol: "MUJC", Name: "Ave Mujica Holdings", Price: 412.08, Change: -5.62, ChangePercent: -1.35} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.QuoteCard(c, quote, mujica.QuoteCardOptions{}) +} +ui.Render(view, 400, 300, 1)`, + "PriceText": `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.UseTrend(c, mujica.RedUp) + mujica.PriceText(c, 18234.5, mujica.PriceTextOptions{Compare: true, Reference: 18000}) +} +ui.Render(view, 400, 300, 1)`, + "PriceChangeBadge": `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.PriceChangeBadge(c, -5.62, -1.35, mujica.PriceChangeBadgeOptions{}) +} +ui.Render(view, 400, 300, 1)`, + "OrderBook": `var state mujica.OrderBookState +book := mujica.OrderBookData{ + Bids: []mujica.BookLevel{{Price: 100.00, Size: 5}, {Price: 99.99, Size: 3}}, + Asks: []mujica.BookLevel{{Price: 100.01, Size: 1}, {Price: 100.02, Size: 2}}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if price, side, ok := mujica.OrderBook(c, &state, book, mujica.OrderBookOptions{Groups: []float64{0.01, 0.05}}).Clicked(); ok { + fmt.Println("order at", price, side) + } +} +ui.Render(view, 400, 300, 1)`, + "Level2Quotes": `data := mujica.Level2Data{ + Bids: []mujica.L2Level{{Price: 100.00, Size: 500, Orders: 12}}, + Asks: []mujica.L2Level{{Price: 100.01, Size: 200, Orders: 3}}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Level2Quotes(c, data, mujica.Level2QuotesOptions{}) +} +ui.Render(view, 400, 300, 1)`, + "TimeAndSales": `var state mujica.TimeAndSalesState +trades := []mujica.TradePrint{{ID: "1", Time: time.Now(), Price: 100.01, Size: 300, Side: mujica.SideBuy}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.TimeAndSales(c, &state, trades, mujica.TimeAndSalesOptions{LargeSize: 1000}) +} +ui.Render(view, 400, 300, 1)`, + "DepthLadder": `var state mujica.DepthLadderState +book := mujica.OrderBookData{Bids: []mujica.BookLevel{{Price: 100, Size: 5}}, Asks: []mujica.BookLevel{{Price: 100.01, Size: 2}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if price, side, ok := mujica.DepthLadder(c, &state, 100, book, mujica.DepthLadderOptions{TickSize: 0.01}).Clicked(); ok { + fmt.Println("place", side, "at", price) + } +} +ui.Render(view, 400, 300, 1)`, + "SpreadIndicator": `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SpreadIndicator(c, 99.95, 100.05, mujica.SpreadIndicatorOptions{WarnPercent: 0.5}) +} +ui.Render(view, 400, 300, 1)`, + "BidAskBar": `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BidAskBar(c, 6234, 3820, mujica.BidAskBarOptions{}) +} +ui.Render(view, 400, 300, 1)`, + "OrderEntry": `var state mujica.OrderEntryState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if order, ok := mujica.OrderEntry(c, &state, mujica.OrderEntryOptions{Symbol: "MUJC", Last: 100.2}).Submitted(); ok { + fmt.Println("place", order.Quantity) + state.EndSubmit("") + } +} +ui.Render(view, 400, 300, 1)`, + "QuickTradeButtons": `quantity := 10.0 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if side, q, ok := mujica.QuickTradeButtons(c, &quantity, mujica.QuickTradeButtonsOptions{Symbol: "MUJC", Confirm: true}).Traded(); ok { + fmt.Println(side, q) + } +} +ui.Render(view, 400, 300, 1)`, + "PositionTable": `var state mujica.DataTableState[string] +rows := []mujica.PositionRow{{ID: "p1", Symbol: "MUJC", Quantity: 100, AvgCost: 400, Price: 412.08}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if id, ok := mujica.PositionTable(c, &state, rows, mujica.PositionTableOptions{}).Acted(); ok { + fmt.Println("close", id) + } +} +ui.Render(view, 400, 300, 1)`, + "OrderTable": `var state mujica.OrderTableState +rows := []mujica.OrderRow{{ID: "o1", Symbol: "MUJC", Side: mujica.SideBuy, Price: 99.5, Quantity: 100, Filled: 40, Status: mujica.OrderPartial}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if id, ok := mujica.OrderTable(c, &state, rows, mujica.OrderTableOptions{}).Acted(); ok { + fmt.Println("cancel", id) + } +} +ui.Render(view, 400, 300, 1)`, + "TradeHistoryTable": `var state mujica.TradeHistoryTableState +rows := []mujica.FillRow{{ID: "f1", Time: time.Now(), Symbol: "MUJC", Side: mujica.SideBuy, Price: 400, Quantity: 10, Fee: 1.2}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if fills, ok := mujica.TradeHistoryTable(c, &state, rows, mujica.TradeHistoryTableOptions{}).Exported(); ok { + fmt.Println("export", len(fills)) + } +} +ui.Render(view, 400, 300, 1)`, + "PnLDisplay": `hidden := false +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.PnLDisplay(c, mujica.PnL{Realized: 1200.5, Unrealized: -340.2, Today: 88}, &hidden, mujica.PnLDisplayOptions{Currency: "$"}) +} +ui.Render(view, 400, 300, 1)`, + "LeverageSlider": `leverage := 5.0 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.LeverageSlider(c, &leverage, mujica.LeverageSliderOptions{Warning: 10, Danger: 50}).Changed() { + fmt.Println("leverage", leverage) + } +} +ui.Render(view, 400, 300, 1)`, + "MarginIndicator": `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.MarginIndicator(c, 0.86, mujica.MarginIndicatorOptions{}) +} +ui.Render(view, 400, 300, 1)`, + "RiskMeter": `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.RiskMeter(c, 4, mujica.RiskMeterOptions{}) +} +ui.Render(view, 400, 300, 1)`, + "OrderConfirmDialog": `open := true +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.OrderConfirmDialog(c, &open, mujica.OrderConfirmDialogOptions{ + Lines: []mujica.OrderSummaryLine{{Label: "Symbol", Value: "MUJC"}, {Label: "Quantity", Value: "100"}}, + Risk: "Leveraged products can lose more than the deposit.", + Acknowledge: "I understand the risk", + }) + if r.Confirmed { + fmt.Println("send order") + } +} +ui.Render(view, 400, 300, 1)`, +} diff --git a/examples/gallery/pages_trading_orders.go b/examples/gallery/pages_trading_orders.go new file mode 100644 index 0000000..cecdc50 --- /dev/null +++ b/examples/gallery/pages_trading_orders.go @@ -0,0 +1,286 @@ +package main + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +type tradingSpreadState struct { + ask, warn float64 +} + +func tradingSpreadDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "169", func() tradingSpreadState { return tradingSpreadState{ask: 100.05, warn: 0.5} }) + if mujica.Slider(c, &d.ask, mujica.SliderOptions{Min: 99.5, Max: 101, Step: 0.01, Label: "Ask (bid 99.95)", ShowValue: true}).Changed() { + log(fmt.Sprintf("ask %.2f", d.ask)) + } + if mujica.Slider(c, &d.warn, mujica.SliderOptions{Min: 0, Max: 2, Step: 0.1, Label: "Warn at percent", ShowValue: true}).Changed() { + log(fmt.Sprintf("warn %.1f%%", d.warn)) + } + mujica.SpreadIndicator(c, 99.95, d.ask, mujica.SpreadIndicatorOptions{WarnPercent: d.warn}) + formStates(c, func() { + mujica.SpreadIndicator(c, 99.95, 100.05, mujica.SpreadIndicatorOptions{}) + mujica.SpreadIndicator(c, 99, 101, mujica.SpreadIndicatorOptions{WarnPercent: 0.5}) + mujica.SpreadIndicator(c, 100.1, 100, mujica.SpreadIndicatorOptions{}) + }) +} + +type tradingBarState struct { + redUp bool + bid, ask float64 +} + +func tradingBarDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "170", func() tradingBarState { return tradingBarState{bid: 6234, ask: 3820} }) + tradingTrend(c, &d.redUp, log) + for _, v := range []struct { + name string + p *float64 + }{{"Bid volume", &d.bid}, {"Ask volume", &d.ask}} { + if mujica.Slider(c, v.p, mujica.SliderOptions{Min: 0, Max: 10000, Step: 1, Label: v.name, ShowValue: true}).Changed() { + log(fmt.Sprintf("%s %.0f", v.name, *v.p)) + } + } + ui.Box(c).Width(360).Children(func() { mujica.BidAskBar(c, d.bid, d.ask, mujica.BidAskBarOptions{}) }) +} + +type tradingEntryState struct { + redUp, disabled, reject bool + entry mujica.OrderEntryState +} + +func tradingEntryDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "171", func() tradingEntryState { return tradingEntryState{} }) + checks := *ui.Local(c.Root(), "171.checks", func() chan [2]any { return make(chan [2]any, 8) }) + placed := *ui.Local(c.Root(), "171.placed", func() chan string { return make(chan string, 1) }) + for drained := false; !drained; { + select { + case r := <-checks: + v, msg := r[0].(uint64), r[1].(string) + log(fmt.Sprintf("buying power check v%d: %q, kept %v", v, msg, d.entry.Resolve(v, msg))) + case e := <-placed: + d.entry.EndSubmit(e) + log(fmt.Sprintf("order placed, error %q", e)) + default: + drained = true + } + } + tradingTrend(c, &d.redUp, log) + formToggles(c, []string{"Disabled", "Broker rejects"}, &d.disabled, &d.reject) + r := mujica.OrderEntry(c, &d.entry, mujica.OrderEntryOptions{Symbol: "MUJC", Last: 100.2, MaxQuantity: 5000, Disabled: d.disabled, + Check: func(o mujica.OrderDraft, v uint64) { + log(fmt.Sprintf("check started v%d", v)) + go func() { + time.Sleep(600 * time.Millisecond) + msg := "" + if o.Quantity*100 > 250000 { + msg = "Not enough buying power." + } + checks <- [2]any{v, msg} + c.Invalidate() + }() + }}) + if o, ok := r.Submitted(); ok { + log(fmt.Sprintf("submitted %+v", o)) + fail := "" + if d.reject { + fail = "The broker rejected the order. Your entry is kept." + } + go func() { + time.Sleep(800 * time.Millisecond) + placed <- fail + c.Invalidate() + }() + } +} + +type tradingQuickState struct { + redUp, confirm, disabled bool + qty float64 +} + +func tradingQuickDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "172", func() tradingQuickState { return tradingQuickState{confirm: true, qty: 10} }) + tradingTrend(c, &d.redUp, log) + formToggles(c, []string{"Confirm first", "Disabled"}, &d.confirm, &d.disabled) + ui.Box(c).Width(400).Children(func() { + if side, q, ok := mujica.QuickTradeButtons(c, &d.qty, mujica.QuickTradeButtonsOptions{Symbol: "MUJC", Confirm: d.confirm, Disabled: d.disabled}).Traded(); ok { + log(fmt.Sprintf("trade %v %v", side, q)) + } + }) +} + +type tradingPositionsState struct { + redUp, disabled bool + rows []mujica.PositionRow + table mujica.DataTableState[string] +} + +func tradingPositionsDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "173", func() tradingPositionsState { + return tradingPositionsState{rows: []mujica.PositionRow{ + {ID: "p1", Symbol: "MUJC", Quantity: 100, AvgCost: 400, Price: 412.08}, + {ID: "p2", Symbol: "AVE", Quantity: 50, AvgCost: 90, Price: 88.2}, + {ID: "p3", Symbol: "OBLV", Quantity: 8, AvgCost: 1180, Price: 1204.5}, + }} + }) + tradingTrend(c, &d.redUp, log) + formToggles(c, []string{"Disabled"}, &d.disabled) + ui.Box(c).Width(1000).Height(260).Children(func() { + r := mujica.PositionTable(c, &d.table, d.rows, mujica.PositionTableOptions{Disabled: d.disabled}) + if id, ok := r.Acted(); ok { + for i, p := range d.rows { + if p.ID == id { + d.rows = append(d.rows[:i:i], d.rows[i+1:]...) + break + } + } + log("close " + id) + } + if r.Table.Changed() { + id, _ := d.table.Selected() + log("select " + id) + } + }) +} + +type tradingOrdersState struct { + disabled bool + rows []mujica.OrderRow + table mujica.OrderTableState + version int +} + +func tradingOrdersDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "174", func() tradingOrdersState { + return tradingOrdersState{rows: []mujica.OrderRow{ + {ID: "o1", Symbol: "MUJC", Side: mujica.SideBuy, Type: mujica.OrderLimit, Price: 99.5, Quantity: 100, Filled: 40, Status: mujica.OrderPartial}, + {ID: "o2", Symbol: "AVE", Side: mujica.SideSell, Type: mujica.OrderMarket, Quantity: 10, Filled: 10, Status: mujica.OrderFilled}, + {ID: "o3", Symbol: "OBLV", Side: mujica.SideBuy, Type: mujica.OrderStop, Price: 12, Quantity: 5, Status: mujica.OrderCanceled}, + {ID: "o4", Symbol: "DOLO", Side: mujica.SideSell, Type: mujica.OrderLimit, Price: 7.25, Quantity: 30, Status: mujica.OrderOpen}, + }} + }) + formToggles(c, []string{"Disabled"}, &d.disabled) + ui.Box(c).Width(1000).Height(300).Children(func() { + if id, ok := mujica.OrderTable(c, &d.table, d.rows, mujica.OrderTableOptions{Disabled: d.disabled, Version: d.version}).Acted(); ok { + for i := range d.rows { + if d.rows[i].ID == id { + d.rows[i].Status = mujica.OrderCanceled + } + } + d.version++ + log("cancel " + id) + } + }) +} + +type tradingHistoryState struct { + disabled bool + rows []mujica.FillRow + table mujica.TradeHistoryTableState +} + +func tradingHistoryDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "175", func() tradingHistoryState { + var rows []mujica.FillRow + for i := range 30 { + side := mujica.SideBuy + if i%3 == 0 { + side = mujica.SideSell + } + rows = append(rows, mujica.FillRow{ID: fmt.Sprint(i), Time: time.Date(2026, 9, 10+i/2, 9+i%6, 0, 0, 0, time.Local), + Symbol: []string{"MUJC", "AVE", "OBLV"}[i%3], Side: side, Price: 100 + float64(i), Quantity: float64(i%5+1) * 10, Fee: 0.5}) + } + return tradingHistoryState{rows: rows} + }) + formToggles(c, []string{"Disabled"}, &d.disabled) + ui.Box(c).Width(1000).Height(360).Children(func() { + if fills, ok := mujica.TradeHistoryTable(c, &d.table, d.rows, mujica.TradeHistoryTableOptions{Disabled: d.disabled}).Exported(); ok { + log(fmt.Sprintf("export %d fills", len(fills))) + } + }) +} + +type tradingPnLState struct { + redUp, hidden bool +} + +func tradingPnLDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "176", func() tradingPnLState { return tradingPnLState{} }) + tradingTrend(c, &d.redUp, log) + if mujica.PnLDisplay(c, mujica.PnL{Realized: 1200.5, Unrealized: -340.2, Today: 88}, &d.hidden, mujica.PnLDisplayOptions{Currency: "$"}).Changed() { + log(fmt.Sprintf("hidden %v", d.hidden)) + } +} + +type tradingLeverageState struct { + disabled bool + value float64 +} + +func tradingLeverageDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "177", func() tradingLeverageState { return tradingLeverageState{value: 5} }) + formToggles(c, []string{"Disabled"}, &d.disabled) + ui.Box(c).Width(380).Children(func() { + if mujica.LeverageSlider(c, &d.value, mujica.LeverageSliderOptions{Warning: 10, Danger: 50, Disabled: d.disabled}).Changed() { + log(fmt.Sprintf("leverage applied %v×", d.value)) + } + }) +} + +type tradingMarginState struct{ ratio float64 } + +func tradingMarginDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "178", func() tradingMarginState { return tradingMarginState{ratio: 0.55} }) + if mujica.Slider(c, &d.ratio, mujica.SliderOptions{Min: 0, Max: 1.4, Step: 0.01, Label: "Margin ratio", ShowValue: true}).Changed() { + log(fmt.Sprintf("ratio %.2f", d.ratio)) + } + ui.Box(c).Width(360).Children(func() { mujica.MarginIndicator(c, d.ratio, mujica.MarginIndicatorOptions{}) }) + formStates(c, func() { + for _, r := range []float64{0.3, 0.85, 1.1} { + ui.Box(c).Width(260).Children(func() { mujica.MarginIndicator(c, r, mujica.MarginIndicatorOptions{}) }) + } + }) +} + +type tradingRiskState struct{ level float64 } + +func tradingRiskDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "179", func() tradingRiskState { return tradingRiskState{level: 3} }) + if mujica.Slider(c, &d.level, mujica.SliderOptions{Min: 1, Max: 5, Step: 1, Label: "Level", ShowValue: true}).Changed() { + log(fmt.Sprintf("level %.0f", d.level)) + } + ui.Box(c).Width(360).Children(func() { mujica.RiskMeter(c, int(d.level), mujica.RiskMeterOptions{}) }) +} + +type tradingConfirmState struct { + open, acknowledge bool +} + +func tradingConfirmDemo(c *ui.Context, log func(string)) { + d := ui.Local(c.Root(), "180", func() tradingConfirmState { return tradingConfirmState{acknowledge: true} }) + formToggles(c, []string{"Require acknowledgement"}, &d.acknowledge) + if tradingAction(c, "Review order") { + d.open = true + log("open") + } + ack := "" + if d.acknowledge { + ack = "I understand leveraged products can lose more than the deposit" + } + r := mujica.OrderConfirmDialog(c, &d.open, mujica.OrderConfirmDialogOptions{ + Lines: []mujica.OrderSummaryLine{{Label: "Symbol", Value: "MUJC"}, {Label: "Side", Value: "Buy"}, {Label: "Type", Value: "Limit 100.20"}, + {Label: "Quantity", Value: "100"}, {Label: "Estimated amount", Value: "10,020.00"}}, + Risk: "5× leverage: a 20% move against you wipes out the margin.", Acknowledge: ack, + }) + if r.Confirmed { + log("confirmed") + } + if r.Canceled { + log("canceled") + } +} diff --git a/level2_quotes.go b/level2_quotes.go new file mode 100644 index 0000000..0df1966 --- /dev/null +++ b/level2_quotes.go @@ -0,0 +1,123 @@ +package mujica + +import ( + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// L2Level is a level's price, size and order count. +type L2Level struct { + Price, Size float64 + Orders int +} + +// Level2Data holds the bid and ask levels, best first. +type Level2Data struct { + Bids, Asks []L2Level +} + +// Level2QuotesOptions configure a Level2Quotes. +type Level2QuotesOptions struct { + // Decimals of prices and sizes; zero means 2 and 0. + Decimals, SizeDecimals int + // Levels shown each side; zero means 5. + Levels int +} + +// level2Mark is a level's last values and size move. +type level2Mark struct { + price, size float64 + dir int + at time.Time + seen bool +} + +// Level2Quotes lists bid and ask levels; changes flash and mark. +func Level2Quotes(c *ui.Context, data Level2Data, opts Level2QuotesOptions) *ui.Element { + dec := priceDecimals("Level2Quotes", opts.Decimals) + if opts.SizeDecimals < 0 || opts.Levels < 0 { + panic("mujica: Level2Quotes SizeDecimals and Levels cannot be negative") + } + n := opts.Levels + if n == 0 { + n = 5 + } + u := Density(c).Unit() + e := ui.Row(c).Gap(u * 3).AlignItems(ui.Start).Role(ui.RoleTable).Label(msg(c, "level2_quotes.label")) + marks := ui.Local(e, "marks", func() map[string]*level2Mark { return map[string]*level2Mark{} }) + e.Children(func() { + for _, side := range []OrderSide{SideBuy, SideSell} { + levels := data.Bids + if side == SideSell { + levels = data.Asks + } + ui.Column(c).Grow(1).Basis(0).MinWidth(0).Children(func() { + for i := range n { + var l *L2Level + if i < len(levels) { + l = &levels[i] + } + level2Row(c, *marks, side, i, l, dec, opts.SizeDecimals) + } + }) + } + }) + return e +} + +// level2Row is one level with its move mark. +func level2Row(c *ui.Context, marks map[string]*level2Mark, side OrderSide, i int, l *L2Level, dec, sizeDec int) { + k := Tokens(c) + d := Density(c) + name := fmt.Sprintf(msg(c, fmt.Sprintf("level2_quotes.side%d", side)), i+1) + key := fmt.Sprint(side, i) + m := marks[key] + if m == nil { + m = &level2Mark{} + marks[key] = m + } + row := ui.Row(c).Gap(d.Unit()*2).AlignItems(ui.Center).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*2). + Radius(theme.ControlRadius).BorderWidth(0, 0, theme.BorderWidth, 0).BorderColor(k.Border) + if l == nil { + row.Children(func() { + ui.Text(c, name).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)).Width(28) + ui.Text(c, "—").TextColor(k.TextMuted) + }) + return + } + if m.seen && (l.Price != m.price || l.Size != m.size) { + // A new price is a new level, not a move. + m.dir, m.at = 0, c.Now() + if l.Price == m.price { + m.dir = trendSign(l.Size - m.size) + } + slog.Debug("mujica: level2_quotes level changed", "level", name) + } + m.price, m.size, m.seen = l.Price, l.Size, true + if dur := Motion(c, priceTextFlash); dur > 0 && !m.at.IsZero() { + if t := c.Now().Sub(m.at); t < dur { + row.Background(k.Selection.Alpha(1 - float32(float64(t)/float64(dur)))) + c.AnimationFrame() + } + } + col := trendColor(c, side.sign()) + sizeText := statisticFormat(l.Size, sizeDec) + orders := fmt.Sprintf(msg(c, "level2_quotes.orders"), l.Orders) + row.Role(ui.RoleRow).Label(name + " " + statisticFormat(l.Price, dec) + " " + sizeText + " " + orders) + row.Children(func() { + ui.Text(c, name).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)).Width(28) + ui.Text(c, statisticFormat(l.Price, dec)).TextColor(col).FontFeatures("tnum").FontWeight(600).Grow(1).Basis(0).SingleLine() + ui.Row(c).Gap(2).AlignItems(ui.Center).Justify(ui.End).Grow(1).Basis(0).Children(func() { + if m.dir != 0 { + ui.Icon(c, trendIcon(m.dir)).Size(12, 12).TextColor(trendColor(c, m.dir)) + } + ui.Text(c, sizeText).FontFeatures("tnum").SingleLine() + }) + ui.Text(c, fmt.Sprint(l.Orders)).TextColor(k.TextMuted).FontFeatures("tnum").TextAlign(ui.End).Width(36).SingleLine() + }) +} diff --git a/level2_quotes_test.go b/level2_quotes_test.go new file mode 100644 index 0000000..492b5fe --- /dev/null +++ b/level2_quotes_test.go @@ -0,0 +1,63 @@ +package mujica + +import ( + "bytes" + "testing" + + "github.com/egoist/mygo/ui" +) + +func level2Sample() Level2Data { + return Level2Data{ + Bids: []L2Level{{100.00, 500, 12}, {99.99, 300, 4}}, + Asks: []L2Level{{100.01, 200, 3}, {100.02, 900, 21}, {100.03, 50, 1}}, + } +} + +func TestLevel2QuotesLevels(t *testing.T) { + tt := tradingTester(GreenUp, 600, 300, func(c *ui.Context) { + ui.Box(c).Width(560).Children(func() { Level2Quotes(c, level2Sample(), Level2QuotesOptions{Levels: 3}) }) + }) + for _, name := range []string{"B1 100.00 500 12 orders", "S2 100.02 900 21 orders"} { + if _, ok := tt.Find(name); !ok { + t.Fatalf("no row %q in %q", name, tt.Texts()) + } + } + if !tt.HasText("B3") || !tt.HasText("—") { + t.Fatal("missing third bid not shown as empty") + } +} + +// A changed level marks its size move and flashes. +func TestLevel2QuotesHighlightsChangedLevel(t *testing.T) { + data := level2Sample() + var marks *map[string]*level2Mark + tt := tradingTester(GreenUp, 600, 300, func(c *ui.Context) { + e := Level2Quotes(c, data, Level2QuotesOptions{Levels: 2}) + marks = ui.Local(e, "marks", func() map[string]*level2Mark { return nil }) + }) + before := bytes.Clone(tt.Image().Pix) + data.Bids = []L2Level{{100.00, 650, 13}, {99.99, 300, 4}} + tt.Frame() + m := (*marks)["1 0"] + if m.dir != 1 || m.at.IsZero() { + t.Fatalf("bid 1 mark %+v", m) + } + if (*marks)["1 1"].dir != 0 || !(*marks)["1 1"].at.IsZero() { + t.Fatal("unchanged level marked") + } + if bytes.Equal(before, tt.Image().Pix) { + t.Fatal("nothing drawn for the change") + } + data.Bids = []L2Level{{100.01, 650, 13}, {99.99, 300, 4}} + tt.Frame() + if (*marks)["1 0"].dir != 0 { + t.Fatal("new price read as a size move") + } +} + +func TestLevel2QuotesSnapshot(t *testing.T) { + snapshot(t, "level2_quotes", 600, 230, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { Level2Quotes(c, level2Sample(), Level2QuotesOptions{}) }) + }) +} diff --git a/leverage_slider.go b/leverage_slider.go new file mode 100644 index 0000000..dd2e101 --- /dev/null +++ b/leverage_slider.go @@ -0,0 +1,159 @@ +package mujica + +import ( + "fmt" + "log/slog" + "math" + "slices" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// LeverageSliderOptions configure a LeverageSlider. +type LeverageSliderOptions struct { + // Levels are the rising leverages; nil means 1× to 100×. + Levels []float64 + // Warning and Danger start the risk zones; zero omits one. + Warning, Danger float64 + // Label names the slider; empty uses the built-in "Leverage". + Label string + Disabled bool +} + +type leverageSliderState struct { + draft float64 + seen float64 +} + +// LeverageSlider drafts a leverage; Apply sets *value. +func LeverageSlider(c *ui.Context, value *float64, opts LeverageSliderOptions) ChoiceResult { + levels := opts.Levels + if levels == nil { + levels = []float64{1, 2, 3, 5, 10, 20, 50, 100} + } + if len(levels) < 2 || !slices.IsSorted(levels) || slices.Index(levels, *value) < 0 { + panic(fmt.Sprintf("mujica: LeverageSlider value %v must be one of at least two rising Levels", *value)) + } + if opts.Warning < 0 || opts.Danger < 0 || opts.Danger != 0 && opts.Danger <= opts.Warning { + panic("mujica: LeverageSlider Danger must be above Warning") + } + k := Tokens(c) + d := Density(c) + label := opts.Label + if label == "" { + label = msg(c, "leverage_slider.label") + } + var r ChoiceResult + r.Element = ui.Column(c).Gap(d.Unit() * 2).MinWidth(260).Disabled(opts.Disabled) + st := ui.Local(r.Element, "lev", func() leverageSliderState { return leverageSliderState{draft: *value, seen: *value} }) + if *value != st.seen { + st.draft, st.seen = *value, *value + } + disabled := r.Element.IsDisabled() + if disabled { + st.draft = *value + } + zone := func(v float64) (string, ui.Color, string) { + switch { + case opts.Danger > 0 && v >= opts.Danger: + return msg(c, "leverage_slider.danger"), k.Danger, "circle-alert" + case opts.Warning > 0 && v >= opts.Warning: + return msg(c, "leverage_slider.warning"), k.Warning, "triangle-alert" + } + return "", k.TextMuted, "" + } + r.Element.Children(func() { + note, col, icon := zone(st.draft) + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, label).TextColor(k.TextMuted).Grow(1) + ui.Text(c, leverageText(st.draft)).FontSize(FontSize(c, theme.H3Size)).FontWeight(600).FontFeatures("tnum") + }) + leverageTrack(c, st, levels, disabled, zone) + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).MinHeight(d.ControlHeight()).Children(func() { + ui.Row(c).Gap(d.Unit()).AlignItems(ui.Center).TextColor(col).Grow(1).Children(func() { + if icon != "" { + ui.Icon(c, icons.Must(icon)).Size(14, 14) + ui.Text(c, note).FontSize(FontSize(c, theme.CaptionSize)).FontWeight(600).Role(ui.RoleStatus) + } + }) + if Button(c, msg(c, "leverage_slider.apply"), ButtonOptions{Disabled: disabled || st.draft == *value}).Clicked() && !disabled { + *value, st.seen, r.changed = st.draft, st.draft, true + slog.Debug("mujica: leverage_slider applied", "leverage", *value) + } + }) + }) + return r +} + +func leverageText(v float64) string { return statisticFormat(v, 0) + "×" } + +// leverageTrack is the slider with zones, ticks and thumb. +func leverageTrack(c *ui.Context, st *leverageSliderState, levels []float64, disabled bool, zone func(float64) (string, ui.Color, string)) { + k := Tokens(c) + n := len(levels) + at := slices.Index(levels, st.draft) + set := func(i int) { + i = max(0, min(n-1, i)) + if levels[i] != st.draft && !disabled { + st.draft = levels[i] + slog.Debug("mujica: leverage_slider draft", "leverage", st.draft) + } + } + const pad = 10 + t := ui.Box(c).Height(theme.MinHitSize+16).FillWidth().Padding(0, pad).Focusable().Role(ui.RoleSlider). + Label(msg(c, "leverage_slider.label")).Description(leverageText(st.draft)) + t.FocusRing(false) + if !disabled { + switch { + case t.Shortcut(0, ui.KeyRight), t.Shortcut(0, ui.KeyUp): + set(at + 1) + case t.Shortcut(0, ui.KeyLeft), t.Shortcut(0, ui.KeyDown): + set(at - 1) + case t.Shortcut(0, ui.KeyHome): + set(0) + case t.Shortcut(0, ui.KeyEnd): + set(n - 1) + } + if _, _, ok := t.Dragged(); ok { + x, _, _ := t.PointerPosition() + if w := t.Bounds().W - 2*pad; w > 0 { + set(int(math.Round(float64((x - pad) / w * float32(n-1))))) + } + } + } + at = slices.Index(levels, st.draft) + t.Draw(func(p *ui.Painter, r ui.Rect) { + x0, w := r.X+pad, r.W-2*pad + y := r.Y + 14 + xs := func(i int) float32 { return internal.Snap(p, x0+w*float32(i)/float32(n-1)) } + // Zone bands run under the track. + for i := 0; i < n-1; i++ { + _, col, icon := zone(levels[i+1]) + if icon != "" { + p.Fill(ui.Rect{X: xs(i), Y: y + 4, W: xs(i+1) - xs(i), H: 3}, col, 0) + } + } + p.Line(x0, y, x0+w, y, 2, k.ControlBorder) + p.Line(x0, y, xs(at), y, 2, k.AccentText) + size := FontSize(c, theme.CaptionSize) + widest, _ := p.MeasureText(0, ui.Span{Text: leverageText(levels[n-1]), Size: size}) + // Crowded labels skip levels, counted back from the last. + every := max(1, int(math.Ceil(float64((widest+8)/(w/float32(n-1)))))) + for i, v := range levels { + p.Line(xs(i), y+4, xs(i), y+8, 1, k.TextMuted) + if (n-1-i)%every == 0 { + tw, _ := p.MeasureText(0, ui.Span{Text: leverageText(v), Size: size}) + p.Text(xs(i)-tw/2, y+11, leverageText(v), size, k.TextMuted) + } + } + p.FillPath(internal.Diamond(xs(at), y, 16), k.Surface) + p.FillPath(internal.Diamond(xs(at), y, 13), k.AccentText) + if t.FocusVisible() { + internal.FocusRing(p, ui.Rect{X: xs(at) - 8, Y: y - 8, W: 16, H: 16}, theme.ControlRadius, k.Focus) + } + }) +} diff --git a/leverage_slider_test.go b/leverage_slider_test.go new file mode 100644 index 0000000..fbbf4ce --- /dev/null +++ b/leverage_slider_test.go @@ -0,0 +1,94 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +type leverageProbe struct { + value float64 + opts LeverageSliderOptions + applied int +} + +func (p *leverageProbe) tester(density theme.Density) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{Density: density}) + ui.Column(c).Padding(10).Children(func() { + if LeverageSlider(c, &p.value, p.opts).Changed() { + p.applied++ + } + }) + }, 420, 200) +} + +func TestLeverageSliderAppliesOnlyOnConfirm(t *testing.T) { + p := &leverageProbe{value: 5, opts: LeverageSliderOptions{Warning: 10, Danger: 50}} + tt := p.tester(theme.Default) + tt.Key(0, ui.KeyTab) + if !tt.Focused("Leverage") { + t.Fatal("slider not focusable") + } + tt.Key(0, ui.KeyRight) + if p.value != 5 || !tt.HasText("10×") || !tt.HasText("High risk") { + t.Fatalf("draft: value %v texts %q", p.value, tt.Texts()) + } + tt.Key(0, ui.KeyEnd) + if !tt.HasText("Very high risk") { + t.Fatalf("danger zone: %q", tt.Texts()) + } + if err := tt.Click("Apply"); err != nil { + t.Fatal(err) + } + if p.value != 100 || p.applied != 1 { + t.Fatalf("apply: %v %d", p.value, p.applied) + } + tt.Key(ui.Shift, ui.KeyTab) + tt.Key(0, ui.KeyHome) + if p.value != 100 || !tt.HasText("1×") { + t.Fatalf("home moved value: %v", p.value) + } +} + +func TestLeverageSliderPointerAndHitArea(t *testing.T) { + p := &leverageProbe{value: 1, opts: LeverageSliderOptions{Levels: []float64{1, 2, 3}}} + tt := p.tester(theme.Compact) + // The track is at least 28 DIPs tall, even Compact. + tt.ClickAt(10+400-10, 70) + if !tt.HasText("3×") { + t.Fatalf("pointer: %q", tt.Texts()) + } + tt.ClickAt(30, 70) + if !tt.HasText("1×") || p.applied != 0 { + t.Fatalf("pointer back: %q", tt.Texts()) + } +} + +func TestLeverageSliderDisabledAndBadValue(t *testing.T) { + p := &leverageProbe{value: 2, opts: LeverageSliderOptions{Disabled: true}} + tt := p.tester(theme.Default) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + _ = tt.Click("Apply") + if p.value != 2 || tt.HasText("3×") || !tt.HasText("2×") { + t.Fatal("disabled slider moved") + } + defer func() { + if recover() == nil { + t.Fatal("value outside Levels accepted") + } + }() + (&leverageProbe{value: 4}).tester(theme.Default) +} + +func TestLeverageSliderSnapshot(t *testing.T) { + v := 20.0 + snapshot(t, "leverage_slider", 360, 160, func(c *ui.Context) { + ui.Column(c).Padding(20).Children(func() { + LeverageSlider(c, &v, LeverageSliderOptions{Warning: 10, Danger: 50}) + }) + }) +} diff --git a/margin_indicator.go b/margin_indicator.go new file mode 100644 index 0000000..4c59696 --- /dev/null +++ b/margin_indicator.go @@ -0,0 +1,71 @@ +package mujica + +import ( + "fmt" + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// MarginIndicatorOptions configure a MarginIndicator. Zero lines mean 80% and 100%. +type MarginIndicatorOptions struct { + // Warning and Liquidation are margin ratios, Warning below Liquidation. + Warning, Liquidation float64 + // Label names the indicator; empty uses the built-in "Margin ratio". + Label string +} + +// MarginIndicator shows maintenance over equity against its two lines. +func MarginIndicator(c *ui.Context, ratio float64, opts MarginIndicatorOptions) *ui.Element { + warn, liq := opts.Warning, opts.Liquidation + if warn == 0 && liq == 0 { + warn, liq = 0.8, 1 + } + if !(warn > 0 && warn < liq) || ratio < 0 || math.IsNaN(ratio) { + panic(fmt.Sprintf("mujica: MarginIndicator ratio %v, lines %v and %v: need 0 < Warning < Liquidation", ratio, warn, liq)) + } + k := Tokens(c) + u := Density(c).Unit() + label := opts.Label + if label == "" { + label = msg(c, "margin_indicator.label") + } + status, col, icon := msg(c, "margin_indicator.safe"), k.Success, "circle-check" + switch { + case ratio >= liq: + status, col, icon = msg(c, "margin_indicator.liquidation"), k.Danger, "circle-x" + case ratio >= warn: + status, col, icon = msg(c, "margin_indicator.warning"), k.Warning, "triangle-alert" + } + pct := func(v float64) string { return statisticFormat(v*100, 1) + "%" } + top := math.Max(liq*1.25, ratio) + e := ui.Column(c).Gap(u * 2).MinWidth(220).Role(ui.RoleMeter).Label(label). + Description(fmt.Sprintf(msg(c, "margin_indicator.spoken"), pct(ratio), status, pct(warn), pct(liq))) + e.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, pct(ratio)).FontSize(FontSize(c, theme.H3Size)).FontFeatures("tnum").FontWeight(600).SingleLine() + ui.Row(c).Gap(u / 2).AlignItems(ui.Center).TextColor(col).Children(func() { + ui.Icon(c, icons.Must(icon)).Size(14, 14) + ui.Text(c, status).FontSize(FontSize(c, theme.CaptionSize)).FontWeight(600).SingleLine() + }) + }) + ui.Box(c).Height(14).FillWidth().Draw(func(p *ui.Painter, r ui.Rect) { + bar := ui.Rect{X: r.X, Y: r.Y + 3, W: r.W, H: 8} + p.Fill(bar, k.SurfaceHover, theme.ControlRadius) + p.Fill(ui.Rect{X: bar.X, Y: bar.Y, W: bar.W * float32(ratio/top), H: bar.H}, col, theme.ControlRadius) + // The liquidation line is drawn heavier than the warning line. + for i, line := range []float64{warn, liq} { + x := bar.X + bar.W*float32(line/top) + p.Line(x, r.Y, x, r.Y+r.H, 1.5+float32(i)*1.5, k.Text) + } + }) + ui.Row(c).Gap(u * 4).Wrap().Children(func() { + ui.Text(c, msg(c, "margin_indicator.warning_line")+" "+pct(warn)).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + ui.Text(c, msg(c, "margin_indicator.liquidation_line")+" "+pct(liq)).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + }) + }) + return e +} diff --git a/margin_indicator_test.go b/margin_indicator_test.go new file mode 100644 index 0000000..0eefd39 --- /dev/null +++ b/margin_indicator_test.go @@ -0,0 +1,39 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestMarginIndicatorStates(t *testing.T) { + ratio := 0.42 + tt := tradingTester(GreenUp, 400, 160, func(c *ui.Context) { + ui.Box(c).Width(300).Children(func() { MarginIndicator(c, ratio, MarginIndicatorOptions{}) }) + }) + for _, tc := range []struct { + ratio float64 + want string + }{{0.42, "Safe"}, {0.8, "Margin call"}, {1.2, "Liquidation"}} { + ratio = tc.ratio + tt.Frame() + if !tt.HasText(tc.want) { + t.Fatalf("%v: %q", tc.ratio, tt.Texts()) + } + } + if !tt.HasText("Warning line 80.0%") || !tt.HasText("Liquidation line 100.0%") || !tt.HasText("120.0%") { + t.Fatalf("lines: %q", tt.Texts()) + } + defer func() { + if recover() == nil { + t.Fatal("warning above liquidation accepted") + } + }() + tradingTester(GreenUp, 100, 100, func(c *ui.Context) { MarginIndicator(c, 1, MarginIndicatorOptions{Warning: 2, Liquidation: 1}) }) +} + +func TestMarginIndicatorSnapshot(t *testing.T) { + snapshot(t, "margin_indicator", 340, 120, func(c *ui.Context) { + ui.Column(c).Padding(20).Children(func() { MarginIndicator(c, 0.86, MarginIndicatorOptions{}) }) + }) +} diff --git a/messages_trading.go b/messages_trading.go new file mode 100644 index 0000000..8f72fe7 --- /dev/null +++ b/messages_trading.go @@ -0,0 +1,161 @@ +package mujica + +func init() { + addMessages(map[string][2]string{ + "price_text.up": {"up", "上涨"}, + "price_text.down": {"down", "下跌"}, + "price_text.flat": {"unchanged", "平"}, + + "ticker_tape.label": {"Market ticker", "行情滚动条"}, + "ticker_tape.pause_hint": {"Pauses under the pointer or keyboard focus", "指针悬停或键盘聚焦时暂停"}, + "ticker_tape.previous": {"Previous page", "上一页"}, + "ticker_tape.next": {"Next page", "下一页"}, + + "spread_indicator.title": {"Spread", "价差"}, + "spread_indicator.value": {"%s (%s%%)", "%s(%s%%)"}, + "spread_indicator.wide": {"Wide spread", "价差过大"}, + "spread_indicator.crossed": {"Crossed market", "买卖价倒挂"}, + + "bid_ask_bar.label": {"Bid and ask volume", "买卖力量"}, + "bid_ask_bar.buy": {"Buy %s%% · %s", "买 %s%% · %s"}, + "bid_ask_bar.sell": {"%s · Sell %s%%", "%s · 卖 %s%%"}, + + "risk_meter.label": {"Risk level", "风险等级"}, + "risk_meter.value": {"Level %d of %d, %s.", "第 %d 级,共 %d 级,%s。"}, + "risk_meter.level1": {"Low", "低"}, + "risk_meter.level2": {"Moderately low", "中低"}, + "risk_meter.level3": {"Medium", "中"}, + "risk_meter.level4": {"Moderately high", "中高"}, + "risk_meter.level5": {"High", "高"}, + + "margin_indicator.label": {"Margin ratio", "保证金率"}, + "margin_indicator.safe": {"Safe", "安全"}, + "margin_indicator.warning": {"Margin call", "追加保证金"}, + "margin_indicator.liquidation": {"Liquidation", "强制平仓"}, + "margin_indicator.warning_line": {"Warning line", "警戒线"}, + "margin_indicator.liquidation_line": {"Liquidation line", "强平线"}, + "margin_indicator.spoken": {"%s, %s. Warning at %s, liquidation at %s.", "%s,%s。警戒线 %s,强平线 %s。"}, + + "pnl_display.label": {"Profit and loss", "盈亏"}, + "pnl_display.realized": {"Realized", "已实现"}, + "pnl_display.unrealized": {"Unrealized", "未实现"}, + "pnl_display.today": {"Today", "当日"}, + "pnl_display.masked": {"hidden", "已隐藏"}, + "pnl_display.hide": {"Hide amounts", "隐藏金额"}, + "pnl_display.show": {"Show amounts", "显示金额"}, + + "order_book.label": {"Order book", "盘口"}, + "order_book.group": {"Group", "合并档位"}, + "order_book.price": {"Price", "价格"}, + "order_book.size": {"Size", "数量"}, + "order_book.total": {"Total", "累计"}, + "order_book.side1": {"Bid", "买"}, + "order_book.side2": {"Ask", "卖"}, + "order_book.level": {"%s %s, size %s", "%s %s,数量 %s"}, + + "level2_quotes.label": {"Level 2 quotes", "多档行情"}, + "level2_quotes.side1": {"B%d", "买%d"}, + "level2_quotes.side2": {"S%d", "卖%d"}, + "level2_quotes.orders": {"%d orders", "%d 笔委托"}, + + "time_and_sales.title": {"Time and sales", "逐笔成交"}, + "time_and_sales.pause": {"Pause", "暂停跟随"}, + "time_and_sales.resume": {"Resume", "继续跟随"}, + "time_and_sales.resume_count": {"Resume (%d new)", "继续跟随(%d 笔新成交)"}, + "time_and_sales.time": {"Time", "时间"}, + "time_and_sales.price": {"Price", "价格"}, + "time_and_sales.size": {"Size", "数量"}, + "time_and_sales.large": {"large trade", "大单"}, + "time_and_sales.empty": {"No trades yet", "暂无成交"}, + + "depth_ladder.label": {"Price ladder", "价格阶梯"}, + "depth_ladder.bid": {"Bid", "买量"}, + "depth_ladder.price": {"Price", "价格"}, + "depth_ladder.ask": {"Ask", "卖量"}, + "depth_ladder.last": {"Last price", "最新价"}, + "depth_ladder.order1": {"Buy at %s", "以 %s 买入"}, + "depth_ladder.order2": {"Sell at %s", "以 %s 卖出"}, + "depth_ladder.recenter": {"Center on last price", "回到最新价"}, + + "order_entry.label": {"Order entry", "下单"}, + "order_entry.side": {"Side", "方向"}, + "order_entry.buy": {"Buy", "买入"}, + "order_entry.sell": {"Sell", "卖出"}, + "order_entry.side1": {"Buy", "买入"}, + "order_entry.side2": {"Sell", "卖出"}, + "order_entry.type": {"Order type", "订单类型"}, + "order_entry.type0": {"Limit", "限价"}, + "order_entry.type1": {"Market", "市价"}, + "order_entry.type2": {"Stop", "止损"}, + "order_entry.type3": {"Stop limit", "条件限价"}, + "order_entry.quantity": {"Quantity", "数量"}, + "order_entry.price": {"Limit price", "限价"}, + "order_entry.trigger": {"Trigger price", "触发价"}, + "order_entry.tif": {"Time in force", "有效期"}, + "order_entry.tif0": {"Day", "当日有效"}, + "order_entry.tif1": {"Good till canceled", "撤销前有效"}, + "order_entry.tif2": {"Immediate or cancel", "立即成交剩余撤销"}, + "order_entry.tif3": {"Fill or kill", "全部成交否则撤销"}, + "order_entry.estimate": {"Estimated amount", "预估金额"}, + "order_entry.submit1": {"Buy %s", "买入 %s"}, + "order_entry.submit2": {"Sell %s", "卖出 %s"}, + "order_entry.quantity_positive": {"Enter a quantity above zero.", "请输入大于零的数量。"}, + "order_entry.quantity_max": {"At most %s.", "最多 %s。"}, + "order_entry.price_positive": {"Enter a price above zero.", "请输入大于零的价格。"}, + "order_entry.trigger_positive": {"Enter a trigger price above zero.", "请输入大于零的触发价。"}, + "order_entry.trigger_above": {"A buy stop triggers above the last price.", "买入止损的触发价须高于最新价。"}, + "order_entry.trigger_below": {"A sell stop triggers below the last price.", "卖出止损的触发价须低于最新价。"}, + + "quick_trade_buttons.label": {"Quick trade", "快速交易"}, + "quick_trade_buttons.quantity": {"Quantity", "数量"}, + "quick_trade_buttons.side1": {"Buy %s", "买入 %s"}, + "quick_trade_buttons.side2": {"Sell %s", "卖出 %s"}, + "quick_trade_buttons.confirm1": {"Buy %s %s?", "买入 %s %s?"}, + "quick_trade_buttons.confirm2": {"Sell %s %s?", "卖出 %s %s?"}, + "quick_trade_buttons.market": {"The order fills at the market price.", "订单将以市价成交。"}, + + "position_table.symbol": {"Symbol", "代码"}, + "position_table.quantity": {"Quantity", "数量"}, + "position_table.cost": {"Avg cost", "成本价"}, + "position_table.price": {"Price", "现价"}, + "position_table.value": {"Market value", "市值"}, + "position_table.pnl": {"Unrealized P/L", "浮动盈亏"}, + "position_table.pnl_percent": {"P/L %", "盈亏比例"}, + "position_table.action": {"Action", "操作"}, + "position_table.close": {"Close", "平仓"}, + "position_table.empty": {"No positions", "暂无持仓"}, + + "order_table.side": {"Side", "方向"}, + "order_table.market": {"Market", "市价"}, + "order_table.filled": {"Filled", "成交"}, + "order_table.status": {"Status", "状态"}, + "order_table.status0": {"Open", "未成交"}, + "order_table.status1": {"Partly filled", "部分成交"}, + "order_table.status2": {"Filled", "已成交"}, + "order_table.status3": {"Canceled", "已撤销"}, + "order_table.status4": {"Rejected", "已拒绝"}, + "order_table.filter": {"Order status", "委托状态"}, + "order_table.filter0": {"All", "全部"}, + "order_table.filter1": {"Working", "进行中"}, + "order_table.filter2": {"Filled", "已成交"}, + "order_table.filter3": {"Closed", "已关闭"}, + "order_table.cancel": {"Cancel", "撤单"}, + "order_table.empty": {"No orders", "暂无委托"}, + + "trade_history_table.time": {"Time", "时间"}, + "trade_history_table.fee": {"Fee", "手续费"}, + "trade_history_table.range": {"Date range", "日期范围"}, + "trade_history_table.all": {"All dates", "全部日期"}, + "trade_history_table.export": {"Export", "导出"}, + "trade_history_table.empty": {"No trades in this range", "该范围内无成交"}, + + "leverage_slider.label": {"Leverage", "杠杆"}, + "leverage_slider.warning": {"High risk", "高风险"}, + "leverage_slider.danger": {"Very high risk", "极高风险"}, + "leverage_slider.apply": {"Apply", "确认"}, + + "order_confirm_dialog.title": {"Confirm order", "确认下单"}, + "order_confirm_dialog.confirm": {"Place order", "确认下单"}, + "order_confirm_dialog.cancel": {"Cancel", "取消"}, + }) +} diff --git a/order_book.go b/order_book.go new file mode 100644 index 0000000..dbf2871 --- /dev/null +++ b/order_book.go @@ -0,0 +1,260 @@ +package mujica + +import ( + "cmp" + "fmt" + "log/slog" + "math" + "slices" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// OrderSide is the buy or sell side. +type OrderSide int + +const ( + SideBuy OrderSide = iota + 1 + SideSell +) + +// sign is +1 for buying and -1 for selling. +func (s OrderSide) sign() int { + switch s { + case SideBuy: + return 1 + case SideSell: + return -1 + } + panic(fmt.Sprintf("mujica: unknown OrderSide %d", s)) +} + +// BookLevel is a price and the size resting there. +type BookLevel struct { + Price, Size float64 +} + +// OrderBookData is the book; bump Version on in-place changes. +type OrderBookData struct { + Bids, Asks []BookLevel + Version int +} + +// OrderBookOptions configure an OrderBook. +type OrderBookOptions struct { + // Decimals of prices and sizes; zero means 2 and 0. + Decimals, SizeDecimals int + // Depth is the levels shown each side; zero means 8. + Depth int + // Groups are the offered aggregation steps; nil shows raw levels. + Groups []float64 + Disabled bool +} + +// OrderBookState is an OrderBook's chosen grouping and its aggregated view. +type OrderBookState struct { + // Group is the aggregation step; zero takes Groups[0]. + Group float64 + cache orderBookCache +} + +type orderBookCache struct { + key bookKey + valid bool + bids, asks []BookLevel +} + +// bookKey tells when a book or its grouping changed. +type bookKey struct { + bid, ask *BookLevel + nb, na int + version int + group float64 +} + +func bookKeyOf(book OrderBookData, group float64) bookKey { + first := func(ls []BookLevel) *BookLevel { + if len(ls) == 0 { + return nil + } + return &ls[0] + } + return bookKey{first(book.Bids), first(book.Asks), len(book.Bids), len(book.Asks), book.Version, group} +} + +// OrderBookResult is a built OrderBook and its clicked level. +type OrderBookResult struct { + Element *ui.Element + price float64 + side OrderSide +} + +// Clicked returns the clicked level's price and side. +func (r OrderBookResult) Clicked() (price float64, side OrderSide, ok bool) { + return r.price, r.side, r.side != 0 +} + +// OrderBook shows clickable asks over bids with depth bars. +func OrderBook(c *ui.Context, s *OrderBookState, book OrderBookData, opts OrderBookOptions) OrderBookResult { + dec := priceDecimals("OrderBook", opts.Decimals) + if opts.SizeDecimals < 0 || opts.Depth < 0 { + panic("mujica: OrderBook SizeDecimals and Depth cannot be negative") + } + depth := opts.Depth + if depth == 0 { + depth = 8 + } + if len(opts.Groups) > 0 && s.Group == 0 { + s.Group = opts.Groups[0] + } + if s.Group != 0 && !slices.Contains(opts.Groups, s.Group) { + panic(fmt.Sprintf("mujica: OrderBook Group %v is not one of Groups", s.Group)) + } + orderBookRefresh(s, book, dec) + k := Tokens(c) + d := Density(c) + var r OrderBookResult + r.Element = ui.Column(c).Gap(d.Unit()).MinWidth(240).Disabled(opts.Disabled).Role(ui.RoleTable).Label(msg(c, "order_book.label")) + r.Element.Children(func() { + if len(opts.Groups) > 0 { + var choices []SelectOption[float64] + for _, g := range opts.Groups { + choices = append(choices, SelectOption[float64]{Value: g, Label: statisticFormat(g, dec)}) + } + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, msg(c, "order_book.group")).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)) + if Select(c, &s.Group, choices, SelectOptions{Label: msg(c, "order_book.group"), Disabled: opts.Disabled}).Changed() { + slog.Debug("mujica: order_book group", "step", s.Group) + } + }) + } + asks := s.cache.asks[:min(depth, len(s.cache.asks))] + bids := s.cache.bids[:min(depth, len(s.cache.bids))] + total := max(orderBookSum(asks), orderBookSum(bids)) + orderBookHeader(c) + list := ui.Column(c).FocusGroup(ui.Vertical) + list.Children(func() { + cum := orderBookSum(asks) + for i := len(asks) - 1; i >= 0; i-- { + orderBookRow(c, &r, asks[i], cum, total, SideSell, dec, opts.SizeDecimals) + cum -= asks[i].Size + } + if len(asks) > 0 && len(bids) > 0 { + ui.Row(c).Padding(d.Unit(), d.Unit()*2).BorderWidth(theme.BorderWidth, 0).BorderColor(k.Border).Children(func() { + SpreadIndicator(c, bids[0].Price, asks[0].Price, SpreadIndicatorOptions{Decimals: dec}) + }) + } + cum = 0 + for _, l := range bids { + cum += l.Size + orderBookRow(c, &r, l, cum, total, SideBuy, dec, opts.SizeDecimals) + } + }) + }) + if r.side != 0 { + slog.Debug("mujica: order_book clicked", "side", r.side) + } + return r +} + +func orderBookSum(ls []BookLevel) float64 { + var t float64 + for _, l := range ls { + t += l.Size + } + return t +} + +// orderBookHeader names the columns. +func orderBookHeader(c *ui.Context) { + k := Tokens(c) + d := Density(c) + ui.Row(c).Padding(0, d.Unit()*2).Children(func() { + for i, key := range []string{"order_book.price", "order_book.size", "order_book.total"} { + t := ui.Text(c, msg(c, key)).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Grow(1).Basis(0) + if i > 0 { + t.TextAlign(ui.End) + } + } + }) +} + +// orderBookRow is one clickable level with its depth bar. +func orderBookRow(c *ui.Context, r *OrderBookResult, l BookLevel, cum, total float64, side OrderSide, dec, sizeDec int) { + k := Tokens(c) + d := Density(c) + col := trendColor(c, side.sign()) + price := statisticFormat(l.Price, dec) + b := ui.ButtonBase(c).Key(fmt.Sprint(side, price)).MinHeight(d.ControlHeight()). + Padding(0, d.Unit()*2).Radius(theme.ControlRadius). + Label(fmt.Sprintf(msg(c, "order_book.level"), msg(c, fmt.Sprintf("order_book.side%d", side)), price, statisticFormat(l.Size, sizeDec))) + internal.Ring(b, k.Focus, theme.ControlRadius) + if b.Hovered() { + b.Background(k.SurfaceHover) + } + share := float32(0) + if total > 0 { + share = float32(cum / total) + } + b.Draw(func(p *ui.Painter, rect ui.Rect) { + w := rect.W * share + p.Fill(ui.Rect{X: rect.X + rect.W - w, Y: rect.Y + 2, W: w, H: rect.H - 4}, col.Alpha(0.14), 0) + }) + b.Children(func() { + ui.Text(c, price).TextColor(col).FontFeatures("tnum").FontWeight(600).Grow(1).Basis(0).SingleLine() + ui.Text(c, statisticFormat(l.Size, sizeDec)).FontFeatures("tnum").TextAlign(ui.End).Grow(1).Basis(0).SingleLine() + ui.Text(c, statisticFormat(cum, sizeDec)).FontFeatures("tnum").TextColor(k.TextMuted).TextAlign(ui.End).Grow(1).Basis(0).SingleLine() + }) + if b.Clicked() && !b.IsDisabled() { + r.price, r.side = l.Price, side + } +} + +// orderBookRefresh regroups only when book or grouping changed. +func orderBookRefresh(s *OrderBookState, book OrderBookData, dec int) { + key := bookKeyOf(book, s.Group) + if s.cache.valid && s.cache.key == key { + return + } + s.cache = orderBookCache{key: key, valid: true, + bids: orderBookGroup(book.Bids, s.Group, dec, false), asks: orderBookGroup(book.Asks, s.Group, dec, true)} +} + +// orderBookGroup merges levels into group steps, best first. +func orderBookGroup(ls []BookLevel, group float64, dec int, up bool) []BookLevel { + scale := math.Pow(10, float64(dec)) + step := int64(1) + if group != 0 { + step = int64(math.Round(group * scale)) + if step < 1 || math.Abs(group*scale-float64(step)) > 1e-6 { + panic(fmt.Sprintf("mujica: OrderBook group %v is not a whole number of %d-decimal ticks", group, dec)) + } + } + sizes := map[int64]float64{} + for _, l := range ls { + if l.Price < 0 || l.Size < 0 { + panic("mujica: OrderBook levels need prices and sizes of zero or more") + } + t := int64(math.Round(l.Price * scale)) + // Bids round down, asks up: groups never beat real prices. + b := t / step * step + if up && b < t { + b += step + } + sizes[b] += l.Size + } + out := make([]BookLevel, 0, len(sizes)) + for t, sz := range sizes { + out = append(out, BookLevel{Price: float64(t) / scale, Size: sz}) + } + slices.SortFunc(out, func(a, b BookLevel) int { + if up { + return cmp.Compare(a.Price, b.Price) + } + return cmp.Compare(b.Price, a.Price) + }) + return out +} diff --git a/order_book_test.go b/order_book_test.go new file mode 100644 index 0000000..b0d6485 --- /dev/null +++ b/order_book_test.go @@ -0,0 +1,123 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func orderBookSample() OrderBookData { + return OrderBookData{ + Bids: []BookLevel{{100.00, 5}, {99.99, 3}, {99.94, 2}, {99.90, 4}}, + Asks: []BookLevel{{100.01, 1}, {100.02, 2}, {100.07, 6}}, + } +} + +func TestOrderBookClickReportsPrice(t *testing.T) { + var s OrderBookState + var price float64 + var side OrderSide + tt := tradingTester(GreenUp, 400, 500, func(c *ui.Context) { + if p, sd, ok := OrderBook(c, &s, orderBookSample(), OrderBookOptions{}).Clicked(); ok { + price, side = p, sd + } + }) + if err := tt.Click("Ask 100.02, size 2"); err != nil { + t.Fatal(err) + } + if price != 100.02 || side != SideSell { + t.Fatalf("clicked %v %v", price, side) + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if price != 100.01 || side != SideSell { + t.Fatalf("keyboard %v %v", price, side) + } + if !tt.HasText("0.01 (0.010%)") { + t.Fatalf("spread missing: %q", tt.Texts()) + } +} + +func TestOrderBookGroupsLevelsByTicks(t *testing.T) { + s := OrderBookState{Group: 0.05} + tt := tradingTester(GreenUp, 400, 500, func(c *ui.Context) { + OrderBook(c, &s, orderBookSample(), OrderBookOptions{Groups: []float64{0.01, 0.05, 0.1}}) + }) + // Bids round down, asks round up. + want := []BookLevel{{100.00, 5}, {99.95, 3}, {99.90, 6}} + for i, l := range want { + if s.cache.bids[i] != l { + t.Fatalf("bids %v", s.cache.bids) + } + } + if s.cache.asks[0] != (BookLevel{100.05, 3}) || s.cache.asks[1] != (BookLevel{100.10, 6}) { + t.Fatalf("asks %v", s.cache.asks) + } + if !tt.HasText("99.95") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestOrderBookAggregatesOnlyOnChange(t *testing.T) { + var s OrderBookState + book := orderBookSample() + tt := tradingTester(GreenUp, 400, 500, func(c *ui.Context) { OrderBook(c, &s, book, OrderBookOptions{}) }) + first := &s.cache.bids[0] + tt.Frame() + if &s.cache.bids[0] != first { + t.Fatal("regrouped without a change") + } + book.Bids[0].Size = 9 + book.Version++ + tt.Frame() + if s.cache.bids[0].Size != 9 { + t.Fatal("version change ignored") + } +} + +func TestOrderBookDisabledAndBadGroup(t *testing.T) { + var s OrderBookState + clicked := false + tt := tradingTester(GreenUp, 400, 500, func(c *ui.Context) { + _, _, clicked = OrderBook(c, &s, orderBookSample(), OrderBookOptions{Disabled: true}).Clicked() + }) + _ = tt.Click("Bid 100.00, size 5") + if clicked { + t.Fatal("disabled book clicked") + } + defer func() { + if recover() == nil { + t.Fatal("off-tick group accepted") + } + }() + bad := OrderBookState{Group: 0.015} + tradingTester(GreenUp, 100, 100, func(c *ui.Context) { + OrderBook(c, &bad, orderBookSample(), OrderBookOptions{Groups: []float64{0.015}}) + }) +} + +func TestOrderBookSnapshot(t *testing.T) { + snapshot(t, "order_book", 320, 420, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + s := ui.Local(c.Root(), "snap", func() OrderBookState { return OrderBookState{} }) + OrderBook(c, s, orderBookSample(), OrderBookOptions{Depth: 4, Groups: []float64{0.01, 0.05}}) + }) + }) +} + +// A 100,000-level book builds only the shown depth. +func TestOrderBookLargeBook(t *testing.T) { + var s OrderBookState + book := OrderBookData{} + for i := range 100_000 { + book.Bids = append(book.Bids, BookLevel{Price: 1000 - float64(i)/100, Size: 1}) + book.Asks = append(book.Asks, BookLevel{Price: 1000.01 + float64(i)/100, Size: 1}) + } + tt := tradingTester(GreenUp, 400, 900, func(c *ui.Context) { OrderBook(c, &s, book, OrderBookOptions{}) }) + if n := len(tt.Texts()); n > 80 { + t.Fatalf("built %d texts", n) + } + if len(s.cache.bids) != 100_000 || s.cache.bids[0].Price != 1000 { + t.Fatalf("bids %d", len(s.cache.bids)) + } +} diff --git a/order_confirm_dialog.go b/order_confirm_dialog.go new file mode 100644 index 0000000..357b5b0 --- /dev/null +++ b/order_confirm_dialog.go @@ -0,0 +1,88 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// OrderSummaryLine is one labeled value of an order summary. +type OrderSummaryLine struct { + Label, Value string +} + +// OrderConfirmDialogOptions configure an OrderConfirmDialog. Lines are required. +type OrderConfirmDialogOptions struct { + // Title is "Confirm order" when empty. + Title string + Lines []OrderSummaryLine + // Risk is a warning shown above the actions. + Risk string + // Acknowledge, when set, must be ticked before confirming. + Acknowledge string + // ConfirmLabel is "Place order" when empty. + ConfirmLabel string +} + +type orderConfirmState struct{ ack bool } + +// OrderConfirmDialog summarizes an order; Cancel has the focus. +func OrderConfirmDialog(c *ui.Context, open *bool, opts OrderConfirmDialogOptions) AlertDialogResult { + if len(opts.Lines) == 0 { + panic("mujica: OrderConfirmDialog needs summary Lines") + } + var res AlertDialogResult + k := Tokens(c) + u := Density(c).Unit() + title, confirm := opts.Title, opts.ConfirmLabel + if title == "" { + title = msg(c, "order_confirm_dialog.title") + } + if confirm == "" { + confirm = msg(c, "order_confirm_dialog.confirm") + } + was := *open + var st *orderConfirmState + Dialog(c, open, DialogOptions{Title: title, KeepOnBackdrop: true, HideClose: true, Actions: func() { + if Button(c, msg(c, "order_confirm_dialog.cancel"), ButtonOptions{Variant: Secondary}).AutoFocus().Clicked() { + res.Canceled = true + } + locked := opts.Acknowledge != "" && !st.ack + if Button(c, confirm, ButtonOptions{Disabled: locked}).Clicked() && !locked { + res.Confirmed = true + } + }}, func() { + list := ui.Column(c) + // The tick lives with the open dialog only. + st = ui.Local(list, "ack", func() orderConfirmState { return orderConfirmState{} }) + list.Children(func() { + for _, l := range opts.Lines { + ui.Row(c).Gap(u*4).MinHeight(Density(c).ControlHeight()).AlignItems(ui.Center). + BorderWidth(0, 0, theme.BorderWidth, 0).BorderColor(k.Border).Children(func() { + ui.Text(c, l.Label).TextColor(k.TextMuted).Grow(1) + ui.Text(c, l.Value).FontFeatures("tnum").FontWeight(600) + }) + } + }) + if opts.Risk != "" { + ui.Row(c).Gap(u * 2).AlignItems(ui.Start).Padding(u * 3).Radius(theme.ControlRadius).Background(k.Warning.Alpha(0.12)).Children(func() { + ui.Icon(c, icons.Must("triangle-alert")).Size(16, 16).TextColor(k.Warning).Shrink(0) + ui.Text(c, opts.Risk).Grow(1) + }) + } + if opts.Acknowledge != "" { + Checkbox(c, &st.ack, opts.Acknowledge, CheckboxOptions{}) + } + }) + if was && !*open && !res.Confirmed { + res.Canceled = true + } + if res.Confirmed || res.Canceled { + *open = false + slog.Debug("mujica: order_confirm_dialog close", "confirmed", res.Confirmed) + } + return res +} diff --git a/order_confirm_dialog_test.go b/order_confirm_dialog_test.go new file mode 100644 index 0000000..68d48f2 --- /dev/null +++ b/order_confirm_dialog_test.go @@ -0,0 +1,78 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func orderConfirmTester(open *bool, opts OrderConfirmDialogOptions, res *AlertDialogResult) *ui.Tester { + return tradingTester(GreenUp, 600, 500, func(c *ui.Context) { + if r := OrderConfirmDialog(c, open, opts); r.Confirmed || r.Canceled { + *res = r + } + }) +} + +var orderConfirmLines = []OrderSummaryLine{{"Symbol", "MUJC"}, {"Side", "Buy"}, {"Quantity", "100"}, {"Est. amount", "10,020.00"}} + +func TestOrderConfirmDialogFocusesCancel(t *testing.T) { + open := true + var res AlertDialogResult + tt := orderConfirmTester(&open, OrderConfirmDialogOptions{Lines: orderConfirmLines, Risk: "Leveraged products can lose more than the deposit."}, &res) + if !tt.Focused("Cancel") || !tt.HasText("10,020.00") || !tt.HasText("Leveraged products can lose more than the deposit.") { + t.Fatalf("texts %q", tt.Texts()) + } + tt.Key(0, ui.KeyEnter) + if !res.Canceled || open { + t.Fatalf("Enter on Cancel: %+v open %v", res, open) + } + open, res = true, AlertDialogResult{} + tt.Frame() + if err := tt.Click("Place order"); err != nil { + t.Fatal(err) + } + if !res.Confirmed || open { + t.Fatalf("confirm: %+v", res) + } +} + +func TestOrderConfirmDialogAcknowledgeAndEscape(t *testing.T) { + open := true + var res AlertDialogResult + tt := orderConfirmTester(&open, OrderConfirmDialogOptions{Lines: orderConfirmLines, Acknowledge: "I understand the risk"}, &res) + _ = tt.Click("Place order") + if res.Confirmed || !open { + t.Fatal("confirmed before acknowledging") + } + _ = tt.Click("I understand the risk") + _ = tt.Click("Place order") + if !res.Confirmed { + t.Fatal("acknowledged confirm refused") + } + open, res = true, AlertDialogResult{} + tt.Frame() + _ = tt.Click("Place order") + if res.Confirmed { + t.Fatal("acknowledgement survived reopening") + } + tt.Key(0, ui.KeyEscape) + if !res.Canceled || open { + t.Fatalf("escape: %+v", res) + } + defer func() { + if recover() == nil { + t.Fatal("empty summary accepted") + } + }() + open = true + orderConfirmTester(&open, OrderConfirmDialogOptions{}, &res) +} + +func TestOrderConfirmDialogSnapshot(t *testing.T) { + open := true + snapshot(t, "order_confirm_dialog", 560, 480, func(c *ui.Context) { + OrderConfirmDialog(c, &open, OrderConfirmDialogOptions{Lines: orderConfirmLines, + Risk: "Leveraged products can lose more than the deposit.", Acknowledge: "I understand the risk"}) + }) +} diff --git a/order_entry.go b/order_entry.go new file mode 100644 index 0000000..0c95398 --- /dev/null +++ b/order_entry.go @@ -0,0 +1,222 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// OrderType is limit, market, stop or stop limit. +type OrderType int + +const ( + OrderLimit OrderType = iota + OrderMarket + OrderStop + OrderStopLimit +) + +// TimeInForce is how long an order rests. +type TimeInForce int + +const ( + TIFDay TimeInForce = iota + TIFGoodTillCanceled + TIFImmediateOrCancel + TIFFillOrKill +) + +// OrderDraft is an order as entered. +type OrderDraft struct { + Side OrderSide + Type OrderType + Quantity float64 + Price float64 + Trigger float64 + TIF TimeInForce +} + +// OrderEntryOptions configure an OrderEntry. Symbol is required. +type OrderEntryOptions struct { + Symbol string + // Last is the last price; zero means unknown. + Last float64 + // TickSize and LotSize step prices and quantities; zero: 0.01, 1. + TickSize, LotSize float64 + // MaxQuantity caps the quantity; zero means no cap. + MaxQuantity float64 + // Initial is what Reset restores; a zero Side means buy. + Initial OrderDraft + // Validate adds the caller's rules, returning a message or "". + Validate func(o OrderDraft) string + // Check starts an async check, finished with OrderEntryState.Resolve. + Check func(o OrderDraft, version uint64) + Disabled bool +} + +// OrderEntryState holds the draft and its form state. +type OrderEntryState struct { + Draft OrderDraft + Form FormState + started bool +} + +// Resolve delivers Check's result; stale versions return false. +func (s *OrderEntryState) Resolve(version uint64, err string) bool { + return s.Form.Resolve("quantity", version, err) +} + +// EndSubmit finishes a submit; a formError shows, keeping the draft. +func (s *OrderEntryState) EndSubmit(formError string) { s.Form.EndSubmit(formError) } + +// OrderEntryResult is a built OrderEntry and its submitted order. +type OrderEntryResult struct { + Element *ui.Element + order OrderDraft + submitted bool +} + +// Submitted returns the checked order; call EndSubmit once placed. +func (r OrderEntryResult) Submitted() (OrderDraft, bool) { return r.order, r.submitted } + +// OrderEntry edits an order and submits it once checked. +func OrderEntry(c *ui.Context, s *OrderEntryState, opts OrderEntryOptions) OrderEntryResult { + if opts.Symbol == "" { + panic("mujica: OrderEntry needs a Symbol") + } + if opts.TickSize < 0 || opts.LotSize < 0 || opts.MaxQuantity < 0 || opts.Last < 0 { + panic("mujica: OrderEntry TickSize, LotSize, MaxQuantity and Last cannot be negative") + } + tick, lot := opts.TickSize, opts.LotSize + if tick == 0 { + tick = 0.01 + } + if lot == 0 { + lot = 1 + } + initial := opts.Initial + if initial.Side == 0 { + initial.Side = SideBuy + } + if !s.started { + s.started, s.Draft = true, initial + } + priceSpec := numberInputResolve(NumberInputOptions{Step: tick}) + k := Tokens(c) + u := Density(c).Unit() + var r OrderEntryResult + r.Element = ui.Column(c).Gap(u * 4).MaxWidth(360).Disabled(opts.Disabled).Role(ui.RoleGroup).Label(msg(c, "order_entry.label")) + disabled := r.Element.IsDisabled() + r.Element.Children(func() { + side := 0 + if s.Draft.Side == SideSell { + side = 1 + } + sides := []Segment{{Label: msg(c, "order_entry.buy")}, {Label: msg(c, "order_entry.sell")}} + SegmentedControl(c, &side, sides, SegmentedControlOptions{Equal: true, Label: msg(c, "order_entry.side"), Disabled: disabled}) + s.Draft.Side = SideBuy + OrderSide(side) + var types []SelectOption[OrderType] + for t := OrderLimit; t <= OrderStopLimit; t++ { + types = append(types, SelectOption[OrderType]{Value: t, Label: msg(c, fmt.Sprintf("order_entry.type%d", t))}) + } + ui.Row(c).Gap(u * 3).AlignItems(ui.Center).Children(func() { + ui.Text(c, opts.Symbol).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).FontWeight(600).Grow(1) + Select(c, &s.Draft.Type, types, SelectOptions{Label: msg(c, "order_entry.type"), Disabled: disabled}) + }) + submit := fmt.Sprintf(msg(c, fmt.Sprintf("order_entry.submit%d", s.Draft.Side)), opts.Symbol) + res := Form(c, &s.Form, FormOptions{SubmitLabel: submit}, func(f *FormScope) { + orderEntryFields(c, f, s, opts, initial, tick, lot, disabled) + }) + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, msg(c, "order_entry.estimate")).TextColor(k.TextMuted) + est := "—" + if p := orderEntryPrice(s.Draft, opts.Last); p > 0 && s.Draft.Quantity > 0 { + est = "≈ " + statisticFormat(p*s.Draft.Quantity, priceSpec.decimals) + } + ui.Text(c, est).FontFeatures("tnum").FontWeight(600) + }) + if res.Submitted() { + r.order, r.submitted = s.Draft, true + slog.Debug("mujica: order_entry submitted", "side", s.Draft.Side, "type", s.Draft.Type) + } + }) + return r +} + +// orderEntryPrice is the expected fill price, or 0 if unknown. +func orderEntryPrice(o OrderDraft, last float64) float64 { + switch o.Type { + case OrderLimit, OrderStopLimit: + return o.Price + case OrderStop: + return o.Trigger + } + return last +} + +// orderEntryFields registers the fields the order type needs. +func orderEntryFields(c *ui.Context, f *FormScope, s *OrderEntryState, opts OrderEntryOptions, initial OrderDraft, tick, lot float64, disabled bool) { + maxQ := opts.MaxQuantity + FormItem(c, f, "quantity", &s.Draft, FormItemOptions[OrderDraft]{Label: msg(c, "order_entry.quantity"), Required: true, Initial: initial, + Validate: func(o OrderDraft) string { return orderEntryCheck(c, o, opts, maxQ) }, + Async: opts.Check, + }, func() *ui.Element { + return NumberInput(c, &s.Draft.Quantity, NumberInputOptions{Step: lot, Disabled: disabled, Error: s.Form.Error("quantity")}).Input + }) + if s.Draft.Type == OrderStop || s.Draft.Type == OrderStopLimit { + FormItem(c, f, "trigger", &s.Draft.Trigger, FormItemOptions[float64]{Label: msg(c, "order_entry.trigger"), Required: true, Initial: initial.Trigger, + Validate: func(v float64) string { return orderEntryTrigger(c, s.Draft, opts.Last) }, + }, func() *ui.Element { + return NumberInput(c, &s.Draft.Trigger, NumberInputOptions{Step: tick, Disabled: disabled, Error: s.Form.Error("trigger")}).Input + }) + } + if s.Draft.Type == OrderLimit || s.Draft.Type == OrderStopLimit { + FormItem(c, f, "price", &s.Draft.Price, FormItemOptions[float64]{Label: msg(c, "order_entry.price"), Required: true, Initial: initial.Price, + Validate: func(v float64) string { + if v <= 0 { + return msg(c, "order_entry.price_positive") + } + return "" + }, + }, func() *ui.Element { + return NumberInput(c, &s.Draft.Price, NumberInputOptions{Step: tick, Disabled: disabled, Error: s.Form.Error("price")}).Input + }) + } + var tifs []SelectOption[TimeInForce] + for t := TIFDay; t <= TIFFillOrKill; t++ { + tifs = append(tifs, SelectOption[TimeInForce]{Value: t, Label: msg(c, fmt.Sprintf("order_entry.tif%d", t))}) + } + FormItem(c, f, "tif", &s.Draft.TIF, FormItemOptions[TimeInForce]{Label: msg(c, "order_entry.tif"), Initial: initial.TIF}, func() *ui.Element { + return Select(c, &s.Draft.TIF, tifs, SelectOptions{Label: msg(c, "order_entry.tif"), Disabled: disabled}).Element + }) +} + +// orderEntryCheck checks the quantity, then the caller's rules. +func orderEntryCheck(c *ui.Context, o OrderDraft, opts OrderEntryOptions, maxQ float64) string { + switch { + case o.Quantity <= 0: + return msg(c, "order_entry.quantity_positive") + case maxQ > 0 && o.Quantity > maxQ: + return fmt.Sprintf(msg(c, "order_entry.quantity_max"), statisticFormat(maxQ, 0)) + } + if opts.Validate != nil { + return opts.Validate(o) + } + return "" +} + +// orderEntryTrigger checks a stop's side of the last price. +func orderEntryTrigger(c *ui.Context, o OrderDraft, last float64) string { + switch { + case o.Trigger <= 0: + return msg(c, "order_entry.trigger_positive") + case last > 0 && o.Side == SideBuy && o.Trigger <= last: + return msg(c, "order_entry.trigger_above") + case last > 0 && o.Side == SideSell && o.Trigger >= last: + return msg(c, "order_entry.trigger_below") + } + return "" +} diff --git a/order_entry_test.go b/order_entry_test.go new file mode 100644 index 0000000..58e9a19 --- /dev/null +++ b/order_entry_test.go @@ -0,0 +1,137 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +type orderEntryProbe struct { + s OrderEntryState + opts OrderEntryOptions + orders []OrderDraft + checks []uint64 + checked []OrderDraft +} + +func (p *orderEntryProbe) tester() *ui.Tester { + return tradingTester(GreenUp, 520, 700, func(c *ui.Context) { + if o, ok := OrderEntry(c, &p.s, p.opts).Submitted(); ok { + p.orders = append(p.orders, o) + } + }) +} + +func TestOrderEntryLimitSubmitOnce(t *testing.T) { + p := &orderEntryProbe{opts: OrderEntryOptions{Symbol: "MUJC", Last: 100}} + tt := p.tester() + _ = tt.Click("Quantity") + tt.Type("10") + _ = tt.Click("Limit price") + tt.Key(ui.Cmd, ui.KeyA) + tt.Type("99.5") + if !tt.HasText("≈ 995.00") { + t.Fatalf("estimate: %q", tt.Texts()) + } + if err := tt.Click("Buy MUJC"); err != nil { + t.Fatal(err) + } + _ = tt.Click("Buy MUJC") + if len(p.orders) != 1 || p.orders[0] != (OrderDraft{Side: SideBuy, Type: OrderLimit, Quantity: 10, Price: 99.5}) { + t.Fatalf("orders %+v", p.orders) + } + p.s.EndSubmit("") + tt.Frame() + _ = tt.Click("Buy MUJC") + if len(p.orders) != 2 { + t.Fatalf("after EndSubmit: %d orders", len(p.orders)) + } +} + +func TestOrderEntryValidatesByType(t *testing.T) { + p := &orderEntryProbe{opts: OrderEntryOptions{Symbol: "MUJC", Last: 100, MaxQuantity: 50}} + tt := p.tester() + _ = tt.Click("Buy MUJC") + if len(p.orders) != 0 || !tt.HasText("Enter a quantity above zero.") || !tt.HasText("Required") { + t.Fatalf("empty order: %q", tt.Texts()) + } + if !tt.Focused("Quantity") { + t.Fatal("first error not focused") + } + tt.Type("80") + tt.Key(0, ui.KeyTab) + if !tt.HasText("At most 50.") { + t.Fatalf("max: %q", tt.Texts()) + } + p.s.Draft.Type, p.s.Draft.Side, p.s.Draft.Quantity, p.s.Draft.Trigger = OrderStop, SideSell, 5, 101 + tt.Frame() + _ = tt.Click("Sell MUJC") + if len(p.orders) != 0 || !tt.HasText("A sell stop triggers below the last price.") || tt.HasText("Limit price") { + t.Fatalf("stop: %q", tt.Texts()) + } + p.s.Draft.Trigger = 98 + tt.Frame() + _ = tt.Click("Sell MUJC") + if len(p.orders) != 1 || p.orders[0].Type != OrderStop || p.orders[0].Trigger != 98 { + t.Fatalf("orders %+v", p.orders) + } +} + +// An old draft's check cannot clear a newer draft. +func TestOrderEntryAsyncCheckIsVersioned(t *testing.T) { + p := &orderEntryProbe{} + p.opts = OrderEntryOptions{Symbol: "MUJC", Last: 100, Check: func(o OrderDraft, v uint64) { + p.checks, p.checked = append(p.checks, v), append(p.checked, o) + }} + p.s.started, p.s.Draft = true, OrderDraft{Side: SideBuy, Type: OrderMarket, Quantity: 10} + tt := p.tester() + _ = tt.Click("Buy MUJC") + if len(p.checks) != 1 || len(p.orders) != 0 { + t.Fatalf("checks %v orders %d", p.checks, len(p.orders)) + } + p.s.Draft.Quantity = 20 + tt.Frame() + if p.s.Resolve(p.checks[0], "") { + t.Fatal("stale check accepted") + } + tt.Frame() + if len(p.checks) != 2 || p.checked[1].Quantity != 20 || len(p.orders) != 0 { + t.Fatalf("checks %v orders %d", p.checks, len(p.orders)) + } + p.s.Resolve(p.checks[1], "Not enough buying power.") + tt.Frame() + tt.Frame() + if len(p.orders) != 0 || !tt.HasText("Not enough buying power.") { + t.Fatalf("failed check submitted: %q", tt.Texts()) + } +} + +func TestOrderEntryDisabledAndReset(t *testing.T) { + p := &orderEntryProbe{opts: OrderEntryOptions{Symbol: "MUJC", Disabled: true, Initial: OrderDraft{Quantity: 1, Price: 50}}} + tt := p.tester() + _ = tt.Click("Quantity") + tt.Type("9") + _ = tt.Click("Buy MUJC") + if p.s.Draft.Quantity != 1 || len(p.orders) != 0 { + t.Fatalf("disabled entry changed: %+v", p.s.Draft) + } + p.opts.Disabled = false + p.s.Draft.Quantity, p.s.Draft.Side = 7, SideSell + tt.Frame() + _ = tt.Click("Reset") + if p.s.Draft != (OrderDraft{Side: SideBuy, Quantity: 1, Price: 50}) { + t.Fatalf("reset: %+v", p.s.Draft) + } +} + +func TestOrderEntrySnapshot(t *testing.T) { + snapshot(t, "order_entry", 420, 520, func(c *ui.Context) { + ui.Column(c).Padding(20).Children(func() { + s := ui.Local(c.Root(), "snap", func() OrderEntryState { return OrderEntryState{} }) + if !s.started { + s.started, s.Draft = true, OrderDraft{Side: SideBuy, Type: OrderStopLimit, Quantity: 25, Price: 101.5, Trigger: 101} + } + OrderEntry(c, s, OrderEntryOptions{Symbol: "MUJC", Last: 100.2}) + }) + }) +} diff --git a/order_table.go b/order_table.go new file mode 100644 index 0000000..7e558ff --- /dev/null +++ b/order_table.go @@ -0,0 +1,194 @@ +package mujica + +import ( + "cmp" + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// OrderStatus is where an order stands. +type OrderStatus int + +const ( + OrderOpen OrderStatus = iota + OrderPartial + OrderFilled + OrderCanceled + OrderRejected +) + +// working reports an order that can still fill. +func (s OrderStatus) working() bool { return s == OrderOpen || s == OrderPartial } + +// OrderRow is one order; ID must be stable across updates. +type OrderRow struct { + ID, Symbol string + Side OrderSide + Type OrderType + Price float64 + Quantity float64 + Filled float64 + Status OrderStatus +} + +// OrderFilter picks which orders an OrderTable shows. +type OrderFilter int + +const ( + OrdersAll OrderFilter = iota + OrdersWorking + OrdersFilled + OrdersClosed +) + +func (f OrderFilter) keeps(s OrderStatus) bool { + switch f { + case OrdersWorking: + return s.working() + case OrdersFilled: + return s == OrderFilled + case OrdersClosed: + return s == OrderCanceled || s == OrderRejected + } + return true +} + +// OrderTableOptions configure an OrderTable. +type OrderTableOptions struct { + // Decimals of prices and quantities; zero means 2 and 0. + Decimals, QuantityDecimals int + // Version must change when rows change in place. + Version int + Status DataStatus + Error string + Disabled bool +} + +// OrderTableState is the status filter and table state. +type OrderTableState struct { + Filter OrderFilter + Table DataTableState[string] + cache tradingRows[OrderRow] +} + +// OrderTable lists orders with filter, progress and Cancel. +func OrderTable(c *ui.Context, s *OrderTableState, rows []OrderRow, opts OrderTableOptions) TableActionResult { + dec := priceDecimals("OrderTable", opts.Decimals) + if opts.QuantityDecimals < 0 { + panic("mujica: OrderTable with negative QuantityDecimals") + } + qd := opts.QuantityDecimals + shown := s.cache.view(rows, opts.Version, s.Filter, func(o OrderRow) bool { + if o.Quantity <= 0 || o.Filled < 0 || o.Filled > o.Quantity { + panic(fmt.Sprintf("mujica: OrderTable order %s fills %v of %v", o.ID, o.Filled, o.Quantity)) + } + return s.Filter.keeps(o.Status) + }) + var r TableActionResult + text := func(id, key string, t func(OrderRow) string) DataColumn[OrderRow] { + return DataColumn[OrderRow]{ID: id, Title: msg(c, key), Sortable: true, Text: t, + Compare: func(a, b OrderRow) int { return cmp.Compare(t(a), t(b)) }} + } + cols := []DataColumn[OrderRow]{ + text("symbol", "position_table.symbol", func(o OrderRow) string { return o.Symbol }), + {ID: "side", Title: msg(c, "order_table.side"), Text: func(o OrderRow) string { return msg(c, fmt.Sprintf("order_entry.side%d", o.Side)) }, + Cell: func(o OrderRow) { tradingSide(c, o.Side) }}, + text("type", "order_entry.type", func(o OrderRow) string { return msg(c, fmt.Sprintf("order_entry.type%d", o.Type)) }), + {ID: "price", Title: msg(c, "order_book.price"), Align: ui.End, Sortable: true, + Compare: func(a, b OrderRow) int { return cmp.Compare(a.Price, b.Price) }, + Text: func(o OrderRow) string { + if o.Type == OrderMarket { + return msg(c, "order_table.market") + } + return statisticFormat(o.Price, dec) + }}, + {ID: "filled", Title: msg(c, "order_table.filled"), Width: 140, + Text: func(o OrderRow) string { + return statisticFormat(o.Filled, qd) + " / " + statisticFormat(o.Quantity, qd) + }, + Cell: func(o OrderRow) { orderTableProgress(c, o, qd) }}, + text("status", "order_table.status", func(o OrderRow) string { return msg(c, fmt.Sprintf("order_table.status%d", o.Status)) }), + {ID: "action", Title: msg(c, "position_table.action"), Width: 96, Text: func(OrderRow) string { return "" }, + Cell: func(o OrderRow) { + if o.Status.working() && Button(c, msg(c, "order_table.cancel"), ButtonOptions{Variant: Secondary}). + Label(msg(c, "order_table.cancel")+" "+o.Symbol).Clicked() { + r.id = o.ID + } + }}, + } + d := Density(c) + r.Element = ui.Column(c).Gap(d.Unit() * 2).Disabled(opts.Disabled).Grow(1).FillWidth().MinHeight(0) + r.Element.Children(func() { + var segs []Segment + for f := OrdersAll; f <= OrdersClosed; f++ { + segs = append(segs, Segment{Label: msg(c, fmt.Sprintf("order_table.filter%d", f))}) + } + at := int(s.Filter) + if SegmentedControl(c, &at, segs, SegmentedControlOptions{Label: msg(c, "order_table.filter"), Disabled: opts.Disabled}).Changed() { + s.Filter = OrderFilter(at) + slog.Debug("mujica: order_table filter", "filter", s.Filter) + } + r.Table = DataTable(c, &s.Table, shown, DataTableOptions[OrderRow, string]{Columns: cols, Key: func(o OrderRow) string { return o.ID }, + Status: opts.Status, Error: opts.Error, Empty: msg(c, "order_table.empty")}) + r.Table.Element.Grow(1) + }) + if r.Element.IsDisabled() { + r.id = "" + } + if r.id != "" { + slog.Debug("mujica: order_table cancel") + } + return r +} + +// orderTableProgress shows the filled share as bar and count. +func orderTableProgress(c *ui.Context, o OrderRow, qd int) { + k := Tokens(c) + share := float32(o.Filled / o.Quantity) + ui.Row(c).Gap(Density(c).Unit() * 2).AlignItems(ui.Center).FillWidth().Children(func() { + ui.Box(c).Size(48, 6).Shrink(0).Role(ui.RoleNone).Draw(func(p *ui.Painter, r ui.Rect) { + p.Fill(r, k.SurfaceHover, theme.ControlRadius) + p.Fill(ui.Rect{X: r.X, Y: r.Y, W: r.W * share, H: r.H}, k.AccentText, theme.ControlRadius) + }) + ui.Text(c, statisticFormat(o.Filled, qd)+" / "+statisticFormat(o.Quantity, qd)).FontFeatures("tnum").FontSize(FontSize(c, theme.CaptionSize)).SingleLine() + }) +} + +// tradingSide names a side with its arrow and trend color. +func tradingSide(c *ui.Context, side OrderSide) { + ui.Row(c).Gap(2).AlignItems(ui.Center).TextColor(trendColor(c, side.sign())).Children(func() { + ui.Icon(c, trendIcon(side.sign())).Size(12, 12) + ui.Text(c, msg(c, fmt.Sprintf("order_entry.side%d", side))).FontWeight(600).SingleLine() + }) +} + +// tradingRows is a filtered view, rebuilt only on change. +type tradingRows[R any] struct { + first *R + n, ver int + filter any + valid bool + visible []R +} + +func (t *tradingRows[R]) view(rows []R, version int, filter any, keep func(R) bool) []R { + var first *R + if len(rows) > 0 { + first = &rows[0] + } + if t.valid && t.first == first && t.n == len(rows) && t.ver == version && t.filter == filter { + return t.visible + } + t.first, t.n, t.ver, t.filter, t.valid = first, len(rows), version, filter, true + t.visible = make([]R, 0, len(rows)) + for _, r := range rows { + if keep(r) { + t.visible = append(t.visible, r) + } + } + return t.visible +} diff --git a/order_table_test.go b/order_table_test.go new file mode 100644 index 0000000..be31cfa --- /dev/null +++ b/order_table_test.go @@ -0,0 +1,118 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +func orderTableSample() []OrderRow { + return []OrderRow{ + {ID: "o1", Symbol: "MUJC", Side: SideBuy, Type: OrderLimit, Price: 99.5, Quantity: 100, Filled: 40, Status: OrderPartial}, + {ID: "o2", Symbol: "AVE", Side: SideSell, Type: OrderMarket, Quantity: 10, Filled: 10, Status: OrderFilled}, + {ID: "o3", Symbol: "OBLV", Side: SideBuy, Type: OrderStop, Price: 12, Quantity: 5, Status: OrderCanceled}, + {ID: "o4", Symbol: "DOLO", Side: SideSell, Type: OrderLimit, Price: 7.25, Quantity: 30, Status: OrderOpen}, + } +} + +func orderTableTester(s *OrderTableState, rows *[]OrderRow, opts *OrderTableOptions, acted *string) *ui.Tester { + return tradingTester(GreenUp, 1000, 400, func(c *ui.Context) { + ui.Box(c).Width(960).Height(320).Children(func() { + if id, ok := OrderTable(c, s, *rows, *opts).Acted(); ok { + *acted = id + } + }) + }) +} + +func TestOrderTableFilterProgressAndCancel(t *testing.T) { + var s OrderTableState + rows, opts, acted := orderTableSample(), OrderTableOptions{}, "" + tt := orderTableTester(&s, &rows, &opts, &acted) + if !tt.HasText("40 / 100") || !tt.HasText("Partly filled") || !tt.HasText("Market") { + t.Fatalf("texts %q", tt.Texts()) + } + if err := tt.Click("Working"); err != nil { + t.Fatal(err) + } + if tt.HasText("AVE") || tt.HasText("OBLV") || !tt.HasText("DOLO") { + t.Fatalf("working filter: %q", tt.Texts()) + } + if _, ok := tt.Find("Cancel AVE"); ok { + t.Fatal("filled order offers cancel") + } + if err := tt.Click("Cancel DOLO"); err != nil { + t.Fatal(err) + } + if acted != "o4" { + t.Fatalf("acted %q", acted) + } + _ = tt.Click("Closed") + if !tt.HasText("OBLV") || tt.HasText("MUJC") { + t.Fatalf("closed filter: %q", tt.Texts()) + } +} + +func TestOrderTableFiltersOnlyOnChange(t *testing.T) { + var s OrderTableState + rows, opts, acted := orderTableSample(), OrderTableOptions{}, "" + tt := orderTableTester(&s, &rows, &opts, &acted) + view := s.cache.visible + tt.Frame() + if &s.cache.visible[0] != &view[0] { + t.Fatal("refiltered without a change") + } + rows[0].Status = OrderFilled + opts.Version++ + _ = tt.Click("Working") + if len(s.cache.visible) != 1 { + t.Fatalf("version change ignored: %d rows", len(s.cache.visible)) + } +} + +func TestOrderTableDisabledAndBadFill(t *testing.T) { + var s OrderTableState + rows, opts, acted := orderTableSample(), OrderTableOptions{Disabled: true}, "" + tt := orderTableTester(&s, &rows, &opts, &acted) + _ = tt.Click("Cancel DOLO") + _ = tt.Click("Working") + if acted != "" || s.Filter != OrdersAll { + t.Fatal("disabled table acted") + } + defer func() { + if recover() == nil { + t.Fatal("overfilled order accepted") + } + }() + var s2 OrderTableState + bad := []OrderRow{{ID: "x", Quantity: 1, Filled: 2}} + orderTableTester(&s2, &bad, &OrderTableOptions{}, &acted) +} + +func TestOrderTableSnapshot(t *testing.T) { + snapshot(t, "order_table", 960, 300, func(c *ui.Context) { + ui.Column(c).Padding(16).Height(280).Width(940).Children(func() { + s := ui.Local(c.Root(), "snap", func() OrderTableState { return OrderTableState{} }) + OrderTable(c, s, orderTableSample(), OrderTableOptions{}) + }) + }) +} + +// 100,000 orders filter once and build only visible rows. +func TestOrderTableLargeData(t *testing.T) { + var s OrderTableState + rows := make([]OrderRow, 100_000) + for i := range rows { + rows[i] = OrderRow{ID: fmt.Sprint(i), Symbol: fmt.Sprintf("S%05d", i), Side: SideBuy, Price: 1, Quantity: 10, Status: OrderStatus(i % 5)} + } + opts, acted := OrderTableOptions{}, "" + tt := orderTableTester(&s, &rows, &opts, &acted) + _ = tt.Click("Working") + if len(s.cache.visible) != 40_000 { + t.Fatalf("working rows %d", len(s.cache.visible)) + } + if n := len(tt.Texts()); n > 400 { + t.Fatalf("built %d texts", n) + } +} diff --git a/pnl_display.go b/pnl_display.go new file mode 100644 index 0000000..605745d --- /dev/null +++ b/pnl_display.go @@ -0,0 +1,82 @@ +package mujica + +import ( + "log/slog" + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// PnL is profit and loss: realized, unrealized and today's. +type PnL struct { + Realized, Unrealized, Today float64 +} + +// PnLDisplayOptions configure a PnLDisplay. +type PnLDisplayOptions struct { + // Decimals of the amounts; zero means 2. + Decimals int + // Currency prefixes each amount, as "$". + Currency string +} + +// PnLDisplay shows three profits signed; *hidden masks them. +func PnLDisplay(c *ui.Context, pnl PnL, hidden *bool, opts PnLDisplayOptions) ChoiceResult { + dec := priceDecimals("PnLDisplay", opts.Decimals) + k := Tokens(c) + u := Density(c).Unit() + var r ChoiceResult + r.Element = ui.Row(c).Gap(u * 6).AlignItems(ui.Start).Wrap().Role(ui.RoleGroup).Label(msg(c, "pnl_display.label")) + r.Element.Children(func() { + for _, item := range []struct { + key string + v float64 + }{{"pnl_display.realized", pnl.Realized}, {"pnl_display.unrealized", pnl.Unrealized}, {"pnl_display.today", pnl.Today}} { + title := msg(c, item.key) + sign := trendSign(item.v) + text := statisticSigned(item.v, dec) + if opts.Currency != "" { + text = pnlDisplaySign(sign) + opts.Currency + statisticFormat(math.Abs(item.v), dec) + } + col := trendColor(c, sign) + spoken := title + ", " + trendWord(c, sign) + " " + text + if *hidden { + text, col, spoken = "••••", k.TextMuted, title+", "+msg(c, "pnl_display.masked") + } + ui.Column(c).Gap(u).Label(spoken).Role(ui.RoleText).Children(func() { + ui.Text(c, title).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Role(ui.RoleNone) + ui.Row(c).Gap(u).AlignItems(ui.Center).TextColor(col).Role(ui.RoleNone).Children(func() { + if !*hidden { + ui.Icon(c, trendIcon(sign)).Size(16, 16) + } + ui.Text(c, text).FontSize(FontSize(c, theme.H3Size)).FontFeatures("tnum").FontWeight(600).SingleLine() + }) + }) + } + name := msg(c, "pnl_display.hide") + icon := icons.Must("eye-off") + if *hidden { + name, icon = msg(c, "pnl_display.show"), icons.Must("eye") + } + b := iconAction(c, icon, name) + if b.Clicked() && !b.IsDisabled() { + *hidden = !*hidden + r.changed = true + slog.Debug("mujica: pnl_display mask", "hidden", *hidden) + } + }) + return r +} + +func pnlDisplaySign(sign int) string { + switch { + case sign > 0: + return "+" + case sign < 0: + return "−" + } + return "" +} diff --git a/pnl_display_test.go b/pnl_display_test.go new file mode 100644 index 0000000..b258102 --- /dev/null +++ b/pnl_display_test.go @@ -0,0 +1,43 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestPnLDisplaySignsAndMask(t *testing.T) { + hidden, n := false, 0 + tt := tradingTester(GreenUp, 520, 160, func(c *ui.Context) { + if PnLDisplay(c, PnL{Realized: 1200.5, Unrealized: -340, Today: 0}, &hidden, PnLDisplayOptions{Currency: "$"}).Changed() { + n++ + } + }) + for _, want := range []string{"+$1,200.50", "−$340.00", "$0.00"} { + if !tt.HasText(want) { + t.Fatalf("missing %q in %q", want, tt.Texts()) + } + } + if err := tt.Click("Hide amounts"); err != nil { + t.Fatal(err) + } + if !hidden || n != 1 || tt.HasText("+$1,200.50") { + t.Fatalf("mask: hidden %v changes %d texts %q", hidden, n, tt.Texts()) + } + if _, ok := tt.Find("Realized, hidden"); !ok { + t.Fatal("masked amount still spoken") + } + tt.Key(0, ui.KeySpace) + if hidden || n != 2 { + t.Fatalf("keyboard toggle: hidden %v", hidden) + } +} + +func TestPnLDisplaySnapshot(t *testing.T) { + hidden := false + snapshot(t, "pnl_display", 460, 100, func(c *ui.Context) { + ui.Column(c).Padding(20).Children(func() { + PnLDisplay(c, PnL{Realized: 1200.5, Unrealized: -340.2, Today: 88}, &hidden, PnLDisplayOptions{Currency: "$"}) + }) + }) +} diff --git a/position_table.go b/position_table.go new file mode 100644 index 0000000..d868894 --- /dev/null +++ b/position_table.go @@ -0,0 +1,107 @@ +package mujica + +import ( + "cmp" + "log/slog" + + "github.com/egoist/mygo/ui" +) + +// PositionRow is one holding; ID must be stable across updates. +type PositionRow struct { + ID, Symbol string + Quantity float64 + AvgCost float64 + Price float64 +} + +// MarketValue is the quantity at the last price. +func (p PositionRow) MarketValue() float64 { return p.Quantity * p.Price } + +// Unrealized is the floating profit against the average cost. +func (p PositionRow) Unrealized() float64 { return (p.Price - p.AvgCost) * p.Quantity } + +// UnrealizedPercent is the floating profit as a percent of cost. +func (p PositionRow) UnrealizedPercent() float64 { + if p.AvgCost == 0 { + return 0 + } + return (p.Price - p.AvgCost) / p.AvgCost * 100 +} + +// PositionTableOptions configure a PositionTable. +type PositionTableOptions struct { + // Decimals of prices and amounts; zero means 2. + Decimals int + // Version must change when rows change in place. + Version int + Status DataStatus + Error string + Disabled bool +} + +// TableActionResult is a trading table and its acted row. +type TableActionResult struct { + Element *ui.Element + Table DataTableView + id string +} + +// Acted returns the ID of the row acted on. +func (r TableActionResult) Acted() (string, bool) { return r.id, r.id != "" } + +// PositionTable lists holdings with floating profit and Close. +func PositionTable(c *ui.Context, s *DataTableState[string], rows []PositionRow, opts PositionTableOptions) TableActionResult { + dec := priceDecimals("PositionTable", opts.Decimals) + var r TableActionResult + num := func(id, key string, v func(PositionRow) float64) DataColumn[PositionRow] { + return DataColumn[PositionRow]{ID: id, Title: msg(c, key), Align: ui.End, Sortable: true, + Compare: func(a, b PositionRow) int { return cmp.Compare(v(a), v(b)) }, + Text: func(p PositionRow) string { return statisticFormat(v(p), dec) }} + } + pnl := num("pnl", "position_table.pnl", PositionRow.Unrealized) + pnl.Cell = func(p PositionRow) { tradingSigned(c, p.Unrealized(), statisticSigned(p.Unrealized(), dec)) } + pct := num("pct", "position_table.pnl_percent", PositionRow.UnrealizedPercent) + pct.Cell = func(p PositionRow) { + tradingSigned(c, p.UnrealizedPercent(), statisticSigned(p.UnrealizedPercent(), 2)+"%") + } + cols := []DataColumn[PositionRow]{ + {ID: "symbol", Title: msg(c, "position_table.symbol"), Sortable: true, + Compare: func(a, b PositionRow) int { return cmp.Compare(a.Symbol, b.Symbol) }, + Text: func(p PositionRow) string { return p.Symbol }}, + num("qty", "position_table.quantity", func(p PositionRow) float64 { return p.Quantity }), + num("cost", "position_table.cost", func(p PositionRow) float64 { return p.AvgCost }), + num("price", "position_table.price", func(p PositionRow) float64 { return p.Price }), + num("value", "position_table.value", PositionRow.MarketValue), + pnl, pct, + {ID: "action", Title: msg(c, "position_table.action"), Width: 96, + Text: func(PositionRow) string { return "" }, + Cell: func(p PositionRow) { + if Button(c, msg(c, "position_table.close"), ButtonOptions{Variant: Secondary}).Label(msg(c, "position_table.close") + " " + p.Symbol).Clicked() { + r.id = p.ID + } + }}, + } + r.Element = ui.Column(c).Disabled(opts.Disabled).Grow(1).FillWidth().MinHeight(0) + r.Element.Children(func() { + r.Table = DataTable(c, s, rows, DataTableOptions[PositionRow, string]{Columns: cols, Key: func(p PositionRow) string { return p.ID }, + Version: opts.Version, Status: opts.Status, Error: opts.Error, Empty: msg(c, "position_table.empty")}) + r.Table.Element.Grow(1) + }) + if r.Element.IsDisabled() { + r.id = "" + } + if r.id != "" { + slog.Debug("mujica: position_table close") + } + return r +} + +// tradingSigned shows a signed amount with its arrow. +func tradingSigned(c *ui.Context, v float64, text string) { + sign := trendSign(v) + ui.Row(c).Gap(2).AlignItems(ui.Center).Justify(ui.End).FillWidth().TextColor(trendColor(c, sign)).Children(func() { + ui.Icon(c, trendIcon(sign)).Size(12, 12) + ui.Text(c, text).FontFeatures("tnum").FontWeight(600).SingleLine() + }) +} diff --git a/position_table_test.go b/position_table_test.go new file mode 100644 index 0000000..95e4a40 --- /dev/null +++ b/position_table_test.go @@ -0,0 +1,84 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +func positionSample() []PositionRow { + return []PositionRow{ + {ID: "p1", Symbol: "MUJC", Quantity: 100, AvgCost: 400, Price: 412.08}, + {ID: "p2", Symbol: "AVE", Quantity: 50, AvgCost: 90, Price: 88.2}, + } +} + +func TestPositionTableValuesAndClose(t *testing.T) { + var s DataTableState[string] + rows := positionSample() + closed := "" + tt := tradingTester(GreenUp, 1000, 400, func(c *ui.Context) { + ui.Box(c).Width(960).Height(300).Children(func() { + if id, ok := PositionTable(c, &s, rows, PositionTableOptions{}).Acted(); ok { + closed = id + } + }) + }) + for _, want := range []string{"41,208.00", "+1,208.00", "+3.02%", "−90.00", "−2.00%"} { + if !tt.HasText(want) { + t.Fatalf("missing %q in %q", want, tt.Texts()) + } + } + if err := tt.Click("Close AVE"); err != nil { + t.Fatal(err) + } + if closed != "p2" { + t.Fatalf("closed %q", closed) + } +} + +// Selection follows the row ID when rows reorder and change. +func TestPositionTableStableIDs(t *testing.T) { + var s DataTableState[string] + rows := positionSample() + tt := tradingTester(GreenUp, 1000, 400, func(c *ui.Context) { + ui.Box(c).Width(960).Height(300).Children(func() { PositionTable(c, &s, rows, PositionTableOptions{}) }) + }) + _ = tt.Click("AVE") + rows = []PositionRow{{ID: "p3", Symbol: "OBLV", Quantity: 1, AvgCost: 1, Price: 1}, {ID: "p2", Symbol: "AVE", Quantity: 60, AvgCost: 90, Price: 91}, rows[0]} + tt.Frame() + if id, ok := s.Selected(); !ok || id != "p2" { + t.Fatalf("selection %q %v", id, ok) + } +} + +func TestPositionTableDisabledAndLargeData(t *testing.T) { + var s DataTableState[string] + rows := make([]PositionRow, 100_000) + for i := range rows { + rows[i] = PositionRow{ID: fmt.Sprint(i), Symbol: fmt.Sprintf("S%05d", i), Quantity: 1, AvgCost: 1, Price: 2} + } + closed := false + tt := tradingTester(GreenUp, 1000, 400, func(c *ui.Context) { + ui.Box(c).Width(960).Height(300).Children(func() { + _, closed = PositionTable(c, &s, rows, PositionTableOptions{Disabled: true}).Acted() + }) + }) + _ = tt.Click("Close S00000") + if closed { + t.Fatal("disabled table closed a position") + } + if n := len(tt.Texts()); n > 400 { + t.Fatalf("built %d texts for 100,000 rows", n) + } +} + +func TestPositionTableSnapshot(t *testing.T) { + snapshot(t, "position_table", 1040, 220, func(c *ui.Context) { + ui.Column(c).Padding(16).Height(200).Width(1010).Children(func() { + s := ui.Local(c.Root(), "snap", func() DataTableState[string] { return DataTableState[string]{} }) + PositionTable(c, s, positionSample(), PositionTableOptions{}) + }) + }) +} diff --git a/price_change_badge.go b/price_change_badge.go new file mode 100644 index 0000000..5989747 --- /dev/null +++ b/price_change_badge.go @@ -0,0 +1,37 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// PriceChangeBadgeOptions configure a PriceChangeBadge. +type PriceChangeBadgeOptions struct { + // Decimals of the amount, zero meaning 2; percents show 2. + Decimals int + // HidePercent shows only the amount. + HidePercent bool +} + +// PriceChangeBadge shows a signed change and percent with an arrow. +func PriceChangeBadge(c *ui.Context, change, percent float64, opts PriceChangeBadgeOptions) *ui.Element { + dec := priceDecimals("PriceChangeBadge", opts.Decimals) + sign := trendSign(change) + if sign == 0 { + sign = trendSign(percent) + } + col := trendColor(c, sign) + u := Density(c).Unit() + text := statisticSigned(change, dec) + if !opts.HidePercent { + text += " (" + statisticSigned(percent, 2) + "%)" + } + e := ui.Row(c).Gap(u).AlignItems(ui.Center).Padding(u/2, u*2).Radius(theme.ControlRadius).Shrink(0). + Background(col.Alpha(0.12)).TextColor(col).Role(ui.RoleText).Label(trendWord(c, sign) + " " + text) + e.Children(func() { + ui.Icon(c, trendIcon(sign)).Size(14, 14) + ui.Text(c, text).FontSize(FontSize(c, theme.CaptionSize)).FontFeatures("tnum").FontWeight(600).SingleLine() + }) + return e +} diff --git a/price_change_badge_test.go b/price_change_badge_test.go new file mode 100644 index 0000000..42a6a1d --- /dev/null +++ b/price_change_badge_test.go @@ -0,0 +1,35 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestPriceChangeBadgeSignsAndWords(t *testing.T) { + tt := tradingTester(GreenUp, 400, 160, func(c *ui.Context) { + PriceChangeBadge(c, 1.25, 0.85, PriceChangeBadgeOptions{}) + PriceChangeBadge(c, -3, -1.5, PriceChangeBadgeOptions{Decimals: 1}) + PriceChangeBadge(c, 0, 0, PriceChangeBadgeOptions{HidePercent: true}) + }) + for _, want := range []string{"+1.25 (+0.85%)", "−3.0 (−1.50%)", "0.00"} { + if !tt.HasText(want) { + t.Fatalf("missing %q in %q", want, tt.Texts()) + } + } + for _, name := range []string{"up +1.25 (+0.85%)", "down −3.0 (−1.50%)", "unchanged 0.00"} { + if _, ok := tt.Find(name); !ok { + t.Fatalf("not spoken: %q", name) + } + } +} + +func TestPriceChangeBadgeSnapshot(t *testing.T) { + snapshot(t, "price_change_badge", 360, 80, func(c *ui.Context) { + ui.Row(c).Padding(20).Gap(10).Children(func() { + PriceChangeBadge(c, 1.25, 0.85, PriceChangeBadgeOptions{}) + PriceChangeBadge(c, -3.4, -1.52, PriceChangeBadgeOptions{}) + PriceChangeBadge(c, 0, 0, PriceChangeBadgeOptions{}) + }) + }) +} diff --git a/price_text.go b/price_text.go new file mode 100644 index 0000000..f415a16 --- /dev/null +++ b/price_text.go @@ -0,0 +1,171 @@ +package mujica + +import ( + "fmt" + "log/slog" + "math" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// Trend picks the rise color: green, or red (China). +type Trend int + +const ( + GreenUp Trend = iota + RedUp +) + +type trendKey struct{} + +// UseTrend sets the window's rise and fall colors. +func UseTrend(c *ui.Context, t Trend) { + if t != GreenUp && t != RedUp { + panic(fmt.Sprintf("mujica: unknown Trend %d", t)) + } + *ui.Local(c.Root(), trendKey{}, func() Trend { return GreenUp }) = t +} + +// trendColor colors a rise (sign > 0), fall or flat. +func trendColor(c *ui.Context, sign int) ui.Color { + k := Tokens(c) + up, down := k.Success, k.Danger + if *ui.Local(c.Root(), trendKey{}, func() Trend { return GreenUp }) == RedUp { + up, down = k.Danger, k.Success + } + switch { + case sign > 0: + return up + case sign < 0: + return down + } + return k.TextMuted +} + +// trendIcon is the arrow that says the direction without color. +func trendIcon(sign int) *ui.SVG { + switch { + case sign > 0: + return icons.Must("arrow-up") + case sign < 0: + return icons.Must("arrow-down") + } + return icons.Must("minus") +} + +// trendWord names the direction for assistive technology. +func trendWord(c *ui.Context, sign int) string { + switch { + case sign > 0: + return msg(c, "price_text.up") + case sign < 0: + return msg(c, "price_text.down") + } + return msg(c, "price_text.flat") +} + +func trendSign(v float64) int { + switch { + case v > 0: + return 1 + case v < 0: + return -1 + } + return 0 +} + +// priceDecimals resolves a Decimals option: zero means 2, negative panics. +func priceDecimals(name string, d int) int { + if d < 0 { + panic("mujica: " + name + " with negative Decimals") + } + if d == 0 { + return 2 + } + return d +} + +// priceTextFlash is the tint's fade, three state steps long. +const priceTextFlash = 3 * theme.StateDuration + +// PriceTextOptions configure a PriceText. +type PriceTextOptions struct { + // Decimals shown; zero means 2. + Decimals int + // NoGrouping drops the thousands separators. + NoGrouping bool + // Compare marks the price's move from Reference. + Compare bool + Reference float64 + // NoFlash keeps the price still when it changes. + NoFlash bool + // Size is the font size; zero is the body size. + Size float32 +} + +type priceTextState struct { + last float64 + seen bool + at time.Time + dir int +} + +// PriceText shows a price; a change tints it once. +func PriceText(c *ui.Context, value float64, opts PriceTextOptions) *ui.Element { + dec := priceDecimals("PriceText", opts.Decimals) + if opts.Size < 0 { + panic("mujica: PriceText with negative Size") + } + size := opts.Size + if size == 0 { + size = theme.BodySize + } + text := statisticFormat(value, dec) + if opts.NoGrouping { + text = priceUngrouped(value, dec) + } + e := ui.Row(c).Gap(Density(c).Unit()).AlignItems(ui.Center).Padding(0, 2).Radius(theme.ControlRadius).Shrink(0) + st := ui.Local(e, "price", func() priceTextState { return priceTextState{} }) + if st.seen && value != st.last { + st.at, st.dir = c.Now(), trendSign(value-st.last) + slog.Debug("mujica: price_text changed", "dir", st.dir) + } + st.last, st.seen = value, true + sign := 0 + if opts.Compare { + sign = trendSign(value - opts.Reference) + } + col := Tokens(c).Text + spoken := text + if opts.Compare { + col = trendColor(c, sign) + spoken += ", " + trendWord(c, sign) + } + if d := Motion(c, priceTextFlash); d > 0 && !opts.NoFlash && !st.at.IsZero() { + if t := c.Now().Sub(st.at); t < d { + e.Background(trendColor(c, st.dir).Alpha(0.2 * float32(1-float64(t)/float64(d)))) + c.AnimationFrame() + } + } + e.Role(ui.RoleText).Label(spoken).TextColor(col) + e.Children(func() { + if opts.Compare { + ui.Icon(c, trendIcon(sign)).Size(size*0.85, size*0.85) + } + ui.Text(c, text).FontSize(FontSize(c, size)).FontFeatures("tnum").FontWeight(500).SingleLine() + }) + return e +} + +// priceUngrouped writes v with dec decimals and no separators. +func priceUngrouped(v float64, dec int) string { + s := fmt.Sprintf("%.*f", dec, math.Abs(v)) + if v < 0 && s != fmt.Sprintf("%.*f", dec, 0.0) { + return "−" + s + } + return s +} diff --git a/price_text_test.go b/price_text_test.go new file mode 100644 index 0000000..bb21a2c --- /dev/null +++ b/price_text_test.go @@ -0,0 +1,106 @@ +package mujica + +import ( + "bytes" + "testing" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// tradingTester runs view in the default theme with trend t. +func tradingTester(t Trend, w, h int, view func(c *ui.Context)) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + UseTrend(c, t) + ui.Column(c).Padding(10).AlignItems(ui.Start).Children(func() { view(c) }) + }, w, h) +} + +func TestPriceTextFormatAndTrend(t *testing.T) { + price := 12345.678 + tt := tradingTester(GreenUp, 300, 100, func(c *ui.Context) { + PriceText(c, price, PriceTextOptions{Decimals: 2, Compare: true, Reference: 12000}) + }) + if !tt.HasText("12,345.68") { + t.Fatalf("texts %q", tt.Texts()) + } + if _, ok := tt.Find("12,345.68, up"); !ok { + t.Fatal("trend not spoken") + } + price = 11000 + tt.Frame() + if _, ok := tt.Find("11,000.00, down"); !ok { + t.Fatalf("down not spoken: %q", tt.Texts()) + } + tt = tradingTester(GreenUp, 300, 100, func(c *ui.Context) { + PriceText(c, 1234.5, PriceTextOptions{Decimals: 3, NoGrouping: true}) + }) + if !tt.HasText("1234.500") { + t.Fatalf("ungrouped %q", tt.Texts()) + } +} + +func TestTrendColorsFollowUseTrend(t *testing.T) { + var up, down [2]ui.Color + for i, tr := range []Trend{GreenUp, RedUp} { + tradingTester(tr, 100, 100, func(c *ui.Context) { + up[i], down[i] = trendColor(c, 1), trendColor(c, -1) + }) + } + k := theme.Light() + if up[0] != k.Success || down[0] != k.Danger || up[1] != k.Danger || down[1] != k.Success { + t.Fatalf("up %v down %v", up, down) + } + defer func() { + if recover() == nil { + t.Fatal("unknown trend accepted") + } + }() + tradingTester(Trend(7), 100, 100, func(*ui.Context) {}) +} + +// A change tints once; reduced motion never tints. +func TestPriceTextFlashesOnceAndNotUnderReducedMotion(t *testing.T) { + for _, still := range []bool{false, true} { + prefs := ui.Preferences{ReduceMotion: still, TextScale: 1} + price := 10.0 + tt := tradingTester(GreenUp, 200, 60, func(c *ui.Context) { PriceText(c, price, PriceTextOptions{}) }) + tt.SetPreferences(prefs) + price = 10.5 + tt.Frame() + fresh := tradingTester(GreenUp, 200, 60, func(c *ui.Context) { PriceText(c, price, PriceTextOptions{}) }) + fresh.SetPreferences(prefs) + fresh.Frame() + same := bytes.Equal(tt.Image().Pix, fresh.Image().Pix) + if same == !still { + t.Fatalf("reduced motion %v: flashed %v", still, !same) + } + time.Sleep(priceTextFlash + 20*time.Millisecond) + tt.Frame() + if !bytes.Equal(tt.Image().Pix, fresh.Image().Pix) { + t.Fatalf("reduced motion %v: flash did not end", still) + } + } +} + +func TestPriceTextRejectsNegativeDecimals(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("negative decimals accepted") + } + }() + tradingTester(GreenUp, 100, 100, func(c *ui.Context) { PriceText(c, 1, PriceTextOptions{Decimals: -1}) }) +} + +func TestPriceTextSnapshot(t *testing.T) { + snapshot(t, "price_text", 320, 150, func(c *ui.Context) { + ui.Column(c).Padding(20).Gap(12).AlignItems(ui.Start).Children(func() { + PriceText(c, 18234.5, PriceTextOptions{Size: theme.H2Size, Compare: true, Reference: 18000}) + PriceText(c, 0.004521, PriceTextOptions{Decimals: 6, Compare: true, Reference: 0.0046}) + PriceText(c, 100, PriceTextOptions{Compare: true, Reference: 100}) + }) + }) +} diff --git a/quick_trade_buttons.go b/quick_trade_buttons.go new file mode 100644 index 0000000..d0926c1 --- /dev/null +++ b/quick_trade_buttons.go @@ -0,0 +1,127 @@ +package mujica + +import ( + "fmt" + "log/slog" + "slices" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// QuickTradeButtonsOptions configure QuickTradeButtons. Symbol is required. +type QuickTradeButtonsOptions struct { + Symbol string + // Presets are the quantities offered; nil means 1, 10, 100. + Presets []float64 + // Decimals of the quantities shown. + Decimals int + // Confirm asks before sending, by the button pressed. + Confirm bool + Disabled bool +} + +// QuickTradeResult is built QuickTradeButtons and their trade. +type QuickTradeResult struct { + Element *ui.Element + side OrderSide + quantity float64 +} + +// Traded returns the side and quantity the user traded. +func (r QuickTradeResult) Traded() (OrderSide, float64, bool) { return r.side, r.quantity, r.side != 0 } + +type quickTradeState struct{ asking OrderSide } + +// QuickTradeButtons trade *quantity at market with one press. +func QuickTradeButtons(c *ui.Context, quantity *float64, opts QuickTradeButtonsOptions) QuickTradeResult { + if opts.Symbol == "" { + panic("mujica: QuickTradeButtons needs a Symbol") + } + if opts.Decimals < 0 { + panic("mujica: QuickTradeButtons with negative Decimals") + } + presets := opts.Presets + if presets == nil { + presets = []float64{1, 10, 100} + } + if *quantity == 0 { + *quantity = presets[0] + } + at := slices.Index(presets, *quantity) + if at < 0 { + panic(fmt.Sprintf("mujica: QuickTradeButtons quantity %v is not one of Presets", *quantity)) + } + u := Density(c).Unit() + var r QuickTradeResult + r.Element = ui.Column(c).Gap(u * 2).Disabled(opts.Disabled).Role(ui.RoleGroup).Label(msg(c, "quick_trade_buttons.label")) + st := ui.Local(r.Element, "quick", func() quickTradeState { return quickTradeState{} }) + disabled := r.Element.IsDisabled() + if disabled { + st.asking = 0 + } + qty := statisticFormat(*quantity, opts.Decimals) + r.Element.Children(func() { + var segs []Segment + for _, p := range presets { + segs = append(segs, Segment{Label: statisticFormat(p, opts.Decimals)}) + } + if SegmentedControl(c, &at, segs, SegmentedControlOptions{Equal: true, Label: msg(c, "quick_trade_buttons.quantity"), Disabled: disabled}).Changed() { + *quantity = presets[at] + qty = statisticFormat(*quantity, opts.Decimals) + } + ui.Row(c).Gap(u * 2).Children(func() { + for _, side := range []OrderSide{SideBuy, SideSell} { + label := fmt.Sprintf(msg(c, fmt.Sprintf("quick_trade_buttons.side%d", side)), qty) + b := quickTradeButton(c, label, side) + if b.Clicked() && !disabled { + if opts.Confirm { + st.asking = side + } else { + r.side, r.quantity = side, *quantity + } + } + open := st.asking == side + res := Popconfirm(c, b, &open, PopconfirmOptions{ + Title: fmt.Sprintf(msg(c, fmt.Sprintf("quick_trade_buttons.confirm%d", side)), qty, opts.Symbol), + Description: msg(c, "quick_trade_buttons.market"), + ConfirmLabel: msg(c, fmt.Sprintf("order_entry.side%d", side)), + Danger: true, + }) + if res.Confirmed && !disabled { + r.side, r.quantity = side, *quantity + } + if !open && st.asking == side { + st.asking = 0 + } + } + }) + }) + if r.side != 0 { + slog.Debug("mujica: quick_trade_buttons traded", "side", r.side) + } + return r +} + +// quickTradeButton is a large button tinted by its side. +func quickTradeButton(c *ui.Context, label string, side OrderSide) *ui.Element { + k := Tokens(c) + d := Density(c) + col := trendColor(c, side.sign()) + b := ui.ButtonBase(c).Grow(1).Basis(0).MinHeight(d.ControlHeight()+d.Unit()*2).Radius(theme.ControlRadius). + Border(theme.BorderWidth*1.5, col).TextColor(col).Background(col.Alpha(0.1)).Label(label) + internal.Ring(b, k.Focus, theme.ControlRadius) + switch { + case b.Pressed(): + b.Background(col.Alpha(0.28)) + case b.Hovered(): + b.Background(col.Alpha(0.18)) + } + b.Children(func() { + ui.Icon(c, trendIcon(side.sign())).Size(16, 16) + ui.Text(c, label).FontWeight(700).SingleLine() + }) + return b +} diff --git a/quick_trade_buttons_test.go b/quick_trade_buttons_test.go new file mode 100644 index 0000000..c764999 --- /dev/null +++ b/quick_trade_buttons_test.go @@ -0,0 +1,86 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +type quickTradeProbe struct { + qty float64 + opts QuickTradeButtonsOptions + trades []OrderSide + sizes []float64 +} + +func (p *quickTradeProbe) tester() *ui.Tester { + return tradingTester(GreenUp, 520, 400, func(c *ui.Context) { + ui.Box(c).Width(400).Children(func() { + if side, q, ok := QuickTradeButtons(c, &p.qty, p.opts).Traded(); ok { + p.trades, p.sizes = append(p.trades, side), append(p.sizes, q) + } + }) + }) +} + +func TestQuickTradeButtonsPresetsAndTrade(t *testing.T) { + p := &quickTradeProbe{opts: QuickTradeButtonsOptions{Symbol: "MUJC"}} + tt := p.tester() + if p.qty != 1 { + t.Fatalf("default preset %v", p.qty) + } + if err := tt.Click("10"); err != nil { + t.Fatal(err) + } + if err := tt.Click("Sell 10"); err != nil { + t.Fatal(err) + } + if len(p.trades) != 1 || p.trades[0] != SideSell || p.sizes[0] != 10 { + t.Fatalf("trades %v %v", p.trades, p.sizes) + } +} + +func TestQuickTradeButtonsConfirmFocusesCancel(t *testing.T) { + p := &quickTradeProbe{qty: 100, opts: QuickTradeButtonsOptions{Symbol: "MUJC", Confirm: true}} + tt := p.tester() + _ = tt.Click("Buy 100") + if len(p.trades) != 0 || !tt.HasText("Buy 100 MUJC?") || !tt.Focused("Cancel") { + t.Fatalf("confirm: %q", tt.Texts()) + } + tt.Key(0, ui.KeyEnter) + if len(p.trades) != 0 || tt.HasText("Buy 100 MUJC?") { + t.Fatal("Enter traded instead of canceling") + } + _ = tt.Click("Buy 100") + if err := tt.Click("Buy"); err != nil { + t.Fatal(err) + } + if len(p.trades) != 1 || p.trades[0] != SideBuy || p.sizes[0] != 100 { + t.Fatalf("trades %v", p.trades) + } +} + +func TestQuickTradeButtonsDisabledAndBadQuantity(t *testing.T) { + p := &quickTradeProbe{opts: QuickTradeButtonsOptions{Symbol: "MUJC", Disabled: true}} + tt := p.tester() + _ = tt.Click("Buy 1") + _ = tt.Click("10") + if len(p.trades) != 0 || p.qty != 1 { + t.Fatal("disabled buttons acted") + } + defer func() { + if recover() == nil { + t.Fatal("quantity outside presets accepted") + } + }() + (&quickTradeProbe{qty: 7, opts: QuickTradeButtonsOptions{Symbol: "MUJC"}}).tester() +} + +func TestQuickTradeButtonsSnapshot(t *testing.T) { + qty := 10.0 + snapshot(t, "quick_trade_buttons", 380, 130, func(c *ui.Context) { + ui.Column(c).Padding(20).Children(func() { + QuickTradeButtons(c, &qty, QuickTradeButtonsOptions{Symbol: "MUJC"}) + }) + }) +} diff --git a/quote_card.go b/quote_card.go new file mode 100644 index 0000000..a35e886 --- /dev/null +++ b/quote_card.go @@ -0,0 +1,52 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// Quote is an instrument's price and change since the close. +type Quote struct { + Symbol, Name string + Price float64 + Change float64 + ChangePercent float64 +} + +// QuoteCardOptions configure a QuoteCard. +type QuoteCardOptions struct { + // Decimals of the price and change; zero means 2. + Decimals int + // Chart builds the mini chart slot; nil leaves it out. + Chart func() +} + +// QuoteCard shows a symbol, name, price, change and mini chart. +func QuoteCard(c *ui.Context, q Quote, opts QuoteCardOptions) *ui.Element { + if q.Symbol == "" { + panic("mujica: QuoteCard needs a Symbol") + } + dec := priceDecimals("QuoteCard", opts.Decimals) + k := Tokens(c) + u := Density(c).Unit() + e := ui.Column(c).Gap(u*2).Padding(u*4).MinWidth(200).Radius(theme.CardRadius). + Background(k.Surface).Border(theme.BorderWidth, k.Border).Role(ui.RoleGroup).Label(q.Symbol) + e.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.End).Children(func() { + ui.Text(c, q.Symbol).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).FontWeight(600).SingleLine() + if q.Name != "" { + ui.Text(c, q.Name).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)).SingleLine(). + Ellipsis("…").MinWidth(0).Shrink(1) + } + }) + ui.Row(c).Gap(u * 3).AlignItems(ui.Center).Wrap().Children(func() { + PriceText(c, q.Price, PriceTextOptions{Decimals: dec, Size: theme.H2Size}) + PriceChangeBadge(c, q.Change, q.ChangePercent, PriceChangeBadgeOptions{Decimals: dec}) + }) + if opts.Chart != nil { + ui.Box(c).Height(40).FillWidth().Children(opts.Chart) + } + }) + return e +} diff --git a/quote_card_test.go b/quote_card_test.go new file mode 100644 index 0000000..6d53d20 --- /dev/null +++ b/quote_card_test.go @@ -0,0 +1,43 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestQuoteCardShowsQuoteAndChartSlot(t *testing.T) { + charted := false + tt := tradingTester(RedUp, 400, 240, func(c *ui.Context) { + QuoteCard(c, Quote{Symbol: "600519", Name: "Kweichow Moutai", Price: 1688.5, Change: 12.3, ChangePercent: 0.73}, + QuoteCardOptions{Chart: func() { charted = true; ui.Text(c, "chart") }}) + }) + for _, want := range []string{"600519", "Kweichow Moutai", "1,688.50", "+12.30 (+0.73%)", "chart"} { + if !tt.HasText(want) { + t.Fatalf("missing %q in %q", want, tt.Texts()) + } + } + if !charted { + t.Fatal("chart slot not built") + } + defer func() { + if recover() == nil { + t.Fatal("empty symbol accepted") + } + }() + tradingTester(GreenUp, 100, 100, func(c *ui.Context) { QuoteCard(c, Quote{}, QuoteCardOptions{}) }) +} + +func TestQuoteCardSnapshot(t *testing.T) { + snapshot(t, "quote_card", 300, 190, func(c *ui.Context) { + ui.Column(c).Padding(20).AlignItems(ui.Start).Children(func() { + QuoteCard(c, Quote{Symbol: "MUJC", Name: "Ave Mujica Holdings", Price: 412.08, Change: -5.62, ChangePercent: -1.35}, + QuoteCardOptions{Chart: func() { + k := Tokens(c) + ui.Box(c).Fill().Draw(func(p *ui.Painter, r ui.Rect) { + p.Line(r.X, r.Y+r.H*0.3, r.X+r.W, r.Y+r.H*0.7, 1.5, k.Info) + }) + }}) + }) + }) +} diff --git a/risk_meter.go b/risk_meter.go new file mode 100644 index 0000000..d0a5685 --- /dev/null +++ b/risk_meter.go @@ -0,0 +1,84 @@ +package mujica + +import ( + "fmt" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// RiskLevel is one step of a RiskMeter's scale. +type RiskLevel struct { + Label string + Description string +} + +// RiskMeterOptions configure a RiskMeter. +type RiskMeterOptions struct { + // Levels rise in risk; nil uses five built-in levels. + Levels []RiskLevel + // Label names the meter; empty uses the built-in "Risk level". + Label string +} + +// RiskMeter shows level, from 1, on a named graded scale. +func RiskMeter(c *ui.Context, level int, opts RiskMeterOptions) *ui.Element { + levels := opts.Levels + if levels == nil { + for i := range 5 { + levels = append(levels, RiskLevel{Label: msg(c, fmt.Sprintf("risk_meter.level%d", i+1))}) + } + } + if len(levels) < 2 || level < 1 || level > len(levels) { + panic(fmt.Sprintf("mujica: RiskMeter level %d outside 1..%d", level, len(levels))) + } + k := Tokens(c) + u := Density(c).Unit() + label := opts.Label + if label == "" { + label = msg(c, "risk_meter.label") + } + cur := levels[level-1] + spoken := fmt.Sprintf(msg(c, "risk_meter.value"), level, len(levels), cur.Label) + col := riskMeterColor(k, level, len(levels)) + e := ui.Column(c).Gap(u * 2).MinWidth(200).Role(ui.RoleMeter).Label(label).Description(spoken + " " + cur.Description) + e.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, cur.Label).TextColor(col).FontWeight(600).SingleLine() + ui.Text(c, fmt.Sprintf("%d / %d", level, len(levels))).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)).FontFeatures("tnum") + }) + ui.Box(c).Height(18).FillWidth().Draw(func(p *ui.Painter, r ui.Rect) { + n := len(levels) + const gap = 3 + w := (r.W - gap*float32(n-1)) / float32(n) + for i := range n { + seg := ui.Rect{X: r.X + float32(i)*(w+gap), Y: r.Y + 8, W: w, H: 8} + if i < level { + p.Fill(seg, riskMeterColor(k, i+1, n), theme.ControlRadius) + } else { + p.Stroke(seg, k.ControlBorder, theme.ControlRadius, theme.BorderWidth) + } + if i == level-1 { + p.FillPath(internal.Diamond(seg.X+seg.W/2, r.Y+3, 7), k.Text) + } + } + }) + if cur.Description != "" { + ui.Text(c, cur.Description).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)) + } + }) + return e +} + +// riskMeterColor grades from success through warning to danger. +func riskMeterColor(k theme.Tokens, level, n int) ui.Color { + switch f := float64(level-1) / float64(n-1); { + case f < 0.34: + return k.Success + case f < 0.67: + return k.Warning + } + return k.Danger +} diff --git a/risk_meter_test.go b/risk_meter_test.go new file mode 100644 index 0000000..83058ed --- /dev/null +++ b/risk_meter_test.go @@ -0,0 +1,42 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestRiskMeterLevelsAndText(t *testing.T) { + level := 4 + levels := []RiskLevel{{Label: "Conservative", Description: "Capital first."}, {Label: "Balanced"}, {Label: "Aggressive", Description: "Losses can exceed half."}} + custom := false + tt := tradingTester(GreenUp, 400, 160, func(c *ui.Context) { + if custom { + RiskMeter(c, level, RiskMeterOptions{Levels: levels}) + } else { + RiskMeter(c, level, RiskMeterOptions{}) + } + }) + if !tt.HasText("Moderately high") || !tt.HasText("4 / 5") { + t.Fatalf("default: %q", tt.Texts()) + } + custom, level = true, 3 + tt.Frame() + if !tt.HasText("Aggressive") || !tt.HasText("Losses can exceed half.") || !tt.HasText("3 / 3") { + t.Fatalf("custom: %q", tt.Texts()) + } + defer func() { + if recover() == nil { + t.Fatal("level 0 accepted") + } + }() + tradingTester(GreenUp, 100, 100, func(c *ui.Context) { RiskMeter(c, 0, RiskMeterOptions{}) }) +} + +func TestRiskMeterSnapshot(t *testing.T) { + snapshot(t, "risk_meter", 320, 110, func(c *ui.Context) { + ui.Column(c).Padding(20).Children(func() { + RiskMeter(c, 4, RiskMeterOptions{Levels: []RiskLevel{{Label: "Low"}, {Label: "Medium"}, {Label: "Elevated"}, {Label: "High", Description: "Suited to experienced traders."}, {Label: "Extreme"}}}) + }) + }) +} diff --git a/spread_indicator.go b/spread_indicator.go new file mode 100644 index 0000000..be7c7fa --- /dev/null +++ b/spread_indicator.go @@ -0,0 +1,53 @@ +package mujica + +import ( + "fmt" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// SpreadIndicatorOptions configure a SpreadIndicator. +type SpreadIndicatorOptions struct { + // Decimals of the spread; zero means 2. + Decimals int + // WarnPercent flags spreads this wide, in percent; zero never. + WarnPercent float64 +} + +// SpreadIndicator shows ask minus bid and its percent. +func SpreadIndicator(c *ui.Context, bid, ask float64, opts SpreadIndicatorOptions) *ui.Element { + if opts.WarnPercent < 0 { + panic("mujica: SpreadIndicator with negative WarnPercent") + } + dec := priceDecimals("SpreadIndicator", opts.Decimals) + k := Tokens(c) + u := Density(c).Unit() + spread := ask - bid + pct := 0.0 + if mid := (ask + bid) / 2; mid > 0 { + pct = spread / mid * 100 + } + text := fmt.Sprintf(msg(c, "spread_indicator.value"), statisticFormat(spread, dec), statisticFormat(pct, 3)) + note, col, icon := "", k.TextMuted, "" + switch { + case spread < 0: + note, col, icon = msg(c, "spread_indicator.crossed"), k.Danger, "circle-alert" + case opts.WarnPercent > 0 && pct >= opts.WarnPercent: + note, col, icon = msg(c, "spread_indicator.wide"), k.Warning, "triangle-alert" + } + e := ui.Row(c).Gap(u * 1.5).AlignItems(ui.Center).Shrink(0).Role(ui.RoleStatus).Label(text + " " + note) + e.Children(func() { + ui.Text(c, msg(c, "spread_indicator.title")).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)) + ui.Text(c, text).FontFeatures("tnum").FontWeight(500).SingleLine() + if note != "" { + ui.Row(c).Gap(u / 2).AlignItems(ui.Center).TextColor(col).Children(func() { + ui.Icon(c, icons.Must(icon)).Size(14, 14) + ui.Text(c, note).FontSize(FontSize(c, theme.CaptionSize)).FontWeight(600).SingleLine() + }) + } + }) + return e +} diff --git a/spread_indicator_test.go b/spread_indicator_test.go new file mode 100644 index 0000000..c9835e4 --- /dev/null +++ b/spread_indicator_test.go @@ -0,0 +1,42 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestSpreadIndicatorValueAndThreshold(t *testing.T) { + bid, ask := 99.95, 100.05 + tt := tradingTester(GreenUp, 400, 100, func(c *ui.Context) { + SpreadIndicator(c, bid, ask, SpreadIndicatorOptions{WarnPercent: 0.5}) + }) + if !tt.HasText("0.10 (0.100%)") || tt.HasText("Wide spread") { + t.Fatalf("narrow: %q", tt.Texts()) + } + ask = 101 + tt.Frame() + if !tt.HasText("Wide spread") { + t.Fatalf("wide: %q", tt.Texts()) + } + ask = 99 + tt.Frame() + if !tt.HasText("Crossed market") { + t.Fatalf("crossed: %q", tt.Texts()) + } + defer func() { + if recover() == nil { + t.Fatal("negative threshold accepted") + } + }() + tradingTester(GreenUp, 100, 100, func(c *ui.Context) { SpreadIndicator(c, 1, 2, SpreadIndicatorOptions{WarnPercent: -1}) }) +} + +func TestSpreadIndicatorSnapshot(t *testing.T) { + snapshot(t, "spread_indicator", 380, 100, func(c *ui.Context) { + ui.Column(c).Padding(20).Gap(10).Children(func() { + SpreadIndicator(c, 99.95, 100.05, SpreadIndicatorOptions{WarnPercent: 0.5}) + SpreadIndicator(c, 99, 101, SpreadIndicatorOptions{WarnPercent: 0.5}) + }) + }) +} diff --git a/testdata/snapshots/darwin/bid_ask_bar-dark.png b/testdata/snapshots/darwin/bid_ask_bar-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..16712d6a5f1b634a9b33ef673904c99d118f2e4f GIT binary patch literal 5801 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/bid_ask_bar-light.png b/testdata/snapshots/darwin/bid_ask_bar-light.png new file mode 100644 index 0000000000000000000000000000000000000000..a2c9c789743b54bfc8ecc56440558a1c6dd63f30 GIT binary patch literal 5715 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 CLVAS& literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/depth_ladder-dark.png b/testdata/snapshots/darwin/depth_ladder-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a4c3a5b919fcb8146b27b60a626c3f2e070bfc5f GIT binary patch literal 11744 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 E20=PHy8r+H literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/level2_quotes-dark.png b/testdata/snapshots/darwin/level2_quotes-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..021ce64404b50535adcaccfb8ac758d73a56c150 GIT binary patch literal 15272 zcmeIZ1yEdFlrEY8A&ocg?!i5HXxtjtAi>?;LueqlL-0W31a}Ya5ZocSyZh^Z=GCoR z_s&$^S8rYf=#OIGS?yUp*@ogo_}F~?lT`Ip0X!3f^Vtw|ma#f8PZM6QK3=rFkzuZmJxzlWGeiBDNrV^5D+UCG4+} zh&}Hgkp0nMzPUZWvAtLMpuxgc5fh`;)u^q7f1>84b2yhl@!j9gCnh?qq{2bHwA85u z+GSkT3L*1$al}xeS(sU4qxtxq;`?H=!1Bv@SPIj4g7j&%`O2w#D&IH@9nJI?Zp|6d zjwIViUHs5qBC_S-^xc9YP2$hbx-6n&=;;2wf!OK#OViVn5NiuBA0()>1S-KF>Czbu zP0e+8`b9G~=5G|ftwKJohao^~OWPj1M@S%sK|8y4|Ku7gBImQAJ~~|NUmsdsg&-|+@A6pN?mj_U1%dh zCR9W&0%dYPs*T5D1nnhYtY!0g6kInHsJDr@m8%wm08S(%(WI+{1O#91%k&#P&CaW5 z?j~-O9KXbP)tCd`J#BUOvl_MpjyO5HKABGVyxm|O$oQ49Y$r-{=-SMioxdUpgtQPV zK__PUxc?eR2akSX4UftuB~*+vRXqr1!5^!e@3=npqV^8?Ll3}Z*m9t?E4H()g$Z8J zK~yDVM3vqt0hr<8^Yf&*m+~hg%l#4ir!Jx3qG{RK?0#O+aDz8bpAZ+j?*3K8gmZt6 zgtFFbsr*>hXEZd^ETxT|Rqv$wcI}w;#9Bn$>s@e|p!-sscuO0#X^oCg{mW}ll@oS< zUsO!gK0cAE9#xed>HGIL+Rqd5nB84!6$R_t$59dQPmj^a5zvt+0dSP+50%>Sj|i#Q z{BG(U^OcL?2cHYe1wJ|n^@{i!u0x4$?P7HM1wV0H-7|+%1qk}-mnq*PJiNcc@OI>p zU;0(W(G?T&G&qudYkm^c&!iRLwXwxNtRyB@HE4=V%=!1S?lm*c>-AZZ=>jFZuO|i- z74@Uv4jjmGCY-iAG?d=2!{K;0ec7}1uF*1I_4-UDR4+v#;JJ>UtI(R8NE&_jB`EYY zF)?k)a+*3qw_@>CsJM5`FlP860&~L6HQBxE0;1LBt7D-5&D4L*v@Pd78be=q= zd5J0W>@7dKPT9Y@K4nJa7InY(NKDZf@wQO8c!35X-jHI8UhJJ`6BDNk46@pknk%L+ zb1^vXw!^=V$!69nHqH&E$35R2bx@9ux~=q@0?A$MMP-fib6rNklU zGTyGnK$W5n%01H+>=~8+eS1A1l%3_aj(4KN zRyn+iK!Xyf--vRm-DdG;dP*c~ZR~9;a*FF)TB0`kA8YiTn z=K-1(0U57bXK@J@$$yW5nLOWwM*_dpY23BO;SNfiue&wRFphb zq1~^4_1ib9Fo`th4OB6pm@u5cILr{H&b_PR(hg?JW$L9BdP;ML*JQpPLPrWf-ICT^ z5S5>|AQuypVE;_OM&K-){M~xs;!u_(_mZ)jYXqerApN zbHP-H-Zb%5qtR$qkTiPsM>7!#N?}7Wfb90gT3Mx`P%s%PVv_qIIA2#^^}|X#)4klH zVmu9Fyk4C>v^p1ytyW2nNyFiE{-JkpGugw6WnIw4D;hj1pr3Z1pwQHO5EuD^AozP~ zxDOz@nD$1=J4N3+)#{k*nT;RW*5i8z`8UCn4Z;k-=rbmNu^JdG{q@ zP+eVb(#u`v^F8gg+(Rbnd)_7S-`V_TSV5hQKBBiCOae2)T_+pmw!AG7*$h;+XGyi` zfE@kDeVb+uXzn@IV_to3bN$AGueMi4QK9TQInvtb>$J=9C}-l90hu(l6$ zw@yAhCBp~GSo$DXDKVd(g-D~dWx0P=DIg)^=eBix9h_QClF55{$?fVgZUqkFZeO*q z2E>_Je83rhDNAG;f>If}IXl~0RxXVOB~Mz{vF+6(udUdPMKa21Y)35-Hd^csY=tj2 zH)HIK%eJK@U$R%^sXt6V^}ik+j(Ua(LyI(-N@nhkbb3G!Y`$JmZuk@s9G(M_A{)M( zLa7QHn?!>%g4;dvs@RZ9RMC#@pXp6uKmi{%Y&OV2Y#RUbHKxisJvd7(k#XPSHPa+z z0lcA=E$I9akdr-@(UJ1_ra_P#vbiZm9Etdz_jAQuX{k*XxreV#yWr3lkw+Jm9g{Xq z3lj+O>>kg(_tt;8R{Hd1y({v zmkL^W{U`4@925w&G|QL${+?}i<)Yum)aeslY6WVe9iozE~N;uyz zQzli3>+aGl(@QfvGhOjMq@9+p8jim?!f$NBI9RiQwdQt>Ry;Q;urCcwPjF||uJ=9J zh*1M)r}NlV2ZXLLTa~JFJ{njj+>q1^& zApdxCWU9wAiT=s+Pmp@oQ>e}#9w|(jJ*qeW0^faSHqNo1Ba%@x?86YfIJy4G}7F!FE%Q@GHy)Wla{2GVqP;Jl5<$ z?pG`im7<>%5fpItO2zpznvX~J*G)KOixu^Yv-P@lv$LAynx%E++BxNaS#zmWF~1$j zYRAVym?1Q$#PL-!c8l~qlQ&PHF%HgSZG7+vT(2W-7BADqGekK>92_Dc;C?nO_@`&Y z%lF71O2a6#NjNPO$#JlrG;UUjduiK5z41}@`qO#&3A@>&G=0vk*Vi|jP(y-*Gr>LC zz{T1{#A1j7ResEG?7-7Q{GN59NGUPs00@vRY|h??fJTvU#>|9|gbAAJKJS*JOqdFZ z>B=-VYPf~FVr|rmVXOE5Ikmsjde&^EI_;}J8CnwwqI7ulTp3|3&a8-?u*8W-CqQqz zM-a+yfm-aG9F*9qRq2eJD@js7K9t&!O$-dVo6nt3^KlvP=G_IqyF>3n$z>%MD%C7u z4mB^!+T9r*T=L)39lIY69YZ7H%jm}#(dJqk%Q`t4vo66*%4mtkxL%_Cq@=9vSyQH% zRCnYS66E(e{h;?g6)|XiM5k5zJUw$wF`aY&7&k(wsU;MZa9)(*%hJtj2@etEkHu&A zUw#$~1xj-}+nJ+3lA?i&)z^p8k@kx6;Sr?x{5$?`QBi2LbjTIj$ug#GEnm;y2 z{NC+%`{#B6|Dt0|G*iHLdhhp(;keI29Qe|>im9gyI%j0{CtN;=J8dOpNyOR7C|f8= zl#;yr zyxZEvXjY%L`4mTYIC-HHcQy;(4FWsA{O&(}vU_M!bL<{X;o>%ObwucZ>TBsbULKub zcMz+}ZIz3V$q~N%g{poKy%@|wa-n|=UMFPzRU}+*Whm_vx((D;QYf1k$!s`FK(nb% z?g&hw9>g84o;6_WVnUMK=xfky?=YQ^XR5(FaBW`B9`mo?W>TYF4ddA>gVZCp9{L^M#FrJ<>ylclm9^jm@d)R%+lQNl_~I;AZJbPqhT)&iyxVt8fpO9yB~5b?YU$d%$rm9qI(omN3~lB49W<5O zQ}auf)v(%Pu6j_d3;rDGEWSCd;l|IVq;CIZ?c}2Ui!cXo`u-Y50G%+exvlMp_T_V% zoZl{3Cwr*caH+ncX4lL-kETzJVe97R=9|3MYs={y%%gW-Ncdt-+B<^d259gdJc=uI z3TK{kfFUYY>Sc1`t-Ne+i3F}LlBLz3wE=BT1vybNi-c&Rw^=Ulpj{HTtOY@!7Z@2hc!_eh4R(ObaEN z88Ewt8n7LxS|Z=j>l%)6A_pJ!I40KBAE1RuH@u-bl7f8smm{D@Mw5j2JMh1Z&ML$q z>cpRovERIT3i!FW2uc=%(RDEMVccFlS9jdz2Dq-Omp$_A?VGP_ffJU~^)|$5#KcSK zNaUu3Fj~k?Hv7qgtPB0`!}M#V0s;RXz0yg@n9mCWmjXCq2Tbi_F=EI~<)I&Fk)abZ z63oHPgbAA)qO~10#PU$}{n}^FjfB`u{)N!F#RrATXQ2xQ=~ld&-=s0!4F0rTV7 z$b6uYcaT`FI#&A{hTFT*SzdvUiJK!hLwO;gmx;rsk~bJ9yF2B7ik511yU_L+J%zHJ zR7^nP?~BwAW;MMGhdJ?iBShJI1_xEjmG`c_yX-;|piq>EVp|((k~a7ulbc6TBO8;= zqpkUAs{M!YW2E`4azYye)5=U`dWmlj@P{5lJy^pzm&4$#cQX291C3n+S`rqoPLD%t!2Odpf!U%`F-n z#_`3(UJ6bf2Sx=i4~TVoJe7#pL1M~9(kZn&br*1SHYJFX zDOUzY8@x#}zLfLbs4?kJkj*Qjcj4RF`7sqLv6y)O)EFCBaMeU_`=iYbs#jJ`auAXV zrB2DqQ(?Tr)UupLsp;T1ym7HWV3CtcB_@qbVSQYmDGTsZ9OaAwKf+tBpKw!4L z!|65)-j9B`KoJa?L>S1+ewUAqAr<-ftM-@P!fc;8N6o6Q-A>|kUgM9-KYw8eW%0&6 zw|_Heb7c8>@{l9PC~xdkkLeeV9%f>CyUTGt64F#RHH33Nx~7oCs`jm3g@3tyzXPrg zx|?KC$}Ro)2yKFl;N|#qEqCz!9n6R+c2`k~Bj$s_1A<;)s<<22ct!sA6=W{8y6-|< zZ_CEgf=?(Cf4J^{{=xsioSh`O?fgOwDm|#X?MlS5Tc~z?eC+2G1?*|h(_&OF0`P6NTHLG5Q-Rg@7ST>v9VSB$`JH1AD;uP`0|6x6@n$&Ew1tBoX0FG z?ppQBu92>H5j;NwFxy4}B$(fT0#_Pm1AXqi125u#jQuTo^pJ1g{Qh z9NI547nhU>`)(nC28I)YfO4|YTm-1YHM6TMrSmnnf2%e{C8G%k%{eeZ3GtiuxGDb4 zRzAT$t$Rz{u)=Je<={BB65u2DGx%K=x4UvDt1m*~+Ry}|cwZM5=ECjU+K-NLZA5>w zA2sPrVS<#D{338=l{&u^sH#PhDRQ+uk#s_2*5@MQQf*b-m zZZFlmDvqAy3g`M!Q7;{x>q!p6_n}m_16$(3TC?PWwXP2CDjKxItCVq~IHFc}@9RBW zeUm+WwK^AWW5}4XdA|_!-Ck2S!;xXfVM2i*`Q$b=1E*K8)k1i~T-@N+)pVF2&G0<4 zxz$43b7;&UZuo|vXbQ>)zgFSV%Y0_M?oOlUK9;7!aja1lLmJRjOk;6zbN!36k;+7w zF&@h6UV==XiC1Cx>C-P|1~vmmQ?Atd`g&nse8Kkupd$S;o;@@`PPDsz3u1@B7oTR` zf2_h@r_MCO#ruI@WVq+TwT=W%8wm|`4zq*9>Ib8$j8KftS0DcZy_{A9^+@2xx$nUN zk@X>w0CBE-${CXc*?501Y%TMnUc2)O_gcAnJq!t@_Fqzl_&N{#NDGOyynP`Dgx38% z*^$eMMPb#qijym~w&n}CA5Hxh0id+9Ieh8vPos@LSZwALqn+!{+?$|=dA@~z`+jE7 zqXq`sL=`E)n5$0|SnCge!U9E7;_M6+pN@)Ey`KHjNbcZopc!lWuZfq%HNxJ%IW2Wm?5;(6GY;1dNeqZFenAht_w4Alauywg=Y8jvXy?>2D2Up@Bb zDW87CVWjB*0(E9`p;WB6TSu#Py~7DDo`VN?VK^OZ=jYbIv^k_R7n|MsikOrN4F5U? zobc}eGUJ*bH#e?b=QPY8863ANDc`&JC)N!G)TprO=m#m6E4K=rHYN6a6eU0P&e?OO z6xnXHIlXO=lRH-`hMLH{{th2{l!ze{V@NP4{Y7E$440Ko43b%Xke`55;)<$1FE6t| z0HK6Jd>H^q&f+kDWVJLmRMl1_^*JLbbEP=mIPfk79?eq-2X6%gDATJN7#y4!9i_Ed zIP}!P?r*CwBMdRR%o?pMoI>BpU^h#J;h=rjj)j~G++hW|?^DEA?&=2>r7!Ut#&_`I zvwqE~jzS`?x+_Y8(LEipcpN-*#vepbre{lPJ)D)9)c+aQxyH<2_ee)B(bq@s&v;r> z6^z8|I94ch|4|(*B54e(UOEo_5L`hMnQ4o!yi!ywulMBYT za7UZ4a`$c%D?J|Vg&+RSZhI5SNabX5vhM;J5C608dg}MIa5XKvpFjsr&tS&l^G|Bq zwQu^JF@keZdb!JxWH-A?Xt&Ean0zt3(48FVVB;!)LfLh`CuYmAk{&0U7n9}hPB7k4 zt&&j}fU%A!Bm&;bl9h{$B7B`rLh0u~RkML*HT6w|Y&1t|I=s{@W|s3mPtnO3@t03W zodT8^R!D_wVjBFNc29(ngE=W5iY;Dv>VAQg)wE)OL>#7Pk+q3Oe($|)F!R}WzsV@C zIXK3m&1gD8ZC!O;J1C#ittFGi^~;K-uC}|-#Hc|!S>=i|Agt63cG0#bODhEoC2(oQhHi2FfJVe5YOB2Py)Y~tnt+!2>yX)zZ`1&}hYE!ig!%m1(uZ-0V{`%!6zSEqWm6SVMW^4r^3u*Un8(qElDi&o(Gp648YGz66G|A4L6j zo+iXwPPEovU)vMRHv6UMdV4ckJnywnWVvO<*#wM z0B>gwzG^J>zl{>huJiWax|%PQMgboS6(l#D-vvrRt6MEi*F z+;0=As>rY2h&O=siIYDfQci2L)c!L(GA3-uM_guyqn`Q(!z4kGkB+{pt^Zj))Ei7n z8chBUD~y{*Shj*sU2E>&UDH5-#kE}i&Fy6rIX(I(fZ)c}J=t^5UM1yP`?cZGA zAkEH8%M!4H;lh}DTOVb6dtsX?YvMdC&agxgI8g&%!ww4cxi8$vM3Q)*yAL8k9CVgn zt@2CsAoSB$j!%`U16#H0o}|)E^BHCiidpfTwvZx?XPqpbr5hm%gXE2NsmdFyibo^?GKk{qmQTeWuyyq>!2FL zdW*V;nFlx-)r{e)>YwmR2eK+@AhgV~6vV0HvO+`3=>k~5%-!1z(fD0{rJiy6)B7x! z)!V0wd4nE_arswAk976q`qMuXCaEYpTdN{aT?`)F^y9hrzXSZ6ItI`C7-(sXN31y$JpXr-L z+06u-0Vq*uzdMC9_0C;;`z^k25#f)|Q7u*DD;ERkH-2T)d}7`#-PL6E+dZBWUKYhb zL(8JNdcB-@B_<&P0sMUT?y_#($?hzb?CsY>u9<+KQ1omH5oaoORbBh6e6IfJ6y6q> zrp;TD9B`o`SWki~?t%?(;`k_+YG*)T>qDJ@x4)^X?-Ad^8sQaUU`&H%p^cSIz^9ID z0 zOz5tHBI#;tl+X33hR}1pJH5+EwK9X(&c!H?Y$lfW3^(XiX8>AHx1>!eH>-P~GQ&sD zI|%!yO8?^v!Mf`m`Z&67hRY3~)@ru|aA8Gpnc+ta>FSB^thfOcbHrrJ>`2+vGzo)) zVG*FhchciAKX7^V9oS8?9$pt8`XE1wti%FI>ebY@^e#0uRd{a9-YMdGEW@`hBarDC zdIYUHUK)FKTIdW|*6O8Uk&QTSs%NqtTkprtHYnQ_WvTgjz4!`-=-Vh>E?luq``wAB z;mH9vajdVuSm~Ha^!&=Bb(%ndZTt94iM;R%Vo>I(7t^rV#kp9}v4mY-UJr>HUbP7C zBTkk4U23p7uPG0Xi`c;XLU2z^g((q1o1>b8#PnR- z&yAVN3bB?2zsU_B#S1UB!8>Kml6tGlGEb5}rBysUVt$Ed{Q%Z{q@;88J}X6Q$Rr;85$(toS82A?OARQ zRaJ`JLr2A%lbxLxv1J!hN9wk8uZg% z54^a!Ioelwnpf$XP2O1_v%!-e*}N&n4>4jTsn;w_|LRtf9Hc;X@3PXPuP-ie+?~jd zT2nZYD1Q5%LWHz;XAcc=;d^iaaFYlJIe2`RG3lVZ{6r-`U`gf1Gzf?Qs|ESV5zZZ* zjYfe0gaf>VyaBzT{0jU8_|N#do&XOba{JZ6h5`4y6mD(;4@H$CjI17HAL_e0#AYsl zA5WEsE`A}9+WJKCXMDht+qyRGhP6p=NpkB;Vkbk8%FVnKp=Z>$Ifnl>Y!6VO^6x2F zgqDJa>zJ^|1_(g#{<=(}qlY(a$&J46DuIqcHq6NDnP%kKC|ykBENV!^C`g=M^qYcg zSaz|LfR`wYo2(o?x(4BGmTk0LDdDtr7`LS!#Av?8XlmJO*@rk`aPLHOxikcf&l0Zx zQ@sQ?+#q+KV_>4QGxZo2u-_qW++qbw1R?zFgwODDuw~u^L9tJtgd|`&le@7M_o7ND z{D&lK@%)l$Ybv966AaT@o7jdKBFCGS9tT#hp7`d%9MSecg|b z?`M+bp~fp21AOr*Qw-{mKfnL{wMos^Z+9U!Z2D?c!2({z!gV>Ne}}%6C76*deiitO z4SlJ&ks-n}RC+Y?ArZG2Kq>fnNzIT96ZxGdUQWg`ir~v5i*ZF5c9?`N34R+DW1L*R z{p+;@B4VQG8kfIl_mx`igl%-*sU+S0wYTi&$McZ{7Q16WPGax5?0Ho^_u`+}osp)~ zY8RC6bU?sWh1E@DCH`DReIYC%ji0TDmsWyJ0H{6>0k+;^+}DIyVKk>l01{{(X7b#8mli`l#){h+K*CktOg|AYzV8{=Jz6t|> z*}t1BE6~4{ncuIr(y4pcBPFQJeDANz*9u9Whw;%Bc9M7JC?OEI4vj&1k=KU`!Bx*k zJ%i3gT*fh5-Vw|$63P)w5g1nQTZKFr)u2ekKqJ|{1$zJ_!YD-Uk zDQ$3PdU)V1*O7FMlr*~h5QjLRPtAieYEc5$m|4S3yqG( znKf~%mUdGYnO>w$mip9;wR&;Zv^K@rjmw}Si37ZxGnjf5PoJ+3H}S_$$N4?la?mMp z{_cQlzx`sv#|FrkCnqIor8YD-OSOLeGnpruq|qQE;8@$9bAP<{l2cg7N6R0$mrlW7 zv!H-za{409zl##KoQII(b+~tg(@>j~n4F@eS+#JdWmr0udAFgyzI}@8=chGn|Ci5; zH1+l-^y^p8yT8rN$_!h%rxor@IHU2&LD~N9IYk7N(|?#n;?KRr6SP-np2Zbeh9?5| z2oh*k^oz4eJWtarW{A+@x`VpERPWu03+Tt~gUwrVcQtKLKr+AGYLuy(Pvw61vTOdK@K)BO(0rDZ@q%rc6@i0)3YM*Go=)>H7d zY4-B zfFU_i)Xwo>Oos5VkVHBy%V<0v>|S}PyzkXFx~e>#NpFV$0N{IQ%&fcB>+j!8OT63o zcpA@+Ejp8vbV-zu@QS4P!7XJK_PH5a4tFDWu*d`lovaTo%+p2l71j?A!hr{SEghDi z#X^9Xh<~|Wl)ro%-sUwECyn zlo}*R7}A8-yA%ZfRpQw)oV)ux`_=X1?Z5zR1w*dOS=M81_JHU%Vg3B-9ot$n!YHXs z@NL5OAYxZOQUq!@;%6eoia93l(*UOgd^Ti%bL5b?_Jp zb#=q5it_ZUfuEGZU>oA6Q=$fKw)^4v5!v#x@oob#X8t;Ab6me?%v(%Ae>0NiZd(9L?98Jyrw+0T0Lt=3gGb$#i$GP%S|+OP8|z@itQTyJJLn;)L^U$KP@y;PO{;_?l83#D#AMA zOetvmAYWSgP}-SQNsPgKs|>fF#@%x5FD?nbfuSLRl$7V&r}cHC%WbWjrYFeVUUA^t zVEhPJ`ky^c?JnWl?ql=0WpxAdE)0cf9CP(Ek9S)uRzULiLjfNtZQE&~%RyUM^gX^u z{03jRymUFSA$2`EWl_Uy3#+HIV_JHG)=&vDPSe(c`C%G<8`F z&^%SD(I-$rG{>_dvSShkhb~1!LCm6}8oOc03t|-xxg)uLJpJt~XPmg~w zusAw4wtS_g_>GZGlU$32jxK9<(Q`*|nV8e@+rnGMQ5-sN{d%V6B{|^cq*5{s!`D}> z0EjYF8;b#TzS6o$F2B6EG=SGM4L-ptDR>2&^bFZR@tc-FCNIAeW|+iKhqgpRO+@$) z>ciO5X=}E2X_>QWC}DQ#^nv6A%5+eWs!o5A!J+m4l5M;NWMi{$_ta~V?792$7PgB&*y%8W7z&$>-M^l#XxQuuV_PcKWb)Ah zDP3PetvATu>los*;Z^9hZ_UT~(Q|?yJbl`qh82$|qnCK@gl}RnNY^e`$Kc722S-_! zEB)Vr_WrD6OOSsYeyXWKO;rGc^>74OK6?B2{Homd4x+rAew~};tFMNLrAb9cj5)clk2#^^`PT3tx94cc`9LP>(G9Yf+L41e}Dl>B`UVv)!+)fgVP%T3U0k4FoL#xQ zs}!ksye=8m*e7BJpbtF2>RNdTP?63j&2EWXFL43AQeOy++Q#uHv7wiYykc5!>C)O{vTf&M03liDjVfeQpAGTyIw^JNSs2y3D z1UdrTbL%gmF9HIBy)1UL`Ps>w1 z*azq8Ogf)UjkDt5rhgcSI!ucvc)g!n13vysn%UKl017b7t^`h8tc=-U=$ygYF69OTwYAz#&3S{0oNb)9_*Y&nN$OQsS`ymmXo`IKvl{&W zja|W8Bmphcm#sn>+8o^KBpxmtS!ta9`R_FeQsj@;EaBL^48iW1qNopt?+?a zSo^NcYlQ)=-V2ks^7x`D@id3A!m?JPA6isUZ%{ageM1T)+S|gTp^OEM($vI6JSX9y&5a(b`~rfd2RH)iso?esbf- z5&=AYcvx5`3Kf3fcZpAqn`5zozbU>_ZbYQKCyN~FMu6973h&Oz{fZAqMpCZ?Nw2+rOWo4ZVpY{m#ti{Q0NFJAaNo|^<8wl-Fn@sO!!~@tY&Qy9tLxRI88EGY z5yGHX`w4&<(d&EtV%O{Qa`F0&rL3&E+{e%D0uGZ_xvszE_A=$ee`q-2>brsTk8`5@*jTAQBFT-Z-1teV;;3O8~VXn zaMZzWmg(KINa`*d1U)^f&$hVr+AB)mjL+)m` zZf(c7J-PMtD@m(;Y*V~og;_Sa!cW$pDz}G-%ekleo9}12aA0o1Y|C~~ym!Fga}{bW zw$IECnEgsGtuWB&ouTCqG#DUeDe`(|qSi$BPM%&DXD+E_B7dN_*AY z!shdm8KuNB_cl6}+^@u~t(oDh$Mt^f&}d(ihTG3|t|~@i{&6lguo_r>wU*r)_zi28 z6y0rf3Iq_vkrbff`GSvI-KTYi?6ghXMJk4b60+ye(7$nRIBuw{p)q%T=mGN>2`zJ} z<`TLjve#lp0$XIn2HaD^c;UUFME;|f5X6Q;UPi`2c2qCHf2?wY0O<}{Ewj=ci|yR( zk9?@V`T^`(uRLsS_g^XH7q32i3iLB1{UGQ9UIj}asUMc2G}N|MmYnT*$2(V0j8>=AjL)?V6}eEU=Si9$JTyYh z>yk71TVDUJ7bj$Cw^W~P&&|GK+9nIy7X-UlD3XY3`aguWwmyqv22A&hTKLzlxT z+GVqr+#mQj%oGUK+@Xwz#(;{~>AgWiF#bq-W>RWga#|V>`z8^j*@!^uSIpvqXzkHa zQ*}*7g>(BuhoB*;`}iN}5K)*Sq!+2fdb=}DHa&;wNW@iPjO0P&j4{6laPvH9K(|JVLxufhQxqUULWSv&G@lF08 z%jF$T5Ka|nGbcmWQVMA3l}PyNSII5yY=*~(KH6WIoSrbxx|x7axEl&@oPAoBC8h-* z6WSgv?5LtQKfbgCEjvtJM!s?~+zClYyvG*H)8uy#x$PP}dlmQoa1#j-da~#=2spc( zJ3Z-mwMuLEyF6Ifl(tHXmfCb!3wXL;D(f&cw^+I?R5IxB#WcYKF_ap$T)LUKl3sB4`>QWi zqG&7^LXgVCnM^H@!;1s^6^d!1ng5N1LuVNPVz9=(0U;C!l>Z@@T`1q!c{%@SF+z-> zW+bVJQ_CH<+_u;-yV2>``*3z;ejuKvI6HNLF@1b@bFfh>X*;hZ8}`)B5bNOWXF|7VJ}!B~I$=*A3t;q?v0$eKW8mQf@iEcUoeDbiMxk82Ci3V2RKW< zTvU~jGhc|&tE=Ov=4)k+B*y)(Y#Ux@kX=<@0tqN85R0p{K?l_>meHunFRK^FzUX9*jcs5%B+i{6B62 z_$+P$y)}c~ujLqw(K$dKF#ot#+i6X(?sXJtTltv<#)pS8_JI=&3EUZYCxsUIM+WKJfzX%dd#(gR+_$HMRUIw`I7LyI`LZJ8xz-`R#96GN`Vhl$*y| zm!l09@sUkgaTN*pDt1}vspaMOF`67%|F&Zr^Q)io7HNN~CBh&UwiAMQlBYh#>p?9% zMybhuPNEeMvyrSKT`u0Ysn9T{SjuLn!frbYUY(jG{8@JGJ~J+d#eI>Xa*bB^TMWe- zN*V%2H9P%Q(J%B(_86ferWYxPkNHfeB>e4dPJzQ))WH!E9IZJ|F`A2iEovwuGVAOQ zd>AM1Cj2)bIM~}1{G^I-c>9={Xz@J)(cN(Emywx)1M+Sxsb&#k_wMRJ8};-{5OrJq zGT+P7vaD1zX-XCD{|-*$7nv)UnH$|};oPLJPuw*{E`BlD;>&JNG4yAOJ92xShXv-o z>f`Xeu6w|^=2uOT;zF8)B@eRbWKW(5_*rzUFdr6x27DUlD`@V6I_QK?QeMp2)?Qkd zx1dZSVB4>$AKFNmtpskeG0>RioN_&;^E+@{%+IH55$QHh#v%=*KF8TkHDIFy1a=xP z32w9p_q-HdHtiVTHq?KR@jG-7Xsukk44({n6=I3-u0P)y`WZ*fnL`Bpt!dD5v7DVc z#G%**V#zshSWxJ@@?9BYhll#ae0H&!Ydrhjss19@v|z`Rd@M1RfIT|A0e5DdRlGh^ z;U+rTZFyg0-;u9uzMH;QCmOnV4PsZyjeQhMDobi6`BCB&oLT8q+UpBqgOB+HyJac(|+C@oZ~|95j3V8g;$txNl-c zrTYGA|Ai4<@Zn3EoVQyZT^qnplih!vZZxv`ssCTk}il(vt{kvHe_Ss z4a+lM(T#F8$td-W)Jr(q{`>&Nby}$4Ty!s0m!0Tf9(e?=Mmz;=_pUBVEDcfdX!`nI zcs^}FwyYyT?LJ3|%GaFoIvYgPBKcHUn{c3-iAuG627yL3r|<}Y@z z!pc-ymUG|=_rr@uhG&Q9fz&bNqJg+9?99tga0erCn9&JiQzE0JtyGz?YYqzoBjs$? zypdakQog-hfE+)ah3ybJO)Thku_h+^3sG77#;qsO0;G_khDs?qGc!JpfXKa~PzTih zSbgxe2eM@45FSM?;+$8#(|;CzQd)uGEm{#xmXkVMP*ueXR#F~>Ks@cBe(ApSduL6t zW6E)#KasGe%1A|vr+H$+z+q|zI%T?lTm zh|_OTbA)h1{F&2PtZuOPvBysx7V}8+Y4!CuW){+-y~OkJNKU^J)Ez2K(kVu^zB44< z7EDzDwN|S)Tdr{$tv%wb3|X1IP!bXV8r0rnUqK!J9QBPC#76tmGM~>UeG8-79p~dC z04ZPLPGqsA^eSY+Z=$_~dtU4v9%5o(-A!JQxHPG=QPzD)_L>|ooEE?YYj~8>B+IMi zD1;MJ(cq%zG09xqwx*EfwDN4p0`P$3*!{!9^5t={k>s-uRx$t*kto(0O=-o5E;Z3a z6(B6u(961WM4L1^)OM=!P5ph!c03SFeP$Jm8{17%0jOU*s#A>S(7l}*o!WH=W&9t<1yKcg%!v>9RYeC#Nw81Z*OUz`j8HpQ-LV4F>&Lbb#G8eFqI#8u_?WN0d zcqf!`6~t5-V-JW(LJzO6Gkl2H{cJ54Y-<5DXM8)@HC8NFZ=vNg!Yj0ec82`s@-qOV zXF1qsAK#OYvS!YF`V{OA&P{L}4hDYL=b-pddZR=2OBis1+OAJHAZFkQIZ2 z5A{fZr9)A9{ivOQpcR>1g#0>XxFn!gRN=_l>Y(;%yNTjEk@9M9w`ChtKro(ONN(;S zX7zo!{X|vzh+bWn*|SFJXkC9($Wf#$1g6ou`cs%q?+V|aXPV6$B?7?05 zLwJixvUx|w^1{TB8F%7jLIKa-X-MU%8BI_pSGoc@cG!VCQ~4$iAPiC%z*(!~{7eUp zOvAFupw{W@-|RVZPm{VUC0A(R+GwRV+gWTMhc2JEa71&42-61+*{e@ycag5^8(w}n zgG=E|v^9fKxa$|KUdviPA^y6IiRoihn;TFHVtUzazl6!@>ALlK!bSml*|E>!22RbZ zUJ~%m$8Ud8rr#uM(;f?&?sjiR{iJjOiyttQO+^^H%yH;8u3`pt?}Z17rc>T*aHprUYDWV%5}f(XH+@Zam*e_V>MJH)waua?$UoC(FfAb)~c3vpx_g zTRcx?M+-+20&f#LkUH&POKoll2KL&t&PQMjoH2xbjPH@cAj)!9zr0<y>5ei(=(VF%Aj0!*J+<7yUWr=!^5UpH?2R_-~N6ZK#Pw| zVNdwXK*Xuvv$cl$Rk<&QO8z_a_lXw8{kU~4vM$Dlx8>DY_c%*-ZGLSL5Hr~)nIOQr$=)ymhow89}-xw}8EOUXE*w+d0^AB%L;gga7 z`h9z+JI2u6)#ZxBF3&qbb1mnMh2^#W4g%GcjKHo8TnQ;WU5PT?J%B^L20@voJYiYc z!hM}u^Fm2o!OTK$%uKoFuy)x@#1BHLmxTJXRuZqIt{JFt(c)ev#2p26$h)wAVPc_A zO7{lOio3vevM?CEPh7`bsD3bu#CI5N@42R6luP@nxab^m)()Ro@{d~Lk;xEo8XO+% z_~I;h#PJWgF!X4}0CQhrV`K@N+9dudMo=Afy-Q0R&@1}FzpYOvjl<(TIZewFGNrm^dDqpt3#g>J^znbRJ-~}Oxji?v*!j8i==e=*K4#2w z)38?GUBuGiuAahtUK>!STc%s)@W)Zq`SNAVhQQLw{p#7{r4Vtbzl)WliS+(LkK?6u zx9g;Z3NyjM)V&yteW7}#72!JC2xw;&Jc=-TfCiyGcoL~6qei}t#UZuM4&0RognXc& zXuiS!z{*}0H?v~c5KsfP^0Tue23j3wk%;E#b%lYo)YS{f6-81q;OiykpQwU0D|9`s zY}RmEu4ksE0$R;8HA|!Q?)kij0)WuyyeYck+RU) z;*v9HHsQW|Ua{%>;00S=9S3upOw$H`y`uto+TPF%l7Z7MLx1iNnW&ez?@uh0G3|8N zt&r}Ed$MGT|GxK{x#E1o>G-G`@bs3`?Dy&!*Bt3We_8HK{OQ_`_uVV`6gD;v=2ZP= z+9o$C4o8w(jlP>ruxLQ_sn6G%);qb;BjD zgFQmLtzhm4ySp?JW6EHEE)m`{b(Y9AF4vLZSNQqI@>S&IzX>AloIheG);U0{ITLQE z+MV8ZR~qNuE{8a84@VQC=W%}jIyWm)-+I4re}|Dm7wje401Bv*eMkRVn;ctY?WsY~ z9&U2n`kpaSi0S_1VqnLcij1t@#(b&c`tf`#hU(?>Sof1YU!U_6XAfWL(GYU-{)>vu z9iu^}7(8@rv={?Q`Sbdhsr}J9#EA(>32xNkb9Y;7aD^padTSZuIq(d1UvQN6o!k8P zsXT))E4D%_O|#X!^qT@JJ4We(3^2hjk?L;2@}~Rw<8w)CKzAcuSg@lP+JTPT+%hTZ zC53L8z}CApowK#VGBa%ZJFo6b>-ZO~LwP$=_+!{lZhwCYa*-3SnRXYAqyZBIPzqbs zl-l7HfoT1#WDXC_zK?e*Hz1ih+qx_c*H^(9l95>w`L5Z=Rr{tP$g#%9H{j;e20jtn zep6Cf;MeXudzaOsJUjjQ;87|7L8qla-k-Sz!B#+(k&$_T|9W`k(3MQ6DkH93Q!fTE zx0)S)zg!P3J~;V8?8Z1YUB0-Bg7f3MzByx}Z1I=o#^$+4&)W(@AmE?l2PztRYka*o zodn>&D-hiw<3DHPIiI2Y?OuB}j9P+;jFAI4`eCpu;I9_}NB=28$m7J#t5T<)km)Pz` zhw9Z$PcY7dm!r$R;9f^+hMZp?y*~d=*{i$fhO(@l0MMf#>#`CqSg0? zDmn%#D(+(^`$mSy;Zj^)uLLcj#$Prr=Q$s+_<2bO_O2^4RS9*eZ#AI16Dj4KfnV5aXNj+{@`M?9?MJ2G4Jp18-X_3 zGNl**G=hS&I0Eg2c--ZQ5;{6W4Sx6L1_ok55@7PHPhF^vlU6Ae$2)o*vcivgzAYL3 zuD;G!=XVzt@jC~OzlsXMgYP#uuZ`}`<#;SP-x10Q2aTFk4ZOtL_uvQqfP76vTl^_} zWw#d7CTzYqked3EElZ*h3du%g#m=5;s8b_xtLTWPxH`5$kM=Ptu^r$b(tq&t%&euP z*%VeMZ(n0ziWiiiR?lP}ggs_U$|05uWR?!Oz13qUq`W!Y!Mc;h)(|T<6}$P$>(wd)};&%Z`Tp!2p7COEX#L^KZOd zZ?x{VdR1bB$1=Ilx+`m5d3zF+;RjJwDY;8k(;u{K3<7Z^mXgwg#M(HQo8t}Q5SwXe zn54_-QrEBNh~LL>M(cHNHQO)WuT?inK_F#|o`?F4)ER?jnp*N&9hcj`I>g|6Ok^@* zq~{m#Zbd~1K4X*w;7B~~vAev@vF#3I3xlJE0GI2Z9x7FG4Go{4|9J`g4bF;(AT$iWfWr+IWw&b+7jhBdR0TI=lDW zgpt)6XI`YQaAX$u3cURmB@LhZ;!wGjr{m67b6V;j)1D)lI>Nnob+uEzt6?AL9IIQ@ zoQG7Wy2J%Y7N#UOOqN3LVWUIITZT88loICSgy#H2M$0|ttFJm5(?mo+dNlpyPYs-mjfz8-QrsDdy4a2QmyJ;uV!47=JGtFcrxtArQ?Cb;_B#9ZMzYR0>LR)_ zh@zxTh%2A0c-=?;bmWEYed`jA6Y z!G;HkAtfc+_+Zm0QKpilo?!5-t*2N`hXB1kVA;0)gP}>4)ka@~uCA_HtR-d~iyBLE zJ{6gm^$`8rOolg+p_pWs9|M33R z!cMV^860=1l<$si%v3r5$D3QZxdn%ZGXSUib?^vN@?Uj7(#{rMNgSwjQMdkXa4eVrhv^GDVjS;oUx1;BYI6pw)XQ|=dS zwwXZ7x1SUuJ_68MUnU|xq{|g#R8T8=X26e_DPOaBI!q~p-%RE%7v(DWNcv_+3H>-Y zJdylU;iSE^N(1QEm~JThV&;gUKJ5;mfzQQ_(rt1xCVke#lZ77sW`1ZuXAH($sDQEz zm2k66LuV5Y(RUfLva^L#tJrPJ8T0Y_&zhU>pQ)O|O%P2O+Zka#uY+={TPONw`$eZV z&Ko)Zcz-_`WLjJxPV(Kn|F)2^P@PciYB?%9D&MC}|I62Db+wZFtHoY>iYG+;Z-*r~ zEDS6HONTV67{s#;+NiPwe8@DMcOs*i8fR$$#<#H(Gm}Q)-dhfFVzHmMRZ3859 zZFIj#dH>Px1df9i8j0UOoG+809a>?JOo%C{u?o~FsAs61|8CK)zLpTn$4ziD`|-Dzi* z*iR(Mnsv2TI`3H&TB;VS*XcsccytaOSnuvSc8tb4;1i{s@!=~kx+@!Ud_209VU8l_ z!}W9>U*07dLsz>>T(n{m2_p{eJFA(M;f9)726146xL92DE1X76o$Vp#TBT=)=pfKq zIaPgfsum*^l1Hv5%fvqRtW^rdkk?5+^!sJ&2I0DFRtjae0Qn5w)#+~R4$#EjqxGxC zphD<-XT>_w?rAhU{$xGt!xn8tA6DH0bcYuL|bG+s(H^;l%S=Sr4nb4h9wu28E!*<>BsJ)X3rP{N&T4 zpIpT70ORlW?`iqh7Z=VR9xm?A4pz6OL(T2&(6KR|)CqAFH4QaYbsmq$Ib?}@Anrj5 z1?tFw-z6Q!O-{U=u>ct580E$=*&YF_8L9?6Hf%h+x#{hofDQhvHMOprSl~aiJyvp> zXV!j{P)7}IUW-N3R@}M3QKEJHrv?AY?oR9K=Q>!K_`V6kahDvk=nW4W1}VCto%-4h z9}wsrKHX7;k(6rnN=Yk?Kp?Kp&Jht&X*W|mu7j9aEUaxB83{=|-uIhvGLp@B*THS* z7IQzo_PFP&Sgc^w?u3a=S}4^_8`P{A-)@etY(~y=Z-9S9XN|hMjB>ON{e-r8A8Wn~ zj)R(&IM%bNQVN6a52om={vI?H*D$^oce$JpGWpbXQ>}zVZ{>!pS%ege;~)LL;sQUc z**;WIND6;^;!y_kDkoX7QhhAD);}4LUHznu?G-2k;Pbs z14n6RkkpH!AyP8Z8^&WSGJFB=do!LJs`s>0Hgz_2x&>bhnw`-4ogJwhqjeK+{Y}0& zjnl2g*4EYGnL1$?#flj1@nz(-9d$tt8n!%vk1v$Ac1lEQD?V}lbU!Yy2bRGumV5I8 zkvU(Hm~wq&`uSLX^e6=Zn3${vqKw(2;O*w4s>$ zMJ_TtbGOJ8y#3yJVPWAnflX`(TBd1Fi4@Vg;11|9+e&lu=+7`?8_jKjc9dM5l7VhZ z-CEa4ti5;l#Tgf(NsTp;wRyp8M%yFEHy$mC^4w0HD+dJQf~ce!@5aG zgsW>Cr&`h9a?yX=JOb!_kV*6Axwu(^)$r7mZ|ZXsV{&7dwzjr$WOumnpX?tsFU}X$ zKoFEzpxTqM$Iw^UrB=U(+1t~#H0}7(EyS;HCkA;>5Wqo3^|u}N8E z=T968p7&Qh#V74Bx+XXCnM5_M3SEo#)bleM=~LgEr;OW*7iH*MWEB-8{4BpZKvx{j z2Yu{yy7nDA03ExO$kJiQ!4C66^Bf`f*Me)x;t#d?i5uU=P<8cmD~#G4II1S}3QU=z z>L9U)kF$PHGuf;m24K2PuZv>0=0{!UAbQyEz0(KZo*x>@beJ_t{Q3iG8nCx;vB2HY zpDnM#^&CXlTfL>kASQS@PU;7@8yIfdJ%Y29%Ff5>1|@ z!MOizaSBoZVEItoy+J_{C8w3yYv64u$Sw zT9&sYvJ(AE8ad?r|C-|QZ!H8t2K0+|X zfqag?X9Cu3&4$vHFAg#MJ&B{G6KL`zi&$A$kPzQ&z2aHShFAc1=F76wC(1YPV@juO zu)`!7kv)ErtNv~eQ#i7h7XK6SUu}kCW;}zz_FuAn>Ye%xv#aelhvlEY9i^V!-5w1h z3{%=)TqwqDo`v4{0DC)-Ix=^rS!%h32O8NHLlA(T^ zAG}q^tTdoE`an=MK{W||OGZyT@5{Rv>Ht_csQa){uB<&jB+T~kfi)G{Ux_K#VfP4prGTTD!h(an>tTRwoM z$90F@uvvSRncDY~QrKMYxW#B`utmb%I8F$oB*x+`6Qu{`A<^a1V`!xJ#N~w>lZVx# z%YnL9?JWOxIfBW7>vfs7v6WUT<>$7`YfI3>SN!GpWnF#mySAg4_P{kxHa-tG0>r`R zQ4uiWX}1BBh^boeZ=aQ;Pnx7a;j#qVmPs8`otD&Um{Q@{V+sUF(qdUdb-o%5&JR=NLOIYgj}CpkWh;17ko*V z33DFnM?;E0MtYGR3?zjOtboU@?s-CE zU%tW2JvSd|i|ffqBW?1Q{fBJv^wbxMjEU;HM7XE@nN-Boq_*Ivh8M;cw&UT)}O_=cZ<=#dJ^=&l+Lkg7LP4QC91q;t#J*VP8_19A61s2-Cj z_gAa&FDukJ`H6JE&*ap7&aJJrtvV}yj2k0SyCh=1*DS;wN;g^2cBTIl&r_Ky*N$Dw44Ce1|=pYT3Slo55i+)i1_1I($3K?)^%8rXTU?a3GXvJ zw;n~(K<`jaVW^fwJ87@DUAM=WIhn=bi)a4f59_cP!3v31`0;^o_Hhps{{c~lNES4r z@tvb&gHxBhkX%0P=f%kw-JwE4ea&|~U%w}gm)11`m&bdqFR3{yu*5Q(Ufv>4n&5v{ z<#i_?#f7GFU(ILry=mO}eNlI&M#r$6w9_j=@st$Jm#C;s&F=;I_!2NnDjY8_E@)yu z0!|o$J-O{(R{deOP2yj+-XHhCq!J?UuFRE?6nja@&>(mJE*Kv4^o05V3qnDGm(tiK zX=tcNlL&_X+sd@bx}W4QVc(eukw-#nlFbi4I*moIZ%q>}-XyDTZQ50w;s1-Ml=UV@ z3(ek|O7j2DF6WOYH|cz7MnP6E(&tQ*Q_i8f+;zIZ2#)iHo((;SIDjD}h+dH(O0;H? zrV@J_8qkNo*K;i=o*Vv+e0CZr zozFm}Fxrx3$&>Cz(fr7IxAI|y0KK5O`rc|nC0g2)j}$cav^?KCAHZT2gID^N26Gs3 z+oIQkBfE0j^GoohSO;#tYMEN&yL2X3**jfF{ze>ADbIr#XxA^j&MnN)`yZykrY6h(YD#A?lf`C zBZ{2FY(=8kXS%vn3j;J)*HBn^y}`a%t82eBQ8XBUVE9>Hw@e_nJvah$1&s}jG$*+B z8guoqMV*~ryWBX<+SCqqFk0q}v^qcaZSEyX%7k3+BGDk_OE!Vw-s!D|O&HH4&sdgl zQ08e7*na^!sItk)(x@Bf@@~tnZ~nUe+HyU|*~6JpWF7@F>$u#cIzUA>gvFR+$>nIA zJF$0e+l!UpmtWX@a)L*vDHhE&B0TLxqpabtcY6bf5d;tY2l#u1$`V9{sXXasddUm!?&IA8n z8HL_Xz$br$CrDtX%48lF=E30Av$S(1p}U2czs{|S)7!h7R*Nu7lv^sKFAh1kKrIYH zZX!&lgYUWfv`N6gID6}i`Z_f3mlwZycFm4I{2NyD_NdIla=CUD49EIs0VP%8zycoB zrg*e({$F|0Sy*kof*Q*~&GAU-i+@5G6b}P!@wbA5ai9Nlm>9qA<*E#T9mKp_R7agJ`(>mZH3J1vEZ@wg2?4Yhu`?` zV@@7zEX}>QN>a6u@Wc!U7l@3m00JO+zgBBw*W_YNQ}NyIT0XNZ^H`Y=(gB2=ZzmQr zwY9e4K6>-tUf7)OOjBNtm0kt^%a-^!Rr|XiaqT4|(+>w7iF<6$)eM8Bvg5K6eJ9N&7ZPjc2;H)&+V+uR~*#z<(;?$9XvZG*bRp%Vd798b6zto(*9E>WWk;= z3Z?OY>3iwwEE;8+yy*&WGedBZ4nnbvY7r!@&!ozS@0h<@*;0N~ejwlXuhwph*Ph8a z0Oj_iGh&*RN68{fLCl+P?{~$xCp_=Y@0pPFVJ+c@4G2=%dgU z!&W~?q@B~*=yCC^KZZOqjbQC?U7`Np)4=x!OaA=U9{?5^Hzp0eZ4x07;V`NB0Zcy@ zmxo00eatMZ9P|}}Vb;C!7gX7SFiv|O$ov!0#7wP||EDC+W~7mu0G+`}dsTg73heRp zOU1T?wba(uX3Qc-3P5rhdeZ*rpgHo#IX0H=;or5D4k{r*+-_>_c6$g zFfwDY$KxJu3A=9h)-2J&TPKy;fXI+a?YYd}|4S_kV#aM0@MK<%##3sHbn=36fq*A* z-aM_R{kvIxQmIx^qE3>gOMJs$f|OnWs>*6FQ9UDVM{oZsT0aYFg^4yAHXYD? z@b0`CPR1e=;9OMT2@dNJe!Lu0$b{7Vt>JA|bG6EltZ8TFE3#;q2P1ZXv_4n*$>o1h zzaM}0{6%L%9J;u%0$=lxO(?M~DU%Fl8+M3YTyxV_#)Zl!tV{aOn9^oEOD`1S5zYG@ zF}YWpLzmZ8qc~Xl2Aaemt7@)MP$%=Lmr)t{1s)zG?i()P`+xNbmPi}6_!IVtugcKb zFO8=#iaB$inRWlIZ87wdotKqp>Jws&g)VO=k$%vEli9Orm_>iaRe?mUFR87bd82S~ z$t^R}VQe+i!PPoRK3|{IACfBlUtY-n^aGt#siXSWi`9n~=<@Qa3B6V#ZI&l95L3i0 z%jLdT?0OCAO{KxOsMnMO7S(sk(NOXQIOnyVB`&n5`R)NSdOcb-mG+gGzm6Zm4!O|3 zaCmYqJ#xx)|Dj#yGu^i;ZHx0yM-<@!C;7U;p+x%_GL+GuI$}L!nmzqnSrbRic;{!v z^vv(}%(Z0`{&a_1nQXZ<#pF{&ACS$qwlE^y=Y~4){n}JatcR$q=o#k?YQwAEj(PdR z84~1sG#}r$;iA*1YfSSgmQJT2-@-X+um%43M4KyATYb*c&2|3vjmp?pBO5UvrNC(OJa}?dmV-y z;K7wF$A3!(gwRN7{7L+0EIRqnh$1fTgj~1j6J?PSUERdvNlCbu$&s(EpxwOF-TGF2 z#o{&PTxm&(yEKi#Wo2a# zo!M}5>18AGMD-+ePqmiUo11&xXDFd|)=tK!$44!!Fhl0y^EZeD_l<)Xf7cPNs7287 zOq&lSP)eh(zdtf8j@fj`Vk}AV{9)hJ)O66yWp(Xu`Yy>N-xaA?>ae?q+lNNPM*!5f zK=AtgcIk~y7(VnRG6xzkwfIzAl7`01T9(6oG%BFxI_72q0K)$+1K#guQc=KPaWZ zQdI~FbcB7x&sQdVhfBR3?*^zv&k3Zeo~rCStiX58eH&-NxB>@?M>=JO6*orO^3GS-S0`ts2 P1(KCg`cw`y4*Wj=e6h7; literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/leverage_slider-dark.png b/testdata/snapshots/darwin/leverage_slider-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..4657808f0f48052a0d30017577f84e55c4546bb4 GIT binary patch literal 8567 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/leverage_slider-light.png b/testdata/snapshots/darwin/leverage_slider-light.png new file mode 100644 index 0000000000000000000000000000000000000000..155c31238825989d1d523a0e79fce81b54ef3de6 GIT binary patch literal 8234 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

gk%(*3}PpMXwPcUOQ$GcR3vF zFCO3Xv`ByzHalaEdxRaoKUURIpUq%5`^V1j6R=?97s}#)AI~e$EHxo1uC;e>aF`K8 zW+^W_dL9cic4-BOFLC(Z0gt_xWQTxf&0D^7ivcK=(LKiSUng=1St_SZ_HpInQ-&*o z$nZmi*3aBc`ir@LGSY&@LzY(#!=UC2HR!NfoZh49Gm;*{JpUY>v3Kuud2hXz%KpS;uI3u^bzC1=+IV#sD1Kz*P?!r5@B)r-!oc+O{Tq`ZDbhx_?d4Y-v)nHb zh4A5MqZGxv?B5-9ySrmFV~?Ma$eF?Pbcj-kQk~wsoRG2(b4rtkvTJbfqZVMx1;Ypu z;>cC|g}-|iA#=#scI(;-v(GIHcpxQ?U+8!@TuLBUE}iC-!@B2-K=wv?u?2Z;zZT|K z9KYTqw-ocb-?Qp1jv3%VuTPd5t&A0s=Z6>*LX|2#}5HtT=0mt_?N1 zmO2#3P7$3pjV={8yL2PozlmyH^q3AEKAW#MAUkY6J+EB^h-*g-asHx0rp%N^LDYI0 zDaJTld2AGYaho)D0j2Q6*?WJB@<1%Syg{cmGIF(S5^A%-uv!n9MV{f1`TDzZqQu2a z8Tq?Lm`TG1>o06-3L1?+-Chhdt4>{@5o||H!V3H-eO|A0GsZyV7QxdyZYsG_-}ZZJ z(1Bb=zxY}A;Pj1i~1Xj*&tRDEOun zEdqB-z2bdL<0U|GPU7m_ad)1InXu8XoKZiVyB(QHx7wIIqA{VV9%+SUEsz^h7B^L?EBpnEi2Zs>7eafVBBw>3Dmp0yC^TnEKDB;)vxd*j>iocXC zY09T8e^KukgdJ1JA*R^T$sr!Y`w<2uDsK1d&$E)+M2*`^eYRDG7mx4A63KY$poFdQ?5otnvv%7*84+NmNV1bubWon;1wFk>Kx5|X51 zMj9vyF`})4@0yUC+xdS@Zo4wW!PVjbkV4<~!f(Ji`0%`IMmwyA{}}N_{b$UN625P)J3=)C7@)<)Niuy#50KCnu#W KStao`;C}!$J*I8| literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/margin_indicator-dark.png b/testdata/snapshots/darwin/margin_indicator-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..f77e26e53d28070cfb8c7813c44d9ce245cf5c33 GIT binary patch literal 8169 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%0Aq7BzQ5L zj##}Qy|WV9T`ie(or17!L*D#O_ZBduvw_#meF1_ya52uxLMg;jygNMJ=eZ#>tR ze{7x5Zcjz0VsshqOf+h+bHpzcoN3lweKc}6;KB?p$a?W`TJt-uL)hf#9*2>LRoB-P zf|DOB3Lr(LShA+WybNL6^PJ5YKm799rkUB0myg}bPiJ?g8o;l!DPR3LZNkTYv{rik zIVN;?TS>cB0{_9A5k6NRJtA2cil1eXZD@eLdnC0yQtjS4sv3aO#*sc@Jbi*e)(-^x z4)b`op$uf^5aj`O^@&Bs%==Y{2>()Hqs_PUo0O8C7Mx0CQbtIzI^Spu$n0KcFK2T z4IgN&v_yi7QLR{PkCVV@{H;(_TcS|1xUxiEYR&3nANruUn)hf9&{9-zdb0s}*WVnU zmr%#sj^hsOU%6&w1&9!T`^yjfTV;y=k1qZvFk+;`R;T`Q*GdqJN$A*GU#zv!L2M-T zIW1swk{vdG!v;Z%Q>HISssaRBNHMPPh0b|4NQA+=9U+?q7w$sXHnr=V_a}?+hZr9g zX!v4t3wW$k-(DmELLmZZ$Y`PQju8JLq)g}&24>`c!{M`UXxW*rQbKbI zOV{|WfUOu7mNeL0J-qh>pNcT3QuTHfqGanPF_)h0^QyWVmR+?GXh5JYTE*7h`5~1P zZR<8#yL#g85#hJHYw)4r6Me7VN^~_|RP;H)c4lIgj1o!s`^k9(e)}Q|&>QoL?cv2Y zv5sh@LuF~Fj;Zh@)!UCIkSCAnGvQKq9NWQpah_jEYu2zwJHx5>BS=~gFx(NOzuB^~q{YK^Bh#|LAl24koH$O-?SnGc`I;R6W&E1XP2 z@&R}l+82?k?mld^PeY1mAFk`ah?`R6E9(3I)hZmOHsBEHdT16WlG-1 zV(xt?X{``43%+^%1n*L0a>A*~ zu{hU22^P_Z#Klg>3r4CfF<4UBg3b*2B@sBI9_MLMjMr)vg*iFba_gtfbv^UY9GUB z3uf~Bx%AX>Jxzg3l@~P#Wv=)K;e653`<-Q$wJC$c)5%>lNs0SH$c+rAJVEP-A(q=q zg^S?9_@G~E6{p)>DDe<&UXs|=Rc%dOo3b|THO7|7%A?Hv#m~YL<|yFf+?+!*Y9nE8 ztvw1MT6;BkuHZ(58gO}je64n3K#Qr#=vse7v$jJm$x^M>aK!jt-%bLZF-;OkH#l<8 zO~Ibv=ZngZ3}tB{m-8#unUQ5LK*?dXpD#cW26iklN+-M5^VI?40|8v& z@LV3ahzEROAC+Uee;YJW+KeT$DhhGXo~Ldh+DA~ze0*?VasH0;mo<38Kz>g3v4 z=12{a1Xjt6`C_#6&(l1ERl26Ns(Wb<(=ZoRypFhh6LijD;~W>zIu|p?v7vAzpx3+x zjxY=fcVg1bQF&C-DOoIGtWn}13I3**>7-1mb7pzpF|)E%YAmHJkfP^{tL@QhRBo@V z@XD=WR(`Cz)?~bt37T3|=64?HWPrY@YjfMw)U~WqOAByxG$O?+9eoSi$YWN)3@jUUC5%<_9ziI_4atx*26<^)IB zc)q3J@cCY`6Ly`v$?xFPsD*4!3oB-0I?Gx$bB**v5;BvbLO8;RRE`h}8N4z+G@>!D zi>^tndd%JLb@JpV@o+75XR9}nt(2u@=6tW)bLU%L9AcG_TdUs{jIB3Yg}q3laA;1B zPvFj+wtc}r=Su9u*?n)eWW_|`;=!Nl%l5M&WkcHMrAh`;A!@Nsw_{QV<}(#szHExO z&U{g7F^BlLE$tTVysOExV}ZVF6{}@A&&!9juaVQA5;T^plbb=X!u^JKy^$Ju_V(&e zhkH~rt#ocIUh{LKDwqQ{K5%|7nrc>BI&WQveA^++IiY4`cbqT=W#Ii3#=t6Ew9c6Lj_@B9qrp|P zj^HOEy8r#hAmYFH*MHgU|4)AaBKnW+(|^&S?NG?q2e93GeU$bIRZFnXO-xu?s8T@J G|9=1=LDlX6 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/order_confirm_dialog-dark.png b/testdata/snapshots/darwin/order_confirm_dialog-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..e36eea50be456bfc396cca7b08f028d8cc0cbbd9 GIT binary patch literal 27098 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/order_confirm_dialog-light.png b/testdata/snapshots/darwin/order_confirm_dialog-light.png new file mode 100644 index 0000000000000000000000000000000000000000..4d91420fbc13186e439e9c412177241af7f1bd86 GIT binary patch literal 27676 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 C>!RWS literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/order_entry-dark.png b/testdata/snapshots/darwin/order_entry-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..45148b8e741a1fd935c8e61f17bdcc400fb7191d GIT binary patch literal 25738 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 g%hO*01h>ZBr{DMe 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/order_table-light.png b/testdata/snapshots/darwin/order_table-light.png new file mode 100644 index 0000000000000000000000000000000000000000..442feec9232ceebed9d520484b7881b56988f6d8 GIT binary patch literal 31963 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 IkunSYKNmSjUH||9 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/position_table-light.png b/testdata/snapshots/darwin/position_table-light.png new file mode 100644 index 0000000000000000000000000000000000000000..860ce9fa1e68efb2b400f3f983390ba6b13a8237 GIT binary patch literal 27071 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 WYD;c;9v1%kGqRFO5>;X*!T$kuHQVq2 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/price_change_badge-dark.png b/testdata/snapshots/darwin/price_change_badge-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..735c54849893dc87a739afc70e86abae2121cd7e GIT binary patch literal 5715 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/price_change_badge-light.png b/testdata/snapshots/darwin/price_change_badge-light.png new file mode 100644 index 0000000000000000000000000000000000000000..2008a6cb87d02dd91c41b4af6a472a950071db3c GIT binary patch literal 5632 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 X{>|Wn=1YCd&n}>@qN7}^Xc_)LvJP$L literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/price_text-dark.png b/testdata/snapshots/darwin/price_text-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..9c9c10145681844f8fd48a70998c155ffe0fe5df GIT binary patch literal 6387 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/price_text-light.png b/testdata/snapshots/darwin/price_text-light.png new file mode 100644 index 0000000000000000000000000000000000000000..c891bbf1769f9f012c7d100dfdfa7f87f51b0aa3 GIT binary patch literal 6279 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 IV*U2t02e+il>h($ literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/quick_trade_buttons-light.png b/testdata/snapshots/darwin/quick_trade_buttons-light.png new file mode 100644 index 0000000000000000000000000000000000000000..34f5b42173aa438695b1b8e1b6706d16aedb63ae GIT binary patch literal 5097 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 MqWijD>CMOg28vA!w*UYD literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/risk_meter-dark.png b/testdata/snapshots/darwin/risk_meter-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..805964c394614c1ee839ec6a7cc29927232ad859 GIT binary patch literal 5465 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/risk_meter-light.png b/testdata/snapshots/darwin/risk_meter-light.png new file mode 100644 index 0000000000000000000000000000000000000000..2ac5c3f1dbccee7a94300a33e0083fba949270b1 GIT binary patch literal 5229 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

  • J=`iE(l>3p>7iiTNs}NkBBrlR}O6lbRz69Ep_5`;$+aA2FF}Z zjpVe;q_EADN+aK58r55DEIpgKV>L`A4HSoEZS@RvIi5PE1R;V}2(o+DHvW(zjXIF0IDS$y6c`)Oct|$g!k}tqrP|7)XJm;TtXa2l+$`2Ub*SK<2C9IQeKSh zBpSHvQlw)M3keQ|Eq*Wj#s;{Kyz}SXRvJPv*nCq0jI3W*8-pSf7XF-)gyY($#ulLN zFJ~R5;yenk0{s2r45*NnQEbZhXjBW>3o?Jot7@%0VP#{R^m9>Ln9?U#n3MNby58*$ zbP1e9&vaq&_Zj)D1mQH&e1oCe)Hoyp>CTz!DYq)lzJ|LEM@9Krro?#}Mpoxgv)?XirV|H5-L!?ok|$#pFeeu{fXNxdy+E0H5c;&`!;&D(1im_vuu7oCPYpku-xrgI+CsF4L9 zDEeDqFsWK|)uqWhn#`Lu6PsdG*n^tE?6W0rrQpH`ix@2?GuY-EhMo^RtwPg&ZtfOU zXxEu4~?ENQS&Mzz!M(3aGi^$?7| zWh+|>VO&L8S6mOJwUw1L0vWy4cNNsrlbJ}J+%@jvuZRk!GlrR7><`(T9{xU~T$7QK z)K1kgWGK|JDbxc+OYIAS2o>by*awsX&c?xzKDGM}{w6k`cvJFM_0)sj3_^ zs?62lmP2Ut4|p}abp+u@MM0i!(r;mDq0c|D@q6NDf)B0gb@X+;j`_e2BU_IyN(8#s zz{w>hJGx!-mW!%$qj+K&_l7Z9U4gr<$gFnyb=YfhS=kErm%FDI9~G_wLnM{TDGh6_ zkP_}Xf9mG#8%2d435hdPZCY;TRbl#p1 z*xjWCv&9P2%Aq{io9xIhH#y5sTR1%3Jm9aqH@Na{<-TRB2=1lCAtBzWXbG*M&Z@_Q z8z}|%D@<%rQAPQgR-ZthB4rmHBoYy7wr*37~&FV4S9} zO)OCv{|;KrJ;CD4DZS=tx9e$=DZw{qZtvOogJVWWAN@0_FrU*Eg}~j>x;=3?J4^0& zI5`)+xKc5!)MKP4l#1lth-{I`NNv3(Eu_l|<@)omqOszOGvX#lIgyingETpxAtzEc z^5SA{F>Fi!*I@qgEpN7m(oFipy3ezF7Omoeugi8X+!t4yrF~`d$y;+qt2e^49d!wK z*<^;B^yl*P^VJr(2k2jLy{>p$Ra}%(hHSfbIwm`gD-+b2fZb|ifUhrnEmjt}fIdQP zl|n&MIePpt4{vjx?^%QN>f$+izuJt5l8Q-s?_@r8YoROfQri6;@N@CbK2ixeC+#tC z{*cnhvCiks0^W*8`+kQQ>61D>ID1{5U=laE&mZBOGzKGjuoyENDVzK~>92wmJ-9Ti zrxbQFa7STQzYXmD;oYSgxD3$F*r2 z`RM$7j?pG4tr(TBN-daHE7H$FFOyv-VYrVy5A*SlK6CtsFsOX}ZGOPP?6ofYhpIyi zj#b{~J9{BLciG%>QhVp{*}cQxeNk?0>sS6>Ym=0l*+ZP^13k*4uAHfVR4U+Ba3(nEwE6O6Z9I literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/spread_indicator-dark.png b/testdata/snapshots/darwin/spread_indicator-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..df230e2e9c30195bfa4619dee896807ad2dff3f9 GIT binary patch literal 7438 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/ticker_tape-dark.png b/testdata/snapshots/darwin/ticker_tape-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..d749ec08b4505196a20194ff0d5679ee994c4d8a GIT binary patch literal 8071 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

    3GCFsquN0#ehdNEk2W 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/ticker_tape-light.png b/testdata/snapshots/darwin/ticker_tape-light.png new file mode 100644 index 0000000000000000000000000000000000000000..f3b79a819cd17d08bc1841fcbf7c18f87ed56a70 GIT binary patch literal 7578 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

    EuF^6sb zgR7s8PR`Qy*In!|buIyhg7sYX=e^j?6x>QmcI_WT#sb*VXiw8w#e*YhZMBR6em}W9 z^mJU$vLGZ;RkyssF54aFpxV0XrHT;(lHjYe3CXY>W25{z_vY2VV)A-^Zr+D6Yg}E`D2E2XG6d5cC>8hi5}|_E%R6 zom+&-G2(`dn!%7PR#$&vU%_eM&p9==in=U58T@$1iqR2p(=y}$JRmO}+UC+u9@t5X zmd@sT7PsaM3VP&eHlWtOoXI_*ee5k9w+Buct(%Rnn`KJ)`uBn0!Iu&(pCo7Yov4qw zY>kZczv#cyI5V@?wFI#<8S)U=`0p}}CHL5``Owrx*&)0PzGCwPW>KbY)qgC(bzidy z;d?K90@h>~@+i*dYhzpPvaLuE*w^0cg2!0!>W;D;mUf%*=PAOK_q=ycL1vLnw;9e@ z2(Ayu$G<&XQ+Vj)vm8hl9#9VEqYma>x?PP5nJWxnTp<(#I~QJOiw(8lwSY?KUb)v% zlC|mKki~D6{27=&YrTSgrOwo$p5#uZVS6AlRn&|vPi8KQrgjD6SjL``k}XDnSMQli zlEt)_>_(T%-#2)v#B5(5hP9+wbW70CE<>mlz?EsPcx4x znP?m96fjN_#UqIdaoNMD!iN=Nzo80}^`Kt5178g@*&lE8Z~rF}gw7bO58Q@OLLU59 zz$1k1PKnYMDP@)s+J$*a7vlS;4XWb^Nc>8vZ{KET>i%LZVeLP-zHRxF+-0}*T|mXG zewphtX@^WDN^T1`eR3hwd`a!x9ezTM?FK=2^I98fL>&)Cz6H^6P6f99-|}M*q_YsG zz+R{J$!BF1uRj=Ny1G?RB~?YymDPrQlNXYKK)C3AX)n71wO>;o*B4HV0zZn-r~M_5gb?o z6}Qoe$;mXsQyxE}ou>%*y;XR)e2YNkbK z=np{cXXiD!C9v3yNf*|SQ}qxe4$x=N%Fa?V^$n%Qw%KH9efW`lm$7RW1&mxc$jQUd zGLR1k_rsh6OYn!`TEgV#kD2Y(EOi5LC=k26-W$T}dSCtK1SIr-cJ~7yQH`!=it~Cx z{R6BisggK%#gPdy!O>sPx%8zB4W(<;u-N*ht)Z&A3_>=#EAVA&M`+c;w0(KI*W}9l z5fmPa`hN3^u3>#+du;ut9`wsAiI7q8w_HEm7v$Z{qq9N{pr`N`y-HXVEH&+XcR%7rLfyl6tXs0j&q^)?KUn{>yY5P5w3#Ed12f=KLGwQx9I{DS)Xw}aOTS-{}kxu|(H zXK;FMxA3OfqEYb615RotdZfYmlhy_yI!P+!93lFX=u8$F3qBgcT6_C#`Sj8GK0#Q7 z{t4ePB&g)-T>RCmoSYN&oq(#!7Jux%0zU)&rbt!p6h&cU13UbB# z6?bku5e;4&H2!va1uos(?qNQ(OApFL^(1@{!38N^>QX6T|3C4Z@h1A8u1>e|wRml+ znJ301k+tV3ikRCXTz#ulAzs1eZj#w2hn^;Cb2d8bP5YNBTZOPmWL}oaA} z?{^yT!{d0F+nt84H5mS3g3-`W7e+G&zSONt8Hns;7F)+fq7blE4sv{Nu5t7CGq{wL zzSG)S`?cc1w3{$4yf9m9{UXtmm@DE0~1I0-WJiy7hbsTs(r{~ zH0%Ak_5f7>O0TbXuBZgOBhwJg;1!mFGP$~8WANTl{cJYkn)zODA4TV)!Tr>*SAA?5 zO+KgNw>hU^d&7Dqswzi^#d#M8b2kN0Tm)uTR@+hgSsJn* zo7^L1F3~$+a$ep!8Bmu0v1Sbh$q>lKHiDu#AQ zok;uRBqn{>6sx@?a+-2*^q4uKi@;|(Y2;s%o0PH~yR;C)Jq!X4lNOt^;IvOiC(Cv9 z^YB4rDvQn-N@OIFA>SIEmE!||{d|5pgYx^sg7=VH!Z}s1DYYs!l##_dXjx@i`&-(+ ze1TT0;sPxYsAeU4!dp^8F;j%T=6_(#0)#>9-gMB*bz?J^Xo|28e?7RMXILi!mD9(0 zA4cJEp-vh-7E&))!vXaMtroIm+DPMH-Mp;0eOVGtzyA<;S!7M0vxDvY%XHsA4hD(~ zLz2^efQx4yl&!+L7mF8K{r&oXohJg+ktD{nUCV;8T=>7?Is3r)fEyCi8hxPL^<2Uj zS7w!e7zU4AdyS`}w7xIU;@U{4wA6LZDhif^C1m06o?Z71EujQLy9#dNtUSH8c)+-QMf&whTb!RJd+m8SeK@xE za){{=nJQBQI8vCp989Z|i46C$F(QZ;%3=AE z+)dRk!vzg-@WPC8cipU|Jiw0~vkGq7c1&h;o7#q}CrY|vc&Y$)r%82>!OzKPZoH@UajG^bidFNPf3PKs^C5g- zoe8#dENoYK^^hfpN;i+z^})c8?Q2eA%PwFjz<2Uf|HjF{y=Gn`gNitV%HYYOWoUma z40#>3Bj)!@0uknwg>TwLB&q9RCJY}5(;3Af&TcXj>E?#6}jWd>7znK4pDs#;l1fX zc71z)D;YbW6>#P?7tWQhPy}dxXfFLXuv5Hko;UCZsPI?>KlA`_M9Zpl<>g>n*$qiK zISZTbR;eI@#NhIB=W^ZL-Bsi`yRY&>(7@8cU`_w#&!6%bt3u4YnUv9AM<6E8fpM^v z8yTRkcPpIir!j?NMP;DdZ9WEpm|XtUGKc3gw08Me7I%D`Bj^*A6TM4l^^UHnS%PtA zoz=>SW-RmYFdN@W$4v2jFdTY?v+jMbHC%m=GI|m^>rrpq*yfbsuAd}P3| zR`1RSLJvpPD(^SFWC?_u%SwW zuq$dZ@WBzqT&TFN{UASMfFT1WGD6F{mRFeXh`g-I(?(E!DgeYRkJi3Dgzr$vbv40V z+X`@bEGka*_n@-`N=#sDWJ3<+G-TtiX0QZ)f)d!y`hRY0`u^Xd!}#x$gYbh|U(i94 YB~^LcRjh8n@^>J4X%(qTuxaT30HN~B5C8xG literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/time_and_sales-light.png b/testdata/snapshots/darwin/time_and_sales-light.png new file mode 100644 index 0000000000000000000000000000000000000000..813e949b628d32fd622438c5cce4fc655f1e1fa1 GIT binary patch literal 27613 zcmdqJbx>Tv_b)gJ1a}DT65QP-XmEE3P9V5@aEIXT46cJSxVyUscX!|UefMp>s#m-F z&wEuXx98rP+kI!IkAJ$)sR>t7kU~blM*si-$THI6DgeNzLdaNPZXP#!ltEn!w4hqMMq{71+nEm~%^DWe^Kh0`dqpj&!wf1KN0t$^yR#%xz$y}*V zO5~w_@{a}$gfOI(+T4K8Y&2nGaA7u7Y(aRG;pU{h!@4p&JZe6PtM{LLJI8gh+nw&0 z#rIO$Czt&!UnlrP(4g^-l!l-ZiAGS&LP6h`^G=mqY54yiyIsGa;>Y*+LplVvYpZVN zp-h&u`W?*?WaIuFID;#1Cxo=HCyuJ8JUqTjkYE6oD$>8R^1dIo!0>1D?&@*CDJ&h^6z-vgjt-abPG?qI5X5@8~FZM=^4 zZo5Ad)=*K&D=+`vNH!EEMwfJNQD@1qLc%sMWjH{Gg}^+C8jsPN!mL|pFc6Z75*3Tc z$<3`!gJr$YJej&xZ}PIAXU+%6wf;4p$(vMxOw5-hYZK7q;;{e5vy#Q{75|$U2_abQ`}e>KsYgmWfLs5QyU8WSb@>~|uf6!S9hIOuAAzwxYj>MTbJUWVRpl)U~#3Fdu zd5&HU{+uU56A>Yxs^dz%EmqNbT(?ZmAW)Px%k~SjGu`X8v#qM4GFz%v7W$%+Gj1^Q z4lpxwQ}82LSzczu2p?G1I$L`R&pP9|z8-O;V!Sa{`7jrpjXT zl*DXR<6>&6WT0rj>0n}|!>4Xf%L!mk={4eF5H#lc>&A8?Sf$r-+Kv+=eeeER6b*-YfV#L4-BFANW8BHZdhlM})6>(<+Ak(Xp`xlq3eAz? zJLCwo3xFC@fMYAHt@D{3KB@*>PVh4|Gze2s0V}k@KPWN2z`WB_^DB~~@$s#Yyj(}t znlM%wjK3}p|GO<0E_?1?t~(eVrJKk^hWV44+Kh;Nl%Mn%BC%#5;6uJ;0AWntgwsopd2oh}2{9vv|*Zw=yvB zPbm(C306^2+3IjC$jj>%Tl63z(l7ol#+!-VaMZ^AGC#K#87GTXqf4U02shv&Up|5#3{-&4LaMFx zrJ!Za?B|FHmq!qIM;1lXZS+l!Pk%4n91OoQQZ176d_E%`ViEh6Qhu@a#qZ5V%samL zz{;?*a(tYzgWnbEj|i!y)%M?m&nctU*4D6pX5z1zUt?QZI|!V&NhBphNS=OUhW7z3 z_iF#79`d-MHo2TE78P5ZuAV5m5*f3DHL;M9kzu`bK}8IWjXs^yqnm!*y+fBjbTpKe zm;1s|2)Mn6_O1#{;sLpZg*`nzr>AaP(4tZJW-4lG0|&yN|5TlaLNp~Lm=A3z!>t*g7r$jJCC#p`^?9ujA?bv84a!X6<@2lzL$XFWb%3HZ0) zm|6wg`*%6kv}m}p!aw(6ZgA4XXn4O-OYyP`eHDQ|>^qY0Nf8dnEiX^VN~q2j*k7l? ziu7vHBL)x(VKkc#_dIAar14Dqp9YckLNTRy(Q;N+)W0S$W_GRa=zy-(! zmL6UBsWF^WP5NYm-K%*b>I6%x(V@kPKFKXk7O@R1*4y=Sb8F?L zErUOCvjiNRNhv;eLAeHsxthGy9%z7#bHRjV6!_1UrZECTT)S(Aq11tvxA$Pu>i!v*Z>imGeL_3ZPQL8Ch$jH z6y8lr6-3miUK$lj3f%w^25jq6lsUs?-X~vvVc0*-emNJXrxPP1sv8c4$}fuUMtFjr ziN}g)a6w2R=*zDHPuzB}u&`=sYG(SKaXE&4d)GY_#!s(vE3{_^V@agY#63KyJf1PQN(oN?R$WIW;l@-}=nV!qn7myT?H^LGW&{|9F+AK5o!wW%+SMA0Mh2oT&VC zx-xDAM)wCBMn-u69Aa#obfJrj4~}wm;tOqc37-SG>F{>&rZ-WI(VG=us&LwXHQzHM zTkac$TKT$m84=@`rXLs>%<#|wnQPv$sBOHN3*SSb7#YT1QP25aZ2n#|28yZ5-VB$( zu?3~^FM1r!^vfo$dgI6&Qmf3m6D?49%CWgmR-^kL(t3E8caMbWQ=}#mbuaiPT zisocBk&$j6PFJiRM&>!N89KdanVPo*KI}|wL~d{GDJV?V*4O36<%YS;@>ELWaPqyp zs4&0rXsD~hzEVijU_Cwlo|~PGj*8m4c{E{Ubab-I{tz1L3u>@xkQzF=XtY^9`e#{P zUF}D~+*wmIG-+2}dX&1_6sfAhv>H_h(INj20f;Mep0`5PU&lGUa+jbTYT??cY#Ltq zGxg7HA#U*F0}Xn5ZDxV~yrI5+>Uo|rj1-Ow?BCDE#brKZ3JQTi2{h_6#!IN~#41(O zG2ApY=aQ6?${-Chynw?&kZ^9r&iN=QC>R}CiLU~3hN1TxJD8}}Wmi?Tv|M+F=`p29 z7h*+7nwZqFCK&ZRvwu5=yCy7-^=o(;f(LPtE}g>qeXN2~Q|*gORfigdW@g!6QHi&% z9vQHmjzCnxL6V7y`vmy--ad4@FBg7jkzSRRm8Yj0zpb_@sRpmzUnfxsA-*JebZ=lF zN+0a4>3b;zxO8vR2jAnYGhs)1jgODV5b{1YjuJWs`C~X+E-nb>2ru$vnud}NU5t{N zJ{;#O(X@g|*wO|PEl3uIP1zctheL!4RgMazV$;SBis3NA#c8nEa09*J_~Dk3lVGvn z0+0|nI5_0wv`o+7Iq=UGi&Qt>7v^3YjuQDb>+7?9Kl2unDE;gX_%g~u_dm710B?Td zr%PJM86#np$Wu}(<@j%F6)$prn1toWe?r;>@H7za-ZLY8I{{k!4ET(Rm7430jER+y zWo}wDaMLUZP4=N!&B=j~^uvTjJ0T0QHh>&mA0W3TR+}|9!mf||?Uj8(0%2A*s1VWx zjr8yK{!HrOZE=kioMfp;(q#JKO68W@5=V2a@~Q^))dTgV%H^eJ>0+h*lB7W@D&2p> zlIu;s5Q=$d*$Xrz8g-@q%${)LI)ESJtk=~iL_oiMdpDqT`xwQ1I_iD9nE23LM1B0t zAVd&3IdHx^Ik25hRJFYIUzf88Yu7H6rBD1nVNd@M)j<6(xv>#)z4u$TQ{3EdLff_7 zet5E5vSnaoJS*{=PqtWKm!0M4lvq_ipqh=1?!J>g%NcZo=h8{pV65%!8A(Tg74<1_T~&9OC{dnkDHk;cWt$1SU_ ze3&ta*)iTW&VKKo{gDJ}Dt4>!t2ymwdoLl1mp8l%(uXJ8UCWt-c&)-hAetCW1OoJD zL$3lJgoegvyW1v?hQxNQ{fCz`?lYW8!!h3MglBs?;ST(mohfOzMQPv8kG;)~%qQ{v zf+8urkkZPkuj|x&9>=EkE^_`NT_j=b;Jd74pQjDGJS7_JNHaF=%l6F$w+dJl6hdiU zr8f;1HRm~z%`ON=Q{`2Z2Nw%J4@zN4?7a(cANf;?NiQ~3(Wg{TMb?uo|Fs$3@c4io z;+7yq6IVhH`Wre!(#q?6vv65C7phvmS+-!w8Tb}h`@D3zc3S7hqx+uWSgUnP=+vn9 z8}G?mynNnV7qs&*Sl}VXJy~IqY?KP?cblt3llTMpB=K}k%S~4JlCzEiF34@py$jUP zZHgAoOpQ%LhDGkKzQLg|JlwhC9dw#Yufdsa({!2apqdyTXGOw%mD#-OXv6ftD~dw& z1OI!Cy=gHNDps8GTY4oU>oam|+q~?comF!O*<1cR^t0$2VhXnyzznjpwXIrQ$S|AW zi+2gy;hBu0MuV$icsV!RNTS~b7R%nf+^O4XJZX`nQ#;?3%$1cKmXvXq3w2!AdW|ry z($7*K!jmEOj!jNtilLYh(s^_g?ml76q9-h#%=aIAS5)tx;U`I|d$y{PC$+hq3%+wh zxo$?SuLw9k#s$5>hx&P@?lg~4v$@o^-hMx_eYoaM^Y8FCH34nqk}(NQB>uubCfW8w z2i^3toffy}thD}KpgTDnDj{1I(TF!1VIkzOtjB*BVdG=_!93#;?BQ_buy3-z_NtdN z8M^Rk|J27nHOv-l%z>v;*fL-#Vw`QWG2`W&~oz8?VdWkE7pB z_8zU>86@nDksVK|P+z!?aP+n3ylc3Vd7%E%Sy<(O(=MG;%F~M)PrI0?0^Du-v)*Kc zLmnY5F`&qnE$~d)3AHStEKX&-eafat0NM z7~E3`8&7QL*#;3r%+BN0-f`Q?QM!H7o7LS!g;;5rnxsZ%>AykvqS`HalkaNAD#nx4 zf)lLNgAO)~HZBW%zR;rQ;yA@OFKz zCr_b+g8b;mQq7%XcsF@oU`9dsl|`3nV*mB4l;q_3k7^Dk`X;)v8RB%cSXwlA!Ta#* z0(1={DnEZ&Sz0|>Lk&8t(AZ4ZNm%E+b-LcAFP`|E#a4gGd7B)clz(y1fsDxC$&cft zOFV>w#K%$PmN>3K^Lvh8V_d;_AFp} z#wANrt)3`npZOC7kPg96tP%Uk|F3k!pTNjJaqh(ch;_uVUNeK9Q2rwBh@T*yU@k@^%ezrGD=Us%XgG``ia@Uy=^**7l*3r6478c4$)krEYx zrDhm&R+Sxrv3J)Q86iaG)v4{q_Yun{3zG)iD9TGq5Z5>7%J9FGg#XLPWP=Na1k`;8 zc_M3)oFEY{jChgzn!rEJbJ3r-7p%~~9xv!LR9Wh;tnM{J&iO_iFFTy_J1hONeD(4G zgpx3I`p@~GFhsb|Od@|6(2|2hhO{>(WgN8vzSK62wohE}`i%*&-+1R^c3AB5ChT@% zxtiB$Ya2|zfwk=kH5cbf%B(%#SFi~OPwI6Frlt8jV}BP9goNl+CRd<`7~w{cy5cOu z-H~92kn%*tH=uAPu5oh<8|x^mW>l3R4SJ?6VB2Knfzlxl7tokXo-%>ZkGbJ{S?ZSM z7T$|Hli$J_uPnVaJVQzwl6vPd)+2Yu&p+Km=4&N2Snf zC&yS~9?RdhFaYJt9R(9)G1|x#lN;nE=N`yosD>9 z5R@(zdsQH|*e(TJ-bi@bJZ0c_U0GY}vEM`0Y3Z`tr-aN#=j51O)30h6jBKAta){Hh z<%46W28Q+``$$sr*(>hrc|kR{%Siqg-*sSmll*7r#h(k`@{9-CC8^{%YKAJ zU}(6NPlzs_8cj`|?%{0h>z%Qjw7Zt7$xgSRL+JK>rTal8F?ohu(JVCv)bj%>F$Y?2 zO*0W#Cu)FOvpSz0SLW&p+~oVQ@!=zG!D2q{)zARkp;w%p$m!Hn`C-8#4LfI2S~)C& zO+uz`B(r}!8K;4%N<-=sbTpczP2#fvDs|Bbo>?YCq5_sM@%N+ zd-usqjnRWb;r{QXo~!uCP}Fas7$GK0d-DWip1ncsn^Rg9uhIOon@`T$in>J0V}D~e zPutWOgzUu<+(zU2$%&MFG-PE*!G0fu{gEl3p`hlhkdH!Emuy#;#_DDB(9!b>$RV47 zYI5~W)pi=5Fo1uOw#30=S)3p0+<8jm2@?j*T|ZfN_1j?pCG%D{Rr>6Q;hp3NU&i#? zXdFjOJ4F5+ovky|C~4}hI+;4@uHKyznn`>Ch!m)#the)E#Ts8GLbN#=^{_YR4?~vqHvDJREFQDm5XY^TiULW2U@3D*b#5cj(&=^48x^ zuYjDINzIedq~lX>0H8W2)_w?Z(tqbzJv@ROlO^xsNEs@2r|sg>TJ+6F#j&UD$w`_d zNS}LYi^rgRdI-yL=2Ia;izE;RP_y(KNn+K>1~&#hoELE@Bsj?XYW-UEK;ik%f0G)Wj$T#l2IPU^bO^yo(2K9_44hrgm{T518Wt8`Px*Ft$L{?+5RU$MV$fn; zL%}}Wo*YQ=k)9HN0efblh@uhaDDnXeNlWI@=#4sk-_W3CWaN4r2qmTqAECEd#eATa zYa`<^W7?ap@6Ix~Q1Mv3dkRakDcq7Z3LNrh)3RJyz5PX28+6+h+<4Dac6WzkVlLl5 znjb#WM|soA7n*KRzW*IlKe1*y_i))eulY|wKA zQ!FU}5E5a9pRm<;G*ktm6a!O#9p_Ak$hW(C+##1gPN<|<&9Bcly4w`v7m+H#5uj*6 zqqV>E@-`J0Gb`Qu`iCb>ME(R}OwVlKP7f8ot8(8GtABSlu)kmX=!hl)qPe-DLs^iI zlbf@L7^#&ZpMO)OFR(Ud;(RJZjK$%j3vd>>tGZ-<2A_dqr}jTAf@}}dAGtDH?3+uk#+MD# z8j&VT+v!g>^;C_U(lOCs$pZU^14l*@`zX2dR+r#+zW4OfjnX^2xTx?t&`|CeuXGD~ zMIs`60u(D!o^RX>;vq?!s$hvCdHSHn&C|`lX9*Wlena=^!$1gjWd8^O;?U61uw;y5 z$a0?~Ig-oJV51`XG_FIPv5t@MBZ;y=A7LJa?Upuyt4iuy29gET4Temcud|x_8WT_U zs@m++^sX8fO!rzJmq?_y-Dv^ADo>G>x-RA@R#rQnZqDEa&X^tGW%{eY(Vv>YnwK{t zZq{$lzS_$zv$Q%5-?pZ<8XFrAzIBMK4YV-fs7$`s+jUk|Rb4Ke6~Lmvz&xNHZju04 z$Zwa!S*JTby;Z=T*y>LTCnQ#=Tc4*SX9>89(O`%7Z4;A6_HEP77RBHRXG`1Nco-E( zX7RhUHrHHkwZF(*!M_E3_IY{2tVa4Xa($h#Sgq*ETI7>}Sg9xpoHh`+*@?99Jw5q6 z;--Vuo0QXj4jy>fdr0v0wLk93O}eQ>Eb*t`|7C}T{eGFykx%!KqZ_B8I@OaB=5!RY zKet?+GLS>==uOVuiKiS4MwvI=g9OWjPKT7;WwLxDD4PTQ^F)ozNy2(#-}FKrB?p+UP^U|&1(uV3>i^cm%0gC~GLWETuJRVu~p@2oL9wop*t7dpNVz%(_U z?Z7^I%Hc{t%+FOhz5Ze7+T_USsxo)WWLRf2DBrSDk|G{0;|CZu*K*zpC1upOj=wEd z#pF9w!mxAxtc(@w2^QnZU8P_S_TIjpg1f)z%WLz|37RG zYCRLbx#&mf?Fp%gxVCtzs!EmB7oF{n8UD{uu#0k~WI@%@-WQRV=#X5Rh& z$152jZ*0tO)<=IN~wW=%B6B?LQtkhA})!QZiER?5#;U%UG&)!nzNFFGb!=-lW zX4vH_D+!t0X68~arwb~DI7+08kuCX<8qcoo9Iuf)VR$qdOurd|19w}==Lp^CDqPk_rW0TT4d z9-dwaJGq`X0r~90J_LZjHLjSItIS%fzV(}Hjr@B{-H64K$b|QkKtH<&i?xYW+|KG& zg&lDxLT*aa@wTKh^bUUCe|>w10}I%n2F;ceQ;H=86j6@q?)!px<)ajU*m|g48V;Q&z-)1jWle+95Km%q*{D-kRwX!$Yyprwr zk@1{$+RjO%+F+*FtKOc9)nEkqab4X`TtWB8kR>;mmoLOJ{Hm*SXbT^B0FhT3F{#9G-?#6cpo7$g5## zwXp^wmJxAqkwV(a7sGsj8X0b9>7sT3fD+Bm^KFSZ)o(XnJ}cT?_=@_suB>EJWUQ`K zSsc*N(*XeZNv)^n>v&G)FOM(7>tCw}m=;Rrsrvf?f2`9|^xc`N8B&>5ht`97mXhd& zv>s@)6sQe()D%JSD1ghJnoFFJU?_mlT08tvBX}6XWp;P**A=_f6#a#h-xFqBflu%B zvb(nVwSiI$={#@Z`yMCBH|_&1sh19{TRVN;i@*d6l-n!CHt#&2+&el=O+)7Pn~l*( zm=~DmQNhItzjiUz1YH$40FTFBK0)lq*4m=C88HI)Rf_DU;OiAP17Cp;L%k4Qv?KwS zxAcp;y88OmRI~A(3W&(oWY~rwW~Tvv9HKdKD5UB`qZh(}|Axic&Hg(UM?!?JZT6ST z`%8<(6GLHMSW!rMaope#$9zk;oYt$|d1bvyt_S=K7}|9_AfDj$VJ$%`; zPxBpJ8k)ovfJzLU|EQhp*fZu^b!xlhOVuaw2_#&hec56ILd{IaiyV>TJT8;Kx>jA| z!GliwiRI9Pe zcd#Bdm+JDgzgSHYKuQ}fGtFLPf}4z$BO)MKVn+(WypBD!h7<2d09;=4TZl;tN}d1K zi5>`7umEWl2D*RJiG~5>s+UKP56ok`RFhSh6?7q5QP60qSNVD8@n%R_QQxb)iKr&GFb4jesBzlOD(fME}yy8} zR78NEUAg{!+xcyoQLuOXBlehY*ehn@`qfmJ&%7cYeudS^!2mU6bKQ9n^RrwCpWe~lW%%I zi*KLXY$kO75&tHE-j}=hfTmrka<=*O{f9Bev=jqmgOB^hZiyHL8!L6(JRF#z#xy&> z&`61lRTgkZ<*M>>Sj4-g=$y*V)g)u z?%TG@OFAK!X}|BM{-Q&|lDU)a4`a422jZOSs#0FxN1BBGsEF_*GPaEIZ^UH5A+4A0 zNZ$%-^R9k)wvOo=O%Y(AyiuyskQWqd{iN=6eiw5As%&lLsh6YnpPAGyClt#Am1trg zEks_v68t+8?pn>Mcq^OOH=Q9QT#3zol>S;=4a5;*K(v48&`a&4zI)7=HAKF?Bs*99 z+|+KN$TMSErMJUUrmnoSx1X+>~?$!vI;;5A2(-XVm4 z!2A#voo*C<>PvYhr>*Ys2kaJH65O(|MJl3w$`Cv^Xq02X&}c> zZwo#qTj_tm(mPR)AQ;FL%N~@Y0WFcFlT@s=;Gv_8=fYx5<%$O0AK(WO{SR&Z0tWnHaUqwR-g+(U z3+4Y88G{sBTB}!Mu~k`w;W(^BUDxJdZoTZzuCj7LS+8g`isG0@qgcb{%L!kE%~xow z2=a(9f=K!wT4u;-t{50%*BdW6DVOBA0nSC1M;9+%)YK1dIGe+xFZ)gxK7{_KfBrw; z49q~YRtwgE(+WX>Dy|Q3zcF;_MM0 zF;9#tXYNO>eO62tOWCb>w1>n>vW1?8+^j~9s>nYmRW^5x8aeV8j&0ul)R~S=omQlKYc`iX}QaXkt|u z5B(%QrmwMYIoys?wCNeKK~h-zdzjEUPauUCXY(^ z_BVbH3kyhHcw3`{jZrVj^_5ucLy=Nec1c4Onaw)3#{!f%nm0-8pURU;N+#)Q)dGv3 z_{j5UyfIfqU~UMZioZD0n~KID3I6YJmD*sdWe}B`Jaup=iGb^^xV$`Lmcqls!<*-U z@Y7snVv>i&Y*D4kFD9{}Syj+gb)LWfrx4vzAdt%W%urRe8d9)y_0*|U6qbhvfKNY5Pm=sJ0++<{rF zF#XHrAb;}omQl+ojrXXkkwKHusxd(RHrGFX~DkiOZv*?d)*K7~OS%!fxOE ztC?8q@sOntD_Nl%gEqpCm+>&W97mwZ^B7AbkdRvIg1V?qNywXc`~${+XK}%1o-VOF z)NMw)f*(w-qG^}z?3ja>QEH=Xgde@RuT+%)wTwmPM9(x|y=nEp{qjS0bZl&_UWd_h zf`R(m{^>-u8+#h|MH~Cs``c-`W_9(e^LShVdQnl)*RP+k@CN!}IPEPG6 zTiUO?`r-w7Es;3Eaz2rEHfP)W`*-PzJ~lQF6xORNw#62SDaqtPyXx~_T3Rk9($3D0 z$Q&^ybwOGN`dQRT_DlSH&U`LYevD6Nu-guwX17uBYDev{sP(u^ z>ZE)+A}Cz#@r6DA&G3FH-a$@ScvU^1WT%!fmor{QgkjEM#(mZ?nqwY_2`Ol4uHd`b z2t&?+3qjuY0>9X47t_#ID|7~;Syfg_!G#YzB7`8b5o(-gy&t{fxLs@rJ0GTk!K;b1 zWNPPlD_{#@vBQGco(cF@d zO*V?qSc)KG!T4{~#i{A(gpWp>_h&}d--W-!`MjJx%#}d+T(Eif=H19V7DF1Q)3T<_ zkdHAW$`G%qPQZdN$g-nDpzv?ECv#&+^6}aB<({Axkr(KK6)E-ff)1T$GrMmpJl5)A zt@g+7fx@YItw!H46vFJb<+8FNQSq~JhRTX1!kE0Y{Ll?@APL5e|JI?u_@jg!!L zOxUTz)`c4pwCL}RS4G0X&R45I-rmd~ZtB+MMQv@L$v9Yd72(M8rfi4)io)du1c(JG z`3gPZ3tTC3;Cn~}P{&*-ssBNXmxk2x4M$=S%4u+Na?UR-D4RU=92q2U-UTmn&Mlre z^Fb0NRA`$ktr|>Ha31a+N6xK5sagS~EJ%@pF6pmm1o)*PSy*m-R%e6s_kML=OC@pL zs^8p%9i`@n_V$rr67F`*cXV|Z4;6D;O5q1<=44Ysq6v=snw~c$>Gn6bXmi#bR66_EVBGAMnBx3p1;e#dX=ox5^waiRRY^M0xa0|vMA8>DLWF2t9kMxmbd1-Q2}(6tk#_7`jBzZglBniu5r_Dg=*l-F5M8f)0HlU!9BI>G+q-q{LBPMpaZ{c4R)@ z$)hE2F7&5A0B%Y`7JK7H+;fYn@bN>Zrz?I`-xPBi&+QC@P07RxhvKh$Xt_#(5<75+8rD2x}viK*-Nx{zhS`xyF} z%;E>m#znfByg^KrwX?b1>?0ylCdCZ&gLsn8`=cBAq;pJ~8t0#}$z$8NkGB&LpnTSJW1}c9ETiLBi>ppjt1c_Ef+EAe7Nk2&_##Tb->Fx8LQzN2 z>3xs#V7K{evt`z@a2YiiWmiZ9JpzqRQK7D8 zD?>MaRz+5`_9sgbq$}<+WLHWxCD7^8#}62<>p?xF03n@q2C2s_S-+Z@-J~#0Gv`mET%e|CYVw0yu)ktS zemo{5_!^gA^jLtFdwryinr2opjJMH5FCSlzM@9}w{LDeA3B`&R=B8X3^2M`Kk5AfH z?$~mXMFT|yrKK?n#y~L-zU#sQEkZV%GT)pOY!b}bqG=u;z7e_+KR(yBiEbgwo}AW9 z;Sz#rIXUnB@!K@+S)MF!14!6p%bV2~3s`9)qO6LY{5CH*)Zjb*Jvlv_2%Xn^{6ib{ zl1)y4j@3``8kLi@d&(+ULnpdDYF- z78{byQJ*PL%P#G-<-m%YEVQYnq=bbl&2+%a%bOJ)+36?za=z|`z6GmJcULIW9f_SV zD?>tZ@%Y#mfuOB211u@Q{iRSle`7Dz|hEDPB^EXZn^Sya_3!cUpMCV7_h&FzU9) zid12u)PJSAQjjcaFW718k7T^9L&eTGJ36z`lB&T(;MJP|-k8=!5pYAhx{~-_*KW|~ z@UulrCb)a(T&?6JC%SuJ?;RNOq}a1Fj%$#nf=$t7H?sy0ZXRE64z`)!<5PXlTH6DA zLvyO!{QUN1_p3dBr0?aw=fgL zk+8c@Zd^Z89M(-PQ1wv{WC`x=?8xs8Su|cd-bffrp&a1dD5brla!Zg)-Ku5jR5H=h z-d$gFoZq!q3=PXU+~J8O83@)vO6+_p(%8)*Km=$YpO5h--q~~NS(}OU>C+WBvO5sg z!}EvdblwNT7z(6S31_Sq`FT%M-Gn9$(>q|3qQTt~ApU3QzlQ(c*3Rd-|FbR8mEJld zMr%vmh(nX z)LlzJ-;;>SPL<3;A#v*ert3vj-Bq$cSw~v}4H`*H94)A=O2OQhgE>l23|e%KK8Y_2 z1;%r7O(OUU&WkUtm^O$Q-7#e-39DyqIgZ0UN1{fvhqe~Dvn#IA%@Yt}pLIQLz zF5F$r0(0Oa1G;2rqV#Yn9Gn6J`P5TW{2oQxs(@br|F+J)-o3vNq2BxH?N`lka1WkE zF?Kqokivy$==KHB#N9xl3RIVsJeu9<5Dsd-U9*Sw`WqE)nDx{g(c^pq#8fOv*MU4u zh1;iVsLw24TU4t%IDXrV;jkdF*`@^E1@hBKctAveTbtDIV`)8lIkyV0MivU4A-Kxf%Z;(2NQ|q*4tZ z>@oVMJFrvtW(P!~fzZEA)cM;A)^P9bMQR(9VBQKKBH!TbcUtw=!KBl$=|0jfx#3s` zbNl`wQ@eVRgx|g7@fjHah}m)AcWXFy&SBCAIrlqaXEa!xxI(z??Uq~FaMpF+zJ3{6 z!ED}BQ~mHasz6)Yr`@6e-b;MT6@0ugrXH!N-*RX<7|1$PhUGH4^Ugc-0W_iK{t!H# zU5h8kh$SH<07$pG?@JFXPZp2MYd3Jd&O4l-oV9yCU=v!P$LwsLE*DNWoW6SZ`&avc zOdL9*-n18iV!wY`>$mt>bH9>#@u`-n8Q0RVI`|FJQ|>kl-oG1$=xaRpcTE>S84}q{ z9w;Iq-re4JB*wu5XhxWGl}auqvUX_D!ZQ2W4^ zoPMu~!vaE^>$7z^ojE$dW8S*ypUvqR)RkqQ0W_x9pqZIpb>^N=&&|z0_Qj=Wcdz-W zs4mz213TX(8$bwI_gqM%cQR*%P=GdGhR1QEZonU@>#EE1GuH2tl$DP_0=J1>v%145 z=8x8{{%Km%p|B^+o>+^w4WVCx$xjzG{}y`#3~{arjlU`S4Ucm3z7P^xCkJoi0 zEyhT;&kjzuJB-hz)FWD7`TJ{#DrCYMK%nQt$~2Zgx3?;^CsY_IM!lh~ZG?o6HR#R_Oe&G7?H!FKkU&NhQdP@s%G(MGzp|*}(MA1t z%ly0DU(6l4lQPk}MFlO)op{Q*DoBLQKzOcfY~hhWg2joLe)A?bC_rLTG9;RIvRfq2 zn-u*VBDNUaX#@Z?q?q%SO0W=ITyFDYerk?CkM2(PP-r>BAZe-5R^MT@DA8io!Fp%v zBTE+ORrbJ(l_kFLxK)`y@_^MxPI4ji21L1oo6`mVSz6dl?yHSh%fS9Ace8u*y&IWv zEBK``X;-=bQJYBjHD&ba989u7$ZfXem7~{ekKRbSab3xe;98=mrr`L6auX?}aQq&pW1=%cVsM3QXZo_)-I7%DYHAzI zSkhQTTvgLI0itMwD8!x~kM?$khD%{{nqQD{L42OdgLDMrBUTU+b3c9m>BSsRXQm(k zd-y5usa1zom1B-TPLkTdV(VX@(_cEXbp+T_m4TYtJr*q%5%a%v!xt=>q+FC|Bm`)W zpjeXM;?J>#DrJyL*QH$B%y$L%x}v9ERBST~!;ompz|XcyQ+T_Yt)g~+KIPh3*Kxv9 zo!eseh$$9lwq?eJ8{ua3#x;W-PKn$93hSjsf zjxA9`T)TVbf_P%U(C~=H&@O9^H_{8apubq4L1+s0bVUU*ijV>WOo4oLDDl+Mu(}#{ z*0cdsqw6oL`6fX`;q@@S>U>YzCyLyT$P_6{AuKEj#Zb)M~We_fUp%4;OF~m zn45)o-yjJ-CtZnd(}&9vYnmK(#(b`ZTjgD5X69JRPh+jae|g_8k`r09E66^5U#!xi zW#MkHZ0KLKgN`B;EzsU53>5iCigru#Ptk&9Mxn5cb0;gC9cOpn)7^uYhYul0fhUHW zn``A}*w~*mOwuJ#ga#T=2rLZK*RxG~VBK}ut*4=;U-g?J#nG%UdqdJ_@Z!?+f3%gS zy8WZ4j|#AN!f;Au;K!C)_^F-z1u!&6r%8=|%i#Dm%z;poi?co@X!lc5$n(8zZK;gV zgl$R$;wQjY5I&%5c=SjVD)h0nxp!Jxu_zd^V2i4zvC;RgL3wykv8OAN>=`LY)!OmPbc(JbOn4o8; zAeh}|vFe(N1o2L(!-eyfoO*163OG;8Qjs51w(7dfZVET zMgF*WS8}Qc4DI9`VW)dv58l`6zt5CR3H@fERw*xb)HtVKcRpz=pBoSt9iIsKV|Zgj zr=Ei_K**_u#lM>StJ^{jn z-L9Y8`R!?DFzNY@-?I2!zoSZ*Tk9Ft2Xt92&rJSv$(bvON6Zw=UDUjKe61_}#X(PB zm9<`KGR!$YkIp*1FTpX=LB#*nu_dE;upM-50*l&`PTja~#z`F5kATbDv$C>c$x%pE z3<#(>xY~7bff$@Q3m#@~kLS>saV_MpENZ$$_`SUN0ypNCoOvmFm(}y8Y@+>#OLSC$!8c!v(`n{PR`Q3@$f(u6%#u>ZDUX?KTlW}2!eGYB61AC z4%l>DqPt7#jV@CPhvDoQ_GKXsVc^U7vKA!$?EZ-a*XtkF?tG*ZB>(Ou2t8;=cYjZ- zQk%nU)8KmFN7;}eCOSxMI2ER{a2Bq)va-@oqfTHLxuT-b` z4#$BDlPX4N5$<<4PfokWOS3uzV-lqYpXl=&M7IZgVqs4{3zi)K7kl&H^BP&{12oU3 zhMW!$;hSo%YC?>=Lcx4q;c*x81#!HGRRliGw^t+-ucvcEg2}5ZE3&ea$qC6(0FD^OiBSe%qfUnL9VG=)Hv@i* z1#@)2g0w1gXFitB=pGq+_Q93bB3V;cZG<4YBi}NirOhgxfl-ntJK~$H%i;|D-*yB1;uo#8<>bxNZWv zFyeSZ;d;y*L3Ny|n6HY8+--MWUOp_Fsd@kTXY089lzQ8Uv^nvO@PhwALBk%dM6j}( z`X)QgrKzh^Rimkq2}U>jC$yTT$?587@mU@mNgUY{+<|)2hv)kw6poh@Me#guCK|2H z#o;Ya29@_1p=W$v#A{4U_dW;g09j-Ncf5BrM8ooHYkz*Ie%Rlm6vwG^azI4z_Yack zehr00K2v75SMg3vc!*eyU98ceNp0^FHc%<UWGj#M{E9|{ZJn}{#d>Y&0$TID4YaB0Sd40W7PDJC zxrGmb%;3;SRz`PG*MnN!{PVdorL0>0NlOsSdA$~%eIdl7xoKm+2vh%DnRrne)8ogn z$NHr=mTQ(bb5?0=F)jkBU-K^I;mBz@vnra@*8q%!ueK)S&22t{sx>wE2G z;S-$vgaiR)*YZ0y?ZBQz|6XDl1-T9%umIR<5WdFD1{o;nJx=7n7LSm3c3O#fSMuOW z3;1uLXKE_B2Hp$~?y^AWJEvZ9v=*i( zv+~x7&}mShuz}7JDj@qlDM!bbwmD=rP~a%T@86q?Rt8R)h-~pV9L&EQ5)XCB;b(RG z3623T%@$@Mti-}`&`p*@NLj98rD$vYa|=q1A@^ao0c%70z>k+=y%rE%Bg&ag(m4ZY@FA)vNDij#4FeiZP4gz|Jq7gGwkmoY`Ih}M^fW&uui z5KGW%rx-hrrkQp@Fp5Ayfq1jyAn8Z6h*b}m04afg(YL=a^ zml`<9;>}7Hdy}!!(w!V!q8`BdM(4N z_-O~Y)v{1tSjv@#m$yF|n{n^=%(dMl5`rusz-6s8Ud-;CxlGE!%4y8pH+0EA7_3?J zb%TbR=2pgMIe?FdBjp9sN?tl<*qESL5}-zo-FZWsW)IGnwtDw=cdg|YiaLTTCwFwd zk~3@Sk59LvH>|U|3$w)Dq*$aV2wJp<9arkZ5ws z>BDbap~$EkY)tJLso@q&;{mB+*5{7iCtNb#uA69k(<%co<71-hQ$@WlUOWrZi{|FV*kI=A-#_m zaU<4^OVudN9Zod|ySvulH~0fm*|qxO;@+b-%OLPmXuIm_r~j&@+q2n$9phudjY+0mkdFCof(^RY`$b2N4o(lLE;3kXu)BGf$VKE_0DiICf2XoYE39K(d73R z>Kvk3IJ3giZh(m(|G!l^@0ej8gC6+6$& zgab3b7epKQu(!DMtG}kwRM*r1WWN}CzN115qEIu{^E>@xfs)R}#abOZ4(HcoOWtE( zHi23zcn(znD%m{Tc_ws*0GPZ~F-V$Q+&keu@7juo=A=a9r*@CfR;X9MNO^h+D52?E z`{P8&(|0VCb&30n2hy_Ou)>w3HDCieVpvd$#1Be@uXMi58~O6hU<(3Vpt#%`jn zeHK!z)t@f+e!B;6Bn2@~?ItW+m`}!1%9ro1=c`Dsq0W1^*B_hQ`2#+-tAvHDhDK0* zmxAmE>AXE@S#@9H2;n3GzCgdJ%Sb2bDV#g3 z`-e#roaf&>-8n?;d8$HX3-&+ZxpCQg(#pJ>eMJZ3CJQSoAL0Il{8hR)l5IhOlOb;5 zktJ4jIjIFTvl0)(ql+ykMV0}s8XGAnV&2?X!uC_^d z!x8rJjO!i%lgJXh)y=p_n$9L-qw1+@Vlzn88}WRH9^oE5!r_0$-IDm*Q}e=n6hPi{ zM4HQ}{cFek^-r@|!=M^$`Ey_%_}O>wIq1V*^hfhQ*wbfE-q<~T(~s$W$xq-RPB@lB z`-vfwQx+o;)o1?_&A!dppp9@8fus7+!hGSketyX=Mg?6w=4;M{G)g zoF<)SV>KuiQks$%v1~(Q1ck#x4E?x$@Ghl%6Z1*UGV904jc&wct<~2CzXJ=E{CkSt zP1bJ{2NY{nn(7P^XbiXhU9Rge5XaC7b#pKn@61YOt>RQ1-6*l8u_)87}3HOYXBf&xW<|w=2sw1zPcb9P+t!QKXwe44~#RC$=4o({=kr zdP3>zgIBY0c=IqCW4L2ZS=D92l%)jU#Yv;Ptj^-1g+u<$>|?&Fp3&pyIw(GQoz~C6 zM52PzFR^t51dg2@OZ@y?7elcsdG_bBcg)P-O}KenlRAp*{wZ2XQ@XZxP@$WtJ#=Tf zCv;jgI1b12?n>FXqv;^*^tCDHQFdV_75qqfccHT-$nNQrUzo>;^Db2gZVr9CD~Hp@ zaJgID)<~HCusL`9HB}_!tHni~K{(E+alT@idV!#76|`)R;(lxGZ>ua|{aa(&p=`7S zk(>Bam`aVN)31e6uD&o}Pqkf)i@~dK;C)_sRr*+q33te1(AEVG!>w$QX_L%?rejxvPPk3U}dg^On_ zs0|z1SERtY(cm$6*xNg3qr@OB%^N>t=cR_Cf(DO*^J#8|zeksu^hPOZknHlh&SK)4 z@xmuUML}Kf@-6AOGF7+#jlkp7yplIgBTIAs`+yWMEVkNnG;dGHVe%38URA|sAu}<0 zhan2CifmVId9DIz%vs@QKOc~m$eDF~tFw0@zqLj9J4_up_|>AYqO3(iJ9T6isI!;8 zL8eB3_llGOg|e=8z+6q<14p)(JwHKWe8Uir%O=Kp3?#VB*E&iiQ2ZY$#wD08>@mpi z>7@=YhvtqdKoZa9Glde$wCN+8WFnlykg1UZ=tbbuoQYW#FE*5+?w`BnP0eHGa`vPO zc6@!YVfl$m9>Q=%dS@3d!ZT`nM`dHZ~`&(RVQ+m|d z*rFiQiq3$ujy5m_HLXjkww~@}9?$9=WOZ4FmxD=zId!e-=OMV^eF%#vGk?s8b>M^l z<3ozG|K(SI=r_q(HgYLOM`!){CC;en1BXhK>Q{iHf=+<+=jp8lqd@k~jxbfTp7COy zmn)4%P~^@kqGVzP9a*<`%VRlT6(@(dvu5xTtvE!S4)&~3AikVEb(^>Jti|BaVc>J8 z1|md-CqM{x)|g(#20B~=f^5nq3i$UrEz*fp^80KXk-CB*j{x?%sv{xXW1-Q_O*cp~ zTRMZBpzsx3Rn%te8mX^L7A$tfT|eMq%%1s9W>Ol}6HiFVNI8*JnQ$!5Ld?lUcFo@K zJI@z>enJ1|7VT8vQI;+v-rMMyKZ0=c#Mni~2Q#*J?=Z;y_br@Zn*wfm!eWa_CW#Js zc4M5RMn;SE7VB=kV-UN=rvO^Kk(&iR;`7ZaPY=o~pOcH0mn<+jbrZV-JUos*_4i4d z?u|EWBG1nfMh@1pz6>v!Daum-n0J2^JHVzC8?G253R+qU$?fMKgx z9u+;KQGUxmG$SLTo-a2fQPWXz@miL}s0HnA)|!=kfJHyLQq5wUk(s1OW*s?g zXUrKy651jffILRWdeSL-o*DyB@DNgo1jW%85Ev9*#Gr4$vi2 z$t8FHd!Q?}iPvB3uP?tfiQn-$9cp}0W7g#9(fcJ#s0Nhu{#+oDdNIh$&p%_|G+$%( zcz=(#{*^qOJm2C$twXhnM)+GxRif=VL3_JuVv0!S^^V%xXyTanRv;PIT4y6t_*I~X ziS$D^dwvyfD@r29Sb&Jw$jtY_GIpGpf!#Cqrv|FCj-7|z!X9hd+1DJVqdjf*3JKkj z$TO%Uv>rw2aoJhwOc@Z7LPEmG8Jke{`R5WY31#ycl6C0U{17Z3$4-hKPU{&G!vPw~ zs{IBFgXjRcch@fkZN~N&@;8zN5|u_hS@N`Ys)dicJDIC3ZV5?wyiM1yXAM@|In@@d zWyOA|Up0%|y_=r?%0M6h3ZC*`#StTxZ{H*@*9X3z3O+0{H1T~r=>0>*yl_Q-79bi# z;Wj8QAsm?+#Cou9K#3{p^|#pxzP^WHVTpp_L+Po#6KE%wozR`kO^Y$$X=7m`p|LaP z5nDMig%qDa`bN^!-`HPO2jC-(p+HcBMy)5uz@Kh2X4%TfHr9w%L>Rp`r180l)niKt zZhkZ9Y$w5oT}164qEbC(NC1H z^Qty0LpN~`UJ;jr)k^bWwX-q@{mqn036&Ur<8lbr}~okKHX-3>}nXxFTB37s71y?@~pqc$+(4WRWwD! z%)jBLW3N%QqT4WZ%w)Qgd)34>m;o<7BWw&Fl+{@#+zqzVR{{Ai_!*VQN|z3T)$$Mn zUTA5@#lNR2G<|DL(Nh}3hw;BmwibMEDR6IF<6-cuBuD_%oc*mnh3DklGbz9^`B|_@ zXBl36Rcw&T?Q?ZfB>O(8(KQnpO5z7%GI(SpJmLHl6zh9m71(TjeSUmJ= zjsYuSrXo2ho~4tWoZa;5>Pi?hBTh%$JhRXK3$j$Iz2lm9)HlVll?IP=K7e?@v39ia z26KAz=q{G%2L1~=fB!im-yw zhq|bM(Asha^x)b7@SI%DPwgPm&U_&fo$U?|q7d$+K5aioP5!!JkCH+lQR3vcW)=`f z;kB=?&My&u3dK7QUzLOc2g7l==54hjOR{7FkmTf=$v0XC@T|PX@nimcTLTnO;^D^X z>}a31Z|ds0cGxWI5ug!gbr$t_;#&%oI{voKU@Dp<~u#6@a3H?sb zeIqULP&X_o`Sr?sQMTK_J#sS0^LlrW@sq;c%G%#5qMj$ai<+-{vu=>^0)`&-FKlo{ z=a3n6cP}66*sM(NB`ftrWcCy-RU~S0s8o4HdVdZsiC<)iA(uiM;B41EX2iKE8Em@x zlv?lN{JmPzHF{-r1#Z3N1IT(~a(ne?R%w4n4Ej{A-ea+#1SCIe^FDc@tU??ZY$Ox_ z*Iz&qNVwkJr(S&5T({sP_V?{pbED>9B#u#_)eQf-d999CAH@CNOMyo~KuknLM4-^y zB}Ct^TdNm@ok9%fk$fB<=QV$Z zELPTqz!GX&7ahr+jNBGhg_{XKG`-VRS8vi&!d16s{*)aT$DRJ>Q(8EtUE4{NbBufg z73|og=i;KUJFF)JHfjjD9`U;fiTHEcyBrQewnLr7$|DyPargbd@kLk!2&B)NX|us=vd`M!QT8qW$xCoxzD^eUT(^{0`>iSA4k6P(JKBCrbkDkR9fPh!P$M|R1Gh5sSNhD%kW4~cnUZYM z$LP5q62FYNDsZJD2`Bo{gHq|W`oP3Pse)4@R`ln_DRV!Mp-w`DVO3SXY(#_tRe*xF zbB-;MXPed=dZ>!3bOtvnYa6cNEd8kCh49nKY$z}VMha^4ciikYy@;p5>MM{*~ z(#7m_eZDf@^;bk3hLxK%_v1W{w(|BwLgWLHnud0r>FEcSte4H8F%R546H+_By(jdp=H0@^IBpyV2z!-a-JO;(v8v`isvhMePFniq zSxFh`<}~;Molm`r6k;J^FVGdI_5cy=6);i?13{tSqw((5GLhwz+55?r4!NBClsZs+ z`Oh0ZBR0eJ8%l6)fF~tHC!@o$L}t^P?UT%n+QB}@*)*q=Hw~5?dAI-8>|HEuf7dp+ ziQjXopu4j2s12>&3AwW=!wjPQozr&vjh^3KP7$?uXeddg9*$Ix%|X5XDReWqBt@U~ zlX1n|p7EG8+Ct@mP)?38+cjE)zWvO0Yea;Zub1B)>@SI+;Abs8=>0e$Na!w5 z*Cs$nN?xamwcW>QqyH`V1zGfQWYa&WL9vomm(h7jC)H9?`rl|zbw4HH{D9^j;cqiC zBF}wwqt$4f4!?6EIq|T0$OXnO#dCQwWrwweg0bdx@vX0O@#Y#ysF&@f_4d}-z~C$2 zzsbt$f5O0z7dnifYq`*yTK_@LR!Oi`YxPW)4s+dsL85$4&Ru^Db~(jTcx)tv5-Weu z?eQHvfSZNjUH<@)M|&Pn0K)?}tHGZ{Y0f)ekuP9HJMS}v=TzftCmJ=}Fp+9Krb;5C zH9nm8!J0-cg+eH>i4X8Fx)-wNnOlyIp`mG<=f!qC^dnoi(141-b>qJ5%%ZAB2JQCt z##$IH-q`pbQur_35pSHpgKj@yK2-tojhqj|ON82GSSzb&j)**tA3n$Z1Xe#fJyQSv zmaPciMitI|K*JKN6L$N<<2QOxk?v5sLeqzZNWvEO1e2$bV+?0ARkj)bIy~y#y4+EU!7JZjubKq7A@MgaWIm~9IXQV;4l{i?T+-a*H;+d&+#@P^AWtkXE}d8XE$*g zyx#(!OH|2{c~WBW$2o7m3{Z7^+K{<7!R09j(WQKPPB|kXxF)J-B-Kp< zb3XEug5$!g-0^Kp$xN*Kc@A!;$;C(d$(_?e$tH*V>e9A_L zdq=c*?#40?{B&Ociib9<(e~&?*$gTgD!&4a3d`RsHczjH68}VPJ_6M&FSiHXonD9V^Agn#Y0i0U9-3x$hIKPCosLh$M02vG zYM;{Zybe*LeeijYyr1qi&xg{f4a~69sJsnb7n&f)#N4Qo1AOpT{bXyve7sqAm3CI2 zV$Z#3ZQc2ArRN*%DTf@Z?vTxD{c#iPtTo}i_vHqjbc(dL_Dwv#huOu$Cr)?bNyJl% zi1noDZ?kD>h3S*<$*IjsB6niHlIJ@3K@ZjbL_;BSJ)M>KW^eE|I z;LtzR8J~@$*R^c?5iF|wY-F+J2Wj5ZSzhg-PAc!it>eBZJGmLb(A`K@vGzTr4M7

    9uxZbm^UpV;#;n+zAbIH~91 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 x=QCHDXE?2Y){3j$df<*uT literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/trade_history_table-light.png b/testdata/snapshots/darwin/trade_history_table-light.png new file mode 100644 index 0000000000000000000000000000000000000000..1b2f118f53eea0278aec364dd2748065ced7be79 GIT binary patch literal 22690 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 literal 0 HcmV?d00001 diff --git a/ticker_tape.go b/ticker_tape.go new file mode 100644 index 0000000..67cc954 --- /dev/null +++ b/ticker_tape.go @@ -0,0 +1,155 @@ +package mujica + +import ( + "fmt" + "log/slog" + "math" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// TickerItem is one symbol on a TickerTape. +type TickerItem struct { + Symbol string + Price float64 + ChangePercent float64 +} + +// TickerTapeOptions configure a TickerTape. +type TickerTapeOptions struct { + // Decimals of the prices; zero means 2. + Decimals int + // Speed is in DIPs a second; zero means 40. + Speed float32 + // PerPage is items per reduced-motion page; zero means 4. + PerPage int + // Label names the tape; empty uses the built-in "Market ticker". + Label string +} + +type tickerTapeState struct { + offset float32 + last time.Time + page int + paused bool +} + +// TickerTape loops quotes, pausing on hover or focus. +func TickerTape(c *ui.Context, items []TickerItem, opts TickerTapeOptions) *ui.Element { + if opts.Speed < 0 || opts.PerPage < 0 { + panic("mujica: TickerTape Speed and PerPage cannot be negative") + } + dec := priceDecimals("TickerTape", opts.Decimals) + speed, per := opts.Speed, opts.PerPage + if speed == 0 { + speed = 40 + } + if per == 0 { + per = 4 + } + label := opts.Label + if label == "" { + label = msg(c, "ticker_tape.label") + } + k := Tokens(c) + d := Density(c) + e := ui.Row(c).MinHeight(d.ControlHeight()).AlignItems(ui.Center).Background(k.Surface). + BorderWidth(theme.BorderWidth, 0).BorderColor(k.Border).Focusable().Role(ui.RoleGroup).Label(label) + e.FocusRing(false) + st := ui.Local(e, "tape", func() tickerTapeState { return tickerTapeState{} }) + if c.Preferences().ReduceMotion || len(items) == 0 { + tickerTapePages(c, e, st, items, per, dec) + return e + } + paused := e.Hovered() || e.FocusWithin() + if paused != st.paused { + st.paused = paused + slog.Debug("mujica: ticker_tape paused", "paused", paused) + } + now := c.Now() + if !paused && !st.last.IsZero() { + st.offset += float32(now.Sub(st.last).Seconds()) * speed + } + st.last = now + if !paused { + c.AnimationFrame() + } + e.Description(msg(c, "ticker_tape.pause_hint")) + e.ClipX().Children(func() { + strip := ui.Row(c).Absolute().Top(0).Bottom(0).AlignItems(ui.Center) + if w := strip.Bounds().W / 2; w > 0 { + st.offset = float32(math.Mod(float64(st.offset), float64(w))) + } + // Quarter steps keep the moving text on the renderer's grid. + strip.Left(-float32(math.Round(float64(st.offset)*4)) / 4) + strip.Children(func() { + // The second copy fills in as the first scrolls out. + for n := range 2 { + r := ui.Row(c).Key(n).AlignItems(ui.Center).Shrink(0) + if n == 1 { + r.Role(ui.RoleNone) + } + r.Children(func() { + for _, it := range items { + tickerTapeItem(c, it, dec) + } + }) + } + }) + }) + return e +} + +// tickerTapePages shows one page of items, for reduced motion. +func tickerTapePages(c *ui.Context, e *ui.Element, st *tickerTapeState, items []TickerItem, per, dec int) { + pages := max(1, (len(items)+per-1)/per) + st.page = min(st.page, pages-1) + turn := func(by int) { + if !e.IsDisabled() { + st.page = (st.page + by + pages) % pages + slog.Debug("mujica: ticker_tape page", "page", st.page) + } + } + if e.Shortcut(0, ui.KeyRight) { + turn(1) + } + if e.Shortcut(0, ui.KeyLeft) { + turn(-1) + } + k := Tokens(c) + e.Children(func() { + ui.Row(c).Grow(1).MinWidth(0).ClipX().AlignItems(ui.Center).Children(func() { + for _, it := range items[st.page*per : min(len(items), (st.page+1)*per)] { + tickerTapeItem(c, it, dec) + } + }) + if pages < 2 { + return + } + if iconAction(c, icons.Must("chevron-left"), msg(c, "ticker_tape.previous")).Clicked() { + turn(-1) + } + ui.Text(c, fmt.Sprintf("%d / %d", st.page+1, pages)).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)).FontFeatures("tnum") + if iconAction(c, icons.Must("chevron-right"), msg(c, "ticker_tape.next")).Clicked() { + turn(1) + } + }) +} + +// tickerTapeItem is one symbol, price and change. +func tickerTapeItem(c *ui.Context, it TickerItem, dec int) { + u := Density(c).Unit() + sign := trendSign(it.ChangePercent) + ui.Row(c).Gap(u*1.5).AlignItems(ui.Center).Padding(0, u*4).Shrink(0).Children(func() { + ui.Text(c, it.Symbol).FontWeight(600).SingleLine() + ui.Text(c, statisticFormat(it.Price, dec)).FontFeatures("tnum").SingleLine() + ui.Row(c).Gap(u / 2).AlignItems(ui.Center).TextColor(trendColor(c, sign)).Label(trendWord(c, sign) + " " + statisticSigned(it.ChangePercent, 2) + "%").Children(func() { + ui.Icon(c, trendIcon(sign)).Size(12, 12) + ui.Text(c, statisticSigned(it.ChangePercent, 2)+"%").FontFeatures("tnum").SingleLine() + }) + }) +} diff --git a/ticker_tape_test.go b/ticker_tape_test.go new file mode 100644 index 0000000..12073db --- /dev/null +++ b/ticker_tape_test.go @@ -0,0 +1,93 @@ +package mujica + +import ( + "fmt" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func tickerTapeItems(n int) []TickerItem { + var items []TickerItem + for i := range n { + items = append(items, TickerItem{Symbol: fmt.Sprintf("SYM%d", i), Price: 100 + float64(i), ChangePercent: float64(i%3 - 1)}) + } + return items +} + +func tickerTapeX(t *testing.T, tt *ui.Tester) float32 { + t.Helper() + r, ok := tt.Find("SYM0") + if !ok { + t.Fatalf("no SYM0 in %q", tt.Texts()) + } + return r.X +} + +func TestTickerTapeScrollsAndPausesOnHover(t *testing.T) { + tt := tradingTester(GreenUp, 400, 80, func(c *ui.Context) { + ui.Box(c).Width(380).Children(func() { TickerTape(c, tickerTapeItems(6), TickerTapeOptions{Speed: 200}) }) + }) + x0 := tickerTapeX(t, tt) + time.Sleep(60 * time.Millisecond) + tt.Frame() + x1 := tickerTapeX(t, tt) + if x1 >= x0 { + t.Fatalf("did not scroll: %v -> %v", x0, x1) + } + tt.Move(100, 25) + tt.Frame() + x2 := tickerTapeX(t, tt) + time.Sleep(60 * time.Millisecond) + tt.Frame() + if x3 := tickerTapeX(t, tt); x3 != x2 { + t.Fatalf("moved under the pointer: %v -> %v", x2, x3) + } +} + +func TestTickerTapePausesOnFocus(t *testing.T) { + tt := tradingTester(GreenUp, 400, 80, func(c *ui.Context) { + ui.Box(c).Width(380).Children(func() { TickerTape(c, tickerTapeItems(6), TickerTapeOptions{Speed: 200}) }) + }) + tt.Key(0, ui.KeyTab) + if !tt.Focused("Market ticker") { + t.Fatal("tape not focusable") + } + x0 := tickerTapeX(t, tt) + time.Sleep(60 * time.Millisecond) + tt.Frame() + if x1 := tickerTapeX(t, tt); x1 != x0 { + t.Fatalf("moved while focused: %v -> %v", x0, x1) + } +} + +func TestTickerTapePagesUnderReducedMotion(t *testing.T) { + tt := tradingTester(GreenUp, 500, 80, func(c *ui.Context) { + TickerTape(c, tickerTapeItems(5), TickerTapeOptions{PerPage: 2}) + }) + tt.SetPreferences(ui.Preferences{ReduceMotion: true, TextScale: 1}) + if !tt.HasText("SYM0") || tt.HasText("SYM2") || !tt.HasText("1 / 3") || !tt.HasText("−1.00%") { + t.Fatalf("page 1: %q", tt.Texts()) + } + if err := tt.Click("Next page"); err != nil { + t.Fatal(err) + } + if !tt.HasText("SYM2") || tt.HasText("SYM0") || !tt.HasText("+1.00%") { + t.Fatalf("page 2: %q", tt.Texts()) + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyLeft) + tt.Key(0, ui.KeyLeft) + if !tt.HasText("SYM4") || !tt.HasText("3 / 3") { + t.Fatalf("wrap back: %q", tt.Texts()) + } +} + +func TestTickerTapeSnapshot(t *testing.T) { + snapshot(t, "ticker_tape", 520, 60, func(c *ui.Context) { + ui.Column(c).Padding(10).Children(func() { + TickerTape(c, []TickerItem{{"MUJC", 412.08, -1.35}, {"AVE", 88.2, 2.1}, {"OBLV", 1204.5, 0}}, TickerTapeOptions{}) + }) + }) +} diff --git a/time_and_sales.go b/time_and_sales.go new file mode 100644 index 0000000..0a6c186 --- /dev/null +++ b/time_and_sales.go @@ -0,0 +1,137 @@ +package mujica + +import ( + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// TradePrint is one executed trade on the tape. +type TradePrint struct { + // ID identifies the trade; required and unique. + ID string + Time time.Time + Price float64 + Size float64 + Side OrderSide +} + +// TimeAndSalesOptions configure a TimeAndSales. +type TimeAndSalesOptions struct { + // Decimals of prices and sizes; zero means 2 and 0. + Decimals, SizeDecimals int + // LargeSize marks trades at or above it; zero marks none. + LargeSize float64 + // Height of the list in DIPs; zero means 320. + Height float32 + Status DataStatus + Error string +} + +// TimeAndSalesState is the tape's follow state and list place. +type TimeAndSalesState struct { + // Paused stops new trades from showing until resumed. + Paused bool + frozen int + shown int + list ListState[string] +} + +// TimeAndSales lists trades newest on top; Paused holds the view. +func TimeAndSales(c *ui.Context, s *TimeAndSalesState, trades []TradePrint, opts TimeAndSalesOptions) ChoiceResult { + dec := priceDecimals("TimeAndSales", opts.Decimals) + if opts.SizeDecimals < 0 || opts.LargeSize < 0 || opts.Height < 0 { + panic("mujica: TimeAndSales SizeDecimals, LargeSize and Height cannot be negative") + } + height := opts.Height + if height == 0 { + height = 320 + } + if !s.Paused { + s.frozen = len(trades) + } + s.frozen = min(s.frozen, len(trades)) + n := s.frozen + if !s.Paused && n != s.shown { + s.list.ScrollTo(0) + } + s.shown = n + k := Tokens(c) + d := Density(c) + var r ChoiceResult + r.Element = ui.Column(c).Gap(d.Unit() * 2).Height(height) + r.Element.Children(func() { + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, msg(c, "time_and_sales.title")).Font(theme.SerifFont).FontWeight(600).Grow(1) + label := msg(c, "time_and_sales.pause") + if s.Paused { + label = msg(c, "time_and_sales.resume") + if waiting := len(trades) - n; waiting > 0 { + label = fmt.Sprintf(msg(c, "time_and_sales.resume_count"), waiting) + } + } + if Button(c, label, ButtonOptions{Variant: Secondary}).Clicked() { + s.Paused, r.changed = !s.Paused, true + slog.Debug("mujica: time_and_sales follow", "paused", s.Paused) + } + }) + ui.Row(c).Padding(0, d.Unit()*4).Gap(d.Unit() * 2).Children(func() { + for i, key := range []string{"time_and_sales.time", "time_and_sales.price", "time_and_sales.size"} { + t := ui.Text(c, msg(c, key)).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Grow(1).Basis(0) + if i > 0 { + t.TextAlign(ui.End) + } + } + ui.Box(c).Width(16) + }) + at := func(i int) TradePrint { return trades[n-1-i] } + List(c, &s.list, n, ListOptions[string]{ + Key: func(i int) string { return at(i).ID }, + Label: func(i int) string { + t := at(i) + return timeAndSalesSpoken(c, t, dec, opts) + }, + Status: opts.Status, Error: opts.Error, Empty: msg(c, "time_and_sales.empty"), + }, func(i int) { timeAndSalesRow(c, at(i), dec, opts) }).Element.Grow(1) + }) + return r +} + +func timeAndSalesLarge(t TradePrint, opts TimeAndSalesOptions) bool { + return opts.LargeSize > 0 && t.Size >= opts.LargeSize +} + +// timeAndSalesSpoken reads a trade with its side and size. +func timeAndSalesSpoken(c *ui.Context, t TradePrint, dec int, opts TimeAndSalesOptions) string { + s := fmt.Sprintf("%s %s %s %s", t.Time.Format("15:04:05"), msg(c, fmt.Sprintf("order_book.side%d", t.Side)), + statisticFormat(t.Price, dec), statisticFormat(t.Size, opts.SizeDecimals)) + if timeAndSalesLarge(t, opts) { + s += ", " + msg(c, "time_and_sales.large") + } + return s +} + +// timeAndSalesRow is one trade with its side and large mark. +func timeAndSalesRow(c *ui.Context, t TradePrint, dec int, opts TimeAndSalesOptions) { + k := Tokens(c) + large := timeAndSalesLarge(t, opts) + sign := t.Side.sign() + ui.Text(c, t.Time.Format("15:04:05")).FontFeatures("tnum").TextColor(k.TextMuted).Grow(1).Basis(0).SingleLine() + ui.Row(c).Gap(2).Justify(ui.End).AlignItems(ui.Center).Grow(1).Basis(0).TextColor(trendColor(c, sign)).Children(func() { + ui.Icon(c, trendIcon(sign)).Size(12, 12) + ui.Text(c, statisticFormat(t.Price, dec)).FontFeatures("tnum").SingleLine() + }) + size := ui.Text(c, statisticFormat(t.Size, opts.SizeDecimals)).FontFeatures("tnum").TextAlign(ui.End).Grow(1).Basis(0).SingleLine() + mark := ui.Box(c).Size(16, 16).Shrink(0) + if large { + size.FontWeight(700) + mark.Draw(func(p *ui.Painter, r ui.Rect) { + p.FillPath(internal.Diamond(r.X+r.W/2, r.Y+r.H/2, 10), k.AccentText) + }) + } +} diff --git a/time_and_sales_test.go b/time_and_sales_test.go new file mode 100644 index 0000000..5bb8056 --- /dev/null +++ b/time_and_sales_test.go @@ -0,0 +1,90 @@ +package mujica + +import ( + "fmt" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func timeAndSalesTrades(n int) []TradePrint { + at := time.Date(2026, 10, 5, 9, 30, 0, 0, time.UTC) + out := make([]TradePrint, n) + for i := range out { + side := SideBuy + if i%2 == 1 { + side = SideSell + } + out[i] = TradePrint{ID: fmt.Sprint(i), Time: at.Add(time.Duration(i) * time.Second), Price: 100 + float64(i%50)/100, Size: float64(i%7 + 1), Side: side} + } + return out +} + +func TestTimeAndSalesNewestFirstAndLargeMark(t *testing.T) { + var s TimeAndSalesState + trades := timeAndSalesTrades(3) + trades[1].Size = 5000 + tt := tradingTester(GreenUp, 500, 400, func(c *ui.Context) { + TimeAndSales(c, &s, trades, TimeAndSalesOptions{LargeSize: 1000}) + }) + newest, _ := tt.Find("09:30:02") + oldest, _ := tt.Find("09:30:00") + if newest.Y >= oldest.Y { + t.Fatalf("newest %v not above oldest %v", newest, oldest) + } + if !tt.HasText("5,000") { + t.Fatalf("texts %q", tt.Texts()) + } + if _, ok := tt.Find("09:30:01 Ask 100.01 5,000, large trade"); !ok { + t.Fatal("large trade not spoken") + } +} + +func TestTimeAndSalesPauseHoldsView(t *testing.T) { + var s TimeAndSalesState + trades := timeAndSalesTrades(2) + n := 0 + tt := tradingTester(GreenUp, 500, 400, func(c *ui.Context) { + if TimeAndSales(c, &s, trades, TimeAndSalesOptions{}).Changed() { + n++ + } + }) + if err := tt.Click("Pause"); err != nil { + t.Fatal(err) + } + trades = timeAndSalesTrades(5) + tt.Frame() + if tt.HasText("09:30:04") || !tt.HasText("Resume (3 new)") || !s.Paused || n != 1 { + t.Fatalf("paused view moved: %q", tt.Texts()) + } + tt.Key(0, ui.KeyEnter) + if !tt.HasText("09:30:04") || s.Paused || n != 2 { + t.Fatalf("resume: %q", tt.Texts()) + } +} + +func TestTimeAndSalesBuildsOnlyVisibleRows(t *testing.T) { + var s TimeAndSalesState + trades := timeAndSalesTrades(100_000) + tt := tradingTester(GreenUp, 500, 400, func(c *ui.Context) { + TimeAndSales(c, &s, trades, TimeAndSalesOptions{}) + }) + if !tt.HasText("13:16:39") { + t.Fatalf("newest trade not on top: %q", tt.Texts()[:8]) + } + if got := len(tt.Texts()); got > 120 { + t.Fatalf("built %d texts for 100,000 trades", got) + } +} + +func TestTimeAndSalesSnapshot(t *testing.T) { + trades := timeAndSalesTrades(8) + trades[5].Size = 4000 + snapshot(t, "time_and_sales", 420, 360, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + s := ui.Local(c.Root(), "snap", func() TimeAndSalesState { return TimeAndSalesState{} }) + TimeAndSales(c, s, trades, TimeAndSalesOptions{LargeSize: 1000, Height: 320}) + }) + }) +} diff --git a/trade_history_table.go b/trade_history_table.go new file mode 100644 index 0000000..2f64054 --- /dev/null +++ b/trade_history_table.go @@ -0,0 +1,110 @@ +package mujica + +import ( + "cmp" + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" +) + +// FillRow is one of the account's fills; ID is stable. +type FillRow struct { + ID string + Time time.Time + Symbol string + Side OrderSide + Price float64 + Quantity float64 + Fee float64 +} + +// TradeHistoryTableOptions configure a TradeHistoryTable. +type TradeHistoryTableOptions struct { + // Decimals of prices and quantities; zero means 2 and 0. + Decimals, QuantityDecimals int + // Version must change when rows change in place. + Version int + Status DataStatus + Error string + Disabled bool +} + +// TradeHistoryTableState is the date range and table state. +type TradeHistoryTableState struct { + // Range keeps fills on its days; zero keeps all. + Range DateRange + Table DataTableState[string] + cache tradingRows[FillRow] +} + +// TradeHistoryResult is a built table and its export request. +type TradeHistoryResult struct { + Element *ui.Element + Table DataTableView + exported []FillRow + export bool +} + +// Exported returns the range's fills when export was asked. +func (r TradeHistoryResult) Exported() ([]FillRow, bool) { return r.exported, r.export } + +// TradeHistoryTable lists fills by date range, with export. +func TradeHistoryTable(c *ui.Context, s *TradeHistoryTableState, rows []FillRow, opts TradeHistoryTableOptions) TradeHistoryResult { + dec := priceDecimals("TradeHistoryTable", opts.Decimals) + if opts.QuantityDecimals < 0 { + panic("mujica: TradeHistoryTable with negative QuantityDecimals") + } + rng := s.Range + shown := s.cache.view(rows, opts.Version, rng, func(f FillRow) bool { + if rng.IsZero() { + return true + } + d := DateOf(f.Time) + return d.Compare(rng.Start) >= 0 && d.Compare(rng.End) <= 0 + }) + num := func(id, key string, dp int, v func(FillRow) float64) DataColumn[FillRow] { + return DataColumn[FillRow]{ID: id, Title: msg(c, key), Align: ui.End, Sortable: true, + Compare: func(a, b FillRow) int { return cmp.Compare(v(a), v(b)) }, + Text: func(f FillRow) string { return statisticFormat(v(f), dp) }} + } + cols := []DataColumn[FillRow]{ + {ID: "time", Title: msg(c, "trade_history_table.time"), Sortable: true, Width: 180, + Compare: func(a, b FillRow) int { return a.Time.Compare(b.Time) }, + Text: func(f FillRow) string { return f.Time.Format("2006-01-02 15:04:05") }}, + {ID: "symbol", Title: msg(c, "position_table.symbol"), Sortable: true, + Compare: func(a, b FillRow) int { return cmp.Compare(a.Symbol, b.Symbol) }, + Text: func(f FillRow) string { return f.Symbol }}, + {ID: "side", Title: msg(c, "order_table.side"), Text: func(f FillRow) string { return msg(c, fmt.Sprintf("order_entry.side%d", f.Side)) }, + Cell: func(f FillRow) { tradingSide(c, f.Side) }}, + num("price", "order_book.price", dec, func(f FillRow) float64 { return f.Price }), + num("qty", "order_entry.quantity", opts.QuantityDecimals, func(f FillRow) float64 { return f.Quantity }), + num("fee", "trade_history_table.fee", dec, func(f FillRow) float64 { return f.Fee }), + } + d := Density(c) + var r TradeHistoryResult + r.Element = ui.Column(c).Gap(d.Unit() * 2).Disabled(opts.Disabled).Grow(1).FillWidth().MinHeight(0) + disabled := r.Element.IsDisabled() + r.Element.Children(func() { + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + if DateRangePicker(c, &s.Range, DateRangePickerOptions{Label: msg(c, "trade_history_table.range"), Disabled: disabled}).Changed() { + slog.Debug("mujica: trade_history_table range", "days", s.Range.Days()) + } + if !s.Range.IsZero() && Button(c, msg(c, "trade_history_table.all"), ButtonOptions{Variant: Ghost, Disabled: disabled}).Clicked() && !disabled { + s.Range = DateRange{} + } + ui.Box(c).Grow(1) + if Button(c, msg(c, "trade_history_table.export"), ButtonOptions{Variant: Secondary, Icon: icons.Must("upload"), Disabled: disabled || len(shown) == 0}).Clicked() && !disabled { + r.exported, r.export = shown, true + slog.Debug("mujica: trade_history_table export", "rows", len(shown)) + } + }) + r.Table = DataTable(c, &s.Table, shown, DataTableOptions[FillRow, string]{Columns: cols, Key: func(f FillRow) string { return f.ID }, + Status: opts.Status, Error: opts.Error, Empty: msg(c, "trade_history_table.empty")}) + r.Table.Element.Grow(1) + }) + return r +} diff --git a/trade_history_table_test.go b/trade_history_table_test.go new file mode 100644 index 0000000..c2a07b8 --- /dev/null +++ b/trade_history_table_test.go @@ -0,0 +1,87 @@ +package mujica + +import ( + "fmt" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func tradeHistorySample() []FillRow { + day := func(d, h int) time.Time { return time.Date(2026, 10, d, h, 0, 0, 0, time.UTC) } + return []FillRow{ + {ID: "f1", Time: day(1, 10), Symbol: "MUJC", Side: SideBuy, Price: 400, Quantity: 10, Fee: 1.2}, + {ID: "f2", Time: day(3, 14), Symbol: "AVE", Side: SideSell, Price: 88.2, Quantity: 5, Fee: 0.4}, + {ID: "f3", Time: day(5, 9), Symbol: "OBLV", Side: SideBuy, Price: 12, Quantity: 100, Fee: 0.6}, + } +} + +func TestTradeHistoryTableRangeAndExport(t *testing.T) { + s := TradeHistoryTableState{Range: DateRange{Start: Date{2026, 10, 2}, End: Date{2026, 10, 4}}} + var exported []FillRow + tt := tradingTester(GreenUp, 1000, 600, func(c *ui.Context) { + ui.Box(c).Width(960).Height(400).Children(func() { + if rows, ok := TradeHistoryTable(c, &s, tradeHistorySample(), TradeHistoryTableOptions{}).Exported(); ok { + exported = rows + } + }) + }) + if tt.HasText("MUJC") || !tt.HasText("AVE") || tt.HasText("OBLV") { + t.Fatalf("range: %q", tt.Texts()) + } + if err := tt.Click("Export"); err != nil { + t.Fatal(err) + } + if len(exported) != 1 || exported[0].ID != "f2" { + t.Fatalf("exported %v", exported) + } + if err := tt.Click("All dates"); err != nil { + t.Fatal(err) + } + if !tt.HasText("MUJC") || !tt.HasText("OBLV") || !s.Range.IsZero() { + t.Fatalf("all dates: %q", tt.Texts()) + } + _ = tt.Click("Export") + if len(exported) != 3 { + t.Fatalf("exported %d", len(exported)) + } +} + +func TestTradeHistoryTableDisabled(t *testing.T) { + var s TradeHistoryTableState + exported := false + tt := tradingTester(GreenUp, 1000, 600, func(c *ui.Context) { + ui.Box(c).Width(960).Height(400).Children(func() { + _, exported = TradeHistoryTable(c, &s, tradeHistorySample(), TradeHistoryTableOptions{Disabled: true}).Exported() + }) + }) + _ = tt.Click("Export") + if exported { + t.Fatal("disabled table exported") + } +} + +func TestTradeHistoryTableSnapshot(t *testing.T) { + snapshot(t, "trade_history_table", 900, 260, func(c *ui.Context) { + ui.Column(c).Padding(16).Height(240).Width(880).Children(func() { + s := ui.Local(c.Root(), "snap", func() TradeHistoryTableState { return TradeHistoryTableState{} }) + TradeHistoryTable(c, s, tradeHistorySample(), TradeHistoryTableOptions{}) + }) + }) +} + +// 100,000 fills build only visible rows. +func TestTradeHistoryTableLargeData(t *testing.T) { + var s TradeHistoryTableState + rows := make([]FillRow, 100_000) + for i := range rows { + rows[i] = FillRow{ID: fmt.Sprint(i), Time: time.Date(2026, 1, 1, 0, 0, i, 0, time.UTC), Symbol: "S", Side: SideSell, Price: 1, Quantity: 1} + } + tt := tradingTester(GreenUp, 1000, 600, func(c *ui.Context) { + ui.Box(c).Width(960).Height(400).Children(func() { TradeHistoryTable(c, &s, rows, TradeHistoryTableOptions{}) }) + }) + if n := len(tt.Texts()); n > 400 { + t.Fatalf("built %d texts", n) + } +} From 7c94e9e1907fb6206bf3a8f694d6a5eeff3a8b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 5 Oct 2026 14:29:40 -0400 Subject: [PATCH 07/13] Agent: components 261-280 --- agent_diff.go | 127 ++++++++ agent_parts.go | 293 ++++++++++++++++++ agent_plan.go | 146 +++++++++ agent_plan_test.go | 94 ++++++ agent_progress.go | 36 +++ agent_progress_test.go | 54 ++++ agent_status.go | 34 ++ agent_status_test.go | 69 +++++ agent_step_list.go | 140 +++++++++ agent_step_list_test.go | 87 ++++++ artifact_panel.go | 148 +++++++++ artifact_panel_test.go | 79 +++++ artifact_version_switcher.go | 89 ++++++ artifact_version_switcher_test.go | 77 +++++ checkpoint_list.go | 119 +++++++ checkpoint_list_test.go | 77 +++++ command_execution_card.go | 128 ++++++++ command_execution_card_test.go | 98 ++++++ docs/components/261-tool-call-card.md | 47 +++ docs/components/262-tool-call-group.md | 47 +++ docs/components/263-tool-approval-dialog.md | 51 +++ docs/components/264-permission-prompt.md | 48 +++ docs/components/265-agent-step-list.md | 51 +++ docs/components/266-agent-plan.md | 49 +++ docs/components/267-agent-status.md | 41 +++ docs/components/268-agent-progress.md | 42 +++ docs/components/269-sub-agent-tree.md | 45 +++ docs/components/270-file-change-card.md | 48 +++ docs/components/271-multi-file-diff-review.md | 48 +++ docs/components/272-command-execution-card.md | 48 +++ docs/components/273-screenshot-stream.md | 45 +++ docs/components/274-artifact-panel.md | 47 +++ .../275-artifact-version-switcher.md | 45 +++ docs/components/276-sandbox-status.md | 43 +++ docs/components/277-mcp-server-list.md | 46 +++ docs/components/278-memory-panel.md | 47 +++ docs/components/279-checkpoint-list.md | 46 +++ docs/components/280-human-input-request.md | 52 ++++ example_agent_test.go | 243 +++++++++++++++ examples/gallery/pages_agent.go | 281 ++++++++++++++++- examples/gallery/pages_agent_code.go | 196 ++++++++++++ examples/gallery/pages_agent_more.go | 285 +++++++++++++++++ file_change_card.go | 85 +++++ file_change_card_test.go | 84 +++++ human_input_request.go | 126 ++++++++ human_input_request_test.go | 94 ++++++ internal/diff.go | 12 +- mcp_server_list.go | 144 +++++++++ mcp_server_list_test.go | 91 ++++++ memory_panel.go | 159 ++++++++++ memory_panel_test.go | 96 ++++++ messages_agent.go | 127 ++++++++ multi_file_diff_review.go | 158 ++++++++++ multi_file_diff_review_test.go | 118 +++++++ permission_prompt.go | 76 +++++ permission_prompt_test.go | 78 +++++ sandbox_status.go | 107 +++++++ sandbox_status_test.go | 68 ++++ screenshot_stream.go | 125 ++++++++ screenshot_stream_test.go | 110 +++++++ sub_agent_tree.go | 104 +++++++ sub_agent_tree_test.go | 81 +++++ testdata/snapshots/darwin/agent_plan-dark.png | Bin 0 -> 22491 bytes .../snapshots/darwin/agent_plan-light.png | Bin 0 -> 21845 bytes .../snapshots/darwin/agent_progress-dark.png | Bin 0 -> 6914 bytes .../snapshots/darwin/agent_progress-light.png | Bin 0 -> 6660 bytes .../snapshots/darwin/agent_status-dark.png | Bin 0 -> 8602 bytes .../snapshots/darwin/agent_status-light.png | Bin 0 -> 8321 bytes .../snapshots/darwin/agent_step_list-dark.png | Bin 0 -> 21118 bytes .../darwin/agent_step_list-light.png | Bin 0 -> 20677 bytes .../snapshots/darwin/artifact_panel-dark.png | Bin 0 -> 23276 bytes .../snapshots/darwin/artifact_panel-light.png | Bin 0 -> 22104 bytes .../darwin/artifact_version_switcher-dark.png | Bin 0 -> 6383 bytes .../artifact_version_switcher-light.png | Bin 0 -> 6098 bytes .../snapshots/darwin/checkpoint_list-dark.png | Bin 0 -> 15247 bytes .../darwin/checkpoint_list-light.png | Bin 0 -> 14910 bytes .../darwin/command_execution_card-dark.png | Bin 0 -> 22439 bytes .../darwin/command_execution_card-light.png | Bin 0 -> 21339 bytes .../darwin/file_change_card-dark.png | Bin 0 -> 24065 bytes .../darwin/file_change_card-light.png | Bin 0 -> 23061 bytes .../darwin/human_input_request-dark.png | Bin 0 -> 16550 bytes .../darwin/human_input_request-light.png | Bin 0 -> 16059 bytes .../snapshots/darwin/mcp_server_list-dark.png | Bin 0 -> 26561 bytes .../darwin/mcp_server_list-light.png | Bin 0 -> 26213 bytes .../snapshots/darwin/memory_panel-dark.png | Bin 0 -> 28687 bytes .../snapshots/darwin/memory_panel-light.png | Bin 0 -> 27454 bytes .../darwin/multi_file_diff_review-dark.png | Bin 0 -> 40763 bytes .../darwin/multi_file_diff_review-light.png | Bin 0 -> 39456 bytes .../darwin/permission_prompt-dark.png | Bin 0 -> 24519 bytes .../darwin/permission_prompt-light.png | Bin 0 -> 25303 bytes .../snapshots/darwin/sandbox_status-dark.png | Bin 0 -> 12023 bytes .../snapshots/darwin/sandbox_status-light.png | Bin 0 -> 11551 bytes .../darwin/screenshot_stream-dark.png | Bin 0 -> 7842 bytes .../darwin/screenshot_stream-light.png | Bin 0 -> 7643 bytes .../snapshots/darwin/sub_agent_tree-dark.png | Bin 0 -> 20444 bytes .../snapshots/darwin/sub_agent_tree-light.png | Bin 0 -> 19589 bytes .../darwin/tool_approval_dialog-dark.png | Bin 0 -> 23291 bytes .../darwin/tool_approval_dialog-light.png | Bin 0 -> 24229 bytes .../snapshots/darwin/tool_call_card-dark.png | Bin 0 -> 13969 bytes .../snapshots/darwin/tool_call_card-light.png | Bin 0 -> 13488 bytes .../snapshots/darwin/tool_call_group-dark.png | Bin 0 -> 17357 bytes .../darwin/tool_call_group-light.png | Bin 0 -> 16891 bytes tool_approval_dialog.go | 65 ++++ tool_approval_dialog_test.go | 97 ++++++ tool_call_card.go | 79 +++++ tool_call_card_test.go | 103 ++++++ tool_call_group.go | 75 +++++ tool_call_group_test.go | 72 +++++ 108 files changed, 6363 insertions(+), 7 deletions(-) create mode 100644 agent_diff.go create mode 100644 agent_parts.go create mode 100644 agent_plan.go create mode 100644 agent_plan_test.go create mode 100644 agent_progress.go create mode 100644 agent_progress_test.go create mode 100644 agent_status.go create mode 100644 agent_status_test.go create mode 100644 agent_step_list.go create mode 100644 agent_step_list_test.go create mode 100644 artifact_panel.go create mode 100644 artifact_panel_test.go create mode 100644 artifact_version_switcher.go create mode 100644 artifact_version_switcher_test.go create mode 100644 checkpoint_list.go create mode 100644 checkpoint_list_test.go create mode 100644 command_execution_card.go create mode 100644 command_execution_card_test.go create mode 100644 docs/components/261-tool-call-card.md create mode 100644 docs/components/262-tool-call-group.md create mode 100644 docs/components/263-tool-approval-dialog.md create mode 100644 docs/components/264-permission-prompt.md create mode 100644 docs/components/265-agent-step-list.md create mode 100644 docs/components/266-agent-plan.md create mode 100644 docs/components/267-agent-status.md create mode 100644 docs/components/268-agent-progress.md create mode 100644 docs/components/269-sub-agent-tree.md create mode 100644 docs/components/270-file-change-card.md create mode 100644 docs/components/271-multi-file-diff-review.md create mode 100644 docs/components/272-command-execution-card.md create mode 100644 docs/components/273-screenshot-stream.md create mode 100644 docs/components/274-artifact-panel.md create mode 100644 docs/components/275-artifact-version-switcher.md create mode 100644 docs/components/276-sandbox-status.md create mode 100644 docs/components/277-mcp-server-list.md create mode 100644 docs/components/278-memory-panel.md create mode 100644 docs/components/279-checkpoint-list.md create mode 100644 docs/components/280-human-input-request.md create mode 100644 example_agent_test.go create mode 100644 examples/gallery/pages_agent_code.go create mode 100644 examples/gallery/pages_agent_more.go create mode 100644 file_change_card.go create mode 100644 file_change_card_test.go create mode 100644 human_input_request.go create mode 100644 human_input_request_test.go create mode 100644 mcp_server_list.go create mode 100644 mcp_server_list_test.go create mode 100644 memory_panel.go create mode 100644 memory_panel_test.go create mode 100644 messages_agent.go create mode 100644 multi_file_diff_review.go create mode 100644 multi_file_diff_review_test.go create mode 100644 permission_prompt.go create mode 100644 permission_prompt_test.go create mode 100644 sandbox_status.go create mode 100644 sandbox_status_test.go create mode 100644 screenshot_stream.go create mode 100644 screenshot_stream_test.go create mode 100644 sub_agent_tree.go create mode 100644 sub_agent_tree_test.go create mode 100644 testdata/snapshots/darwin/agent_plan-dark.png create mode 100644 testdata/snapshots/darwin/agent_plan-light.png create mode 100644 testdata/snapshots/darwin/agent_progress-dark.png create mode 100644 testdata/snapshots/darwin/agent_progress-light.png create mode 100644 testdata/snapshots/darwin/agent_status-dark.png create mode 100644 testdata/snapshots/darwin/agent_status-light.png create mode 100644 testdata/snapshots/darwin/agent_step_list-dark.png create mode 100644 testdata/snapshots/darwin/agent_step_list-light.png create mode 100644 testdata/snapshots/darwin/artifact_panel-dark.png create mode 100644 testdata/snapshots/darwin/artifact_panel-light.png create mode 100644 testdata/snapshots/darwin/artifact_version_switcher-dark.png create mode 100644 testdata/snapshots/darwin/artifact_version_switcher-light.png create mode 100644 testdata/snapshots/darwin/checkpoint_list-dark.png create mode 100644 testdata/snapshots/darwin/checkpoint_list-light.png create mode 100644 testdata/snapshots/darwin/command_execution_card-dark.png create mode 100644 testdata/snapshots/darwin/command_execution_card-light.png create mode 100644 testdata/snapshots/darwin/file_change_card-dark.png create mode 100644 testdata/snapshots/darwin/file_change_card-light.png create mode 100644 testdata/snapshots/darwin/human_input_request-dark.png create mode 100644 testdata/snapshots/darwin/human_input_request-light.png create mode 100644 testdata/snapshots/darwin/mcp_server_list-dark.png create mode 100644 testdata/snapshots/darwin/mcp_server_list-light.png create mode 100644 testdata/snapshots/darwin/memory_panel-dark.png create mode 100644 testdata/snapshots/darwin/memory_panel-light.png create mode 100644 testdata/snapshots/darwin/multi_file_diff_review-dark.png create mode 100644 testdata/snapshots/darwin/multi_file_diff_review-light.png create mode 100644 testdata/snapshots/darwin/permission_prompt-dark.png create mode 100644 testdata/snapshots/darwin/permission_prompt-light.png create mode 100644 testdata/snapshots/darwin/sandbox_status-dark.png create mode 100644 testdata/snapshots/darwin/sandbox_status-light.png create mode 100644 testdata/snapshots/darwin/screenshot_stream-dark.png create mode 100644 testdata/snapshots/darwin/screenshot_stream-light.png create mode 100644 testdata/snapshots/darwin/sub_agent_tree-dark.png create mode 100644 testdata/snapshots/darwin/sub_agent_tree-light.png create mode 100644 testdata/snapshots/darwin/tool_approval_dialog-dark.png create mode 100644 testdata/snapshots/darwin/tool_approval_dialog-light.png create mode 100644 testdata/snapshots/darwin/tool_call_card-dark.png create mode 100644 testdata/snapshots/darwin/tool_call_card-light.png create mode 100644 testdata/snapshots/darwin/tool_call_group-dark.png create mode 100644 testdata/snapshots/darwin/tool_call_group-light.png create mode 100644 tool_approval_dialog.go create mode 100644 tool_approval_dialog_test.go create mode 100644 tool_call_card.go create mode 100644 tool_call_card_test.go create mode 100644 tool_call_group.go create mode 100644 tool_call_group_test.go diff --git a/agent_diff.go b/agent_diff.go new file mode 100644 index 0000000..c686101 --- /dev/null +++ b/agent_diff.go @@ -0,0 +1,127 @@ +package mujica + +import ( + "fmt" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// FileChange is a proposed edit; empty Old adds a file. +type FileChange struct { + Path string + Old, New string +} + +// FileDecision is a review state; zero is FilePending. +type FileDecision int + +const ( + FilePending FileDecision = iota + FileAccepted + FileRejected +) + +// agentDiffCache holds a change's line diff until its text changes. +type agentDiffCache struct { + old, new string + lines []internal.DiffLine + add, del int + firstEdit int + done bool +} + +func (dc *agentDiffCache) update(ch FileChange) { + if dc.done && dc.old == ch.Old && dc.new == ch.New { + return + } + dc.old, dc.new, dc.done = ch.Old, ch.New, true + dc.lines = internal.LineDiff(internal.SplitLines(ch.Old), internal.SplitLines(ch.New)) + dc.add, dc.del = internal.DiffStats(dc.lines) + dc.firstEdit = 0 + for i, l := range dc.lines { + if l.Op != internal.DiffEqual { + dc.firstEdit = i + break + } + } +} + +// agentDiffOf returns the cached diff of ch kept on holder. +func agentDiffOf(holder *ui.Element, ch FileChange) *agentDiffCache { + dc := ui.Local(holder, "mujica.agent.diff", func() *agentDiffCache { return &agentDiffCache{} }) + (*dc).update(ch) + return *dc +} + +// agentDiffStats shows signed added and removed counts. +func agentDiffStats(c *ui.Context, add, del int) { + k := Tokens(c) + size := FontSize(c, theme.CaptionSize+1) + ui.Row(c).Gap(Density(c).Unit() * 1.5).Shrink(0).Label(fmt.Sprintf(msg(c, "file_change_card.stats"), add, del)).Children(func() { + ui.Text(c, fmt.Sprintf("+%d", add)).TextColor(k.Success).FontSize(size).Font(theme.MonoFont) + ui.Text(c, fmt.Sprintf("−%d", del)).TextColor(k.Danger).FontSize(size).Font(theme.MonoFont) + }) +} + +// agentDiffRow draws one numbered, signed, tinted diff line. +func agentDiffRow(c *ui.Context, l internal.DiffLine) { + k := Tokens(c) + u := Density(c).Unit() + sign, bg, fg := " ", ui.Transparent, k.TextMuted + switch l.Op { + case internal.DiffInsert: + sign, bg, fg = "+", k.Success.Alpha(0.14), k.Success + case internal.DiffDelete: + sign, bg, fg = "−", k.Danger.Alpha(0.14), k.Danger + } + num := func(n int) string { + if n == 0 { + return "" + } + return fmt.Sprint(n) + } + ui.Row(c).Gap(u*2).Background(bg).Padding(0, u).Children(func() { + ui.Text(c, num(l.Old)).Width(36).TextAlign(ui.End).TextColor(k.TextMuted).Shrink(0) + ui.Text(c, num(l.New)).Width(36).TextAlign(ui.End).TextColor(k.TextMuted).Shrink(0) + ui.Text(c, sign).TextColor(fg).Width(10).Shrink(0) + text := l.Text + if text == "" { + text = " " + } + ui.Text(c, text).Grow(1).Shrink(1) + }) +} + +// agentDiffView shows lines[from:to] in a capped well, virtualized when long. +func agentDiffView(c *ui.Context, lines []internal.DiffLine, maxHeight float32) *ui.Element { + w := agentWellRows(c, len(lines), func(i int) { agentDiffRow(c, lines[i]) }, maxHeight) + return w.Padding(Density(c).Unit(), 0) +} + +// agentDecisionMark shows a decision by icon and word. +func agentDecisionMark(c *ui.Context, d FileDecision) { + ui.Row(c).Gap(Density(c).Unit()).AlignItems(ui.Center).Shrink(0).Children(func() { + agentCaption(c, agentDecisionIcon(c, d)) + }) +} + +// agentDecisionIcon draws a named decision icon, returning its word. +func agentDecisionIcon(c *ui.Context, d FileDecision) string { + k := Tokens(c) + tone, icon, word := k.TextMuted, "circle", msg(c, "file_change_card.pending") + switch d { + case FileAccepted: + tone, icon, word = k.Success, "circle-check", msg(c, "file_change_card.accepted") + case FileRejected: + tone, icon, word = k.Danger, "circle-x", msg(c, "file_change_card.rejected") + case FilePending: + default: + panic(fmt.Sprintf("mujica: unknown FileDecision %d", int(d))) + } + ui.Icon(c, icons.Must(icon)).Size(14, 14).TextColor(tone).Shrink(0).Label(word) + return word +} diff --git a/agent_parts.go b/agent_parts.go new file mode 100644 index 0000000..d2758a0 --- /dev/null +++ b/agent_parts.go @@ -0,0 +1,293 @@ +package mujica + +import ( + "bytes" + "encoding/json" + "fmt" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// AgentState is an agent or step state; zero is pending. +type AgentState int + +const ( + AgentPending AgentState = iota + AgentPlanning + AgentRunning + AgentWaiting + AgentDone + AgentFailed + AgentSkipped +) + +func (s AgentState) String() string { + switch s { + case AgentPending: + return "pending" + case AgentPlanning: + return "planning" + case AgentRunning: + return "running" + case AgentWaiting: + return "waiting" + case AgentDone: + return "done" + case AgentFailed: + return "failed" + case AgentSkipped: + return "skipped" + } + panic(fmt.Sprintf("mujica: unknown AgentState %d", int(s))) +} + +// agentTone returns the color and icon marking s. +func agentTone(k theme.Tokens, s AgentState) (ui.Color, *ui.SVG) { + switch s { + case AgentPlanning: + return k.Info, icons.Must("list") + case AgentRunning: + return k.AccentText, icons.Must("loader-circle") + case AgentWaiting: + return k.Warning, icons.Must("clock") + case AgentDone: + return k.Success, icons.Must("circle-check") + case AgentFailed: + return k.Danger, icons.Must("circle-x") + case AgentSkipped: + return k.TextMuted, icons.Must("ban") + } + return k.TextMuted, icons.Must("circle") +} + +// agentMark draws s; running spins unless still. +func agentMark(c *ui.Context, s AgentState, size float32, still bool) *ui.Element { + tone, icon := agentTone(Tokens(c), s) + if s == AgentRunning && !still { + return Spinner(c, SpinnerOptions{Size: size, Color: tone, Label: msg(c, "agent_status.running")}) + } + return ui.Icon(c, icon).Size(size, size).TextColor(tone).Shrink(0) +} + +// agentWord is the built-in word for s. +func agentWord(c *ui.Context, s AgentState) string { return msg(c, "agent_status."+s.String()) } + +// agentDuration formats d like "320 ms" or "4.2 s". +func agentDuration(d time.Duration) string { + if d < 0 { + panic(fmt.Sprintf("mujica: negative duration %v", d)) + } + switch { + case d < time.Second: + return fmt.Sprintf("%d ms", d.Milliseconds()) + case d < time.Minute: + return fmt.Sprintf("%.1f s", d.Seconds()) + case d < time.Hour: + return fmt.Sprintf("%d m %02d s", int(d.Minutes()), int(d.Seconds())%60) + } + return fmt.Sprintf("%d h %02d m", int(d.Hours()), int(d.Minutes())%60) +} + +// agentCard is the bordered surface every agent card sits on. +func agentCard(c *ui.Context) *ui.Element { + k := Tokens(c) + u := Density(c).Unit() + return ui.Column(c).Shrink(0).Padding(u*3).Gap(u*2).Radius(theme.CardRadius). + Background(k.Surface).Border(theme.BorderWidth, k.Border) +} + +// agentCaption is small muted text. +func agentCaption(c *ui.Context, s string) *ui.Element { + return ui.Text(c, s).FontSize(FontSize(c, theme.CaptionSize)).TextColor(Tokens(c).TextMuted) +} + +// agentWell styles a sunken monospace well. +func agentWell(c *ui.Context, l *ui.Element, maxHeight float32) *ui.Element { + k := Tokens(c) + u := Density(c).Unit() + return l.Shrink(1).MaxHeight(maxHeight).Padding(u*2, u*3).Radius(theme.ControlRadius). + Background(k.Background).Border(theme.BorderWidth, k.Border).Font(theme.MonoFont). + FontSize(FontSize(c, theme.CaptionSize+1)) +} + +// agentWellRows builds n rows in a well. +func agentWellRows(c *ui.Context, n int, row func(i int), maxHeight float32) *ui.Element { + return agentWell(c, agentRows(c, n, row), maxHeight) +} + +// agentRows builds n scrolling rows, virtualized when many. +func agentRows(c *ui.Context, n int, row func(i int)) *ui.Element { + if n > agentVirtualRows { + return ui.List(c, nil, n, row) + } + return ui.Scroll(c).Children(func() { + for i := range n { + row(i) + } + }) +} + +// agentVirtualRows is the row count above which wells virtualize. +const agentVirtualRows = 200 + +// agentCodeCache keeps lines and comment states per text. +type agentCodeCache struct { + language, text string + lines []string + open []bool +} + +func (cc *agentCodeCache) update(language, text string) { + if cc.lines != nil && cc.language == language && cc.text == text { + return + } + cc.language, cc.text = language, text + cc.lines = internal.SplitLines(text) + cc.open = make([]bool, len(cc.lines)) + block := false + for i, line := range cc.lines { + cc.open[i] = block + _, block = internal.Highlight(language, line, block) + } +} + +// agentPrettyJSON indents valid JSON; anything else comes back unchanged. +func agentPrettyJSON(s string) string { + var b bytes.Buffer + if json.Indent(&b, []byte(s), "", " ") != nil { + return s + } + return b.String() +} + +// agentTokenColor colors a highlight token from the theme. +func agentTokenColor(k theme.Tokens, kind internal.TokenKind) ui.Color { + switch kind { + case internal.TokKeyword: + return k.AccentText + case internal.TokString: + return k.Success + case internal.TokNumber, internal.TokType: + return k.Info + case internal.TokComment, internal.TokPunct: + return k.TextMuted + } + return k.Text +} + +// agentCodeLine builds one highlighted line of language. +func agentCodeLine(c *ui.Context, language, line string, inBlock bool) { + k := Tokens(c) + toks, _ := internal.Highlight(language, line, inBlock) + spans := make([]ui.Span, 0, len(toks)) + for _, t := range toks { + spans = append(spans, ui.Span{Text: t.Text, Color: agentTokenColor(k, t.Kind)}) + } + if len(spans) == 0 { + spans = append(spans, ui.Span{Text: " "}) + } + ui.RichText(c, spans...) +} + +// agentCode shows highlighted text in a capped well. +func agentCode(c *ui.Context, language, text string, maxHeight float32) *ui.Element { + holder := ui.Column(c).Shrink(1) + cc := ui.Local(holder, "mujica.agent.code", func() *agentCodeCache { return &agentCodeCache{} }) + (*cc).update(language, text) + lines, open := (*cc).lines, (*cc).open + row := func(i int) { agentCodeLine(c, language, lines[i], open[i]) } + holder.Children(func() { + agentWellRows(c, len(lines), row, maxHeight) + }) + return holder +} + +// agentAnsiColor maps a terminal color onto the theme. +func agentAnsiColor(k theme.Tokens, a internal.AnsiColor, fallback ui.Color) ui.Color { + switch a.Kind { + case internal.AnsiRGB: + return ui.RGB(a.R, a.G, a.B) + case internal.AnsiIndexed: + switch a.Index % 8 { + case 0: + return k.TextMuted + case 1: + return k.Danger + case 2: + return k.Success + case 3: + return k.Warning + case 4, 6: + return k.Info + case 5: + return k.AccentText + case 7: + return k.Text + } + } + return fallback +} + +// agentAnsiSpans turns parsed terminal spans into rich text spans. +func agentAnsiSpans(k theme.Tokens, in []internal.AnsiSpan) []ui.Span { + out := make([]ui.Span, 0, len(in)+1) + for _, s := range in { + fg := agentAnsiColor(k, s.Style.FG, k.Text) + bg := agentAnsiColor(k, s.Style.BG, ui.Transparent) + if s.Style.Inverse { + fg, bg = agentAnsiColor(k, s.Style.BG, k.Background), fg + } + if s.Style.Dim { + fg = fg.Alpha(0.7) + } + sp := ui.Span{Text: s.Text, Color: fg, Background: bg, Italic: s.Style.Italic, + Underline: s.Style.Underline, Strikethrough: s.Style.Strike} + if s.Style.Bold { + sp.Weight = 700 + } + out = append(out, sp) + } + if len(out) == 0 { + out = append(out, ui.Span{Text: " "}) + } + return out +} + +// agentBar is a thin progress bar named label. +func agentBar(c *ui.Context, frac float64, label string) *ui.Element { + if frac < 0 || frac > 1 || frac != frac { + panic(fmt.Sprintf("mujica: progress %v outside 0..1", frac)) + } + k := Tokens(c) + return ui.Box(c).FillWidth().Height(4).Shrink(0).Role(ui.RoleProgress).Label(label). + Draw(func(p *ui.Painter, r ui.Rect) { + p.Fill(r, k.Border, 2) + if frac > 0 { + p.Fill(ui.Rect{X: r.X, Y: r.Y, W: r.W * float32(frac), H: r.H}, k.AccentText, 2) + } + }) +} + +// agentToggle is a small text button reporting a click. +func agentToggle(c *ui.Context, label string, icon string, disabled bool) bool { + k := Tokens(c) + u := Density(c).Unit() + b := ui.ButtonBase(c).MinHeight(theme.MinHitSize).MinWidth(theme.MinHitSize).Padding(0, u*2).Gap(u). + Radius(theme.ControlRadius).Disabled(disabled).TextColor(k.AccentText) + internal.Ring(b, k.Focus, theme.ControlRadius) + if !disabled && b.Hovered() { + b.Background(k.SurfaceHover) + } + b.Children(func() { + if icon != "" { + ui.Icon(c, icons.Must(icon)).Size(14, 14) + } + ui.Text(c, label).FontSize(FontSize(c, theme.CaptionSize+1)).SingleLine() + }) + return !b.IsDisabled() && b.Clicked() +} diff --git a/agent_plan.go b/agent_plan.go new file mode 100644 index 0000000..2be4683 --- /dev/null +++ b/agent_plan.go @@ -0,0 +1,146 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// PlanItem is a plan task: pending, running, done or skipped. +type PlanItem struct { + ID string + Text string + State AgentState +} + +// AgentPlanOptions configure an AgentPlan. +type AgentPlanOptions struct { + // Title heads the checklist; empty uses "Plan". + Title string + Disabled bool + Still bool +} + +type agentPlanState struct{ draft string } + +// AgentPlan is a live checklist with skip, restore and add. +func AgentPlan(c *ui.Context, items *[]PlanItem, opts AgentPlanOptions) ChoiceResult { + if items == nil { + panic("mujica: AgentPlan needs items") + } + seen := map[string]bool{} + done, counted := 0, 0 + for i, it := range *items { + if it.ID == "" || seen[it.ID] { + panic(fmt.Sprintf("mujica: AgentPlan item %d needs a unique ID", i)) + } + switch it.State { + case AgentPending, AgentRunning, AgentDone, AgentSkipped: + default: + panic(fmt.Sprintf("mujica: AgentPlan item %q has state %v", it.ID, it.State)) + } + seen[it.ID] = true + if it.State != AgentSkipped { + counted++ + } + done += agentB2I(it.State == AgentDone) + } + u := Density(c).Unit() + title := opts.Title + if title == "" { + title = msg(c, "agent_plan.title") + } + var r ChoiceResult + r.Element = agentCard(c).Disabled(opts.Disabled).Label(title) + st := ui.Local(r.Element, "mujica.plan", func() agentPlanState { return agentPlanState{} }) + locked := r.Element.IsDisabled() + r.Element.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, title).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).FontWeight(600).Grow(1) + agentCaption(c, fmt.Sprintf(msg(c, "agent_plan.progress"), done, counted)) + }) + frac := 0.0 + if counted > 0 { + frac = float64(done) / float64(counted) + } + agentBar(c, frac, fmt.Sprintf(msg(c, "agent_plan.progress"), done, counted)) + list := *items + for i := range list { + ui.Row(c).Key(list[i].ID).Gap(u * 2).AlignItems(ui.Center).MinHeight(Density(c).ControlHeight()).Children(func() { + if agentPlanRow(c, &list[i], locked, opts.Still) { + r.changed = true + } + }) + } + if !locked && agentPlanAdd(c, &st.draft) { + *items = append(*items, PlanItem{ID: agentPlanID(seen), Text: strings.TrimSpace(st.draft)}) + st.draft = "" + r.changed = true + } + }) + if r.changed { + slog.Debug("mujica: agent_plan change", "items", len(*items)) + } + return r +} + +// agentPlanRow builds one item, reporting a user change. +func agentPlanRow(c *ui.Context, it *PlanItem, locked, still bool) bool { + k := Tokens(c) + checked := it.State == AgentDone + box := Checkbox(c, &checked, "", CheckboxOptions{Disabled: locked || it.State == AgentSkipped}).Label(it.Text) + changed := !locked && box.Changed() + if changed { + it.State = AgentPending + if checked { + it.State = AgentDone + } + } + t := ui.Text(c, it.Text).Grow(1).Shrink(1) + switch it.State { + case AgentSkipped: + t.Strikethrough().TextColor(k.TextMuted) + case AgentRunning: + agentMark(c, AgentRunning, 14, still) + agentCaption(c, msg(c, "agent_plan.doing")) + } + if it.State == AgentDone || locked { + return changed + } + label, icon, next := msg(c, "agent_plan.skip"), "ban", AgentSkipped + if it.State == AgentSkipped { + label, icon, next = msg(c, "agent_plan.restore"), "refresh-cw", AgentPending + } + if agentToggle(c, label, icon, false) { + it.State = next + changed = true + } + return changed +} + +// agentPlanAdd builds the new-item field and reports a non-empty submit. +func agentPlanAdd(c *ui.Context, draft *string) bool { + u := Density(c).Unit() + add := false + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + in := TextInput(c, draft, TextInputOptions{Placeholder: msg(c, "agent_plan.placeholder"), Label: msg(c, "agent_plan.placeholder")}) + in.Element.Grow(1) + blank := strings.TrimSpace(*draft) == "" + add = Button(c, msg(c, "agent_plan.add"), ButtonOptions{Variant: Secondary, Disabled: blank}).Clicked() + add = (add || in.Submitted()) && !blank + }) + return add +} + +// agentPlanID returns an ID no item uses yet. +func agentPlanID(seen map[string]bool) string { + for n := len(seen) + 1; ; n++ { + if id := fmt.Sprintf("item-%d", n); !seen[id] { + return id + } + } +} diff --git a/agent_plan_test.go b/agent_plan_test.go new file mode 100644 index 0000000..1353cc3 --- /dev/null +++ b/agent_plan_test.go @@ -0,0 +1,94 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func agentPlanSample() []PlanItem { + return []PlanItem{ + {ID: "a", Text: "Read the guest list", State: AgentDone}, + {ID: "b", Text: "Assign the seats", State: AgentRunning}, + {ID: "c", Text: "Order the flowers"}, + } +} + +func planTester(items *[]PlanItem, opts AgentPlanOptions, changes *int) *ui.Tester { + opts.Still = true + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if AgentPlan(c, items, opts).Changed() { + *changes++ + } + }, 560, 500) +} + +func TestAgentPlanProgressCheckSkipAdd(t *testing.T) { + items := agentPlanSample() + changes := 0 + tt := planTester(&items, AgentPlanOptions{}, &changes) + if !tt.HasText("1 / 3 done") || !tt.HasText("In progress") { + t.Fatalf("texts %q", tt.Texts()) + } + _ = tt.Click("Order the flowers") // the box is named by the item + if items[2].State != AgentDone || changes != 1 || !tt.HasText("2 / 3 done") { + t.Fatalf("check: %+v changes %d", items[2], changes) + } + skips, _ := tt.Find("Skip") + tt.ClickAt(skips.X+4, skips.Y+4) // the running item's Skip + if items[1].State != AgentSkipped || !tt.HasText("2 / 2 done") { + t.Fatalf("skip: %+v texts %q", items[1], tt.Texts()) + } + _ = tt.Click("Restore") + if items[1].State != AgentPending { + t.Fatalf("restore: %+v", items[1]) + } + _ = tt.Click("Add a step") + tt.Type(" ") + tt.Key(0, ui.KeyEnter) + if len(items) != 3 { + t.Fatal("blank item added") + } + tt.Type("Light the candles") + tt.Key(0, ui.KeyEnter) + if len(items) != 4 || items[3].Text != "Light the candles" || items[3].ID == "" || !tt.HasText("Light the candles") { + t.Fatalf("add: %+v", items) + } +} + +func TestAgentPlanLiveUpdateAndDisabled(t *testing.T) { + items := agentPlanSample() + changes := 0 + tt := planTester(&items, AgentPlanOptions{Disabled: true, Title: "Ball"}, &changes) + _ = tt.Click("Order the flowers") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeySpace) + if changes != 0 || items[2].State != AgentPending || tt.HasText("Add a step") || tt.HasText("Skip") { + t.Fatalf("disabled plan changed: %+v", items) + } + items[2].State = AgentDone // the agent checks it off + tt.Frame() + if !tt.HasText("2 / 3 done") || !tt.HasText("Ball") { + t.Fatalf("live update: %q", tt.Texts()) + } +} + +func TestAgentPlanRejectsBadState(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + items := []PlanItem{{ID: "a", Text: "x", State: AgentFailed}} + n := 0 + planTester(&items, AgentPlanOptions{}, &n) +} + +func TestAgentPlanSnapshot(t *testing.T) { + snapshot(t, "agent_plan", 520, 330, func(c *ui.Context) { + items := agentPlanSample() + items = append(items, PlanItem{ID: "d", Text: "Hire the quartet", State: AgentSkipped}) + ui.Column(c).Padding(16).Children(func() { AgentPlan(c, &items, AgentPlanOptions{Still: true}) }) + }) +} diff --git a/agent_progress.go b/agent_progress.go new file mode 100644 index 0000000..3fb6459 --- /dev/null +++ b/agent_progress.go @@ -0,0 +1,36 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" +) + +// AgentProgressOptions configure an AgentProgress. +type AgentProgressOptions struct { + // Label names the work; empty uses "Progress". + Label string + // Action is what the agent does now. + Action string + // Indeterminate shows work of unknown length; the value is ignored. + Indeterminate bool + Still bool +} + +// AgentProgress shows progress 0 to 1 and the current action. +func AgentProgress(c *ui.Context, value float64, opts AgentProgressOptions) *ui.Element { + label := opts.Label + if label == "" { + label = msg(c, "agent_progress.label") + } + u := Density(c).Unit() + col := ui.Column(c).FillWidth().Shrink(0).Gap(u * 1.5) + col.Children(func() { + Progress(c, value, ProgressOptions{Label: label, ShowValue: !opts.Indeterminate, Indeterminate: opts.Indeterminate}) + if opts.Action != "" { + ui.Row(c).Gap(u * 1.5).AlignItems(ui.Center).Role(ui.RoleStatus).Label(opts.Action).Children(func() { + agentMark(c, AgentRunning, 14, opts.Still) + agentCaption(c, opts.Action) + }) + } + }) + return col +} diff --git a/agent_progress_test.go b/agent_progress_test.go new file mode 100644 index 0000000..5103ede --- /dev/null +++ b/agent_progress_test.go @@ -0,0 +1,54 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestAgentProgressValueAndAction(t *testing.T) { + value, action := 0.25, "Reading ledger.md" + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + AgentProgress(c, value, AgentProgressOptions{Action: action, Still: true}) + }, 400, 200) + if !tt.HasText("25%") || !tt.HasText("Reading ledger.md") || !tt.HasText("Progress") { + t.Fatalf("texts %q", tt.Texts()) + } + value, action = 0.8, "Writing summary.md" + tt.Frame() + if !tt.HasText("80%") || !tt.HasText("Writing summary.md") || tt.HasText("Reading ledger.md") { + t.Fatalf("update: %q", tt.Texts()) + } +} + +func TestAgentProgressIndeterminate(t *testing.T) { + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + AgentProgress(c, 0, AgentProgressOptions{Label: "Research", Indeterminate: true, Still: true}) + }, 400, 200) + tt.SetPreferences(ui.Preferences{ReduceMotion: true, TextScale: 1}) + if tt.HasText("0%") || !tt.HasText("Research") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestAgentProgressRejectsOutOfRange(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + AgentProgress(c, 1.5, AgentProgressOptions{}) + }, 200, 100) +} + +func TestAgentProgressSnapshot(t *testing.T) { + snapshot(t, "agent_progress", 420, 110, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + AgentProgress(c, 0.62, AgentProgressOptions{Label: "Preparing the ball", Action: "Writing the seating chart"}) + }) + }) +} diff --git a/agent_status.go b/agent_status.go new file mode 100644 index 0000000..4384112 --- /dev/null +++ b/agent_status.go @@ -0,0 +1,34 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// AgentStatusOptions configure an AgentStatus. +type AgentStatusOptions struct { + // Label replaces the built-in word, as "Writing the report". + Label string + // Still stops the running animation. + Still bool +} + +// AgentStatus shows a state by icon shape and word. +func AgentStatus(c *ui.Context, state AgentState, opts AgentStatusOptions) *ui.Element { + label := opts.Label + if label == "" { + label = agentWord(c, state) // panics on an unknown state + } + k := Tokens(c) + u := Density(c).Unit() + tone, _ := agentTone(k, state) + pill := ui.Row(c).Shrink(0).AlignSelf(ui.Start).AlignItems(ui.Center).Gap(u*1.5).Padding(u, u*2.5). + Radius(theme.CardRadius).Border(theme.BorderWidth, tone).Background(k.Surface). + Role(ui.RoleStatus).Label(label) + pill.Children(func() { + agentMark(c, state, 14, opts.Still) + ui.Text(c, label).FontSize(FontSize(c, theme.CaptionSize+1)).TextColor(k.Text).SingleLine() + }) + return pill +} diff --git a/agent_status_test.go b/agent_status_test.go new file mode 100644 index 0000000..a642c4c --- /dev/null +++ b/agent_status_test.go @@ -0,0 +1,69 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func TestAgentStatusWords(t *testing.T) { + states := []AgentState{AgentPlanning, AgentRunning, AgentWaiting, AgentDone, AgentFailed} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + for _, s := range states { + AgentStatus(c, s, AgentStatusOptions{Still: true}) + } + AgentStatus(c, AgentRunning, AgentStatusOptions{Label: "Writing the report", Still: true}) + }, 400, 400) + for _, w := range []string{"Planning", "Running", "Waiting", "Done", "Failed", "Writing the report"} { + if !tt.HasText(w) { + t.Fatalf("missing %q in %q", w, tt.Texts()) + } + } +} + +func TestAgentStatusAnimationStopsWhenStill(t *testing.T) { + still := false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + AgentStatus(c, AgentRunning, AgentStatusOptions{Still: still}) + }, 300, 100) + tt.Frame() + moving := string(tt.Image().Pix) + time.Sleep(80 * time.Millisecond) + tt.Frame() + if moving == string(tt.Image().Pix) { + t.Fatal("running status did not animate") + } + still = true + tt.Frame() + a := string(tt.Image().Pix) + time.Sleep(80 * time.Millisecond) + tt.Frame() + if a != string(tt.Image().Pix) { + t.Fatal("still status kept moving") + } +} + +func TestAgentStatusRejectsUnknownState(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + AgentStatus(c, AgentState(42), AgentStatusOptions{}) + }, 200, 100) +} + +func TestAgentStatusSnapshot(t *testing.T) { + snapshot(t, "agent_status", 480, 120, func(c *ui.Context) { + ui.Row(c).Padding(16).Gap(8).Wrap().Children(func() { + for _, s := range []AgentState{AgentPlanning, AgentRunning, AgentWaiting, AgentDone, AgentFailed} { + AgentStatus(c, s, AgentStatusOptions{}) + } + }) + }) +} diff --git a/agent_step_list.go b/agent_step_list.go new file mode 100644 index 0000000..710dc56 --- /dev/null +++ b/agent_step_list.go @@ -0,0 +1,140 @@ +package mujica + +import ( + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// AgentStep is one step of an agent run. +type AgentStep struct { + ID string + Title string + Detail string + State AgentState + Duration time.Duration +} + +// AgentStepListOptions configure an AgentStepList. +type AgentStepListOptions struct { + Disabled bool + Still bool +} + +// AgentStepListResult reports this frame's events. +type AgentStepListResult struct { + Element *ui.Element + // Retry is the failed step to retry, else "". + Retry string + // Toggled is the step whose detail toggled, else "". + Toggled string +} + +// AgentStepList is a step timeline with details and retries. +func AgentStepList(c *ui.Context, steps []AgentStep, opts AgentStepListOptions) AgentStepListResult { + current := -1 + seen := make(map[string]bool, len(steps)) + for i, s := range steps { + if s.ID == "" || s.Title == "" || seen[s.ID] { + panic(fmt.Sprintf("mujica: AgentStepList step %d needs a unique ID and a Title", i)) + } + seen[s.ID] = true + if current < 0 && (s.State == AgentRunning || s.State == AgentWaiting || s.State == AgentPlanning) { + current = i + } + } + var r AgentStepListResult + r.Element = ui.Column(c).Shrink(0).FocusGroup(ui.Vertical).Disabled(opts.Disabled) + open := ui.Local(r.Element, "mujica.steps.open", func() map[string]bool { return map[string]bool{} }) + r.Element.Children(func() { + for i, s := range steps { + ui.Column(c).Key(s.ID).Children(func() { + if agentStepRow(c, s, i, len(steps), i == current, (*open)[s.ID], opts.Still, &r) { + (*open)[s.ID] = !(*open)[s.ID] + r.Toggled = s.ID + } + }) + } + }) + if r.Element.IsDisabled() { + r.Retry, r.Toggled = "", "" + } + for id := range *open { + if !seen[id] { + delete(*open, id) + } + } + if r.Retry != "" || r.Toggled != "" { + slog.Debug("mujica: agent_step_list event", "retry", r.Retry, "toggled", r.Toggled) + } + return r +} + +// agentStepRow builds one step, reporting a header click. +func agentStepRow(c *ui.Context, s AgentStep, i, n int, current, open, still bool, r *AgentStepListResult) bool { + k := Tokens(c) + d := Density(c) + u := d.Unit() + clicked := false + top := (d.ControlHeight() - 18) / 2 // centers the mark on the step header + ui.Row(c).Gap(u * 3).AlignItems(ui.Stretch).Children(func() { + // The rail joins the marks; it is drawn, not focusable. + ui.Column(c).Width(20).Shrink(0).AlignItems(ui.Center).Draw(func(p *ui.Painter, rc ui.Rect) { + x := internal.Snap(p, rc.X+rc.W/2) + if i > 0 { + p.Line(x, rc.Y, x, rc.Y+top-3, 1, k.ControlBorder) + } + if i < n-1 { + p.Line(x, rc.Y+top+21, x, rc.Y+rc.H, 1, k.ControlBorder) + } + }).Children(func() { + ui.Box(c).Height(top) + agentMark(c, s.State, 18, still) + }) + ui.Column(c).Grow(1).Shrink(1).Gap(u).Padding(0, 0, u*2, 0).Children(func() { + head := ui.ButtonBase(c).Justify(ui.Start).Gap(u*2).MinHeight(d.ControlHeight()).Padding(0, u*2). + Radius(theme.ControlRadius).Label(s.Title + ", " + agentWord(c, s.State)) + internal.Ring(head, k.Focus, theme.ControlRadius) + if current { + head.Background(k.Selection).Border(theme.BorderWidth, k.AccentText) + } else if head.Hovered() { + head.Background(k.SurfaceHover) + } + head.Children(func() { + ui.Text(c, s.Title).FontWeight(600).Grow(1).Shrink(1) + if current { + agentCaption(c, msg(c, "agent_step_list.current")) + } + agentCaption(c, agentWord(c, s.State)) + if s.State == AgentDone || s.State == AgentFailed { + agentCaption(c, agentDuration(s.Duration)) + } + if s.Detail != "" { + chev := "chevron-right" + if open { + chev = "chevron-down" + } + ui.Icon(c, icons.Must(chev)).Size(14, 14).TextColor(k.TextMuted) + } + }) + clicked = s.Detail != "" && !head.IsDisabled() && head.Clicked() + if open && s.Detail != "" { + ui.Text(c, s.Detail).TextColor(k.TextMuted).Selectable().Padding(0, u*2) + } + if s.State == AgentFailed { + ui.Row(c).Children(func() { + if agentToggle(c, msg(c, "agent_step_list.retry"), "refresh-cw", head.IsDisabled()) { + r.Retry = s.ID + } + }) + } + }) + }) + return clicked +} diff --git a/agent_step_list_test.go b/agent_step_list_test.go new file mode 100644 index 0000000..fa9d0b4 --- /dev/null +++ b/agent_step_list_test.go @@ -0,0 +1,87 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +var agentStepsSample = []AgentStep{ + {ID: "plan", Title: "Read the guest list", State: AgentDone, Duration: 800 * time.Millisecond, Detail: "42 guests, 3 late."}, + {ID: "seat", Title: "Assign the seats", State: AgentFailed, Duration: 2 * time.Second, Detail: "Table 4 is over capacity."}, + {ID: "send", Title: "Send the invitations", State: AgentRunning}, + {ID: "log", Title: "Record the ledger", State: AgentPending}, +} + +func stepTester(steps []AgentStep, opts AgentStepListOptions, got *[]AgentStepListResult) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := AgentStepList(c, steps, opts) + if r.Retry != "" || r.Toggled != "" { + *got = append(*got, r) + } + }, 600, 500) +} + +func TestAgentStepListCurrentDetailRetry(t *testing.T) { + var got []AgentStepListResult + tt := stepTester(agentStepsSample, AgentStepListOptions{Still: true}, &got) + if !tt.HasText("Current") || !tt.HasText("Running") || !tt.HasText("800 ms") { + t.Fatalf("texts %q", tt.Texts()) + } + if tt.HasText("Table 4 is over capacity.") { + t.Fatal("detail shown while closed") + } + _ = tt.Click("Assign the seats") + if len(got) != 1 || got[0].Toggled != "seat" || !tt.HasText("Table 4 is over capacity.") { + t.Fatalf("toggle: %+v", got) + } + _ = tt.Click("Retry") + if len(got) != 2 || got[1].Retry != "seat" { + t.Fatalf("retry: %+v", got) + } +} + +func TestAgentStepListKeyboard(t *testing.T) { + var got []AgentStepListResult + tt := stepTester(agentStepsSample, AgentStepListOptions{Still: true}, &got) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if len(got) != 1 || got[0].Toggled != "plan" || !tt.HasText("42 guests, 3 late.") { + t.Fatalf("Enter on the first step: %+v", got) + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDown) // past Assign the seats onto its Retry + tt.Key(0, ui.KeyEnter) + if len(got) != 2 || got[1].Retry != "seat" { + t.Fatalf("arrows to Retry: %+v", got) + } +} + +func TestAgentStepListDisabled(t *testing.T) { + var got []AgentStepListResult + tt := stepTester(agentStepsSample, AgentStepListOptions{Disabled: true, Still: true}, &got) + _ = tt.Click("Assign the seats") + _ = tt.Click("Retry") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if len(got) != 0 { + t.Fatalf("disabled list reported %+v", got) + } +} + +func TestAgentStepListRejectsDuplicateIDs(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + stepTester([]AgentStep{{ID: "a", Title: "x"}, {ID: "a", Title: "y"}}, AgentStepListOptions{}, nil) +} + +func TestAgentStepListSnapshot(t *testing.T) { + snapshot(t, "agent_step_list", 520, 340, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { AgentStepList(c, agentStepsSample, AgentStepListOptions{Still: true}) }) + }) +} diff --git a/artifact_panel.go b/artifact_panel.go new file mode 100644 index 0000000..189333b --- /dev/null +++ b/artifact_panel.go @@ -0,0 +1,148 @@ +package mujica + +import ( + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// ArtifactKind is what an artifact holds; zero is code. +type ArtifactKind int + +const ( + ArtifactCode ArtifactKind = iota + ArtifactDocument + ArtifactWeb +) + +// Artifact is something an agent made; the caller owns it. +type Artifact struct { + Title string + Kind ArtifactKind + // Language highlights code, as "go" or "json". + Language string + Content string +} + +// ArtifactPanelOptions configure an ArtifactPanel. +type ArtifactPanelOptions struct { + // Preview renders documents and web pages; the caller supplies it. + Preview func() + // Height of the body; 320 DIPs when zero. + Height float32 + Disabled bool +} + +// ArtifactPanelResult reports this frame's events. +type ArtifactPanelResult struct { + Element *ui.Element + // Copied reports the content went to the clipboard. + Copied bool + // Exported asks the caller to export the artifact. + Exported bool +} + +type artifactPanelState struct { + source bool + copiedAt time.Time +} + +// ArtifactPanel shows an artifact, with copy and export. +func ArtifactPanel(c *ui.Context, art Artifact, opts ArtifactPanelOptions) ArtifactPanelResult { + if art.Title == "" { + panic("mujica: ArtifactPanel needs a Title") + } + if art.Kind < ArtifactCode || art.Kind > ArtifactWeb { + panic(fmt.Sprintf("mujica: unknown ArtifactKind %d", int(art.Kind))) + } + if art.Kind != ArtifactCode && opts.Preview == nil { + panic("mujica: ArtifactPanel needs a Preview for documents and web pages") + } + if opts.Height < 0 { + panic("mujica: ArtifactPanel Height is negative") + } + h := opts.Height + if h == 0 { + h = 320 + } + k := Tokens(c) + u := Density(c).Unit() + var r ArtifactPanelResult + r.Element = agentCard(c).Disabled(opts.Disabled).Label(art.Title) + st := ui.Local(r.Element, "mujica.artifact", func() artifactPanelState { return artifactPanelState{source: art.Kind == ArtifactCode} }) + locked := r.Element.IsDisabled() + r.Element.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, art.Title).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).FontWeight(600).SingleLine().Grow(1).Shrink(1) + if opts.Preview != nil { + artifactViewSwitch(c, &st.source, locked) + } + copied := !st.copiedAt.IsZero() && c.Now().Sub(st.copiedAt) < 2*time.Second + label, icon := msg(c, "artifact_panel.copy"), "copy" + if copied { + label, icon = msg(c, "artifact_panel.copied"), "check" + c.After(2*time.Second - c.Now().Sub(st.copiedAt)) + } + if agentToggle(c, label, icon, locked) { + c.WriteClipboard(art.Content) + st.copiedAt, r.Copied = c.Now(), true + } + if agentToggle(c, msg(c, "artifact_panel.export"), "upload", locked) { + r.Exported = true + } + }) + ui.Column(c).Height(h).Shrink(0).Children(func() { + if st.source || opts.Preview == nil { + agentCode(c, art.Language, art.Content, h).Grow(1) + return + } + ui.Scroll(c).Grow(1).Padding(u*3).Radius(theme.ControlRadius).Background(k.Background). + Border(theme.BorderWidth, k.Border).Children(opts.Preview) + }) + }) + if r.Copied || r.Exported { + slog.Debug("mujica: artifact_panel event", "title", art.Title, "copied", r.Copied, "exported", r.Exported) + } + return r +} + +// artifactViewSwitch is the Preview / Source segmented switch. +func artifactViewSwitch(c *ui.Context, source *bool, locked bool) { + k := Tokens(c) + u := Density(c).Unit() + ui.Row(c).Shrink(0).FocusGroup(ui.Horizontal).Border(theme.BorderWidth, k.ControlBorder).Radius(theme.ControlRadius). + Role(ui.RoleRadioGroup).Children(func() { + for _, src := range []bool{false, true} { + label, icon := msg(c, "artifact_panel.preview"), "eye" + if src { + label, icon = msg(c, "artifact_panel.source"), "file-text" + } + b := ui.ButtonBase(c).MinHeight(theme.MinHitSize).Padding(0, u*2).Gap(u).Role(ui.RoleRadio).Label(label). + Disabled(locked) + internal.Ring(b, k.Focus, theme.ControlRadius) + on := *source == src + if on { + b.Background(k.Selection) + } else if b.Hovered() { + b.Background(k.SurfaceHover) + } + b.Children(func() { + if on { + ui.Icon(c, icons.Must("check")).Size(12, 12).TextColor(k.AccentText) + } + ui.Icon(c, icons.Must(icon)).Size(14, 14) + ui.Text(c, label).FontSize(FontSize(c, theme.CaptionSize+1)) + }) + if !b.IsDisabled() && b.Clicked() && !on { + *source = src + slog.Debug("mujica: artifact_panel view", "source", src) + } + } + }) +} diff --git a/artifact_panel_test.go b/artifact_panel_test.go new file mode 100644 index 0000000..a37f441 --- /dev/null +++ b/artifact_panel_test.go @@ -0,0 +1,79 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +var artifactCodeSample = Artifact{Title: "seating.go", Language: "go", Content: "package court\n\n// Seats maps guests to tables.\nfunc Seats() map[string]int {\n\treturn map[string]int{\"Sakiko\": 1}\n}\n"} + +func artifactTester(art Artifact, opts ArtifactPanelOptions, got *[]ArtifactPanelResult) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := ArtifactPanel(c, art, opts) + if r.Copied || r.Exported { + *got = append(*got, r) + } + }, 600, 460) +} + +func TestArtifactPanelCodeCopyExport(t *testing.T) { + var got []ArtifactPanelResult + tt := artifactTester(artifactCodeSample, ArtifactPanelOptions{}, &got) + if !tt.HasText("// Seats maps guests to tables.") || tt.HasText("Preview") { + t.Fatalf("texts %q", tt.Texts()) + } + _ = tt.Click("Copy") + if len(got) != 1 || !got[0].Copied || tt.Clipboard() != artifactCodeSample.Content || !tt.HasText("Copied") { + t.Fatalf("copy: %+v clipboard %q", got, tt.Clipboard()) + } + _ = tt.Click("Export") + if len(got) != 2 || !got[1].Exported { + t.Fatalf("export: %+v", got) + } +} + +func TestArtifactPanelPreviewSourceSwitch(t *testing.T) { + doc := Artifact{Title: "Invitation", Kind: ArtifactDocument, Content: "# You are invited\n"} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ArtifactPanel(c, doc, ArtifactPanelOptions{Preview: func() { ui.Text(c, "Rendered invitation") }}) + }, 600, 460) + if !tt.HasText("Rendered invitation") || tt.HasText("# You are invited") { + t.Fatalf("preview first: %q", tt.Texts()) + } + _ = tt.Click("Source") + if !tt.HasText("# You are invited") || tt.HasText("Rendered invitation") { + t.Fatalf("source: %q", tt.Texts()) + } + tt.Key(0, ui.KeyLeft) // the switch is a focus group + tt.Key(0, ui.KeyEnter) + if !tt.HasText("Rendered invitation") { + t.Fatal("keyboard back to preview failed") + } +} + +func TestArtifactPanelDisabledAndRules(t *testing.T) { + var got []ArtifactPanelResult + tt := artifactTester(artifactCodeSample, ArtifactPanelOptions{Disabled: true}, &got) + _ = tt.Click("Copy") + _ = tt.Click("Export") + if len(got) != 0 || tt.Clipboard() != "" { + t.Fatalf("disabled panel acted: %+v", got) + } + defer func() { + if recover() == nil { + t.Fatal("web artifact without Preview did not panic") + } + }() + artifactTester(Artifact{Title: "x", Kind: ArtifactWeb}, ArtifactPanelOptions{}, &got) +} + +func TestArtifactPanelSnapshot(t *testing.T) { + snapshot(t, "artifact_panel", 560, 300, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + ArtifactPanel(c, artifactCodeSample, ArtifactPanelOptions{Height: 170, Preview: func() {}}) + }) + }) +} diff --git a/artifact_version_switcher.go b/artifact_version_switcher.go new file mode 100644 index 0000000..2913f14 --- /dev/null +++ b/artifact_version_switcher.go @@ -0,0 +1,89 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" +) + +// ArtifactVersion is one saved version of an artifact. +type ArtifactVersion struct { + Label string + Note string +} + +// ArtifactVersionSwitcherOptions configure an ArtifactVersionSwitcher. +type ArtifactVersionSwitcherOptions struct { + Disabled bool +} + +// ArtifactVersionResult reports this frame's events. +type ArtifactVersionResult struct { + Element *ui.Element + // Changed reports *current moved. + Changed bool + // Compare asks to diff current against the previous version. + Compare bool +} + +// ArtifactVersionSwitcher steps between artifact versions. +func ArtifactVersionSwitcher(c *ui.Context, current *int, versions []ArtifactVersion, opts ArtifactVersionSwitcherOptions) ArtifactVersionResult { + if current == nil || len(versions) == 0 || *current < 0 || *current >= len(versions) { + panic("mujica: ArtifactVersionSwitcher needs versions and a current index inside them") + } + for i, v := range versions { + if v.Label == "" { + panic(fmt.Sprintf("mujica: ArtifactVersionSwitcher version %d needs a Label", i)) + } + } + u := Density(c).Unit() + n := len(versions) + var r ArtifactVersionResult + r.Element = ui.Row(c).Shrink(0).Gap(u * 2).AlignItems(ui.Center).Disabled(opts.Disabled). + Label(msg(c, "artifact_version_switcher.label")) + locked := r.Element.IsDisabled() + move := func(d int) { + if to := *current + d; !locked && to >= 0 && to < n { + *current, r.Changed = to, true + } + } + r.Element.Children(func() { + if iconAction(c, icons.Must("chevron-left"), msg(c, "artifact_version_switcher.older")).Disabled(locked || *current == 0).Clicked() { + move(-1) + } + v := versions[*current] + ui.Column(c).Shrink(1).Role(ui.RoleStatus).Label(v.Label).Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, v.Label).FontWeight(600).SingleLine() + agentCaption(c, fmt.Sprintf(msg(c, "artifact_version_switcher.count"), *current+1, n)) + }) + if v.Note != "" { + agentCaption(c, v.Note).SingleLine() + } + }) + if iconAction(c, icons.Must("chevron-right"), msg(c, "artifact_version_switcher.newer")).Disabled(locked || *current == n-1).Clicked() { + move(1) + } + if *current > 0 { + label := fmt.Sprintf(msg(c, "artifact_version_switcher.compare"), versions[*current-1].Label) + if agentToggle(c, label, "arrow-up-down", locked) { + r.Compare = true + } + } + }) + if !locked { + if r.Element.Shortcut(0, ui.KeyLeft) { + move(-1) + } + if r.Element.Shortcut(0, ui.KeyRight) { + move(1) + } + } + if r.Changed || r.Compare { + slog.Debug("mujica: artifact_version_switcher event", "current", *current, "compare", r.Compare) + } + return r +} diff --git a/artifact_version_switcher_test.go b/artifact_version_switcher_test.go new file mode 100644 index 0000000..f910887 --- /dev/null +++ b/artifact_version_switcher_test.go @@ -0,0 +1,77 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +var artifactVersionsSample = []ArtifactVersion{ + {Label: "v1", Note: "First draft"}, + {Label: "v2", Note: "Added the quartet"}, + {Label: "v3", Note: "Moved the wine table"}, +} + +func versionTester(cur *int, opts ArtifactVersionSwitcherOptions, got *[]ArtifactVersionResult) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := ArtifactVersionSwitcher(c, cur, artifactVersionsSample, opts) + if r.Changed || r.Compare { + *got = append(*got, r) + } + }, 600, 120) +} + +func TestArtifactVersionSwitcherStepsAndCompare(t *testing.T) { + cur := 2 + var got []ArtifactVersionResult + tt := versionTester(&cur, ArtifactVersionSwitcherOptions{}, &got) + if !tt.HasText("3 of 3") || !tt.HasText("Moved the wine table") || !tt.HasText("Compare with v2") { + t.Fatalf("texts %q", tt.Texts()) + } + _ = tt.Click("Compare with v2") + if len(got) != 1 || !got[0].Compare || cur != 2 { + t.Fatalf("compare: %+v", got) + } + _ = tt.Click("Older version") + _ = tt.Click("Older version") + if cur != 0 || tt.HasText("Compare with v1") || !tt.HasText("First draft") { + t.Fatalf("older: cur %d texts %q", cur, tt.Texts()) + } + _ = tt.Click("Older version") // disabled at the first version + if cur != 0 || len(got) != 3 { + t.Fatalf("past the first: cur %d events %d", cur, len(got)) + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + if cur != 1 { + t.Fatalf("Right: cur %d", cur) + } +} + +func TestArtifactVersionSwitcherDisabledAndRange(t *testing.T) { + cur := 1 + var got []ArtifactVersionResult + tt := versionTester(&cur, ArtifactVersionSwitcherOptions{Disabled: true}, &got) + _ = tt.Click("Older version") + _ = tt.Click("Compare with v1") + if cur != 1 || len(got) != 0 { + t.Fatalf("disabled moved: cur %d %+v", cur, got) + } + defer func() { + if recover() == nil { + t.Fatal("out-of-range current did not panic") + } + }() + cur = 5 + versionTester(&cur, ArtifactVersionSwitcherOptions{}, &got) +} + +func TestArtifactVersionSwitcherSnapshot(t *testing.T) { + snapshot(t, "artifact_version_switcher", 560, 90, func(c *ui.Context) { + cur := 1 + ui.Column(c).Padding(16).Children(func() { + ArtifactVersionSwitcher(c, &cur, artifactVersionsSample, ArtifactVersionSwitcherOptions{}) + }) + }) +} diff --git a/checkpoint_list.go b/checkpoint_list.go new file mode 100644 index 0000000..ff721e8 --- /dev/null +++ b/checkpoint_list.go @@ -0,0 +1,119 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// Checkpoint is a saved point to roll back to. +type Checkpoint struct { + ID string + Label string + Note string +} + +// CheckpointListOptions configure a CheckpointList. +type CheckpointListOptions struct { + // MaxHeight caps the scrolling list; zero means 360. + MaxHeight float32 + Disabled bool +} + +type checkpointListState struct { + asking bool + target string +} + +// CheckpointList marks the current point and confirms rollbacks. +func CheckpointList(c *ui.Context, current *string, points []Checkpoint, opts CheckpointListOptions) ChoiceResult { + if current == nil { + panic("mujica: CheckpointList needs current") + } + if opts.MaxHeight < 0 { + panic("mujica: CheckpointList MaxHeight is negative") + } + seen := map[string]bool{} + for i, p := range points { + if p.ID == "" || p.Label == "" || seen[p.ID] { + panic(fmt.Sprintf("mujica: CheckpointList point %d needs a unique ID and a Label", i)) + } + seen[p.ID] = true + } + maxH := opts.MaxHeight + if maxH == 0 { + maxH = 360 + } + k := Tokens(c) + var r ChoiceResult + r.Element = ui.Column(c).Shrink(0).Disabled(opts.Disabled).Label(msg(c, "checkpoint_list.label")) + st := ui.Local(r.Element, "mujica.checkpoints", func() checkpointListState { return checkpointListState{} }) + locked := r.Element.IsDisabled() + if locked { + st.asking = false // a disabled list closes its confirmation + } + r.Element.Children(func() { + if len(points) == 0 { + agentCaption(c, msg(c, "checkpoint_list.empty")) + return + } + agentRows(c, len(points), func(i int) { + if checkpointRow(c, points[i], points[i].ID == *current, locked) { + st.asking, st.target = true, points[i].ID + } + }).Shrink(1).MaxHeight(maxH).Background(k.Surface).Border(theme.BorderWidth, k.Border). + Radius(theme.CardRadius).Dividers(theme.BorderWidth, k.Border) + label := st.target + for _, p := range points { + if p.ID == st.target { + label = p.Label + } + } + res := AlertDialog(c, &st.asking, AlertDialogOptions{Title: fmt.Sprintf(msg(c, "checkpoint_list.confirm"), label), + Description: msg(c, "checkpoint_list.warning"), ConfirmLabel: msg(c, "checkpoint_list.rollback")}) + if res.Confirmed && !locked && seen[st.target] { + *current, r.changed = st.target, true + slog.Debug("mujica: checkpoint_list rollback", "to", st.target) + } + }) + return r +} + +// checkpointRow shows one checkpoint and reports a rollback request. +func checkpointRow(c *ui.Context, p Checkpoint, current, locked bool) bool { + k := Tokens(c) + d := Density(c) + u := d.Unit() + asked := false + row := ui.Row(c).Key(p.ID).Gap(u*3).AlignItems(ui.Center).MinHeight(d.ControlHeight()+u*2).Padding(u*2, u*3) + if current { + row.Background(k.Selection) + } + row.Children(func() { + ui.Box(c).Size(14, 14).Shrink(0).Draw(func(pt *ui.Painter, r ui.Rect) { + cx, cy := internal.Snap(pt, r.X+r.W/2), internal.Snap(pt, r.Y+r.H/2) + if current { + pt.FillPath(internal.Diamond(cx, cy, 12), k.AccentText) + return + } + pt.StrokePath(internal.Diamond(cx, cy, 10), 1.5, k.ControlBorder) + }) + ui.Column(c).Grow(1).Shrink(1).Gap(u / 2).Children(func() { + ui.Text(c, p.Label).FontWeight(600).SingleLine() + if p.Note != "" { + agentCaption(c, p.Note) + } + }) + if current { + agentCaption(c, msg(c, "checkpoint_list.current")) + return + } + asked = agentToggle(c, msg(c, "checkpoint_list.rollback"), "refresh-cw", locked) + }) + row.Label(p.Label) + return asked +} diff --git a/checkpoint_list_test.go b/checkpoint_list_test.go new file mode 100644 index 0000000..f37f863 --- /dev/null +++ b/checkpoint_list_test.go @@ -0,0 +1,77 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +var checkpointsSample = []Checkpoint{ + {ID: "c3", Label: "Seats assigned", Note: "12 files changed"}, + {ID: "c2", Label: "Menu drafted", Note: "3 files changed"}, + {ID: "c1", Label: "Start"}, +} + +func checkpointTester(cur *string, points []Checkpoint, opts CheckpointListOptions, changes *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if CheckpointList(c, cur, points, opts).Changed() { + *changes++ + } + }, 560, 420) +} + +func TestCheckpointListRollbackConfirm(t *testing.T) { + cur, changes := "c3", 0 + tt := checkpointTester(&cur, checkpointsSample, CheckpointListOptions{}, &changes) + if !tt.HasText("Current") || !tt.HasText("12 files changed") { + t.Fatalf("texts %q", tt.Texts()) + } + rolls, _ := tt.Find("Roll back") + tt.ClickAt(rolls.X+4, rolls.Y+4) // Menu drafted + if !tt.HasText("Roll back to “Menu drafted”?") || !tt.Focused("Cancel") { + t.Fatalf("confirm: %q", tt.Texts()) + } + tt.Key(0, ui.KeyEnter) // Enter on Cancel cancels + if cur != "c3" || changes != 0 { + t.Fatalf("Enter rolled back: %s", cur) + } + tt.ClickAt(rolls.X+4, rolls.Y+4) + _ = tt.Click("Roll back to “Menu drafted”?") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if cur != "c2" || changes != 1 { + t.Fatalf("rollback: cur %s changes %d", cur, changes) + } +} + +func TestCheckpointListDisabledEmptyAndMany(t *testing.T) { + cur, n := "c3", 0 + tt := checkpointTester(&cur, checkpointsSample, CheckpointListOptions{Disabled: true}, &n) + _ = tt.Click("Roll back") + if tt.HasText("Roll back to “Menu drafted”?") || cur != "c3" { + t.Fatal("disabled list asked") + } + tt = checkpointTester(&cur, nil, CheckpointListOptions{}, &n) + if !tt.HasText("No checkpoints yet") { + t.Fatalf("empty: %q", tt.Texts()) + } + many := make([]Checkpoint, 100000) + for i := range many { + many[i] = Checkpoint{ID: fmt.Sprint(i), Label: fmt.Sprintf("point %d", i)} + } + tt = checkpointTester(&cur, many, CheckpointListOptions{}, &n) + if got := len(tt.Texts()); got > 300 { + t.Fatalf("%d texts built for 100000 checkpoints", got) + } +} + +func TestCheckpointListSnapshot(t *testing.T) { + snapshot(t, "checkpoint_list", 520, 240, func(c *ui.Context) { + cur := "c2" + ui.Column(c).Padding(16).Children(func() { + CheckpointList(c, &cur, checkpointsSample, CheckpointListOptions{}) + }) + }) +} diff --git a/command_execution_card.go b/command_execution_card.go new file mode 100644 index 0000000..347f707 --- /dev/null +++ b/command_execution_card.go @@ -0,0 +1,128 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// CommandRun is a command run; the caller appends Output. +type CommandRun struct { + Command string + Dir string + // Output is the raw terminal output; ANSI colors are kept. + Output string + Running bool + ExitCode int + Duration time.Duration +} + +// CommandExecutionCardOptions configure a CommandExecutionCard. +type CommandExecutionCardOptions struct { + // Height of the output well; 240 DIPs when zero. + Height float32 + Disabled bool + Still bool +} + +// commandOutput keeps parsed lines; appends parse only new lines. +type commandOutput struct { + src string + lines [][]internal.AnsiSpan + style internal.AnsiStyle + list ui.ListState +} + +func (o *commandOutput) update(out string) { + if out == o.src { + return + } + if !strings.HasPrefix(out, o.src) || o.src != "" && !strings.HasSuffix(o.src, "\n") { + o.lines, o.style = nil, internal.AnsiStyle{} + o.src = "" + } + for _, line := range internal.SplitLines(out[len(o.src):]) { + var spans []internal.AnsiSpan + spans, o.style = internal.ParseAnsi(line, o.style) + o.lines = append(o.lines, spans) + } + o.src = out +} + +// CommandExecutionCard shows a command run; Changed requests an abort. +func CommandExecutionCard(c *ui.Context, run CommandRun, opts CommandExecutionCardOptions) ChoiceResult { + if run.Command == "" { + panic("mujica: CommandExecutionCard needs a Command") + } + if opts.Height < 0 { + panic("mujica: CommandExecutionCard Height is negative") + } + h := opts.Height + if h == 0 { + h = 240 + } + k := Tokens(c) + u := Density(c).Unit() + var r ChoiceResult + r.Element = agentCard(c).Disabled(opts.Disabled).Label(run.Command) + out := ui.Local(r.Element, "mujica.cmd.output", func() *commandOutput { return &commandOutput{} }) + o := *out + o.list.FollowEnd = true + o.update(run.Output) + r.Element.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).MinHeight(theme.MinHitSize).Children(func() { + ui.Text(c, "$").Font(theme.MonoFont).TextColor(k.TextMuted).Shrink(0) + ui.Text(c, run.Command).Font(theme.MonoFont).FontWeight(600).Grow(1).Shrink(1).Selectable() + if run.Running { + agentMark(c, AgentRunning, 16, opts.Still) + agentCaption(c, msg(c, "agent_status.running")) + locked := r.Element.IsDisabled() + if Button(c, msg(c, "command_execution_card.abort"), ButtonOptions{Variant: Outline, Disabled: locked}).Clicked() && !locked { + r.changed = true + } + return + } + commandExit(c, run.ExitCode) + agentCaption(c, agentDuration(run.Duration)) + }) + if run.Dir != "" { + ui.Row(c).Gap(u * 1.5).AlignItems(ui.Center).Children(func() { + ui.Icon(c, icons.Must("folder")).Size(14, 14).TextColor(k.TextMuted) + agentCaption(c, run.Dir).Font(theme.MonoFont) + }) + } + well := ui.List(c, &o.list, len(o.lines), func(i int) { + ui.RichText(c, agentAnsiSpans(k, o.lines[i])...) + }) + agentWell(c, well, h).Height(h).Label(msg(c, "command_execution_card.output")).Children(func() { + if len(o.lines) == 0 { + agentCaption(c, msg(c, "command_execution_card.no_output")) + } + }) + }) + if r.changed { + slog.Debug("mujica: command_execution_card abort", "command", run.Command) + } + return r +} + +// commandExit shows the exit code by icon and word. +func commandExit(c *ui.Context, code int) { + k := Tokens(c) + tone, icon := k.Success, "circle-check" + if code != 0 { + tone, icon = k.Danger, "circle-x" + } + ui.Row(c).Gap(Density(c).Unit()).AlignItems(ui.Center).Shrink(0).Children(func() { + ui.Icon(c, icons.Must(icon)).Size(14, 14).TextColor(tone) + ui.Text(c, fmt.Sprintf(msg(c, "command_execution_card.exit"), code)).TextColor(tone). + FontSize(FontSize(c, theme.CaptionSize+1)).SingleLine() + }) +} diff --git a/command_execution_card_test.go b/command_execution_card_test.go new file mode 100644 index 0000000..82b0da5 --- /dev/null +++ b/command_execution_card_test.go @@ -0,0 +1,98 @@ +package mujica + +import ( + "fmt" + "strings" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func cmdTester(run *CommandRun, opts CommandExecutionCardOptions, aborts *int) *ui.Tester { + opts.Still = true + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if CommandExecutionCard(c, *run, opts).Changed() { + *aborts++ + } + }, 600, 420) +} + +func TestCommandExecutionCardRunningAbortAndFinish(t *testing.T) { + run := CommandRun{Command: "go test ./...", Dir: "~/court", Running: true, Output: "\x1b[32mok\x1b[0m court\n"} + aborts := 0 + tt := cmdTester(&run, CommandExecutionCardOptions{}, &aborts) + for _, s := range []string{"go test ./...", "~/court", "ok", " court", "Running"} { + if !tt.HasText(s) { + t.Fatalf("missing %q in %q", s, tt.Texts()) + } + } + if tt.HasText("\x1b[32mok") { + t.Fatal("escape codes shown as text") + } + _ = tt.Click("Abort") + if aborts != 1 { + t.Fatalf("aborts %d", aborts) + } + run.Output += "FAIL ledger\n" + run.Running, run.ExitCode, run.Duration = false, 1, 3200*time.Millisecond + tt.Frame() + if !tt.HasText("FAIL ledger") || !tt.HasText("Exit 1") || !tt.HasText("3.2 s") || tt.HasText("Abort") { + t.Fatalf("finished: %q", tt.Texts()) + } +} + +func TestCommandExecutionCardAnsiAcrossLinesAndReset(t *testing.T) { + var o commandOutput + o.update("\x1b[31mred\nstill red\x1b[0m plain\n") + if len(o.lines) != 2 || o.lines[1][0].Style.FG.Index != 1 || o.lines[1][1].Style.FG.Index != 0 { + t.Fatalf("lines %+v", o.lines) + } + o.update("\x1b[31mred\nstill red\x1b[0m plain\nnext\n") + if len(o.lines) != 3 || o.lines[2][0].Text != "next" { + t.Fatalf("append: %+v", o.lines) + } + o.update("fresh\n") + if len(o.lines) != 1 || o.lines[0][0].Text != "fresh" { + t.Fatalf("replace: %+v", o.lines) + } +} + +func TestCommandExecutionCardDisabledAndEmpty(t *testing.T) { + run := CommandRun{Command: "sleep 10", Running: true} + aborts := 0 + tt := cmdTester(&run, CommandExecutionCardOptions{Disabled: true}, &aborts) + _ = tt.Click("Abort") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if aborts != 0 || !tt.HasText("No output") { + t.Fatalf("aborts %d texts %q", aborts, tt.Texts()) + } +} + +func TestCommandExecutionCardLargeOutputVirtualized(t *testing.T) { + var b strings.Builder + for i := range 100000 { + fmt.Fprintf(&b, "\x1b[2mline %d\x1b[0m\n", i) + } + run := CommandRun{Command: "yes", Output: b.String()} + n := 0 + tt := cmdTester(&run, CommandExecutionCardOptions{}, &n) + if got := len(tt.Texts()); got > 200 { + t.Fatalf("%d texts built for 100000 lines", got) + } + if !tt.HasText("line 99999") { + t.Fatal("output does not follow its end") + } +} + +func TestCommandExecutionCardSnapshot(t *testing.T) { + snapshot(t, "command_execution_card", 560, 300, func(c *ui.Context) { + run := CommandRun{Command: "go test ./court/...", Dir: "~/projects/court", ExitCode: 1, Duration: 4200 * time.Millisecond, + Output: "\x1b[32mok\x1b[0m court/guests 0.21s\n\x1b[1;31mFAIL\x1b[0m court/ledger 0.08s\n ledger_test.go:14: want 42 guests, got 40\n\x1b[33mwarning:\x1b[0m 1 test skipped\n"} + ui.Column(c).Padding(16).Children(func() { + CommandExecutionCard(c, run, CommandExecutionCardOptions{Height: 140}) + }) + }) +} diff --git a/docs/components/261-tool-call-card.md b/docs/components/261-tool-call-card.md new file mode 100644 index 0000000..71f100f --- /dev/null +++ b/docs/components/261-tool-call-card.md @@ -0,0 +1,47 @@ +# 261 ToolCallCard 工具调用卡片 + +## 用途 + +显示一次工具调用:工具名、状态、耗时,参数与结果可折叠,JSON 自动格式化并高亮。 + +## 最小示例 + +```go +call := mujica.ToolCall{ID: "1", Name: "read_file", Args: "{\"path\":\"ledger.md\"}", + Result: "{\"lines\":40}", State: mujica.AgentDone, Duration: 420 * time.Millisecond} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ToolCallCard(c, call, mujica.ToolCallCardOptions{OpenArgs: true}) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func ToolCallCard(c *ui.Context, call ToolCall, opts ToolCallCardOptions) ChoiceResult`。`call.Name` 为空时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `OpenArgs` | `bool` | `false` | 参数区初始展开。 | +| `OpenResult` | `bool` | `false` | 结果区初始展开。 | +| `Still` | `bool` | `false` | 停止执行中动画;系统减少动画时也自动静止。 | + +## 状态 + +- `ToolCall` 字段:`ID`、`Name`、`Args`(JSON 或纯文本)、`Result`、`Error`(非空时替代结果并以错误色显示)、`State`、`Duration`。 +- `AgentState`:`AgentPending`、`AgentPlanning`、`AgentRunning`、`AgentWaiting`、`AgentDone`、`AgentFailed`、`AgentSkipped`,越界 panic。状态同时由图标形状和文字表达,不只靠颜色。 +- 仅完成或失败时显示耗时;合法 JSON 以两格缩进格式化,非 JSON 原样显示。 +- 结果超过 200 行时虚拟化,只构建可见行。 + +## 事件 + +- `Changed()`:用户展开或折叠参数、结果。 + +## 键盘操作 + +- Tab 到“参数”“结果”折叠按钮,Enter / Space 展开或折叠。 + +## 限制 + +- 展开状态保存在卡片元素上;在列表中请用稳定 `Key` 包裹每张卡片。 +- 高亮只区分关键字、字符串、数字和标点,不做 JSON 结构校验提示。 diff --git a/docs/components/262-tool-call-group.md b/docs/components/262-tool-call-group.md new file mode 100644 index 0000000..76f405a --- /dev/null +++ b/docs/components/262-tool-call-group.md @@ -0,0 +1,47 @@ +# 262 ToolCallGroup 工具调用组 + +## 用途 + +把连续的工具调用折叠成一组,标题行显示调用次数、总耗时与失败数。 + +## 最小示例 + +```go +open := false +calls := []mujica.ToolCall{ + {ID: "a", Name: "list_dir", State: mujica.AgentDone, Duration: 300 * time.Millisecond}, + {ID: "b", Name: "read_file", State: mujica.AgentFailed, Error: "not found"}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ToolCallGroup(c, &open, calls, mujica.ToolCallGroupOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func ToolCallGroup(c *ui.Context, open *bool, calls []ToolCall, opts ToolCallGroupOptions) ChoiceResult`。`open` 为 nil、调用 `ID` 为空或重复时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Title` | `string` | “N 次工具调用” | 替换内置标题。 | +| `Still` | `bool` | `false` | 停止执行中动画;系统减少动画时也自动静止。 | + +## 状态 + +- 组的状态:有调用执行中为执行中,否则有失败为失败,否则为完成。 +- 失败数以文字“N 次失败”显示。 +- 展开后每次调用用 ToolCallCard 显示。 + +## 事件 + +- `Changed()`:用户展开或折叠该组。 + +## 键盘操作 + +- Tab 到组标题,Enter / Space 展开或折叠;组内卡片各自可折叠。 + +## 限制 + +- 总耗时是各调用耗时之和,不扣除并行重叠。 diff --git a/docs/components/263-tool-approval-dialog.md b/docs/components/263-tool-approval-dialog.md new file mode 100644 index 0000000..20932bf --- /dev/null +++ b/docs/components/263-tool-approval-dialog.md @@ -0,0 +1,51 @@ +# 263 ToolApprovalDialog 工具审批对话框 + +## 用途 + +工具执行前请求批准:显示工具名、执行理由和参数预览,允许或拒绝。遵循 Dialog 与 AlertDialog 规则。 + +## 最小示例 + +```go +open := true +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ToolApprovalDialog(c, &open, mujica.ToolApprovalOptions{ + Tool: "delete_files", Args: "{\"glob\":\"*.tmp\"}", Reason: "Clean the build folder.", + }) + if r.Allowed { + fmt.Println("run the tool") + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func ToolApprovalDialog(c *ui.Context, open *bool, opts ToolApprovalOptions) ToolApprovalResult`。`Tool` 为空时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Tool` | `string` | 必填 | 工具名。 | +| `Args` | `string` | `""` | 参数,合法 JSON 会格式化高亮。 | +| `Reason` | `string` | `""` | Agent 给出的理由,作为对话框说明。 | + +## 状态 + +- 打开时焦点在“拒绝”;点击遮罩不做任何事。 +- 参数过长时在预览区内滚动,按钮始终可见。 + +## 事件 + +- `Allowed`:点击允许,或焦点在允许上按 Enter / Space。 +- `Denied`:点击拒绝、焦点在拒绝上按 Enter、或按 Escape。 +- `Element`:对话框面板,关闭时为 nil。 + +## 键盘操作 + +- 打开时焦点在拒绝,Enter 只触发聚焦按钮,必须 Tab 到“允许”才能批准。 +- Escape 等同拒绝;Tab 在对话框内循环;关闭后焦点回到打开者。 + +## 限制 + +- 输入法组合期间按 Escape 仍会拒绝(MyGo 不公开组合状态,`ui/editor.go:73`)。 diff --git a/docs/components/264-permission-prompt.md b/docs/components/264-permission-prompt.md new file mode 100644 index 0000000..c3b4e9e --- /dev/null +++ b/docs/components/264-permission-prompt.md @@ -0,0 +1,48 @@ +# 264 PermissionPrompt 权限请求 + +## 用途 + +请求权限:允许一次、始终允许或拒绝,并说明“始终允许”覆盖的范围。 + +## 最小示例 + +```go +open := true +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.PermissionPrompt(c, &open, mujica.PermissionPromptOptions{ + Title: "Write to the ledger?", Scope: "Write access to ~/court/ledger", + }) + if r.Choice == mujica.PermissionAllowAlways { + fmt.Println("remember the grant") + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func PermissionPrompt(c *ui.Context, open *bool, opts PermissionPromptOptions) PermissionResult`。`Title` 或 `Scope` 为空时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Title` | `string` | 必填 | 问题。 | +| `Description` | `string` | `""` | 补充说明。 | +| `Scope` | `string` | 必填 | “始终允许”覆盖的范围。 | + +## 状态 + +- 范围说明放在带锁形图标的框内。 +- 打开时焦点在“拒绝”,点击遮罩无效。 + +## 事件 + +- `Choice`:本帧的选择,`PermissionAllowOnce`、`PermissionAllowAlways`、`PermissionDeny`;无选择为 `PermissionNone`。Escape 记为拒绝。 + +## 键盘操作 + +- 打开时焦点在拒绝;Tab 依次到“始终允许”“允许一次”;Enter 触发聚焦按钮;Escape 拒绝。 + +## 限制 + +- 组件不保存授权,记住“始终允许”由调用方负责。 diff --git a/docs/components/265-agent-step-list.md b/docs/components/265-agent-step-list.md new file mode 100644 index 0000000..5f87bed --- /dev/null +++ b/docs/components/265-agent-step-list.md @@ -0,0 +1,51 @@ +# 265 AgentStepList 执行步骤列表 + +## 用途 + +以时间线显示 Agent 的执行步骤:当前步加框标出,步骤可展开详情,失败步提供重试。 + +## 最小示例 + +```go +steps := []mujica.AgentStep{ + {ID: "read", Title: "Read the guest list", State: mujica.AgentDone, Duration: time.Second}, + {ID: "seat", Title: "Assign the seats", State: mujica.AgentFailed, Detail: "Table 4 is full."}, + {ID: "send", Title: "Send invitations", State: mujica.AgentPending}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.AgentStepList(c, steps, mujica.AgentStepListOptions{}); r.Retry != "" { + fmt.Println("retry", r.Retry) + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func AgentStepList(c *ui.Context, steps []AgentStep, opts AgentStepListOptions) AgentStepListResult`。步骤 `ID` 为空或重复、`Title` 为空时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Disabled` | `bool` | `false` | 禁止展开与重试。 | +| `Still` | `bool` | `false` | 停止执行中动画;系统减少动画时也自动静止。 | + +## 状态 + +- `AgentStep` 字段:`ID`、`Title`、`Detail`、`State`、`Duration`。 +- `AgentState`:`AgentPending`、`AgentPlanning`、`AgentRunning`、`AgentWaiting`、`AgentDone`、`AgentFailed`、`AgentSkipped`,越界 panic。状态同时由图标形状和文字表达,不只靠颜色。 +- 当前步是第一个执行中、等待或规划中的步骤,用选中底色、边框和“当前”文字标出。 +- 失败步下方显示“重试”。 + +## 事件 + +- `Toggled`:本帧展开或折叠的步骤 ID。 +- `Retry`:本帧请求重试的步骤 ID。 + +## 键盘操作 + +- Tab 进入列表;↑ ↓ 在步骤与重试按钮间移动;Enter / Space 展开详情或重试。 + +## 限制 + +- 步骤数量较少时使用;列表不虚拟化。 diff --git a/docs/components/266-agent-plan.md b/docs/components/266-agent-plan.md new file mode 100644 index 0000000..d2f4ec1 --- /dev/null +++ b/docs/components/266-agent-plan.md @@ -0,0 +1,49 @@ +# 266 AgentPlan 执行计划 + +## 用途 + +显示 Agent 的计划清单与进度:随 Agent 实时勾选,用户可勾选、跳过、恢复和新增项。 + +## 最小示例 + +```go +items := []mujica.PlanItem{ + {ID: "a", Text: "Read the guest list", State: mujica.AgentDone}, + {ID: "b", Text: "Assign the seats", State: mujica.AgentRunning}, + {ID: "c", Text: "Order the flowers"}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AgentPlan(c, &items, mujica.AgentPlanOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func AgentPlan(c *ui.Context, items *[]PlanItem, opts AgentPlanOptions) ChoiceResult`。`items` 为 nil、项 `ID` 重复或状态不是待办、进行中、完成、跳过之一时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Title` | `string` | “计划” | 标题。 | +| `Disabled` | `bool` | `false` | 只读显示,隐藏跳过与新增。 | +| `Still` | `bool` | `false` | 停止执行中动画;系统减少动画时也自动静止。 | + +## 状态 + +- `PlanItem` 字段:`ID`、`Text`、`State`(`AgentPending`、`AgentRunning`、`AgentDone`、`AgentSkipped`)。 +- 进度为“已完成 / 未跳过总数”,以文字和细进度条显示。 +- 跳过的项加删除线并禁用勾选;进行中的项显示“进行中”。 +- 新增项的 ID 自动生成为未使用的 `item-N`。 + +## 事件 + +- `Changed()`:用户勾选、跳过、恢复或新增了项,`*items` 已更新。 + +## 键盘操作 + +- Tab 到每项的勾选框(Space 切换)、跳过或恢复按钮;在新增输入框中按 Enter 添加。 + +## 限制 + +- 空白内容不会被添加。 diff --git a/docs/components/267-agent-status.md b/docs/components/267-agent-status.md new file mode 100644 index 0000000..15637fc --- /dev/null +++ b/docs/components/267-agent-status.md @@ -0,0 +1,41 @@ +# 267 AgentStatus Agent 状态 + +## 用途 + +显示 Agent 当前状态:规划中、执行中、等待、完成、失败,用图标形状和文字表达,不只靠颜色。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AgentStatus(c, mujica.AgentWaiting, mujica.AgentStatusOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func AgentStatus(c *ui.Context, state AgentState, opts AgentStatusOptions) *ui.Element`。未知状态 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Label` | `string` | 内置状态词 | 替换显示的文字。 | +| `Still` | `bool` | `false` | 停止执行中动画;系统减少动画时也自动静止。 | + +## 状态 + +- `AgentState`:`AgentPending`、`AgentPlanning`、`AgentRunning`、`AgentWaiting`、`AgentDone`、`AgentFailed`、`AgentSkipped`,越界 panic。状态同时由图标形状和文字表达,不只靠颜色。 +- 执行中显示旋转的菱形;`Still` 或系统减少动画时改为静态图标。 + +## 事件 + +- 无事件;屏幕阅读器以状态角色读出文字。 + +## 键盘操作 + +- 不获取焦点。 + +## 限制 + +- 状态动画只在显示时重绘,隐藏后停止。 diff --git a/docs/components/268-agent-progress.md b/docs/components/268-agent-progress.md new file mode 100644 index 0000000..b25e5d1 --- /dev/null +++ b/docs/components/268-agent-progress.md @@ -0,0 +1,42 @@ +# 268 AgentProgress Agent 进度 + +## 用途 + +显示整体进度和当前动作文字;时长未知时用不确定模式。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AgentProgress(c, 0.4, mujica.AgentProgressOptions{Action: "Reading ledger.md"}) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func AgentProgress(c *ui.Context, value float64, opts AgentProgressOptions) *ui.Element`。确定模式下 `value` 不在 0 到 1 时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Label` | `string` | “进度” | 进度名称。 | +| `Action` | `string` | `""` | 当前动作,如“正在读取 ledger.md”。 | +| `Indeterminate` | `bool` | `false` | 不确定模式,忽略 value。 | +| `Still` | `bool` | `false` | 停止执行中动画;系统减少动画时也自动静止。 | + +## 状态 + +- 确定模式显示百分比;不确定模式显示流动条,减少动画时为静态条加“进行中”。 + +## 事件 + +- 无事件;当前动作以状态角色读出。 + +## 键盘操作 + +- 不获取焦点。 + +## 限制 + +- 进度值由调用方计算。 diff --git a/docs/components/269-sub-agent-tree.md b/docs/components/269-sub-agent-tree.md new file mode 100644 index 0000000..5349566 --- /dev/null +++ b/docs/components/269-sub-agent-tree.md @@ -0,0 +1,45 @@ +# 269 SubAgentTree 子 Agent 树 + +## 用途 + +以树显示子 Agent 层级、各自任务与状态,可展开查看下级。 + +## 最小示例 + +```go +agents := []mujica.SubAgent{{ID: "lead", Name: "Steward", State: mujica.AgentRunning, Children: []mujica.SubAgent{ + {ID: "cook", Name: "Cook", Task: "Plan the menu", State: mujica.AgentWaiting}, +}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SubAgentTree(c, agents, mujica.SubAgentTreeOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func SubAgentTree(c *ui.Context, roots []SubAgent, opts SubAgentTreeOptions) ChoiceResult`。`ID` 为空或重复、`Name` 为空时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Disabled` | `bool` | `false` | 禁止展开与折叠。 | +| `Still` | `bool` | `false` | 停止执行中动画;系统减少动画时也自动静止。 | + +## 状态 + +- `SubAgent` 字段:`ID`、`Name`、`Task`、`State`、`Children`。 +- `AgentState`:`AgentPending`、`AgentPlanning`、`AgentRunning`、`AgentWaiting`、`AgentDone`、`AgentFailed`、`AgentSkipped`,越界 panic。状态同时由图标形状和文字表达,不只靠颜色。 +- 有下级的行显示箭头和“N 个子智能体”。 + +## 事件 + +- `Changed()`:用户展开或折叠了某个 Agent。 + +## 键盘操作 + +- Tab 进入树;↑ ↓ 移动;→ 展开,← 折叠;Enter / Space 切换。 + +## 限制 + +- 树不虚拟化,适合几十到几百个 Agent。 diff --git a/docs/components/270-file-change-card.md b/docs/components/270-file-change-card.md new file mode 100644 index 0000000..045a63f --- /dev/null +++ b/docs/components/270-file-change-card.md @@ -0,0 +1,48 @@ +# 270 FileChangeCard 文件变更卡片 + +## 用途 + +预览一个文件的变更:增删行数、首处修改附近的差异行,提供接受、拒绝和打开完整差异的入口。 + +## 最小示例 + +```go +decision := mujica.FilePending +change := mujica.FileChange{Path: "ledger.md", Old: "Guests: 40\n", New: "Guests: 42\n"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.FileChangeCard(c, &decision, change, mujica.FileChangeCardOptions{}).OpenDiff { + fmt.Println("open the full diff") + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func FileChangeCard(c *ui.Context, decision *FileDecision, change FileChange, opts FileChangeCardOptions) FileChangeResult`。`decision` 为 nil、`Path` 为空或 `Preview` 为负时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Preview` | `int` | 8 | 从首处修改前两行起显示的差异行数。 | +| `Disabled` | `bool` | `false` | 禁止决定与打开差异。 | + +## 状态 + +- `FileChange` 字段:`Path`、`Old`、`New`;`Old` 为空表示新文件,`New` 为空表示删除。 +- 差异由 `internal.LineDiff`(Myers 行差异)计算,文本不变时只算一次。 +- 新增行带“+”、删除行带“−”和行号,颜色只是辅助。 +- 决定状态 `FilePending`、`FileAccepted`、`FileRejected` 以图标和文字显示;已决定后显示“撤销”。 + +## 事件 + +- `Decided`:`*decision` 被用户改变。 +- `OpenDiff`:请求调用方打开完整差异。 + +## 键盘操作 + +- Tab 依次到“打开差异”“拒绝”“接受”(或“撤销”),Enter / Space 触发。 + +## 限制 + +- 只做行级差异;词级高亮由 Git 组扩展。 diff --git a/docs/components/271-multi-file-diff-review.md b/docs/components/271-multi-file-diff-review.md new file mode 100644 index 0000000..b60c4cb --- /dev/null +++ b/docs/components/271-multi-file-diff-review.md @@ -0,0 +1,48 @@ +# 271 MultiFileDiffReview 多文件差异审阅 + +## 用途 + +审阅多个文件的变更:左侧文件列表,右侧所选文件的完整差异,逐文件接受或拒绝,全部接受,并显示审阅进度。 + +## 最小示例 + +```go +files := []mujica.FileChange{ + {Path: "ledger.md", Old: "Guests: 40\n", New: "Guests: 42\n"}, + {Path: "menu.md", Old: "soup\n", New: "soup\ntart\n"}, +} +decisions := make([]mujica.FileDecision, len(files)) +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.MultiFileDiffReview(c, &decisions, files, mujica.MultiFileDiffReviewOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func MultiFileDiffReview(c *ui.Context, decisions *[]FileDecision, files []FileChange, opts MultiFileDiffReviewOptions) ChoiceResult`。`decisions` 与 `files` 数量不同、`Path` 为空或重复、`Height` 为负时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Height` | `float32` | 420 | 组件高度。 | +| `Disabled` | `bool` | `false` | 禁止选择与决定。 | + +## 状态 + +- 进度为“已审阅 N / 总数”,以文字和细进度条显示。 +- 所选文件用选中底色和左侧竖条标出。 +- 文件超过 200 个或差异超过 200 行时虚拟化。 +- “全部接受”只接受尚未决定的文件,全部决定后禁用。 + +## 事件 + +- `Changed()`:用户改变了任一文件的决定。 + +## 键盘操作 + +- Tab 进入文件列表;↑ ↓ 移动,Enter 选择;Tab 到右侧按钮后 Enter 接受或拒绝。 + +## 限制 + +- 文件很多时方向键只在已构建的可见行间移动,滚动后再继续。 diff --git a/docs/components/272-command-execution-card.md b/docs/components/272-command-execution-card.md new file mode 100644 index 0000000..8d0ca9d --- /dev/null +++ b/docs/components/272-command-execution-card.md @@ -0,0 +1,48 @@ +# 272 CommandExecutionCard 命令执行卡片 + +## 用途 + +显示一条命令的执行:命令、工作目录、带 ANSI 颜色的输出、退出码与耗时,执行中可请求中止。 + +## 最小示例 + +```go +run := mujica.CommandRun{Command: "go test ./...", Dir: "~/court", Running: true, Output: "\x1b[32mok\x1b[0m court\n"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.CommandExecutionCard(c, run, mujica.CommandExecutionCardOptions{}).Changed() { + fmt.Println("abort the process") + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func CommandExecutionCard(c *ui.Context, run CommandRun, opts CommandExecutionCardOptions) ChoiceResult`。`Command` 为空或 `Height` 为负时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Height` | `float32` | 240 | 输出区高度。 | +| `Disabled` | `bool` | `false` | 禁止中止。 | +| `Still` | `bool` | `false` | 停止执行中动画;系统减少动画时也自动静止。 | + +## 状态 + +- `CommandRun` 字段:`Command`、`Dir`、`Output`、`Running`、`ExitCode`、`Duration`。 +- 输出由 `internal.ParseAnsi` 解析,颜色映射到主题;样式可跨行延续;追加输出只解析新增行。 +- 输出虚拟化并跟随末尾,用户向上滚动后停止跟随。 +- 退出码以图标和“退出码 N”文字显示。 + +## 事件 + +- `Changed()`:用户点击了“中止”;终止进程由调用方完成。 + +## 键盘操作 + +- Tab 到“中止”,Enter / Space 触发;输出区可滚动。 + +## 限制 + +- 只支持 SGR 颜色与样式,其它转义序列原样显示。 +- 不运行命令,也不提供 PTY。 diff --git a/docs/components/273-screenshot-stream.md b/docs/components/273-screenshot-stream.md new file mode 100644 index 0000000..2c2b652 --- /dev/null +++ b/docs/components/273-screenshot-stream.md @@ -0,0 +1,45 @@ +# 273 ScreenshotStream Agent 画面流 + +## 用途 + +查看 Agent 的画面帧序列:默认跟随最新帧,可暂停并逐帧前后查看。帧由调用方提供。 + +## 最小示例 + +```go +var st mujica.ScreenshotStreamState +var frames []mujica.ScreenshotFrame // appended as the agent captures them +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ScreenshotStream(c, &st, frames, mujica.ScreenshotStreamOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func ScreenshotStream(c *ui.Context, st *ScreenshotStreamState, frames []ScreenshotFrame, opts ScreenshotStreamOptions) ChoiceResult`。`st` 为 nil、帧没有图像或 `Height` 为负时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Height` | `float32` | 280 | 画面区高度。 | +| `Disabled` | `bool` | `false` | 禁止暂停与逐帧。 | + +## 状态 + +- `ScreenshotFrame` 字段:`Image`(`ui.ImageSource`)、`Caption`、`At`。 +- `ScreenshotStreamState` 字段:`Index`、`Paused`;未暂停时 `Index` 总是最后一帧。 +- 逐帧操作会自动暂停;“回到实时”恢复跟随。 +- 没有帧时显示“等待画面”。 + +## 事件 + +- `Changed()`:用户暂停、恢复或移动了帧。 + +## 键盘操作 + +- Tab 到画面区:← → 逐帧,Space 暂停或恢复;上一帧、下一帧按钮同样可用。 + +## 限制 + +- 不解码视频,帧图像由调用方提供。 diff --git a/docs/components/274-artifact-panel.md b/docs/components/274-artifact-panel.md new file mode 100644 index 0000000..58164e4 --- /dev/null +++ b/docs/components/274-artifact-panel.md @@ -0,0 +1,47 @@ +# 274 ArtifactPanel 产物面板 + +## 用途 + +展示 Agent 生成的产物:代码高亮显示,文档与网页由调用方的预览插槽渲染,可在预览与源码间切换,提供复制与导出。 + +## 最小示例 + +```go +art := mujica.Artifact{Title: "seating.go", Language: "go", Content: "package court\n"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ArtifactPanel(c, art, mujica.ArtifactPanelOptions{}).Exported { + fmt.Println("save the file") + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func ArtifactPanel(c *ui.Context, art Artifact, opts ArtifactPanelOptions) ArtifactPanelResult`。`Title` 为空、`Kind` 越界、文档或网页缺少 `Preview`、`Height` 为负时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Preview` | `func()` | `nil` | 预览插槽;文档与网页必填。 | +| `Height` | `float32` | 320 | 内容区高度。 | +| `Disabled` | `bool` | `false` | 禁止复制、导出与切换。 | + +## 状态 + +- `Artifact` 字段:`Title`、`Kind`(`ArtifactCode`、`ArtifactDocument`、`ArtifactWeb`)、`Language`、`Content`。 +- 预览与源码切换用选中底色加勾号标出当前项。 +- 复制后两秒内按钮显示“已复制”。 + +## 事件 + +- `Copied`:内容已写入剪贴板。 +- `Exported`:请求调用方导出。 + +## 键盘操作 + +- Tab 到切换组,← → 移动,Enter / Space 选择;Tab 到复制、导出。 + +## 限制 + +- 不内置网页渲染,网页预览须由调用方提供(无 WebView)。 diff --git a/docs/components/275-artifact-version-switcher.md b/docs/components/275-artifact-version-switcher.md new file mode 100644 index 0000000..0cabdb2 --- /dev/null +++ b/docs/components/275-artifact-version-switcher.md @@ -0,0 +1,45 @@ +# 275 ArtifactVersionSwitcher 产物版本切换 + +## 用途 + +在产物的多个版本之间切换,并提供与上一版本比较差异的入口。 + +## 最小示例 + +```go +current := 1 +versions := []mujica.ArtifactVersion{{Label: "v1", Note: "First draft"}, {Label: "v2", Note: "Added music"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ArtifactVersionSwitcher(c, ¤t, versions, mujica.ArtifactVersionSwitcherOptions{}).Compare { + fmt.Println("diff v1 and v2") + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func ArtifactVersionSwitcher(c *ui.Context, current *int, versions []ArtifactVersion, opts ArtifactVersionSwitcherOptions) ArtifactVersionResult`。没有版本、`*current` 越界或版本 `Label` 为空时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Disabled` | `bool` | `false` | 禁止切换与比较。 | + +## 状态 + +- 显示版本名、“N / 总数”和说明;第一个版本时“较早版本”禁用,最后一个时“较新版本”禁用。 +- 非第一个版本显示“与上一版本比较”。 + +## 事件 + +- `Changed`:`*current` 改变。 +- `Compare`:请求比较当前版本与上一版本。 + +## 键盘操作 + +- 焦点在组件内时 ← → 切换版本;Tab 到各按钮,Enter / Space 触发。 + +## 限制 + +- 差异视图由调用方打开,可用 FileChangeCard 或 MultiFileDiffReview 呈现。 diff --git a/docs/components/276-sandbox-status.md b/docs/components/276-sandbox-status.md new file mode 100644 index 0000000..495f6da --- /dev/null +++ b/docs/components/276-sandbox-status.md @@ -0,0 +1,43 @@ +# 276 SandboxStatus 沙箱状态 + +## 用途 + +显示沙箱的运行状态、资源占用和剩余时间。 + +## 最小示例 + +```go +info := mujica.SandboxInfo{Name: "sandbox-7", State: mujica.SandboxRunning, + Resources: []mujica.SandboxResource{{Name: "CPU", Used: 1.5, Limit: 2, Unit: "cores"}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SandboxStatus(c, info, mujica.SandboxStatusOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func SandboxStatus(c *ui.Context, info SandboxInfo, opts SandboxStatusOptions) *ui.Element`。状态未知、资源名为空、`Limit` 不大于 0 或 `Used` 不在 0 到 `Limit` 之间时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Still` | `bool` | `false` | 停止执行中动画;系统减少动画时也自动静止。 | + +## 状态 + +- `SandboxInfo` 字段:`Name`、`State`(`SandboxStarting`、`SandboxRunning`、`SandboxStopped`、`SandboxFailed`)、`Resources`、`Expires`。 +- 每项资源显示“已用 / 上限 单位”与细条;达到 90% 时加警示图标和“接近上限”说明。 +- 设置 `Expires` 且运行中时显示剩余时间,每秒刷新;到时显示“已到时”。 + +## 事件 + +- 无事件。 + +## 键盘操作 + +- 不获取焦点。 + +## 限制 + +- 倒计时依赖界面帧,窗口隐藏时 MyGo 暂停帧,重新显示后立即校正。 diff --git a/docs/components/277-mcp-server-list.md b/docs/components/277-mcp-server-list.md new file mode 100644 index 0000000..82a5d34 --- /dev/null +++ b/docs/components/277-mcp-server-list.md @@ -0,0 +1,46 @@ +# 277 MCPServerList MCP 服务器列表 + +## 用途 + +列出 MCP 服务器:连接状态、传输方式、工具数,提供启动、停止与重新连接回调。 + +## 最小示例 + +```go +servers := []mujica.MCPServer{{ID: "fs", Name: "filesystem", Transport: "stdio", State: mujica.MCPConnected, Tools: 12}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MCPServerList(c, servers, mujica.MCPServerListOptions{}); r.Action == mujica.MCPStop { + fmt.Println("stop", r.Server) + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func MCPServerList(c *ui.Context, servers []MCPServer, opts MCPServerListOptions) MCPServerListResult`。`ID` 为空或重复、`Name` 为空、状态未知、`Tools` 为负、`MaxHeight` 为负时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `MaxHeight` | `float32` | 360 | 列表最大高度,超出后滚动。 | +| `Disabled` | `bool` | `false` | 禁止所有操作。 | +| `Still` | `bool` | `false` | 停止执行中动画;系统减少动画时也自动静止。 | + +## 状态 + +- `MCPServer` 字段:`ID`、`Name`、`Transport`、`State`(`MCPStopped`、`MCPConnecting`、`MCPConnected`、`MCPError`)、`Tools`、`Error`。 +- 已连接时显示“N 个工具”;连接失败时显示错误文字与“重新连接”。 +- 超过 200 台服务器时虚拟化。 + +## 事件 + +- `Action`:本帧请求 `MCPStart`、`MCPStop` 或 `MCPReconnect`,`Server` 为对应 ID。 + +## 键盘操作 + +- Tab 依次到各行按钮,Enter / Space 触发。 + +## 限制 + +- 组件只发出请求,连接管理由调用方完成。 diff --git a/docs/components/278-memory-panel.md b/docs/components/278-memory-panel.md new file mode 100644 index 0000000..e9ff905 --- /dev/null +++ b/docs/components/278-memory-panel.md @@ -0,0 +1,47 @@ +# 278 MemoryPanel 记忆面板 + +## 用途 + +列出 Agent 的记忆条目,支持搜索、行内编辑和确认后删除。 + +## 最小示例 + +```go +entries := []mujica.MemoryEntry{{ID: "1", Text: "Lady Sakiko prefers the east wing.", Source: "Chat"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MemoryPanel(c, &entries, mujica.MemoryPanelOptions{}); r.Deleted != "" { + fmt.Println("forget", r.Deleted) + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func MemoryPanel(c *ui.Context, entries *[]MemoryEntry, opts MemoryPanelOptions) MemoryPanelResult`。`entries` 为 nil、条目 `ID` 为空或 `MaxHeight` 为负时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `MaxHeight` | `float32` | 360 | 列表最大高度。 | +| `Disabled` | `bool` | `false` | 只读,禁止搜索、编辑与删除。 | + +## 状态 + +- `MemoryEntry` 字段:`ID`、`Text`、`Source`。 +- 搜索不区分大小写,匹配内容与来源;只在搜索词或条目变化时重新筛选。 +- 编辑时出现文本框和保存、取消;删除前用 Popconfirm 确认,确认按钮为危险样式且默认聚焦取消。 +- 条目超过 200 条时虚拟化。 + +## 事件 + +- `Edited`:本帧保存的条目 ID,`*entries` 已更新。 +- `Deleted`:本帧删除的条目 ID,已从 `*entries` 移除。 + +## 键盘操作 + +- Tab 到搜索框、各条的编辑与删除;删除确认中 Escape 取消。 + +## 限制 + +- 调用方原地修改条目文本而不改变切片长度时,筛选结果到下次搜索变化才更新。 diff --git a/docs/components/279-checkpoint-list.md b/docs/components/279-checkpoint-list.md new file mode 100644 index 0000000..3854182 --- /dev/null +++ b/docs/components/279-checkpoint-list.md @@ -0,0 +1,46 @@ +# 279 CheckpointList 检查点列表 + +## 用途 + +列出 Agent 运行的检查点,标出当前点,回滚到其它检查点前要求确认。 + +## 最小示例 + +```go +current := "c2" +points := []mujica.Checkpoint{{ID: "c2", Label: "Menu drafted"}, {ID: "c1", Label: "Start"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.CheckpointList(c, ¤t, points, mujica.CheckpointListOptions{}).Changed() { + fmt.Println("restore", current) + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func CheckpointList(c *ui.Context, current *string, points []Checkpoint, opts CheckpointListOptions) ChoiceResult`。`current` 为 nil、`ID` 为空或重复、`Label` 为空、`MaxHeight` 为负时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `MaxHeight` | `float32` | 360 | 列表最大高度。 | +| `Disabled` | `bool` | `false` | 禁止回滚。 | + +## 状态 + +- 当前点用实心菱形、选中底色和“当前”文字标出;其它点为空心菱形。 +- 回滚用 AlertDialog 确认:默认聚焦取消,Enter 不会直接回滚。 +- 超过 200 个检查点时虚拟化。 + +## 事件 + +- `Changed()`:确认回滚后 `*current` 已改为目标 ID。 + +## 键盘操作 + +- Tab 到各“回滚”,Enter 打开确认;确认框内 Tab 到“回滚”再按 Enter。 + +## 限制 + +- 恢复文件与状态由调用方完成。 diff --git a/docs/components/280-human-input-request.md b/docs/components/280-human-input-request.md new file mode 100644 index 0000000..288fbba --- /dev/null +++ b/docs/components/280-human-input-request.md @@ -0,0 +1,52 @@ +# 280 HumanInputRequest 人工输入请求 + +## 用途 + +Agent 向用户提问:显示问题、可选答案与自由回答,并提示剩余时间与超时。 + +## 最小示例 + +```go +answer := "" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.HumanInputRequest(c, &answer, mujica.HumanInputRequestOptions{ + Question: "Which hall?", Options: []string{"East wing", "Great hall"}, AllowFree: true, + }) + if r.Submitted { + fmt.Println("reply", answer) + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func HumanInputRequest(c *ui.Context, answer *string, opts HumanInputRequestOptions) HumanInputResult`。`answer` 为 nil、`Question` 为空、既无选项又不允许自由回答时 panic。 + +## 参数 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Question` | `string` | 必填 | 问题。 | +| `Options` | `[]string` | `nil` | 可选答案。 | +| `AllowFree` | `bool` | `false` | 允许自由回答。 | +| `Deadline` | `time.Time` | 零值 | 截止时间;零值不限时。 | +| `Disabled` | `bool` | `false` | 禁止回答。 | + +## 状态 + +- 选择选项会清空自由回答;输入自由回答会取代所选选项。 +- 剩余时间每秒刷新;到时显示“智能体已停止等待”并禁用。 +- 回答为空白时“发送回答”禁用。 + +## 事件 + +- `Submitted`:用户发送了 `*answer`。 +- `TimedOut`:截止时间在本帧到达(只报告一次)。 + +## 键盘操作 + +- Tab 进入选项组,方向键选择;Tab 到输入框,Enter 发送;或 Tab 到“发送回答”。 + +## 限制 + +- 超时只在界面帧中检测,窗口隐藏期间推迟到重新显示。 diff --git a/example_agent_test.go b/example_agent_test.go new file mode 100644 index 0000000..0d17a41 --- /dev/null +++ b/example_agent_test.go @@ -0,0 +1,243 @@ +package mujica_test + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func ExampleToolCallCard() { + call := mujica.ToolCall{ID: "1", Name: "read_file", Args: "{\"path\":\"ledger.md\"}", + Result: "{\"lines\":40}", State: mujica.AgentDone, Duration: 420 * time.Millisecond} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ToolCallCard(c, call, mujica.ToolCallCardOptions{OpenArgs: true}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleToolCallGroup() { + open := false + calls := []mujica.ToolCall{ + {ID: "a", Name: "list_dir", State: mujica.AgentDone, Duration: 300 * time.Millisecond}, + {ID: "b", Name: "read_file", State: mujica.AgentFailed, Error: "not found"}, + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ToolCallGroup(c, &open, calls, mujica.ToolCallGroupOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleToolApprovalDialog() { + open := true + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ToolApprovalDialog(c, &open, mujica.ToolApprovalOptions{ + Tool: "delete_files", Args: "{\"glob\":\"*.tmp\"}", Reason: "Clean the build folder.", + }) + if r.Allowed { + fmt.Println("run the tool") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExamplePermissionPrompt() { + open := true + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.PermissionPrompt(c, &open, mujica.PermissionPromptOptions{ + Title: "Write to the ledger?", Scope: "Write access to ~/court/ledger", + }) + if r.Choice == mujica.PermissionAllowAlways { + fmt.Println("remember the grant") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleAgentStepList() { + steps := []mujica.AgentStep{ + {ID: "read", Title: "Read the guest list", State: mujica.AgentDone, Duration: time.Second}, + {ID: "seat", Title: "Assign the seats", State: mujica.AgentFailed, Detail: "Table 4 is full."}, + {ID: "send", Title: "Send invitations", State: mujica.AgentPending}, + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.AgentStepList(c, steps, mujica.AgentStepListOptions{}); r.Retry != "" { + fmt.Println("retry", r.Retry) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleAgentPlan() { + items := []mujica.PlanItem{ + {ID: "a", Text: "Read the guest list", State: mujica.AgentDone}, + {ID: "b", Text: "Assign the seats", State: mujica.AgentRunning}, + {ID: "c", Text: "Order the flowers"}, + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AgentPlan(c, &items, mujica.AgentPlanOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleAgentStatus() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AgentStatus(c, mujica.AgentWaiting, mujica.AgentStatusOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleAgentProgress() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AgentProgress(c, 0.4, mujica.AgentProgressOptions{Action: "Reading ledger.md"}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleSubAgentTree() { + agents := []mujica.SubAgent{{ID: "lead", Name: "Steward", State: mujica.AgentRunning, Children: []mujica.SubAgent{ + {ID: "cook", Name: "Cook", Task: "Plan the menu", State: mujica.AgentWaiting}, + }}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SubAgentTree(c, agents, mujica.SubAgentTreeOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleFileChangeCard() { + decision := mujica.FilePending + change := mujica.FileChange{Path: "ledger.md", Old: "Guests: 40\n", New: "Guests: 42\n"} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.FileChangeCard(c, &decision, change, mujica.FileChangeCardOptions{}).OpenDiff { + fmt.Println("open the full diff") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMultiFileDiffReview() { + files := []mujica.FileChange{ + {Path: "ledger.md", Old: "Guests: 40\n", New: "Guests: 42\n"}, + {Path: "menu.md", Old: "soup\n", New: "soup\ntart\n"}, + } + decisions := make([]mujica.FileDecision, len(files)) + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.MultiFileDiffReview(c, &decisions, files, mujica.MultiFileDiffReviewOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCommandExecutionCard() { + run := mujica.CommandRun{Command: "go test ./...", Dir: "~/court", Running: true, Output: "\x1b[32mok\x1b[0m court\n"} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.CommandExecutionCard(c, run, mujica.CommandExecutionCardOptions{}).Changed() { + fmt.Println("abort the process") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleScreenshotStream() { + var st mujica.ScreenshotStreamState + var frames []mujica.ScreenshotFrame // appended as the agent captures them + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ScreenshotStream(c, &st, frames, mujica.ScreenshotStreamOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleArtifactPanel() { + art := mujica.Artifact{Title: "seating.go", Language: "go", Content: "package court\n"} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ArtifactPanel(c, art, mujica.ArtifactPanelOptions{}).Exported { + fmt.Println("save the file") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleArtifactVersionSwitcher() { + current := 1 + versions := []mujica.ArtifactVersion{{Label: "v1", Note: "First draft"}, {Label: "v2", Note: "Added music"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ArtifactVersionSwitcher(c, ¤t, versions, mujica.ArtifactVersionSwitcherOptions{}).Compare { + fmt.Println("diff v1 and v2") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleSandboxStatus() { + info := mujica.SandboxInfo{Name: "sandbox-7", State: mujica.SandboxRunning, + Resources: []mujica.SandboxResource{{Name: "CPU", Used: 1.5, Limit: 2, Unit: "cores"}}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SandboxStatus(c, info, mujica.SandboxStatusOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMCPServerList() { + servers := []mujica.MCPServer{{ID: "fs", Name: "filesystem", Transport: "stdio", State: mujica.MCPConnected, Tools: 12}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MCPServerList(c, servers, mujica.MCPServerListOptions{}); r.Action == mujica.MCPStop { + fmt.Println("stop", r.Server) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMemoryPanel() { + entries := []mujica.MemoryEntry{{ID: "1", Text: "Lady Sakiko prefers the east wing.", Source: "Chat"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MemoryPanel(c, &entries, mujica.MemoryPanelOptions{}); r.Deleted != "" { + fmt.Println("forget", r.Deleted) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCheckpointList() { + current := "c2" + points := []mujica.Checkpoint{{ID: "c2", Label: "Menu drafted"}, {ID: "c1", Label: "Start"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.CheckpointList(c, ¤t, points, mujica.CheckpointListOptions{}).Changed() { + fmt.Println("restore", current) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleHumanInputRequest() { + answer := "" + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.HumanInputRequest(c, &answer, mujica.HumanInputRequestOptions{ + Question: "Which hall?", Options: []string{"East wing", "Great hall"}, AllowFree: true, + }) + if r.Submitted { + fmt.Println("reply", answer) + } + } + ui.Render(view, 400, 300, 1) +} diff --git a/examples/gallery/pages_agent.go b/examples/gallery/pages_agent.go index f1cb354..ead48c3 100644 --- a/examples/gallery/pages_agent.go +++ b/examples/gallery/pages_agent.go @@ -1,3 +1,282 @@ package main -var agentPages = []page{} +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +const agentCategory = "Agent" + +var agentPages = []page{ + {ID: "261", Name: "ToolCallCard", ZhName: "工具调用卡片", Category: agentCategory, Demo: toolCallCardDemo, Code: toolCallCardCode, + Keys: "Tab 到参数、结果折叠按钮,Enter / Space 展开或折叠。"}, + {ID: "262", Name: "ToolCallGroup", ZhName: "工具调用组", Category: agentCategory, Demo: toolCallGroupDemo, Code: toolCallGroupCode, + Keys: "Tab 到组标题,Enter / Space 展开或折叠。"}, + {ID: "263", Name: "ToolApprovalDialog", ZhName: "工具审批对话框", Category: agentCategory, Demo: toolApprovalDemo, Code: toolApprovalDialogCode, + Keys: "打开时焦点在拒绝;Enter 只触发聚焦按钮,Tab 到允许才能批准;Escape 拒绝。"}, + {ID: "264", Name: "PermissionPrompt", ZhName: "权限请求", Category: agentCategory, Demo: permissionDemo, Code: permissionPromptCode, + Keys: "打开时焦点在拒绝;Tab 到始终允许、允许一次;Escape 拒绝。"}, + {ID: "265", Name: "AgentStepList", ZhName: "执行步骤列表", Category: agentCategory, Demo: agentStepListDemo, Code: agentStepListCode, + Keys: "↑ ↓ 在步骤与重试间移动;Enter 展开详情或重试。"}, + {ID: "266", Name: "AgentPlan", ZhName: "执行计划", Category: agentCategory, Demo: agentPlanDemo, Code: agentPlanCode, + Keys: "Space 勾选;Tab 到跳过或恢复;在输入框中按 Enter 新增。"}, + {ID: "267", Name: "AgentStatus", ZhName: "Agent 状态", Category: agentCategory, Demo: agentStatusDemo, Code: agentStatusCode, + Keys: "不获取焦点;屏幕阅读器读出状态文字。"}, + {ID: "268", Name: "AgentProgress", ZhName: "Agent 进度", Category: agentCategory, Demo: agentProgressDemo, Code: agentProgressCode, + Keys: "不获取焦点;当前动作以状态读出。"}, + {ID: "269", Name: "SubAgentTree", ZhName: "子 Agent 树", Category: agentCategory, Demo: subAgentTreeDemo, Code: subAgentTreeCode, + Keys: "↑ ↓ 移动;→ 展开,← 折叠;Enter / Space 切换。"}, + {ID: "270", Name: "FileChangeCard", ZhName: "文件变更卡片", Category: agentCategory, Demo: fileChangeCardDemo, Code: fileChangeCardCode, + Keys: "Tab 到打开差异、拒绝、接受或撤销,Enter / Space 触发。"}, + {ID: "271", Name: "MultiFileDiffReview", ZhName: "多文件差异审阅", Category: agentCategory, Demo: multiFileDiffDemo, Code: multiFileDiffReviewCode, + Keys: "文件列表中 ↑ ↓ 移动,Enter 选择;Tab 到接受、拒绝、全部接受。"}, + {ID: "272", Name: "CommandExecutionCard", ZhName: "命令执行卡片", Category: agentCategory, Demo: commandExecutionDemo, Code: commandExecutionCardCode, + Keys: "Tab 到中止,Enter / Space 请求中止;输出区可滚动。"}, + {ID: "273", Name: "ScreenshotStream", ZhName: "Agent 画面流", Category: agentCategory, Demo: screenshotStreamDemo, Code: screenshotStreamCode, + Keys: "画面区中 ← → 逐帧,Space 暂停或恢复。"}, + {ID: "274", Name: "ArtifactPanel", ZhName: "产物面板", Category: agentCategory, Demo: artifactPanelDemo, Code: artifactPanelCode, + Keys: "切换组中 ← → 移动、Enter 选择;Tab 到复制、导出。"}, + {ID: "275", Name: "ArtifactVersionSwitcher", ZhName: "产物版本切换", Category: agentCategory, Demo: artifactVersionDemo, Code: artifactVersionSwitcherCode, + Keys: "焦点在组件内时 ← → 切换版本;Tab 到比较按钮。"}, + {ID: "276", Name: "SandboxStatus", ZhName: "沙箱状态", Category: agentCategory, Demo: sandboxStatusDemo, Code: sandboxStatusCode, + Keys: "不获取焦点;剩余时间每秒刷新。"}, + {ID: "277", Name: "MCPServerList", ZhName: "MCP 服务器列表", Category: agentCategory, Demo: mcpServerListDemo, Code: mcpServerListCode, + Keys: "Tab 到各行的启动、停止、重新连接,Enter / Space 触发。"}, + {ID: "278", Name: "MemoryPanel", ZhName: "记忆面板", Category: agentCategory, Demo: memoryPanelDemo, Code: memoryPanelCode, + Keys: "Tab 到搜索、编辑、删除;删除确认默认聚焦取消,Escape 取消。"}, + {ID: "279", Name: "CheckpointList", ZhName: "检查点列表", Category: agentCategory, Demo: checkpointListDemo, Code: checkpointListCode, + Keys: "Tab 到回滚,Enter 打开确认;确认框默认聚焦取消。"}, + {ID: "280", Name: "HumanInputRequest", ZhName: "人工输入请求", Category: agentCategory, Demo: humanInputDemo, Code: humanInputRequestCode, + Keys: "方向键选择选项;输入框中 Enter 发送;Tab 到发送回答。"}, +} + +// agentStates are the states a demo can pick from. +var agentStates = []string{"Pending", "Planning", "Running", "Waiting", "Done", "Failed", "Skipped"} + +// agentStatePick is a select over agentStates, logging changes. +func agentStatePick(c *ui.Context, log func(string), v *string) mujica.AgentState { + if ui.Select(c, v, agentStates).Changed() { + log("state = " + *v) + } + for i, s := range agentStates { + if s == *v { + return mujica.AgentState(i) + } + } + panic("gallery: unknown state " + *v) +} + +type toolCallDemoState struct { + state string + failed bool + still bool +} + +func toolCallCardDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "261", func() toolCallDemoState { return toolCallDemoState{state: "Done"} }) + var st mujica.AgentState + overlayControls(c, func() { + st = agentStatePick(c, log, &s.state) + overlayCheck(c, log, &s.failed, "Error") + overlayCheck(c, log, &s.still, "Still") + }) + call := mujica.ToolCall{ID: "1", Name: "read_file", Args: `{"path":"court/ledger.md","limit":40}`, + Result: `{"lines":40,"truncated":false}`, State: st, Duration: 420 * time.Millisecond} + if s.failed { + call.Error = "permission denied: court/ledger.md" + } + if mujica.ToolCallCard(c, call, mujica.ToolCallCardOptions{Still: s.still}).Changed() { + log("folded or unfolded a section") + } +} + +func toolCallGroupDemo(c *ui.Context, log func(string)) { + open := ui.Local(c.Root(), "262", func() bool { return true }) + calls := []mujica.ToolCall{ + {ID: "a", Name: "list_dir", Args: `{"path":"court"}`, Result: `["ledger.md","menu.md"]`, State: mujica.AgentDone, Duration: 300 * time.Millisecond}, + {ID: "b", Name: "read_file", Args: `{"path":"court/wine.md"}`, Error: "not found", State: mujica.AgentFailed, Duration: 1200 * time.Millisecond}, + {ID: "c", Name: "grep", Args: `{"pattern":"Sakiko"}`, Result: `{"matches":3}`, State: mujica.AgentDone, Duration: 500 * time.Millisecond}, + } + if mujica.ToolCallGroup(c, open, calls, mujica.ToolCallGroupOptions{}).Changed() { + log(fmt.Sprintf("group open = %v", *open)) + } +} + +func toolApprovalDemo(c *ui.Context, log func(string)) { + open := ui.Local(c.Root(), "263", func() bool { return false }) + if mujica.Button(c, "Run delete_files", mujica.ButtonOptions{}).Clicked() { + *open = true + log("asked for approval") + } + r := mujica.ToolApprovalDialog(c, open, mujica.ToolApprovalOptions{Tool: "delete_files", + Args: `{"glob":"build/*.tmp","dry_run":false}`, Reason: "The agent wants to clean temporary files from the build folder."}) + if r.Allowed { + log("allowed") + } + if r.Denied { + log("denied") + } +} + +type permissionDemoState struct { + open bool + grant string +} + +func permissionDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "264", func() permissionDemoState { return permissionDemoState{grant: "none"} }) + ui.Row(c).Gap(12).AlignItems(ui.Center).Children(func() { + if mujica.Button(c, "Ask to write", mujica.ButtonOptions{}).Clicked() { + s.open = true + log("asked for permission") + } + ui.Text(c, "Grant: "+s.grant) + }) + r := mujica.PermissionPrompt(c, &s.open, mujica.PermissionPromptOptions{Title: "Write to the ledger?", + Description: "The agent wants to record tonight's guests.", Scope: "Write access to ~/court/ledger and its subfolders"}) + if r.Choice != mujica.PermissionNone { + s.grant = [...]string{"none", "once", "always", "denied"}[r.Choice] + log("choice = " + s.grant) + } +} + +type stepDemoState struct { + steps []mujica.AgentStep + disabled bool +} + +func agentStepListDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "265", func() stepDemoState { + return stepDemoState{steps: []mujica.AgentStep{ + {ID: "read", Title: "Read the guest list", State: mujica.AgentDone, Duration: 800 * time.Millisecond, Detail: "42 guests, 3 arrive late."}, + {ID: "seat", Title: "Assign the seats", State: mujica.AgentFailed, Duration: 2 * time.Second, Detail: "Table 4 is over capacity."}, + {ID: "send", Title: "Send the invitations", State: mujica.AgentPending}, + }} + }) + overlayControls(c, func() { overlayCheck(c, log, &s.disabled, "Disabled") }) + r := mujica.AgentStepList(c, s.steps, mujica.AgentStepListOptions{Disabled: s.disabled}) + if r.Toggled != "" { + log("toggled " + r.Toggled) + } + if r.Retry != "" { + log("retry " + r.Retry) + for i := range s.steps { + if s.steps[i].ID == r.Retry { + s.steps[i].State, s.steps[i].Detail = mujica.AgentRunning, "Retrying with a larger table." + } + } + } +} + +type planDemoState struct { + items []mujica.PlanItem + disabled bool +} + +func agentPlanDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "266", func() planDemoState { + return planDemoState{items: []mujica.PlanItem{ + {ID: "a", Text: "Read the guest list", State: mujica.AgentDone}, + {ID: "b", Text: "Assign the seats", State: mujica.AgentRunning}, + {ID: "c", Text: "Order the flowers"}, + }} + }) + overlayControls(c, func() { + overlayCheck(c, log, &s.disabled, "Disabled") + if mujica.Button(c, "Agent finishes a step", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + for i := range s.items { + if s.items[i].State != mujica.AgentDone && s.items[i].State != mujica.AgentSkipped { + s.items[i].State = mujica.AgentDone + log("agent checked " + s.items[i].Text) + break + } + } + } + }) + if mujica.AgentPlan(c, &s.items, mujica.AgentPlanOptions{Disabled: s.disabled}).Changed() { + log(fmt.Sprintf("plan changed (%d items)", len(s.items))) + } +} + +type statusDemoState struct { + state string + still bool +} + +func agentStatusDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "267", func() statusDemoState { return statusDemoState{state: "Running"} }) + var st mujica.AgentState + overlayControls(c, func() { + st = agentStatePick(c, log, &s.state) + overlayCheck(c, log, &s.still, "Still") + }) + ui.Row(c).Gap(8).Wrap().Children(func() { + mujica.AgentStatus(c, st, mujica.AgentStatusOptions{Still: s.still}) + for _, v := range []mujica.AgentState{mujica.AgentPlanning, mujica.AgentRunning, mujica.AgentWaiting, mujica.AgentDone, mujica.AgentFailed} { + mujica.AgentStatus(c, v, mujica.AgentStatusOptions{Still: s.still}) + } + }) +} + +type progressDemoState struct { + value float64 + indeterminate bool +} + +func agentProgressDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "268", func() progressDemoState { return progressDemoState{value: 0.4} }) + overlayControls(c, func() { + if ui.Slider(c, &s.value, 0, 1).Width(200).Changed() { + log(fmt.Sprintf("value = %.2f", s.value)) + } + overlayCheck(c, log, &s.indeterminate, "Indeterminate") + }) + action := "Reading ledger.md" + if s.value > 0.5 { + action = "Writing the seating chart" + } + mujica.AgentProgress(c, s.value, mujica.AgentProgressOptions{Label: "Preparing the ball", Action: action, Indeterminate: s.indeterminate}) +} + +func subAgentTreeDemo(c *ui.Context, log func(string)) { + disabled := ui.Local(c.Root(), "269", func() bool { return false }) + overlayControls(c, func() { overlayCheck(c, log, disabled, "Disabled") }) + agents := []mujica.SubAgent{{ID: "lead", Name: "Steward", Task: "Prepare the ball", State: mujica.AgentRunning, Children: []mujica.SubAgent{ + {ID: "music", Name: "Musician", Task: "Hire the quartet", State: mujica.AgentDone}, + {ID: "kitchen", Name: "Cook", Task: "Plan the menu", State: mujica.AgentWaiting, Children: []mujica.SubAgent{ + {ID: "wine", Name: "Sommelier", Task: "Choose the wine", State: mujica.AgentFailed}, + }}, + }}} + if mujica.SubAgentTree(c, agents, mujica.SubAgentTreeOptions{Disabled: *disabled}).Changed() { + log("expanded or collapsed an agent") + } +} + +type fileChangeDemoState struct { + decision mujica.FileDecision + disabled bool + preview float64 +} + +func fileChangeCardDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "270", func() fileChangeDemoState { return fileChangeDemoState{preview: 8} }) + overlayControls(c, func() { + overlayCheck(c, log, &s.disabled, "Disabled") + overlaySlider(c, log, &s.preview, "Preview", "lines", 2, 12, 1) + }) + r := mujica.FileChangeCard(c, &s.decision, agentDemoChange, mujica.FileChangeCardOptions{Preview: int(s.preview), Disabled: s.disabled}) + if r.Decided { + log(fmt.Sprintf("decision = %d", s.decision)) + } + if r.OpenDiff { + log("open the full diff") + } +} + +var agentDemoChange = mujica.FileChange{Path: "court/ledger.md", + Old: "# Ledger\nGuests: 40\nWine: claret\nMusic: none\nHall: east wing\n", + New: "# Ledger\nGuests: 42\nWine: claret\nMusic: quartet\nFlowers: lilies\nHall: east wing\n"} diff --git a/examples/gallery/pages_agent_code.go b/examples/gallery/pages_agent_code.go new file mode 100644 index 0000000..1503640 --- /dev/null +++ b/examples/gallery/pages_agent_code.go @@ -0,0 +1,196 @@ +package main + +// Code snippets of the Agent pages, the same as their compiled Examples. + +const toolCallCardCode = `call := mujica.ToolCall{ID: "1", Name: "read_file", Args: "{\"path\":\"ledger.md\"}", + Result: "{\"lines\":40}", State: mujica.AgentDone, Duration: 420 * time.Millisecond} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ToolCallCard(c, call, mujica.ToolCallCardOptions{OpenArgs: true}) +} +ui.Render(view, 400, 300, 1)` + +const toolCallGroupCode = `open := false +calls := []mujica.ToolCall{ + {ID: "a", Name: "list_dir", State: mujica.AgentDone, Duration: 300 * time.Millisecond}, + {ID: "b", Name: "read_file", State: mujica.AgentFailed, Error: "not found"}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ToolCallGroup(c, &open, calls, mujica.ToolCallGroupOptions{}) +} +ui.Render(view, 400, 300, 1)` + +const toolApprovalDialogCode = `open := true +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ToolApprovalDialog(c, &open, mujica.ToolApprovalOptions{ + Tool: "delete_files", Args: "{\"glob\":\"*.tmp\"}", Reason: "Clean the build folder.", + }) + if r.Allowed { + fmt.Println("run the tool") + } +} +ui.Render(view, 400, 300, 1)` + +const permissionPromptCode = `open := true +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.PermissionPrompt(c, &open, mujica.PermissionPromptOptions{ + Title: "Write to the ledger?", Scope: "Write access to ~/court/ledger", + }) + if r.Choice == mujica.PermissionAllowAlways { + fmt.Println("remember the grant") + } +} +ui.Render(view, 400, 300, 1)` + +const agentStepListCode = `steps := []mujica.AgentStep{ + {ID: "read", Title: "Read the guest list", State: mujica.AgentDone, Duration: time.Second}, + {ID: "seat", Title: "Assign the seats", State: mujica.AgentFailed, Detail: "Table 4 is full."}, + {ID: "send", Title: "Send invitations", State: mujica.AgentPending}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.AgentStepList(c, steps, mujica.AgentStepListOptions{}); r.Retry != "" { + fmt.Println("retry", r.Retry) + } +} +ui.Render(view, 400, 300, 1)` + +const agentPlanCode = `items := []mujica.PlanItem{ + {ID: "a", Text: "Read the guest list", State: mujica.AgentDone}, + {ID: "b", Text: "Assign the seats", State: mujica.AgentRunning}, + {ID: "c", Text: "Order the flowers"}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AgentPlan(c, &items, mujica.AgentPlanOptions{}) +} +ui.Render(view, 400, 300, 1)` + +const agentStatusCode = `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AgentStatus(c, mujica.AgentWaiting, mujica.AgentStatusOptions{}) +} +ui.Render(view, 400, 300, 1)` + +const agentProgressCode = `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AgentProgress(c, 0.4, mujica.AgentProgressOptions{Action: "Reading ledger.md"}) +} +ui.Render(view, 400, 300, 1)` + +const subAgentTreeCode = `agents := []mujica.SubAgent{{ID: "lead", Name: "Steward", State: mujica.AgentRunning, Children: []mujica.SubAgent{ + {ID: "cook", Name: "Cook", Task: "Plan the menu", State: mujica.AgentWaiting}, +}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SubAgentTree(c, agents, mujica.SubAgentTreeOptions{}) +} +ui.Render(view, 400, 300, 1)` + +const fileChangeCardCode = `decision := mujica.FilePending +change := mujica.FileChange{Path: "ledger.md", Old: "Guests: 40\n", New: "Guests: 42\n"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.FileChangeCard(c, &decision, change, mujica.FileChangeCardOptions{}).OpenDiff { + fmt.Println("open the full diff") + } +} +ui.Render(view, 400, 300, 1)` + +const multiFileDiffReviewCode = `files := []mujica.FileChange{ + {Path: "ledger.md", Old: "Guests: 40\n", New: "Guests: 42\n"}, + {Path: "menu.md", Old: "soup\n", New: "soup\ntart\n"}, +} +decisions := make([]mujica.FileDecision, len(files)) +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.MultiFileDiffReview(c, &decisions, files, mujica.MultiFileDiffReviewOptions{}) +} +ui.Render(view, 400, 300, 1)` + +const commandExecutionCardCode = `run := mujica.CommandRun{Command: "go test ./...", Dir: "~/court", Running: true, Output: "\x1b[32mok\x1b[0m court\n"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.CommandExecutionCard(c, run, mujica.CommandExecutionCardOptions{}).Changed() { + fmt.Println("abort the process") + } +} +ui.Render(view, 400, 300, 1)` + +const screenshotStreamCode = `var st mujica.ScreenshotStreamState +var frames []mujica.ScreenshotFrame // appended as the agent captures them +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ScreenshotStream(c, &st, frames, mujica.ScreenshotStreamOptions{}) +} +ui.Render(view, 400, 300, 1)` + +const artifactPanelCode = `art := mujica.Artifact{Title: "seating.go", Language: "go", Content: "package court\n"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ArtifactPanel(c, art, mujica.ArtifactPanelOptions{}).Exported { + fmt.Println("save the file") + } +} +ui.Render(view, 400, 300, 1)` + +const artifactVersionSwitcherCode = `current := 1 +versions := []mujica.ArtifactVersion{{Label: "v1", Note: "First draft"}, {Label: "v2", Note: "Added music"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ArtifactVersionSwitcher(c, ¤t, versions, mujica.ArtifactVersionSwitcherOptions{}).Compare { + fmt.Println("diff v1 and v2") + } +} +ui.Render(view, 400, 300, 1)` + +const sandboxStatusCode = `info := mujica.SandboxInfo{Name: "sandbox-7", State: mujica.SandboxRunning, + Resources: []mujica.SandboxResource{{Name: "CPU", Used: 1.5, Limit: 2, Unit: "cores"}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SandboxStatus(c, info, mujica.SandboxStatusOptions{}) +} +ui.Render(view, 400, 300, 1)` + +const mcpServerListCode = `servers := []mujica.MCPServer{{ID: "fs", Name: "filesystem", Transport: "stdio", State: mujica.MCPConnected, Tools: 12}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MCPServerList(c, servers, mujica.MCPServerListOptions{}); r.Action == mujica.MCPStop { + fmt.Println("stop", r.Server) + } +} +ui.Render(view, 400, 300, 1)` + +const memoryPanelCode = `entries := []mujica.MemoryEntry{{ID: "1", Text: "Lady Sakiko prefers the east wing.", Source: "Chat"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MemoryPanel(c, &entries, mujica.MemoryPanelOptions{}); r.Deleted != "" { + fmt.Println("forget", r.Deleted) + } +} +ui.Render(view, 400, 300, 1)` + +const checkpointListCode = `current := "c2" +points := []mujica.Checkpoint{{ID: "c2", Label: "Menu drafted"}, {ID: "c1", Label: "Start"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.CheckpointList(c, ¤t, points, mujica.CheckpointListOptions{}).Changed() { + fmt.Println("restore", current) + } +} +ui.Render(view, 400, 300, 1)` + +const humanInputRequestCode = `answer := "" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.HumanInputRequest(c, &answer, mujica.HumanInputRequestOptions{ + Question: "Which hall?", Options: []string{"East wing", "Great hall"}, AllowFree: true, + }) + if r.Submitted { + fmt.Println("reply", answer) + } +} +ui.Render(view, 400, 300, 1)` diff --git a/examples/gallery/pages_agent_more.go b/examples/gallery/pages_agent_more.go new file mode 100644 index 0000000..dbc4b9b --- /dev/null +++ b/examples/gallery/pages_agent_more.go @@ -0,0 +1,285 @@ +package main + +import ( + "fmt" + "image" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +type multiFileDemoState struct { + decisions []mujica.FileDecision + disabled bool +} + +var agentDemoFiles = []mujica.FileChange{ + agentDemoChange, + {Path: "court/menu.md", Old: "soup\nroast\n", New: "soup\nroast\ntart\n"}, + {Path: "court/old-plan.md", Old: "Hold the ball in the cellar.\n"}, +} + +func multiFileDiffDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "271", func() multiFileDemoState { + return multiFileDemoState{decisions: make([]mujica.FileDecision, len(agentDemoFiles))} + }) + overlayControls(c, func() { + overlayCheck(c, log, &s.disabled, "Disabled") + if mujica.Button(c, "Reset", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + clear(s.decisions) + log("reset") + } + }) + if mujica.MultiFileDiffReview(c, &s.decisions, agentDemoFiles, mujica.MultiFileDiffReviewOptions{Disabled: s.disabled}).Changed() { + log(fmt.Sprintf("decisions = %v", s.decisions)) + } +} + +type commandDemoState struct { + run mujica.CommandRun + disabled bool + lines int +} + +func commandExecutionDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "272", func() commandDemoState { + return commandDemoState{run: mujica.CommandRun{Command: "go test ./court/...", Dir: "~/projects/court", Running: true}} + }) + overlayControls(c, func() { + overlayCheck(c, log, &s.disabled, "Disabled") + if mujica.Button(c, "Print a line", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.lines++ + color := []string{"32mok ", "33mwarn", "31mFAIL"}[s.lines%3] + s.run.Output += fmt.Sprintf("\x1b[%s\x1b[0m court/case%d 0.%02ds\n", color, s.lines, s.lines) + log("printed a line") + } + if mujica.Button(c, "Restart", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.run.Running, s.run.Output, s.lines = true, "", 0 + log("restarted") + } + }) + if mujica.CommandExecutionCard(c, s.run, mujica.CommandExecutionCardOptions{Disabled: s.disabled}).Changed() { + s.run.Running, s.run.ExitCode, s.run.Duration = false, 130, time.Duration(s.lines)*time.Second + s.run.Output += "\x1b[31maborted by user\x1b[0m\n" + log("abort requested") + } +} + +type screenshotDemoState struct { + st mujica.ScreenshotStreamState + frames []mujica.ScreenshotFrame + disabled bool +} + +// agentDemoFrame paints a frame with a moving block. +func agentDemoFrame(i int) mujica.ScreenshotFrame { + img := image.NewRGBA(image.Rect(0, 0, 320, 180)) + for y := range 180 { + for x := range 320 { + o := img.PixOffset(x, y) + v := uint8(235) + if x >= 20+i*24%260 && x < 60+i*24%260 && y > 60 && y < 120 { + v = 120 + } + img.Pix[o], img.Pix[o+1], img.Pix[o+2], img.Pix[o+3] = v, v-10, v-20, 255 + } + } + return mujica.ScreenshotFrame{Image: ui.NewBitmap(img), Caption: fmt.Sprintf("Clicked button %d", i+1), At: time.Duration(i) * 2 * time.Second} +} + +func screenshotStreamDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "273", func() screenshotDemoState { + return screenshotDemoState{frames: []mujica.ScreenshotFrame{agentDemoFrame(0), agentDemoFrame(1)}} + }) + overlayControls(c, func() { + overlayCheck(c, log, &s.disabled, "Disabled") + if mujica.Button(c, "Capture a frame", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.frames = append(s.frames, agentDemoFrame(len(s.frames))) + log(fmt.Sprintf("frame %d arrived", len(s.frames))) + } + }) + if mujica.ScreenshotStream(c, &s.st, s.frames, mujica.ScreenshotStreamOptions{Height: 220, Disabled: s.disabled}).Changed() { + log(fmt.Sprintf("frame %d, paused = %v", s.st.Index+1, s.st.Paused)) + } +} + +type artifactDemoState struct { + kind string + disabled bool +} + +func artifactPanelDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "274", func() artifactDemoState { return artifactDemoState{kind: "Code"} }) + overlayControls(c, func() { + if ui.Select(c, &s.kind, []string{"Code", "Document"}).Changed() { + log("kind = " + s.kind) + } + overlayCheck(c, log, &s.disabled, "Disabled") + }) + art := mujica.Artifact{Title: "seating.go", Language: "go", + Content: "package court\n\n// Seats maps guests to tables.\nfunc Seats() map[string]int {\n\treturn map[string]int{\"Sakiko\": 1, \"Uika\": 2}\n}\n"} + opts := mujica.ArtifactPanelOptions{Height: 200, Disabled: s.disabled} + if s.kind == "Document" { + art = mujica.Artifact{Title: "Invitation", Kind: mujica.ArtifactDocument, Content: "# You are invited\n\nThe masquerade begins at nine.\n"} + opts.Preview = func() { + mujica.Heading(c, "You are invited", mujica.HeadingOptions{}) + ui.Text(c, "The masquerade begins at nine.") + } + } + r := mujica.ArtifactPanel(c, art, opts) + if r.Copied { + log("copied to the clipboard") + } + if r.Exported { + log("export requested") + } +} + +type versionDemoState struct { + current int + disabled bool +} + +func artifactVersionDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "275", func() versionDemoState { return versionDemoState{current: 2} }) + overlayControls(c, func() { overlayCheck(c, log, &s.disabled, "Disabled") }) + versions := []mujica.ArtifactVersion{{Label: "v1", Note: "First draft"}, {Label: "v2", Note: "Added the quartet"}, {Label: "v3", Note: "Moved the wine table"}} + r := mujica.ArtifactVersionSwitcher(c, &s.current, versions, mujica.ArtifactVersionSwitcherOptions{Disabled: s.disabled}) + if r.Changed { + log("version = " + versions[s.current].Label) + } + if r.Compare { + log("compare " + versions[s.current-1].Label + " and " + versions[s.current].Label) + } +} + +type sandboxDemoState struct { + state string + cpu float64 + expires time.Time +} + +func sandboxStatusDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "276", func() sandboxDemoState { + return sandboxDemoState{state: "Running", cpu: 1.2, expires: time.Now().Add(10 * time.Minute)} + }) + names := []string{"Starting", "Running", "Stopped", "Failed"} + state := mujica.SandboxStarting + overlayControls(c, func() { + if ui.Select(c, &s.state, names).Changed() { + log("state = " + s.state) + } + overlaySlider(c, log, &s.cpu, "CPU", "cores", 0, 2, 0.1) + if mujica.Button(c, "Extend 5 min", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.expires = s.expires.Add(5 * time.Minute) + log("extended") + } + }) + for i, n := range names { + if n == s.state { + state = mujica.SandboxState(i) + } + } + mujica.SandboxStatus(c, mujica.SandboxInfo{Name: "sandbox-7", State: state, Expires: s.expires, Resources: []mujica.SandboxResource{ + {Name: "CPU", Used: s.cpu, Limit: 2, Unit: "cores"}, {Name: "Memory", Used: 3.1, Limit: 4, Unit: "GB"}, + }}, mujica.SandboxStatusOptions{}) +} + +type mcpDemoState struct { + servers []mujica.MCPServer + disabled bool +} + +func mcpServerListDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "277", func() mcpDemoState { + return mcpDemoState{servers: []mujica.MCPServer{ + {ID: "fs", Name: "filesystem", Transport: "stdio", State: mujica.MCPConnected, Tools: 12}, + {ID: "gh", Name: "github", Transport: "http", State: mujica.MCPError, Error: "401 Unauthorized"}, + {ID: "db", Name: "postgres", Transport: "stdio", State: mujica.MCPStopped}, + }} + }) + overlayControls(c, func() { overlayCheck(c, log, &s.disabled, "Disabled") }) + r := mujica.MCPServerList(c, s.servers, mujica.MCPServerListOptions{Disabled: s.disabled}) + if r.Action == mujica.MCPNone { + return + } + log(fmt.Sprintf("%s: %s", r.Server, [...]string{"", "start", "stop", "reconnect"}[r.Action])) + for i := range s.servers { + if s.servers[i].ID != r.Server { + continue + } + switch r.Action { + case mujica.MCPStop: + s.servers[i].State = mujica.MCPStopped + default: + s.servers[i].State, s.servers[i].Tools, s.servers[i].Error = mujica.MCPConnected, 5, "" + } + } +} + +type memoryDemoState struct { + entries []mujica.MemoryEntry + disabled bool +} + +func memoryPanelDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "278", func() memoryDemoState { + return memoryDemoState{entries: []mujica.MemoryEntry{ + {ID: "1", Text: "Lady Sakiko prefers the east wing.", Source: "Chat, 3 Oct"}, + {ID: "2", Text: "The quartet needs two days' notice.", Source: "Plan, 1 Oct"}, + {ID: "3", Text: "Claret is served after nine.", Source: "Ledger"}, + }} + }) + overlayControls(c, func() { overlayCheck(c, log, &s.disabled, "Disabled") }) + r := mujica.MemoryPanel(c, &s.entries, mujica.MemoryPanelOptions{Disabled: s.disabled}) + if r.Edited != "" { + log("edited " + r.Edited) + } + if r.Deleted != "" { + log("deleted " + r.Deleted) + } +} + +type checkpointDemoState struct { + current string + disabled bool +} + +func checkpointListDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "279", func() checkpointDemoState { return checkpointDemoState{current: "c3"} }) + overlayControls(c, func() { overlayCheck(c, log, &s.disabled, "Disabled") }) + points := []mujica.Checkpoint{{ID: "c3", Label: "Seats assigned", Note: "12 files changed"}, + {ID: "c2", Label: "Menu drafted", Note: "3 files changed"}, {ID: "c1", Label: "Start"}} + if mujica.CheckpointList(c, &s.current, points, mujica.CheckpointListOptions{Disabled: s.disabled}).Changed() { + log("rolled back to " + s.current) + } +} + +type humanDemoState struct { + answer string + free bool + deadline time.Time + disabled bool +} + +func humanInputDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "280", func() humanDemoState { return humanDemoState{free: true} }) + overlayControls(c, func() { + overlayCheck(c, log, &s.free, "AllowFree") + overlayCheck(c, log, &s.disabled, "Disabled") + if mujica.Button(c, "Start a 30 s timer", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.deadline = time.Now().Add(30 * time.Second) + log("timer started") + } + }) + r := mujica.HumanInputRequest(c, &s.answer, mujica.HumanInputRequestOptions{Question: "Which hall should host the masquerade?", + Options: []string{"East wing", "Great hall"}, AllowFree: s.free, Deadline: s.deadline, Disabled: s.disabled}) + if r.Submitted { + log("answer sent: " + s.answer) + } + if r.TimedOut { + log("timed out") + } +} diff --git a/file_change_card.go b/file_change_card.go new file mode 100644 index 0000000..76785dc --- /dev/null +++ b/file_change_card.go @@ -0,0 +1,85 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// FileChangeCardOptions configure a FileChangeCard. +type FileChangeCardOptions struct { + // Preview is the diff lines shown; zero means 8. + Preview int + Disabled bool +} + +// FileChangeResult reports this frame's events. +type FileChangeResult struct { + Element *ui.Element + // Decided reports that *decision changed. + Decided bool + // OpenDiff asks the caller to show the full diff. + OpenDiff bool +} + +// FileChangeCard previews a file change to accept or reject. +func FileChangeCard(c *ui.Context, decision *FileDecision, change FileChange, opts FileChangeCardOptions) FileChangeResult { + if decision == nil || change.Path == "" { + panic("mujica: FileChangeCard needs a decision and a Path") + } + if opts.Preview < 0 { + panic("mujica: FileChangeCard Preview is negative") + } + preview := opts.Preview + if preview == 0 { + preview = 8 + } + u := Density(c).Unit() + var r FileChangeResult + r.Element = agentCard(c).Disabled(opts.Disabled).Label(change.Path) + dc := agentDiffOf(r.Element, change) + locked := r.Element.IsDisabled() + r.Element.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).MinHeight(theme.MinHitSize).Children(func() { + ui.Icon(c, icons.Must("file-text")).Size(16, 16).TextColor(Tokens(c).TextMuted).Shrink(0) + ui.Text(c, change.Path).Font(theme.MonoFont).FontWeight(600).SingleLine().Grow(1).Shrink(1) + switch { + case change.Old == "" && change.New != "": + agentCaption(c, msg(c, "file_change_card.new")) + case change.New == "" && change.Old != "": + agentCaption(c, msg(c, "file_change_card.deleted")) + } + agentDiffStats(c, dc.add, dc.del) + agentDecisionMark(c, *decision) + }) + from := max(0, dc.firstEdit-2) + shown := dc.lines[from:min(len(dc.lines), from+preview)] + if len(shown) > 0 { + agentDiffView(c, shown, 320).Font(theme.MonoFont) + } + ui.Row(c).Gap(u * 2).Justify(ui.End).Wrap().Children(func() { + if Button(c, msg(c, "file_change_card.open"), ButtonOptions{Variant: Ghost, Disabled: locked}).Clicked() && !locked { + r.OpenDiff = true + } + if *decision != FilePending { + if Button(c, msg(c, "file_change_card.undo"), ButtonOptions{Variant: Secondary, Disabled: locked}).Clicked() && !locked { + *decision, r.Decided = FilePending, true + } + return + } + if Button(c, msg(c, "file_change_card.reject"), ButtonOptions{Variant: Secondary, Disabled: locked}).Clicked() && !locked { + *decision, r.Decided = FileRejected, true + } + if Button(c, msg(c, "file_change_card.accept"), ButtonOptions{Disabled: locked}).Clicked() && !locked { + *decision, r.Decided = FileAccepted, true + } + }) + }) + if r.Decided || r.OpenDiff { + slog.Debug("mujica: file_change_card event", "path", change.Path, "decision", int(*decision), "open", r.OpenDiff) + } + return r +} diff --git a/file_change_card_test.go b/file_change_card_test.go new file mode 100644 index 0000000..0c93ff4 --- /dev/null +++ b/file_change_card_test.go @@ -0,0 +1,84 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +var fileChangeSample = FileChange{Path: "court/ledger.md", + Old: "# Ledger\nGuests: 40\nWine: claret\nMusic: none\n", + New: "# Ledger\nGuests: 42\nWine: claret\nMusic: quartet\nFlowers: lilies\n"} + +func fileChangeTester(d *FileDecision, ch FileChange, opts FileChangeCardOptions, got *[]FileChangeResult) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := FileChangeCard(c, d, ch, opts) + if r.Decided || r.OpenDiff { + *got = append(*got, r) + } + }, 560, 400) +} + +func TestFileChangeCardStatsPreviewAndDecide(t *testing.T) { + d := FilePending + var got []FileChangeResult + tt := fileChangeTester(&d, fileChangeSample, FileChangeCardOptions{}, &got) + for _, s := range []string{"court/ledger.md", "+3", "−2", "Pending", "Guests: 40", "Guests: 42", "Flowers: lilies"} { + if !tt.HasText(s) { + t.Fatalf("missing %q in %q", s, tt.Texts()) + } + } + _ = tt.Click("Open diff") + if len(got) != 1 || !got[0].OpenDiff || d != FilePending { + t.Fatalf("open diff: %+v", got) + } + _ = tt.Click("Accept") + if d != FileAccepted || !got[1].Decided || !tt.HasText("Accepted") { + t.Fatalf("accept: %v", d) + } + _ = tt.Click("Undo") + if d != FilePending { + t.Fatalf("undo: %v", d) + } + tt = fileChangeTester(&d, fileChangeSample, FileChangeCardOptions{}, &got) + for range 3 { + tt.Key(0, ui.KeyTab) + if tt.Focused("Reject") { + break + } + } + tt.Key(0, ui.KeyEnter) + if d != FileRejected || !tt.HasText("Rejected") { + t.Fatalf("keyboard reject: %v", d) + } +} + +func TestFileChangeCardPreviewLimitAndNewFile(t *testing.T) { + d := FilePending + var got []FileChangeResult + tt := fileChangeTester(&d, FileChange{Path: "a.txt", New: "1\n2\n3\n4\n5\n"}, FileChangeCardOptions{Preview: 2}, &got) + if !tt.HasText("New file") || !tt.HasText("+5") || !tt.HasText("2") || tt.HasText("3") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestFileChangeCardDisabled(t *testing.T) { + d := FilePending + var got []FileChangeResult + tt := fileChangeTester(&d, fileChangeSample, FileChangeCardOptions{Disabled: true}, &got) + _ = tt.Click("Accept") + _ = tt.Click("Open diff") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if len(got) != 0 || d != FilePending { + t.Fatalf("disabled card acted: %+v %v", got, d) + } +} + +func TestFileChangeCardSnapshot(t *testing.T) { + snapshot(t, "file_change_card", 520, 330, func(c *ui.Context) { + d := FilePending + ui.Column(c).Padding(16).Children(func() { FileChangeCard(c, &d, fileChangeSample, FileChangeCardOptions{}) }) + }) +} diff --git a/human_input_request.go b/human_input_request.go new file mode 100644 index 0000000..1d4a6cf --- /dev/null +++ b/human_input_request.go @@ -0,0 +1,126 @@ +package mujica + +import ( + "fmt" + "log/slog" + "slices" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// HumanInputRequestOptions configure a HumanInputRequest. Question is required. +type HumanInputRequestOptions struct { + Question string + // Options are suggested answers; AllowFree adds a free one. + Options []string + AllowFree bool + // Deadline is when the agent stops waiting; zero waits forever. + Deadline time.Time + Disabled bool +} + +// HumanInputResult reports this frame's events. +type HumanInputResult struct { + Element *ui.Element + Submitted bool + // TimedOut reports the frame the deadline passed. + TimedOut bool +} + +type humanInputState struct { + draft string + expired bool +} + +// HumanInputRequest asks the user a question before a deadline. +func HumanInputRequest(c *ui.Context, answer *string, opts HumanInputRequestOptions) HumanInputResult { + if answer == nil || opts.Question == "" { + panic("mujica: HumanInputRequest needs an answer and a Question") + } + if len(opts.Options) == 0 && !opts.AllowFree { + panic("mujica: HumanInputRequest needs Options or AllowFree") + } + k := Tokens(c) + u := Density(c).Unit() + var r HumanInputResult + r.Element = agentCard(c).Border(theme.BorderWidth, k.Info).Role(ui.RoleGroup).Label(opts.Question) + st := ui.Local(r.Element, "mujica.humaninput", func() humanInputState { return humanInputState{} }) + left := time.Duration(0) + if !opts.Deadline.IsZero() { + left = opts.Deadline.Sub(c.Now()) + if left <= 0 && !st.expired { + st.expired, r.TimedOut = true, true + } + } + r.Element.Disabled(opts.Disabled || st.expired) + locked := r.Element.IsDisabled() + r.Element.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Start).Children(func() { + ui.Icon(c, icons.Must("user")).Size(18, 18).TextColor(k.Info).Shrink(0).Margin(2, 0, 0, 0) + ui.Text(c, opts.Question).FontWeight(600).Grow(1).Shrink(1) + }) + if len(opts.Options) > 0 { + items := make([]RadioItem[string], len(opts.Options)) + for i, o := range opts.Options { + items[i] = RadioItem[string]{Value: o, Label: o} + } + chosen := *answer + if RadioGroup(c, &chosen, items, RadioGroupOptions{Label: opts.Question, Disabled: locked}).Changed() && !locked { + *answer, st.draft = chosen, "" + } + } + submit := false + if opts.AllowFree { + in := TextInput(c, &st.draft, TextInputOptions{Placeholder: msg(c, "human_input_request.free"), + Label: msg(c, "human_input_request.free"), Disabled: locked}) + if in.Changed() && !locked { + *answer = st.draft + } + submit = in.Submitted() + } + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + humanInputClock(c, opts.Deadline, left, st.expired) + blank := strings.TrimSpace(*answer) == "" + if Button(c, msg(c, "human_input_request.send"), ButtonOptions{Disabled: locked || blank}).Clicked() { + submit = true + } + r.Submitted = submit && !locked && !blank + }) + }) + if len(opts.Options) > 0 && !opts.AllowFree && *answer != "" && !slices.Contains(opts.Options, *answer) { + panic(fmt.Sprintf("mujica: HumanInputRequest answer %q is not an option", *answer)) + } + if r.Submitted || r.TimedOut { + slog.Debug("mujica: human_input_request event", "submitted", r.Submitted, "timed_out", r.TimedOut) + } + return r +} + +// humanInputClock shows the time left, or that it ran out. +func humanInputClock(c *ui.Context, deadline time.Time, left time.Duration, expired bool) { + k := Tokens(c) + text, tone := "", k.TextMuted + switch { + case expired: + text, tone = msg(c, "human_input_request.timeout"), k.Warning + case !deadline.IsZero(): + text = fmt.Sprintf(msg(c, "human_input_request.left"), agentDuration(left.Truncate(time.Second))) + wait := left % time.Second + if wait == 0 { + wait = time.Second + } + c.After(wait) + } + ui.Row(c).Grow(1).Gap(Density(c).Unit()).AlignItems(ui.Center).Role(ui.RoleStatus).Label(text).Children(func() { + if text == "" { + return + } + ui.Icon(c, icons.Must("clock")).Size(14, 14).TextColor(tone) + ui.Text(c, text).TextColor(tone).FontSize(FontSize(c, theme.CaptionSize+1)) + }) +} diff --git a/human_input_request_test.go b/human_input_request_test.go new file mode 100644 index 0000000..cb82671 --- /dev/null +++ b/human_input_request_test.go @@ -0,0 +1,94 @@ +package mujica + +import ( + "strings" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func humanTester(answer *string, opts *HumanInputRequestOptions, got *[]HumanInputResult) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := HumanInputRequest(c, answer, *opts) + if r.Submitted || r.TimedOut { + *got = append(*got, r) + } + }, 560, 400) +} + +func TestHumanInputRequestOptionAndFree(t *testing.T) { + answer := "" + opts := HumanInputRequestOptions{Question: "Which hall for the ball?", Options: []string{"East wing", "Great hall"}, AllowFree: true} + var got []HumanInputResult + tt := humanTester(&answer, &opts, &got) + _ = tt.Click("Send answer") // disabled while blank + if len(got) != 0 { + t.Fatal("blank answer sent") + } + _ = tt.Click("Great hall") + if answer != "Great hall" { + t.Fatalf("option: %q", answer) + } + _ = tt.Click("Or write your own answer") + tt.Type("The garden") + if answer != "The garden" { + t.Fatalf("free: %q", answer) + } + tt.Key(0, ui.KeyEnter) + if len(got) != 1 || !got[0].Submitted { + t.Fatalf("Enter: %+v", got) + } +} + +func TestHumanInputRequestDeadline(t *testing.T) { + answer := "East wing" + opts := HumanInputRequestOptions{Question: "Which hall?", Options: []string{"East wing"}, Deadline: time.Now().Add(75 * time.Second)} + var got []HumanInputResult + tt := humanTester(&answer, &opts, &got) + found := false + for _, s := range tt.Texts() { + found = found || strings.HasPrefix(s, "Answer within 1 m 1") + } + if !found { + t.Fatalf("countdown missing: %q", tt.Texts()) + } + opts.Deadline = time.Now().Add(-time.Second) + tt.Frame() + tt.Frame() + if len(got) != 1 || !got[0].TimedOut || !tt.HasText("The agent stopped waiting") { + t.Fatalf("timeout: %+v", got) + } + _ = tt.Click("Send answer") + if len(got) != 1 { + t.Fatal("answer sent after the deadline") + } +} + +func TestHumanInputRequestDisabledAndRules(t *testing.T) { + answer := "" + opts := HumanInputRequestOptions{Question: "Which hall?", Options: []string{"East wing"}, Disabled: true} + var got []HumanInputResult + tt := humanTester(&answer, &opts, &got) + _ = tt.Click("East wing") + if answer != "" { + t.Fatal("disabled request changed the answer") + } + defer func() { + if recover() == nil { + t.Fatal("no options and no free answer did not panic") + } + }() + humanTester(&answer, &HumanInputRequestOptions{Question: "x"}, &got) +} + +func TestHumanInputRequestSnapshot(t *testing.T) { + snapshot(t, "human_input_request", 520, 300, func(c *ui.Context) { + answer := "Great hall" + ui.Column(c).Padding(16).Children(func() { + HumanInputRequest(c, &answer, HumanInputRequestOptions{Question: "Which hall should host the masquerade?", + Options: []string{"East wing", "Great hall"}, AllowFree: true}) + }) + }) +} diff --git a/internal/diff.go b/internal/diff.go index ccc9071..332c68f 100644 --- a/internal/diff.go +++ b/internal/diff.go @@ -2,7 +2,7 @@ package internal import "strings" -// DiffOp says whether a diff line is kept, removed or added. +// DiffOp says a line is kept, removed or added. type DiffOp uint8 const ( @@ -11,14 +11,14 @@ const ( DiffInsert ) -// DiffLine is one line of a line diff with its 1-based line numbers; 0 means absent. +// DiffLine is a numbered diff line; 0 means absent. type DiffLine struct { Op DiffOp Text string Old, New int } -// SplitLines splits text into lines without their line breaks; "" has no lines. +// SplitLines splits text into lines; "" has none. func SplitLines(s string) []string { if s == "" { return nil @@ -26,7 +26,7 @@ func SplitLines(s string) []string { return strings.Split(strings.TrimSuffix(s, "\n"), "\n") } -// LineDiff returns a shortest edit script turning a into b (Myers, O((N+M)D)). +// LineDiff returns a shortest edit script from a to b. func LineDiff(a, b []string) []DiffLine { // Common prefix and suffix need no search. pre := 0 @@ -49,7 +49,7 @@ func LineDiff(a, b []string) []DiffLine { return out } -// myers appends the edit script of a to b, numbering from offsets ao and bo. +// myers appends the edit script, numbering from ao and bo. func myers(out []DiffLine, a, b []string, ao, bo int) []DiffLine { n, m := len(a), len(b) total := n + m @@ -80,7 +80,7 @@ func myers(out []DiffLine, a, b []string, ao, bo int) []DiffLine { } } } - // Walk the trace back from (n, m), collecting moves in reverse. + // Walk the trace back, collecting moves in reverse. var rev []DiffLine x, y := n, m for d := end; d >= 0; d-- { diff --git a/mcp_server_list.go b/mcp_server_list.go new file mode 100644 index 0000000..649fdaa --- /dev/null +++ b/mcp_server_list.go @@ -0,0 +1,144 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// MCPState is a server connection; zero is stopped. +type MCPState int + +const ( + MCPStopped MCPState = iota + MCPConnecting + MCPConnected + MCPError +) + +// MCPServer is one configured MCP server; the caller owns it. +type MCPServer struct { + ID string + Name string + Transport string + State MCPState + Tools int + // Error explains MCPError. + Error string +} + +// MCPAction is a list request; zero is none. +type MCPAction int + +const ( + MCPNone MCPAction = iota + MCPStart + MCPStop + MCPReconnect +) + +// MCPServerListOptions configure an MCPServerList. +type MCPServerListOptions struct { + // MaxHeight caps the scrolling list; zero means 360. + MaxHeight float32 + Disabled bool + Still bool +} + +// MCPServerListResult reports this frame's request. +type MCPServerListResult struct { + Element *ui.Element + Action MCPAction + // Server is the ID the action is for. + Server string +} + +// MCPServerList lists MCP servers with start, stop and reconnect. +func MCPServerList(c *ui.Context, servers []MCPServer, opts MCPServerListOptions) MCPServerListResult { + seen := map[string]bool{} + for i, s := range servers { + if s.ID == "" || s.Name == "" || seen[s.ID] || s.Tools < 0 || s.State < MCPStopped || s.State > MCPError { + panic(fmt.Sprintf("mujica: MCPServerList server %d needs a unique ID, a Name, a known State and Tools >= 0", i)) + } + seen[s.ID] = true + } + if opts.MaxHeight < 0 { + panic("mujica: MCPServerList MaxHeight is negative") + } + maxH := opts.MaxHeight + if maxH == 0 { + maxH = 360 + } + var r MCPServerListResult + r.Element = ui.Column(c).Shrink(0).Disabled(opts.Disabled).Label(msg(c, "mcp_server_list.label")) + locked := r.Element.IsDisabled() + r.Element.Children(func() { + if len(servers) == 0 { + agentCaption(c, msg(c, "mcp_server_list.empty")) + return + } + k := Tokens(c) + agentRows(c, len(servers), func(i int) { + if a := mcpServerRow(c, servers[i], locked, opts.Still); a != MCPNone && !locked { + r.Action, r.Server = a, servers[i].ID + } + }).Shrink(1).MaxHeight(maxH).Background(k.Surface).Border(theme.BorderWidth, k.Border).Radius(theme.CardRadius). + Dividers(theme.BorderWidth, k.Border) + }) + if r.Action != MCPNone { + slog.Debug("mujica: mcp_server_list action", "server", r.Server, "action", int(r.Action)) + } + return r +} + +// mcpServerRow builds one server, returning its pressed action. +func mcpServerRow(c *ui.Context, s MCPServer, locked, still bool) MCPAction { + k := Tokens(c) + d := Density(c) + u := d.Unit() + words := [...]string{"stopped", "connecting", "connected", "error"} + word := msg(c, "mcp_server_list."+words[s.State]) + act := MCPNone + ui.Row(c).Key(s.ID).Gap(u*3).AlignItems(ui.Center).MinHeight(d.ControlHeight()+u*2).Padding(u*2, u*3). + Label(s.Name + ", " + word).Children(func() { + switch s.State { + case MCPConnecting: + agentMark(c, AgentRunning, 16, still) + case MCPConnected: + agentMark(c, AgentDone, 16, still) + case MCPError: + agentMark(c, AgentFailed, 16, still) + default: + ui.Icon(c, icons.Must("wifi-off")).Size(16, 16).TextColor(k.TextMuted) + } + ui.Column(c).Grow(1).Shrink(1).Gap(u / 2).Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, s.Name).FontWeight(600).SingleLine() + agentCaption(c, s.Transport).Font(theme.MonoFont) + }) + line := word + if s.State == MCPConnected { + line += " · " + fmt.Sprintf(msg(c, "mcp_server_list.tools"), s.Tools) + } + agentCaption(c, line) + if s.State == MCPError && s.Error != "" { + ui.Text(c, s.Error).TextColor(k.Danger).FontSize(FontSize(c, theme.CaptionSize)).Selectable() + } + }) + if s.State == MCPError && Button(c, msg(c, "mcp_server_list.reconnect"), ButtonOptions{Variant: Outline, Disabled: locked}).Clicked() { + act = MCPReconnect + } + if s.State == MCPStopped { + if Button(c, msg(c, "mcp_server_list.start"), ButtonOptions{Variant: Secondary, Disabled: locked}).Clicked() { + act = MCPStart + } + } else if Button(c, msg(c, "mcp_server_list.stop"), ButtonOptions{Variant: Secondary, Disabled: locked}).Clicked() { + act = MCPStop + } + }) + return act +} diff --git a/mcp_server_list_test.go b/mcp_server_list_test.go new file mode 100644 index 0000000..a3954ee --- /dev/null +++ b/mcp_server_list_test.go @@ -0,0 +1,91 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +var mcpServersSample = []MCPServer{ + {ID: "fs", Name: "filesystem", Transport: "stdio", State: MCPConnected, Tools: 12}, + {ID: "gh", Name: "github", Transport: "http", State: MCPError, Error: "401 Unauthorized"}, + {ID: "db", Name: "postgres", Transport: "stdio", State: MCPStopped}, + {ID: "web", Name: "browser", Transport: "sse", State: MCPConnecting}, +} + +func mcpTester(servers []MCPServer, opts MCPServerListOptions, got *[]MCPServerListResult) *ui.Tester { + opts.Still = true + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := MCPServerList(c, servers, opts) + if r.Action != MCPNone { + *got = append(*got, r) + } + }, 600, 460) +} + +func TestMCPServerListStatesAndActions(t *testing.T) { + var got []MCPServerListResult + tt := mcpTester(mcpServersSample, MCPServerListOptions{}, &got) + for _, s := range []string{"Connected · 12 tools", "Connection failed", "401 Unauthorized", "Stopped", "Connecting"} { + if !tt.HasText(s) { + t.Fatalf("missing %q in %q", s, tt.Texts()) + } + } + _ = tt.Click("Reconnect") + _ = tt.Click("Start") + if len(got) != 2 || got[0].Action != MCPReconnect || got[0].Server != "gh" || got[1].Action != MCPStart || got[1].Server != "db" { + t.Fatalf("actions %+v", got) + } + tt = mcpTester(mcpServersSample, MCPServerListOptions{}, &got) + tt.Key(0, ui.KeyTab) // filesystem's Stop + tt.Key(0, ui.KeyEnter) + if len(got) != 3 || got[2].Action != MCPStop || got[2].Server != "fs" { + t.Fatalf("keyboard stop: %+v", got) + } +} + +func TestMCPServerListDisabledAndEmpty(t *testing.T) { + var got []MCPServerListResult + tt := mcpTester(mcpServersSample, MCPServerListOptions{Disabled: true}, &got) + _ = tt.Click("Reconnect") + _ = tt.Click("Start") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if len(got) != 0 { + t.Fatalf("disabled list acted: %+v", got) + } + tt = mcpTester(nil, MCPServerListOptions{}, &got) + if !tt.HasText("No MCP servers") { + t.Fatalf("empty: %q", tt.Texts()) + } +} + +func TestMCPServerListManyServersVirtualized(t *testing.T) { + servers := make([]MCPServer, 100000) + for i := range servers { + servers[i] = MCPServer{ID: fmt.Sprint(i), Name: fmt.Sprintf("server-%d", i), State: MCPConnected, Tools: i % 30} + } + var got []MCPServerListResult + tt := mcpTester(servers, MCPServerListOptions{}, &got) + if n := len(tt.Texts()); n > 300 { + t.Fatalf("%d texts built for 100000 servers", n) + } +} + +func TestMCPServerListRejectsDuplicateIDs(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + var got []MCPServerListResult + mcpTester([]MCPServer{{ID: "a", Name: "x"}, {ID: "a", Name: "y"}}, MCPServerListOptions{}, &got) +} + +func TestMCPServerListSnapshot(t *testing.T) { + snapshot(t, "mcp_server_list", 560, 330, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { MCPServerList(c, mcpServersSample, MCPServerListOptions{Still: true}) }) + }) +} diff --git a/memory_panel.go b/memory_panel.go new file mode 100644 index 0000000..fd275f5 --- /dev/null +++ b/memory_panel.go @@ -0,0 +1,159 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// MemoryEntry is one memory; the caller persists it. +type MemoryEntry struct { + ID string + Text string + // Source says where it came from, as "Chat, 3 Oct". + Source string +} + +// MemoryPanelOptions configure a MemoryPanel. +type MemoryPanelOptions struct { + // MaxHeight caps the scrolling list; zero means 360. + MaxHeight float32 + Disabled bool +} + +// MemoryPanelResult reports this frame's in-place edits. +type MemoryPanelResult struct { + Element *ui.Element + // Edited and Deleted are changed IDs, else "". + Edited string + Deleted string +} + +type memoryPanelState struct { + query, editing, draft string + confirm string + // The filter reruns only when query or entries change. + key string + shown []int +} + +// MemoryPanel lists memories with search, inline edit and confirmed delete. +func MemoryPanel(c *ui.Context, entries *[]MemoryEntry, opts MemoryPanelOptions) MemoryPanelResult { + if entries == nil { + panic("mujica: MemoryPanel needs entries") + } + if opts.MaxHeight < 0 { + panic("mujica: MemoryPanel MaxHeight is negative") + } + maxH := opts.MaxHeight + if maxH == 0 { + maxH = 360 + } + u := Density(c).Unit() + var r MemoryPanelResult + r.Element = agentCard(c).Disabled(opts.Disabled).Label(msg(c, "memory_panel.title")) + st := ui.Local(r.Element, "mujica.memory", func() memoryPanelState { return memoryPanelState{} }) + locked := r.Element.IsDisabled() + r.Element.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, msg(c, "memory_panel.title")).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).FontWeight(600).Grow(1) + agentCaption(c, fmt.Sprintf(msg(c, "memory_panel.count"), len(*entries))) + }) + SearchInput(c, &st.query, SearchInputOptions{Placeholder: msg(c, "memory_panel.search"), Disabled: locked}) + memoryFilter(st, *entries) + if len(st.shown) == 0 { + agentCaption(c, msg(c, "memory_panel.empty")) + return + } + agentRows(c, len(st.shown), func(i int) { + idx := st.shown[i] + ui.Column(c).Key((*entries)[idx].ID).Children(func() { memoryRow(c, entries, idx, st, locked, &r) }) + }).Shrink(1).MaxHeight(maxH).Dividers(theme.BorderWidth, Tokens(c).Border) + }) + if r.Deleted != "" { + for i, e := range *entries { + if e.ID == r.Deleted { + *entries = append((*entries)[:i:i], (*entries)[i+1:]...) + break + } + } + st.key = "" // refilter + } + if r.Edited != "" || r.Deleted != "" { + slog.Debug("mujica: memory_panel change", "edited", r.Edited, "deleted", r.Deleted) + } + return r +} + +// memoryFilter recomputes matches when inputs change. +func memoryFilter(st *memoryPanelState, entries []MemoryEntry) { + key := fmt.Sprintf("%s\x00%d", st.query, len(entries)) + if len(entries) > 0 { + key += fmt.Sprintf("\x00%p", &entries[0]) + } + if key == st.key && st.shown != nil { + return + } + st.key = key + q := strings.ToLower(strings.TrimSpace(st.query)) + st.shown = st.shown[:0] + for i, e := range entries { + if q == "" || strings.Contains(strings.ToLower(e.Text), q) || strings.Contains(strings.ToLower(e.Source), q) { + st.shown = append(st.shown, i) + } + } + if st.shown == nil { + st.shown = []int{} + } +} + +// memoryRow shows one entry or its editor. +func memoryRow(c *ui.Context, entries *[]MemoryEntry, idx int, st *memoryPanelState, locked bool, r *MemoryPanelResult) { + e := &(*entries)[idx] + if e.ID == "" { + panic(fmt.Sprintf("mujica: MemoryPanel entry %d needs an ID", idx)) + } + u := Density(c).Unit() + ui.Column(c).Gap(u).Padding(u*2, 0).Children(func() { + if st.editing == e.ID && !locked { + TextArea(c, &st.draft, TextAreaOptions{Label: msg(c, "memory_panel.edit"), MinHeight: 60}).Input.AutoFocus() + ui.Row(c).Gap(u * 2).Justify(ui.End).Children(func() { + if Button(c, msg(c, "memory_panel.cancel"), ButtonOptions{Variant: Secondary}).Clicked() { + st.editing = "" + } + blank := strings.TrimSpace(st.draft) == "" + if Button(c, msg(c, "memory_panel.save"), ButtonOptions{Disabled: blank}).Clicked() && !blank { + e.Text, st.editing, st.key = strings.TrimSpace(st.draft), "", "" + r.Edited = e.ID + } + }) + return + } + ui.Text(c, e.Text).Selectable() + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + agentCaption(c, e.Source).Grow(1) + if agentToggle(c, msg(c, "memory_panel.edit"), "", locked) { + st.editing, st.draft = e.ID, e.Text + } + del := ui.Row(c) + del.Children(func() { + if agentToggle(c, msg(c, "memory_panel.delete"), "trash-2", locked) { + st.confirm = e.ID + } + }) + open := st.confirm == e.ID && !locked + res := Popconfirm(c, del, &open, PopconfirmOptions{Title: msg(c, "memory_panel.confirm"), Description: e.Text, + ConfirmLabel: msg(c, "memory_panel.delete"), Danger: true}) + if st.confirm == e.ID && !open { + st.confirm = "" + } + if res.Confirmed { + r.Deleted = e.ID + } + }) + }) +} diff --git a/memory_panel_test.go b/memory_panel_test.go new file mode 100644 index 0000000..3d2db38 --- /dev/null +++ b/memory_panel_test.go @@ -0,0 +1,96 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +func memorySample() []MemoryEntry { + return []MemoryEntry{ + {ID: "1", Text: "Lady Sakiko prefers the east wing.", Source: "Chat, 3 Oct"}, + {ID: "2", Text: "The quartet needs two days' notice.", Source: "Plan, 1 Oct"}, + {ID: "3", Text: "Claret is served after nine.", Source: "Ledger"}, + } +} + +func memoryTester(entries *[]MemoryEntry, opts MemoryPanelOptions, got *[]MemoryPanelResult) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := MemoryPanel(c, entries, opts) + if r.Edited != "" || r.Deleted != "" { + *got = append(*got, r) + } + }, 560, 560) +} + +func TestMemoryPanelSearchEditDelete(t *testing.T) { + entries := memorySample() + var got []MemoryPanelResult + tt := memoryTester(&entries, MemoryPanelOptions{}, &got) + if !tt.HasText("3 entries") || !tt.HasText("Claret is served after nine.") { + t.Fatalf("texts %q", tt.Texts()) + } + _ = tt.Click("Search memory") + tt.Type("quartet") + if tt.HasText("Claret is served after nine.") || !tt.HasText("The quartet needs two days' notice.") { + t.Fatalf("search: %q", tt.Texts()) + } + _ = tt.Click("Edit") + tt.Key(ui.Cmd, ui.KeyA) + tt.Type("The quartet needs a week's notice.") + _ = tt.Click("Save") + if entries[1].Text != "The quartet needs a week's notice." || len(got) != 1 || got[0].Edited != "2" { + t.Fatalf("edit: %+v %+v", entries[1], got) + } + _ = tt.Click("Delete") + if !tt.HasText("Forget this memory?") || len(entries) != 3 { + t.Fatal("delete did not ask first") + } + _ = tt.Click("Cancel") + if len(entries) != 3 { + t.Fatal("cancel deleted") + } + _ = tt.Click("Delete") + tt.Key(0, ui.KeyTab) // Cancel has the focus; Tab to Delete + tt.Key(0, ui.KeyEnter) + if len(entries) != 2 || got[1].Deleted != "2" || !tt.HasText("No memories match") { + t.Fatalf("delete: %+v %+v %q", entries, got, tt.Texts()) + } +} + +func TestMemoryPanelDisabled(t *testing.T) { + entries := memorySample() + var got []MemoryPanelResult + tt := memoryTester(&entries, MemoryPanelOptions{Disabled: true}, &got) + _ = tt.Click("Edit") + _ = tt.Click("Delete") + if tt.HasText("Save") || tt.HasText("Forget this memory?") || len(got) != 0 { + t.Fatal("disabled panel acted") + } +} + +func TestMemoryPanelManyEntriesVirtualized(t *testing.T) { + entries := make([]MemoryEntry, 100000) + for i := range entries { + entries[i] = MemoryEntry{ID: fmt.Sprint(i), Text: fmt.Sprintf("fact %d", i), Source: "import"} + } + var got []MemoryPanelResult + tt := memoryTester(&entries, MemoryPanelOptions{}, &got) + if n := len(tt.Texts()); n > 300 { + t.Fatalf("%d texts built for 100000 entries", n) + } + _ = tt.Click("Search memory") + tt.Type("fact 99999") + if !tt.HasText("fact 99999") || tt.HasText("fact 0") { + t.Fatal("search over many entries failed") + } +} + +func TestMemoryPanelSnapshot(t *testing.T) { + snapshot(t, "memory_panel", 520, 360, func(c *ui.Context) { + entries := memorySample() + ui.Column(c).Padding(16).Children(func() { MemoryPanel(c, &entries, MemoryPanelOptions{}) }) + }) +} diff --git a/messages_agent.go b/messages_agent.go new file mode 100644 index 0000000..6bd824e --- /dev/null +++ b/messages_agent.go @@ -0,0 +1,127 @@ +package mujica + +func init() { + addMessages(map[string][2]string{ + "agent_status.pending": {"Pending", "待开始"}, + "agent_status.planning": {"Planning", "规划中"}, + "agent_status.running": {"Running", "执行中"}, + "agent_status.waiting": {"Waiting", "等待中"}, + "agent_status.done": {"Done", "已完成"}, + "agent_status.failed": {"Failed", "失败"}, + "agent_status.skipped": {"Skipped", "已跳过"}, + + "tool_call_card.args": {"Arguments", "参数"}, + "tool_call_card.result": {"Result", "结果"}, + "tool_call_card.error": {"Error", "错误"}, + + "tool_call_group.count": {"%d tool calls", "%d 次工具调用"}, + "tool_call_group.failed": {"%d failed", "%d 次失败"}, + + "tool_approval_dialog.title": {"Allow this tool to run?", "允许运行此工具?"}, + "tool_approval_dialog.tool": {"Tool", "工具"}, + "tool_approval_dialog.allow": {"Allow", "允许"}, + "tool_approval_dialog.deny": {"Deny", "拒绝"}, + + "permission_prompt.deny": {"Deny", "拒绝"}, + "permission_prompt.always": {"Always allow", "始终允许"}, + "permission_prompt.once": {"Allow once", "允许一次"}, + "permission_prompt.scope": {"Always allowing covers", "始终允许的范围"}, + + "agent_step_list.current": {"Current", "当前"}, + "agent_step_list.retry": {"Retry", "重试"}, + + "agent_progress.label": {"Progress", "进度"}, + "sub_agent_tree.children": {"%d sub-agents", "%d 个子智能体"}, + + "file_change_card.stats": {"%d added, %d removed lines", "新增 %d 行,删除 %d 行"}, + "file_change_card.pending": {"Pending", "待审阅"}, + "file_change_card.accepted": {"Accepted", "已接受"}, + "file_change_card.rejected": {"Rejected", "已拒绝"}, + "file_change_card.new": {"New file", "新文件"}, + "file_change_card.deleted": {"Deleted", "已删除"}, + "file_change_card.open": {"Open diff", "打开差异"}, + "file_change_card.undo": {"Undo", "撤销"}, + "file_change_card.reject": {"Reject", "拒绝"}, + "file_change_card.accept": {"Accept", "接受"}, + + "multi_file_diff_review.title": {"Review changes", "审阅变更"}, + "multi_file_diff_review.progress": {"%d of %d files reviewed", "已审阅 %d / %d 个文件"}, + "multi_file_diff_review.accept_all": {"Accept all", "全部接受"}, + "multi_file_diff_review.empty": {"No changes to review", "没有需要审阅的变更"}, + + "command_execution_card.abort": {"Abort", "中止"}, + "command_execution_card.exit": {"Exit %d", "退出码 %d"}, + "command_execution_card.output": {"Output", "输出"}, + "command_execution_card.no_output": {"No output", "没有输出"}, + + "screenshot_stream.label": {"Agent screen", "智能体画面"}, + "screenshot_stream.waiting": {"Waiting for frames", "等待画面"}, + "screenshot_stream.prev": {"Previous frame", "上一帧"}, + "screenshot_stream.next": {"Next frame", "下一帧"}, + "screenshot_stream.pause": {"Pause", "暂停"}, + "screenshot_stream.live": {"Go live", "回到实时"}, + "screenshot_stream.counter": {"Frame %d of %d", "第 %d / %d 帧"}, + "screenshot_stream.following": {"Live", "实时"}, + + "artifact_panel.copy": {"Copy", "复制"}, + "artifact_panel.copied": {"Copied", "已复制"}, + "artifact_panel.export": {"Export", "导出"}, + "artifact_panel.preview": {"Preview", "预览"}, + "artifact_panel.source": {"Source", "源码"}, + + "artifact_version_switcher.label": {"Versions", "版本"}, + "artifact_version_switcher.older": {"Older version", "较早版本"}, + "artifact_version_switcher.newer": {"Newer version", "较新版本"}, + "artifact_version_switcher.count": {"%d of %d", "%d / %d"}, + "artifact_version_switcher.compare": {"Compare with %s", "与 %s 比较"}, + + "sandbox_status.starting": {"Starting", "启动中"}, + "sandbox_status.running": {"Running", "运行中"}, + "sandbox_status.stopped": {"Stopped", "已停止"}, + "sandbox_status.failed": {"Failed", "故障"}, + "sandbox_status.high": {"Near the limit", "接近上限"}, + "sandbox_status.left": {"%s left", "剩余 %s"}, + "sandbox_status.expired": {"Time is up", "已到时"}, + + "mcp_server_list.label": {"MCP servers", "MCP 服务器"}, + "mcp_server_list.empty": {"No MCP servers", "没有 MCP 服务器"}, + "mcp_server_list.stopped": {"Stopped", "已停止"}, + "mcp_server_list.connecting": {"Connecting", "连接中"}, + "mcp_server_list.connected": {"Connected", "已连接"}, + "mcp_server_list.error": {"Connection failed", "连接失败"}, + "mcp_server_list.tools": {"%d tools", "%d 个工具"}, + "mcp_server_list.start": {"Start", "启动"}, + "mcp_server_list.stop": {"Stop", "停止"}, + "mcp_server_list.reconnect": {"Reconnect", "重新连接"}, + + "memory_panel.title": {"Memory", "记忆"}, + "memory_panel.count": {"%d entries", "%d 条"}, + "memory_panel.search": {"Search memory", "搜索记忆"}, + "memory_panel.empty": {"No memories match", "没有匹配的记忆"}, + "memory_panel.edit": {"Edit", "编辑"}, + "memory_panel.save": {"Save", "保存"}, + "memory_panel.cancel": {"Cancel", "取消"}, + "memory_panel.delete": {"Delete", "删除"}, + "memory_panel.confirm": {"Forget this memory?", "删除这条记忆?"}, + + "checkpoint_list.label": {"Checkpoints", "检查点"}, + "checkpoint_list.empty": {"No checkpoints yet", "暂无检查点"}, + "checkpoint_list.current": {"Current", "当前"}, + "checkpoint_list.rollback": {"Roll back", "回滚"}, + "checkpoint_list.confirm": {"Roll back to “%s”?", "回滚到“%s”?"}, + "checkpoint_list.warning": {"Changes made after this checkpoint will be discarded.", "此检查点之后的更改将被丢弃。"}, + + "human_input_request.free": {"Or write your own answer", "或填写你的回答"}, + "human_input_request.send": {"Send answer", "发送回答"}, + "human_input_request.left": {"Answer within %s", "请在 %s 内回答"}, + "human_input_request.timeout": {"The agent stopped waiting", "智能体已停止等待"}, + + "agent_plan.title": {"Plan", "计划"}, + "agent_plan.progress": {"%d / %d done", "已完成 %d / %d"}, + "agent_plan.doing": {"In progress", "进行中"}, + "agent_plan.skip": {"Skip", "跳过"}, + "agent_plan.restore": {"Restore", "恢复"}, + "agent_plan.add": {"Add", "添加"}, + "agent_plan.placeholder": {"Add a step", "新增一项"}, + }) +} diff --git a/multi_file_diff_review.go b/multi_file_diff_review.go new file mode 100644 index 0000000..8d1eaf4 --- /dev/null +++ b/multi_file_diff_review.go @@ -0,0 +1,158 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// MultiFileDiffReviewOptions configure a MultiFileDiffReview. +type MultiFileDiffReviewOptions struct { + // Height is 420 DIPs when zero. + Height float32 + Disabled bool +} + +type multiFileDiffState struct{ selected int } + +// MultiFileDiffReview reviews many file changes, one diff at a time. +func MultiFileDiffReview(c *ui.Context, decisions *[]FileDecision, files []FileChange, opts MultiFileDiffReviewOptions) ChoiceResult { + if decisions == nil || len(*decisions) != len(files) { + panic("mujica: MultiFileDiffReview needs one decision per file") + } + if opts.Height < 0 { + panic("mujica: MultiFileDiffReview Height is negative") + } + seen := map[string]bool{} + reviewed := 0 + for i, f := range files { + if f.Path == "" || seen[f.Path] { + panic(fmt.Sprintf("mujica: MultiFileDiffReview file %d needs a unique Path", i)) + } + seen[f.Path] = true + reviewed += agentB2I((*decisions)[i] != FilePending) + } + h := opts.Height + if h == 0 { + h = 420 + } + k := Tokens(c) + u := Density(c).Unit() + var r ChoiceResult + r.Element = agentCard(c).Height(h).Disabled(opts.Disabled).Label(msg(c, "multi_file_diff_review.title")) + st := ui.Local(r.Element, "mujica.mfdr", func() multiFileDiffState { return multiFileDiffState{} }) + st.selected = max(0, min(st.selected, len(files)-1)) + locked := r.Element.IsDisabled() + r.Element.Children(func() { + ui.Row(c).Gap(u * 3).AlignItems(ui.Center).Children(func() { + ui.Text(c, msg(c, "multi_file_diff_review.title")).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).FontWeight(600) + agentCaption(c, fmt.Sprintf(msg(c, "multi_file_diff_review.progress"), reviewed, len(files))).Grow(1) + all := reviewed < len(files) + if Button(c, msg(c, "multi_file_diff_review.accept_all"), ButtonOptions{Variant: Secondary, Disabled: locked || !all}).Clicked() && !locked && all { + for i := range *decisions { + if (*decisions)[i] == FilePending { + (*decisions)[i] = FileAccepted + } + } + r.changed = true + } + }) + frac := 0.0 + if len(files) > 0 { + frac = float64(reviewed) / float64(len(files)) + } + agentBar(c, frac, fmt.Sprintf(msg(c, "multi_file_diff_review.progress"), reviewed, len(files))) + if len(files) == 0 { + agentCaption(c, msg(c, "multi_file_diff_review.empty")) + return + } + ui.Row(c).Grow(1).Shrink(1).Gap(u * 3).AlignItems(ui.Stretch).Children(func() { + row := func(i int) { + if multiFileRow(c, files[i], (*decisions)[i], i == st.selected) && !locked { + st.selected = i + slog.Debug("mujica: multi_file_diff_review select", "path", files[i].Path) + } + } + var list *ui.Element + if len(files) > agentVirtualRows { + list = ui.List(c, nil, len(files), row) + } else { + list = ui.Scroll(c).Children(func() { + for i := range files { + row(i) + } + }) + } + list.Width(240).Shrink(0).FocusGroup(ui.Vertical).Border(theme.BorderWidth, k.Border). + Radius(theme.ControlRadius).Padding(u) + ui.Column(c).Grow(1).Shrink(1).Gap(u * 2).Children(func() { + i := st.selected + if fileChangeDecide(c, &(*decisions)[i], files[i], locked) { + r.changed = true + } + }) + }) + }) + if r.changed { + slog.Debug("mujica: multi_file_diff_review decide", "reviewed", reviewed) + } + return r +} + +// multiFileRow is one listed file; it reports a choice. +func multiFileRow(c *ui.Context, f FileChange, d FileDecision, selected bool) bool { + k := Tokens(c) + u := Density(c).Unit() + row := ui.ButtonBase(c).Key(f.Path).Justify(ui.Start).Gap(u*2).MinHeight(Density(c).ControlHeight()). + Padding(0, u*2).Radius(theme.ControlRadius).Label(f.Path) + internal.Ring(row, k.Focus, theme.ControlRadius) + dc := agentDiffOf(row, f) + switch { + case selected: + row.Background(k.Selection).DrawOver(func(p *ui.Painter, r ui.Rect) { + p.Fill(ui.Rect{X: r.X, Y: r.Y + 4, W: 2, H: r.H - 8}, k.AccentText, 1) + }) + case row.Hovered(): + row.Background(k.SurfaceHover) + } + row.Children(func() { + agentDecisionIcon(c, d) + ui.Text(c, f.Path).Font(theme.MonoFont).FontSize(FontSize(c, theme.CaptionSize+1)).SingleLine().Grow(1).Shrink(1) + agentDiffStats(c, dc.add, dc.del) + }) + return row.Clicked() +} + +// fileChangeDecide shows a full diff and its decision buttons. +func fileChangeDecide(c *ui.Context, d *FileDecision, f FileChange, locked bool) bool { + u := Density(c).Unit() + changed := false + holder := ui.Column(c).Key(f.Path).Grow(1).Shrink(1).Gap(u * 2) + dc := agentDiffOf(holder, f) + holder.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, f.Path).Font(theme.MonoFont).FontWeight(600).SingleLine().Grow(1).Shrink(1) + agentDecisionMark(c, *d) + }) + agentDiffView(c, dc.lines, 1e5).Grow(1).Font(theme.MonoFont) + ui.Row(c).Gap(u * 2).Justify(ui.End).Children(func() { + if *d != FilePending { + if Button(c, msg(c, "file_change_card.undo"), ButtonOptions{Variant: Secondary, Disabled: locked}).Clicked() && !locked { + *d, changed = FilePending, true + } + return + } + if Button(c, msg(c, "file_change_card.reject"), ButtonOptions{Variant: Secondary, Disabled: locked}).Clicked() && !locked { + *d, changed = FileRejected, true + } + if Button(c, msg(c, "file_change_card.accept"), ButtonOptions{Disabled: locked}).Clicked() && !locked { + *d, changed = FileAccepted, true + } + }) + }) + return changed +} diff --git a/multi_file_diff_review_test.go b/multi_file_diff_review_test.go new file mode 100644 index 0000000..a8d5455 --- /dev/null +++ b/multi_file_diff_review_test.go @@ -0,0 +1,118 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +func reviewFiles() []FileChange { + return []FileChange{ + fileChangeSample, + {Path: "court/menu.md", Old: "soup\nroast\n", New: "soup\nroast\ntart\n"}, + {Path: "court/old.md", Old: "gone\n"}, + } +} + +func reviewTester(d *[]FileDecision, files []FileChange, opts MultiFileDiffReviewOptions, changes *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(8).Children(func() { + if MultiFileDiffReview(c, d, files, opts).Changed() { + *changes++ + } + }) + }, 760, 520) +} + +func TestMultiFileDiffReviewPerFileAndAll(t *testing.T) { + files := reviewFiles() + d := make([]FileDecision, len(files)) + changes := 0 + tt := reviewTester(&d, files, MultiFileDiffReviewOptions{}, &changes) + if !tt.HasText("0 of 3 files reviewed") || !tt.HasText("Guests: 42") { + t.Fatalf("texts %q", tt.Texts()) + } + _ = tt.Click("court/menu.md") + if !tt.HasText("tart") || tt.HasText("Guests: 42") { + t.Fatal("choosing a file did not show its diff") + } + _ = tt.Click("Reject") + if d[1] != FileRejected || changes != 1 || !tt.HasText("1 of 3 files reviewed") { + t.Fatalf("reject: %v", d) + } + _ = tt.Click("Accept all") + if d[0] != FileAccepted || d[1] != FileRejected || d[2] != FileAccepted || !tt.HasText("3 of 3 files reviewed") { + t.Fatalf("accept all: %v", d) + } +} + +func TestMultiFileDiffReviewKeyboard(t *testing.T) { + files := reviewFiles() + d := make([]FileDecision, len(files)) + n := 0 + tt := reviewTester(&d, files, MultiFileDiffReviewOptions{}, &n) + _ = tt.Click("court/ledger.md") + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if !tt.HasText("gone") || tt.HasText("Guests: 42") { + t.Fatalf("keyboard choice: %q", tt.Texts()) + } +} + +func TestMultiFileDiffReviewDisabledAndEmpty(t *testing.T) { + files := reviewFiles() + d := make([]FileDecision, len(files)) + n := 0 + tt := reviewTester(&d, files, MultiFileDiffReviewOptions{Disabled: true}, &n) + _ = tt.Click("Accept all") + _ = tt.Click("Accept") + _ = tt.Click("court/menu.md") + if n != 0 || d[0] != FilePending || tt.HasText("tart") { + t.Fatalf("disabled review acted: %v", d) + } + var none []FileDecision + tt = reviewTester(&none, nil, MultiFileDiffReviewOptions{}, &n) + if !tt.HasText("No changes to review") { + t.Fatalf("empty: %q", tt.Texts()) + } +} + +func TestMultiFileDiffReviewManyFilesVirtualized(t *testing.T) { + files := make([]FileChange, 100000) + for i := range files { + files[i] = FileChange{Path: fmt.Sprintf("f%06d.txt", i), Old: "a\n", New: "b\n"} + } + d := make([]FileDecision, len(files)) + n := 0 + tt := reviewTester(&d, files, MultiFileDiffReviewOptions{}, &n) + if got := len(tt.Texts()); got > 400 { + t.Fatalf("%d texts built for 100000 files", got) + } + if !tt.HasText("f000000.txt") { + t.Fatal("first file missing") + } +} + +func TestMultiFileDiffReviewNeedsMatchingDecisions(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + d := []FileDecision{} + n := 0 + reviewTester(&d, reviewFiles(), MultiFileDiffReviewOptions{}, &n) +} + +func TestMultiFileDiffReviewSnapshot(t *testing.T) { + snapshot(t, "multi_file_diff_review", 760, 420, func(c *ui.Context) { + files := reviewFiles() + d := []FileDecision{FilePending, FileAccepted, FileRejected} + ui.Column(c).Padding(12).Children(func() { + MultiFileDiffReview(c, &d, files, MultiFileDiffReviewOptions{Height: 390}) + }) + }) +} diff --git a/permission_prompt.go b/permission_prompt.go new file mode 100644 index 0000000..ac13a5c --- /dev/null +++ b/permission_prompt.go @@ -0,0 +1,76 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// PermissionChoice answers a PermissionPrompt; zero is no answer. +type PermissionChoice int + +const ( + PermissionNone PermissionChoice = iota + PermissionAllowOnce + PermissionAllowAlways + PermissionDeny +) + +// PermissionPromptOptions configure a PermissionPrompt. Title and Scope are required. +type PermissionPromptOptions struct { + Title string + Description string + // Scope says what "always" covers, as "Write access to ~/court". + Scope string +} + +// PermissionResult reports the choice made in this frame. +type PermissionResult struct { + Element *ui.Element + Choice PermissionChoice +} + +// PermissionPrompt asks allow once, always, or deny; Deny has focus. +func PermissionPrompt(c *ui.Context, open *bool, opts PermissionPromptOptions) PermissionResult { + if opts.Title == "" || opts.Scope == "" { + panic("mujica: PermissionPrompt needs a Title and a Scope") + } + var r PermissionResult + was := *open + k := Tokens(c) + u := Density(c).Unit() + r.Element = Dialog(c, open, DialogOptions{ + Title: opts.Title, Description: opts.Description, KeepOnBackdrop: true, HideClose: true, + Actions: func() { + if Button(c, msg(c, "permission_prompt.deny"), ButtonOptions{Variant: Secondary}).AutoFocus().Clicked() { + r.Choice = PermissionDeny + } + if Button(c, msg(c, "permission_prompt.always"), ButtonOptions{Variant: Outline}).Clicked() { + r.Choice = PermissionAllowAlways + } + if Button(c, msg(c, "permission_prompt.once"), ButtonOptions{}).Clicked() { + r.Choice = PermissionAllowOnce + } + }, + }, func() { + ui.Row(c).Gap(u*2).AlignItems(ui.Start).Padding(u*2, u*3).Background(k.Background).Radius(theme.ControlRadius). + Border(1, k.Border).Children(func() { + ui.Icon(c, icons.Must("lock")).Size(16, 16).TextColor(k.Info).Shrink(0).Margin(2, 0, 0, 0) + ui.Column(c).Gap(u / 2).Shrink(1).Children(func() { + agentCaption(c, msg(c, "permission_prompt.scope")) + ui.Text(c, opts.Scope) + }) + }) + }) + if was && !*open && r.Choice == PermissionNone { + r.Choice = PermissionDeny // Escape + } + if r.Choice != PermissionNone { + slog.Debug("mujica: permission_prompt choose", "choice", int(r.Choice)) + *open = false + } + return r +} diff --git a/permission_prompt_test.go b/permission_prompt_test.go new file mode 100644 index 0000000..bba25c7 --- /dev/null +++ b/permission_prompt_test.go @@ -0,0 +1,78 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func permissionTester(open *bool, got *[]PermissionChoice) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if Button(c, "Ask", ButtonOptions{}).Clicked() { + *open = true + } + r := PermissionPrompt(c, open, PermissionPromptOptions{Title: "Write to the ledger?", Scope: "Write access to ~/court/ledger"}) + if r.Choice != PermissionNone { + *got = append(*got, r.Choice) + } + }, 600, 400) +} + +func TestPermissionPromptChoices(t *testing.T) { + for _, tc := range []struct { + tabs int + want PermissionChoice + }{{0, PermissionDeny}, {1, PermissionAllowAlways}, {2, PermissionAllowOnce}} { + open := false + var got []PermissionChoice + tt := permissionTester(&open, &got) + _ = tt.Click("Ask") + if !tt.Focused("Deny") || !tt.HasText("Write access to ~/court/ledger") { + t.Fatalf("Deny focused %v, texts %q", tt.Focused("Deny"), tt.Texts()) + } + for range tc.tabs { + tt.Key(0, ui.KeyTab) + } + tt.Key(0, ui.KeyEnter) + if len(got) != 1 || got[0] != tc.want || open { + t.Fatalf("tabs %d: got %v open %v", tc.tabs, got, open) + } + } +} + +func TestPermissionPromptEscapeAndBackdrop(t *testing.T) { + open := false + var got []PermissionChoice + tt := permissionTester(&open, &got) + _ = tt.Click("Ask") + tt.ClickAt(5, 395) + if !open || len(got) != 0 { + t.Fatal("backdrop acted") + } + tt.Key(0, ui.KeyEscape) + if len(got) != 1 || got[0] != PermissionDeny { + t.Fatalf("Escape gave %v", got) + } +} + +func TestPermissionPromptNeedsScope(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + open := true + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + PermissionPrompt(c, &open, PermissionPromptOptions{Title: "x"}) + }, 200, 200) +} + +func TestPermissionPromptSnapshot(t *testing.T) { + snapshot(t, "permission_prompt", 600, 340, func(c *ui.Context) { + open := true + PermissionPrompt(c, &open, PermissionPromptOptions{Title: "Write to the ledger?", + Description: "The agent wants to record tonight's guests.", Scope: "Write access to ~/court/ledger and its subfolders"}) + }) +} diff --git a/sandbox_status.go b/sandbox_status.go new file mode 100644 index 0000000..e9390bd --- /dev/null +++ b/sandbox_status.go @@ -0,0 +1,107 @@ +package mujica + +import ( + "fmt" + "math" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// SandboxState is a sandbox's lifecycle. The zero value is SandboxStarting. +type SandboxState int + +const ( + SandboxStarting SandboxState = iota + SandboxRunning + SandboxStopped + SandboxFailed +) + +// SandboxResource is one metered resource, as CPU or memory. +type SandboxResource struct { + Name string + Used, Limit float64 + // Unit follows the numbers, as "GB" or "cores". + Unit string +} + +// SandboxInfo is the sandbox the caller reports. +type SandboxInfo struct { + Name string + State SandboxState + Resources []SandboxResource + // Expires is the shutdown time; zero means none. + Expires time.Time +} + +// SandboxStatusOptions configure a SandboxStatus. +type SandboxStatusOptions struct { + Still bool +} + +// SandboxStatus shows sandbox state, resources and time left. +func SandboxStatus(c *ui.Context, info SandboxInfo, opts SandboxStatusOptions) *ui.Element { + agent := map[SandboxState]AgentState{SandboxStarting: AgentPlanning, SandboxRunning: AgentRunning, SandboxStopped: AgentSkipped, SandboxFailed: AgentFailed} + state, ok := agent[info.State] + if !ok { + panic(fmt.Sprintf("mujica: unknown SandboxState %d", int(info.State))) + } + for _, r := range info.Resources { + if r.Name == "" || !(r.Limit > 0) || r.Used < 0 || math.IsNaN(r.Used) || r.Used > r.Limit { + panic(fmt.Sprintf("mujica: SandboxStatus resource %q needs a name and 0 <= Used <= Limit", r.Name)) + } + } + k := Tokens(c) + u := Density(c).Unit() + word := msg(c, "sandbox_status."+[...]string{"starting", "running", "stopped", "failed"}[info.State]) + card := agentCard(c).Label(info.Name + ", " + word) + card.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, info.Name).FontWeight(600).SingleLine().Grow(1).Shrink(1) + AgentStatus(c, state, AgentStatusOptions{Label: word, Still: opts.Still}) + }) + for _, r := range info.Resources { + frac := r.Used / r.Limit + ui.Column(c).Gap(u).Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + agentCaption(c, r.Name).Grow(1) + if frac >= 0.9 { + ui.Icon(c, icons.Must("triangle-alert")).Size(12, 12).TextColor(k.Warning).Label(msg(c, "sandbox_status.high")) + } + ui.Text(c, fmt.Sprintf("%s / %s %s", sandboxNum(r.Used), sandboxNum(r.Limit), r.Unit)). + FontSize(FontSize(c, theme.CaptionSize)).FontFeatures("tnum").TextColor(k.Text) + }) + agentBar(c, frac, fmt.Sprintf("%s %.0f%%", r.Name, frac*100)) + }) + } + if !info.Expires.IsZero() && info.State != SandboxStopped && info.State != SandboxFailed { + left := info.Expires.Sub(c.Now()) + text := msg(c, "sandbox_status.expired") + if left > 0 { + text = fmt.Sprintf(msg(c, "sandbox_status.left"), agentDuration(left.Truncate(time.Second))) + wait := left % time.Second + if wait == 0 { + wait = time.Second + } + c.After(wait) + } + ui.Row(c).Gap(u * 1.5).AlignItems(ui.Center).Role(ui.RoleStatus).Label(text).Children(func() { + ui.Icon(c, icons.Must("clock")).Size(14, 14).TextColor(k.TextMuted) + agentCaption(c, text) + }) + } + }) + return card +} + +// sandboxNum prints a resource amount with at most one decimal. +func sandboxNum(v float64) string { + if v == math.Trunc(v) { + return fmt.Sprintf("%.0f", v) + } + return fmt.Sprintf("%.1f", v) +} diff --git a/sandbox_status_test.go b/sandbox_status_test.go new file mode 100644 index 0000000..2a8815b --- /dev/null +++ b/sandbox_status_test.go @@ -0,0 +1,68 @@ +package mujica + +import ( + "strings" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func sandboxSample(expires time.Time) SandboxInfo { + return SandboxInfo{Name: "sandbox-7", State: SandboxRunning, Expires: expires, Resources: []SandboxResource{ + {Name: "CPU", Used: 1.5, Limit: 2, Unit: "cores"}, + {Name: "Memory", Used: 3.8, Limit: 4, Unit: "GB"}, + }} +} + +func TestSandboxStatusResourcesAndCountdown(t *testing.T) { + info := sandboxSample(time.Now().Add(90 * time.Second)) + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + SandboxStatus(c, info, SandboxStatusOptions{Still: true}) + }, 480, 300) + for _, s := range []string{"sandbox-7", "Running", "1.5 / 2 cores", "3.8 / 4 GB", "Near the limit"} { + if !tt.HasText(s) { + t.Fatalf("missing %q in %q", s, tt.Texts()) + } + } + left := "" + for _, s := range tt.Texts() { + if strings.HasSuffix(s, " left") { + left = s + } + } + if !strings.HasPrefix(left, "1 m ") { + t.Fatalf("countdown %q", left) + } + info.Expires = time.Now().Add(-time.Second) + tt.Frame() + if !tt.HasText("Time is up") { + t.Fatalf("expired: %q", tt.Texts()) + } + info.State = SandboxStopped + tt.Frame() + if !tt.HasText("Stopped") || tt.HasText("Time is up") { + t.Fatalf("stopped: %q", tt.Texts()) + } +} + +func TestSandboxStatusRejectsBadResource(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + SandboxStatus(c, SandboxInfo{Name: "x", Resources: []SandboxResource{{Name: "CPU", Used: 3, Limit: 2}}}, SandboxStatusOptions{}) + }, 200, 200) +} + +func TestSandboxStatusSnapshot(t *testing.T) { + snapshot(t, "sandbox_status", 440, 230, func(c *ui.Context) { + info := sandboxSample(time.Time{}) + info.Resources = append(info.Resources, SandboxResource{Name: "Disk", Used: 12, Limit: 40, Unit: "GB"}) + ui.Column(c).Padding(16).Children(func() { SandboxStatus(c, info, SandboxStatusOptions{Still: true}) }) + }) +} diff --git a/screenshot_stream.go b/screenshot_stream.go new file mode 100644 index 0000000..86df6d9 --- /dev/null +++ b/screenshot_stream.go @@ -0,0 +1,125 @@ +package mujica + +import ( + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// ScreenshotFrame is one caller-supplied frame of the agent's screen. +type ScreenshotFrame struct { + Image ui.ImageSource + Caption string + // At is the time since the run started. + At time.Duration +} + +// ScreenshotStreamState is the shown frame; unpaused, it follows the newest. +type ScreenshotStreamState struct { + Index int + Paused bool +} + +// ScreenshotStreamOptions configure a ScreenshotStream. +type ScreenshotStreamOptions struct { + // Height of the viewport; 280 DIPs when zero. + Height float32 + Disabled bool +} + +// ScreenshotStream shows screen frames live, paused or stepped. +func ScreenshotStream(c *ui.Context, st *ScreenshotStreamState, frames []ScreenshotFrame, opts ScreenshotStreamOptions) ChoiceResult { + if st == nil { + panic("mujica: ScreenshotStream needs a state") + } + if opts.Height < 0 { + panic("mujica: ScreenshotStream Height is negative") + } + for i, f := range frames { + if f.Image == nil { + panic(fmt.Sprintf("mujica: ScreenshotStream frame %d has no Image", i)) + } + } + h := opts.Height + if h == 0 { + h = 280 + } + k := Tokens(c) + u := Density(c).Unit() + n := len(frames) + if st.Index < 0 { + panic(fmt.Sprintf("mujica: ScreenshotStream Index %d is negative", st.Index)) + } + if !st.Paused || st.Index >= n { // frames may be dropped while paused + + st.Index = max(0, n-1) + } + var r ChoiceResult + r.Element = agentCard(c).Disabled(opts.Disabled).Label(msg(c, "screenshot_stream.label")) + locked := r.Element.IsDisabled() + step := func(d int) { + if n == 0 || locked { + return + } + st.Index = max(0, min(n-1, st.Index+d)) + st.Paused, r.changed = true, true + } + r.Element.Children(func() { + view := ui.Box(c).FillWidth().Height(h).Center().Clip().Radius(theme.ControlRadius). + Background(k.Background).Border(theme.BorderWidth, k.Border).Focusable(). + Label(msg(c, "screenshot_stream.label")) + internal.Ring(view, k.Focus, theme.ControlRadius) + view.Children(func() { + if n == 0 { + agentCaption(c, msg(c, "screenshot_stream.waiting")) + return + } + ui.Image(c, frames[st.Index].Image).Fill().Fit(ui.Contain).Label(frames[st.Index].Caption) + }) + if !locked { + switch { + case view.Shortcut(0, ui.KeyLeft): + step(-1) + case view.Shortcut(0, ui.KeyRight): + step(1) + case view.Shortcut(0, ui.KeySpace): + st.Paused, r.changed = !st.Paused, true + } + } + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + if iconAction(c, icons.Must("chevron-left"), msg(c, "screenshot_stream.prev")).Disabled(locked || st.Index == 0).Clicked() { + step(-1) + } + pause := msg(c, "screenshot_stream.pause") + if st.Paused { + pause = msg(c, "screenshot_stream.live") + } + if Button(c, pause, ButtonOptions{Variant: Secondary, Disabled: locked || n == 0}).Clicked() && !locked { + st.Paused, r.changed = !st.Paused, true + } + if iconAction(c, icons.Must("chevron-right"), msg(c, "screenshot_stream.next")).Disabled(locked || st.Index >= n-1).Clicked() { + step(1) + } + counter := fmt.Sprintf(msg(c, "screenshot_stream.counter"), min(st.Index+1, n), n) + agentCaption(c, counter).Role(ui.RoleStatus) + if n > 0 { + f := frames[st.Index] + ui.Text(c, f.Caption).SingleLine().Grow(1).Shrink(1) + agentCaption(c, agentDuration(f.At)) + } + if !st.Paused && n > 0 { + AgentStatus(c, AgentRunning, AgentStatusOptions{Label: msg(c, "screenshot_stream.following"), Still: true}) + } + }) + }) + if r.changed { + slog.Debug("mujica: screenshot_stream move", "index", st.Index, "paused", st.Paused) + } + return r +} diff --git a/screenshot_stream_test.go b/screenshot_stream_test.go new file mode 100644 index 0000000..bd52c20 --- /dev/null +++ b/screenshot_stream_test.go @@ -0,0 +1,110 @@ +package mujica + +import ( + "fmt" + "image" + "image/color" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +// screenshotFrames makes n solid frames of shifting colors. +func screenshotFrames(n int) []ScreenshotFrame { + out := make([]ScreenshotFrame, n) + for i := range out { + img := image.NewRGBA(image.Rect(0, 0, 160, 90)) + for p := 0; p < len(img.Pix); p += 4 { + img.Pix[p], img.Pix[p+1], img.Pix[p+2], img.Pix[p+3] = uint8(60+i*40), 90, uint8(160-i*20), 255 + } + img.Set(10, 10, color.White) + out[i] = ScreenshotFrame{Image: ui.NewBitmap(img), Caption: fmt.Sprintf("Step %d", i+1), At: time.Duration(i) * time.Second} + } + return out +} + +func screenshotTester(st *ScreenshotStreamState, frames *[]ScreenshotFrame, opts ScreenshotStreamOptions, changes *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if ScreenshotStream(c, st, *frames, opts).Changed() { + *changes++ + } + }, 600, 420) +} + +func TestScreenshotStreamFollowsPausesAndSteps(t *testing.T) { + var st ScreenshotStreamState + frames := screenshotFrames(3) + changes := 0 + tt := screenshotTester(&st, &frames, ScreenshotStreamOptions{}, &changes) + if st.Index != 2 || !tt.HasText("Frame 3 of 3") || !tt.HasText("Live") { + t.Fatalf("live: %+v %q", st, tt.Texts()) + } + frames = append(frames, screenshotFrames(4)[3]) + tt.Frame() + if st.Index != 3 || !tt.HasText("Step 4") { + t.Fatalf("new frame not followed: %+v", st) + } + _ = tt.Click("Previous frame") + if !st.Paused || st.Index != 2 || changes != 1 || !tt.HasText("Step 3") { + t.Fatalf("step back: %+v", st) + } + frames = append(frames, screenshotFrames(5)[4]) + tt.Frame() + if st.Index != 2 { + t.Fatal("paused viewer moved") + } + _ = tt.Click("Go live") + if st.Paused || st.Index != 4 { + t.Fatalf("go live: %+v", st) + } +} + +func TestScreenshotStreamKeyboard(t *testing.T) { + var st ScreenshotStreamState + frames := screenshotFrames(3) + n := 0 + tt := screenshotTester(&st, &frames, ScreenshotStreamOptions{}, &n) + tt.Key(0, ui.KeyTab) // the viewport + tt.Key(0, ui.KeyLeft) + tt.Key(0, ui.KeyLeft) + tt.Key(0, ui.KeyLeft) // stops at the first + if st.Index != 0 || !st.Paused { + t.Fatalf("left: %+v", st) + } + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeySpace) + if st.Paused || st.Index != 2 { + t.Fatalf("space: %+v", st) + } +} + +func TestScreenshotStreamEmptyAndDisabled(t *testing.T) { + var st ScreenshotStreamState + var frames []ScreenshotFrame + n := 0 + tt := screenshotTester(&st, &frames, ScreenshotStreamOptions{}, &n) + if !tt.HasText("Waiting for frames") || !tt.HasText("Frame 0 of 0") { + t.Fatalf("empty: %q", tt.Texts()) + } + frames = screenshotFrames(3) + st = ScreenshotStreamState{} + tt = screenshotTester(&st, &frames, ScreenshotStreamOptions{Disabled: true}, &n) + _ = tt.Click("Previous frame") + _ = tt.Click("Pause") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyLeft) + if n != 0 || st.Paused || st.Index != 2 { + t.Fatalf("disabled moved: %+v", st) + } +} + +func TestScreenshotStreamSnapshot(t *testing.T) { + snapshot(t, "screenshot_stream", 520, 330, func(c *ui.Context) { + st := ScreenshotStreamState{Index: 1, Paused: true} + ui.Column(c).Padding(16).Children(func() { + ScreenshotStream(c, &st, screenshotFrames(3), ScreenshotStreamOptions{Height: 200}) + }) + }) +} diff --git a/sub_agent_tree.go b/sub_agent_tree.go new file mode 100644 index 0000000..c142006 --- /dev/null +++ b/sub_agent_tree.go @@ -0,0 +1,104 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// SubAgent is one agent in a hierarchy. +type SubAgent struct { + ID string + Name string + Task string + State AgentState + Children []SubAgent +} + +// SubAgentTreeOptions configure a SubAgentTree. +type SubAgentTreeOptions struct { + Disabled bool + Still bool +} + +// SubAgentTree shows nested agents and their states. +func SubAgentTree(c *ui.Context, roots []SubAgent, opts SubAgentTreeOptions) ChoiceResult { + seen := map[string]bool{} + var check func([]SubAgent) + check = func(list []SubAgent) { + for _, a := range list { + if a.ID == "" || a.Name == "" || seen[a.ID] { + panic(fmt.Sprintf("mujica: SubAgentTree agent %q needs a unique ID and a Name", a.ID)) + } + seen[a.ID] = true + check(a.Children) + } + } + check(roots) + var r ChoiceResult + r.Element = ui.Column(c).Shrink(0).FocusGroup(ui.Vertical).Disabled(opts.Disabled) + open := ui.Local(r.Element, "mujica.subagents.open", func() map[string]bool { return map[string]bool{} }) + r.Element.Children(func() { + var rows func([]SubAgent, int) + rows = func(list []SubAgent, depth int) { + for _, a := range list { + if subAgentRow(c, a, depth, (*open)[a.ID], opts.Still) { + (*open)[a.ID] = !(*open)[a.ID] + r.changed = true + slog.Debug("mujica: sub_agent_tree toggle", "id", a.ID, "open", (*open)[a.ID]) + } + if (*open)[a.ID] { + rows(a.Children, depth+1) + } + } + } + rows(roots, 0) + }) + for id := range *open { + if !seen[id] { + delete(*open, id) + } + } + return r +} + +// subAgentRow builds one row, reporting an expand or collapse. +func subAgentRow(c *ui.Context, a SubAgent, depth int, open, still bool) bool { + k := Tokens(c) + d := Density(c) + u := d.Unit() + parent := len(a.Children) > 0 + row := ui.ButtonBase(c).Key(a.ID).Justify(ui.Start).Gap(u*2).MinHeight(d.ControlHeight()). + Padding(0, u*2, 0, u*2+float32(depth)*u*5).Radius(theme.ControlRadius). + Label(a.Name + ", " + agentWord(c, a.State)) + internal.Ring(row, k.Focus, theme.ControlRadius) + if row.Hovered() { + row.Background(k.SurfaceHover) + } + row.Children(func() { + chev := ui.Box(c).Size(14, 14).Shrink(0) + if parent { + name := "chevron-right" + if open { + name = "chevron-down" + } + chev.Children(func() { ui.Icon(c, icons.Must(name)).Size(14, 14).TextColor(k.TextMuted) }) + } + agentMark(c, a.State, 16, still) + ui.Text(c, a.Name).FontWeight(600).SingleLine().Shrink(0) + ui.Text(c, a.Task).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize+1)).SingleLine().Grow(1).Shrink(1) + agentCaption(c, agentWord(c, a.State)) + if parent { + agentCaption(c, fmt.Sprintf(msg(c, "sub_agent_tree.children"), len(a.Children))) + } + }) + if !parent || row.IsDisabled() { + return false + } + return row.Clicked() || !open && row.Shortcut(0, ui.KeyRight) || open && row.Shortcut(0, ui.KeyLeft) +} diff --git a/sub_agent_tree_test.go b/sub_agent_tree_test.go new file mode 100644 index 0000000..8961923 --- /dev/null +++ b/sub_agent_tree_test.go @@ -0,0 +1,81 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +var subAgentSample = []SubAgent{ + {ID: "lead", Name: "Steward", Task: "Prepare the ball", State: AgentRunning, Children: []SubAgent{ + {ID: "music", Name: "Musician", Task: "Hire the quartet", State: AgentDone}, + {ID: "kitchen", Name: "Cook", Task: "Plan the menu", State: AgentWaiting, Children: []SubAgent{ + {ID: "wine", Name: "Sommelier", Task: "Choose the wine", State: AgentFailed}, + }}, + }}, +} + +func subAgentTester(opts SubAgentTreeOptions, changes *int) *ui.Tester { + opts.Still = true + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if SubAgentTree(c, subAgentSample, opts).Changed() { + *changes++ + } + }, 560, 300) +} + +func TestSubAgentTreeExpandByPointerAndKeys(t *testing.T) { + changes := 0 + tt := subAgentTester(SubAgentTreeOptions{}, &changes) + if tt.HasText("Musician") || !tt.HasText("Running") { + t.Fatalf("texts %q", tt.Texts()) + } + _ = tt.Click("Steward") + if changes != 1 || !tt.HasText("Musician") || !tt.HasText("Waiting") || tt.HasText("Sommelier") { + t.Fatalf("click: changes %d texts %q", changes, tt.Texts()) + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDown) // Cook + tt.Key(0, ui.KeyRight) + if !tt.HasText("Sommelier") || !tt.HasText("Failed") { + t.Fatal("Right did not expand Cook") + } + tt.Key(0, ui.KeyRight) // already open: nothing + tt.Key(0, ui.KeyLeft) + if tt.HasText("Sommelier") || changes != 3 { + t.Fatalf("Left: changes %d", changes) + } +} + +func TestSubAgentTreeDisabled(t *testing.T) { + changes := 0 + tt := subAgentTester(SubAgentTreeOptions{Disabled: true}, &changes) + _ = tt.Click("Steward") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + if changes != 0 || tt.HasText("Musician") { + t.Fatal("disabled tree expanded") + } +} + +func TestSubAgentTreeRejectsDuplicateIDs(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + SubAgentTree(c, []SubAgent{{ID: "a", Name: "x", Children: []SubAgent{{ID: "a", Name: "y"}}}}, SubAgentTreeOptions{}) + }, 200, 200) +} + +func TestSubAgentTreeSnapshot(t *testing.T) { + snapshotAfter(t, "sub_agent_tree", 540, 200, func(c *ui.Context) { + ui.Column(c).Padding(12).Children(func() { SubAgentTree(c, subAgentSample, SubAgentTreeOptions{Still: true}) }) + }, func(tt *ui.Tester) { + _ = tt.Click("Steward") + _ = tt.Click("Cook") + }) +} diff --git a/testdata/snapshots/darwin/agent_plan-dark.png b/testdata/snapshots/darwin/agent_plan-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..726c0f655bf2ef98aa82850f6dd9f2f6ab48ddd9 GIT binary patch literal 22491 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/agent_status-dark.png b/testdata/snapshots/darwin/agent_status-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..aac7f1ca350c0ff6d2738bb9f0ea626b561e3c3b GIT binary patch literal 8602 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/agent_status-light.png b/testdata/snapshots/darwin/agent_status-light.png new file mode 100644 index 0000000000000000000000000000000000000000..753bb619bd66f9cddbe99b6393d862b329054e27 GIT binary patch literal 8321 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/agent_step_list-dark.png b/testdata/snapshots/darwin/agent_step_list-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..6c0fbe6b5fcf5bf7e27b154753436a9d6e256371 GIT binary patch literal 21118 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/agent_step_list-light.png b/testdata/snapshots/darwin/agent_step_list-light.png new file mode 100644 index 0000000000000000000000000000000000000000..e4f70fa3ef3a295f6b88d2ae4c72523f2a91277f GIT binary patch literal 20677 zcmd?QWprG<(lzMViJ93kGc&W@W@ct)h?$u&=9pt31 zO{>@GbtIiWQmLfc+Et2Fl$St&{SFHT28JLdDXI(x1`Z7d_C*yM9F#N3qe2b_rWhk7 zDy-^}b(ZC>tD>>lqW}#96BvTx_A7`;=OvU7J?^&M23j?(hp_~#{B>L+mB@Iy;>yy6b6DzDQ{YUq(rPdal#*_ z|A^;fsJ{mbRt3%(&55-<<9jVO%fiC@)UsVza6NcnzyL_90sfF&>SLs5x4FgD`^O8n zloc7@Cvd_Liw}z1;6oJ6Oni;ZJUxA5Yn$wc6Ty5D=+7MgBmTFF0ma1|HX;|!NJ-tp zeb(hsM7YNUHSG>YhA2wpEZxp8YhdJtaH-+Xpjz z$4$g6R!3T;t)0yf%NHg?$ zTwE|{ew?Ct9^|8nO>Y9B;3QSNd0C0CGxENeoTwfTEY8h^ONhdR{2fW6Fb?m~=^rGo z)jU%W)FPvN%({fq_Z04ZpPAYGj+=ROVy!9g608oS27B8)-i08)Yv$c>WOJr6z!SrBMB%&q?86`+2A0&5L!c$|P4;6qzh=KP)lF-g|%W5n+Ji%mvjmWLO1^Z->4Zn`& zEze;O%AwdZH%uq(DaobNCfGVXI8oKVJ{qgxz}jFObQ1qnqM!pn%56zZ4*Ry@NER_hTCvYEb!3 z;-SM7J|HFIhx=&*9|LbYxRS-?mET&16WxhR8pc3SQ(iXx+G(Y^g`@k$-?x9dZl(NO z23(O5q^MXIx|ciG;?_tuJuC*~AO#G!MrQk*Lht zUqCM#+L&+4IAB;lQ%cRe4#nUO~=O62k%zl%Iu=55|tsRXG%8(H|p zP4!XU!okLeoP#>hrKuqGawFmfhVzq%O=LP9+UeQo~TYHoAt1hdB#o zRLE-#oe%_FR9{SE7VPisC6|qQy?Cwb&2Z;SV8job)AfYxs7G_BIRuag z{Wa(*cgLUhJ+@THC3}Zw*_TEAF1}~mG3S;K1wa{>qe;;4h7gOZZ_!WWtuNdJC3Uhi zu4Cb#k8c@DAN@|Dwen#8fKNfoQa3!Z?RA(O0iAbF{5qKxOH54_gKOb@s(w%o>^5TI z?Ki$2?QzAyXF%zu z-ZaXzE;14&ea)ir=_whiTR>Gst*o+grNitoskj6>Pp7$_!|tQ{_I{5FW2&UuO4y_P8eSp zuN)MIyUy!izP7H$^sz|f%r)qcCI0OT$GC=BL#~L89~!-`)K%EY$;ry9nM_$?6n_beWp%c_y6eYfjzeUBnu5#1++3$7FuDpdz#S?dJOPl` z(A)&~1TGLS___P+!Ixvy0U{|L)JT-sHmu!GBOT{g!~BnAS!g&X!7%s zTHfX4jb%71gYri(j%a>M(VM_SD4KE_L^OPD9c{gm7LpLUO1c%DBE&7HR>>eTQ-R^_}c3*Z$uH6z4zHITpN^q+HuvPGmWnUzLkpE*xGH1BBH}Z7VMsSxBsgCf_?h zN%#o5orfSLhHBj}%t=F5R?>wHzCK>!QPI=p3Ob}_R?Obt@ve5Q&n}Nx+b6_nx3zX` z(pDe?F6px=??;RWfj^9ty*>B%J)Zx=c2~v@ksesF~E)9*+1j+9fFF`Q7L!E~gEc1P? zipv_p1_lnICxKs&tH=rBhqfKr8rZDMt>=!cJ^1uF8Uc%ioPu_#k%7ek5ol_alxvR; zAtFmF>uopZ=5G#tCqLaj!_go>wvGp%eaL3gqvV<-f$GFXRaZ7^6IPHWR{Oo>J1=al zmMsPbMhLQ8%Ak?+%V-@J7harrfsw>Lc{=yr^$nRVL$(kR^wUh>09mutedB%j1A(%V z+K(Tu30AvmKPAbeuBFJu$PK>v-$NyOuNwdUDLJ^(7McRQ@D;8XoGC2Bv9y+BBjh93 z)6}xBtl|w~9Dx?ZkS0S75-oPS){ZNHELltb z+>i&EF+9ZZz5`XhN=X^1Om_FwtgNh@z?=Za;f|zZzLD0#(!$oV<>7v4+G{*`UvYPL zcYE~m#qqaYHPNC}Hkk1lhduCCU}#R-0ukU|)BS7}hCL}9?%i~Q{DJRc~EwTHRo z*iwsVA}1>ciO)n9HW+r=Tz%Oc_!i%dD)J%?59AhTbVcCSqDGIp)9~hDc~Lz2!K+hI zZxQF_QpaJx=2`RS7w}MpDr)R4?aB9m9yQYKY%Mn{kpVRl4}VCyKk@JDfRsi){M|ih zB5>HQsHv+nFfw)evGODGsu7lu7BCK#%q=YBa`^>}?N@&|seC?>-i!|f zhsW8i*G<}Vxdg8y6l`B#Q&-uYbK%*KCXZ~|zh{US2vn51#~lq$#CShOp<|5b>*w5d z3Mi?mwdQ!i5I0yjEEO%$0`eRimZ=~`4j0ZVlZKFFe;Epz78EMH>vp_t5-QYd+TtNv zm|LUP`M&?!*cJn+3zSHFN@^-Fo7H6Opm8aEI=g-OU8Cz|Ob%q#h71HujBUAe`5|=p zfBelo{raV6HDqY_9=QJbW5>-|%5>&8_r|ueh6YxGB;H*^hA4?q6YIRb2TL;W5H1uz zPEJmDb+~oyAxd&RZ&AN_?@rzs%s7n(8!Br~nO)6sRWg2f`wcv=?gqJ=1F=L#*yyU} zQ_RcD%M?E(ZDwXhx=0BlqF>lkPfw4S_korsv0MLnf3GL&Ft-aP^Q zOXfiF?7Ts((v0gd2SsF|5Y8X1{7s=2{Xac2*wr~24(woHpDZ7V*jtUOH6JVIAk11+ zScnGw6;`aapdd+FO~B`<{l~8DA0H5p&^-EC?@pkogn#~-YgWWyo9AxyMeG~K8I_>| z;I9pMDm0nHS7yk$Cu?*Y_`x@X)KaC&ghZl{Qe>VWSgKAcs%V$tpu09Y9Ygoa&oc(B z1j3&oN0G$9$7SaZR_Dt}TpTl(88Wi}eXs?ea#*^0EM19@2%H}kY5{0IEox*}D z_Pb1 z!Q#H)L2yAj!f#>sFn8?z&-MSe$N#@}yNv(|5jd|MN*HVcHuS%AGvJ?$zOlG3J^v9? zSXvJgjNnrR>YbA}ZUzc~Os`6cOswPke`d|;8~E{}(01zTv&yRtdA4eG*0rK12!+w+^)yIblTGGsY5 zuO>c|5nQilzx;cEnDTmi%sJLJ8~hW4I#S|G;@0^(yo6$rZU|oW(5{}wAmSl#0}y&3 z4I%z)6ZVJwpvVn<>jJ%kf_j*-^=kjK2pk|eWWSLJXCSZq6Ugl$K783%VG#R5{#V9d z`%7RRgT2n`3hz~v2E}Lemq1}7516muoz&%2RYzw>qR`AX>G=Lb%*@{xzJkl~;V-#@^)YpXtO>euvU2vxFruU3 znD7I=jz^0?sBo6PWOZp}i@tz{n|ax%?b*0}z+=F%)_bW}@GB<>M1_!$wk51maEcYB zJ*+45(MPu74_p|{s#=}uE#iL1*`eQEbYSle{Tk-scoD9oF)+7Z@DUz6;TJtkNYXS5;%W z1`i8cQQ_d|tVc=tSZw=negZt}OhMdk{DLIWk_f8!swaaHZf}7gc3sIrbSQG=4q2VEycgxhY zw9(D+Dj=pJwVuA_#bAA>bN{~9h|duD&Pi+DRb}miRgnVO<@``1WY7>m3@Byc+ZZ4C zF(qU<-bjTMiFxN_FhZbC5TBNqXm7+EJGM_jS#t5X%xsnTgxR9IQ8xRbwfxM_Z;OUj zke%z#iXzweSIX%;q{+C4t|WvVY;~?P$^3Wm1|Tr40S`J!iG-TfJUp4 zC}g49-QVV(#evaX3hrg!d`^LwlN;}%t|%JmjL-wG!p5)Nhn!3BlQ~vg&z9AH$W7sx zlW@+md1`ah|Kl&xF%I{-9^EN-eTSekCku-Z^!z+$7N2WiFBMv(=)plT)WavJk&imv z&et%H$N-B;eHesJe6QV6%k>~3G;wKZ>Cw?q519MMdkG0q)*KcP8kyIvaL3yuMuyH4 z&SR}IpKS1APCos;^rY_Etmb+RspJUf0!Y=E7eZQ@TBF*@{6PQ1;jHEt$0 z=(S?xVx(H6^VhxOM2E(x5xEH5;^K~q3&huwIZHb_J|zx$^6|5hqFzsqYmO+WYLruv zNg_%o85m~^?!VPRHQLxWM;0%Mex7em*rE!b1pVs z!?@$(X1d!x-Z{EsM2gxIdW(rs`qi%Li0u!sS@i3Gz%X;IySZ%c%WOPWq^Plw;Zf^l zO>v=lN26DIczZ=yTSnD6AY`iTo?stC&Cc!|w3si=_H_|B_RYJVdtX))ROy(Rp?;VM z|Mu@-$ZjWlMjII$dwqFk(5|zbP87oqyMFfJhv+;gHlL*~erjdBYq&brPHTJ#djWl8 zC}VDBob-J4gu8pJg3%Hr=Q!v52R*`ac~hC-U&;5dGH52ea_;}YhoDNqFcPCi_8WI5 zhaNb!LW}%@uK#6bbRG8mbR7^_SV0b&LH_$f;3Z3+VRN(*8V-MVVMKR+TOC!G;&<#Z zifd@No15pPriLj}C8wkmDN~n~;dFN5p-Nfxf}fsbY%WwjTTZTN!C{U2E*cfJWzd9H z<`-1m?^%tMH!n=&S~SjWm=8Fu26mCVXn;;p2{JqVGjS93eHm?t^`L>H8sivnUuP?8rmm*0P zwWw@rI>!!~`eiV#f2sea?ZvLW31Q6WC-okPK<&j7N2&;yF4`ggLD!_C3#=6M-l0no zZ>(*s)q9vZViPyS#ze!pExa13_HDN;XX|*mgzO_rBuTfQ$}r$l9Q+g3pv#ISK@ATr zYAm8%9hw%+HUTP;EynFg{3@dCR1RX6?Co8(Ut#paFG~1ad@if_4QvZ$V=u^x(9!uu z#>e5HTTn2))HF1BxsCu!Koq3edNkC_0m`+;+I07k&rr&rNod`_CUy~GO85v2UdRxn zz5Y%GZ_fXA#pc8Q^_{3NuUb5>RC3X?{|_EZrVwwfxBMPr&`BxikMy^OO= zk{~HA9tPZXcX25#tLS9wQ>SQkaJ@8p#N=m)ijA3{p2eA7j*$%=QqZ@#@#N!%ye@B> zJ(-+28HDoOK@I%F^LF-I?9Y{3ioH}~*TI68ww${*|Jlv8R9oEM`Tmcmt?E7~cf0F1 z$v5QwP0+kH+gEe0w9xBz&6`IKh;nMowq+`7yoj>d(!T3dl0{2uxn_` zhvOhou>Ke1s_9RMkV7~Q^?tPV_mAyM9Dti)by`{FUDsV)e>$FN9zvp}mcnK=9ddMF zw1~04t{3_ZQ`*%fkjNqxTB)q1uLZ0esxU|-laTCoKO{&SJ2$%js*6ZPM>WSfwR`P> zq(TV$@=fbltGoTkKuI0Nm3P!Lm{lsY-@LvRuX=7_NPO_d)2F`79FWIEN)PgnQczNW zFrOEs*Hh7s0zeiZYZ{ZExHG=Yy1&1FeXw2S-+B=9gINNdkpTj-uK;tAa61Ik|gall_ik3*Nt&k#N4RXI@@B)eJTcAsgDw z8zP{k0YHqjN`2SPY*uci=iB!YJj7Ay?_c&_`kJjl*NgxU%m3rX$GP4EOGVL<3!n*D z141KUQ-cRG?a*U?Khe>amjMoQyF5L`;2b1$52mE35q$cGvynlPkniV#SfSp6eCslk z6t1u`6_2oBkIU#zTMmjdC2BKym9SI$87w3*iGd)Se;aZU) zQIdpx+cBI}R?~gc#rDehxQMv;C{8vOwqLePP2BQPGN^ZO0B{j9^1_Oeb`xM+>OpGO zcoxXI+F0B0_#fe+5d5ILKuia0JY9<)lg$4%*8;-AA&yOqk|RUcAC42GwiD1(;3_;k z&m02dRM8%~`+pwjarzxK04<>O!{eTEp6(Z)dm2 zBu0O5?jMi|q*F%<6k=j6BD}v(=dc?+?D>WSmIuHsp zcy9!$m6td0!gNQhE1TS|BI05){Bqu}<8nwy$@YI~k4{Np#}1p0rTkajB^m620ibwC zXtn)9AjHrOT-1|~KxARVa^Hk+QnV1!)63HFQj005!R{BfvLP6JG*OXVMwY*a4sRa` z-zWsT70FPG1S9aPbdW8<;rf^u(s;KDhhjie1T@@t_u%k-9()^?mm+T{Qfcv!-lu0r zcx^N6vU~&z@*wBF-wwv$r^V%lNrv?$SAgIlSm@v1y0FPIc|x#V$xbR)z6qy;J~$+- zh-8zsg2m2UE*WCu=$x+Fy2V`6d1z>;eOXGoBviMEM=@$0qJv^z16de?oG`|UQrr?c z;}z)!Jw#3(U*DW3opT7ttzNblH)n6kjGo}TMHR~M@CXQM>oeD4k1sCRSy{91az2*4 z_6eIUGBcf77itciCSc)!cFPZkN2Q+J-exW%I${OWOeT3~D&~e;t>PdytMaIS^#j_v zv8}l|7ucNr^z}Oqj#AkiS~G{-{aMyY6Lb(!&0(h@Q$Wr7MuV2RuFpt+fB)aV9W^zZ zqoYon8{=4ko5B*og|5x0|^1=_^8B!D#6zA2IHdN$^v6k1~I$p=Zxo46d`;?YG9qvD8 z`blYg`KJ$0;D%GyY*?nA^8dx${t;c@c=&b@UCq9|oOQ1}RPF1SGayK1$9SPAXXDSI_=c2;3ZfoY zjYKL1>_?JQK9eU7u|&x;O4!m&(IB(rFRTCzrtZjzdw4?ESfj+YW;A28>Xp7-BF z;Svr~Ak$2o&T1tDk@wC7+|jX#P55K&jsUEQF|#u>1Ijqx8fm6aGEij2R4hAXs4x;;9{UXgM7 z6chZ7w%h7_ch)!NbU!8OZPr=ey>uA9>B8P5Q0DLvO1HWeW^sP9L{?MU?j(bUZ%w|1 z26!T12r*I(?hE-@$}V^t1x;b{;|gV7KQ+8cvYfVcz`4#H;V$nJ{GZtqb{xF9%`%n>wl8+44vI{QU|U*tdWp`z}4#_oQT}InlL_m-ikBgLMag0IW<2SUa8*F}^b#~15Z;4q21sW~?Ng2_#84HF}&tC7i z+_=7VkAFXP8N3LZiv=mnrg?QCoGa^gn!l7!VP~4o@&-6*oYc*STqiw#I9An&f|kPz z|Ls)nr^gurd4j^(;$ag$m7sDz(|BPx8sH669LdG)m0WZd2DIdfz}=o%LGXWojjWS{ za6_R5As1FXA{1Sm>mADbqrB_H^Xa;rT_wucBdRo-$%Za%2XT2XahRFhxGbe_*9$o` zU4g}zt&x<~Eivm)I2HN`!Kstf){2BTfI_FoqS$21y44=ijSe{^9a zl&`|@9B1RNj3$PlkI(p*|6Y&(r)8Fj2>WAb!!tnaN0sjzd|fhzn^9Vu%q70C(oYgG zr5Yu)xd@6{QSwM7hnPfMI1LjKlR%rk%u-JAccDtl5UQYvAaL-R==`1;VMC*3{Vof4 zoM1LwY_!cysT_*~{=+lw_OnU6=>H z8nkexVTILs-=Mrs5x1^kmb6#n*{o=Nkg>p7B(^mj0Z(qWCiiW&{7vOBmFOqHb?DHVT=Q}2kR<@^@7(#5Uhat42yd1yJo2G~g z8o^O6ZnHhUfL~?VbBY7A1ax*pq*lkyX-QR;$CeoiY$$CP9723d55$pO9OAc8UbU~_ z!WI^kU60L0jaB#8Nw7YbHM`g>3c44i4mpprNRSL19=1zXCM zrR{$NukF;;y$p)ega!@iM=@~lQVMn__8z%QL!_()y}jidJGi^Eq9t+S;Dc?TtgL7= z>a{AWjDeIxl;p?C98S|h->dGw=$E#am1zc(DOz+dh)?!TjWK zYeq#iPD{%Oqg988^o9`+A))SVQ!Wk z5w|d%KPusKKAk7zi3J-!^xDlzNu4p5V&Gd)Ek8Oj7Rir=UuW9dl_RiWdQ?_ZGch@W zr;AM{37|+2No7cjAfIPfOY?7+BuU`s@3?+hG!1IbjZb6jdc;Br3)>k25Ny&I;t_b@ z{#ia-d-HK+Z=Bflk2hUfUfMgrV&mXUk|GOK#CCmqTCbEfmk5t8Fd6Bk)xf{S7|p(5-q?*51J(_vn-oGy3{R8%m_;Z5n+FWtsqt z7RSgUr|C9{7J`@NHP_8>0;QUoIwmIWVr9|sF>we@MMZqh8#^zfLXxbTJ8t{iEf51E z_tgW5kT)YGv)y6U4WGWs&q7UCyUpw|KCa2lC@*j3w&3A`v0JaIpbEd0^lcU4^q6hs zg0Sf>TUky|&s0@a$}?S(uBqt{v|j6IfcUEO)mGykS;$mxuD^iu^$ue=q9E>ifH=tG zs`Sa5^Fy$`tY~?9l7Y)IH8UCxK*h&G!YSx~Y>_LLD`+rasHvkJR)vt#-QE)N((#33*z*l3CH5&A+}ZLqhm5SG1hy5GneZ|Ea@tg3L?-LX_))_hm)^Qvu9bAqve#~dB5v!B12ov z0{nj$hnaWxu61Nlro;!EPhK>uXY5I~r(`FQBg6W1yv$?$r%KSvS4H9)vBCmciYFpfC&W{DAddw_?ns7$04uOI$R#t z*N#d{Pa+~xTUl*Z8Y~W)M)mJVL+mL{sKJK`5n)@ZFQle|q6ZdL>~B2yo~ixGgN@9MX;LL= zaAH6jYaVCdT~7!!wh z_~;uc1=c2vta0D!Ezdopj<%hgE5Vs*6e(wTI{q2F7c!$EbkVtDeW4&O9{ zg^do2CvIZi9%7Az31x?D6dk83b4f^m?>EulVJXRJAlkzQMEl3a8qn!B+-_#ZeH;q9 zEi7o%7@Q{iVnEXPT8JsC-aS4X+&(XRA|V5gwbG&UgakK*i~IK-F+oln_tPeRohH%q zbqgbNbv>2YnU$C2wN}3kWma6gyJ^;7^3R&qqW#B0GGDz;6^RerTHm1z4BA${jpddW z3xrg9&8tmc6v~1)q7eHLfr>YhvIc)PyOpS-F~sxb_TzScoSCr47jUqnZ}q`a6batn zpe#Dt(>kjlQf7RmIqgp1RnS=TX=+OgnR@(DW5wNZ_N`4V-%5A#DhXoockRusFV6M= zCAg}5eud@v(#n)5&{1tXZBeA?uQ*`g11B+&{P?~Ha~s2YJ_5kyks^)YoTHNy&zM^_ zc4lWB_TruE0^y)w7ixda15jN5*&Zlb>Ls3fR;dQjK^NU%t*{%woIrqe0!yg<1fS|_ zlPm?EUOcO?ZnJ%QjNyLb0+@*%KRa6s3OeOXa@cJ5w*3rjd*OMudObmyDS2{rag)Rf z9UX&se?tL4vSoaU4MTSNk?b`XR!otns5xM0`Ew*^w{V$BglBzZgP8PHKwuKi(LJfl z27zUHZmA`|E^%Ue_@0{lT;5He08m=gs78{I%hq~D(W=(`E@(^1S~#0@^PZ@Rn@!G>u9e71NWGLkdR91wWJbPWWi1fWVD|s%m=S!2Ghj z=W>nX7`*2-*IR4r89l`C+4*@4d}mlBQn`tXF=ok@tDjP)fm`vo_4=CV7#PPc5TLGp z{Gqcvz>A_N$`$t@-iFJsQ+f*i3Uxd)-OI+xp62c;#d*sSA`G0ARnjWsqc(9gqKZ=> zFQvk5TiFRD7SfTi>0R6U<{X^c)MUTZMBhv#$j%>I&8QcktfDfTO77E8rs|BQ0;j^N zg;ZErIAbe7$qkHT{7QNM20zLPuQ4!B zBL2Hrks=6VV5UB~ySVw?^+I{beX=z-&}n|Cd3(24HL~mF7SnlCkNnO_q-9-^ej49* z2prmd%>Kn9z^q|$DAN9@+wzjh*NX1E{TAl1IR1+Vu8Q-dVLp`rVzk zyChj%a5ia}5#F0=1n}^2laLV<^$GGf!wKpE{J9r-pK8ip+0|4#`6(rV&^j5Hg(cd* zWSq}x*eW#WwY68^#T#AV@=i`@_}(l^5>+LwtDQ^G2TB(9QW2A-%Ne~?pH}JH%Qi&r zJz_vh3*k82MvHIe+cmZ-?7+Z?l3NVvlBTv)HwYbqpaSR%@&V=wn2kQwnp{_Rf}&!J zXD#I>CNLCoB%PBhC;uk)Vgi6OGLx|2~yAuM_ zcz@4~#UObr+2!XU=dhP|D=AdANpvYOXe54Z>)EAQFBmFl6w*yCiPm) zth8Kj(qkT}>=5L9OJ!;4s1`nZIr@U))N9>l0Yhk3W)`_l-=wkqI?YOzX-ZhwTdzjX zFq(v=g@w_R?{t)F^-uE9rRCMhhe1>s=;Cs&W3%RnX-R3h!JIhXb+hznbNJdEk8Pbs zWBd1PJf47V@X&d+aOTMr8=Wm~kKyf$*liD887*B$N-o3ZbzKi3DYw^4nZ{;Dkw%)v z($ZL&=O=r*i&MyH$e@4`0(%pLV;67S)w}U=LccXL3p-zK;=GQ0fN*^UElx`}b?lM{|}_*{OIu;!tFnuF8h=hO6G5q;sfnT3yC z*#fwmi7W7J$wcG2PogXC{beUpz4aeZN{(++`+&^paX@VKc14{(k2OFqWY1=6-i`sIcA5aKtbl`?8Fogch&r> zW$5MAaTjnkX_?%lR1dm$7ZHxNnzk0FhO>|6&~F$ZnAgzI@F;%q;}!30ZwV*(-ci~TFk$4+ zX0mXNCb&!gVQZvFUg7U!Y2q?`u(ZGGC4gE`eP!h7B>qukiqK}S*xwy?W#t8n?dI{A zBgfk}%gQ>-S_D_Gt$H%ZZnM95AYr@NWo6-^Y;Emh4D!M0c9|ZV`uj7)FTScdc4@Yh zmbH@aPo6ucF~+;PvU4!Ccpl1c3J!NHJ8Q45)DiMc&CcIHV8{C(w&9LGGQqR5GC%*A zJsAEZcz#|)19_kOhb`ARE2K_NfSp;D>=Y14_rbwcRbAEkz9u5S4Vv|i2vGZ8g%HmRP2SjI`ZPf!*kO#-1PPDo^O?nj+njrAMi8X!Yl+mex@b} z&(6Nu&(jDp*5ruX84Ei)`l^_Wp0B#s*Cj)TjC_1VANmJrfcNMCf-A3||C;F%r1hEG zSXvuD0jH*VsP0x>@en1{?&Dc&&2s%i9Y|QTOl}7+WFY{SWIy(HzR5g;3xpYc6$5NO z)C*+IW~-A^(d)g1O45DLV*;-^i_MPh%#P*n3J)@$9AvE>jmDzezxIgwI$*Ir)b1VY z{+Q_ATwB*zTZd1@H929Dl{qBTh!IZ+!st-)8Rey=9*m^frP6rZPQ!5xGa|wg&I6}+ zebH~kUZEPwA^ZgSoI$^j?u-H~hVj&5594DPd+nQBY0>0&z2EyzPK@UktZl5U?pq@@ zh|rswn^nr@x-@X^;S7kjZlA3gUt|Z2ui=o6o_2XOQ6meR$>1UQOZq{FzrX|Av_IoZ zQKJXmH^QmWVR^OaUk8Z8py7?ao5pIKvaV^6|BHw5*Z4O_^1uIXWH8~abmDJ* z{SQsz0SpzU_}7bi9RJO6{P%AFTpx5$z9@<3fc$^)F`xrJAcrzC`sdAGp@qe&5n6&# zjS%o}u*r{gpfLOls8G|4jWIXu72LHjRXET$;_C`-tQ2V%su~o>GSR$1p5YyPNn#<2L2zy<$rC||5JBY3~&$&)4G8U z!T*=Rp0{ydLjFhE<~G8v^Dhk_+UNIuK_?b1Qch7zzGi}k_$T#wQ^11<67jOWUSzk& z-p6{tAD^6hd3eSU@MZ`RZ82;5gbi5ybMZsM%+1WqP*JY*vNCK2uIZ&^e0V!G4ON@t0eCLZ zpwSJ(65^lKXCR3yUio^F`}9CdgbW=gjt}zZ6Vn1@C*-cL2#=0VmX?-qqy#+y}glWU{Uf-A;ssaX7jm%pd!e#wpE+9&;FvW z&f>?9Gj<3U6KmkfMWy(=!=|XJv8uL9NknDWYHYSGg9kPxXtCqg27Wnx86=Ke`e#`U z1+4gcaSa7dOZ%x26Uutl`gQ*G>nqT~VhK2Gc2~);y1Kg9#(_kjU^Jr-8=SFn6sp}9ofGl`ex}Lo~oVa-) z2tvXE>0OP|f`7X{Ny0FaoH?d>eUL@0DsH4k*LS2bf&=q?zuJ>%sAZ%mxM+=Ptw>N? z(<(MPofmtiemg*xVLik>K!!oOU#<;6i1g%#_7aZ?++Mpe($+j3ti~>LdwNXdikq0+ z`agWSJdd*Tfu`GQs3?in&3xh?JEL5`4=W3a!*msktBgfTL#Li72aPT7%MO#RAD$p# zpn+3t1@&@cRpOwWKba1+=a$Li&(`Akd%2WNMr?6aav=>#AwpITWJU7?A-To1b zJUTv_{yc4=Ya&>bRht7U_ z4iS*+F8v+Rw;hASOW~;f`|kJXZuV=p^S;@>wzf7f@%EARLW8gJ*X!}x_}zGv1O_1R z&yG=OO4WQaQt|Mu45!1|xGWI;>f1-)M{}Y>m3I3{qunSn7v%Fh?2XM&{fLhAju9MX71;Q8;s4y#zvX<^)R~<`P|(fo`{GXo}OZ3U7C6m zrDD+U-m}#P^8GHg+=z%xj~D9(_rUwmP;%(JmzTj&>A^|8S1mm~wu~H6l4rm5g)t4k z!`r9wa+*^P+r!)Er>FJOve?4edlZ1Eni}Xll$sib7Pel8N8|55A^Bz3N7G5MM%(uY zvBBf@1~~$DIv@A$oc3!@IQymLC!`Ud$h+4l`bnc78U)#x(t-h z;qeA3Qu)buG?U;ljq2>kPF1auEho=l`1Moz-I}jpJvM)BO+Xfxii%3N)1|Sv?O+xt zh=0obV0)+a%>JI8o&CsqseqIrupdkflH2@(WV~b=(7@i-QumK(uSf3n9pL*nGA2A&D)OCe4KGYj^Wb{x2Ft#5AKkY5@dYRp;%aD=uvc`$<`C{|8RFKu(*jDHn!XU5 z8cOn_y|V@iJ?)IKKeE(CM~#Y8#T>ck2ouWn8JuzNpxMtYa#m}%+KwFNMhxsIV9~|5 zzrC)o8&Hyw)oSX^3jXS_JLRd>?4UEfe?PnMSy^^YLjfp-`{SLT=o)Ntz3u`%`O0YE z?@;)0UzT;kz`u>2ri7aztE8O^N$TP}ITGXkkR6q&p~Y#~S?AV`Dr-}3(}!0|Z0 zGQ2rFG$oX6!jbbU`OK0I9(+dmd3Hk{Xz`WYL+`ZgWgfdud7 z*s#5W1!h|EJufgYB(Ja#k2pEmhxhaYB1BPUOeIoOSy}nxYTD#j!)Oq_Y*$6`X)9Q$ zmC2Dy7qUQILc*ru>@vTm=JezwIfF)T%X51QxWNKKANn<>>to7fRR4mMFCH&)HzxJV zbeO08K*}pG(dm<}t_WEQcL&R#&pra}(G%wNt}d=^jH}c0=d|#q2p!SI4bgLH4Xpbo zB)S{eq;`ENz`0i{$mQ}c`Xf5T1jcwY#~$^S0We#}o#TbWza2@;X~ zAMIOPSdv*3rM!;ONHyjCR+?58nphL1G+G)tQ^;r|<)w18)XBV#7qmY!H7`MGX=X^I zBwCr~r8I@o(o)oHkdzV02+_(!NI_AV)7!kw%Y0uiegAp*U(R`0XP>>!+Gnrxoc{ip zI=Zy9^q2Z-yZZYm;WBk?i={L<@m*BoE91*~D6KRE9-n8*1Vu2jMwg@p>0hUUM4t+> z)X$x3?OHF;-p`Lq#ynae-bi@sl-M>BfpFm+_S#DD8#c8-MOo(d3gt=3R`VAT+F9V7 zT(Txf;yQ^hXw;UVFQn{W#ENj{Um{Ifczb(W1<^0vbA|iIj5lud^u}TKAQ#m>b3BG7z1>?p^$+G+`ovcuON3)(;gf4u^Htw3x z&~lO*%_bY0A(qN~ zW=QlH%aqOl{**qPPa5KKE9LvN37sS!I9h2gw3|1NCnj>u3C&x!83{g8Q${mi%iFnJ z^z5h!1f6c&!3gFwpfG@N8tPCUjlf-2VBbk-x^zZ-z)day7RA=qy0Wr)&Umy;tU;%r z2tFZh8GZ?aHCuqfcTusGpU0fyFLK(_kwMkY5AR3Op`UG<7j=Oovv+8WoM@ldkQMzL z%;n$tDO@f7kQ>>^WSYuwu}+2mqJdd{pYn1W9JlTf>M_QGWX2PHee*&yovY&Gf>Fcumn&9 z;D*~w!s)QUgekmBbaYp%M)buT_;uq6(ETNvlIfjkv-^X`$!zJ^{hZAiV6)%#m0DAg zv*q+Fv-M#w;=7~u4Gb6z#;$mrK2wIFCZn}<8iQl^|idn$9dGKI4 zjW+I>t_ge7UE~1uRH!JthR9+c+dqv(19H^dpkGt1xZ64M^V5RmN8CupA*W98htY2w zH(b4Aett~zGYB}Q(x+3Q_3p?DM~-L%|$ZC_(yE_fPR^|=oPLDUS<>Iaj*4>etB z7ey69^$Ot*2YdK3iF^y>6RA4m4`9z*d5kX?DB>S=33bh!nGgoK&LP94&$m8mP|Iu| z(lGnrL(gso1%td`d&CQe!$~5{C;>RUkJp@JL}*2Y@Hn5FWo2~{PkfW`{1-NRpRI6o zj13ttVlqoyXcD;~-+jl<9C?JRwn(&^|0qrncdnd5iDk*22DlxrtkmzF!`m2w?bb-M zdR--8vpXG8Hzssc4=O5hNu+`*(jja}LU{O+jJD+^O3wq~%>4Y8a)FzD^&%ra+|xs?^&Uf3S5Oi*ggk)uqk zAlOqMa?PCLyQ0+E)TAc_!rp`-MWjE||4jb8@pY5-9HVtkREKSO$m2%EhL~DIUK3B) zLXVqvwk2Mr7OThxs_N+KO>E?yAkKkn=nzJU*3^T<3niexIxH|W#53`(y0-e#VE6Jv z)M*16ZlJFZOFOx^!VtFRwg-VQo~D}(QH9kY~$Nb?Q%Y3X8OGmXZ zzUP^+ve&stICk=g;N_3R9`PeT%mM#$SEq5us z;;@jg7WRhmzgKB0G7^XDA%=LQt)t?>B=`09{m9>9!K#r@!+?PG&$3vh334PrRc@mr z*_ke|pC_rLtU!e3zrJ)9-EJPEjI{$Z&hBOln%wob=d4h(M|>M!1p!xIxL(`9?bI(t z5%uGXT&LEDo^be4n411$n5Ny?CEtGkUmOq_BX&6pXng?pZu8O8{B=1-?H5w?zm2bh xfW?;d>|-DMYruBE&e}mAdMw@S|2yj8AjQTSGe*^Cn-yPXV)q`{Q{{5>+&?z5j935w literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/artifact_panel-dark.png b/testdata/snapshots/darwin/artifact_panel-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..5f0cd25734078fc27bc84d7f07e89eb370eeac01 GIT binary patch literal 23276 zcmd?QWl$td8!g!A;4t{$Ft{_g%i!+rFu1$BySohT?hb>yySqDsG8q@RB zH}(f3#)RCnJ_XlO!&ZPoEk`L=?(|_M}?Wm7nxICzg%7#iJu| z(1eB-3tF*C@$|tal;-Q#`1jLCSBqqeR%(Po+R3|H4(;%;u#0KR=>`^fwP1hrYi~+; zH4+k%SLSS4Wc!x&3!=7?DPHHRGDo>=&ofD1Ii0WS69@@RpcxHNs;N|$Ypb-CJE$C% zkEtYAQ2*~An38ELXZqyCMb71Pb?H*5ArEKgJ@lSu&XMNY%&u6j_Vv8

    1+u?Fv2N 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 z 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/artifact_panel-light.png b/testdata/snapshots/darwin/artifact_panel-light.png new file mode 100644 index 0000000000000000000000000000000000000000..1b1f06b2106091c682a41326527e00a2aaf777fb GIT binary patch literal 22104 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/artifact_version_switcher-dark.png b/testdata/snapshots/darwin/artifact_version_switcher-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..2e1db4321c1a0aceda3d77b7f7d230d9d413e646 GIT binary patch literal 6383 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/artifact_version_switcher-light.png b/testdata/snapshots/darwin/artifact_version_switcher-light.png new file mode 100644 index 0000000000000000000000000000000000000000..ecdbb71e67bada6a838ad692f9dcf0e788808d65 GIT binary patch literal 6098 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/checkpoint_list-dark.png b/testdata/snapshots/darwin/checkpoint_list-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a31d5238791cf74c9fd1ca09fa58cfe05115423a GIT binary patch literal 15247 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/command_execution_card-dark.png b/testdata/snapshots/darwin/command_execution_card-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..5dc61aa57c659ceb6acbefaf132702a8a429764d GIT binary patch literal 22439 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/file_change_card-light.png b/testdata/snapshots/darwin/file_change_card-light.png new file mode 100644 index 0000000000000000000000000000000000000000..ba001c481fe601231911b146e9e18847358782f6 GIT binary patch literal 23061 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%0Dv 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/mcp_server_list-dark.png b/testdata/snapshots/darwin/mcp_server_list-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a8a5a4d82ad3ea02f94f8744ad6a82c29b3c8d55 GIT binary patch literal 26561 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 TGOGr!E?iDpNvcTVh2Q@H4zt9| literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/mcp_server_list-light.png b/testdata/snapshots/darwin/mcp_server_list-light.png new file mode 100644 index 0000000000000000000000000000000000000000..75ca50a4537029178f537016e729a3725208c73e GIT binary patch literal 26213 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 SjRnkfkg|e?e5I`UyZ-^TOL7YU literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/memory_panel-dark.png b/testdata/snapshots/darwin/memory_panel-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..c5f6834cf714b9bdb9252b60674bd17d6676eaec GIT binary patch literal 28687 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 z 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/multi_file_diff_review-dark.png b/testdata/snapshots/darwin/multi_file_diff_review-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..5b3c55b799e6e0477086e28eeb22253cee768850 GIT binary patch literal 40763 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/permission_prompt-dark.png b/testdata/snapshots/darwin/permission_prompt-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..d1bd8d5d2ca6f68ee2acfba54afaa56aa0888936 GIT binary patch literal 24519 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%0D)R?a8q=Bvi6t_CJx*S=K6ah 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 D7tzpN literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/sandbox_status-light.png b/testdata/snapshots/darwin/sandbox_status-light.png new file mode 100644 index 0000000000000000000000000000000000000000..6a92c0653e5876bb772bd20e68af71b9763f08c6 GIT binary patch literal 11551 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/screenshot_stream-light.png b/testdata/snapshots/darwin/screenshot_stream-light.png new file mode 100644 index 0000000000000000000000000000000000000000..408ca79f98a6e8b22968ed62de1e8018190860a5 GIT binary patch literal 7643 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/sub_agent_tree-dark.png b/testdata/snapshots/darwin/sub_agent_tree-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..ab686fe38934c743d49cece2937f643cf100a0be GIT binary patch literal 20444 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 N-yC6MTnWD!|8E$ysY3t& literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/sub_agent_tree-light.png b/testdata/snapshots/darwin/sub_agent_tree-light.png new file mode 100644 index 0000000000000000000000000000000000000000..6309770160231733fb52af4955a0c36e7cba6e90 GIT binary patch literal 19589 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/tool_approval_dialog-light.png b/testdata/snapshots/darwin/tool_approval_dialog-light.png new file mode 100644 index 0000000000000000000000000000000000000000..77c70a644b54efeec7c4a5b9b6db700f42caa7ab GIT binary patch literal 24229 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 YUOTWYA%BMb^$7Nokx&$`6f+F?9}F8K@&Et; literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/tool_call_card-light.png b/testdata/snapshots/darwin/tool_call_card-light.png new file mode 100644 index 0000000000000000000000000000000000000000..68ca034e43c047134110f18ff91d9a1a2e323137 GIT binary patch literal 13488 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/tool_call_group-light.png b/testdata/snapshots/darwin/tool_call_group-light.png new file mode 100644 index 0000000000000000000000000000000000000000..f7acfa463ca7e11141a1ffbbaec8afc56a3b8261 GIT binary patch literal 16891 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 literal 0 HcmV?d00001 diff --git a/tool_approval_dialog.go b/tool_approval_dialog.go new file mode 100644 index 0000000..7509c91 --- /dev/null +++ b/tool_approval_dialog.go @@ -0,0 +1,65 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// ToolApprovalOptions configure a ToolApprovalDialog. Tool is required. +type ToolApprovalOptions struct { + Tool string + // Args is the call's arguments, JSON when valid. + Args string + // Reason says why the agent wants to run the tool. + Reason string +} + +// ToolApprovalResult reports the choice made in this frame. +type ToolApprovalResult struct { + Element *ui.Element + Allowed bool + Denied bool +} + +// ToolApprovalDialog asks to approve a tool call; Deny has focus. +func ToolApprovalDialog(c *ui.Context, open *bool, opts ToolApprovalOptions) ToolApprovalResult { + if opts.Tool == "" { + panic("mujica: ToolApprovalDialog needs a Tool") + } + var r ToolApprovalResult + was := *open + u := Density(c).Unit() + r.Element = Dialog(c, open, DialogOptions{ + Title: msg(c, "tool_approval_dialog.title"), Description: opts.Reason, KeepOnBackdrop: true, HideClose: true, + Actions: func() { + // Deny first: a reflexive Enter never runs the tool. + if Button(c, msg(c, "tool_approval_dialog.deny"), ButtonOptions{Variant: Secondary}).AutoFocus().Clicked() { + r.Denied = true + } + if Button(c, msg(c, "tool_approval_dialog.allow"), ButtonOptions{}).Clicked() { + r.Allowed = true + } + }, + }, func() { + ui.Column(c).Gap(u * 2).Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + agentCaption(c, msg(c, "tool_approval_dialog.tool")) + ui.Text(c, opts.Tool).Font(theme.MonoFont).FontWeight(600) + }) + if opts.Args != "" { + agentCode(c, "json", agentPrettyJSON(opts.Args), 260) + } + }) + }) + if was && !*open && !r.Allowed { + r.Denied = true // Escape + } + if r.Allowed || r.Denied { + slog.Debug("mujica: tool_approval_dialog choose", "tool", opts.Tool, "allowed", r.Allowed) + *open = false + } + return r +} diff --git a/tool_approval_dialog_test.go b/tool_approval_dialog_test.go new file mode 100644 index 0000000..331255e --- /dev/null +++ b/tool_approval_dialog_test.go @@ -0,0 +1,97 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +type approvalApp struct { + open bool + allowed, denied int +} + +func (a *approvalApp) view(c *ui.Context) { + Use(c, Settings{}) + if Button(c, "Run", ButtonOptions{}).Clicked() { + a.open = true + } + r := ToolApprovalDialog(c, &a.open, ToolApprovalOptions{Tool: "delete_files", Args: `{"glob":"*.tmp"}`, Reason: "Clean the build folder."}) + if r.Allowed { + a.allowed++ + } + if r.Denied { + a.denied++ + } +} + +func newApprovalApp() (*approvalApp, *ui.Tester) { + a := &approvalApp{} + tt := ui.NewTester(a.view, 600, 500) + _ = tt.Click("Run") + return a, tt +} + +func TestToolApprovalDialogDenyFirst(t *testing.T) { + a, tt := newApprovalApp() + for _, s := range []string{"delete_files", "Clean the build folder.", ` "glob": "*.tmp"`} { + if !tt.HasText(s) { + t.Fatalf("missing %q in %q", s, tt.Texts()) + } + } + if !tt.Focused("Deny") { + t.Fatal("Deny does not have the focus") + } + tt.Key(0, ui.KeyEnter) + if a.denied != 1 || a.allowed != 0 || a.open { + t.Fatalf("Enter: denied %d allowed %d open %v", a.denied, a.allowed, a.open) + } + if !tt.Focused("Run") { + t.Fatal("focus not restored") + } +} + +func TestToolApprovalDialogAllowByTabAndBackdrop(t *testing.T) { + a, tt := newApprovalApp() + tt.ClickAt(5, 495) + if !a.open || a.denied != 0 { + t.Fatal("backdrop click acted") + } + tt.Key(0, ui.KeyTab) + if !tt.Focused("Allow") { + t.Fatal("Tab did not reach Allow") + } + tt.Key(0, ui.KeyEnter) + if a.allowed != 1 || a.denied != 0 || a.open { + t.Fatalf("allowed %d denied %d", a.allowed, a.denied) + } +} + +func TestToolApprovalDialogEscapeDenies(t *testing.T) { + a, tt := newApprovalApp() + tt.Key(0, ui.KeyEscape) + if a.denied != 1 || a.allowed != 0 || a.open { + t.Fatalf("Escape: denied %d allowed %d open %v", a.denied, a.allowed, a.open) + } +} + +func TestToolApprovalDialogNeedsTool(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + open := true + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ToolApprovalDialog(c, &open, ToolApprovalOptions{}) + }, 200, 200) +} + +func TestToolApprovalDialogSnapshot(t *testing.T) { + snapshot(t, "tool_approval_dialog", 560, 380, func(c *ui.Context) { + open := true + ToolApprovalDialog(c, &open, ToolApprovalOptions{Tool: "delete_files", Args: `{"glob":"build/*.tmp","dry_run":false}`, + Reason: "The agent wants to clean temporary files from the build folder."}) + }) +} diff --git a/tool_call_card.go b/tool_call_card.go new file mode 100644 index 0000000..164e6ec --- /dev/null +++ b/tool_call_card.go @@ -0,0 +1,79 @@ +package mujica + +import ( + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// ToolCall is one tool invocation; the caller owns it. +type ToolCall struct { + ID string + Name string + // Args and Result show as JSON when valid. + Args string + Result string + // Error replaces Result when the call failed. + Error string + State AgentState + Duration time.Duration +} + +// ToolCallCardOptions configure a ToolCallCard. +type ToolCallCardOptions struct { + // OpenArgs and OpenResult start the sections expanded. + OpenArgs, OpenResult bool + // Still stops the running animation. + Still bool +} + +type toolCallCardState struct{ args, result bool } + +// ToolCallCard shows a tool call with foldable arguments and result. +func ToolCallCard(c *ui.Context, call ToolCall, opts ToolCallCardOptions) ChoiceResult { + if call.Name == "" { + panic("mujica: ToolCallCard needs a Name") + } + k := Tokens(c) + u := Density(c).Unit() + var r ChoiceResult + r.Element = agentCard(c).Role(ui.RoleGroup).Label(call.Name + ", " + agentWord(c, call.State)) + st := ui.Local(r.Element, "mujica.toolcall", func() toolCallCardState { + return toolCallCardState{opts.OpenArgs, opts.OpenResult} + }) + r.Element.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).MinHeight(theme.MinHitSize).Children(func() { + agentMark(c, call.State, 16, opts.Still) + ui.Text(c, call.Name).Font(theme.MonoFont).FontWeight(600).SingleLine().Grow(1).Shrink(1) + agentCaption(c, agentWord(c, call.State)) + if call.State == AgentDone || call.State == AgentFailed { + agentCaption(c, agentDuration(call.Duration)) + } + }) + if call.Args != "" { + r.changed = Collapsible(c, &st.args, CollapsibleOptions{Title: msg(c, "tool_call_card.args")}, func() { + agentCode(c, "json", agentPrettyJSON(call.Args), 240) + }).Changed() || r.changed + } + body, title := call.Result, msg(c, "tool_call_card.result") + if call.Error != "" { + body, title = call.Error, msg(c, "tool_call_card.error") + } + if body != "" { + r.changed = Collapsible(c, &st.result, CollapsibleOptions{Title: title}, func() { + if call.Error != "" { + ui.Text(c, call.Error).TextColor(k.Danger).Selectable() + return + } + agentCode(c, "json", agentPrettyJSON(body), 320) + }).Changed() || r.changed + } + }) + if r.changed { + slog.Debug("mujica: tool_call_card toggle", "tool", call.Name, "args", st.args, "result", st.result) + } + return r +} diff --git a/tool_call_card_test.go b/tool_call_card_test.go new file mode 100644 index 0000000..770a4c1 --- /dev/null +++ b/tool_call_card_test.go @@ -0,0 +1,103 @@ +package mujica + +import ( + "fmt" + "strings" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +var toolCallSample = ToolCall{ID: "1", Name: "read_file", Args: `{"path":"court/ledger.md","limit":40}`, + Result: `{"lines":40,"truncated":false}`, State: AgentDone, Duration: 420 * time.Millisecond} + +func TestToolCallCardShowsAndFolds(t *testing.T) { + call := toolCallSample + changes := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if ToolCallCard(c, call, ToolCallCardOptions{}).Changed() { + changes++ + } + }, 500, 500) + for _, s := range []string{"read_file", "Done", "420 ms", "Arguments", "Result"} { + if !tt.HasText(s) { + t.Fatalf("missing %q in %q", s, tt.Texts()) + } + } + if tt.HasText(` "path": "court/ledger.md",`) { + t.Fatal("arguments shown while folded") + } + _ = tt.Click("Arguments") + if changes != 1 || !tt.HasText(` "path": "court/ledger.md",`) { + t.Fatalf("changes %d, pretty JSON %q", changes, tt.Texts()) + } + tt.Key(0, ui.KeyTab) // keyboard reaches the Result fold + tt.Key(0, ui.KeyEnter) + if changes != 2 || !tt.HasText(` "lines": 40,`) { + t.Fatalf("keyboard fold: changes %d", changes) + } +} + +func TestToolCallCardErrorAndPlainText(t *testing.T) { + call := ToolCall{Name: "shell", Args: "not json at all", Error: "permission denied", State: AgentFailed, Duration: 3 * time.Second} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ToolCallCard(c, call, ToolCallCardOptions{OpenArgs: true, OpenResult: true}) + }, 500, 400) + for _, s := range []string{"Failed", "3.0 s", "Error", "permission denied", "not json at all"} { + if !tt.HasText(s) { + t.Fatalf("missing %q in %q", s, tt.Texts()) + } + } +} + +func TestToolCallCardRunningHidesDuration(t *testing.T) { + call := ToolCall{Name: "search", State: AgentRunning, Duration: time.Second} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ToolCallCard(c, call, ToolCallCardOptions{Still: true}) + }, 400, 200) + if !tt.HasText("Running") || tt.HasText("1.0 s") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestToolCallCardLargeResultIsVirtualized(t *testing.T) { + var b strings.Builder + for i := range 100000 { + fmt.Fprintf(&b, "row %d\n", i) + } + call := ToolCall{Name: "dump", Result: b.String(), State: AgentDone} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ToolCallCard(c, call, ToolCallCardOptions{OpenResult: true}) + }, 500, 500) + if n := len(tt.Texts()); n > 200 { + t.Fatalf("%d texts built for 100000 rows", n) + } + if !tt.HasText("row 0") { + t.Fatal("first row missing") + } +} + +func TestToolCallCardNeedsName(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ToolCallCard(c, ToolCall{}, ToolCallCardOptions{}) + }, 200, 200) +} + +func TestToolCallCardSnapshot(t *testing.T) { + snapshot(t, "tool_call_card", 460, 300, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + ToolCallCard(c, toolCallSample, ToolCallCardOptions{OpenArgs: true}) + }) + }) +} diff --git a/tool_call_group.go b/tool_call_group.go new file mode 100644 index 0000000..dbe5a61 --- /dev/null +++ b/tool_call_group.go @@ -0,0 +1,75 @@ +package mujica + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// ToolCallGroupOptions configure a ToolCallGroup. +type ToolCallGroupOptions struct { + // Title replaces the built-in "N tool calls". + Title string + Still bool +} + +// ToolCallGroup folds tool calls under a count, time, failures summary. +func ToolCallGroup(c *ui.Context, open *bool, calls []ToolCall, opts ToolCallGroupOptions) ChoiceResult { + if open == nil { + panic("mujica: ToolCallGroup needs open") + } + seen := make(map[string]bool, len(calls)) + var total time.Duration + failed, running := 0, false + for _, call := range calls { + if call.ID == "" || seen[call.ID] { + panic(fmt.Sprintf("mujica: ToolCallGroup call IDs must be unique and set, got %q", call.ID)) + } + seen[call.ID] = true + total += call.Duration + failed += agentB2I(call.State == AgentFailed) + running = running || call.State == AgentRunning + } + k := Tokens(c) + u := Density(c).Unit() + title := opts.Title + if title == "" { + title = fmt.Sprintf(msg(c, "tool_call_group.count"), len(calls)) + } + state := AgentDone + switch { + case running: + state = AgentRunning + case failed > 0: + state = AgentFailed + } + summary := title + " · " + agentDuration(total) + if failed > 0 { + summary += " · " + fmt.Sprintf(msg(c, "tool_call_group.failed"), failed) + } + return Collapsible(c, open, CollapsibleOptions{Title: summary, Trigger: func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + agentMark(c, state, 16, opts.Still) + ui.Text(c, title).FontWeight(600).SingleLine() + agentCaption(c, agentDuration(total)) + if failed > 0 { + ui.Text(c, fmt.Sprintf(msg(c, "tool_call_group.failed"), failed)).TextColor(k.Danger). + FontSize(FontSize(c, theme.CaptionSize+1)).SingleLine() + } + }) + }}, func() { + for _, call := range calls { + ui.Column(c).Key(call.ID).Children(func() { ToolCallCard(c, call, ToolCallCardOptions{Still: opts.Still}) }) + } + }) +} + +func agentB2I(b bool) int { + if b { + return 1 + } + return 0 +} diff --git a/tool_call_group_test.go b/tool_call_group_test.go new file mode 100644 index 0000000..2e96b31 --- /dev/null +++ b/tool_call_group_test.go @@ -0,0 +1,72 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +var toolCallGroupSample = []ToolCall{ + {ID: "a", Name: "list_dir", State: AgentDone, Duration: 300 * time.Millisecond}, + {ID: "b", Name: "read_file", State: AgentFailed, Error: "not found", Duration: 1200 * time.Millisecond}, + {ID: "c", Name: "grep", State: AgentDone, Duration: 500 * time.Millisecond}, +} + +func TestToolCallGroupSummaryAndFold(t *testing.T) { + open, changes := false, 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if ToolCallGroup(c, &open, toolCallGroupSample, ToolCallGroupOptions{}).Changed() { + changes++ + } + }, 500, 600) + for _, s := range []string{"3 tool calls", "2.0 s", "1 failed"} { + if !tt.HasText(s) { + t.Fatalf("missing %q in %q", s, tt.Texts()) + } + } + if tt.HasText("read_file") { + t.Fatal("calls shown while folded") + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if !open || changes != 1 || !tt.HasText("read_file") || !tt.HasText("grep") { + t.Fatalf("open %v changes %d texts %q", open, changes, tt.Texts()) + } +} + +func TestToolCallGroupRunningAndEmpty(t *testing.T) { + open := false + calls := []ToolCall{{ID: "x", Name: "fetch", State: AgentRunning}} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ToolCallGroup(c, &open, calls, ToolCallGroupOptions{Title: "Research", Still: true}) + ToolCallGroup(c, &open, nil, ToolCallGroupOptions{}) + }, 500, 300) + if !tt.HasText("Research") || !tt.HasText("0 tool calls") || tt.HasText("1 failed") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestToolCallGroupRejectsDuplicateIDs(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + open := false + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ToolCallGroup(c, &open, []ToolCall{{ID: "a", Name: "x"}, {ID: "a", Name: "y"}}, ToolCallGroupOptions{}) + }, 200, 200) +} + +func TestToolCallGroupSnapshot(t *testing.T) { + snapshot(t, "tool_call_group", 460, 330, func(c *ui.Context) { + open := true + ui.Column(c).Padding(16).Children(func() { + ToolCallGroup(c, &open, toolCallGroupSample, ToolCallGroupOptions{}) + }) + }) +} From e789683ffa969856257dccb80cdcf3dd06f857c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 5 Oct 2026 14:31:37 -0400 Subject: [PATCH 08/13] Git: components 301-320 --- ansi_text.go | 67 ++++ ansi_text_test.go | 59 +++ blame_view.go | 107 +++++ blame_view_test.go | 96 +++++ branch_list.go | 120 ++++++ branch_list_test.go | 85 ++++ branch_selector.go | 211 ++++++++++ branch_selector_test.go | 85 ++++ changes_list.go | 163 ++++++++ changes_list_test.go | 95 +++++ command_block.go | 158 ++++++++ command_block_test.go | 105 +++++ commit_graph.go | 204 ++++++++++ commit_graph_test.go | 98 +++++ commit_input.go | 106 +++++ commit_input_test.go | 101 +++++ commit_list.go | 105 +++++ commit_list_test.go | 91 +++++ conflict_resolver.go | 220 +++++++++++ conflict_resolver_test.go | 86 ++++ diff_stat.go | 72 ++++ diff_stat_test.go | 60 +++ diff_viewer.go | 225 +++++++++++ diff_viewer_test.go | 105 +++++ docs/components/301-diff-viewer.md | 52 +++ docs/components/302-inline-diff.md | 44 +++ docs/components/303-three-way-merge.md | 53 +++ docs/components/304-conflict-resolver.md | 51 +++ docs/components/305-changes-list.md | 66 ++++ docs/components/306-commit-input.md | 62 +++ docs/components/307-commit-graph.md | 67 ++++ docs/components/308-commit-list.md | 53 +++ docs/components/309-branch-selector.md | 64 +++ docs/components/310-branch-list.md | 62 +++ docs/components/311-tag-list.md | 59 +++ docs/components/312-stash-list.md | 58 +++ docs/components/313-blame-view.md | 62 +++ docs/components/314-file-history.md | 53 +++ docs/components/315-pull-request-card.md | 62 +++ docs/components/316-review-comment.md | 66 ++++ docs/components/317-diff-stat.md | 45 +++ docs/components/318-git-status-badge.md | 44 +++ docs/components/319-command-block.md | 62 +++ docs/components/320-ansi-text.md | 45 +++ example_git_test.go | 263 +++++++++++++ examples/gallery/pages_git.go | 297 +++++++++++++- examples/gallery/pages_git_cards.go | 134 +++++++ examples/gallery/pages_git_demos.go | 367 ++++++++++++++++++ file_history.go | 48 +++ file_history_test.go | 65 ++++ git_status_badge.go | 72 ++++ git_status_badge_test.go | 65 ++++ icons/svg/archive.svg | 16 + icons/svg/arrow-left-right.svg | 17 + icons/svg/chevrons-up-down.svg | 15 + icons/svg/git-branch.svg | 16 + icons/svg/git-commit-horizontal.svg | 16 + icons/svg/git-merge.svg | 16 + icons/svg/git-pull-request.svg | 17 + icons/svg/history.svg | 16 + icons/svg/message-square.svg | 14 + icons/svg/reply.svg | 15 + icons/svg/rotate-ccw.svg | 15 + icons/svg/tag.svg | 15 + inline_diff.go | 66 ++++ inline_diff_test.go | 49 +++ internal/diff.go | 60 ++- internal/diff_word_test.go | 38 ++ internal/git.go | 76 ++++ internal/git_test.go | 41 ++ messages_git.go | 114 ++++++ pull_request_card.go | 179 +++++++++ pull_request_card_test.go | 82 ++++ review_comment.go | 127 ++++++ review_comment_test.go | 97 +++++ stash_list.go | 58 +++ stash_list_test.go | 72 ++++ tag_list.go | 50 +++ tag_list_test.go | 64 +++ testdata/snapshots/darwin/ansi_text-dark.png | Bin 0 -> 20216 bytes testdata/snapshots/darwin/ansi_text-light.png | Bin 0 -> 19973 bytes testdata/snapshots/darwin/blame_view-dark.png | Bin 0 -> 23174 bytes .../snapshots/darwin/blame_view-light.png | Bin 0 -> 22795 bytes .../snapshots/darwin/branch_list-dark.png | Bin 0 -> 17777 bytes .../snapshots/darwin/branch_list-light.png | Bin 0 -> 17219 bytes .../snapshots/darwin/branch_selector-dark.png | Bin 0 -> 14174 bytes .../darwin/branch_selector-light.png | Bin 0 -> 15585 bytes .../snapshots/darwin/changes_list-dark.png | Bin 0 -> 16290 bytes .../snapshots/darwin/changes_list-light.png | Bin 0 -> 15959 bytes .../snapshots/darwin/command_block-dark.png | Bin 0 -> 22032 bytes .../snapshots/darwin/command_block-light.png | Bin 0 -> 21418 bytes .../snapshots/darwin/commit_graph-dark.png | Bin 0 -> 26659 bytes .../snapshots/darwin/commit_graph-light.png | Bin 0 -> 25685 bytes .../snapshots/darwin/commit_input-dark.png | Bin 0 -> 14947 bytes .../snapshots/darwin/commit_input-light.png | Bin 0 -> 14411 bytes .../snapshots/darwin/commit_list-dark.png | Bin 0 -> 26509 bytes .../snapshots/darwin/commit_list-light.png | Bin 0 -> 25597 bytes .../darwin/conflict_resolver-dark.png | Bin 0 -> 36981 bytes .../darwin/conflict_resolver-light.png | Bin 0 -> 35612 bytes testdata/snapshots/darwin/diff_stat-dark.png | Bin 0 -> 3007 bytes testdata/snapshots/darwin/diff_stat-light.png | Bin 0 -> 2949 bytes .../snapshots/darwin/diff_viewer-dark.png | Bin 0 -> 30001 bytes .../snapshots/darwin/diff_viewer-light.png | Bin 0 -> 29137 bytes .../snapshots/darwin/file_history-dark.png | Bin 0 -> 24432 bytes .../snapshots/darwin/file_history-light.png | Bin 0 -> 23448 bytes .../darwin/git_status_badge-dark.png | Bin 0 -> 5894 bytes .../darwin/git_status_badge-light.png | Bin 0 -> 5798 bytes .../snapshots/darwin/inline_diff-dark.png | Bin 0 -> 14515 bytes .../snapshots/darwin/inline_diff-light.png | Bin 0 -> 13783 bytes .../darwin/pull_request_card-dark.png | Bin 0 -> 28452 bytes .../darwin/pull_request_card-light.png | Bin 0 -> 28065 bytes .../snapshots/darwin/review_comment-dark.png | Bin 0 -> 27660 bytes .../snapshots/darwin/review_comment-light.png | Bin 0 -> 26334 bytes testdata/snapshots/darwin/stash_list-dark.png | Bin 0 -> 13961 bytes .../snapshots/darwin/stash_list-light.png | Bin 0 -> 13563 bytes testdata/snapshots/darwin/tag_list-dark.png | Bin 0 -> 8883 bytes testdata/snapshots/darwin/tag_list-light.png | Bin 0 -> 8733 bytes .../snapshots/darwin/three_way_merge-dark.png | Bin 0 -> 22445 bytes .../darwin/three_way_merge-light.png | Bin 0 -> 21696 bytes three_way_merge.go | 327 ++++++++++++++++ three_way_merge_test.go | 80 ++++ 121 files changed, 7031 insertions(+), 2 deletions(-) create mode 100644 ansi_text.go create mode 100644 ansi_text_test.go create mode 100644 blame_view.go create mode 100644 blame_view_test.go create mode 100644 branch_list.go create mode 100644 branch_list_test.go create mode 100644 branch_selector.go create mode 100644 branch_selector_test.go create mode 100644 changes_list.go create mode 100644 changes_list_test.go create mode 100644 command_block.go create mode 100644 command_block_test.go create mode 100644 commit_graph.go create mode 100644 commit_graph_test.go create mode 100644 commit_input.go create mode 100644 commit_input_test.go create mode 100644 commit_list.go create mode 100644 commit_list_test.go create mode 100644 conflict_resolver.go create mode 100644 conflict_resolver_test.go create mode 100644 diff_stat.go create mode 100644 diff_stat_test.go create mode 100644 diff_viewer.go create mode 100644 diff_viewer_test.go create mode 100644 docs/components/301-diff-viewer.md create mode 100644 docs/components/302-inline-diff.md create mode 100644 docs/components/303-three-way-merge.md create mode 100644 docs/components/304-conflict-resolver.md create mode 100644 docs/components/305-changes-list.md create mode 100644 docs/components/306-commit-input.md create mode 100644 docs/components/307-commit-graph.md create mode 100644 docs/components/308-commit-list.md create mode 100644 docs/components/309-branch-selector.md create mode 100644 docs/components/310-branch-list.md create mode 100644 docs/components/311-tag-list.md create mode 100644 docs/components/312-stash-list.md create mode 100644 docs/components/313-blame-view.md create mode 100644 docs/components/314-file-history.md create mode 100644 docs/components/315-pull-request-card.md create mode 100644 docs/components/316-review-comment.md create mode 100644 docs/components/317-diff-stat.md create mode 100644 docs/components/318-git-status-badge.md create mode 100644 docs/components/319-command-block.md create mode 100644 docs/components/320-ansi-text.md create mode 100644 example_git_test.go create mode 100644 examples/gallery/pages_git_cards.go create mode 100644 examples/gallery/pages_git_demos.go create mode 100644 file_history.go create mode 100644 file_history_test.go create mode 100644 git_status_badge.go create mode 100644 git_status_badge_test.go create mode 100644 icons/svg/archive.svg create mode 100644 icons/svg/arrow-left-right.svg create mode 100644 icons/svg/chevrons-up-down.svg create mode 100644 icons/svg/git-branch.svg create mode 100644 icons/svg/git-commit-horizontal.svg create mode 100644 icons/svg/git-merge.svg create mode 100644 icons/svg/git-pull-request.svg create mode 100644 icons/svg/history.svg create mode 100644 icons/svg/message-square.svg create mode 100644 icons/svg/reply.svg create mode 100644 icons/svg/rotate-ccw.svg create mode 100644 icons/svg/tag.svg create mode 100644 inline_diff.go create mode 100644 inline_diff_test.go create mode 100644 internal/diff_word_test.go create mode 100644 internal/git.go create mode 100644 internal/git_test.go create mode 100644 messages_git.go create mode 100644 pull_request_card.go create mode 100644 pull_request_card_test.go create mode 100644 review_comment.go create mode 100644 review_comment_test.go create mode 100644 stash_list.go create mode 100644 stash_list_test.go create mode 100644 tag_list.go create mode 100644 tag_list_test.go create mode 100644 testdata/snapshots/darwin/ansi_text-dark.png create mode 100644 testdata/snapshots/darwin/ansi_text-light.png create mode 100644 testdata/snapshots/darwin/blame_view-dark.png create mode 100644 testdata/snapshots/darwin/blame_view-light.png create mode 100644 testdata/snapshots/darwin/branch_list-dark.png create mode 100644 testdata/snapshots/darwin/branch_list-light.png create mode 100644 testdata/snapshots/darwin/branch_selector-dark.png create mode 100644 testdata/snapshots/darwin/branch_selector-light.png create mode 100644 testdata/snapshots/darwin/changes_list-dark.png create mode 100644 testdata/snapshots/darwin/changes_list-light.png create mode 100644 testdata/snapshots/darwin/command_block-dark.png create mode 100644 testdata/snapshots/darwin/command_block-light.png create mode 100644 testdata/snapshots/darwin/commit_graph-dark.png create mode 100644 testdata/snapshots/darwin/commit_graph-light.png create mode 100644 testdata/snapshots/darwin/commit_input-dark.png create mode 100644 testdata/snapshots/darwin/commit_input-light.png create mode 100644 testdata/snapshots/darwin/commit_list-dark.png create mode 100644 testdata/snapshots/darwin/commit_list-light.png create mode 100644 testdata/snapshots/darwin/conflict_resolver-dark.png create mode 100644 testdata/snapshots/darwin/conflict_resolver-light.png create mode 100644 testdata/snapshots/darwin/diff_stat-dark.png create mode 100644 testdata/snapshots/darwin/diff_stat-light.png create mode 100644 testdata/snapshots/darwin/diff_viewer-dark.png create mode 100644 testdata/snapshots/darwin/diff_viewer-light.png create mode 100644 testdata/snapshots/darwin/file_history-dark.png create mode 100644 testdata/snapshots/darwin/file_history-light.png create mode 100644 testdata/snapshots/darwin/git_status_badge-dark.png create mode 100644 testdata/snapshots/darwin/git_status_badge-light.png create mode 100644 testdata/snapshots/darwin/inline_diff-dark.png create mode 100644 testdata/snapshots/darwin/inline_diff-light.png create mode 100644 testdata/snapshots/darwin/pull_request_card-dark.png create mode 100644 testdata/snapshots/darwin/pull_request_card-light.png create mode 100644 testdata/snapshots/darwin/review_comment-dark.png create mode 100644 testdata/snapshots/darwin/review_comment-light.png create mode 100644 testdata/snapshots/darwin/stash_list-dark.png create mode 100644 testdata/snapshots/darwin/stash_list-light.png create mode 100644 testdata/snapshots/darwin/tag_list-dark.png create mode 100644 testdata/snapshots/darwin/tag_list-light.png create mode 100644 testdata/snapshots/darwin/three_way_merge-dark.png create mode 100644 testdata/snapshots/darwin/three_way_merge-light.png create mode 100644 three_way_merge.go create mode 100644 three_way_merge_test.go diff --git a/ansi_text.go b/ansi_text.go new file mode 100644 index 0000000..0795f99 --- /dev/null +++ b/ansi_text.go @@ -0,0 +1,67 @@ +package mujica + +import ( + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// AnsiTextOptions configure an AnsiText. +type AnsiTextOptions struct { + // Wrap breaks long lines at the width. + Wrap bool +} + +// AnsiText renders terminal output with its SGR styles. +func AnsiText(c *ui.Context, text string, opts AnsiTextOptions) *ui.Element { + k := Tokens(c) + col := ui.Column(c).Font(theme.MonoFont).TextColor(k.Text).Shrink(0) + col.Children(func() { + var st internal.AnsiStyle + for _, line := range strings.Split(text, "\n") { + var spans []internal.AnsiSpan + spans, st = internal.ParseAnsi(line, st) + out := make([]ui.Span, 0, len(spans)) + for _, s := range spans { + out = append(out, ansiTextSpan(k, s)) + } + if len(out) == 0 { + out = append(out, ui.Span{Text: " "}) + } + t := ui.RichText(c, out...) + if !opts.Wrap { + t.NoWrap() + } + } + }) + return col +} + +// ansiTextSpan maps one parsed span onto theme-readable colors. +func ansiTextSpan(k theme.Tokens, s internal.AnsiSpan) ui.Span { + fg, hasFG := internal.AnsiResolve(k.Dark, s.Style.FG) + if !hasFG { + fg = k.Text + } + bg, hasBG := internal.AnsiResolve(k.Dark, s.Style.BG) + if s.Style.Inverse { + if !hasBG { + bg = k.Surface + } + fg, bg, hasBG = bg, fg, true + } + if s.Style.Dim { + fg = fg.Mix(k.Surface, 0.4) + } + out := ui.Span{Text: s.Text, Color: fg, Italic: s.Style.Italic, Underline: s.Style.Underline, Strikethrough: s.Style.Strike} + if s.Style.Bold { + out.Weight = 700 + } + if hasBG { + out.Background = bg + } + return out +} diff --git a/ansi_text_test.go b/ansi_text_test.go new file mode 100644 index 0000000..1107284 --- /dev/null +++ b/ansi_text_test.go @@ -0,0 +1,59 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +func TestAnsiTextStripsSGRKeepsUnknown(t *testing.T) { + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + AnsiText(c, "\x1b[1;31merror\x1b[0m: bad\n\x1b[2Kcleared", AnsiTextOptions{}) + }, 400, 100) + if !tt.HasText("error: bad") { + t.Fatalf("styled line: %q", tt.Texts()) + } + if !tt.HasText("\x1b[2Kcleared") { + t.Fatalf("unknown escape not kept: %q", tt.Texts()) + } +} + +func TestAnsiTextSpanStyles(t *testing.T) { + k := theme.Light() + parse := func(s string) ui.Span { + spans, _ := internal.ParseAnsi(s, internal.AnsiStyle{}) + return ansiTextSpan(k, spans[0]) + } + red, _ := internal.AnsiResolve(false, internal.AnsiColor{Kind: internal.AnsiIndexed, Index: 1}) + if s := parse("\x1b[1;3;4;31mx"); s.Color != red || s.Weight != 700 || !s.Italic || !s.Underline { + t.Errorf("bold italic underline red: %+v", s) + } + if s := parse("\x1b[38;5;196mx"); s.Color != ui.RGB(255, 0, 0) { + t.Errorf("256 color: %+v", s.Color) + } + if s := parse("\x1b[38;2;10;20;30;48;2;1;2;3mx"); s.Color != ui.RGB(10, 20, 30) || s.Background != ui.RGB(1, 2, 3) { + t.Errorf("true color: %+v", s) + } + if s := parse("\x1b[7mx"); s.Color != k.Surface || s.Background != k.Text { + t.Errorf("inverse: %+v", s) + } + if s := parse("\x1b[9mx"); !s.Strikethrough || s.Color != k.Text { + t.Errorf("strike: %+v", s) + } +} + +func TestAnsiTextSnapshot(t *testing.T) { + snapshot(t, "ansi_text", 520, 200, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + AnsiText(c, "\x1b[1mBuilding\x1b[0m mujica \x1b[2m(v1.1)\x1b[0m\n"+ + "\x1b[32m✓\x1b[0m 300 passed \x1b[31m✗\x1b[0m 2 failed \x1b[33m!\x1b[0m 1 skipped\n"+ + "\x1b[30m0\x1b[31m1\x1b[32m2\x1b[33m3\x1b[34m4\x1b[35m5\x1b[36m6\x1b[37m7\x1b[90m8\x1b[91m9\x1b[92mA\x1b[93mB\x1b[94mC\x1b[95mD\x1b[96mE\x1b[97mF\x1b[0m\n"+ + "\x1b[38;5;208m256-color\x1b[0m \x1b[38;2;125;32;52mtrue color\x1b[0m \x1b[4munderline\x1b[0m \x1b[3mitalic\x1b[0m \x1b[7m inverse \x1b[0m\n"+ + "\x1b[41;97m FAIL \x1b[0m kept: \x1b[2K", AnsiTextOptions{}) + }) + }) +} diff --git a/blame_view.go b/blame_view.go new file mode 100644 index 0000000..0bac5bc --- /dev/null +++ b/blame_view.go @@ -0,0 +1,107 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strconv" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// BlameLine is a source line and its last commit. +type BlameLine struct { + Hash string + Author string + When time.Time + Summary string + Text string +} + +// BlameViewState keeps scroll place and highlight state. +type BlameViewState struct { + list ui.ListState + blocks []bool + src *BlameLine + n int + lang string +} + +// BlameViewOptions configure a BlameView. +type BlameViewOptions struct { + // Language picks syntax colors, as "go"; empty is plain. + Language string + // TimeFormat lays out commit dates; empty means "2006-01-02". + TimeFormat string +} + +// BlameView shows code with its commits; give it a height. +func BlameView(c *ui.Context, s *BlameViewState, lines []BlameLine, opts BlameViewOptions) *ui.Element { + var first *BlameLine + if len(lines) > 0 { + first = &lines[0] + } + if first != s.src || len(lines) != s.n || opts.Language != s.lang { + s.blocks = blameViewBlocks(lines, opts.Language) + s.src, s.n, s.lang = first, len(lines), opts.Language + slog.Debug("mujica: blame view index", "lines", len(lines)) + } + layout := opts.TimeFormat + if layout == "" { + layout = "2006-01-02" + } + k := Tokens(c) + d := Density(c) + u := d.Unit() + digits := float32(len(strconv.Itoa(len(lines)))) + s.list.Label = func(i int) string { return lines[i].Text } + e := ui.List(c, &s.list, len(lines), func(i int) { + ln := lines[i] + if ln.Hash == "" { + panic("mujica: BlameLine needs a Hash") + } + head := i == 0 || lines[i-1].Hash != ln.Hash + row := ui.Row(c).AlignItems(ui.Stretch).MinHeight(theme.MinHitSize) + if head && i > 0 { + row.Draw(func(p *ui.Painter, r ui.Rect) { p.Fill(ui.Rect{X: r.X, Y: r.Y, W: r.W, H: 1}, k.Border, 0) }) + } + row.Children(func() { + gut := ui.Row(c).Width(240).Shrink(0).AlignItems(ui.Center).Gap(u*2).Padding(0, u*3).Background(k.Surface). + Label(fmt.Sprintf(msg(c, "blame_view.line"), i+1, ln.Author, gitShortHash(ln.Hash))) + gut.Tooltip(fmt.Sprintf("%s\n%s · %s\n%s", ln.Hash, ln.Author, ln.When.Format(layout), ln.Summary)) + if gut.Hovered() { + gut.Background(k.SurfaceHover) + } + gut.Transition(colorFade) + gut.Children(func() { + if !head { + return + } + small := FontSize(c, theme.CaptionSize) + ui.Text(c, gitShortHash(ln.Hash)).Font(theme.MonoFont).FontSize(small).TextColor(k.AccentText).Shrink(0) + ui.Text(c, ln.Author).FontSize(small).SingleLine().Grow(1).MinWidth(0) + ui.Text(c, ln.When.Format(layout)).FontSize(small).FontFeatures("tnum").TextColor(k.TextMuted).Shrink(0) + }) + ui.Text(c, strconv.Itoa(i+1)).Font(theme.MonoFont).FontSize(FontSize(c, theme.CaptionSize)).FontFeatures("tnum"). + TextColor(k.TextMuted).Width(digits*8+u*4).TextAlign(ui.End).Padding(u, u*2, 0, 0).Shrink(0) + spans, _ := internal.CodeSpans(k, opts.Language, ln.Text, s.blocks[i]) + ui.RichText(c, spans...).Font(theme.MonoFont).NoWrap().Padding(u, u*2).AlignSelf(ui.Center) + }) + }) + e.Background(k.Background).Border(theme.BorderWidth, k.Border).Radius(theme.ControlRadius) + return e +} + +// blameViewBlocks records where block comments are open. +func blameViewBlocks(lines []BlameLine, language string) []bool { + blocks := make([]bool, len(lines)) + open := false + for i, ln := range lines { + blocks[i] = open + _, open = internal.Highlight(language, ln.Text, open) + } + return blocks +} diff --git a/blame_view_test.go b/blame_view_test.go new file mode 100644 index 0000000..3120bf7 --- /dev/null +++ b/blame_view_test.go @@ -0,0 +1,96 @@ +package mujica + +import ( + "fmt" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func blameSample() []BlameLine { + a := BlameLine{Hash: gitTestHash(1), Author: "Sakiko", When: gitTestTime, Summary: "Add the graph"} + b := BlameLine{Hash: gitTestHash(2), Author: "Uika", When: gitTestTime, Summary: "Comment the lanes"} + lines := []string{"package mujica", "", "/* lanes", " per row */", "func lanes() int {", "\treturn 2", "}"} + out := make([]BlameLine, len(lines)) + for i, s := range lines { + ln := a + if i >= 2 && i <= 3 { + ln = b + } + ln.Text = s + out[i] = ln + } + return out +} + +func TestBlameViewGroupsCommits(t *testing.T) { + var s BlameViewState + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + BlameView(c, &s, blameSample(), BlameViewOptions{Language: "go"}).Height(300) + }, 700, 340) + count := 0 + for _, txt := range tt.Texts() { + if txt == "Sakiko" || txt == "Uika" { + count++ + } + } + // Three runs: lines 1-2, 3-4 and 5-7. + if count != 3 { + t.Fatalf("author shown %d times, want 3: %q", count, tt.Texts()) + } + if _, ok := tt.Find(fmt.Sprintf("Line 4, Uika, %s", gitShortHash(gitTestHash(2)))); !ok { + t.Fatal("line 4 gutter not named") + } + if !s.blocks[3] || s.blocks[4] { + t.Fatalf("block comment state %v", s.blocks) + } +} + +func TestBlameViewHoverDetails(t *testing.T) { + var s BlameViewState + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + BlameView(c, &s, blameSample(), BlameViewOptions{}).Height(300) + }, 700, 340) + r, _ := tt.Find("Uika") + tt.Move(r.X+2, r.Y+2) + time.Sleep(650 * time.Millisecond) + tt.Move(r.X+3, r.Y+2) + tt.Frame() + if tt.HasText(gitTestHash(2) + "\nUika · 2026-10-05\nComment the lanes") { + return + } + t.Fatalf("no hover details: %q", tt.Texts()) +} + +func TestBlameViewVirtualized(t *testing.T) { + lines := make([]BlameLine, 100000) + for i := range lines { + lines[i] = BlameLine{Hash: gitTestHash(i / 3), Author: "Sakiko", When: gitTestTime, Text: fmt.Sprintf("line %d", i)} + } + var s BlameViewState + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + BlameView(c, &s, lines, BlameViewOptions{}).Height(400) + }, 700, 440) + if n := len(tt.Texts()); n > 400 { + t.Fatalf("%d texts for 100,000 lines", n) + } + blocks := &s.blocks[0] + tt.Frame() + if &s.blocks[0] != blocks { + t.Fatal("highlight state recomputed without a data change") + } +} + +func TestBlameViewSnapshot(t *testing.T) { + lines := blameSample() + snapshot(t, "blame_view", 640, 300, func(c *ui.Context) { + s := ui.Local(c.Root(), "blame", func() *BlameViewState { return &BlameViewState{} }) + ui.Column(c).Padding(16).Children(func() { + BlameView(c, *s, lines, BlameViewOptions{Language: "go"}).Height(260) + }) + }) +} diff --git a/branch_list.go b/branch_list.go new file mode 100644 index 0000000..7e7cfe7 --- /dev/null +++ b/branch_list.go @@ -0,0 +1,120 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// Branch is a local or remote branch. +type Branch struct { + // Name is unique; remote names carry the remote, as origin/main. + Name string + Remote bool + // Current marks the checked-out branch. + Current bool + // Upstream is the tracked remote branch, if any. + Upstream string + Ahead, Behind int +} + +// GitAction is a row action of a version-control list. +type GitAction struct { + ID string + Label string + // Icon names an icon from icons/. + Icon string +} + +// BranchListOptions configure a BranchList. +type BranchListOptions struct { + // Actions show on every row; Action returns their IDs. + Actions []GitAction + Status DataStatus + Error string +} + +// BranchList shows branches with upstream and ahead/behind counts. +func BranchList(c *ui.Context, s *ListState[string], branches []Branch, opts BranchListOptions) GitListResult { + gitActionsCheck(opts.Actions) + var r GitListResult + v := List(c, s, len(branches), ListOptions[string]{ + Key: func(i int) string { return branchKey(branches[i]) }, + Label: func(i int) string { return branches[i].Name }, + Status: opts.Status, Error: opts.Error, Empty: msg(c, "branch_list.empty"), + }, func(i int) { + b := branches[i] + branchListRow(c, b) + gitRowActions(c, opts.Actions, b.Name, &r) + }) + r.Element, r.changed, r.submitted = v.Element, v.Changed(), v.Submitted() + return r +} + +func branchKey(b Branch) string { + if b.Name == "" { + panic("mujica: Branch needs a Name") + } + if b.Ahead < 0 || b.Behind < 0 { + panic("mujica: Branch Ahead and Behind must not be negative") + } + return b.Name +} + +func branchListRow(c *ui.Context, b Branch) { + k := Tokens(c) + u := Density(c).Unit() + small := FontSize(c, theme.CaptionSize) + mark := ui.Box(c).Size(16, 16).Shrink(0).Center().Role(ui.RoleNone) + if b.Current { + mark.TextColor(k.AccentText).Children(func() { ui.Icon(c, icons.Must("check")).Size(14, 14) }) + } + ui.Icon(c, icons.Must("git-branch")).Size(14, 14).Shrink(0).TextColor(k.TextMuted) + name := ui.Text(c, b.Name).SingleLine().MinWidth(0).Shrink(1) + if b.Current { + name.FontWeight(600) + ui.Text(c, msg(c, "branch_list.current")).FontSize(small).TextColor(k.AccentText).Shrink(0) + } + ui.Spacer(c) + if b.Upstream != "" { + ui.Row(c).Gap(u).AlignItems(ui.Center).Shrink(0).TextColor(k.TextMuted).Children(func() { + ui.Text(c, b.Upstream).FontSize(small).SingleLine().MaxWidth(160) + if b.Ahead > 0 { + ui.Text(c, fmt.Sprintf("↑%d", b.Ahead)).FontSize(small).FontFeatures("tnum").Label(fmt.Sprintf(msg(c, "branch_list.ahead"), b.Ahead)) + } + if b.Behind > 0 { + ui.Text(c, fmt.Sprintf("↓%d", b.Behind)).FontSize(small).FontFeatures("tnum").Label(fmt.Sprintf(msg(c, "branch_list.behind"), b.Behind)) + } + }) + } +} + +// gitActionsCheck panics on incomplete or duplicate actions. +func gitActionsCheck(actions []GitAction) { + seen := map[string]bool{} + for _, a := range actions { + if a.ID == "" || a.Label == "" || a.Icon == "" { + panic("mujica: GitAction needs an ID, Label and Icon") + } + if seen[a.ID] { + panic("mujica: duplicate GitAction " + a.ID) + } + seen[a.ID] = true + icons.Must(a.Icon) + } +} + +// gitRowActions shows row actions and records the one used. +func gitRowActions(c *ui.Context, actions []GitAction, item string, r *GitListResult) { + for _, a := range actions { + b := iconAction(c, icons.Must(a.Icon), a.Label).Tooltip(a.Label).Shrink(0) + if b.Clicked() && !b.IsDisabled() { + r.action, r.item = a.ID, item + slog.Debug("mujica: git list action", "action", a.ID, "item", item) + } + } +} diff --git a/branch_list_test.go b/branch_list_test.go new file mode 100644 index 0000000..51afde4 --- /dev/null +++ b/branch_list_test.go @@ -0,0 +1,85 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func branchSample() []Branch { + return []Branch{ + {Name: "main", Current: true, Upstream: "origin/main", Ahead: 2, Behind: 1}, + {Name: "feature/graph", Upstream: "origin/feature/graph"}, + {Name: "fix/blame"}, + {Name: "origin/main", Remote: true}, + {Name: "origin/release", Remote: true}, + } +} + +func TestBranchListRowsAndActions(t *testing.T) { + var s ListState[string] + var acted [][2]string + actions := []GitAction{{ID: "checkout", Label: "Check out", Icon: "git-branch"}, {ID: "delete", Label: "Delete", Icon: "trash-2"}} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := BranchList(c, &s, branchSample(), BranchListOptions{Actions: actions}) + r.Element.Height(300) + if a, item, ok := r.Action(); ok { + acted = append(acted, [2]string{a, item}) + } + }, 700, 340) + if !tt.HasText("current") || !tt.HasText("origin/feature/graph") { + t.Fatalf("current, ahead, behind: %q", tt.Texts()) + } + for _, name := range []string{"2 ahead of upstream", "1 behind upstream"} { + if _, ok := tt.Find(name); !ok { + t.Fatalf("%q not shown", name) + } + } + r, _ := tt.Find("fix/blame") + if err := tt.Click("fix/blame"); err != nil { + t.Fatal(err) + } + if key, _ := s.Selected(); key != "fix/blame" { + t.Fatalf("selected %q", key) + } + // The third row's Delete button sits at the row's right end. + tt.ClickAt(700-60, r.Y+r.H/2) + if len(acted) != 1 || acted[0] != [2]string{"delete", "fix/blame"} { + t.Fatalf("actions %q", acted) + } +} + +func TestBranchListInvalid(t *testing.T) { + for name, tc := range map[string]struct { + b []Branch + a []GitAction + }{ + "name": {[]Branch{{}}, nil}, + "ahead": {[]Branch{{Name: "x", Ahead: -1}}, nil}, + "action": {nil, []GitAction{{ID: "x"}}}, + "dup": {nil, []GitAction{{ID: "x", Label: "X", Icon: "x"}, {ID: "x", Label: "Y", Icon: "x"}}}, + } { + t.Run(name, func(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + var s ListState[string] + BranchList(c, &s, tc.b, BranchListOptions{Actions: tc.a}).Element.Height(100) + }, 300, 120, 1) + }) + } +} + +func TestBranchListSnapshot(t *testing.T) { + snapshot(t, "branch_list", 600, 260, func(c *ui.Context) { + s := ui.Local(c.Root(), "list", func() *ListState[string] { return &ListState[string]{} }) + ui.Column(c).Padding(16).Children(func() { + BranchList(c, *s, branchSample(), BranchListOptions{Actions: []GitAction{{ID: "checkout", Label: "Check out", Icon: "git-branch"}}}).Element.Height(220) + }) + }) +} diff --git a/branch_selector.go b/branch_selector.go new file mode 100644 index 0000000..642b4ab --- /dev/null +++ b/branch_selector.go @@ -0,0 +1,211 @@ +package mujica + +import ( + "log/slog" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// BranchSelectorOptions configure a BranchSelector. +type BranchSelectorOptions struct { + // AllowCreate offers to create a branch named by the search. + AllowCreate bool + Disabled bool +} + +// BranchSelectorResult is a built BranchSelector and its events. +type BranchSelectorResult struct { + Element *ui.Element + changed bool + create string +} + +// Changed reports a new branch in *selected this frame. +func (r BranchSelectorResult) Changed() bool { return r.changed } + +// Created returns a branch name to create this frame. +func (r BranchSelectorResult) Created() (string, bool) { return r.create, r.create != "" } + +type branchSelectorState struct { + open, wasOpen bool + query string + hl int + reveal bool + // found caches the filter of src for query fq. + found []Branch + fq string + src *Branch + n int +} + +// BranchSelector chooses a branch from a searchable popup. +func BranchSelector(c *ui.Context, selected *string, branches []Branch, opts BranchSelectorOptions) BranchSelectorResult { + for _, b := range branches { + branchKey(b) + } + k := Tokens(c) + d := Density(c) + u := d.Unit() + tr := ui.ButtonBase(c).MinHeight(d.ControlHeight()).Padding(0, u*3).Gap(u*2).Radius(theme.ControlRadius). + Background(k.Surface).Border(theme.BorderWidth, k.ControlBorder).Disabled(opts.Disabled). + Label(msg(c, "branch_selector.label") + ": " + *selected) + internal.Ring(tr, k.Focus, theme.ControlRadius) + if tr.Hovered() { + tr.Background(k.SurfaceHover) + } + tr.Transition(colorFade) + st := ui.Local(tr, "state", func() *branchSelectorState { return &branchSelectorState{} }) + s := *st + res := BranchSelectorResult{Element: tr} + if tr.Clicked() && !tr.IsDisabled() { + s.open = !s.open + } + if tr.IsDisabled() { + s.open = false + } + if s.open && !s.wasOpen { + s.query, s.hl = "", 0 + slog.Debug("mujica: branch selector open") + } + s.wasOpen = s.open + tr.Children(func() { + ui.Icon(c, icons.Must("git-branch")).Size(16, 16).TextColor(k.TextMuted) + ui.Text(c, *selected).SingleLine().MaxWidth(220) + ui.Icon(c, icons.Must("chevrons-up-down")).Size(14, 14).TextColor(k.TextMuted) + }) + b := tr.Bounds() + ui.PopoverBase(c, tr, &s.open, func(panel *ui.Element) { + overlayStyle(c, panel, overlayAnchored(c, panel, b)) + panel.Margin(6, 0, 0, 0).Padding(u * 2).Gap(u * 2).Width(300).MaxHeight(popoverRoom(c, b)).AlignItems(ui.Stretch) + var first *Branch + if len(branches) > 0 { + first = &branches[0] + } + if s.found == nil || s.fq != s.query || s.src != first || s.n != len(branches) { + s.found, s.fq, s.src, s.n = branchSelectorFilter(branches, s.query), s.query, first, len(branches) + } + found := s.found + create := opts.AllowCreate && strings.TrimSpace(s.query) != "" && !branchSelectorHas(branches, strings.TrimSpace(s.query)) + n := len(found) + if create { + n++ + } + in := TextInput(c, &s.query, TextInputOptions{Placeholder: msg(c, "branch_selector.search"), Label: msg(c, "branch_selector.search"), + Leading: func() { ui.Icon(c, icons.Must("search")).Size(14, 14).TextColor(k.TextMuted) }}) + in.Input.AutoFocus() + if in.Changed() { + s.hl, s.reveal = 0, true + } + switch { + case n == 0: + case in.Input.Shortcut(0, ui.KeyDown): + s.hl, s.reveal = (s.hl+1)%n, true + case in.Input.Shortcut(0, ui.KeyUp): + s.hl, s.reveal = (s.hl-1+n)%n, true + } + s.hl = max(0, min(s.hl, n-1)) + pick := -1 + if in.Submitted() && n > 0 { + pick = s.hl + } + ui.Scroll(c).Shrink(1).Gap(2).Role(ui.RoleList).Children(func() { + if n == 0 { + ui.Text(c, msg(c, "branch_selector.empty")).TextColor(k.TextMuted).Padding(u * 3) + } + group := -1 + for i, br := range found { + if g := branchSelectorGroup(br); g != group { + group = g + ui.Text(c, msg(c, []string{"branch_selector.local", "branch_selector.remote"}[g])).Font(theme.SerifFont). + FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.Ornament.Mix(k.Text, 0.35)).Padding(u*2, u*2, u, u*2) + } + if branchSelectorRow(c, s, i, br.Name, br.Name == *selected, "git-branch") { + pick = i + } + } + if create && branchSelectorRow(c, s, len(found), msg(c, "branch_selector.create")+" “"+strings.TrimSpace(s.query)+"”", false, "plus") { + pick = len(found) + } + }) + switch { + case pick < 0: + case pick == len(found): + res.create = strings.TrimSpace(s.query) + s.open = false + slog.Debug("mujica: branch selector create", "name", res.create) + default: + s.open = false + if found[pick].Name != *selected { + *selected, res.changed = found[pick].Name, true + slog.Debug("mujica: branch selector choose", "branch", *selected) + } + } + }) + return res +} + +// branchSelectorRow builds row i and reports a click on it. +func branchSelectorRow(c *ui.Context, s *branchSelectorState, i int, label string, current bool, icon string) bool { + k := Tokens(c) + d := Density(c) + u := d.Unit() + row := ui.Row(c).AlignItems(ui.Center).Gap(u*2).MinHeight(d.ControlHeight()).Padding(0, u*2).Radius(theme.ControlRadius). + Role(ui.RoleListItem).Label(label).Cursor(ui.CursorPointer) + if i == s.hl { + row.Background(k.Selection) + if s.reveal { + row.ScrollIntoView() + s.reveal = false + } + } else if row.Hovered() { + row.Background(k.SurfaceHover) + } + row.Transition(colorFade) + row.Children(func() { + ui.Icon(c, icons.Must(icon)).Size(14, 14).TextColor(k.TextMuted) + t := ui.Text(c, label).SingleLine().Grow(1).MinWidth(0) + if current { + t.FontWeight(600) + ui.Icon(c, icons.Must("check")).Size(14, 14).TextColor(k.AccentText) + } + }) + return row.Clicked() +} + +func branchSelectorGroup(b Branch) int { + if b.Remote { + return 1 + } + return 0 +} + +// branchSelectorFilter keeps branches whose name holds the query, locals first. +func branchSelectorFilter(branches []Branch, query string) []Branch { + q := strings.ToLower(strings.TrimSpace(query)) + var local, remote []Branch + for _, b := range branches { + if !strings.Contains(strings.ToLower(b.Name), q) { + continue + } + if b.Remote { + remote = append(remote, b) + } else { + local = append(local, b) + } + } + return append(append(make([]Branch, 0, len(local)+len(remote)), local...), remote...) +} + +func branchSelectorHas(branches []Branch, name string) bool { + for _, b := range branches { + if b.Name == name { + return true + } + } + return false +} diff --git a/branch_selector_test.go b/branch_selector_test.go new file mode 100644 index 0000000..33ec927 --- /dev/null +++ b/branch_selector_test.go @@ -0,0 +1,85 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestBranchSelectorSearchAndChoose(t *testing.T) { + sel, changes := "main", 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if BranchSelector(c, &sel, branchSample(), BranchSelectorOptions{}).Changed() { + changes++ + } + }, 600, 500) + if err := tt.Click("Branch: main"); err != nil { + t.Fatal(err) + } + if !tt.HasText("Local") || !tt.HasText("Remote") || !tt.HasText("origin/release") { + t.Fatalf("groups: %q", tt.Texts()) + } + tt.Type("rel") + if tt.HasText("fix/blame") || !tt.HasText("origin/release") { + t.Fatalf("filter: %q", tt.Texts()) + } + tt.Key(0, ui.KeyEnter) + if sel != "origin/release" || changes != 1 || tt.HasText("Remote") { + t.Fatalf("Enter chose %q changes %d", sel, changes) + } + _ = tt.Click("Branch: origin/release") + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if sel != "fix/blame" { + t.Fatalf("arrows chose %q", sel) + } + _ = tt.Click("Branch: fix/blame") + tt.Key(0, ui.KeyEscape) + if tt.HasText("Local") { + t.Fatal("Escape did not close") + } +} + +func TestBranchSelectorCreateAndDisabled(t *testing.T) { + sel, created, disabled := "main", "", false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := BranchSelector(c, &sel, branchSample(), BranchSelectorOptions{AllowCreate: true, Disabled: disabled}) + if name, ok := r.Created(); ok { + created = name + } + }, 600, 500) + _ = tt.Click("Branch: main") + tt.Type("feature/new") + if !tt.HasText("Create branch “feature/new”") { + t.Fatalf("create row: %q", tt.Texts()) + } + tt.Key(0, ui.KeyEnter) + if created != "feature/new" || sel != "main" { + t.Fatalf("created %q sel %q", created, sel) + } + _ = tt.Click("Branch: main") + disabled = true + tt.Frame() + if tt.HasText("Local") { + t.Fatal("popup stayed open on a disabled selector") + } + _ = tt.Click("Branch: main") + if tt.HasText("Local") { + t.Fatal("disabled selector opened") + } +} + +func TestBranchSelectorSnapshot(t *testing.T) { + snapshotAfter(t, "branch_selector", 420, 420, func(c *ui.Context) { + sel := ui.Local(c.Root(), "sel", func() string { return "main" }) + ui.Column(c).Padding(16).AlignItems(ui.Start).Children(func() { + BranchSelector(c, sel, branchSample(), BranchSelectorOptions{AllowCreate: true}) + }) + }, func(tt *ui.Tester) { + _ = tt.Click("Branch: main") + tt.Type("ma") + }) +} diff --git a/changes_list.go b/changes_list.go new file mode 100644 index 0000000..c313e18 --- /dev/null +++ b/changes_list.go @@ -0,0 +1,163 @@ +package mujica + +import ( + "fmt" + "log/slog" + "path" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// ChangedFile is a changed file in the tree or index. +type ChangedFile struct { + Path string + Status GitStatus + // Staged puts the file in the index group. + Staged bool +} + +// ChangesListState is a ChangesList's selection and grouping. +type ChangesListState struct { + list ui.ListState + cursor int + // rows maps rows to files; negatives are group headers. + rows []int + staged int + src *ChangedFile + n int + started bool +} + +// Selected returns the chosen file's index, or -1. +func (s *ChangesListState) Selected() int { + if s.cursor < 0 || s.cursor >= len(s.rows) { + return -1 + } + return s.rows[s.cursor] +} + +// ChangesListOptions configure a ChangesList. +type ChangesListOptions struct { + Disabled bool +} + +// ChangesList groups staged and unstaged files; give it a height. +func ChangesList(c *ui.Context, s *ChangesListState, files []ChangedFile, opts ChangesListOptions) GitListResult { + if !s.started { + s.started, s.cursor = true, -1 + } + var first *ChangedFile + if len(files) > 0 { + first = &files[0] + } + if first != s.src || len(files) != s.n { + s.rows, s.staged = changesListRows(files) + s.src, s.n, s.cursor = first, len(files), -1 + slog.Debug("mujica: changes list regroup", "files", len(files), "staged", s.staged) + } + k := Tokens(c) + var r GitListResult + s.list.Selected = &s.cursor + s.list.Header = func(i int) bool { return s.rows[i] < 0 } + s.list.Key = func(i int) any { + if f := s.rows[i]; f >= 0 { + return fmt.Sprint(files[f].Staged, files[f].Path) + } + return s.rows[i] + } + s.list.Label = func(i int) string { + if f := s.rows[i]; f >= 0 { + return files[f].Path + } + return "" + } + prev := s.cursor + outer := ui.Column(c).AlignItems(ui.Stretch).Disabled(opts.Disabled) + var e *ui.Element + outer.Children(func() { + restore := dataSelectTheme(c, 0) + defer restore() + e = ui.List(c, &s.list, len(s.rows), func(i int) { changesListRow(c, s, files, i, &r) }) + e.Grow(1).Background(k.Surface).Border(theme.BorderWidth, k.Border).Radius(theme.ControlRadius) + }) + r.Element, r.changed, r.submitted = outer, e.Changed(), e.Submitted() + if outer.IsDisabled() { + s.cursor, r.changed, r.submitted, r.action, r.item = prev, false, false, "", "" + } + if r.action != "" { + slog.Debug("mujica: changes list action", "action", r.action, "path", r.item) + } + return r +} + +// changesListRow builds row i: a header or a file. +func changesListRow(c *ui.Context, s *ChangesListState, files []ChangedFile, i int, r *GitListResult) { + k := Tokens(c) + d := Density(c) + u := d.Unit() + f := s.rows[i] + row := ui.Row(c).AlignItems(ui.Center).Gap(u*2).MinHeight(d.ControlHeight()).Padding(0, u*2, 0, u*3) + if f < 0 { + key, all, icon, count := "changes_list.staged", "unstage_all", "minus", s.staged + if f == -2 { + key, all, icon, count = "changes_list.unstaged", "stage_all", "plus", len(files)-s.staged + } + row.Background(k.Background).Children(func() { + ui.Text(c, fmt.Sprintf(msg(c, key), count)).Font(theme.SerifFont).FontWeight(600). + FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.Ornament.Mix(k.Text, 0.35)).Grow(1) + b := iconAction(c, icons.Must(icon), msg(c, "changes_list."+all)).Disabled(count == 0) + if b.Tooltip(msg(c, "changes_list."+all)).Clicked() && !b.IsDisabled() { + r.action = all + } + }) + return + } + cf := files[f] + if s.cursor == i { + row.Draw(func(p *ui.Painter, rc ui.Rect) { + p.Fill(ui.Rect{X: rc.X, Y: rc.Y + 4, W: 3, H: rc.H - 8}, k.AccentText, 1.5) + }) + } + row.Children(func() { + GitStatusBadge(c, cf.Status, GitStatusBadgeOptions{}) + dir := path.Dir(cf.Path) + ui.Text(c, path.Base(cf.Path)).SingleLine().Shrink(0).MaxWidth(240) + if dir != "." { + ui.Text(c, dir).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine().MinWidth(0) + } + ui.Spacer(c) + id, icon := "stage", "plus" + if cf.Staged { + id, icon = "unstage", "minus" + } + b := iconAction(c, icons.Must(icon), msg(c, "changes_list."+id)+" "+cf.Path).Tooltip(msg(c, "changes_list."+id)) + if b.Clicked() && !b.IsDisabled() { + r.action, r.item = id, cf.Path + } + }) +} + +// changesListRows orders staged files, then unstaged, each under a header. +func changesListRows(files []ChangedFile) ([]int, int) { + rows := []int{-1} + for i, f := range files { + if f.Path == "" { + panic("mujica: ChangedFile needs a Path") + } + gitStatusIndex(f.Status) + if f.Staged { + rows = append(rows, i) + } + } + staged := len(rows) - 1 + rows = append(rows, -2) + for i, f := range files { + if !f.Staged { + rows = append(rows, i) + } + } + return rows, staged +} diff --git a/changes_list_test.go b/changes_list_test.go new file mode 100644 index 0000000..0cf540d --- /dev/null +++ b/changes_list_test.go @@ -0,0 +1,95 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func changesSample() []ChangedFile { + return []ChangedFile{ + {Path: "commit_graph.go", Status: GitAdded, Staged: true}, + {Path: "internal/git.go", Status: GitModified}, + {Path: "docs/old.md", Status: GitDeleted}, + {Path: "notes.txt", Status: GitUntracked}, + } +} + +func TestChangesListGroupsAndStage(t *testing.T) { + var s ChangesListState + files := changesSample() + var acted [][2]string + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := ChangesList(c, &s, files, ChangesListOptions{}) + r.Element.Height(320) + if a, item, ok := r.Action(); ok { + acted = append(acted, [2]string{a, item}) + } + }, 600, 360) + if !tt.HasText("Staged changes (1)") || !tt.HasText("Changes (3)") { + t.Fatalf("groups: %q", tt.Texts()) + } + for _, name := range []string{"Stage internal/git.go", "Unstage commit_graph.go", "Stage all", "Unstage all"} { + if err := tt.Click(name); err != nil { + t.Fatal(err) + } + } + want := [][2]string{{"stage", "internal/git.go"}, {"unstage", "commit_graph.go"}, {"stage_all", ""}, {"unstage_all", ""}} + for i := range want { + if i >= len(acted) || acted[i] != want[i] { + t.Fatalf("actions %q, want %q", acted, want) + } + } + if err := tt.Click("old.md"); err != nil { + t.Fatal(err) + } + if got := s.Selected(); got != 2 { + t.Fatalf("selected %d, want 2", got) + } + tt.Key(0, ui.KeyDown) + if got := s.Selected(); got != 3 { + t.Fatalf("Down selected %d", got) + } +} + +func TestChangesListDisabledAndEmptyGroups(t *testing.T) { + var s ChangesListState + files := []ChangedFile{{Path: "a.go", Status: GitModified}} + acted := false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := ChangesList(c, &s, files, ChangesListOptions{Disabled: true}) + r.Element.Height(200) + _, _, ok := r.Action() + acted = acted || ok || r.Changed() + }, 500, 240) + if !tt.HasText("Staged changes (0)") { + t.Fatalf("empty group: %q", tt.Texts()) + } + _ = tt.Click("Stage a.go") + _ = tt.Click("a.go") + if acted || s.Selected() != -1 { + t.Fatal("disabled list acted") + } + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + var s ChangesListState + ChangesList(c, &s, []ChangedFile{{Status: GitAdded}}, ChangesListOptions{}) + }, 300, 100, 1) +} + +func TestChangesListSnapshot(t *testing.T) { + files := changesSample() + snapshot(t, "changes_list", 520, 300, func(c *ui.Context) { + s := ui.Local(c.Root(), "changes", func() *ChangesListState { return &ChangesListState{} }) + ui.Column(c).Padding(16).Children(func() { + ChangesList(c, *s, files, ChangesListOptions{}).Element.Height(260) + }) + }) +} diff --git a/command_block.go b/command_block.go new file mode 100644 index 0000000..194e807 --- /dev/null +++ b/command_block.go @@ -0,0 +1,158 @@ +package mujica + +import ( + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// CommandRun is a command and its output from the caller. +type CommandRun struct { + Command string + // Output may hold ANSI escapes. + Output string + ExitCode int + Duration time.Duration + // Running hides ExitCode and Duration behind a live mark. + Running bool +} + +// CommandBlockOptions configure a CommandBlock. +type CommandBlockOptions struct { + // Prompt precedes the command; empty means "$". + Prompt string + // MaxOutputHeight scrolls longer output; zero means 320 DIPs. + MaxOutputHeight float32 +} + +// CommandBlockResult is a built CommandBlock and its events. +type CommandBlockResult struct { + Element *ui.Element + toggled bool + copied string +} + +// Toggled reports the output was shown or hidden this frame. +func (r CommandBlockResult) Toggled() bool { return r.toggled } + +// Copied returns "command" or "output" when copied. +func (r CommandBlockResult) Copied() (string, bool) { return r.copied, r.copied != "" } + +// CommandBlock shows a command run; *open shows its output. +func CommandBlock(c *ui.Context, run CommandRun, open *bool, opts CommandBlockOptions) CommandBlockResult { + if run.Command == "" { + panic("mujica: CommandBlock needs a Command") + } + if run.Duration < 0 || opts.MaxOutputHeight < 0 { + panic("mujica: CommandBlock Duration and MaxOutputHeight must not be negative") + } + prompt := opts.Prompt + if prompt == "" { + prompt = "$" + } + maxH := opts.MaxOutputHeight + if maxH == 0 { + maxH = 320 + } + k := Tokens(c) + d := Density(c) + u := d.Unit() + box := ui.Column(c).AlignItems(ui.Stretch).Background(k.Surface).Border(theme.BorderWidth, k.Border).Radius(theme.CardRadius).Clip() + res := CommandBlockResult{Element: box} + box.Children(func() { + ui.Row(c).AlignItems(ui.Center).Gap(u).Padding(0, u*2, 0, 0).MinHeight(d.ControlHeight()).Children(func() { + was := *open + tr := ui.CollapsibleBase(c, open).Trigger + if box.IsDisabled() { + *open = was + } + if *open != was { + res.toggled = true + slog.Debug("mujica: command block toggle", "open", *open) + } + tr.Grow(1).MinWidth(0).MinHeight(d.ControlHeight()).AlignItems(ui.Center).Gap(u*2).Padding(0, u*3). + Radius(theme.ControlRadius).Label(prompt + " " + run.Command).Cursor(ui.CursorPointer) + internal.Ring(tr, k.Focus, theme.ControlRadius) + if tr.Hovered() { + tr.Background(k.SurfaceHover) + } + tr.Transition(colorFade) + turn := tr.Animate("mujica.turn", commandBlockTurn(*open), Motion(c, theme.StateDuration)) + tr.Children(func() { + ui.Icon(c, icons.Must("chevron-right")).Size(14, 14).Shrink(0).Rotate(turn).TextColor(k.TextMuted) + ui.Text(c, prompt).Font(theme.MonoFont).TextColor(k.Ornament.Mix(k.Text, 0.35)).Shrink(0) + spans, _ := internal.CodeSpans(k, "shell", run.Command, false) + ui.RichText(c, spans...).Font(theme.MonoFont).SingleLine().MinWidth(0) + }) + commandBlockStatus(c, run) + if iconAction(c, icons.Must("copy"), msg(c, "command_block.copy_command")).Clicked() && !box.IsDisabled() { + c.WriteClipboard(run.Command) + res.copied = "command" + } + if iconAction(c, icons.Must("file-text"), msg(c, "command_block.copy_output")).Disabled(run.Output == "").Clicked() && !box.IsDisabled() { + c.WriteClipboard(internal.StripAnsi(run.Output)) + res.copied = "output" + } + }) + if *open { + ui.Box(c).Height(1).Background(k.Border).Role(ui.RoleNone) + out := ui.ScrollBoth(c).MaxHeight(maxH).Padding(u*3, u*4).Background(k.Background).Label(msg(c, "command_block.output")) + out.Children(func() { + if run.Output == "" { + ui.Text(c, msg(c, "command_block.no_output")).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)) + return + } + AnsiText(c, run.Output, AnsiTextOptions{}) + }) + } + }) + if res.copied != "" { + slog.Debug("mujica: command block copy", "what", res.copied) + } + return res +} + +// commandBlockStatus shows running, success or failure with icon and words. +func commandBlockStatus(c *ui.Context, run CommandRun) { + k := Tokens(c) + u := Density(c).Unit() + ui.Row(c).AlignItems(ui.Center).Gap(u * 1.5).Shrink(0).FontSize(FontSize(c, theme.CaptionSize)).Children(func() { + if run.Running { + Spinner(c, SpinnerOptions{Label: msg(c, "command_block.running"), ShowLabel: true, Size: 12}) + return + } + icon, col := "circle-check", k.Success + if run.ExitCode != 0 { + icon, col = "circle-x", k.Danger + } + ui.Row(c).Gap(u).AlignItems(ui.Center).TextColor(col).Children(func() { + ui.Icon(c, icons.Must(icon)).Size(14, 14) + ui.Text(c, fmt.Sprintf(msg(c, "command_block.exit"), run.ExitCode)).FontFeatures("tnum").SingleLine() + }) + ui.Text(c, commandBlockDuration(run.Duration)).TextColor(k.TextMuted).FontFeatures("tnum").SingleLine() + }) +} + +func commandBlockTurn(open bool) float32 { + if open { + return 90 + } + return 0 +} + +// commandBlockDuration prints milliseconds, seconds or minutes. +func commandBlockDuration(d time.Duration) string { + if d < time.Second { + return fmt.Sprintf("%d ms", d.Milliseconds()) + } + if d < time.Minute { + return fmt.Sprintf("%.1f s", d.Seconds()) + } + return fmt.Sprintf("%dm %02ds", int(d.Minutes()), int(d.Seconds())%60) +} diff --git a/command_block_test.go b/command_block_test.go new file mode 100644 index 0000000..589b857 --- /dev/null +++ b/command_block_test.go @@ -0,0 +1,105 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func commandBlockSample() CommandRun { + return CommandRun{Command: "go test ./...", Output: "\x1b[32mok\x1b[0m mujicaui 3.2s", ExitCode: 0, Duration: 3200 * time.Millisecond} +} + +func TestCommandBlockToggleAndCopy(t *testing.T) { + open, toggles := false, 0 + var copied []string + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := CommandBlock(c, commandBlockSample(), &open, CommandBlockOptions{}) + if r.Toggled() { + toggles++ + } + if w, ok := r.Copied(); ok { + copied = append(copied, w) + } + }, 600, 300) + if tt.HasText("mujicaui 3.2s") { + t.Fatal("closed block shows output") + } + if !tt.HasText("exit 0") || !tt.HasText("3.2 s") { + t.Fatalf("status: %q", tt.Texts()) + } + if err := tt.Click("$ go test ./..."); err != nil { + t.Fatal(err) + } + if !open || toggles != 1 || !tt.HasText("ok mujicaui 3.2s") { + t.Fatalf("open %v toggles %d texts %q", open, toggles, tt.Texts()) + } + tt.Key(0, ui.KeyEnter) + if open || toggles != 2 { + t.Fatalf("Enter on the focused header: open %v toggles %d", open, toggles) + } + _ = tt.Click("Copy command") + if tt.Clipboard() != "go test ./..." { + t.Fatalf("clipboard %q", tt.Clipboard()) + } + _ = tt.Click("Copy output") + if tt.Clipboard() != "ok mujicaui 3.2s" || len(copied) != 2 || copied[1] != "output" { + t.Fatalf("output copy %q %q", tt.Clipboard(), copied) + } +} + +func TestCommandBlockFailureRunningDisabled(t *testing.T) { + open := true + run := CommandRun{Command: "make", Output: "boom", ExitCode: 2, Duration: 90 * time.Second} + disabled := false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Disabled(disabled).Children(func() { + CommandBlock(c, run, &open, CommandBlockOptions{Prompt: "❯"}) + }) + }, 600, 300) + if !tt.HasText("exit 2") || !tt.HasText("1m 30s") { + t.Fatalf("failure: %q", tt.Texts()) + } + run.Running = true + tt.Frame() + if !tt.HasText("Running") || tt.HasText("exit 2") { + t.Fatalf("running: %q", tt.Texts()) + } + disabled = true + tt.Frame() + _ = tt.Click("❯ make") + _ = tt.Click("Copy command") + if !open || tt.Clipboard() != "" { + t.Fatalf("disabled block acted: open %v clipboard %q", open, tt.Clipboard()) + } +} + +func TestCommandBlockInvalid(t *testing.T) { + for _, run := range []CommandRun{{}, {Command: "x", Duration: -1}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%+v did not panic", run) + } + }() + open := false + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + CommandBlock(c, run, &open, CommandBlockOptions{}) + }, 100, 50, 1) + }() + } +} + +func TestCommandBlockSnapshot(t *testing.T) { + snapshot(t, "command_block", 620, 300, func(c *ui.Context) { + a, b := true, false + ui.Column(c).Padding(16).Gap(12).Children(func() { + CommandBlock(c, CommandRun{Command: "go test -run Git ./...", Output: "\x1b[32mok\x1b[0m \tmujicaui\t3.214s\n\x1b[33mwarn\x1b[0m slow test: TestCommitGraphVirtualized", Duration: 3214 * time.Millisecond}, &a, CommandBlockOptions{}) + CommandBlock(c, CommandRun{Command: "git push origin main", ExitCode: 1, Duration: 640 * time.Millisecond, Output: "rejected"}, &b, CommandBlockOptions{}) + }) + }) +} diff --git a/commit_graph.go b/commit_graph.go new file mode 100644 index 0000000..1bb1bde --- /dev/null +++ b/commit_graph.go @@ -0,0 +1,204 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// CommitGraphState is a CommitGraph's selection and its lane layout. +type CommitGraphState struct { + List ListState[string] + rows []commitGraphRow + // lanes is the widest the graph gets. + lanes int + src *Commit + n int +} + +// CommitGraphOptions configure a CommitGraph. +type CommitGraphOptions struct { + // TimeFormat lays out commit times; empty means "2006-01-02 15:04". + TimeFormat string + // MaxLanes caps the graph width in lanes; zero means 8. + MaxLanes int + Status DataStatus + Error string +} + +// commitGraphLink joins lane from to lane to within a row. +type commitGraphLink struct{ from, to, color int } + +type commitGraphRow struct { + node, color int + merge bool + // top links enter from above; bottom links leave the node. + top, bottom []commitGraphLink +} + +type commitGraphLane struct { + hash string + color int +} + +// CommitGraph shows commits with branch lanes; give it a height. +func CommitGraph(c *ui.Context, s *CommitGraphState, commits []Commit, opts CommitGraphOptions) GitListResult { + maxLanes := opts.MaxLanes + if maxLanes == 0 { + maxLanes = 8 + } + if maxLanes < 0 { + panic("mujica: CommitGraph MaxLanes is negative") + } + var first *Commit + if len(commits) > 0 { + first = &commits[0] + } + if first != s.src || len(commits) != s.n { + s.rows, s.lanes = commitGraphLayout(commits) + s.src, s.n = first, len(commits) + slog.Debug("mujica: commit graph layout", "commits", len(commits), "lanes", s.lanes) + } + layout := gitTimeLayout(opts.TimeFormat) + lane := Density(c).Unit() * 4 + width := float32(min(max(s.lanes, 1), maxLanes)) * lane + h := Density(c).ControlHeight() + v := List(c, &s.List, len(commits), ListOptions[string]{ + Key: func(i int) string { return gitCommitHash(commits[i]) }, + Label: func(i int) string { return commits[i].Subject }, + Status: opts.Status, Error: opts.Error, Empty: msg(c, "commit_list.empty"), + }, func(i int) { + row := s.rows[i] + ui.Box(c).Size(width, h).Shrink(0).Clip().Role(ui.RoleNone).Draw(func(p *ui.Painter, r ui.Rect) { + commitGraphDraw(p, Tokens(c), r, row, lane) + }) + commitListRow(c, commits[i], layout) + }) + res := GitListResult{Element: v.Element, changed: v.Changed(), submitted: v.Submitted()} + if res.changed || res.submitted { + key, _ := s.List.Selected() + slog.Debug("mujica: commit graph choose", "hash", key, "open", res.submitted) + } + return res +} + +// commitGraphLayout gives each commit a lane and parent links. +func commitGraphLayout(commits []Commit) ([]commitGraphRow, int) { + rows := make([]commitGraphRow, len(commits)) + var lanes []commitGraphLane + colors, widest := 0, 0 + free := func() int { + for j, l := range lanes { + if l.hash == "" { + return j + } + } + lanes = append(lanes, commitGraphLane{}) + return len(lanes) - 1 + } + for i, cm := range commits { + h := gitCommitHash(cm) + var row commitGraphRow + row.node = -1 + for j, l := range lanes { + if l.hash == h && row.node < 0 { + row.node = j + } + } + for j, l := range lanes { + switch { + case l.hash == "": + case l.hash == h: + row.top = append(row.top, commitGraphLink{j, row.node, l.color}) + default: + row.top = append(row.top, commitGraphLink{j, j, l.color}) + } + } + if row.node < 0 { + row.node = free() + lanes[row.node] = commitGraphLane{h, colors % 6} + colors++ + } + row.color = lanes[row.node].color + for j := range lanes { + if lanes[j].hash == h { + lanes[j].hash = "" + } + } + row.merge = len(cm.Parents) > 1 + for pi, p := range cm.Parents { + if pi == 0 { + lanes[row.node] = commitGraphLane{p, row.color} + row.bottom = append(row.bottom, commitGraphLink{row.node, row.node, row.color}) + continue + } + to := -1 + for j, l := range lanes { + if l.hash == p { + to = j + break + } + } + if to < 0 { + to = free() + lanes[to] = commitGraphLane{p, colors % 6} + colors++ + } + row.bottom = append(row.bottom, commitGraphLink{row.node, to, lanes[to].color}) + } + for len(lanes) > 0 && lanes[len(lanes)-1].hash == "" { + lanes = lanes[:len(lanes)-1] + } + widest = max(widest, len(lanes), row.node+1) + rows[i] = row + } + return rows, widest +} + +// commitGraphColors are the lane colors; place also tells lanes apart. +func commitGraphColors(k theme.Tokens) [6]ui.Color { + return [6]ui.Color{k.AccentText, k.Info, k.Success, k.Warning, k.Danger, k.TextMuted} +} + +func commitGraphDraw(p *ui.Painter, k theme.Tokens, r ui.Rect, row commitGraphRow, lane float32) { + cols := commitGraphColors(k) + x := func(j int) float32 { return internal.Snap(p, r.X+lane/2+float32(j)*lane) } + top, mid, bot := internal.Snap(p, r.Y), internal.Snap(p, r.Y+r.H/2), internal.Snap(p, r.Y+r.H) + seg := func(l commitGraphLink, y0, y1 float32) { + var path ui.Path + xa, xb := x(l.from), x(l.to) + path.MoveTo(xa, y0) + if xa == xb { + path.LineTo(xb, y1) + } else { + m := (y0 + y1) / 2 + path.CubeTo(xa, m, xb, m, xb, y1) + } + p.StrokePath(&path, 2, cols[l.color]) + } + for _, l := range row.top { + if l.from == l.to && l.to != row.node { + seg(l, top, bot) + continue + } + seg(l, top, mid) + } + for _, l := range row.bottom { + seg(l, mid, bot) + } + cx, col := x(row.node), cols[row.color] + if row.merge { + p.FillPath(internal.Diamond(cx, mid, 11), k.Surface) + p.StrokePath(internal.Diamond(cx, mid, 9), 2, col) + return + } + var dot ui.Path + dot.Circle(cx, mid, 5.5) + p.FillPath(&dot, k.Surface) + var ring ui.Path + ring.Circle(cx, mid, 4) + p.FillPath(&ring, col) +} diff --git a/commit_graph_test.go b/commit_graph_test.go new file mode 100644 index 0000000..2945268 --- /dev/null +++ b/commit_graph_test.go @@ -0,0 +1,98 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +// commitGraphSample is main with a feature branch merged back. +func commitGraphSample() []Commit { + cs := []Commit{ + {Hash: "m3", Parents: []string{"m2", "f2"}, Subject: "Merge feature", Refs: []string{"main"}}, + {Hash: "f2", Parents: []string{"f1"}, Subject: "Feature work"}, + {Hash: "m2", Parents: []string{"m1"}, Subject: "Fix on main"}, + {Hash: "f1", Parents: []string{"m1"}, Subject: "Start feature"}, + {Hash: "m1", Subject: "Initial commit"}, + } + for i := range cs { + cs[i].Author = []string{"Sakiko", "Mutsumi", "Uika"}[i%3] + cs[i].When = gitTestTime.Add(-time.Duration(i) * 3 * time.Hour) + } + return cs +} + +func TestCommitGraphLayoutLanes(t *testing.T) { + rows, lanes := commitGraphLayout(commitGraphSample()) + if lanes != 2 { + t.Fatalf("lanes %d, want 2", lanes) + } + want := []struct { + node int + merge bool + }{{0, true}, {1, false}, {0, false}, {1, false}, {0, false}} + for i, w := range want { + if rows[i].node != w.node || rows[i].merge != w.merge { + t.Errorf("row %d: node %d merge %v, want %+v", i, rows[i].node, rows[i].merge, w) + } + } + // The merge sends a line to the feature lane; f1 joins main again at m1. + if l := rows[0].bottom; len(l) != 2 || l[1].from != 0 || l[1].to != 1 { + t.Errorf("merge links %+v", l) + } + if l := rows[4].top; len(l) != 2 || l[1].from != 1 || l[1].to != 0 { + t.Errorf("fork point links %+v", l) + } +} + +func TestCommitGraphVirtualized(t *testing.T) { + commits := gitHistory(100000) + var s CommitGraphState + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + CommitGraph(c, &s, commits, CommitGraphOptions{}).Element.Height(400) + }, 700, 440) + if n := len(tt.Texts()); n > 400 { + t.Fatalf("%d texts built for 100,000 commits", n) + } + rows := &s.rows[0] + tt.Scroll(300, 200, 0, 50000) + tt.Frame() + if &s.rows[0] != rows { + t.Fatal("layout recomputed without a data change") + } + if tt.HasText("Commit number 100000") { + t.Fatal("scroll did not move the window of rows") + } +} + +func TestCommitGraphChooseAndKeys(t *testing.T) { + var s CommitGraphState + changes := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := CommitGraph(c, &s, commitGraphSample(), CommitGraphOptions{}) + r.Element.Height(300) + if r.Changed() { + changes++ + } + }, 700, 400) + if err := tt.Click("Fix on main"); err != nil { + t.Fatal(err) + } + tt.Key(0, ui.KeyDown) + if key, _ := s.List.Selected(); key != "f1" || changes != 2 { + t.Fatalf("selected %q changes %d", key, changes) + } +} + +func TestCommitGraphSnapshot(t *testing.T) { + commits := commitGraphSample() + snapshot(t, "commit_graph", 640, 240, func(c *ui.Context) { + s := ui.Local(c.Root(), "graph", func() *CommitGraphState { return &CommitGraphState{} }) + ui.Column(c).Padding(16).Children(func() { + CommitGraph(c, *s, commits, CommitGraphOptions{}).Element.Height(200) + }) + }) +} diff --git a/commit_input.go b/commit_input.go new file mode 100644 index 0000000..4ec91fe --- /dev/null +++ b/commit_input.go @@ -0,0 +1,106 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strings" + "unicode/utf8" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// CommitMessage is a commit's title and body. +type CommitMessage struct { + Title string + Body string +} + +// CommitInputOptions configure a CommitInput. +type CommitInputOptions struct { + // TitleLimit warns past this many title characters; zero means 50. + TitleLimit int + // Busy shows a commit in progress and blocks another. + Busy bool + Disabled bool +} + +// CommitInputResult is a built CommitInput and its events. +type CommitInputResult struct { + Element *ui.Element + committed, amend bool +} + +// Committed reports Commit, or Cmd+Enter, this frame. +func (r CommitInputResult) Committed() bool { return r.committed } + +// Amended reports Amend this frame. +func (r CommitInputResult) Amended() bool { return r.amend } + +type commitInputState struct { + // pending blocks commits until Busy comes and goes. + pending, sawBusy bool +} + +// CommitInput edits a commit message and commits or amends once. +func CommitInput(c *ui.Context, m *CommitMessage, opts CommitInputOptions) CommitInputResult { + limit := opts.TitleLimit + if limit == 0 { + limit = 50 + } + if limit < 0 { + panic("mujica: CommitInput TitleLimit is negative") + } + k := Tokens(c) + u := Density(c).Unit() + col := ui.Column(c).AlignItems(ui.Stretch).Gap(u * 2).Disabled(opts.Disabled) + res := CommitInputResult{Element: col} + st := ui.Local(col, "state", func() *commitInputState { return &commitInputState{} }) + s := *st + if opts.Busy { + s.sawBusy = true + } else if s.sawBusy { + s.pending, s.sawBusy = false, false + } + blocked := opts.Busy || s.pending + n := utf8.RuneCountInString(m.Title) + col.Children(func() { + title := TextInput(c, &m.Title, TextInputOptions{Placeholder: msg(c, "commit_input.title"), Label: msg(c, "commit_input.title"), + Disabled: opts.Disabled, ReadOnly: blocked, + Trailing: func() { + col := k.TextMuted + if n > limit { + col = k.Warning + } + name := fmt.Sprintf(msg(c, "commit_input.count"), n, limit) + if n > limit { + name = fmt.Sprintf(msg(c, "commit_input.long"), n-limit) + } + ui.Text(c, fmt.Sprintf("%d/%d", n, limit)).FontSize(FontSize(c, theme.CaptionSize)).FontFeatures("tnum").TextColor(col).Shrink(0). + Label(name).Tooltip(name) + }}) + body := TextArea(c, &m.Body, TextAreaOptions{Placeholder: msg(c, "commit_input.body"), Label: msg(c, "commit_input.body"), + MinHeight: 72, MaxHeight: 200, Disabled: opts.Disabled, ReadOnly: blocked}) + empty := strings.TrimSpace(m.Title) == "" + send := (title.Submitted() || body.Submitted()) && !empty + ui.Row(c).Gap(u * 2).Justify(ui.End).Children(func() { + if Button(c, msg(c, "commit_input.amend"), ButtonOptions{Variant: Secondary, Icon: icons.Must("rotate-ccw"), Disabled: blocked || empty}).Clicked() { + res.amend = true + } + if Button(c, msg(c, "commit_input.commit"), ButtonOptions{Icon: icons.Must("check"), Loading: opts.Busy, Disabled: s.pending || empty}).Clicked() { + send = true + } + }) + res.committed = send && !res.amend + }) + if blocked || col.IsDisabled() { + res.committed, res.amend = false, false + } + if res.committed || res.amend { + s.pending = true + slog.Debug("mujica: commit input submit", "amend", res.amend) + } + return res +} diff --git a/commit_input_test.go b/commit_input_test.go new file mode 100644 index 0000000..ae70439 --- /dev/null +++ b/commit_input_test.go @@ -0,0 +1,101 @@ +package mujica + +import ( + "strings" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestCommitInputCommitOnceWhileBusy(t *testing.T) { + m := CommitMessage{} + busy := false + commits, amends := 0, 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := CommitInput(c, &m, CommitInputOptions{Busy: busy}) + if r.Committed() { + commits++ + } + if r.Amended() { + amends++ + } + }, 600, 400) + _ = tt.Click("Commit") + if commits != 0 { + t.Fatal("empty title committed") + } + if err := tt.Click("Summary"); err != nil { + t.Fatal(err) + } + tt.Type("Add git components") + tt.Key(0, ui.KeyEnter) + _ = tt.Click("Commit") + if commits != 1 { + t.Fatalf("commits %d, want 1 before Busy clears", commits) + } + busy = true + tt.Frame() + _ = tt.Click("Commit") + _ = tt.Click("Amend") + busy = false + tt.Frame() + if commits != 1 || amends != 0 { + t.Fatalf("busy: commits %d amends %d", commits, amends) + } + _ = tt.Click("Amend") + if amends != 1 { + t.Fatalf("amends %d", amends) + } +} + +func TestCommitInputTitleHint(t *testing.T) { + m := CommitMessage{Title: strings.Repeat("x", 55)} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + CommitInput(c, &m, CommitInputOptions{}) + }, 600, 400) + if _, ok := tt.Find("Summary is 5 characters over the suggested length"); !ok { + t.Fatal("over-length hint not named") + } + m.Title = "short" + tt.Frame() + if _, ok := tt.Find("5 of 50 characters"); !ok { + t.Fatal("count not named") + } +} + +func TestCommitInputDisabledAndInvalid(t *testing.T) { + m := CommitMessage{Title: "x"} + acted := false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := CommitInput(c, &m, CommitInputOptions{Disabled: true}) + acted = acted || r.Committed() || r.Amended() + }, 600, 400) + _ = tt.Click("Commit") + _ = tt.Click("Amend") + if acted { + t.Fatal("disabled input committed") + } + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + CommitInput(c, &m, CommitInputOptions{TitleLimit: -1}) + }, 300, 100, 1) +} + +func TestCommitInputSnapshot(t *testing.T) { + snapshot(t, "commit_input", 520, 280, func(c *ui.Context) { + m := ui.Local(c.Root(), "msg", func() CommitMessage { + return CommitMessage{Title: "Add CommitGraph lanes with merge lines", Body: "Lanes are laid out once per history."} + }) + ui.Column(c).Padding(16).Children(func() { + CommitInput(c, m, CommitInputOptions{}) + }) + }) +} diff --git a/commit_list.go b/commit_list.go new file mode 100644 index 0000000..161e7e6 --- /dev/null +++ b/commit_list.go @@ -0,0 +1,105 @@ +package mujica + +import ( + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// Commit is one commit of a history, newest first. +type Commit struct { + Hash string + Parents []string + Author string + When time.Time + Subject string + // Refs are branch and tag names pointing at the commit. + Refs []string +} + +// GitListResult is a built version-control list and its events. +type GitListResult struct { + Element *ui.Element + changed, submitted bool + action, item string +} + +// Changed reports a new selection. +func (r GitListResult) Changed() bool { return r.changed } + +// Submitted reports Enter or a double click on a row. +func (r GitListResult) Submitted() bool { return r.submitted } + +// Action returns this frame's action ID and its item. +func (r GitListResult) Action() (action, item string, ok bool) { + return r.action, r.item, r.action != "" +} + +// CommitListOptions configure a CommitList. +type CommitListOptions struct { + // TimeFormat lays out commit times; empty means "2006-01-02 15:04". + TimeFormat string + Status DataStatus + Error string +} + +// CommitList shows commits to choose from; give it a height. +func CommitList(c *ui.Context, s *ListState[string], commits []Commit, opts CommitListOptions) GitListResult { + layout := gitTimeLayout(opts.TimeFormat) + v := List(c, s, len(commits), ListOptions[string]{ + Key: func(i int) string { return gitCommitHash(commits[i]) }, + Label: func(i int) string { return commits[i].Subject }, + Status: opts.Status, Error: opts.Error, Empty: msg(c, "commit_list.empty"), + }, func(i int) { commitListRow(c, commits[i], layout) }) + r := GitListResult{Element: v.Element, changed: v.Changed(), submitted: v.Submitted()} + if r.changed || r.submitted { + key, _ := s.Selected() + slog.Debug("mujica: commit list choose", "hash", key, "open", r.submitted) + } + return r +} + +func commitListRow(c *ui.Context, cm Commit, layout string) { + k := Tokens(c) + gitRefs(c, cm.Refs) + ui.Text(c, cm.Subject).SingleLine().Grow(1).MinWidth(0) + small := FontSize(c, theme.CaptionSize) + ui.Text(c, cm.Author).FontSize(small).TextColor(k.TextMuted).SingleLine().MaxWidth(140).Shrink(0) + ui.Text(c, gitShortHash(cm.Hash)).Font(theme.MonoFont).FontSize(small).TextColor(k.AccentText).Shrink(0) + ui.Text(c, cm.When.Format(layout)).FontSize(small).FontFeatures("tnum").TextColor(k.TextMuted).Shrink(0) +} + +// gitRefs shows branch and tag names as small outlined pills. +func gitRefs(c *ui.Context, refs []string) { + k := Tokens(c) + u := Density(c).Unit() + for _, ref := range refs { + ui.Text(c, ref).FontSize(FontSize(c, theme.CaptionSize)).FontWeight(600).TextColor(k.AccentText).SingleLine(). + Padding(0, u*1.5).Radius(theme.ControlRadius).Border(theme.BorderWidth, k.AccentText).Shrink(0).MaxWidth(160) + } +} + +func gitCommitHash(cm Commit) string { + if cm.Hash == "" { + panic("mujica: Commit needs a Hash") + } + return cm.Hash +} + +// gitShortHash is the first seven characters of a hash. +func gitShortHash(h string) string { + if len(h) > 7 { + return h[:7] + } + return h +} + +func gitTimeLayout(f string) string { + if f == "" { + return "2006-01-02 15:04" + } + return f +} diff --git a/commit_list_test.go b/commit_list_test.go new file mode 100644 index 0000000..1dd521f --- /dev/null +++ b/commit_list_test.go @@ -0,0 +1,91 @@ +package mujica + +import ( + "fmt" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +var gitTestTime = time.Date(2026, 10, 5, 9, 30, 0, 0, time.UTC) + +// gitTestHash is a stable, hash-like hex string for commit i. +func gitTestHash(i int) string { return fmt.Sprintf("%016x%024x", uint64(i)*0x9E3779B97F4A7C15, i) } + +// gitHistory is a linear history of n commits, newest first. +func gitHistory(n int) []Commit { + out := make([]Commit, n) + for i := range out { + out[i] = Commit{Hash: gitTestHash(n - i), Author: "Sakiko", When: gitTestTime.Add(-time.Duration(i) * time.Hour), + Subject: fmt.Sprintf("Commit number %d", n-i)} + if i+1 < n { + out[i].Parents = []string{gitTestHash(n - i - 1)} + } + } + return out +} + +func TestCommitListChooseAndOpen(t *testing.T) { + commits := gitHistory(5) + commits[0].Refs = []string{"main"} + var s ListState[string] + changes, opens := 0, 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := CommitList(c, &s, commits, CommitListOptions{}) + r.Element.Height(300) + if r.Changed() { + changes++ + } + if r.Submitted() { + opens++ + } + }, 700, 340) + if !tt.HasText("main") || !tt.HasText("1715609") || !tt.HasText("2026-10-05 09:30") { + t.Fatalf("row parts: %q", tt.Texts()) + } + if err := tt.Click("Commit number 3"); err != nil { + t.Fatal(err) + } + if key, _ := s.Selected(); key != commits[2].Hash || changes != 1 { + t.Fatalf("selected %q changes %d", key, changes) + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if key, _ := s.Selected(); key != commits[3].Hash || opens != 1 { + t.Fatalf("keyboard: %q opens %d", key, opens) + } +} + +func TestCommitListEmptyAndInvalid(t *testing.T) { + var s ListState[string] + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + CommitList(c, &s, nil, CommitListOptions{}) + }, 400, 200) + if !tt.HasText("No commits") { + t.Fatalf("empty: %q", tt.Texts()) + } + defer func() { + if recover() == nil { + t.Fatal("hashless commit did not panic") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + var s ListState[string] + CommitList(c, &s, []Commit{{Subject: "x"}}, CommitListOptions{}) + }, 300, 100, 1) +} + +func TestCommitListSnapshot(t *testing.T) { + commits := gitHistory(4) + commits[0].Refs = []string{"main", "v1.1"} + snapshot(t, "commit_list", 640, 220, func(c *ui.Context) { + s := ui.Local(c.Root(), "list", func() *ListState[string] { return &ListState[string]{} }) + ui.Column(c).Padding(16).Children(func() { + CommitList(c, *s, commits, CommitListOptions{}).Element.Height(180) + }) + }) +} diff --git a/conflict_resolver.go b/conflict_resolver.go new file mode 100644 index 0000000..9806b4e --- /dev/null +++ b/conflict_resolver.go @@ -0,0 +1,220 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// ConflictResolverState holds conflict blocks and their choices. +type ConflictResolverState struct { + text string + parts []conflictPart + choices []MergeChoice + bad int + built bool +} + +// conflictPart is plain text or a conflict block. +type conflictPart struct { + lines []string + ours, theirs []string + oursRef, theirsRef string + line int + conflict bool +} + +// Resolved returns chosen blocks and all blocks. +func (s *ConflictResolverState) Resolved() (done, total int) { + for i, p := range s.parts { + if p.conflict { + total++ + if s.choices[i] != MergeUnresolved { + done++ + } + } + } + return done, total +} + +// Result applies the choices; unresolved blocks keep markers. +func (s *ConflictResolverState) Result() string { + var out []string + for i, p := range s.parts { + if !p.conflict { + out = append(out, p.lines...) + continue + } + switch s.choices[i] { + case MergeOurs: + out = append(out, p.ours...) + case MergeTheirs: + out = append(out, p.theirs...) + case MergeBoth: + out = append(append(out, p.ours...), p.theirs...) + default: + out = append(out, p.lines...) + } + } + return strings.Join(out, "\n") +} + +// ConflictResolverOptions configure a ConflictResolver. +type ConflictResolverOptions struct { + Disabled bool +} + +// ConflictResolver resolves the git conflict blocks of text. +func ConflictResolver(c *ui.Context, s *ConflictResolverState, text string, opts ConflictResolverOptions) ChoiceResult { + if !s.built || s.text != text { + s.parts, s.bad = conflictParse(internal.SplitLines(text)) + s.choices = make([]MergeChoice, len(s.parts)) + s.text, s.built = text, true + _, total := s.Resolved() + slog.Debug("mujica: conflict resolver parse", "conflicts", total, "badLine", s.bad) + } + k := Tokens(c) + u := Density(c).Unit() + col := ui.Column(c).AlignItems(ui.Stretch).Gap(u * 3).Disabled(opts.Disabled) + res := ChoiceResult{Element: col} + col.Children(func() { + done, total := s.Resolved() + ui.Row(c).AlignItems(ui.Center).Gap(u * 3).Children(func() { + ui.Text(c, fmt.Sprintf(msg(c, "conflict_resolver.resolved"), done, total)).FontWeight(600).Role(ui.RoleStatus) + if total > 0 { + ui.Box(c).Height(4).Grow(1).Radius(2).Background(k.Border).Role(ui.RoleNone).Draw(func(p *ui.Painter, r ui.Rect) { + p.Fill(ui.Rect{X: r.X, Y: r.Y, W: r.W * float32(done) / float32(total), H: r.H}, k.Success, 2) + }) + } + }) + if s.bad > 0 { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).TextColor(k.Danger).Children(func() { + ui.Icon(c, icons.Must("circle-alert")).Size(16, 16) + ui.Text(c, fmt.Sprintf(msg(c, "conflict_resolver.broken"), s.bad)).Role(ui.RoleStatus) + }) + } + if total == 0 && s.bad == 0 { + ui.Text(c, msg(c, "conflict_resolver.none")).TextColor(k.TextMuted) + } + n := 0 + for i, p := range s.parts { + if !p.conflict { + continue + } + n++ + if conflictBlock(c, s, i, n) && !col.IsDisabled() { + res.changed = true + } + } + }) + return res +} + +// conflictBlock shows one conflict and its choice buttons. +func conflictBlock(c *ui.Context, s *ConflictResolverState, i, n int) bool { + k := Tokens(c) + u := Density(c).Unit() + p := s.parts[i] + choice := s.choices[i] + changed := false + card := ui.Column(c).AlignItems(ui.Stretch).Background(k.Surface).Border(theme.BorderWidth, k.Border).Radius(theme.CardRadius).Clip() + card.Children(func() { + ui.Row(c).AlignItems(ui.Center).Gap(u*2).Padding(u*2, u*3).Background(k.Background).Children(func() { + icon, colr, key := "triangle-alert", k.Warning, "conflict_resolver.open" + if choice != MergeUnresolved { + icon, colr, key = "circle-check", k.Success, "conflict_resolver.done" + } + ui.Icon(c, icons.Must(icon)).Size(14, 14).TextColor(colr) + ui.Text(c, fmt.Sprintf(msg(c, "conflict_resolver.title"), n, p.line)).Font(theme.SerifFont).FontWeight(600) + ui.Text(c, msg(c, key)).FontSize(FontSize(c, theme.CaptionSize)).TextColor(colr) + }) + ui.Grid(c).ColumnTracks(ui.Fr(1), ui.Fr(1)).Children(func() { + side := func(title, ref string, lines []string, col ui.Color, on bool) { + cell := ui.Column(c).Gap(u).Padding(u*2, u*3).MinWidth(0).Clip() + if on { + cell.Background(col.Mix(k.Surface, 0.88)) + } + cell.Children(func() { + ui.Row(c).Gap(u).AlignItems(ui.Center).Children(func() { + if on { + ui.Icon(c, icons.Must("check")).Size(14, 14).TextColor(k.AccentText) + } + ui.Text(c, title).FontSize(FontSize(c, theme.CaptionSize)).FontWeight(600).TextColor(col) + ui.Text(c, ref).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine() + }) + mergeLines(c, lines, false) + }) + } + side(msg(c, "conflict_resolver.current"), p.oursRef, p.ours, k.Info, choice == MergeOurs || choice == MergeBoth) + side(msg(c, "conflict_resolver.incoming"), p.theirsRef, p.theirs, k.Warning, choice == MergeTheirs || choice == MergeBoth) + }) + ui.Row(c).Gap(u*2).Padding(u*2, u*3).Wrap().Children(func() { + for _, opt := range []struct { + choice MergeChoice + key string + }{{MergeOurs, "take_current"}, {MergeTheirs, "take_incoming"}, {MergeBoth, "take_both"}, {MergeUnresolved, "reset"}} { + if opt.choice == MergeUnresolved && choice == MergeUnresolved { + continue + } + if mergeChoiceButton(c, msg(c, "conflict_resolver."+opt.key), choice == opt.choice && opt.choice != MergeUnresolved).Clicked() && choice != opt.choice { + s.choices[i], changed = opt.choice, true + slog.Debug("mujica: conflict resolver choose", "block", n, "choice", opt.key) + } + } + }) + }) + return changed +} + +// conflictParse splits at markers; bad is an unclosed block's line. +func conflictParse(lines []string) (parts []conflictPart, bad int) { + var plain []string + for i := 0; i < len(lines); i++ { + if !strings.HasPrefix(lines[i], "<<<<<<<") { + plain = append(plain, lines[i]) + continue + } + start := i + p := conflictPart{conflict: true, line: i + 1, oursRef: strings.TrimSpace(lines[i][7:])} + stage, j := 0, i+1 + for ; j < len(lines); j++ { + l := lines[j] + switch { + case stage == 0 && strings.HasPrefix(l, "|||||||"): + stage = 1 + case stage < 2 && l == "=======": + stage = 2 + case stage == 2 && strings.HasPrefix(l, ">>>>>>>"): + p.theirsRef = strings.TrimSpace(l[7:]) + stage = 3 + case stage == 0: + p.ours = append(p.ours, l) + case stage == 2: + p.theirs = append(p.theirs, l) + } + if stage == 3 { + break + } + } + if stage != 3 { + return []conflictPart{{lines: lines}}, start + 1 + } + if len(plain) > 0 { + parts = append(parts, conflictPart{lines: plain}) + plain = nil + } + p.lines = lines[start : j+1] + parts = append(parts, p) + i = j + } + if len(plain) > 0 { + parts = append(parts, conflictPart{lines: plain}) + } + return parts, 0 +} diff --git a/conflict_resolver_test.go b/conflict_resolver_test.go new file mode 100644 index 0000000..9318d60 --- /dev/null +++ b/conflict_resolver_test.go @@ -0,0 +1,86 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +const conflictText = "intro\n<<<<<<< HEAD\nours one\n=======\ntheirs one\n>>>>>>> feature\nmiddle\n<<<<<<< HEAD\nours two\n||||||| base\nold two\n=======\ntheirs two\n>>>>>>> feature\nend" + +func TestConflictParse(t *testing.T) { + parts, bad := conflictParse([]string{"a", "<<<<<<< HEAD", "x", "=======", "y", ">>>>>>> br", "b"}) + if bad != 0 || len(parts) != 3 || !parts[1].conflict || parts[1].oursRef != "HEAD" || parts[1].theirsRef != "br" || parts[1].line != 2 { + t.Fatalf("parts %+v bad %d", parts, bad) + } + parts, bad = conflictParse([]string{"a", "<<<<<<< HEAD", "x", "======="}) + if bad != 2 || len(parts) != 1 || parts[0].conflict { + t.Fatalf("unclosed: %+v bad %d", parts, bad) + } +} + +func TestConflictResolverAcceptAndCount(t *testing.T) { + var s ConflictResolverState + changes := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Scroll(c).Fill().Children(func() { + if ConflictResolver(c, &s, conflictText, ConflictResolverOptions{}).Changed() { + changes++ + } + }) + }, 800, 900) + if !tt.HasText("0 of 2 conflicts resolved") || !tt.HasText("Conflict 2 · line 8") { + t.Fatalf("start: %q", tt.Texts()) + } + if err := tt.Click("Accept incoming"); err != nil { + t.Fatal(err) + } + if !tt.HasText("1 of 2 conflicts resolved") || changes != 1 { + t.Fatalf("after one: %q", tt.Texts()) + } + if err := tt.Click("Accept both"); err != nil { + t.Fatal(err) + } + if got := s.Result(); got != "intro\nours one\ntheirs one\nmiddle\n<<<<<<< HEAD\nours two\n||||||| base\nold two\n=======\ntheirs two\n>>>>>>> feature\nend" { + t.Fatalf("result %q", got) + } + if err := tt.Click("Undo"); err != nil { + t.Fatal(err) + } + if d, n := s.Resolved(); d != 0 || n != 2 || changes != 3 { + t.Fatalf("undo: %d/%d changes %d", d, n, changes) + } +} + +func TestConflictResolverBrokenAndDisabled(t *testing.T) { + var s ConflictResolverState + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ConflictResolver(c, &s, "a\n<<<<<<< HEAD\nx", ConflictResolverOptions{}) + }, 600, 300) + if !tt.HasText("Conflict markers are not closed after line 2") { + t.Fatalf("broken: %q", tt.Texts()) + } + if s.Result() != "a\n<<<<<<< HEAD\nx" { + t.Fatalf("broken result %q", s.Result()) + } + var d ConflictResolverState + tt = ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ConflictResolver(c, &d, conflictText, ConflictResolverOptions{Disabled: true}) + }, 800, 900) + _ = tt.Click("Accept current") + if done, _ := d.Resolved(); done != 0 { + t.Fatal("disabled resolver accepted") + } +} + +func TestConflictResolverSnapshot(t *testing.T) { + snapshotAfter(t, "conflict_resolver", 640, 560, func(c *ui.Context) { + s := ui.Local(c.Root(), "s", func() *ConflictResolverState { return &ConflictResolverState{} }) + ui.Column(c).Padding(16).Children(func() { + ConflictResolver(c, *s, conflictText, ConflictResolverOptions{}) + }) + }, func(tt *ui.Tester) { _ = tt.Click("Accept incoming") }) +} diff --git a/diff_stat.go b/diff_stat.go new file mode 100644 index 0000000..cba272f --- /dev/null +++ b/diff_stat.go @@ -0,0 +1,72 @@ +package mujica + +import ( + "fmt" + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// DiffStatOptions configure a DiffStat. +type DiffStatOptions struct { + // Blocks is the ratio bar length; zero means 5. + Blocks int +} + +// DiffStat shows added and deleted counts with a ratio bar. +func DiffStat(c *ui.Context, added, deleted int, opts DiffStatOptions) *ui.Element { + if added < 0 || deleted < 0 { + panic("mujica: DiffStat counts must not be negative") + } + n := opts.Blocks + if n == 0 { + n = 5 + } + if n < 0 { + panic("mujica: DiffStat Blocks is negative") + } + k := Tokens(c) + u := Density(c).Unit() + plus, minus := diffStatBlocks(added, deleted, n) + row := ui.Row(c).AlignItems(ui.Center).Gap(u * 2).Shrink(0). + Label(fmt.Sprintf(msg(c, "diff_stat.label"), added, deleted)) + row.Children(func() { + mono := func(s string, col ui.Color) { + ui.Text(c, s).Font(theme.MonoFont).FontFeatures("tnum").FontSize(FontSize(c, theme.CaptionSize)).TextColor(col).SingleLine() + } + mono(fmt.Sprintf("+%d", added), k.Success) + mono(fmt.Sprintf("−%d", deleted), k.Danger) + ui.Row(c).Gap(2).Shrink(0).Role(ui.RoleNone).Children(func() { + for i := range n { + col := k.Border + switch { + case i < plus: + col = k.Success + case i < plus+minus: + col = k.Danger + } + ui.Box(c).Size(8, 8).Radius(1).Background(col) + } + }) + }) + return row +} + +// diffStatBlocks splits n blocks, one at least per nonzero side. +func diffStatBlocks(added, deleted, n int) (plus, minus int) { + total := added + deleted + if total == 0 { + return 0, 0 + } + plus = int(math.Round(float64(added) / float64(total) * float64(n))) + minus = n - plus + if added > 0 && plus == 0 { + plus, minus = 1, n-1 + } + if deleted > 0 && minus == 0 && n > 1 { + plus, minus = n-1, 1 + } + return plus, minus +} diff --git a/diff_stat_test.go b/diff_stat_test.go new file mode 100644 index 0000000..feeefc1 --- /dev/null +++ b/diff_stat_test.go @@ -0,0 +1,60 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestDiffStatBlocks(t *testing.T) { + for _, tc := range []struct{ a, d, n, plus, minus int }{ + {0, 0, 5, 0, 0}, + {10, 0, 5, 5, 0}, + {0, 3, 5, 0, 5}, + {6, 4, 5, 3, 2}, + {1000, 1, 5, 4, 1}, + {1, 1000, 5, 1, 4}, + {1, 1, 1, 1, 0}, + } { + p, m := diffStatBlocks(tc.a, tc.d, tc.n) + if p != tc.plus || m != tc.minus { + t.Errorf("blocks(%d,%d,%d) = %d,%d want %d,%d", tc.a, tc.d, tc.n, p, m, tc.plus, tc.minus) + } + } +} + +func TestDiffStatTextAndName(t *testing.T) { + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + DiffStat(c, 12, 3, DiffStatOptions{}) + }, 300, 60) + if !tt.HasText("+12") || !tt.HasText("−3") { + t.Fatalf("counts: %q", tt.Texts()) + } + if _, ok := tt.Find("12 additions, 3 deletions"); !ok { + t.Fatal("not named for assistive technology") + } + for _, tc := range []struct{ a, d, n int }{{-1, 0, 0}, {0, -1, 0}, {1, 1, -2}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%v did not panic", tc) + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + DiffStat(c, tc.a, tc.d, DiffStatOptions{Blocks: tc.n}) + }, 100, 50, 1) + }() + } +} + +func TestDiffStatSnapshot(t *testing.T) { + snapshot(t, "diff_stat", 360, 120, func(c *ui.Context) { + ui.Column(c).Padding(16).Gap(10).Children(func() { + DiffStat(c, 128, 32, DiffStatOptions{}) + DiffStat(c, 4, 0, DiffStatOptions{}) + DiffStat(c, 0, 0, DiffStatOptions{Blocks: 8}) + }) + }) +} diff --git a/diff_viewer.go b/diff_viewer.go new file mode 100644 index 0000000..839c0d7 --- /dev/null +++ b/diff_viewer.go @@ -0,0 +1,225 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strconv" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// DiffViewerState keeps a DiffViewer's diff, opened folds and scroll place. +type DiffViewerState struct { + list ui.ListState + from, to string + diff []internal.DiffLine + rows []diffViewerRow + expanded map[int]bool + split bool + context int + built bool + dirty bool +} + +// DiffViewerOptions configure a DiffViewer. +type DiffViewerOptions struct { + // SideBySide shows old and new in two columns. + SideBySide bool + // Context is unchanged lines kept around changes; zero means 3. + Context int + // Language picks syntax colors, as "go"; empty is plain. + Language string +} + +// diffViewerRow is a fold or one line per side. +type diffViewerRow struct { + left, right int + fold, hidden int +} + +// DiffViewer compares two texts by line; give it a height. +func DiffViewer(c *ui.Context, s *DiffViewerState, from, to string, opts DiffViewerOptions) *ui.Element { + ctx := opts.Context + if ctx == 0 { + ctx = 3 + } + if ctx < 0 { + panic("mujica: DiffViewer Context is negative") + } + if !s.built || s.from != from || s.to != to { + s.diff = internal.LineDiff(internal.SplitLines(from), internal.SplitLines(to)) + s.from, s.to, s.built, s.dirty, s.expanded = from, to, true, true, map[int]bool{} + add, del := internal.DiffStats(s.diff) + slog.Debug("mujica: diff viewer diff", "lines", len(s.diff), "added", add, "deleted", del) + } + if s.dirty || s.split != opts.SideBySide || s.context != ctx { + s.rows = diffViewerRows(s.diff, ctx, s.expanded, opts.SideBySide) + s.split, s.context, s.dirty = opts.SideBySide, ctx, false + } + k := Tokens(c) + digits := float32(len(strconv.Itoa(max(len(s.diff), 1)))) + numW := digits*8 + Density(c).Unit()*3 + e := ui.List(c, &s.list, len(s.rows), func(i int) { + r := s.rows[i] + if r.hidden > 0 { + diffViewerFold(c, s, r) + return + } + row := ui.Row(c).AlignItems(ui.Stretch).MinHeight(theme.MinHitSize) + row.Children(func() { + if !opts.SideBySide { + diffViewerCell(c, s.diff[r.left], opts.Language, numW, true) + return + } + for _, side := range []int{r.left, r.right} { + half := ui.Row(c).Grow(1).Basis(0).MinWidth(0).AlignItems(ui.Stretch).Clip() + half.Children(func() { + if side < 0 { + half.Background(k.Background) + return + } + diffViewerCell(c, s.diff[side], opts.Language, numW, false) + }) + } + }) + }) + e.Background(k.Surface).Border(theme.BorderWidth, k.Border).Radius(theme.ControlRadius).Font(theme.MonoFont) + return e +} + +// diffViewerCell shows one diff line with numbers, sign and tint. +func diffViewerCell(c *ui.Context, d internal.DiffLine, language string, numW float32, both bool) { + k := Tokens(c) + u := Density(c).Unit() + small := FontSize(c, theme.CaptionSize) + sign, col, name := " ", k.TextMuted, "" + switch d.Op { + case internal.DiffDelete: + sign, col, name = "−", k.Danger, msg(c, "diff_viewer.deleted") + case internal.DiffInsert: + sign, col, name = "+", k.Success, msg(c, "diff_viewer.added") + } + cell := ui.Row(c).Grow(1).MinWidth(0).AlignItems(ui.Center) + if d.Op != internal.DiffEqual { + cell.Background(col.Mix(k.Surface, 0.88)) + } + num := func(n int) { + t := "" + if n > 0 { + t = strconv.Itoa(n) + } + ui.Text(c, t).FontSize(small).FontFeatures("tnum").TextColor(k.TextMuted).Width(numW).TextAlign(ui.End).Shrink(0).Padding(0, u, 0, 0) + } + cell.Children(func() { + if both || d.Op != internal.DiffInsert { + num(d.Old) + } + if both || d.Op == internal.DiffInsert { + num(d.New) + } + ui.Text(c, sign).FontWeight(700).TextColor(col).Width(u * 4).TextAlign(ui.Center).Shrink(0) + spans, _ := internal.CodeSpans(k, language, d.Text, false) + if len(spans) == 0 || d.Text == "" { + spans = []ui.Span{{Text: " "}} + } + t := ui.RichText(c, spans...).NoWrap().MinWidth(0).Padding(u*0.5, u*2, u*0.5, 0) + if name != "" { + t.Label(name + ": " + d.Text) + } + }) +} + +// diffViewerFold is the button standing for hidden unchanged lines. +func diffViewerFold(c *ui.Context, s *DiffViewerState, r diffViewerRow) { + k := Tokens(c) + u := Density(c).Unit() + b := ui.ButtonBase(c).Justify(ui.Start).Gap(u*2).MinHeight(theme.MinHitSize).Padding(0, u*3).Background(k.Background). + TextColor(k.TextMuted).Cursor(ui.CursorPointer) + label := fmt.Sprintf(msg(c, "diff_viewer.fold"), r.hidden) + b.Label(label) + internal.Ring(b, k.Focus, 0) + if b.Hovered() { + b.Background(k.SurfaceHover).TextColor(k.Text) + } + b.Transition(colorFade) + b.Children(func() { + ui.Text(c, "⋯").FontWeight(700) + ui.Text(c, label).Font(theme.SerifFont).FontSize(FontSize(c, theme.CaptionSize)) + }) + if b.Clicked() && !b.IsDisabled() { + s.expanded[r.fold] = true + s.dirty = true + slog.Debug("mujica: diff viewer unfold", "at", r.fold, "lines", r.hidden) + } +} + +// diffViewerRows folds long unchanged runs and pairs split sides. +func diffViewerRows(diff []internal.DiffLine, ctx int, expanded map[int]bool, split bool) []diffViewerRow { + var rows []diffViewerRow + var dels, ins []int + flush := func() { + for j := 0; j < max(len(dels), len(ins)); j++ { + r := diffViewerRow{left: -1, right: -1} + if j < len(dels) { + r.left = dels[j] + } + if j < len(ins) { + r.right = ins[j] + } + rows = append(rows, r) + } + dels, ins = dels[:0], ins[:0] + } + line := func(i int) { + switch { + case !split: + rows = append(rows, diffViewerRow{left: i, right: -1}) + case diff[i].Op == internal.DiffDelete: + dels = append(dels, i) + case diff[i].Op == internal.DiffInsert: + ins = append(ins, i) + default: + flush() + rows = append(rows, diffViewerRow{left: i, right: i}) + } + } + for i := 0; i < len(diff); { + if diff[i].Op != internal.DiffEqual { + line(i) + i++ + continue + } + end := i + for end < len(diff) && diff[end].Op == internal.DiffEqual { + end++ + } + keepHead, keepTail := ctx, ctx + if i == 0 { + keepHead = 0 + } + if end == len(diff) { + keepTail = 0 + } + hidden := end - i - keepHead - keepTail + if hidden <= 1 || expanded[i+keepHead] { + for j := i; j < end; j++ { + line(j) + } + } else { + for j := i; j < i+keepHead; j++ { + line(j) + } + flush() + rows = append(rows, diffViewerRow{left: -1, right: -1, fold: i + keepHead, hidden: hidden}) + for j := end - keepTail; j < end; j++ { + line(j) + } + } + i = end + } + flush() + return rows +} diff --git a/diff_viewer_test.go b/diff_viewer_test.go new file mode 100644 index 0000000..702a6e7 --- /dev/null +++ b/diff_viewer_test.go @@ -0,0 +1,105 @@ +package mujica + +import ( + "fmt" + "strings" + "testing" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" +) + +const diffOld = "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tfmt.Println(\"hi\")\n}\n" +const diffNew = "package main\n\nimport \"fmt\"\n\nfunc main() {\n\tname := \"court\"\n\tfmt.Println(\"hi\", name)\n}\n" + +func TestDiffViewerRowsFoldAndPair(t *testing.T) { + var a, b []string + for i := range 30 { + a = append(a, fmt.Sprintf("line %d", i)) + } + b = append(b, a...) + b[15] = "changed" + d := internal.LineDiff(a, b) + rows := diffViewerRows(d, 3, map[int]bool{}, false) + // 12 hidden, 3 context, delete, insert, 3 context, 11 hidden. + if len(rows) != 10 || rows[0].hidden != 12 || rows[9].hidden != 11 { + t.Fatalf("unified rows %+v", rows) + } + split := diffViewerRows(d, 3, map[int]bool{}, true) + if len(split) != 9 || split[4].left < 0 || split[4].right < 0 || d[split[4].left].Op != internal.DiffDelete { + t.Fatalf("split rows %+v", split) + } + open := diffViewerRows(d, 3, map[int]bool{0: true}, false) + if len(open) != 21 || open[0].hidden != 0 { + t.Fatalf("expanded rows %d", len(open)) + } +} + +func TestDiffViewerUnfoldAndModes(t *testing.T) { + var s DiffViewerState + from := strings.Repeat("same\n", 20) + "old\n" + to := strings.Repeat("same\n", 20) + "new\n" + split := false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + DiffViewer(c, &s, from, to, DiffViewerOptions{SideBySide: split}).Height(760) + }, 700, 800) + if !tt.HasText("17 unchanged lines") { + t.Fatalf("fold: %q", tt.Texts()) + } + if _, ok := tt.Find("Deleted: old"); !ok { + t.Fatal("deleted line not named") + } + if _, ok := tt.Find("Added: new"); !ok { + t.Fatal("added line not named") + } + if err := tt.Click("17 unchanged lines"); err != nil { + t.Fatal(err) + } + if tt.HasText("17 unchanged lines") || !tt.HasText("17") { + t.Fatalf("unfold: %q", tt.Texts()) + } + split = true + tt.Frame() + if !tt.HasText("−") || !tt.HasText("+") { + t.Fatalf("split: %q", tt.Texts()) + } +} + +func TestDiffViewerVirtualized(t *testing.T) { + var a, b strings.Builder + for i := range 100000 { + fmt.Fprintf(&a, "line %d\n", i) + if i%1000 == 0 { + fmt.Fprintf(&b, "edit %d\n", i) + } else { + fmt.Fprintf(&b, "line %d\n", i) + } + } + from, to := a.String(), b.String() + var s DiffViewerState + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + DiffViewer(c, &s, from, to, DiffViewerOptions{}).Height(400) + }, 700, 440) + if n := len(tt.Texts()); n > 400 { + t.Fatalf("%d texts for 100,000 lines", n) + } + rows := &s.rows[0] + tt.Frame() + if &s.rows[0] != rows { + t.Fatal("rows rebuilt without a change") + } +} + +func TestDiffViewerSnapshot(t *testing.T) { + snapshot(t, "diff_viewer", 640, 520, func(c *ui.Context) { + s := ui.Local(c.Root(), "u", func() *DiffViewerState { return &DiffViewerState{} }) + p := ui.Local(c.Root(), "p", func() *DiffViewerState { return &DiffViewerState{} }) + ui.Column(c).Padding(16).Gap(12).Children(func() { + DiffViewer(c, *s, diffOld, diffNew, DiffViewerOptions{Language: "go", Context: 1}).Height(220) + DiffViewer(c, *p, diffOld, diffNew, DiffViewerOptions{Language: "go", SideBySide: true, Context: 1}).Height(220) + }) + }) +} diff --git a/docs/components/301-diff-viewer.md b/docs/components/301-diff-viewer.md new file mode 100644 index 0000000..e002e9f --- /dev/null +++ b/docs/components/301-diff-viewer.md @@ -0,0 +1,52 @@ +# 301 DiffViewer 差异查看器 + +## 用途 + +按行比较两段文本,统一或并排显示:行号、增删高亮、折叠较长的未变更区;大文件只构建可见行。 + +## 最小示例 + +```go +var state mujica.DiffViewerState +from := "func main() {\n\tprintln(\"hi\")\n}\n" +to := "func main() {\n\tprintln(\"hello\")\n}\n" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.DiffViewer(c, &state, from, to, mujica.DiffViewerOptions{Language: "go", SideBySide: true}).Height(240) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func DiffViewer(c *ui.Context, s *DiffViewerState, from, to string, opts DiffViewerOptions) *ui.Element` + +## 参数 + +`DiffViewerOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| SideBySide | bool | false | 并排两栏;否则统一一栏。 | +| Context | int | 0(即 3) | 变更前后保留的未变更行数;为负 panic。 | +| Language | string | "" | 语法高亮语言,如 go;空为纯文本。 | + +`DiffViewerState` 由调用方持有,保存差异、已展开的折叠与滚动位置。差异只在 from 或 to 改变时重新计算(Myers 行差异)。给返回元素一个高度。 + +## 状态 + +- 删除行:Danger 浅色底与 − 号;新增行:Success 浅色底与 + 号;不只靠颜色。 +- 统一视图显示新旧两列行号;并排视图每侧一列,缺行的一侧为空底。 +- 超过 2×Context 的未变更区折叠为“N 行未更改”按钮,点击展开,悬停 120 ms 过渡。 + +## 事件 + +- 无;展开折叠保存在状态中。 + +## 键盘操作 + +- 列表可获得焦点并滚动;折叠按钮用 Tab 到达,Enter 或 Space 展开。 + +## 限制 + +- 只做行级差异;词级差异见 InlineDiff。 +- 长行不换行,超出部分裁剪。 +- 文本换成新字符串后折叠全部重置。 diff --git a/docs/components/302-inline-diff.md b/docs/components/302-inline-diff.md new file mode 100644 index 0000000..f3e5410 --- /dev/null +++ b/docs/components/302-inline-diff.md @@ -0,0 +1,44 @@ +# 302 InlineDiff 行内差异 + +## 用途 + +并列显示一行的旧版与新版,标出词级的删除与新增。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.InlineDiff(c, "The court meets at noon", "The court meets at dusk", mujica.InlineDiffOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func InlineDiff(c *ui.Context, from, to string, opts InlineDiffOptions) *ui.Element` + +## 参数 + +`InlineDiffOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Mono | bool | false | 使用等宽字体,适合代码。 | + +词按字母数字、空白与单个标点切分;差异只在 from 或 to 改变时重新计算。 + +## 状态 + +- 旧行以 − 开头,删除的词带浅色底与删除线;新行以 + 开头,新增的词带浅色底与下划线。 +- 两行分别以“原文”“新文”加全文朗读。 + +## 事件 + +- 无。 + +## 键盘操作 + +- 无:纯展示。 + +## 限制 + +- 只比较一行;多行请用 DiffViewer。 diff --git a/docs/components/303-three-way-merge.md b/docs/components/303-three-way-merge.md new file mode 100644 index 0000000..c03a2be --- /dev/null +++ b/docs/components/303-three-way-merge.md @@ -0,0 +1,53 @@ +# 303 ThreeWayMerge 三方合并 + +## 用途 + +以本地、基准、远端三栏和结果栏显示三方合并,逐块采纳本地、远端、两者或基准。 + +## 最小示例 + +```go +var state mujica.ThreeWayMergeState +base, local, remote := "a\nb\nc", "a\nB1\nc", "a\nB2\nc" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ThreeWayMerge(c, &state, base, local, remote, mujica.ThreeWayMergeOptions{}) + r.Element.Height(280) + if done, total := state.Resolved(); r.Changed() && done == total { + _ = state.Result() // write the merged file + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func ThreeWayMerge(c *ui.Context, s *ThreeWayMergeState, base, ours, theirs string, opts ThreeWayMergeOptions) ChoiceResult` + +## 参数 + +`ThreeWayMergeOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Disabled | bool | false | 禁用采纳。 | + +`ThreeWayMergeState.Result()` 返回合并文本,未解决的冲突保留冲突标记;`Resolved()` 返回已解决与总冲突数。分块只在三段文本改变时计算。给返回的 `Element` 一个高度。 + +## 状态 + +- 只有一侧修改或两侧相同修改的块自动合并,来源一侧以浅色底标出。 +- 冲突块在结果栏显示 Danger 色“未解决”与警示图标。 +- 已采纳的按钮为 Selection 底、AccentText 边框与对勾。 +- 较长的未变更块只显示首尾各两行。 + +## 事件 + +- `Changed()`:某个冲突的选择改变。 + +## 键盘操作 + +- 列表可获得焦点并滚动;采纳按钮用 Tab 到达,Enter 或 Space 选择。 + +## 限制 + +- 按行合并,不做词级合并。 +- 相邻(中间没有未变更行)的两侧修改视为冲突。 diff --git a/docs/components/304-conflict-resolver.md b/docs/components/304-conflict-resolver.md new file mode 100644 index 0000000..8f7fed8 --- /dev/null +++ b/docs/components/304-conflict-resolver.md @@ -0,0 +1,51 @@ +# 304 ConflictResolver 冲突解决 + +## 用途 + +读取带 git 冲突标记的文本,列出冲突块,逐块采纳当前、传入或两者,并显示已解决计数。 + +## 最小示例 + +```go +var state mujica.ConflictResolverState +text := "a\n<<<<<<< HEAD\nmine\n=======\ntheirs\n>>>>>>> feature\nb" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ConflictResolver(c, &state, text, mujica.ConflictResolverOptions{}).Changed() { + _ = state.Result() // save the file once every block is resolved + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func ConflictResolver(c *ui.Context, s *ConflictResolverState, text string, opts ConflictResolverOptions) ChoiceResult` + +## 参数 + +`ConflictResolverOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Disabled | bool | false | 禁用采纳。 | + +`ConflictResolverState.Result()` 返回替换后的文本,未解决的块保留原标记;`Resolved()` 返回已解决与总数。只在文本改变时重新解析。 + +## 状态 + +- 顶部显示“已解决 n / m 个冲突”与 Success 色进度条。 +- 未解决块标题为警示图标与“未解决”,已解决为对勾与“已解决”。 +- 被采纳的一侧显示浅色底与对勾,按钮带对勾;已解决块提供“撤销”。 +- 标记未闭合时显示 Danger 色提示与起始行号,不列出冲突。 + +## 事件 + +- `Changed()`:某块的选择改变。 + +## 键盘操作 + +- Tab 依次经过各块按钮,Enter 或 Space 采纳。 + +## 限制 + +- 支持 diff3 样式的 ||||||| 基准段,但不显示它。 +- 冲突块不虚拟化;适合单个文件的冲突数量。 diff --git a/docs/components/305-changes-list.md b/docs/components/305-changes-list.md new file mode 100644 index 0000000..54ae845 --- /dev/null +++ b/docs/components/305-changes-list.md @@ -0,0 +1,66 @@ +# 305 ChangesList 更改列表 + +## 用途 + +把工作区更改分为“已暂存”与“更改”两组,逐文件或整组暂存、取消暂存,并选择文件查看差异。只构建可见行。 + +## 最小示例 + +```go +var state mujica.ChangesListState +files := []mujica.ChangedFile{ + {Path: "main.go", Status: mujica.GitModified, Staged: true}, + {Path: "notes.txt", Status: mujica.GitUntracked}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ChangesList(c, &state, files, mujica.ChangesListOptions{}) + r.Element.Height(240) + if action, path, ok := r.Action(); ok { + _, _ = action, path // run git add or git restore --staged + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func ChangesList(c *ui.Context, s *ChangesListState, files []ChangedFile, opts ChangesListOptions) GitListResult` + +## 参数 + +`ChangedFile` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Path | string | 必填 | 文件路径;为空时 panic。 | +| Status | GitStatus | GitModified | 状态,见 GitStatusBadge;未知值 panic。 | +| Staged | bool | false | 放入已暂存组。 | + +`ChangesListOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Disabled | bool | false | 禁用:不暂存、不改变选择。 | + +`ChangesListState` 由调用方持有,`Selected()` 返回所选文件在 `files` 中的下标,无则 -1。`files` 换成新切片或长度变化时重新分组,分组不在每帧计算。给返回的 `Element` 一个高度。 + +## 状态 + +- 组标题为衬线小字与计数,空组的整组按钮禁用。 +- 每行显示 GitStatusBadge(字母、边框与颜色)、文件名与目录。 +- 选中行:Selection 背景加左侧 AccentText 竖线。 +- 悬停与按下:图标按钮 SurfaceHover / Selection 背景。 + +## 事件 + +- `Action()` 返回 `"stage"`、`"unstage"`(附路径)或 `"stage_all"`、`"unstage_all"`。 +- `Changed()` 选择变化;`Submitted()` 双击或 Enter。 + +## 键盘操作 + +- Tab 进入列表;↑/↓、Home/End 移动选择,跳过组标题;输入文件名开头字母跳转;Enter 提交。 +- 行内暂存按钮可用 Tab 到达,Enter 或 Space 执行。 + +## 限制 + +- 不读取仓库:文件列表与暂存操作都由调用方完成。 +- 重命名的旧路径不单独显示。 diff --git a/docs/components/306-commit-input.md b/docs/components/306-commit-input.md new file mode 100644 index 0000000..4676a1a --- /dev/null +++ b/docs/components/306-commit-input.md @@ -0,0 +1,62 @@ +# 306 CommitInput 提交输入 + +## 用途 + +编辑提交标题与正文,标题长度提示,提交与修订(amend),并防止重复提交。 + +## 最小示例 + +```go +msg := mujica.CommitMessage{} +busy := false +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CommitInput(c, &msg, mujica.CommitInputOptions{Busy: busy}) + if r.Committed() || r.Amended() { + busy = true // run git commit, then clear busy + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func CommitInput(c *ui.Context, m *CommitMessage, opts CommitInputOptions) CommitInputResult` + +## 参数 + +`CommitMessage` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Title | string | "" | 提交标题;为空时提交与修订禁用。 | +| Body | string | "" | 提交正文。 | + +`CommitInputOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| TitleLimit | int | 0(即 50) | 建议的标题长度;为负 panic。 | +| Busy | bool | false | 提交进行中:提交按钮显示加载,输入只读。 | +| Disabled | bool | false | 整体禁用。 | + +返回 `CommitInputResult`,含 `Element`。 + +## 状态 + +- 标题右侧显示“已用/上限”,超出时变为 Warning 色并朗读超出字数。 +- 提交后进入待定状态:按钮与输入锁定,直到调用方把 Busy 设为 true 再恢复 false。 +- Busy 时提交按钮保留尺寸并显示加载。 + +## 事件 + +- `Committed()`:点击提交、标题内 Enter 或正文内 Cmd+Enter。 +- `Amended()`:点击修订。 + +## 键盘操作 + +- Tab 依次经过标题、正文、修订、提交。 +- 标题中 Enter、正文中 Cmd+Enter(非 macOS 为 Ctrl+Enter)提交。 + +## 限制 + +- 防重入依赖调用方在提交期间设置 Busy;从未设置 Busy 时组件保持锁定。 +- 不做提交信息格式校验。 diff --git a/docs/components/307-commit-graph.md b/docs/components/307-commit-graph.md new file mode 100644 index 0000000..82398ea --- /dev/null +++ b/docs/components/307-commit-graph.md @@ -0,0 +1,67 @@ +# 307 CommitGraph 提交图谱 + +## 用途 + +按从新到旧的顺序显示提交,左侧绘制泳道、分支与合并线;只构建可见行,可承载十万级提交。 + +## 最小示例 + +```go +var state mujica.CommitGraphState +commits := []mujica.Commit{ + {Hash: "c3", Parents: []string{"c2", "b1"}, Subject: "Merge branch", Refs: []string{"main"}}, + {Hash: "b1", Parents: []string{"c1"}, Subject: "Feature"}, + {Hash: "c2", Parents: []string{"c1"}, Subject: "Fix"}, + {Hash: "c1", Subject: "Initial commit"}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CommitGraph(c, &state, commits, mujica.CommitGraphOptions{}).Element.Height(240) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func CommitGraph(c *ui.Context, s *CommitGraphState, commits []Commit, opts CommitGraphOptions) GitListResult` + +## 参数 + +`Commit` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Hash | string | 必填 | 提交哈希;为空时 panic。 | +| Parents | []string | nil | 父提交;两个以上为合并提交。 | +| Author | string | "" | 作者。 | +| When | time.Time | 零值 | 提交时间。 | +| Subject | string | "" | 提交标题。 | +| Refs | []string | nil | 指向该提交的分支与标签。 | + +`CommitGraphOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| TimeFormat | string | "2006-01-02 15:04" | 时间格式。 | +| MaxLanes | int | 0(即 8) | 图谱最多显示的泳道数,超出部分裁剪;为负 panic。 | +| Status | DataStatus | DataReady | 加载、追加、失败状态。 | +| Error | string | "" | 失败说明。 | + +`CommitGraphState.List` 保存选择(`Selected()` 返回哈希)。泳道布局在提交切片或长度变化时计算一次,不在每帧计算。提交须按子提交在前的拓扑顺序给出。给返回的 `Element` 一个高度。 + +## 状态 + +- 普通提交为实心圆点,合并提交为空心菱形,形状区分而不只靠颜色。 +- 泳道颜色取自 AccentText、Info、Success、Warning、Danger、TextMuted,按位置区分。 +- 选中行:Selection 背景与对勾。 + +## 事件 + +- `Changed()` 选择变化;`Submitted()` 双击或 Enter 打开提交。 + +## 键盘操作 + +- Tab 进入列表;↑/↓、Home/End 移动选择;输入标题开头字母跳转;Enter 打开。 + +## 限制 + +- 原地修改提交切片而不改变其地址与长度时,布局不会重算;请传入新切片。 +- 泳道数超过 MaxLanes 时,右侧泳道被裁剪。 diff --git a/docs/components/308-commit-list.md b/docs/components/308-commit-list.md new file mode 100644 index 0000000..1cc292b --- /dev/null +++ b/docs/components/308-commit-list.md @@ -0,0 +1,53 @@ +# 308 CommitList 提交列表 + +## 用途 + +显示提交列表:标题、引用、作者、短哈希与时间,选择后查看。只构建可见行。 + +## 最小示例 + +```go +var state mujica.ListState[string] +commits := []mujica.Commit{{Hash: "a1b2c3d4", Author: "Sakiko", When: time.Now(), Subject: "Add the commit list"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CommitList(c, &state, commits, mujica.CommitListOptions{}) + r.Element.Height(240) + if hash, ok := state.Selected(); ok && r.Submitted() { + _ = hash // show the commit + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func CommitList(c *ui.Context, s *ListState[string], commits []Commit, opts CommitListOptions) GitListResult` + +## 参数 + +`CommitListOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| TimeFormat | string | "2006-01-02 15:04" | 时间格式。 | +| Status | DataStatus | DataReady | 加载、追加、失败状态。 | +| Error | string | "" | 失败说明。 | + +`Commit` 见 CommitGraph。选择保存在 `ListState`,以哈希为键。给返回的 `Element` 一个高度。 + +## 状态 + +- 引用以 AccentText 描边小标签显示;短哈希为等宽 AccentText。 +- 空列表显示“没有提交”;加载与失败使用列表的统一占位。 +- 选中行:Selection 背景与对勾。 + +## 事件 + +- `Changed()` 选择变化;`Submitted()` 双击或 Enter。 + +## 键盘操作 + +- Tab 进入列表;↑/↓、Home/End 移动选择;输入标题开头字母跳转;Enter 打开。 + +## 限制 + +- 时间按调用方给定格式显示,不做相对时间。 diff --git a/docs/components/309-branch-selector.md b/docs/components/309-branch-selector.md new file mode 100644 index 0000000..e567aec --- /dev/null +++ b/docs/components/309-branch-selector.md @@ -0,0 +1,64 @@ +# 309 BranchSelector 分支选择器 + +## 用途 + +按钮显示当前分支,点击弹出可搜索的本地与远端分支列表;可选“新建分支”入口。 + +## 最小示例 + +```go +branch := "main" +branches := []mujica.Branch{{Name: "main", Current: true}, {Name: "origin/main", Remote: true}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.BranchSelector(c, &branch, branches, mujica.BranchSelectorOptions{AllowCreate: true}) + if name, ok := r.Created(); ok { + _ = name // run git switch -c name + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func BranchSelector(c *ui.Context, selected *string, branches []Branch, opts BranchSelectorOptions) BranchSelectorResult` + +## 参数 + +`Branch` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Name | string | 必填 | 唯一名称,远端分支带远端名,如 origin/main;为空时 panic。 | +| Remote | bool | false | 归入远端组。 | +| Current | bool | false | 当前检出的分支。 | +| Upstream | string | "" | 上游分支。 | +| Ahead, Behind | int | 0 | 领先、落后的提交数;为负 panic。 | + +`BranchSelectorOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| AllowCreate | bool | false | 搜索词不是已有分支名时,列表末尾提供“新建分支”。 | +| Disabled | bool | false | 禁用;打开中的弹层会关闭。 | + +返回 `BranchSelectorResult`,含 `Element`。过滤结果在搜索词或分支切片变化时才重新计算。 + +## 状态 + +- 弹层使用统一浮层外观,160 ms 淡入,尺寸限制在窗口内,内容滚动。 +- 本地、远端分组标题为衬线小字;当前分支加粗并带对勾。 +- 高亮项:Selection 背景,键盘移动时滚入视野。 + +## 事件 + +- `Changed()`:选择了另一个分支,`*selected` 已更新。 +- `Created()`:用户要求新建的分支名(已去除首尾空白)。 + +## 键盘操作 + +- Enter 或 Space 打开;焦点进入搜索框。 +- ↑/↓ 移动高亮并循环,Enter 选择,Escape 关闭并把焦点还给按钮。 + +## 限制 + +- 不执行 git:选择与新建都由调用方处理。 +- 搜索为大小写不敏感的子串匹配。 diff --git a/docs/components/310-branch-list.md b/docs/components/310-branch-list.md new file mode 100644 index 0000000..cec3aa1 --- /dev/null +++ b/docs/components/310-branch-list.md @@ -0,0 +1,62 @@ +# 310 BranchList 分支列表 + +## 用途 + +分支列表:标出当前分支,显示上游与领先、落后数,每行提供调用方定义的操作按钮。 + +## 最小示例 + +```go +var state mujica.ListState[string] +branches := []mujica.Branch{{Name: "main", Current: true, Upstream: "origin/main", Ahead: 2}} +actions := []mujica.GitAction{{ID: "delete", Label: "Delete", Icon: "trash-2"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.BranchList(c, &state, branches, mujica.BranchListOptions{Actions: actions}) + r.Element.Height(200) + if action, name, ok := r.Action(); ok { + _, _ = action, name // run the action on the branch + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func BranchList(c *ui.Context, s *ListState[string], branches []Branch, opts BranchListOptions) GitListResult` + +## 参数 + +`BranchListOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Actions | []GitAction | nil | 每行的图标操作;ID、Label、Icon 必填且 ID 唯一,否则 panic。 | +| Status | DataStatus | DataReady | 加载、追加、失败状态。 | +| Error | string | "" | 失败说明。 | + +`GitAction` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| ID | string | 必填 | `Action()` 返回的标识。 | +| Label | string | 必填 | 按钮名称与提示。 | +| Icon | string | 必填 | icons/ 中的图标名。 | + +`Branch` 见 BranchSelector。选择以分支名为键。给返回的 `Element` 一个高度。 + +## 状态 + +- 当前分支:对勾、加粗与“当前”文字。 +- 领先 ↑n、落后 ↓n 以箭头与数字显示,朗读完整说明。 + +## 事件 + +- `Action()` 返回操作 ID 与分支名。 +- `Changed()`、`Submitted()` 同 CommitList。 + +## 键盘操作 + +- ↑/↓、Home/End 移动选择;行内操作按钮用 Tab 到达,Enter 或 Space 执行。 + +## 限制 + +- 操作由调用方执行;组件不确认危险操作,需要时在回调里使用 Popconfirm 等组件。 diff --git a/docs/components/311-tag-list.md b/docs/components/311-tag-list.md new file mode 100644 index 0000000..13d9b89 --- /dev/null +++ b/docs/components/311-tag-list.md @@ -0,0 +1,59 @@ +# 311 TagList 标签列表 + +## 用途 + +标签列表:名称、注释与目标提交,每行可跳转到提交。 + +## 最小示例 + +```go +var state mujica.ListState[string] +tags := []mujica.GitTag{{Name: "v1.1.0", Target: "a1b2c3d4", Annotation: "Release"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.TagList(c, &state, tags, mujica.TagListOptions{}) + r.Element.Height(200) + if _, hash, ok := r.Action(); ok { + _ = hash // show the tagged commit + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func TagList(c *ui.Context, s *ListState[string], tags []GitTag, opts TagListOptions) GitListResult` + +## 参数 + +`GitTag` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Name | string | 必填 | 标签名,唯一。 | +| Target | string | 必填 | 目标提交哈希。 | +| Annotation | string | "" | 注释;轻量标签留空。 | + +`TagListOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Status | DataStatus | DataReady | 加载、追加、失败状态。 | +| Error | string | "" | 失败说明。 | + +Name 或 Target 为空时 panic。给返回的 `Element` 一个高度。 + +## 状态 + +- 注释为 TextMuted 单行,超长省略。 + +## 事件 + +- `Action()` 返回 `"jump"` 与目标哈希。 +- `Changed()`、`Submitted()` 同 CommitList。 + +## 键盘操作 + +- ↑/↓、Home/End 移动选择;“跳转到提交”按钮用 Tab 到达。 + +## 限制 + +- 不读取标签:数据由调用方提供。 diff --git a/docs/components/312-stash-list.md b/docs/components/312-stash-list.md new file mode 100644 index 0000000..f7901bd --- /dev/null +++ b/docs/components/312-stash-list.md @@ -0,0 +1,58 @@ +# 312 StashList 贮藏列表 + +## 用途 + +贮藏列表,每行提供应用、弹出与删除。 + +## 最小示例 + +```go +var state mujica.ListState[string] +stashes := []mujica.Stash{{Ref: "stash@{0}", Message: "WIP on main", Branch: "main"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.StashList(c, &state, stashes, mujica.StashListOptions{}) + r.Element.Height(200) + if action, ref, ok := r.Action(); ok { + _, _ = action, ref // run git stash apply, pop or drop + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func StashList(c *ui.Context, s *ListState[string], stashes []Stash, opts StashListOptions) GitListResult` + +## 参数 + +`Stash` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Ref | string | 必填 | 如 stash@{0};为空时 panic。 | +| Message | string | "" | 贮藏说明。 | +| Branch | string | "" | 创建时所在分支。 | + +`StashListOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Status | DataStatus | DataReady | 加载、追加、失败状态。 | +| Error | string | "" | 失败说明。 | + +给返回的 `Element` 一个高度。 + +## 状态 + +- Ref 为等宽 AccentText;三个操作为带名称与提示的图标按钮。 + +## 事件 + +- `Action()` 返回 `"apply"`、`"pop"` 或 `"drop"` 与 Ref。 + +## 键盘操作 + +- ↑/↓ 移动选择;操作按钮用 Tab 到达,Enter 或 Space 执行。 + +## 限制 + +- 删除不带确认;需要时由调用方在回调里确认。 diff --git a/docs/components/313-blame-view.md b/docs/components/313-blame-view.md new file mode 100644 index 0000000..ba5eada --- /dev/null +++ b/docs/components/313-blame-view.md @@ -0,0 +1,62 @@ +# 313 BlameView 逐行追溯 + +## 用途 + +代码逐行显示最后修改的作者与提交;同一提交的连续行合并显示,悬停显示提交详情。只构建可见行。 + +## 最小示例 + +```go +var state mujica.BlameViewState +lines := []mujica.BlameLine{ + {Hash: "a1b2c3d4", Author: "Sakiko", When: time.Now(), Summary: "Add main", Text: "package main"}, + {Hash: "a1b2c3d4", Author: "Sakiko", When: time.Now(), Summary: "Add main", Text: "func main() {}"}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BlameView(c, &state, lines, mujica.BlameViewOptions{Language: "go"}).Height(240) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func BlameView(c *ui.Context, s *BlameViewState, lines []BlameLine, opts BlameViewOptions) *ui.Element` + +## 参数 + +`BlameLine` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Hash | string | 必填 | 提交哈希;为空时 panic。 | +| Author | string | "" | 作者。 | +| When | time.Time | 零值 | 提交时间。 | +| Summary | string | "" | 提交标题,悬停时显示。 | +| Text | string | "" | 该行代码。 | + +`BlameViewOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Language | string | "" | 语法高亮语言,如 go;空为纯文本。 | +| TimeFormat | string | "2006-01-02" | 日期格式。 | + +`BlameViewState` 由调用方持有;块注释状态在数据或语言变化时计算一次。给返回元素一个高度。 + +## 状态 + +- 每段同提交行只在首行显示短哈希、作者与日期,段之间有细分隔线。 +- 左栏悬停为 SurfaceHover,600 ms 后显示提示:完整哈希、作者、日期与标题。 +- 代码使用统一的语法颜色,注释为斜体。 + +## 事件 + +- 无。 + +## 键盘操作 + +- 列表可获得焦点并滚动;输入行首文字跳转到该行。 + +## 限制 + +- 长行不换行,超出部分裁剪。 +- 悬停详情使用 MyGo 提示,只能用指针触发;每行左栏的名称同样朗读作者与提交。 diff --git a/docs/components/314-file-history.md b/docs/components/314-file-history.md new file mode 100644 index 0000000..5aab49a --- /dev/null +++ b/docs/components/314-file-history.md @@ -0,0 +1,53 @@ +# 314 FileHistory 文件历史 + +## 用途 + +单个文件的提交历史,每条提交提供“查看差异”入口。 + +## 最小示例 + +```go +var state mujica.ListState[string] +commits := []mujica.Commit{{Hash: "a1b2c3d4", Author: "Sakiko", When: time.Now(), Subject: "Edit main.go"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.FileHistory(c, &state, "main.go", commits, mujica.FileHistoryOptions{}) + r.Element.Height(240) + if _, hash, ok := r.Action(); ok { + _ = hash // open the diff of main.go at hash + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func FileHistory(c *ui.Context, s *ListState[string], path string, commits []Commit, opts FileHistoryOptions) GitListResult` + +## 参数 + +`FileHistoryOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| TimeFormat | string | "2006-01-02 15:04" | 时间格式。 | +| Status | DataStatus | DataReady | 加载、追加、失败状态。 | +| Error | string | "" | 失败说明。 | + +path 为空时 panic。给返回的 `Element` 一个高度,列表填满其余空间。 + +## 状态 + +- 标题行显示历史图标、等宽路径与“历史”。 +- 空历史显示“此文件没有历史”。 + +## 事件 + +- `Action()` 返回 `"diff"` 与提交哈希。 +- `Changed()`、`Submitted()` 同 CommitList。 + +## 键盘操作 + +- ↑/↓、Home/End 移动选择;“查看差异”按钮用 Tab 到达。 + +## 限制 + +- 不跟踪重命名:提交列表由调用方提供。 diff --git a/docs/components/315-pull-request-card.md b/docs/components/315-pull-request-card.md new file mode 100644 index 0000000..a5ad61a --- /dev/null +++ b/docs/components/315-pull-request-card.md @@ -0,0 +1,62 @@ +# 315 PullRequestCard 拉取请求卡片 + +## 用途 + +概览一个拉取请求:标题、作者、状态、检查、评审人与差异统计。 + +## 最小示例 + +```go +pr := mujica.PullRequest{Number: 42, Title: "Add git components", Author: "Sakiko", Head: "feature", Base: "main", + ChecksPassed: 3, Reviewers: []mujica.Reviewer{{Name: "Uika", State: mujica.ReviewApproved}}, Added: 120, Deleted: 8, Files: 6} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.PullRequestCard(c, pr, mujica.PullRequestCardOptions{}).Changed() { + // open the pull request + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func PullRequestCard(c *ui.Context, pr PullRequest, opts PullRequestCardOptions) ChoiceResult` + +## 参数 + +`PullRequest` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Number | int | 必填 | 编号,须为正。 | +| Title | string | 必填 | 标题。 | +| Author | string | "" | 作者。 | +| State | PullRequestState | PullRequestOpen | Open、Draft、Merged、Closed;未知值 panic。 | +| Head, Base | string | "" | 源分支与目标分支,都有值时显示。 | +| ChecksPassed, ChecksFailed, ChecksPending | int | 0 | 检查计数;为负 panic。 | +| Reviewers | []Reviewer | nil | 评审人与状态(Pending、Approved、ChangesRequested)。 | +| Added, Deleted, Files | int | 0 | 差异统计。 | + +`PullRequestCardOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Disabled | bool | false | 禁用打开。 | + +返回 `ChoiceResult`。 + +## 状态 + +- 状态徽章同时使用图标、文字与描边颜色。 +- 检查以图标加数字显示,朗读完整说明;为 0 的类别不显示。 +- 评审人以头像加角标图标表示状态,名称与状态写入提示和朗读文本。 + +## 事件 + +- `Changed()`:点击标题或在标题上按 Enter,表示打开。 + +## 键盘操作 + +- Tab 到标题链接,Enter 或 Space 打开。 + +## 限制 + +- 数据由调用方获取;组件不刷新检查状态。 diff --git a/docs/components/316-review-comment.md b/docs/components/316-review-comment.md new file mode 100644 index 0000000..6ed4b9a --- /dev/null +++ b/docs/components/316-review-comment.md @@ -0,0 +1,66 @@ +# 316 ReviewComment 评审评论 + +## 用途 + +行级评审讨论:显示文件与行号、评论列表,支持回复、解决与重新打开。 + +## 最小示例 + +```go +thread := mujica.ReviewThread{File: "main.go", Line: 12, Messages: []mujica.ReviewMessage{ + {Author: "Uika", When: time.Now(), Body: "Can this return early?"}, +}} +draft := "" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ReviewComment(c, thread, &draft, mujica.ReviewCommentOptions{}) + if text, ok := r.Replied(); ok { + thread.Messages = append(thread.Messages, mujica.ReviewMessage{Author: "Sakiko", When: time.Now(), Body: text}) + } + if r.Resolved() || r.Reopened() { + thread.Resolved = !thread.Resolved + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func ReviewComment(c *ui.Context, thread ReviewThread, draft *string, opts ReviewCommentOptions) ReviewCommentResult` + +## 参数 + +`ReviewThread` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| File | string | 必填 | 文件路径。 | +| Line | int | 必填 | 行号,须为正。 | +| Resolved | bool | false | 已解决:隐藏回复框,显示“重新打开”。 | +| Messages | []ReviewMessage | 必填 | 至少一条评论(作者、时间、正文)。 | + +`ReviewCommentOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| TimeFormat | string | "2006-01-02 15:04" | 时间格式。 | +| Disabled | bool | false | 禁用回复、解决与重新打开。 | + +`draft` 保存回复草稿,发送后清空。 + +## 状态 + +- 已解决:标题栏显示 Success 色图标与“已解决”。 +- 回复按钮在草稿为空时禁用。 + +## 事件 + +- `Replied()`:发送的回复文本(去除首尾空白)。 +- `Resolved()`、`Reopened()`:对应按钮。 + +## 键盘操作 + +- Tab 经过回复框与按钮;回复框内 Cmd+Enter(非 macOS 为 Ctrl+Enter)发送。 + +## 限制 + +- 评论正文为纯文本,不渲染 Markdown。 +- 线程状态由调用方更新。 diff --git a/docs/components/317-diff-stat.md b/docs/components/317-diff-stat.md new file mode 100644 index 0000000..fc4143b --- /dev/null +++ b/docs/components/317-diff-stat.md @@ -0,0 +1,45 @@ +# 317 DiffStat 差异统计 + +## 用途 + +显示 +新增 −删除 行数,以及按比例填充的方块条。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.DiffStat(c, 120, 8, mujica.DiffStatOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func DiffStat(c *ui.Context, added, deleted int, opts DiffStatOptions) *ui.Element` + +## 参数 + +`DiffStatOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Blocks | int | 0(即 5) | 比例条方块数;为负 panic。 | + +added、deleted 为负时 panic。 + +## 状态 + +- 数字带 + 与 − 符号,不只靠颜色;非零一侧至少占一格。 +- 无变化时方块为 Border 色。 +- 朗读为“新增 n 行,删除 m 行”。 + +## 事件 + +- 无。 + +## 键盘操作 + +- 无:纯展示,不获取焦点。 + +## 限制 + +- 无。 diff --git a/docs/components/318-git-status-badge.md b/docs/components/318-git-status-badge.md new file mode 100644 index 0000000..c4f7ac1 --- /dev/null +++ b/docs/components/318-git-status-badge.md @@ -0,0 +1,44 @@ +# 318 GitStatusBadge Git 状态标记 + +## 用途 + +以字母 M、A、D、U、R、C 加描边与颜色标记文件状态。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.GitStatusBadge(c, mujica.GitModified, mujica.GitStatusBadgeOptions{ShowLabel: true}) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func GitStatusBadge(c *ui.Context, status GitStatus, opts GitStatusBadgeOptions) *ui.Element` + +## 参数 + +`GitStatusBadgeOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| ShowLabel | bool | false | 在字母旁写出状态名称;否则作为提示。 | + +`GitStatus`:GitModified、GitAdded、GitDeleted、GitUntracked、GitRenamed、GitCopied;`Letter()` 返回字母。未知值 panic。 + +## 状态 + +- 字母为等宽粗体,颜色依状态:修改 Warning、添加 Success、删除 Danger、未跟踪与重命名 Info、复制 AccentText。 +- 名称写入朗读文本与提示,不只靠颜色。 + +## 事件 + +- 无。 + +## 键盘操作 + +- 无:纯展示。 + +## 限制 + +- 无。 diff --git a/docs/components/319-command-block.md b/docs/components/319-command-block.md new file mode 100644 index 0000000..ee28831 --- /dev/null +++ b/docs/components/319-command-block.md @@ -0,0 +1,62 @@ +# 319 CommandBlock 命令块 + +## 用途 + +把一次命令执行显示为一块:提示符与高亮的命令、退出码、耗时与可折叠的 ANSI 输出,可复制命令或输出。 + +## 最小示例 + +```go +open := true +run := mujica.CommandRun{Command: "go test ./...", Output: "\x1b[32mok\x1b[0m example 0.4s", Duration: 400 * time.Millisecond} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CommandBlock(c, run, &open, mujica.CommandBlockOptions{}) + if what, ok := r.Copied(); ok { + _ = what // "command" or "output" is on the clipboard + } +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func CommandBlock(c *ui.Context, run CommandRun, open *bool, opts CommandBlockOptions) CommandBlockResult` + +## 参数 + +`CommandRun` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Command | string | 必填 | 命令;为空时 panic。 | +| Output | string | "" | 输出,可含 ANSI 转义。 | +| ExitCode | int | 0 | 退出码。 | +| Duration | time.Duration | 0 | 耗时;为负 panic。 | +| Running | bool | false | 运行中:显示加载标记,不显示退出码与耗时。 | + +`CommandBlockOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Prompt | string | "$" | 命令前的提示符。 | +| MaxOutputHeight | float32 | 0(即 320) | 输出区最大高度,超出滚动;为负 panic。 | + +`open` 控制输出是否展开。 + +## 状态 + +- 成功:Success 色对勾与“退出码 0”;失败:Danger 色叉号与退出码。 +- 展开箭头 120 ms 转动,减少动画时直接切换。 +- 输出区为 Background 底色,等宽字体,横纵滚动。 + +## 事件 + +- `Toggled()`:展开或折叠。 +- `Copied()`:`"command"` 或 `"output"`;复制的输出已去除 ANSI 转义。 + +## 键盘操作 + +- Tab 到标题行,Enter 或 Space 展开或折叠;复制按钮用 Tab 到达。 + +## 限制 + +- 不运行命令:输出与状态由调用方提供。 diff --git a/docs/components/320-ansi-text.md b/docs/components/320-ansi-text.md new file mode 100644 index 0000000..a5255f7 --- /dev/null +++ b/docs/components/320-ansi-text.md @@ -0,0 +1,45 @@ +# 320 AnsiText ANSI 文本 + +## 用途 + +渲染终端输出:16 色、256 色、真彩,以及粗体、斜体、下划线、删除线、暗淡与反显。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AnsiText(c, "\x1b[1;32mPASS\x1b[0m 12 tests\n\x1b[31mFAIL\x1b[0m 1 test", mujica.AnsiTextOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +签名:`func AnsiText(c *ui.Context, text string, opts AnsiTextOptions) *ui.Element` + +## 参数 + +`AnsiTextOptions` + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| Wrap | bool | false | 按宽度换行;否则每行保持完整。 | + +样式跨行延续。 + +## 状态 + +- 16 色映射为在两种主题 Surface 上都达到 4.5:1 的颜色;256 色与真彩按原值显示。 +- 默认前景为 Text;反显以 Surface 为前景。 + +## 事件 + +- 无。 + +## 键盘操作 + +- 无:纯展示。 + +## 限制 + +- 只解释 SGR(m 结尾)序列;光标移动、清屏等其他 CSI 序列原样保留为文字,并以 slog.Debug 记录。 +- 256 色与真彩不做对比度调整。 diff --git a/example_git_test.go b/example_git_test.go new file mode 100644 index 0000000..51e60e0 --- /dev/null +++ b/example_git_test.go @@ -0,0 +1,263 @@ +package mujica_test + +import ( + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func ExampleDiffViewer() { + var state mujica.DiffViewerState + from := "func main() {\n\tprintln(\"hi\")\n}\n" + to := "func main() {\n\tprintln(\"hello\")\n}\n" + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.DiffViewer(c, &state, from, to, mujica.DiffViewerOptions{Language: "go", SideBySide: true}).Height(240) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleInlineDiff() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.InlineDiff(c, "The court meets at noon", "The court meets at dusk", mujica.InlineDiffOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleThreeWayMerge() { + var state mujica.ThreeWayMergeState + base, local, remote := "a\nb\nc", "a\nB1\nc", "a\nB2\nc" + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ThreeWayMerge(c, &state, base, local, remote, mujica.ThreeWayMergeOptions{}) + r.Element.Height(280) + if done, total := state.Resolved(); r.Changed() && done == total { + _ = state.Result() // write the merged file + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleConflictResolver() { + var state mujica.ConflictResolverState + text := "a\n<<<<<<< HEAD\nmine\n=======\ntheirs\n>>>>>>> feature\nb" + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ConflictResolver(c, &state, text, mujica.ConflictResolverOptions{}).Changed() { + _ = state.Result() // save the file once every block is resolved + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleChangesList() { + var state mujica.ChangesListState + files := []mujica.ChangedFile{ + {Path: "main.go", Status: mujica.GitModified, Staged: true}, + {Path: "notes.txt", Status: mujica.GitUntracked}, + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ChangesList(c, &state, files, mujica.ChangesListOptions{}) + r.Element.Height(240) + if action, path, ok := r.Action(); ok { + _, _ = action, path // run git add or git restore --staged + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCommitInput() { + msg := mujica.CommitMessage{} + busy := false + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CommitInput(c, &msg, mujica.CommitInputOptions{Busy: busy}) + if r.Committed() || r.Amended() { + busy = true // run git commit, then clear busy + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCommitGraph() { + var state mujica.CommitGraphState + commits := []mujica.Commit{ + {Hash: "c3", Parents: []string{"c2", "b1"}, Subject: "Merge branch", Refs: []string{"main"}}, + {Hash: "b1", Parents: []string{"c1"}, Subject: "Feature"}, + {Hash: "c2", Parents: []string{"c1"}, Subject: "Fix"}, + {Hash: "c1", Subject: "Initial commit"}, + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CommitGraph(c, &state, commits, mujica.CommitGraphOptions{}).Element.Height(240) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCommitList() { + var state mujica.ListState[string] + commits := []mujica.Commit{{Hash: "a1b2c3d4", Author: "Sakiko", When: time.Now(), Subject: "Add the commit list"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CommitList(c, &state, commits, mujica.CommitListOptions{}) + r.Element.Height(240) + if hash, ok := state.Selected(); ok && r.Submitted() { + _ = hash // show the commit + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleBranchSelector() { + branch := "main" + branches := []mujica.Branch{{Name: "main", Current: true}, {Name: "origin/main", Remote: true}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.BranchSelector(c, &branch, branches, mujica.BranchSelectorOptions{AllowCreate: true}) + if name, ok := r.Created(); ok { + _ = name // run git switch -c name + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleBranchList() { + var state mujica.ListState[string] + branches := []mujica.Branch{{Name: "main", Current: true, Upstream: "origin/main", Ahead: 2}} + actions := []mujica.GitAction{{ID: "delete", Label: "Delete", Icon: "trash-2"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.BranchList(c, &state, branches, mujica.BranchListOptions{Actions: actions}) + r.Element.Height(200) + if action, name, ok := r.Action(); ok { + _, _ = action, name // run the action on the branch + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleTagList() { + var state mujica.ListState[string] + tags := []mujica.GitTag{{Name: "v1.1.0", Target: "a1b2c3d4", Annotation: "Release"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.TagList(c, &state, tags, mujica.TagListOptions{}) + r.Element.Height(200) + if _, hash, ok := r.Action(); ok { + _ = hash // show the tagged commit + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleStashList() { + var state mujica.ListState[string] + stashes := []mujica.Stash{{Ref: "stash@{0}", Message: "WIP on main", Branch: "main"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.StashList(c, &state, stashes, mujica.StashListOptions{}) + r.Element.Height(200) + if action, ref, ok := r.Action(); ok { + _, _ = action, ref // run git stash apply, pop or drop + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleBlameView() { + var state mujica.BlameViewState + lines := []mujica.BlameLine{ + {Hash: "a1b2c3d4", Author: "Sakiko", When: time.Now(), Summary: "Add main", Text: "package main"}, + {Hash: "a1b2c3d4", Author: "Sakiko", When: time.Now(), Summary: "Add main", Text: "func main() {}"}, + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BlameView(c, &state, lines, mujica.BlameViewOptions{Language: "go"}).Height(240) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleFileHistory() { + var state mujica.ListState[string] + commits := []mujica.Commit{{Hash: "a1b2c3d4", Author: "Sakiko", When: time.Now(), Subject: "Edit main.go"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.FileHistory(c, &state, "main.go", commits, mujica.FileHistoryOptions{}) + r.Element.Height(240) + if _, hash, ok := r.Action(); ok { + _ = hash // open the diff of main.go at hash + } + } + ui.Render(view, 400, 300, 1) +} + +func ExamplePullRequestCard() { + pr := mujica.PullRequest{Number: 42, Title: "Add git components", Author: "Sakiko", Head: "feature", Base: "main", + ChecksPassed: 3, Reviewers: []mujica.Reviewer{{Name: "Uika", State: mujica.ReviewApproved}}, Added: 120, Deleted: 8, Files: 6} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.PullRequestCard(c, pr, mujica.PullRequestCardOptions{}).Changed() { + // open the pull request + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleReviewComment() { + thread := mujica.ReviewThread{File: "main.go", Line: 12, Messages: []mujica.ReviewMessage{ + {Author: "Uika", When: time.Now(), Body: "Can this return early?"}, + }} + draft := "" + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ReviewComment(c, thread, &draft, mujica.ReviewCommentOptions{}) + if text, ok := r.Replied(); ok { + thread.Messages = append(thread.Messages, mujica.ReviewMessage{Author: "Sakiko", When: time.Now(), Body: text}) + } + if r.Resolved() || r.Reopened() { + thread.Resolved = !thread.Resolved + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleDiffStat() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.DiffStat(c, 120, 8, mujica.DiffStatOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleGitStatusBadge() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.GitStatusBadge(c, mujica.GitModified, mujica.GitStatusBadgeOptions{ShowLabel: true}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCommandBlock() { + open := true + run := mujica.CommandRun{Command: "go test ./...", Output: "\x1b[32mok\x1b[0m example 0.4s", Duration: 400 * time.Millisecond} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CommandBlock(c, run, &open, mujica.CommandBlockOptions{}) + if what, ok := r.Copied(); ok { + _ = what // "command" or "output" is on the clipboard + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleAnsiText() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AnsiText(c, "\x1b[1;32mPASS\x1b[0m 12 tests\n\x1b[31mFAIL\x1b[0m 1 test", mujica.AnsiTextOptions{}) + } + ui.Render(view, 400, 300, 1) +} diff --git a/examples/gallery/pages_git.go b/examples/gallery/pages_git.go index 103b0e7..4ac34b8 100644 --- a/examples/gallery/pages_git.go +++ b/examples/gallery/pages_git.go @@ -1,3 +1,298 @@ package main -var gitPages = []page{} +var gitPages = []page{ + { + ID: "301", Name: "DiffViewer", ZhName: "差异查看器 比较 diff", Category: "Git", + Demo: gitDiffViewerDemo, + Code: `var state mujica.DiffViewerState +from := "func main() {\n\tprintln(\"hi\")\n}\n" +to := "func main() {\n\tprintln(\"hello\")\n}\n" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.DiffViewer(c, &state, from, to, mujica.DiffViewerOptions{Language: "go", SideBySide: true}).Height(240) +} +ui.Render(view, 400, 300, 1)`, + Keys: "Tab focuses the list; arrows and Page Up/Down scroll. Fold buttons take Tab; Enter or Space shows the hidden lines.", + }, + { + ID: "302", Name: "InlineDiff", ZhName: "行内差异 词级差异", Category: "Git", + Demo: gitInlineDiffDemo, + Code: `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.InlineDiff(c, "The court meets at noon", "The court meets at dusk", mujica.InlineDiffOptions{}) +} +ui.Render(view, 400, 300, 1)`, + Keys: "Not focusable; each line is read with its full text.", + }, + { + ID: "303", Name: "ThreeWayMerge", ZhName: "三方合并 合并冲突", Category: "Git", + Demo: gitThreeWayMergeDemo, + Code: `var state mujica.ThreeWayMergeState +base, local, remote := "a\nb\nc", "a\nB1\nc", "a\nB2\nc" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ThreeWayMerge(c, &state, base, local, remote, mujica.ThreeWayMergeOptions{}) + r.Element.Height(280) + if done, total := state.Resolved(); r.Changed() && done == total { + _ = state.Result() // write the merged file + } +} +ui.Render(view, 400, 300, 1)`, + Keys: "Tab reaches the take buttons of each conflict; Enter or Space chooses. The list scrolls with the arrows.", + }, + { + ID: "304", Name: "ConflictResolver", ZhName: "冲突解决 冲突标记", Category: "Git", + Demo: gitConflictResolverDemo, + Code: `var state mujica.ConflictResolverState +text := "a\n<<<<<<< HEAD\nmine\n=======\ntheirs\n>>>>>>> feature\nb" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ConflictResolver(c, &state, text, mujica.ConflictResolverOptions{}).Changed() { + _ = state.Result() // save the file once every block is resolved + } +} +ui.Render(view, 400, 300, 1)`, + Keys: "Tab moves through each block's buttons; Enter or Space accepts a side; Undo clears the choice.", + }, + { + ID: "305", Name: "ChangesList", ZhName: "更改列表 暂存 未暂存", Category: "Git", + Demo: gitChangesListDemo, + Code: `var state mujica.ChangesListState +files := []mujica.ChangedFile{ + {Path: "main.go", Status: mujica.GitModified, Staged: true}, + {Path: "notes.txt", Status: mujica.GitUntracked}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ChangesList(c, &state, files, mujica.ChangesListOptions{}) + r.Element.Height(240) + if action, path, ok := r.Action(); ok { + _, _ = action, path // run git add or git restore --staged + } +} +ui.Render(view, 400, 300, 1)`, + Keys: "Up/Down choose a file, skipping group titles; typing jumps by name; stage buttons take Tab, Enter or Space.", + }, + { + ID: "306", Name: "CommitInput", ZhName: "提交输入 提交信息", Category: "Git", + Demo: gitCommitInputDemo, + Code: `msg := mujica.CommitMessage{} +busy := false +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CommitInput(c, &msg, mujica.CommitInputOptions{Busy: busy}) + if r.Committed() || r.Amended() { + busy = true // run git commit, then clear busy + } +} +ui.Render(view, 400, 300, 1)`, + Keys: "Enter in the summary or Cmd/Ctrl+Enter in the description commits; Tab reaches Amend and Commit.", + }, + { + ID: "307", Name: "CommitGraph", ZhName: "提交图谱 泳道 分支图", Category: "Git", + Demo: gitCommitGraphDemo, + Code: `var state mujica.CommitGraphState +commits := []mujica.Commit{ + {Hash: "c3", Parents: []string{"c2", "b1"}, Subject: "Merge branch", Refs: []string{"main"}}, + {Hash: "b1", Parents: []string{"c1"}, Subject: "Feature"}, + {Hash: "c2", Parents: []string{"c1"}, Subject: "Fix"}, + {Hash: "c1", Subject: "Initial commit"}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CommitGraph(c, &state, commits, mujica.CommitGraphOptions{}).Element.Height(240) +} +ui.Render(view, 400, 300, 1)`, + Keys: "Up/Down/Home/End choose a commit; typing jumps by subject; Enter opens it.", + }, + { + ID: "308", Name: "CommitList", ZhName: "提交列表 提交历史", Category: "Git", + Demo: gitCommitListDemo, + Code: `var state mujica.ListState[string] +commits := []mujica.Commit{{Hash: "a1b2c3d4", Author: "Sakiko", When: time.Now(), Subject: "Add the commit list"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CommitList(c, &state, commits, mujica.CommitListOptions{}) + r.Element.Height(240) + if hash, ok := state.Selected(); ok && r.Submitted() { + _ = hash // show the commit + } +} +ui.Render(view, 400, 300, 1)`, + Keys: "Up/Down/Home/End choose a commit; typing jumps by subject; Enter opens it.", + }, + { + ID: "309", Name: "BranchSelector", ZhName: "分支选择器 切换分支", Category: "Git", + Demo: gitBranchSelectorDemo, + Code: `branch := "main" +branches := []mujica.Branch{{Name: "main", Current: true}, {Name: "origin/main", Remote: true}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.BranchSelector(c, &branch, branches, mujica.BranchSelectorOptions{AllowCreate: true}) + if name, ok := r.Created(); ok { + _ = name // run git switch -c name + } +} +ui.Render(view, 400, 300, 1)`, + Keys: "Enter or Space opens; type to filter; Up/Down move; Enter chooses or creates; Escape closes.", + }, + { + ID: "310", Name: "BranchList", ZhName: "分支列表 上游 领先落后", Category: "Git", + Demo: gitBranchListDemo, + Code: `var state mujica.ListState[string] +branches := []mujica.Branch{{Name: "main", Current: true, Upstream: "origin/main", Ahead: 2}} +actions := []mujica.GitAction{{ID: "delete", Label: "Delete", Icon: "trash-2"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.BranchList(c, &state, branches, mujica.BranchListOptions{Actions: actions}) + r.Element.Height(200) + if action, name, ok := r.Action(); ok { + _, _ = action, name // run the action on the branch + } +} +ui.Render(view, 400, 300, 1)`, + Keys: "Up/Down choose a branch; row actions take Tab, Enter or Space.", + }, + { + ID: "311", Name: "TagList", ZhName: "标签列表 tag", Category: "Git", + Demo: gitTagListDemo, + Code: `var state mujica.ListState[string] +tags := []mujica.GitTag{{Name: "v1.1.0", Target: "a1b2c3d4", Annotation: "Release"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.TagList(c, &state, tags, mujica.TagListOptions{}) + r.Element.Height(200) + if _, hash, ok := r.Action(); ok { + _ = hash // show the tagged commit + } +} +ui.Render(view, 400, 300, 1)`, + Keys: "Up/Down choose a tag; the jump button takes Tab, Enter or Space.", + }, + { + ID: "312", Name: "StashList", ZhName: "贮藏列表 stash", Category: "Git", + Demo: gitStashListDemo, + Code: `var state mujica.ListState[string] +stashes := []mujica.Stash{{Ref: "stash@{0}", Message: "WIP on main", Branch: "main"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.StashList(c, &state, stashes, mujica.StashListOptions{}) + r.Element.Height(200) + if action, ref, ok := r.Action(); ok { + _, _ = action, ref // run git stash apply, pop or drop + } +} +ui.Render(view, 400, 300, 1)`, + Keys: "Up/Down choose a stash; Apply, Pop and Drop take Tab, Enter or Space.", + }, + { + ID: "313", Name: "BlameView", ZhName: "逐行追溯 blame 作者", Category: "Git", + Demo: gitBlameViewDemo, + Code: `var state mujica.BlameViewState +lines := []mujica.BlameLine{ + {Hash: "a1b2c3d4", Author: "Sakiko", When: time.Now(), Summary: "Add main", Text: "package main"}, + {Hash: "a1b2c3d4", Author: "Sakiko", When: time.Now(), Summary: "Add main", Text: "func main() {}"}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BlameView(c, &state, lines, mujica.BlameViewOptions{Language: "go"}).Height(240) +} +ui.Render(view, 400, 300, 1)`, + Keys: "Tab focuses the code; arrows scroll; typing jumps to a line starting with the text. Hover the left column for details.", + }, + { + ID: "314", Name: "FileHistory", ZhName: "文件历史 单文件提交", Category: "Git", + Demo: gitFileHistoryDemo, + Code: `var state mujica.ListState[string] +commits := []mujica.Commit{{Hash: "a1b2c3d4", Author: "Sakiko", When: time.Now(), Subject: "Edit main.go"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.FileHistory(c, &state, "main.go", commits, mujica.FileHistoryOptions{}) + r.Element.Height(240) + if _, hash, ok := r.Action(); ok { + _ = hash // open the diff of main.go at hash + } +} +ui.Render(view, 400, 300, 1)`, + Keys: "Up/Down choose a commit; View changes takes Tab, Enter or Space.", + }, + { + ID: "315", Name: "PullRequestCard", ZhName: "拉取请求卡片 合并请求 PR", Category: "Git", + Demo: gitPullRequestCardDemo, + Code: `pr := mujica.PullRequest{Number: 42, Title: "Add git components", Author: "Sakiko", Head: "feature", Base: "main", + ChecksPassed: 3, Reviewers: []mujica.Reviewer{{Name: "Uika", State: mujica.ReviewApproved}}, Added: 120, Deleted: 8, Files: 6} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.PullRequestCard(c, pr, mujica.PullRequestCardOptions{}).Changed() { + // open the pull request + } +} +ui.Render(view, 400, 300, 1)`, + Keys: "Tab reaches the title link; Enter or Space opens the pull request.", + }, + { + ID: "316", Name: "ReviewComment", ZhName: "评审评论 代码评审", Category: "Git", + Demo: gitReviewCommentDemo, + Code: `thread := mujica.ReviewThread{File: "main.go", Line: 12, Messages: []mujica.ReviewMessage{ + {Author: "Uika", When: time.Now(), Body: "Can this return early?"}, +}} +draft := "" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ReviewComment(c, thread, &draft, mujica.ReviewCommentOptions{}) + if text, ok := r.Replied(); ok { + thread.Messages = append(thread.Messages, mujica.ReviewMessage{Author: "Sakiko", When: time.Now(), Body: text}) + } + if r.Resolved() || r.Reopened() { + thread.Resolved = !thread.Resolved + } +} +ui.Render(view, 400, 300, 1)`, + Keys: "Tab moves through the reply field and buttons; Cmd/Ctrl+Enter sends the reply.", + }, + { + ID: "317", Name: "DiffStat", ZhName: "差异统计 增删行数", Category: "Git", + Demo: gitDiffStatDemo, + Code: `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.DiffStat(c, 120, 8, mujica.DiffStatOptions{}) +} +ui.Render(view, 400, 300, 1)`, + Keys: "Not focusable; read as additions and deletions.", + }, + { + ID: "318", Name: "GitStatusBadge", ZhName: "Git 状态标记 文件状态", Category: "Git", + Demo: gitStatusBadgeDemo, + Code: `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.GitStatusBadge(c, mujica.GitModified, mujica.GitStatusBadgeOptions{ShowLabel: true}) +} +ui.Render(view, 400, 300, 1)`, + Keys: "Not focusable; each badge is read by its status name.", + }, + { + ID: "319", Name: "CommandBlock", ZhName: "命令块 终端输出 退出码", Category: "Git", + Demo: gitCommandBlockDemo, + Code: `open := true +run := mujica.CommandRun{Command: "go test ./...", Output: "\x1b[32mok\x1b[0m example 0.4s", Duration: 400 * time.Millisecond} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CommandBlock(c, run, &open, mujica.CommandBlockOptions{}) + if what, ok := r.Copied(); ok { + _ = what // "command" or "output" is on the clipboard + } +} +ui.Render(view, 400, 300, 1)`, + Keys: "Tab reaches the header; Enter or Space folds the output; the copy buttons take Tab.", + }, + { + ID: "320", Name: "AnsiText", ZhName: "ANSI 文本 终端颜色", Category: "Git", + Demo: gitAnsiTextDemo, + Code: `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AnsiText(c, "\x1b[1;32mPASS\x1b[0m 12 tests\n\x1b[31mFAIL\x1b[0m 1 test", mujica.AnsiTextOptions{}) +} +ui.Render(view, 400, 300, 1)`, + Keys: "Not focusable; shows the text with its styles.", + }, +} diff --git a/examples/gallery/pages_git_cards.go b/examples/gallery/pages_git_cards.go new file mode 100644 index 0000000..3f6dc03 --- /dev/null +++ b/examples/gallery/pages_git_cards.go @@ -0,0 +1,134 @@ +package main + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func gitPullRequestCardDemo(c *ui.Context, log func(string)) { + type state struct { + st int + failed, disabled bool + } + s := ui.Local(c.Root(), "315", func() state { return state{} }) + navigationDemo(c, func() { + mujica.SegmentedControl(c, &s.st, []mujica.Segment{{Label: "Open"}, {Label: "Draft"}, {Label: "Merged"}, {Label: "Closed"}}, mujica.SegmentedControlOptions{Label: "State"}) + navigationCheck(c, &s.failed, "Failing check", log) + navigationCheck(c, &s.disabled, "Disabled", log) + }, func() { + pr := mujica.PullRequest{Number: 318, Title: "Git components 301–320", Author: "Sakiko", State: mujica.PullRequestState(s.st), + Head: "feature/git", Base: "main", ChecksPassed: 12, ChecksPending: 1, + Reviewers: []mujica.Reviewer{{Name: "Uika", State: mujica.ReviewApproved}, {Name: "Mutsumi", State: mujica.ReviewChangesRequested}, {Name: "Umiri"}}, + Added: 2412, Deleted: 310, Files: 46} + if s.failed { + pr.ChecksFailed = 1 + } + if mujica.PullRequestCard(c, pr, mujica.PullRequestCardOptions{Disabled: s.disabled}).Changed() { + log(fmt.Sprintf("Open #%d", pr.Number)) + } + }) +} + +func gitReviewCommentDemo(c *ui.Context, log func(string)) { + type state struct { + thread mujica.ReviewThread + draft string + disabled bool + } + s := ui.Local(c.Root(), "316", func() state { + return state{thread: mujica.ReviewThread{File: "commit_graph.go", Line: 88, Messages: []mujica.ReviewMessage{ + {Author: "Uika", When: gitDemoTime, Body: "Should merge lanes reuse the parent's color?"}, + {Author: "Sakiko", When: gitDemoTime.Add(time.Hour), Body: "Yes, the first parent keeps it."}, + }}} + }) + navigationDemo(c, func() { + navigationCheck(c, &s.disabled, "Disabled", log) + }, func() { + r := mujica.ReviewComment(c, s.thread, &s.draft, mujica.ReviewCommentOptions{Disabled: s.disabled}) + if text, ok := r.Replied(); ok { + log("Reply: " + text) + s.thread.Messages = append(s.thread.Messages, mujica.ReviewMessage{Author: "You", When: c.Now(), Body: text}) + } + if r.Resolved() { + log("Resolved") + s.thread.Resolved = true + } + if r.Reopened() { + log("Reopened") + s.thread.Resolved = false + } + }) +} + +func gitDiffStatDemo(c *ui.Context, log func(string)) { + type state struct{ added, deleted, blocks float64 } + s := ui.Local(c.Root(), "317", func() state { return state{added: 120, deleted: 30, blocks: 5} }) + navigationDemo(c, func() { + navigationSlider(c, &s.added, "Added", 0, 500, log) + navigationSlider(c, &s.deleted, "Deleted", 0, 500, log) + navigationSlider(c, &s.blocks, "Blocks", 1, 10, log) + }, func() { + mujica.DiffStat(c, int(s.added), int(s.deleted), mujica.DiffStatOptions{Blocks: int(s.blocks)}) + }) +} + +func gitStatusBadgeDemo(c *ui.Context, log func(string)) { + type state struct{ labels bool } + s := ui.Local(c.Root(), "318", func() state { return state{} }) + navigationDemo(c, func() { + navigationCheck(c, &s.labels, "Show labels", log) + }, func() { + ui.Row(c).Gap(16).Wrap().Children(func() { + for st := mujica.GitModified; st <= mujica.GitCopied; st++ { + mujica.GitStatusBadge(c, st, mujica.GitStatusBadgeOptions{ShowLabel: s.labels}) + } + }) + }) +} + +func gitCommandBlockDemo(c *ui.Context, log func(string)) { + type state struct { + open, failed, running bool + } + s := ui.Local(c.Root(), "319", func() state { return state{open: true} }) + navigationDemo(c, func() { + navigationCheck(c, &s.failed, "Failed", log) + navigationCheck(c, &s.running, "Running", log) + }, func() { + run := mujica.CommandRun{Command: "go test -run Git ./...", Duration: 3214 * time.Millisecond, + Output: "\x1b[32mok\x1b[0m \tmujicaui\t3.214s\n\x1b[33mwarn\x1b[0m slow test: TestCommitGraphVirtualized"} + if s.failed { + run.ExitCode = 1 + run.Output = "\x1b[31m--- FAIL\x1b[0m: TestDiffViewer (0.02s)\n\x1b[1mFAIL\x1b[0m\tmujicaui\t0.401s" + } + run.Running = s.running + r := mujica.CommandBlock(c, run, &s.open, mujica.CommandBlockOptions{}) + if r.Toggled() { + log(fmt.Sprintf("Toggled: open=%v", s.open)) + } + if what, ok := r.Copied(); ok { + log("Copied " + what) + } + }) +} + +func gitAnsiTextDemo(c *ui.Context, log func(string)) { + type state struct{ wrap bool } + s := ui.Local(c.Root(), "320", func() state { return state{} }) + navigationDemo(c, func() { + navigationCheck(c, &s.wrap, "Wrap", log) + }, func() { + ui.Column(c).Padding(12).Background(mujica.Tokens(c).Surface).Radius(4).Children(func() { + mujica.AnsiText(c, "\x1b[1mBuilding\x1b[0m mujica \x1b[2m(v1.1)\x1b[0m\n"+ + "\x1b[32m✓\x1b[0m 300 passed \x1b[31m✗\x1b[0m 2 failed \x1b[33m!\x1b[0m 1 skipped\n"+ + "\x1b[30m0\x1b[31m1\x1b[32m2\x1b[33m3\x1b[34m4\x1b[35m5\x1b[36m6\x1b[37m7\x1b[90m8\x1b[91m9\x1b[92mA\x1b[93mB\x1b[94mC\x1b[95mD\x1b[96mE\x1b[97mF\x1b[0m\n"+ + "\x1b[38;5;208m256-color\x1b[0m \x1b[38;2;125;32;52mtrue color\x1b[0m \x1b[4munderline\x1b[0m \x1b[3mitalic\x1b[0m \x1b[9mstruck\x1b[0m \x1b[7m inverse \x1b[0m\n"+ + "A long line that only breaks when wrapping is on, so the terminal layout of columns stays intact as it was printed.\n"+ + "Unknown escapes stay as text: \x1b[2K(cleared line)", mujica.AnsiTextOptions{Wrap: s.wrap}) + }) + }) +} diff --git a/examples/gallery/pages_git_demos.go b/examples/gallery/pages_git_demos.go new file mode 100644 index 0000000..8ad4b9b --- /dev/null +++ b/examples/gallery/pages_git_demos.go @@ -0,0 +1,367 @@ +package main + +import ( + "fmt" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +var gitDemoTime = time.Date(2026, 10, 5, 9, 30, 0, 0, time.UTC) + +const gitDemoOld = "package court\n\nimport \"fmt\"\n\n// Greet welcomes a guest.\nfunc Greet(name string) {\n\tfmt.Println(\"Welcome,\", name)\n}\n\nfunc Leave() {}\n\nfunc Dance() {}\n\nfunc Bow() {}\n" +const gitDemoNew = "package court\n\nimport \"fmt\"\n\n// Greet welcomes a guest by title.\nfunc Greet(title, name string) {\n\tfmt.Println(\"Welcome,\", title, name)\n}\n\nfunc Leave() {}\n\nfunc Dance() {}\n\nfunc Bow() {}\n\nfunc Curtsy() {}\n" + +func gitDemoCommits(n int) []mujica.Commit { + out := make([]mujica.Commit, n) + authors := []string{"Sakiko", "Mutsumi", "Uika", "Umiri", "Nyamu"} + for i := range out { + out[i] = mujica.Commit{Hash: fmt.Sprintf("%016x%024x", uint64(n-i)*0x9E3779B97F4A7C15, n-i), Author: authors[i%5], + When: gitDemoTime.Add(-time.Duration(i) * 37 * time.Minute), Subject: fmt.Sprintf("Chapter %d of the chronicle", n-i)} + if i+1 < n { + out[i].Parents = []string{fmt.Sprintf("%016x%024x", uint64(n-i-1)*0x9E3779B97F4A7C15, n-i-1)} + } + } + if n > 0 { + out[0].Refs = []string{"main", "origin/main"} + } + return out +} + +func gitDemoGraph() []mujica.Commit { + cs := []mujica.Commit{ + {Hash: "e7", Parents: []string{"e5", "f3"}, Subject: "Merge branch 'feature/lanes'", Refs: []string{"main"}}, + {Hash: "f3", Parents: []string{"f2"}, Subject: "Color lanes by branch"}, + {Hash: "e5", Parents: []string{"e4", "h1"}, Subject: "Merge hotfix"}, + {Hash: "h1", Parents: []string{"e3"}, Subject: "Fix the overture timing", Refs: []string{"hotfix"}}, + {Hash: "f2", Parents: []string{"f1"}, Subject: "Draw merge lines"}, + {Hash: "e4", Parents: []string{"e3"}, Subject: "Tune the ballroom palette"}, + {Hash: "f1", Parents: []string{"e3"}, Subject: "Start lane layout"}, + {Hash: "e3", Parents: []string{"e2"}, Subject: "Add the commit list"}, + {Hash: "e2", Parents: []string{"e1"}, Subject: "Add the blame view"}, + {Hash: "e1", Subject: "Initial commit", Refs: []string{"v1.0.0"}}, + } + for i := range cs { + cs[i].Author = []string{"Sakiko", "Mutsumi", "Uika"}[i%3] + cs[i].When = gitDemoTime.Add(-time.Duration(i) * 2 * time.Hour) + } + return cs +} + +func gitDemoBranches() []mujica.Branch { + return []mujica.Branch{ + {Name: "main", Current: true, Upstream: "origin/main", Ahead: 2, Behind: 1}, + {Name: "feature/lanes", Upstream: "origin/feature/lanes", Ahead: 5}, + {Name: "fix/blame"}, + {Name: "origin/main", Remote: true}, + {Name: "origin/feature/lanes", Remote: true}, + {Name: "origin/release/1.1", Remote: true}, + } +} + +func gitDiffViewerDemo(c *ui.Context, log func(string)) { + type state struct { + viewer mujica.DiffViewerState + split, plain bool + context float64 + } + s := ui.Local(c.Root(), "301", func() state { return state{context: 2} }) + navigationDemo(c, func() { + navigationCheck(c, &s.split, "Side by side", log) + navigationCheck(c, &s.plain, "Plain text", log) + navigationSlider(c, &s.context, "Context", 1, 6, log) + }, func() { + lang := "go" + if s.plain { + lang = "" + } + mujica.DiffViewer(c, &s.viewer, gitDemoOld, gitDemoNew, mujica.DiffViewerOptions{SideBySide: s.split, Context: int(s.context), Language: lang}).Height(380) + }) +} + +func gitInlineDiffDemo(c *ui.Context, log func(string)) { + type state struct { + from, to string + mono bool + } + s := ui.Local(c.Root(), "302", func() state { + return state{from: "The court meets at noon in the east hall.", to: "The council meets at dusk in the east hall."} + }) + navigationDemo(c, func() { + navigationCheck(c, &s.mono, "Monospace", log) + }, func() { + if mujica.TextInput(c, &s.from, mujica.TextInputOptions{Label: "Old line"}).Changed() { + log("Old: " + s.from) + } + if mujica.TextInput(c, &s.to, mujica.TextInputOptions{Label: "New line"}).Changed() { + log("New: " + s.to) + } + mujica.InlineDiff(c, s.from, s.to, mujica.InlineDiffOptions{Mono: s.mono}) + }) +} + +func gitThreeWayMergeDemo(c *ui.Context, log func(string)) { + type state struct { + merge mujica.ThreeWayMergeState + disabled bool + } + s := ui.Local(c.Root(), "303", func() state { return state{} }) + base := "title: Overture\ntempo: 96\nkey: D minor\nlength: 4:10\nhall: east" + ours := "title: Overture\ntempo: 104\nkey: D minor\nlength: 4:10\nhall: east\nencore: yes" + theirs := "title: Overture\ntempo: 92\nkey: D minor\nlength: 4:30\nhall: east" + navigationDemo(c, func() { + navigationCheck(c, &s.disabled, "Disabled", log) + }, func() { + r := mujica.ThreeWayMerge(c, &s.merge, base, ours, theirs, mujica.ThreeWayMergeOptions{Disabled: s.disabled}) + r.Element.Height(360) + if r.Changed() { + done, total := s.merge.Resolved() + log(fmt.Sprintf("Changed: %d of %d resolved", done, total)) + } + ui.Text(c, s.merge.Result()).Font("monospace").TextColor(mujica.Tokens(c).TextMuted) + }) +} + +func gitConflictResolverDemo(c *ui.Context, log func(string)) { + type state struct { + res mujica.ConflictResolverState + disabled bool + } + s := ui.Local(c.Root(), "304", func() state { return state{} }) + text := "# Program\n<<<<<<< HEAD\nOpening: Overture in D minor\n=======\nOpening: Prelude in G major\n>>>>>>> feature/program\nInterval: 15 minutes\n<<<<<<< HEAD\nFinale: Masquerade\n=======\nFinale: Ave Mujica\n>>>>>>> feature/program" + navigationDemo(c, func() { + navigationCheck(c, &s.disabled, "Disabled", log) + }, func() { + if mujica.ConflictResolver(c, &s.res, text, mujica.ConflictResolverOptions{Disabled: s.disabled}).Changed() { + done, total := s.res.Resolved() + log(fmt.Sprintf("Changed: %d of %d resolved", done, total)) + } + }) +} + +func gitChangesListDemo(c *ui.Context, log func(string)) { + type state struct { + list mujica.ChangesListState + files []mujica.ChangedFile + disabled bool + } + s := ui.Local(c.Root(), "305", func() state { + return state{files: []mujica.ChangedFile{ + {Path: "commit_graph.go", Status: mujica.GitAdded, Staged: true}, + {Path: "internal/git.go", Status: mujica.GitModified}, + {Path: "docs/old.md", Status: mujica.GitDeleted}, + {Path: "notes.txt", Status: mujica.GitUntracked}, + {Path: "icons/svg/tag.svg", Status: mujica.GitRenamed}, + }} + }) + navigationDemo(c, func() { + navigationCheck(c, &s.disabled, "Disabled", log) + }, func() { + r := mujica.ChangesList(c, &s.list, s.files, mujica.ChangesListOptions{Disabled: s.disabled}) + r.Element.Height(320) + if a, path, ok := r.Action(); ok { + log("Action: " + a + " " + path) + s.files = gitStage(s.files, a, path) + } + if r.Changed() && s.list.Selected() >= 0 { + log("Selected: " + s.files[s.list.Selected()].Path) + } + }) +} + +// gitStage applies a stage action to a copy of files. +func gitStage(files []mujica.ChangedFile, action, path string) []mujica.ChangedFile { + out := append([]mujica.ChangedFile(nil), files...) + for i := range out { + switch { + case action == "stage_all": + out[i].Staged = true + case action == "unstage_all": + out[i].Staged = false + case out[i].Path == path: + out[i].Staged = action == "stage" + } + } + return out +} + +func gitCommitInputDemo(c *ui.Context, log func(string)) { + type state struct { + msg mujica.CommitMessage + busy, disabled bool + until time.Time + } + s := ui.Local(c.Root(), "306", func() state { return state{} }) + if s.busy && c.Now().After(s.until) { + s.busy = false + s.msg = mujica.CommitMessage{} + log("Committed") + } + if s.busy { + c.After(s.until.Sub(c.Now())) + } + navigationDemo(c, func() { + navigationCheck(c, &s.disabled, "Disabled", log) + }, func() { + r := mujica.CommitInput(c, &s.msg, mujica.CommitInputOptions{Busy: s.busy, Disabled: s.disabled}) + if r.Committed() || r.Amended() { + log(fmt.Sprintf("Submit: amend=%v title=%q", r.Amended(), s.msg.Title)) + s.busy, s.until = true, c.Now().Add(1200*time.Millisecond) + } + }) +} + +func gitCommitGraphDemo(c *ui.Context, log func(string)) { + type state struct { + graph mujica.CommitGraphState + big bool + } + s := ui.Local(c.Root(), "307", func() state { return state{} }) + small, big := gitDemoGraph(), gitDemoCommits(100000) + navigationDemo(c, func() { + navigationCheck(c, &s.big, "100,000 commits", log) + }, func() { + commits := small + if s.big { + commits = big + } + r := mujica.CommitGraph(c, &s.graph, commits, mujica.CommitGraphOptions{}) + r.Element.Height(380) + if hash, ok := s.graph.List.Selected(); ok && (r.Changed() || r.Submitted()) { + log(fmt.Sprintf("Selected %s, open=%v", hash[:min(7, len(hash))], r.Submitted())) + } + }) +} + +func gitCommitListDemo(c *ui.Context, log func(string)) { + type state struct { + list mujica.ListState[string] + loading bool + } + s := ui.Local(c.Root(), "308", func() state { return state{} }) + commits := gitDemoCommits(40) + navigationDemo(c, func() { + navigationCheck(c, &s.loading, "Loading more", log) + }, func() { + st := mujica.DataReady + if s.loading { + st = mujica.DataLoadingMore + } + r := mujica.CommitList(c, &s.list, commits, mujica.CommitListOptions{Status: st}) + r.Element.Height(360) + if hash, ok := s.list.Selected(); ok && (r.Changed() || r.Submitted()) { + log(fmt.Sprintf("Selected %s, open=%v", hash[:7], r.Submitted())) + } + }) +} + +func gitBranchSelectorDemo(c *ui.Context, log func(string)) { + type state struct { + branch string + create, disabled bool + branches []mujica.Branch + } + s := ui.Local(c.Root(), "309", func() state { return state{branch: "main", create: true, branches: gitDemoBranches()} }) + navigationDemo(c, func() { + navigationCheck(c, &s.create, "Allow create", log) + navigationCheck(c, &s.disabled, "Disabled", log) + }, func() { + r := mujica.BranchSelector(c, &s.branch, s.branches, mujica.BranchSelectorOptions{AllowCreate: s.create, Disabled: s.disabled}) + if r.Changed() { + log("Changed: " + s.branch) + } + if name, ok := r.Created(); ok { + log("Create: " + name) + s.branches = append(append([]mujica.Branch(nil), s.branches...), mujica.Branch{Name: name}) + s.branch = name + } + }) +} + +func gitBranchListDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "310", func() mujica.ListState[string] { return mujica.ListState[string]{} }) + actions := []mujica.GitAction{{ID: "checkout", Label: "Check out", Icon: "git-branch"}, {ID: "delete", Label: "Delete", Icon: "trash-2"}} + r := mujica.BranchList(c, s, gitDemoBranches(), mujica.BranchListOptions{Actions: actions}) + r.Element.Height(300) + if a, name, ok := r.Action(); ok { + log("Action: " + a + " " + name) + } + if key, ok := s.Selected(); ok && r.Changed() { + log("Selected: " + key) + } +} + +func gitTagListDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "311", func() mujica.ListState[string] { return mujica.ListState[string]{} }) + tags := []mujica.GitTag{ + {Name: "v1.1.0", Target: "9e3779b97f4a7c15", Annotation: "Five hundred components"}, + {Name: "v1.0.0", Target: "3c6ef372fe94f82a", Annotation: "The first hundred"}, + {Name: "nightly", Target: "daa66d2c7ddf743f"}, + } + r := mujica.TagList(c, s, tags, mujica.TagListOptions{}) + r.Element.Height(220) + if _, hash, ok := r.Action(); ok { + log("Jump to " + hash[:7]) + } + if key, ok := s.Selected(); ok && r.Changed() { + log("Selected: " + key) + } +} + +func gitStashListDemo(c *ui.Context, log func(string)) { + type state struct { + list mujica.ListState[string] + stashes []mujica.Stash + } + s := ui.Local(c.Root(), "312", func() state { + return state{stashes: []mujica.Stash{ + {Ref: "stash@{0}", Message: "WIP on main: lane colors", Branch: "main"}, + {Ref: "stash@{1}", Message: "Try serif headings", Branch: "feature/type"}, + {Ref: "stash@{2}", Message: "Blame hover experiment", Branch: "fix/blame"}, + }} + }) + r := mujica.StashList(c, &s.list, s.stashes, mujica.StashListOptions{}) + r.Element.Height(240) + if a, ref, ok := r.Action(); ok { + log("Action: " + a + " " + ref) + if a != "apply" { + var keep []mujica.Stash + for _, st := range s.stashes { + if st.Ref != ref { + keep = append(keep, st) + } + } + s.stashes = keep + } + } +} + +func gitBlameViewDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "313", func() mujica.BlameViewState { return mujica.BlameViewState{} }) + var lines []mujica.BlameLine + for i, l := range strings.Split(strings.TrimSuffix(gitDemoNew, "\n"), "\n") { + who := []mujica.BlameLine{ + {Hash: "9e3779b97f4a7c15", Author: "Sakiko", When: gitDemoTime, Summary: "Create the court package"}, + {Hash: "3c6ef372fe94f82a", Author: "Uika", When: gitDemoTime.Add(-48 * time.Hour), Summary: "Greet guests by title"}, + }[min(i/4%2, 1)] + who.Text = l + lines = append(lines, who) + } + mujica.BlameView(c, s, lines, mujica.BlameViewOptions{Language: "go"}).Height(380) + ui.Text(c, "Hover the left column for commit details.").TextColor(mujica.Tokens(c).TextMuted) +} + +func gitFileHistoryDemo(c *ui.Context, log func(string)) { + s := ui.Local(c.Root(), "314", func() mujica.ListState[string] { return mujica.ListState[string]{} }) + r := mujica.FileHistory(c, s, "court/greet.go", gitDemoCommits(12), mujica.FileHistoryOptions{}) + r.Element.Height(360) + if _, hash, ok := r.Action(); ok { + log("Diff at " + hash[:7]) + } + if key, ok := s.Selected(); ok && r.Changed() { + log("Selected: " + key[:7]) + } +} diff --git a/file_history.go b/file_history.go new file mode 100644 index 0000000..d13a1fb --- /dev/null +++ b/file_history.go @@ -0,0 +1,48 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// FileHistoryOptions configure a FileHistory. +type FileHistoryOptions struct { + // TimeFormat lays out commit times; empty means "2006-01-02 15:04". + TimeFormat string + Status DataStatus + Error string +} + +// FileHistory lists commits that changed path; Action "diff" opens one. +func FileHistory(c *ui.Context, s *ListState[string], path string, commits []Commit, opts FileHistoryOptions) GitListResult { + if path == "" { + panic("mujica: FileHistory needs a path") + } + k := Tokens(c) + u := Density(c).Unit() + layout := gitTimeLayout(opts.TimeFormat) + var r GitListResult + col := ui.Column(c).AlignItems(ui.Stretch).Gap(u * 2) + col.Children(func() { + ui.Row(c).AlignItems(ui.Center).Gap(u * 2).Children(func() { + ui.Icon(c, icons.Must("history")).Size(16, 16).TextColor(k.Ornament.Mix(k.Text, 0.35)) + ui.Text(c, path).Font(theme.MonoFont).FontWeight(600).SingleLine().MinWidth(0) + ui.Text(c, msg(c, "file_history.title")).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Shrink(0) + }) + actions := []GitAction{{ID: "diff", Label: msg(c, "file_history.diff"), Icon: "arrow-left-right"}} + v := List(c, s, len(commits), ListOptions[string]{ + Key: func(i int) string { return gitCommitHash(commits[i]) }, + Label: func(i int) string { return commits[i].Subject }, + Status: opts.Status, Error: opts.Error, Empty: msg(c, "file_history.empty"), + }, func(i int) { + commitListRow(c, commits[i], layout) + gitRowActions(c, actions, commits[i].Hash, &r) + }) + v.Element.Grow(1) + r.changed, r.submitted = v.Changed(), v.Submitted() + }) + r.Element = col + return r +} diff --git a/file_history_test.go b/file_history_test.go new file mode 100644 index 0000000..21fcbac --- /dev/null +++ b/file_history_test.go @@ -0,0 +1,65 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestFileHistoryDiffAction(t *testing.T) { + var s ListState[string] + commits := gitHistory(3) + diff := "" + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := FileHistory(c, &s, "commit_graph.go", commits, FileHistoryOptions{}) + r.Element.Height(240) + if a, item, ok := r.Action(); ok && a == "diff" { + diff = item + } + }, 700, 280) + if !tt.HasText("commit_graph.go") || !tt.HasText("History") { + t.Fatalf("header: %q", tt.Texts()) + } + r, _ := tt.Find("Commit number 2") + tt.ClickAt(700-30, r.Y+r.H/2) + if diff != commits[1].Hash { + t.Fatalf("diff %q", diff) + } + _ = tt.Click("Commit number 1") + tt.Key(0, ui.KeyUp) + if key, _ := s.Selected(); key != commits[1].Hash { + t.Fatalf("selected %q", key) + } +} + +func TestFileHistoryEmptyAndInvalid(t *testing.T) { + var s ListState[string] + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + FileHistory(c, &s, "a.go", nil, FileHistoryOptions{}).Element.Height(200) + }, 400, 240) + if !tt.HasText("No history for this file") { + t.Fatalf("empty: %q", tt.Texts()) + } + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + var s ListState[string] + FileHistory(c, &s, "", nil, FileHistoryOptions{}) + }, 300, 120, 1) +} + +func TestFileHistorySnapshot(t *testing.T) { + commits := gitHistory(3) + snapshot(t, "file_history", 640, 200, func(c *ui.Context) { + s := ui.Local(c.Root(), "list", func() *ListState[string] { return &ListState[string]{} }) + ui.Column(c).Padding(16).Children(func() { + FileHistory(c, *s, "internal/git.go", commits, FileHistoryOptions{}).Element.Height(170) + }) + }) +} diff --git a/git_status_badge.go b/git_status_badge.go new file mode 100644 index 0000000..b9b44a4 --- /dev/null +++ b/git_status_badge.go @@ -0,0 +1,72 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// GitStatus is a file's change state in version control. +type GitStatus int + +const ( + GitModified GitStatus = iota + GitAdded + GitDeleted + GitUntracked + GitRenamed + GitCopied +) + +var gitStatusKeys = [...]string{"modified", "added", "deleted", "untracked", "renamed", "copied"} + +// Letter is the git status code, as M. +func (s GitStatus) Letter() string { return string("MADURC"[gitStatusIndex(s)]) } + +func gitStatusIndex(s GitStatus) int { + if s < GitModified || s > GitCopied { + panic("mujica: unknown GitStatus") + } + return int(s) +} + +// GitStatusBadgeOptions configure a GitStatusBadge. +type GitStatusBadgeOptions struct { + // ShowLabel writes the status name beside the letter. + ShowLabel bool +} + +// GitStatusBadge marks a status by letter, outline and color. +func GitStatusBadge(c *ui.Context, status GitStatus, opts GitStatusBadgeOptions) *ui.Element { + k := Tokens(c) + name := msg(c, "git_status_badge."+gitStatusKeys[gitStatusIndex(status)]) + col := gitStatusColor(k, status) + row := ui.Row(c).AlignItems(ui.Center).Gap(Density(c).Unit() * 1.5).Shrink(0).Label(name).Role(ui.RoleImage) + if !opts.ShowLabel { + row.Tooltip(name) + } + row.Children(func() { + ui.Box(c).Size(18, 18).Shrink(0).Center().Radius(theme.ControlRadius).Border(theme.BorderWidth, col). + Children(func() { + ui.Text(c, status.Letter()).Font(theme.MonoFont).FontWeight(700).FontSize(FontSize(c, theme.CaptionSize)).TextColor(col) + }) + if opts.ShowLabel { + ui.Text(c, name).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine() + } + }) + return row +} + +func gitStatusColor(k theme.Tokens, s GitStatus) ui.Color { + switch s { + case GitAdded: + return k.Success + case GitDeleted: + return k.Danger + case GitUntracked, GitRenamed: + return k.Info + case GitCopied: + return k.AccentText + } + return k.Warning +} diff --git a/git_status_badge_test.go b/git_status_badge_test.go new file mode 100644 index 0000000..2888fdc --- /dev/null +++ b/git_status_badge_test.go @@ -0,0 +1,65 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestGitStatusBadgeLettersAndNames(t *testing.T) { + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Row(c).Gap(8).Children(func() { + for s := GitModified; s <= GitCopied; s++ { + GitStatusBadge(c, s, GitStatusBadgeOptions{}) + } + }) + }, 400, 80) + for i, name := range []string{"Modified", "Added", "Deleted", "Untracked", "Renamed", "Copied"} { + if _, ok := tt.Find(name); !ok { + t.Errorf("no badge named %q", name) + } + if got := GitStatus(i).Letter(); got != string("MADURC"[i]) { + t.Errorf("letter %d = %q", i, got) + } + } + if !tt.HasText("R") || !tt.HasText("U") { + t.Fatalf("letters not shown: %q", tt.Texts()) + } +} + +func TestGitStatusBadgeLabelAndInvalid(t *testing.T) { + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{Locale: ZhCN}) + GitStatusBadge(c, GitDeleted, GitStatusBadgeOptions{ShowLabel: true}) + }, 300, 80) + if !tt.HasText("已删除") { + t.Fatalf("label missing: %q", tt.Texts()) + } + defer func() { + if recover() == nil { + t.Fatal("unknown status did not panic") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + GitStatusBadge(c, GitStatus(9), GitStatusBadgeOptions{}) + }, 100, 50, 1) +} + +func TestGitStatusBadgeSnapshot(t *testing.T) { + snapshot(t, "git_status_badge", 520, 90, func(c *ui.Context) { + ui.Column(c).Padding(16).Gap(12).Children(func() { + ui.Row(c).Gap(10).Children(func() { + for s := GitModified; s <= GitCopied; s++ { + GitStatusBadge(c, s, GitStatusBadgeOptions{}) + } + }) + ui.Row(c).Gap(14).Children(func() { + for _, s := range []GitStatus{GitModified, GitAdded, GitDeleted} { + GitStatusBadge(c, s, GitStatusBadgeOptions{ShowLabel: true}) + } + }) + }) + }) +} diff --git a/icons/svg/archive.svg b/icons/svg/archive.svg new file mode 100644 index 0000000..47823fa --- /dev/null +++ b/icons/svg/archive.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/icons/svg/arrow-left-right.svg b/icons/svg/arrow-left-right.svg new file mode 100644 index 0000000..1b0e8bd --- /dev/null +++ b/icons/svg/arrow-left-right.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/icons/svg/chevrons-up-down.svg b/icons/svg/chevrons-up-down.svg new file mode 100644 index 0000000..629ee86 --- /dev/null +++ b/icons/svg/chevrons-up-down.svg @@ -0,0 +1,15 @@ + + + + diff --git a/icons/svg/git-branch.svg b/icons/svg/git-branch.svg new file mode 100644 index 0000000..85b3f96 --- /dev/null +++ b/icons/svg/git-branch.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/icons/svg/git-commit-horizontal.svg b/icons/svg/git-commit-horizontal.svg new file mode 100644 index 0000000..5ee4eb5 --- /dev/null +++ b/icons/svg/git-commit-horizontal.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/icons/svg/git-merge.svg b/icons/svg/git-merge.svg new file mode 100644 index 0000000..dc901a4 --- /dev/null +++ b/icons/svg/git-merge.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/icons/svg/git-pull-request.svg b/icons/svg/git-pull-request.svg new file mode 100644 index 0000000..d2540a1 --- /dev/null +++ b/icons/svg/git-pull-request.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/icons/svg/history.svg b/icons/svg/history.svg new file mode 100644 index 0000000..02ac266 --- /dev/null +++ b/icons/svg/history.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/icons/svg/message-square.svg b/icons/svg/message-square.svg new file mode 100644 index 0000000..4908056 --- /dev/null +++ b/icons/svg/message-square.svg @@ -0,0 +1,14 @@ + + + diff --git a/icons/svg/reply.svg b/icons/svg/reply.svg new file mode 100644 index 0000000..eb1eb3f --- /dev/null +++ b/icons/svg/reply.svg @@ -0,0 +1,15 @@ + + + + diff --git a/icons/svg/rotate-ccw.svg b/icons/svg/rotate-ccw.svg new file mode 100644 index 0000000..1d22d4a --- /dev/null +++ b/icons/svg/rotate-ccw.svg @@ -0,0 +1,15 @@ + + + + diff --git a/icons/svg/tag.svg b/icons/svg/tag.svg new file mode 100644 index 0000000..954f3f2 --- /dev/null +++ b/icons/svg/tag.svg @@ -0,0 +1,15 @@ + + + + diff --git a/inline_diff.go b/inline_diff.go new file mode 100644 index 0000000..bcbca60 --- /dev/null +++ b/inline_diff.go @@ -0,0 +1,66 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// InlineDiffOptions configure an InlineDiff. +type InlineDiffOptions struct { + // Mono sets the lines in the code font. + Mono bool +} + +type inlineDiffCache struct { + from, to string + a, b []internal.WordSpan + done bool +} + +// InlineDiff shows old and new lines with changed words marked. +func InlineDiff(c *ui.Context, from, to string, opts InlineDiffOptions) *ui.Element { + k := Tokens(c) + col := ui.Column(c).AlignItems(ui.Stretch).Shrink(0).Radius(theme.ControlRadius).Clip() + cache := ui.Local(col, "words", func() *inlineDiffCache { return &inlineDiffCache{} }) + w := *cache + if !w.done || w.from != from || w.to != to { + w.a, w.b = internal.WordDiff(from, to) + w.from, w.to, w.done = from, to, true + } + if opts.Mono { + col.Font(theme.MonoFont) + } + col.Children(func() { + inlineDiffLine(c, "−", msg(c, "inline_diff.removed"), w.a, k.Danger, k) + inlineDiffLine(c, "+", msg(c, "inline_diff.added"), w.b, k.Success, k) + }) + return col +} + +// inlineDiffLine shows one side with its changed words marked. +func inlineDiffLine(c *ui.Context, sign, name string, spans []internal.WordSpan, col ui.Color, k theme.Tokens) { + u := Density(c).Unit() + out := make([]ui.Span, 0, len(spans)) + plain := "" + for _, s := range spans { + plain += s.Text + sp := ui.Span{Text: s.Text} + switch s.Op { + case internal.DiffDelete: + sp.Background, sp.Strikethrough, sp.DecorationColor = col.Mix(k.Surface, 0.7), true, col + case internal.DiffInsert: + sp.Background, sp.Underline, sp.DecorationColor = col.Mix(k.Surface, 0.7), true, col + } + out = append(out, sp) + } + if len(out) == 0 { + out = append(out, ui.Span{Text: " "}) + } + ui.Row(c).AlignItems(ui.Start).Gap(u*2).Padding(u, u*3).Background(col.Mix(k.Surface, 0.9)).Label(name + ": " + plain). + Children(func() { + ui.Text(c, sign).Font(theme.MonoFont).FontWeight(700).TextColor(col).Shrink(0) + ui.RichText(c, out...).TextColor(k.Text).MinWidth(0) + }) +} diff --git a/inline_diff_test.go b/inline_diff_test.go new file mode 100644 index 0000000..1f78728 --- /dev/null +++ b/inline_diff_test.go @@ -0,0 +1,49 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestInlineDiffNamesAndShowsBothLines(t *testing.T) { + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + InlineDiff(c, "The court meets at noon", "The court meets at dusk", InlineDiffOptions{}) + }, 600, 120) + if _, ok := tt.Find("Old: The court meets at noon"); !ok { + t.Fatalf("old line: %q", tt.Texts()) + } + if _, ok := tt.Find("New: The court meets at dusk"); !ok { + t.Fatalf("new line: %q", tt.Texts()) + } +} + +func TestInlineDiffCachesWords(t *testing.T) { + from, to := "a b", "a c" + var cache *inlineDiffCache + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + e := InlineDiff(c, from, to, InlineDiffOptions{Mono: true}) + cache = *ui.Local(e, "words", func() *inlineDiffCache { return nil }) + }, 300, 100) + first := &cache.a[0] + tt.Frame() + if &cache.a[0] != first { + t.Fatal("word diff recomputed without a change") + } + to = "a d" + tt.Frame() + if cache.b[1].Text != "d" { + t.Fatalf("new text not diffed: %+v", cache.b) + } +} + +func TestInlineDiffSnapshot(t *testing.T) { + snapshot(t, "inline_diff", 560, 200, func(c *ui.Context) { + ui.Column(c).Padding(16).Gap(12).Children(func() { + InlineDiff(c, "The court meets at noon in the east hall.", "The council meets at dusk in the east hall.", InlineDiffOptions{}) + InlineDiff(c, "return a + b", "return a - total", InlineDiffOptions{Mono: true}) + }) + }) +} diff --git a/internal/diff.go b/internal/diff.go index ccc9071..9b0f2af 100644 --- a/internal/diff.go +++ b/internal/diff.go @@ -1,6 +1,9 @@ package internal -import "strings" +import ( + "strings" + "unicode" +) // DiffOp says whether a diff line is kept, removed or added. type DiffOp uint8 @@ -119,6 +122,61 @@ func myers(out []DiffLine, a, b []string, ao, bo int) []DiffLine { return out } +// WordSpan is a run of a line that a word diff kept, removed or added. +type WordSpan struct { + Op DiffOp + Text string +} + +// WordDiff compares two lines by words: from holds kept and removed spans, to kept and added. +func WordDiff(a, b string) (from, to []WordSpan) { + add := func(spans []WordSpan, op DiffOp, s string) []WordSpan { + if n := len(spans); n > 0 && spans[n-1].Op == op { + spans[n-1].Text += s + return spans + } + return append(spans, WordSpan{op, s}) + } + for _, d := range LineDiff(wordTokens(a), wordTokens(b)) { + switch d.Op { + case DiffEqual: + from, to = add(from, DiffEqual, d.Text), add(to, DiffEqual, d.Text) + case DiffDelete: + from = add(from, DiffDelete, d.Text) + case DiffInsert: + to = add(to, DiffInsert, d.Text) + } + } + return from, to +} + +// wordTokens splits s into words, runs of spaces and single other characters. +func wordTokens(s string) []string { + var out []string + kind := func(r rune) int { + switch { + case r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r): + return 1 + case unicode.IsSpace(r): + return 2 + } + return 0 + } + start, prev := 0, -1 + for i, r := range s { + k := kind(r) + if i > start && (k != prev || k == 0) { + out = append(out, s[start:i]) + start = i + } + prev = k + } + if start < len(s) { + out = append(out, s[start:]) + } + return out +} + // DiffStats counts the added and removed lines of a diff. func DiffStats(d []DiffLine) (added, removed int) { for _, l := range d { diff --git a/internal/diff_word_test.go b/internal/diff_word_test.go new file mode 100644 index 0000000..29bdb1d --- /dev/null +++ b/internal/diff_word_test.go @@ -0,0 +1,38 @@ +package internal + +import ( + "slices" + "testing" +) + +func TestWordTokens(t *testing.T) { + got := wordTokens("let x_1 = foo(bar); ok") + want := []string{"let", " ", "x_1", " ", "=", " ", "foo", "(", "bar", ")", ";", " ", "ok"} + if !slices.Equal(got, want) { + t.Fatalf("tokens %q", got) + } + if wordTokens("") != nil { + t.Fatal("empty line has tokens") + } +} + +func TestWordDiff(t *testing.T) { + from, to := WordDiff("return a + b", "return a - total") + wantFrom := []WordSpan{{DiffEqual, "return a "}, {DiffDelete, "+"}, {DiffEqual, " "}, {DiffDelete, "b"}} + wantTo := []WordSpan{{DiffEqual, "return a "}, {DiffInsert, "-"}, {DiffEqual, " "}, {DiffInsert, "total"}} + if !slices.Equal(from, wantFrom) || !slices.Equal(to, wantTo) { + t.Fatalf("from %+v to %+v", from, to) + } + join := func(s []WordSpan) (out string) { + for _, w := range s { + out += w.Text + } + return + } + for _, p := range [][2]string{{"", "new text"}, {"old text", ""}, {"same", "same"}, {"中文 词语", "中文 句子"}} { + f, to := WordDiff(p[0], p[1]) + if join(f) != p[0] || join(to) != p[1] { + t.Errorf("%q→%q rebuilt %q→%q", p[0], p[1], join(f), join(to)) + } + } +} diff --git a/internal/git.go b/internal/git.go new file mode 100644 index 0000000..6d0f166 --- /dev/null +++ b/internal/git.go @@ -0,0 +1,76 @@ +package internal + +import ( + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// CodeSpans colors a code line; inBlock carries block comments. +func CodeSpans(k theme.Tokens, language, line string, inBlock bool) ([]ui.Span, bool) { + toks, open := Highlight(language, line, inBlock) + spans := make([]ui.Span, 0, len(toks)) + for _, t := range toks { + s := ui.Span{Text: t.Text, Color: k.Text} + switch t.Kind { + case TokKeyword: + s.Color, s.Weight = k.AccentText, 600 + case TokString: + s.Color = k.Success + case TokNumber: + s.Color = k.Info + case TokComment: + s.Color, s.Italic = k.TextMuted, true + case TokType: + s.Color = k.Warning + case TokPunct: + s.Color = k.TextMuted + } + spans = append(spans, s) + } + return spans, open +} + +// ansiLight and ansiDark are 16 colors readable on Surface. +var ( + ansiLight = [16]string{"#211C1D", "#A12635", "#326247", "#805714", "#355E80", "#7A3B78", "#2F6B6B", "#6A5B55", + "#6A5B55", "#B0303F", "#3B7352", "#8E6417", "#3F6E94", "#8A4787", "#367A7A", "#211C1D"} + ansiDark = [16]string{"#A89A95", "#F0A1AA", "#94C6A4", "#DFC080", "#9DBDDA", "#D9A6D6", "#8FCFCF", "#F2EBDD", + "#BCAEAA", "#F5B7BE", "#ADD6B9", "#E9CF99", "#B5CDE4", "#E4BDE2", "#A9DCDC", "#FFFFFF"} + ansiCube = [6]uint8{0, 95, 135, 175, 215, 255} +) + +// AnsiResolve resolves a color; ok is false for default. +func AnsiResolve(dark bool, col AnsiColor) (ui.Color, bool) { + switch col.Kind { + case AnsiRGB: + return ui.RGB(col.R, col.G, col.B), true + case AnsiIndexed: + i := col.Index + switch { + case i < 16 && dark: + return ui.Hex(ansiDark[i]), true + case i < 16: + return ui.Hex(ansiLight[i]), true + case i < 232: + i -= 16 + return ui.RGB(ansiCube[i/36], ansiCube[i/6%6], ansiCube[i%6]), true + default: + g := 8 + 10*(i-232) + return ui.RGB(g, g, g), true + } + } + return ui.Color{}, false +} + +// StripAnsi drops SGR escapes from s, keeping its text. +func StripAnsi(s string) string { + spans, _ := ParseAnsi(s, AnsiStyle{}) + var b strings.Builder + for _, sp := range spans { + b.WriteString(sp.Text) + } + return b.String() +} diff --git a/internal/git_test.go b/internal/git_test.go new file mode 100644 index 0000000..d5831b8 --- /dev/null +++ b/internal/git_test.go @@ -0,0 +1,41 @@ +package internal + +import ( + "testing" + + "mujicaui/theme" +) + +func TestAnsiPaletteReadable(t *testing.T) { + for _, k := range []theme.Tokens{theme.Light(), theme.Dark()} { + for i := range 16 { + col, ok := AnsiResolve(k.Dark, AnsiColor{Kind: AnsiIndexed, Index: uint8(i)}) + if !ok { + t.Fatalf("index %d unresolved", i) + } + if r := theme.Contrast(col, k.Surface); r < 4.5 { + t.Errorf("dark=%v color %d contrast %.2f", k.Dark, i, r) + } + } + } + if c, _ := AnsiResolve(false, AnsiColor{Kind: AnsiIndexed, Index: 196}); c.R != 255 || c.G != 0 || c.B != 0 { + t.Errorf("cube 196 = %v", c) + } + if c, _ := AnsiResolve(false, AnsiColor{Kind: AnsiIndexed, Index: 244}); c.R != 128 { + t.Errorf("gray 244 = %v", c) + } + if _, ok := AnsiResolve(true, AnsiColor{}); ok { + t.Error("default color resolved") + } +} + +func TestCodeSpansColorKeywords(t *testing.T) { + k := theme.Light() + spans, _ := CodeSpans(k, "go", "func main() // hi", false) + if spans[0].Text != "func" || spans[0].Color != k.AccentText { + t.Fatalf("keyword span %+v", spans[0]) + } + if last := spans[len(spans)-1]; last.Color != k.TextMuted || !last.Italic { + t.Fatalf("comment span %+v", last) + } +} diff --git a/messages_git.go b/messages_git.go new file mode 100644 index 0000000..445a4cd --- /dev/null +++ b/messages_git.go @@ -0,0 +1,114 @@ +package mujica + +func init() { + addMessages(map[string][2]string{ + "git_status_badge.modified": {"Modified", "已修改"}, + "git_status_badge.added": {"Added", "已添加"}, + "git_status_badge.deleted": {"Deleted", "已删除"}, + "git_status_badge.untracked": {"Untracked", "未跟踪"}, + "git_status_badge.renamed": {"Renamed", "已重命名"}, + "git_status_badge.copied": {"Copied", "已复制"}, + + "diff_stat.label": {"%d additions, %d deletions", "新增 %d 行,删除 %d 行"}, + + "command_block.copy_command": {"Copy command", "复制命令"}, + "command_block.copy_output": {"Copy output", "复制输出"}, + "command_block.exit": {"exit %d", "退出码 %d"}, + "command_block.no_output": {"No output", "无输出"}, + "command_block.output": {"Command output", "命令输出"}, + "command_block.running": {"Running", "运行中"}, + + "commit_list.empty": {"No commits", "没有提交"}, + + "branch_list.ahead": {"%d ahead of upstream", "领先上游 %d 个提交"}, + "branch_list.behind": {"%d behind upstream", "落后上游 %d 个提交"}, + "branch_list.current": {"current", "当前"}, + "branch_list.empty": {"No branches", "没有分支"}, + + "branch_selector.create": {"Create branch", "新建分支"}, + "branch_selector.empty": {"No matching branches", "没有匹配的分支"}, + "branch_selector.label": {"Branch", "分支"}, + "branch_selector.search": {"Search branches", "搜索分支"}, + "branch_selector.local": {"Local", "本地"}, + "branch_selector.remote": {"Remote", "远端"}, + + "tag_list.empty": {"No tags", "没有标签"}, + "tag_list.jump": {"Go to commit", "跳转到提交"}, + + "stash_list.apply": {"Apply", "应用"}, + "stash_list.pop": {"Pop", "弹出"}, + "stash_list.drop": {"Drop", "删除"}, + "stash_list.empty": {"No stashes", "没有贮藏"}, + + "blame_view.line": {"Line %d, %s, %s", "第 %d 行,%s,%s"}, + + "file_history.title": {"History", "历史"}, + "file_history.diff": {"View changes", "查看差异"}, + "file_history.empty": {"No history for this file", "此文件没有历史"}, + + "pull_request_card.open": {"Open", "开放"}, + "pull_request_card.draft": {"Draft", "草稿"}, + "pull_request_card.merged": {"Merged", "已合并"}, + "pull_request_card.closed": {"Closed", "已关闭"}, + "pull_request_card.files": {"%d files", "%d 个文件"}, + "pull_request_card.passed": {"%d checks passed", "%d 项检查通过"}, + "pull_request_card.failed": {"%d checks failed", "%d 项检查失败"}, + "pull_request_card.pending": {"%d checks pending", "%d 项检查进行中"}, + "pull_request_card.approved": {"approved", "已批准"}, + "pull_request_card.changes": {"changes requested", "要求修改"}, + "pull_request_card.review_pending": {"review pending", "待评审"}, + + "review_comment.placeholder": {"Write a reply", "写下回复"}, + "review_comment.reply": {"Reply", "回复"}, + "review_comment.field": {"Reply text", "回复内容"}, + "review_comment.resolve": {"Resolve", "解决"}, + "review_comment.reopen": {"Reopen", "重新打开"}, + "review_comment.resolved": {"Resolved", "已解决"}, + + "changes_list.staged": {"Staged changes (%d)", "已暂存的更改(%d)"}, + "changes_list.unstaged": {"Changes (%d)", "更改(%d)"}, + "changes_list.stage": {"Stage", "暂存"}, + "changes_list.unstage": {"Unstage", "取消暂存"}, + "changes_list.stage_all": {"Stage all", "全部暂存"}, + "changes_list.unstage_all": {"Unstage all", "全部取消暂存"}, + + "diff_viewer.added": {"Added", "新增"}, + "diff_viewer.deleted": {"Deleted", "删除"}, + "diff_viewer.fold": {"%d unchanged lines", "%d 行未更改"}, + + "inline_diff.removed": {"Old", "原文"}, + "inline_diff.added": {"New", "新文"}, + + "three_way_merge.resolved": {"%d of %d conflicts resolved", "已解决 %d / %d 个冲突"}, + "three_way_merge.ours": {"Local", "本地"}, + "three_way_merge.base": {"Base", "基准"}, + "three_way_merge.theirs": {"Remote", "远端"}, + "three_way_merge.result": {"Result", "结果"}, + "three_way_merge.unresolved": {"Unresolved", "未解决"}, + "three_way_merge.empty": {"No lines", "无内容"}, + "three_way_merge.take_ours": {"Take local", "采纳本地"}, + "three_way_merge.take_theirs": {"Take remote", "采纳远端"}, + "three_way_merge.take_both": {"Take both", "两者都要"}, + "three_way_merge.take_base": {"Keep base", "保留基准"}, + + "conflict_resolver.resolved": {"%d of %d conflicts resolved", "已解决 %d / %d 个冲突"}, + "conflict_resolver.broken": {"Conflict markers are not closed after line %d", "第 %d 行起的冲突标记未闭合"}, + "conflict_resolver.none": {"No conflicts", "没有冲突"}, + "conflict_resolver.title": {"Conflict %d · line %d", "冲突 %d · 第 %d 行"}, + "conflict_resolver.open": {"unresolved", "未解决"}, + "conflict_resolver.done": {"resolved", "已解决"}, + "conflict_resolver.current": {"Current", "当前"}, + "conflict_resolver.incoming": {"Incoming", "传入"}, + "conflict_resolver.take_current": {"Accept current", "采纳当前"}, + "conflict_resolver.take_incoming": {"Accept incoming", "采纳传入"}, + "conflict_resolver.take_both": {"Accept both", "两者都采纳"}, + "conflict_resolver.reset": {"Undo", "撤销"}, + + "commit_input.title": {"Summary", "提交标题"}, + "commit_input.body": {"Description", "提交说明"}, + "commit_input.count": {"%d of %d characters", "%d / %d 字符"}, + "commit_input.long": {"Summary is %d characters over the suggested length", "标题超出建议长度 %d 个字符"}, + "commit_input.commit": {"Commit", "提交"}, + "commit_input.amend": {"Amend", "修订"}, + }) +} diff --git a/pull_request_card.go b/pull_request_card.go new file mode 100644 index 0000000..e51706b --- /dev/null +++ b/pull_request_card.go @@ -0,0 +1,179 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// PullRequestState is where a pull request stands. +type PullRequestState int + +const ( + PullRequestOpen PullRequestState = iota + PullRequestDraft + PullRequestMerged + PullRequestClosed +) + +// ReviewState is a reviewer's verdict. +type ReviewState int + +const ( + ReviewPending ReviewState = iota + ReviewApproved + ReviewChangesRequested +) + +// Reviewer is a person asked to review. +type Reviewer struct { + Name string + State ReviewState +} + +// PullRequest is what a PullRequestCard shows; the caller fetches it. +type PullRequest struct { + Number int + Title string + Author string + State PullRequestState + Head, Base string + // Checks counts CI results. + ChecksPassed, ChecksFailed, ChecksPending int + Reviewers []Reviewer + Added, Deleted, Files int +} + +// PullRequestCardOptions configure a PullRequestCard. +type PullRequestCardOptions struct { + Disabled bool +} + +// PullRequestCard summarizes a pull request; Changed reports opening. +func PullRequestCard(c *ui.Context, pr PullRequest, opts PullRequestCardOptions) ChoiceResult { + if pr.Number <= 0 || pr.Title == "" { + panic("mujica: PullRequest needs a positive Number and a Title") + } + if pr.ChecksPassed < 0 || pr.ChecksFailed < 0 || pr.ChecksPending < 0 || pr.Files < 0 { + panic("mujica: PullRequest counts must not be negative") + } + k := Tokens(c) + u := Density(c).Unit() + small := FontSize(c, theme.CaptionSize) + card := ui.Column(c).AlignItems(ui.Stretch).Gap(u*2).Padding(u*4).Background(k.Surface). + Border(theme.BorderWidth, k.Border).Radius(theme.CardRadius).Disabled(opts.Disabled) + res := ChoiceResult{Element: card} + card.Children(func() { + ui.Row(c).AlignItems(ui.Center).Gap(u * 2).Children(func() { + pullRequestStateBadge(c, pr.State) + title := ui.ButtonBase(c).Justify(ui.Start).Gap(u*2).Padding(u, u).Radius(theme.ControlRadius). + Role(ui.RoleLink).Label(fmt.Sprintf("#%d %s", pr.Number, pr.Title)).Shrink(1).MinWidth(0).Cursor(ui.CursorPointer) + internal.Ring(title, k.Focus, theme.ControlRadius) + if title.Hovered() { + title.Background(k.SurfaceHover) + } + title.Transition(colorFade) + title.Children(func() { + ui.Text(c, pr.Title).FontWeight(600).SingleLine().MinWidth(0) + ui.Text(c, fmt.Sprintf("#%d", pr.Number)).TextColor(k.TextMuted).FontFeatures("tnum").Shrink(0) + }) + if title.Clicked() && !title.IsDisabled() { + res.changed = true + slog.Debug("mujica: pull request card open", "number", pr.Number) + } + }) + ui.Row(c).AlignItems(ui.Center).Gap(u * 2).FontSize(small).TextColor(k.TextMuted).Wrap().Children(func() { + ui.Text(c, pr.Author).FontWeight(600).TextColor(k.Text) + if pr.Head != "" && pr.Base != "" { + ui.Icon(c, icons.Must("git-pull-request")).Size(12, 12) + ui.Text(c, pr.Head+" → "+pr.Base).Font(theme.MonoFont).SingleLine().MaxWidth(320) + } + }) + ui.Row(c).AlignItems(ui.Center).Gap(u * 4).Wrap().FontSize(small).Children(func() { + pullRequestChecks(c, pr) + if len(pr.Reviewers) > 0 { + ui.Row(c).AlignItems(ui.Center).Gap(u * 2).Children(func() { + for _, r := range pr.Reviewers { + pullRequestReviewer(c, r) + } + }) + } + ui.Spacer(c) + ui.Text(c, fmt.Sprintf(msg(c, "pull_request_card.files"), pr.Files)).TextColor(k.TextMuted).FontFeatures("tnum") + DiffStat(c, pr.Added, pr.Deleted, DiffStatOptions{}) + }) + }) + return res +} + +func pullRequestStateBadge(c *ui.Context, st PullRequestState) { + k := Tokens(c) + u := Density(c).Unit() + icon, col, key := "git-pull-request", k.Success, "open" + switch st { + case PullRequestOpen: + case PullRequestDraft: + icon, col, key = "git-pull-request", k.TextMuted, "draft" + case PullRequestMerged: + icon, col, key = "git-merge", k.AccentText, "merged" + case PullRequestClosed: + icon, col, key = "circle-x", k.Danger, "closed" + default: + panic("mujica: unknown PullRequestState") + } + ui.Row(c).AlignItems(ui.Center).Gap(u).Padding(2, u*2).Radius(theme.ControlRadius).Border(theme.BorderWidth, col). + TextColor(col).Shrink(0).Children(func() { + ui.Icon(c, icons.Must(icon)).Size(14, 14) + ui.Text(c, msg(c, "pull_request_card."+key)).FontSize(FontSize(c, theme.CaptionSize)).FontWeight(600).SingleLine() + }) +} + +func pullRequestChecks(c *ui.Context, pr PullRequest) { + k := Tokens(c) + u := Density(c).Unit() + ui.Row(c).AlignItems(ui.Center).Gap(u * 3).Children(func() { + for _, ch := range []struct { + n int + icon, key string + col ui.Color + }{ + {pr.ChecksPassed, "circle-check", "pull_request_card.passed", k.Success}, + {pr.ChecksFailed, "circle-x", "pull_request_card.failed", k.Danger}, + {pr.ChecksPending, "clock", "pull_request_card.pending", k.Warning}, + } { + if ch.n == 0 { + continue + } + name := fmt.Sprintf(msg(c, ch.key), ch.n) + ui.Row(c).AlignItems(ui.Center).Gap(u).TextColor(ch.col).Label(name).Tooltip(name).Children(func() { + ui.Icon(c, icons.Must(ch.icon)).Size(14, 14) + ui.Text(c, fmt.Sprint(ch.n)).FontFeatures("tnum") + }) + } + }) +} + +func pullRequestReviewer(c *ui.Context, r Reviewer) { + k := Tokens(c) + key, icon, col := "pull_request_card.review_pending", "clock", k.TextMuted + switch r.State { + case ReviewPending: + case ReviewApproved: + key, icon, col = "pull_request_card.approved", "check", k.Success + case ReviewChangesRequested: + key, icon, col = "pull_request_card.changes", "circle-alert", k.Danger + default: + panic("mujica: unknown ReviewState") + } + name := r.Name + ": " + msg(c, key) + ui.Box(c).Size(28, 28).Shrink(0).Label(name).Tooltip(name).Children(func() { + Avatar(c, r.Name, AvatarOptions{Size: 24}).Absolute().Left(0).Top(0) + ui.Box(c).Size(14, 14).Radius(7).Background(k.Surface).Center().Absolute().Right(0).Bottom(0).TextColor(col). + Children(func() { ui.Icon(c, icons.Must(icon)).Size(10, 10) }) + }) +} diff --git a/pull_request_card_test.go b/pull_request_card_test.go new file mode 100644 index 0000000..caa4960 --- /dev/null +++ b/pull_request_card_test.go @@ -0,0 +1,82 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func pullRequestSample() PullRequest { + return PullRequest{Number: 318, Title: "Git components 301–320", Author: "Sakiko", State: PullRequestOpen, + Head: "feature/git", Base: "main", ChecksPassed: 12, ChecksFailed: 1, ChecksPending: 2, + Reviewers: []Reviewer{{Name: "Uika", State: ReviewApproved}, {Name: "Mutsumi", State: ReviewChangesRequested}, {Name: "Umiri"}}, + Added: 2412, Deleted: 310, Files: 46} +} + +func TestPullRequestCardShowsAndOpens(t *testing.T) { + opens := 0 + disabled := false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if PullRequestCard(c, pullRequestSample(), PullRequestCardOptions{Disabled: disabled}).Changed() { + opens++ + } + }, 700, 240) + for _, name := range []string{"Open", "#318", "feature/git → main", "12 checks passed", "1 checks failed", "2 checks pending", + "Uika: approved", "Mutsumi: changes requested", "Umiri: review pending", "46 files", "2412 additions, 310 deletions"} { + if _, ok := tt.Find(name); !ok { + t.Errorf("missing %q", name) + } + } + if err := tt.Click("Git components 301–320"); err != nil { + t.Fatal(err) + } + tt.Key(0, ui.KeyEnter) + if opens != 2 { + t.Fatalf("opens %d", opens) + } + disabled = true + tt.Frame() + _ = tt.Click("Git components 301–320") + if opens != 2 { + t.Fatal("disabled card opened") + } +} + +func TestPullRequestCardStatesAndInvalid(t *testing.T) { + for st, word := range map[PullRequestState]string{PullRequestDraft: "Draft", PullRequestMerged: "Merged", PullRequestClosed: "Closed"} { + pr := pullRequestSample() + pr.State = st + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + PullRequestCard(c, pr, PullRequestCardOptions{}) + }, 700, 240) + if !tt.HasText(word) { + t.Errorf("state %d: %q", st, tt.Texts()) + } + } + for _, pr := range []PullRequest{{Title: "x"}, {Number: 1}, {Number: 1, Title: "x", Files: -1}, {Number: 1, Title: "x", State: 9}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%+v did not panic", pr) + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + PullRequestCard(c, pr, PullRequestCardOptions{}) + }, 300, 100, 1) + }() + } +} + +func TestPullRequestCardSnapshot(t *testing.T) { + snapshot(t, "pull_request_card", 640, 300, func(c *ui.Context) { + ui.Column(c).Padding(16).Gap(12).Children(func() { + PullRequestCard(c, pullRequestSample(), PullRequestCardOptions{}) + pr := pullRequestSample() + pr.Number, pr.State, pr.Title, pr.Reviewers, pr.ChecksFailed, pr.ChecksPending = 301, PullRequestMerged, "Diff viewer", nil, 0, 0 + PullRequestCard(c, pr, PullRequestCardOptions{}) + }) + }) +} diff --git a/review_comment.go b/review_comment.go new file mode 100644 index 0000000..5731307 --- /dev/null +++ b/review_comment.go @@ -0,0 +1,127 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// ReviewMessage is one comment of a review thread. +type ReviewMessage struct { + Author string + When time.Time + Body string +} + +// ReviewThread is a line-level review discussion. +type ReviewThread struct { + File string + Line int + Resolved bool + Messages []ReviewMessage +} + +// ReviewCommentOptions configure a ReviewComment. +type ReviewCommentOptions struct { + // TimeFormat lays out message times; empty means "2006-01-02 15:04". + TimeFormat string + Disabled bool +} + +// ReviewCommentResult is a built ReviewComment and its events. +type ReviewCommentResult struct { + Element *ui.Element + reply string + resolved, reopened bool +} + +// Replied returns the reply sent this frame. +func (r ReviewCommentResult) Replied() (string, bool) { return r.reply, r.reply != "" } + +// Resolved reports the Resolve button this frame. +func (r ReviewCommentResult) Resolved() bool { return r.resolved } + +// Reopened reports the Reopen button this frame. +func (r ReviewCommentResult) Reopened() bool { return r.reopened } + +// ReviewComment shows a line's review thread; *draft is the reply. +func ReviewComment(c *ui.Context, thread ReviewThread, draft *string, opts ReviewCommentOptions) ReviewCommentResult { + if thread.File == "" || thread.Line <= 0 || len(thread.Messages) == 0 { + panic("mujica: ReviewThread needs a File, a positive Line and a message") + } + k := Tokens(c) + u := Density(c).Unit() + small := FontSize(c, theme.CaptionSize) + layout := gitTimeLayout(opts.TimeFormat) + card := ui.Column(c).AlignItems(ui.Stretch).Background(k.Surface).Border(theme.BorderWidth, k.Border). + Radius(theme.CardRadius).Disabled(opts.Disabled).Clip() + res := ReviewCommentResult{Element: card} + card.Children(func() { + ui.Row(c).AlignItems(ui.Center).Gap(u*2).Padding(u*2, u*3).Background(k.Background).FontSize(small).Children(func() { + ui.Icon(c, icons.Must("message-square")).Size(14, 14).TextColor(k.TextMuted) + ui.Text(c, fmt.Sprintf("%s:%d", thread.File, thread.Line)).Font(theme.MonoFont).SingleLine().Grow(1).MinWidth(0) + if thread.Resolved { + ui.Row(c).AlignItems(ui.Center).Gap(u).TextColor(k.Success).Children(func() { + ui.Icon(c, icons.Must("circle-check")).Size(14, 14) + ui.Text(c, msg(c, "review_comment.resolved")).FontWeight(600) + }) + } + }) + for i, m := range thread.Messages { + ui.Column(c).Gap(u).Padding(u*3, u*4).Children(func() { + if i > 0 { + ui.Box(c).Height(1).Background(k.Border).Margin(0, 0, u*2, 0).Role(ui.RoleNone) + } + ui.Row(c).AlignItems(ui.Center).Gap(u * 2).Children(func() { + Avatar(c, m.Author, AvatarOptions{Size: 20}) + ui.Text(c, m.Author).FontWeight(600).SingleLine() + ui.Text(c, m.When.Format(layout)).FontSize(small).TextColor(k.TextMuted).FontFeatures("tnum") + }) + ui.Text(c, m.Body) + }) + } + ui.Box(c).Height(1).Background(k.Border).Role(ui.RoleNone) + ui.Column(c).Gap(u * 2).Padding(u * 3).AlignItems(ui.Stretch).Children(func() { + if !thread.Resolved { + in := TextArea(c, draft, TextAreaOptions{Placeholder: msg(c, "review_comment.placeholder"), Label: msg(c, "review_comment.field"), + MinHeight: 56, MaxHeight: 160, Disabled: opts.Disabled}) + send := in.Submitted() + ui.Row(c).Gap(u * 2).Justify(ui.End).Children(func() { + if Button(c, msg(c, "review_comment.resolve"), ButtonOptions{Variant: Secondary, Icon: icons.Must("check"), Disabled: opts.Disabled}).Clicked() { + res.resolved = true + } + if Button(c, msg(c, "review_comment.reply"), ButtonOptions{Icon: icons.Must("reply"), Disabled: opts.Disabled || strings.TrimSpace(*draft) == ""}).Clicked() { + send = true + } + }) + if send && !card.IsDisabled() && strings.TrimSpace(*draft) != "" { + res.reply, *draft = strings.TrimSpace(*draft), "" + } + return + } + ui.Row(c).Justify(ui.End).Children(func() { + if Button(c, msg(c, "review_comment.reopen"), ButtonOptions{Variant: Secondary, Icon: icons.Must("rotate-ccw"), Disabled: opts.Disabled}).Clicked() { + res.reopened = true + } + }) + }) + }) + if card.IsDisabled() { + res.resolved, res.reopened = false, false + } + switch { + case res.reply != "": + slog.Debug("mujica: review comment reply", "file", thread.File, "line", thread.Line) + case res.resolved: + slog.Debug("mujica: review comment resolve", "file", thread.File, "line", thread.Line) + case res.reopened: + slog.Debug("mujica: review comment reopen", "file", thread.File, "line", thread.Line) + } + return res +} diff --git a/review_comment_test.go b/review_comment_test.go new file mode 100644 index 0000000..f2b8711 --- /dev/null +++ b/review_comment_test.go @@ -0,0 +1,97 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func reviewSample() ReviewThread { + return ReviewThread{File: "commit_graph.go", Line: 88, Messages: []ReviewMessage{ + {Author: "Uika", When: gitTestTime, Body: "Should merge lanes reuse the parent's color?"}, + {Author: "Sakiko", When: gitTestTime, Body: "Yes, the first parent keeps it."}, + }} +} + +func TestReviewCommentReplyResolveReopen(t *testing.T) { + thread := reviewSample() + draft := "" + var replies []string + resolves, reopens := 0, 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := ReviewComment(c, thread, &draft, ReviewCommentOptions{}) + if s, ok := r.Replied(); ok { + replies = append(replies, s) + } + if r.Resolved() { + resolves++ + thread.Resolved = true + } + if r.Reopened() { + reopens++ + thread.Resolved = false + } + }, 600, 500) + if !tt.HasText("commit_graph.go:88") || !tt.HasText("Yes, the first parent keeps it.") { + t.Fatalf("thread: %q", tt.Texts()) + } + _ = tt.Click("Reply") + if len(replies) != 0 { + t.Fatal("empty reply sent") + } + if err := tt.Click("Reply text"); err != nil { + t.Fatal(err) + } + tt.Type(" Agreed. ") + tt.Key(ui.Cmd, ui.KeyEnter) + if len(replies) != 1 || replies[0] != "Agreed." || draft != "" { + t.Fatalf("replies %q draft %q", replies, draft) + } + _ = tt.Click("Resolve") + if resolves != 1 || !tt.HasText("Resolved") || tt.HasText("Reply text") { + t.Fatalf("resolve: %d %q", resolves, tt.Texts()) + } + _ = tt.Click("Reopen") + if reopens != 1 || !tt.HasText("Reply") { + t.Fatalf("reopen: %d", reopens) + } +} + +func TestReviewCommentDisabledAndInvalid(t *testing.T) { + draft := "Text" + acted := false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := ReviewComment(c, reviewSample(), &draft, ReviewCommentOptions{Disabled: true}) + _, replied := r.Replied() + acted = acted || replied || r.Resolved() + }, 600, 500) + _ = tt.Click("Resolve") + _ = tt.Click("Reply") + if acted || draft != "Text" { + t.Fatal("disabled thread acted") + } + for _, th := range []ReviewThread{{Line: 1, Messages: reviewSample().Messages}, {File: "a", Messages: reviewSample().Messages}, {File: "a", Line: 1}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%+v did not panic", th) + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + ReviewComment(c, th, &draft, ReviewCommentOptions{}) + }, 300, 100, 1) + }() + } +} + +func TestReviewCommentSnapshot(t *testing.T) { + snapshot(t, "review_comment", 560, 420, func(c *ui.Context) { + draft := ui.Local(c.Root(), "draft", func() string { return "" }) + ui.Column(c).Padding(16).Children(func() { + ReviewComment(c, reviewSample(), draft, ReviewCommentOptions{}) + }) + }) +} diff --git a/stash_list.go b/stash_list.go new file mode 100644 index 0000000..f505ca0 --- /dev/null +++ b/stash_list.go @@ -0,0 +1,58 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// Stash is one stash entry. +type Stash struct { + // Ref names the entry, as stash@{0}. + Ref string + Message string + Branch string +} + +// StashListOptions configure a StashList. +type StashListOptions struct { + // Status and Error show the load state. + Status DataStatus + Error string +} + +// StashList shows stashes with apply, pop and drop actions. +func StashList(c *ui.Context, s *ListState[string], stashes []Stash, opts StashListOptions) GitListResult { + var r GitListResult + k := Tokens(c) + actions := []GitAction{ + {ID: "apply", Label: msg(c, "stash_list.apply"), Icon: "check"}, + {ID: "pop", Label: msg(c, "stash_list.pop"), Icon: "upload"}, + {ID: "drop", Label: msg(c, "stash_list.drop"), Icon: "trash-2"}, + } + v := List(c, s, len(stashes), ListOptions[string]{ + Key: func(i int) string { return stashListKey(stashes[i]) }, + Label: func(i int) string { return stashes[i].Message }, + Status: opts.Status, Error: opts.Error, Empty: msg(c, "stash_list.empty"), + }, func(i int) { + st := stashes[i] + small := FontSize(c, theme.CaptionSize) + ui.Icon(c, icons.Must("archive")).Size(14, 14).Shrink(0).TextColor(k.TextMuted) + ui.Text(c, st.Ref).Font(theme.MonoFont).FontSize(small).TextColor(k.AccentText).Shrink(0) + ui.Text(c, st.Message).SingleLine().Grow(1).MinWidth(0) + if st.Branch != "" { + ui.Text(c, st.Branch).FontSize(small).TextColor(k.TextMuted).SingleLine().MaxWidth(140).Shrink(0) + } + gitRowActions(c, actions, st.Ref, &r) + }) + r.Element, r.changed, r.submitted = v.Element, v.Changed(), v.Submitted() + return r +} + +func stashListKey(s Stash) string { + if s.Ref == "" { + panic("mujica: Stash needs a Ref") + } + return s.Ref +} diff --git a/stash_list_test.go b/stash_list_test.go new file mode 100644 index 0000000..fd76dd0 --- /dev/null +++ b/stash_list_test.go @@ -0,0 +1,72 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func stashSample() []Stash { + return []Stash{ + {Ref: "stash@{0}", Message: "WIP on main: graph lanes", Branch: "main"}, + {Ref: "stash@{1}", Message: "Experiment with blame colors", Branch: "fix/blame"}, + } +} + +func TestStashListActions(t *testing.T) { + var s ListState[string] + var acted [][2]string + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := StashList(c, &s, stashSample(), StashListOptions{}) + r.Element.Height(200) + if a, item, ok := r.Action(); ok { + acted = append(acted, [2]string{a, item}) + } + }, 700, 240) + r, _ := tt.Find("Experiment with blame colors") + y := r.Y + r.H/2 + // Apply, Pop and Drop sit at the right end, 28 DIPs each. + for _, x := range []float32{700 - 90, 700 - 60, 700 - 30} { + tt.ClickAt(x, y) + } + want := [][2]string{{"apply", "stash@{1}"}, {"pop", "stash@{1}"}, {"drop", "stash@{1}"}} + if len(acted) != 3 || acted[0] != want[0] || acted[1] != want[1] || acted[2] != want[2] { + t.Fatalf("actions %q", acted) + } + for _, name := range []string{"Apply", "Pop", "Drop"} { + if _, ok := tt.Find(name); !ok { + t.Errorf("no %s button", name) + } + } +} + +func TestStashListEmptyAndInvalid(t *testing.T) { + var s ListState[string] + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{Locale: ZhCN}) + StashList(c, &s, nil, StashListOptions{}) + }, 400, 200) + if !tt.HasText("没有贮藏") { + t.Fatalf("empty: %q", tt.Texts()) + } + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + var s ListState[string] + StashList(c, &s, []Stash{{Message: "x"}}, StashListOptions{}).Element.Height(100) + }, 300, 120, 1) +} + +func TestStashListSnapshot(t *testing.T) { + snapshot(t, "stash_list", 640, 140, func(c *ui.Context) { + s := ui.Local(c.Root(), "list", func() *ListState[string] { return &ListState[string]{} }) + ui.Column(c).Padding(16).Children(func() { + StashList(c, *s, stashSample(), StashListOptions{}).Element.Height(100) + }) + }) +} diff --git a/tag_list.go b/tag_list.go new file mode 100644 index 0000000..7e14756 --- /dev/null +++ b/tag_list.go @@ -0,0 +1,50 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// GitTag is a tag and the commit it names. +type GitTag struct { + Name string + Target string + // Annotation is the tag message; empty for a lightweight tag. + Annotation string +} + +// TagListOptions configure a TagList. +type TagListOptions struct { + Status DataStatus + Error string +} + +// TagList shows tags; Action "jump" carries the target hash. +func TagList(c *ui.Context, s *ListState[string], tags []GitTag, opts TagListOptions) GitListResult { + var r GitListResult + k := Tokens(c) + v := List(c, s, len(tags), ListOptions[string]{ + Key: func(i int) string { return tagListKey(tags[i]) }, + Label: func(i int) string { return tags[i].Name }, + Status: opts.Status, Error: opts.Error, Empty: msg(c, "tag_list.empty"), + }, func(i int) { + t := tags[i] + small := FontSize(c, theme.CaptionSize) + ui.Icon(c, icons.Must("tag")).Size(14, 14).Shrink(0).TextColor(k.TextMuted) + ui.Text(c, t.Name).FontWeight(600).SingleLine().Shrink(0).MaxWidth(200) + ui.Text(c, t.Annotation).FontSize(small).TextColor(k.TextMuted).SingleLine().Grow(1).MinWidth(0) + ui.Text(c, gitShortHash(t.Target)).Font(theme.MonoFont).FontSize(small).TextColor(k.AccentText).Shrink(0) + gitRowActions(c, []GitAction{{ID: "jump", Label: msg(c, "tag_list.jump"), Icon: "git-commit-horizontal"}}, t.Target, &r) + }) + r.Element, r.changed, r.submitted = v.Element, v.Changed(), v.Submitted() + return r +} + +func tagListKey(t GitTag) string { + if t.Name == "" || t.Target == "" { + panic("mujica: GitTag needs a Name and a Target") + } + return t.Name +} diff --git a/tag_list_test.go b/tag_list_test.go new file mode 100644 index 0000000..5f4ada8 --- /dev/null +++ b/tag_list_test.go @@ -0,0 +1,64 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func tagSample() []GitTag { + return []GitTag{ + {Name: "v1.1.0", Target: gitTestHash(42), Annotation: "Five hundred components"}, + {Name: "v1.0.0", Target: gitTestHash(7)}, + } +} + +func TestTagListJumpAndSelect(t *testing.T) { + var s ListState[string] + jump := "" + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := TagList(c, &s, tagSample(), TagListOptions{}) + r.Element.Height(200) + if a, item, ok := r.Action(); ok && a == "jump" { + jump = item + } + }, 600, 240) + if !tt.HasText("Five hundred components") || !tt.HasText(gitShortHash(gitTestHash(42))) { + t.Fatalf("row: %q", tt.Texts()) + } + if err := tt.Click("v1.0.0"); err != nil { + t.Fatal(err) + } + if key, _ := s.Selected(); key != "v1.0.0" { + t.Fatalf("selected %q", key) + } + if err := tt.Click("Go to commit"); err != nil { + t.Fatal(err) + } + if jump != gitTestHash(42) { + t.Fatalf("jump %q", jump) + } +} + +func TestTagListInvalid(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + ui.Render(func(c *ui.Context) { + Use(c, Settings{}) + var s ListState[string] + TagList(c, &s, []GitTag{{Name: "v1"}}, TagListOptions{}).Element.Height(100) + }, 300, 120, 1) +} + +func TestTagListSnapshot(t *testing.T) { + snapshot(t, "tag_list", 600, 140, func(c *ui.Context) { + s := ui.Local(c.Root(), "list", func() *ListState[string] { return &ListState[string]{} }) + ui.Column(c).Padding(16).Children(func() { + TagList(c, *s, tagSample(), TagListOptions{}).Element.Height(100) + }) + }) +} diff --git a/testdata/snapshots/darwin/ansi_text-dark.png b/testdata/snapshots/darwin/ansi_text-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..0f36ef05500c59af98566a623b9e7866866c8837 GIT binary patch literal 20216 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/ansi_text-light.png b/testdata/snapshots/darwin/ansi_text-light.png new file mode 100644 index 0000000000000000000000000000000000000000..a6c5d94cd6a22d6c80665185eba3b4f9d26652a6 GIT binary patch literal 19973 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

    80)xTpMeF7|pCZ`H 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 Dm)9yE literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/blame_view-light.png b/testdata/snapshots/darwin/blame_view-light.png new file mode 100644 index 0000000000000000000000000000000000000000..5c64377712ab649b2ae6c639d64eaca553373d13 GIT binary patch literal 22795 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/branch_list-light.png b/testdata/snapshots/darwin/branch_list-light.png new file mode 100644 index 0000000000000000000000000000000000000000..3019690cf2195674f8bc392a75e2affef3fc2869 GIT binary patch literal 17219 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%0AM4MR7IAXd?#fZ3zTZZAr-&S$`NGeGC=)*( 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 o58;$H7h>CF?*EC2NkGHy)>oqW}N^ literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/branch_selector-light.png b/testdata/snapshots/darwin/branch_selector-light.png new file mode 100644 index 0000000000000000000000000000000000000000..bd8ae7c2e5aea4b24a83a7ff6dd6bcedd71867d6 GIT binary patch literal 15585 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/changes_list-dark.png b/testdata/snapshots/darwin/changes_list-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..4225ab63fc4aa37eb27bbf41a474d6b7ec1fe575 GIT binary patch literal 16290 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/changes_list-light.png b/testdata/snapshots/darwin/changes_list-light.png new file mode 100644 index 0000000000000000000000000000000000000000..e7964854735dd08a6f1d9a8d0c5fbeabafd3aee9 GIT binary patch literal 15959 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 J1kexs-vCcNx_bZs literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/command_block-dark.png b/testdata/snapshots/darwin/command_block-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..892e54a68c5a4afd2352db68aeeb3729e6591e10 GIT binary patch literal 22032 zcmdRVRd5{5y5vZfEM~Hp!D42%n3=(1W@cuxn3`X^@Peo(ZSNUaT)kG-Bi6g+`zybgO1W5@IB>({28UO&Jg$4(eT#LI00RXCtk|IJX z?pbHq9vVseIANQ1X^;>B*uM;x!bC+y9KJyI{alk!um@w~!OSZ!wwP1ZU6}5ekX%Kl zo0ee}nWY+5vX_mM87QF*gbNJEAsVWH|1!quRAb;iAIT`FaOWoQIrhrC={*v?d)_%l zs%>m42f8(2%0c4}j0`qHxZoGn|CgI1fmEtY{v!Z5sgW`%nhzfzVrDP$Uq<-qf8GxG zwOOm0LL^^hXb&OTWq#hJxoO4*72_LrW@g&(-c95R_5OM%T@M%pcz__0rwJo`@3aB# z32qwP7&I~dy?I!wlWdHPv7?8HZj5kwu#kbmH}tO|LIzVCRto3FO`7FpRh98pxemSULUYh<{u(3ZVb>fK34{e&(-X|HYNO&8on^ zPG5l`NIl*AIk0E@!$K;wt3LjKNKpbE zHAIAXno_?2p0ufTE7R&_eQvFao`ITt@=6`dL+65rCM7)B)W#R1uByxM{N<>|%ULY% z6JoR8**W)mGG_g0K6X=j)EpdincSZdE6bX<&tjUI9;{%$S;7*-qRhex^^KL3)g+;} zqhzc`Dtw~^6o0wq=-pUv@BO4i&8XJwIbMlD&9LfUSh-ops9jms*vG=0)}g$h$1>8$8~-6-s4dWwm#8MTL(3 zd@Bv>k6b6fXuQ7#d&f7g!8Q11I=?#Fs|TGA10WE{$xn!gD$$jg*g$_!wBAdtkJq<_ zeLWI(eCQLM<^4f^S23~0=$QBWZ&K_BrjM^a{zPx-4?OnHxEuofX0WLK6El*Z^#lRv zO_gnaY-Q}v*P-M6i+-gM6TJ)5!`zDl0?Gv~eQ$c6PR~1x((zp5e3dMU-SNJA1-}Dg zQ-XiB#Yh)hV72z)D^n#kZJ-5@!CPBfzdUa#X1E7lEPNqG{^r;ALO01osx3xFzCZR_ zDNtQw`>v0uLal0GP(RhB?;>l1^j0+SjxQ?Q82ly70^ENvIx%dtZkRxzW?ePIFZ&?8 zpq^`&(qg#S>d)m^r>b{j;;mw6dK2eU0qfx&hvY%5ny^++G=&Z4Advw_Tn#;%1 z?BRlB+hxLeTVwu}cg68d2}=y(zEvX?sh8#S*%I0;0k`=Tm!>5v@)M#KI_mC^pQVDK z250BiH99~sG{4bG2Kg4$^u9AL6!ujH(@6#tCvrBI`_2bR3m|10w~L|fdbT)ukhoVX z!OwGXn)OgbZdYC|K2onIM)l9(Zo(>0r{mMhX>J((Z<2(rukzdzqlFb66qknlvVbcM zgKv|_J$LUjPzV)V8-EQlSD>YDYfCRvJwu-`iu8}hKFYL!@An9i6fr+(p;qAIqu(k; zC~31QdKV(RcvcE}V#s*&SU+Fp&%m|1;*7IWf!XIBM>fqat-XgK6B!S0pdU?TFx~aj zXU74Xm+~@vnHan#GhLcO>C5e~`-SN>S8Z!<>a0BPyuSk}BBaAW<3cs)NgVa9`mG^r$ z$e^?h)Hdc>xYYlez7jm^$5!P>^jp?aqV+OLV@{?%dE$OMGBY`3V`s=Iugv9_d;iO}L@K@w3yE)WYB* zYwP<5Dh-XI(Drg@sRz@*8n+ z0*rb)=SNgEZK}=umZ!&?%tv&qg0wBzT!urfUcPVE>zL=Y zS__3Ja$k2UKd)R)ov&hIbf6I4z8`_$MDf zozBzeVix*ROVj!bA$~jpj-62s#H!DWjcR9v7Y(GA&*xh{RSxP3TNU^#yfweEEp~D( zC0D1z4MNzcNEqVh5K-HjAoF63-tMm!W{vV683jt^N-Pas;&D5-G1RuI)7;aSg^z|u zcLDGCnHd?y-;bfSu==Dn4>4~j=)qZfE{CQW@I&StVkSb=j zbQ*)^Sp1a-C<*zM=Z|7rqnK$#V5uN1;pv*+nOWGg$#{OXcqctvj%87g@NvIWb(MN} z$HpolJL*ihkNJ)9&x+KX67gt?STK+^b96t4JDGWC`54q9ggYlPxr^*vT!+Oob3AUw z&CRXFGb-h*Y#fiM76zWbJ~QoTXXf|G@wpAGtnRNfk{{V2d-Zep_?AA8>i3FzDNCND zQ|J)9Kv98`uG#*Iib^N)mn&b0r9}RFhv&PBqos`vK5^f`fG|~8Pn;n`3lkgDv@g7M z6&>lOdr0qoNl{L713H}-U6$TFJ9xM0FgXiND#ei1sM-X)W|<0gW@aW@Vl1Hyub#3p zC8qXg?_xF0_U>_wQn_4d_CLVR;_W0Pt65y2$P$HfAka};9>0+Hl_C_XaHsjSgUuv) zg|rii*;gnpxp94X=|?|TNWv8$3XJ_Q*5nB1$Rk9mO1F=m-xgcov*LN|=Jn>~NRP*@ znCQOiE%t0_A=h&BB1+b4HL|kW%xok|Dn^vTCMSD%0%-rC6mXgcwmazY>KXTZ8g{f2 zlYrm3t4cktbu?t~!*;X0wyGjuRQBoFJ;KJOJ9gcPh*RdwG>#b6VJ%oUA_O=|x6XjE#FDpIx^6 zOB;jh)cvM?7WGC3(}JPjjXtoeeEGBtL_t-*m#br^~G~Jl)=zk3k{7T+RFUbWO{2+yJmcvv-cqfE)ckO%b-sj z+}4gjPe-@e@~++9b!}~W0lW`(y?FTfmJ59Kw>nwb1^C)xN`N;MiI6DUZ$luUmWxz- zHH$XUS>_g7+En(hXxZ!oOWQhV7l2x?5ZaYWr%oi$U&Co3zYOIB{y`Q)6~pw%C0j#Q z3+6m&{M_uxWp8iiAhX!=y5u^{sq`BiUyc_m+KNMOE5_k;pHGyW#<0w`b?)Pj3XD`b$e1#K9sY_xnbrviFURvrARN$*SJ% zIu37r7QqUBaJTtC);yovvGGabhYVxoC&v<4*>^^Xeqm9uBYx>RY|z5VRHdG8Kks3U z@_Z{m4Tn&_%+Crx#n2=NEpmlxS%Yor`^keJ&K?sTqVz`V9`(maj#4iAD)n{wu?%=* z$*Jo!GoJ-Y)nh2a9fWhVmIay_r=LXc1;2(zQy`|wOxgZwofBKMV)KkRF-Lja+-cI4 zbtsI#G`F-+qemWb%IT0iav{ku>DbcC5fgTalQe6WC{R7%d2{=D=s}CP#C|yKQl7MQ zuM6BMDcpA_=NTNvDHe)z+CA^dQig#M(;RB0W$H$p*AIG45rs81!N*G!Y_w?o%1*Si z6c&P>HlI^JvnC~(w9*D|Y`ld4-~P#A=H1CZINz^WuHxHh71g0FGFxSkX9K(Sk&%&`ZUm95^DA_kYif#AE9iOZ&;~d1ylf zKW65xt*Vb&jFlt1L@}LqX4a4^X3PEz3TzYx#aK%z=3e~0v=25mu#zN6T)Lbv?cvdG z1k9_!A`6Fn=b9Hyu5IJ8pB&ge#ffZF3r1#cEQ+w2lT}cW&S-1Nzm;;AG-;R=ZhdTJ z^yB&YCo->JyTva`V1__Ev{zt54?WlY)iqU7l&LjACma9A0z_+*1e)^9#JflTRT)XS zOodJL`2*nYSj|IpKR&T^*fV?tBl0FvY7_zOtf|U0U+d3nBqC|!>=^BY&%*e3C zX(Xrn6PBLZ#VMRw>>~kR$arLg?348_yLV@|$>wz89zE&ez9W~fvaaM>Q;iQO$m?w$ z6NSafdRONz42Xh_fk(r&wd$WKv7o9Rm4(x52O~yru-%`@_@i1{7M_0H4-tzXjyY@Py*B1Zh4hl;yY!F(h!;S2W)%JzW;3 zhu9cNvH3M0We~SDn3gYQMPv<`d%N)J`W`pQc0Sm`(-k~iM0ZqV*rH^!#ptSC6H(UY z36UMxD+_q~wZ}9k*R}izsy6Y9LJCSfz(mh}-bL-M;tRytj=g+bUD03x4vb}TRX4o} zon*_r{jpV2PQY3;j7QsEal`wt@V#kh12>iPuL<8mpJffzRIdfztt-pRC7*I^to`)Q zPnoW)`BasiSS&BrW7L*CP3DP&7h%UkLGQUUqg+IW9#gTkS`^gzhj7q9=6 zhan*Mi@iC?7+nVbsGMe%q#AKTk&wHr$#=2&h3GBYouYHC8lO}kS` zh%ZJ$e7dgYuzZgb60tK4vB&(Y(CfoRn$O)4`+}Dr zZ;9~G`22TDN_|Rm`AJieBWE5YHxBTCp`TNfJ=}`4DMz87WMn0@aIi}cmy?8i71Q0y zg}sLYkx_>)@;UAgW7AfPy8~Wv28>6Gg}d6?+LB~5==-EEU?c{Ki%-&_!TCSJ zNC!#I&a6SH98QOo;da9(q9{Imvb)~LtSthj-);s%K)_U1_WZ)`fs*W@g68^aS{WYd zRg+~I4r^?WtjK)%^?47w1Gt{GtUTxymomI}IHAw&rMLdIK!v*3H8`vaVWZ2UTB>+t zXl#Mt6~~vI^zVb2jYf}_Q*Y||rM89&PMdM^0SY>XOaJ<~$AV0YaQ@S+;hoj&TT^Gu z%jZIu3L61zztIC#uj`v2MWROcu7F0fOu5QHzf)`Ix#Hug#+2*%Qgm&ItLT3V(|6^-^%#i2zEtpKz=^eSg+~I@zj?8s^gw|eOXMLI_-&6jWU7BYWvTT5ML~3AND;9A z%bPm}vAMKiOwfyNas2zW&*2JuvN2%(@lJnX34mJgDsw6eZoK{9SFh2TPXB(+|NW=? zfAYrVMBG39V>ZbMN#es9%%du!5?dF|-!>XyLk-Y;y72Lip1_A@hd!4&QQgZr9{n!H zmc|tdXpMfc2}?*Vmrr#oXi?co&Xjm2KHRies(a3_-l#RrP!H3Opf-q;GqqR;8I0Y0 zuC>#n{t&hM)PH<^ngdQcU9?XEolLtQc@McBf09MUQ;8LPi}=_f}|#h0Uz=x||L-OZ+O=*~lm;YU;`dySqOy ze2j*WnOxXR!1E6wH;AEyIeGwnkR4(Fad|_~eU9AX%a#kuVOOXHc4dNS_xF=?ttY^@iltfF?b0t%xfm)q?TaF5aT%(naHn13^aP4!RQqiB2&%&>I^ws*PlLceg0ry zLNC7tq@pC+#jn4{UTnCbub&3bqPjUdAzwe7^PokgA8kDT?DgbeNrVxP&8B0h)oC!_ zcxk3#+1%@vkP$oQ+p6{1c=22rl!Nf5{jPh&`8qjn)zEO8pgglb+z^IzF*iSLZCld2 z?jZb#+?sw2p^HDRY(`(FVXg9Sbzp8s1}j8?xKJUcRb;S(aVdp%DF&2g5VSep!a_~! zG$}`x+*^5YqLaO|UC8yfaAl{_!BSOIwTe~h@n&-`xaNe6)Yy&{h7|_ zd&WJ95gB;6cDQ%mE0@!}L7;=!u0|hX(^R zF@5{`!cCe?)g`GS6yW`O(d*w+3l88Tm`yER$R#=6dI#SZWCB{o7Egoxr>h<8`rUq-(+0$cA^#5(w;C$pjJj~$K zkauh{XlXGK>B12sV4Cz=h9=jXgN6&po&00go)v27{&UFhZ{E;SPQ{6YkdP2}cK3u6 zh^VJx7uj_gfh7F-5qY8&#YiVH? zCj9-9vCF9PrY2u(00iWe=hwQ)q%X z+~WL`F@!OSuC4w&0ASTZj>i>$$2PG3r32t!P=EyRFDrW*Zi#if;5T;LmA}YME{-^$ zYVKjsBSjH4n`}D&=7(>U*J%;t<>T{1a7z_3a!qLSyr6(YA1~rwq&|mg0j=M&pvO$! zd9H{lnXoLiB?}y2EJ9Yx3zVE!XnfOs1rX%;=eEvks;Tn3Z-yjfJst^tA}n~F*JT^F zyF`_?#?@|XtY@zRCCErD&%ojc#GRduDOb}9EvFV1T-mpnneEH+Ya%NQ>g(C}4-Z${ zEEanQCyAiB-43Rf>WymNyx;%|S1sn3zCE~qh-ooTmA|_*E?TP2$3sGj9_8~9G4wDp z^dJMK{`76qk&yf?XXuUh&g~VS?DEo&)_U|Hi+0f9@QbPbx5TmOtuMQ&$ zXPgq)Cqs=GHy!M84{-)l@30f5BO+(}p`o$lcBy7@yxm(&W?;DM%HbE=)YRnu`lLj) z_nrMf4|h$#uLg+q0>SnGi=B>gIDrT9CUqNKwR4TKluI?rDq`0Ty`nc}0#8;@&@zvX zw>|G?j^~=j(w6%2w!CGTMz_ z3zj`$YM6-%qrU}(0OgU*`dEBstNju{xZeq=GZQF96 z`Mv(L8tl^aoygEoze;bv!EbWmD%>2GhJ~2;&q{ZR4=OYSu9Y%$AUek0wR=`}H3oo) zkF>KX2?s5+&2^m6%hi^kIG_6a_iawUgY?Ev0DajUtdCE&$pqY$` zqJ2eAO%Xs#Y4oSqJ`NlS5yE zJ2P*KY5p8zYnqmzY0$b#S$@^RBvp(SVM6VfxZ|LhzWS{IW*`&;!@YuOWRZJHm zD?uh!M9dsF=>1|LYT;4as~=mBor<0Q_Wkk)QZqbr8ZBlb3>s46uyNxuC_sme|9&=T zq}w^#L992nHtHR=lTem!c^GF!MxuJ^@H|02P0MQZN%R?sKjeA+zPz#p{EpQP3$zP4 zH~_A9pKf6?#IaST&YH&{5rlp^afNHcKIL}q?E-yADdI{>4u*!@LAe-_{*H&B&NDfx zGt=q*FymC{5tCsK3WUm|+xGC3GB)OU`IMJfDYZI&Z$}&CQHNgu z-=bSq-3W3xF~V_#RGj~QTc56--E?N8dTaS^Yo_ItlyN}CCUU!_=&mC3mkL4kk}k*m z`_{!*d4z%#^^Nw&vQ-2qK;5*#+--omY7)lbM2nl=&eishVHAPS1bGv4P55t&Kc6tb zKw3qx^%ato4p>yh>U_EC-@6MD40+sSs&f4a4-Wq3&f85B1puI9>_0y}Nr+4%oURQV zSz>>awY5B1gcL?5`~F=~TYGb1Vc{G+LS(w6#FRY~K?wP9RFh<9$I!*)KKu0xf`bDS z6KZ|5)^)QwCtmFM1*zT9V8GyR7$S!FO9|*XeqXU%<3l_qdKL^3X7+!4j^+)`$vZcq zE!I3q!{dXuwYeXQ31FjN1UhjJ&BfLV{b*F`WTFE6RKP|r?`c(jgZR4NO%)%)L^Y82 zEyxi5 zzC_33=kFFs;UOMvY-(xws@D~(ZB{!?u?K{~k7$AY3oSIr)R#sC((3eWRb=|gw zdnhR~4Ptjrw=bQ21Q8-+i6$fE|1joPx4zb4chWBy7{xT|b_J2HM1(@EUK{s5s+(?H zUm(4-tzbnF?NMHc&Soi3;xd|qS>KxYBX_;i<91#q@zKWbCkhbuuXkc-KEVU7 zsGsjk=)6W~s1;uY1N#lJ(9tF1e!XNMdfmwy9{mdPdzQ&C?_2+J4a30k+3xncd~U`t z0a$&%NY>%A>RAfuG)8NtIJ$ZnIvdEvu+Uf1Qc`;dn9iirmsiyS1?BlIt}#~DIwb#*QC?0H%t7wv{GJEE-^Q=TB~1WL z6$$fTtf8{f?&#r`?_2Y>Jtv7`Q+GF*>K!aj%t7NV03wh0M<08YlNT!HGYJzm;8#{g zEG9PNCgR7w5wnAL-|f;!U zn4@k>U0d7UprmuuBR}9bsIv<#PULs^u3O45KIf+93Ke)QXfDnki8J)cH!A3}8jV%p z6E~GC_{DMSbY;J=)(GlLFSz6cWHo7gbXJ(bh|2G-U`_LOdJWX&lK}jG92y5RATx5L7W=xyqIeN9a_@!o>~ zSit8-`ztbE6A$9kOZ37F(dcm9@|pN!Ef_#aX%@s&;oCGi`V2zfjT^eGeSNq4r8!6n zcfhcelzP|JbtrIfcdnm`Qp*SBb85@VP8!+q5FejD*hED=KAk?Dbt8(!n_8G{*F#fz z6B83R>L%#;NKX&W8MsTn>}TFVe|J*e<#8kQwEKhu*pqSwlQ5LlmdcVuvQOa@i%Zz7 z@03?p4{zHuvot;uaw=+S($Ujndei0A9Ra&@CQhTP+(Zcv##-bhWgk}>R##@6Lrx1u zDlEqpPf}~Y%Ci!b3dX~AxxeR*3V|4OYY@1@n(8KQW`^0McBr0IZFh`{5+feZ!A?rrX-}s)mjXOJ-)u;?a}0KTq-@5eoF~USHTwET~b4 zkT5YZaXqP-iHA4U{YRe^2h6202T7z0XWqjNV7n7jB zkdM@l*SoQv`F`c9e^>D>O5N+>`Px=x7yh1iEw#Kn*84M`jHA_wPnWhHTAKEy8Z9d0 z7#^s|e3f`ch27AUmXT1@70s!sRn^fVX&8Q0Z{td)7|aHOnjoJ z07PtbXw|sxHXF?#+|V*Y6A;+kkD|1x8i$3AjEvlnZ(-_jyhaZY+&Vl2oop3HkgTs@ zZeYsmm7;5_7towsUK6|Ui`cNDf)o-G^4R$WB-lZ->o#UOEccb51GTiV^O61vUxdxi zEr8-raB^Uk!yP7|W;C^vfsu?7pRoie45L>{^{}O?nO& zco1BST3VeJ7NS+r%067)+xC3^6-I~k7(dyE04JuQnH1DNJUb3bNI*T}<|=Z@p^4n^ zdD2j_WF9u($g&t(af+Y5HbQWgBx`%m%#b5OhL-Ow{8gH@L0`(T`K>zoC@r`zwH)C8 z)+#!boT4-e2KcM98E(Eyi6Z(Py`ip-@dh1Z%TL2Ic&?BVr8f-ecD++oGCnY;!tCnm z+(`0xw@zZOwxA(Hn3(08O&9L`)pmlJJmK8ptfZXe;I0E4o>_jf0iR+O<%`#&h!ZT0 z&G_7vdsaq*u{N%>tfZ1icw8@-hp4J>ptm^qE~>s?RfPp?%uqXFU7us%O;0`ulu#HV zEl;#DWoEZYx3Ij{i(0+wnbqe;-8$v?!#Z)s;Y*J@e)I)fp7v-7Mp;epeHZ%N})4G~$_8l2A~vO2P^2 zod$vE6X&h0?IU#u^bC-Nd8Tw42kG_s%M`X$7I%L^dpf^UEKATdrl-J}+SFzV#cn(V zf)8Kz40FY2yR@_CXyx7_S%P_Pvjb^UjQHEz{eb!B6Y?eCh28p_OhL2m#ThdKF15+@_=_A^mpU* zZ28sCICK zbi5Nzr8sfA{<>Tb+}na&A^E=~@y_`m7z*A%3L>K7Kj;p57Ws5a1pq*?RJy#JmWds< zfz;T-Y-4R5>30q5Yi?zAdhY1{5|VrUETXl0!_et-v(eAEY`4h|7n zS$DUkt>@=e@;L_>!&}?hdcFpF{9UGXRaJMwgPI_v3v%$TY*j+P8i|MmBjIs}(AIiw zUmBrN-o1NA|3m+JAR|z(I58k$BBR|kbOJhN82Q0#+NxS2Cd><1m~Tf)HOolHU>^&D zpQmdkA#%R6C>}Lg-WZD*Oyd&C?ZMA-#)vChnL%GG`%!g z;=FPD7XfA{O!U(Ds;WuIsC0#DM03)`DT@n#aUpE;68a5Q)znB!m@PeIZTKLBg1d8K z+yU1%^|NbC9a^09!k1w#(KH|vQGBplaP)6NLIyD{?OCT=Wz*f&wo<~{0?pdAXD)wK z=;s$AUJ}n;PmV}$FISqVeprwphbOmk$^kNpxg}cL(``*GP#;)lj0+S&lq$AHJNKs9 zZZn{v;Ra-AJUf+w95iS+I0sHV6qN0YkZwf?h$ngcO(daThc7nxG%ybfWqbSEW`$Sb zX%D7Xv|sPkw6yPmB>W^NK>hDiGz z(1>A1dHP+wR8Ee!=`sgn*viLuDIk4j9;2kJsOEi30Y&#T4lblXT3x?qWHCHA zv$K-`qT{a7iy#HpW|*vQs1!NP`JOoVNcgxKMR1qM=-*AeZOf-irvla_9+x5D){&P7 zK!j@T#k{}|<oaQWrqk-sQXagUN#3$e^xN4}o!`}g(r_gtY}7o@zo zpC=|Vx}b}ovhumB{T4dzZ5(-VgyeVY2M(2`%(J^?PN^UBR-+d+FhC$1^&X~6)z{Da zhARzu^wWrs5ep!p@UbQE6pe9Ub^#D|^k8r^5rblmoQO5Pl($k^UZrTIleC4%^<=1_AhK zYpbLCj;-m$(~~zeGD1c}!$9{Q)7F+25O7gGi#4_D9?-iDk53(Y(OlTjkU`7fbyVgD zB03O4Xal$kDNUjaIi3m01J!J z9rQmI$vaRIJ>ux3EDqWub9QM?OSn2Q6-C^$K$OtR9(j*fn}Ma)d)pabCl$(1^hUu1 zmRG5`hU`1_*k^fHen$%on=cD39YuR5mwpFoR!+Q$DR)4>A*m)A1o)qU6_7U$3F*O0 z5cY;xVrHD0qGYs-ip4nw&*^kD0Tc%@0CDQ?&SW&ErU&M+N~1$#NUhH)u+fPYLi@ zO|06T0Nc!h>3I4b#JyYrS-l3j2bUF%aucUu==P#V4QQ^c zz22FB#kN3iy%8BXIXabnOGZFI&96EIQBhTpJ%+R?W>IFl*^*yUa-nSTT!pQ?ZO_!a zvtP+d5JOE)m)LLUVFQA-0{GN~Ce}+b_kYF7x+H5WvhRRMI18u`Yb9u?z{e4Zkpo%S zRI)fkNB_7wk5xX-H_PG+6(P_Myl7p0i+H4FaUU4HPgVc%GeHoxZpv^-EH}UOe{V3^ z3qwS>pA8W-p@*1 zKiH#9?In|t5EzX#8mLWaF?sm6_Xoy1x8BZ8JEBfIg1Y&oG5zP#Rd@QYflql24M&4-Q?-_eF)X?yr8D7@1$aaLEgCezr-xhaH{lma67SieKgMy@c^Dkb z&GYy?->hGnhSzb(DAL|6!T;S-Y_c68gb*Mk2n*8EN=Js^%(|>95(xa4^;cW*(gIHe zvXTb|N@@gL1)w=ULj;f5_kIu|7m<;Jx=7E*ykLVLE^g+FJ}$HOsOh8C?>2dCjZF|w zBPRzPP{AGgl}AKF1A1FUg(>`KnuA19Mc7b6)B_Y*opwNwiDqMIY1+7qZ+AR9KMmjQ zyWs?se`+)b`9App3+nhmaAYXJRWnL@dbLGz<&Ga9rs04byD>9!UmO$!Mi3JzLNa3> z6XfYC!+5ON9kk`EB%jpExU$kC8uVTbqO_YMc>sR`KPz7m5W#8Pv@H@38GC%f0V<-$ zt+eSr1Q<+#Jyw^OV`FQ5;0T2AdpwC1vdz3mtzLx2-spcGIdNuvW(oC_$Zu44kVf+^ z;SCfjzQb}Lj8617IQiwD>42=C>OD|*E@#2|MfM&3OXR1~<%MhF*Dsui%3{mZt0S;G zU3Rpj8oHymuent}kcQF3ZWr7Ny3zRNE=7uaEr8v=w-35b z|tYJIlYyOl^;>ye_zoTVP$BEdhSPKkVu$YZMgN&v-Z1Z$XS_Q zK5Ke@j;j#AXC5z^wSb=Q{n0!arq9CCXx89>PEI*odA9$2c6MT`>)n0%@SUC`vvbON`y5jR>^RE&Y-Ajj5YcG-Ys8c(Ih06snJ6%iN}EQ-Bs|J6fP1P%>$Q6Uv7g>7o6Z(5yiE{}>LoBz z;Q?L2!Jl|caEWG@;@OXW8=QpX$Fr4J_vGR1L9~t?;_&;rQ_dmpqyC5R8+gfkkj3ZE z6@jz|r2pFP>mca(uLwA-=2M}JsPUYV@?j!m1{i$y9&2XB@bqzEs?jjIHXR9p;A-Fy z;Cezi2?;st{o6lX6h!jFg;7FCU`6jfB}E)K*OFjZ=}b%jfX4i72N#UBEszHGB_p|B zjroIPSrKG=RcSDPzDCIHihqBTcDTa`M{~c;YqpSYR7z86RR>E|U?(rKzh^u?9@EeW z$B9R;_E`HvJglaSDmPa@TGbn{8``^FRgw-;UFwTpRxwcxQVB#WHkejbMNk z73#(Sd{0W^YXg)8NM_E&J7?B86}Pj`#;yX`%2T0Cxzz@T?AVlp#6uH}bt;Ft*70Em zUTj~KN|dQ*UTs`rH7-+?8|(w^1%@IqJMCkFCRC;8H_ z%c^kg(i`uq{*Nxi%UkZQ$&bZfOK)8^aKON9oq9b|(}IeOck#sf8Eru|wNT-dUMV|& z5t4*`(sioi%3H+ zvjqqElh8G;{NdV{9Ihnkm{@k%A6v$Vi4lPTSL1-DNqv@x5AQ@I*uIT#2BX0ocY}*+ zi>@v?Sy|O`bKrFMmjB4sWGT_s&cGM&$}evx=bV}}+kSJxDy$;~YDw2;o)hp}!bL@1o37_c zbRuZRpB%9@k-*v6(W?h72+}E_y-h|a2OPlZcJNDq3Oz#PBiCnsc{v2%1vxh4g4#??v0N%t89_^H zb;oX<&*uOY@N!iQ(0mejsoy|VCC=NYVY5*vWkue zU&n!nM3kj#|LCf_Sp8OwG+a2*0`1mId|qc%D-Sv+(@Bk%Ij0#iUCc^;F0S37dZ(S- zyXCqsH?T*8T=rLee<7Xd=wxBsyBaeYKy4=ArNQf;jjucUwqPKRGv0Q5dU~<`zPmqK zKOx6*fA4a7f(x2jpOcXigYSrZFz)g+w%OXqy%@ie?T470efVMxQF z1t{2`y3PayQPzn;8z(u7qbf3(lz;)8%cu>6tb}WHApya(H;9}bO+_UyN~SB^W{cm^ z%;PHbv=UkKt*YG|G7E&fG*q9xyw_ON&eJCs`OW4(P@Q5(=X_eJQ?<>O_K@5Apg{8hDU`TmL8UF4uET^ih;?K6d7a}2P ze7Ht1wL$x1;9V6jn=17Jz6=Y?#DtfE!W}dKIoI7UzEj%|MO8T;1eh9kWql)mn}ERG z5q%C_e6!;zHV~lqqv>d3TL|b+4u5^op=TiHqq%s%KdZJgO~{FT`Smd^>B-$6muu)^ zR8ZJRW4svf@u66?-}@L5>B4#`G~F_en}m+>mAz-60X9dTV>b8Dd_x!9&n%hDjCTMB zYFk+#_xEH1 zC5_>K7gI7^U66h8uJ; z%=~eJkixGhH7QAq1SJSOwHoOI-Wd%o^;fETk!b1rW9CoN-eC)i<>zNnXp*gKcMe;M zfprOMOUvo`;y8yjW0NWQj^oq$1QA0|u^I~5-O>91jomFOs-e@q`I1;VDWAhnyjT-iT9nPJ z$CXKkxO^_ECuVv%gMmlj_j*qS1OD-7;+p{RH$CYUj;^}oSWf5iOpHvTZ*O0rsJPr% z%1V7PKiD1cd-&CD7Y?q@=A zF)A7gf%t&m(;IT?+NXWXL!HAG7q)WFD-dVZM)z?KuHTyLadG6ub@=fe($}ZL=VNG4 zcOT_r)(Y%QsTGU`9I`{@$T^%dV zg9E&GiS~{O{x`F403zy_uTiQ!_J4GE!7k4`E8252_f#~W?O)YP_x0l8d6 zrHLRtgx(Pal@10HdXXX}6pS1+_`t&-1q1FSabH-XU*AXueH8!efuyXw>W+`W5~&@H&C_$5pbE^^!WqW zq3Wq`s9bfmiJ^t?10(8MZB5BYKMl>C<5#Tf9y(|L=H3Xx%O!AeQh;Ksob;vq1X&BT zbSEv8pe63_aPUJI!@i`lxTc!!)S6B?toQb(I8)U+7ZsZGY68R(PckoI+R8yfd;3nugW z0+L)Sc}In(a<*5-eIp~?w?38!j2KdGaw;kYb(K)_c2dnGiln5OkyDY8D)sdtqM{>R zDQ>3Cx%kd7bX}dLjg3?FJ6x0(^;|Hcp1SYJu*WUOEKE!Sa{K#vz%bbYI&>Z$uN`d- zj2#-P0GfbCH%U!lnnRzw2x#PVUtnO?rEe}|m}2c0N^&;LHlowC_&x*T&IMkcx-v^{ zF!o7L_Uj8mw^9!XtI~^~9o$c}6uq>&2iut2dVdFZLJ5BE9G!q5)y?T0I-};xlPu!3 zle-sqzdsoWPqngsQ2+L)DOEF}x99oo_evpZW0x*wG0{BRCiX7)zYqFS1QSsckQWk? zl$7jS`I>ESCwVLIz@9cf7VqhEo7;bepu88`y&??f!%SZ8{Jfh03AXQi@oQb8iXCrU z+!a3G+twzQMn|L5;6}AzmVD(G%B%Eyn>@7zMA9c%Uktb(%IdD09_uo1Nr~e!$Hv-a zai?6WhWUJ~PX?!Y4lOUW`Zz9ndR)4jK*y&=uk)IQe*4S9f`jioMxXh~b$Pe#=qz3(q=G*$JQNbB#(*KX-k+#?Vj@$bkB#A2|_sd8Vc! zt(jTrX=%1%QD5c4dwC-q;9Wk>6uaph6aAaj>s>LUz5#9*Cq128tLkNI(bPt=XhbQ( zYin`W;owNDvmlwY8pcktn-2AF;#6tY%i3G)e}L5tKV{$H(~jRS-93z^qn)iPttu}p zD&3)ssAsnY*RM(S8$eBSt6VRy-afbzAa;BFs)Mh${d68wAT2Vq!;kVESa`PfSrLOF z?h4YiUj>|#<91%BnRmPb%AeWFIB0bZ0>=%G3AGC#j;>9cbw;Z5jh>k)JJCL%MljO~TS!U46X6FW{IEXylh z11%-MM3`_-suB4%F;@%k^s!R3yS|(6)*$XspKneSGTdF}RLrDT`+n+aQ|emTMKSKz zA;G(v0tTrWj>;Xr(ecVvL7Jp zEpM4#zr?gO%g%J~lpM9}Z6c|g;v<*R5QHklWVnZ%DM#7i!_b^B-t?o^G^4LJ?CBmJ zv~H~7ym($JDL2&e+95TuR%uUvqFLGWbwy}MDz)6wYWQB{@hcCvF^2J2SX6Ypt*sIz zQB@p&GW}IialG%KNR+dVYuHdPkbX1VBg>mrhrxv!h0oz-MpI9Eq!!emE zZtQ5S-eG>CwXdhecnuD>EI4_5-Dm@GD##TMuV}sLdvKSL$Mk}-PFRrrGj2&qsWhBK zRjF1L9XmTahB*{K`0VY^rieE-4buY6km{9{F3FKIa~U{ig~RAhBt8fVT>&C!+4a*z zVice5rL23Y3sBEJ+C)fUSxeI}8&iDPb}=)m`7}Byt@FMv1Ci%G)%u>OIK1EJ?9beN ztciHS8`}LK@WuCzvm$o0Gj&SjeujpKhb7bgq@%O?VVP$(9=17&X+}K%Qdd-$6XG^| z56E@n!KvY|riK?FpKr;&aDirI%prvtRE-32>P{Xja(WexO-C!+%88JIl4AKvhgP&n z0>#*}`O5Q`%NgV?|LnTgGy0Lu=omxB@T0GadciY>F3?5Z*tz5VIl(+sdx=0* z6opxpW^#9(ljfa#D}NF`G>BtKOk-hgoHMwJK^Qh)5`K=BEIG!^2xeu{)yZenW=(~O zXwd`N2_PVXV+Xz0S$NA|-3CHj{p#u_GtIkU0&)6yf1?|#aQThGWzIwh^YC0n#U>pj zA<2IR^vH!has>ro4gj7)xZ1LBN@<`*ekf;}lEx*nJnXfw;8)9;l&lrmGfU}IR{BJ( zsSw9+Yp5vE(`?|`YFFGh)~$nq`pc=`sK+4A3_ig0soqK79O%0J#v)8~+g@0jH2g5E z=ZFhb$7ntB^cHN?vx0ZneGM7u5>mP-u5=b|bAra9k!-W=cq|z6Nmx`@hXgwoob~r% zJT47A7;%_!;Q-O0n-X2N;@Xb+mc{M~tA89rkDKw^-W1^#eppb`P+Q{hZ1h8VXiS6J zYIdQ6z;W?Cn;UihIh@G$#OquDA{MWMM}F0@i`?%v7P>*nPEAYGVr{zotrUpgT4xlN5*fI=B5tf9vl21!ucq`` zCLqBWAU0yQjR0hmR46mWps6H+)sO^v6_2uHBMP6WsRz8Qi#Sx_wq8= z=W7U#Bd#F`^cJw8C=)WWvUp^ykvca6?IMQ_hx|^?cjbQgh}{+~K2v(^&z&0(2M8Pw zGR+4e$6jEj-*lI&=i?I=oussZI8RTN5S~LUw6}b&ZrQ2p?f8ho`z#uU2YIvK<>uIx0_Y#3>3-LA|4WYSFY%M`K=%?bIF(1Vz;?m9?Dqny j+Vz)suiyFA@N5Vgvfu@lOJ literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/command_block-light.png b/testdata/snapshots/darwin/command_block-light.png new file mode 100644 index 0000000000000000000000000000000000000000..028584bfe1f912f88944ce432e7c7d8bd7820f6a GIT binary patch literal 21418 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 al@2s literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/commit_graph-dark.png b/testdata/snapshots/darwin/commit_graph-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..902eb327a7da0adb69d26e4fcd59641e59aa13ff GIT binary patch literal 26659 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 TQYwHt@_~}Px?Hi$yU+g%q!b#< literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/commit_graph-light.png b/testdata/snapshots/darwin/commit_graph-light.png new file mode 100644 index 0000000000000000000000000000000000000000..6344bcc45036203e653b30841655b8244f3afc6a GIT binary patch literal 25685 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/commit_input-dark.png b/testdata/snapshots/darwin/commit_input-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a83bb5474fcb4a25d9e2347ee54c8a5aebec0774 GIT binary patch literal 14947 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 Ppe80HEm+B~>-RqZ(y}wQ literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/commit_input-light.png b/testdata/snapshots/darwin/commit_input-light.png new file mode 100644 index 0000000000000000000000000000000000000000..99b1d49d366eeedb76bccfc1d004abbc2120d7f9 GIT binary patch literal 14411 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%0DW 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/commit_list-light.png b/testdata/snapshots/darwin/commit_list-light.png new file mode 100644 index 0000000000000000000000000000000000000000..78f01a3f3dafe217d460d7b4fe4e66afc9a257e2 GIT binary patch literal 25597 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�xDGHo@z3oXzlK~mtnjZ=KVS8aC0Zn8WuFFXq%bkXOexPqM@Mtnu6h+W z{X8a=zr8^~$oXa`Kr;k7GBd-To&UA?gBS1S8zS4_#9aBQZ35?`1Pm+_eB+g4n-g6- zhZLoQZM}OVnl=Z!k%F`)aGBo>tnkFM+~jah;Zuu{*++IOeZ;Zl6;Cu~$nHp0o3$SE@<7!joAR{p{*A$ts|- zVvEUXnX^ZWkTI^R z>IM~eS6NDR#Y0F#9No^=THObJNGOYGmW-B@Zdqq%6$lHA_V(qS@+s&7lWziTttOM$ zqh7EK>Z!61^^RZ4ID zHg13F3kMC2<@N6M@GxXN{3mF20ToB0+|vs`dS*qCnu;5k`mbsLev=`B2meXlp|@?_ zg))8qGXbhm!@sMamY(c2@WKi+`f0EtWJg`^tANFydlExBu?8%4g8I} zdItOGK0~#tyB`M}y!TR3)JT1IneK%P+;3Dc<-t8GFfcN-v}%0?1rx@>FmRD_a$sqG z1VJwPoA5I^wzM^qzxOt_@Fi=5ig6s)zqsDxnb;p;^Y_kiUmiAa>J!W6#tr(X-*jwr zLXmTLsF&4=Q#v}HoGbnIsa5p2S-ii~h_P4AHKcQNEKg0bpvt9b&hBe;%4(%+&`Y9r zbv{T-i>RqI&EjR7_dEVQ_ynJ)J;IG+US!DQljJ28tDx^A7W~^<30w3Xv(2pD?F_N- z1KNSHtA$Tfy2O5O&q1%9f{mhVw@Xv)^Dg&(=V`X5o~q{ZfFe#pTwE|?0D4aXIt36y zq^xO@4lrFQA%%0DRHQ!yf#)+D)tBz(rs39Mlep|(@gpm#r154aY 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%0A&D~8|S9z{f`=)dtSr;UL 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�f7aQ-Ks&55R=2{S#^p}^q7bd zwts0~{Z%`ue^x3_jD4@Gtpe3LUE9`8c_T$&VxQevrO(~Gw>ByKD5#AY(a*q3O!3d( zFC&CX9~gxdBo@@8r~J;o;`$bVnIc1{T-^A#1}G(_X(#pn0c&)-Zh#5%SorGfrAi$M z9!QEp?tLut2(Zf~^o2$J1_Mvn34_S~-*5k8<-mu2221|n^fz73_u~kpS&EQ10*f6M z=fB&3i3Du5I|;G>5B@*CcU3=qtG}{FX2MipC&mp<~3M1lwoBsc_buS9u(|5p|3>6SJCFW(r z306OvA%a}zf4Bb{36K(;y%M}R(D*z3KPGoL;p_Z=&-c;uC4n(HnlaCSE5ZHS&(D$y K66Ipw{Qd_=R+(l1 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/diff_stat-dark.png b/testdata/snapshots/darwin/diff_stat-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..0b399844a27f70bdaa4a313ad1bc535c69efd78a GIT binary patch literal 3007 zcmc&$X*e6$8jjMjlqjld#9C_C8MUO1+G=mBNbP%rYAvDmop2dLgQlo0sUfw5lxvAt z!dQ~3+8QEFQHnNdE!C1(u6FMIdH>CG@AE#-dA{@GocG(_@0?5$xdI&gQXi-|W+dL&wW1%LR zc~8(N*9a+cpvhxf9e=i~`NoIKA7*?@me0kg`Oeqv67@(ZQp*7|4&$Lwe<4k&?>4Ul z)XmK_Z9!#w2zj(-SXhI?hiHu({aJE$0M|*5C>rL@;+xfH5sMb&UV)ia%;nmjRI= zdZ=C{1ewch7+)7=oDW0697!E1ANyf31~X8hMTlZ(;yPLcG8Kfw;oaNxYuM;pb?z>X z_9chCZ!-uR0+~SQFh5omB+&OuO_m6$+gWUTMB?6MMTb|J=ua!=JkDYwy0bG0F|iD| z=HYt-hr`v1?PWel;~pVs=BHm1p(iq8X=VaLo}7IqT($m!Apm5C7;xgsKXPN{XfST|5g%xMz()ql6dJG?l?>D+`CFWBa{s_s#G_t5$2+Lwb`BK z`3G8hQg1L!K^I^jde`}CDt$JI$wVN&;#UWN zMbn8bFAH=zv+*knuWniX>{HeqZCM{9=HkQvuQ6%P(3@0ri5k-jdn2jp@af8xuZdv= zNRIE~NEbwEK&x!w4W(a&@Kk@zPXc8}D{fS{mDhCEt);bL66>OXtchC0&FRkCIh%E2 zUyL1*{kyKCxx&C=Vtnt2RRC4uVNg1d(WC`)9L4N9dmp}={OG5oxEjAcAYJ@((+Ii| zh;n>in9f#4QQyHYony*<*Cb{0Pg^X>2}`oz;eDdtxa*VBx+`4Pi1~G4DYL|}plq*| znT0;uPcYsWPbcO={WYHiyW_gu>~^**`ez5hW!Jh7&tNn36dtT&nsSyOlI4OT1}BH+ z6JM&`Nm(dj#&n}4iGJTSZXVo>B_4!;DD+PGRv>Vvu4sXd87{uOj@Jj8hk{u)Qb>jt zArz*U&sS6k={tQ3+Y7A;ImH?=sGhzkf-H;6M5TEy{eMF?-gX%o(~y=po6FK0M= z6>I&hYoG6>%#z2ag9BW3AX}5WSdIsyiqEV|)}?K1qq^AhOF3DEAbrou6(-O24hC#( z2Tf}rn!Z=?zZ5?w%^U3 zDv*CD%r^`wbhJgY-gtD4x5e$Se(RBmpDy*y27|}O#-ygnz^#M-=`2k>l|d-!$i4VudS^R< zOMhy^=Wq?9n|-L%<%@w`+Z`4gHOf~Pi$zTS7yT#m-#zBPAz=KXpsGN-wN<}0VyJb&{P6U*MJ}S)@v*~|Cg7CX z_vfO*033Lq;_~&Bx5_AB1JM@~J~t~Tl66-_G5!hLH(_Wk>9&VfM8v>NfeI84BKv8> zx42Xfbxq|D?A|SDiC~I8MkXZmSs&6&BTthb>Kv7@6^%)i(AjdLK~*YH;DsJ>?h&xm z;w2>MJ|&i$y_craU?8ezp2T` z#)TdvCj`kILm796(5iK(Ya|0!e{pG*$UKFAeD7!Y^n1uQuk4Au+@+nE?ezx@T?Sb^7aSAr;J~1j;2RX^ASWCODlCd(r9u^XWl>~yd?G2=nlU&w8QFz#{;uZ?Nigfabl1NA&{o|5 z(;OS<&K|@;juNmVABqpDuV?YJ`+p!1f;FQ9*1X$~UXoN)%TbYbuK1RiLT_kSgp;4` zpg{h#&0u}ERj^JAY@^v$bLw5vKFbr65C*vDdq9cxsrT4W$iKW52I4{RJDR!iT9EC4 zw0g^`fNPhX9;cdKrh7JkRyXx(`5nN>j#;`z92eYv)8QoCUMiiS;_u%b$i5gCCCIof zeKMr&o=Y)d@2PTv&|4KQ^#enkhJ6QD<;GkOh&epNU1+6v>{mF<-*x|0KP7F}VH4tI2hZUjL3hN;Z}gr>TQ`gnk0MFd9)! z)IF@AsiA<0ur#$c!5e!a{sq%9ds+Yh literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/diff_stat-light.png b/testdata/snapshots/darwin/diff_stat-light.png new file mode 100644 index 0000000000000000000000000000000000000000..93e0b93f150c0abfa1045ab4094cde4d3b81cc14 GIT binary patch literal 2949 zcmc&$X*3&H8;)YAC8(+f5r*1}X+{O5MbuW*Qv0q-Cx|9?L2LbJh1Q@bYK>i6QMClE zlD2B!fugJdM<-Vfn+i+eMZS`{*tpJgS%>Dpi zI};4RM*cr+h&%#7wm#vdCjr||a>*)JdriG^Z+V#HwyV*WwP9&-P&*ozcB&tiEnq=*<Y7vW8R)8w&2opTOPB%IqCC#0!hP8fav_sV3 zpr{`o7CW08_O>lK3k}9TX-0JBDPa$Hw=NNnS68fjN!xuqDwor8^?8Wb__u5SY%5lD z3AV^Amv7NC3lM8$fJOEk;UCIVq!N zwIZb$H5tpReLgU5SCjC)@E39Td3eVblE&o^z)A~Z@k7!^m0STgzf^E*MAltf+y!xU z^sBhnk4LIq)>5#Q*hoE+!MG=C&){z@Ref7~FHv$Xg)b%nXt96s^1ZM^0-p$`|Hb`m z*0WFGS7b0;^64lkd2x8Db+X+L^zOr>^+#H|g&)3NTG(XKsvs9}XjNhH5FpYXwhu5pGEw@RwJbarqp$A5cO@9LtS^1+i+|49ZImcu8fI^7hF7ghkaV@K zBJ^72*jQmU1KRjHF!+MlRPskqu`H&Da4?%}-WHaacPh$FQIV|O#!OV*S@C%Fxq=N4 zsHxH@&fV?6v5BFTxq&iuY(AKNHc~7*7o&5%(f`}rlR2qMPgAQWj#5QDO@`Wg=7`SV z5^nLk{`0Ulk^%LYa?`K3H-bA}h+Zi9RPgx)!Ao`yJ7Ife%(EV}Gd~BRXos8{YLLzm zw-FTU)^csZDDFeIrK#!^)l_f1RJXkHoFEJLmP9NGw*N&_Lr_}s2zF({`|72rSBFE7 zy`JSoJ=Izf;!$d}TGaFE6<@;udRE_+Q689Yb(RQb6n}~sVXAY_$@olXCdxtEA}K`; zpu||wGe3v%gepZmdzIG&y||WER^Bu74FA*~eV9Gm)+Pd0)%0;6I`g?XYD|1}jbEyc zYi`m^pc;&mSMX-WlHsZj+l5xdQ>|<5&P`+y zHftOgM44taTJNh5L;>^Wz)!P(`%Z0}K3K!)%C`ACHS9+8`iOIVzaC-qF*~lxDlBm7 zEwb<4puRzr37NCp;it!}7*Z)TceuGiZMAi{EMZ|i2<$Ixj<>c7-7AwsnKi|V8KmIG z$nEXzAsDvF9tPY0(lKeyFrm$nmfRvJi}s%5HTBS%bXwB7YB58tB`8g2G;3zPE<;$c z7BgvYcX|DQR8sryFk&O2h#J-$s=kZJQ968n!RM^<%C=TYlL?s zaT~T_LBghehsQy$&JbT)lm`tQw8z493?e85+{CiV44UB7{O0j#4xp-lKEh*X_Rb>G z@0P>vXo7K+KKppHkMI1D{Z7i;E4JkUq~WuBmE+MdweL_vA^UkQK9W-bX?fr26X{L? zC|zmQ02HD!EytKaO6ces_o^{Inl+nTumCwBkX7k-GBbSNSX(7VD=Y4fkTdV~gHL*Y zd(WNIz&Oi!rShhREj~t1gQPzWeCx%4iE6hT{xX!wGE+fz5WrNfOJXXcAFX*4k4eqJ zW2Jk_59g?{n-OS4n6|eJ`%-^_ZURRj{o9OK5Fec;1^Z8#9h{HNYth0xbLnLfnH7BA zS3byG7M$c>)eq0cvrZPlUR+wB4RUElhLmnoGA~2&WL^9pGK-J_Y_N7F;J+DSW4MT2 zqu+L{p-09V)~DD`p_8U$n$%Pef6y_!zj)|&*qG)YDoqL~X$)ekt809aZza;@GvpFd zN>JZt{T~!lX1x(atx(nDZ*%+Ok4M5YYiesoL|ZU?Nc9oy)INCs(DHNjJ^KbSKwpUb z^QeRUwa|l)1$ome7>a@C>f)eI%K&!d6eixp$m&{1HP;boyuA0;Wre68qh&;4y6q`Q zu|YoQaD-}-;$MUfD7#|5x@B%wl8ZO-k5fqDJ-T;4(D&;!I|r-LRH$32qfD0)-lP5$ z{1dO4BM#$^(KgajP`7sn3qv=ME(e8{bX&oM#~qyyTotj!APC5*Ji-}KHI^gHKKB45;IJgPWlT S&YXO&0fu^}@ERT0=)VDF2wgb< literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/diff_viewer-dark.png b/testdata/snapshots/darwin/diff_viewer-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..96b226d254f09411b0a7a9b2aa6d41535f8e9329 GIT binary patch literal 30001 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 Z*B{`$bkGay`cP@1A?_ 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/file_history-dark.png b/testdata/snapshots/darwin/file_history-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..6ad872e62ea7e99afd9a61774582426121c4e4e6 GIT binary patch literal 24432 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/file_history-light.png b/testdata/snapshots/darwin/file_history-light.png new file mode 100644 index 0000000000000000000000000000000000000000..733704f3ef2a616095b5bb7a2203cbf378cd66b8 GIT binary patch literal 23448 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 M&0AW9FuSmS0x}J*LI3~& literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/git_status_badge-dark.png b/testdata/snapshots/darwin/git_status_badge-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..7ef1ce6376832c9832dc4be49e53ae29b70c83cf GIT binary patch literal 5894 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 ULwnoe@oo;aCtAwy6|Exv2h{|&fB*mh literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/inline_diff-dark.png b/testdata/snapshots/darwin/inline_diff-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..da868df0061df61b6eb7fef24c6c551a0fb1abba GIT binary patch literal 14515 zcmeHt1yEg0-yaa%B?PzNPH>ltyF)JSF2NmwyE_C3?(QDk-95N-gFEy-&-=dZ*J;16 z?M$bg&UE+8o;`c+?%ng(-~M;Ql@ugV5b+TqARthrrNmSqAfQ;l^Cf-On68j8V(2EyVj9Yj;seoTC6yZ1g<9nc<#(Ii z+UJFf<*5OUi*5ea*r!_9N}n(=FvMNsec*r;ad9SZQxtMhanRd`tIxh${IP7HAL(p| znb+f?PG+nsE{!he@X%2H!XRzLJtzo-@6f_fq>ynCQVLkkQ{IgvozmOiSTMqXTdOYKZFK zcB)PMIGT@$t?*zoSD(LkK3q`g}+84Ip zk<6)arXnP@KXi$FSKB9s!^Ekc$i}w&INzPlm56LvFLO(}si`ieNNgg(Oe%P{Bu&r2 zdv9>_0x2$^6vF4m=SxJnIDH=TMR#;{Lj`^URCT&kzCB%k{}sNs3bD^Ma-DfgKhk(l zE-IQbF^mz&0h<`^%dVqoU-AsS)DyTc5)IO-Lp}qAhd*C?*<*C@!s`*;%yjb}+4k4( z%r=&Hi^9)XH0W+?C)gDaW_L%RTUlCCMtXl`ZDe=B2YqxR4Uy~6_3(@}XTeQn(xb-u z5D)&BE?;7yw`X(KOJe7Xv%-S@`HT}@)=MV*x1t*|T=>5wZj(2ToA6>+k_VoQl2SZK zNmMk^LY)ByCYZxole?W49y*}C^q%~V_#-?teC{#ZYp3^M{a4RNk6?3!*K`M=$n|_} zXILMtVRj^XB-0Q_Q=sYDA4jHZe(>D zddeYEC@VF=d&(z(K2RjKJv}WurPW5fq^U_m++!hoLs>j{3LT)am~ss;`?`i)U0$vz z(?Q^KR`JcA*5g*h%Im#d6$l(zS=jz_83t;8FRp4bTsSFQ<4(<;hJ zBvQ=+zE!;R_h3c4MAzvgBx@GYSFd$3-78o5hx;?hHW#+;U!{+s%@HTuqHphH@ zRXc+aC1qo|)GZ>JiMi0#Twx9_{z-FF6D4&a5ijobL^Hi99?fY#3o=r+fXl2&HQB0G zW86EGx+DKxopw z#P*j1KRHK!LrYRcG&~1~x`05|uTo#jQoP&SXpy;Mo3+;3qP9C%z$lAT;(|W2B>eI5 zF}QJNbdZ&dEPd=8QJ3FsvV#=pp+HSdCYU~TxU{gi6`|<6Ip5)VepqEpgte21wUZ#h zw_LT=5>e5iZK%(9dqw4d3=&Xzr{WXFw7CPWBwiYYVYKb-uKF1t7w#2d#qs`*78^0kVd+iUc%H;~ljLNX% zt1If8YfbM>DokeWd5MNtR6RJ>nrv^PP}jl3$YrHvYNzFBTJVj^%)0`8Wn?ro<4>@& zM7C;ANis456|hN=vls%rhnS=rKcZTcG5H(zp1V$ z(Zgygtxt5i9i1roAmr)MPQ?4*h%YaxKh(SWnemG}d$SqH2t;sHZeL(;Xe(kqP3|Us zV17s*^eL3F$*E2iWKH)D7!TH7vI{RhyFtFK`q2rn^A>+5N7HY07PSsD8!y#&%>HQe zICKxa30uk&Q!5JZ@!ZCiUS{3PDKs*fKVyNREF^b#&*So0L*s22L~RZY$4}41=Y2#0 z7+zm*C~CX75Bx%idaoeEt6F(@inP0vfVq>Hm^h0LsI0WDKaiVSAb478gwBj7mz#(Z zgFCJiQhcMe+9>)X-xSky7?b5hcu2EA3G^V24MnG8qKR3@4&Qx9dZP6e@eL^o;Yr3e zp%l2K;Ir>*tK^PZnje2P5vke#W9ZQuELAe8pb#6PO(q+pG=3=*Lo67KzDiI#*E<^p z$Q{0lt_Xq$>WY_XT3N~AN2esYa~(X8s99Bn7Hb26;v#RVkFa-wwGj~~0`2*j_JvK& z^}BXd5@N3grnd37ESc*c{`T>mSfnUR3z_?SUhHzhCk{st*>26oYXs0$i?Us&?;nRVVt-L_8OpC3dVaV=7!1T(-E{jW1 z$bkWDAQSzRnOhtj)sF8|pR{U+;*Yo6oU38=@Z2Uum~;UraI6B8`1+vU3`3u)Cx_rTJpH0XZvRy+5bdlS51K7h+ z@cStrRNWLMLk^x)XH0^t!(@FcbuLcd(tEd^L9+`Blv|1p!^ddh~3)T|JBxq@)up>adN`ddz3&7Jq~xc=ypzqDah5fvRS4xgTu+2YwY zs2kxlm>C|5lVGortWFkW#+b1mGTtO98A~X@I{f)acra^SvK2SP7PnEPFtLs2pd>SP zjlsGv3&;4>`a~R!d0aL9u%i0$d?itbskxgOjgijNOvrO@1nZEVz6=9k))%#~u)w!W zRCl!_bRF)8Ue|?4aXp|G*0(XYG*M{3?>YN>4`uSdxs1GlpqJQqs( z>nE5UOX2!$Gef47Zc3^jUGC8pwxpO`9o@cnE9xd5g++tx?6dE?;{(Q$3IuqypV5N6 z++(mll!p2{8vV$ei)^}6Jn){}y_8%5KFeQGG)rM5%j7E27?u5vN(;DP3*4}pcM{E~ zP@a~WZcE)}i3rcvsauHo9G}v@nJM0sGF4a6m0zWu`LoPlbqqMw71OES&K}DG@9X$q z_yx7EfjhTiD2&k#o4cbCWB67CWuxKrXANnFOatrwxrw;jvVuPZ^#&cxB=} zBU}m3NCkWS?Q`Z2pykHn-bb*LqpLrJT~J$M(yf!wASP1-D%d&XoTfsP?dV<$U~HW~BO@~k zXJBA!+gX}^`4U{8&DA)bDU>KDt2tlY&cOjUmDAoagv|K&O32e*7!&>*;SgnUM-ZC< z)C`K#Wm(BD`)-LjJZH2i2d1hRe&YApfm7C^vmK#N^rad2frY z+{J@M@RhGD`5O2d2ncZJ*YkCKyDZs-&kdl4p}nMKx?p0%nY6L9siG-0C}SH?{RY+b zou9=s?&;U+q-Vpa1*HBT&C#*Y{W(c|3xq(^YW*I8(X}CVGY@IM!ldYose+8jCkYk&OfMJEP*>c&fnl2M zr973o3yAzJ@YR*2 zYx6tv@6U6HRg_3Koh}RVIu1jYkaz=`0PyKYUtdp_g(#w zlfVQlpEo}#72SkH5XLK!$X$v_AKdTam#WWW^mX4PW6Qho3u9u%v`T+FGl7$-*VFg96u^VV~dT&v$M;;<3@F`o})N195199wYSm zFX2SswdPnN3Gc-MMnM(kOoaEIhM?EbezmG8h2n z!I6Fb`_!h(FAkSRkdrhi#aX9$+;?OkDmvU}Zeek;Zy&`!Hfq@tH8!qRSC%g{RZXck zs@V)8> zbx0}xom`NLf$0(!wF{Ci?nZ%N?u8Vb!rF-#_c`fr=qe-o;#DNXYJH(meHaD1-uA9jc4DS$kT+a#T|5Oh!S|Zq zziu&PS&-{lxz=jJz z^Jy1kO{39jeMR_yCGYA*)udHf*-eNaikD9&yH<|niWZhuE$zJ4 zmL-WW)rf0`z0 z#YQ`EzOIA+@1ETPpHKxvXsDp+^%Y;i#KClY0MAxLi}J??d_S8ycIztBDDO z8Z#}Mje7fv%(0j6cxZ_U8@gEw>grdKva#9WWmT2p@U>~5{8fE`a;%?DrL~53zT5G;<|#q2e9J5BT+KRNuGc%s z1Y#VNgI;4e?XBEOH1ox!c%j{Vx?9s>=yfEMh*=~@2Ii`|eO)-u5A!QyCst*WXlE*F z1s+kZ0)8jcIQkdWRi(P!RJ}bh;_>+=`v>QI&UJZp8T>+q;NMzr>F(@VNNN^fe@Z3h ze-d@Ido#}z`h&Ym7ixH@NYv(Y=(`t-GjbBt%DX&qb8D87zBs>7Y-XA`aFnl(QTd~( zuhEm8}^)6P<>Q^?#33=<&6U86AI8N^vK#W`B#u8llbpGwc=<>!! zcBgB^?o}@_{y&=vRy z*VoxnVrn ztZ}WOnQw%LpB^3Qw7GBg#(j4sX6B`eiQQG_I6G>0xJ8KuTZi7c4MtvYa4>B-o+(C~ ztCCD{GZ@91+?y&|c5E0-rp?jWm(wh57GzmD1={M8Pl&-YZo74kSDqBni_BABfeA@~?ZT9=dF%^0W-;nKATiiDwS6$ohO#70`^EXH?g zIX7qPUa?riti5XLNzur+*p}?IsR!d3i<^^?K50Mm^BeDUKQl^dh;>Rb(n&zRb>RW0 z*qpNYcu;ZBbjs$2`{y3ngVFi|S-)GPt-o%&PfGOY9ZXcdxf#1)}q| zoX>&HZ#)iDEQx?hc+c|VR=(mKfjjQHo|KHj#>t9(wq z^{G=1j`!2$vm6o|zPw>l=G?wD7aC!>7`(cAJq}}9Ujxgvvzw~AvRp zc`K{ayed7=(V3i_w7MC~uz*F?d&4iwF2D6i0kB;-`(>sjan}~xj1b&gsD9o133jEf zg0()!4MT;mdZ^?)6ib&E>-PHIoQX6jhG^N;c%ndwMzv!|)&<`Kv-c@OR)xq^U>uX| zqsM`fr`crXn%jmB;p*C&sk`FK$wuvL-RQ=1%;36T|MoZgtyaICX}k9A#Sz-$1gd{{ zlR#l93C^OJM9Bp0;rY$k`RoVeLuymBs5t!045Ua|3;@U3YME720%o9sCi|B!RyGz- zSJ$y&`0xlp0P7-{l>io5wt$bjmAHlE(<^V*ZGg7rKMo^P4nf5(2l^vpm!%R z`%&?>%kx4^#nEcLFDPw!XfKtpuRhkni!RqlJf%^^j|DvIeQZPsN9$d912 zX=w3cTrJFcKN`V}zzA>%j7=_TiHN)vDkOeME#Rg5!o$Hm{r+e3y!3blL3+wJwrg#D zRwlcfglLSOhLw%O)Be#&SJ(DZKJe@v>ThT@D-2)C&Cy*M{LoO(f3|STew|onEgR0x zQJfoGF)Q@PooG*ceq|*bJ)u}-pQR#stkTTQl*(=+hL(wz+8ToyF*pFd7ls=+4dX%A znE0L-$Ly(ytxlyi;v!Ah+HI8;6H_G^#wR>qpak8C`W6wg%Z!hxte7l}rJHtgLa^)t zt*l;e4R$Ydbmd@!>P?u6416hS9(=g_eK~()Q|(|p80CD24-%YMvfdb48_o(MT50a< z9jB=NNz?rkS9Dnx=aXt_l7e8)I^e|)gdiDD+$SddnNY}!49xSW$ol%%Z*H3A%=cf` z?np3)l(n_A87JfhV~IV41mpQboc~DWT=Vk2*X?2#$-q6@dzQ|bj8m4zL@0W7v7Z0GiX4R`4=5F8ojTpTBs{~q^OhV_ptyBaIM zLa<}OHLIv91}5l{dMWooOs~&s>8g(HH=VDz$&sQP;Bu}`l(rR}27LC#PC?Hb9q17h z2o1ZgN&A#2F!big*H+UoK9gc$Mv8i2(rWzQ=UT2pSSHAWQvQX!^11BB&Wny7rzQvaL;-)>tYh|UVz;v^XD8K)wU!!e(W@LU@MBN_KX8-bZ z@AzJ`&>N`SJ{BEgj00nm{H#qO3Oyw5bM)fmZahp7cB(q}a?N;jbiXX%$9ZU?SJ+s2 zdOSu5MmeH9G73eIiM45ZdM3#=OLkRBi^naZq;^UjCPrhqz0J$RnEjp2N&~C2ue7+S zvL&8J0VII+q)V;|%!tA+Ldv&{`3oP(FUZ>H{MP%kZW66A=+*W~C!Jk3FU!h|l|Oip zH2*xdT*J2?t9E!U9+|0uHxhHDzM{Y*fb+3B!f{SdR=WdIzz0{KF4_y_9U4t)Frt&grUfvU0kyQs$o~%~KCgwcKXFSZbV{jQ?99vjDDf}6y zr>inr`jm>LxiP(l@~`QtJzm?5&#BgLx7@FjZ@=ph0}iu~lvHm; zQH^;5Lgq}S3XxK)WnJc9egfx;-F4fZv}Lr4A`?G2SgWYf^?CW^mSxzQS`yz)u7hK< z;@5|91GATXGxlI88L$alA?HU5f(GZCvY;gIYvsE@cGt^tL4EKt88N8$Vw*wPS$0}L zB4`)NAsEypH1>0jTAq;4HHsi7R=?fhdC196nVLHW^a84F+>R`g{~=tca)OWF{di#_ zs_G=FdhI_vcWwU2jG8fVc&%FRh$@jywy0xr_~!BMpE{KG$3vtM1qFt(@FWk^5TO`~ z1kKD#>Y1ajQ}@1C3IoXoIE01|?ycx}=_{W69Q44=gszVM+dcN^M~M>Y8K(r{(4)zV zlFsnZW0v>ZAR}M1ofaFj1y!<4slCN|?X!W1Ap*c+C_7LVCm0NNLJYr3Xk1KIhjZfs zXijFCWpSn=;WKltI}C;{0tptGwrX5?03`(#M)#ZK8|*d_D;gY!LJU#tq~6j zVerKL`Q|M5j8pY)W@>kG zadNhOaK%opsxJwL^BX+No?*5zoDc?m+yL~lk}4iYDjD#WIW$yPiTdL83tMV66GAo? zF=hj$50?jV|4_KyZ|==C*@W(m%I6XX9a4l}5p+mlqVPd@z*Zj~d8ksS@Ts9f-jluK zYtOb-C#a&Stn;DmZ?TdR;cNlmMQU|S7Prgf`n>xk)J`$|#k$XLj-C&P*X@cA7bp&d zsr^sCeub17!nVCWL*nY@cVEtMe_-K3R#jF%_|}qu<_#)-pcx)hrE#=97x+NyERLTO z>oye=2D-3hhe2&VUuZq@~^3S$*Z`*w0Le2pzDQt){H9)6^*40yK(X#}EFz^n8$2RT36g(|iaw zz@s9`*!Sd^an?GYns31llMw&_?IU+~QWMC?Am<9xg?kiN(^6qI~n!nv88rS(%?KHxO%6n{AVec*e4qTh}yh{WPGeSVHI70;81jJF? z-@doKf<7C-dtJ%9q5i`Q8(_?4Udp0?kCQ;)UO|9E4FAfWjPT)4gRu}sB7S}h@ccYq zv!VanK*>!TeSt3)=H%ghH6$)LEw7n>AdLjKG$#jMI{-QU8upJXm@DhLB$%Uwug=asthD-?!OvUIjoOkP$+l zMFYrs;tZr%C~z_V_diBAlSMx0Nb(e#} ztG(1{8lD|0T9_Pss}m#tjENpDZUk<&*{Ow;rogOa3IKQeI*DuW#fr2i`nSY4@)nGB zcsrAsXkv^{`Bh}O0!G?DolQ63RA!vBTqN5}A9TTglStqDxn1N50i+iK`)6g8TCjs=(EMAdm5cCj0kxRb`Pb5zv1u%rA~GzS5J z{%d=xmqCN0)mD0wTiLQD<1Nl^c4ax8g4EQZ>O@~jF_O2(4_;o^DT=YawRWO4u~T4| zjoZetDo*AFdM&8#da)P&J<5|^Z@<;$be6cA@e+B4q7@@W;mPQ|RtC{ss#>hWKqD=X zs0VaNW<JK{E8{E60LGRda9@v&1^hR>_2pcsxO1SZ36#h^5`LZmCo9aXF8m1If*AfnDXPJiKQHrf#7RCnU1 zWi#|mT3)()VYUs-3?-VVmFq~s0~89O=0D)kFlV}6zhpLbFeLIcHmsXPeo|4@_1pWS zKUq-VKw^@v2bhix-CV4sV}tEg^JPY)#~QvhNWz5OAc&z+E$qPBQ2g|sBCtaQ6_LRtau=nJfK z$9RE!t`F^@avwb@++u+?4re?$iTCKyVMl8fNIqG0vk~&zdfD6DKJKK+$tkjhP2tj) ztSjT`3Nd07$ucW>!8A!%0?&6f7^RCPPaV{^B&91jkt+@RNft6se5(l)hM8G=3N|qR z(j$B*sR0z19Mdf0{O9ABsz{g6D9-M%Lk~_?E=UAtULV!D3Ewh~BE43lPVdiuIZ}}= z*_E%nSAWp&p1OE>oe#Rhq85LxEcNCC`dmA;G_-&~hy9BzPA)D=?b;tWKd=Sf>Dli4 z0lA}@)i!(fo8)=7cQPB1A~~j}b@m-3OL#HQer?%dy(yK;$4@^zWUSsmHaEI$Q8}0n zH}KCAU`_v9;g7w9%d9M`tSrs)XZD|SIvSfc)oJ!~hy@H;)1jeyu4Pl#+c<``JmYs+ zHhlj`WGOIziWKNvFRxlyU6sk!Z!4&*%woJNu2;SP-M|Hw-;RfF<=azN$~K6d1Gy$`wh*i#>C+MAe}xScqsj?G>F1mQ}qDlb*ZjiO=yY{El#$ zz6_VZ1FU59h0VnaoTDKJo!fn@Ch(ETe;C_nk~odh7qIGQW{Ebg>o;~Z6$x_k&U6ST zz1;ha?M+%Q!ahAPfpw{r_PCVR(uM@vB2uM`pWtC9wTBU>mZYiZ$jV}I0|RzC{` z5q0^sUU#W#QHQ(wGHp)ZH6lDxr^TYH_4*qAGp_^xWB;WI>wB-R-S4SQg{j}$N<6pC zbC>pFLxbY@H?X%J=O;haHJWdHT=3dZ-{1aB3}V#Q44L?{1-Axoc5SNgSw45(?M)?W z+c(y^fV~Da8C39i@U7%Wx7Hp1OEm1-uVBNJ-*|hWBy>4o^kv8)@KlkLb1F>ib6}6> z_6Y`?X+)Nu{cjK7pH{bNz9b34q&3N__%|W(X8?5QM+emVa2wGFH7_v0|w%#fxudKmQQGdG4Fx3f4NOn;(rP0 zKV|iww{S>l{*g`4-V|;O+3!6l1*X3Xx#dKpf8*5!EJK3uF|DLZ$a4R?mDx0FDOj~E z-=i|D{~ivgGm`@26S@2h{(3myEgJ?A*IrC`Sz(R7&!odD=yb&M5sb5Mj2e}<)rGD_ zjqYU|F}CJfhdygKGBnv#@?E z*BaIvVS_+-qS=Qd?R&3r`XC=B3|ZH&b$tm$DQ7h%p_J_~>UDhr6zihB|G8-6x{r&~ z536rJ)-OJ{vB)_kb7LrK`EOjIsqHLu zaz@@TN?Y^ZwNIG9p8qnsWf8Ka^tWGgil$CHNLv+!~Z8E$q+mFXE!4D1s0LXIVE_}#%!hZ-*8p#p}rnkHXK|k7$kN!@- z9PSSo&_BzHPZ`~v+)mWGd_2`CdT^iAkUA{f=V1m-d3g9$H|2~Qj-dX7N*e(*E8-P; zOo*2}uQN+R$+}cdMJsKz*836A5Zo#HzfV4gMTR>&Huznmfj(vn!a)Ghs)6YVG|nzn z))r6q+tri0G#|dt?>$Tqu-V#tg8cOiBE~J0#4~VxG0V{tdU(jkqm{l?6wE?0-m~%R zRXn?W+2n%wZSUtZHn{3O>_y_;VWuwQZov{c;7MbhSswZOzWV&}>Y-U0q1MP=IaTI$ z^ZA{DshpI{0-rOp(_@!B++nPu;$aqX2 zf)3(aP5nmQwqb3tg>ZGMhW;osf91mQ@B$bN`Vw8FBxX{sE4^8!<9 z*l+OC+t_@4gP!0NDE#|3(~pO>S^F+NU7+qRld}(#xwg`GeQ97}#S^RiT*{|U7l0*m zH@j^|oSr;m>~B@R}KB*=#>v|?R>SA7Hgl~!JG5NdjD z49O#ftgZf>zOxYe4i_=hodWB!^rrkwTxQzNZ28#GtGjg79OEl~MfC4`zW!b;zK@EE`a$!u{pyC+FD5y^ z$gxOcW&N@7z1dLL-QrJZj`s{#JKbFE3zVtmeTF(M!zb&xyTidOw`iooedewwPKYyK z*XO53%Sosqg~AAijGtY(kIbOgSBp(IcKK#E=L4{84QZ=wP0KCXhYalwGNDlCpU!hN z%3WK-H=;y?FR&g!Gv7Ub2A%qD+?wNJVT_v9-@iX@JRN+B$V2VA_0%!x?~WlP!6$yZ z8QWDry+flKOjc9#aXTR7>3!I`A1DmH?j`~OxoeoY1g(y9JM4!)BO?5*jf|vZ2p_}} z=4n`=l*3|a`r#l>3L;8_oKe)9p8%FTczAtdb6G{lTb*VV-O3+fAU5kaKc-Vn{$Oq$ zk%0L2BscSbl>TxB{yOksj5(xI89ie|!!9?s7_e~c8K6OcWx!+x8j5-d=j~mZwQX|f zU4V|hoGPD()X_<`l;d`S5#kq%oMkeDz#}9Z+vfB%i$^5FD4ppS3`4J+m7eCBZ?2An zcz9&=G!!2(!BcLi37V%UpR>Ll^m*7PYnr@sQ3);+M}XjsUc7@dK6l@B|ulPKzT{Z5EPfZ=g zqjw@C=1#XSBsApaRu|*1uY6hC6slbhsEsir@ZJ- zukgjS+Y5sqA1*%ri=@J2F7u79^Nmp7%X8W*>wW4wd5c*o==#Nk@>=7a8J8l%7!Kw;I0ufLPSf;7U1LO&+C$jMRluI3Hz#2uljO zxw$=t3$4;cg{Z&*#y1m?Pivli{`Pb3@MCxq^O}J^*41bdk~I4^$x6zEDc2t zm?3QF>=@@aytb8{WYl8Q(52XIB;5`*>(g?3aPl*l>_-H-q53Y*8+{~(VCN*z?`SaB z>?y5Z_0`=jt*U0Cl+~gnHNErm*T5k2PMk2GcIIGF zO1UjjqMa$zOsSf53bbI#BYNhE$G}gh zwpeOoj_tC3CnlzAGaKU9t|JU8s)MpDUI;C1HN_!#&73Z|9QmL@Ra6{e-+6RUT6%nX zVwu9_yx1IrJfQ?BtEhcBo2_f}X>3k3ErXEcH?!c=LU=89$z$!}OphQF6)PE&*4{#(BN%3jz@&es#4# z=ZB*uh?@7p!#R~Gc~fOsQPsrV=Z4p0*4@pnz|M`;n|Z8Yp{VB((W8_MLO%*nkk$s< zu>|$pOeyl!z4onviqcPg9Q}ZXt6VIofJt!WrmCB}r>kmEy zwX%KreH2583bX7Ri=~9qXiNw?ghW)e&5eweCA<&Ehxz$fXrYE_3dwZ8G{G;zQITw| zY;A2UiSUUzr=2an341#iw6+3$RFSr3S>N~W2ZNY-uhJ)Cha`e7TXd-5o|nUF(!y#w z61S||*!T3nuE#7=VNGb`YU-yB4Ab6i1vOZc*Zd&@NYEpxAx5Hl2J?wxOU$QHY>gLM&N0T*BFIh*K3!g8HNPm zVVX&$k^QsMoIo}KlxpZ<*!Cz^8ON0RV!)u$zmgwv$ z>`fcwob|s!g?tPv8?^~Uf5+Dby}`$>{t2u8smA|@9%p+oX5W{q10lg7L1?45MSBm;@c)1P-=V+`pe=4tj|l0n5H0+5^9730#}Als-=Qf;ArYj6q5g-}Sz#*(P6N1F T%oLBbzs8UjR}iZL7zF$$#;Hb} literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/inline_diff-light.png b/testdata/snapshots/darwin/inline_diff-light.png new file mode 100644 index 0000000000000000000000000000000000000000..ca6f3a2fed15623a956def0a8cc34d426017369b GIT binary patch literal 13783 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

    q$QHuDYR?Nip?&V|o4>XMWm+z#eaW4m zbnJ^KpI~UMBI;_ZgTHEV&Z9<%R%`}PwR7~HGojDYM(vZ`E74{$_R3RdCfFyd?`B-S zqVJJ%>dwk^F0QUUa9P*+gYskkGe8cj%1cz$J@T6vPR%{7CG-$VFxd4ttKj0>hv+tK z0keDZ%=}d1<&?=bQxXZ_i0uN1y{VN*`c2%IOOIb$ye_?NH7RMtb+}TCIKgQ4Vk;L@ zzxNa8VSrMh9=m~!E#$|-*iqdV`IB-1j@ZkGZvyQY8GMRMj(UUM@MWdzNpMOLF#q07 z@O{q9D%+~r>-58hr}ULj7S@<12kV^462s=%YA&vErmc(?BKNk>KQ9Kgd~%El9UR6~ zB`qD2Pj4hT!{r9K9FP4grO9`8WaUCjqfI%5g5ckDR8`2cQ&W>tWb}(05_==<>}(YW zZcFpaqYh5Bp1lrMARTwghS!k!qM%HJE3`BPAx`KMI2w4kN^^bsyz(c+jlc89WasSO zRlHVyoy#e&%PDbh)KiWjJ}fLOa>!Ol%(0wdQh_B1Ab3X^=l?8P%g)9sT3*4*4g&Pb zWnh!*xRz=>FV3Q7^16xI&8tE9^ zY&saK9EusXVmjzg#B@@LI*i?fEOwFq!9^~4J_Z^CIz6sDJ!Z%SBII4``6yc*1ZW** z=SB`k4-=H|tS^0Dn`Q63rq-A=8VUSHEucLQK6HY!F#|jI`L0)-1aIrZ{O%Rf7`lLL>$8^BZObJ$Ix7noo_hH^nSjzp zKs1$Q&buF#A@1F}mRgqQwkR}+IA3DyfbB7dNjW;778R8o9bOhk$r%_UYMqn3Jw1ip zzGQLYbe>%!y_b)3NzRl!Z}8Z4%z7%PCqC3KpA?H-QHMu1ag+={sqF8_Wf+200CEg7 z_f8ERIft(zzKZ&+Q025zBT^Hl72^H`W?!|7ON;jpP_@q6J7<{KaUmt}74)!_qU)sCbQr}pT86FBkI+#3n1bLCpM zJCg6>nyAB?vHPAVjA1v$XC~r>fx(z$2obYL-S|662FC6sw!XJq#njZOC=8S=`ou3F6Fvnp5P)y9Wsc~(8Nz+_lCt2-U);|ZuN)EmPvIF(H17Y3AbSwU zHaX#9p(yn$TGcm_{uD$Lv7du6co~X-;<#8=;D7y==o*D;O50#X7!J<;;Cr1PjlaKm zJCjac5G+Li6c5B8B$5LEo}6q+{}(s;{ZV;t6+mwZ&68Y(qfN>5sAB2qhu0}07sbMu z^bDb~bQ1mmtbd#2*^vPMTZBIzhYrh3)=OsN%I&zqurb>08Y3|~J;h;l?ML)BeT zlhDg8th*l-zbWqa$g7glQrdOV%hT+>I!Z!`EnkbS%&6WgAM~ay$34|+>0R9Xg4>0# znuTW^tsAuJR!2#g4}y?W!rKnZMk(>C2kea|FFtK3Wq9{{h4HtPA35$D$u|bu_m4s| zu6kp#*f@Rt_??X>Ygy)&3@~RhI82YcQ$-LiE+%8dw*i#^j;r9o*5*lbIHSgz3r3;9q$jdtAFrY?!0jTjmd9B~Pmi+ol#_XVv$$Py zk@{+O6&I0PHt(j&QQ)CS6~cc#pY{{v^RYC-&)B|Y8LoYLHHLXk^G8Bc#mLJm6SM!d zQI<}*YhoVK&>ve}?I>p1dlmu?%QJgxMz@$a*X|v{$y7*~6l&TVg{A*^bSZd@!$@8M z>~Xu>2$h7p`@v^sbXOM{t*ouDR?YN{Zzb{4O=YVxNCfnhjqri$2C~Aw>t2V%CCSOj z0TEwdL(CZH%RXn&z!@ZNbJbTIU}Ai%z8w37>)KHpjcD|&uUB=pvZDl7!pP?t-3M&A zZ>A@{N2_UMet710Nv5HpG1))qJ}|^A#hCvKDX$=8D&8mIMVh(B?{dbFjkU#Z2V(bL zAB6!=3Te-FXWW>CwY0R{#77r?WIc)0)6+Xg2s#TtZPuWBvdQ;$)=ggQsti+N(_QBx zPO|rCpX><*MPxRzt^p<$2mZAKs;Q{oH(AL)p=@y7ztYfBcDv#fcG~~-Xg*Ns=E|G4 zNncM7+t+dEgUD^`BBq_C+2J=4R%^ML5?b6SoCe!j2gXyDhA?55mB_7{f(xbd_GZ(w zGUQf}6Iqt3yeIhy#Y(ez@HiA#LpTWUcSj`wHzRW z?T=n&TNZsonh=*2Mlb+%a=U?1Mn>YM_%wg&_aeW%QI3jo_6n3@!q55^=dtJ#nm#=d zHkmZ3N6&}ihIkQB(Dt;h?yy-Kvr@%K3b7ijJ3|_9=ze`U=i&8y<*VSy!-o<@sc?NG zz3dNs4in#0BwyostH1ehwQlPWLaov^#_}$~5-HGp+UD_cFJ|1AE>N3OMj*MPm5Cf1k0e(SMs5FfR>79Xch zA)EvoQsI-Uq$CoJh~$TJUJxjw$9(p*JrN+VyB)jErItFAitGXB#E(hQuN!YIUTePZ zi_Zr}93#kf7wRc}EyAK{M18g-!VxFTei7?hTGM5CMiB%Q+*6(AA8UexFLQqeaoo>1 zZ2eUAscbRbjhm9Z)u~{9WEiwGX@DKe!jh0P0_cZ%0hP&=IKR$ae+(H{a=IKQzF zI(1Ol{h{50ZIQ~)HPVxDdUjm(S=*JKF-nu&rqe2a*CzR|%w z!%n{aX(wwgDDiIWXIu#jXla=&Qi|Sov9VDmhQ_qVJ(7G&19@;bYAiXDA-b{6_jVGt z49GEl8tf5s4t3!+JxY{C(sivKaaF+6Ucz9VgTz2HTTAcd^RCM@p>0!^gm#>mOIa-= zGN*fCiI3gd-Re0-mFm|qhA+nMMI4uumK-}B_bO1OXD9T&Gm}Eh=E2oyfq8|MS}KNq zZoUD}KEz~$+(?rr^O7yhE$nAnvcL=!=}#Vv7+klMEp$yFy}ZT-Lf<&t$|xIgnyl$Q zJ2qc0pGOr8OwRquAKme(QMf0_Z(W36f@6-JI3T~PsBtI!$kN_bRba2GuOjkYaNV?o znY5w@&xrI!(}*owJ7II%Tnyx)Ha9Ij{Yq#?M_X6KU7tY|EVH(@V88NS(>|J@H>HDb zIVo=tsWi*N>1k{M*%z9?1)7;lE;~ODTo`Pnthqy8|GcP>)Ia2#r4U|nT8@7J0J`9w z7S&NwQc`pi6X+FcMEE9qH#jHu0s`OIDlT@OBt z7gQ!E7dZJA=F+oBfc?&YDJtAKL2p9bgimUi2mq*)5_NvyqmG=J=>iL3{J~S9m~Qw2A^C;6G>V1|`iw{y!C~qtTQ`MJMxQ-?p7+A5kn4_7f_@35oZX6AmS6mY8wv`4Rs9Z13%VXdG z9$a|g;^Nv;%T`$AHjo7!Jy^o7(G)NJ_KI<~M{#s)tSU~bhXy-M@8DsWRBqd1zvN|s zq!3X8&W7e3y@=pmKFIr{wb}oH#K5?FyoFtT(6Pn|;gpL0Av3}?d@+bnQhHs&A-qXBtEBI4M^ zBR+rW?K3lXk0x4f5Ia0L;(5v6=(MBc>ftIUafDlOOh=#>xV9UG7kKQ{_qo#gaG*CrfOZ zzB41Bs{RJO_hSo(D>V|)J2XKwSey7bY12E}yUYS=W?pF7i0i^#^`bf5r6Coj1&L`I zkjpaO;&Mvpx$K#mn!233gn4>L6Ic~_YADAub7R*m3{lafoTsw9hQ~8?*FKti0b54i zx{-BLL}a&ih<HEGhY=q9QtpWNm7A=yNxA;(XlqHOKDFj(cpe6E2@P_oy$0 zng#0W>ZB{-RKELOGIYHB{6A#Dv$Kz#(1mpGn<`dqS+m+$3pbr_MosLP(CNHklbjBc4yuHo4`%V| zO@|qr-+`N~+zVzPk46~XqgNao({w3NwVf2>fmxnq@Xgn4<911{bHAe&Cgl{hF}Aj^ zp>;<&3`ASsE3XFS1|RLOBj&!xM?XUD^K?~!a39H z;r#>bo|>d}u3st}Xd}8^X?LI55LZNnvUo@gHyaVW5Pt5cSR2@C(bFh+P9ysKF#scC z9g`F5vVK=b$JW-sRGI*GfvXrG{ z6W7^8(vmf_DVidOP44P<-WR^8EuC_h{Geya{61~PNjB??Qg_DTQAS2m zs$wB`mS}gY%2L;m6e@4aYAL5^YGk^#ea`#F<7iuJqP06yf7QFT{7C=aA0Fxw8Uv#J z3;i{jO61TI4H$#rX{z+A$~gc=|I`FT)M@=9J3Q<(UC8rl%HS4`gx)gI$@}PALChO{ z=Ua;o`huH+%~>V;%p74$pn%R++oJLq90T7E8^H8dKEJ(`ca%@a6*Bm?49}pvaGAUe zWmlR_1-d?Pr7^b+JO{2OCSXIJFcSJmugz_cCY;^8M?|blvXJ-MTfhRNu{1$+v8OyP zIeDE`t1OGxc0a&BB)#5lbaL_~-^=h@#v|#Ahzlow{{RV(^L_FvSMw`69+x!yxT4y3 zKJPUcZBNtQopmKyiBqaj!_D!T z_z?^6fl@-+(C_DVZK3EyyGwD_$-=3OaH?`xF4aVFi{}SfEnye1REUkqW2(noFtM-r z`7tFW+ohtRqmZ}K?$Q^>j)!h3A73qMU})ZqkJvscFOC{*+>)fs92uROA~GVQJLV8A zFE3{wW-qZSiKqUCVjLtSTq?4~Wgs1fEkKf_+aNNRH>z!Z;vtxkoxf(&;4GFc0uBkGar9YuBy_pF|V#( z(FwygppV1pzNcWA2^f$IQ9-a>aRo&V=Y{w#nJx}x8c5?{I^l%j(2 z-fyt~07d^vvS{M`kIKe>);j)AytCvMII)JPmMjOr> z%Z~WHOcOj~hY$bm2DyoNMf3>1U0ITqoRlqeh1q(l3>p;6Nq0lM)JAcpTRg0P8e6MK z;XG~!tU_4#(?Eap*5bS$9Qg$r8q-uuP}`3+#1hXL_byYv1zN7Hx$;fPqu;-rod*V1 zJ0Wamt3rmC4=#oiEJvgPas9t)dhvmQMDg)zm4;$1S6YW~Ahn=FQ&HYYN*^yE=O=AP zc3aUa6qTfM`3Y9g+&3^cUpqM*nqKrK)#!=@J42xS9W4yX<8JF_eL|9<_7J}Owtql^!z6&FrF9)^*YNH z+M#JZm7C&*VoA*cc=&i;@bMtaWMa}&b+ksZ_bwVmTQLn9Zwnh!A?jUnfunC5{GRrB zZY;ql#d^NDRc5XBejosJVW+6}#vFccZWE98-t#!w^dm6gGNM^*P5?9f^n5`n?D6Zo zJ>skSv$$_N-|dIl*;&lETGfKth7@CV7nfIlg%XU7O zcJr2KRs6t@rHZFf1QLwO*(g9)K3`ksjqQClYniV+c#w&x`0=!LTk2`x=s`|E7yjkk z91lN#n^*rfPpXmy#0~{8>k$p6NgB0tO&&RK`qmst(89(iPHv`bk)%QdOvOGy!|7K+ zdcG|>^$S!~Z<-&@%*G`qvRGODog_~l(rx+3Zjo`(!aJl$(wdJdiuE0xv437g4m>_L%zKHVig0u>4`2B*OLaUEkG-abD|N6S5k<# z8=U#k)F9OirIysVApSuT^RyI0qn)#m%@oG=5&4a?yD`nf>AVt3%5UXY_kw~OJn$&^ z9MC16BV<+P>y1J}FobmVmZ86segfHHxyQ}1m7QHhd8xgvwW*T;%8XK2m-oV_;4>RF zlJ36p5!TeaUAgXltc-v(o*x}%_T_>g^|sTkGQK29q6v9N!QYze>*{WrEbnemXvb$! zLq#LVt+&GM^Ef#mC-}98tpO+-9*J-#OQoO$J@>l)`D4`|)f2EUHUU9gO?IE09P{6{ zxQN-q8=b7OyMvRTrjS0*?JH#iSLd`8Fc6Ohp+~i>~Cmr|(20JAi$)ryC z@N(ItIzmmXtymPF_HJ^Cx_tg*@H8Fu-|AqKJ`L2YM2@%}N!eg7+n+K>Ts>PxL{+BW zofN|cvS2z-%JPd}diL<_Dm%k@q)Loh_3Vr%g5(>#K_W`}EnQ|co;y3z90p}`Ut~6D ze%BG^i0>u7;bK0*hoVD9@sEN!UJFSoYn`965*|pXl*Y%a$^_P;@CkoIXpQS#k+w~J zaFdYVE0i2yZ#Hx1F2>-hmJpmaHy?>A(x36mU;z8cJ=2KTrRVf<$i`NhRz}IZ>55Nu zb=dGr%=}_tW7&Qb&*feD(85uAsp>nv>6 z664<)8J8#Y|FU0k`PKFj9LO8z_uEf-@&f0{LmW@;&WTvSzj+|2!g&h?Y=;m-*YE`Nzbi6oAEH^)Z6tXYRvqMfd&((`7Ml zmCjxpm&v;GYJ_nN!M5pm@3y?P7ydtekbQWpT(~^`-W4u=?YFv zBU9>=KXL5|QU+N$Svfgbl@%43hd8^^|B)TH#xYf8H7@pKE)?*v?Kk}cC4jeY;s&xn zVxG_N;FpD2Yo-L{@vf(;6s@P4L|8#6L3qb%=OCEB?;88KTZ~QTx-%Z;dD=DqH^{5d z%iE2wzHN!iuCcTG8j(c3^i0pel6a)fiIMI-M|pU1T85@#=@Qhpxh4Wt^Y@PGzSSJA znXmB~&0%mn`s%hB@rP*LTfa!9M4Sy58F#~z2vvASD;6a!FB_JEa+_K`?_3>fomXax z<5$M|qO1ue!~z4M&wc#}=33Y<`*Kzr-S$~n6I3f0c_;YU@bu3lH{A-AvzT*|oA6yT zd3!7I*RZ|(9Z!2310%xvZTLJ#3EbdYYA7w^5QI>S!KUe^iCS}LM4|f9)*CEfURha- z>%0)wX@p$-h`|R#-81(}*kTCo(ZSJUH8Fa#q$k@v8>S=g_pztU9`) z{)xzr@6wBP>zLwkulNz8M>lqB{qUGA-wJyR1)QuPdReEOQUWw3d z6RmN>wPHgqqp8WMh-3BRbr>@<^NsmxWe7f%G1n)QTkz``)%k>~T_tjJ1x4(VA^7Ax zGkZ2RR3YOhgJ)65mu5TbQF?85vx1gcZDGZSv)sPw<5u;13y}yfd#)FJCuu7ha_mqS z-bL$hvSf%xd|7RMldH@`B^1|FITI9hx!I5C9f{RY4|d0q1Vm-8OioR?nw{Ho?B5?^ z8zztd;d;mdyy=23$tFE}em%ou+FE#EYp~b;H25d%;XnF}7Xe^pLlM^J>=J;aNp)c0 z80`XkF`EoPkwQdOBR@oej+}y=f`a^PGbi4C=j=k>A^Uuy_x$sY)*TNwf0TBJ^h3J< z{a#OnCSQL0Apw{n)FYaFLza$+lQBP76(AuE)t6alp$|&U2bMX@*;Nh@i(% z(a+fK8DY`54{s66$;qVMIRPlSYDrQ!Gvf*vh$3-Xx8KsbO(0fQD_6qu&mWV5Jm@|4 zu-`{1L>+{1<&{?Mh}sbNfrnbMmQjy`oAR*e>j9)>1jUHKcNk{H3Ed6H3Yr_TkmO{ysHQ z(Aapvm@o<9${bqgC@U}DYY31*>6tEdrxH1_^Id9ac_*NCs zk;>0AZ`3E%=Nn?b$hYM=ksV|@n%i35Alp|<$;M}FTrX-Id0lwD@c+>d?!rlT+EA^w zb4V_+sk=mNB|VFAzFYvp{rW`WblBeOzCPwpd`6=1K;1cARG>82=jgzZv!^#i@C!{V zTib5h)-g0Kvg>8mQ=~$NJR@U%+g_|GO3vbYZAUJ8#A;1hng#V(-yr$vX;zBzEHGg- zJq?CoQXaiz63-vU_YWXRHT68w2YJqHmTq!)yFZHGztlco<~>YHOFIDlwVTk7W{|fw zkhg3jiz=)G`ej$Ghq(`ni%Yzxit{aDSuS-hPWLS$^eDC|Jx)H5SP+HP@1Y4!wBh-T=U3#Gj#1BzvgDB4?M zpywz)w;`#GPc(vBJ$(HTm9`&YpdT93l89{EnjLI^#ZVab5^aql4;cCI;ZD3yd64?j z^remtxuWo$Dz5mphg75cCcuQio@~@fH41i=rzL zWbx46tEJ}j5QNnFy7rjObTrf#N4@m92baM36f^N+LWU)MhM85wEO`(4rxEteLD8-k+CKoKujK0TXa4ri;L0b-BL8e(=%BX|1Epc3;(^=Zl0*A39s6CV zR4yEkMqaLEVrI0cA}8z2($SM!sP+zQB0;pnI9Ti}#%evV+R=tbH5)*1$;`8Y%5})& z&m^pE*&^mdu8q2iduEl8UM1@K`YH*)%_*|q-=35)zh}p{q9|DXtjtDjVhXiQJiNS? zNM+$#M8k2)$m#atj(z6Rz9Er)%S|AdLGJqIy4tssjA-auFjQXZxC(aI-7E@it;6r znR9B|hra?WqS_D;DbP&Eu#l0PhYi^u=as+jG5tIvM!dhm;$@7>0MVj@5h|!Ny#$_~ z9QVGF!+_*~Wo3(3JsnUX;N(;zV0|7FK5T;0O^E>*ao`CDbOae#6-9gq!@87|yNs(Q z=Qcj_Un{P3sLD*EJYbYmp6o9FH_3;htDe8{>Y4mfjD?(n^OzUOe4iFYPO)n6POx9Q z;I^I`o8`feN6&X|r~dxpL!L4P7{MrUd5-%Ru-Y;TjSUTV_4oUI-RS+5@=<4WOy(W~ zc=l$VS@^eP6a!Fojjay&OE+r1dp!^haK6`s_NQz#=vg=@i~}T;j;#sEp#EDoV(yzI zB%~*lzC*grG84x-l8yTV{!K7KDMz<{pHZg}g-6dh|6bUCl8yc*Xn(KcUjoVh`QPU4 z-_N_NGQzx%`gRYX>$==C(4q4QkdWyAkN-P6&>iFqjDiZ0q8M>F6KIh})Th>H_`ARFAuFvURUz@#|9=4hgL~Nk literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/pull_request_card-dark.png b/testdata/snapshots/darwin/pull_request_card-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..353a57b29041813b8efe7893eb61fa31afd5580f GIT binary patch literal 28452 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 Beq{gv literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/review_comment-light.png b/testdata/snapshots/darwin/review_comment-light.png new file mode 100644 index 0000000000000000000000000000000000000000..67db2b53e740b737356068ef88201235bb0077b8 GIT binary patch literal 26334 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/stash_list-light.png b/testdata/snapshots/darwin/stash_list-light.png new file mode 100644 index 0000000000000000000000000000000000000000..6bb21d644734c4967450f91b55a99b1307f5a79f GIT binary patch literal 13563 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 Z4thIV=B7`}*q>1zyi-(HK!Uym{s&ibeCq%J literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/tag_list-light.png b/testdata/snapshots/darwin/tag_list-light.png new file mode 100644 index 0000000000000000000000000000000000000000..da5953d11a19f48a36d1a75b38c3ef1382cff4f1 GIT binary patch literal 8733 zcmd^@Wl&tto9_vbFu@^sa0^aw4=}+(a2ObZ1&81eBta&GK?V&TJh(Hs3;}{eu;A|Q z!DR;6`Th6a+I_LL?{3xB-BVqsx=-~vRsD3I=lOiUFf9#b0$dtg3=9l{H!2D`7#Nsf zbUzY+iN5m-%cWspFm1e1kk|7`KUg$#)CJN0IvM}G|IKNFpf-aY_qn8rKs!b_QAEe< zH*!%=iP%%G<$$hS;%iwyo)Q;olg4{mA=q=M07`{!e1;+)h!wFMnWkpThRRaNJPEIHA3l6m01iDJomKeTkt33VC z)Q(=+%kGz-rD>jKo^0cq4=d-UoMYqWF#fB(kLC2a&#d&*2C>U9K{CVu5+s`n3D2}O z6#nVd`e-O@N9zp}SA%&dB0#DU^h`3q&(L$gF3A{6p0Y~JxBqDm__yiJ1D;7s32t23 zK2VgL;I8wE8eOb)pMGM*2L7vcj0L~+@!Cj~@#WQb$iD%yaFOAAwaho&r4+i9nXtn# z|9u*ekw+U4iVBFByhXj`bzeu_4qjA^k51Lr+~k12_gg`U+2h|hqnz|WlfvrSWI^qW zS2ju@k*w*4GB0~Y#o&bjrzb6~4!lWwY!b^W(IK6&qg8WhNdr+R<#Aznug88kd3X-l zo=hdU>;}B6AhH4q6yCx5#$=R5yDa1EIBO%aWqJ2Bqo2o6GOHJT`-G zZ&mEf6K89GsF`-#LMhjUfF{$0$B!*XcVO^nhg5dxjO%fM=ko&%<@uB>%+n4(c3S$y zsyj}j&JvN*=bKA|cBz+_?VSy9V+RND#nAMNjmtrCDZ+)i%gmuP2EF~}k@R*($_r9Y!m{mT`CaN(&T#B34&O$N~ zj<*5_)C+C*t6oSJ+`R5OsPe=dd0`_q^f2 z$R9Ftq^}Ozth1OAx<37_-gbf9Pe&Z}@x{e;*V^gH$yfJX^-H?`$}s^q3l)n_NVCL| z5kW+SScREw*5_?t7wCBsu5x0T3YQuZ8>>`Z`w*)0COw& z!?U;u%tyP|$ZUUzi(lqO`c-E7^S--9kKvY?b(j{1>cgf1rMDPqN@U`rU-NQzoxK*> zFHy$Q(LcodDpPoR4afb&Dzs^X`&gk`mi_TU+G(CcO2i_4iw^?jdd%w4*Mm;G(j!-2 z(=zq^+oZjqEEz}Z+2T)IGlgt2U4Ge)hC4#}Amo}^N4r;9VN-J<55s1b$J^Gs5~i1T zYo~mE=XJg_nCn%S;3Kob>nbXVf;~!UzQq>#^`;$sgtxc9H!#5Mb$~i`b~aU2<B)aLP%I5E6Lc1VG3Lzflx+By14s9e|HmXwCjTt0j^;P z@dt~S(FcnR&DQZ;u|7v1$AXZ-owcDi*w~RCp1U#$BoUf)GMAN&;N|x|cGo4V!tZQ) z$SL9_WW@nYdU~$>{9$_sO=M)Ce=Y{78w6d#6qvIx zAU9eCQQfy*NWuo#vuYt1?9gCwammX=jI7?bs?vt~?{dWa8WW=krjjXzCnodLWeiMi z^s;O!897v5xuwQuWcc4H`92@$84l3y(;UA)_kwN5Aj~+D&qtPqXUqye$f!r)Zo1Q^K)XSO^lnDDKRaybM@9n zr+DHpO^gM4c{n5T2{9rJX`2^wHXZ3(shsu7Rl*78(S1>D>H7r3g%sxw_}G{}d6NEN z*d0pjk0{hs^Re|PWmnHCD{tHY-usvuu2+4C-H(%4{`}Z81~1cK>aUap{c40Owse%U zz1U)nBs}bBT{||z`=<1In1Vt+SnJbU(KL~>0ir>ZUe|Z?gC?|3OSnEK6{HIL6V{ZM zQh#*P{7M6|bpHsrbcSSvAP^ZwZQtN43%`G!oJUR^qR?Bv$3If%|kAH9Su)Xtp)!(CZb2|lCC!rh< z$drW;>IfPuSXAX9N|X!?dfVGIT3dHswS($&3{S}3YDX(DlUVe@gAVOnw$HAo>g%sg zPrI2(fIIDXKofr%(v_Rc{%ZO%J#Pq~iILb9BIB{|m z%MCMd#m#q|BKpN-a8dHdhj#pioHca0}De;tuzOM+hW5WBx451ooGumOq8rW94h`>(XB z+pH_kBYg*qMBOWu08Kn89xO*z0b}suv{pr(;>6^GpDBjAW`8Yd2t$#4J9mTry=IyG zbgaRTAH$UIxgmbuJAgpB8FGdO?pM)rjOd|?H^^N6QGNG32M`g2mE76i_&tRDoc;YJ zPppdGebMr)EfJBo)1kTd(E>S40W*+MOl;)Ow=H4kvZ(S4jOh?N2O=RsK|Rw@EfbRr zImREO_?4Kf5Yw9yk%7TTZUGYQ)86$lWw1bXWj%AOiYC2m60EXP>(wO}>h3D#Y&#`2 zt=ZS-9oQ%_@q9@coh;f?gvuP9q+j@oO^LnlR(&Zbnz<&m7=qsWa~|%*I$a&(1Htx1 z|G2`$@p}-D;RLT0bM2Fb;Ny4WPK(m)h)O;-z`Z%a={68}qIMsgSP*360->aNgQl%@%Q-AzR+v zqM#tOq&3QvH9#HwZ0T)oo}C%B#NJs;OwrsF|)yQD|#gKf8CDUx12x@S}D zR+Yu2B~%uQBUmG_d!ok$YSrN&4adhPuxxNl-P?{hq{jGZ{%0qtQw<+95hg6fotlxD zwCV~aE)1U3(UrB_mweD<=B_?-rWJ?fUn#{Gxa>*as!eQ-otJS-MN9V&3wgQkkg^8b z*eZ_Y=$zMX@;(#k12EN`-VQbPv zxoT^f-n4h3D7xZkF2;iJcyU^Wa*iAK^pqG_z=F)6VIv0I-?#Sn+v4FKMRZ&6B{%!@ zGw1Jr4I*-%?n1~h{=)qx$Jl(Ha9(0B9Miuvj=Cdjvz;Me0x;1MZf^+Qx8HS;u(NxL z)Riuq4Vc$RNlKEg5n6Dn7-%y1mc0L7U%v*6j#gnk0F?^s8YwIPO7=ubbCZ3#}YS%s?baNOd3mP8`>jdXxFGQ2zze;&;9C<|W8nJ+anF>{@F;AR?aQTdiR z_7=%uN{BAF%hboL8R9TfP4Q@t)CRlQCyH35*k8mlXXh>TCc?TZ;6}c>XPpr#LrBNO&OUMWfkLN+ zRaeM`s)>)RtgOU|)y&@C)hGNK-51A>LnPsWw3yX@H zKQ781z)4D?00+9Ou*Uh_l<*HbS3Jd8k5X56Iy~&7q0uSUQ&;D`%_UMF8mdY#2e_b+zn zA1ROR>*4g1yn~aQ4I#=AGcZ{-S?MEml;hrtMP(ci99qYxfR-+=h`A1@xMn+`)QC)H5<{Er0aOU0a>yvdm;h?fIBSXW6 zp&|86JYQ9kh;C2Mi{JYQ`nozupUY}xef{3S!A~y{U9a!X4sD-=p2zgI=|HiduoUW8 zm7l2rpVCVmn@B=C4QJ=9@(SD}(l6^TJAJPxQAveXHJLlR`vxF=Q2{Di!WYLHeEMbB zZyol3rZ3#e-mkce@3x`B$=l@Yaa_gIgA+kYdy0gi<5~t;zWbs{6~87H)L2PPS`zrk zaL+v4+fW-qe4&==4MPL{<)!7DZl98M0z~NSH4e7lEttA(+vw|BvNXqMxCsn(C|yp{ z`RPv8R}Y3DBw-41UQC;z>oBmoiyjCRreFb5WCIqVv}XfNnk5`X7uz#MJ5<8+TH+q9 zL={w>znM$&FRvpQN~~*pQJC5k8B2GC4J53I>U4}(WkYF*hR(9DxROs3gmrU1_m&*K zq~1M()@5U38Q~Qx_+3qWA~E}eI*%EPbWF`)1NJRAIS!wA(2czFq049>%o6o}9^rIC zDIh3HXiQ7nDDD#m{(BJx@QuP_BYpGh!0_>>PyMhLIF|BFdYDTmZ>0lpnaIfNXt?!( zdKbRKjOssbCh^YG%Y07H@Ndq|6_WOA zijMY*A-HE9uBez65>%4n3^1VJCz1-d?ki;IQt4W&TF+=6Kq^hcQV+7$#S0gV8rqg> zgNq7mUKchrG+gxU|Bl;a+SuCF)&;eABMD&&YZ9~1OOFD_2zdzc)WxYD`VjCR2 z+RNjG?oC(q!9n0MUNUcATQ#R6jtRR)5xi8Y(nBn3WLoScz~6;DX;doyN6wmv(_Yi~ zn-MDfWojV~y}hZKD6W!{C&F_pI0+apvD^D80zc!g7dV66L_a&En{g1v2zk@(KVw0@ zBY*g;?iKvjpkubq$XYp0Vto53OcAj7Ds|Aj4%yQhD)J?;vqf5tm0&!*!NYQH8(Bk` zN%|D3A8#yeFi_ExRV`Y(xyyhoBQTRh4$;f;1ia$jXu8wWOEt~5YIA=_Ev=QQ5!u&(4DplK9i!_bSz@K7rRo`? z)+3pRkW2m={3nmHVmenruo5h`3w-+ILRCFliw>AJw3`v65cN*^NKNeWn|4V9JhlV*8p8 znEdnz-iL*OaUJSosQ@_PhYd#)iilhUDwi?>iJ8KP6|URJR~<}Ppw|tLgH;b32r)4+ zE$p!GJ=>VD|GB!faQ`(8z>H1u6(A4&KX3gn82Vu;6n&Msc?cf;12#0}OH?JlWn0-L zB$PxTz%uB-{ofF{zyZ_*QD!bn7IL}Tb+sGJem(EgHSgUHl?7}lSgLsbQ}~v3Nc5AE zpZ~GTaztWse^cz~u0^MFMMv;MOrsVD88Z}}L#w{hhjqt|#f`;MY?0wU=GFyzdh!N- z5fc#T`NxY5;lLy`;312xEdmGfbOE({Ybba-SH-0Xxv@wH2}o4)b#B0wxh*Z%OLu66 z|JUc|@*p)JyY09miDGNps14zF!0WdrB&Sm+&DR-Ttj1&W71=87cB@6j@NO*}`-h3Z~hRH{19!y@! zlP-!t`Vp(L&JHZ2KFMk)Lo_Ri9>~=Pb>PG>hx9d{&wgvx>AOuNHR&D6zFs&;ptCfZZ;T}sy6nz2Kcv*U=P)%)RqsIc782@SR+ zK*(~igoL+PS&Vg!gn0VtcveEfM2qh_4=-;{j=}QK-Qir_^M~0+`{nyZa0?F&4b8L? zWI>1L)r6VvZWp6tkJjCvjhHM{Pdg)CL^C$i#x0J$^I@{Q z*=+%rh7CEg#JzEVr|*3Z25|8!{1Ll3f@KL_u|?Hp!^~D7Ndi}#$55fJ8Cao5;$bDup zM{u)Me~#@)=ELoPVj2BE`-#=u1e%}tR#wgi`B5Ph;J+VRQ|~YL5AA=%cjWas%m6TH zIHZLmQg<7*#igA$uwOh1eL)H!W0(50TD z-%lU$N_pFTu;=nz{VovghC^u9>Sx`f27&(BJm&_1CN(rHImmwFFtoyRa>jhI9PKOr z!#DVf_6;s#WcRqZGoz`@q1M^q;e`Mue*TdPgT4XZvHti%Zf+b>AqHrem> zVl$LS$1lO;!Zw-wz`n6gL$25<%H+un%4rJea{v(#5JhDzwJ?YB8=Ovx@1e{bp%U^& ze3+&oZVS5eJ%!7MHVFLYqGr?V;rm7hoaN0OW<<3V`LYk)r)_1$7NOHV;{gAzcZDUxCTAkyi4 zDhhy3HO7Q5)-7oC|D=7Htx;gszRA@o`yob8e>6AOd9={PO$x)tly`Q{%w`(0UjRQh z+P~)sLw~yT830>2^^yLUjS+6&=vP@@5^yQ?`wjaMS`3UY(~)4t4R7~vdWh>CuTbv- z6k<0m1Sf_(8OOb8TlQAcqBfmGK_RT+^H%?eXrfBc@+0RkbN3{3&Er_S*&B|rbVA*Uz17$ zvW-n9sG9O+vziJcG3w4gK7NFPY=JVO+nCS$B+ejayx%JBV2;Z%;KzQ`!P=N9<-oaW zysWmtvA;Y4de`=$a(X5Z7FY>9f@LMDcLrp&4O-%SN#hhj%>3cov`zX(^_;FO@^UT7 zzg@Xr=67G~-LlXq^$Sn6D6V6&bkjPw!$jSQRYY3`;w7?_sEVC@=0>CXoC=;Th0l~{ zZRPsQmb0e7G`;{Xd~@837THJHnSLLHMO8(AlSOoMvrOX$TX#$|0ioYgy8F;(P9oxO zKtO=|T0a^|Itfhi7jFeU^yS=7XAjEenPUM=!X7pl`s4h!x3_v+`Bf*~m@coU_kQH( zKh|f&!;6T$IwBVp7Jdhg^ozBeWWhlf-8B)M!n(tyrni}^@?6*=v(!H+K&=PfXkk6I z5eUJdEaK);2 ztvTglz2a`wGc%rAx*l{J{s{dh3BuB347V7HB=^sNjoPgRT~qLl z*|C!QQE_b@I<7 z{i@1HxNLsKo6!crt+kLpc+hzmixS5Y{-^CN zl)qVvITm{`6Z9=PIo-$oCB;E1M(^XF>&ZUGmmcBa@1n@LnYi5jZEU7iS#S!}(@^Gv z25rqq)7avkho3qO&u3f5)!SSS2dz?&HydVY3&c&TjN;-ngvk&+ir4*-WIc z3X`GQ`ucP!7m6u#D*p9=Astw`lBPKVIrl^t4A5j){1i|9_m_lB8_29Mk7G!y%O2_M z&*c2sjz(TUcGcP4emFfHk!h#_6C3yy)FH@4hA`ZVqgdN_dpOM@3AJZWHTml#vuW5>FqfXLG z;NuR&J@!uVs;o4KIW+SqNCzNmlFV7~|6*h6Pr0CvGrB;rt21!>y!AOps(T<Wm?c!D0{R-T<5E5}Gh zh2Q%RV0{sbY-8-0mK2$zOMRERzPMOr@F3lCU%){aT2tlk1}T#MY)H&xWo0$9E`px^ zmmlLn)<+ZF!=MuU^1lj@|KAA$zaWKc$iZ}bL8ly9@2c8Dn$;xf>HRSXu~YH!+3O-N zf&BD44)eY%v!SPkkbrP45-y-(5r90KSr7W(4(RIvx_iwPUDoJ-clbADaRw8Lp^z8u zmXeYpQeD02NmVHBa77t2m$AJW(EQVEMCW5R-$XD%i*m0+AMr9jfU0o(XIJQ4KB}>2 zesJ)>bsvHvf-+(=0ptNd;;+R2zja+-0A#T+#_f$MEQr4L{d2_MC~7EF0N;Q8H?0Zs AM*si- literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/three_way_merge-dark.png b/testdata/snapshots/darwin/three_way_merge-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a18d9901a3c5d9357acde0095c124be1cd4da223 GIT binary patch literal 22445 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 literal 0 HcmV?d00001 diff --git a/three_way_merge.go b/three_way_merge.go new file mode 100644 index 0000000..7a7ab59 --- /dev/null +++ b/three_way_merge.go @@ -0,0 +1,327 @@ +package mujica + +import ( + "fmt" + "log/slog" + "slices" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// MergeChoice is how a conflict is resolved. +type MergeChoice int + +const ( + MergeUnresolved MergeChoice = iota + // MergeOurs takes the local (current) side. + MergeOurs + // MergeTheirs takes the remote (incoming) side. + MergeTheirs + // MergeBoth takes ours, then theirs. + MergeBoth + // MergeBase keeps the common ancestor. + MergeBase +) + +// mergeChunk is a merge run; stable when all three agree. +type mergeChunk struct { + base, ours, theirs []string + conflict bool + // auto is the merged text of a non-conflicting change. + auto []string + stable bool +} + +// ThreeWayMergeState holds a merge's chunks and conflict choices. +type ThreeWayMergeState struct { + list ui.ListState + base, ours, theirs string + chunks []mergeChunk + choices []MergeChoice + built bool +} + +// Resolved returns chosen conflicts and all conflicts. +func (s *ThreeWayMergeState) Resolved() (done, total int) { + for i, ch := range s.chunks { + if ch.conflict { + total++ + if s.choices[i] != MergeUnresolved { + done++ + } + } + } + return done, total +} + +// Result is the merged text; unresolved conflicts keep conflict markers. +func (s *ThreeWayMergeState) Result() string { + var out []string + for i, ch := range s.chunks { + out = append(out, mergeChunkText(ch, s.choices[i])...) + } + return strings.Join(out, "\n") +} + +func mergeChunkText(ch mergeChunk, choice MergeChoice) []string { + switch { + case ch.stable: + return ch.base + case !ch.conflict: + return ch.auto + } + switch choice { + case MergeOurs: + return ch.ours + case MergeTheirs: + return ch.theirs + case MergeBoth: + return slices.Concat(ch.ours, ch.theirs) + case MergeBase: + return ch.base + } + return slices.Concat([]string{"<<<<<<< ours"}, ch.ours, []string{"======="}, ch.theirs, []string{">>>>>>> theirs"}) +} + +// ThreeWayMergeOptions configure a ThreeWayMerge. +type ThreeWayMergeOptions struct { + Disabled bool +} + +// ThreeWayMerge shows four columns per chunk; give it a height. +func ThreeWayMerge(c *ui.Context, s *ThreeWayMergeState, base, ours, theirs string, opts ThreeWayMergeOptions) ChoiceResult { + if !s.built || s.base != base || s.ours != ours || s.theirs != theirs { + s.chunks = mergeChunks(internal.SplitLines(base), internal.SplitLines(ours), internal.SplitLines(theirs)) + s.choices = make([]MergeChoice, len(s.chunks)) + s.base, s.ours, s.theirs, s.built = base, ours, theirs, true + _, total := s.Resolved() + slog.Debug("mujica: three way merge chunks", "chunks", len(s.chunks), "conflicts", total) + } + k := Tokens(c) + u := Density(c).Unit() + col := ui.Column(c).AlignItems(ui.Stretch).Disabled(opts.Disabled).Background(k.Surface). + Border(theme.BorderWidth, k.Border).Radius(theme.ControlRadius).Clip() + res := ChoiceResult{Element: col} + col.Children(func() { + done, total := s.Resolved() + ui.Row(c).AlignItems(ui.Center).Gap(u*3).Padding(u*2, u*3).Background(k.Background).Children(func() { + ui.Text(c, fmt.Sprintf(msg(c, "three_way_merge.resolved"), done, total)).FontWeight(600).Role(ui.RoleStatus) + }) + ui.Grid(c).ColumnTracks(ui.Fr(1), ui.Fr(1), ui.Fr(1), ui.Fr(1)).Background(k.Background).Children(func() { + for _, key := range []string{"ours", "base", "theirs", "result"} { + ui.Text(c, msg(c, "three_way_merge."+key)).Font(theme.SerifFont).FontSize(FontSize(c, theme.CaptionSize)). + TextColor(k.Ornament.Mix(k.Text, 0.35)).Padding(u, u*3) + } + }) + ui.List(c, &s.list, len(s.chunks), func(i int) { + if threeWayMergeChunk(c, s, i) && !col.IsDisabled() { + res.changed = true + } + }).Grow(1) + }) + return res +} + +// threeWayMergeChunk builds chunk i and reports a new choice. +func threeWayMergeChunk(c *ui.Context, s *ThreeWayMergeState, i int) bool { + k := Tokens(c) + u := Density(c).Unit() + ch := s.chunks[i] + changed := false + ui.Column(c).AlignItems(ui.Stretch).Children(func() { + grid := ui.Grid(c).ColumnTracks(ui.Fr(1), ui.Fr(1), ui.Fr(1), ui.Fr(1)) + grid.Draw(func(p *ui.Painter, r ui.Rect) { p.Fill(ui.Rect{X: r.X, Y: r.Y, W: r.W, H: 1}, k.Border, 0) }) + grid.Children(func() { + tint := func(lines []string, col ui.Color, on bool) { + cell := ui.Column(c).Padding(u, u*3).MinWidth(0).Clip() + if on { + cell.Background(col.Mix(k.Surface, 0.88)) + } + cell.Children(func() { mergeLines(c, lines, ch.stable) }) + } + if ch.stable { + tint(ch.base, k.Text, false) + tint(ch.base, k.Text, false) + tint(ch.base, k.Text, false) + tint(ch.base, k.Text, false) + return + } + choice := s.choices[i] + tint(ch.ours, k.Info, ch.conflict && (choice == MergeOurs || choice == MergeBoth) || !ch.conflict && slices.Equal(ch.auto, ch.ours)) + tint(ch.base, k.TextMuted, choice == MergeBase) + tint(ch.theirs, k.Warning, ch.conflict && (choice == MergeTheirs || choice == MergeBoth) || !ch.conflict && slices.Equal(ch.auto, ch.theirs)) + result := ui.Column(c).Padding(u, u*3).MinWidth(0).Clip() + result.Children(func() { + if ch.conflict && choice == MergeUnresolved { + ui.Row(c).Gap(u).AlignItems(ui.Center).TextColor(k.Danger).Children(func() { + ui.Icon(c, icons.Must("triangle-alert")).Size(14, 14) + ui.Text(c, msg(c, "three_way_merge.unresolved")).FontSize(FontSize(c, theme.CaptionSize)) + }) + return + } + mergeLines(c, mergeChunkText(ch, choice), false) + }) + }) + if !ch.conflict { + return + } + ui.Row(c).Gap(u*2).Padding(u, u*3, u*2, u*3).Wrap().Children(func() { + for _, opt := range []struct { + choice MergeChoice + key string + }{{MergeOurs, "take_ours"}, {MergeTheirs, "take_theirs"}, {MergeBoth, "take_both"}, {MergeBase, "take_base"}} { + if mergeChoiceButton(c, msg(c, "three_way_merge."+opt.key), s.choices[i] == opt.choice).Clicked() && s.choices[i] != opt.choice { + s.choices[i], changed = opt.choice, true + slog.Debug("mujica: three way merge choose", "chunk", i, "choice", opt.key) + } + } + }) + }) + return changed +} + +// mergeChoiceButton is a toggle marking the chosen side. +func mergeChoiceButton(c *ui.Context, label string, on bool) *ui.Element { + k := Tokens(c) + u := Density(c).Unit() + b := ui.ButtonBase(c).MinHeight(theme.MinHitSize).Padding(0, u*3).Gap(u*1.5).Radius(theme.ControlRadius). + Border(theme.BorderWidth, k.ControlBorder).Label(label).TextColor(k.Text) + internal.Ring(b, k.Focus, theme.ControlRadius) + switch { + case on: + b.Background(k.Selection).Border(theme.BorderWidth, k.AccentText).FontWeight(600) + case b.Pressed(): + b.Background(k.Selection) + case b.Hovered(): + b.Background(k.SurfaceHover) + } + b.Transition(colorFade) + b.Children(func() { + if on { + ui.Icon(c, icons.Must("check")).Size(14, 14).TextColor(k.AccentText) + } + ui.Text(c, label).FontSize(FontSize(c, theme.CaptionSize)).SingleLine() + }) + return b +} + +// mergeLines shows code lines, folding long stable runs. +func mergeLines(c *ui.Context, lines []string, fold bool) { + k := Tokens(c) + show := func(ls []string) { + for _, l := range ls { + if l == "" { + l = " " + } + t := ui.Text(c, l).Font(theme.MonoFont).NoWrap().FontSize(FontSize(c, theme.CaptionSize)) + if fold { + t.TextColor(k.TextMuted) + } + } + } + if len(lines) == 0 { + ui.Text(c, "∅").TextColor(k.TextMuted).Label(msg(c, "three_way_merge.empty")) + return + } + if !fold || len(lines) <= 5 { + show(lines) + return + } + show(lines[:2]) + ui.Text(c, fmt.Sprintf(msg(c, "diff_viewer.fold"), len(lines)-4)).Font(theme.SerifFont). + FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + show(lines[len(lines)-2:]) +} + +// mergeHunk replaces base lines [from, to) with lines. +type mergeHunk struct { + from, to int + lines []string +} + +// mergeHunks lists the changes a diff makes to base. +func mergeHunks(d []internal.DiffLine) []mergeHunk { + var out []mergeHunk + at, open := 0, -1 + for _, l := range d { + if l.Op == internal.DiffEqual { + at = l.Old + open = -1 + continue + } + if open < 0 { + out = append(out, mergeHunk{from: at, to: at}) + open = len(out) - 1 + } + h := &out[open] + if l.Op == internal.DiffDelete { + h.to = l.Old + } else { + h.lines = append(h.lines, l.Text) + } + } + return out +} + +// mergeChunks splits a merge into stable, clean and conflicting runs. +func mergeChunks(base, ours, theirs []string) []mergeChunk { + type tagged struct { + mergeHunk + side int + } + var all []tagged + for side, other := range [][]string{ours, theirs} { + for _, h := range mergeHunks(internal.LineDiff(base, other)) { + all = append(all, tagged{h, side}) + } + } + slices.SortStableFunc(all, func(a, b tagged) int { return a.from - b.from }) + var chunks []mergeChunk + at := 0 + for i := 0; i < len(all); { + from, to := all[i].from, all[i].to + j := i + 1 + for j < len(all) && (all[j].from < to || all[j].from == to && (all[j].from == all[j].to || from == to)) { + to = max(to, all[j].to) + j++ + } + if from > at { + chunks = append(chunks, mergeChunk{base: base[at:from], stable: true}) + } + sides := [2][]string{} + touched := [2]bool{} + for s := range 2 { + cur := from + for _, h := range all[i:j] { + if h.side != s { + continue + } + touched[s] = true + sides[s] = append(sides[s], base[cur:h.from]...) + sides[s] = append(sides[s], h.lines...) + cur = h.to + } + sides[s] = append(sides[s], base[cur:to]...) + } + ch := mergeChunk{base: base[from:to], ours: sides[0], theirs: sides[1]} + switch { + case !touched[1]: + ch.auto = ch.ours + case !touched[0], slices.Equal(ch.ours, ch.theirs): + ch.auto = ch.theirs + default: + ch.conflict = true + } + chunks = append(chunks, ch) + at, i = to, j + } + if at < len(base) { + chunks = append(chunks, mergeChunk{base: base[at:], stable: true}) + } + return chunks +} diff --git a/three_way_merge_test.go b/three_way_merge_test.go new file mode 100644 index 0000000..87e7551 --- /dev/null +++ b/three_way_merge_test.go @@ -0,0 +1,80 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +const ( + mergeBase = "a\nb\nc\nd\ne\nf" + mergeOurs = "a\nB1\nc\nd\ne\nf\ng" + mergeTheirs = "a\nB2\nc\nD\ne\nf" +) + +func TestMergeChunks(t *testing.T) { + chunks := mergeChunks([]string{"a", "b", "c", "d", "e", "f"}, []string{"a", "B1", "c", "d", "e", "f", "g"}, []string{"a", "B2", "c", "D", "e", "f"}) + // a | b conflict | c | d→D clean | e f | +g clean + if len(chunks) != 6 { + t.Fatalf("%d chunks: %+v", len(chunks), chunks) + } + if !chunks[1].conflict || chunks[1].ours[0] != "B1" || chunks[1].theirs[0] != "B2" { + t.Errorf("conflict chunk %+v", chunks[1]) + } + if chunks[3].conflict || chunks[3].auto[0] != "D" { + t.Errorf("clean remote change %+v", chunks[3]) + } + if chunks[5].conflict || len(chunks[5].auto) != 1 || chunks[5].auto[0] != "g" { + t.Errorf("clean local append %+v", chunks[5]) + } + same := mergeChunks([]string{"x"}, []string{"y"}, []string{"y"}) + if len(same) != 1 || same[0].conflict { + t.Errorf("identical changes conflict: %+v", same) + } +} + +func TestThreeWayMergeTakeSides(t *testing.T) { + var s ThreeWayMergeState + changes := 0 + disabled := false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := ThreeWayMerge(c, &s, mergeBase, mergeOurs, mergeTheirs, ThreeWayMergeOptions{Disabled: disabled}) + r.Element.Height(560) + if r.Changed() { + changes++ + } + }, 900, 600) + if !tt.HasText("0 of 1 conflicts resolved") || !tt.HasText("Unresolved") { + t.Fatalf("start: %q", tt.Texts()) + } + if got := s.Result(); got != "a\n<<<<<<< ours\nB1\n=======\nB2\n>>>>>>> theirs\nc\nD\ne\nf\ng" { + t.Fatalf("unresolved result %q", got) + } + if err := tt.Click("Take remote"); err != nil { + t.Fatal(err) + } + if s.Result() != "a\nB2\nc\nD\ne\nf\ng" || changes != 1 || !tt.HasText("1 of 1 conflicts resolved") { + t.Fatalf("take remote: %q changes %d", s.Result(), changes) + } + tt.Key(0, ui.KeyTab) + _ = tt.Click("Take both") + if s.Result() != "a\nB1\nB2\nc\nD\ne\nf\ng" { + t.Fatalf("take both: %q", s.Result()) + } + disabled = true + tt.Frame() + _ = tt.Click("Keep base") + if s.Result() != "a\nB1\nB2\nc\nD\ne\nf\ng" || changes != 2 { + t.Fatalf("disabled merge changed: %q", s.Result()) + } +} + +func TestThreeWayMergeSnapshot(t *testing.T) { + snapshot(t, "three_way_merge", 860, 420, func(c *ui.Context) { + s := ui.Local(c.Root(), "m", func() *ThreeWayMergeState { return &ThreeWayMergeState{} }) + ui.Column(c).Padding(16).Children(func() { + ThreeWayMerge(c, *s, mergeBase, mergeOurs, mergeTheirs, ThreeWayMergeOptions{}).Element.Height(380) + }) + }) +} From 85575ea2e2f66e74d70e09e6e2625599c706c191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 5 Oct 2026 14:33:40 -0400 Subject: [PATCH 09/13] Media: components 341-360 --- audio_player.go | 84 +++++ audio_player_test.go | 89 ++++++ audio_spectrum.go | 146 +++++++++ audio_spectrum_test.go | 74 +++++ audio_waveform.go | 187 +++++++++++ audio_waveform_test.go | 131 ++++++++ camera_preview.go | 93 ++++++ camera_preview_test.go | 86 ++++++ device_selector.go | 78 +++++ device_selector_test.go | 74 +++++ docs/components/341-image-cropper.md | 55 ++++ docs/components/342-image-annotator.md | 59 ++++ docs/components/343-image-thumbnail.md | 54 ++++ docs/components/344-lightbox.md | 53 ++++ docs/components/345-video-player.md | 59 ++++ docs/components/346-video-scrubber.md | 56 ++++ docs/components/347-video-thumbnail-strip.md | 51 +++ docs/components/348-audio-player.md | 51 +++ docs/components/349-audio-waveform.md | 58 ++++ docs/components/350-audio-spectrum.md | 49 +++ docs/components/351-volume-control.md | 46 +++ docs/components/352-playback-speed-control.md | 48 +++ docs/components/353-media-controls.md | 53 ++++ docs/components/354-playlist.md | 52 ++++ docs/components/355-subtitle-editor.md | 52 ++++ .../356-screen-recorder-controls.md | 51 +++ docs/components/357-camera-preview.md | 48 +++ docs/components/358-mic-level-meter.md | 45 +++ docs/components/359-device-selector.md | 51 +++ docs/components/360-image-compare.md | 48 +++ example_media_test.go | 246 +++++++++++++++ examples/gallery/pages_media.go | 117 ++++++- examples/gallery/pages_media_av.go | 191 ++++++++++++ examples/gallery/pages_media_code.go | 178 +++++++++++ examples/gallery/pages_media_devices.go | 225 ++++++++++++++ examples/gallery/pages_media_image.go | 162 ++++++++++ image_annotator.go | 292 ++++++++++++++++++ image_annotator_test.go | 121 ++++++++ image_compare.go | 74 +++++ image_compare_test.go | 73 +++++ image_cropper.go | 245 +++++++++++++++ image_cropper_geom.go | 81 +++++ image_cropper_test.go | 101 ++++++ image_thumbnail.go | 87 ++++++ image_thumbnail_test.go | 82 +++++ lightbox.go | 89 ++++++ lightbox_test.go | 66 ++++ media_controls.go | 77 +++++ media_controls_test.go | 91 ++++++ media_helpers_test.go | 44 +++ media_icons.go | 53 ++++ media_palette_test.go | 24 ++ messages_media.go | 106 +++++++ mic_level_meter.go | 101 ++++++ mic_level_meter_test.go | 62 ++++ playback_speed_control.go | 46 +++ playback_speed_control_test.go | 77 +++++ playlist.go | 159 ++++++++++ playlist_test.go | 123 ++++++++ screen_recorder_controls.go | 76 +++++ screen_recorder_controls_test.go | 75 +++++ subtitle_editor.go | 244 +++++++++++++++ subtitle_editor_test.go | 131 ++++++++ .../snapshots/darwin/audio_player-dark.png | Bin 0 -> 10475 bytes .../snapshots/darwin/audio_player-light.png | Bin 0 -> 10039 bytes .../snapshots/darwin/audio_spectrum-dark.png | Bin 0 -> 1666 bytes .../snapshots/darwin/audio_spectrum-light.png | Bin 0 -> 1673 bytes .../snapshots/darwin/audio_waveform-dark.png | Bin 0 -> 3181 bytes .../snapshots/darwin/audio_waveform-light.png | Bin 0 -> 3221 bytes .../snapshots/darwin/camera_preview-dark.png | Bin 0 -> 5170 bytes .../snapshots/darwin/camera_preview-light.png | Bin 0 -> 5182 bytes .../snapshots/darwin/device_selector-dark.png | Bin 0 -> 12843 bytes .../darwin/device_selector-light.png | Bin 0 -> 12358 bytes .../snapshots/darwin/image_annotator-dark.png | Bin 0 -> 8632 bytes .../darwin/image_annotator-light.png | Bin 0 -> 8595 bytes .../snapshots/darwin/image_compare-dark.png | Bin 0 -> 3694 bytes .../snapshots/darwin/image_compare-light.png | Bin 0 -> 3606 bytes .../snapshots/darwin/image_cropper-dark.png | Bin 0 -> 5969 bytes .../snapshots/darwin/image_cropper-light.png | Bin 0 -> 5790 bytes .../snapshots/darwin/image_thumbnail-dark.png | Bin 0 -> 4517 bytes .../darwin/image_thumbnail-light.png | Bin 0 -> 4442 bytes testdata/snapshots/darwin/lightbox-dark.png | Bin 0 -> 6197 bytes testdata/snapshots/darwin/lightbox-light.png | Bin 0 -> 6272 bytes .../snapshots/darwin/media_controls-dark.png | Bin 0 -> 3633 bytes .../snapshots/darwin/media_controls-light.png | Bin 0 -> 3548 bytes .../snapshots/darwin/mic_level_meter-dark.png | Bin 0 -> 3704 bytes .../darwin/mic_level_meter-light.png | Bin 0 -> 3654 bytes .../darwin/playback_speed_control-dark.png | Bin 0 -> 1584 bytes .../darwin/playback_speed_control-light.png | Bin 0 -> 1520 bytes testdata/snapshots/darwin/playlist-dark.png | Bin 0 -> 12296 bytes testdata/snapshots/darwin/playlist-light.png | Bin 0 -> 12010 bytes .../darwin/screen_recorder_controls-dark.png | Bin 0 -> 10125 bytes .../darwin/screen_recorder_controls-light.png | Bin 0 -> 10021 bytes .../snapshots/darwin/subtitle_editor-dark.png | Bin 0 -> 20314 bytes .../darwin/subtitle_editor-light.png | Bin 0 -> 19550 bytes .../snapshots/darwin/video_player-dark.png | Bin 0 -> 9864 bytes .../snapshots/darwin/video_player-light.png | Bin 0 -> 9732 bytes .../snapshots/darwin/video_scrubber-dark.png | Bin 0 -> 1132 bytes .../snapshots/darwin/video_scrubber-light.png | Bin 0 -> 1002 bytes .../darwin/video_thumbnail_strip-dark.png | Bin 0 -> 3371 bytes .../darwin/video_thumbnail_strip-light.png | Bin 0 -> 3355 bytes .../snapshots/darwin/volume_control-dark.png | Bin 0 -> 2270 bytes .../snapshots/darwin/volume_control-light.png | Bin 0 -> 2182 bytes video_player.go | 162 ++++++++++ video_player_test.go | 120 +++++++ video_scrubber.go | 118 +++++++ video_scrubber_test.go | 91 ++++++ video_thumbnail_strip.go | 116 +++++++ video_thumbnail_strip_test.go | 102 ++++++ volume_control.go | 49 +++ volume_control_test.go | 74 +++++ 111 files changed, 6831 insertions(+), 1 deletion(-) create mode 100644 audio_player.go create mode 100644 audio_player_test.go create mode 100644 audio_spectrum.go create mode 100644 audio_spectrum_test.go create mode 100644 audio_waveform.go create mode 100644 audio_waveform_test.go create mode 100644 camera_preview.go create mode 100644 camera_preview_test.go create mode 100644 device_selector.go create mode 100644 device_selector_test.go create mode 100644 docs/components/341-image-cropper.md create mode 100644 docs/components/342-image-annotator.md create mode 100644 docs/components/343-image-thumbnail.md create mode 100644 docs/components/344-lightbox.md create mode 100644 docs/components/345-video-player.md create mode 100644 docs/components/346-video-scrubber.md create mode 100644 docs/components/347-video-thumbnail-strip.md create mode 100644 docs/components/348-audio-player.md create mode 100644 docs/components/349-audio-waveform.md create mode 100644 docs/components/350-audio-spectrum.md create mode 100644 docs/components/351-volume-control.md create mode 100644 docs/components/352-playback-speed-control.md create mode 100644 docs/components/353-media-controls.md create mode 100644 docs/components/354-playlist.md create mode 100644 docs/components/355-subtitle-editor.md create mode 100644 docs/components/356-screen-recorder-controls.md create mode 100644 docs/components/357-camera-preview.md create mode 100644 docs/components/358-mic-level-meter.md create mode 100644 docs/components/359-device-selector.md create mode 100644 docs/components/360-image-compare.md create mode 100644 example_media_test.go create mode 100644 examples/gallery/pages_media_av.go create mode 100644 examples/gallery/pages_media_code.go create mode 100644 examples/gallery/pages_media_devices.go create mode 100644 examples/gallery/pages_media_image.go create mode 100644 image_annotator.go create mode 100644 image_annotator_test.go create mode 100644 image_compare.go create mode 100644 image_compare_test.go create mode 100644 image_cropper.go create mode 100644 image_cropper_geom.go create mode 100644 image_cropper_test.go create mode 100644 image_thumbnail.go create mode 100644 image_thumbnail_test.go create mode 100644 lightbox.go create mode 100644 lightbox_test.go create mode 100644 media_controls.go create mode 100644 media_controls_test.go create mode 100644 media_helpers_test.go create mode 100644 media_icons.go create mode 100644 media_palette_test.go create mode 100644 messages_media.go create mode 100644 mic_level_meter.go create mode 100644 mic_level_meter_test.go create mode 100644 playback_speed_control.go create mode 100644 playback_speed_control_test.go create mode 100644 playlist.go create mode 100644 playlist_test.go create mode 100644 screen_recorder_controls.go create mode 100644 screen_recorder_controls_test.go create mode 100644 subtitle_editor.go create mode 100644 subtitle_editor_test.go create mode 100644 testdata/snapshots/darwin/audio_player-dark.png create mode 100644 testdata/snapshots/darwin/audio_player-light.png create mode 100644 testdata/snapshots/darwin/audio_spectrum-dark.png create mode 100644 testdata/snapshots/darwin/audio_spectrum-light.png create mode 100644 testdata/snapshots/darwin/audio_waveform-dark.png create mode 100644 testdata/snapshots/darwin/audio_waveform-light.png create mode 100644 testdata/snapshots/darwin/camera_preview-dark.png create mode 100644 testdata/snapshots/darwin/camera_preview-light.png create mode 100644 testdata/snapshots/darwin/device_selector-dark.png create mode 100644 testdata/snapshots/darwin/device_selector-light.png create mode 100644 testdata/snapshots/darwin/image_annotator-dark.png create mode 100644 testdata/snapshots/darwin/image_annotator-light.png create mode 100644 testdata/snapshots/darwin/image_compare-dark.png create mode 100644 testdata/snapshots/darwin/image_compare-light.png create mode 100644 testdata/snapshots/darwin/image_cropper-dark.png create mode 100644 testdata/snapshots/darwin/image_cropper-light.png create mode 100644 testdata/snapshots/darwin/image_thumbnail-dark.png create mode 100644 testdata/snapshots/darwin/image_thumbnail-light.png create mode 100644 testdata/snapshots/darwin/lightbox-dark.png create mode 100644 testdata/snapshots/darwin/lightbox-light.png create mode 100644 testdata/snapshots/darwin/media_controls-dark.png create mode 100644 testdata/snapshots/darwin/media_controls-light.png create mode 100644 testdata/snapshots/darwin/mic_level_meter-dark.png create mode 100644 testdata/snapshots/darwin/mic_level_meter-light.png create mode 100644 testdata/snapshots/darwin/playback_speed_control-dark.png create mode 100644 testdata/snapshots/darwin/playback_speed_control-light.png create mode 100644 testdata/snapshots/darwin/playlist-dark.png create mode 100644 testdata/snapshots/darwin/playlist-light.png create mode 100644 testdata/snapshots/darwin/screen_recorder_controls-dark.png create mode 100644 testdata/snapshots/darwin/screen_recorder_controls-light.png create mode 100644 testdata/snapshots/darwin/subtitle_editor-dark.png create mode 100644 testdata/snapshots/darwin/subtitle_editor-light.png create mode 100644 testdata/snapshots/darwin/video_player-dark.png create mode 100644 testdata/snapshots/darwin/video_player-light.png create mode 100644 testdata/snapshots/darwin/video_scrubber-dark.png create mode 100644 testdata/snapshots/darwin/video_scrubber-light.png create mode 100644 testdata/snapshots/darwin/video_thumbnail_strip-dark.png create mode 100644 testdata/snapshots/darwin/video_thumbnail_strip-light.png create mode 100644 testdata/snapshots/darwin/volume_control-dark.png create mode 100644 testdata/snapshots/darwin/volume_control-light.png create mode 100644 video_player.go create mode 100644 video_player_test.go create mode 100644 video_scrubber.go create mode 100644 video_scrubber_test.go create mode 100644 video_thumbnail_strip.go create mode 100644 video_thumbnail_strip_test.go create mode 100644 volume_control.go create mode 100644 volume_control_test.go diff --git a/audio_player.go b/audio_player.go new file mode 100644 index 0000000..144976a --- /dev/null +++ b/audio_player.go @@ -0,0 +1,84 @@ +package mujica + +import ( + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// AudioState is what the caller's playback reports. +type AudioState struct { + Title string + Position time.Duration + Duration time.Duration + Playing bool +} + +// AudioPlayerOptions are the callbacks a player shell reports to. +type AudioPlayerOptions struct { + OnPlay, OnPause func() + OnSeek func(time.Duration) + Disabled bool +} + +// AudioPlayer is a play, pause and seek shell. +func AudioPlayer(c *ui.Context, st AudioState, opts AudioPlayerOptions) *ui.Element { + if opts.OnPlay == nil || opts.OnPause == nil || opts.OnSeek == nil { + panic("mujica: AudioPlayer needs OnPlay, OnPause and OnSeek") + } + k := Tokens(c) + u := Density(c).Unit() + row := ui.Row(c).Gap(u*3).AlignItems(ui.Center).MinHeight(Density(c).ControlHeight()).Padding(u*2, u*3). + Radius(theme.CardRadius).Background(k.Surface).Border(theme.BorderWidth, k.Border).Role(ui.RoleGroup). + Disabled(opts.Disabled) + if st.Title != "" { + row.Label(st.Title) + } + row.Children(func() { + mediaPlayToggle(c, st.Playing, opts.OnPlay, opts.OnPause) + ui.Column(c).Grow(1).MinWidth(0).Gap(2).Children(func() { + if st.Title != "" { + ui.Text(c, st.Title).SingleLine() + } + if st.Duration > 0 { + pos := min(max(0, st.Position), st.Duration) + if VideoScrubber(c, &pos, VideoScrubberOptions{Duration: st.Duration, Label: st.Title}).Changed() { + opts.OnSeek(pos) + } + } + }) + ui.Text(c, mediaClock(st.Position)+" / "+mediaClock(st.Duration)).FontSize(FontSize(c, theme.CaptionSize)). + TextColor(k.TextMuted).FontFeatures("tnum").SingleLine() + }) + // Space plays or pauses wherever the focus is inside. + if !row.IsDisabled() && row.Shortcut(0, ui.KeySpace) { + mediaToggle(st.Playing, opts.OnPlay, opts.OnPause) + } + return row +} + +// mediaPlayToggle is the play/pause button; it calls the matching callback. +func mediaPlayToggle(c *ui.Context, playing bool, onPlay, onPause func()) *ui.Element { + icon, label := mediaPlay, msg(c, "media_controls.play") + if playing { + icon, label = mediaPause, msg(c, "media_controls.pause") + } + b := IconButton(c, icon, label, IconButtonOptions{}) + if b.Clicked() && !b.IsDisabled() { + mediaToggle(playing, onPlay, onPause) + } + return b +} + +func mediaToggle(playing bool, onPlay, onPause func()) { + if playing { + slog.Debug("mujica: media pause") + onPause() + return + } + slog.Debug("mujica: media play") + onPlay() +} diff --git a/audio_player_test.go b/audio_player_test.go new file mode 100644 index 0000000..1f90d57 --- /dev/null +++ b/audio_player_test.go @@ -0,0 +1,89 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +type mediaCalls struct { + play, pause int + seeks []time.Duration +} + +func (m *mediaCalls) opts() AudioPlayerOptions { + return AudioPlayerOptions{OnPlay: func() { m.play++ }, OnPause: func() { m.pause++ }, OnSeek: func(d time.Duration) { m.seeks = append(m.seeks, d) }} +} + +func audioTester(st *AudioState, m *mediaCalls, disabled bool) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + o := m.opts() + o.Disabled = disabled + ui.Column(c).Padding(20).Children(func() { AudioPlayer(c, *st, o) }) + }, 600, 200) +} + +func TestAudioPlayerPlayPause(t *testing.T) { + st := AudioState{Title: "Ave Mujica", Position: 30 * time.Second, Duration: 3 * time.Minute} + var m mediaCalls + tt := audioTester(&st, &m, false) + if err := tt.Click("Play"); err != nil { + t.Fatal(err) + } + st.Playing = true + tt.Frame() + if err := tt.Click("Pause"); err != nil { + t.Fatal(err) + } + if m.play != 1 || m.pause != 1 { + t.Fatalf("play %d pause %d", m.play, m.pause) + } + if !tt.HasText("0:30 / 3:00") { + t.Fatalf("texts %v", tt.Texts()) + } +} + +func TestAudioPlayerKeyboard(t *testing.T) { + st := AudioState{Title: "Ave Mujica", Position: 30 * time.Second, Duration: 3 * time.Minute} + var m mediaCalls + tt := audioTester(&st, &m, false) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + if len(m.seeks) != 1 || m.seeks[0] != 35*time.Second { + t.Fatalf("seeks %v", m.seeks) + } + tt.Key(0, ui.KeySpace) + if m.play != 1 { + t.Fatalf("Space on the timeline: play %d", m.play) + } +} + +func TestAudioPlayerDisabled(t *testing.T) { + st := AudioState{Title: "Ave Mujica", Duration: time.Minute} + var m mediaCalls + tt := audioTester(&st, &m, true) + _ = tt.Click("Play") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeySpace) + tt.Key(0, ui.KeyRight) + if m.play != 0 || len(m.seeks) != 0 { + t.Fatalf("disabled player reported %+v", m) + } +} + +func TestAudioPlayerNeedsCallbacks(t *testing.T) { + mediaPanics(t, "no callbacks", func(c *ui.Context) { AudioPlayer(c, AudioState{}, AudioPlayerOptions{}) }) +} + +func TestAudioPlayerSnapshot(t *testing.T) { + var m mediaCalls + snapshot(t, "audio_player", 560, 200, func(c *ui.Context) { + ui.Column(c).Padding(20).Gap(12).Children(func() { + AudioPlayer(c, AudioState{Title: "Ave Mujica — Overture", Position: 72 * time.Second, Duration: 4 * time.Minute, Playing: true}, m.opts()) + AudioPlayer(c, AudioState{Title: "Imprisoned XII", Duration: 5 * time.Minute}, m.opts()) + }) + }) +} diff --git a/audio_spectrum.go b/audio_spectrum.go new file mode 100644 index 0000000..13ebd33 --- /dev/null +++ b/audio_spectrum.go @@ -0,0 +1,146 @@ +package mujica + +import ( + "fmt" + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// AudioSpectrumOptions configure an AudioSpectrum. +type AudioSpectrumOptions struct { + // Height is the chart's height; zero means 120. + Height float32 + // BandLabel names band i in the readout; nil numbers them. + BandLabel func(i int) string + // Status and Error show loading and failure at one size. + Status DataStatus + Error string + // Label names the chart for assistive technology. + Label string +} + +type spectrumKey struct{} + +// AudioSpectrum draws caller bands as bars; it never animates itself. +func AudioSpectrum(c *ui.Context, bands []float32, opts AudioSpectrumOptions) *ui.Element { + for _, b := range bands { + if b < 0 || b > 1 || math.IsNaN(float64(b)) { + panic("mujica: AudioSpectrum band outside 0..1") + } + } + h := opts.Height + if h < 0 { + panic("mujica: AudioSpectrum Height must not be negative") + } + if h == 0 { + h = 120 + } + k := Tokens(c) + label := opts.Label + if label == "" { + label = msg(c, "audio_spectrum.label") + } + e := ui.Box(c).Height(h).MinWidth(120).Radius(theme.ControlRadius).Background(k.Surface). + Border(theme.BorderWidth, k.Border).Focusable().Label(label) + internal.Ring(e, k.Focus, theme.ControlRadius) + if mediaChartState(c, e, opts.Status, opts.Error, len(bands) == 0, "audio_spectrum.empty") { + return e + } + cur := ui.Local(e, spectrumKey{}, func() int { return -1 }) + *cur = min(*cur, len(bands)-1) + name := func(i int) string { + if opts.BandLabel != nil { + return opts.BandLabel(i) + } + return fmt.Sprintf(msg(c, "audio_spectrum.band"), i+1) + } + if moved, ok := chartCursor(e, cur, len(bands)); ok && moved { + c.Announce(spectrumReadout(name(*cur), bands[*cur])) + } + readout := "" + if *cur >= 0 { + readout = spectrumReadout(name(*cur), bands[*cur]) + e.Description(readout) + } + sel, size := *cur, FontSize(c, theme.CaptionSize) + e.Draw(func(p *ui.Painter, r ui.Rect) { + pad := float32(8) + n := float32(len(bands)) + w := (r.W - 2*pad) / n + base := r.Y + r.H - pad + for i, b := range bands { + x := internal.Snap(p, r.X+pad+float32(i)*w) + bh := internal.Snap(p, (r.H-2*pad-16)*b) + col := k.AccentText + if i == sel { + col = k.Text + } + p.Fill(ui.Rect{X: x + 1, Y: base - bh, W: max(1, w-2), H: bh}, col, 0) + } + p.Fill(ui.Rect{X: r.X + pad, Y: base, W: r.W - 2*pad, H: 1}, k.Border, 0) + if sel >= 0 { + x := r.X + pad + float32(sel)*w + p.StrokeDashed(ui.Rect{X: x, Y: r.Y + pad, W: w, H: base - r.Y - pad}, k.TextMuted, 0, 1) + p.Text(r.X+pad, r.Y+4, readout, size, k.Text) + } + }) + return e +} + +func spectrumReadout(name string, v float32) string { + return fmt.Sprintf("%s: %d%%", name, int(math.Round(float64(v*100)))) +} + +// chartCursor moves *cur by arrows, Home and End. +func chartCursor(e *ui.Element, cur *int, n int) (moved, ok bool) { + if e.IsDisabled() || n == 0 { + return false, false + } + old := *cur + switch { + case e.Shortcut(0, ui.KeyRight): + *cur = min(n-1, *cur+1) + case e.Shortcut(0, ui.KeyLeft): + *cur = max(0, *cur-1) + case e.Shortcut(0, ui.KeyHome): + *cur = 0 + case e.Shortcut(0, ui.KeyEnd): + *cur = n - 1 + default: + return false, false + } + return *cur != old, true +} + +// mediaChartState fills e with a loading, error or empty state. +func mediaChartState(c *ui.Context, e *ui.Element, status DataStatus, errText string, empty bool, emptyKey string) bool { + k := Tokens(c) + switch { + case status == DataLoading: + e.Center().Children(func() { Spinner(c, SpinnerOptions{ShowLabel: true}) }) + case status == DataFailed: + if errText == "" { + panic("mujica: a failed media chart needs Error") + } + e.Center().Description(errText).Children(func() { + ui.Row(c).Gap(6).AlignItems(ui.Center).Children(func() { + ui.Icon(c, icons.Must("circle-alert")).Size(16, 16).TextColor(k.Danger) + ui.Text(c, errText).TextColor(k.Danger).MaxLines(2) + }) + }) + case status != DataReady: + panic(fmt.Sprintf("mujica: media chart Status %d is not Ready, Loading or Failed", status)) + case empty: + e.Center().Description(msg(c, emptyKey)).Children(func() { + ui.Text(c, msg(c, emptyKey)).TextColor(k.TextMuted) + }) + default: + return false + } + return true +} diff --git a/audio_spectrum_test.go b/audio_spectrum_test.go new file mode 100644 index 0000000..fb1d21b --- /dev/null +++ b/audio_spectrum_test.go @@ -0,0 +1,74 @@ +package mujica + +import ( + "slices" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestAudioSpectrumKeyboardReadout(t *testing.T) { + bands := []float32{0.2, 0.9, 0.5} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).Width(300).Children(func() { + AudioSpectrum(c, bands, AudioSpectrumOptions{BandLabel: func(i int) string { return []string{"63 Hz", "1 kHz", "8 kHz"}[i] }}) + }) + }, 400, 200) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyEnd) + if got := tt.Announcements(); !slices.Equal(got, []string{"63 Hz: 20%", "1 kHz: 90%", "8 kHz: 50%"}) { + t.Fatalf("announced %v", got) + } +} + +func TestAudioSpectrumNeverAnimates(t *testing.T) { + builds := 0 + bands := []float32{0.3, 0.6} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + builds++ + AudioSpectrum(c, bands, AudioSpectrumOptions{}) + }, 300, 200) + start := builds + tt.Frame() + if builds-start != 1 { + t.Fatalf("one frame built %d times: the spectrum asked for more", builds-start) + } +} + +func TestAudioSpectrumStates(t *testing.T) { + var got []ui.Rect + for _, o := range []AudioSpectrumOptions{{}, {Status: DataLoading}, {Status: DataFailed, Error: "Device lost"}} { + var r ui.Rect + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Width(300).Children(func() { r = AudioSpectrum(c, nil, o).Bounds() }) + }, 400, 200) + tt.Frame() + got = append(got, r) + if o.Status == DataFailed && !tt.HasText("Device lost") { + t.Fatal("error not shown") + } + if o.Status == DataReady && !tt.HasText("No signal") { + t.Fatal("empty state not shown") + } + } + if got[1] != got[0] || got[2] != got[0] { + t.Fatalf("state sizes %v", got) + } + mediaPanics(t, "band over 1", func(c *ui.Context) { AudioSpectrum(c, []float32{2}, AudioSpectrumOptions{}) }) + mediaPanics(t, "failed without error", func(c *ui.Context) { AudioSpectrum(c, nil, AudioSpectrumOptions{Status: DataFailed}) }) +} + +func TestAudioSpectrumSnapshot(t *testing.T) { + bands := make([]float32, 32) + for i := range bands { + bands[i] = float32(0.15 + 0.8*float64((i*37)%29)/29) + } + snapshot(t, "audio_spectrum", 420, 160, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(380).Children(func() { AudioSpectrum(c, bands, AudioSpectrumOptions{}) }) + }) +} diff --git a/audio_waveform.go b/audio_waveform.go new file mode 100644 index 0000000..f22a24c --- /dev/null +++ b/audio_waveform.go @@ -0,0 +1,187 @@ +package mujica + +import ( + "log/slog" + "math" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// AudioWaveformOptions configure an AudioWaveform. +type AudioWaveformOptions struct { + // Duration is the audio's length; required when data is ready. + Duration time.Duration + // Position draws the played part; OnSeek reports clicks and arrows. + Position time.Duration + OnSeek func(time.Duration) + // Selection, when set, is chosen by dragging or Shift+arrows. + Selection *MediaRange + // Height is the chart's height; zero means 96. + Height float32 + Status DataStatus + Error string + Label string +} + +// waveformPeaks caches column peaks until data or width change. +type waveformPeaks struct { + first *float32 + n int + cols int + peaks []float32 +} + +type waveformKey struct{} + +type waveformPress struct { + on, dragged bool + x float32 +} + +// waveformBuckets counts peak rebuilds, for tests. +var waveformBuckets int + +// AudioWaveform draws samples with played part and selectable range. +func AudioWaveform(c *ui.Context, samples []float32, opts AudioWaveformOptions) ChoiceResult { + h := opts.Height + if h < 0 || opts.Position < 0 { + panic("mujica: AudioWaveform Height and Position must not be negative") + } + if h == 0 { + h = 96 + } + k := Tokens(c) + label := opts.Label + if label == "" { + label = msg(c, "audio_waveform.label") + } + e := ui.Box(c).Height(h).MinWidth(120).Radius(theme.ControlRadius).Background(k.Surface). + Border(theme.BorderWidth, k.Border).Focusable().Label(label).Cursor(ui.CursorText) + internal.Ring(e, k.Focus, theme.ControlRadius) + v := ChoiceResult{Element: e} + if mediaChartState(c, e, opts.Status, opts.Error, len(samples) == 0, "audio_waveform.empty") { + return v + } + if opts.Duration <= 0 || opts.OnSeek == nil || opts.Position > opts.Duration { + panic("mujica: AudioWaveform needs Duration > 0, OnSeek and Position <= Duration") + } + if s := opts.Selection; s != nil && (s.Start < 0 || s.End < s.Start || s.End > opts.Duration) { + panic("mujica: AudioWaveform Selection outside 0..Duration") + } + r := e.Bounds() + cols := int(r.W) + cache := ui.Local(e, waveformKey{}, func() waveformPeaks { return waveformPeaks{} }) + if cols <= 0 { + // Peaks need the width: lay out first, then build again. + c.AnimationFrame() + } else if cache.first != &samples[0] || cache.n != len(samples) || cache.cols != cols { + *cache = waveformPeaks{&samples[0], len(samples), cols, waveformBucket(samples, cols)} + } + if !e.IsDisabled() { + v.changed = waveformInput(c, e, r, opts) + } + e.Description(mediaClock(opts.Position) + " / " + mediaClock(opts.Duration)) + peaks, pos, sel := cache.peaks, float32(opts.Position)/float32(opts.Duration), opts.Selection + dur := float32(opts.Duration) + e.Draw(func(p *ui.Painter, r ui.Rect) { + mid := r.Y + r.H/2 + amp := r.H/2 - 6 + if sel != nil && sel.End > sel.Start { + x0, x1 := r.X+r.W*float32(sel.Start)/dur, r.X+r.W*float32(sel.End)/dur + p.Fill(ui.Rect{X: x0, Y: r.Y, W: x1 - x0, H: r.H}, k.Selection, 0) + p.Fill(ui.Rect{X: x0, Y: r.Y, W: 1, H: r.H}, k.AccentText, 0) + p.Fill(ui.Rect{X: x1 - 1, Y: r.Y, W: 1, H: r.H}, k.AccentText, 0) + } + played := r.X + r.W*pos + for i, pk := range peaks { + x := r.X + r.W*float32(i)/float32(len(peaks)) + col := k.TextMuted + if x < played { + col = k.AccentText + } + ph := max(1, amp*pk) + p.Fill(ui.Rect{X: x, Y: mid - ph, W: max(1, r.W/float32(len(peaks))-0.5), H: 2 * ph}, col, 0) + } + px := internal.Snap(p, played) + p.Fill(ui.Rect{X: px - 1, Y: r.Y, W: 2, H: r.H}, k.Text, 0) + p.FillPath(internal.Diamond(px, internal.Snap(p, r.Y+5), 8), k.Text) + }) + return v +} + +// waveformBucket returns the largest magnitude in each of cols spans. +func waveformBucket(samples []float32, cols int) []float32 { + waveformBuckets++ + peaks := make([]float32, cols) + for i, s := range samples { + col := i * cols / len(samples) + peaks[col] = max(peaks[col], float32(math.Abs(float64(s)))) + } + return peaks +} + +// waveformInput seeks and selects; true means the selection changed. +func waveformInput(c *ui.Context, e *ui.Element, r ui.Rect, opts AudioWaveformOptions) bool { + at := func(x float32) time.Duration { + f := max(0, min(1, (x-r.X)/max(1, r.W))) + return time.Duration(float64(f) * float64(opts.Duration)).Round(time.Millisecond) + } + seek := func(t time.Duration) { + t = max(0, min(opts.Duration, t)) + slog.Debug("mujica: audio_waveform seek", "pos", t) + opts.OnSeek(t) + } + sel := opts.Selection + old := MediaRange{} + if sel != nil { + old = *sel + } + px, _, _ := e.PointerPosition() + px += r.X + st := ui.Local(e, waveformPress{}, func() waveformPress { return waveformPress{} }) + _, _, dragging := e.Dragged() + switch { + case e.Pressed() && !st.on: + *st = waveformPress{on: true, x: px} + case e.Pressed() && sel != nil && (dragging || st.dragged) && math.Abs(float64(px-st.x)) > 3: + st.dragged = true + a, b := at(st.x), at(px) + *sel = MediaRange{min(a, b), max(a, b)} + case !e.Pressed() && st.on: + if !st.dragged { + seek(at(st.x)) + } + *st = waveformPress{} + } + const step = 5 * time.Second + switch { + case e.Shortcut(0, ui.KeyLeft): + seek(opts.Position - step) + case e.Shortcut(0, ui.KeyRight): + seek(opts.Position + step) + case sel != nil && e.Shortcut(ui.Shift, ui.KeyRight): + *sel = waveformExtend(*sel, opts.Position, step, opts.Duration) + case sel != nil && e.Shortcut(ui.Shift, ui.KeyLeft): + *sel = waveformExtend(*sel, opts.Position, -step, opts.Duration) + case sel != nil && e.Shortcut(0, ui.KeyEscape): + *sel = MediaRange{} + } + changed := sel != nil && *sel != old + if changed { + slog.Debug("mujica: audio_waveform select", "start", sel.Start, "end", sel.End) + } + return changed +} + +// waveformExtend starts a selection at pos or moves its end. +func waveformExtend(s MediaRange, pos, d, dur time.Duration) MediaRange { + if s.End <= s.Start { + s = MediaRange{pos, pos} + } + s.End = max(s.Start, min(dur, s.End+d)) + return s +} diff --git a/audio_waveform_test.go b/audio_waveform_test.go new file mode 100644 index 0000000..9ccb2c0 --- /dev/null +++ b/audio_waveform_test.go @@ -0,0 +1,131 @@ +package mujica + +import ( + "math" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func waveSamples(n int) []float32 { + s := make([]float32, n) + for i := range s { + s[i] = float32(math.Sin(float64(i)/40) * (0.3 + 0.6*math.Abs(math.Sin(float64(i)/3000)))) + } + return s +} + +func waveTester(samples []float32, opts *AudioWaveformOptions, n *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).Width(400).Children(func() { + if AudioWaveform(c, samples, *opts).Changed() { + *n++ + } + }) + }, 500, 200) +} + +func TestAudioWaveformSeekAndSelect(t *testing.T) { + var seeks []time.Duration + sel := MediaRange{} + opts := AudioWaveformOptions{Duration: 100 * time.Second, Position: 10 * time.Second, Selection: &sel, + OnSeek: func(d time.Duration) { seeks = append(seeks, d) }} + n := 0 + tt := waveTester(waveSamples(5000), &opts, &n) + r, ok := tt.Find("Waveform") + if !ok { + t.Fatal("not named") + } + tt.ClickAt(r.X+r.W/2, r.Y+r.H/2) + if len(seeks) != 1 || seeks[0] < 48*time.Second || seeks[0] > 52*time.Second { + t.Fatalf("click seeks %v", seeks) + } + tt.Press(r.X+r.W*0.2, r.Y+r.H/2) + tt.Move(r.X+r.W*0.3, r.Y+r.H/2) + tt.Move(r.X+r.W*0.4, r.Y+r.H/2) + tt.Release(r.X+r.W*0.4, r.Y+r.H/2) + if sel.Start < 18*time.Second || sel.Start > 22*time.Second || sel.End < 38*time.Second || sel.End > 42*time.Second || len(seeks) != 1 { + t.Fatalf("drag selection %+v, seeks %v", sel, seeks) + } + tt.Key(0, ui.KeyEscape) + tt.Key(ui.Shift, ui.KeyRight) + if sel != (MediaRange{10 * time.Second, 15 * time.Second}) || n < 3 { + t.Fatalf("Shift+Right selection %+v, changes %d", sel, n) + } + tt.Key(0, ui.KeyRight) + if seeks[len(seeks)-1] != 15*time.Second { + t.Fatalf("Right seek %v", seeks) + } +} + +func TestAudioWaveformComputesPeaksOnce(t *testing.T) { + samples := waveSamples(100000) + opts := AudioWaveformOptions{Duration: time.Minute, OnSeek: func(time.Duration) {}} + n := 0 + tt := waveTester(samples, &opts, &n) + before := waveformBuckets + for range 5 { + opts.Position += time.Second + tt.Frame() + } + if got := waveformBuckets - before; got != 0 { + t.Fatalf("peaks rebuilt %d times without new data", got) + } + samples = waveSamples(100000) + tt = waveTester(samples, &opts, &n) + tt.Frame() + if waveformBuckets-before == 0 { + t.Fatal("new data did not rebuild peaks") + } +} + +func TestAudioWaveformStatesKeepSize(t *testing.T) { + var got []ui.Rect + seek := func(time.Duration) {} + for _, o := range []AudioWaveformOptions{{Duration: time.Second, OnSeek: seek}, {Status: DataLoading}, {Status: DataFailed, Error: "Decode failed"}} { + var r ui.Rect + data := waveSamples(100) + if o.Status != DataReady { + data = nil + } + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Width(300).Children(func() { r = AudioWaveform(c, data, o).Element.Bounds() }) + }, 400, 200) + tt.Frame() + got = append(got, r) + } + if got[1] != got[0] || got[2] != got[0] { + t.Fatalf("state sizes %v", got) + } +} + +func TestAudioWaveformDisabled(t *testing.T) { + var seeks []time.Duration + opts := AudioWaveformOptions{Duration: time.Minute, OnSeek: func(d time.Duration) { seeks = append(seeks, d) }} + n := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Disabled(true).Width(300).Children(func() { AudioWaveform(c, waveSamples(500), opts) }) + }, 400, 200) + r, _ := tt.Find("Waveform") + tt.ClickAt(r.X+10, r.Y+10) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + if len(seeks) != 0 || n != 0 { + t.Fatalf("disabled waveform seeked %v", seeks) + } +} + +func TestAudioWaveformSnapshot(t *testing.T) { + samples := waveSamples(20000) + sel := MediaRange{50 * time.Second, 70 * time.Second} + snapshot(t, "audio_waveform", 460, 150, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(420).Children(func() { + AudioWaveform(c, samples, AudioWaveformOptions{Duration: 2 * time.Minute, Position: 40 * time.Second, + Selection: &sel, OnSeek: func(time.Duration) {}}) + }) + }) +} diff --git a/camera_preview.go b/camera_preview.go new file mode 100644 index 0000000..599365b --- /dev/null +++ b/camera_preview.go @@ -0,0 +1,93 @@ +package mujica + +import ( + "image" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// CameraFrame is the caller's latest camera picture. +type CameraFrame struct { + // Image is the frame; nil shows "No signal". + Image image.Image + // Seq numbers frames; a new number redraws a reused Image. + Seq uint64 +} + +// CameraPreviewOptions configure a CameraPreview. +type CameraPreviewOptions struct { + // Label names the camera for assistive technology. + Label string + Disabled bool +} + +type cameraCache struct { + img image.Image + seq uint64 + mirror bool + bmp *ui.Bitmap +} + +type cameraKey struct{} + +// CameraPreview shows frame at 16:9, mirrored while *mirror. +func CameraPreview(c *ui.Context, frame CameraFrame, mirror *bool, opts CameraPreviewOptions) ChoiceResult { + k := Tokens(c) + old := *mirror + label := opts.Label + if label == "" { + label = msg(c, "camera_preview.label") + } + box := ui.Box(c).FillWidth().AspectRatio(16.0 / 9).Background(videoBlack).Radius(theme.CardRadius).Clip(). + Center().Focusable().Role(ui.RoleImage).Label(label).Disabled(opts.Disabled) + internal.Ring(box, k.Focus, theme.CardRadius) + cache := ui.Local(box, cameraKey{}, func() cameraCache { return cameraCache{} }) + box.Children(func() { + if frame.Image == nil { + box.Description(msg(c, "camera_preview.noSignal")) + ui.Column(c).Gap(8).AlignItems(ui.Center).Children(func() { + ui.Icon(c, mediaCamera).Size(28, 28).TextColor(ui.Hex("#BCAEAA")) + ui.Text(c, msg(c, "camera_preview.noSignal")).TextColor(ui.Hex("#BCAEAA")) + }) + } else { + // Copies are made once per frame number, not per paint. + if cache.img != frame.Image || cache.seq != frame.Seq || cache.mirror != *mirror || cache.bmp == nil { + *cache = cameraCache{frame.Image, frame.Seq, *mirror, cameraBitmap(frame.Image, *mirror)} + } + ui.Image(c, cache.bmp).Fit(ui.Contain).Fill() + } + ui.Box(c).Absolute().Top(8).Right(8).Background(ui.RGBA(0, 0, 0, 0.5)).Radius(theme.ControlRadius).Children(func() { + b := mediaToggleAction(c, mediaMirror, msg(c, "camera_preview.mirror"), *mirror) + if b.Clicked() && !b.IsDisabled() { + *mirror = !*mirror + } + }) + }) + if !box.IsDisabled() && box.Shortcut(0, ui.KeyM) { + *mirror = !*mirror + } + changed := *mirror != old + if changed { + slog.Debug("mujica: camera_preview mirror", "on", *mirror) + } + return ChoiceResult{Element: box, changed: changed} +} + +// cameraBitmap copies img into a bitmap, flipped when mirror. +func cameraBitmap(img image.Image, mirror bool) *ui.Bitmap { + if !mirror { + return ui.NewBitmap(img) + } + b := img.Bounds() + out := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy())) + for y := b.Min.Y; y < b.Max.Y; y++ { + for x := b.Min.X; x < b.Max.X; x++ { + out.Set(b.Max.X-1-x, y-b.Min.Y, img.At(x, y)) + } + } + return ui.NewBitmap(out) +} diff --git a/camera_preview_test.go b/camera_preview_test.go new file mode 100644 index 0000000..cde85b9 --- /dev/null +++ b/camera_preview_test.go @@ -0,0 +1,86 @@ +package mujica + +import ( + "image" + "testing" + + "github.com/egoist/mygo/ui" +) + +func cameraTester(frame *CameraFrame, mirror *bool, disabled bool, n *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).Width(320).Children(func() { + if CameraPreview(c, *frame, mirror, CameraPreviewOptions{Disabled: disabled}).Changed() { + *n++ + } + }) + }, 400, 260) +} + +func TestCameraPreviewNoSignalAndMirror(t *testing.T) { + frame, mirror, n := CameraFrame{}, false, 0 + tt := cameraTester(&frame, &mirror, false, &n) + if !tt.HasText("No signal") { + t.Fatalf("texts %v", tt.Texts()) + } + if err := tt.Click("Mirror"); err != nil { + t.Fatal(err) + } + tt.Key(0, ui.KeyTab) + if !tt.Focused("Camera") { + t.Fatal("preview not focusable") + } + tt.Key(0, ui.KeyM) + if mirror || n != 2 { + t.Fatalf("mirror %v changes %d", mirror, n) + } + frame = CameraFrame{Image: mediaTestImage(32, 18), Seq: 1} + tt.Frame() + if tt.HasText("No signal") { + t.Fatal("frame did not replace No signal") + } +} + +func TestCameraPreviewDisabled(t *testing.T) { + frame, mirror, n := CameraFrame{}, false, 0 + tt := cameraTester(&frame, &mirror, true, &n) + _ = tt.Click("Mirror") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyM) + if mirror || n != 0 { + t.Fatal("disabled preview flipped") + } +} + +func TestCameraBitmapMirrors(t *testing.T) { + img := mediaTestImage(8, 8) + flipped := image.NewRGBA(image.Rect(0, 0, 8, 8)) + for y := range 8 { + for x := range 8 { + flipped.Set(7-x, y, img.At(x, y)) + } + } + got := ui.Render(func(c *ui.Context) { + ui.Image(c, cameraBitmap(img, true)).Size(8, 8) + }, 8, 8, 1) + want := ui.Render(func(c *ui.Context) { + ui.Image(c, ui.NewBitmap(flipped)).Size(8, 8) + }, 8, 8, 1) + if got.RGBAAt(1, 6) != want.RGBAAt(1, 6) || got.RGBAAt(1, 6) == ui.Render(func(c *ui.Context) { + ui.Image(c, ui.NewBitmap(img)).Size(8, 8) + }, 8, 8, 1).RGBAAt(1, 6) { + t.Fatal("mirrored bitmap is not flipped") + } +} + +func TestCameraPreviewSnapshot(t *testing.T) { + img := mediaTestImage(160, 90) + m1, m2 := true, false + snapshot(t, "camera_preview", 560, 180, func(c *ui.Context) { + ui.Row(c).Padding(20).Gap(12).Children(func() { + ui.Column(c).Grow(1).Children(func() { CameraPreview(c, CameraFrame{Image: img}, &m1, CameraPreviewOptions{}) }) + ui.Column(c).Grow(1).Children(func() { CameraPreview(c, CameraFrame{}, &m2, CameraPreviewOptions{}) }) + }) + }) +} diff --git a/device_selector.go b/device_selector.go new file mode 100644 index 0000000..e7b9e92 --- /dev/null +++ b/device_selector.go @@ -0,0 +1,78 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// MediaDevice is one device; IDs are unique within a kind. +type MediaDevice struct { + ID, Name string +} + +// MediaDevices are the caller's lists; nil hides that kind. +type MediaDevices struct { + Microphones, Cameras, Speakers []MediaDevice +} + +// DeviceSelection holds each kind's chosen ID; empty is none. +type DeviceSelection struct { + Microphone, Camera, Speaker string +} + +// DeviceSelectorOptions configure a DeviceSelector. +type DeviceSelectorOptions struct { + Disabled bool +} + +// DeviceSelector chooses a microphone, camera and speaker. +func DeviceSelector(c *ui.Context, sel *DeviceSelection, devices MediaDevices, opts DeviceSelectorOptions) ChoiceResult { + old := *sel + k := Tokens(c) + u := Density(c).Unit() + col := ui.Column(c).Gap(u * 3).Role(ui.RoleGroup).Label(msg(c, "device_selector.label")).Disabled(opts.Disabled) + col.Children(func() { + deviceRow(c, k, mediaMic, "device_selector.microphone", &sel.Microphone, devices.Microphones, opts.Disabled) + deviceRow(c, k, mediaCamera, "device_selector.camera", &sel.Camera, devices.Cameras, opts.Disabled) + deviceRow(c, k, mediaSpeaker, "device_selector.speaker", &sel.Speaker, devices.Speakers, opts.Disabled) + }) + changed := *sel != old + if changed { + slog.Debug("mujica: device_selector changed", "selection", *sel) + } + return ChoiceResult{Element: col, changed: changed} +} + +func deviceRow(c *ui.Context, k theme.Tokens, icon *ui.SVG, key string, id *string, list []MediaDevice, disabled bool) { + if list == nil { + return + } + options := make([]SelectOption[string], len(list)) + for i, d := range list { + if d.ID == "" { + panic("mujica: DeviceSelector device without an ID") + } + for _, o := range options[:i] { + if o.Value == d.ID { + panic("mujica: DeviceSelector duplicate device ID " + d.ID) + } + } + options[i] = SelectOption[string]{Value: d.ID, Label: d.Name} + } + if _, ok := selectLabel(options, *id); *id != "" && !ok { + panic("mujica: DeviceSelector selection " + *id + " is not in its list") + } + ui.Row(c).Gap(Density(c).Unit() * 2).AlignItems(ui.Center).Children(func() { + ui.Icon(c, icon).Size(16, 16).TextColor(k.TextMuted) + ui.Text(c, msg(c, key)).Width(96).SingleLine() + hint := msg(c, "device_selector.choose") + if len(list) == 0 { + hint = msg(c, "device_selector.none") + } + Select(c, id, options, SelectOptions{Disabled: disabled || len(list) == 0, Label: msg(c, key), + Placeholder: hint, Empty: msg(c, "device_selector.none")}).Element.Grow(1) + }) +} diff --git a/device_selector_test.go b/device_selector_test.go new file mode 100644 index 0000000..74c8b79 --- /dev/null +++ b/device_selector_test.go @@ -0,0 +1,74 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +var deviceTestList = MediaDevices{ + Microphones: []MediaDevice{{"m1", "Built-in Microphone"}, {"m2", "Studio Mic"}}, + Cameras: []MediaDevice{}, + Speakers: []MediaDevice{{"s1", "Headphones"}}, +} + +func deviceTester(sel *DeviceSelection, devices MediaDevices, disabled bool, n *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).Width(420).Children(func() { + if DeviceSelector(c, sel, devices, DeviceSelectorOptions{Disabled: disabled}).Changed() { + *n++ + } + }) + }, 500, 400) +} + +func TestDeviceSelectorChoose(t *testing.T) { + sel, n := DeviceSelection{Microphone: "m1"}, 0 + tt := deviceTester(&sel, deviceTestList, false, &n) + if !tt.HasText("Built-in Microphone") || !tt.HasText("No devices found") { + t.Fatalf("texts %v", tt.Texts()) + } + if err := tt.Click("Built-in Microphone"); err != nil { + t.Fatal(err) + } + if err := tt.Click("Studio Mic"); err != nil { + t.Fatal(err) + } + if sel.Microphone != "m2" || n != 1 { + t.Fatalf("selection %+v changes %d", sel, n) + } +} + +func TestDeviceSelectorHidesNilListsAndDisabled(t *testing.T) { + sel, n := DeviceSelection{}, 0 + tt := deviceTester(&sel, MediaDevices{Speakers: deviceTestList.Speakers}, true, &n) + if tt.HasText("Camera") || tt.HasText("Microphone") { + t.Fatalf("nil lists shown: %v", tt.Texts()) + } + _ = tt.Click("Choose a device") + _ = tt.Click("Headphones") + if sel.Speaker != "" || n != 0 { + t.Fatal("disabled selector chose") + } +} + +func TestDeviceSelectorBadLists(t *testing.T) { + sel := DeviceSelection{} + mediaPanics(t, "duplicate", func(c *ui.Context) { + DeviceSelector(c, &sel, MediaDevices{Cameras: []MediaDevice{{"a", "A"}, {"a", "B"}}}, DeviceSelectorOptions{}) + }) + gone := DeviceSelection{Camera: "x"} + mediaPanics(t, "unknown selection", func(c *ui.Context) { + DeviceSelector(c, &gone, MediaDevices{Cameras: []MediaDevice{{"a", "A"}}}, DeviceSelectorOptions{}) + }) +} + +func TestDeviceSelectorSnapshot(t *testing.T) { + sel := DeviceSelection{Microphone: "m2", Speaker: "s1"} + snapshot(t, "device_selector", 460, 190, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(420).Children(func() { + DeviceSelector(c, &sel, deviceTestList, DeviceSelectorOptions{}) + }) + }) +} diff --git a/docs/components/341-image-cropper.md b/docs/components/341-image-cropper.md new file mode 100644 index 0000000..bef9a87 --- /dev/null +++ b/docs/components/341-image-cropper.md @@ -0,0 +1,55 @@ +# 341 ImageCropper 图片裁剪 + +## 用途 + +在图片上拖出裁剪框,可锁定宽高比、按 90 度旋转,输出裁剪矩形。 + +## 最小示例 + +```go +crop := mujica.ImageCrop{} // empty: starts fitted to the image +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ImageCropper(c, examplePhoto, &crop, mujica.ImageCropperOptions{Aspect: 1}).Changed() { + _ = crop.Rect // in pixels of the photo turned by crop.Rotation + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ImageCropper(c *ui.Context, src image.Image, crop *ImageCrop, opts ImageCropperOptions) ChoiceResult` + +`src` 必填,是标准库 `image.Image`(组件要自己转动像素)。`ImageCrop.Rect` 是旋转 `Rotation` 度之后那张图上的像素矩形;`Rotation` 只能是 0、90、180、270。`Rect` 为空时自动设为最大的居中框。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Aspect` | `float64` | 0 | 锁定宽除以高;0 为自由比例。`Rect` 不符合比例时 panic。 | +| `Height` | `float32` | 0(即 320) | 舞台高度。 | +| `Disabled` | `bool` | false | 禁用拖动、按键与旋转。 | +| `Label` | `string` | "Crop area" | 舞台的无障碍名称。 | + +## 状态 + +- 默认:框外区域压暗,框线与三分线为象牙色,四角有菱形手柄。 +- 聚焦:舞台显示 2 DIP 焦点环;下方读数同时作为无障碍描述。 +- 禁用:MyGo 统一调暗,不响应输入。 + +## 事件 + +`Changed()` 在框移动、缩放或旋转后为 true。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| 方向键 | 移动裁剪框,每次图片宽度的 1% | +| Shift+方向键 | 右、下放大,左、上缩小;锁定比例时保持比例 | +| R / Shift+R | 向右 / 向左旋转 90 度 | + +## 限制 + +- MyGo 的 Painter 不能旋转位图(只有单色图标能转,ui/svg.go:98),所以组件在图片或角度变化时复制一份转好的像素;超大图片会在那一帧花时间。 +- 锁定比例时旋转会重新取最大的居中框,原选区不保留。 +- 拖动角点时,按下点距角 14 DIP 以内才算抓住手柄。 diff --git a/docs/components/342-image-annotator.md b/docs/components/342-image-annotator.md new file mode 100644 index 0000000..c947050 --- /dev/null +++ b/docs/components/342-image-annotator.md @@ -0,0 +1,59 @@ +# 342 ImageAnnotator 图片标注 + +## 用途 + +在图片上画矩形、箭头和文字标注,可选择、移动和删除,并导出标注数据。 + +## 最小示例 + +```go +photo := ui.NewBitmap(examplePhoto) +var notes []mujica.Annotation +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ImageAnnotator(c, photo, ¬es, mujica.ImageAnnotatorOptions{}).Changed() { + data, _ := mujica.ExportAnnotations(notes) + _ = data // save the JSON + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ImageAnnotator(c *ui.Context, src ui.ImageSource, notes *[]Annotation, opts ImageAnnotatorOptions) ChoiceResult` + +`func ExportAnnotations(notes []Annotation) ([]byte, error)` 把标注写成 JSON(kind、x0、y0、x1、y1、text)。 + +`Annotation` 的坐标是图片像素;文字标注以 `From` 为左上角,`Text` 不能为空。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Height` | `float32` | 0(即 320) | 舞台高度。 | +| `Disabled` | `bool` | false | 禁用绘制、选择和删除。 | +| `Label` | `string` | "Annotations" | 舞台的无障碍名称。 | + +## 状态 + +- 工具:选择、矩形、箭头、文字,用分段控件切换。 +- 选中:虚线框加菱形标记,不只靠颜色。 +- 标注用暗红墨线加浅色描边,在任何图片上都看得清。 + +## 事件 + +`Changed()` 在新增、移动、改字或删除标注后为 true。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| [ / ] | 选中上一个 / 下一个标注 | +| 方向键 | 移动选中的标注,每次图片宽度的 1% | +| Delete / Backspace | 删除选中的标注 | +| Escape | 取消选择 | + +## 限制 + +- 文字工具:先在工具栏输入文字,再点击放置;选中文字标注时同一输入框可改字。 +- 标注不能缩放,只能移动;要改大小请删除后重画。 +- 文字的命中区域按每字 8 像素估算。 diff --git a/docs/components/343-image-thumbnail.md b/docs/components/343-image-thumbnail.md new file mode 100644 index 0000000..eaf0c67 --- /dev/null +++ b/docs/components/343-image-thumbnail.md @@ -0,0 +1,54 @@ +# 343 ImageThumbnail 缩略图 + +## 用途 + +固定尺寸、按比例裁切的可点击缩略图,带选中、加载中和加载失败状态。 + +## 最小示例 + +```go +photo := ui.NewBitmap(examplePhoto) +selected := false +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ImageThumbnail(c, photo, mujica.ImageThumbnailOptions{Alt: "Grand hall", Aspect: 4.0 / 3, Selected: selected}).Changed() { + selected = !selected + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ImageThumbnail(c *ui.Context, src ui.ImageSource, opts ImageThumbnailOptions) ChoiceResult` + +`src` 为 nil 时显示占位图标。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Width` | `float32` | 0(即 96) | 宽度。 | +| `Aspect` | `float32` | 0(即 1) | 宽除以高,图片按 Cover 裁切填满。 | +| `Selected` | `bool` | false | 选中:2 DIP 强调边框加右上角菱形。 | +| `Loading` | `bool` | false | 显示加载标记,尺寸不变。 | +| `Err` | `error` | nil | 显示失败图标;错误文字作为提示与描述。 | +| `Alt` | `string` | 必填 | 替代说明,为空时 panic。 | +| `Disabled` | `bool` | false | 禁用点击。 | + +## 状态 + +默认、悬停(边框加深)、聚焦、选中、加载、失败、禁用,所有状态尺寸相同。 + +## 事件 + +`Changed()` 表示本帧被点击,或聚焦时按了 Enter / Space。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| Tab | 聚焦缩略图 | +| Enter / Space | 激活 | + +## 限制 + +- 选中状态由调用方保存;组件只报告点击。 diff --git a/docs/components/344-lightbox.md b/docs/components/344-lightbox.md new file mode 100644 index 0000000..5c5103a --- /dev/null +++ b/docs/components/344-lightbox.md @@ -0,0 +1,53 @@ +# 344 Lightbox 灯箱 + +## 用途 + +全窗口浏览图片:左右切换、显示说明文字,Escape 关闭后焦点回到触发控件。 + +## 最小示例 + +```go +images := []mujica.ViewerImage{{Source: ui.NewBitmap(examplePhoto), Alt: "The grand hall"}} +open, index := false, 0 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.Button(c, "View photos", mujica.ButtonOptions{}).Clicked() { + open = true + } + mujica.Lightbox(c, &open, &index, images) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func Lightbox(c *ui.Context, open *bool, index *int, images []ViewerImage) ChoiceResult` + +与 ImageViewer 共用 `ViewerImage`(`Source`、`Alt`)。`Alt` 同时是说明文字。关闭时 `Element` 为 nil。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `open` | `*bool` | — | 是否显示;Escape、点击关闭或背景时设为 false。 | +| `index` | `*int` | — | 当前图片;越界 panic。 | +| `images` | `[]ViewerImage` | — | 至少一张,`Source` 须为 `*ui.Bitmap` 或 `*ui.SVG`。 | + +## 状态 + +- 黑色遮罩铺满窗口,图片按 Contain 居中;首尾时对应切换按钮禁用。 +- 打开时按弹层时长淡入,减少动画时直接出现。 + +## 事件 + +`Changed()` 在切换图片后为 true,并朗读“第 n 张,共 m 张”。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| ← / → | 上一张 / 下一张 | +| Home / End | 第一张 / 最后一张 | +| Escape | 关闭并把焦点还给打开它的控件 | + +## 限制 + +- 不提供缩放与平移;需要时请用 ImageViewer。 diff --git a/docs/components/345-video-player.md b/docs/components/345-video-player.md new file mode 100644 index 0000000..7a9beca --- /dev/null +++ b/docs/components/345-video-player.md @@ -0,0 +1,59 @@ +# 345 VideoPlayer 视频播放器 + +## 用途 + +播放器外壳:画面由调用方提供,组件绘制状态并通过回调报告播放、暂停、跳转、倍速、字幕、全屏和画中画。 + +## 最小示例 + +```go +st := mujica.VideoState{Duration: 4 * time.Minute, Rate: 1} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.VideoPlayer(c, st, mujica.VideoPlayerOptions{ + OnPlay: func() { st.Playing = true }, // start your decoder + OnPause: func() { st.Playing = false }, // pause it + OnSeek: func(d time.Duration) { st.Position = d }, + OnRate: func(r float64) { st.Rate = r }, + }) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func VideoPlayer(c *ui.Context, st VideoState, opts VideoPlayerOptions) *ui.Element` + +`VideoState`:`Frame`(当前画面,nil 显示“暂无视频”)、`Position`、`Duration`、`Buffered`、`Playing`、`Rate`、`Subtitle`、`SubtitlesOn`、`Fullscreen`、`PiP`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `OnPlay / OnPause / OnSeek` | `func` | 必填 | 播放、暂停、跳转。 | +| `OnRate` | `func(float64)` | nil | 倍速;nil 时不显示倍速选择。 | +| `OnSubtitles / OnFullscreen / OnPiP` | `func(bool)` | nil | 开关回调;nil 时隐藏对应按钮。 | +| `Disabled` | `bool` | false | 禁用全部控件。 | +| `Label` | `string` | "Video" | 无障碍名称。 | + +## 状态 + +- 画面区 16:9,黑底;字幕开启且有字幕时在底部显示。 +- 字幕、画中画、全屏按钮开启时有选中底色和下划线。 + +## 事件 + +全部通过回调报告;组件不改动 `st`。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| Tab | 先聚焦画面,再到进度条和各按钮 | +| Space / K | 画面聚焦时播放或暂停 | +| ← / → | 画面聚焦时后退 / 前进 5 秒 | +| F | 切换全屏 | +| C | 切换字幕 | + +## 限制 + +- 组件不解码视频,也不实现全屏或画中画窗口,只报告用户的请求。 +- 帧率取决于调用方更新 `Frame` 并调用 `c.Invalidate()` 的频率。 diff --git a/docs/components/346-video-scrubber.md b/docs/components/346-video-scrubber.md new file mode 100644 index 0000000..6ada0d3 --- /dev/null +++ b/docs/components/346-video-scrubber.md @@ -0,0 +1,56 @@ +# 346 VideoScrubber 视频时间轴 + +## 用途 + +可拖动的时间轴:显示已缓冲区间,悬停显示时间和缩略图插槽。 + +## 最小示例 + +```go +pos := 30 * time.Second +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.VideoScrubber(c, &pos, mujica.VideoScrubberOptions{ + Duration: 2 * time.Minute, + Buffered: []mujica.MediaRange{{Start: 0, End: time.Minute}}, + }) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func VideoScrubber(c *ui.Context, pos *time.Duration, opts VideoScrubberOptions) ChoiceResult` + +`*pos` 必须在 0 到 `Duration` 之间,否则 panic。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Duration` | `time.Duration` | 必填 | 时间轴长度,须大于 0。 | +| `Buffered` | `[]MediaRange` | nil | 已缓冲区间,以浅色填充。 | +| `Preview` | `func(at time.Duration)` | nil | 悬停时在插槽里构建该时间的缩略图。 | +| `PreviewWidth / PreviewHeight` | `float32` | 160×90 | 插槽尺寸。 | +| `Step` | `time.Duration` | 5 秒 | 方向键每次移动的时长。 | +| `Disabled` | `bool` | false | 禁用。 | +| `Label` | `string` | "Timeline" | 无障碍名称;以滑块角色报告范围与数值。 | + +## 状态 + +默认、悬停(显示时间气泡)、拖动、聚焦(菱形手柄外圈)、禁用。 + +## 事件 + +`Changed()` 在拖动、点击或按键改变 `*pos` 后为 true。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| ← / ↓ | 后退一个 Step | +| → / ↑ | 前进一个 Step | +| Home / End | 开头 / 结尾 | + +## 限制 + +- 位置按毫秒取整。 +- 悬停插槽只在指针位于时间轴上时显示,键盘操作时不显示。 diff --git a/docs/components/347-video-thumbnail-strip.md b/docs/components/347-video-thumbnail-strip.md new file mode 100644 index 0000000..e36b6ef --- /dev/null +++ b/docs/components/347-video-thumbnail-strip.md @@ -0,0 +1,51 @@ +# 347 VideoThumbnailStrip 缩略帧条 + +## 用途 + +横向缩略帧条:标出当前帧,点击或按键跳转。 + +## 最小示例 + +```go +frames := []mujica.StripFrame{{At: 0}, {At: 10 * time.Second}, {At: 20 * time.Second}} +current := 0 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.VideoThumbnailStrip(c, ¤t, frames, mujica.VideoThumbnailStripOptions{}).Changed() { + _ = frames[current].At // seek the player there + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func VideoThumbnailStrip(c *ui.Context, current *int, frames []StripFrame, opts VideoThumbnailStripOptions) ChoiceResult` + +`StripFrame` 有 `Image`(可为 nil)和 `At`。`*current` 越界 panic。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `FrameWidth` | `float32` | 0(即 96) | 每格宽度,高度按 16:9。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +- 只构建放得下的那几格,窗口跟随当前帧移动;10 万帧也只建十几个元素。 +- 当前帧:强调边框加菱形;每格左下角显示时间。 + +## 事件 + +`Changed()` 在当前帧变化后为 true;调用方据此跳转播放器。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| Tab | 聚焦帧条 | +| ← / → | 上一帧 / 下一帧 | +| Home / End | 第一帧 / 最后一帧 | + +## 限制 + +- 不提供横向滚动条,用两侧按钮或键盘移动。 diff --git a/docs/components/348-audio-player.md b/docs/components/348-audio-player.md new file mode 100644 index 0000000..426e71d --- /dev/null +++ b/docs/components/348-audio-player.md @@ -0,0 +1,51 @@ +# 348 AudioPlayer 音频播放器 + +## 用途 + +音频播放外壳:播放、暂停、进度与时长,播放本身由调用方驱动。 + +## 最小示例 + +```go +st := mujica.AudioState{Title: "Overture", Duration: 3 * time.Minute} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AudioPlayer(c, st, mujica.AudioPlayerOptions{ + OnPlay: func() { st.Playing = true }, + OnPause: func() { st.Playing = false }, + OnSeek: func(d time.Duration) { st.Position = d }, + }) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func AudioPlayer(c *ui.Context, st AudioState, opts AudioPlayerOptions) *ui.Element` + +`AudioState`:`Title`、`Position`、`Duration`、`Playing`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `OnPlay / OnPause / OnSeek` | `func` | 必填 | 缺少任一回调时 panic。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +播放中显示暂停按钮,暂停时显示播放按钮;`Duration` 为 0 时不显示进度条。 + +## 事件 + +通过回调报告,组件不改动 `st`。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| Tab | 播放按钮、进度条 | +| Space | 组件内任意位置播放或暂停(按钮聚焦时由按钮处理) | +| ← / → | 进度条聚焦时跳转 5 秒 | + +## 限制 + +- 组件不播放声音。 diff --git a/docs/components/349-audio-waveform.md b/docs/components/349-audio-waveform.md new file mode 100644 index 0000000..674f8ad --- /dev/null +++ b/docs/components/349-audio-waveform.md @@ -0,0 +1,58 @@ +# 349 AudioWaveform 音频波形 + +## 用途 + +绘制调用方提供的采样波形,覆盖播放进度,可拖动选择区间。 + +## 最小示例 + +```go +samples := make([]float32, 48000) // from your decoder, -1 to 1 +pos, sel := time.Duration(0), mujica.MediaRange{} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AudioWaveform(c, samples, mujica.AudioWaveformOptions{ + Duration: time.Second, Position: pos, Selection: &sel, + OnSeek: func(d time.Duration) { pos = d }, + }) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func AudioWaveform(c *ui.Context, samples []float32, opts AudioWaveformOptions) ChoiceResult` + +`samples` 取值 -1 到 1。数据就绪时 `Duration` 须大于 0,`OnSeek` 必填。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Duration` | `time.Duration` | — | 音频长度。 | +| `Position` | `time.Duration` | 0 | 已播放部分。 | +| `OnSeek` | `func(time.Duration)` | — | 点击或方向键跳转。 | +| `Selection` | `*MediaRange` | nil | 非 nil 时可拖动或 Shift+方向键选择区间。 | +| `Height` | `float32` | 0(即 96) | 高度。 | +| `Status / Error` | `DataStatus / string` | DataReady | 加载中、失败(须给 Error)与无数据时显示同尺寸占位。 | +| `Label` | `string` | "Waveform" | 无障碍名称。 | + +## 状态 + +- 已播放部分用强调色,其余用说明色,并有播放线和菱形标记,不只靠颜色区分。 +- 选区用 Selection 底色加两条边线。 + +## 事件 + +`Changed()` 在选区变化后为 true;跳转通过 `OnSeek` 报告。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| ← / → | 跳转 ±5 秒 | +| Shift+← / → | 从播放位置开始或调整选区终点 | +| Escape | 清除选区 | + +## 限制 + +- 峰值按像素列计算,只在数据或宽度变化时重算,不会每帧计算。 +- 数据以首元素地址和长度识别;原地修改采样请换一个切片。 diff --git a/docs/components/350-audio-spectrum.md b/docs/components/350-audio-spectrum.md new file mode 100644 index 0000000..b7e2994 --- /dev/null +++ b/docs/components/350-audio-spectrum.md @@ -0,0 +1,49 @@ +# 350 AudioSpectrum 音频频谱 + +## 用途 + +把调用方提供的频带数值画成柱状频谱;组件自己不做动画,隐藏时不重绘。 + +## 最小示例 + +```go +bands := []float32{0.2, 0.6, 0.9, 0.4, 0.1} // set by your analyser, then c.Invalidate() +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AudioSpectrum(c, bands, mujica.AudioSpectrumOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func AudioSpectrum(c *ui.Context, bands []float32, opts AudioSpectrumOptions) *ui.Element` + +每个频带取 0 到 1,超出范围 panic。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Height` | `float32` | 0(即 120) | 高度。 | +| `BandLabel` | `func(i int) string` | nil | 读数中频带的名称,如“1 kHz”;nil 时编号。 | +| `Status / Error` | `DataStatus / string` | DataReady | 加载、失败与无数据占位,尺寸相同。 | +| `Label` | `string` | "Spectrum" | 无障碍名称。 | + +## 状态 + +聚焦后用方向键选中的频带以正文色显示,带虚线框和读数,不只靠颜色。 + +## 事件 + +无事件;方向键读数会通过 `Announce` 朗读。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| Tab | 聚焦频谱 | +| ← / → | 上一个 / 下一个频带 | +| Home / End | 第一个 / 最后一个频带 | + +## 限制 + +- 刷新节奏由调用方决定:更新数据后调用 `c.Invalidate()`。 diff --git a/docs/components/351-volume-control.md b/docs/components/351-volume-control.md new file mode 100644 index 0000000..ef6eb3d --- /dev/null +++ b/docs/components/351-volume-control.md @@ -0,0 +1,46 @@ +# 351 VolumeControl 音量控制 + +## 用途 + +音量滑块与静音按钮。 + +## 最小示例 + +```go +volume, muted := 0.8, false +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.VolumeControl(c, &volume, &muted, mujica.VolumeControlOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func VolumeControl(c *ui.Context, volume *float64, muted *bool, opts VolumeControlOptions) ChoiceResult` + +`*volume` 取 0 到 1,超出 panic;步长 5%。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +静音或音量为 0 时显示静音图标;静音按钮开启时有选中底色和下划线。静音时调高音量会自动取消静音。 + +## 事件 + +`Changed()` 在音量或静音变化后为 true。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| ← / → | 音量 ±5% | +| Home / End | 0% / 100% | +| M | 组件内切换静音 | + +## 限制 + +- 组件不调节系统音量,只改调用方的值。 diff --git a/docs/components/352-playback-speed-control.md b/docs/components/352-playback-speed-control.md new file mode 100644 index 0000000..9a7e829 --- /dev/null +++ b/docs/components/352-playback-speed-control.md @@ -0,0 +1,48 @@ +# 352 PlaybackSpeedControl 倍速选择 + +## 用途 + +在 0.5× 到 2× 之间选择播放速度。 + +## 最小示例 + +```go +rate := 1.0 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.PlaybackSpeedControl(c, &rate, mujica.PlaybackSpeedControlOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func PlaybackSpeedControl(c *ui.Context, rate *float64, opts PlaybackSpeedControlOptions) ChoiceResult` + +`*rate` 必须是 `Rates` 中的一项,否则 panic。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Rates` | `[]float64` | 0.5, 0.75, 1, 1.25, 1.5, 2 | 升序的正数。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +基于 Select,状态与键盘同 Select。 + +## 事件 + +`Changed()` 在选择新倍速后为 true。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| Enter / Space | 打开列表 | +| ↑ / ↓ | 移动 | +| Enter | 确认 | +| Escape | 关闭 | + +## 限制 + +- 无。 diff --git a/docs/components/353-media-controls.md b/docs/components/353-media-controls.md new file mode 100644 index 0000000..3d35038 --- /dev/null +++ b/docs/components/353-media-controls.md @@ -0,0 +1,53 @@ +# 353 MediaControls 媒体控制 + +## 用途 + +上一首、播放/暂停、下一首、循环、随机,一组可用方向键切换焦点的按钮。 + +## 最小示例 + +```go +st := mujica.MediaControlsState{} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.MediaControls(c, st, mujica.MediaControlsOptions{ + OnPrevious: func() {}, OnNext: func() {}, + OnPlay: func() { st.Playing = true }, OnPause: func() { st.Playing = false }, + OnLoop: func(m mujica.LoopMode) { st.Loop = m }, OnShuffle: func(on bool) { st.Shuffle = on }, + }) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func MediaControls(c *ui.Context, st MediaControlsState, opts MediaControlsOptions) *ui.Element` + +`MediaControlsState`:`Playing`、`Loop`(`LoopOff`、`LoopAll`、`LoopOne`)、`Shuffle`、`NoPrevious`、`NoNext`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `OnPrevious / OnPlay / OnPause / OnNext` | `func()` | 必填 | 按钮回调。 | +| `OnLoop` | `func(LoopMode)` | 必填 | 收到下一个循环模式:不循环 → 列表 → 单曲。 | +| `OnShuffle` | `func(bool)` | 必填 | 随机开关。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +循环与随机开启时有选中底色和下划线,单曲循环换用带“1”的图标;循环按钮的名称说明当前模式。 + +## 事件 + +全部通过回调报告。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| Tab | 进入按钮组 | +| ← / → | 在按钮间移动焦点 | +| Enter / Space | 按下 | + +## 限制 + +- 无。 diff --git a/docs/components/354-playlist.md b/docs/components/354-playlist.md new file mode 100644 index 0000000..85bac64 --- /dev/null +++ b/docs/components/354-playlist.md @@ -0,0 +1,52 @@ +# 354 Playlist 播放列表 + +## 用途 + +播放列表:标出当前项,可拖动排序、移除,只构建可见行。 + +## 最小示例 + +```go +items := []mujica.PlaylistItem{{ID: "a", Title: "Overture"}, {ID: "b", Title: "Masquerade"}} +current := "a" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.Playlist(c, &items, mujica.PlaylistOptions{Current: current}); r.Played != "" { + current = r.Played + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func Playlist(c *ui.Context, items *[]PlaylistItem, opts PlaylistOptions) PlaylistResult` + +`PlaylistItem`:`ID`(唯一且非空,否则 panic)、`Title`、`Subtitle`、`Duration`。组件直接修改 `*items` 完成排序和移除。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Current` | `string` | "" | 正在播放项的 ID,显示播放标记和强调文字。 | +| `Height` | `float32` | 0(即 320) | 列表高度。 | +| `Disabled` | `bool` | false | 禁用选择、排序和移除。 | + +## 状态 + +基于 List:选中行使用 Selection 底色加勾选标记;空列表显示提示。 + +## 事件 + +`PlaylistResult`:`Played` 为 Enter 或双击选择的 ID;`Removed` 为被移除的 ID;`Moved` 表示顺序变化。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| ↑ / ↓ | 移动选择 | +| Enter | 播放选中项 | +| Alt+↑ / Alt+↓ | 上移 / 下移选中项 | +| Delete / Backspace | 移除选中项 | + +## 限制 + +- 拖动排序由 MyGo List 的 Reorder 提供,拖动时显示插入线。 diff --git a/docs/components/355-subtitle-editor.md b/docs/components/355-subtitle-editor.md new file mode 100644 index 0000000..eb921bc --- /dev/null +++ b/docs/components/355-subtitle-editor.md @@ -0,0 +1,52 @@ +# 355 SubtitleEditor 字幕编辑器 + +## 用途 + +逐条编辑字幕的开始、结束时间和文本,校验时间先后与重叠。 + +## 最小示例 + +```go +cues := []mujica.SubtitleCue{{Start: 0, End: 2 * time.Second, Text: "The curtain rises."}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SubtitleEditor(c, &cues, mujica.SubtitleEditorOptions{}) + if len(mujica.CheckSubtitles(cues)) > 0 { + _ = cues // block saving until the issues are fixed + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func SubtitleEditor(c *ui.Context, cues *[]SubtitleCue, opts SubtitleEditorOptions) ChoiceResult` + +`func CheckSubtitles(cues []SubtitleCue) []SubtitleIssue` 返回结束早于开始(`SubtitleEndBeforeStart`)和与上一条重叠(`SubtitleOverlap`)的条目,供调用方阻止保存。时间格式为 `m:ss.mmm` 或 `h:mm:ss.mmm`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Height` | `float32` | 0(即 360) | 列表高度。 | +| `Disabled` | `bool` | false | 禁用编辑、添加和删除。 | + +## 状态 + +- 无法解析的时间保留在输入框中,并显示格式提示;有效后才写回。 +- 时间问题在该行下方用错误色说明,并报告给辅助技术。 +- 只构建可见行,10 万条也保持流畅。 + +## 事件 + +`Changed()` 在任一字段、添加或删除后为 true。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| Tab | 在一行的开始、结束、文本、删除之间移动 | +| Enter | 提交输入 | + +## 限制 + +- 虚拟化只构建可见行,Tab 不会跳到未显示的行;请先滚动。 +- 组件不排序字幕;顺序由调用方决定。 diff --git a/docs/components/356-screen-recorder-controls.md b/docs/components/356-screen-recorder-controls.md new file mode 100644 index 0000000..d0dcb96 --- /dev/null +++ b/docs/components/356-screen-recorder-controls.md @@ -0,0 +1,51 @@ +# 356 ScreenRecorderControls 录屏控制 + +## 用途 + +开始、暂停、继续、停止录制并显示计时;录制本身由调用方实现。 + +## 最小示例 + +```go +st := mujica.RecorderState{} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ScreenRecorderControls(c, st, mujica.ScreenRecorderControlsOptions{ + OnStart: func() { st.Status = mujica.RecorderRecording }, + OnPause: func() { st.Status = mujica.RecorderPaused }, + OnResume: func() { st.Status = mujica.RecorderRecording }, + OnStop: func() { st = mujica.RecorderState{} }, + }) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ScreenRecorderControls(c *ui.Context, st RecorderState, opts ScreenRecorderControlsOptions) *ui.Element` + +`RecorderState`:`Status`(`RecorderIdle`、`RecorderRecording`、`RecorderPaused`)、`Elapsed`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `OnStart / OnPause / OnResume / OnStop` | `func()` | 必填 | 缺少任一回调时 panic。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +就绪、录制中(红点)、已暂停;状态同时用文字表示,不只靠圆点颜色。录制中的圆点不闪烁。 + +## 事件 + +全部通过回调报告。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| Tab | 在按钮间移动 | +| Enter / Space | 按下 | + +## 限制 + +- 计时由调用方更新 `Elapsed`。 diff --git a/docs/components/357-camera-preview.md b/docs/components/357-camera-preview.md new file mode 100644 index 0000000..e7d4aa5 --- /dev/null +++ b/docs/components/357-camera-preview.md @@ -0,0 +1,48 @@ +# 357 CameraPreview 摄像头预览 + +## 用途 + +显示调用方提供的摄像头帧,无帧时显示“无信号”,可切换镜像。 + +## 最小示例 + +```go +frame := mujica.CameraFrame{Image: examplePhoto, Seq: 1} // a new Seq for each captured frame +mirror := true +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CameraPreview(c, frame, &mirror, mujica.CameraPreviewOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func CameraPreview(c *ui.Context, frame CameraFrame, mirror *bool, opts CameraPreviewOptions) ChoiceResult` + +`CameraFrame`:`Image`(标准库 `image.Image`,nil 为无信号)、`Seq`(帧序号,复用同一图像缓冲时用新序号触发重绘)。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Label` | `string` | "Camera" | 无障碍名称。 | +| `Disabled` | `bool` | false | 禁用镜像切换。 | + +## 状态 + +16:9 黑底;镜像按钮开启时有选中底色和下划线。 + +## 事件 + +`Changed()` 在镜像切换后为 true。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| Tab | 聚焦预览 | +| M | 切换镜像 | + +## 限制 + +- MyGo 的 Painter 不能水平翻转位图(ui/paint.go:834),所以镜像时组件每个新帧复制一份翻转后的像素;高分辨率帧会占用 CPU。 +- 组件不打开摄像头。 diff --git a/docs/components/358-mic-level-meter.md b/docs/components/358-mic-level-meter.md new file mode 100644 index 0000000..29152ea --- /dev/null +++ b/docs/components/358-mic-level-meter.md @@ -0,0 +1,45 @@ +# 358 MicLevelMeter 麦克风电平 + +## 用途 + +分段电平条,带峰值保持与 dB 读数。 + +## 最小示例 + +```go +level := float32(0.4) // the input's peak, 0 to 1 of full scale +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.MicLevelMeter(c, level, mujica.MicLevelMeterOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func MicLevelMeter(c *ui.Context, level float32, opts MicLevelMeterOptions) *ui.Element` + +`level` 为满刻度的 0 到 1,超出 panic。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Hold` | `time.Duration` | 1.5 秒 | 峰值保持时长。 | +| `Label` | `string` | "Microphone level" | 无障碍名称;描述中读出当前与峰值 dB。 | + +## 状态 + +24 段:前 70% 为成功色,接着警告色,最后 10% 为危险色;峰值段为空心标记;右侧显示 dB 数值,不只靠颜色。 + +## 事件 + +无。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| — | 不获取焦点 | + +## 限制 + +- 保持结束时只请求一次重绘,空闲时不持续重绘。 diff --git a/docs/components/359-device-selector.md b/docs/components/359-device-selector.md new file mode 100644 index 0000000..06f202b --- /dev/null +++ b/docs/components/359-device-selector.md @@ -0,0 +1,51 @@ +# 359 DeviceSelector 设备选择 + +## 用途 + +选择麦克风、摄像头、扬声器,设备列表由调用方提供。 + +## 最小示例 + +```go +devices := mujica.MediaDevices{ + Microphones: []mujica.MediaDevice{{ID: "mic-1", Name: "Built-in Microphone"}}, + Speakers: []mujica.MediaDevice{{ID: "out-1", Name: "Headphones"}}, +} +sel := mujica.DeviceSelection{Microphone: "mic-1"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.DeviceSelector(c, &sel, devices, mujica.DeviceSelectorOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func DeviceSelector(c *ui.Context, sel *DeviceSelection, devices MediaDevices, opts DeviceSelectorOptions) ChoiceResult` + +`MediaDevices` 的某类列表为 nil 时不显示该类;为空切片时显示禁用的“未找到设备”。设备 ID 重复,或已选 ID 不在列表中时 panic。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Disabled` | `bool` | false | 禁用全部选择。 | + +## 状态 + +每类一行:图标、名称和 Select。 + +## 事件 + +`Changed()` 在任一类选择变化后为 true。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| Tab | 在各选择框间移动 | +| Enter / Space | 打开列表 | +| ↑ / ↓ | 移动 | +| 输入字母 | 跳到匹配的设备 | + +## 限制 + +- 组件不枚举设备,也不监听设备插拔;调用方更新列表即可。 diff --git a/docs/components/360-image-compare.md b/docs/components/360-image-compare.md new file mode 100644 index 0000000..cc03a72 --- /dev/null +++ b/docs/components/360-image-compare.md @@ -0,0 +1,48 @@ +# 360 ImageCompare 前后对比 + +## 用途 + +前后两张图片叠放,用滑块分隔对比。 + +## 最小示例 + +```go +before, after := ui.NewBitmap(examplePhoto), ui.NewBitmap(examplePhoto) +split := 0.5 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ImageCompare(c, before, after, &split, mujica.ImageCompareOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ImageCompare(c *ui.Context, before, after ui.ImageSource, split *float64, opts ImageCompareOptions) ChoiceResult` + +`*split` 取 0 到 1,表示分隔线位置;超出 panic。两张图都须为 `*ui.Bitmap` 或 `*ui.SVG`,盒子按 `before` 的宽高比。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `BeforeLabel / AfterLabel` | `string` | "Before" / "After" | 两侧标签,也组成无障碍名称。 | +| `Disabled` | `bool` | false | 禁用。 | + +## 状态 + +分隔线与菱形手柄;两侧标签始终显示,不只靠画面区分。 + +## 事件 + +`Changed()` 在分隔位置变化后为 true。 + +## 键盘操作 + +| 按键 | 作用 | +| --- | --- | +| ← / → | 移动 1% | +| Home / End | 最左 / 最右 | +| 拖动 | 任意位置拖动分隔线 | + +## 限制 + +- 两张图都按 Cover 铺满盒子,尺寸不同时会裁切。 diff --git a/example_media_test.go b/example_media_test.go new file mode 100644 index 0000000..52b53f1 --- /dev/null +++ b/example_media_test.go @@ -0,0 +1,246 @@ +package mujica_test + +import ( + "image" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +// examplePhoto stands in for a decoded picture. +var examplePhoto = image.NewRGBA(image.Rect(0, 0, 320, 180)) + +func ExampleImageCropper() { + crop := mujica.ImageCrop{} // empty: starts fitted to the image + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ImageCropper(c, examplePhoto, &crop, mujica.ImageCropperOptions{Aspect: 1}).Changed() { + _ = crop.Rect // in pixels of the photo turned by crop.Rotation + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleImageAnnotator() { + photo := ui.NewBitmap(examplePhoto) + var notes []mujica.Annotation + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ImageAnnotator(c, photo, ¬es, mujica.ImageAnnotatorOptions{}).Changed() { + data, _ := mujica.ExportAnnotations(notes) + _ = data // save the JSON + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleImageThumbnail() { + photo := ui.NewBitmap(examplePhoto) + selected := false + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ImageThumbnail(c, photo, mujica.ImageThumbnailOptions{Alt: "Grand hall", Aspect: 4.0 / 3, Selected: selected}).Changed() { + selected = !selected + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleLightbox() { + images := []mujica.ViewerImage{{Source: ui.NewBitmap(examplePhoto), Alt: "The grand hall"}} + open, index := false, 0 + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.Button(c, "View photos", mujica.ButtonOptions{}).Clicked() { + open = true + } + mujica.Lightbox(c, &open, &index, images) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleVideoPlayer() { + st := mujica.VideoState{Duration: 4 * time.Minute, Rate: 1} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.VideoPlayer(c, st, mujica.VideoPlayerOptions{ + OnPlay: func() { st.Playing = true }, // start your decoder + OnPause: func() { st.Playing = false }, // pause it + OnSeek: func(d time.Duration) { st.Position = d }, + OnRate: func(r float64) { st.Rate = r }, + }) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleVideoScrubber() { + pos := 30 * time.Second + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.VideoScrubber(c, &pos, mujica.VideoScrubberOptions{ + Duration: 2 * time.Minute, + Buffered: []mujica.MediaRange{{Start: 0, End: time.Minute}}, + }) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleVideoThumbnailStrip() { + frames := []mujica.StripFrame{{At: 0}, {At: 10 * time.Second}, {At: 20 * time.Second}} + current := 0 + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.VideoThumbnailStrip(c, ¤t, frames, mujica.VideoThumbnailStripOptions{}).Changed() { + _ = frames[current].At // seek the player there + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleAudioPlayer() { + st := mujica.AudioState{Title: "Overture", Duration: 3 * time.Minute} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AudioPlayer(c, st, mujica.AudioPlayerOptions{ + OnPlay: func() { st.Playing = true }, + OnPause: func() { st.Playing = false }, + OnSeek: func(d time.Duration) { st.Position = d }, + }) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleAudioWaveform() { + samples := make([]float32, 48000) // from your decoder, -1 to 1 + pos, sel := time.Duration(0), mujica.MediaRange{} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AudioWaveform(c, samples, mujica.AudioWaveformOptions{ + Duration: time.Second, Position: pos, Selection: &sel, + OnSeek: func(d time.Duration) { pos = d }, + }) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleAudioSpectrum() { + bands := []float32{0.2, 0.6, 0.9, 0.4, 0.1} // set by your analyser, then c.Invalidate() + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AudioSpectrum(c, bands, mujica.AudioSpectrumOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleVolumeControl() { + volume, muted := 0.8, false + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.VolumeControl(c, &volume, &muted, mujica.VolumeControlOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExamplePlaybackSpeedControl() { + rate := 1.0 + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.PlaybackSpeedControl(c, &rate, mujica.PlaybackSpeedControlOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMediaControls() { + st := mujica.MediaControlsState{} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.MediaControls(c, st, mujica.MediaControlsOptions{ + OnPrevious: func() {}, OnNext: func() {}, + OnPlay: func() { st.Playing = true }, OnPause: func() { st.Playing = false }, + OnLoop: func(m mujica.LoopMode) { st.Loop = m }, OnShuffle: func(on bool) { st.Shuffle = on }, + }) + } + ui.Render(view, 400, 300, 1) +} + +func ExamplePlaylist() { + items := []mujica.PlaylistItem{{ID: "a", Title: "Overture"}, {ID: "b", Title: "Masquerade"}} + current := "a" + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.Playlist(c, &items, mujica.PlaylistOptions{Current: current}); r.Played != "" { + current = r.Played + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleSubtitleEditor() { + cues := []mujica.SubtitleCue{{Start: 0, End: 2 * time.Second, Text: "The curtain rises."}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SubtitleEditor(c, &cues, mujica.SubtitleEditorOptions{}) + if len(mujica.CheckSubtitles(cues)) > 0 { + _ = cues // block saving until the issues are fixed + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleScreenRecorderControls() { + st := mujica.RecorderState{} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ScreenRecorderControls(c, st, mujica.ScreenRecorderControlsOptions{ + OnStart: func() { st.Status = mujica.RecorderRecording }, + OnPause: func() { st.Status = mujica.RecorderPaused }, + OnResume: func() { st.Status = mujica.RecorderRecording }, + OnStop: func() { st = mujica.RecorderState{} }, + }) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCameraPreview() { + frame := mujica.CameraFrame{Image: examplePhoto, Seq: 1} // a new Seq for each captured frame + mirror := true + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CameraPreview(c, frame, &mirror, mujica.CameraPreviewOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMicLevelMeter() { + level := float32(0.4) // the input's peak, 0 to 1 of full scale + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.MicLevelMeter(c, level, mujica.MicLevelMeterOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleDeviceSelector() { + devices := mujica.MediaDevices{ + Microphones: []mujica.MediaDevice{{ID: "mic-1", Name: "Built-in Microphone"}}, + Speakers: []mujica.MediaDevice{{ID: "out-1", Name: "Headphones"}}, + } + sel := mujica.DeviceSelection{Microphone: "mic-1"} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.DeviceSelector(c, &sel, devices, mujica.DeviceSelectorOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleImageCompare() { + before, after := ui.NewBitmap(examplePhoto), ui.NewBitmap(examplePhoto) + split := 0.5 + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ImageCompare(c, before, after, &split, mujica.ImageCompareOptions{}) + } + ui.Render(view, 400, 300, 1) +} diff --git a/examples/gallery/pages_media.go b/examples/gallery/pages_media.go index 92da6e4..dd1d945 100644 --- a/examples/gallery/pages_media.go +++ b/examples/gallery/pages_media.go @@ -1,3 +1,118 @@ package main -var mediaPages = []page{} +import ( + "fmt" + "image" + "image/color" + "math" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" + "mujicaui/theme" +) + +const mediaCategory = "Media" + +var mediaPages = []page{ + {ID: "341", Name: "ImageCropper", ZhName: "图片裁剪", Category: mediaCategory, Demo: imageCropperDemo, Code: imageCropperCode, + Keys: "方向键移动裁剪框;Shift+方向键缩放;R / Shift+R 向右 / 向左旋转。"}, + {ID: "342", Name: "ImageAnnotator", ZhName: "图片标注", Category: mediaCategory, Demo: imageAnnotatorDemo, Code: imageAnnotatorCode, + Keys: "[ / ] 切换选中标注;方向键移动;Delete 删除;Escape 取消选择。"}, + {ID: "343", Name: "ImageThumbnail", ZhName: "缩略图", Category: mediaCategory, Demo: imageThumbnailDemo, Code: imageThumbnailCode, + Keys: "Tab 聚焦;Enter / Space 激活。"}, + {ID: "344", Name: "Lightbox", ZhName: "灯箱", Category: mediaCategory, Demo: lightboxDemo, Code: lightboxCode, + Keys: "← / → 切换;Home / End 首尾;Escape 关闭并恢复焦点。"}, + {ID: "345", Name: "VideoPlayer", ZhName: "视频播放器", Category: mediaCategory, Demo: videoPlayerDemo, Code: videoPlayerCode, + Keys: "画面聚焦时 Space / K 播放暂停,← / → 跳转 5 秒,F 全屏,C 字幕。"}, + {ID: "346", Name: "VideoScrubber", ZhName: "视频时间轴", Category: mediaCategory, Demo: videoScrubberDemo, Code: videoScrubberCode, + Keys: "← / → 跳转一个步长;Home / End 开头结尾。"}, + {ID: "347", Name: "VideoThumbnailStrip", ZhName: "缩略帧条", Category: mediaCategory, Demo: videoStripDemo, Code: videoStripCode, + Keys: "Tab 聚焦帧条;← / → 上下帧;Home / End 首尾帧。"}, + {ID: "348", Name: "AudioPlayer", ZhName: "音频播放器", Category: mediaCategory, Demo: audioPlayerDemo, Code: audioPlayerCode, + Keys: "Space 播放或暂停;进度条聚焦时 ← / → 跳转 5 秒。"}, + {ID: "349", Name: "AudioWaveform", ZhName: "音频波形", Category: mediaCategory, Demo: audioWaveformDemo, Code: audioWaveformCode, + Keys: "← / → 跳转 5 秒;Shift+← / → 调整选区;Escape 清除选区。"}, + {ID: "350", Name: "AudioSpectrum", ZhName: "音频频谱", Category: mediaCategory, Demo: audioSpectrumDemo, Code: audioSpectrumCode, + Keys: "Tab 聚焦;← / → 逐个读出频带;Home / End 首尾。"}, + {ID: "351", Name: "VolumeControl", ZhName: "音量控制", Category: mediaCategory, Demo: volumeDemo, Code: volumeCode, + Keys: "← / → 音量 ±5%;Home / End;M 静音。"}, + {ID: "352", Name: "PlaybackSpeedControl", ZhName: "倍速选择", Category: mediaCategory, Demo: speedDemo, Code: speedCode, + Keys: "Enter / Space 打开;↑ / ↓ 移动;Enter 确认;Escape 关闭。"}, + {ID: "353", Name: "MediaControls", ZhName: "媒体控制", Category: mediaCategory, Demo: mediaControlsDemo, Code: mediaControlsCode, + Keys: "Tab 进入;← / → 在按钮间移动;Enter / Space 按下。"}, + {ID: "354", Name: "Playlist", ZhName: "播放列表", Category: mediaCategory, Demo: playlistDemo, Code: playlistCode, + Keys: "↑ / ↓ 选择;Enter 播放;Alt+↑ / ↓ 移动;Delete 移除;可拖动排序。"}, + {ID: "355", Name: "SubtitleEditor", ZhName: "字幕编辑器", Category: mediaCategory, Demo: subtitleDemo, Code: subtitleCode, + Keys: "Tab 在一行的开始、结束、文本、删除间移动;时间格式 m:ss.mmm。"}, + {ID: "356", Name: "ScreenRecorderControls", ZhName: "录屏控制", Category: mediaCategory, Demo: recorderDemo, Code: recorderCode, + Keys: "Tab 在按钮间移动;Enter / Space 按下。"}, + {ID: "357", Name: "CameraPreview", ZhName: "摄像头预览", Category: mediaCategory, Demo: cameraDemo, Code: cameraCode, + Keys: "Tab 聚焦预览;M 切换镜像。"}, + {ID: "358", Name: "MicLevelMeter", ZhName: "麦克风电平", Category: mediaCategory, Demo: micDemo, Code: micCode, + Keys: "不获取焦点;读数随描述朗读。"}, + {ID: "359", Name: "DeviceSelector", ZhName: "设备选择", Category: mediaCategory, Demo: deviceDemo, Code: deviceCode, + Keys: "Tab 在选择框间移动;Enter 打开;输入字母跳转。"}, + {ID: "360", Name: "ImageCompare", ZhName: "前后对比", Category: mediaCategory, Demo: compareDemo, Code: compareCode, + Keys: "← / → 移动 1%;Home / End;可拖动。"}, +} + +// mediaSection titles a part of a demo. +func mediaSection(c *ui.Context, title string, fn func()) { + ui.Column(c).Gap(8).FillWidth().Children(func() { + ui.Text(c, title).FontSize(mujica.FontSize(c, theme.CaptionSize)).TextColor(mujica.Tokens(c).TextMuted) + fn() + }) +} + +// mediaCheck is a parameter checkbox that logs its changes. +func mediaCheck(c *ui.Context, log func(string), v *bool, label string) { + before := *v + mujica.Checkbox(c, v, label, mujica.CheckboxOptions{}) + if *v != before { + log(fmt.Sprintf("%s = %v", label, *v)) + } +} + +// mediaPicture draws a w×h court scene in variant hues. +func mediaPicture(w, h, variant int) *image.RGBA { + walls := []color.RGBA{{36, 28, 32, 255}, {242, 235, 221, 255}, {73, 42, 54, 255}} + arch := []color.RGBA{{125, 32, 52, 255}, {173, 145, 100, 255}, {53, 94, 128, 255}} + img := image.NewRGBA(image.Rect(0, 0, w, h)) + cx := float64(w) / 2 + for y := range h { + for x := range w { + c := walls[variant%3] + dx, dy := (float64(x)-cx)/(float64(w)*0.28), (float64(y)-float64(h)*0.55)/(float64(h)*0.5) + if dy > 0 && math.Abs(dx) < 1 || dx*dx+dy*dy < 1 { + c = arch[variant%3] + } + if x%(w/6) < w/40 || y > h*7/8 { + c = color.RGBA{189, 161, 114, 255} + } + if math.Abs(float64(x)-cx)/float64(w)+math.Abs(float64(y)-float64(h)*0.45)/float64(h) < 0.06 { + c = color.RGBA{251, 247, 239, 255} + } + img.Set(x, y, c) + } + } + return img +} + +var ( + mediaPhotos = []*image.RGBA{mediaPicture(480, 270, 0), mediaPicture(480, 270, 1), mediaPicture(360, 360, 2)} + mediaBitmaps = func() []*ui.Bitmap { + out := make([]*ui.Bitmap, len(mediaPhotos)) + for i, p := range mediaPhotos { + out[i] = ui.NewBitmap(p) + } + return out + }() +) + +// mediaClockLabel writes d as m:ss for event logs. +func mediaClockLabel(d time.Duration) string { + s := int(d / time.Second) + return fmt.Sprintf("%d:%02d", s/60, s%60) +} diff --git a/examples/gallery/pages_media_av.go b/examples/gallery/pages_media_av.go new file mode 100644 index 0000000..394b94a --- /dev/null +++ b/examples/gallery/pages_media_av.go @@ -0,0 +1,191 @@ +package main + +import ( + "fmt" + "math" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +// mediaClockState simulates the caller's playback: position advances while playing. +type mediaClockState struct { + pos, dur time.Duration + playing bool + rate float64 + last time.Time +} + +// tick advances the position; frames are asked only while playing. +func (m *mediaClockState) tick(c *ui.Context) { + now := c.Now() + if m.playing { + if !m.last.IsZero() { + m.pos += time.Duration(float64(now.Sub(m.last)) * m.rate) + } + if m.pos >= m.dur { + m.pos, m.playing = m.dur, false + } else { + c.AnimationFrame() + } + } + m.last = now +} + +func videoPlayerDemo(c *ui.Context, log func(string)) { + type state struct { + clock mediaClockState + subs, full, pip, noFrame bool + disabled bool + } + s := ui.Local(c.Root(), "345", func() state { + return state{clock: mediaClockState{dur: 3 * time.Minute, rate: 1}, subs: true} + }) + s.clock.tick(c) + mediaSection(c, "Parameters", func() { + ui.Row(c).Gap(16).Children(func() { + mediaCheck(c, log, &s.noFrame, "No frame") + mediaCheck(c, log, &s.disabled, "Disabled") + }) + }) + cues := []string{"The curtain rises.", "Welcome to the masquerade.", "Ave Mujica."} + var frame ui.ImageSource = mediaBitmaps[int(s.clock.pos/(20*time.Second))%3] + if s.noFrame { + frame = nil + } + st := mujica.VideoState{Frame: frame, Position: s.clock.pos, Duration: s.clock.dur, Playing: s.clock.playing, + Rate: s.clock.rate, Buffered: []mujica.MediaRange{{Start: 0, End: s.clock.pos + 40*time.Second}}, + Subtitle: cues[int(s.clock.pos/(10*time.Second))%3], SubtitlesOn: s.subs, Fullscreen: s.full, PiP: s.pip} + mediaSection(c, "Live", func() { + ui.Column(c).MaxWidth(640).Children(func() { + mujica.VideoPlayer(c, st, mujica.VideoPlayerOptions{ + OnPlay: func() { s.clock.playing = true; log("play") }, + OnPause: func() { s.clock.playing = false; log("pause") }, + OnSeek: func(d time.Duration) { s.clock.pos = d; log("seek " + mediaClockLabel(d)) }, + OnRate: func(r float64) { s.clock.rate = r; log(fmt.Sprintf("rate %v×", r)) }, + OnSubtitles: func(on bool) { s.subs = on; log(fmt.Sprintf("subtitles %v", on)) }, + OnFullscreen: func(on bool) { s.full = on; log(fmt.Sprintf("full screen requested %v", on)) }, + OnPiP: func(on bool) { s.pip = on; log(fmt.Sprintf("picture in picture requested %v", on)) }, + Disabled: s.disabled, + }) + }) + }) +} + +func videoScrubberDemo(c *ui.Context, log func(string)) { + type state struct { + pos time.Duration + preview, disabled bool + } + s := ui.Local(c.Root(), "346", func() state { return state{pos: 40 * time.Second, preview: true} }) + mediaSection(c, "Parameters", func() { + ui.Row(c).Gap(16).Children(func() { + mediaCheck(c, log, &s.preview, "Preview slot") + mediaCheck(c, log, &s.disabled, "Disabled") + }) + }) + opts := mujica.VideoScrubberOptions{Duration: 3 * time.Minute, Disabled: s.disabled, + Buffered: []mujica.MediaRange{{Start: 0, End: 90 * time.Second}, {Start: 120 * time.Second, End: 140 * time.Second}}} + if s.preview { + opts.Preview = func(at time.Duration) { + ui.Image(c, mediaBitmaps[int(at/(time.Minute))%3]).Fit(ui.Cover).Fill() + } + } + mediaSection(c, "Live", func() { + ui.Column(c).MaxWidth(560).Padding(110, 0, 0, 0).Children(func() { + if mujica.VideoScrubber(c, &s.pos, opts).Changed() { + log("seek " + mediaClockLabel(s.pos)) + } + }) + }) +} + +func audioPlayerDemo(c *ui.Context, log func(string)) { + type state struct { + clock mediaClockState + disabled bool + } + s := ui.Local(c.Root(), "348", func() state { return state{clock: mediaClockState{dur: 4*time.Minute + 5*time.Second, rate: 1}} }) + s.clock.tick(c) + mediaSection(c, "Parameters", func() { mediaCheck(c, log, &s.disabled, "Disabled") }) + mediaSection(c, "Live", func() { + ui.Column(c).MaxWidth(560).Children(func() { + mujica.AudioPlayer(c, mujica.AudioState{Title: "Ave Mujica — Overture", Position: s.clock.pos, Duration: s.clock.dur, Playing: s.clock.playing}, + mujica.AudioPlayerOptions{ + OnPlay: func() { s.clock.playing = true; log("play") }, + OnPause: func() { s.clock.playing = false; log("pause") }, + OnSeek: func(d time.Duration) { s.clock.pos = d; log("seek " + mediaClockLabel(d)) }, + Disabled: s.disabled, + }) + }) + }) +} + +// mediaSamples is a synthetic voice-like recording, made once. +var mediaSamples = func() []float32 { + s := make([]float32, 120000) + for i := range s { + env := 0.25 + 0.7*math.Abs(math.Sin(float64(i)/9000))*math.Abs(math.Sin(float64(i)/2100)) + s[i] = float32(env * math.Sin(float64(i)/7)) + } + return s +}() + +func audioWaveformDemo(c *ui.Context, log func(string)) { + type state struct { + pos time.Duration + sel mujica.MediaRange + status int + selecting bool + } + s := ui.Local(c.Root(), "349", func() state { return state{pos: 20 * time.Second, selecting: true} }) + mediaSection(c, "Parameters", func() { + ui.Row(c).Gap(16).AlignItems(ui.Center).Children(func() { + before := s.status + mujica.SegmentedControl(c, &s.status, []mujica.Segment{{Label: "Ready"}, {Label: "Loading"}, {Label: "Failed"}, {Label: "Empty"}}, mujica.SegmentedControlOptions{Label: "Status"}) + if s.status != before { + log(fmt.Sprintf("status %d", s.status)) + } + mediaCheck(c, log, &s.selecting, "Selectable") + }) + }) + opts := mujica.AudioWaveformOptions{Duration: time.Minute, Position: s.pos, OnSeek: func(d time.Duration) { s.pos = d; log("seek " + mediaClockLabel(d)) }} + if s.selecting { + opts.Selection = &s.sel + } + data := mediaSamples + switch s.status { + case 1: + opts.Status, data = mujica.DataLoading, nil + case 2: + opts.Status, opts.Error, data = mujica.DataFailed, "The recording could not be decoded.", nil + case 3: + data = nil + } + mediaSection(c, "Live", func() { + if mujica.AudioWaveform(c, data, opts).Changed() { + log(fmt.Sprintf("selection %s – %s", mediaClockLabel(s.sel.Start), mediaClockLabel(s.sel.End))) + } + }) +} + +func audioSpectrumDemo(c *ui.Context, log func(string)) { + type state struct{ live bool } + s := ui.Local(c.Root(), "350", func() state { return state{live: true} }) + mediaSection(c, "Parameters", func() { mediaCheck(c, log, &s.live, "Live input") }) + freqs := []string{"32 Hz", "63 Hz", "125 Hz", "250 Hz", "500 Hz", "1 kHz", "2 kHz", "4 kHz", "8 kHz", "16 kHz"} + bands := make([]float32, len(freqs)) + t := float64(c.Now().UnixMilli()) / 1000 + for i := range bands { + bands[i] = float32(0.2 + 0.6*math.Abs(math.Sin(float64(i)*0.9+t*(1+float64(i)*0.2)))) + } + if s.live { + // The demo is its own analyser; the component only draws. + c.AnimationFrame() + } + mediaSection(c, "Live", func() { + mujica.AudioSpectrum(c, bands, mujica.AudioSpectrumOptions{BandLabel: func(i int) string { return freqs[i] }}) + }) +} diff --git a/examples/gallery/pages_media_code.go b/examples/gallery/pages_media_code.go new file mode 100644 index 0000000..7a2528d --- /dev/null +++ b/examples/gallery/pages_media_code.go @@ -0,0 +1,178 @@ +package main + +// Media page snippets, each its compiled Example's body. +const ( + imageCropperCode = `crop := mujica.ImageCrop{} // empty: starts fitted to the image +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ImageCropper(c, examplePhoto, &crop, mujica.ImageCropperOptions{Aspect: 1}).Changed() { + _ = crop.Rect // in pixels of the photo turned by crop.Rotation + } +} +ui.Render(view, 400, 300, 1)` + imageAnnotatorCode = `photo := ui.NewBitmap(examplePhoto) +var notes []mujica.Annotation +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ImageAnnotator(c, photo, ¬es, mujica.ImageAnnotatorOptions{}).Changed() { + data, _ := mujica.ExportAnnotations(notes) + _ = data // save the JSON + } +} +ui.Render(view, 400, 300, 1)` + imageThumbnailCode = `photo := ui.NewBitmap(examplePhoto) +selected := false +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ImageThumbnail(c, photo, mujica.ImageThumbnailOptions{Alt: "Grand hall", Aspect: 4.0 / 3, Selected: selected}).Changed() { + selected = !selected + } +} +ui.Render(view, 400, 300, 1)` + lightboxCode = `images := []mujica.ViewerImage{{Source: ui.NewBitmap(examplePhoto), Alt: "The grand hall"}} +open, index := false, 0 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.Button(c, "View photos", mujica.ButtonOptions{}).Clicked() { + open = true + } + mujica.Lightbox(c, &open, &index, images) +} +ui.Render(view, 400, 300, 1)` + videoPlayerCode = `st := mujica.VideoState{Duration: 4 * time.Minute, Rate: 1} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.VideoPlayer(c, st, mujica.VideoPlayerOptions{ + OnPlay: func() { st.Playing = true }, // start your decoder + OnPause: func() { st.Playing = false }, // pause it + OnSeek: func(d time.Duration) { st.Position = d }, + OnRate: func(r float64) { st.Rate = r }, + }) +} +ui.Render(view, 400, 300, 1)` + videoScrubberCode = `pos := 30 * time.Second +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.VideoScrubber(c, &pos, mujica.VideoScrubberOptions{ + Duration: 2 * time.Minute, + Buffered: []mujica.MediaRange{{Start: 0, End: time.Minute}}, + }) +} +ui.Render(view, 400, 300, 1)` + videoStripCode = `frames := []mujica.StripFrame{{At: 0}, {At: 10 * time.Second}, {At: 20 * time.Second}} +current := 0 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.VideoThumbnailStrip(c, ¤t, frames, mujica.VideoThumbnailStripOptions{}).Changed() { + _ = frames[current].At // seek the player there + } +} +ui.Render(view, 400, 300, 1)` + audioPlayerCode = `st := mujica.AudioState{Title: "Overture", Duration: 3 * time.Minute} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AudioPlayer(c, st, mujica.AudioPlayerOptions{ + OnPlay: func() { st.Playing = true }, + OnPause: func() { st.Playing = false }, + OnSeek: func(d time.Duration) { st.Position = d }, + }) +} +ui.Render(view, 400, 300, 1)` + audioWaveformCode = `samples := make([]float32, 48000) // from your decoder, -1 to 1 +pos, sel := time.Duration(0), mujica.MediaRange{} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AudioWaveform(c, samples, mujica.AudioWaveformOptions{ + Duration: time.Second, Position: pos, Selection: &sel, + OnSeek: func(d time.Duration) { pos = d }, + }) +} +ui.Render(view, 400, 300, 1)` + audioSpectrumCode = `bands := []float32{0.2, 0.6, 0.9, 0.4, 0.1} // set by your analyser, then c.Invalidate() +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AudioSpectrum(c, bands, mujica.AudioSpectrumOptions{}) +} +ui.Render(view, 400, 300, 1)` + volumeCode = `volume, muted := 0.8, false +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.VolumeControl(c, &volume, &muted, mujica.VolumeControlOptions{}) +} +ui.Render(view, 400, 300, 1)` + speedCode = `rate := 1.0 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.PlaybackSpeedControl(c, &rate, mujica.PlaybackSpeedControlOptions{}) +} +ui.Render(view, 400, 300, 1)` + mediaControlsCode = `st := mujica.MediaControlsState{} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.MediaControls(c, st, mujica.MediaControlsOptions{ + OnPrevious: func() {}, OnNext: func() {}, + OnPlay: func() { st.Playing = true }, OnPause: func() { st.Playing = false }, + OnLoop: func(m mujica.LoopMode) { st.Loop = m }, OnShuffle: func(on bool) { st.Shuffle = on }, + }) +} +ui.Render(view, 400, 300, 1)` + playlistCode = `items := []mujica.PlaylistItem{{ID: "a", Title: "Overture"}, {ID: "b", Title: "Masquerade"}} +current := "a" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.Playlist(c, &items, mujica.PlaylistOptions{Current: current}); r.Played != "" { + current = r.Played + } +} +ui.Render(view, 400, 300, 1)` + subtitleCode = `cues := []mujica.SubtitleCue{{Start: 0, End: 2 * time.Second, Text: "The curtain rises."}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SubtitleEditor(c, &cues, mujica.SubtitleEditorOptions{}) + if len(mujica.CheckSubtitles(cues)) > 0 { + _ = cues // block saving until the issues are fixed + } +} +ui.Render(view, 400, 300, 1)` + recorderCode = `st := mujica.RecorderState{} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ScreenRecorderControls(c, st, mujica.ScreenRecorderControlsOptions{ + OnStart: func() { st.Status = mujica.RecorderRecording }, + OnPause: func() { st.Status = mujica.RecorderPaused }, + OnResume: func() { st.Status = mujica.RecorderRecording }, + OnStop: func() { st = mujica.RecorderState{} }, + }) +} +ui.Render(view, 400, 300, 1)` + cameraCode = `frame := mujica.CameraFrame{Image: examplePhoto, Seq: 1} // a new Seq for each captured frame +mirror := true +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CameraPreview(c, frame, &mirror, mujica.CameraPreviewOptions{}) +} +ui.Render(view, 400, 300, 1)` + micCode = `level := float32(0.4) // the input's peak, 0 to 1 of full scale +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.MicLevelMeter(c, level, mujica.MicLevelMeterOptions{}) +} +ui.Render(view, 400, 300, 1)` + deviceCode = `devices := mujica.MediaDevices{ + Microphones: []mujica.MediaDevice{{ID: "mic-1", Name: "Built-in Microphone"}}, + Speakers: []mujica.MediaDevice{{ID: "out-1", Name: "Headphones"}}, +} +sel := mujica.DeviceSelection{Microphone: "mic-1"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.DeviceSelector(c, &sel, devices, mujica.DeviceSelectorOptions{}) +} +ui.Render(view, 400, 300, 1)` + compareCode = `before, after := ui.NewBitmap(examplePhoto), ui.NewBitmap(examplePhoto) +split := 0.5 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ImageCompare(c, before, after, &split, mujica.ImageCompareOptions{}) +} +ui.Render(view, 400, 300, 1)` +) diff --git a/examples/gallery/pages_media_devices.go b/examples/gallery/pages_media_devices.go new file mode 100644 index 0000000..19527d7 --- /dev/null +++ b/examples/gallery/pages_media_devices.go @@ -0,0 +1,225 @@ +package main + +import ( + "fmt" + "math" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func volumeDemo(c *ui.Context, log func(string)) { + type state struct { + volume float64 + muted, disabled bool + } + s := ui.Local(c.Root(), "351", func() state { return state{volume: 0.7} }) + mediaSection(c, "Parameters", func() { mediaCheck(c, log, &s.disabled, "Disabled") }) + mediaSection(c, "Live", func() { + if mujica.VolumeControl(c, &s.volume, &s.muted, mujica.VolumeControlOptions{Disabled: s.disabled}).Changed() { + log(fmt.Sprintf("volume %.0f%%, muted %v", s.volume*100, s.muted)) + } + }) +} + +func speedDemo(c *ui.Context, log func(string)) { + type state struct { + rate float64 + disabled bool + } + s := ui.Local(c.Root(), "352", func() state { return state{rate: 1} }) + mediaSection(c, "Parameters", func() { mediaCheck(c, log, &s.disabled, "Disabled") }) + mediaSection(c, "Live", func() { + if mujica.PlaybackSpeedControl(c, &s.rate, mujica.PlaybackSpeedControlOptions{Disabled: s.disabled}).Changed() { + log(fmt.Sprintf("rate %v×", s.rate)) + } + }) +} + +func mediaControlsDemo(c *ui.Context, log func(string)) { + type state struct { + st mujica.MediaControlsState + track int + disabled bool + } + s := ui.Local(c.Root(), "353", func() state { return state{} }) + tracks := []string{"Ave Mujica", "Imprisoned XII", "KiLLKiSS", "Symbol I: △"} + s.st.NoPrevious, s.st.NoNext = s.track == 0, s.track == len(tracks)-1 + mediaSection(c, "Parameters", func() { mediaCheck(c, log, &s.disabled, "Disabled") }) + mediaSection(c, "Live", func() { + ui.Text(c, fmt.Sprintf("Now: %s (%d of %d)", tracks[s.track], s.track+1, len(tracks))) + mujica.MediaControls(c, s.st, mujica.MediaControlsOptions{ + OnPrevious: func() { s.track--; log("previous") }, + OnNext: func() { s.track++; log("next") }, + OnPlay: func() { s.st.Playing = true; log("play") }, + OnPause: func() { s.st.Playing = false; log("pause") }, + OnLoop: func(m mujica.LoopMode) { s.st.Loop = m; log(fmt.Sprintf("loop mode %d", m)) }, + OnShuffle: func(on bool) { s.st.Shuffle = on; log(fmt.Sprintf("shuffle %v", on)) }, + Disabled: s.disabled, + }) + }) +} + +func playlistDemo(c *ui.Context, log func(string)) { + type state struct { + items []mujica.PlaylistItem + current string + disabled bool + } + s := ui.Local(c.Root(), "354", func() state { + titles := []string{"Ave Mujica", "Imprisoned XII", "KiLLKiSS", "Symbol I: △", "Choir 'S' Choir", "Georgette Me, Georgette You"} + items := make([]mujica.PlaylistItem, len(titles)) + for i, t := range titles { + items[i] = mujica.PlaylistItem{ID: fmt.Sprint("t", i), Title: t, Subtitle: fmt.Sprintf("Act %d", i+1), Duration: time.Duration(200+i*17) * time.Second} + } + return state{items: items, current: "t1"} + }) + mediaSection(c, "Parameters", func() { + ui.Row(c).Gap(16).AlignItems(ui.Center).Children(func() { + mediaCheck(c, log, &s.disabled, "Disabled") + if mujica.Button(c, "Add track", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + id := fmt.Sprint("t", len(s.items)+int(time.Now().UnixNano()%1000000)) + s.items = append(s.items, mujica.PlaylistItem{ID: id, Title: "Encore " + id, Duration: 3 * time.Minute}) + log("added " + id) + } + }) + }) + mediaSection(c, "Live", func() { + ui.Column(c).MaxWidth(520).Children(func() { + r := mujica.Playlist(c, &s.items, mujica.PlaylistOptions{Current: s.current, Disabled: s.disabled}) + switch { + case r.Played != "": + s.current = r.Played + log("play " + r.Played) + case r.Removed != "": + log("removed " + r.Removed) + case r.Moved: + log("reordered") + } + }) + }) +} + +func subtitleDemo(c *ui.Context, log func(string)) { + type state struct { + cues []mujica.SubtitleCue + disabled bool + } + s := ui.Local(c.Root(), "355", func() state { + return state{cues: []mujica.SubtitleCue{ + {Start: 0, End: 2500 * time.Millisecond, Text: "The curtain rises."}, + {Start: 2 * time.Second, End: 5 * time.Second, Text: "Welcome to the masquerade."}, + {Start: 6 * time.Second, End: 9 * time.Second, Text: "Ave Mujica."}, + }} + }) + mediaSection(c, "Parameters", func() { mediaCheck(c, log, &s.disabled, "Disabled") }) + mediaSection(c, "Live", func() { + ui.Column(c).MaxWidth(720).Children(func() { + if mujica.SubtitleEditor(c, &s.cues, mujica.SubtitleEditorOptions{Height: 260, Disabled: s.disabled}).Changed() { + log(fmt.Sprintf("%d cues, %d issues", len(s.cues), len(mujica.CheckSubtitles(s.cues)))) + } + }) + }) +} + +func recorderDemo(c *ui.Context, log func(string)) { + type state struct { + st mujica.RecorderState + since time.Time + disabled bool + accumulated time.Duration + } + s := ui.Local(c.Root(), "356", func() state { return state{} }) + if s.st.Status == mujica.RecorderRecording { + s.st.Elapsed = s.accumulated + c.Now().Sub(s.since) + // The clock changes each second; ask for that frame only. + c.After(time.Second - s.st.Elapsed%time.Second) + } + mediaSection(c, "Parameters", func() { mediaCheck(c, log, &s.disabled, "Disabled") }) + mediaSection(c, "Live", func() { + mujica.ScreenRecorderControls(c, s.st, mujica.ScreenRecorderControlsOptions{ + OnStart: func() { + s.st, s.since, s.accumulated = mujica.RecorderState{Status: mujica.RecorderRecording}, c.Now(), 0 + log("start") + }, + OnPause: func() { s.st.Status, s.accumulated = mujica.RecorderPaused, s.st.Elapsed; log("pause") }, + OnResume: func() { s.st.Status, s.since = mujica.RecorderRecording, c.Now(); log("resume") }, + OnStop: func() { log("stop at " + mediaClockLabel(s.st.Elapsed)); s.st = mujica.RecorderState{} }, + Disabled: s.disabled, + }) + }) +} + +func cameraDemo(c *ui.Context, log func(string)) { + type state struct { + mirror, signal, disabled bool + } + s := ui.Local(c.Root(), "357", func() state { return state{mirror: true, signal: true} }) + mediaSection(c, "Parameters", func() { + ui.Row(c).Gap(16).Children(func() { + mediaCheck(c, log, &s.signal, "Signal") + mediaCheck(c, log, &s.disabled, "Disabled") + }) + }) + frame := mujica.CameraFrame{} + if s.signal { + frame = mujica.CameraFrame{Image: mediaPhotos[2], Seq: 1} + } + mediaSection(c, "Live", func() { + ui.Column(c).MaxWidth(480).Children(func() { + if mujica.CameraPreview(c, frame, &s.mirror, mujica.CameraPreviewOptions{Disabled: s.disabled}).Changed() { + log(fmt.Sprintf("mirror %v", s.mirror)) + } + }) + }) +} + +func micDemo(c *ui.Context, log func(string)) { + type state struct{ live bool } + s := ui.Local(c.Root(), "358", func() state { return state{live: true} }) + mediaSection(c, "Parameters", func() { mediaCheck(c, log, &s.live, "Live input") }) + level := float32(0.3) + if s.live { + t := float64(c.Now().UnixMilli()) / 1000 + level = float32(math.Min(1, 0.15+0.8*math.Abs(math.Sin(t*1.3)*math.Sin(t*0.37)))) + c.AnimationFrame() + } + mediaSection(c, "Live", func() { + ui.Column(c).MaxWidth(420).Children(func() { mujica.MicLevelMeter(c, level, mujica.MicLevelMeterOptions{}) }) + }) +} + +func deviceDemo(c *ui.Context, log func(string)) { + type state struct { + sel mujica.DeviceSelection + noCamera, disabled bool + } + s := ui.Local(c.Root(), "359", func() state { return state{sel: mujica.DeviceSelection{Microphone: "m1", Speaker: "s2"}} }) + devices := mujica.MediaDevices{ + Microphones: []mujica.MediaDevice{{ID: "m1", Name: "Built-in Microphone"}, {ID: "m2", Name: "Studio Condenser"}}, + Cameras: []mujica.MediaDevice{{ID: "c1", Name: "FaceTime HD Camera"}}, + Speakers: []mujica.MediaDevice{{ID: "s1", Name: "Built-in Speakers"}, {ID: "s2", Name: "Headphones"}}, + } + mediaSection(c, "Parameters", func() { + ui.Row(c).Gap(16).Children(func() { + before := s.noCamera + mediaCheck(c, log, &s.noCamera, "No cameras") + if s.noCamera != before { + s.sel.Camera = "" + } + mediaCheck(c, log, &s.disabled, "Disabled") + }) + }) + if s.noCamera { + devices.Cameras = []mujica.MediaDevice{} + } + mediaSection(c, "Live", func() { + ui.Column(c).MaxWidth(480).Children(func() { + if mujica.DeviceSelector(c, &s.sel, devices, mujica.DeviceSelectorOptions{Disabled: s.disabled}).Changed() { + log(fmt.Sprintf("microphone %q, camera %q, speaker %q", s.sel.Microphone, s.sel.Camera, s.sel.Speaker)) + } + }) + }) +} diff --git a/examples/gallery/pages_media_image.go b/examples/gallery/pages_media_image.go new file mode 100644 index 0000000..f62ff53 --- /dev/null +++ b/examples/gallery/pages_media_image.go @@ -0,0 +1,162 @@ +package main + +import ( + "errors" + "fmt" + "image" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func imageCropperDemo(c *ui.Context, log func(string)) { + type state struct { + crop mujica.ImageCrop + aspect int + disabled bool + } + s := ui.Local(c.Root(), "341", func() state { return state{} }) + aspects := []float64{0, 1, 16.0 / 9, 4.0 / 3} + mediaSection(c, "Parameters", func() { + ui.Row(c).Gap(16).AlignItems(ui.Center).Children(func() { + before := s.aspect + mujica.SegmentedControl(c, &s.aspect, []mujica.Segment{{Label: "Free"}, {Label: "1:1"}, {Label: "16:9"}, {Label: "4:3"}}, mujica.SegmentedControlOptions{Label: "Aspect"}) + if s.aspect != before { + s.crop.Rect = image.Rectangle{} // refit to the new ratio + log(fmt.Sprintf("aspect = %v", aspects[s.aspect])) + } + mediaCheck(c, log, &s.disabled, "Disabled") + }) + }) + mediaSection(c, "Live", func() { + if mujica.ImageCropper(c, mediaPhotos[0], &s.crop, mujica.ImageCropperOptions{Aspect: aspects[s.aspect], Disabled: s.disabled}).Changed() { + log(fmt.Sprintf("crop %v rotated %d°", s.crop.Rect, s.crop.Rotation)) + } + }) +} + +func imageAnnotatorDemo(c *ui.Context, log func(string)) { + type state struct { + notes []mujica.Annotation + disabled bool + } + s := ui.Local(c.Root(), "342", func() state { + return state{notes: []mujica.Annotation{{Kind: mujica.AnnotateRect, From: image.Pt(150, 60), To: image.Pt(330, 230)}}} + }) + mediaSection(c, "Parameters", func() { + ui.Row(c).Gap(16).AlignItems(ui.Center).Children(func() { + mediaCheck(c, log, &s.disabled, "Disabled") + if mujica.Button(c, "Export JSON", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + data, err := mujica.ExportAnnotations(s.notes) + if err != nil { + log("export failed: " + err.Error()) + } else { + c.WriteClipboard(string(data)) + log(fmt.Sprintf("exported %d bytes to the clipboard", len(data))) + } + } + }) + }) + mediaSection(c, "Live", func() { + if mujica.ImageAnnotator(c, mediaBitmaps[1], &s.notes, mujica.ImageAnnotatorOptions{Disabled: s.disabled}).Changed() { + log(fmt.Sprintf("annotations: %d", len(s.notes))) + } + }) +} + +func imageThumbnailDemo(c *ui.Context, log func(string)) { + type state struct { + selected int + loading, failed, disabled bool + } + s := ui.Local(c.Root(), "343", func() state { return state{} }) + mediaSection(c, "Parameters", func() { + ui.Row(c).Gap(16).Children(func() { + mediaCheck(c, log, &s.loading, "Loading") + mediaCheck(c, log, &s.failed, "Failed") + mediaCheck(c, log, &s.disabled, "Disabled") + }) + }) + mediaSection(c, "Live", func() { + ui.Row(c).Gap(12).Wrap().Children(func() { + for i, b := range mediaBitmaps { + var err error + if s.failed && i == 2 { + err = errors.New("the file could not be read") + } + o := mujica.ImageThumbnailOptions{Alt: fmt.Sprintf("Scene %d", i+1), Aspect: 4.0 / 3, Width: 120, + Selected: s.selected == i, Loading: s.loading && i == 1, Err: err, Disabled: s.disabled} + if mujica.ImageThumbnail(c, b, o).Changed() { + s.selected = i + log(fmt.Sprintf("selected scene %d", i+1)) + } + } + }) + }) +} + +func lightboxDemo(c *ui.Context, log func(string)) { + type state struct { + open bool + index int + } + s := ui.Local(c.Root(), "344", func() state { return state{} }) + images := []mujica.ViewerImage{ + {Source: mediaBitmaps[0], Alt: "The grand hall at dusk"}, + {Source: mediaBitmaps[1], Alt: "The ivory gallery"}, + {Source: mediaBitmaps[2], Alt: "The blue chapel"}, + } + mediaSection(c, "Live", func() { + ui.Row(c).Gap(12).Children(func() { + for i, im := range images { + if mujica.ImageThumbnail(c, im.Source, mujica.ImageThumbnailOptions{Alt: im.Alt, Aspect: 4.0 / 3}).Changed() { + s.open, s.index = true, i + log(fmt.Sprintf("open at %d", i+1)) + } + } + }) + was := s.open + if mujica.Lightbox(c, &s.open, &s.index, images).Changed() { + log(fmt.Sprintf("image %d", s.index+1)) + } + if was && !s.open { + log("closed") + } + }) +} + +func videoStripDemo(c *ui.Context, log func(string)) { + type state struct { + current int + disabled bool + } + s := ui.Local(c.Root(), "347", func() state { return state{} }) + frames := make([]mujica.StripFrame, 240) + for i := range frames { + frames[i] = mujica.StripFrame{Image: mediaBitmaps[i%3], At: time.Duration(i) * 5 * time.Second} + } + mediaSection(c, "Parameters", func() { mediaCheck(c, log, &s.disabled, "Disabled") }) + mediaSection(c, "Live", func() { + if mujica.VideoThumbnailStrip(c, &s.current, frames, mujica.VideoThumbnailStripOptions{Disabled: s.disabled}).Changed() { + log("jump to " + mediaClockLabel(frames[s.current].At)) + } + }) +} + +func compareDemo(c *ui.Context, log func(string)) { + type state struct { + split float64 + disabled bool + } + s := ui.Local(c.Root(), "360", func() state { return state{split: 0.5} }) + mediaSection(c, "Parameters", func() { mediaCheck(c, log, &s.disabled, "Disabled") }) + mediaSection(c, "Live", func() { + ui.Column(c).MaxWidth(560).Children(func() { + if mujica.ImageCompare(c, mediaBitmaps[0], mediaBitmaps[1], &s.split, mujica.ImageCompareOptions{Disabled: s.disabled}).Changed() { + log(fmt.Sprintf("split %.0f%%", s.split*100)) + } + }) + }) +} diff --git a/image_annotator.go b/image_annotator.go new file mode 100644 index 0000000..90461d2 --- /dev/null +++ b/image_annotator.go @@ -0,0 +1,292 @@ +package mujica + +import ( + "encoding/json" + "fmt" + "image" + "log/slog" + "math" + "slices" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// AnnotationKind is the shape of an Annotation. +type AnnotationKind int + +const ( + AnnotateRect AnnotationKind = iota + AnnotateArrow + AnnotateText +) + +// Annotation is a mark in image pixels; text at From. +type Annotation struct { + Kind AnnotationKind + From, To image.Point + Text string +} + +// annotationJSON is the exported form of an Annotation. +type annotationJSON struct { + Kind string `json:"kind"` + X0 int `json:"x0"` + Y0 int `json:"y0"` + X1 int `json:"x1"` + Y1 int `json:"y1"` + Text string `json:"text,omitempty"` +} + +// ExportAnnotations writes notes as JSON: kind, corners and text. +func ExportAnnotations(notes []Annotation) ([]byte, error) { + out := make([]annotationJSON, len(notes)) + for i, n := range notes { + out[i] = annotationJSON{[]string{"rect", "arrow", "text"}[n.Kind], n.From.X, n.From.Y, n.To.X, n.To.Y, n.Text} + } + return json.Marshal(out) +} + +// ImageAnnotatorOptions configure an ImageAnnotator. +type ImageAnnotatorOptions struct { + // Height is the stage's height; zero means 320. + Height float32 + Disabled bool + Label string +} + +type annotatorState struct { + tool int // 0 select, 1 rect, 2 arrow, 3 text + selected int + draft string + pressing bool + start, now image.Point + moved image.Point +} + +type annotatorKey struct{} + +// ImageAnnotator draws, selects, moves and deletes marks over src. +func ImageAnnotator(c *ui.Context, src ui.ImageSource, notes *[]Annotation, opts ImageAnnotatorOptions) ChoiceResult { + iw, ih := viewerSize(src) + size := image.Pt(int(iw), int(ih)) + for _, n := range *notes { + if n.Kind < AnnotateRect || n.Kind > AnnotateText || (n.Kind == AnnotateText && n.Text == "") { + panic(fmt.Sprintf("mujica: ImageAnnotator bad annotation %+v", n)) + } + } + if opts.Height < 0 { + panic("mujica: ImageAnnotator Height must not be negative") + } + h := opts.Height + if h == 0 { + h = 320 + } + k := Tokens(c) + u := Density(c).Unit() + before := slices.Clone(*notes) + col := ui.Column(c).Gap(u * 2).Disabled(opts.Disabled) + st := ui.Local(col, annotatorKey{}, func() *annotatorState { return &annotatorState{selected: -1, draft: msg(c, "image_annotator.note")} }) + s := *st + if s.selected >= len(*notes) { + s.selected = -1 + } + col.Children(func() { + annotatorToolbar(c, k, s, notes) + stage := ui.Box(c).FillWidth().Height(h).Focusable().Clip().Radius(theme.ControlRadius). + Background(videoBlack).Label(annotatorLabel(c, opts.Label)).Cursor(ui.CursorCrosshair) + internal.Ring(stage, k.Focus, theme.ControlRadius) + r := stage.Bounds() + scale, ox, oy := cropperPlace(r, size) + if !stage.IsDisabled() && scale > 0 { + annotatorPointer(stage, s, notes, r, size, scale, ox, oy) + annotatorKeys(stage, s, notes, size) + } + if s.selected >= 0 { + n := (*notes)[s.selected] + stage.Description(fmt.Sprintf(msg(c, "image_annotator.selected"), s.selected+1, len(*notes), annotatorKind(c, n.Kind))) + } + list, sel, preview := slices.Clone(*notes), s.selected, annotatorPreview(s) + size := FontSize(c, theme.BodySize) + stage.Draw(func(p *ui.Painter, r ui.Rect) { + scale, ox, oy := cropperPlace(r, image.Pt(int(iw), int(ih))) + p.Image(src, ui.Rect{X: ox, Y: oy, W: iw * scale, H: ih * scale}, ui.FillBox) + at := func(pt image.Point) (float32, float32) { + return internal.Snap(p, ox+float32(pt.X)*scale), internal.Snap(p, oy+float32(pt.Y)*scale) + } + for i, n := range append(list, preview...) { + annotatorPaint(p, k, n, at, size, i == sel) + } + }) + }) + changed := !slices.Equal(before, *notes) + if changed { + slog.Debug("mujica: image_annotator changed", "count", len(*notes)) + } + return ChoiceResult{Element: col, changed: changed} +} + +func annotatorLabel(c *ui.Context, l string) string { + if l != "" { + return l + } + return msg(c, "image_annotator.label") +} + +func annotatorKind(c *ui.Context, k AnnotationKind) string { + return msg(c, []string{"image_annotator.rect", "image_annotator.arrow", "image_annotator.text"}[k]) +} + +// annotatorToolbar picks tools, edits text and deletes the selection. +func annotatorToolbar(c *ui.Context, k theme.Tokens, s *annotatorState, notes *[]Annotation) { + u := Density(c).Unit() + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Wrap().Children(func() { + SegmentedControl(c, &s.tool, []Segment{ + {Label: msg(c, "image_annotator.select"), Icon: mediaPointer, HideLabel: true}, + {Label: msg(c, "image_annotator.rect"), Icon: mediaRect, HideLabel: true}, + {Label: msg(c, "image_annotator.arrow"), Icon: mediaArrow, HideLabel: true}, + {Label: msg(c, "image_annotator.text"), Icon: mediaText, HideLabel: true}, + }, SegmentedControlOptions{Label: msg(c, "image_annotator.tool")}) + editing := s.selected >= 0 && (*notes)[s.selected].Kind == AnnotateText + if editing { + s.draft = (*notes)[s.selected].Text + } + if s.tool == 3 || editing { + in := TextInput(c, &s.draft, TextInputOptions{Label: msg(c, "image_annotator.textLabel")}) + in.Element.Width(180) + if editing && in.Changed() && s.draft != "" { + (*notes)[s.selected].Text = s.draft + } + } + del := iconAction(c, icons.Must("trash-2"), msg(c, "image_annotator.delete")).Disabled(s.selected < 0) + if del.Clicked() && !del.IsDisabled() { + *notes = slices.Delete(*notes, s.selected, s.selected+1) + s.selected = -1 + } + ui.Textf(c, msg(c, "image_annotator.count"), len(*notes)).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + }) +} + +// annotatorPreview is the shape being drawn, if any. +func annotatorPreview(s *annotatorState) []Annotation { + if !s.pressing || s.tool == 0 || s.tool == 3 { + return nil + } + return []Annotation{{Kind: AnnotationKind(s.tool - 1), From: s.start, To: s.now}} +} + +// annotatorPointer draws shapes, selects by click, drags the selection. +func annotatorPointer(stage *ui.Element, s *annotatorState, notes *[]Annotation, r ui.Rect, size image.Point, scale, ox, oy float32) { + _, _, _ = stage.Dragged() + px, py, _ := stage.PointerPosition() + pt := image.Pt(int(math.Round(float64((px+r.X-ox)/scale))), int(math.Round(float64((py+r.Y-oy)/scale)))) + pt = image.Pt(max(0, min(size.X, pt.X)), max(0, min(size.Y, pt.Y))) + switch { + case stage.Pressed() && !s.pressing: + s.pressing, s.start, s.now, s.moved = true, pt, pt, image.Point{} + if s.tool == 0 { + s.selected = annotatorHit(*notes, pt, int(8/scale)+1) + } + case stage.Pressed(): + if s.tool == 0 && s.selected >= 0 { + d := pt.Sub(s.now) + n := &(*notes)[s.selected] + n.From, n.To = n.From.Add(d), n.To.Add(d) + } + s.now = pt + case s.pressing: + s.pressing = false + big := absInt(s.now.X-s.start.X) >= 4 || absInt(s.now.Y-s.start.Y) >= 4 + switch { + case s.tool == 3 && s.draft != "": + *notes = append(*notes, Annotation{Kind: AnnotateText, From: s.start, To: s.start, Text: s.draft}) + s.selected = len(*notes) - 1 + case (s.tool == 1 || s.tool == 2) && big: + *notes = append(*notes, Annotation{Kind: AnnotationKind(s.tool - 1), From: s.start, To: s.now}) + s.selected = len(*notes) - 1 + } + } +} + +// annotatorKeys: [ ] select, arrows move, Delete removes, Escape clears. +func annotatorKeys(stage *ui.Element, s *annotatorState, notes *[]Annotation, size image.Point) { + n := len(*notes) + step := max(1, size.X/100) + move := func(dx, dy int) { + if s.selected >= 0 { + a := &(*notes)[s.selected] + a.From, a.To = a.From.Add(image.Pt(dx, dy)), a.To.Add(image.Pt(dx, dy)) + } + } + switch { + case n > 0 && stage.Shortcut(0, ui.KeyBracketRight): + s.selected = (s.selected + 1) % n + case n > 0 && stage.Shortcut(0, ui.KeyBracketLeft): + s.selected = (s.selected - 1 + n) % n + case s.selected >= 0 && (stage.Shortcut(0, ui.KeyDelete) || stage.Shortcut(0, ui.KeyBackspace)): + *notes = slices.Delete(*notes, s.selected, s.selected+1) + s.selected = -1 + case stage.Shortcut(0, ui.KeyEscape): + s.selected = -1 + case stage.Shortcut(0, ui.KeyLeft): + move(-step, 0) + case stage.Shortcut(0, ui.KeyRight): + move(step, 0) + case stage.Shortcut(0, ui.KeyUp): + move(0, -step) + case stage.Shortcut(0, ui.KeyDown): + move(0, step) + } +} + +// annotatorHit is the topmost mark near pt, or -1. +func annotatorHit(notes []Annotation, pt image.Point, slop int) int { + for i := len(notes) - 1; i >= 0; i-- { + n := notes[i] + b := image.Rectangle{Min: n.From, Max: n.To}.Canon() + if n.Kind == AnnotateText { + b = image.Rectangle{Min: n.From, Max: n.From.Add(image.Pt(len(n.Text)*8, 18))} + } + if pt.In(b.Inset(-slop)) { + return i + } + } + return -1 +} + +func absInt(v int) int { return max(v, -v) } + +// annotatorPaint draws a mark with a halo for any picture. +func annotatorPaint(p *ui.Painter, k theme.Tokens, n Annotation, at func(image.Point) (float32, float32), size float32, selected bool) { + x0, y0 := at(n.From) + x1, y1 := at(n.To) + halo, ink := ui.Hex("#FBF7EF"), ui.Hex("#A12635") + switch n.Kind { + case AnnotateRect: + b := ui.Rect{X: min(x0, x1), Y: min(y0, y1), W: abs32(x1 - x0), H: abs32(y1 - y0)} + p.Stroke(b, halo, 0, 4) + p.Stroke(b, ink, 0, 2) + case AnnotateArrow: + var path ui.Path + path.MoveTo(x0, y0).LineTo(x1, y1) + a := math.Atan2(float64(y1-y0), float64(x1-x0)) + for _, d := range []float64{2.6, -2.6} { + path.MoveTo(x1, y1).LineTo(x1+12*float32(math.Cos(a+d)), y1+12*float32(math.Sin(a+d))) + } + p.StrokePath(&path, 4, halo) + p.StrokePath(&path, 2, ink) + case AnnotateText: + w, h := p.MeasureText(1000, ui.Span{Text: n.Text, Size: size}) + p.Fill(ui.Rect{X: x0, Y: y0, W: w + 8, H: h + 4}, halo, theme.ControlRadius) + p.Text(x0+4, y0+2, n.Text, size, ink) + x1, y1 = x0+w+8, y0+h+4 + } + if selected { + b := ui.Rect{X: min(x0, x1) - 4, Y: min(y0, y1) - 4, W: abs32(x1-x0) + 8, H: abs32(y1-y0) + 8} + p.StrokeDashed(b, k.Focus, 0, 1) + p.FillPath(internal.Diamond(internal.Snap(p, b.X), internal.Snap(p, b.Y), 8), k.Focus) + } +} diff --git a/image_annotator_test.go b/image_annotator_test.go new file mode 100644 index 0000000..2229d6a --- /dev/null +++ b/image_annotator_test.go @@ -0,0 +1,121 @@ +package mujica + +import ( + "image" + "testing" + + "github.com/egoist/mygo/ui" +) + +func annotatorTester(notes *[]Annotation, disabled bool, n *int) *ui.Tester { + src := mediaTestBitmap(400, 200) + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).Width(440).Children(func() { + if ImageAnnotator(c, src, notes, ImageAnnotatorOptions{Height: 200, Disabled: disabled}).Changed() { + *n++ + } + }) + }, 520, 360) +} + +// annotatorAt maps image pixel (x, y) to window DIPs on the stage. +func annotatorAt(tt *ui.Tester, x, y float32) (float32, float32) { + r, _ := tt.Find("Annotations") + scale := min(r.W/400, r.H/200) + return r.X + (r.W-400*scale)/2 + x*scale, r.Y + (r.H-200*scale)/2 + y*scale +} + +func annotatorDrag(tt *ui.Tester, x0, y0, x1, y1 float32) { + ax, ay := annotatorAt(tt, x0, y0) + bx, by := annotatorAt(tt, x1, y1) + tt.Press(ax, ay) + tt.Move((ax+bx)/2, (ay+by)/2) + tt.Move(bx, by) + tt.Release(bx, by) +} + +func TestImageAnnotatorDrawShapes(t *testing.T) { + var notes []Annotation + n := 0 + tt := annotatorTester(¬es, false, &n) + if err := tt.Click("Rectangle"); err != nil { + t.Fatal(err) + } + annotatorDrag(tt, 40, 40, 140, 100) + if err := tt.Click("Arrow"); err != nil { + t.Fatal(err) + } + annotatorDrag(tt, 200, 150, 300, 60) + if err := tt.Click("Text"); err != nil { + t.Fatal(err) + } + x, y := annotatorAt(tt, 250, 20) + tt.ClickAt(x, y) + if len(notes) != 3 || n != 3 { + t.Fatalf("notes %+v, changes %d", notes, n) + } + near := func(p, q image.Point) bool { return absInt(p.X-q.X) <= 2 && absInt(p.Y-q.Y) <= 2 } + if notes[0].Kind != AnnotateRect || !near(notes[0].From, image.Pt(40, 40)) || !near(notes[0].To, image.Pt(140, 100)) { + t.Fatalf("rect %+v", notes[0]) + } + if notes[1].Kind != AnnotateArrow || !near(notes[1].To, image.Pt(300, 60)) { + t.Fatalf("arrow %+v", notes[1]) + } + if notes[2].Kind != AnnotateText || notes[2].Text != "Note" { + t.Fatalf("text %+v", notes[2]) + } +} + +func TestImageAnnotatorSelectMoveDelete(t *testing.T) { + notes := []Annotation{{Kind: AnnotateRect, From: image.Pt(40, 40), To: image.Pt(140, 100)}, {Kind: AnnotateArrow, From: image.Pt(200, 150), To: image.Pt(300, 60)}} + n := 0 + tt := annotatorTester(¬es, false, &n) + x, y := annotatorAt(tt, 90, 70) + tt.ClickAt(x, y) + if !tt.Focused("Annotations") { + t.Fatal("stage not focused") + } + tt.Key(0, ui.KeyRight) + if notes[0].From != image.Pt(44, 40) { + t.Fatalf("Right moved %+v", notes[0]) + } + tt.Key(0, ui.KeyBracketRight) + tt.Key(0, ui.KeyDelete) + if len(notes) != 1 || notes[0].Kind != AnnotateRect { + t.Fatalf("delete left %+v", notes) + } + data, err := ExportAnnotations(notes) + if err != nil || string(data) != `[{"kind":"rect","x0":44,"y0":40,"x1":144,"y1":100}]` { + t.Fatalf("export %s %v", data, err) + } +} + +func TestImageAnnotatorDisabledAndBad(t *testing.T) { + var notes []Annotation + n := 0 + tt := annotatorTester(¬es, true, &n) + _ = tt.Click("Rectangle") + annotatorDrag(tt, 40, 40, 140, 100) + if len(notes) != 0 || n != 0 { + t.Fatalf("disabled annotator drew %+v", notes) + } + bad := []Annotation{{Kind: AnnotateText}} + mediaPanics(t, "empty text", func(c *ui.Context) { + ImageAnnotator(c, mediaTestBitmap(10, 10), &bad, ImageAnnotatorOptions{}) + }) +} + +func TestImageAnnotatorSnapshot(t *testing.T) { + src := mediaTestBitmap(400, 200) + notes := []Annotation{ + {Kind: AnnotateRect, From: image.Pt(30, 40), To: image.Pt(150, 120)}, + {Kind: AnnotateArrow, From: image.Pt(330, 160), To: image.Pt(220, 80)}, + {Kind: AnnotateText, From: image.Pt(230, 30), To: image.Pt(230, 30), Text: "Chandelier"}, + } + snapshot(t, "image_annotator", 460, 320, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(420).Children(func() { + ImageAnnotator(c, src, ¬es, ImageAnnotatorOptions{Height: 220}) + }) + }) +} diff --git a/image_compare.go b/image_compare.go new file mode 100644 index 0000000..d621e6f --- /dev/null +++ b/image_compare.go @@ -0,0 +1,74 @@ +package mujica + +import ( + "log/slog" + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// ImageCompareOptions configure an ImageCompare. +type ImageCompareOptions struct { + // BeforeLabel and AfterLabel caption the sides; empty uses defaults. + BeforeLabel, AfterLabel string + Disabled bool +} + +// ImageCompare shows before left of *split, after right. +func ImageCompare(c *ui.Context, before, after ui.ImageSource, split *float64, opts ImageCompareOptions) ChoiceResult { + if *split < 0 || *split > 1 || math.IsNaN(*split) { + panic("mujica: ImageCompare split outside 0..1") + } + bw, bh := viewerSize(before) + viewerSize(after) + k := Tokens(c) + bl, al := opts.BeforeLabel, opts.AfterLabel + if bl == "" { + bl = msg(c, "image_compare.before") + } + if al == "" { + al = msg(c, "image_compare.after") + } + g, _ := sliderSetup(0, 1, 0.01, nil, false, c) + old := *split + var s *ui.Element + var next float64 + ui.Box(c).Disabled(opts.Disabled).Children(func() { + s, next, _ = sliderControl(c, old, g, 0, 1) + }) + s.FillWidth().AspectRatio(bw / bh).FocusRing(false).Cursor(ui.CursorResizeEW).Clip().Radius(theme.ControlRadius). + Label(bl + " / " + al) + internal.Ring(s, k.Focus, theme.ControlRadius) + if !s.IsDisabled() { + *split = next + } + changed := *split != old + if changed { + slog.Debug("mujica: image_compare split", "split", *split) + } + v, size := float32(*split), FontSize(c, theme.CaptionSize) + s.Draw(func(p *ui.Painter, r ui.Rect) { + x := internal.Snap(p, r.X+r.W*v) + p.Image(after, r, ui.Cover) + p.Clip(ui.Rect{X: r.X, Y: r.Y, W: x - r.X, H: r.H}, 0, func() { p.Image(before, r, ui.Cover) }) + compareTag(p, k, r.X+8, r.Y+8, bl, size) + w, _ := p.MeasureText(1000, ui.Span{Text: al, Size: size}) + compareTag(p, k, r.X+r.W-w-20, r.Y+8, al, size) + p.Fill(ui.Rect{X: x - 1, Y: r.Y, W: 2, H: r.H}, k.Surface, 0) + cy := internal.Snap(p, r.Y+r.H/2) + p.FillPath(internal.Diamond(x, cy, 22), k.Surface) + p.FillPath(internal.Diamond(x, cy, 16), k.AccentText) + }) + return ChoiceResult{Element: s, changed: changed} +} + +// compareTag draws a caption chip at (x, y). +func compareTag(p *ui.Painter, k theme.Tokens, x, y float32, s string, size float32) { + w, h := p.MeasureText(1000, ui.Span{Text: s, Size: size}) + b := ui.Rect{X: x, Y: y, W: w + 12, H: h + 4} + p.Fill(b, k.Surface.Alpha(0.88), theme.ControlRadius) + p.Text(b.X+6, b.Y+2, s, size, k.Text) +} diff --git a/image_compare_test.go b/image_compare_test.go new file mode 100644 index 0000000..89c476b --- /dev/null +++ b/image_compare_test.go @@ -0,0 +1,73 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func compareTester(split *float64, disabled bool, n *int) *ui.Tester { + before, after := mediaTestBitmap(160, 90), mediaTestBitmap(160, 90) + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).Width(320).Children(func() { + if ImageCompare(c, before, after, split, ImageCompareOptions{Disabled: disabled}).Changed() { + *n++ + } + }) + }, 400, 300) +} + +func TestImageCompareKeysAndDrag(t *testing.T) { + split, n := 0.5, 0 + tt := compareTester(&split, false, &n) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + if split != 0.51 { + t.Fatalf("Right: %v", split) + } + tt.Key(0, ui.KeyHome) + if split != 0 { + t.Fatalf("Home: %v", split) + } + r, ok := tt.Find("Before / After") + if !ok { + t.Fatal("not named") + } + tt.Press(r.X+r.W/2, r.Y+r.H/2) + tt.Move(r.X+r.W*0.75, r.Y+r.H/2) + tt.Release(r.X+r.W*0.75, r.Y+r.H/2) + if split < 0.7 || split > 0.8 { + t.Fatalf("drag: %v", split) + } + if n < 3 { + t.Fatalf("changes %d", n) + } +} + +func TestImageCompareDisabled(t *testing.T) { + split, n := 0.5, 0 + tt := compareTester(&split, true, &n) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + r, _ := tt.Find("Before / After") + tt.ClickAt(r.X+10, r.Y+10) + if split != 0.5 || n != 0 { + t.Fatalf("disabled moved to %v", split) + } + bad := 2.0 + mediaPanics(t, "split over 1", func(c *ui.Context) { + ImageCompare(c, mediaTestBitmap(4, 4), mediaTestBitmap(4, 4), &bad, ImageCompareOptions{}) + }) +} + +func TestImageCompareSnapshot(t *testing.T) { + split := 0.4 + before := mediaTestBitmap(160, 90) + after := ui.NewBitmap(mediaTestImage(90, 160)) + snapshot(t, "image_compare", 360, 220, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(320).Children(func() { + ImageCompare(c, before, after, &split, ImageCompareOptions{}) + }) + }) +} diff --git a/image_cropper.go b/image_cropper.go new file mode 100644 index 0000000..aac97bb --- /dev/null +++ b/image_cropper.go @@ -0,0 +1,245 @@ +package mujica + +import ( + "fmt" + "image" + "log/slog" + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// ImageCrop is Rect in pixels of the turned image. +type ImageCrop struct { + Rect image.Rectangle + // Rotation is 0, 90, 180 or 270. + Rotation int +} + +// ImageCropperOptions configure an ImageCropper. +type ImageCropperOptions struct { + // Aspect locks width over height; zero is free. + Aspect float64 + // Height is the stage's height; zero means 320. + Height float32 + Disabled bool + Label string +} + +type cropperCache struct { + src image.Image + rot int + bmp *ui.Bitmap +} + +type cropperDrag struct { + mode int // 0 none, 1 move, 2-5 corners + start image.Rectangle + dx, dy float32 +} + +type cropperKey struct{} + +// ImageCropper edits *crop over src; empty Rect starts fitted. +func ImageCropper(c *ui.Context, src image.Image, crop *ImageCrop, opts ImageCropperOptions) ChoiceResult { + if src == nil || src.Bounds().Empty() || opts.Aspect < 0 || opts.Height < 0 { + panic("mujica: ImageCropper needs an image, Aspect >= 0 and Height >= 0") + } + if crop.Rotation%90 != 0 || crop.Rotation < 0 || crop.Rotation >= 360 { + panic(fmt.Sprintf("mujica: ImageCropper Rotation %d is not 0, 90, 180 or 270", crop.Rotation)) + } + size := cropperSize(src, crop.Rotation) + if crop.Rect.Empty() { + crop.Rect = cropperFit(size, opts.Aspect) + } + if !crop.Rect.In(image.Rectangle{Max: size}) { + panic(fmt.Sprintf("mujica: ImageCropper Rect %v outside the %v image", crop.Rect, size)) + } + if opts.Aspect > 0 && math.Abs(float64(crop.Rect.Dx())-float64(crop.Rect.Dy())*opts.Aspect) > 1+opts.Aspect { + panic(fmt.Sprintf("mujica: ImageCropper Rect %v does not keep Aspect %v", crop.Rect, opts.Aspect)) + } + h := opts.Height + if h == 0 { + h = 320 + } + k := Tokens(c) + u := Density(c).Unit() + old := *crop + label := opts.Label + if label == "" { + label = msg(c, "image_cropper.label") + } + col := ui.Column(c).Gap(u * 2).Disabled(opts.Disabled) + col.Children(func() { + stage := ui.Box(c).FillWidth().Height(h).Focusable().Clip().Radius(theme.ControlRadius). + Background(videoBlack).Label(label).Cursor(ui.CursorMove) + internal.Ring(stage, k.Focus, theme.ControlRadius) + r := stage.Bounds() + scale, ox, oy := cropperPlace(r, size) + live := !stage.IsDisabled() + if live && scale > 0 { + cropperPointer(stage, crop, r, size, scale, ox, oy, opts.Aspect) + cropperKeys(stage, crop, size, opts.Aspect) + } + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + left := iconAction(c, mediaRotateLeft, msg(c, "image_cropper.rotateLeft")) + right := iconAction(c, mediaRotate, msg(c, "image_cropper.rotateRight")) + switch { + case live && (right.Clicked() || stage.Shortcut(0, ui.KeyR)): + cropperRotate(crop, size, 90, opts.Aspect) + case live && (left.Clicked() || stage.Shortcut(ui.Shift, ui.KeyR)): + cropperRotate(crop, size, 270, opts.Aspect) + } + ui.Text(c, cropperReadout(*crop)).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).FontFeatures("tnum") + }) + stage.Description(cropperReadout(*crop)) + // Turned pixels are copied only when image or rotation change. + cache := ui.Local(stage, cropperKey{}, func() cropperCache { return cropperCache{} }) + if cache.src != src || cache.rot != crop.Rotation || cache.bmp == nil { + *cache = cropperCache{src, crop.Rotation, ui.NewBitmap(cropperTurn(src, crop.Rotation))} + } + size := cropperSize(src, crop.Rotation) + bmp, rect := cache.bmp, crop.Rect + stage.Draw(func(p *ui.Painter, r ui.Rect) { + scale, ox, oy := cropperPlace(r, size) + img := ui.Rect{X: ox, Y: oy, W: float32(size.X) * scale, H: float32(size.Y) * scale} + p.Image(bmp, img, ui.FillBox) + f := ui.Rect{X: internal.Snap(p, ox+float32(rect.Min.X)*scale), Y: internal.Snap(p, oy+float32(rect.Min.Y)*scale), + W: internal.Snap(p, float32(rect.Dx())*scale), H: internal.Snap(p, float32(rect.Dy())*scale)} + shade := ui.RGBA(0, 0, 0, 0.55) + p.Fill(ui.Rect{X: img.X, Y: img.Y, W: img.W, H: f.Y - img.Y}, shade, 0) + p.Fill(ui.Rect{X: img.X, Y: f.Y + f.H, W: img.W, H: img.Y + img.H - f.Y - f.H}, shade, 0) + p.Fill(ui.Rect{X: img.X, Y: f.Y, W: f.X - img.X, H: f.H}, shade, 0) + p.Fill(ui.Rect{X: f.X + f.W, Y: f.Y, W: img.X + img.W - f.X - f.W, H: f.H}, shade, 0) + light := ui.Hex("#F2EBDD") + p.Stroke(f, light, 0, 1) + for i := 1; i < 3; i++ { + p.Fill(ui.Rect{X: f.X + f.W*float32(i)/3, Y: f.Y, W: 1, H: f.H}, light.Alpha(0.4), 0) + p.Fill(ui.Rect{X: f.X, Y: f.Y + f.H*float32(i)/3, W: f.W, H: 1}, light.Alpha(0.4), 0) + } + for _, pt := range [4][2]float32{{f.X, f.Y}, {f.X + f.W, f.Y}, {f.X, f.Y + f.H}, {f.X + f.W, f.Y + f.H}} { + p.FillPath(internal.Diamond(internal.Snap(p, pt[0]), internal.Snap(p, pt[1]), 12), light) + } + }) + }) + changed := *crop != old + if changed { + slog.Debug("mujica: image_cropper changed", "rect", crop.Rect, "rotation", crop.Rotation) + } + return ChoiceResult{Element: col, changed: changed} +} + +func cropperReadout(cr ImageCrop) string { + r := cr.Rect + return fmt.Sprintf("%d, %d · %d × %d · %d°", r.Min.X, r.Min.Y, r.Dx(), r.Dy(), cr.Rotation) +} + +// cropperSize is src's size after turning it rot degrees. +func cropperSize(src image.Image, rot int) image.Point { + s := src.Bounds().Size() + if rot == 90 || rot == 270 { + return image.Pt(s.Y, s.X) + } + return s +} + +// cropperFit is the largest centered aspect rectangle inside size. +func cropperFit(size image.Point, aspect float64) image.Rectangle { + w, h := size.X, size.Y + if aspect > 0 { + if float64(w) > float64(h)*aspect { + w = int(math.Round(float64(h) * aspect)) + } else { + h = int(math.Round(float64(w) / aspect)) + } + } + x, y := (size.X-w)/2, (size.Y-h)/2 + return image.Rect(x, y, x+w, y+h) +} + +// cropperPlace fits size in r: scale and top-left corner. +func cropperPlace(r ui.Rect, size image.Point) (scale, x, y float32) { + if r.W <= 0 { + return 0, 0, 0 + } + scale = min(r.W/float32(size.X), r.H/float32(size.Y)) + return scale, r.X + (r.W-float32(size.X)*scale)/2, r.Y + (r.H-float32(size.Y)*scale)/2 +} + +// cropperTurn copies src turned rot degrees clockwise. +func cropperTurn(src image.Image, rot int) image.Image { + if rot == 0 { + return src + } + b := src.Bounds() + size := cropperSize(src, rot) + out := image.NewRGBA(image.Rectangle{Max: size}) + for y := 0; y < b.Dy(); y++ { + for x := 0; x < b.Dx(); x++ { + var nx, ny int + switch rot { + case 90: + nx, ny = b.Dy()-1-y, x + case 180: + nx, ny = b.Dx()-1-x, b.Dy()-1-y + case 270: + nx, ny = y, b.Dx()-1-x + } + out.Set(nx, ny, src.At(b.Min.X+x, b.Min.Y+y)) + } + } + return out +} + +// cropperRotate turns the crop d degrees; locked aspects refit. +func cropperRotate(cr *ImageCrop, size image.Point, d int, aspect float64) { + r := cr.Rect + for range d / 90 { + r = image.Rect(size.Y-r.Max.Y, r.Min.X, size.Y-r.Min.Y, r.Max.X) + size = image.Pt(size.Y, size.X) + } + cr.Rotation = (cr.Rotation + d) % 360 + cr.Rect = r + if aspect > 0 { + cr.Rect = cropperFit(size, aspect) + } +} + +// cropperPointer moves the frame, or resizes it by a corner. +func cropperPointer(stage *ui.Element, cr *ImageCrop, r ui.Rect, size image.Point, scale, ox, oy float32, aspect float64) { + d := ui.Local(stage, cropperDrag{}, func() cropperDrag { return cropperDrag{} }) + dx, dy, ok := stage.Dragged() + if !stage.Pressed() { + d.mode = 0 + return + } + if d.mode == 0 { + px, py, _ := stage.PointerPosition() + px, py = (px+r.X-ox)/scale, (py+r.Y-oy)/scale + d.start, d.dx, d.dy, d.mode = cr.Rect, 0, 0, cropperHit(cr.Rect, px, py, 14/scale) + } + if !ok || d.mode == 0 { + return + } + d.dx, d.dy = d.dx+dx/scale, d.dy+dy/scale + cr.Rect = cropperDragRect(d.start, d.mode, int(math.Round(float64(d.dx))), int(math.Round(float64(d.dy))), size, aspect) +} + +// cropperHit says what a press grabs: corner, inside or nothing. +func cropperHit(r image.Rectangle, x, y, slop float32) int { + corners := [4][2]int{{r.Min.X, r.Min.Y}, {r.Max.X, r.Min.Y}, {r.Min.X, r.Max.Y}, {r.Max.X, r.Max.Y}} + for i, c := range corners { + if abs32(x-float32(c[0])) <= slop && abs32(y-float32(c[1])) <= slop { + return 2 + i + } + } + if x >= float32(r.Min.X) && x <= float32(r.Max.X) && y >= float32(r.Min.Y) && y <= float32(r.Max.Y) { + return 1 + } + return 0 +} + +func abs32(v float32) float32 { return float32(math.Abs(float64(v))) } diff --git a/image_cropper_geom.go b/image_cropper_geom.go new file mode 100644 index 0000000..7d39e42 --- /dev/null +++ b/image_cropper_geom.go @@ -0,0 +1,81 @@ +package mujica + +import ( + "image" + "math" + + "github.com/egoist/mygo/ui" +) + +// cropperMin is the smallest crop side in pixels. +const cropperMin = 8 + +// cropperDragRect moves (mode 1) or corner-resizes (2-5) start. +func cropperDragRect(start image.Rectangle, mode, dx, dy int, size image.Point, aspect float64) image.Rectangle { + if mode == 1 { + dx = max(-start.Min.X, min(size.X-start.Max.X, dx)) + dy = max(-start.Min.Y, min(size.Y-start.Max.Y, dy)) + return start.Add(image.Pt(dx, dy)) + } + corners := [4]image.Point{start.Min, {start.Max.X, start.Min.Y}, {start.Min.X, start.Max.Y}, start.Max} + moving, anchor := corners[mode-2], corners[5-mode] + x := max(0, min(size.X, moving.X+dx)) + y := max(0, min(size.Y, moving.Y+dy)) + sx, sy := 1, 1 + room := image.Pt(size.X-anchor.X, size.Y-anchor.Y) + if x < anchor.X { + sx, room.X = -1, anchor.X + } + if y < anchor.Y { + sy, room.Y = -1, anchor.Y + } + w, h := cropperClampSize(max(cropperMin, (x-anchor.X)*sx), max(cropperMin, (y-anchor.Y)*sy), room, aspect) + return image.Rectangle{Min: anchor, Max: anchor.Add(image.Pt(w*sx, h*sy))}.Canon() +} + +// cropperClampSize fits w×h inside room, keeping aspect when locked. +func cropperClampSize(w, h int, room image.Point, aspect float64) (int, int) { + w, h = min(w, room.X), min(h, room.Y) + if aspect <= 0 { + return w, h + } + h = int(math.Round(float64(w) / aspect)) + if h > room.Y { + h = room.Y + w = int(math.Round(float64(h) * aspect)) + } + return w, h +} + +// cropperKeys: arrows move, Shift+arrows resize, 1% per press. +func cropperKeys(stage *ui.Element, cr *ImageCrop, size image.Point, aspect float64) { + step := max(1, size.X/100) + r := cr.Rect + move := func(dx, dy int) { cr.Rect = cropperDragRect(r, 1, dx, dy, size, aspect) } + grow := func(dw, dh int) { + w, h := max(cropperMin, r.Dx()+dw), max(cropperMin, r.Dy()+dh) + if aspect > 0 && dw == 0 { + w = int(math.Round(float64(h) * aspect)) + } + w, h = cropperClampSize(w, h, image.Pt(size.X-r.Min.X, size.Y-r.Min.Y), aspect) + cr.Rect = image.Rectangle{Min: r.Min, Max: r.Min.Add(image.Pt(w, h))} + } + switch { + case stage.Shortcut(0, ui.KeyLeft): + move(-step, 0) + case stage.Shortcut(0, ui.KeyRight): + move(step, 0) + case stage.Shortcut(0, ui.KeyUp): + move(0, -step) + case stage.Shortcut(0, ui.KeyDown): + move(0, step) + case stage.Shortcut(ui.Shift, ui.KeyRight): + grow(step, 0) + case stage.Shortcut(ui.Shift, ui.KeyLeft): + grow(-step, 0) + case stage.Shortcut(ui.Shift, ui.KeyDown): + grow(0, step) + case stage.Shortcut(ui.Shift, ui.KeyUp): + grow(0, -step) + } +} diff --git a/image_cropper_test.go b/image_cropper_test.go new file mode 100644 index 0000000..9ba67a5 --- /dev/null +++ b/image_cropper_test.go @@ -0,0 +1,101 @@ +package mujica + +import ( + "image" + "testing" + + "github.com/egoist/mygo/ui" +) + +func cropperTester(src image.Image, crop *ImageCrop, opts ImageCropperOptions, n *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).Width(440).Children(func() { + if ImageCropper(c, src, crop, opts).Changed() { + *n++ + } + }) + }, 500, 420) +} + +func TestImageCropperDefaultAndKeys(t *testing.T) { + crop, n := ImageCrop{}, 0 + tt := cropperTester(mediaTestImage(400, 200), &crop, ImageCropperOptions{Aspect: 1, Height: 200}, &n) + if crop.Rect != image.Rect(100, 0, 300, 200) { + t.Fatalf("default %v", crop.Rect) + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + if crop.Rect != image.Rect(104, 0, 304, 200) { + t.Fatalf("Right: %v", crop.Rect) + } + tt.Key(ui.Shift, ui.KeyLeft) + if crop.Rect.Dx() != crop.Rect.Dy() || crop.Rect.Dx() != 196 { + t.Fatalf("Shift+Left keeps 1:1: %v", crop.Rect) + } + if n != 2 || !tt.HasText("104, 0 · 196 × 196 · 0°") { + t.Fatalf("changes %d, texts %v", n, tt.Texts()) + } +} + +func TestImageCropperRotate(t *testing.T) { + crop, n := ImageCrop{Rect: image.Rect(10, 20, 110, 70)}, 0 + tt := cropperTester(mediaTestImage(400, 200), &crop, ImageCropperOptions{Height: 200}, &n) + if err := tt.Click("Rotate right"); err != nil { + t.Fatal(err) + } + if crop.Rotation != 90 || crop.Rect != image.Rect(130, 10, 180, 110) { + t.Fatalf("rotated %+v", crop) + } + tt.Key(0, ui.KeyTab) + tt.Key(ui.Shift, ui.KeyR) + if crop.Rotation != 0 || crop.Rect != image.Rect(10, 20, 110, 70) { + t.Fatalf("rotated back %+v", crop) + } +} + +func TestImageCropperDragCorner(t *testing.T) { + crop, n := ImageCrop{Rect: image.Rect(0, 0, 200, 100)}, 0 + tt := cropperTester(mediaTestImage(400, 200), &crop, ImageCropperOptions{Aspect: 2, Height: 200}, &n) + r, _ := tt.Find("Crop area") + scale := min(r.W/400, r.H/200) + ox, oy := r.X+(r.W-400*scale)/2, r.Y+(r.H-200*scale)/2 + cx, cy := ox+200*scale, oy+100*scale + tt.Press(cx, cy) + tt.Move(cx+50*scale, cy+5*scale) + tt.Move(cx+100*scale, cy+10*scale) + tt.Release(cx+100*scale, cy+10*scale) + if crop.Rect.Min != (image.Point{}) || crop.Rect.Dx() < 290 || crop.Rect.Dx() > 310 || crop.Rect.Dx() != 2*crop.Rect.Dy() { + t.Fatalf("corner drag %v", crop.Rect) + } +} + +func TestImageCropperDisabledAndBad(t *testing.T) { + crop, n := ImageCrop{}, 0 + tt := cropperTester(mediaTestImage(100, 100), &crop, ImageCropperOptions{Disabled: true}, &n) + start := crop + _ = tt.Click("Rotate right") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + if crop != start || n != 0 { + t.Fatalf("disabled cropper changed %+v", crop) + } + img := mediaTestImage(100, 100) + mediaPanics(t, "outside", func(c *ui.Context) { + ImageCropper(c, img, &ImageCrop{Rect: image.Rect(0, 0, 200, 10)}, ImageCropperOptions{}) + }) + mediaPanics(t, "rotation", func(c *ui.Context) { ImageCropper(c, img, &ImageCrop{Rotation: 45}, ImageCropperOptions{}) }) + mediaPanics(t, "aspect", func(c *ui.Context) { + ImageCropper(c, img, &ImageCrop{Rect: image.Rect(0, 0, 50, 10)}, ImageCropperOptions{Aspect: 1}) + }) +} + +func TestImageCropperSnapshot(t *testing.T) { + img := mediaTestImage(320, 180) + crop := ImageCrop{Rect: image.Rect(60, 30, 220, 150)} + snapshot(t, "image_cropper", 440, 300, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(400).Children(func() { + ImageCropper(c, img, &crop, ImageCropperOptions{Height: 220}) + }) + }) +} diff --git a/image_thumbnail.go b/image_thumbnail.go new file mode 100644 index 0000000..27d0c71 --- /dev/null +++ b/image_thumbnail.go @@ -0,0 +1,87 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// ImageThumbnailOptions configure an ImageThumbnail. +type ImageThumbnailOptions struct { + // Width is the thumbnail's width; zero means 96. + Width float32 + // Aspect is width over height, cropped; zero is 1. + Aspect float32 + Selected bool + // Loading and Err show the load state at one size. + Loading bool + Err error + // Alt names the picture; required. + Alt string + Disabled bool +} + +// ImageThumbnail is a cropped picture; Changed reports activation. +func ImageThumbnail(c *ui.Context, src ui.ImageSource, opts ImageThumbnailOptions) ChoiceResult { + if opts.Width < 0 || opts.Aspect < 0 { + panic("mujica: ImageThumbnail needs Width and Aspect >= 0") + } + if opts.Alt == "" { + panic("mujica: ImageThumbnail needs Alt") + } + w, aspect := opts.Width, opts.Aspect + if w == 0 { + w = 96 + } + if aspect == 0 { + aspect = 1 + } + k := Tokens(c) + h := w / aspect + b := ui.ButtonBase(c).Size(w, h).Radius(theme.ControlRadius).Clip(). + Disabled(opts.Disabled).Label(opts.Alt).Selected(opts.Selected).Background(k.SurfaceHover) + internal.Ring(b, k.Focus, theme.ControlRadius) + edge, width := k.Border, theme.BorderWidth + switch { + case opts.Selected: + edge, width = k.AccentText, 2 + case b.Hovered(): + edge = k.ControlBorder + } + b.Border(width, edge).Transition(colorFade) + b.Children(func() { + switch { + case opts.Err != nil: + b.Description(opts.Err.Error()).Tooltip(opts.Err.Error()) + ui.Column(c).Gap(4).AlignItems(ui.Center).Children(func() { + ui.Icon(c, icons.Must("circle-alert")).Size(20, 20).TextColor(k.Danger) + if h >= 64 { + ui.Text(c, msg(c, "image_thumbnail.failed")).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.Danger).SingleLine() + } + }) + case opts.Loading: + Spinner(c, SpinnerOptions{Size: min(20, h/2), Label: msg(c, "image_thumbnail.loading")}) + case src == nil: + ui.Icon(c, icons.Must("image")).Size(20, 20).TextColor(k.TextMuted) + default: + ui.Image(c, src).Fit(ui.Cover).Size(w, h) + } + if opts.Selected { + // A diamond mark, so selection never rests on color alone. + ui.Box(c).Absolute().Top(4).Right(4).Size(14, 14).PassThrough().Draw(func(p *ui.Painter, r ui.Rect) { + cx, cy := internal.Snap(p, r.X+r.W/2), internal.Snap(p, r.Y+r.H/2) + p.FillPath(internal.Diamond(cx, cy, 14), k.Surface) + p.FillPath(internal.Diamond(cx, cy, 10), k.AccentText) + }) + } + }) + clicked := b.Clicked() && !b.IsDisabled() + if clicked { + slog.Debug("mujica: image_thumbnail click", "alt", opts.Alt) + } + return ChoiceResult{Element: b, changed: clicked} +} diff --git a/image_thumbnail_test.go b/image_thumbnail_test.go new file mode 100644 index 0000000..fe83abf --- /dev/null +++ b/image_thumbnail_test.go @@ -0,0 +1,82 @@ +package mujica + +import ( + "errors" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestImageThumbnailClickAndKeys(t *testing.T) { + n := 0 + bmp := mediaTestBitmap(120, 80) + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Row(c).Padding(20).AlignItems(ui.Start).Children(func() { + if ImageThumbnail(c, bmp, ImageThumbnailOptions{Alt: "Hall", Aspect: 4.0 / 3}).Changed() { + n++ + } + }) + }, 300, 200) + r, ok := tt.Find("Hall") + if !ok || r.W != 96 || r.H != 72 { + t.Fatalf("bounds %v", r) + } + tt.ClickAt(r.X+r.W/2, r.Y+r.H/2) + tt.Key(0, ui.KeyEnter) + tt.Key(0, ui.KeySpace) + if n != 3 { + t.Fatalf("activations %d", n) + } +} + +func TestImageThumbnailStatesKeepSize(t *testing.T) { + var got []ui.Rect + for _, o := range []ImageThumbnailOptions{{}, {Loading: true}, {Err: errors.New("404")}, {Selected: true}} { + o.Alt, o.Width = "Hall", 120 + var r ui.Rect + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Row(c).AlignItems(ui.Start).Children(func() { + r = ImageThumbnail(c, mediaTestBitmap(40, 40), o).Element.Bounds() + }) + }, 300, 200) + tt.Frame() + got = append(got, r) + } + for _, r := range got { + if r != got[0] || r.W != 120 || r.H != 120 { + t.Fatalf("sizes %v", got) + } + } +} + +func TestImageThumbnailDisabledAndBad(t *testing.T) { + n := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if ImageThumbnail(c, nil, ImageThumbnailOptions{Alt: "Hall", Disabled: true}).Changed() { + n++ + } + }, 300, 200) + _ = tt.Click("Hall") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if n != 0 { + t.Fatal("disabled thumbnail activated") + } + mediaPanics(t, "no alt", func(c *ui.Context) { ImageThumbnail(c, nil, ImageThumbnailOptions{}) }) +} + +func TestImageThumbnailSnapshot(t *testing.T) { + bmp := mediaTestBitmap(160, 90) + snapshot(t, "image_thumbnail", 520, 120, func(c *ui.Context) { + ui.Row(c).Padding(20).Gap(12).AlignItems(ui.Start).Children(func() { + ImageThumbnail(c, bmp, ImageThumbnailOptions{Alt: "Hall", Width: 80}) + ImageThumbnail(c, bmp, ImageThumbnailOptions{Alt: "Hall", Width: 80, Selected: true}) + ImageThumbnail(c, bmp, ImageThumbnailOptions{Alt: "Hall", Width: 80, Loading: true}) + ImageThumbnail(c, bmp, ImageThumbnailOptions{Alt: "Hall", Width: 80, Err: errors.New("404")}) + ImageThumbnail(c, bmp, ImageThumbnailOptions{Alt: "Hall", Width: 80, Disabled: true}) + }) + }) +} diff --git a/lightbox.go b/lightbox.go new file mode 100644 index 0000000..4b19858 --- /dev/null +++ b/lightbox.go @@ -0,0 +1,89 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// Lightbox fills the window with images[*index] while *open. +func Lightbox(c *ui.Context, open *bool, index *int, images []ViewerImage) ChoiceResult { + var v ChoiceResult + if !*open { + return v + } + if len(images) == 0 || *index < 0 || *index >= len(images) { + panic("mujica: Lightbox index out of range") + } + for _, im := range images { + viewerSize(im.Source) + } + u := Density(c).Unit() + w, h := c.Size() + light := ui.Hex("#F2EBDD") + v.Element = ui.DialogBase(c, open, func(back, panel *ui.Element) { + back.Background(ui.RGBA(0, 0, 0, 0.92)) + panel.Size(w, h).Padding(u * 4).Gap(u * 3).TextColor(light).Label(msg(c, "lightbox.title")). + Opacity(overlayEnter(c, panel)) + goTo := func(i int) { + if i < 0 || i >= len(images) || i == *index { + return + } + *index, v.changed = i, true + c.Announce(fmt.Sprintf(msg(c, "lightbox.position"), i+1, len(images))) + slog.Debug("mujica: lightbox image", "index", i) + } + switch { + case panel.Shortcut(0, ui.KeyLeft): + goTo(*index - 1) + case panel.Shortcut(0, ui.KeyRight): + goTo(*index + 1) + case panel.Shortcut(0, ui.KeyHome): + goTo(0) + case panel.Shortcut(0, ui.KeyEnd): + goTo(len(images) - 1) + } + img := images[*index] + ui.Row(c).AlignItems(ui.Center).Children(func() { + ui.Text(c, fmt.Sprintf(msg(c, "lightbox.position"), *index+1, len(images))).FontFeatures("tnum").Grow(1) + if lightboxButton(c, "x", "lightbox.close", false).Clicked() { + *open = false + } + }) + ui.Row(c).Grow(1).MinHeight(0).Gap(u * 3).AlignItems(ui.Center).Children(func() { + if b := lightboxButton(c, "chevron-left", "lightbox.previous", *index == 0); b.Clicked() && !b.IsDisabled() { + goTo(*index - 1) + } + ui.Box(c).Grow(1).FillHeight().MinWidth(0).Center().Children(func() { + ui.Image(c, img.Source).Fit(ui.Contain).Fill().Label(img.Alt) + }) + if b := lightboxButton(c, "chevron-right", "lightbox.next", *index == len(images)-1); b.Clicked() && !b.IsDisabled() { + goTo(*index + 1) + } + }) + if img.Alt != "" { + ui.Text(c, img.Alt).TextAlign(ui.Center).FillWidth().MaxLines(3) + } + }) + if !*open { + slog.Debug("mujica: lightbox close") + } + return v +} + +// lightboxButton is a 40 DIP icon button on the backdrop. +func lightboxButton(c *ui.Context, icon, key string, disabled bool) *ui.Element { + light := ui.Hex("#F2EBDD") + b := iconAction(c, icons.Must(icon), msg(c, key)).Size(40, 40).TextColor(light).Disabled(disabled) + // The theme's focus color is too dark on the backdrop. + internal.Ring(b, light, theme.ControlRadius) + if b.Hovered() { + b.Background(ui.RGBA(255, 255, 255, 0.12)).TextColor(ui.Hex("#FFFFFF")) + } + return b +} diff --git a/lightbox_test.go b/lightbox_test.go new file mode 100644 index 0000000..d50e70c --- /dev/null +++ b/lightbox_test.go @@ -0,0 +1,66 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func lightboxImages() []ViewerImage { + return []ViewerImage{ + {Source: mediaTestBitmap(160, 90), Alt: "The grand hall"}, + {Source: mediaTestBitmap(90, 160), Alt: "The east tower"}, + {Source: mediaTestBitmap(120, 120), Alt: "The garden"}, + } +} + +func TestLightboxBrowseAndClose(t *testing.T) { + open, index, n := false, 0, 0 + images := lightboxImages() + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if Button(c, "Open gallery", ButtonOptions{}).Clicked() { + open = true + } + if Lightbox(c, &open, &index, images).Changed() { + n++ + } + }, 640, 480) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if !open || !tt.HasText("The grand hall") || !tt.HasText("1 of 3") { + t.Fatalf("not open: %v", tt.Texts()) + } + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + if index != 2 || n != 2 || !tt.HasText("The garden") { + t.Fatalf("index %d changes %d", index, n) + } + if err := tt.Click("Previous image"); err != nil { + t.Fatal(err) + } + if index != 1 { + t.Fatalf("previous: %d", index) + } + tt.Key(0, ui.KeyEscape) + if open { + t.Fatal("Escape did not close") + } + if !tt.Focused("Open gallery") { + t.Fatal("focus not restored to the opener") + } +} + +func TestLightboxBadIndex(t *testing.T) { + open, index := true, 5 + mediaPanics(t, "index", func(c *ui.Context) { Lightbox(c, &open, &index, lightboxImages()) }) +} + +func TestLightboxSnapshot(t *testing.T) { + open, index := true, 0 + images := lightboxImages() + snapshot(t, "lightbox", 520, 360, func(c *ui.Context) { + Lightbox(c, &open, &index, images) + }) +} diff --git a/media_controls.go b/media_controls.go new file mode 100644 index 0000000..a0913d1 --- /dev/null +++ b/media_controls.go @@ -0,0 +1,77 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" +) + +// LoopMode is how playback repeats. The zero value repeats nothing. +type LoopMode int + +const ( + LoopOff LoopMode = iota + LoopAll + LoopOne +) + +// next cycles off, all, one. +func (m LoopMode) next() LoopMode { return (m + 1) % 3 } + +// MediaControlsState is what the caller's playback reports. +type MediaControlsState struct { + Playing bool + Loop LoopMode + Shuffle bool + // NoPrevious and NoNext disable those buttons at the ends. + NoPrevious, NoNext bool +} + +// MediaControlsOptions are the callbacks; every one is required. +type MediaControlsOptions struct { + OnPrevious, OnPlay, OnPause, OnNext func() + OnLoop func(LoopMode) + OnShuffle func(bool) + Disabled bool +} + +// MediaControls are previous, play, next, loop and shuffle buttons. +func MediaControls(c *ui.Context, st MediaControlsState, opts MediaControlsOptions) *ui.Element { + if opts.OnPrevious == nil || opts.OnPlay == nil || opts.OnPause == nil || opts.OnNext == nil || opts.OnLoop == nil || opts.OnShuffle == nil { + panic("mujica: MediaControls needs every callback") + } + if st.Loop < LoopOff || st.Loop > LoopOne { + panic(fmt.Sprintf("mujica: unknown LoopMode %d", st.Loop)) + } + row := ui.Row(c).Gap(Density(c).Unit()).AlignItems(ui.Center).FocusGroup(ui.Horizontal).Role(ui.RoleToolbar). + Label(msg(c, "media_controls.label")).Disabled(opts.Disabled) + row.Children(func() { + shuffle := mediaToggleAction(c, mediaShuffle, msg(c, "media_controls.shuffle"), st.Shuffle) + if shuffle.Clicked() && !shuffle.IsDisabled() { + slog.Debug("mujica: media_controls shuffle", "on", !st.Shuffle) + opts.OnShuffle(!st.Shuffle) + } + prev := iconAction(c, mediaPrev, msg(c, "media_controls.previous")).Disabled(st.NoPrevious) + if prev.Clicked() && !prev.IsDisabled() { + slog.Debug("mujica: media_controls previous") + opts.OnPrevious() + } + mediaPlayToggle(c, st.Playing, opts.OnPlay, opts.OnPause) + next := iconAction(c, mediaNext, msg(c, "media_controls.next")).Disabled(st.NoNext) + if next.Clicked() && !next.IsDisabled() { + slog.Debug("mujica: media_controls next") + opts.OnNext() + } + icon := mediaRepeat + if st.Loop == LoopOne { + icon = mediaRepeatOne + } + loop := mediaToggleAction(c, icon, msg(c, []string{"media_controls.loopOff", "media_controls.loopAll", "media_controls.loopOne"}[st.Loop]), st.Loop != LoopOff) + if loop.Clicked() && !loop.IsDisabled() { + slog.Debug("mujica: media_controls loop", "mode", st.Loop.next()) + opts.OnLoop(st.Loop.next()) + } + }) + return row +} diff --git a/media_controls_test.go b/media_controls_test.go new file mode 100644 index 0000000..9b2e220 --- /dev/null +++ b/media_controls_test.go @@ -0,0 +1,91 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +type controlsCalls struct { + prev, play, pause, next int + loops []LoopMode + shuffles []bool +} + +func (m *controlsCalls) opts() MediaControlsOptions { + return MediaControlsOptions{OnPrevious: func() { m.prev++ }, OnPlay: func() { m.play++ }, OnPause: func() { m.pause++ }, + OnNext: func() { m.next++ }, OnLoop: func(l LoopMode) { m.loops = append(m.loops, l) }, + OnShuffle: func(on bool) { m.shuffles = append(m.shuffles, on) }} +} + +func controlsTester(st *MediaControlsState, o MediaControlsOptions) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).AlignItems(ui.Start).Children(func() { MediaControls(c, *st, o) }) + }, 400, 120) +} + +func TestMediaControlsClicks(t *testing.T) { + st := MediaControlsState{Loop: LoopAll} + var m controlsCalls + tt := controlsTester(&st, m.opts()) + for _, name := range []string{"Previous", "Play", "Next", "Repeat all", "Shuffle"} { + if err := tt.Click(name); err != nil { + t.Fatal(err) + } + } + if m.prev != 1 || m.play != 1 || m.next != 1 || len(m.loops) != 1 || m.loops[0] != LoopOne || len(m.shuffles) != 1 || !m.shuffles[0] { + t.Fatalf("calls %+v", m) + } +} + +func TestMediaControlsArrowsMoveFocus(t *testing.T) { + st := MediaControlsState{} + var m controlsCalls + tt := controlsTester(&st, m.opts()) + tt.Key(0, ui.KeyTab) + if !tt.Focused("Shuffle") { + t.Fatal("Tab did not enter at Shuffle") + } + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + if !tt.Focused("Play") { + t.Fatal("arrows did not reach Play") + } + tt.Key(0, ui.KeyEnter) + if m.play != 1 { + t.Fatalf("Enter: play %d", m.play) + } +} + +func TestMediaControlsEndsAndDisabled(t *testing.T) { + st := MediaControlsState{NoPrevious: true, NoNext: true} + var m controlsCalls + tt := controlsTester(&st, m.opts()) + _ = tt.Click("Previous") + _ = tt.Click("Next") + o := m.opts() + o.Disabled = true + off := controlsTester(&MediaControlsState{}, o) + _ = off.Click("Play") + _ = off.Click("Shuffle") + if m.prev != 0 || m.next != 0 || m.play != 0 || len(m.shuffles) != 0 { + t.Fatalf("blocked buttons reported %+v", m) + } +} + +func TestMediaControlsBadOptions(t *testing.T) { + mediaPanics(t, "no callbacks", func(c *ui.Context) { MediaControls(c, MediaControlsState{}, MediaControlsOptions{}) }) + var m controlsCalls + mediaPanics(t, "bad loop", func(c *ui.Context) { MediaControls(c, MediaControlsState{Loop: 7}, m.opts()) }) +} + +func TestMediaControlsSnapshot(t *testing.T) { + var m controlsCalls + snapshot(t, "media_controls", 300, 120, func(c *ui.Context) { + ui.Column(c).Padding(20).Gap(12).AlignItems(ui.Start).Children(func() { + MediaControls(c, MediaControlsState{Playing: true, Loop: LoopOne, Shuffle: true}, m.opts()) + MediaControls(c, MediaControlsState{NoPrevious: true}, m.opts()) + }) + }) +} diff --git a/media_helpers_test.go b/media_helpers_test.go new file mode 100644 index 0000000..b6e7fc4 --- /dev/null +++ b/media_helpers_test.go @@ -0,0 +1,44 @@ +package mujica + +import ( + "image" + "image/color" + "testing" + + "github.com/egoist/mygo/ui" +) + +// mediaTestImage is a w×h picture whose left half is wine and right half ivory. +func mediaTestImage(w, h int) *image.RGBA { + img := image.NewRGBA(image.Rect(0, 0, w, h)) + for y := range h { + for x := range w { + c := color.RGBA{125, 32, 52, 255} + if x >= w/2 { + c = color.RGBA{242, 235, 221, 255} + } + if y < h/8 { + c = color.RGBA{173, 145, 100, 255} + } + img.Set(x, y, c) + } + } + return img +} + +func mediaTestBitmap(w, h int) *ui.Bitmap { return ui.NewBitmap(mediaTestImage(w, h)) } + +// mediaPanics fails t unless fn panics. +func mediaPanics(t *testing.T, name string, fn func(c *ui.Context)) { + t.Helper() + defer func() { + if recover() == nil { + t.Errorf("%s: no panic", name) + } + }() + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + fn(c) + }, 400, 300) + tt.Frame() +} diff --git a/media_icons.go b/media_icons.go new file mode 100644 index 0000000..ed5de5f --- /dev/null +++ b/media_icons.go @@ -0,0 +1,53 @@ +package mujica + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" +) + +// mediaSVG wraps stroked 24×24 path data as an icon. +func mediaSVG(body string) *ui.SVG { + return ui.MustParseSVG([]byte(`` + body + ``)) +} + +// Media glyphs drawn for this group. +var ( + mediaPlay = mediaSVG(``) + mediaPause = mediaSVG(``) + mediaPrev = mediaSVG(``) + mediaNext = mediaSVG(``) + mediaRepeat = mediaSVG(``) + mediaRepeatOne = mediaSVG(``) + mediaShuffle = mediaSVG(``) + mediaVolume = mediaSVG(``) + mediaMute = mediaSVG(``) + mediaRotate = mediaSVG(``) + mediaRotateLeft = mediaSVG(``) + mediaMirror = mediaSVG(``) + mediaPiP = mediaSVG(``) + mediaFullscreen = mediaSVG(``) + mediaCaptions = mediaSVG(``) + mediaRecord = mediaSVG(``) + mediaStop = mediaSVG(``) + mediaMic = mediaSVG(``) + mediaCamera = mediaSVG(``) + mediaSpeaker = mediaSVG(``) + mediaRect = mediaSVG(``) + mediaArrow = mediaSVG(``) + mediaText = mediaSVG(``) + mediaPointer = mediaSVG(``) +) + +// mediaClock writes d as m:ss, or h:mm:ss past an hour. +func mediaClock(d time.Duration) string { + if d < 0 { + d = 0 + } + s := int(d / time.Second) + if s >= 3600 { + return fmt.Sprintf("%d:%02d:%02d", s/3600, s/60%60, s%60) + } + return fmt.Sprintf("%d:%02d", s/60, s%60) +} diff --git a/media_palette_test.go b/media_palette_test.go new file mode 100644 index 0000000..3deed2a --- /dev/null +++ b/media_palette_test.go @@ -0,0 +1,24 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// TestMediaChartInksContrast keeps every chart ink at 3:1 against Surface in both themes. +func TestMediaChartInksContrast(t *testing.T) { + for _, k := range []theme.Tokens{theme.Light(), theme.Dark()} { + inks := map[string]ui.Color{ + "played (AccentText)": k.AccentText, "unplayed (TextMuted)": k.TextMuted, "cursor (Text)": k.Text, + "mic safe": micZone(k, 0), "mic loud": micZone(k, micSegments*7/10), "mic clip": micZone(k, micSegments-1), + } + for name, c := range inks { + if r := theme.Contrast(c, k.Surface); r < 3 { + t.Errorf("dark=%v %s: %.2f:1 against Surface", k.Dark, name, r) + } + } + } +} diff --git a/messages_media.go b/messages_media.go new file mode 100644 index 0000000..fcb1f82 --- /dev/null +++ b/messages_media.go @@ -0,0 +1,106 @@ +package mujica + +func init() { + addMessages(map[string][2]string{ + "image_cropper.label": {"Crop area", "裁剪区域"}, + "image_cropper.rotateLeft": {"Rotate left", "向左旋转"}, + "image_cropper.rotateRight": {"Rotate right", "向右旋转"}, + + "image_annotator.label": {"Annotations", "标注"}, + "image_annotator.tool": {"Tool", "工具"}, + "image_annotator.select": {"Select", "选择"}, + "image_annotator.rect": {"Rectangle", "矩形"}, + "image_annotator.arrow": {"Arrow", "箭头"}, + "image_annotator.text": {"Text", "文字"}, + "image_annotator.textLabel": {"Annotation text", "标注文字"}, + "image_annotator.note": {"Note", "注释"}, + "image_annotator.delete": {"Delete annotation", "删除标注"}, + "image_annotator.count": {"%d annotations", "%d 个标注"}, + "image_annotator.selected": {"Annotation %d of %d selected: %s", "已选中第 %d 个标注(共 %d 个):%s"}, + + "image_thumbnail.failed": {"Failed to load", "加载失败"}, + "image_thumbnail.loading": {"Loading", "加载中"}, + + "lightbox.title": {"Image", "图片"}, + "lightbox.close": {"Close", "关闭"}, + "lightbox.position": {"%d of %d", "第 %d 张,共 %d 张"}, + "lightbox.previous": {"Previous image", "上一张"}, + "lightbox.next": {"Next image", "下一张"}, + + "video_player.label": {"Video", "视频"}, + "video_player.empty": {"No video", "暂无视频"}, + "video_player.subtitles": {"Subtitles", "字幕"}, + "video_player.pip": {"Picture in picture", "画中画"}, + "video_player.fullscreen": {"Full screen", "全屏"}, + + "video_scrubber.label": {"Timeline", "时间轴"}, + + "video_thumbnail_strip.label": {"Frames", "缩略帧"}, + "video_thumbnail_strip.position": {"Frame %d of %d, %s", "第 %d 帧,共 %d 帧,%s"}, + "video_thumbnail_strip.previous": {"Previous frame", "上一帧"}, + "video_thumbnail_strip.next": {"Next frame", "下一帧"}, + + "audio_waveform.label": {"Waveform", "波形"}, + "audio_waveform.empty": {"No audio", "暂无音频"}, + + "audio_spectrum.label": {"Spectrum", "频谱"}, + "audio_spectrum.empty": {"No signal", "无信号"}, + "audio_spectrum.band": {"Band %d", "第 %d 段"}, + + "volume_control.label": {"Volume", "音量"}, + "volume_control.mute": {"Mute", "静音"}, + "volume_control.unmute": {"Unmute", "取消静音"}, + + "playback_speed_control.label": {"Playback speed", "播放速度"}, + + "media_controls.label": {"Playback", "播放控制"}, + "media_controls.play": {"Play", "播放"}, + "media_controls.pause": {"Pause", "暂停"}, + "media_controls.previous": {"Previous", "上一首"}, + "media_controls.next": {"Next", "下一首"}, + "media_controls.shuffle": {"Shuffle", "随机播放"}, + "media_controls.loopOff": {"Repeat off", "不循环"}, + "media_controls.loopAll": {"Repeat all", "列表循环"}, + "media_controls.loopOne": {"Repeat one", "单曲循环"}, + + "playlist.empty": {"The playlist is empty", "播放列表为空"}, + "playlist.playing": {"Playing", "正在播放"}, + "playlist.remove": {"Remove", "移除"}, + + "subtitle_editor.start": {"Start", "开始"}, + "subtitle_editor.end": {"End", "结束"}, + "subtitle_editor.text": {"Text", "文本"}, + "subtitle_editor.add": {"Add cue", "添加字幕"}, + "subtitle_editor.remove": {"Remove cue", "删除字幕"}, + "subtitle_editor.empty": {"No cues yet", "还没有字幕"}, + "subtitle_editor.badTime": {"Use m:ss.mmm, as 1:05.250", "请使用 m:ss.mmm 格式,例如 1:05.250"}, + "subtitle_editor.order": {"End must be after start", "结束时间须晚于开始时间"}, + "subtitle_editor.overlap": {"Overlaps cue %d", "与第 %d 条重叠"}, + + "screen_recorder_controls.label": {"Screen recording", "屏幕录制"}, + "screen_recorder_controls.idle": {"Ready", "就绪"}, + "screen_recorder_controls.recording": {"Recording", "录制中"}, + "screen_recorder_controls.paused": {"Paused", "已暂停"}, + "screen_recorder_controls.start": {"Record", "开始录制"}, + "screen_recorder_controls.pause": {"Pause", "暂停"}, + "screen_recorder_controls.resume": {"Resume", "继续"}, + "screen_recorder_controls.stop": {"Stop", "停止"}, + + "camera_preview.label": {"Camera", "摄像头"}, + "camera_preview.noSignal": {"No signal", "无信号"}, + "camera_preview.mirror": {"Mirror", "镜像"}, + + "mic_level_meter.label": {"Microphone level", "麦克风电平"}, + "mic_level_meter.peak": {"peak", "峰值"}, + + "device_selector.label": {"Devices", "设备"}, + "device_selector.microphone": {"Microphone", "麦克风"}, + "device_selector.camera": {"Camera", "摄像头"}, + "device_selector.speaker": {"Speaker", "扬声器"}, + "device_selector.choose": {"Choose a device", "选择设备"}, + "device_selector.none": {"No devices found", "未找到设备"}, + + "image_compare.before": {"Before", "之前"}, + "image_compare.after": {"After", "之后"}, + }) +} diff --git a/mic_level_meter.go b/mic_level_meter.go new file mode 100644 index 0000000..d3aef5c --- /dev/null +++ b/mic_level_meter.go @@ -0,0 +1,101 @@ +package mujica + +import ( + "fmt" + "math" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// MicLevelMeterOptions configure a MicLevelMeter. +type MicLevelMeterOptions struct { + // Hold keeps the peak mark this long; zero is 1.5s. + Hold time.Duration + // Label names the meter for assistive technology. + Label string +} + +const micSegments = 24 + +type micPeak struct { + level float32 + at time.Time +} + +// MicLevelMeter shows level as segments, held peak and dB. +func MicLevelMeter(c *ui.Context, level float32, opts MicLevelMeterOptions) *ui.Element { + if level < 0 || level > 1 || math.IsNaN(float64(level)) || opts.Hold < 0 { + panic("mujica: MicLevelMeter needs level in 0..1 and Hold >= 0") + } + hold := opts.Hold + if hold == 0 { + hold = 1500 * time.Millisecond + } + k := Tokens(c) + label := opts.Label + if label == "" { + label = msg(c, "mic_level_meter.label") + } + row := ui.Row(c).Gap(Density(c).Unit() * 2).AlignItems(ui.Center).MinHeight(theme.MinHitSize) + pk := ui.Local(row, micPeak{}, func() micPeak { return micPeak{} }) + now := c.Now() + switch { + case level >= pk.level: + *pk = micPeak{level, now} + case now.Sub(pk.at) >= hold: + *pk = micPeak{level, now} + default: + // Repaint once when the hold ends; nothing runs while idle. + c.After(hold - now.Sub(pk.at)) + } + peak := pk.level + row.Role(ui.RoleMeter).Label(label).Description(micDB(level) + ", " + msg(c, "mic_level_meter.peak") + " " + micDB(peak)) + row.Children(func() { + ui.Box(c).Height(12).MinWidth(120).Grow(1).Draw(func(p *ui.Painter, r ui.Rect) { + gap := float32(2) + w := (r.W - gap*(micSegments-1)) / micSegments + lit := int(math.Round(float64(level * micSegments))) + mark := int(math.Round(float64(peak*micSegments))) - 1 + for i := range micSegments { + x := r.X + float32(i)*(w+gap) + seg := ui.Rect{X: x, Y: r.Y, W: w, H: r.H} + col := micZone(k, i) + switch { + case i < lit: + p.Fill(seg, col, 1) + case i == mark: + p.Fill(seg, col, 1) + p.Fill(ui.Rect{X: x + 1, Y: r.Y + 2, W: w - 2, H: r.H - 4}, k.Surface, 0) + default: + p.Stroke(seg, k.Border, 1, 1) + } + } + }) + ui.Text(c, micDB(level)).FontSize(FontSize(c, theme.CaptionSize)).FontFeatures("tnum"). + TextColor(k.TextMuted).MinWidth(56).TextAlign(ui.End).SingleLine() + }) + return row +} + +// micZone colors the safe, loud and clipping zones. +func micZone(k theme.Tokens, i int) ui.Color { + switch { + case i >= micSegments*9/10: + return k.Danger + case i >= micSegments*7/10: + return k.Warning + } + return k.Success +} + +// micDB writes a full-scale level in decibels. +func micDB(v float32) string { + if v <= 0 { + return "-∞ dB" + } + // Adding 0 turns a rounded -0 into 0. + return fmt.Sprintf("%.0f dB", math.Round(20*math.Log10(float64(v)))+0) +} diff --git a/mic_level_meter_test.go b/mic_level_meter_test.go new file mode 100644 index 0000000..1e9736b --- /dev/null +++ b/mic_level_meter_test.go @@ -0,0 +1,62 @@ +package mujica + +import ( + "strings" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func TestMicLevelMeterPeakHold(t *testing.T) { + level := float32(1) + var e *ui.Element + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + e = MicLevelMeter(c, level, MicLevelMeterOptions{Hold: 40 * time.Millisecond}) + }, 400, 100) + if !tt.HasText("0 dB") { + t.Fatalf("texts %v", tt.Texts()) + } + level = 0.1 + tt.Frame() + if !tt.HasText("-20 dB") { + t.Fatalf("level readout %v", tt.Texts()) + } + if r, ok := tt.Find("Microphone level"); !ok || r.W == 0 { + t.Fatal("meter not named") + } + if !strings.Contains(micTestDescription(e), "peak 0 dB") { + t.Fatal("peak not held") + } + time.Sleep(60 * time.Millisecond) + tt.Frame() + if !strings.Contains(micTestDescription(e), "peak -20 dB") { + t.Fatal("peak did not fall after the hold") + } +} + +// micTestDescription rebuilds the meter's spoken value from its state. +func micTestDescription(e *ui.Element) string { + pk := *ui.Local(e, micPeak{}, func() micPeak { return micPeak{} }) + return "peak " + micDB(pk.level) +} + +func TestMicLevelMeterDB(t *testing.T) { + for v, want := range map[float32]string{0: "-∞ dB", 1: "0 dB", 0.5: "-6 dB"} { + if got := micDB(v); got != want { + t.Errorf("%v: %s, want %s", v, got, want) + } + } + mediaPanics(t, "over full scale", func(c *ui.Context) { MicLevelMeter(c, 1.2, MicLevelMeterOptions{}) }) +} + +func TestMicLevelMeterSnapshot(t *testing.T) { + snapshot(t, "mic_level_meter", 360, 150, func(c *ui.Context) { + ui.Column(c).Padding(20).Gap(8).Children(func() { + MicLevelMeter(c, 0.35, MicLevelMeterOptions{}) + MicLevelMeter(c, 0.8, MicLevelMeterOptions{}) + MicLevelMeter(c, 0.97, MicLevelMeterOptions{}) + }) + }) +} diff --git a/playback_speed_control.go b/playback_speed_control.go new file mode 100644 index 0000000..e3fe9d0 --- /dev/null +++ b/playback_speed_control.go @@ -0,0 +1,46 @@ +package mujica + +import ( + "log/slog" + "slices" + "strconv" + + "github.com/egoist/mygo/ui" +) + +// playbackRates are the default choices, 0.5× to 2×. +var playbackRates = []float64{0.5, 0.75, 1, 1.25, 1.5, 2} + +// PlaybackSpeedControlOptions configure a PlaybackSpeedControl. +type PlaybackSpeedControlOptions struct { + // Rates are the ascending choices; nil means 0.5× to 2×. + Rates []float64 + Disabled bool +} + +// PlaybackSpeedControl chooses *rate from Rates in a drop-down. +func PlaybackSpeedControl(c *ui.Context, rate *float64, opts PlaybackSpeedControlOptions) ChoiceResult { + rates := opts.Rates + if rates == nil { + rates = playbackRates + } + if len(rates) == 0 || !slices.IsSorted(rates) || rates[0] <= 0 { + panic("mujica: PlaybackSpeedControl needs positive Rates in ascending order") + } + if !slices.Contains(rates, *rate) { + panic("mujica: PlaybackSpeedControl rate is not one of Rates") + } + options := make([]SelectOption[float64], len(rates)) + for i, r := range rates { + options[i] = SelectOption[float64]{Value: r, Label: playbackLabel(r)} + } + res := Select(c, rate, options, SelectOptions{Disabled: opts.Disabled, Label: msg(c, "playback_speed_control.label")}) + res.Element.MinWidth(88).Width(96) + if res.Changed() { + slog.Debug("mujica: playback_speed changed", "rate", *rate) + } + return res +} + +// playbackLabel writes a rate as "1.25×". +func playbackLabel(r float64) string { return strconv.FormatFloat(r, 'f', -1, 64) + "×" } diff --git a/playback_speed_control_test.go b/playback_speed_control_test.go new file mode 100644 index 0000000..8d0dee2 --- /dev/null +++ b/playback_speed_control_test.go @@ -0,0 +1,77 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func speedTester(rate *float64, opts PlaybackSpeedControlOptions, n *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).AlignItems(ui.Start).Children(func() { + if PlaybackSpeedControl(c, rate, opts).Changed() { + *n++ + } + }) + }, 300, 400) +} + +func TestPlaybackSpeedChoose(t *testing.T) { + rate, n := 1.0, 0 + tt := speedTester(&rate, PlaybackSpeedControlOptions{}, &n) + if !tt.HasText("1×") { + t.Fatalf("texts %v", tt.Texts()) + } + if err := tt.Click("Playback speed"); err != nil { + t.Fatal(err) + } + for _, want := range []string{"0.5×", "0.75×", "1.25×", "1.5×", "2×"} { + if !tt.HasText(want) { + t.Fatalf("no %s in %v", want, tt.Texts()) + } + } + if err := tt.Click("2×"); err != nil { + t.Fatal(err) + } + if rate != 2 || n != 1 { + t.Fatalf("rate %v changes %d", rate, n) + } +} + +func TestPlaybackSpeedKeyboardAndDisabled(t *testing.T) { + rate, n := 1.0, 0 + tt := speedTester(&rate, PlaybackSpeedControlOptions{}, &n) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if rate != 1.25 { + t.Fatalf("keyboard chose %v", rate) + } + rate2, n2 := 1.0, 0 + off := speedTester(&rate2, PlaybackSpeedControlOptions{Disabled: true}, &n2) + _ = off.Click("Playback speed") + _ = off.Click("2×") + if rate2 != 1 || n2 != 0 { + t.Fatalf("disabled chose %v", rate2) + } +} + +func TestPlaybackSpeedBadOptions(t *testing.T) { + odd := 3.0 + mediaPanics(t, "rate not offered", func(c *ui.Context) { PlaybackSpeedControl(c, &odd, PlaybackSpeedControlOptions{}) }) + one := 1.0 + mediaPanics(t, "unsorted", func(c *ui.Context) { + PlaybackSpeedControl(c, &one, PlaybackSpeedControlOptions{Rates: []float64{2, 1}}) + }) +} + +func TestPlaybackSpeedSnapshot(t *testing.T) { + rate := 1.25 + snapshot(t, "playback_speed_control", 200, 80, func(c *ui.Context) { + ui.Column(c).Padding(20).AlignItems(ui.Start).Children(func() { + PlaybackSpeedControl(c, &rate, PlaybackSpeedControlOptions{}) + }) + }) +} diff --git a/playlist.go b/playlist.go new file mode 100644 index 0000000..c077165 --- /dev/null +++ b/playlist.go @@ -0,0 +1,159 @@ +package mujica + +import ( + "log/slog" + "slices" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// PlaylistItem is one track; ID must be unique and stable. +type PlaylistItem struct { + ID, Title, Subtitle string + Duration time.Duration +} + +// PlaylistOptions configure a Playlist. +type PlaylistOptions struct { + // Current is the playing item's ID; empty is none. + Current string + Disabled bool + // Height caps the list; zero means 320. + Height float32 +} + +// PlaylistResult is the playlist's element and this frame's events. +type PlaylistResult struct { + Element *ui.Element + // Played is the ID chosen by Enter or double click. + Played string + // Removed is the ID taken out of *items. + Removed string + // Moved reports a reorder of *items. + Moved bool +} + +type playlistKey struct{} + +// Playlist lists *items, building only rows in view. +func Playlist(c *ui.Context, items *[]PlaylistItem, opts PlaylistOptions) PlaylistResult { + if opts.Height < 0 { + panic("mujica: Playlist Height must not be negative") + } + h := opts.Height + if h == 0 { + h = 320 + } + seen := make(map[string]bool, len(*items)) + for _, it := range *items { + if it.ID == "" || seen[it.ID] { + panic("mujica: Playlist item IDs must be unique and non-empty: " + it.ID) + } + seen[it.ID] = true + } + k := Tokens(c) + var r PlaylistResult + box := ui.Column(c).Height(h).Disabled(opts.Disabled) + r.Element = box + st := ui.Local(box, playlistKey{}, func() *ListState[string] { return &ListState[string]{} }) + s := *st + list := *items + live := !box.IsDisabled() + s.rows.Reorder = nil + if live { + s.rows.Reorder = func(rows []int, to int) { + *items = playlistMove(*items, rows, to) + r.Moved = true + } + } + removeAt := -1 + box.Children(func() { + v := List(c, s, len(list), ListOptions[string]{ + Key: func(i int) string { return list[i].ID }, + Label: func(i int) string { return list[i].Title }, + Empty: msg(c, "playlist.empty"), + }, func(i int) { + playlistRow(c, k, list[i], i, list[i].ID == opts.Current) + if iconAction(c, icons.Must("x"), msg(c, "playlist.remove")+" "+list[i].Title).Clicked() && live { + removeAt = i + } + }) + v.Element.Grow(1) + if removeAt >= 0 { + r.Removed = list[removeAt].ID + *items = slices.Delete(*items, removeAt, removeAt+1) + return + } + sel, ok := s.Selected() + i := slices.IndexFunc(*items, func(it PlaylistItem) bool { return it.ID == sel }) + if !live || !ok || i < 0 { + return + } + switch { + case v.Submitted(): + r.Played = sel + case v.Element.Shortcut(0, ui.KeyDelete), v.Element.Shortcut(0, ui.KeyBackspace): + r.Removed = sel + *items = slices.Delete(*items, i, i+1) + case v.Element.Shortcut(ui.Alt, ui.KeyUp) && i > 0: + *items, r.Moved = playlistMove(*items, []int{i}, i-1), true + case v.Element.Shortcut(ui.Alt, ui.KeyDown) && i < len(*items)-1: + *items, r.Moved = playlistMove(*items, []int{i}, i+2), true + } + }) + switch { + case r.Played != "": + slog.Debug("mujica: playlist play", "id", r.Played) + case r.Removed != "": + slog.Debug("mujica: playlist remove", "id", r.Removed) + case r.Moved: + slog.Debug("mujica: playlist move") + } + return r +} + +// playlistRow shows a track's mark, title, subtitle and length. +func playlistRow(c *ui.Context, k theme.Tokens, it PlaylistItem, i int, playing bool) { + ui.Icon(c, icons.Must("grip-vertical")).Size(14, 14).TextColor(k.TextMuted).Shrink(0) + ui.Box(c).Width(20).Center().Shrink(0).Children(func() { + if playing { + ui.Icon(c, mediaPlay).Size(14, 14).TextColor(k.AccentText).Label(msg(c, "playlist.playing")) + } else { + ui.Textf(c, "%d", i+1).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).FontFeatures("tnum") + } + }) + ui.Column(c).Grow(1).MinWidth(0).Children(func() { + t := ui.Text(c, it.Title).SingleLine() + if playing { + t.TextColor(k.AccentText).FontWeight(600) + } + if it.Subtitle != "" { + ui.Text(c, it.Subtitle).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine() + } + }) + if it.Duration > 0 { + ui.Text(c, mediaClock(it.Duration)).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).FontFeatures("tnum") + } +} + +// playlistMove puts rows before index to; len means the end. +func playlistMove(items []PlaylistItem, rows []int, to int) []PlaylistItem { + moved := make([]PlaylistItem, 0, len(rows)) + rest := make([]PlaylistItem, 0, len(items)) + at := to + for i, it := range items { + if slices.Contains(rows, i) { + moved = append(moved, it) + if i < to { + at-- + } + continue + } + rest = append(rest, it) + } + return slices.Concat(rest[:at], moved, rest[at:]) +} diff --git a/playlist_test.go b/playlist_test.go new file mode 100644 index 0000000..fb3cb2f --- /dev/null +++ b/playlist_test.go @@ -0,0 +1,123 @@ +package mujica + +import ( + "fmt" + "slices" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func playlistItems(n int) []PlaylistItem { + items := make([]PlaylistItem, n) + for i := range items { + items[i] = PlaylistItem{ID: fmt.Sprint("t", i), Title: fmt.Sprint("Track ", i), Duration: time.Duration(180+i) * time.Second} + } + return items +} + +func playlistIDs(items []PlaylistItem) []string { + ids := make([]string, len(items)) + for i, it := range items { + ids[i] = it.ID + } + return ids +} + +func playlistTester(items *[]PlaylistItem, disabled bool, got *[]PlaylistResult) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).Width(420).Children(func() { + r := Playlist(c, items, PlaylistOptions{Current: "t1", Disabled: disabled}) + if r.Played != "" || r.Removed != "" || r.Moved { + *got = append(*got, r) + } + }) + }, 500, 420) +} + +func TestPlaylistKeyboard(t *testing.T) { + items := playlistItems(4) + var got []PlaylistResult + tt := playlistTester(&items, false, &got) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if len(got) != 1 || got[0].Played != "t0" { + t.Fatalf("Enter played %+v", got) + } + tt.Key(ui.Alt, ui.KeyDown) + if !slices.Equal(playlistIDs(items), []string{"t1", "t0", "t2", "t3"}) { + t.Fatalf("Alt+Down order %v", playlistIDs(items)) + } + tt.Key(0, ui.KeyDelete) + if !slices.Equal(playlistIDs(items), []string{"t1", "t2", "t3"}) || got[len(got)-1].Removed != "t0" { + t.Fatalf("Delete left %v, %+v", playlistIDs(items), got) + } +} + +func TestPlaylistRemoveButtonAndDrag(t *testing.T) { + items := playlistItems(4) + var got []PlaylistResult + tt := playlistTester(&items, false, &got) + if err := tt.Click("Remove Track 3"); err != nil { + t.Fatal(err) + } + if len(items) != 3 || got[0].Removed != "t3" { + t.Fatalf("remove button: %v", playlistIDs(items)) + } + a, _ := tt.Find("Track 0") + b, _ := tt.Find("Track 2") + tt.Press(a.X+4, a.Y+a.H/2) + tt.Move(a.X+4, a.Y+a.H/2+10) + tt.Move(b.X+4, b.Y+b.H-2) + tt.Release(b.X+4, b.Y+b.H-2) + if !slices.Equal(playlistIDs(items), []string{"t1", "t2", "t0"}) || !got[len(got)-1].Moved { + t.Fatalf("drag order %v", playlistIDs(items)) + } +} + +func TestPlaylistBuildsOnlyVisible(t *testing.T) { + items := playlistItems(100000) + var got []PlaylistResult + tt := playlistTester(&items, false, &got) + tt.Frame() + built := 0 + for _, s := range tt.Texts() { + if len(s) > 6 && s[:6] == "Track " { + built++ + } + } + if built == 0 || built > 40 { + t.Fatalf("built %d rows of 100000", built) + } +} + +func TestPlaylistDisabledAndBad(t *testing.T) { + items := playlistItems(3) + var got []PlaylistResult + tt := playlistTester(&items, true, &got) + _ = tt.Click("Remove Track 0") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyDelete) + tt.Key(0, ui.KeyEnter) + if len(items) != 3 || len(got) != 0 { + t.Fatalf("disabled playlist changed: %v %+v", playlistIDs(items), got) + } + dup := []PlaylistItem{{ID: "a"}, {ID: "a"}} + mediaPanics(t, "duplicate", func(c *ui.Context) { Playlist(c, &dup, PlaylistOptions{}) }) +} + +func TestPlaylistSnapshot(t *testing.T) { + items := []PlaylistItem{ + {ID: "a", Title: "Ave Mujica", Subtitle: "Overture", Duration: 245 * time.Second}, + {ID: "b", Title: "Imprisoned XII", Subtitle: "Act I", Duration: 302 * time.Second}, + {ID: "c", Title: "KiLLKiSS", Subtitle: "Act II", Duration: 268 * time.Second}, + } + snapshot(t, "playlist", 440, 240, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(400).Children(func() { + Playlist(c, &items, PlaylistOptions{Current: "b", Height: 200}) + }) + }) +} diff --git a/screen_recorder_controls.go b/screen_recorder_controls.go new file mode 100644 index 0000000..d23ce6f --- /dev/null +++ b/screen_recorder_controls.go @@ -0,0 +1,76 @@ +package mujica + +import ( + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// RecorderStatus is where a recording is; zero is idle. +type RecorderStatus int + +const ( + RecorderIdle RecorderStatus = iota + RecorderRecording + RecorderPaused +) + +// RecorderState is what the caller's recorder reports. +type RecorderState struct { + Status RecorderStatus + Elapsed time.Duration +} + +// ScreenRecorderControlsOptions are the callbacks; every one is required. +type ScreenRecorderControlsOptions struct { + OnStart, OnPause, OnResume, OnStop func() + Disabled bool +} + +// ScreenRecorderControls start, pause, resume and stop a recording. +func ScreenRecorderControls(c *ui.Context, st RecorderState, opts ScreenRecorderControlsOptions) *ui.Element { + if opts.OnStart == nil || opts.OnPause == nil || opts.OnResume == nil || opts.OnStop == nil { + panic("mujica: ScreenRecorderControls needs every callback") + } + if st.Status < RecorderIdle || st.Status > RecorderPaused || st.Elapsed < 0 { + panic(fmt.Sprintf("mujica: bad RecorderState %+v", st)) + } + k := Tokens(c) + u := Density(c).Unit() + row := ui.Row(c).Gap(u*2).Padding(u, u*2).AlignItems(ui.Center).Radius(theme.CardRadius). + Background(k.Surface).Border(theme.BorderWidth, k.Border).Role(ui.RoleToolbar). + Label(msg(c, "screen_recorder_controls.label")).Disabled(opts.Disabled) + act := func(icon *ui.SVG, key string, variant ButtonVariant, fn func()) { + if Button(c, msg(c, key), ButtonOptions{Variant: variant, Icon: icon}).Clicked() && !row.IsDisabled() { + slog.Debug("mujica: recorder " + key) + fn() + } + } + row.Children(func() { + status := []string{"screen_recorder_controls.idle", "screen_recorder_controls.recording", "screen_recorder_controls.paused"}[st.Status] + ui.Row(c).Gap(u * 1.5).AlignItems(ui.Center).Role(ui.RoleStatus).Label(msg(c, status) + " " + mediaClock(st.Elapsed)).Children(func() { + dot := k.TextMuted + if st.Status == RecorderRecording { + dot = k.Danger + } + ui.Box(c).Size(10, 10).Radius(5).Background(dot) + ui.Text(c, msg(c, status)).TextColor(k.TextMuted).SingleLine() + ui.Text(c, mediaClock(st.Elapsed)).FontFeatures("tnum").SingleLine().MinWidth(48) + }) + switch st.Status { + case RecorderIdle: + act(mediaRecord, "screen_recorder_controls.start", Danger, opts.OnStart) + case RecorderRecording: + act(mediaPause, "screen_recorder_controls.pause", Secondary, opts.OnPause) + act(mediaStop, "screen_recorder_controls.stop", Danger, opts.OnStop) + case RecorderPaused: + act(mediaRecord, "screen_recorder_controls.resume", Secondary, opts.OnResume) + act(mediaStop, "screen_recorder_controls.stop", Danger, opts.OnStop) + } + }) + return row +} diff --git a/screen_recorder_controls_test.go b/screen_recorder_controls_test.go new file mode 100644 index 0000000..f83ba6d --- /dev/null +++ b/screen_recorder_controls_test.go @@ -0,0 +1,75 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +type recorderCalls struct{ start, pause, resume, stop int } + +func (r *recorderCalls) opts() ScreenRecorderControlsOptions { + return ScreenRecorderControlsOptions{OnStart: func() { r.start++ }, OnPause: func() { r.pause++ }, + OnResume: func() { r.resume++ }, OnStop: func() { r.stop++ }} +} + +func TestScreenRecorderControlsFlow(t *testing.T) { + st := RecorderState{} + var r recorderCalls + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).AlignItems(ui.Start).Children(func() { ScreenRecorderControls(c, st, r.opts()) }) + }, 500, 120) + if !tt.HasText("Ready") || tt.HasText("Stop") { + t.Fatalf("idle shows %v", tt.Texts()) + } + if err := tt.Click("Record"); err != nil { + t.Fatal(err) + } + st = RecorderState{Status: RecorderRecording, Elapsed: 65 * time.Second} + tt.Frame() + if !tt.HasText("1:05") || !tt.HasText("Recording") { + t.Fatalf("recording shows %v", tt.Texts()) + } + if err := tt.Click("Pause"); err != nil { + t.Fatal(err) + } + st.Status = RecorderPaused + tt.Frame() + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if r != (recorderCalls{1, 1, 1, 1}) { + t.Fatalf("calls %+v", r) + } +} + +func TestScreenRecorderControlsDisabledAndBad(t *testing.T) { + var r recorderCalls + o := r.opts() + o.Disabled = true + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ScreenRecorderControls(c, RecorderState{}, o) + }, 500, 120) + _ = tt.Click("Record") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if r.start != 0 { + t.Fatal("disabled recorder started") + } + mediaPanics(t, "no callbacks", func(c *ui.Context) { ScreenRecorderControls(c, RecorderState{}, ScreenRecorderControlsOptions{}) }) + mediaPanics(t, "bad status", func(c *ui.Context) { ScreenRecorderControls(c, RecorderState{Status: 9}, r.opts()) }) +} + +func TestScreenRecorderControlsSnapshot(t *testing.T) { + var r recorderCalls + snapshot(t, "screen_recorder_controls", 420, 140, func(c *ui.Context) { + ui.Column(c).Padding(20).Gap(12).AlignItems(ui.Start).Children(func() { + ScreenRecorderControls(c, RecorderState{}, r.opts()) + ScreenRecorderControls(c, RecorderState{Status: RecorderRecording, Elapsed: 3*time.Minute + 7*time.Second}, r.opts()) + }) + }) +} diff --git a/subtitle_editor.go b/subtitle_editor.go new file mode 100644 index 0000000..8a1a5fa --- /dev/null +++ b/subtitle_editor.go @@ -0,0 +1,244 @@ +package mujica + +import ( + "fmt" + "log/slog" + "slices" + "strconv" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// SubtitleCue is one subtitle: shown from Start until End. +type SubtitleCue struct { + Start, End time.Duration + Text string +} + +// SubtitleIssueKind is what is wrong with a cue. +type SubtitleIssueKind int + +const ( + // SubtitleEndBeforeStart: End is not after Start. + SubtitleEndBeforeStart SubtitleIssueKind = iota + // SubtitleOverlap: Start is before the previous cue's End. + SubtitleOverlap +) + +// SubtitleIssue is a problem with cue Index. +type SubtitleIssue struct { + Index int + Kind SubtitleIssueKind +} + +// CheckSubtitles lists misordered cues and cues overlapping the previous. +func CheckSubtitles(cues []SubtitleCue) []SubtitleIssue { + var out []SubtitleIssue + for i, q := range cues { + if q.End <= q.Start { + out = append(out, SubtitleIssue{i, SubtitleEndBeforeStart}) + } + if i > 0 && q.Start < cues[i-1].End { + out = append(out, SubtitleIssue{i, SubtitleOverlap}) + } + } + return out +} + +// SubtitleEditorOptions configure a SubtitleEditor. +type SubtitleEditorOptions struct { + // Height is the visible list's height; zero means 360. + Height float32 + Disabled bool +} + +type subtitleState struct { + scroll ui.ScrollState + drafts map[subtitleField]string +} + +type subtitleField struct{ row, part int } + +type subtitleKey struct{} + +// SubtitleEditor edits cue times and text, building visible rows. +func SubtitleEditor(c *ui.Context, cues *[]SubtitleCue, opts SubtitleEditorOptions) ChoiceResult { + if opts.Height < 0 { + panic("mujica: SubtitleEditor Height must not be negative") + } + h := opts.Height + if h == 0 { + h = 360 + } + k := Tokens(c) + u := Density(c).Unit() + rowH := Density(c).ControlHeight() + FontSize(c, theme.CaptionSize)*theme.LineHeight + u*3 + col := ui.Column(c).Gap(u * 2).Disabled(opts.Disabled) + st := ui.Local(col, subtitleKey{}, func() *subtitleState { return &subtitleState{drafts: map[subtitleField]string{}} }) + s := *st + issues := map[int]string{} + for _, is := range CheckSubtitles(*cues) { + if is.Kind == SubtitleOverlap { + issues[is.Index] = fmt.Sprintf(msg(c, "subtitle_editor.overlap"), is.Index) + } else { + issues[is.Index] = msg(c, "subtitle_editor.order") + } + } + changed := false + col.Children(func() { + list := ui.Scroll(c).Height(h).TrackScroll(&s.scroll).Background(k.Surface). + Border(theme.BorderWidth, k.Border).Radius(theme.ControlRadius) + list.Children(func() { + n := len(*cues) + // The container keeps Y inside the content; match it. + y := max(0, min(s.scroll.Y, float32(n)*rowH-h)) + first := max(0, int(y/rowH)-1) + last := min(n, int((y+h)/rowH)+2) + ui.Box(c).Height(float32(n) * rowH).Children(func() { + for i := first; i < last; i++ { + before := len(*cues) + if subtitleRow(c, k, cues, s, i, rowH, issues[i]) { + changed = true + } + if len(*cues) != before { + // A removal shifts rows below; the next frame builds them. + c.AnimationFrame() + return + } + } + }) + if n == 0 { + ui.Text(c, msg(c, "subtitle_editor.empty")).TextColor(k.TextMuted).Padding(u * 3) + } + }) + if Button(c, msg(c, "subtitle_editor.add"), ButtonOptions{Variant: Secondary, Icon: icons.Must("plus")}).Clicked() && !col.IsDisabled() { + var at time.Duration + if n := len(*cues); n > 0 { + at = (*cues)[n-1].End + } + *cues = append(*cues, SubtitleCue{Start: at, End: at + 2*time.Second}) + s.scroll.Y = float32(len(*cues)) * rowH + changed = true + } + }) + if changed { + slog.Debug("mujica: subtitle_editor changed", "cues", len(*cues)) + } + return ChoiceResult{Element: col, changed: changed} +} + +// subtitleRow edits cue i; true means changed or removed. +func subtitleRow(c *ui.Context, k theme.Tokens, cues *[]SubtitleCue, s *subtitleState, i int, rowH float32, issue string) bool { + u := Density(c).Unit() + q := &(*cues)[i] + changed, removed := false, false + row := ui.Column(c).Key(i).Absolute().Left(0).Right(0).Top(float32(i)*rowH).Height(rowH).Padding(u*1.5, u*2).Gap(2). + BorderWidth(0, 0, 1, 0).BorderColor(k.Border) + row.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ui.Textf(c, "%d", i+1).Width(28).TextColor(k.TextMuted).FontFeatures("tnum") + for part, t := range []*time.Duration{&q.Start, &q.End} { + f := subtitleField{i, part} + text, editing := s.drafts[f] + if !editing { + text = subtitleClock(*t) + } + name := msg(c, []string{"subtitle_editor.start", "subtitle_editor.end"}[part]) + in := TextInput(c, &text, TextInputOptions{Label: fmt.Sprintf("%s %d", name, i+1)}) + in.Element.Width(112) + bad := false + if in.Changed() { + if v, ok := subtitleParse(text); ok { + *t, changed = v, true + delete(s.drafts, f) + } else { + s.drafts[f], bad = text, true + } + } else if editing { + _, ok := subtitleParse(text) + bad = !ok + } + if bad { + in.Input.Error(msg(c, "subtitle_editor.badTime")) + } else if issue != "" { + in.Input.Error(issue) + } + } + txt := TextInput(c, &q.Text, TextInputOptions{Label: fmt.Sprintf("%s %d", msg(c, "subtitle_editor.text"), i+1)}) + txt.Element.Grow(1) + if txt.Changed() { + changed = true + } + if b := iconAction(c, icons.Must("trash-2"), fmt.Sprintf("%s %d", msg(c, "subtitle_editor.remove"), i+1)); b.Clicked() && !b.IsDisabled() { + removed = true + } + }) + ui.Row(c).Gap(u).PaddingX(28 + u*2).Children(func() { + note := issue + for part := range 2 { + if d, ok := s.drafts[subtitleField{i, part}]; ok { + if _, valid := subtitleParse(d); !valid { + note = msg(c, "subtitle_editor.badTime") + } + } + } + if note != "" { + ui.Text(c, note).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.Danger).SingleLine() + } + }) + }) + if removed { + *cues = slices.Delete(*cues, i, i+1) + clear(s.drafts) + return true + } + return changed +} + +// subtitleClock writes d as m:ss.mmm. +func subtitleClock(d time.Duration) string { + ms := d.Milliseconds() + return fmt.Sprintf("%d:%02d.%03d", ms/60000, ms/1000%60, ms%1000) +} + +// subtitleParse reads m:ss.mmm or h:mm:ss.mmm; the fraction is optional. +func subtitleParse(s string) (time.Duration, bool) { + parts := strings.Split(strings.TrimSpace(s), ":") + if len(parts) < 2 || len(parts) > 3 { + return 0, false + } + acc := 0 + for i, p := range parts[:len(parts)-1] { + n, err := strconv.Atoi(p) + if err != nil || !subtitleDigits(p) || (i > 0 && n > 59) { + return 0, false + } + acc = acc*60 + n + } + sec := parts[len(parts)-1] + whole, frac, _ := strings.Cut(sec, ".") + s0, err := strconv.Atoi(whole) + if err != nil || len(whole) != 2 || s0 < 0 || s0 > 59 || len(frac) > 3 || !subtitleDigits(whole+frac) { + return 0, false + } + ms := 0 + if frac != "" { + ms, _ = strconv.Atoi(frac + strings.Repeat("0", 3-len(frac))) + } + return time.Duration(acc*60+s0)*time.Second + time.Duration(ms)*time.Millisecond, true +} + +// subtitleDigits reports whether s is ASCII digits only. +func subtitleDigits(s string) bool { + for _, r := range s { + if r < '0' || r > '9' { + return false + } + } + return true +} diff --git a/subtitle_editor_test.go b/subtitle_editor_test.go new file mode 100644 index 0000000..9c2b4c7 --- /dev/null +++ b/subtitle_editor_test.go @@ -0,0 +1,131 @@ +package mujica + +import ( + "slices" + "strings" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func subtitleTester(cues *[]SubtitleCue, disabled bool, n *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).Width(620).Children(func() { + if SubtitleEditor(c, cues, SubtitleEditorOptions{Height: 260, Disabled: disabled}).Changed() { + *n++ + } + }) + }, 700, 400) +} + +func TestCheckSubtitles(t *testing.T) { + cues := []SubtitleCue{{0, 2 * time.Second, "a"}, {time.Second, 3 * time.Second, "b"}, {4 * time.Second, 4 * time.Second, "c"}} + want := []SubtitleIssue{{1, SubtitleOverlap}, {2, SubtitleEndBeforeStart}} + if got := CheckSubtitles(cues); !slices.Equal(got, want) { + t.Fatalf("issues %v", got) + } +} + +func TestSubtitleParse(t *testing.T) { + for s, want := range map[string]time.Duration{"0:01.5": 1500 * time.Millisecond, "1:05.250": 65250 * time.Millisecond, "1:00:00": time.Hour, "2:03": 123 * time.Second} { + if got, ok := subtitleParse(s); !ok || got != want { + t.Errorf("%q: %v %v", s, got, ok) + } + } + for _, s := range []string{"", "5", "1:60", "1:5", "a:00", "1:00.1234", "1:-1", "+1:00"} { + if _, ok := subtitleParse(s); ok { + t.Errorf("%q parsed", s) + } + } +} + +func TestSubtitleEditorEditTimesAndText(t *testing.T) { + cues := []SubtitleCue{{0, 2 * time.Second, "Welcome"}, {3 * time.Second, 5 * time.Second, "to the court"}} + n := 0 + tt := subtitleTester(&cues, false, &n) + if err := tt.Click("End 1"); err != nil { + t.Fatal(err) + } + tt.Command("selectAll") + tt.Type("0:04") + if cues[0].End != 4*time.Second || !tt.HasText("Overlaps cue 1") { + t.Fatalf("end edit %+v, texts %v", cues[0], tt.Texts()) + } + tt.Command("selectAll") + tt.Type("zz") + if cues[0].End != 4*time.Second || !tt.HasText("Use m:ss.mmm, as 1:05.250") { + t.Fatalf("bad time kept? %+v", cues[0]) + } + if err := tt.Click("Text 2"); err != nil { + t.Fatal(err) + } + tt.Type("!") + if cues[1].Text != "to the court!" || n < 2 { + t.Fatalf("text %q changes %d", cues[1].Text, n) + } +} + +func TestSubtitleEditorAddRemove(t *testing.T) { + cues := []SubtitleCue{{0, 2 * time.Second, "a"}} + n := 0 + tt := subtitleTester(&cues, false, &n) + if err := tt.Click("Add cue"); err != nil { + t.Fatal(err) + } + if len(cues) != 2 || cues[1].Start != 2*time.Second || cues[1].End != 4*time.Second { + t.Fatalf("added %+v", cues) + } + if err := tt.Click("Remove cue 1"); err != nil { + t.Fatal(err) + } + if len(cues) != 1 || cues[0].Start != 2*time.Second || n != 2 { + t.Fatalf("removed %+v, changes %d", cues, n) + } +} + +func TestSubtitleEditorBuildsOnlyVisible(t *testing.T) { + cues := make([]SubtitleCue, 100000) + for i := range cues { + cues[i] = SubtitleCue{time.Duration(i) * time.Second, time.Duration(i)*time.Second + 900*time.Millisecond, "line"} + } + n := 0 + tt := subtitleTester(&cues, false, &n) + tt.Frame() + built := 0 + for _, x := range tt.Texts() { + if strings.HasPrefix(x, "Remove cue ") { + built++ + } + } + if built == 0 || built > 20 { + t.Fatalf("built %d rows of 100000", built) + } +} + +func TestSubtitleEditorDisabled(t *testing.T) { + cues := []SubtitleCue{{0, 2 * time.Second, "a"}} + n := 0 + tt := subtitleTester(&cues, true, &n) + _ = tt.Click("Add cue") + _ = tt.Click("Remove cue 1") + _ = tt.Click("Text 1") + tt.Type("x") + if len(cues) != 1 || cues[0].Text != "a" || n != 0 { + t.Fatalf("disabled editor changed %+v", cues) + } +} + +func TestSubtitleEditorSnapshot(t *testing.T) { + cues := []SubtitleCue{ + {0, 2500 * time.Millisecond, "The curtain rises."}, + {2 * time.Second, 5 * time.Second, "Welcome to the masquerade."}, + {6 * time.Second, 9 * time.Second, "Ave Mujica."}, + } + snapshot(t, "subtitle_editor", 640, 300, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(600).Children(func() { + SubtitleEditor(c, &cues, SubtitleEditorOptions{Height: 200}) + }) + }) +} diff --git a/testdata/snapshots/darwin/audio_player-dark.png b/testdata/snapshots/darwin/audio_player-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a19fc33c89f40715722d602f0ce5811a451908b6 GIT binary patch literal 10475 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 Ca$i*d literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/audio_player-light.png b/testdata/snapshots/darwin/audio_player-light.png new file mode 100644 index 0000000000000000000000000000000000000000..6d5dba4fe929b481ba84651075bbf1456d1edf2e GIT binary patch literal 10039 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/audio_spectrum-dark.png b/testdata/snapshots/darwin/audio_spectrum-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..8c621f0c1118a0f2aeb0c866a23a9751313922ef GIT binary patch literal 1666 zcmeAS@N?(olHy`uVBq!ia0y~yU|a%ZFW_JTl4nlzA7Ef$^YnCa45^s&=DML5v!h7E z!+EHv zw)bSe>0dS!n^_D2hzWg;&Z|N5sS^uKW^?4hL_wI^|U2hw+ zKG){YRsKKDlm68VpwGw%(s#;lig+%qFWbGl^J8rI?$;7a{l6WXCws?$0~ob$_rI30 zaP^qLE3s#u`t^jDeAcMD^&V~o=1GumQbAUGr>yz(DjMO$zp3s@ zDnfb_eU<9&?6rpkf}T?uECk|DMLb=)XUg?3gpL&RrEff1TviDwLV^%T?v6}N?=W$Z zQo1jzbP{ZaQi?jnK9E5-4);urb>7?!3&OrP=Rl!;i9;D4Ql@Yx#u_Ha#>N1l(Rw|& zv@cNo>ZBH!0qfMPVg5M`3Prt}rL$rY?(cikc9PF6fyJ%vU9udGn2t*=~O8 z@->$XL|PeVG;rz4E?u#>d9t40zW-02ESlWRA28)yX4`88c5zX?PLrL_ts^J(INAOC zFSjzq{BVkTr-#yIHNo2vaCqZY?i#7p$5w630#VnlL}-fx;dIOOF)G$4{WeX01Eln7 zHwnA-NxLCL*6H0`3DL1?0)#vjhkXo>o-Cs_gd;075q`$>!^)N&HHqG`0 z8dKCJh!9!rT?V!mX#1NEsnumGW3#TGxb?Jq_P6ff;VZEU+DthHc$}{rYqJDe?RW=%j$RQ@*iE3*!-0iY@J?q?#-N=OD#6jq1=t;D4R4lMg68H9%`vy*?eXO<-`RG Uw(-w01=cMLp00i_>zopr0P=w+CjbBd literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/audio_spectrum-light.png b/testdata/snapshots/darwin/audio_spectrum-light.png new file mode 100644 index 0000000000000000000000000000000000000000..0d0b85256cea62a24d94ecb78bdc2e83f90b8b2b GIT binary patch literal 1673 zcmeAS@N?(olHy`uVBq!ia0y~yU|a%ZFW_JTl4nlzA7Ef$3-EMt45^s&=K4mjwg8a> zAMFgg>@IOh-MY1i{pD7vsxdUfx9z16&fXXWQr)zsaX zxa7|2qz2hH3GCK44)T?4Xr@1Nx6Q`Y$v?ak- z1s;~bE&taQKM+xLG)wqUH7}-l>G$-LeQ!>H(Z30@JqJ!4mQb|bqzp!@Px>7@6(Ome zoVupx@41L@aUh(&FI*fdt-PDz=D`zZu&IBuMsoF@Dd8TK6J>8g5bKF^pZny0Z~lMp zUy6Gf5D9LYywNBOV*dP75jRzLf4k`ll7JxF)aS1r0in^aS562~@f3F@an+>Fn{VEH zlT&79Jv+8?Gt8LT(>I>-uJjF!gPW03?pU@?4+K}o#X|h3l%fvu%~X)pdJ{LETAhz@ z;@9c2ofABExR`bRDE$7<0_@A(95+uwL!eeOdFu2}L2=Ot9TV?P*`zEew9=~u8iYVg z(x%Q;yd;p>QB&Tb0uIIQ33DO#frFCYIIN8KtR5@~tv6Xu28Ozaa?b=v)-gY{lj+}6pAU=Gs}L$-EX}~TFqLbQBdM1t1>XS z=AJ#5mcIG)jW>30?rijW;vjSU26E?GmxpWIo zIp}sYG2G|b|CuJwRy|gb-)H|U;HK|}H&Z%XdxyK_fT;Zvih+Ty9p-%OdiDY)#EUd_$UiTis6;R5T{y*U$Me67bc`Rt9# za}lRcf67X$)U<}lKRkWz@y~x3{~6wnzX=na?E^GphT$Tpk$yL?PMr(0b@$;O)7@wE zHfJBd`Lz4?d+~ILW1w!zKDNy$Ig#RG>eg|+-u~@RpT8)Pe-Z@u3=Wml^GpZK+>4dZ z8T!m^YW!tyX{sy#g&Wmc%Tq&7IF*$ZZAoPV$Wv^RX>B zLSG6+p?jhy&l?e~`KMX}Tvmzkin->^P8%ABTQ=m%aKD4|;vF+0i1Lq!d~&vjp!r4{ zJ3Bjl)c0YFpke`IVN$HhFF4D)IEs0RhLGokuV_HDRJLA)SdZ%Q*1 zmj=0=gB^464O=(%jZM&$B`3afu=iEo6dv=YzJ9UM0p4{VFKsXG35enMW;v{w3yI!x zSgkPX-frc3cM?%jPY|Wkh3XqNl69%I2y&^|*`(6?S%k@Yx3LQd&q;A1`r-uTlj1$dJ%+{%TW0SIjBOcxphM3boV!8;;_koCgtt=9^Fz?vyK^mui^d z>0m20)gR8Or8Yk#w4_FAtnqR~B^0ur$a>nBoOf858BN(1Z3*O;0lu@>2_sB_KyDoD zY(ct;eHwCRxu1K-GrH^qePx82FwEodF!RAsm}VBx<$?REW~2L@DLU*!ZM>;O+W2Oj zKB*m5Ch;m@A(Bz++Eg;6m&`22m&2L@n$#6JSlS{aadMT+NIUY4O-t^5esAkQ}#e zGp$BVSLzh+s2~y+Zuix&pAiR7QRBy#zdap`JAk)?Vi#Nza0_!GeNnuu9E~Pr0H@eT zB_!gE`oK-;xexl``PWv3ns=qZy`=Utwu2(UFANdSPeNGk{7rc)VFO>aJYYdwcq0Xd zPUVv7bbZ4Ul|5`p!;bgj-u?W|Jg(Ghwnx5bhKQONiSYX$v=k})deGLy31Im455qT# zeq%f*zT8S>hUe_=_|0!M(z;~QKG7eu$?WbOn|Pbqw$?+*f)@8duw~wo99}r&hq^z_Ca&LVyOn_~E7W~?P7>4<^|A4z3ro4(4s(YJXvCPd2T9fY zIgHMev1+aA&SdqW0;#nd7LGp<&F#$C!9?et(Skq=Ad*(RqiIj43#eJDQi==5SjTqg z9X+64W^B>G7s?Fco5F@BRPX7Ha5sGft~F__a+KjfQY#t1nSYU zX>WU)Yufu`Z8-9>Z$*esmm29eV{y%Cac!V{=-b)aQcHRNLOsbV($}|0+;Yf|iCQ#V z|BSmu2syKCK3OHFhk4%U*z4M2ph3iF0j>}S2e|yY0;Mm*#GtYe1aP$O|@mi#rP ze~}9g^Xp9f7h!N3Kfn>bx4->nq?|<=8bsge7nv$Og4em}^2f?1`PpJIrr$qK!s`Zo zUQ%CBDKNJ*gx?=(_+tHvFGUEB(^oS=gMARb9r1_u(8hwzt03*S`q0y*lhx%De_rF2m#{u zj=7nTIeMX>rka*D!t!bL=xYU%{%U? zGVO2d0v7e7x68E_6R9y6?an?k$F&wdbs-YMjF4Sa5roqG-S+sx$r_t+)j_!PLu>EF z6z}I+B^ZDtRNG8PgNA>q!9%nXMyPU2heDtxcNi1$!v14;Y~t@gS*iz)n_ zC)&|)dD@v9a$-ZtuzMsuO}LyO{W&Rk01;Hs!DKC9cVHW_oBtC?Pp-0NBB7Vv+jGq{yBFQfQ%?`M*KlfPYUC( zY$C*_EY|s}zdFzwc_pS)uhf}Lj$!9QV?%v50b5v(*!OK1s{Dnn;!B>HjwQ+#Rt9$6 zJ8)7s^J+$~dX5+)dv$xVo8i0f8U!sgXf`>ROrk_UNuB z{ZmZa^SMrJC1@eVpz~0sip05;w@;mA1)WG>aXdOf1uFNKVz5ru?HeZ0VW>clEcE8w z`qqpSPDx(NvB$dCagKO<(Z6vS&RJr&4Iq`2IO;Du$6n2=(_Y?edzY!HZL5ue(Svlb z>*Kp$a>qXRMUHpAF1zFuh^Io!$*Hwx|1#)*%<6xwpcMCaHT#?F=I7IQfm~NbI;gU1 SVEFzU!DV4;Wl{n5jQtZF&k(5q literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/audio_waveform-light.png b/testdata/snapshots/darwin/audio_waveform-light.png new file mode 100644 index 0000000000000000000000000000000000000000..0440cbf51ff5dbd8d5ab6c1be447f5b95397b10e GIT binary patch literal 3221 zcmd5(n~ZDL=r>+DL+6Y5erg8;Ryuv0ZK9QG!zje zK)_&>fP#q>A#{-%LQx_hT@XSEB+5rW3$v-L%yRl5v>X1?9NZ!?caj$w5fmB3 z;VO&PvODHSMmlw3l&2r^w-KV?#F|zo)!z&l@&AXwI5E0Nf>}8#>Z+=0h%O|tx3o;l z``cG`Hazq8&Ndo#t}B}uV@$i_7JPSdG(qR#Ng6u%U{XhCno*ju@o3H4%9^6tq`UJy zU+XJakz}v;#d=N$AW-OOBg*Y1TG{J7*v4IEM}0`Xl|jtggA1cz^~*y+MA! zRTnhgb}!PPGBS0)jJuVo0?@)<=1PU3Jv`j)ttJ0#vXUmjL(WfH-Vb&_9uTxeL!nTI zbBXrnx^cqHAL+Re(mvUAVb647=1}^mr%$h?2@!{XboWu`n&ghjjdyQp84y&il{~QL zKBfQK%=nk%uQ{fCOom9*qc2>axpq*H8lp8LPSIeA zdEOxp-UGwg4uYnJhI@iT`>#}NSI^%&fE6W612IA5gP-M&uQl^mDGsH>a%_O8}@ z@mj57u(cP3_}Qa;#rSdvC6K02%Z|>dGlDB8co)?uVXZm=j!OZl;#wPOwH1oO=G zW32VxHze_N0?x1(kCU_-2nD={-PDTUEn#z-)EiT$2OXc6+32qM zPsBIjiXuw`{8*vhcXG&SSEx@-crVU^m*D2oZwWTCK)f!Q);?h(Sp3 zGE6T{0u@1xPoZRAo_{g1zJHt9)@9kf5MP_pP8iHyyEhc@ZDEvtQg0EwajD@_q(ce@ zJP8wuGusL-0r)6N@pkyE>vXz`ZdyXDt(u~(62e~WtdmbtY6JM;L(74wGy2SrpM2NE z$b!py{7i+J3EaYzts&<_O^k+l(;GH!K}f1<7)7BLL|LR0;h90|j)(^qd@IjLe&n3Dt%Vwy2Dr$+pP91~sKRXtE} zp^9TV2_6ZDm!dU*BkQhH7HErpeYg=M3lGcq*!vcyEovhhe3Pgnl>?%Js4jlL_DGzf zouPftS7kwM_dl-(<}6V9FVjc=L-5~3i*3Xfeb>HU`z^|3&2g*X+NXaRsRRh~xj1mh zdcV-}q01-=16p0@f`6yt_Rj5{#f!O~MTtIpdDJu-Wn1|}rmU;145C=4goy5L&A7wg zAvL4D^13Hkb1}rSG?Ehi)I20p<#tr;`7Od3mqr!0)+BvT!s+ihsV)Tx^;bBpzRA9A zF*4kT&+=rmW~VoYbrBU=W@O{Y1KD%ZujZnnVr6(eK?O7NW zdI$UlAqV%I5_~b9?%13zayFx(+>v;d(chn36&(eDZ-U%RXi~SnblhRN$x?6;6x<3m z>;5DSTfcYOaln;ORPpCrO3t!}g8m#!ZO3M%c6@G}De%>;J8-?EEe96ek7H=B`94ux zJqt${WR8{qxn5!yl)ZYX$Y$HItgD)|YYU{)FPMn;omEfY%a~@yYRRQe1g>l|OcP}8 zP44FsHb%+gp|5W$AlAwr@FwTiW|p$*eCGD08i0!3hJqe00{YW?Ns-YMDR*9oNX)QK zf~pfd!ePLb)MFY`9@In2QvYTdxWbjY?xW4`aJxe(oc#try>uhsH_TBA;cscek9p&S zVI6j;ZxWD-&8HSzM@lIOTXup?MHq*)VrIXd%QTmy%(gS~ym%D~tJNQO8qiW#xMqI* zFfQ*Rm~lCylYNL)Y}6aE-GKNZ_n9?3*SW+!IzbMef(phB)y9mJJTc$*VGKWZus;QK z7$$k|SgE;yq;T*T39oqlt0G-i1i_+HvYmYOWxxIZJnd9@-mUyR;DZ8Y0# zHt5@Rz~t*E@oir#>TwEdRT1SeY7qv#J6mydDS03-#iX6-V7gi_sxHBxI#8bwsTj#4 z$=0%qD%GwFhJ6v97RCY7Nw)48eP^5{D6$Twe;fRvR3P=B!UA&v28}$hP?xgX!mlEz z?$YTR2Zovi(@k=DjC!Ln@puvhVWEAs8l_icV|hfC1JNlq1i%CtCU$sVn)@q$SAZOy zpxHsc5%y-G5StK)Wksl!MDr3{1S#pGX_zD0Z~ePeG&^&X6}*8B!^<)T zZxsyY23ASkuLw_p1P3=_Wz!oE>7s26F~D)a=Ug>y*#dWbtO+J1aZjla)Lr9cKW5#XT7| z|CV}J40uvo*X`_*+NY$<#cersc2+XC_BPTEc!p71Tzc>Txib23yJ@hn_jTCCu(+M= zSInq9*oU9(#zXSWJBPjp? literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/camera_preview-dark.png b/testdata/snapshots/darwin/camera_preview-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..e9d7a4acb42015f91088231dfef9f4052a8ac302 GIT binary patch literal 5170 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/camera_preview-light.png b/testdata/snapshots/darwin/camera_preview-light.png new file mode 100644 index 0000000000000000000000000000000000000000..142ea8ceb8be3dc7d8bb5a1e9f4bd2462bb1cf22 GIT binary patch literal 5182 zcmeHLcQl+`w@37ZAfk6dh!zoT^xi_W2qD5~QD1F{8X;Q3jNXD*H_C{bC_{+oL=7{7 z7h%FXqZ`a%?j-L@?)S(2=UeOEweDT(uD#c@_H&-I&$G{O|Mos>oy7YldUUiLv?L@X zbO!p`<|HI!(nPzNnvD3QkceI;Az`L4(AKaFd4paUGqUvL`mpD=!Ol8>shR z3NIOi&v{CIRd8Hnm*kqQ+VM>Y;6 zrUnUa9lKPYUAGNunG+07uuE$L=5CDRuNJAghDXW0D^gt$367kYIYdwFo}BfX3*-(v zrvtPlhqCLi;AMak5{Dl@3Je}9=!}t7yq)%1Z%Zo^>nJFOY@REHD=|+PLY>bL-(t6h zddi@ii2Qdx^=y7NeEyEPUNxSaL>(ECQZ_8u+7=rX=?D_Uc?Ol+F}8K*Z4Czj&0zGN z?jc;s6N8H!7|%}$badbmt0j$nyo}5Zv26cv42m_&+0arF5svYWwp_1=h?=!!ta%pc zSNt9=YpGLnlQ#7Gc7hCujTXGJ4e0&jYdu`TOu=FxSLwI_8nD$uC8SPP*7>6Ei8R}l zIE$DyB-b2h$j^IO>Yha1iaK9a%TmDF_uPtH6JK^Iw>t~BZ3M+uM!BbD?~Rxn+TeY- zRlozK%}eKt&{_o+fDlMu62afn92e8Wf#<+PW=tzF0x!3Q`SxdG%WwDEs5ge zBTajy?j+4tu1Z35{H>xpe4kte8gdit{LuNpWiI^2y!=3yA{KMlu)`I0bOJT67X2!E zS^KcOA7@)WgZx{*@dJG#Hxr-?h~&5V;+U=N;sDgL2Wl1AWg_V}cUseB$~#-(nQ}a1 z-oE87#iJu2U16%b0l|Dq3ZXzRb(Wcer5X`QY+SuV>dQ-p$_9ghzS%ClA^=sy-VjV* z6>)wf)y*Y7Dn(_{->>PVq%PwZ-mIy;nU2aa zn<_mZL|u6Lv(dXn8C4o&AAx#W9ay&42pnXc9PNEsUyc{*OeLjtWE{G7Orvq#nfkWdZMxZ$n;RqlrwzZ{N zS1D}4mT1FFjjJj7vtAX4(Qi@B*eg*TU5eW_3(l10XEfhvJN*dmn%vu7i4M&U@DJ5( z;VoY~>RNwU&waVj~Qzlz`<+Nw4pjoiRhK9(Be)F^^HUC+(qB@z7x)_;0 zv(CC$1fk2M-Y;l4D$1qhc-IiF^{gmlLk2eCKW zP?T93v>_z;AB?p?IoTZ)amT@FKgbIu=TkYGMFu>yXVM(LMO^s{St8I%@j)igN}i|2 z`YL+#SG$fj3gake=fxY!%MTnPA~sRCs`)_+n3!`B2aJ;c z>2Ql_HzucX0Ly6HIcaEn;{KN4?0bA`D}ME2 zxcXx$H)sWQO9#cwKH7QaY;jm|iO*S|W zq;VU8#1U3oY4(mb-~rw__nQ2}-wsJMObF=N*b-^$^O_mnNz!j&$RYFwm-crE0e}QBFa`^JfV^St{GJO&nz6cs2(q$eH z1%%|+0E#cU(PR;@=}S3o+2BaeM=JE3{Kr?EiH66{`%Myqa!d5$k?t@~JHt@zn>meI zKJWHtN(~5pHN>JiyON4CM`+szracp2y@N)7TiL#tzPq<#q!}1|8!**OlK_7oSNKZ_q0gPC^PSqW#py)m!V%fp0)yp4}l5km9d^ScVI=(>IU zq30r+R8HCeM@8v>l`F7wD?dT3#!5etJY~&i=I&doD#(5QVolALv9vVTr-!x^ni+>o3m1 zRf?Y5sf=jaUpZ~Ql$cP)G{h@M$QoE{h_2^^7Y85kPOB<|UeNJ@@13B@H5k5yB}_W! zsRf&?Zdp~1v%GECOZZfhZJx$DdO6Lo?_M27#H4645Y#ZVN3NoRw-)8hh>X-t-)!1X zTB|e(;41I#!We6q?R_%R&Ulla-g86Rd3Y+8Ck{RWCG%#~oE_HViav+Gdx9iJ8} z@10o4j#@2Es^&~#!jxywk$_Xg)APb~96tzOeIS0E8pfE~l%5W@>ylK3y{jjzuA9qS&pG&> zu`|-V?B#|&ih#o}8%fHxw4N*A+A_+tLGqURzbGtQN2G5kA?70<>)hGyGVKYtGtc&H z1fCTqj(h*-_rX1ILRCA=$J*B8B#l9DaZTYYyz`Tj+0)aO-n7d)D5*$L%W8_rfG}oY z9|fGT#lYSL)IRt->Q&M)W+>1fS0ew=$|Adoz^m>29fQ~LPcwwRpRNPsMAfcUYN$>fqd?NSs~qtj7(3>A&trSRC}8 zYM`fQCZ=StB6nL_8B;s*^DCNa)+&U>1eDcRb_CL&g}y)je&nV2Pg(w~&*^p-)QMP4 zRi~vb%R8sjRf+=}zZ@! z!Is(z`DJD!RiB(v4TZd(J5NcCV=n9Vcb`^$k}>m#r#IZW9hs>w)Va9mElbzf@~c}E zUV$Xslp<6uP2^`VsDX4mlCu(Cppsc-iKNpJ#!R@+`{VgD^*fbSKC@(_Lp*nGJzW_4 z`0=xz%82lgM+>y2VDhu>2`*%z+iK#gPR|-LVwSPpy;xg(d>HW#wb;GRt!T(K;5yN$ zH9{`|Xhu&ohLPEVQtFF~!*{wHM9>@C(#4#N!L`&$ciZFDtuWVs^<-q?k+!VS zbx4~^UCCB|+p6hVM1+o}BMS9yzU=&D_xs*!%+nos!7Q<(OB~DO8GCK?Ombe)ZkEAP zkD$l=hpEze~Wc5rk@O*;(4>of>YOb$}u0 zBl~-OUWGqep*w7D3i#HL2-C61x#)uF96VS2w(z+%X^6Moa+KDwa&Ru`{>?!D)!ea< zUVmNehICfi*-^&Fadmg@5)e7fCeU3xo{GRB&EXaj`pwm?wY4UAXUy^7YKs0%X6loQ z9)7v!#{BkM9-t)R!NDXZWT_7}eR(L&o{Mg?Oj)CRtqVFTZw6J(!7dCQ`=l&A*-afG z_L6aCmWHAF(cM96p16Xkk8cS;RLVUz^4^;y%ajI`G|{83-YX$2V&BP1O8ku;+Su4o zSBCFM`98nO1GYdw(Uu^wjs%c)6cq;)KO;L7tNf{hUF@^#A4$r2btT0$IwExjU?r1(L`VRDnLmxxIZs zwK0r6bSA^hj_uyUws^9x!iT5yk$+Lm)AaPux(mwnD%>JB0Sv=r6poLJHtZ-{kt+jj zazdPGbVG5@T8;b&NaQ>IAbZx*45NsKB)_T*^VjB*-Y4&t8On-o8@A01?3#8PgHci8 zt$O5}t0Qx4<#xC|H{P)^4;G?})m=`yvh{rnqE9Bi<2Jq3+yQZd5)4%u9T?<>Iy=*P zQ?_{=;Tbd|=f|-X*`d%G#31q%x2USD;K}M|TbaC#PuX62c7R=MLe*Du&K+Z6<<09$ zU*V^R+hcgAS%;+=;=0Gkjh@o@J=dy@!!q%t0n@^+kW<{+en7BIXNIu3;Zs0)bsqQJ zK@({5O<`YtkXW~UC)g&fY_ffyHS*HGkMjQ@N!RJ7>PbmBmg?guO;A5>2T2TcOtfK| HPhR{7Bc}Nq literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/device_selector-dark.png b/testdata/snapshots/darwin/device_selector-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..645f377a60c20184a6683d6694236454790f3fc2 GIT binary patch literal 12843 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 O8#yUu$#T%A!2bYlK$SHB literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/device_selector-light.png b/testdata/snapshots/darwin/device_selector-light.png new file mode 100644 index 0000000000000000000000000000000000000000..a9d6d441a5430fa089517aa5509ec15c3db5f112 GIT binary patch literal 12358 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/image_annotator-dark.png b/testdata/snapshots/darwin/image_annotator-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..70d803d6585645d445de0b12c3db2047c18deab8 GIT binary patch literal 8632 zcmdUV2T;?&x-TdQ5&;3}y$DF}y+{Y?h(Kr&i4^G|y+oQQ7>FRfiS!Pk3JL&d*#HX* z`v>Or5dQ{-Y3iMD$HHQUXecWf`lPK-0rVal)8K7;c#yrvd8FurqX3IwiZsX|z+u!g zb3jF!It?_G9yryM)k;@6)zRlq0c~w-J*A{JyeglM@D9e08(Gz`MBezMuZ%+y2CJ7@ zjK_P8vr{iF&748y%gJ>6QPV|oB{~S%kDIrc*!C5fArSZl2meO!L#Eo>H(jvcuXvaM zT{r%}dBl*xwY~`U;GCSOhTS^4En{Kvo2~8M&BLV22o*9c! z6k`!7$f{gwjelYON^6@6sv7y}LtSIv#Sm*A9`C>jg+kOEeN4QC6rY9c~)ylfRc372L7-FtRh zMW1aFnf41Ui9Pm54Iz~H&Dq)nCB_H3m*N@P%|_-gbQ`R7gP+vr{kNz^Y<^OVn#&yg z^P^KKLGl*z)k9SVc8#5*O|4jEd}_`|>~XZ51VK0HR>ZMjH6-vdxeT}RavphDF|3u% zt26z3KU=p-w?-Kso%zEe=l#`Bq^=Zc=|27Aw7|TfoNu_5!GLG?ZTaFEC5m9RvkaX* zd$SK25~I*syqr(h-Y*={XcP0jb8A%$xj1bx`Xa7=zJo4*fok{pSv$8oWnm$aANBLW z2Mc^=hEb>Y0`Gr%yEtrpi@4gH(p+Hj!R2Vv2l75#qcgTD9Ym{RLjDG{)Pj#C_=5^Q zgQ^Ei0xS*npU32fi8}?fhi*lqH`!0NNxn#SxOw>BV6K*Ct#ToD^0iiKw%ElMgO

  • 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/image_annotator-light.png b/testdata/snapshots/darwin/image_annotator-light.png new file mode 100644 index 0000000000000000000000000000000000000000..001ebe888752a803a5cb0b6ddeada45d5e41e4ab GIT binary patch literal 8595 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 Tv|;{ifu*dVE?*)0+W+4G<6s7` literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/image_compare-dark.png b/testdata/snapshots/darwin/image_compare-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a1d42b682cbe2e422a1fc01ff95855a37b9eea56 GIT binary patch literal 3694 zcmd^Cdo&YnAD?La^xHB?#Y8KYP%eeJCSr-CNU28sEacL1TN6e^q~?-BE{UIP=04#^ zZq3YcS#zChW-&CBOBk(p{my&N`_KEwd*1W@(K+uq&v~BDdCvFwobU7be81;8PrQRY z0wgIX2><{ zK}z5_(aA{oFR*AM{Nq>?R;-3ukiM8!M{I3`G!s^NGd|5qNg6NlO<_OJ0LHqcBwcx2 z+Zd;76bU--pF3$zz5ghG%^5nwF;^7l!#~jOn}JvSa}!0w|Kly~5Jd#Sf8(CZ+?$j- zz6YM`QW`2Hp$TMN=3~`qi9smC4}*pwb3FDZ$KB5^8fD|#qYBQ7X~{_LmfRRkav{6D ze4j#q50l^*%AWNNn9gB*q#(4fdM{qv4xYKZZN+~DYHt?YRBTbmu|tDkl^vSd&;0P}P*>)LZ|K!Y&WU6?icVJ*I!+OroY5AnKUC1o2nuO6%DG6aFs^xz>T#zr z2*(0(`r!c~AyXHF^+y^OVcP7`b4uDt>4YmyxIhbwyy)n#?|ilDiX#DkH9URlZfEEF zN8Y0;fVSbn!qNSfV+x-z?r*K-q*3S-ADB$`({sDN5mVx3xa7i3K9)STc^r9wog)zp1oF#V$azIY)&+bGh_bSRY2fr$XNDt%l7>PN))vML z!q&?bj8`H~XV}e6=@r%0sp#vw!XW68>g2eO4V!^JpK&8K5!Y|sqRWcqk}qGrY?s4} zVAuDhrY498%%tOM>!w@oiz4D@+L^tcjPIKcOEniS>bbZWG;VdAgz;C)oS!HhyZ2Ik zmcRP8pY-l64X*gPQQH1IJyxL-|FWfOvpkTL98r|T1~Sy`i& z5AnO0xhLO80-9=TO^L*Pr-G)=c(}UaF0-`y=8BQ^(s6`pXY$PsG;e-Bj!;+U@p)ix z4mUblwBSOfX=o#%q=Zyj8jl}05$eX{$@`uK7{wHFHNXM&sXK^rXOZhmF}OyKR#@7L z=dV;?!5;QF+yRJQ-wDmbhiz?})RW^>-x^JS7De>*^v~|gaBq9Ol%YL6Wp}1!vY3-PAGE?3=H%S3><3u5m>Eg)0#5i z#$9cinwv|>!S$!pn}RdrMz0~`2zhxa+!dF*2A5#NWUiyW2q?hW!*gtg_X;Kzn=bu{ zvAp#@&ViHPJE0W5+M-`gb(uXRBT12E?6_)@_`BM(k`nsVR6~&)<$Y|5U zRRq#MXt2JHwJp&1-CUCp<8yy&yJvWNaQw%X0rI7CkM|qjJyCE$BD|<_IE{qQkwzq# z9YYa9ITRIyDpmf#u{br`@Ua0*bCF)hYrD+U%%?R*>em*oH(>>5>`5P83a5gO)IC1F zI@dmh?#@Ogxvkry*2AN{;CODxIJ}S_APcc-tXY~Er0;TDM#@3tDh@3gE6VqTWs>uQwy@f- zB_HnQo#6Mjfs&cV`oexhUF$XpSgG=76q3eV<6|zcTiY02l0Iqr``n=iLGl>M@SRA}Ul9s+T&v+-t=%4Ju$SCjfXa(v#fW~O~x=yrC`Akm8 z_6{5J562{l?Dx<8+V=O0?rI@eK+EUURWR4s%yZTq@(k!3AHX?Y+h z!VuoYhUar@21)fJ*%-}{Z*vRZHs*t~n76=*0p+-DLLztc#JYwt;pCG_??_G|d)@LU ze(xQbFAm2Hp9Fc!ToQ$TZ?2$%y&du!2HiCtt`Z2F+HG-~PAdnC2Uu<-q^ieU>F0 zS8 zrvKHl2yH0kwnDq`2L+H=uEFQe%c_DWmHvMQz5y-=;OQvZ1%0iX`Kf}9mHnwwi|bMU E0C%K*Bme*a literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/image_compare-light.png b/testdata/snapshots/darwin/image_compare-light.png new file mode 100644 index 0000000000000000000000000000000000000000..53eb4124d4c096d4ee67b3185e331319e6c99bf0 GIT binary patch literal 3606 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 JE5GIv{Wlr*S6cu8 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/image_cropper-dark.png b/testdata/snapshots/darwin/image_cropper-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..e7e23fe166a325cfc54c24d5443fe76337c8c741 GIT binary patch literal 5969 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/image_cropper-light.png b/testdata/snapshots/darwin/image_cropper-light.png new file mode 100644 index 0000000000000000000000000000000000000000..d4273bb7a986ef2f7452b845768ed24b4e591920 GIT binary patch literal 5790 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/image_thumbnail-dark.png b/testdata/snapshots/darwin/image_thumbnail-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a4d396f1f23907c7b62787b58b28c54498419730 GIT binary patch literal 4517 zcmdT`i8~Zt_aBXh7`vDdStEP)b!^38kR?m9g|a1-eakR*V@*g5l6{w*VGOBc-?zyc zvPDRkclxfszu@=0?|trbo_p@S&$(y$oO@2Rfu1H61q%fL0HA_tX&3?k7s!cgU-An? z3gOP41pw$=VH&E&zOTN`-P3V30bus(kAw>4H!NogUlplem47DxG~oS(OK%y`xxMfC zzv2R;zA7A0`Ns^UlWd`BY&aE$!v^`uMX7Wdb(0)3yC8hl!aZ~=FtOk~;S>Rkof`(zx@Vh8C zA3mc>?<2_zh!ovQ_p~ELefXo9?4hC*U6~qvvy>C5=!Tx{4u9UuC<`?gh=xP?@>!j| z6D1YT#%X&s6tW_kepXxdteX11n=B{ek+rNTqY?*;EC|V|i1UC9g+Xw+X!|tk9A-+ZK2u_ri^rg%`vC>X(rWZYmdzRW1Te03e%V zX5<5DQZeFbZkW>zq6<&Sh#P;f&wsOQkzY7ioyiJR>1Oom>nJ$K-!)JNaX>;zAfaC_ zh^d6>@mNOR{^hQ8c-o&OBQL+zLGXff7zzjxPRx~|)nW}xem&*nzvCiF23#MKps@;R zs9bPznb|x19vh1rgND;i4EsO_w_DHDb_Df(+II9logO3nvp;Q!9)6ZAEEkMjI#LoH z5Zo1W0fVM%ko4rLZd11OFA9Y(6&U9~j(e1;+pLi^?Ie|X*D1}mBZYw3*IoRRaWzp_Vl(Xhj+GS>U#u zGBXBX0}wmD3X!gWEtnWON@hV%w`W$jjX+7E}YIR^`V~mK#jzg@v}P|MxOZKtSTQy4R6_>ysOa12oI~ z9s|WhONe_O+7#0ND&By>aP@UZX+>ynvAbDmfNIUrhSzUv)M(NF^)LXeOpdfcNAZwr zI&RQEb2?>#(I(_{sNSWw=lzQ$yF2pwnXF*|icGs^zRFBQmmmnC&wIaI3qRl+@f5L> z%XG}Fo_4KHrgd$s2ni%yZGZLF3>G!!IHD^t3AhKVN+bPEmc8!56sgy&%)hnOn31uc zYBQDAyFXp7s4|Gz`dKf^&FAf=E3_?lt9r^OBH}PUL4|~uKX>^?F6r;6u|U|2b7k3L zuzUK_fg>}5c*DzAGA8k(MpJV7Ys-tTjfm_8ksok((Z8)n3_RylHq^F-7_jLD7BHfY zW2v(hO2^loJ@*SFe**=^U62oU`WVq@~fK6c?!&v+id;QO+T0fLk!}%?OHSjhyfsX zr6DTU1_|m!)LcqYh%e|GiLFU;uKrA2J^iggOG z^-wh&4#UbAJyu)v!fkrc{6@+ja9KZeqH7@$sJBq` zy?;MlMEUTjZ3)c4P8;Rcz$K14da5^H-PswPam5w!)I`fP;y3w$dumeIj7`GNBPBE2 z?_7thZUh>%X7j!=_wZnf{qc)3C;-JqeVJ^OaJaXo{EJjS!$qL9V1SX4FI@8#$CY40 z7B@vb1!tXzNQHEz3g4ym<|4eu>e)_VL|2=>VgzkTssDk>K!(12LdA>QW2?+ONKO8V zVkiN<)M!UL@Wc4oc+iTIOISqLYqa2x?{~Kj4&r0$%*s_Sbm}9=lc=rI(M-uAxk?s1Bp1_x%VI1ub(&C?dE6_TnNJG^8pi7 zj9)7&b01&dr^&_>b+VPUU=4B{GF%(cngaT#B*>6ptyjv|w!}fKHB+?OQBi@#Ws34< zb{ra{s`%&$-V`k}o}YaZGgTxoC;!Xv(q~3-swmn_DHctp@>9C2Y-QtcI4hW(GXYUG;>?cuWPY;{G#l9CI%gaOXlB)U&-Bc7ygeQw21&oQk$X}&xmJ5=~zyK@}pH-iU zjj5NAaF+~0k2))t72{U@4B_x~c%kr))a0tc&51ZB9S=|KDuZr5SnZfLy+)K-+}i<$ z=R5dJ-D`|2*Y0NLbQ!HWxq99d!eo%GG(xg6XWNR0A0$mcdK_yb$Vd-R@m%3uzz~yH zY<6JU2cZyPH{?{l2R|e$^rFvIJQL13QJ_f{K;Tu~sYvYf% zltvJi9O$7Ai{r7^-1DcyVMnqvr6EFhUGxIO67&2c(@0fYtJ*dAl15jVwZrp>c=laX zd}iHbnfTH;H8s%3Z1P=K9%sDcE8EAG1)cUAtXI$OTLr86YN*-`yBpqJVh#QGORKU+ zbvhH;cTUE4e1oQk&Nq4@mFJp+v?MA7pZQob6X0MMOt| zV=)sQW=C%;;3h?iaSfWHIj-I54KRJ^VOO=+TMu{D?7&|^;e%u?n^m0;p)ZPGu!kFr zb9mce!6^P#Z9DBW+fx2vzWJi{JYP`t z4jwrtY-*>N&|S0PKb1ci7U5;Dj4tU8Mli`eupFl1 z>;Z^_qQq6=NbJBm@#3K>A4UEF=|9cY-@V&kP2#`oIW>|{?L$_22j~HalyL*cYQGUN z*{t>56+T!UN)g5PP23^H#rl3z%~4lPY;Np-SD}>+)7Y?drZRs4_o-cgri&>#upA$6 zvE@M+5q1XP7*%n85H9!spFt9su?wgOcg*DnW8cjOg3hZJOg~1>y_~R5h^)WPybV*D zjB@+AUr>5>LFk}=jTW2kV!Hh~IGdo}Q2{BHshp3146BUIVTN|vNdCb>g$iFxj!^x6kcEm@ci=n^nF7m@+DPG-8i;*^JJuVK={aB*cQS8 z2jven%=jG{i3w~J#$m3`Z{5|Z|@sVOZ$G1%S(s*J0CXF-AA^D*S;yqz0NL(FnQ%l z7|(vX6W4hKApv>_{tS5~F67+<0EvZ?fNcOk2M{K z*;ku7TXaBOImXJ;itU6vVqv^x_|2g6&BJ0%N9D5X85w2{DvqC+N~_540Ghe*=cvSWs%Q%5qSYl-8<8X`GI?^gB#enarGk^*++@0{l| zGYLH)J3%v?j`Z7o{1((olXpoN-@NJ3_$Bh~wJm!?%n|e-&-VoyQm|Xyw02$rQ;|oS zP@s@tRV$rJtPM9odSnHkK2VbWj3<&gqK&bK*6zWXt<1ah(kyu?Y|rKnhaSy>My8EHXSFVch9yDXVG@KDj~ zmyx+gUfG#^1tZ6Zxq}+x=)(-Ym?`i2q%yq~ZfWt^ z(UXtE5s(eH?^2)`)q|V9Aifv|*DoddGA?>kZ-ixx{-iP}a$*&5VOBAkx~mF#Tu3gE zgCdu*qL5m1jOf_5^2@20i`B$Ri#r6{NXv_-4UjEMDj&SyKH5v_h}-?HoM8%XhAbMh zRHgc-qp;;DLzlahMt3P^i~v+t{*0Y(qzcFd3c{lWNXl=HeDOY-0AST4WA!#9@wUJU z6!?W^Feaf(BNw6=G^kN`)ymQNDY}w|2sfe9}%s!%ekSUIu%mJ`gx zhWT@d%<3-nTRc?6R1ib6ytmVG5F_V1mOK7E(9HPtY zN??n7Hg1A(eout7T{DVn0i27F znuk693-wmJ0scd5X)UitXGb9B%0&6*rEuOiV$`&0$#)$k!dToWr|CK#a6g8G(lt+E zn_6};(Ft~N%8bnlrTensvTY@;)rZ%H=*sHO(CsjG>}3Swub`r{C?ejygZn+95C92Hcqxk%`Ds6>LhCu1rmXqk6mkcOgR-Db(af?qVzHCz=?x279ttph}Ekc$W zK-AMs(lpc;)#w-`@t7Dj(U9*A8+uaRqXGf3!%^?dl9Wt^1Bn5;iV3&MHLI^6AG4B3 zwPB!#sJn{fmOnCrsNdF)lRK}z6k6jS>}e?)m)kfF)sd?hnQd zcGm_mSn);bgZTo^t0NH+fi~v_oOPW(EA7^G5ei=O9+-{g7cMmEBo7oEAzVj(2j#jS znK&+8;j=e}_LoUq{Tf%KP!duD+Gd*OGMwR(jH0{f<6F4>SA>2kvwl*!3f3;+W|a8L zP`ZNmBSs{RML%btq6t6aA}5*b^i=9q+2e{sIwS8)Cm};6B|2_gQMjL(`2%W3(aFP+ z+FN|{Dm_A8Of-u^;Fp`wJ@)=pcKlOD^g@?$O3V=YP<%a7!j@${c^thlS^|cLe+0nE zE>j3mnbE&-6jv2~9kjKy(ZXelXP74oFK}idWzL5yKyo9G2@Q)weKeU1fTQ&fjvr#i zwR^liEWmQgC-mBJDVRJ-PWYMfKQhgeHd<}jZ!@7o(%xIWvyjk)>As)7woI)k%SRVJ z2Qp8Rf;Zn)FCKE(4A>TwuiRyw>xX^~qptWJPHV83Ln2s9aBMAsDt8cF1Jf=&Cvud2 zGdcU-(v+9=bRsFA_eSQIxAb`vweZb4;&fhd*|lcLo_kL-Gy5k4H|;@SErG)8Idcz0 zrJ+OO>9T%f6N*Y|=3_!9yBW_c&Uu7YdAS8>^+}>>Y}E&63bsebmZIDp{ye?YR->Gs zf9?KmT0x@bF3(59WxE;uy4(!RA8Z=OtqH24bHo+7=U8`r9)~Ik)`c<}Q?+`5_r~_# z^-d!a6v=nv4XO;;_fcv@`Ptgs6DlRw49xO#ziES`@zYt))j`Wcxthx2b1aryhp%`__(a`FTT!+#bv`&3O_U6d01+i}}kuhXrNk+9dHEtj{jA zd<~gY!r@+?oA`E2j$(KzAGx89XHQWj+h}|LUNdu}htSH;jv|&kYQyBKiq&6550``| z?;8>lqrS}iK2y-?`#$cxebRBw*8>CAZ|@qq$&83S-FUdZw;7K+uRm$0K3tJ%<8O5B zOj`rtljjGG-rYl3n;#L>qjaX4?Lcb!+3J zZB+PGd)*KfH@@c_BmNpm^N&^)cPSuzg67{or*NIdS5G#OWe;F8U5;ogl0mF1lZqF< zF@N?}dFFl10wWuJg7^k7@22_#X4B?WBe>(v^z@Zlj;rOcyR4$JK^(4{_Doqk=HIvwQE`K?e*0qA2$7oovQPY3C zlN@Iafr@=1oRuu)vXM&H(`pe_QrW$nnOE2ImO?bhc+Pu0It|y(A zQ_hDR@dU)mO3J!2=2HAbd5^he2zFG?Y-g>EBy5M7)^88{f_;S$Hgge);&T^ zqZ2bBThCn;`*Z#8^@rOFR@QVcCMHQ4yDAadsq75G*X8cOB79*C4$*O(b-ADeXA{4v zSEtLOsW_j};ZJAkWn2jIbHc~muey%LSdQ{_RxdV9>AbXCR^x&<*nHhY z_6Nbz@gMN3xvvR5&<~)Ga?mK9d&9TZ3wUDC@a#n}Wt-*XedJU4{Ng292KMH{@4;d#0x<=3~ZMoFU0ZRS5MMD#OQi>Rb`OOF%RYTsd%X z-@BCgG)x+qcT9ZuIp1X+WOcQRECFeF>#zngE}s7OU~JW2VF`2TbK|I?oR z?$Z8g)|w+0LbhfU+=uU8ZMV)Jh%QSbTqd&^hgz>tcw0s5#(wAu&msb@u|t!S3-}|M z3E`}^s-J~b<5;-W2A7FV5kc9ym3e24IW~Iq@yg=-R38g~mm>ZjE=<_&(Y#2AQNb!v z|5e%80~~fet6spm)%#E%i3(k1*#O@ooci`)&PCpBbO-tRwuYW{aa-?B%a? zmFehit{k7rbtYx5JC5yr3q8y2TZf9yRA!rv_6@A3mlL@tr+bSzfids>B)x!IlpDW@l<@VIqIG zHu&!b?h`kwYPFr&b=a5Iq4>eQy-x%E!$|xiIQ~PP5FX<~u$5w8J%v}-pM5V{UOSo` z+y$FsE>PJfh!eE~%&IO>iG`BUTLCD5?STI}lLr{g1c(=zKANO^OHcY|0syP&s8*_2 Gh5sL#t@0ZH literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/lightbox-dark.png b/testdata/snapshots/darwin/lightbox-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..05e90336336b9807ad788e5f97289e8e5344559f GIT binary patch literal 6197 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/lightbox-light.png b/testdata/snapshots/darwin/lightbox-light.png new file mode 100644 index 0000000000000000000000000000000000000000..284b8e6e31b572bf1fad486417af99bead38ad83 GIT binary patch literal 6272 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/mic_level_meter-dark.png b/testdata/snapshots/darwin/mic_level_meter-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..0c478e13a2a7f5e9d651b3f4c51b2b959b80e750 GIT binary patch literal 3704 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 iQvmw^*&+Tkln!8D$N#3VTR7c0A%6$z!m4=y literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/mic_level_meter-light.png b/testdata/snapshots/darwin/mic_level_meter-light.png new file mode 100644 index 0000000000000000000000000000000000000000..5e2c50d11328e3744303a5a32c3d2a4da950d289 GIT binary patch literal 3654 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 Y0Mf_LC^5e^x_cbEo|X~30(L**pI5-6!2kdN literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/playback_speed_control-dark.png b/testdata/snapshots/darwin/playback_speed_control-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..13c007780c302b5403e5dcad506870fab7ef2f9b GIT binary patch literal 1584 zcmbuAX)qfI7>1*5>ZrSovyF<;?mCOOSEwSyEu=~*rLLxwqK>*1jV5)hGoi&$O*WL$ zy6;xQrg0xtK^&m z4cDm?9TXrl0RSM|%;>s(7-3~H(gNu%c6Ob;eQ|)>qDC=G&1k5~@+!Y9=DgQX`eN5J z9i{4D{k|ECyF&T{H>$NoFR1u0b%`aY^(yI@X<+%iRd~!D<{)1w##ou)*bi=Ghd6rn z?mAxp`qi~u7_D3C2fgrOMrS3H5FLO#W4mh1H9$|V;*144{!d=;o4W~sWo1sC1p;|j zSS-0r4j(le64mQkJ|-Bn|C&}U;Z_So*|Zs8-<#fv%mN9*wQyTPdN&f1Vbr(aWsAYd zNf42RG&TxtY$h&Xk{c!E0VqlL8J;jUNRX4sN;oa9*wYq9h`R#K@AEM%;l}>UV*TWN z1KFbupf7$^UQxH3hq|$~EV|y)>-Da_-0`N1i}{yrJ5m>uweMQjgJ^Dlm_P+Aze%2F zv9bwuZXI|JtjS<*9~a8Mr}*g_4TJSN@QEF6@Y_lH!5NhDiz zXMgg+&1U43@^i0STRTVZ_!Zn%(!?vGD_7HIfgdX>CLx`jDc>JfpzJ{6;OyG998PPG z*kSIs5|UIb)=T5?wSrkLlQ|mDJ5nGlRBG36PL@+{eWiyI`z>gU`BK(N0cB}L*PQZt zV~-IZlsR*qO9D2Rw6W0iLfEp*8Lhc0Ldo>(4Wu#cWkDRIE%#bgwK8~@1)jj3cvktC z6)I9*Q^V*h`lhV;;KRf!ozAFOQ-w?wmQyG)#mXA~>}`9TlxA5`k+c%5zHC=@!crH0 z_kwyjL}+z95gaD+_FOusa}spe0&*xjguR377$`Zg2=-8_p z@3);ncV7}dd1znj>fl{i6&lq#j4b8CUznJ1wy<_?-+E%Zk@vma4984?<~PYjg_u#s z-yl2u=}iu(=xD@Vn63SBjV3;2Axcahvy>=H+O#gzi7JD7JX*>~tj{NWTOO?n{pv7c zb&PZr@y-`9R2(sRH;bcB#Tb0>rwR5qsvyUcf;a9uWVPt{-dZ}S0lo7!)}7*jvW^1p zEa0S4d}bH^TuFdqtQS+tTUy*_7+K0KeNw~*oE(G!X2vZ3k*gosiBr(H@9e3HOF?Vs z%GZcJEr!#;-~;{pPWvO(sm~L&(@CvgDPCG0A#>u(teT|Xp-W4=At7fqZX8LahitCF z3;O^fZX7?M2T>qVKLuWN)8k5=)gn=M)2;$Y>Th{XGGBbBc$p%#aLY18K9j*#baECu z8%0kI1{Jl(f%k}?MOx%CKz;IPk4nMQC8g4x()Gt_{}}Oe=zqL~03Boa0A$kGt8ITp R;7Jnz%#5v!Dh%D?{|1Nm;?@8F literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/playback_speed_control-light.png b/testdata/snapshots/darwin/playback_speed_control-light.png new file mode 100644 index 0000000000000000000000000000000000000000..0db46878b9d6832a2ced5249a6ca76d54c5e9470 GIT binary patch literal 1520 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/playlist-light.png b/testdata/snapshots/darwin/playlist-light.png new file mode 100644 index 0000000000000000000000000000000000000000..7fc92aaeb682e518db504f9c22b10c76e1123d0e GIT binary patch literal 12010 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/screen_recorder_controls-dark.png b/testdata/snapshots/darwin/screen_recorder_controls-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..925cdf88f0e8a30cd245b2d57ff82c9b936f2b64 GIT binary patch literal 10125 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 T=CbaCH-wUrP!z8fH4gbN5jgES literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/subtitle_editor-dark.png b/testdata/snapshots/darwin/subtitle_editor-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..00ed59948c1454464dc50e119096c45ef261310d GIT binary patch literal 20314 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/video_player-dark.png b/testdata/snapshots/darwin/video_player-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..2759883bacfe0018892d0e31dd283e9260385b16 GIT binary patch literal 9864 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 KDpUe3g8vU@dJt;> literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/video_player-light.png b/testdata/snapshots/darwin/video_player-light.png new file mode 100644 index 0000000000000000000000000000000000000000..1817b4d9f1fb42be770edd1fef391f1435c7b98b GIT binary patch literal 9732 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⋘vwZT|3)4{Cb!NSn&CrSeEB+in2;`Red-2_D-AKbvNYA zvLtiS@;AOmZ@XGunz*i`WJ9-{_0o`oO-KncmgPp}=Fe%*&z_q-*W5b4?B1I_H%A3f i!=v=??7Qn38B~5f4P&ghZwD+z7(8A5T-G@yGywq1Yhqvk literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/video_scrubber-light.png b/testdata/snapshots/darwin/video_scrubber-light.png new file mode 100644 index 0000000000000000000000000000000000000000..52f3ed72c025d1b2593e3a19c903e60b7023f3e7 GIT binary patch literal 1002 zcmeAS@N?(olHy`uVBq!ia0y~yU|a%Z2XHU}$(vErZZa@1Z}fC=45^s&=C)zBaJ~%t zhttJB)kSWJe`FV5zNON8 zm(rN$t7T~CcQ&?5u(oLa`^|qUUX(QQ|M|5yTTbpxx{}i8c>?S=4)T?4XqJ7Gz-~Q+ zn6XYbOr7ra7=xXCR=uqE+M%TCM9uU6yUoF#G0(rzyX5zWPj8Q1y{)*V;<)v_&?<3{ z=^IM2@7_()wDt#kU@w)oF|<$G3t(VL)``SMtM`JTtIOUoNeR(b=q ze$114&-C({gVnu{edSZ{ney>}du+4$PV7z@_nD5f-i9r|esj&+^LKPr{oyY*O9a`wh! z{{-KNh}17#Ao2h3y34ywWyG2fZm(G0d-YgW^45)-TQ{m74gCMVTij}I-sZbXvM)W# z)m|n{7bp|GH?gl|iS|Ukvdl#Di`JKbyr-8A>RG<=`v??Qj$K;9)z!k)b@_LfdH?pX z_jeV5TEq2Z-&{KSZh3j-J)OQ^OO$0_o?7~u)s-nez{hTJo!OJ01qCwsE-6V(@p>2I z-yOG91nM#GE!p5LYb`j_3^`$WGwgo<=2{~#fipBH)W3E-r?g4gdbpt7d*4Vg^b|gy U_4u&R8ju$~UHx3vIVCg!0L%Bu3;+NC literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/video_thumbnail_strip-dark.png b/testdata/snapshots/darwin/video_thumbnail_strip-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..d05c3b619a350f9e89bfd5d0ecd8b7efb52dd30d GIT binary patch literal 3371 zcmeHJX*3&L8cu5qqE(HeC?V9YrKs3Z(=008}h8|vK(%UPSOvUIc;V%_xiiQxLs!SADh@3=pFM&3~X z_7VrmonVvNNVQMIdzfYVSS$VJ)6J6x0kU9!i{{~Xf%=%(MWni(!$LCqh%Fm(i+Svk z*puoMI@rz&4iytqqTax8rA9MDMNhGt>YnELA4_fC=*q6O^0?;sax`@ZTzri!_id)?J_ghj$a7KutOZCn)f)y!q#91!ko53!J$QU|^fiL0idmm=u|S@op-tWwu6;q} z*T%(&l%tD8FCwsO3>PxRG5PZ{GKW@dCk-xY`y3X;ugWL_Y&>mqs7Ly~`tHI=sWnlD z0#-}oDU-^|3xoq)z<1kzd!2jJ5~!YjLbkosTdN^97Lx@O~(#<2B| zI_QwjzJ;DjlYgo%S*TFfBL7^nr(wacH*+DJ`N3D{Me;M_Yor)sHP;W2Y=R+U!dQU+ z?OduP9~Ar!Xe32CV^pywxks`zgmxUX&y1U>gv>lVhMT@;j@RXBMPp#dIAcj8@#mrx3|?JvPX*u+m1+yA0Q4yVs%Zqd19F%djI*b&hfy;bTjt5 z=wns@p!JRM(s9w}eKwJH#>Sm{d<1D|R zw)!>n@Dk&>@K!ID4oyht{ zL$Q&V?Jw=z3(uFs@qsAuZ$Q1abT+4CeGM%_~6N1`is)`49jjSAJx4wOm&c=P>*(c`1kzB zqhH2rlFKH#6T{_aYs?~XsJUMq^1^OAVRmea!uCjM&qsvt`XQaCsiM#>Ft*oTTgEhP zH_Ggxv-RO_4c>e@VR?3_uz%O zq_k~oTxfX7$n%ijamCIP4Tp)pHkQgX+wTW)GRJJMKWMCbe^;?FbUVo)mb*CRd4FQr zgqsoY9R0@eZk*0r&Etg~ymzp++lZxIo|2;eGm1kLoZPX+g3KMuaTnNqKD|w`|pYtm2-+R?vp|Wn;Uu)k=!~3OCJ&?oSdUf}DOe25ZNZ zT^b zIINBK^nC$TfImMqKY#vAWL|c9o>BO5dkjJSk)!I~T1QZpq$KFlN)~#vp6prZ>oy`O z`#R-@fFMy#;)mseFHAtsZvFm(bQX`k-(7j6aCSiXHfgXu7Rd}MsMa^-#=3GOIC=>3 z7Jk2wb-MFKMZF)@$8@|&P0>*b9C|Ifk^5eY>k#HkWnIOT>EaLh+-rLzmY(-7*e5?p zJn}m}CJ(%L_s5x~W3y2Pm182^>Pr$?iH2hK38j+*;bcVG?d-Bd&ZL=y7qj&dk+ig? zkt%iz*h!_Nrnv{^?_#v+n_dy?BP>Z=O?>#2Z0>R#cR=@;oukmHi(4sqC`4_+De5Jv z;Lr>okojoWO}3MTRf}(Ga_BGpBm+hlY|Xu!@~dL?HMn0wLS12wdycCXD^*1#3!VS# z-^lJ4XA$DZNg%x2GqjQb61sn6#w)m5s3n!z_vxT<4QIa2;6(#L~}{veC|R z>^4^O+nrkXohOQsTR&@Wv7CbiTnOz+yvmQv)~Ke&A9d}D9F+e;Gr$`a4g5%7D?5Q| z0E;I%ihoUJZ+*!KL~b-3g*3z&Ptej%6}`xdAp2_y&x7Btdu9`?gtTdh5}B3qSD2nz zA0N+S=mWI#%yJfybx=f~Ax@c=Uz;(;j+NyNA$9r38kk^i{A111{Gmk#OiFuSwxABO za%f}fcn%lD$NE!C7MMWS_abIazdqH}r5aQX%FcQ962B}$)Y6LjKL?F7izIs@Zf%intrT9bD@_QVsHUVK|GreXL9rn#akG(SLWd-&VhH&{Bp04#xH0dHbKP^Z)Jt{_hA|z`jgp0<7gLmMB$0 RKn(f;a3f2@3Vl?}-vEq%&@=!5 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/video_thumbnail_strip-light.png b/testdata/snapshots/darwin/video_thumbnail_strip-light.png new file mode 100644 index 0000000000000000000000000000000000000000..24fef2cc0f2bac86099bcf2ae3522c8e363b26a1 GIT binary patch literal 3355 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 a09aTNi@$K_d$;};fb&Ur2j+=@lz#)g=lr$+ literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/volume_control-light.png b/testdata/snapshots/darwin/volume_control-light.png new file mode 100644 index 0000000000000000000000000000000000000000..1930be30a74bf9d9720fa2efa56fb5a5a49abfcc GIT binary patch literal 2182 zcmdUxdo&XaAIGPa4bw`hDP0y5Jwmg0x!;Bv#uP#{mxvgT+ndY7G;)b#&22;G79N+^ zLl43vmym|o`*dnCOGs%8WA1ysf4zUc|Gw`z-}5`4-#Onue&_tYzjJ;W1P83V>?v6Q z03eUEvAhNVNFChgeDHz&+ScMz1^|HZI7@TqnBpZa(f+23a?f&PSm%gATN^#k`D(#& zk^czF2Wq$eJdLgy?~b1TK z?jWp(APuwdE4xTEcE53~D{p%D>2Aa22D-hqL$VYE@$l8oK*)CYk9WIRHV=J+0K)y^8)n@wzxH2K!~@x6QmE*7ceezjnnq(j@o_nJ=Le)AyZ{qC8NsH z@!n%$Y^hMcRR8uHLvZg=etvRE7OmQGI%YMsYs)Z8cJ}QD-2k0CGhgMfeUm<$(7gL^ z2<3VARmFh$Nj&-_*7!BD(=$L6oW<)?zOWsXUV`q5{4)LBBepbVOT?!6n7=bKn}PVy5{Z{ZnF$BYVeJai_{+o= z?gqHBv(D~t5G{~a%ux$R*J_TcQE%Rt4A(@b# z<0N1<8iy~s&0VxtbK(BXka#{S#!zf!ya}m3!B89Z?t?lt{Y`X`syY=QJpkKVl#=;f zwJFK9HEAAv72B@g%X)QGKmqkdj<;Uk_w<+~Qxa0y6RnfKjF5kRsO}vzc{QU5u}IG% zEi*HhneJwWky3cQi~r>|G48$_nXGNOjQWQ_y+i@4MYpr5$u2mPi^TMXnv?V8Z+>qJgjqaynLX$iECTZU>c7&?-{BVR0{)`|#wacH*bDmWdaOqDtLDZ?-mhZX zbhGT3O83eA!Jh>^)B3{=>m5`?jos9r{jhZzZu*S=rQ)9r>_BUwQg*@I7j!B~fm_)d zLVGfjFi46nX;`Uov!0X(A?;wawHjlMRE8E0<{s)UHp~A1Rakb*We2g zs;#qRlT%O2L5Kd`pF<4YK!}*0Py@tH=fOBa3#de4BHs)uyPmU(t)n;g8F?fu*p}>U zm=5wI;&wZECqGrEu%h`N^B7{{X@SrkJUSFh-VeSl}H9*`-!*lT)oEI$}XI|zr zPrqJVoy&`c4j+Tigu{1>oNETq8Ki4ktvD+s%ycM|hKSh>TUzShq*xD=%`tP;I9H<+ z4eblf?}d@=#fy7V2z6)5=PSzNK!m!>fh#+Apt(#BnTLZpS#bP5ddocInN`0m-CLjJ kGqMA02@MC~{pWyyTjDj}0|mX*{r>`hvvRO(wD6|<3l2@jFaQ7m literal 0 HcmV?d00001 diff --git a/video_player.go b/video_player.go new file mode 100644 index 0000000..1c115b0 --- /dev/null +++ b/video_player.go @@ -0,0 +1,162 @@ +package mujica + +import ( + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// VideoState is what the caller's playback reports. +type VideoState struct { + // Frame is the current picture; nil shows "No video". + Frame ui.ImageSource + Position, Duration time.Duration + Buffered []MediaRange + Playing bool + // Rate is the speed; zero means 1. + Rate float64 + // Subtitle is the cue to show now; empty shows none. + Subtitle string + SubtitlesOn, Fullscreen, PiP bool +} + +// VideoPlayerOptions are callbacks; nil optional ones hide their buttons. +type VideoPlayerOptions struct { + OnPlay, OnPause func() + OnSeek func(time.Duration) + OnRate func(float64) + OnSubtitles func(on bool) + OnFullscreen func(on bool) + OnPiP func(on bool) + Disabled bool + // Label names the video for assistive technology. + Label string +} + +// videoBlack is the stage behind letterboxed frames in both themes. +var videoBlack = ui.Hex("#0E0C0D") + +// VideoPlayer draws the caller's frame and reports controls through callbacks. +func VideoPlayer(c *ui.Context, st VideoState, opts VideoPlayerOptions) *ui.Element { + if opts.OnPlay == nil || opts.OnPause == nil || opts.OnSeek == nil { + panic("mujica: VideoPlayer needs OnPlay, OnPause and OnSeek") + } + if st.Duration < 0 || st.Rate < 0 { + panic("mujica: VideoPlayer needs Duration and Rate >= 0") + } + k := Tokens(c) + u := Density(c).Unit() + col := ui.Column(c).Radius(theme.CardRadius).Border(theme.BorderWidth, k.Border).Background(k.Surface). + Clip().Role(ui.RoleGroup).Label(videoLabel(c, opts.Label)).Disabled(opts.Disabled) + col.Children(func() { + videoStage(c, k, st, opts) + ui.Column(c).Padding(u, u*2, u*2, u*2).Children(func() { + if st.Duration > 0 { + pos := min(max(0, st.Position), st.Duration) + if VideoScrubber(c, &pos, VideoScrubberOptions{Duration: st.Duration, Buffered: st.Buffered}).Changed() { + opts.OnSeek(pos) + } + } + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + mediaPlayToggle(c, st.Playing, opts.OnPlay, opts.OnPause) + ui.Text(c, mediaClock(st.Position)+" / "+mediaClock(st.Duration)).FontSize(FontSize(c, theme.CaptionSize)). + TextColor(k.TextMuted).FontFeatures("tnum").SingleLine().Grow(1) + videoButtons(c, st, opts) + }) + }) + }) + return col +} + +func videoLabel(c *ui.Context, label string) string { + if label != "" { + return label + } + return msg(c, "video_player.label") +} + +// videoStage is the focusable picture with playback keys. +func videoStage(c *ui.Context, k theme.Tokens, st VideoState, opts VideoPlayerOptions) { + stage := ui.Box(c).FillWidth().AspectRatio(16.0 / 9).Background(videoBlack).Center().Focusable(). + Role(ui.RoleImage).Label(videoLabel(c, opts.Label)) + internal.Ring(stage, k.Focus, 0) + if !stage.IsDisabled() { + videoKeys(stage, st, opts) + if stage.Clicked() { + mediaToggle(st.Playing, opts.OnPlay, opts.OnPause) + } + } + stage.Children(func() { + if st.Frame == nil { + ui.Text(c, msg(c, "video_player.empty")).TextColor(ui.Hex("#BCAEAA")) + } else { + ui.Image(c, st.Frame).Fill() + } + if st.SubtitlesOn && st.Subtitle != "" { + ui.Box(c).Absolute().Left(0).Right(0).Bottom(16).Center().PassThrough().Children(func() { + ui.Text(c, st.Subtitle).TextColor(ui.Hex("#F2EBDD")).Background(ui.RGBA(0, 0, 0, 0.72)). + TextAlign(ui.Center).MaxLines(3) + }) + } + }) +} + +func videoKeys(stage *ui.Element, st VideoState, opts VideoPlayerOptions) { + seek := func(d time.Duration) { + to := min(max(0, st.Position+d), st.Duration) + slog.Debug("mujica: video_player seek", "pos", to) + opts.OnSeek(to) + } + switch { + case stage.Shortcut(0, ui.KeySpace), stage.Shortcut(0, ui.KeyK): + mediaToggle(st.Playing, opts.OnPlay, opts.OnPause) + case stage.Shortcut(0, ui.KeyLeft): + seek(-5 * time.Second) + case stage.Shortcut(0, ui.KeyRight): + seek(5 * time.Second) + case opts.OnFullscreen != nil && stage.Shortcut(0, ui.KeyF): + opts.OnFullscreen(!st.Fullscreen) + case opts.OnSubtitles != nil && stage.Shortcut(0, ui.KeyC): + opts.OnSubtitles(!st.SubtitlesOn) + } +} + +// videoButtons are rate, subtitles, picture-in-picture and full screen. +func videoButtons(c *ui.Context, st VideoState, opts VideoPlayerOptions) { + if opts.OnRate != nil { + rate := st.Rate + if rate == 0 { + rate = 1 + } + if PlaybackSpeedControl(c, &rate, PlaybackSpeedControlOptions{}).Changed() { + opts.OnRate(rate) + } + } + toggle := func(icon *ui.SVG, key string, on bool, fn func(bool)) { + if fn == nil { + return + } + b := mediaToggleAction(c, icon, msg(c, key), on) + if b.Clicked() && !b.IsDisabled() { + slog.Debug("mujica: video_player toggle", "control", key, "on", !on) + fn(!on) + } + } + toggle(mediaCaptions, "video_player.subtitles", st.SubtitlesOn, opts.OnSubtitles) + toggle(mediaPiP, "video_player.pip", st.PiP, opts.OnPiP) + toggle(mediaFullscreen, "video_player.fullscreen", st.Fullscreen, opts.OnFullscreen) +} + +// mediaToggleAction is an iconAction that shows when it is on. +func mediaToggleAction(c *ui.Context, icon *ui.SVG, label string, on bool) *ui.Element { + k := Tokens(c) + b := iconAction(c, icon, label).Role(ui.RoleToggleButton).Selected(on) + if on { + b.Background(k.Selection).TextColor(k.AccentText).BorderWidth(0, 0, 2, 0).BorderColor(k.AccentText) + } + return b +} diff --git a/video_player_test.go b/video_player_test.go new file mode 100644 index 0000000..006b3dd --- /dev/null +++ b/video_player_test.go @@ -0,0 +1,120 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +type videoCalls struct { + mediaCalls + rates []float64 + subs, full, pip []bool +} + +func (v *videoCalls) opts() VideoPlayerOptions { + a := v.mediaCalls.opts() + return VideoPlayerOptions{OnPlay: a.OnPlay, OnPause: a.OnPause, OnSeek: a.OnSeek, + OnRate: func(r float64) { v.rates = append(v.rates, r) }, + OnSubtitles: func(on bool) { v.subs = append(v.subs, on) }, + OnFullscreen: func(on bool) { v.full = append(v.full, on) }, + OnPiP: func(on bool) { v.pip = append(v.pip, on) }} +} + +func videoTester(st *VideoState, o *VideoPlayerOptions) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Width(640).Children(func() { VideoPlayer(c, *st, *o) }) + }, 700, 520) +} + +func TestVideoPlayerStageKeys(t *testing.T) { + st := VideoState{Frame: mediaTestBitmap(160, 90), Position: 20 * time.Second, Duration: time.Minute} + var v videoCalls + o := v.opts() + tt := videoTester(&st, &o) + tt.Key(0, ui.KeyTab) + if !tt.Focused("Video") { + t.Fatal("stage not first in Tab order") + } + tt.Key(0, ui.KeySpace) + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyF) + tt.Key(0, ui.KeyC) + if v.play != 1 || len(v.seeks) != 1 || v.seeks[0] != 25*time.Second || len(v.full) != 1 || !v.full[0] || len(v.subs) != 1 || !v.subs[0] { + t.Fatalf("calls %+v", v) + } +} + +func TestVideoPlayerButtons(t *testing.T) { + st := VideoState{Position: 0, Duration: time.Minute, Fullscreen: true, Rate: 1} + var v videoCalls + o := v.opts() + tt := videoTester(&st, &o) + if !tt.HasText("No video") { + t.Fatal("empty stage not shown") + } + for _, name := range []string{"Picture in picture", "Full screen", "Subtitles"} { + if err := tt.Click(name); err != nil { + t.Fatal(err) + } + } + if len(v.pip) != 1 || !v.pip[0] || len(v.full) != 1 || v.full[0] || len(v.subs) != 1 || !v.subs[0] { + t.Fatalf("toggles %+v", v) + } + if err := tt.Click("Playback speed"); err != nil { + t.Fatal(err) + } + if err := tt.Click("1.5×"); err != nil { + t.Fatal(err) + } + if len(v.rates) != 1 || v.rates[0] != 1.5 { + t.Fatalf("rates %v", v.rates) + } +} + +func TestVideoPlayerSubtitleAndOptionalButtons(t *testing.T) { + st := VideoState{Duration: time.Minute, Subtitle: "Welcome to the masquerade"} + var v videoCalls + o := v.opts() + o.OnPiP, o.OnRate = nil, nil + tt := videoTester(&st, &o) + if tt.HasText("Welcome to the masquerade") { + t.Fatal("subtitle shown while off") + } + if _, ok := tt.Find("Picture in picture"); ok { + t.Fatal("PiP button without OnPiP") + } + st.SubtitlesOn = true + tt.Frame() + if !tt.HasText("Welcome to the masquerade") { + t.Fatal("subtitle not shown") + } +} + +func TestVideoPlayerDisabled(t *testing.T) { + st := VideoState{Duration: time.Minute} + var v videoCalls + o := v.opts() + o.Disabled = true + tt := videoTester(&st, &o) + _ = tt.Click("Play") + _ = tt.Click("Full screen") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeySpace) + if v.play != 0 || len(v.full) != 0 { + t.Fatalf("disabled player reported %+v", v) + } +} + +func TestVideoPlayerSnapshot(t *testing.T) { + var v videoCalls + snapshot(t, "video_player", 560, 400, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(520).Children(func() { + VideoPlayer(c, VideoState{Frame: mediaTestBitmap(320, 180), Position: 95 * time.Second, Duration: 4 * time.Minute, + Buffered: []MediaRange{{0, 150 * time.Second}}, Playing: true, Rate: 1, SubtitlesOn: true, + Subtitle: "The curtain rises."}, v.opts()) + }) + }) +} diff --git a/video_scrubber.go b/video_scrubber.go new file mode 100644 index 0000000..156e06b --- /dev/null +++ b/video_scrubber.go @@ -0,0 +1,118 @@ +package mujica + +import ( + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// MediaRange is a span of a media timeline. +type MediaRange struct{ Start, End time.Duration } + +// VideoScrubberOptions configure a VideoScrubber. +type VideoScrubberOptions struct { + // Duration is the timeline's length; required. + Duration time.Duration + // Buffered spans show as a lighter fill. + Buffered []MediaRange + // Preview builds the hover slot's content for a time. + Preview func(at time.Duration) + // PreviewWidth, PreviewHeight size the slot; zero means 160×90. + PreviewWidth, PreviewHeight float32 + // Step is one arrow press; zero means 5 seconds. + Step time.Duration + Disabled bool + // Label names the timeline for assistive technology. + Label string +} + +// VideoScrubber sets *pos by dragging, clicking, arrows, Home and End. +func VideoScrubber(c *ui.Context, pos *time.Duration, opts VideoScrubberOptions) ChoiceResult { + if opts.Duration <= 0 || opts.Step < 0 || opts.PreviewWidth < 0 || opts.PreviewHeight < 0 { + panic("mujica: VideoScrubber needs Duration > 0 and no negative Step or preview size") + } + if *pos < 0 || *pos > opts.Duration { + panic("mujica: VideoScrubber position outside 0..Duration") + } + step := opts.Step + if step == 0 { + step = 5 * time.Second + } + pw, ph := opts.PreviewWidth, opts.PreviewHeight + if pw == 0 { + pw, ph = 160, 90 + } + k := Tokens(c) + dur := opts.Duration.Seconds() + g, h := sliderSetup(0, dur, min(step.Seconds(), dur), nil, false, c) + old := *pos + var s *ui.Element + var next float64 + wrap := ui.Box(c).MinWidth(120).Shrink(0).Disabled(opts.Disabled) + wrap.Children(func() { + s, next, _ = sliderControl(c, old.Seconds(), g, 0, dur) + s.Height(h).PaddingX(sliderThumb / 2).FocusRing(false).Cursor(ui.CursorPointer). + Label(scrubberLabel(c, opts.Label)) + px, _, over := s.PointerPosition() + r := s.Bounds() + at := time.Duration(float64((px-sliderThumb/2)/max(r.W-sliderThumb, 1)) * float64(opts.Duration)) + at = max(0, min(opts.Duration, at)) + if over && !s.IsDisabled() { + scrubberHover(c, k, r, g, at, opts, pw, ph) + } + }) + if !s.IsDisabled() { + *pos = max(0, min(opts.Duration, time.Duration(next*float64(time.Second)).Round(time.Millisecond))) + if next == dur { + *pos = opts.Duration + } + } + changed := *pos != old + if changed { + slog.Debug("mujica: video_scrubber seek", "pos", *pos) + } + v, buffered, focus := pos.Seconds(), opts.Buffered, s + s.Draw(func(p *ui.Painter, r ui.Rect) { + y := r.Y + g.trackY + x0 := g.x(r, 0) + sliderTrackPaint(p, r, g, k, nil, 0, x0, x0) + // Buffered spans fill the rail under the played part. + for _, b := range buffered { + b0, b1 := g.x(r, b.Start.Seconds()), g.x(r, b.End.Seconds()) + p.Fill(ui.Rect{X: b0, Y: y - sliderTrack/2, W: b1 - b0, H: sliderTrack}, k.TextMuted.Alpha(0.45), 0) + } + p.Fill(ui.Rect{X: x0, Y: y - sliderTrack/2, W: g.x(r, v) - x0, H: sliderTrack}, k.AccentText, 0) + sliderThumbPaint(p, k, g.x(r, v), y, focus.Hovered(), focus.FocusVisible()) + }) + return ChoiceResult{Element: s, changed: changed} +} + +func scrubberLabel(c *ui.Context, label string) string { + if label != "" { + return label + } + return msg(c, "video_scrubber.label") +} + +// scrubberHover shows hover time and preview slot above the track. +func scrubberHover(c *ui.Context, k theme.Tokens, r ui.Rect, g sliderGeom, at time.Duration, opts VideoScrubberOptions, pw, ph float32) { + x := g.x(ui.Rect{W: r.W}, at.Seconds()) + w := pw + if opts.Preview == nil { + w = 64 + } + panel := ui.Column(c).Absolute().Left(max(0, min(r.W-w, x-w/2))).Bottom(r.H - g.trackY + sliderThumb). + Width(w).Padding(4).Gap(4).AlignItems(ui.Center).PassThrough() + overlayStyle(c, panel, 1) + panel.Children(func() { + if opts.Preview != nil { + ui.Box(c).Size(pw-8, ph).Clip().Radius(theme.ControlRadius).Background(k.Background).Children(func() { + opts.Preview(at) + }) + } + ui.Text(c, mediaClock(at)).FontSize(FontSize(c, theme.CaptionSize)).FontFeatures("tnum").SingleLine() + }) +} diff --git a/video_scrubber_test.go b/video_scrubber_test.go new file mode 100644 index 0000000..7805684 --- /dev/null +++ b/video_scrubber_test.go @@ -0,0 +1,91 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func scrubberTester(pos *time.Duration, opts VideoScrubberOptions, changes *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(40).Children(func() { + if VideoScrubber(c, pos, opts).Changed() { + *changes++ + } + }) + }, 500, 300) +} + +func TestVideoScrubberKeys(t *testing.T) { + pos, n := 10*time.Second, 0 + tt := scrubberTester(&pos, VideoScrubberOptions{Duration: time.Minute}, &n) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + if pos != 15*time.Second { + t.Fatalf("Right: %v", pos) + } + tt.Key(0, ui.KeyLeft) + tt.Key(0, ui.KeyLeft) + if pos != 5*time.Second { + t.Fatalf("Left twice: %v", pos) + } + tt.Key(0, ui.KeyEnd) + if pos != time.Minute { + t.Fatalf("End: %v", pos) + } + tt.Key(0, ui.KeyHome) + if pos != 0 || n != 5 { + t.Fatalf("Home: %v, changes %d", pos, n) + } +} + +func TestVideoScrubberClickAndHover(t *testing.T) { + pos, n := time.Duration(0), 0 + var asked time.Duration + opts := VideoScrubberOptions{Duration: 100 * time.Second, Preview: func(at time.Duration) { asked = at }} + tt := scrubberTester(&pos, opts, &n) + r, ok := tt.Find("Timeline") + if !ok { + t.Fatal("no timeline") + } + mid := r.X + r.W/2 + tt.Move(mid, r.Y+r.H/2) + if asked < 45*time.Second || asked > 55*time.Second || !tt.HasText(mediaClock(asked)) { + t.Fatalf("hover preview at %v, texts %v", asked, tt.Texts()) + } + tt.ClickAt(mid, r.Y+r.H/2) + if pos < 45*time.Second || pos > 55*time.Second || n != 1 { + t.Fatalf("click seek %v, changes %d", pos, n) + } +} + +func TestVideoScrubberDisabled(t *testing.T) { + pos, n := 10*time.Second, 0 + tt := scrubberTester(&pos, VideoScrubberOptions{Duration: time.Minute, Disabled: true}, &n) + r, _ := tt.Find("Timeline") + tt.ClickAt(r.X+r.W-10, r.Y+r.H/2) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + if pos != 10*time.Second || n != 0 { + t.Fatalf("disabled moved to %v", pos) + } +} + +func TestVideoScrubberBadOptions(t *testing.T) { + pos := time.Duration(0) + mediaPanics(t, "no duration", func(c *ui.Context) { VideoScrubber(c, &pos, VideoScrubberOptions{}) }) + far := 2 * time.Minute + mediaPanics(t, "past end", func(c *ui.Context) { VideoScrubber(c, &far, VideoScrubberOptions{Duration: time.Minute}) }) +} + +func TestVideoScrubberSnapshot(t *testing.T) { + pos := 40 * time.Second + snapshot(t, "video_scrubber", 420, 80, func(c *ui.Context) { + ui.Column(c).Padding(20).Children(func() { + VideoScrubber(c, &pos, VideoScrubberOptions{Duration: 2 * time.Minute, + Buffered: []MediaRange{{0, 70 * time.Second}, {90 * time.Second, 100 * time.Second}}}) + }) + }) +} diff --git a/video_thumbnail_strip.go b/video_thumbnail_strip.go new file mode 100644 index 0000000..af92ed4 --- /dev/null +++ b/video_thumbnail_strip.go @@ -0,0 +1,116 @@ +package mujica + +import ( + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// StripFrame is one thumbnail of a VideoThumbnailStrip. +type StripFrame struct { + // Image is a bitmap or SVG; nil leaves it empty. + Image ui.ImageSource + At time.Duration +} + +// VideoThumbnailStripOptions configure a VideoThumbnailStrip. +type VideoThumbnailStripOptions struct { + // FrameWidth is each cell's width; zero means 96. + FrameWidth float32 + Disabled bool +} + +const stripGap = 4 + +type stripKey struct{} + +// VideoThumbnailStrip shows the frames fitting around *current. +func VideoThumbnailStrip(c *ui.Context, current *int, frames []StripFrame, opts VideoThumbnailStripOptions) ChoiceResult { + if len(frames) == 0 || *current < 0 || *current >= len(frames) { + panic("mujica: VideoThumbnailStrip current out of range") + } + if opts.FrameWidth < 0 { + panic("mujica: VideoThumbnailStrip FrameWidth must not be negative") + } + fw := opts.FrameWidth + if fw == 0 { + fw = 96 + } + fh := fw * 9 / 16 + k := Tokens(c) + old := *current + row := ui.Row(c).Gap(Density(c).Unit()).AlignItems(ui.Center).Disabled(opts.Disabled) + row.Children(func() { + prev := iconAction(c, icons.Must("chevron-left"), msg(c, "video_thumbnail_strip.previous")).Disabled(*current == 0) + view := ui.Row(c).Grow(1).MinWidth(fw).Height(fh + 4).Gap(stripGap).Clip().Focusable(). + Role(ui.RoleGroup).Label(msg(c, "video_thumbnail_strip.label")). + Description(fmt.Sprintf(msg(c, "video_thumbnail_strip.position"), *current+1, len(frames), mediaClock(frames[*current].At))) + internal.Ring(view, k.Focus, theme.ControlRadius) + next := iconAction(c, icons.Must("chevron-right"), msg(c, "video_thumbnail_strip.next")).Disabled(*current == len(frames)-1) + live := !row.IsDisabled() + switch { + case live && (prev.Clicked() || view.Shortcut(0, ui.KeyLeft)): + *current = max(0, *current-1) + case live && (next.Clicked() || view.Shortcut(0, ui.KeyRight)): + *current = min(len(frames)-1, *current+1) + case live && view.Shortcut(0, ui.KeyHome): + *current = 0 + case live && view.Shortcut(0, ui.KeyEnd): + *current = len(frames) - 1 + } + // Only frames that fit are built, around *current. + w := view.Bounds().W + if w <= 0 { + // The count needs the width: lay out, then rebuild. + c.AnimationFrame() + } + n := max(1, int((w+stripGap)/(fw+stripGap))) + start := ui.Local(view, stripKey{}, func() int { return 0 }) + *start = max(0, min(*start, *current, len(frames)-n)) + if *current >= *start+n { + *start = *current - n + 1 + } + view.Children(func() { + for i := *start; i < min(len(frames), *start+n); i++ { + if stripCell(c, k, frames[i], i, i == *current, fw, fh) && live { + *current = i + } + } + }) + }) + changed := *current != old + if changed { + slog.Debug("mujica: video_strip jump", "index", *current) + } + return ChoiceResult{Element: row, changed: changed} +} + +// stripCell draws one frame and reports a click on it. +func stripCell(c *ui.Context, k theme.Tokens, f StripFrame, i int, on bool, fw, fh float32) bool { + cell := ui.Box(c).Key(i).Size(fw, fh).Shrink(0).Radius(theme.ControlRadius).Clip().Background(videoBlack). + Cursor(ui.CursorPointer).AlignSelf(ui.Center) + edge, width := k.Border, theme.BorderWidth + if on { + edge, width = k.AccentText, 2 + } + cell.Border(width, edge) + cell.Children(func() { + if f.Image != nil { + ui.Image(c, f.Image).Fit(ui.Cover).Size(fw, fh) + } + ui.Text(c, mediaClock(f.At)).Absolute().Left(4).Bottom(3).FontSize(FontSize(c, theme.CaptionSize)). + TextColor(ui.Hex("#F2EBDD")).Background(ui.RGBA(0, 0, 0, 0.6)).FontFeatures("tnum") + if on { + ui.Box(c).Absolute().Top(3).Right(3).Size(10, 10).Draw(func(p *ui.Painter, r ui.Rect) { + p.FillPath(internal.Diamond(internal.Snap(p, r.X+5), internal.Snap(p, r.Y+5), 10), k.AccentText) + }) + } + }) + return cell.Clicked() +} diff --git a/video_thumbnail_strip_test.go b/video_thumbnail_strip_test.go new file mode 100644 index 0000000..6cc95fe --- /dev/null +++ b/video_thumbnail_strip_test.go @@ -0,0 +1,102 @@ +package mujica + +import ( + "strings" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func stripFrames(n int) []StripFrame { + f := make([]StripFrame, n) + for i := range f { + f[i].At = time.Duration(i) * time.Second + } + return f +} + +func stripTester(cur *int, frames []StripFrame, disabled bool, n *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).Width(520).Children(func() { + if VideoThumbnailStrip(c, cur, frames, VideoThumbnailStripOptions{Disabled: disabled}).Changed() { + *n++ + } + }) + }, 600, 160) +} + +// stripBuilt counts the time labels the strip built. +func stripBuilt(tt *ui.Tester) int { + k := 0 + for _, s := range tt.Texts() { + if strings.Contains(s, ":") && !strings.Contains(s, " ") { + k++ + } + } + return k +} + +func TestVideoThumbnailStripKeysAndClick(t *testing.T) { + cur, n := 0, 0 + tt := stripTester(&cur, stripFrames(40), false, &n) + tt.Key(0, ui.KeyTab) + if !tt.Focused("Frames") { + t.Fatal("Tab did not reach the frames") + } + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + if cur != 2 { + t.Fatalf("Right twice: %d", cur) + } + tt.Key(0, ui.KeyEnd) + if cur != 39 || !tt.HasText("0:39") { + t.Fatalf("End: %d, %v", cur, tt.Texts()) + } + r, _ := tt.Find("0:37") + tt.ClickAt(r.X+20, r.Y-10) + if cur != 37 || n != 4 { + t.Fatalf("click: %d, changes %d", cur, n) + } +} + +func TestVideoThumbnailStripBuildsOnlyVisible(t *testing.T) { + cur, n := 50000, 0 + tt := stripTester(&cur, stripFrames(100000), false, &n) + tt.Frame() + if b := stripBuilt(tt); b < 3 || b > 10 { + t.Fatalf("built %d frames of 100000", b) + } + if !tt.HasText(mediaClock(50000 * time.Second)) { + t.Fatal("current frame not built") + } +} + +func TestVideoThumbnailStripDisabledAndBad(t *testing.T) { + cur, n := 3, 0 + tt := stripTester(&cur, stripFrames(10), true, &n) + _ = tt.Click("Next frame") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + if cur != 3 || n != 0 { + t.Fatal("disabled strip moved") + } + bad := 5 + mediaPanics(t, "out of range", func(c *ui.Context) { + VideoThumbnailStrip(c, &bad, stripFrames(3), VideoThumbnailStripOptions{}) + }) +} + +func TestVideoThumbnailStripSnapshot(t *testing.T) { + frames := stripFrames(12) + for i := range frames { + frames[i].Image = mediaTestBitmap(64, 36) + } + cur := 2 + snapshot(t, "video_thumbnail_strip", 560, 110, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(520).Children(func() { + VideoThumbnailStrip(c, &cur, frames, VideoThumbnailStripOptions{}) + }) + }) +} diff --git a/volume_control.go b/volume_control.go new file mode 100644 index 0000000..7fac647 --- /dev/null +++ b/volume_control.go @@ -0,0 +1,49 @@ +package mujica + +import ( + "fmt" + "log/slog" + "math" + + "github.com/egoist/mygo/ui" +) + +// VolumeControlOptions configure a VolumeControl. +type VolumeControlOptions struct { + Disabled bool +} + +// VolumeControl sets *volume in 5% steps and toggles *muted. +func VolumeControl(c *ui.Context, volume *float64, muted *bool, opts VolumeControlOptions) ChoiceResult { + if *volume < 0 || *volume > 1 || math.IsNaN(*volume) { + panic("mujica: VolumeControl volume outside 0..1") + } + oldV, oldM := *volume, *muted + u := Density(c).Unit() + row := ui.Row(c).Gap(u).AlignItems(ui.Center).Role(ui.RoleGroup).Label(msg(c, "volume_control.label")).Disabled(opts.Disabled) + row.Children(func() { + icon, key := mediaVolume, "volume_control.mute" + if *muted || *volume == 0 { + icon, key = mediaMute, "volume_control.unmute" + } + b := mediaToggleAction(c, icon, msg(c, key), *muted) + if b.Clicked() && !b.IsDisabled() { + *muted = !*muted + } + s := Slider(c, volume, SliderOptions{Min: 0, Max: 1, Step: 0.05, Disabled: opts.Disabled, + Label: msg(c, "volume_control.label"), ShowValue: true, Format: func(v float64) string { return fmt.Sprintf("%d%%", int(math.Round(v*100))) }}) + s.Element.Width(120) + // Raising the volume while muted unmutes, as players do. + if s.Changed() && *muted && *volume > oldV { + *muted = false + } + }) + if !row.IsDisabled() && row.Shortcut(0, ui.KeyM) { + *muted = !*muted + } + changed := *volume != oldV || *muted != oldM + if changed { + slog.Debug("mujica: volume changed", "volume", *volume, "muted", *muted) + } + return ChoiceResult{Element: row, changed: changed} +} diff --git a/volume_control_test.go b/volume_control_test.go new file mode 100644 index 0000000..94a6b71 --- /dev/null +++ b/volume_control_test.go @@ -0,0 +1,74 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func volumeTester(v *float64, muted *bool, disabled bool, n *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(40).AlignItems(ui.Start).Children(func() { + if VolumeControl(c, v, muted, VolumeControlOptions{Disabled: disabled}).Changed() { + *n++ + } + }) + }, 400, 200) +} + +func TestVolumeControlArrowsAndMute(t *testing.T) { + v, muted, n := 0.5, false, 0 + tt := volumeTester(&v, &muted, false, &n) + if err := tt.Click("Mute"); err != nil { + t.Fatal(err) + } + if !muted { + t.Fatal("mute button did not mute") + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyLeft) + if v != 0.45 || !muted { + t.Fatalf("Left: %v muted %v", v, muted) + } + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + if v != 0.55 || muted { + t.Fatalf("raising should unmute: %v muted %v", v, muted) + } + tt.Key(0, ui.KeyM) + if !muted || n != 5 { + t.Fatalf("M: muted %v changes %d", muted, n) + } + tt.Key(0, ui.KeyEnd) + if v != 1 { + t.Fatalf("End: %v", v) + } +} + +func TestVolumeControlDisabled(t *testing.T) { + v, muted, n := 0.5, false, 0 + tt := volumeTester(&v, &muted, true, &n) + _ = tt.Click("Mute") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyM) + if v != 0.5 || muted || n != 0 { + t.Fatalf("disabled changed %v %v", v, muted) + } +} + +func TestVolumeControlRange(t *testing.T) { + loud, m := 1.5, false + mediaPanics(t, "over 1", func(c *ui.Context) { VolumeControl(c, &loud, &m, VolumeControlOptions{}) }) +} + +func TestVolumeControlSnapshot(t *testing.T) { + a, b, ma, mb := 0.7, 0.3, false, true + snapshot(t, "volume_control", 260, 150, func(c *ui.Context) { + ui.Column(c).Padding(20).Gap(16).AlignItems(ui.Start).Children(func() { + VolumeControl(c, &a, &ma, VolumeControlOptions{}) + VolumeControl(c, &b, &mb, VolumeControlOptions{}) + }) + }) +} From efee19c7d4c3e914d7fee7e12983b861364e91c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 5 Oct 2026 14:34:31 -0400 Subject: [PATCH 10/13] Charts I: components 101-120 --- area_chart.go | 74 +++++ area_chart_test.go | 54 ++++ bar_chart.go | 185 ++++++++++++ bar_chart_test.go | 90 ++++++ box_plot.go | 160 +++++++++++ box_plot_test.go | 59 ++++ bullet_chart.go | 149 ++++++++++ bullet_chart_test.go | 69 +++++ calendar_heatmap.go | 139 +++++++++ calendar_heatmap_test.go | 95 +++++++ chart_frame.go | 260 +++++++++++++++++ chart_frame_test.go | 108 +++++++ chart_series.go | 206 ++++++++++++++ chart_tree.go | 171 ++++++++++++ data_table.go | 2 +- docs/components/101-line-chart.md | 54 ++++ docs/components/102-area-chart.md | 54 ++++ docs/components/103-bar-chart.md | 52 ++++ docs/components/104-pie-chart.md | 50 ++++ docs/components/105-scatter-chart.md | 52 ++++ docs/components/106-radar-chart.md | 49 ++++ docs/components/107-heatmap-chart.md | 48 ++++ docs/components/108-calendar-heatmap.md | 50 ++++ docs/components/109-histogram.md | 50 ++++ docs/components/110-box-plot.md | 47 ++++ docs/components/111-waterfall-chart.md | 52 ++++ docs/components/112-funnel-chart.md | 47 ++++ docs/components/113-bullet-chart.md | 51 ++++ docs/components/114-sparkline.md | 48 ++++ docs/components/115-gauge.md | 51 ++++ docs/components/116-treemap.md | 53 ++++ docs/components/117-sunburst.md | 53 ++++ docs/components/118-sankey-chart.md | 49 ++++ docs/components/119-network-graph.md | 51 ++++ docs/components/120-realtime-chart.md | 53 ++++ example_charts1_test.go | 221 +++++++++++++++ examples/gallery/pages_charts1.go | 76 ++++- examples/gallery/pages_charts1_code.go | 174 ++++++++++++ examples/gallery/pages_charts1_flow.go | 137 +++++++++ examples/gallery/pages_charts1_series.go | 197 +++++++++++++ examples/gallery/pages_charts1_stats.go | 171 ++++++++++++ examples/gallery/pages_charts1_test.go | 71 +++++ funnel_chart.go | 85 ++++++ funnel_chart_test.go | 54 ++++ gauge.go | 154 ++++++++++ gauge_test.go | 75 +++++ heatmap_chart.go | 123 ++++++++ heatmap_chart_test.go | 68 +++++ histogram.go | 157 +++++++++++ histogram_test.go | 76 +++++ internal/chart.go | 264 ++++++++++++++++++ internal/chart_test.go | 101 +++++++ line_chart.go | 159 +++++++++++ line_chart_test.go | 194 +++++++++++++ list.go | 2 +- messages_charts1.go | 30 ++ network_graph.go | 263 +++++++++++++++++ network_graph_test.go | 101 +++++++ pie_chart.go | 146 ++++++++++ pie_chart_test.go | 82 ++++++ radar_chart.go | 141 ++++++++++ radar_chart_test.go | 71 +++++ realtime_chart.go | 121 ++++++++ realtime_chart_test.go | 86 ++++++ sankey_chart.go | 235 ++++++++++++++++ sankey_chart_test.go | 81 ++++++ scatter_chart.go | 162 +++++++++++ scatter_chart_test.go | 82 ++++++ sparkline.go | 170 +++++++++++ sparkline_test.go | 78 ++++++ sunburst.go | 155 ++++++++++ sunburst_test.go | 64 +++++ testdata/snapshots/darwin/area_chart-dark.png | Bin 0 -> 18845 bytes .../snapshots/darwin/area_chart-light.png | Bin 0 -> 18427 bytes testdata/snapshots/darwin/bar_chart-dark.png | Bin 0 -> 19288 bytes testdata/snapshots/darwin/bar_chart-light.png | Bin 0 -> 18661 bytes testdata/snapshots/darwin/box_plot-dark.png | Bin 0 -> 12335 bytes testdata/snapshots/darwin/box_plot-light.png | Bin 0 -> 11813 bytes .../snapshots/darwin/bullet_chart-dark.png | Bin 0 -> 11624 bytes .../snapshots/darwin/bullet_chart-light.png | Bin 0 -> 11159 bytes .../darwin/calendar_heatmap-dark.png | Bin 0 -> 18785 bytes .../darwin/calendar_heatmap-light.png | Bin 0 -> 18469 bytes .../snapshots/darwin/funnel_chart-dark.png | Bin 0 -> 17621 bytes .../snapshots/darwin/funnel_chart-light.png | Bin 0 -> 16706 bytes testdata/snapshots/darwin/gauge-dark.png | Bin 0 -> 30567 bytes testdata/snapshots/darwin/gauge-light.png | Bin 0 -> 30341 bytes .../snapshots/darwin/heatmap_chart-dark.png | Bin 0 -> 16948 bytes .../snapshots/darwin/heatmap_chart-light.png | Bin 0 -> 16409 bytes testdata/snapshots/darwin/histogram-dark.png | Bin 0 -> 13217 bytes testdata/snapshots/darwin/histogram-light.png | Bin 0 -> 12658 bytes testdata/snapshots/darwin/line_chart-dark.png | Bin 0 -> 23341 bytes .../snapshots/darwin/line_chart-light.png | Bin 0 -> 22386 bytes .../snapshots/darwin/network_graph-dark.png | Bin 0 -> 15448 bytes .../snapshots/darwin/network_graph-light.png | Bin 0 -> 14812 bytes testdata/snapshots/darwin/pie_chart-dark.png | Bin 0 -> 41218 bytes testdata/snapshots/darwin/pie_chart-light.png | Bin 0 -> 41206 bytes .../snapshots/darwin/radar_chart-dark.png | Bin 0 -> 30389 bytes .../snapshots/darwin/radar_chart-light.png | Bin 0 -> 29501 bytes .../snapshots/darwin/realtime_chart-dark.png | Bin 0 -> 29105 bytes .../snapshots/darwin/realtime_chart-light.png | Bin 0 -> 28010 bytes .../snapshots/darwin/sankey_chart-dark.png | Bin 0 -> 13436 bytes .../snapshots/darwin/sankey_chart-light.png | Bin 0 -> 13005 bytes .../snapshots/darwin/scatter_chart-dark.png | Bin 0 -> 13704 bytes .../snapshots/darwin/scatter_chart-light.png | Bin 0 -> 13140 bytes testdata/snapshots/darwin/sparkline-dark.png | Bin 0 -> 2981 bytes testdata/snapshots/darwin/sparkline-light.png | Bin 0 -> 2901 bytes testdata/snapshots/darwin/sunburst-dark.png | Bin 0 -> 27106 bytes testdata/snapshots/darwin/sunburst-light.png | Bin 0 -> 26863 bytes testdata/snapshots/darwin/treemap-dark.png | Bin 0 -> 15168 bytes testdata/snapshots/darwin/treemap-light.png | Bin 0 -> 15103 bytes .../snapshots/darwin/waterfall_chart-dark.png | Bin 0 -> 13251 bytes .../darwin/waterfall_chart-light.png | Bin 0 -> 12729 bytes treemap.go | 98 +++++++ treemap_test.go | 89 ++++++ waterfall_chart.go | 125 +++++++++ waterfall_chart_test.go | 54 ++++ 116 files changed, 7825 insertions(+), 3 deletions(-) create mode 100644 area_chart.go create mode 100644 area_chart_test.go create mode 100644 bar_chart.go create mode 100644 bar_chart_test.go create mode 100644 box_plot.go create mode 100644 box_plot_test.go create mode 100644 bullet_chart.go create mode 100644 bullet_chart_test.go create mode 100644 calendar_heatmap.go create mode 100644 calendar_heatmap_test.go create mode 100644 chart_frame.go create mode 100644 chart_frame_test.go create mode 100644 chart_series.go create mode 100644 chart_tree.go create mode 100644 docs/components/101-line-chart.md create mode 100644 docs/components/102-area-chart.md create mode 100644 docs/components/103-bar-chart.md create mode 100644 docs/components/104-pie-chart.md create mode 100644 docs/components/105-scatter-chart.md create mode 100644 docs/components/106-radar-chart.md create mode 100644 docs/components/107-heatmap-chart.md create mode 100644 docs/components/108-calendar-heatmap.md create mode 100644 docs/components/109-histogram.md create mode 100644 docs/components/110-box-plot.md create mode 100644 docs/components/111-waterfall-chart.md create mode 100644 docs/components/112-funnel-chart.md create mode 100644 docs/components/113-bullet-chart.md create mode 100644 docs/components/114-sparkline.md create mode 100644 docs/components/115-gauge.md create mode 100644 docs/components/116-treemap.md create mode 100644 docs/components/117-sunburst.md create mode 100644 docs/components/118-sankey-chart.md create mode 100644 docs/components/119-network-graph.md create mode 100644 docs/components/120-realtime-chart.md create mode 100644 example_charts1_test.go create mode 100644 examples/gallery/pages_charts1_code.go create mode 100644 examples/gallery/pages_charts1_flow.go create mode 100644 examples/gallery/pages_charts1_series.go create mode 100644 examples/gallery/pages_charts1_stats.go create mode 100644 examples/gallery/pages_charts1_test.go create mode 100644 funnel_chart.go create mode 100644 funnel_chart_test.go create mode 100644 gauge.go create mode 100644 gauge_test.go create mode 100644 heatmap_chart.go create mode 100644 heatmap_chart_test.go create mode 100644 histogram.go create mode 100644 histogram_test.go create mode 100644 internal/chart.go create mode 100644 internal/chart_test.go create mode 100644 line_chart.go create mode 100644 line_chart_test.go create mode 100644 messages_charts1.go create mode 100644 network_graph.go create mode 100644 network_graph_test.go create mode 100644 pie_chart.go create mode 100644 pie_chart_test.go create mode 100644 radar_chart.go create mode 100644 radar_chart_test.go create mode 100644 realtime_chart.go create mode 100644 realtime_chart_test.go create mode 100644 sankey_chart.go create mode 100644 sankey_chart_test.go create mode 100644 scatter_chart.go create mode 100644 scatter_chart_test.go create mode 100644 sparkline.go create mode 100644 sparkline_test.go create mode 100644 sunburst.go create mode 100644 sunburst_test.go create mode 100644 testdata/snapshots/darwin/area_chart-dark.png create mode 100644 testdata/snapshots/darwin/area_chart-light.png create mode 100644 testdata/snapshots/darwin/bar_chart-dark.png create mode 100644 testdata/snapshots/darwin/bar_chart-light.png create mode 100644 testdata/snapshots/darwin/box_plot-dark.png create mode 100644 testdata/snapshots/darwin/box_plot-light.png create mode 100644 testdata/snapshots/darwin/bullet_chart-dark.png create mode 100644 testdata/snapshots/darwin/bullet_chart-light.png create mode 100644 testdata/snapshots/darwin/calendar_heatmap-dark.png create mode 100644 testdata/snapshots/darwin/calendar_heatmap-light.png create mode 100644 testdata/snapshots/darwin/funnel_chart-dark.png create mode 100644 testdata/snapshots/darwin/funnel_chart-light.png create mode 100644 testdata/snapshots/darwin/gauge-dark.png create mode 100644 testdata/snapshots/darwin/gauge-light.png create mode 100644 testdata/snapshots/darwin/heatmap_chart-dark.png create mode 100644 testdata/snapshots/darwin/heatmap_chart-light.png create mode 100644 testdata/snapshots/darwin/histogram-dark.png create mode 100644 testdata/snapshots/darwin/histogram-light.png create mode 100644 testdata/snapshots/darwin/line_chart-dark.png create mode 100644 testdata/snapshots/darwin/line_chart-light.png create mode 100644 testdata/snapshots/darwin/network_graph-dark.png create mode 100644 testdata/snapshots/darwin/network_graph-light.png create mode 100644 testdata/snapshots/darwin/pie_chart-dark.png create mode 100644 testdata/snapshots/darwin/pie_chart-light.png create mode 100644 testdata/snapshots/darwin/radar_chart-dark.png create mode 100644 testdata/snapshots/darwin/radar_chart-light.png create mode 100644 testdata/snapshots/darwin/realtime_chart-dark.png create mode 100644 testdata/snapshots/darwin/realtime_chart-light.png create mode 100644 testdata/snapshots/darwin/sankey_chart-dark.png create mode 100644 testdata/snapshots/darwin/sankey_chart-light.png create mode 100644 testdata/snapshots/darwin/scatter_chart-dark.png create mode 100644 testdata/snapshots/darwin/scatter_chart-light.png create mode 100644 testdata/snapshots/darwin/sparkline-dark.png create mode 100644 testdata/snapshots/darwin/sparkline-light.png create mode 100644 testdata/snapshots/darwin/sunburst-dark.png create mode 100644 testdata/snapshots/darwin/sunburst-light.png create mode 100644 testdata/snapshots/darwin/treemap-dark.png create mode 100644 testdata/snapshots/darwin/treemap-light.png create mode 100644 testdata/snapshots/darwin/waterfall_chart-dark.png create mode 100644 testdata/snapshots/darwin/waterfall_chart-light.png create mode 100644 treemap.go create mode 100644 treemap_test.go create mode 100644 waterfall_chart.go create mode 100644 waterfall_chart_test.go diff --git a/area_chart.go b/area_chart.go new file mode 100644 index 0000000..739085d --- /dev/null +++ b/area_chart.go @@ -0,0 +1,74 @@ +package mujica + +import ( + "math" + "time" + + "github.com/egoist/mygo/ui" +) + +// AreaChartOptions configure an AreaChart. +type AreaChartOptions struct { + Frame ChartFrame + // X places point i at ascending X[i]; nil means i. + X []float64 + // Times makes a time axis; set X or Times. + Times []time.Time + // Stacked piles visible series on each other. + Stacked bool + // Baseline is where areas start; zero by default. + Baseline float64 + Format func(v float64) string +} + +// AreaChart fills series to the baseline, or stacked. +func AreaChart(c *ui.Context, series []ChartSeries, opts AreaChartOptions) ChartResult { + n := chartCheckSeries(series) + ch := newChart(c, opts.Frame) + ax := chartMemo(ch, "x", [3]string{chartID(opts.X), chartID(opts.Times), chartID(series)}, func() chartX { return newChartX(n, opts.X, opts.Times) }) + deps := struct { + id string + stacked bool + base float64 + }{chartSeriesID(ch, series), opts.Stacked, opts.Baseline} + bands := chartMemo(ch, "bands", deps, func() [2][][]float64 { return areaBands(series, ch.hidden, opts.Stacked, opts.Baseline) }) + lo, hi, ok := chartYRange(ch, series, false, bands[0]) + if !ok { + n = 0 + } + lo, hi = min(lo, opts.Baseline), max(hi, opts.Baseline) + return chartLines(ch, chartLineData{series: series, tops: bands[0], bases: bands[1], ax: ax, lo: lo, hi: hi, n: n, format: opts.Format}) +} + +// areaBands returns each series' top and bottom edges. +func areaBands(series []ChartSeries, hidden func(string) bool, stacked bool, base float64) [2][][]float64 { + var tops, bases [][]float64 + var run []float64 + if len(series) > 0 { + run = make([]float64, len(series[0].Values)) + for i := range run { + run[i] = base + } + } + for _, s := range series { + top, bot := make([]float64, len(s.Values)), make([]float64, len(s.Values)) + for i, v := range s.Values { + bot[i], top[i] = base, v + if stacked { + bot[i], top[i] = run[i], run[i]+v + } + if stacked && !math.IsNaN(v) && !hidden(s.Name) { + run[i] += v + } + } + tops, bases = append(tops, top), append(bases, bot) + } + return [2][][]float64{tops, bases} +} + +func chartBool(b bool) float64 { + if b { + return 1 + } + return 0 +} diff --git a/area_chart_test.go b/area_chart_test.go new file mode 100644 index 0000000..04db044 --- /dev/null +++ b/area_chart_test.go @@ -0,0 +1,54 @@ +package mujica + +import ( + "math" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestAreaBands(t *testing.T) { + series := []ChartSeries{{Name: "a", Values: []float64{1, math.NaN(), 3}}, {Name: "b", Values: []float64{2, 2, 2}}} + none := func(string) bool { return false } + st := areaBands(series, none, true, 10) + if st[0][0][0] != 11 || st[1][1][0] != 11 || st[0][1][0] != 13 || !math.IsNaN(st[0][0][1]) || st[0][1][1] != 12 { + t.Fatalf("stacked %v", st) + } + hideA := func(s string) bool { return s == "a" } + st = areaBands(series, hideA, true, 0) + if st[0][1][2] != 2 || st[1][1][2] != 0 { + t.Fatalf("hidden series still stacked: %v", st) + } + flat := areaBands(series, none, false, -1) + if flat[0][0][2] != 3 || flat[1][0][2] != -1 || flat[1][1][2] != -1 { + t.Fatalf("baseline %v", flat) + } +} + +func TestAreaChartStackedReadout(t *testing.T) { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return AreaChart(c, lineSeries(), AreaChartOptions{Frame: ChartFrame{Label: "Nave"}, Stacked: true, Baseline: 1}) + }} + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "Nave") + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "0 · Pews 3 · Candles 5" { + t.Fatalf("readout shows the series values, not the stack: %q", got) + } + b := h.res.Element.Bounds() + tt.Move(b.X+52+(b.W-64)*0.5, b.Y+b.H/2) + if got := chartReadout(tt); got != "2 · Pews no value · Candles 6" || h.res.Point != 2 { + t.Fatalf("hover %q", got) + } +} + +func TestAreaChartSnapshot(t *testing.T) { + snapshot(t, "area_chart", 520, 340, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + AreaChart(c, []ChartSeries{ + {Name: "Matins", Values: []float64{3, 4, 6, 5, 7, 8}}, + {Name: "Vespers", Values: []float64{2, 3, 2, 4, 3, 5}}, + }, AreaChartOptions{Frame: ChartFrame{Label: "Attendance"}, Stacked: true}) + }) + }) +} diff --git a/bar_chart.go b/bar_chart.go new file mode 100644 index 0000000..7989ad2 --- /dev/null +++ b/bar_chart.go @@ -0,0 +1,185 @@ +package mujica + +import ( + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// BarChartOptions configure a BarChart. +type BarChartOptions struct { + Frame ChartFrame + // Horizontal lays categories down the side and bars across. + Horizontal bool + // Stacked piles series into one bar per category. + Stacked bool + // Labels writes each bar's value at its end. + Labels bool + Format func(v float64) string +} + +type barMark struct{ cat, series int } + +// BarChart draws grouped or stacked bars; NaN draws none. +func BarChart(c *ui.Context, categories []string, series []ChartSeries, opts BarChartOptions) ChartResult { + if n := chartCheckSeries(series); n != len(categories) && len(series) > 0 { + panic("mujica: BarChart series length differs from categories") + } + ch := newChart(c, opts.Frame) + k := Tokens(c) + pal := internal.Palette(k) + size := FontSize(c, theme.CaptionSize) + keys := make([]chartKey, len(series)) + var vis []int + for i, s := range series { + keys[i] = chartKey{Name: s.Name, Color: pal[i%len(pal)], Shape: i} + if !ch.hidden(s.Name) { + vis = append(vis, i) + } + } + // Bars stacked or not; lo and hi always include zero. + type layout struct { + marks []barMark + from []float64 + lo, hi float64 + } + lay := chartMemo(ch, "bars", [2]any{chartSeriesID(ch, series), opts.Stacked}, func() layout { + var l layout + for ci := range categories { + pos, neg := 0.0, 0.0 + for _, si := range vis { + v := series[si].Values[ci] + if math.IsNaN(v) { + continue + } + from := 0.0 + if opts.Stacked && v >= 0 { + from, pos = pos, pos+v + } else if opts.Stacked { + from, neg = neg, neg+v + } + l.marks, l.from = append(l.marks, barMark{ci, si}), append(l.from, from) + l.lo, l.hi = min(l.lo, from, from+v), max(l.hi, from, from+v) + } + } + return l + }) + var lo, hi, step float64 + var ticks []float64 + if len(lay.marks) > 0 { + lo, hi = lay.lo, lay.hi + if opts.Labels { + // Headroom keeps value labels inside the plot. + pad := (hi - lo) * 0.15 + lo, hi = lo-pad*chartBool(lo < 0), hi+pad*chartBool(hi > 0) + } + lo, hi, step = internal.Nice(lo, hi, 4) + ticks = internal.Ticks(lo, hi, step) + } + geom := func(r ui.Rect) (ui.Rect, internal.Band, internal.Linear) { + if opts.Horizontal { + plot := chartInset(r, 96, 26) + return plot, internal.Band{N: len(categories), R0: plot.Y, R1: plot.Y + plot.H, Pad: 0.3}, + internal.Linear{D0: lo, D1: hi, R0: float64(plot.X), R1: float64(plot.X + plot.W)} + } + plot := chartInset(r, 52, 26) + return plot, internal.Band{N: len(categories), R0: plot.X, R1: plot.X + plot.W, Pad: 0.3}, + internal.Linear{D0: lo, D1: hi, R0: float64(plot.Y + plot.H), R1: float64(plot.Y)} + } + // rect is bar i's box in plot space. + rect := func(band internal.Band, vs internal.Linear, i int) ui.Rect { + m := lay.marks[i] + at, w := band.Start(m.cat), band.Width() + if !opts.Stacked && len(vis) > 0 { + slot := 0 + for j, si := range vis { + if si == m.series { + slot = j + } + } + w /= float32(len(vis)) + at += w * float32(slot) + } + a, b := vs.Map(lay.from[i]), vs.Map(lay.from[i]+series[m.series].Values[m.cat]) + a, b = min(a, b), max(a, b) + if opts.Horizontal { + return ui.Rect{X: a, Y: at, W: max(b-a, 1), H: w} + } + return ui.Rect{X: at, Y: a, W: w, H: max(b-a, 1)} + } + value := func(i int) float64 { m := lay.marks[i]; return series[m.series].Values[m.cat] } + spec := chartSpec{n: len(lay.marks), keys: keys, toggle: len(series) > 1} + spec.readout = func(i int) string { + m := lay.marks[i] + return categories[m.cat] + " · " + series[m.series].Name + " " + chartValue(c, value(i), opts.Format) + } + spec.pick = func(r ui.Rect, x, y float32) int { + _, band, vs := geom(r) + for i := range lay.marks { + b := rect(band, vs, i) + // Thin bars still take a 6 DIP target. + if (ui.Rect{X: b.X - 3, Y: b.Y - 3, W: b.W + 6, H: b.H + 6}).Contains(x, y) { + return i + } + } + return -1 + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + plot, band, vs := geom(r) + label := func(v float64) string { return internal.FormatTick(v, step) } + var pos []float32 + for i := range categories { + pos = append(pos, band.Center(i)) + } + zero := vs.Map(0) + if opts.Horizontal { + for _, t := range ticks { + x := internal.Snap(p, vs.Map(t)) + p.Line(x, plot.Y, x, plot.Y+plot.H, 1, k.Border) + chartText(p, label(t), x, plot.Y+plot.H+6, size, k.TextMuted, 0.5, 0) + } + for i, y := range pos { + chartText(p, categories[i], plot.X-8, y, size, k.TextMuted, 1, 0.5) + } + p.Line(internal.Snap(p, zero), plot.Y, internal.Snap(p, zero), plot.Y+plot.H, 1, k.ControlBorder) + } else { + internal.AxisY(p, plot, vs, ticks, label, size, k) + internal.AxisX(p, plot, pos, categories, size, k) + internal.Rule(p, plot.X, plot.X+plot.W, zero, k.ControlBorder) + } + for i, m := range lay.marks { + b := rect(band, vs, i) + col := keys[m.series].Color + p.Fill(b, col, 1) + if i == active { + p.Stroke(ui.Rect{X: b.X - 2, Y: b.Y - 2, W: b.W + 4, H: b.H + 4}, k.Text, 2, 1.5) + } + // The series shape marks the bar besides its color. + if min(b.W, b.H) >= 10 && max(b.W, b.H) >= 14 { + internal.Marker(p, m.series, b.X+b.W/2, b.Y+b.H/2, min(b.W, b.H, 14)*0.6, k.Surface) + } + if opts.Labels && !opts.Stacked { + barLabel(p, chartValue(c, value(i), opts.Format), b, value(i) < 0, opts.Horizontal, size, k.Text) + } + } + } + res, _ := ch.build(spec) + return res +} + +// barLabel writes a value just past the bar's far end. +func barLabel(p *ui.Painter, s string, b ui.Rect, neg, horizontal bool, size float32, col ui.Color) { + switch { + case horizontal && neg: + chartText(p, s, b.X-4, b.Y+b.H/2, size, col, 1, 0.5) + case horizontal: + chartText(p, s, b.X+b.W+4, b.Y+b.H/2, size, col, 0, 0.5) + case neg: + chartText(p, s, b.X+b.W/2, b.Y+b.H+2, size, col, 0.5, 0) + default: + chartText(p, s, b.X+b.W/2, b.Y-2, size, col, 0.5, 1) + } +} diff --git a/bar_chart_test.go b/bar_chart_test.go new file mode 100644 index 0000000..dfde4b0 --- /dev/null +++ b/bar_chart_test.go @@ -0,0 +1,90 @@ +package mujica + +import ( + "math" + "testing" + + "github.com/egoist/mygo/ui" +) + +var barCats = []string{"Nave", "Choir", "Crypt"} + +func barSeries() []ChartSeries { + return []ChartSeries{ + {Name: "Gold", Values: []float64{4, -2, 3}}, + {Name: "Silver", Values: []float64{2, 5, math.NaN()}}, + } +} + +func TestBarChartKeyboardPerBar(t *testing.T) { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return BarChart(c, barCats, barSeries(), BarChartOptions{Frame: ChartFrame{Label: "Tithes"}}) + }} + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "Tithes") + want := []string{"Nave · Gold 4", "Nave · Silver 2", "Choir · Gold -2", "Choir · Silver 5", "Crypt · Gold 3"} + for i, w := range want { + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != w { + t.Fatalf("bar %d readout %q, want %q", i, got, w) + } + } + tt.Key(0, ui.KeyRight) + if h.res.Point != 4 { + t.Fatalf("stepped past the missing bar: %d", h.res.Point) + } +} + +func TestBarChartHoverStackedHorizontal(t *testing.T) { + for _, o := range []BarChartOptions{{Stacked: true}, {Horizontal: true, Labels: true}, {Horizontal: true, Stacked: true}} { + o.Frame = ChartFrame{Label: "Tithes"} + h := &chartHarness{build: func(c *ui.Context) ChartResult { return BarChart(c, barCats, barSeries(), o) }} + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "Tithes") + found := map[string]bool{} + b := h.res.Element.Bounds() + for y := b.Y + 30; y < b.Y+b.H-40; y += 4 { + for x := b.X + 60; x < b.X+b.W-16; x += 8 { + tt.Move(x, y) + if h.res.Point >= 0 { + found[chartReadout(tt)] = true + } + } + } + if len(found) != 5 || !found["Choir · Gold -2"] { + t.Fatalf("%+v: hover found %v", o, found) + } + } +} + +func TestBarChartBadAndEmpty(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic for mismatched categories") + } + }() + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return BarChart(c, barCats, nil, BarChartOptions{Frame: ChartFrame{Label: "Tithes"}}) + }} + tt := ui.NewTester(h.view, 520, 420) + if !tt.HasText("No data") { + t.Fatalf("empty: %q", tt.Texts()) + } + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + BarChart(c, barCats[:2], barSeries(), BarChartOptions{Frame: ChartFrame{Label: "x"}}) + }, 300, 300) +} + +func TestBarChartSnapshot(t *testing.T) { + snapshot(t, "bar_chart", 640, 320, func(c *ui.Context) { + ui.Row(c).Padding(16).Gap(16).Children(func() { + ui.Column(c).Width(296).Children(func() { + BarChart(c, barCats, barSeries(), BarChartOptions{Frame: ChartFrame{Label: "Grouped", Height: 220}, Labels: true}) + }) + ui.Column(c).Width(296).Children(func() { + BarChart(c, barCats, barSeries(), BarChartOptions{Frame: ChartFrame{Label: "Stacked", Height: 220}, Horizontal: true, Stacked: true}) + }) + }) + }) +} diff --git a/box_plot.go b/box_plot.go new file mode 100644 index 0000000..518ad02 --- /dev/null +++ b/box_plot.go @@ -0,0 +1,160 @@ +package mujica + +import ( + "fmt" + "math" + "slices" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// BoxGroup is one named sample of a BoxPlot. +type BoxGroup struct { + Name string + Values []float64 +} + +// BoxPlotOptions configure a BoxPlot. +type BoxPlotOptions struct { + Frame ChartFrame + Format func(v float64) string +} + +// boxStats are quartiles, whisker ends and outliers. +type boxStats struct { + q1, median, q3, lo, hi float64 + outliers []float64 + n int +} + +// boxSummary summarizes finite values; n is 0 without any. +func boxSummary(values []float64) boxStats { + var v []float64 + for _, x := range values { + if !math.IsNaN(x) && !math.IsInf(x, 0) { + v = append(v, x) + } + } + if len(v) == 0 { + return boxStats{} + } + slices.Sort(v) + q := func(p float64) float64 { + at := p * float64(len(v)-1) + i := int(at) + if i+1 >= len(v) { + return v[i] + } + return v[i] + (at-float64(i))*(v[i+1]-v[i]) + } + s := boxStats{q1: q(0.25), median: q(0.5), q3: q(0.75), n: len(v)} + fence := 1.5 * (s.q3 - s.q1) + s.lo, s.hi = s.q1, s.q3 + for _, x := range v { + if x < s.q1-fence || x > s.q3+fence { + s.outliers = append(s.outliers, x) + continue + } + s.lo, s.hi = min(s.lo, x), max(s.hi, x) + } + return s +} + +// BoxPlot compares groups by quartile box, whiskers and outlier points. +func BoxPlot(c *ui.Context, groups []BoxGroup, opts BoxPlotOptions) ChartResult { + ch := newChart(c, opts.Frame) + k := Tokens(c) + pal := internal.Palette(k) + size := FontSize(c, theme.CaptionSize) + ids := "" + for _, g := range groups { + if g.Name == "" { + panic("mujica: BoxPlot groups need names") + } + ids += chartID(g.Values) + ";" + } + stats := chartMemo(ch, "stats", ids, func() []boxStats { + out := make([]boxStats, len(groups)) + for i, g := range groups { + out[i] = boxSummary(g.Values) + } + return out + }) + lo, hi, n := math.Inf(1), math.Inf(-1), 0 + for _, s := range stats { + if s.n > 0 { + n++ + lo, hi = min(lo, s.lo, slices.Min(append([]float64{s.lo}, s.outliers...))), max(hi, s.hi, slices.Max(append([]float64{s.hi}, s.outliers...))) + } + } + var step float64 + if n > 0 { + lo, hi, step = internal.Nice(lo, hi, 4) + } else { + groups = nil + } + val := func(v float64) string { return chartValue(c, v, opts.Format) } + geom := func(r ui.Rect) (ui.Rect, internal.Band, internal.Linear) { + plot := chartInset(r, 52, 26) + return plot, internal.Band{N: len(groups), R0: plot.X, R1: plot.X + plot.W, Pad: 0.45}, + internal.Linear{D0: lo, D1: hi, R0: float64(plot.Y + plot.H), R1: float64(plot.Y)} + } + spec := chartSpec{n: len(groups)} + spec.readout = func(i int) string { + s := stats[i] + if s.n == 0 { + return groups[i].Name + " · " + msg(c, "chart.missing") + } + return fmt.Sprintf(msg(c, "box_plot.readout"), groups[i].Name, val(s.median), val(s.q1), val(s.q3), val(s.lo), val(s.hi), len(s.outliers)) + } + spec.pick = func(r ui.Rect, x, y float32) int { + plot, band, _ := geom(r) + if !plot.Contains(x, y) { + return -1 + } + return min(len(groups)-1, int((x-plot.X)/band.Step())) + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + plot, band, ys := geom(r) + internal.AxisY(p, plot, ys, internal.Ticks(lo, hi, step), func(v float64) string { return internal.FormatTick(v, step) }, size, k) + var xs []float32 + var names []string + for i, g := range groups { + xs, names = append(xs, band.Center(i)), append(names, g.Name) + } + internal.AxisX(p, plot, xs, names, size, k) + for i, s := range stats { + if s.n == 0 { + continue + } + col := pal[i%len(pal)] + x, w := band.Start(i), band.Width() + cx := internal.Snap(p, x+w/2) + whisker := func(a, b float64) { + var path ui.Path + path.MoveTo(cx, ys.Map(a)).LineTo(cx, ys.Map(b)) + p.StrokePath(&path, 1.5, k.TextMuted) + p.Line(cx-w/4, ys.Map(b), cx+w/4, ys.Map(b), 1.5, k.TextMuted) + } + whisker(s.q3, s.hi) + whisker(s.q1, s.lo) + box := ui.Rect{X: x, Y: ys.Map(s.q3), W: w, H: max(ys.Map(s.q1)-ys.Map(s.q3), 1)} + p.Fill(box, col.Alpha(0.22), 2) + p.Stroke(box, col, 2, 1.5) + p.Line(x, ys.Map(s.median), x+w, ys.Map(s.median), 2.5, k.Text) + for _, o := range s.outliers { + var dot ui.Path + dot.Circle(cx, internal.Snap(p, ys.Map(o)), 3.5) + p.StrokePath(&dot, 1.5, col) + } + if i == active { + p.Stroke(ui.Rect{X: x - 6, Y: plot.Y, W: w + 12, H: plot.H}, k.Text, 3, 1.5) + } + } + } + res, _ := ch.build(spec) + return res +} diff --git a/box_plot_test.go b/box_plot_test.go new file mode 100644 index 0000000..34b3bfd --- /dev/null +++ b/box_plot_test.go @@ -0,0 +1,59 @@ +package mujica + +import ( + "fmt" + "math" + "testing" + + "github.com/egoist/mygo/ui" +) + +var boxGroups = []BoxGroup{ + {Name: "Choir", Values: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 40}}, + {Name: "Nave", Values: []float64{4, 5, 5, 6, 7, math.NaN()}}, +} + +func TestBoxSummary(t *testing.T) { + s := boxSummary(boxGroups[0].Values) + if s.q1 != 3.25 || s.median != 5.5 || s.q3 != 7.75 || s.lo != 1 || s.hi != 9 || fmt.Sprint(s.outliers) != "[40]" || s.n != 10 { + t.Fatalf("summary %+v", s) + } + if s := boxSummary([]float64{math.NaN()}); s.n != 0 { + t.Fatal("NaN counted") + } +} + +func TestBoxPlotReadout(t *testing.T) { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return BoxPlot(c, boxGroups, BoxPlotOptions{Frame: ChartFrame{Label: "Hymns"}}) + }} + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "Hymns") + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "Choir · median 5.5 · quartiles 3.25–7.75 · whiskers 1–9 · 1 outliers" { + t.Fatalf("readout %q", got) + } + b := h.res.Element.Bounds() + tt.Key(0, ui.KeyEscape) + tt.Move(b.X+52+(b.W-64)*0.75, b.Y+100) + if got := chartReadout(tt); got != "Nave · median 5 · quartiles 5–6 · whiskers 4–7 · 0 outliers" { + t.Fatalf("hover %q", got) + } +} + +func TestBoxPlotEmpty(t *testing.T) { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return BoxPlot(c, []BoxGroup{{Name: "a"}}, BoxPlotOptions{Frame: ChartFrame{Label: "Hymns"}}) + }} + if tt := ui.NewTester(h.view, 520, 420); !tt.HasText("No data") { + t.Fatalf("empty: %q", tt.Texts()) + } +} + +func TestBoxPlotSnapshot(t *testing.T) { + snapshot(t, "box_plot", 520, 320, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + BoxPlot(c, append(boxGroups, BoxGroup{Name: "Crypt", Values: []float64{12, 14, 15, 18, 22, 25}}), BoxPlotOptions{Frame: ChartFrame{Label: "Hymns"}}) + }) + }) +} diff --git a/bullet_chart.go b/bullet_chart.go new file mode 100644 index 0000000..7dbd32e --- /dev/null +++ b/bullet_chart.go @@ -0,0 +1,149 @@ +package mujica + +import ( + "fmt" + "math" + "slices" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// BulletChartOptions configure a BulletChart; Frame.Height 0 means 72 DIPs. +type BulletChartOptions struct { + Frame ChartFrame + // Target, when set, draws a cross line at the goal. + Target *float64 + // Bands are the ascending upper ends of the qualitative ranges. + Bands []float64 + // Max ends the scale; 0 means automatic. + Max float64 + Vertical bool + Format func(v float64) string +} + +// BulletChart shows a value against a target and ranges. +func BulletChart(c *ui.Context, value float64, opts BulletChartOptions) ChartResult { + if math.IsNaN(value) || value < 0 || opts.Max < 0 || !slices.IsSorted(opts.Bands) || len(opts.Bands) > 0 && opts.Bands[0] <= 0 { + panic("mujica: BulletChart needs a value ≥ 0, Max ≥ 0 and positive ascending Bands") + } + if opts.Frame.Height == 0 { + opts.Frame.Height = 72 + } + ch := newChart(c, opts.Frame) + k := Tokens(c) + size := FontSize(c, theme.CaptionSize) + top := opts.Max + if top == 0 { + top = value + if opts.Target != nil { + top = max(top, *opts.Target) + } + if len(opts.Bands) > 0 { + top = max(top, opts.Bands[len(opts.Bands)-1]) + } + _, top, _ = internal.Nice(0, max(top, 1e-9), 4) + } + _, _, step := internal.Nice(0, top, 4) + val := func(v float64) string { return chartValue(c, v, opts.Format) } + marks := []string{msg(c, "bullet_chart.actual") + " " + val(value)} + if opts.Target != nil { + marks = append(marks, msg(c, "bullet_chart.target")+" "+val(*opts.Target)) + } + for i, b := range opts.Bands { + lo := 0.0 + if i > 0 { + lo = opts.Bands[i-1] + } + marks = append(marks, fmt.Sprintf(msg(c, "bullet_chart.band"), i+1, val(lo), val(b))) + } + // geom returns the plot and its value scale. + geom := func(r ui.Rect) (ui.Rect, internal.Linear) { + if opts.Vertical { + plot := ui.Rect{X: r.X + r.W/2 - 14, Y: r.Y + 8, W: 28, H: r.H - 16} + return plot, internal.Linear{D0: 0, D1: top, R0: float64(plot.Y + plot.H), R1: float64(plot.Y)} + } + plot := ui.Rect{X: r.X + 8, Y: r.Y + 6, W: r.W - 24, H: max(r.H-30, 12)} + return plot, internal.Linear{D0: 0, D1: top, R0: float64(plot.X), R1: float64(plot.X + plot.W)} + } + span := func(plot ui.Rect, s internal.Linear, a, b, inset float32) ui.Rect { + if opts.Vertical { + return ui.Rect{X: plot.X + inset, Y: s.Map(float64(b)), W: plot.W - 2*inset, H: s.Map(float64(a)) - s.Map(float64(b))} + } + return ui.Rect{X: s.Map(float64(a)), Y: plot.Y + inset, W: s.Map(float64(b)) - s.Map(float64(a)), H: plot.H - 2*inset} + } + spec := chartSpec{n: len(marks)} + spec.readout = func(i int) string { return marks[i] } + spec.pick = func(r ui.Rect, x, y float32) int { + plot, s := geom(r) + if !plot.Contains(x, y) { + return -1 + } + at := x + if opts.Vertical { + at = y + } + v := s.Invert(at) + if opts.Target != nil && math.Abs(float64(s.Map(*opts.Target)-at)) < 4 { + return 1 + } + if span(plot, s, 0, float32(min(value, top)), bulletInset(plot, opts.Vertical)).Contains(x, y) { + return 0 + } + for i, b := range opts.Bands { + if v <= b { + return len(marks) - len(opts.Bands) + i + } + } + return -1 + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + plot, s := geom(r) + inset := bulletInset(plot, opts.Vertical) + prev := 0.0 + for i, b := range opts.Bands { + shade := k.SurfaceHover.Mix(k.Border, float32(len(opts.Bands)-1-i)/float32(max(len(opts.Bands)-1, 1))) + p.Fill(span(plot, s, float32(prev), float32(min(b, top)), 0), shade, 0) + if active == len(marks)-len(opts.Bands)+i { + p.Stroke(span(plot, s, float32(prev), float32(min(b, top)), 0), k.Text, 0, 1.5) + } + prev = b + } + bar := span(plot, s, 0, float32(min(value, top)), inset) + p.Fill(bar, internal.Palette(k)[0], 0) + if active == 0 { + p.Stroke(ui.Rect{X: bar.X - 2, Y: bar.Y - 2, W: bar.W + 4, H: bar.H + 4}, k.Text, 1, 1.5) + } + if opts.Target != nil { + t := internal.Snap(p, s.Map(min(*opts.Target, top))) + w := float32(2.5) + if active == 1 { + w = 4 + } + if opts.Vertical { + p.Line(plot.X+2, t, plot.X+plot.W-2, t, w, k.Text) + } else { + p.Line(t, plot.Y+2, t, plot.Y+plot.H-2, w, k.Text) + } + } + for _, tk := range internal.Ticks(0, top, step) { + if opts.Vertical { + chartText(p, internal.FormatTick(tk, step), plot.X+plot.W+6, s.Map(tk), size, k.TextMuted, 0, 0.5) + } else { + chartText(p, internal.FormatTick(tk, step), s.Map(tk), plot.Y+plot.H+4, size, k.TextMuted, 0.5, 0) + } + } + } + res, _ := ch.build(spec) + return res +} + +// bulletInset is a third of the band's thickness. +func bulletInset(plot ui.Rect, vertical bool) float32 { + if vertical { + return plot.W / 3 + } + return plot.H / 3 +} diff --git a/bullet_chart_test.go b/bullet_chart_test.go new file mode 100644 index 0000000..1d8ba54 --- /dev/null +++ b/bullet_chart_test.go @@ -0,0 +1,69 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestBulletChartReadout(t *testing.T) { + target := 250.0 + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return BulletChart(c, 270, BulletChartOptions{Frame: ChartFrame{Label: "Alms"}, Target: &target, Bands: []float64{150, 225, 300}}) + }} + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "Alms") + want := []string{"Actual 270", "Target 250", "Range 1: 0–150", "Range 2: 150–225", "Range 3: 225–300"} + for i, w := range want { + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != w { + t.Fatalf("mark %d %q, want %q", i, got, w) + } + } + tt.Key(0, ui.KeyEscape) + b := h.res.Element.Bounds() + plotW := b.W - 24 + tt.Move(b.X+8+plotW*0.1, b.Y+6+21) // band 1, inside the value bar + if got := chartReadout(tt); got != "Actual 270" { + t.Fatalf("hover bar %q", got) + } + tt.Move(b.X+8+plotW*0.1, b.Y+8) // band 1, above the bar + if got := chartReadout(tt); got != "Range 1: 0–150" { + t.Fatalf("hover band %q", got) + } +} + +func TestBulletChartVerticalAndBad(t *testing.T) { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return BulletChart(c, 40, BulletChartOptions{Frame: ChartFrame{Label: "Alms", Height: 200}, Vertical: true, Max: 100}) + }} + tt := ui.NewTester(h.view, 520, 420) + b := h.res.Element.Bounds() + tt.Move(b.X+b.W/2, b.Y+8+184*0.8) // low on the scale: inside the bar + if got := chartReadout(tt); got != "Actual 40" { + t.Fatalf("vertical hover %q", got) + } + defer func() { + if recover() == nil { + t.Fatal("no panic for unsorted bands") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + BulletChart(c, 1, BulletChartOptions{Frame: ChartFrame{Label: "x"}, Bands: []float64{5, 2}}) + }, 300, 300) +} + +func TestBulletChartSnapshot(t *testing.T) { + target := 250.0 + snapshot(t, "bullet_chart", 520, 300, func(c *ui.Context) { + ui.Row(c).Padding(16).Gap(16).Children(func() { + ui.Column(c).Width(360).Children(func() { + BulletChart(c, 270, BulletChartOptions{Frame: ChartFrame{Label: "Alms"}, Target: &target, Bands: []float64{150, 225, 300}}) + }) + ui.Column(c).Width(100).Children(func() { + BulletChart(c, 40, BulletChartOptions{Frame: ChartFrame{Label: "Oil", Height: 200}, Vertical: true, Target: &[]float64{70}[0], Bands: []float64{50, 80, 100}}) + }) + }) + }) +} diff --git a/calendar_heatmap.go b/calendar_heatmap.go new file mode 100644 index 0000000..1b3e542 --- /dev/null +++ b/calendar_heatmap.go @@ -0,0 +1,139 @@ +package mujica + +import ( + "log/slog" + "strconv" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// CalendarHeatmapOptions configure a CalendarHeatmap. +type CalendarHeatmapOptions struct { + Frame ChartFrame + // WeekStart picks each column's first weekday; zero follows the locale. + WeekStart WeekStart + Format func(v float64) string +} + +// CalendarHeatmap colors each day of *year, a column per week. +func CalendarHeatmap(c *ui.Context, year *int, values map[Date]float64, opts CalendarHeatmapOptions) ChartResult { + if *year < 1 || *year > 9999 { + panic("mujica: CalendarHeatmap year out of range") + } + k := Tokens(c) + u := Density(c).Unit() + size := FontSize(c, theme.CaptionSize) + first := Date{Year: *year, Month: time.January, Day: 1} + days := first.AddMonths(12).civil().Sub(first.civil()).Hours() / 24 + n := int(days) + lead := (int(first.Weekday()) - int(calendarFirstWeekday(c, opts.WeekStart)) + 7) % 7 + weeks := (lead + n + 6) / 7 + top := 0.0 + for i := range n { + if v, ok := values[first.AddDays(i)]; ok { + top = max(top, v) + } + } + // level is a day's color step, 0 to 4. + level := func(i int) int { + v, ok := values[first.AddDays(i)] + if !ok || v <= 0 || top <= 0 { + return 0 + } + return 1 + min(3, int(v/top*4)) + } + var res ChartResult + wrap := ui.Column(c).Gap(u * 2).MinWidth(0) + wrap.Children(func() { + ui.Row(c).Gap(u).AlignItems(ui.Center).Children(func() { + prev := iconAction(c, icons.Must("chevron-left"), msg(c, "calendar_heatmap.prev")).Disabled(*year <= 1) + ui.Text(c, strconv.Itoa(*year)).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).Width(64).TextAlign(ui.Center) + next := iconAction(c, icons.Must("chevron-right"), msg(c, "calendar_heatmap.next")).Disabled(*year >= 9999) + if prev.Clicked() && !prev.IsDisabled() { + *year-- + res.value = true + } + if next.Clicked() && !next.IsDisabled() { + *year++ + res.value = true + } + }) + ch := newChart(c, opts.Frame) + geom := func(r ui.Rect) (x, y, step float32) { + step = min((r.W-36)/float32(weeks), (r.H-48)/7) + return r.X + 32, r.Y + 18, step + } + cell := func(r ui.Rect, i int) ui.Rect { + x, y, step := geom(r) + at := lead + i + return ui.Rect{X: x + float32(at/7)*step, Y: y + float32(at%7)*step, W: step - 2, H: step - 2} + } + spec := chartSpec{n: n} + spec.readout = func(i int) string { + d := first.AddDays(i) + v, ok := values[d] + s := d.String() + " · " + if !ok { + return s + msg(c, "chart.missing") + } + return s + chartValue(c, v, opts.Format) + } + spec.move = func(i int, key ui.Key) int { + step := map[ui.Key]int{ui.KeyLeft: -7, ui.KeyRight: 7, ui.KeyUp: -1, ui.KeyDown: 1}[key] + return max(0, min(n-1, i+step)) + } + spec.pick = func(r ui.Rect, x, y float32) int { + x0, y0, step := geom(r) + col, row := int((x-x0)/step), int((y-y0)/step) + i := col*7 + row - lead + if x < x0 || y < y0 || row > 6 || i < 0 || i >= n { + return -1 + } + return i + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + x0, y0, step := geom(r) + for i := range n { + b := cell(r, i) + if lv := level(i); lv == 0 { + p.Fill(b, k.SurfaceHover, 2) + } else { + p.Fill(b, internal.Ramp(k, float64(lv)/4), 2) + } + if d := first.AddDays(i); d.Day == 1 { + chartText(p, d.Format("Jan"), b.X, y0-4, size, k.TextMuted, 0, 1) + } + if i == active { + p.Stroke(ui.Rect{X: b.X - 2, Y: b.Y - 2, W: b.W + 4, H: b.H + 4}, k.Text, 3, 2) + } + } + for row := 0; row < 7; row += 2 { + wd := time.Weekday((int(calendarFirstWeekday(c, opts.WeekStart)) + row) % 7) + chartText(p, wd.String()[:3], x0-4, y0+float32(row)*step+step/2, size, k.TextMuted, 1, 0.5) + } + ly := y0 + 7*step + 8 + w, _ := chartText(p, msg(c, "calendar_heatmap.less"), x0, ly, size, k.TextMuted, 0, 0) + for lv := range 5 { + sw := ui.Rect{X: x0 + w + 6 + float32(lv)*(step+2), Y: ly + 2, W: step - 2, H: step - 2} + if lv == 0 { + p.Fill(sw, k.SurfaceHover, 2) + } else { + p.Fill(sw, internal.Ramp(k, float64(lv)/4), 2) + } + } + chartText(p, msg(c, "calendar_heatmap.more"), x0+w+12+5*(step+2), ly, size, k.TextMuted, 0, 0) + } + res2, _ := ch.build(spec) + res.Point, res.changed, res.retry = res2.Point, res2.changed, res2.retry + }) + if res.value { + slog.Debug("mujica: calendar_heatmap year", "year", *year) + } + res.Element = wrap + return res +} diff --git a/calendar_heatmap_test.go b/calendar_heatmap_test.go new file mode 100644 index 0000000..6c417e2 --- /dev/null +++ b/calendar_heatmap_test.go @@ -0,0 +1,95 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func calendarValues() map[Date]float64 { + m := map[Date]float64{} + d := Date{Year: 2026, Month: time.January, Day: 1} + for i := range 365 { + if i%3 == 0 { + m[d.AddDays(i)] = float64(i % 11) + } + } + return m +} + +func TestCalendarHeatmapKeysAndYear(t *testing.T) { + year := 2026 + values := 0 + start := WeekStartMonday + h := &chartHarness{build: func(c *ui.Context) ChartResult { + r := CalendarHeatmap(c, &year, calendarValues(), CalendarHeatmapOptions{Frame: ChartFrame{Label: "Prayers"}, WeekStart: start}) + if r.ValueChanged() { + values++ + } + return r + }} + tt := ui.NewTester(h.view, 560, 420) + tabTo(t, tt, "Prayers") + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "2026-01-01 · 0" { + t.Fatalf("first day %q", got) + } + tt.Key(0, ui.KeyRight) // a week later + tt.Key(0, ui.KeyDown) // a day later + if got := chartReadout(tt); got != "2026-01-09 · no value" { + t.Fatalf("week and day %q", got) + } + tt.Key(0, ui.KeyEnd) + if got := chartReadout(tt); got != "2026-12-31 · no value" { + t.Fatalf("End %q", got) + } + if err := tt.Click("Next year"); err != nil { + t.Fatal(err) + } + if year != 2027 || values != 1 || !tt.HasText("2027") { + t.Fatalf("year %d events %d", year, values) + } +} + +func TestCalendarHeatmapWeekStartHover(t *testing.T) { + year := 2026 // 1 January 2026 is a Thursday + for _, tc := range []struct { + start WeekStart + row int + }{{WeekStartSunday, 4}, {WeekStartMonday, 3}} { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return CalendarHeatmap(c, &year, calendarValues(), CalendarHeatmapOptions{Frame: ChartFrame{Label: "Prayers"}, WeekStart: tc.start}) + }} + tt := ui.NewTester(h.view, 560, 420) + b := h.res.Element.Bounds() + plotY := b.Y + b.H - 20 - 8 - 240 // above the readout line and gap + step := min((b.W-36)/53, float32(240-48)/7) + tt.Move(b.X+32+step/2, plotY+18+float32(tc.row)*step+step/2) + if got := chartReadout(tt); got != "2026-01-01 · 0" { + t.Fatalf("start %d: row %d reads %q", tc.start, tc.row, got) + } + } +} + +func TestCalendarHeatmapBadYear(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic") + } + }() + year := 0 + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + CalendarHeatmap(c, &year, nil, CalendarHeatmapOptions{Frame: ChartFrame{Label: "x"}}) + }, 300, 300) +} + +func TestCalendarHeatmapSnapshot(t *testing.T) { + snapshot(t, "calendar_heatmap", 600, 260, func(c *ui.Context) { + year := 2026 + ui.Column(c).Padding(16).Children(func() { + CalendarHeatmap(c, &year, calendarValues(), CalendarHeatmapOptions{Frame: ChartFrame{Label: "Prayers", Height: 150}, WeekStart: WeekStartMonday}) + }) + }) +} diff --git a/chart_frame.go b/chart_frame.go new file mode 100644 index 0000000..9fdad75 --- /dev/null +++ b/chart_frame.go @@ -0,0 +1,260 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// ChartFrame is what every chart shares. +type ChartFrame struct { + // Label names the chart for assistive technology; required. + Label string + // Height is the plot height in DIPs; 0 means 240. + Height float32 + // Status shows loading or failure in the plot's place. + Status DataStatus + Error string + // Empty replaces the built-in "No data" text. + Empty string +} + +// ChartResult is a built chart and this frame's events. +type ChartResult struct { + Element *ui.Element + // Point is the hovered or focused mark, -1 for none. + Point int + changed, retry bool + toggled string + value bool +} + +// Changed reports that the readout moved to another mark. +func (r ChartResult) Changed() bool { return r.changed } + +// Retried reports a click on a failed load's retry. +func (r ChartResult) Retried() bool { return r.retry } + +// ValueChanged reports a changed selection, path, year or pause. +func (r ChartResult) ValueChanged() bool { return r.value } + +// Toggled returns the legend series switched in this frame. +func (r ChartResult) Toggled() (string, bool) { return r.toggled, r.toggled != "" } + +// chartKey is a legend entry: name, color and shape. +type chartKey struct { + Name string + Color ui.Color + Shape int +} + +// chartSpec is one chart's drawing and behavior. +type chartSpec struct { + // n counts the marks keys step through; 0 is empty. + n int + keys []chartKey + // toggle lets legend entries hide and show series. + toggle bool + draw func(p *ui.Painter, r ui.Rect, active int) + // pick returns the mark at (x, y), or -1. + pick func(r ui.Rect, x, y float32) int + readout func(i int) string + // move steps from mark i; nil steps in order. + move func(i int, key ui.Key) int + // activate runs on Enter, Space or a click. + activate func(i int) +} + +type chartState struct { + focus, last int + hidden map[string]bool +} + +// chart is a chart being built. +type chart struct { + c *ui.Context + frame ChartFrame + st *chartState + res ChartResult +} + +// newChart starts a chart; ask it which series are hidden. +func newChart(c *ui.Context, frame ChartFrame) *chart { + if frame.Label == "" || frame.Height < 0 { + panic("mujica: chart needs a Label and a non-negative Height") + } + if frame.Height == 0 { + frame.Height = 240 + } + ch := &chart{c: c, frame: frame} + ch.res.Element = ui.Column(c).Gap(Density(c).Unit() * 2).MinWidth(0) + ch.st = ui.Local(ch.res.Element, "mujica.chart", func() chartState { return chartState{focus: -1, last: -1, hidden: map[string]bool{}} }) + return ch +} + +// hidden reports whether the legend switched series name off. +func (ch *chart) hidden(name string) bool { return ch.st.hidden[name] } + +// build lays out legend, plot and readout; returns the plot. +func (ch *chart) build(spec chartSpec) (ChartResult, *ui.Element) { + c, k, st := ch.c, Tokens(ch.c), ch.st + u := Density(c).Unit() + var plot *ui.Element + ch.res.Element.Children(func() { + if len(spec.keys) > 0 { + ch.legend(spec) + } + box := ui.Box(c).Height(ch.frame.Height).FillWidth().MinWidth(0) + if ch.frame.Status == DataLoading || ch.frame.Status == DataFailed || spec.n == 0 { + st.focus = -1 + box.Children(func() { + ui.Column(c).Fill().Children(func() { + ch.res.retry = dataPlaceholder(c, ch.frame.Status, ch.frame.Error, ch.frame.Empty, msg(c, "chart.empty")) + }) + }) + ch.res.Point = -1 + ui.Box(c).Height(u * 5) + return + } + plot = box.Focusable().Label(ch.frame.Label).Role(ui.RoleGroup) + internal.Ring(plot, k.Focus, theme.ControlRadius) + st.focus = min(st.focus, spec.n-1) + ch.input(plot, spec) + active := -1 + if x, y, over := plot.PointerPosition(); over && !plot.IsDisabled() { + b := plot.Bounds() + active = spec.pick(ui.Rect{W: b.W, H: b.H}, x, y) + } + if active < 0 && plot.Focused() { + active = st.focus + } + ch.res.Point = active + plot.Draw(func(p *ui.Painter, r ui.Rect) { spec.draw(p, r, active) }) + text, col := msg(c, "chart.hint"), k.TextMuted + if active >= 0 { + text, col = spec.readout(active), k.Text + } + ui.Text(c, text).FontSize(FontSize(c, theme.CaptionSize)).TextColor(col).Role(ui.RoleStatus).SingleLine().Height(u * 5) + }) + ch.res.changed = ch.res.Point != st.last + st.last = ch.res.Point + return ch.res, plot +} + +// input moves the keyboard mark, and takes clicks on marks. +func (ch *chart) input(plot *ui.Element, spec chartSpec) { + st := ch.st + if plot.IsDisabled() { + return + } + to := st.focus + for _, key := range []ui.Key{ui.KeyLeft, ui.KeyRight, ui.KeyUp, ui.KeyDown} { + if !plot.Shortcut(0, key) { + continue + } + switch { + case st.focus < 0: + to = 0 + case spec.move != nil: + to = spec.move(st.focus, key) + case key == ui.KeyLeft || key == ui.KeyUp: + to = max(st.focus-1, 0) + default: + to = min(st.focus+1, spec.n-1) + } + } + if plot.Shortcut(0, ui.KeyHome) { + to = 0 + } + if plot.Shortcut(0, ui.KeyEnd) { + to = spec.n - 1 + } + if plot.Shortcut(0, ui.KeyEscape) { + to = -1 + } + if to != st.focus { + st.focus = to + if to >= 0 { + ch.c.Announce(spec.readout(to)) + } + slog.Debug("mujica: chart focus", "label", ch.frame.Label, "mark", to) + } + act := st.focus >= 0 && (plot.Shortcut(0, ui.KeyEnter) || plot.Shortcut(0, ui.KeySpace)) + if plot.Clicked() { + plot.Focus() + x, y, _ := plot.PointerPosition() + b := plot.Bounds() + if i := spec.pick(ui.Rect{W: b.W, H: b.H}, x, y); i >= 0 { + st.focus, act = i, true + } + } + if act && spec.activate != nil { + spec.activate(st.focus) + } +} + +// legend shows the series keys; toggling ones are check boxes. +func (ch *chart) legend(spec chartSpec) { + c, k, st := ch.c, Tokens(ch.c), ch.st + u := Density(c).Unit() + ui.Row(c).Wrap().Gap(u * 3).Children(func() { + for _, key := range spec.keys { + ui.Row(c).Key(key.Name).Children(func() { + on := !st.hidden[key.Name] + var e *ui.Element + if spec.toggle { + e = ui.CheckboxBase(c, &on).Disabled(ch.res.Element.IsDisabled()).Label(key.Name) + internal.Ring(e, k.Focus, theme.ControlRadius) + if e.Changed() && !e.IsDisabled() { + st.hidden[key.Name] = !on + ch.res.toggled = key.Name + slog.Debug("mujica: chart toggle", "series", key.Name, "visible", on) + } + } else { + e = ui.Row(c) + } + e.MinHeight(theme.MinHitSize).Gap(u*2).AlignItems(ui.Center).Padding(0, u).Radius(theme.ControlRadius) + col := key.Color + if !on { + col = k.TextMuted + } + e.Children(func() { + ui.Box(c).Size(12, 12).Shrink(0).Draw(func(p *ui.Painter, r ui.Rect) { + if on { + internal.Marker(p, key.Shape, r.X+6, r.Y+6, 10, col) + } else { + p.Stroke(r, col, 2, 1) + } + }) + t := ui.Text(c, key.Name).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.Text) + if !on { + t.Strikethrough().TextColor(k.TextMuted) + } + }) + }) + } + }) +} + +// chartText draws s anchored at (x, y) by ax, ay. +func chartText(p *ui.Painter, s string, x, y, size float32, col ui.Color, ax, ay float32) (w, h float32) { + w, h = p.MeasureText(0, ui.Span{Text: s, Size: size}) + p.Text(x-w*ax, y-h*ay, s, size, col) + return w, h +} + +// chartInset is r less room for axis labels. +func chartInset(r ui.Rect, left, bottom float32) ui.Rect { + return ui.Rect{X: r.X + left, Y: r.Y + 8, W: max(r.W-left-12, 1), H: max(r.H-bottom-8, 1)} +} + +// chartInk is Text or Surface, whichever reads better on bg. +func chartInk(k theme.Tokens, bg ui.Color) ui.Color { + if theme.Contrast(k.Text, bg) >= theme.Contrast(k.Surface, bg) { + return k.Text + } + return k.Surface +} diff --git a/chart_frame_test.go b/chart_frame_test.go new file mode 100644 index 0000000..a678038 --- /dev/null +++ b/chart_frame_test.go @@ -0,0 +1,108 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +// chartBuilders builds every Charts I component with a small data set. +func chartBuilders() map[string]func(c *ui.Context) ChartResult { + year := 2026 + var path, path2 []string + var sel []ScatterKey + var graph NetworkGraphState + var rt RealtimeChartState + buf := NewRealtimeBuffer(10, "a") + buf.Append(rtStart, 1) + buf.Append(rtStart.Add(time.Second), 2) + target := 3.0 + f := ChartFrame{Label: "Under test"} + return map[string]func(c *ui.Context) ChartResult{ + "line": func(c *ui.Context) ChartResult { return LineChart(c, lineSeries(), LineChartOptions{Frame: f}) }, + "area": func(c *ui.Context) ChartResult { return AreaChart(c, lineSeries(), AreaChartOptions{Frame: f}) }, + "bar": func(c *ui.Context) ChartResult { return BarChart(c, barCats, barSeries(), BarChartOptions{Frame: f}) }, + "pie": func(c *ui.Context) ChartResult { return PieChart(c, pieSlices, PieChartOptions{Frame: f}) }, + "scat": func(c *ui.Context) ChartResult { + return ScatterChart(c, &sel, scatterGroups, ScatterChartOptions{Frame: f}) + }, + "radar": func(c *ui.Context) ChartResult { + return RadarChart(c, radarAxes, radarSeries(), RadarChartOptions{Frame: f}) + }, + "heat": func(c *ui.Context) ChartResult { + return HeatmapChart(c, heatRows, heatCols, heatValues(), HeatmapChartOptions{Frame: f}) + }, + "cal": func(c *ui.Context) ChartResult { + return CalendarHeatmap(c, &year, calendarValues(), CalendarHeatmapOptions{Frame: f}) + }, + "hist": func(c *ui.Context) ChartResult { return Histogram(c, []float64{1, 2, 3}, HistogramOptions{Frame: f}) }, + "box": func(c *ui.Context) ChartResult { return BoxPlot(c, boxGroups, BoxPlotOptions{Frame: f}) }, + "fall": func(c *ui.Context) ChartResult { + return WaterfallChart(c, waterfallSteps, WaterfallChartOptions{Frame: f}) + }, + "funnel": func(c *ui.Context) ChartResult { return FunnelChart(c, funnelStages, FunnelChartOptions{Frame: f}) }, + "bullet": func(c *ui.Context) ChartResult { + return BulletChart(c, 2, BulletChartOptions{Frame: f, Target: &target, Bands: []float64{1, 4}}) + }, + "spark": func(c *ui.Context) ChartResult { return Sparkline(c, sparkValues, SparklineOptions{Frame: f}) }, + "gauge": func(c *ui.Context) ChartResult { + return Gauge(c, 72, GaugeOptions{Frame: f, Max: 100, Segments: gaugeSegments}) + }, + "tree": func(c *ui.Context) ChartResult { return Treemap(c, &path, chartTree(), TreemapOptions{Frame: f}) }, + "sun": func(c *ui.Context) ChartResult { return Sunburst(c, &path2, chartTree(), SunburstOptions{Frame: f}) }, + "sankey": func(c *ui.Context) ChartResult { + return SankeyChart(c, sankeyNodes, sankeyLinks, SankeyChartOptions{Frame: f}) + }, + "graph": func(c *ui.Context) ChartResult { + return NetworkGraph(c, &graph, graphNodes, graphEdges, NetworkGraphOptions{Frame: f}) + }, + "rt": func(c *ui.Context) ChartResult { + return RealtimeChart(c, &rt, buf, RealtimeChartOptions{Frame: f, Window: time.Minute}) + }, + } +} + +func TestChartsIgnoreInputWhenDisabled(t *testing.T) { + for name, build := range chartBuilders() { + values := 0 + h := &chartHarness{disabled: true, build: func(c *ui.Context) ChartResult { + r := build(c) + if r.ValueChanged() || r.Retried() { + values++ + } + if _, ok := r.Toggled(); ok { + values++ + } + return r + }} + tt := ui.NewTester(h.view, 560, 480) + for range 6 { + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyEnter) + tt.Key(0, ui.KeySpace) + } + b := h.res.Element.Bounds() + tt.Click("Under test") + tt.ClickAt(b.X+b.W/2, b.Y+b.H/2) + if h.res.Point != -1 || values != 0 { + t.Errorf("%s: disabled chart took input: point %d, events %d", name, h.res.Point, values) + } + } +} + +func TestChartsEnterAtFirstMark(t *testing.T) { + for name, build := range chartBuilders() { + h := &chartHarness{build: build} + tt := ui.NewTester(h.view, 560, 480) + tabTo(t, tt, "Under test") + tt.Key(0, ui.KeyRight) + if h.res.Point != 0 || chartReadout(tt) == msg2(tt) { + t.Errorf("%s: first arrow read point %d", name, h.res.Point) + } + } +} + +// msg2 is the hint line, read back to tell it from a readout. +func msg2(*ui.Tester) string { return "Focus the chart and use the arrow keys to read values" } diff --git a/chart_series.go b/chart_series.go new file mode 100644 index 0000000..2e992bc --- /dev/null +++ b/chart_series.go @@ -0,0 +1,206 @@ +package mujica + +import ( + "fmt" + "math" + "sort" + "strconv" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" +) + +// ChartSeries is named values; NaN marks a missing one. +type ChartSeries struct { + Name string + Values []float64 +} + +type chartMemoEntry struct { + deps any + val any +} + +// chartMemo recomputes f only when the comparable deps change. +func chartMemo[T any](ch *chart, name string, deps any, f func() T) T { + m := ui.Local(ch.res.Element, "mujica.memo."+name, func() chartMemoEntry { return chartMemoEntry{} }) + if m.val == nil || m.deps != deps { + m.deps, m.val = deps, f() + } + return m.val.(T) +} + +// chartID identifies a slice by first element and length. +func chartID[T any](s []T) string { + if len(s) == 0 { + return "0" + } + return fmt.Sprintf("%p:%d", &s[0], len(s)) +} + +// chartSeriesID identifies series data and the hidden set together. +func chartSeriesID(ch *chart, series []ChartSeries) string { + var b strings.Builder + for _, s := range series { + fmt.Fprintf(&b, "%s|%s|%v;", s.Name, chartID(s.Values), ch.hidden(s.Name)) + } + return b.String() +} + +// chartCheckSeries panics on duplicate names or unequal lengths. +func chartCheckSeries(series []ChartSeries) int { + if len(series) == 0 { + return 0 + } + n := len(series[0].Values) + seen := map[string]bool{} + for _, s := range series { + if s.Name == "" || seen[s.Name] || len(s.Values) != n { + panic("mujica: chart series need unique names and equal lengths: " + s.Name) + } + seen[s.Name] = true + } + return n +} + +// chartX is an ascending axis of numbers, times or indices. +type chartX struct { + vals []float64 + times bool + // d0 and d1, when d1 > d0, fix the domain. + d0, d1 float64 +} + +func newChartX(n int, x []float64, times []time.Time) chartX { + switch { + case x != nil && times != nil: + panic("mujica: chart takes X or Times, not both") + case x != nil && len(x) != n, times != nil && len(times) != n: + panic("mujica: chart X or Times length differs from the series") + } + a := chartX{vals: x, times: times != nil} + if times != nil { + a.vals = make([]float64, n) + for i, t := range times { + a.vals[i] = float64(t.UnixNano()) / 1e9 + } + } + if a.vals == nil { + a.vals = make([]float64, n) + for i := range a.vals { + a.vals[i] = float64(i) + } + } + if !sort.Float64sAreSorted(a.vals) { + panic("mujica: chart X or Times must ascend") + } + return a +} + +func (a chartX) scale(plot ui.Rect) internal.Linear { + d0, d1 := a.vals[0], a.vals[len(a.vals)-1] + if a.d1 > a.d0 { + d0, d1 = a.d0, a.d1 + } + return internal.Linear{D0: d0, D1: d1, R0: float64(plot.X), R1: float64(plot.X + plot.W)} +} + +func (a chartX) label(i int) string { + if a.times { + return chartTime(a.vals[i]).Format("2006-01-02 15:04:05") + } + return strconv.FormatFloat(a.vals[i], 'g', 6, 64) +} + +// ticks returns tick positions and labels along plot. +func (a chartX) ticks(plot ui.Rect) ([]float32, []string) { + s := a.scale(plot) + n := max(2, int(plot.W/90)) + var xs []float32 + var labels []string + if a.times { + ts, layout := internal.TimeTicks(chartTime(s.D0), chartTime(s.D1), n) + for _, t := range ts { + xs = append(xs, s.Map(float64(t.UnixNano())/1e9)) + labels = append(labels, t.Format(layout)) + } + return xs, labels + } + lo, hi, step := internal.Nice(s.D0, s.D1, n) + for _, t := range internal.Ticks(lo, hi, step) { + if t >= s.D0 && t <= s.D1 { + xs = append(xs, s.Map(t)) + labels = append(labels, internal.FormatTick(t, step)) + } + } + return xs, labels +} + +// nearest returns the index whose x is closest to v. +func (a chartX) nearest(v float64) int { + i := sort.SearchFloat64s(a.vals, v) + if i == len(a.vals) || i > 0 && v-a.vals[i-1] < a.vals[i]-v { + i-- + } + return i +} + +func chartTime(sec float64) time.Time { + return time.Unix(0, int64(math.Round(sec*1e9))).UTC() +} + +// chartYDomain spans visible finite values, optionally with zero. +func chartYDomain(series []ChartSeries, hidden func(string) bool, withZero bool) (lo, hi float64, ok bool) { + lo, hi = math.Inf(1), math.Inf(-1) + for _, s := range series { + if hidden(s.Name) { + continue + } + for _, v := range s.Values { + if !math.IsNaN(v) { + lo, hi = min(lo, v), max(hi, v) + } + } + } + if math.IsInf(lo, 1) { + return 0, 0, false + } + if withZero { + lo, hi = min(lo, 0), max(hi, 0) + } + return lo, hi, true +} + +// chartValue formats v, or names a missing value. +func chartValue(c *ui.Context, v float64, format func(float64) string) string { + if math.IsNaN(v) { + return msg(c, "chart.missing") + } + if format != nil { + return format(v) + } + return strconv.FormatFloat(v, 'g', 6, 64) +} + +// chartRuns calls f per finite run, thinned to pixel columns. +func chartRuns(vals []float64, x func(i int) float32, f func(idx []int)) { + for i := 0; i < len(vals); { + if math.IsNaN(vals[i]) { + i++ + continue + } + j := i + for j < len(vals) && !math.IsNaN(vals[j]) { + j++ + } + run := internal.Columns(j-i, func(k int) float32 { return x(i + k) }, func(k int) float64 { return vals[i+k] }) + for k := range run { + run[k] += i + } + f(run) + i = j + } +} diff --git a/chart_tree.go b/chart_tree.go new file mode 100644 index 0000000..4f51d5a --- /dev/null +++ b/chart_tree.go @@ -0,0 +1,171 @@ +package mujica + +import ( + "log/slog" + "math" + "slices" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// ChartNode is a hierarchy node; branches sum their leaves. +type ChartNode struct { + Name string + Value float64 + Children []ChartNode +} + +// total is the node's value, or its children's sum. +func (n ChartNode) total() float64 { + if len(n.Children) == 0 { + return n.Value + } + s := 0.0 + for _, ch := range n.Children { + s += ch.total() + } + return s +} + +// chartCheckTree panics on unnamed, duplicate-sibling or negative nodes. +func chartCheckTree(n ChartNode) { + if n.Name == "" || n.Value < 0 || math.IsNaN(n.Value) || math.IsInf(n.Value, 0) { + panic("mujica: chart nodes need a name and a finite value ≥ 0") + } + seen := map[string]bool{} + for _, ch := range n.Children { + if seen[ch.Name] { + panic("mujica: chart node has two children named " + ch.Name) + } + seen[ch.Name] = true + chartCheckTree(ch) + } +} + +// chartDescend returns the node at path, panicking if unknown. +func chartDescend(root ChartNode, path []string) ChartNode { + n := root + for _, name := range path { + i := slices.IndexFunc(n.Children, func(ch ChartNode) bool { return ch.Name == name }) + if i < 0 { + panic("mujica: chart path has no node " + name) + } + n = n.Children[i] + } + return n +} + +// chartPath shows Back and the breadcrumb; reports a move up. +func chartPath(c *ui.Context, root string, path *[]string, disabled bool) bool { + k := Tokens(c) + u := Density(c).Unit() + moved := false + ui.Row(c).Gap(u).AlignItems(ui.Center).Wrap().Children(func() { + back := iconAction(c, icons.Must("chevron-left"), msg(c, "chart.back")).Disabled(disabled || len(*path) == 0) + if back.Clicked() && !back.IsDisabled() { + *path, moved = (*path)[:len(*path)-1], true + } + names := append([]string{root}, *path...) + for i, name := range names { + if i > 0 { + ui.Text(c, "›").TextColor(k.TextMuted) + } + if i == len(names)-1 { + ui.Text(c, name).FontWeight(600).SingleLine() + continue + } + crumb := ui.ButtonBase(c).MinHeight(theme.MinHitSize).Padding(0, u).Radius(theme.ControlRadius).Disabled(disabled).TextColor(k.AccentText) + internal.Ring(crumb, k.Focus, theme.ControlRadius) + crumb.Children(func() { ui.Text(c, name).Underline().SingleLine() }) + if crumb.Clicked() && !crumb.IsDisabled() { + *path, moved = slices.Clone((*path)[:i]), true + } + } + }) + if moved { + slog.Debug("mujica: chart path", "path", strings.Join(*path, "/")) + } + return moved +} + +// chartFit shortens s with an ellipsis to fit w. +func chartFit(p *ui.Painter, s string, w, size float32) string { + r := []rune(s) + for len(r) > 0 { + t := string(r) + if len(r) < len([]rune(s)) { + t += "…" + } + if tw, _ := p.MeasureText(0, ui.Span{Text: t, Size: size}); tw <= w { + return t + } + r = r[:len(r)-1] + } + return "" +} + +// squarify tiles descending values into near-square rectangles. +func squarify(values []float64, r ui.Rect) []ui.Rect { + out := make([]ui.Rect, len(values)) + total := 0.0 + for _, v := range values { + total += v + } + if total <= 0 { + return out + } + scale := float64(r.W*r.H) / total + for i := 0; i < len(values); { + side := float64(min(r.W, r.H)) + j, best := i+1, math.Inf(1) + for ; j <= len(values); j++ { + worst := squarifyWorst(values[i:j], side, scale) + if worst > best { + break + } + best = worst + } + j-- + row := 0.0 + for _, v := range values[i:j] { + row += v * scale + } + thick := float32(row / side) + at := float32(0) + for k := i; k < j; k++ { + l := float32(values[k]*scale) / thick + if r.W >= r.H { + out[k] = ui.Rect{X: r.X, Y: r.Y + at, W: thick, H: l} + } else { + out[k] = ui.Rect{X: r.X + at, Y: r.Y, W: l, H: thick} + } + at += l + } + if r.W >= r.H { + r.X, r.W = r.X+thick, r.W-thick + } else { + r.Y, r.H = r.Y+thick, r.H-thick + } + i = j + } + return out +} + +// squarifyWorst is a row's worst aspect ratio along side. +func squarifyWorst(row []float64, side, scale float64) float64 { + sum, lo, hi := 0.0, math.Inf(1), 0.0 + for _, v := range row { + a := v * scale + sum, lo, hi = sum+a, min(lo, a), max(hi, a) + } + if lo == 0 { + return math.Inf(1) + } + s2 := side * side + return max(s2*hi/(sum*sum), sum*sum/(s2*lo)) +} diff --git a/data_table.go b/data_table.go index b5ea36c..9d36c5e 100644 --- a/data_table.go +++ b/data_table.go @@ -98,7 +98,7 @@ func (v DataTableView) Submitted() bool { return v.submitted } // SortChanged reports a header click or menu choice that changed State.Sort. func (v DataTableView) SortChanged() bool { return v.sorted } -// Retried reports a click on the retry action of a failed load. +// Retried reports a click on a failed load's retry. func (v DataTableView) Retried() bool { return v.retry } const dataTableMarkID = "mujica.select" diff --git a/docs/components/101-line-chart.md b/docs/components/101-line-chart.md new file mode 100644 index 0000000..aefc23b --- /dev/null +++ b/docs/components/101-line-chart.md @@ -0,0 +1,54 @@ +# 101 LineChart 折线图 + +## 用途 + +多序列折线图:数值或时间横轴,缺值(NaN)处断开,悬停与键盘读数,图例勾选框控制序列显隐。大数据按像素列抽稀绘制,10 万点保持流畅。 + +## 最小示例 + +```go +series := []mujica.ChartSeries{ + {Name: "Pews", Values: []float64{3, 5, math.NaN(), 4, 8}}, + {Name: "Candles", Values: []float64{5, 2, 6, 7, 1}}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.LineChart(c, series, mujica.LineChartOptions{Frame: mujica.ChartFrame{Label: "Chapel"}}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func LineChart(c *ui.Context, series []ChartSeries, opts LineChartOptions) ChartResult`;`ChartSeries{Name, Values}`,各序列等长且名称唯一。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `X` | `[]float64` | nil | 点 i 的横坐标,须递增;nil 时为下标。 | +| `Times` | `[]time.Time` | nil | 时间轴;与 `X` 二选一,须递增。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 读数中的数值格式。 | + +## 状态 + +默认、悬停或键盘读数(竖线 + 各序列放大标记)、隐藏序列(图例划线、空心标记)、加载、失败、无数据(全部为缺值时)。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试;`Toggled()` 返回本帧被切换显隐的序列名。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):在数据点之间移动,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 +- 图例勾选框:Space 切换序列显隐。 + +## 限制 + +- 数据切片以首元素地址与长度识别;原地修改数据后请传入新切片,缓存的坐标范围才会更新。 +- 每条序列除颜色外还有不同形状的标记(圆、方、菱形、三角),密集时按间隔绘制。 diff --git a/docs/components/102-area-chart.md b/docs/components/102-area-chart.md new file mode 100644 index 0000000..bf747b7 --- /dev/null +++ b/docs/components/102-area-chart.md @@ -0,0 +1,54 @@ +# 102 AreaChart 面积图 + +## 用途 + +面积图:单序列填充到基线,或多序列堆叠;基线可配置;悬停与键盘读数显示各序列原值(不是堆叠后的值)。 + +## 最小示例 + +```go +series := []mujica.ChartSeries{ + {Name: "Matins", Values: []float64{3, 4, 6, 5}}, + {Name: "Vespers", Values: []float64{2, 3, 2, 4}}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AreaChart(c, series, mujica.AreaChartOptions{Frame: mujica.ChartFrame{Label: "Attendance"}, Stacked: true}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func AreaChart(c *ui.Context, series []ChartSeries, opts AreaChartOptions) ChartResult`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `X`, `Times` | | nil | 同 LineChart。 | +| `Stacked` | `bool` | false | 可见序列依次堆叠;隐藏序列不参与堆叠。 | +| `Baseline` | `float64` | `0` | 面积的起始值;坐标轴总包含基线。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 读数格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试;`Toggled()` 同 LineChart。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):在数据点之间移动,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 + +## 限制 + +- 缺值处面积断开;堆叠时缺值按 0 计入后续序列。 +- 填充为半透明的序列色,边线保持实色以满足 3:1 对比。 diff --git a/docs/components/103-bar-chart.md b/docs/components/103-bar-chart.md new file mode 100644 index 0000000..d162090 --- /dev/null +++ b/docs/components/103-bar-chart.md @@ -0,0 +1,52 @@ +# 103 BarChart 柱状图 + +## 用途 + +柱状图:纵向或横向,分组或堆叠,支持负值与柱端数值标签,键盘逐柱读数。 + +## 最小示例 + +```go +categories := []string{"Nave", "Choir", "Crypt"} +series := []mujica.ChartSeries{{Name: "Gold", Values: []float64{4, -2, 3}}, {Name: "Silver", Values: []float64{2, 5, 1}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BarChart(c, categories, series, mujica.BarChartOptions{Frame: mujica.ChartFrame{Label: "Tithes"}, Labels: true}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func BarChart(c *ui.Context, categories []string, series []ChartSeries, opts BarChartOptions) ChartResult`;每条序列的值与类别一一对应,NaN 不画柱。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Horizontal` | `bool` | false | 类别在纵轴,柱横向延伸。 | +| `Stacked` | `bool` | false | 每个类别一根柱,正值向上、负值向下堆叠。 | +| `Labels` | `bool` | false | 在柱端写出数值(堆叠时不写)。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 数值格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 选中柱以描边标出,柱内有序列形状标记。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试;多序列时 `Toggled()` 报告图例切换。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):逐柱移动(按类别、再按序列),读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 + +## 限制 + +- 极细的柱仍有 6 DIP 的悬停范围。 +- 类别标签过密时会跳过重叠的标签,读数仍包含完整类别名。 diff --git a/docs/components/104-pie-chart.md b/docs/components/104-pie-chart.md new file mode 100644 index 0000000..a2e760c --- /dev/null +++ b/docs/components/104-pie-chart.md @@ -0,0 +1,50 @@ +# 104 PieChart 饼图 + +## 用途 + +饼图与环形图:扇区按占比绘制并标注百分比;过窄的扇区可合并为“其他”;环形图中心显示总计。 + +## 最小示例 + +```go +slices := []mujica.ChartSlice{{Label: "Wax", Value: 50}, {Label: "Oil", Value: 30}, {Label: "Salt", Value: 4}, {Label: "Ash", Value: 3}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.PieChart(c, slices, mujica.PieChartOptions{Frame: mujica.ChartFrame{Label: "Stores"}, Donut: true, MinAngle: 20}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func PieChart(c *ui.Context, slices []ChartSlice, opts PieChartOptions) ChartResult`;`ChartSlice{Label, Value}`,值须为有限且 ≥ 0。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Donut` | `bool` | false | 环形图,中心写总计。 | +| `MinAngle` | `float64` | `0` | 小于该角度(度)的扇区达到两个及以上时合并为“其他”;须在 [0, 360)。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 数值格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 当前扇区向外凸出。总计为 0 时显示无数据。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):在数据点之间移动,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 + +## 限制 + +- 只有一个窄扇区时不合并,以免“其他”只代表一项。 +- 扇区内的形状标记与百分比文字按对比度自动选用正文色或表面色。 diff --git a/docs/components/105-scatter-chart.md b/docs/components/105-scatter-chart.md new file mode 100644 index 0000000..baf1af2 --- /dev/null +++ b/docs/components/105-scatter-chart.md @@ -0,0 +1,52 @@ +# 105 ScatterChart 散点图 + +## 用途 + +散点图:按分组着色并配不同形状,点大小可映射为气泡,拖动框选或用键盘选中点。 + +## 最小示例 + +```go +var selected []mujica.ScatterKey +groups := []mujica.ScatterGroup{{Name: "Monks", Points: []mujica.ScatterPoint{{X: 1, Y: 2, Size: 4}, {X: 3, Y: 5, Size: 9}}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ScatterChart(c, &selected, groups, mujica.ScatterChartOptions{Frame: mujica.ChartFrame{Label: "Choir"}, Bubbles: true}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ScatterChart(c *ui.Context, selected *[]ScatterKey, groups []ScatterGroup, opts ScatterChartOptions) ChartResult`;`ScatterGroup{Name, Points []ScatterPoint{X, Y, Size}}`,`ScatterKey{Group, Point}` 标识一个点。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Bubbles` | `bool` | false | 按 `Size` 映射点面积(直径 4–18 DIP)。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 读数格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 选中的点外加圆环,读数注明“已选”。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试;`ValueChanged()` 表示 `*selected` 被框选或键盘改变;多组时 `Toggled()` 报告图例切换。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):在数据点之间移动,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 +- Enter/Space:选中或取消当前点。 +- 在绘图区拖动:框选,替换现有选择。 + +## 限制 + +- 框选替换选择,不支持按住修饰键追加。 +- 点数较多时逐点绘制,没有抽稀。 diff --git a/docs/components/106-radar-chart.md b/docs/components/106-radar-chart.md new file mode 100644 index 0000000..35a017e --- /dev/null +++ b/docs/components/106-radar-chart.md @@ -0,0 +1,49 @@ +# 106 RadarChart 雷达图 + +## 用途 + +雷达图:三个及以上维度,多序列多边形,刻度环,按维度悬停或键盘读数。 + +## 最小示例 + +```go +axes := []string{"Voice", "Latin", "Chant", "Organ"} +series := []mujica.ChartSeries{{Name: "Agnès", Values: []float64{8, 6, 9, 4}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.RadarChart(c, axes, series, mujica.RadarChartOptions{Frame: mujica.ChartFrame{Label: "Skills"}}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func RadarChart(c *ui.Context, axes []string, series []ChartSeries, opts RadarChartOptions) ChartResult`;每条序列每个维度一个值,值须 ≥ 0。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Max` | `float64` | 自动取整 | 外环代表的值;0 按数据向上取整。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 读数格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 当前维度的轴线加粗、标签变为正文色。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试;多序列时 `Toggled()` 报告图例切换。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):按维度移动,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 + +## 限制 + +- 缺值按 0 画在中心,读数显示“无数值”。 diff --git a/docs/components/107-heatmap-chart.md b/docs/components/107-heatmap-chart.md new file mode 100644 index 0000000..b931ea2 --- /dev/null +++ b/docs/components/107-heatmap-chart.md @@ -0,0 +1,48 @@ +# 107 HeatmapChart 热力图 + +## 用途 + +二维矩阵热力图:按值分五级着色,右侧色阶图例标出最小与最大值;单元格读数;空值单元格为虚线框。 + +## 最小示例 + +```go +rows, cols := []string{"Mon", "Tue"}, []string{"Matins", "Lauds", "Vespers"} +values := [][]float64{{1, 4, 9}, {3, math.NaN(), 7}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.HeatmapChart(c, rows, cols, values, mujica.HeatmapChartOptions{Frame: mujica.ChartFrame{Label: "Hours"}}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func HeatmapChart(c *ui.Context, rows, cols []string, values [][]float64, opts HeatmapChartOptions) ChartResult`;`values[行][列]`,NaN 为空值。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 单元格与读数格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 单元格足够大时直接写出数值,不只依赖颜色。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试。 + +## 键盘操作 + +- Tab:聚焦热力图。 +- ←/→:同一行左右移动;↑/↓:同一列上下移动;第一次按键进入左上角。 +- Home/End:第一个/最后一个单元格;Escape:清除读数。 + +## 限制 + +- 颜色分五级,不做连续渐变。 diff --git a/docs/components/108-calendar-heatmap.md b/docs/components/108-calendar-heatmap.md new file mode 100644 index 0000000..26f6a30 --- /dev/null +++ b/docs/components/108-calendar-heatmap.md @@ -0,0 +1,50 @@ +# 108 CalendarHeatmap 日历热力图 + +## 用途 + +按日的贡献图:一列一周,按当年最大值分四级着色;年份切换;周起始可配置;逐日读数。 + +## 最小示例 + +```go +year := 2026 +values := map[mujica.Date]float64{{Year: 2026, Month: time.March, Day: 4}: 5} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CalendarHeatmap(c, &year, values, mujica.CalendarHeatmapOptions{Frame: mujica.ChartFrame{Label: "Prayers"}}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func CalendarHeatmap(c *ui.Context, year *int, values map[Date]float64, opts CalendarHeatmapOptions) ChartResult`;`*year` 须在 1–9999。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `WeekStart` | `WeekStart` | 跟随语言 | 每列第一行是星期几。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 读数格式。 | + +## 状态 + +默认、无记录日(浅色格)、四级色阶、悬停或键盘读数(描边)、加载、失败。下方图例从“少”到“多”。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试;`ValueChanged()` 表示上一年/下一年按钮改变了 `*year`。 + +## 键盘操作 + +- Tab:年份按钮,再到日历。 +- ←/→:前后一周;↑/↓:前后一天;Home/End:全年第一天与最后一天。 +- 上一年/下一年按钮:Enter/Space。 + +## 限制 + +- 方格较小,只作读数目标,不是独立操作,因此不要求 28 DIP 命中区。 +- 值 ≤ 0 视为无记录。 diff --git a/docs/components/109-histogram.md b/docs/components/109-histogram.md new file mode 100644 index 0000000..3817d33 --- /dev/null +++ b/docs/components/109-histogram.md @@ -0,0 +1,50 @@ +# 109 Histogram 直方图 + +## 用途 + +分箱计数直方图:箱数或箱宽可配置,可切换为累计模式;分箱只在数据或参数变化时计算一次。 + +## 最小示例 + +```go +values := []float64{1, 2, 2, 3, 4, 5, 9, 10} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Histogram(c, values, mujica.HistogramOptions{Frame: mujica.ChartFrame{Label: "Ages"}, BinWidth: 5}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func Histogram(c *ui.Context, values []float64, opts HistogramOptions) ChartResult`;NaN 与无穷值被忽略。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Bins` | `int` | Sturges 规则 | 箱数;负数 panic。 | +| `BinWidth` | `float64` | 0 | 箱宽;设定时优先于 `Bins`,箱边取箱宽的整数倍。超过 10000 箱 panic。 | +| `Cumulative` | `bool` | false | 每箱计入不超过其上界的全部值。 | +| `Format` | `func(float64) string` | 按箱宽取精度 | 箱边格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):逐箱移动,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 + +## 限制 + +- 按箱数分箱时最后一箱包含上界,读数用 `]` 表示。 diff --git a/docs/components/110-box-plot.md b/docs/components/110-box-plot.md new file mode 100644 index 0000000..bd80246 --- /dev/null +++ b/docs/components/110-box-plot.md @@ -0,0 +1,47 @@ +# 110 BoxPlot 箱线图 + +## 用途 + +箱线图:四分位箱、中位线、1.5 倍四分距内的须线与离群点,多组对比。统计只在数据变化时计算。 + +## 最小示例 + +```go +groups := []mujica.BoxGroup{{Name: "Choir", Values: []float64{1, 2, 3, 4, 5, 40}}, {Name: "Nave", Values: []float64{4, 5, 6, 7}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BoxPlot(c, groups, mujica.BoxPlotOptions{Frame: mujica.ChartFrame{Label: "Hymns"}}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func BoxPlot(c *ui.Context, groups []BoxGroup, opts BoxPlotOptions) ChartResult`;`BoxGroup{Name, Values}`,名称必填。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 读数格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 离群点画为空心圆。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):按组移动,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 + +## 限制 + +- 四分位数用线性插值计算。 diff --git a/docs/components/111-waterfall-chart.md b/docs/components/111-waterfall-chart.md new file mode 100644 index 0000000..2dfb8c9 --- /dev/null +++ b/docs/components/111-waterfall-chart.md @@ -0,0 +1,52 @@ +# 111 WaterfallChart 瀑布图 + +## 用途 + +瀑布图:增减项累计,小计与总计柱显示累计值;增加为 Success 色并配 ▲,减少为 Danger 色并配 ▼,合计为中性色配 ■,柱端写出带符号的数值。 + +## 最小示例 + +```go +steps := []mujica.WaterfallStep{ + {Label: "Tithes", Value: 12}, + {Label: "Repairs", Value: -5}, + {Label: "Year", Kind: mujica.WaterfallTotal}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.WaterfallChart(c, steps, mujica.WaterfallChartOptions{Frame: mujica.ChartFrame{Label: "Ledger"}}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func WaterfallChart(c *ui.Context, steps []WaterfallStep, opts WaterfallChartOptions) ChartResult`;`WaterfallStep{Label, Value, Kind}`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `steps[i].Kind` | `WaterfallKind` | `WaterfallDelta` | `WaterfallDelta` 累加;`WaterfallSubtotal`、`WaterfallTotal` 显示当前累计,`Value` 须为 0。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 数值格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):逐柱移动,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 + +## 限制 + +- 小计与总计都显示到该步为止的累计值,不清零。 diff --git a/docs/components/112-funnel-chart.md b/docs/components/112-funnel-chart.md new file mode 100644 index 0000000..436180c --- /dev/null +++ b/docs/components/112-funnel-chart.md @@ -0,0 +1,47 @@ +# 112 FunnelChart 漏斗图 + +## 用途 + +漏斗图:阶段宽度与值成比例,右侧写出值与相对上一阶段的转化率;读数同时给出相对首阶段的比例。 + +## 最小示例 + +```go +stages := []mujica.ChartSlice{{Label: "Visitors", Value: 1000}, {Label: "Novices", Value: 400}, {Label: "Vows", Value: 100}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.FunnelChart(c, stages, mujica.FunnelChartOptions{Frame: mujica.ChartFrame{Label: "Order"}}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func FunnelChart(c *ui.Context, stages []ChartSlice, opts FunnelChartOptions) ChartResult`;值须为有限且 ≥ 0。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 数值格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 全部为 0 时显示无数据。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):逐阶段移动,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 + +## 限制 + +- 上一阶段为 0 时转化率显示“—”。 diff --git a/docs/components/113-bullet-chart.md b/docs/components/113-bullet-chart.md new file mode 100644 index 0000000..aab7ffa --- /dev/null +++ b/docs/components/113-bullet-chart.md @@ -0,0 +1,51 @@ +# 113 BulletChart 子弹图 + +## 用途 + +子弹图:实际值的细条、目标值的垂直线与定性区间带,可横向或纵向。 + +## 最小示例 + +```go +target := 250.0 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BulletChart(c, 270, mujica.BulletChartOptions{Frame: mujica.ChartFrame{Label: "Alms"}, Target: &target, Bands: []float64{150, 225, 300}}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func BulletChart(c *ui.Context, value float64, opts BulletChartOptions) ChartResult`;值须 ≥ 0。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `72` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Target` | `*float64` | nil | 目标值,画为与刻度垂直的粗线。 | +| `Bands` | `[]float64` | nil | 各区间的上界,须为正且递增。 | +| `Max` | `float64` | 自动取整 | 刻度终点;0 按值、目标与区间取整。 | +| `Vertical` | `bool` | false | 纵向摆放。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 数值格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 区间由浅到深的中性色带表示,读数写出区间范围。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):依次读实际值、目标值与各区间,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 + +## 限制 + +- 超出 `Max` 的值画到刻度终点,读数仍为原值。 diff --git a/docs/components/114-sparkline.md b/docs/components/114-sparkline.md new file mode 100644 index 0000000..7ff932f --- /dev/null +++ b/docs/components/114-sparkline.md @@ -0,0 +1,48 @@ +# 114 Sparkline 迷你图 + +## 用途 + +行内迷你图:折线、柱形或面积,无坐标轴;末值以菱形标记并在右侧写出数值;聚焦后可逐点读数。 + +## 最小示例 + +```go +values := []float64{3, 5, 4, 7, 6, 9} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Sparkline(c, values, mujica.SparklineOptions{Frame: mujica.ChartFrame{Label: "Bells"}, Kind: mujica.SparklineArea}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func Sparkline(c *ui.Context, values []float64, opts SparklineOptions) ChartResult`;NaN 为缺值。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `28` | 迷你图高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Kind` | `SparklineKind` | `SparklineLine` | `SparklineLine`、`SparklineBar` 或 `SparklineArea`。 | +| `Width` | `float32` | `96` | 迷你图宽度(DIP)。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 右侧数值格式。 | + +## 状态 + +默认(显示末值)、悬停或键盘读数(右侧数值变为当前点,点外加圆环)、加载(小型加载标记)、失败(错误文字与重试图标)、无数据。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试。 + +## 键盘操作 + +- Tab:聚焦迷你图。 +- ←/→:逐点移动;Home/End:首尾;Escape:恢复显示末值。 + +## 限制 + +- 不显示图例与提示行,以便放在表格行或文字中。 diff --git a/docs/components/115-gauge.md b/docs/components/115-gauge.md new file mode 100644 index 0000000..64360d8 --- /dev/null +++ b/docs/components/115-gauge.md @@ -0,0 +1,51 @@ +# 115 Gauge 仪表盘 + +## 用途 + +仪表盘:半圆或整圆表盘,按阈值分段着色,指针指向当前值,下方写出数值、单位和所在分段的名称,不只靠颜色表达区间。 + +## 最小示例 + +```go +segments := []mujica.GaugeSegment{{To: 60, Label: "Calm", Tone: mujica.GaugeGood}, {To: 100, Label: "Crowded", Tone: mujica.GaugeDanger}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Gauge(c, 72, mujica.GaugeOptions{Frame: mujica.ChartFrame{Label: "Nave"}, Max: 100, Unit: "%", Segments: segments}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func Gauge(c *ui.Context, value float64, opts GaugeOptions) ChartResult`;值须在 `Min`–`Max` 之间。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `200` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Min`, `Max` | `float64` | 必须 `Min < Max` | 刻度范围。 | +| `Segments` | `[]GaugeSegment` | nil | 分段 `{To, Label, Tone}`,上界递增且最后一段止于 `Max`;`Tone` 为 `GaugeNeutral`、`GaugeGood`、`GaugeWarning`、`GaugeDanger`。 | +| `Unit` | `string` | 空 | 数值后的单位。 | +| `Full` | `bool` | false | 整圆表盘,从底部顺时针一周。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 数值格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 当前分段加宽显示。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):依次读当前值与各分段,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 + +## 限制 + +- 不做指针动画,值变化时直接切换。 diff --git a/docs/components/116-treemap.md b/docs/components/116-treemap.md new file mode 100644 index 0000000..e2347b4 --- /dev/null +++ b/docs/components/116-treemap.md @@ -0,0 +1,53 @@ +# 116 Treemap 矩形树图 + +## 用途 + +层级矩形树图:按大小平铺当前节点的子项(squarify 布局),点击或回车下钻有子项的矩形,返回按钮与面包屑回到上层;标签按面积显示并截断。 + +## 最小示例 + +```go +var path []string +root := mujica.ChartNode{Name: "Abbey", Children: []mujica.ChartNode{ + {Name: "Library", Children: []mujica.ChartNode{{Name: "Psalters", Value: 30}, {Name: "Maps", Value: 10}}}, + {Name: "Kitchen", Value: 25}, +}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Treemap(c, &path, root, mujica.TreemapOptions{Frame: mujica.ChartFrame{Label: "Rooms"}}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func Treemap(c *ui.Context, path *[]string, root ChartNode, opts TreemapOptions) ChartResult`;`ChartNode{Name, Value, Children}`,叶子的 `Value` 为大小,分支为子项之和;`*path` 是从根的子项起的名称路径。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 数值格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 当前矩形内描边。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试;`ValueChanged()` 表示下钻、返回或点击面包屑改变了 `*path`。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):按大小顺序在矩形间移动,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 +- Enter/Space:下钻;Backspace:返回上一层;返回按钮与面包屑可用 Tab 到达。 + +## 限制 + +- 名称为空、兄弟同名或值为负时 panic;`*path` 指向不存在的节点时 panic。 +- 只显示当前节点的一层子项。 diff --git a/docs/components/117-sunburst.md b/docs/components/117-sunburst.md new file mode 100644 index 0000000..908abbb --- /dev/null +++ b/docs/components/117-sunburst.md @@ -0,0 +1,53 @@ +# 117 Sunburst 旭日图 + +## 用途 + +层级环形图:中心是当前节点及总计,外圈依次是各层后代;点击或回车下钻,路径面包屑与返回按钮回到上层。 + +## 最小示例 + +```go +var path []string +root := mujica.ChartNode{Name: "Abbey", Children: []mujica.ChartNode{ + {Name: "Library", Children: []mujica.ChartNode{{Name: "Psalters", Value: 30}, {Name: "Maps", Value: 10}}}, + {Name: "Kitchen", Value: 25}, +}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Sunburst(c, &path, root, mujica.SunburstOptions{Frame: mujica.ChartFrame{Label: "Rooms"}}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func Sunburst(c *ui.Context, path *[]string, root ChartNode, opts SunburstOptions) ChartResult`;数据结构同 Treemap。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Depth` | `int` | `3` | 显示的层数;负数 panic。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 数值格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 外层颜色向表面色淡化,但保持 3:1 对比。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试;`ValueChanged()` 表示 `*path` 改变。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):按深度优先顺序在扇区间移动,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 +- Enter/Space:下钻到当前扇区;Backspace:返回上一层。 + +## 限制 + +- 弧长不足时不写标签,名称在读数中完整给出。 diff --git a/docs/components/118-sankey-chart.md b/docs/components/118-sankey-chart.md new file mode 100644 index 0000000..f3568a3 --- /dev/null +++ b/docs/components/118-sankey-chart.md @@ -0,0 +1,49 @@ +# 118 SankeyChart 桑基图 + +## 用途 + +桑基图:节点按最长路径分列,列内顺序与传入顺序一致(稳定);流量带宽度与值成比例;悬停或键盘读到节点或流量时,高亮经过它的全部路径。 + +## 最小示例 + +```go +nodes := []mujica.SankeyNode{{ID: "tithe", Label: "Tithes"}, {ID: "fund", Label: "Fund"}, {ID: "roof", Label: "Roof"}} +links := []mujica.SankeyLink{{From: "tithe", To: "fund", Value: 60}, {From: "fund", To: "roof", Value: 50}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SankeyChart(c, nodes, links, mujica.SankeyChartOptions{Frame: mujica.ChartFrame{Label: "Money"}}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func SankeyChart(c *ui.Context, nodes []SankeyNode, links []SankeyLink, opts SankeyChartOptions) ChartResult`;`SankeyNode{ID, Label}`,`SankeyLink{From, To, Value}`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 数值格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 高亮时其余流量淡化。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):先按节点、再按流量移动,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 + +## 限制 + +- 链接成环、端点未知或值不为正时 panic。 +- 布局只在节点或链接切片变化时计算。 diff --git a/docs/components/119-network-graph.md b/docs/components/119-network-graph.md new file mode 100644 index 0000000..5677d5e --- /dev/null +++ b/docs/components/119-network-graph.md @@ -0,0 +1,51 @@ +# 119 NetworkGraph 网络图 + +## 用途 + +网络图:节点与边,使用调用方给定的坐标或简单的力导布局;拖动节点、拖动空白处平移、滚轮或 +/- 缩放。 + +## 最小示例 + +```go +var state mujica.NetworkGraphState +nodes := []mujica.GraphNode{{ID: "a", Label: "Abbot"}, {ID: "b", Label: "Prior"}, {ID: "c", Label: "Novice"}} +edges := []mujica.GraphEdge{{From: "a", To: "b"}, {From: "b", To: "c"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.NetworkGraph(c, &state, nodes, edges, mujica.NetworkGraphOptions{Frame: mujica.ChartFrame{Label: "House"}, Force: true}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func NetworkGraph(c *ui.Context, s *NetworkGraphState, nodes []GraphNode, edges []GraphEdge, opts NetworkGraphOptions) ChartResult`;`GraphNode{ID, Label, X, Y}`,`GraphEdge{From, To}`。`NetworkGraphState` 保存拖动后的位置与视图:`Position(id)`、`Zoom()`、`ResetView()`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Force` | `bool` | false | 用力导模拟布局(固定 300 步,结果确定);最多 500 个节点。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 当前节点外加圆环,相连的边加粗。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试。 + +## 键盘操作 + +- Tab:聚焦绘图区(图例勾选框在其前)。 +- ←/→(以及 ↑/↓):在节点间移动,读数显示在图表下方并向读屏软件播报;第一次按键进入第一个点。 +- Home/End:第一个/最后一个点;Escape:清除读数。 +- Shift+方向键:移动当前节点;+/-:缩放;0:复位视图。 + +## 限制 + +- 布局只在节点或边的切片变化时重新计算,拖动不会重新适配视图。 +- 不支持边标签与有向箭头。 diff --git a/docs/components/120-realtime-chart.md b/docs/components/120-realtime-chart.md new file mode 100644 index 0000000..edb1c70 --- /dev/null +++ b/docs/components/120-realtime-chart.md @@ -0,0 +1,53 @@ +# 120 RealtimeChart 实时图表 + +## 用途 + +实时折线图:调用方向 `RealtimeBuffer` 追加数据后刷新,图表显示截至最新数据的固定时间窗口;可暂停视图;组件自身不设计时器,隐藏或空闲时不重绘。 + +## 最小示例 + +```go +buf := mujica.NewRealtimeBuffer(600, "Bell") +start := time.Date(2026, 10, 5, 9, 0, 0, 0, time.UTC) +for i := range 60 { + buf.Append(start.Add(time.Duration(i)*time.Second), float64(i%7)) +} +var state mujica.RealtimeChartState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.RealtimeChart(c, &state, buf, mujica.RealtimeChartOptions{Frame: mujica.ChartFrame{Label: "Sound"}, Window: 30 * time.Second}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func RealtimeChart(c *ui.Context, s *RealtimeChartState, buf *RealtimeBuffer, opts RealtimeChartOptions) ChartResult`;`NewRealtimeBuffer(capacity, names...)` 保存最近 `capacity` 个样本,`Append(t, values...)` 每个序列一个值且时间不倒退。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Frame.Label` | `string` | 必填 | 图表的无障碍名称;为空 panic。 | +| `Frame.Height` | `float32` | `240` | 绘图区高度(DIP);负数 panic。 | +| `Frame.Status` | `DataStatus` | `DataReady` | `DataLoading` 显示加载标记,`DataFailed` 显示错误与“重试”;占位与图表同尺寸。 | +| `Frame.Error` | `string` | 内置“加载失败” | 失败时的具体说明。 | +| `Frame.Empty` | `string` | 内置“暂无数据” | 无数据时的说明。 | +| `Window` | `time.Duration` | 必填 | 显示的时间窗口,止于最新样本(暂停时止于暂停那一刻)。 | +| `Format` | `func(float64) string` | 6 位有效数字 | 读数格式。 | + +## 状态 + +默认、悬停读数、键盘读数(焦点环 + 当前点加粗或描边)、加载、失败(可重试)、无数据。图表区始终保持同样尺寸。 暂停时按钮显示“继续”,新数据继续进入缓冲区但不改变视图。 + +## 事件 + +返回 `ChartResult`:`Point` 为当前读数点(无则 -1);`Changed()` 读数点变化;`Retried()` 点击了重试;`ValueChanged()` 表示暂停或继续;`Toggled()` 报告图例切换。 + +## 键盘操作 + +- Tab:暂停按钮、图例、图表。 +- 图表读数键同 LineChart;暂停按钮:Enter/Space。 + +## 限制 + +- 数据追加在后台时,请通过 `Window.Update` 回到界面线程追加并刷新。 +- 缓冲区按块丢弃旧样本,最多占用两倍容量。 diff --git a/example_charts1_test.go b/example_charts1_test.go new file mode 100644 index 0000000..90433bb --- /dev/null +++ b/example_charts1_test.go @@ -0,0 +1,221 @@ +package mujica_test + +import ( + "math" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func ExampleLineChart() { + series := []mujica.ChartSeries{ + {Name: "Pews", Values: []float64{3, 5, math.NaN(), 4, 8}}, + {Name: "Candles", Values: []float64{5, 2, 6, 7, 1}}, + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.LineChart(c, series, mujica.LineChartOptions{Frame: mujica.ChartFrame{Label: "Chapel"}}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleAreaChart() { + series := []mujica.ChartSeries{ + {Name: "Matins", Values: []float64{3, 4, 6, 5}}, + {Name: "Vespers", Values: []float64{2, 3, 2, 4}}, + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AreaChart(c, series, mujica.AreaChartOptions{Frame: mujica.ChartFrame{Label: "Attendance"}, Stacked: true}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleBarChart() { + categories := []string{"Nave", "Choir", "Crypt"} + series := []mujica.ChartSeries{{Name: "Gold", Values: []float64{4, -2, 3}}, {Name: "Silver", Values: []float64{2, 5, 1}}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BarChart(c, categories, series, mujica.BarChartOptions{Frame: mujica.ChartFrame{Label: "Tithes"}, Labels: true}) + } + ui.Render(view, 400, 300, 1) +} + +func ExamplePieChart() { + slices := []mujica.ChartSlice{{Label: "Wax", Value: 50}, {Label: "Oil", Value: 30}, {Label: "Salt", Value: 4}, {Label: "Ash", Value: 3}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.PieChart(c, slices, mujica.PieChartOptions{Frame: mujica.ChartFrame{Label: "Stores"}, Donut: true, MinAngle: 20}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleScatterChart() { + var selected []mujica.ScatterKey + groups := []mujica.ScatterGroup{{Name: "Monks", Points: []mujica.ScatterPoint{{X: 1, Y: 2, Size: 4}, {X: 3, Y: 5, Size: 9}}}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ScatterChart(c, &selected, groups, mujica.ScatterChartOptions{Frame: mujica.ChartFrame{Label: "Choir"}, Bubbles: true}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleRadarChart() { + axes := []string{"Voice", "Latin", "Chant", "Organ"} + series := []mujica.ChartSeries{{Name: "Agnès", Values: []float64{8, 6, 9, 4}}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.RadarChart(c, axes, series, mujica.RadarChartOptions{Frame: mujica.ChartFrame{Label: "Skills"}}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleHeatmapChart() { + rows, cols := []string{"Mon", "Tue"}, []string{"Matins", "Lauds", "Vespers"} + values := [][]float64{{1, 4, 9}, {3, math.NaN(), 7}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.HeatmapChart(c, rows, cols, values, mujica.HeatmapChartOptions{Frame: mujica.ChartFrame{Label: "Hours"}}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCalendarHeatmap() { + year := 2026 + values := map[mujica.Date]float64{{Year: 2026, Month: time.March, Day: 4}: 5} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CalendarHeatmap(c, &year, values, mujica.CalendarHeatmapOptions{Frame: mujica.ChartFrame{Label: "Prayers"}}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleHistogram() { + values := []float64{1, 2, 2, 3, 4, 5, 9, 10} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Histogram(c, values, mujica.HistogramOptions{Frame: mujica.ChartFrame{Label: "Ages"}, BinWidth: 5}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleBoxPlot() { + groups := []mujica.BoxGroup{{Name: "Choir", Values: []float64{1, 2, 3, 4, 5, 40}}, {Name: "Nave", Values: []float64{4, 5, 6, 7}}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BoxPlot(c, groups, mujica.BoxPlotOptions{Frame: mujica.ChartFrame{Label: "Hymns"}}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleWaterfallChart() { + steps := []mujica.WaterfallStep{ + {Label: "Tithes", Value: 12}, + {Label: "Repairs", Value: -5}, + {Label: "Year", Kind: mujica.WaterfallTotal}, + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.WaterfallChart(c, steps, mujica.WaterfallChartOptions{Frame: mujica.ChartFrame{Label: "Ledger"}}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleFunnelChart() { + stages := []mujica.ChartSlice{{Label: "Visitors", Value: 1000}, {Label: "Novices", Value: 400}, {Label: "Vows", Value: 100}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.FunnelChart(c, stages, mujica.FunnelChartOptions{Frame: mujica.ChartFrame{Label: "Order"}}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleBulletChart() { + target := 250.0 + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BulletChart(c, 270, mujica.BulletChartOptions{Frame: mujica.ChartFrame{Label: "Alms"}, Target: &target, Bands: []float64{150, 225, 300}}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleSparkline() { + values := []float64{3, 5, 4, 7, 6, 9} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Sparkline(c, values, mujica.SparklineOptions{Frame: mujica.ChartFrame{Label: "Bells"}, Kind: mujica.SparklineArea}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleGauge() { + segments := []mujica.GaugeSegment{{To: 60, Label: "Calm", Tone: mujica.GaugeGood}, {To: 100, Label: "Crowded", Tone: mujica.GaugeDanger}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Gauge(c, 72, mujica.GaugeOptions{Frame: mujica.ChartFrame{Label: "Nave"}, Max: 100, Unit: "%", Segments: segments}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleTreemap() { + var path []string + root := mujica.ChartNode{Name: "Abbey", Children: []mujica.ChartNode{ + {Name: "Library", Children: []mujica.ChartNode{{Name: "Psalters", Value: 30}, {Name: "Maps", Value: 10}}}, + {Name: "Kitchen", Value: 25}, + }} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Treemap(c, &path, root, mujica.TreemapOptions{Frame: mujica.ChartFrame{Label: "Rooms"}}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleSunburst() { + var path []string + root := mujica.ChartNode{Name: "Abbey", Children: []mujica.ChartNode{ + {Name: "Library", Children: []mujica.ChartNode{{Name: "Psalters", Value: 30}, {Name: "Maps", Value: 10}}}, + {Name: "Kitchen", Value: 25}, + }} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Sunburst(c, &path, root, mujica.SunburstOptions{Frame: mujica.ChartFrame{Label: "Rooms"}}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleSankeyChart() { + nodes := []mujica.SankeyNode{{ID: "tithe", Label: "Tithes"}, {ID: "fund", Label: "Fund"}, {ID: "roof", Label: "Roof"}} + links := []mujica.SankeyLink{{From: "tithe", To: "fund", Value: 60}, {From: "fund", To: "roof", Value: 50}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SankeyChart(c, nodes, links, mujica.SankeyChartOptions{Frame: mujica.ChartFrame{Label: "Money"}}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleNetworkGraph() { + var state mujica.NetworkGraphState + nodes := []mujica.GraphNode{{ID: "a", Label: "Abbot"}, {ID: "b", Label: "Prior"}, {ID: "c", Label: "Novice"}} + edges := []mujica.GraphEdge{{From: "a", To: "b"}, {From: "b", To: "c"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.NetworkGraph(c, &state, nodes, edges, mujica.NetworkGraphOptions{Frame: mujica.ChartFrame{Label: "House"}, Force: true}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleRealtimeChart() { + buf := mujica.NewRealtimeBuffer(600, "Bell") + start := time.Date(2026, 10, 5, 9, 0, 0, 0, time.UTC) + for i := range 60 { + buf.Append(start.Add(time.Duration(i)*time.Second), float64(i%7)) + } + var state mujica.RealtimeChartState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.RealtimeChart(c, &state, buf, mujica.RealtimeChartOptions{Frame: mujica.ChartFrame{Label: "Sound"}, Window: 30 * time.Second}) + } + ui.Render(view, 400, 300, 1) +} diff --git a/examples/gallery/pages_charts1.go b/examples/gallery/pages_charts1.go index 77aacff..f7cb1dd 100644 --- a/examples/gallery/pages_charts1.go +++ b/examples/gallery/pages_charts1.go @@ -1,3 +1,77 @@ package main -var charts1Pages = []page{} +import ( + "fmt" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" + "mujicaui/theme" +) + +const c1Category = "Charts I" + +const c1Keys = "Tab focuses the chart (legend check boxes first); arrows move between points and the readout is announced; Home/End jump; Escape clears." + +var charts1Pages = []page{ + {ID: "101", Name: "LineChart", ZhName: "折线图", Category: c1Category, Demo: c1LineDemo, Code: c1LineCode, Keys: c1Keys + " Space on a legend entry hides or shows its series."}, + {ID: "102", Name: "AreaChart", ZhName: "面积图", Category: c1Category, Demo: c1AreaDemo, Code: c1AreaCode, Keys: c1Keys}, + {ID: "103", Name: "BarChart", ZhName: "柱状图", Category: c1Category, Demo: c1BarDemo, Code: c1BarCode, Keys: c1Keys + " Arrows step bar by bar."}, + {ID: "104", Name: "PieChart", ZhName: "饼图", Category: c1Category, Demo: c1PieDemo, Code: c1PieCode, Keys: c1Keys}, + {ID: "105", Name: "ScatterChart", ZhName: "散点图", Category: c1Category, Demo: c1ScatterDemo, Code: c1ScatterCode, Keys: c1Keys + " Enter or Space selects the point; drag a box to select."}, + {ID: "106", Name: "RadarChart", ZhName: "雷达图", Category: c1Category, Demo: c1RadarDemo, Code: c1RadarCode, Keys: c1Keys}, + {ID: "107", Name: "HeatmapChart", ZhName: "热力图", Category: c1Category, Demo: c1HeatDemo, Code: c1HeatCode, Keys: "Tab focuses the map; Left/Right move along a row, Up/Down along a column; Home/End jump; Escape clears."}, + {ID: "108", Name: "CalendarHeatmap", ZhName: "日历热力图", Category: c1Category, Demo: c1CalendarDemo, Code: c1CalendarCode, Keys: "Left/Right move a week, Up/Down a day; Home/End jump to the year's ends; the year buttons take Enter or Space."}, + {ID: "109", Name: "Histogram", ZhName: "直方图", Category: c1Category, Demo: c1HistogramDemo, Code: c1HistogramCode, Keys: c1Keys + " Arrows step bin by bin."}, + {ID: "110", Name: "BoxPlot", ZhName: "箱线图", Category: c1Category, Demo: c1BoxDemo, Code: c1BoxCode, Keys: c1Keys + " Arrows step group by group."}, + {ID: "111", Name: "WaterfallChart", ZhName: "瀑布图", Category: c1Category, Demo: c1WaterfallDemo, Code: c1WaterfallCode, Keys: c1Keys}, + {ID: "112", Name: "FunnelChart", ZhName: "漏斗图", Category: c1Category, Demo: c1FunnelDemo, Code: c1FunnelCode, Keys: c1Keys + " Arrows step stage by stage."}, + {ID: "113", Name: "BulletChart", ZhName: "子弹图", Category: c1Category, Demo: c1BulletDemo, Code: c1BulletCode, Keys: c1Keys + " Arrows read the value, the target, then each range."}, + {ID: "114", Name: "Sparkline", ZhName: "迷你图", Category: c1Category, Demo: c1SparkDemo, Code: c1SparkCode, Keys: "Tab focuses the sparkline; Left/Right read points; Home/End jump; Escape shows the last value again."}, + {ID: "115", Name: "Gauge", ZhName: "仪表盘", Category: c1Category, Demo: c1GaugeDemo, Code: c1GaugeCode, Keys: c1Keys + " Arrows read the value, then each segment."}, + {ID: "116", Name: "Treemap", ZhName: "矩形树图", Category: c1Category, Demo: c1TreemapDemo, Code: c1TreemapCode, Keys: c1Keys + " Enter or Space drills into a branch; Backspace goes back; Back and the breadcrumb take Tab."}, + {ID: "117", Name: "Sunburst", ZhName: "旭日图", Category: c1Category, Demo: c1SunburstDemo, Code: c1SunburstCode, Keys: c1Keys + " Enter or Space drills in; Backspace goes back."}, + {ID: "118", Name: "SankeyChart", ZhName: "桑基图", Category: c1Category, Demo: c1SankeyDemo, Code: c1SankeyCode, Keys: c1Keys + " Reading a node or link highlights every path through it."}, + {ID: "119", Name: "NetworkGraph", ZhName: "网络图", Category: c1Category, Demo: c1NetworkDemo, Code: c1NetworkCode, Keys: c1Keys + " Shift+arrows move the node; +/- zoom; 0 resets the view; drag nodes or the background."}, + {ID: "120", Name: "RealtimeChart", ZhName: "实时图表", Category: c1Category, Demo: c1RealtimeDemo, Code: c1RealtimeCode, Keys: "Tab reaches Pause, the legend and the chart; chart keys as in LineChart."}, +} + +var c1Statuses = []string{"Ready", "Loading", "Failed", "Empty"} + +// c1Frame shows the status picker and returns the frame. +func c1Frame(c *ui.Context, label string, status *string) (mujica.ChartFrame, bool) { + ui.Select(c, status, c1Statuses).Width(160).AlignSelf(ui.Start) + f := mujica.ChartFrame{Label: label} + switch *status { + case "Loading": + f.Status = mujica.DataLoading + case "Failed": + f.Status, f.Error = mujica.DataFailed, "The archive did not answer" + } + return f, *status != "Empty" +} + +// c1Section lays out a title, controls, then the chart. +func c1Section(c *ui.Context, title string, controls, body func()) { + ui.Column(c).Gap(12).Children(func() { + ui.Text(c, title).Font(theme.SerifFont).FontSize(mujica.FontSize(c, theme.H3Size)) + ui.Row(c).Gap(16).Wrap().AlignItems(ui.Center).Children(controls) + ui.Column(c).Width(560).Children(body) + }) +} + +// c1Log records a chart's events in the gallery log. +func c1Log(log func(string), name string, r mujica.ChartResult) { + if r.Changed() { + log(fmt.Sprintf("%s: point %d", name, r.Point)) + } + if s, ok := r.Toggled(); ok { + log(name + ": toggled " + s) + } + if r.ValueChanged() { + log(name + ": value changed") + } + if r.Retried() { + log(name + ": retry") + } +} diff --git a/examples/gallery/pages_charts1_code.go b/examples/gallery/pages_charts1_code.go new file mode 100644 index 0000000..8548a47 --- /dev/null +++ b/examples/gallery/pages_charts1_code.go @@ -0,0 +1,174 @@ +package main + +// Snippets are the bodies of the Examples in example_charts1_test.go. + +const c1LineCode = `series := []mujica.ChartSeries{ + {Name: "Pews", Values: []float64{3, 5, math.NaN(), 4, 8}}, + {Name: "Candles", Values: []float64{5, 2, 6, 7, 1}}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.LineChart(c, series, mujica.LineChartOptions{Frame: mujica.ChartFrame{Label: "Chapel"}}) +} +ui.Render(view, 400, 300, 1)` + +const c1AreaCode = `series := []mujica.ChartSeries{ + {Name: "Matins", Values: []float64{3, 4, 6, 5}}, + {Name: "Vespers", Values: []float64{2, 3, 2, 4}}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.AreaChart(c, series, mujica.AreaChartOptions{Frame: mujica.ChartFrame{Label: "Attendance"}, Stacked: true}) +} +ui.Render(view, 400, 300, 1)` + +const c1BarCode = `categories := []string{"Nave", "Choir", "Crypt"} +series := []mujica.ChartSeries{{Name: "Gold", Values: []float64{4, -2, 3}}, {Name: "Silver", Values: []float64{2, 5, 1}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BarChart(c, categories, series, mujica.BarChartOptions{Frame: mujica.ChartFrame{Label: "Tithes"}, Labels: true}) +} +ui.Render(view, 400, 300, 1)` + +const c1PieCode = `slices := []mujica.ChartSlice{{Label: "Wax", Value: 50}, {Label: "Oil", Value: 30}, {Label: "Salt", Value: 4}, {Label: "Ash", Value: 3}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.PieChart(c, slices, mujica.PieChartOptions{Frame: mujica.ChartFrame{Label: "Stores"}, Donut: true, MinAngle: 20}) +} +ui.Render(view, 400, 300, 1)` + +const c1ScatterCode = `var selected []mujica.ScatterKey +groups := []mujica.ScatterGroup{{Name: "Monks", Points: []mujica.ScatterPoint{{X: 1, Y: 2, Size: 4}, {X: 3, Y: 5, Size: 9}}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ScatterChart(c, &selected, groups, mujica.ScatterChartOptions{Frame: mujica.ChartFrame{Label: "Choir"}, Bubbles: true}) +} +ui.Render(view, 400, 300, 1)` + +const c1RadarCode = `axes := []string{"Voice", "Latin", "Chant", "Organ"} +series := []mujica.ChartSeries{{Name: "Agnès", Values: []float64{8, 6, 9, 4}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.RadarChart(c, axes, series, mujica.RadarChartOptions{Frame: mujica.ChartFrame{Label: "Skills"}}) +} +ui.Render(view, 400, 300, 1)` + +const c1HeatCode = `rows, cols := []string{"Mon", "Tue"}, []string{"Matins", "Lauds", "Vespers"} +values := [][]float64{{1, 4, 9}, {3, math.NaN(), 7}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.HeatmapChart(c, rows, cols, values, mujica.HeatmapChartOptions{Frame: mujica.ChartFrame{Label: "Hours"}}) +} +ui.Render(view, 400, 300, 1)` + +const c1CalendarCode = `year := 2026 +values := map[mujica.Date]float64{{Year: 2026, Month: time.March, Day: 4}: 5} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CalendarHeatmap(c, &year, values, mujica.CalendarHeatmapOptions{Frame: mujica.ChartFrame{Label: "Prayers"}}) +} +ui.Render(view, 400, 300, 1)` + +const c1HistogramCode = `values := []float64{1, 2, 2, 3, 4, 5, 9, 10} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Histogram(c, values, mujica.HistogramOptions{Frame: mujica.ChartFrame{Label: "Ages"}, BinWidth: 5}) +} +ui.Render(view, 400, 300, 1)` + +const c1BoxCode = `groups := []mujica.BoxGroup{{Name: "Choir", Values: []float64{1, 2, 3, 4, 5, 40}}, {Name: "Nave", Values: []float64{4, 5, 6, 7}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BoxPlot(c, groups, mujica.BoxPlotOptions{Frame: mujica.ChartFrame{Label: "Hymns"}}) +} +ui.Render(view, 400, 300, 1)` + +const c1WaterfallCode = `steps := []mujica.WaterfallStep{ + {Label: "Tithes", Value: 12}, + {Label: "Repairs", Value: -5}, + {Label: "Year", Kind: mujica.WaterfallTotal}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.WaterfallChart(c, steps, mujica.WaterfallChartOptions{Frame: mujica.ChartFrame{Label: "Ledger"}}) +} +ui.Render(view, 400, 300, 1)` + +const c1FunnelCode = `stages := []mujica.ChartSlice{{Label: "Visitors", Value: 1000}, {Label: "Novices", Value: 400}, {Label: "Vows", Value: 100}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.FunnelChart(c, stages, mujica.FunnelChartOptions{Frame: mujica.ChartFrame{Label: "Order"}}) +} +ui.Render(view, 400, 300, 1)` + +const c1BulletCode = `target := 250.0 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.BulletChart(c, 270, mujica.BulletChartOptions{Frame: mujica.ChartFrame{Label: "Alms"}, Target: &target, Bands: []float64{150, 225, 300}}) +} +ui.Render(view, 400, 300, 1)` + +const c1SparkCode = `values := []float64{3, 5, 4, 7, 6, 9} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Sparkline(c, values, mujica.SparklineOptions{Frame: mujica.ChartFrame{Label: "Bells"}, Kind: mujica.SparklineArea}) +} +ui.Render(view, 400, 300, 1)` + +const c1GaugeCode = `segments := []mujica.GaugeSegment{{To: 60, Label: "Calm", Tone: mujica.GaugeGood}, {To: 100, Label: "Crowded", Tone: mujica.GaugeDanger}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Gauge(c, 72, mujica.GaugeOptions{Frame: mujica.ChartFrame{Label: "Nave"}, Max: 100, Unit: "%", Segments: segments}) +} +ui.Render(view, 400, 300, 1)` + +const c1TreemapCode = `var path []string +root := mujica.ChartNode{Name: "Abbey", Children: []mujica.ChartNode{ + {Name: "Library", Children: []mujica.ChartNode{{Name: "Psalters", Value: 30}, {Name: "Maps", Value: 10}}}, + {Name: "Kitchen", Value: 25}, +}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Treemap(c, &path, root, mujica.TreemapOptions{Frame: mujica.ChartFrame{Label: "Rooms"}}) +} +ui.Render(view, 400, 300, 1)` + +const c1SunburstCode = `var path []string +root := mujica.ChartNode{Name: "Abbey", Children: []mujica.ChartNode{ + {Name: "Library", Children: []mujica.ChartNode{{Name: "Psalters", Value: 30}, {Name: "Maps", Value: 10}}}, + {Name: "Kitchen", Value: 25}, +}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Sunburst(c, &path, root, mujica.SunburstOptions{Frame: mujica.ChartFrame{Label: "Rooms"}}) +} +ui.Render(view, 400, 300, 1)` + +const c1SankeyCode = `nodes := []mujica.SankeyNode{{ID: "tithe", Label: "Tithes"}, {ID: "fund", Label: "Fund"}, {ID: "roof", Label: "Roof"}} +links := []mujica.SankeyLink{{From: "tithe", To: "fund", Value: 60}, {From: "fund", To: "roof", Value: 50}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.SankeyChart(c, nodes, links, mujica.SankeyChartOptions{Frame: mujica.ChartFrame{Label: "Money"}}) +} +ui.Render(view, 400, 300, 1)` + +const c1NetworkCode = `var state mujica.NetworkGraphState +nodes := []mujica.GraphNode{{ID: "a", Label: "Abbot"}, {ID: "b", Label: "Prior"}, {ID: "c", Label: "Novice"}} +edges := []mujica.GraphEdge{{From: "a", To: "b"}, {From: "b", To: "c"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.NetworkGraph(c, &state, nodes, edges, mujica.NetworkGraphOptions{Frame: mujica.ChartFrame{Label: "House"}, Force: true}) +} +ui.Render(view, 400, 300, 1)` + +const c1RealtimeCode = `buf := mujica.NewRealtimeBuffer(600, "Bell") +start := time.Date(2026, 10, 5, 9, 0, 0, 0, time.UTC) +for i := range 60 { + buf.Append(start.Add(time.Duration(i)*time.Second), float64(i%7)) +} +var state mujica.RealtimeChartState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.RealtimeChart(c, &state, buf, mujica.RealtimeChartOptions{Frame: mujica.ChartFrame{Label: "Sound"}, Window: 30 * time.Second}) +} +ui.Render(view, 400, 300, 1)` diff --git a/examples/gallery/pages_charts1_flow.go b/examples/gallery/pages_charts1_flow.go new file mode 100644 index 0000000..02161ff --- /dev/null +++ b/examples/gallery/pages_charts1_flow.go @@ -0,0 +1,137 @@ +package main + +import ( + "fmt" + "math" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +var c1Abbey = mujica.ChartNode{Name: "Abbey", Children: []mujica.ChartNode{ + {Name: "Library", Children: []mujica.ChartNode{{Name: "Psalters", Value: 30}, {Name: "Maps", Value: 10}, {Name: "Letters", Value: 8}}}, + {Name: "Kitchen", Value: 25}, + {Name: "Garden", Children: []mujica.ChartNode{{Name: "Herbs", Value: 12}, {Name: "Vines", Value: 8}}}, + {Name: "Chapel", Children: []mujica.ChartNode{{Name: "Nave", Value: 18}, {Name: "Crypt", Value: 6}}}, +}} + +func c1TreemapDemo(c *ui.Context, log func(string)) { + type state struct { + status string + path []string + } + s := ui.Local(c.Root(), "116", func() state { return state{status: "Ready"} }) + c1Section(c, "Treemap", func() {}, func() { + frame, show := c1Frame(c, "Rooms", &s.status) + root := c1Abbey + if !show { + root = mujica.ChartNode{Name: "Abbey"} + s.path = nil + } + r := mujica.Treemap(c, &s.path, root, mujica.TreemapOptions{Frame: frame}) + c1Log(log, "Treemap", r) + if r.ValueChanged() { + log("Treemap: path /" + strings.Join(s.path, "/")) + } + }) +} + +func c1SunburstDemo(c *ui.Context, log func(string)) { + type state struct { + status string + path []string + depth float64 + } + s := ui.Local(c.Root(), "117", func() state { return state{status: "Ready", depth: 2} }) + c1Section(c, "Sunburst", func() { + ui.Text(c, fmt.Sprintf("%.0f rings", s.depth)) + ui.StepSlider(c, &s.depth, 1, 3, 1).Width(120) + }, func() { + frame, show := c1Frame(c, "Rooms", &s.status) + frame.Height = 300 + root := c1Abbey + if !show { + root = mujica.ChartNode{Name: "Abbey"} + s.path = nil + } + r := mujica.Sunburst(c, &s.path, root, mujica.SunburstOptions{Frame: frame, Depth: int(s.depth)}) + c1Log(log, "Sunburst", r) + if r.ValueChanged() { + log("Sunburst: path /" + strings.Join(s.path, "/")) + } + }) +} + +func c1SankeyDemo(c *ui.Context, log func(string)) { + type state struct{ status string } + s := ui.Local(c.Root(), "118", func() state { return state{status: "Ready"} }) + c1Section(c, "SankeyChart", func() {}, func() { + frame, show := c1Frame(c, "Money", &s.status) + nodes := []mujica.SankeyNode{{ID: "tithe", Label: "Tithes"}, {ID: "alms", Label: "Alms"}, {ID: "fund", Label: "Fund"}, {ID: "roof", Label: "Roof"}, {ID: "bread", Label: "Bread"}, {ID: "bells", Label: "Bells"}} + links := []mujica.SankeyLink{{From: "tithe", To: "fund", Value: 60}, {From: "alms", To: "fund", Value: 30}, {From: "alms", To: "bread", Value: 10}, {From: "fund", To: "roof", Value: 50}, {From: "fund", To: "bells", Value: 40}} + if !show { + links = nil + } + c1Log(log, "SankeyChart", mujica.SankeyChart(c, nodes, links, mujica.SankeyChartOptions{Frame: frame})) + }) +} + +func c1NetworkDemo(c *ui.Context, log func(string)) { + type state struct { + status string + force bool + graph mujica.NetworkGraphState + } + s := ui.Local(c.Root(), "119", func() state { return state{status: "Ready", force: true} }) + c1Section(c, "NetworkGraph", func() { + ui.Checkbox(c, &s.force, "Force layout") + if mujica.Button(c, "Reset view", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.graph.ResetView() + log("NetworkGraph: reset view") + } + }, func() { + frame, show := c1Frame(c, "House", &s.status) + nodes := []mujica.GraphNode{{ID: "a", Label: "Abbot", X: 0, Y: 0}, {ID: "b", Label: "Prior", X: 10, Y: 0}, {ID: "c", Label: "Cellarer", X: 10, Y: 10}, {ID: "d", Label: "Novice", X: 0, Y: 10}, {ID: "e", Label: "Cantor", X: 5, Y: 5}} + edges := []mujica.GraphEdge{{From: "a", To: "b"}, {From: "a", To: "c"}, {From: "c", To: "d"}, {From: "b", To: "e"}, {From: "e", To: "d"}} + if !show { + nodes, edges = nil, nil + } + c1Log(log, "NetworkGraph", mujica.NetworkGraph(c, &s.graph, nodes, edges, mujica.NetworkGraphOptions{Frame: frame, Force: s.force})) + }) +} + +func c1RealtimeDemo(c *ui.Context, log func(string)) { + type state struct { + status string + feed bool + buf *mujica.RealtimeBuffer + next time.Time + tick int + view mujica.RealtimeChartState + } + s := ui.Local(c.Root(), "120", func() state { + return state{status: "Ready", feed: true, buf: mujica.NewRealtimeBuffer(600, "Bell", "Organ")} + }) + // The demo appends a sample every 500 ms while feeding. + if s.feed && !c.Now().Before(s.next) { + t := time.Date(2026, 10, 5, 9, 0, 0, 0, time.UTC).Add(time.Duration(s.tick) * 500 * time.Millisecond) + x := float64(s.tick) + s.buf.Append(t, 5+3*math.Sin(x/6), 4+2*math.Sin(x/4+1)) + s.tick++ + s.next = c.Now().Add(500 * time.Millisecond) + } + if s.feed { + c.After(s.next.Sub(c.Now())) + } + c1Section(c, "RealtimeChart", func() { ui.Checkbox(c, &s.feed, "Feed data") }, func() { + frame, _ := c1Frame(c, "Sound", &s.status) + r := mujica.RealtimeChart(c, &s.view, s.buf, mujica.RealtimeChartOptions{Frame: frame, Window: 20 * time.Second}) + c1Log(log, "RealtimeChart", r) + if r.ValueChanged() { + log(fmt.Sprintf("RealtimeChart: paused=%v", s.view.Paused)) + } + }) +} diff --git a/examples/gallery/pages_charts1_series.go b/examples/gallery/pages_charts1_series.go new file mode 100644 index 0000000..6716f57 --- /dev/null +++ b/examples/gallery/pages_charts1_series.go @@ -0,0 +1,197 @@ +package main + +import ( + "fmt" + "math" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func c1Series(gap bool) []mujica.ChartSeries { + a := []float64{3, 5, 4, 6, 8, 7, 9, 11} + if gap { + a = []float64{3, 5, math.NaN(), 6, 8, 7, 9, 11} + } + return []mujica.ChartSeries{ + {Name: "Matins", Values: a}, + {Name: "Vespers", Values: []float64{2, 3, 5, 4, 6, 9, 8, 7}}, + {Name: "Compline", Values: []float64{1, 2, 2, 3, 2, 4, 5, 4}}, + } +} + +func c1LineDemo(c *ui.Context, log func(string)) { + type state struct { + status string + gap, time bool + big bool + } + s := ui.Local(c.Root(), "101", func() state { return state{status: "Ready", gap: true} }) + c1Section(c, "LineChart", func() { + ui.Checkbox(c, &s.gap, "Missing value") + ui.Checkbox(c, &s.time, "Time axis") + ui.Checkbox(c, &s.big, "100,000 points") + }, func() { + frame, show := c1Frame(c, "Attendance", &s.status) + series, opts := c1Series(s.gap), mujica.LineChartOptions{Frame: frame} + if s.big { + series = []mujica.ChartSeries{{Name: "Wave", Values: c1Wave()}} + } + if s.time { + t0 := time.Date(2026, 10, 5, 6, 0, 0, 0, time.UTC) + opts.Times = make([]time.Time, len(series[0].Values)) + for i := range opts.Times { + opts.Times[i] = t0.Add(time.Duration(i) * time.Hour) + } + } + if !show { + series = nil + opts.Times = nil + } + c1Log(log, "LineChart", mujica.LineChart(c, series, opts)) + }) +} + +var c1WaveData []float64 + +// c1Wave is 100,000 points, made once. +func c1Wave() []float64 { + if c1WaveData == nil { + c1WaveData = make([]float64, 100_000) + for i := range c1WaveData { + c1WaveData[i] = math.Sin(float64(i)/900) + 0.3*math.Sin(float64(i)/37) + } + } + return c1WaveData +} + +func c1AreaDemo(c *ui.Context, log func(string)) { + type state struct { + status string + stacked bool + base float64 + } + s := ui.Local(c.Root(), "102", func() state { return state{status: "Ready", stacked: true} }) + c1Section(c, "AreaChart", func() { + ui.Checkbox(c, &s.stacked, "Stacked") + ui.Text(c, fmt.Sprintf("Baseline %.0f", s.base)) + ui.StepSlider(c, &s.base, -4, 4, 1).Width(140) + }, func() { + frame, show := c1Frame(c, "Attendance", &s.status) + series := c1Series(false) + if !show { + series = nil + } + c1Log(log, "AreaChart", mujica.AreaChart(c, series, mujica.AreaChartOptions{Frame: frame, Stacked: s.stacked, Baseline: s.base})) + }) +} + +func c1BarDemo(c *ui.Context, log func(string)) { + type state struct { + status string + horizontal, stacked, labels bool + } + s := ui.Local(c.Root(), "103", func() state { return state{status: "Ready", labels: true} }) + c1Section(c, "BarChart", func() { + ui.Checkbox(c, &s.horizontal, "Horizontal") + ui.Checkbox(c, &s.stacked, "Stacked") + ui.Checkbox(c, &s.labels, "Labels") + }, func() { + frame, show := c1Frame(c, "Tithes", &s.status) + cats := []string{"Nave", "Choir", "Crypt", "Bells"} + series := []mujica.ChartSeries{{Name: "Gold", Values: []float64{4, -2, 3, 5}}, {Name: "Silver", Values: []float64{2, 5, 1, -1}}} + if !show { + series = nil + } + c1Log(log, "BarChart", mujica.BarChart(c, cats, series, mujica.BarChartOptions{Frame: frame, Horizontal: s.horizontal, Stacked: s.stacked, Labels: s.labels})) + }) +} + +func c1PieDemo(c *ui.Context, log func(string)) { + type state struct { + status string + donut bool + min float64 + } + s := ui.Local(c.Root(), "104", func() state { return state{status: "Ready", donut: true, min: 20} }) + c1Section(c, "PieChart", func() { + ui.Checkbox(c, &s.donut, "Donut") + ui.Text(c, fmt.Sprintf("Merge under %.0f°", s.min)) + ui.StepSlider(c, &s.min, 0, 40, 5).Width(140) + }, func() { + frame, show := c1Frame(c, "Stores", &s.status) + slices := []mujica.ChartSlice{{Label: "Wax", Value: 50}, {Label: "Oil", Value: 30}, {Label: "Myrrh", Value: 12}, {Label: "Salt", Value: 4}, {Label: "Ash", Value: 4}} + if !show { + slices = nil + } + c1Log(log, "PieChart", mujica.PieChart(c, slices, mujica.PieChartOptions{Frame: frame, Donut: s.donut, MinAngle: s.min})) + }) +} + +func c1ScatterDemo(c *ui.Context, log func(string)) { + type state struct { + status string + bubbles bool + selected []mujica.ScatterKey + } + s := ui.Local(c.Root(), "105", func() state { return state{status: "Ready", bubbles: true} }) + c1Section(c, "ScatterChart", func() { + ui.Checkbox(c, &s.bubbles, "Bubbles") + ui.Text(c, fmt.Sprintf("%d selected", len(s.selected))) + }, func() { + frame, show := c1Frame(c, "Choir", &s.status) + groups := []mujica.ScatterGroup{ + {Name: "Monks", Points: []mujica.ScatterPoint{{X: 1, Y: 2, Size: 4}, {X: 3, Y: 5, Size: 9}, {X: 6, Y: 4, Size: 1}, {X: 7, Y: 8, Size: 6}}}, + {Name: "Nuns", Points: []mujica.ScatterPoint{{X: 2, Y: 7, Size: 16}, {X: 8, Y: 9, Size: 2}, {X: 5, Y: 2, Size: 8}}}, + } + if !show { + groups = nil + } + r := mujica.ScatterChart(c, &s.selected, groups, mujica.ScatterChartOptions{Frame: frame, Bubbles: s.bubbles}) + c1Log(log, "ScatterChart", r) + if r.ValueChanged() { + log(fmt.Sprintf("ScatterChart: %d selected", len(s.selected))) + } + }) +} + +func c1RadarDemo(c *ui.Context, log func(string)) { + type state struct{ status string } + s := ui.Local(c.Root(), "106", func() state { return state{status: "Ready"} }) + c1Section(c, "RadarChart", func() {}, func() { + frame, show := c1Frame(c, "Skills", &s.status) + series := []mujica.ChartSeries{{Name: "Agnès", Values: []float64{8, 6, 9, 4, 7}}, {Name: "Clare", Values: []float64{5, 9, 6, 8, 3}}} + if !show { + series = nil + } + c1Log(log, "RadarChart", mujica.RadarChart(c, []string{"Voice", "Latin", "Chant", "Organ", "Bells"}, series, mujica.RadarChartOptions{Frame: frame})) + }) +} + +func c1HeatDemo(c *ui.Context, log func(string)) { + type state struct { + status string + gaps bool + } + s := ui.Local(c.Root(), "107", func() state { return state{status: "Ready", gaps: true} }) + c1Section(c, "HeatmapChart", func() { ui.Checkbox(c, &s.gaps, "Empty cells") }, func() { + frame, show := c1Frame(c, "Hours", &s.status) + rows, cols := []string{"Mon", "Tue", "Wed", "Thu"}, []string{"Matins", "Lauds", "Terce", "Vespers", "Compline"} + values := make([][]float64, len(rows)) + for r := range rows { + values[r] = make([]float64, len(cols)) + for col := range cols { + values[r][col] = float64((r*7 + col*5) % 11) + if s.gaps && (r+col)%6 == 1 { + values[r][col] = math.NaN() + } + } + } + if !show { + rows, values = nil, nil + } + c1Log(log, "HeatmapChart", mujica.HeatmapChart(c, rows, cols, values, mujica.HeatmapChartOptions{Frame: frame})) + }) +} diff --git a/examples/gallery/pages_charts1_stats.go b/examples/gallery/pages_charts1_stats.go new file mode 100644 index 0000000..3cb2c1e --- /dev/null +++ b/examples/gallery/pages_charts1_stats.go @@ -0,0 +1,171 @@ +package main + +import ( + "fmt" + "math" + "strconv" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func c1CalendarDemo(c *ui.Context, log func(string)) { + type state struct { + status, start string + year int + } + s := ui.Local(c.Root(), "108", func() state { return state{status: "Ready", start: "Monday", year: 2026} }) + c1Section(c, "CalendarHeatmap", func() { ui.Select(c, &s.start, []string{"Locale", "Sunday", "Monday", "Saturday"}) }, func() { + frame, show := c1Frame(c, "Prayers", &s.status) + frame.Height = 160 + values := map[mujica.Date]float64{} + if show { + d := mujica.Date{Year: s.year, Month: time.January, Day: 1} + for i := range 366 { + if (i*37)%5 != 0 { + values[d.AddDays(i)] = float64((i * 13) % 9) + } + } + } + start := map[string]mujica.WeekStart{"Locale": mujica.WeekStartLocale, "Sunday": mujica.WeekStartSunday, "Monday": mujica.WeekStartMonday, "Saturday": mujica.WeekStartSaturday}[s.start] + r := mujica.CalendarHeatmap(c, &s.year, values, mujica.CalendarHeatmapOptions{Frame: frame, WeekStart: start}) + c1Log(log, "CalendarHeatmap", r) + if r.ValueChanged() { + log("CalendarHeatmap: year " + strconv.Itoa(s.year)) + } + }) +} + +func c1HistogramDemo(c *ui.Context, log func(string)) { + type state struct { + status string + bins float64 + cumulative bool + values []float64 + } + s := ui.Local(c.Root(), "109", func() state { + v := make([]float64, 500) + for i := range v { + v[i] = 50 + 12*math.Sin(float64(i)*1.7)*math.Cos(float64(i)*0.31) + } + return state{status: "Ready", bins: 10, values: v} + }) + c1Section(c, "Histogram", func() { + ui.Text(c, fmt.Sprintf("%.0f bins", s.bins)) + ui.StepSlider(c, &s.bins, 3, 30, 1).Width(140) + ui.Checkbox(c, &s.cumulative, "Cumulative") + }, func() { + frame, show := c1Frame(c, "Ages", &s.status) + values := s.values + if !show { + values = nil + } + c1Log(log, "Histogram", mujica.Histogram(c, values, mujica.HistogramOptions{Frame: frame, Bins: int(s.bins), Cumulative: s.cumulative})) + }) +} + +func c1BoxDemo(c *ui.Context, log func(string)) { + type state struct{ status string } + s := ui.Local(c.Root(), "110", func() state { return state{status: "Ready"} }) + c1Section(c, "BoxPlot", func() {}, func() { + frame, show := c1Frame(c, "Hymns", &s.status) + groups := []mujica.BoxGroup{ + {Name: "Choir", Values: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 24}}, + {Name: "Nave", Values: []float64{4, 5, 5, 6, 7, 8}}, + {Name: "Crypt", Values: []float64{12, 14, 15, 18, 22, 25}}, + } + if !show { + groups = nil + } + c1Log(log, "BoxPlot", mujica.BoxPlot(c, groups, mujica.BoxPlotOptions{Frame: frame})) + }) +} + +func c1WaterfallDemo(c *ui.Context, log func(string)) { + type state struct{ status string } + s := ui.Local(c.Root(), "111", func() state { return state{status: "Ready"} }) + c1Section(c, "WaterfallChart", func() {}, func() { + frame, show := c1Frame(c, "Ledger", &s.status) + steps := []mujica.WaterfallStep{ + {Label: "Tithes", Value: 12}, {Label: "Repairs", Value: -5}, {Label: "Q1", Kind: mujica.WaterfallSubtotal}, + {Label: "Alms", Value: 4}, {Label: "Bread", Value: -2}, {Label: "Year", Kind: mujica.WaterfallTotal}, + } + if !show { + steps = nil + } + c1Log(log, "WaterfallChart", mujica.WaterfallChart(c, steps, mujica.WaterfallChartOptions{Frame: frame})) + }) +} + +func c1FunnelDemo(c *ui.Context, log func(string)) { + type state struct{ status string } + s := ui.Local(c.Root(), "112", func() state { return state{status: "Ready"} }) + c1Section(c, "FunnelChart", func() {}, func() { + frame, show := c1Frame(c, "Order", &s.status) + stages := []mujica.ChartSlice{{Label: "Visitors", Value: 1000}, {Label: "Novices", Value: 400}, {Label: "Vows", Value: 100}, {Label: "Priors", Value: 12}} + if !show { + stages = nil + } + c1Log(log, "FunnelChart", mujica.FunnelChart(c, stages, mujica.FunnelChartOptions{Frame: frame})) + }) +} + +func c1BulletDemo(c *ui.Context, log func(string)) { + type state struct { + status string + value, target float64 + vertical bool + } + s := ui.Local(c.Root(), "113", func() state { return state{status: "Ready", value: 270, target: 250} }) + c1Section(c, "BulletChart", func() { + ui.Text(c, fmt.Sprintf("Value %.0f", s.value)) + ui.StepSlider(c, &s.value, 0, 300, 10).Width(140) + ui.Checkbox(c, &s.vertical, "Vertical") + }, func() { + frame, _ := c1Frame(c, "Alms", &s.status) + if s.vertical { + frame.Height = 200 + } + target := s.target + c1Log(log, "BulletChart", mujica.BulletChart(c, s.value, mujica.BulletChartOptions{Frame: frame, Target: &target, Bands: []float64{150, 225, 300}, Vertical: s.vertical})) + }) +} + +func c1SparkDemo(c *ui.Context, log func(string)) { + type state struct{ status string } + s := ui.Local(c.Root(), "114", func() state { return state{status: "Ready"} }) + c1Section(c, "Sparkline", func() {}, func() { + frame, show := c1Frame(c, "Bells", &s.status) + values := []float64{3, 5, 4, math.NaN(), 7, 6, 9, 8, 11} + if !show { + values = nil + } + ui.Row(c).Gap(24).Wrap().Children(func() { + for _, k := range []mujica.SparklineKind{mujica.SparklineLine, mujica.SparklineBar, mujica.SparklineArea} { + f := frame + f.Label = fmt.Sprintf("Bells %d", k+1) + c1Log(log, f.Label, mujica.Sparkline(c, values, mujica.SparklineOptions{Frame: f, Kind: k})) + } + }) + }) +} + +func c1GaugeDemo(c *ui.Context, log func(string)) { + type state struct { + status string + value float64 + full bool + } + s := ui.Local(c.Root(), "115", func() state { return state{status: "Ready", value: 72} }) + c1Section(c, "Gauge", func() { + ui.Text(c, fmt.Sprintf("Value %.0f", s.value)) + ui.StepSlider(c, &s.value, 0, 100, 1).Width(140) + ui.Checkbox(c, &s.full, "Full circle") + }, func() { + frame, _ := c1Frame(c, "Nave", &s.status) + segments := []mujica.GaugeSegment{{To: 60, Label: "Calm", Tone: mujica.GaugeGood}, {To: 85, Label: "Busy", Tone: mujica.GaugeWarning}, {To: 100, Label: "Crowded", Tone: mujica.GaugeDanger}} + c1Log(log, "Gauge", mujica.Gauge(c, s.value, mujica.GaugeOptions{Frame: frame, Max: 100, Unit: "%", Segments: segments, Full: s.full})) + }) +} diff --git a/examples/gallery/pages_charts1_test.go b/examples/gallery/pages_charts1_test.go new file mode 100644 index 0000000..af673ca --- /dev/null +++ b/examples/gallery/pages_charts1_test.go @@ -0,0 +1,71 @@ +package main + +import ( + "slices" + "strings" + "testing" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +// c1Demo runs page id's demo with an event log. +func c1Demo(t *testing.T, id string) (*ui.Tester, *[]string) { + t.Helper() + i := slices.IndexFunc(charts1Pages, func(p page) bool { return p.ID == id }) + if i < 0 { + t.Fatalf("no page %s", id) + } + events := &[]string{} + tt := ui.NewTester(func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + ui.Scroll(c).Fill().Padding(24).Children(func() { + charts1Pages[i].Demo(c, func(s string) { *events = append(*events, s) }) + }) + }, 900, 760) + tt.SetPreferences(ui.Preferences{ReduceMotion: true, TextScale: 1}) + return tt, events +} + +// c1Labels names each demo's chart for the keys. +var c1Labels = map[string]string{ + "101": "Attendance", "102": "Attendance", "103": "Tithes", "104": "Stores", "105": "Choir", "106": "Skills", + "107": "Hours", "108": "Prayers", "109": "Ages", "110": "Hymns", "111": "Ledger", "112": "Order", "113": "Alms", + "114": "Bells 1", "115": "Nave", "116": "Rooms", "117": "Rooms", "118": "Money", "119": "House", "120": "Sound", +} + +func TestCharts1DemosLogReadouts(t *testing.T) { + for _, p := range charts1Pages { + if p.Category != "Charts I" || p.Code == "" || p.Keys == "" { + t.Fatalf("%s: incomplete page", p.ID) + } + tt, events := c1Demo(t, p.ID) + tabUntil(t, tt, c1Labels[p.ID]) + tt.Key(0, ui.KeyRight) + if len(*events) == 0 || !strings.HasSuffix((*events)[len(*events)-1], "point 0") { + t.Errorf("%s: keyboard readout not logged: %q", p.ID, *events) + } + } +} + +func TestCharts1TreemapDrillLogs(t *testing.T) { + tt, events := c1Demo(t, "116") + tabUntil(t, tt, "Rooms") + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyEnter) + if !slices.Contains(*events, "Treemap: path /Library") { + t.Fatalf("drill not logged: %q", *events) + } +} + +func tabUntil(t *testing.T, tt *ui.Tester, label string) { + t.Helper() + for range 40 { + if tt.Focused(label) { + return + } + tt.Key(0, ui.KeyTab) + } + t.Fatalf("Tab never reached %q", label) +} diff --git a/funnel_chart.go b/funnel_chart.go new file mode 100644 index 0000000..afac694 --- /dev/null +++ b/funnel_chart.go @@ -0,0 +1,85 @@ +package mujica + +import ( + "fmt" + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// FunnelChartOptions configure a FunnelChart. +type FunnelChartOptions struct { + Frame ChartFrame + Format func(v float64) string +} + +// FunnelChart narrows by stage, labeled with conversion rates. +func FunnelChart(c *ui.Context, stages []ChartSlice, opts FunnelChartOptions) ChartResult { + top := 0.0 + for _, s := range stages { + if s.Label == "" || s.Value < 0 || math.IsNaN(s.Value) || math.IsInf(s.Value, 0) { + panic("mujica: FunnelChart stages need a label and a finite value ≥ 0") + } + top = max(top, s.Value) + } + ch := newChart(c, opts.Frame) + k := Tokens(c) + col := internal.Palette(k)[0] + size := FontSize(c, theme.CaptionSize) + n := len(stages) + if top == 0 { + n = 0 + } + pct := func(a, b float64) string { + if b == 0 { + return "—" + } + return fmt.Sprintf("%.1f%%", 100*a/b) + } + rate := func(i int) string { + if i == 0 { + return pct(stages[0].Value, stages[0].Value) + } + return pct(stages[i].Value, stages[i-1].Value) + } + geom := func(r ui.Rect) (ui.Rect, internal.Band) { + plot := ui.Rect{X: r.X + 8, Y: r.Y + 4, W: r.W * 0.58, H: r.H - 8} + return plot, internal.Band{N: len(stages), R0: plot.Y, R1: plot.Y + plot.H, Pad: 0.08} + } + spec := chartSpec{n: n} + spec.readout = func(i int) string { + s := stages[i] + return fmt.Sprintf(msg(c, "funnel_chart.readout"), s.Label, chartValue(c, s.Value, opts.Format), rate(i), pct(s.Value, stages[0].Value)) + } + spec.pick = func(r ui.Rect, x, y float32) int { + plot, band := geom(r) + if y < plot.Y || y >= plot.Y+plot.H || x < r.X || x > r.X+r.W { + return -1 + } + return min(len(stages)-1, int((y-plot.Y)/band.Step())) + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + plot, band := geom(r) + cx := plot.X + plot.W/2 + width := func(i int) float32 { return max(plot.W*float32(stages[min(i, len(stages)-1)].Value/top), 2) } + for i, s := range stages { + y0, y1 := band.Start(i), band.Start(i)+band.Width() + w0, w1 := width(i), width(i+1) + var shape ui.Path + shape.MoveTo(cx-w0/2, y0).LineTo(cx+w0/2, y0).LineTo(cx+w1/2, y1).LineTo(cx-w1/2, y1).Close() + p.FillPath(&shape, col) + if i == active { + p.StrokePath(&shape, 2, k.Text) + } + ly := (y0 + y1) / 2 + lx := plot.X + plot.W + 16 + chartText(p, s.Label+" · "+chartValue(c, s.Value, opts.Format), lx, ly, size, k.Text, 0, 1) + chartText(p, rate(i), lx, ly+2, size, k.TextMuted, 0, 0) + } + } + res, _ := ch.build(spec) + return res +} diff --git a/funnel_chart_test.go b/funnel_chart_test.go new file mode 100644 index 0000000..d3dbfa6 --- /dev/null +++ b/funnel_chart_test.go @@ -0,0 +1,54 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +var funnelStages = []ChartSlice{{"Visitors", 1000}, {"Novices", 400}, {"Vows", 100}, {"Abbots", 0}} + +func TestFunnelChartReadout(t *testing.T) { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return FunnelChart(c, funnelStages, FunnelChartOptions{Frame: ChartFrame{Label: "Order"}}) + }} + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "Order") + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "Novices · 400 · 40.0% of the stage before · 40.0% of the first" { + t.Fatalf("readout %q", got) + } + tt.Key(0, ui.KeyEscape) + b := h.res.Element.Bounds() + tt.Move(b.X+b.W/3, b.Y+4+232*0.6) // third stage band + if got := chartReadout(tt); got != "Vows · 100 · 25.0% of the stage before · 10.0% of the first" { + t.Fatalf("hover %q", got) + } +} + +func TestFunnelChartBadAndEmpty(t *testing.T) { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return FunnelChart(c, []ChartSlice{{"a", 0}}, FunnelChartOptions{Frame: ChartFrame{Label: "Order"}}) + }} + if tt := ui.NewTester(h.view, 520, 420); !tt.HasText("No data") { + t.Fatal("all-zero funnel is not empty") + } + defer func() { + if recover() == nil { + t.Fatal("no panic for a negative stage") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + FunnelChart(c, []ChartSlice{{"a", -1}}, FunnelChartOptions{Frame: ChartFrame{Label: "x"}}) + }, 300, 300) +} + +func TestFunnelChartSnapshot(t *testing.T) { + snapshot(t, "funnel_chart", 520, 300, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + FunnelChart(c, funnelStages[:3], FunnelChartOptions{Frame: ChartFrame{Label: "Order", Height: 220}}) + }) + }) +} diff --git a/gauge.go b/gauge.go new file mode 100644 index 0000000..21915df --- /dev/null +++ b/gauge.go @@ -0,0 +1,154 @@ +package mujica + +import ( + "fmt" + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// GaugeTone colors a Gauge segment; its label still names it. +type GaugeTone int + +const ( + GaugeNeutral GaugeTone = iota + GaugeGood + GaugeWarning + GaugeDanger +) + +// GaugeSegment is a named dial range up to To. +type GaugeSegment struct { + To float64 + Label string + Tone GaugeTone +} + +// GaugeOptions configure a Gauge; Frame.Height 0 means 200 DIPs. +type GaugeOptions struct { + Frame ChartFrame + Min, Max float64 + // Segments split Min..Max ascending; the last ends at Max. + Segments []GaugeSegment + Unit string + // Full draws a whole circle instead of a half. + Full bool + Format func(v float64) string +} + +// Gauge points a needle at value on named segments. +func Gauge(c *ui.Context, value float64, opts GaugeOptions) ChartResult { + if !(opts.Max > opts.Min) || math.IsNaN(value) || value < opts.Min || value > opts.Max { + panic("mujica: Gauge needs Min < Max and a value between them") + } + prev := opts.Min + for i, s := range opts.Segments { + if s.To <= prev || s.Label == "" || i == len(opts.Segments)-1 && s.To != opts.Max { + panic("mujica: Gauge segments need labels and ascending ends finishing at Max") + } + prev = s.To + } + if opts.Frame.Height == 0 { + opts.Frame.Height = 200 + } + ch := newChart(c, opts.Frame) + k := Tokens(c) + size := FontSize(c, theme.CaptionSize) + tone := func(t GaugeTone) ui.Color { + return map[GaugeTone]ui.Color{GaugeNeutral: internal.Palette(k)[5], GaugeGood: k.Success, GaugeWarning: k.Warning, GaugeDanger: k.Danger}[t] + } + val := func(v float64) string { return chartValue(c, v, opts.Format) } + seg := -1 + for i, s := range opts.Segments { + if value <= s.To && seg < 0 { + seg = i + } + } + a0, a1 := -math.Pi/2, math.Pi/2 + if opts.Full { + a0, a1 = -math.Pi, math.Pi + } + angle := func(v float64) float64 { return a0 + (a1-a0)*(v-opts.Min)/(opts.Max-opts.Min) } + geom := func(r ui.Rect) (cx, cy, rad float32) { + if opts.Full { + rad = min(r.W, r.H)/2 - 12 + return r.X + r.W/2, r.Y + r.H/2, rad + } + rad = min(r.W/2-12, r.H-36) + return r.X + r.W/2, r.Y + 8 + rad, rad + } + reading := val(value) + " " + opts.Unit + if seg >= 0 { + reading += " · " + opts.Segments[seg].Label + } + spec := chartSpec{n: 1 + len(opts.Segments)} + spec.readout = func(i int) string { + if i == 0 { + return reading + } + s, from := opts.Segments[i-1], opts.Min + if i > 1 { + from = opts.Segments[i-2].To + } + return fmt.Sprintf("%s: %s–%s", s.Label, val(from), val(s.To)) + } + spec.pick = func(r ui.Rect, x, y float32) int { + cx, cy, rad := geom(r) + d := float32(math.Hypot(float64(x-cx), float64(y-cy))) + if d < rad*0.45 { + return 0 + } + if d > rad+6 { + return -1 + } + a := math.Atan2(float64(x-cx), float64(cy-y)) + from := a0 + for i, s := range opts.Segments { + if a >= from && a <= angle(s.To) { + return i + 1 + } + from = angle(s.To) + } + return -1 + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + cx, cy, rad := geom(r) + from := a0 + if len(opts.Segments) == 0 { + p.FillPath(internal.Sector(cx, cy, rad*0.78, rad, a0, a1), k.SurfaceHover) + } + for i, s := range opts.Segments { + to := angle(s.To) + grow := float32(0) + if active == i+1 { + grow = 4 + } + p.FillPath(internal.Sector(cx, cy, rad*0.78-grow, rad+grow, from, to), tone(s.Tone)) + p.StrokePath(internal.Sector(cx, cy, rad*0.78-grow, rad+grow, from, to), 1.5, k.Surface) + lx, ly := internal.Polar(cx, cy, rad+10, to) + if i < len(opts.Segments)-1 { + chartText(p, val(s.To), lx, ly, size, k.TextMuted, 0.5, 1) + } + from = to + } + nx, ny := internal.Polar(cx, cy, rad*0.9, angle(value)) + var needle ui.Path + needle.MoveTo(cx, cy).LineTo(internal.Snap(p, nx), internal.Snap(p, ny)) + w := float32(3) + if active == 0 { + w = 4.5 + } + p.StrokePath(&needle, w, k.Text) + p.FillPath(internal.Diamond(cx, cy, 12), k.Text) + ty := cy + 34 + chartText(p, val(value)+" "+opts.Unit, cx, ty, FontSize(c, theme.H3Size), k.Text, 0.5, 1) + if seg >= 0 { + chartText(p, opts.Segments[seg].Label, cx, ty+2, size, k.TextMuted, 0.5, 0) + } + } + res, _ := ch.build(spec) + return res +} diff --git a/gauge_test.go b/gauge_test.go new file mode 100644 index 0000000..5f87b6a --- /dev/null +++ b/gauge_test.go @@ -0,0 +1,75 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +var gaugeSegments = []GaugeSegment{{60, "Calm", GaugeGood}, {85, "Busy", GaugeWarning}, {100, "Crowded", GaugeDanger}} + +func TestGaugeReadoutNamesSegment(t *testing.T) { + full := false + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return Gauge(c, 72, GaugeOptions{Frame: ChartFrame{Label: "Nave"}, Max: 100, Unit: "%", Segments: gaugeSegments, Full: full}) + }} + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "Nave") + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "72 % · Busy" { + t.Fatalf("value %q", got) + } + tt.Key(0, ui.KeyEnd) + if got := chartReadout(tt); got != "Crowded: 85–100" { + t.Fatalf("last segment %q", got) + } + tt.Key(0, ui.KeyEscape) + for _, full = range []bool{false, true} { + tt.Frame() + b := h.res.Element.Bounds() + cx := b.X + b.W/2 + var cy, rad float32 + if full { + rad = 200/2 - 12 + cy = b.Y + 100 + } else { + rad = min(b.W/2-12, 200-36) + cy = b.Y + 8 + rad + } + tt.Move(cx-rad*0.7, cy-rad*0.6) // the left of the dial: the first segment + if got := chartReadout(tt); got != "Calm: 0–60" { + t.Fatalf("full=%v hover %q", full, got) + } + } +} + +func TestGaugeBad(t *testing.T) { + for name, o := range map[string]GaugeOptions{ + "range": {Max: 0}, + "segments": {Max: 100, Segments: []GaugeSegment{{50, "a", 0}, {40, "b", 0}}}, + "end": {Max: 100, Segments: []GaugeSegment{{50, "a", 0}}}, + } { + func() { + defer func() { + if recover() == nil { + t.Errorf("%s: no panic", name) + } + }() + o.Frame.Label = "x" + ui.NewTester(func(c *ui.Context) { Use(c, Settings{}); Gauge(c, 0, o) }, 300, 300) + }() + } +} + +func TestGaugeSnapshot(t *testing.T) { + snapshot(t, "gauge", 560, 300, func(c *ui.Context) { + ui.Row(c).Padding(16).Gap(16).Children(func() { + ui.Column(c).Width(256).Children(func() { + Gauge(c, 72, GaugeOptions{Frame: ChartFrame{Label: "Half"}, Max: 100, Unit: "%", Segments: gaugeSegments}) + }) + ui.Column(c).Width(256).Children(func() { + Gauge(c, 30, GaugeOptions{Frame: ChartFrame{Label: "Full"}, Max: 100, Unit: "%", Segments: gaugeSegments, Full: true}) + }) + }) + }) +} diff --git a/heatmap_chart.go b/heatmap_chart.go new file mode 100644 index 0000000..321dbf0 --- /dev/null +++ b/heatmap_chart.go @@ -0,0 +1,123 @@ +package mujica + +import ( + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// HeatmapChartOptions configure a HeatmapChart. +type HeatmapChartOptions struct { + Frame ChartFrame + Format func(v float64) string +} + +// heatSteps is the number of color steps. +const heatSteps = 5 + +// HeatmapChart colors a matrix by value; NaN cells are dashed. +func HeatmapChart(c *ui.Context, rows, cols []string, values [][]float64, opts HeatmapChartOptions) ChartResult { + if len(values) != len(rows) { + panic("mujica: HeatmapChart needs one value row per row label") + } + lo, hi := math.Inf(1), math.Inf(-1) + for _, r := range values { + if len(r) != len(cols) { + panic("mujica: HeatmapChart needs one value per column label") + } + for _, v := range r { + if !math.IsNaN(v) { + lo, hi = min(lo, v), max(hi, v) + } + } + } + ch := newChart(c, opts.Frame) + k := Tokens(c) + size := FontSize(c, theme.CaptionSize) + n := len(rows) * len(cols) + if math.IsInf(lo, 1) { + n = 0 + } + // level is v's color step, 0 to heatSteps-1. + level := func(v float64) int { + if hi == lo { + return heatSteps - 1 + } + return min(heatSteps-1, int((v-lo)/(hi-lo)*heatSteps)) + } + geom := func(r ui.Rect) (ui.Rect, internal.Band, internal.Band) { + plot := ui.Rect{X: r.X + 72, Y: r.Y + 4, W: max(r.W-72-64, 1), H: max(r.H-28, 1)} + return plot, internal.Band{N: len(cols), R0: plot.X, R1: plot.X + plot.W, Pad: 0.06}, internal.Band{N: len(rows), R0: plot.Y, R1: plot.Y + plot.H, Pad: 0.06} + } + cell := func(xb, yb internal.Band, i int) ui.Rect { + return ui.Rect{X: xb.Start(i % len(cols)), Y: yb.Start(i / len(cols)), W: xb.Width(), H: yb.Width()} + } + spec := chartSpec{n: n} + spec.readout = func(i int) string { + return rows[i/len(cols)] + " · " + cols[i%len(cols)] + " · " + chartValue(c, values[i/len(cols)][i%len(cols)], opts.Format) + } + spec.move = func(i int, key ui.Key) int { + r, col := i/len(cols), i%len(cols) + switch key { + case ui.KeyLeft: + col = max(col-1, 0) + case ui.KeyRight: + col = min(col+1, len(cols)-1) + case ui.KeyUp: + r = max(r-1, 0) + default: + r = min(r+1, len(rows)-1) + } + return r*len(cols) + col + } + spec.pick = func(r ui.Rect, x, y float32) int { + plot, xb, yb := geom(r) + if !plot.Contains(x, y) { + return -1 + } + col := min(len(cols)-1, int((x-plot.X)/xb.Step())) + row := min(len(rows)-1, int((y-plot.Y)/yb.Step())) + return row*len(cols) + col + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + plot, xb, yb := geom(r) + for i := range len(rows) * len(cols) { + b := cell(xb, yb, i) + v := values[i/len(cols)][i%len(cols)] + if math.IsNaN(v) { + p.StrokeDashed(b, k.ControlBorder, 2, 1) + } else { + bg := internal.Ramp(k, (float64(level(v))+0.5)/heatSteps) + p.Fill(b, bg, 2) + if b.W >= 30 && b.H >= 18 { + chartText(p, chartValue(c, v, opts.Format), b.X+b.W/2, b.Y+b.H/2, size, chartInk(k, bg), 0.5, 0.5) + } + } + if i == active { + p.Stroke(ui.Rect{X: b.X - 2, Y: b.Y - 2, W: b.W + 4, H: b.H + 4}, k.Text, 3, 2) + } + } + for i, name := range rows { + chartText(p, name, plot.X-8, yb.Center(i), size, k.TextMuted, 1, 0.5) + } + for i, name := range cols { + chartText(p, name, xb.Center(i), plot.Y+plot.H+4, size, k.TextMuted, 0.5, 0) + } + heatLegend(p, ui.Rect{X: plot.X + plot.W + 16, Y: plot.Y, W: 14, H: plot.H}, lo, hi, size, k, opts.Format, c) + } + res, _ := ch.build(spec) + return res +} + +// heatLegend stacks the color steps with the range at ends. +func heatLegend(p *ui.Painter, r ui.Rect, lo, hi float64, size float32, k theme.Tokens, format func(float64) string, c *ui.Context) { + h := min(r.H, 120) / heatSteps + for i := range heatSteps { + p.Fill(ui.Rect{X: r.X, Y: r.Y + float32(heatSteps-1-i)*h, W: r.W, H: h - 1}, internal.Ramp(k, (float64(i)+0.5)/heatSteps), 1) + } + chartText(p, chartValue(c, hi, format), r.X+r.W+4, r.Y, size, k.TextMuted, 0, 0) + chartText(p, chartValue(c, lo, format), r.X+r.W+4, r.Y+h*heatSteps, size, k.TextMuted, 0, 1) +} diff --git a/heatmap_chart_test.go b/heatmap_chart_test.go new file mode 100644 index 0000000..4b6b10d --- /dev/null +++ b/heatmap_chart_test.go @@ -0,0 +1,68 @@ +package mujica + +import ( + "math" + "testing" + + "github.com/egoist/mygo/ui" +) + +var heatRows = []string{"Mon", "Tue", "Wed"} +var heatCols = []string{"Matins", "Lauds", "Vespers", "Compline"} + +func heatValues() [][]float64 { + return [][]float64{{1, 4, 9, 2}, {3, math.NaN(), 7, 5}, {8, 6, 0, 3}} +} + +func TestHeatmapChartKeyboard2D(t *testing.T) { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return HeatmapChart(c, heatRows, heatCols, heatValues(), HeatmapChartOptions{Frame: ChartFrame{Label: "Hours"}}) + }} + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "Hours") + tt.Key(0, ui.KeyRight) // enters at the first cell + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyDown) + if got := chartReadout(tt); got != "Tue · Lauds · no value" { + t.Fatalf("readout %q", got) + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnd) + if got := chartReadout(tt); got != "Wed · Compline · 3" { + t.Fatalf("End %q", got) + } +} + +func TestHeatmapChartHover(t *testing.T) { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return HeatmapChart(c, heatRows, heatCols, heatValues(), HeatmapChartOptions{Frame: ChartFrame{Label: "Hours"}}) + }} + tt := ui.NewTester(h.view, 520, 420) + b := h.res.Element.Bounds() + plotW := b.W - 72 - 64 + tt.Move(b.X+72+plotW*0.6, b.Y+4+212*0.2) // third column, first row + if got := chartReadout(tt); got != "Mon · Vespers · 9" { + t.Fatalf("hover %q", got) + } +} + +func TestHeatmapChartBad(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic for a short row") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + HeatmapChart(c, heatRows[:1], heatCols, [][]float64{{1}}, HeatmapChartOptions{Frame: ChartFrame{Label: "x"}}) + }, 300, 300) +} + +func TestHeatmapChartSnapshot(t *testing.T) { + snapshot(t, "heatmap_chart", 520, 300, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + HeatmapChart(c, heatRows, heatCols, heatValues(), HeatmapChartOptions{Frame: ChartFrame{Label: "Hours", Height: 220}}) + }) + }) +} diff --git a/histogram.go b/histogram.go new file mode 100644 index 0000000..b36e96d --- /dev/null +++ b/histogram.go @@ -0,0 +1,157 @@ +package mujica + +import ( + "fmt" + "math" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// HistogramOptions configure a Histogram. +type HistogramOptions struct { + Frame ChartFrame + // Bins is the bin count; 0 uses Sturges' rule. + Bins int + BinWidth float64 + // Cumulative counts every value up to each bin's upper edge. + Cumulative bool + Format func(v float64) string +} + +// histogramMaxBins bounds the bins a width may make. +const histogramMaxBins = 10_000 + +type histBins struct { + start, width float64 + counts []int +} + +// histogramBin counts finite values into equal bins. +func histogramBin(values []float64, bins int, width float64, cumulative bool) histBins { + lo, hi := math.Inf(1), math.Inf(-1) + n := 0 + for _, v := range values { + if !math.IsNaN(v) && !math.IsInf(v, 0) { + lo, hi, n = min(lo, v), max(hi, v), n+1 + } + } + if n == 0 { + return histBins{} + } + var b histBins + switch { + case width > 0: + b.start, b.width = math.Floor(lo/width)*width, width + bins = max(1, int(math.Ceil((hi-b.start)/width-1e-9))) + if hi == b.start+float64(bins)*width { + bins++ + } + default: + if bins == 0 { + bins = int(math.Ceil(math.Log2(float64(n)))) + 1 + } + b.start, b.width = lo, (hi-lo)/float64(bins) + if b.width == 0 { + b.width = 1 + } + } + if bins > histogramMaxBins { + panic("mujica: Histogram would make more than 10000 bins") + } + b.counts = make([]int, bins) + for _, v := range values { + if math.IsNaN(v) || math.IsInf(v, 0) { + continue + } + b.counts[min(bins-1, int((v-b.start)/b.width))]++ + } + if cumulative { + for i := 1; i < bins; i++ { + b.counts[i] += b.counts[i-1] + } + } + return b +} + +// Histogram counts values into equal bins drawn as bars. +func Histogram(c *ui.Context, values []float64, opts HistogramOptions) ChartResult { + if opts.Bins < 0 || opts.BinWidth < 0 || math.IsNaN(opts.BinWidth) { + panic("mujica: Histogram Bins and BinWidth must be ≥ 0") + } + ch := newChart(c, opts.Frame) + k := Tokens(c) + col := internal.Palette(k)[0] + size := FontSize(c, theme.CaptionSize) + b := chartMemo(ch, "bins", [4]any{chartID(values), opts.Bins, opts.BinWidth, opts.Cumulative}, func() histBins { + return histogramBin(values, opts.Bins, opts.BinWidth, opts.Cumulative) + }) + top := 0 + for _, n := range b.counts { + top = max(top, n) + } + var ys internal.Linear + var hi, step float64 + if top > 0 { + _, hi, step = internal.Nice(0, float64(top), 4) + step = max(step, 1) + } + // edge writes bin edge i at a given precision. + edge := func(i int, fine float64) string { + v := b.start + float64(i)*b.width + if opts.Format != nil { + return opts.Format(v) + } + s := internal.FormatTick(v, b.width/fine) + if strings.Contains(s, ".") { + s = strings.TrimRight(strings.TrimRight(s, "0"), ".") + } + return s + } + geom := func(r ui.Rect) (ui.Rect, internal.Band) { + plot := chartInset(r, 52, 26) + ys = internal.Linear{D0: 0, D1: hi, R0: float64(plot.Y + plot.H), R1: float64(plot.Y)} + return plot, internal.Band{N: len(b.counts), R0: plot.X, R1: plot.X + plot.W, Pad: 0.06} + } + spec := chartSpec{n: len(b.counts)} + spec.readout = func(i int) string { + if opts.Cumulative { + return fmt.Sprintf("≤ %s · %d", edge(i+1, 100), b.counts[i]) + } + closer := ")" + if i == len(b.counts)-1 && opts.BinWidth == 0 { + closer = "]" + } + return fmt.Sprintf("[%s, %s%s · %d", edge(i, 100), edge(i+1, 100), closer, b.counts[i]) + } + spec.pick = func(r ui.Rect, x, y float32) int { + plot, band := geom(r) + if !plot.Contains(x, y) { + return -1 + } + return min(len(b.counts)-1, int((x-plot.X)/band.Step())) + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + plot, band := geom(r) + internal.AxisY(p, plot, ys, internal.Ticks(0, hi, step), func(v float64) string { return internal.FormatTick(v, step) }, size, k) + var xs []float32 + var labels []string + for i := 0; i <= len(b.counts); i++ { + xs, labels = append(xs, plot.X+band.Step()*float32(i)), append(labels, edge(i, 1)) + } + internal.AxisX(p, plot, xs, labels, size, k) + for i, n := range b.counts { + y := ys.Map(float64(n)) + bar := ui.Rect{X: band.Start(i), Y: y, W: band.Width(), H: plot.Y + plot.H - y} + p.Fill(bar, col, 1) + if i == active { + p.Stroke(ui.Rect{X: bar.X - 2, Y: bar.Y - 2, W: bar.W + 4, H: bar.H + 4}, k.Text, 2, 1.5) + } + } + } + res, _ := ch.build(spec) + return res +} diff --git a/histogram_test.go b/histogram_test.go new file mode 100644 index 0000000..514bbdd --- /dev/null +++ b/histogram_test.go @@ -0,0 +1,76 @@ +package mujica + +import ( + "fmt" + "math" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestHistogramBin(t *testing.T) { + vals := []float64{1, 2, 2, 3, 4, 5, 9, 10, math.NaN()} + if got := histogramBin(vals, 3, 0, false); fmt.Sprint(got.counts) != "[4 2 2]" || got.start != 1 || got.width != 3 { + t.Fatalf("3 bins %+v", got) + } + if got := histogramBin(vals, 0, 5, false); fmt.Sprint(got.counts) != "[5 2 1]" || got.start != 0 { + t.Fatalf("width 5 %+v", got) + } + if got := histogramBin(vals, 0, 5, true); fmt.Sprint(got.counts) != "[5 7 8]" { + t.Fatalf("cumulative %+v", got) + } + if got := histogramBin(vals, 0, 0, false); len(got.counts) != 4 { + t.Fatalf("Sturges for 8 values: %d bins", len(got.counts)) + } + if got := histogramBin([]float64{math.NaN()}, 3, 0, false); got.counts != nil { + t.Fatal("no finite values made bins") + } +} + +func TestHistogramReadoutAndModes(t *testing.T) { + opts := HistogramOptions{Frame: ChartFrame{Label: "Ages"}, BinWidth: 5} + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return Histogram(c, []float64{1, 2, 2, 3, 4, 5, 9, 10}, opts) + }} + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "Ages") + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "[0, 5) · 5" { + t.Fatalf("first bin %q", got) + } + tt.Key(0, ui.KeyEnd) + if got := chartReadout(tt); got != "[10, 15) · 1" { + t.Fatalf("last bin %q", got) + } + opts.Cumulative = true + tt.Frame() + if got := chartReadout(tt); got != "≤ 15 · 8" { + t.Fatalf("cumulative %q", got) + } +} + +func TestHistogramBad(t *testing.T) { + for _, o := range []HistogramOptions{{Bins: -1}, {BinWidth: 1e-9}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%+v: no panic", o) + } + }() + o.Frame.Label = "x" + ui.NewTester(func(c *ui.Context) { Use(c, Settings{}); Histogram(c, []float64{0, 1}, o) }, 300, 300) + }() + } +} + +func TestHistogramSnapshot(t *testing.T) { + vals := make([]float64, 400) + for i := range vals { + vals[i] = 50 + 15*math.Sin(float64(i)*1.7)*math.Cos(float64(i)*0.3) + } + snapshot(t, "histogram", 520, 320, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + Histogram(c, vals, HistogramOptions{Frame: ChartFrame{Label: "Ages"}, Bins: 12}) + }) + }) +} diff --git a/internal/chart.go b/internal/chart.go new file mode 100644 index 0000000..30286b9 --- /dev/null +++ b/internal/chart.go @@ -0,0 +1,264 @@ +package internal + +import ( + "math" + "strconv" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// Linear maps domain D0..D1 onto pixels R0..R1. +type Linear struct{ D0, D1, R0, R1 float64 } + +// Map returns the pixel of v. +func (s Linear) Map(v float64) float32 { + if s.D1 == s.D0 { + return float32((s.R0 + s.R1) / 2) + } + return float32(s.R0 + (v-s.D0)/(s.D1-s.D0)*(s.R1-s.R0)) +} + +// Invert returns the value at pixel px. +func (s Linear) Invert(px float32) float64 { + if s.R1 == s.R0 { + return s.D0 + } + return s.D0 + (float64(px)-s.R0)/(s.R1-s.R0)*(s.D1-s.D0) +} + +// Nice widens lo..hi to round steps of about n ticks. +func Nice(lo, hi float64, n int) (nlo, nhi, step float64) { + if n < 1 || math.IsNaN(lo) || math.IsNaN(hi) || lo > hi { + panic("internal: bad Nice domain") + } + if lo == hi { + lo, hi = lo-1, hi+1 + } + raw := (hi - lo) / float64(n) + mag := math.Pow(10, math.Floor(math.Log10(raw))) + step = 10 * mag + for _, m := range []float64{1, 2, 5} { + if m*mag >= raw { + step = m * mag + break + } + } + return math.Floor(lo/step) * step, math.Ceil(hi/step) * step, step +} + +// Ticks lists the multiples of step from lo to hi. +func Ticks(lo, hi, step float64) []float64 { + var out []float64 + for i := math.Ceil(lo/step - 1e-9); i*step <= hi+step*1e-9; i++ { + out = append(out, i*step) + } + return out +} + +// FormatTick writes v with as many decimals as step needs. +func FormatTick(v, step float64) string { + d := max(0, int(-math.Floor(math.Log10(step)+1e-9))) + if math.Abs(v) < step*1e-9 { + v = 0 + } + return strconv.FormatFloat(v, 'f', d, 64) +} + +// timeSteps are the tick spacings a time axis chooses from. +var timeSteps = []struct { + d time.Duration + layout string +}{ + {time.Second, "15:04:05"}, {5 * time.Second, "15:04:05"}, {15 * time.Second, "15:04:05"}, {30 * time.Second, "15:04:05"}, + {time.Minute, "15:04"}, {5 * time.Minute, "15:04"}, {15 * time.Minute, "15:04"}, {30 * time.Minute, "15:04"}, + {time.Hour, "15:04"}, {3 * time.Hour, "15:04"}, {6 * time.Hour, "Jan 2 15:04"}, {12 * time.Hour, "Jan 2 15:04"}, + {24 * time.Hour, "Jan 2"}, {7 * 24 * time.Hour, "Jan 2"}, {30 * 24 * time.Hour, "Jan 2006"}, {365 * 24 * time.Hour, "2006"}, +} + +// TimeTicks returns about n round times and their layout. +func TimeTicks(lo, hi time.Time, n int) ([]time.Time, string) { + if n < 1 || hi.Before(lo) { + panic("internal: bad TimeTicks domain") + } + span := hi.Sub(lo) / time.Duration(n) + step := timeSteps[len(timeSteps)-1] + for _, s := range timeSteps { + if s.d >= span { + step = s + break + } + } + var out []time.Time + for t := lo.Truncate(step.d); !t.After(hi); t = t.Add(step.d) { + if !t.Before(lo) { + out = append(out, t) + } + } + return out, step.layout +} + +// Band splits R0..R1 into N bands, each Pad empty. +type Band struct { + N int + R0, R1 float32 + Pad float32 +} + +// Step is the room one band takes. +func (b Band) Step() float32 { return (b.R1 - b.R0) / float32(max(b.N, 1)) } + +// Width is a band's drawn width. +func (b Band) Width() float32 { return b.Step() * (1 - b.Pad) } + +// Start is where band i is drawn from. +func (b Band) Start(i int) float32 { return b.R0 + b.Step()*float32(i) + b.Step()*b.Pad/2 } + +// Center is the middle of band i. +func (b Band) Center(i int) float32 { return b.R0 + b.Step()*(float32(i)+0.5) } + +// Palette returns six series colors at 3:1 against Surface. +func Palette(k theme.Tokens) []ui.Color { + out := []ui.Color{k.AccentText, k.Info, k.Success, k.Warning, k.Ornament, k.TextMuted} + for i, col := range out { + for t := float32(0.1); theme.Contrast(col, k.Surface) < 3; t += 0.1 { + col = out[i].Mix(k.Text, t) + } + out[i] = col + } + return out +} + +// Ramp is the sequential color for t in 0..1. +func Ramp(k theme.Tokens, t float64) ui.Color { + return k.Surface.Mix(k.AccentText, float32(0.12+0.88*max(0, min(t, 1)))) +} + +// Marker draws series shape i centered at (cx, cy). +func Marker(p *ui.Painter, i int, cx, cy, size float32, col ui.Color) { + cx, cy = Snap(p, cx), Snap(p, cy) + h := size / 2 + var path ui.Path + switch i % 5 { + case 0: + path.Circle(cx, cy, h) + case 1: + h *= 0.85 + path.MoveTo(cx-h, cy-h).LineTo(cx+h, cy-h).LineTo(cx+h, cy+h).LineTo(cx-h, cy+h).Close() + case 2: + p.FillPath(Diamond(cx, cy, size*1.2), col) + return + case 3: + path.MoveTo(cx, cy-h).LineTo(cx+h, cy+h*0.8).LineTo(cx-h, cy+h*0.8).Close() + default: + path.MoveTo(cx-h, cy-h*0.8).LineTo(cx+h, cy-h*0.8).LineTo(cx, cy+h).Close() + } + p.FillPath(&path, col) +} + +// Arc appends a polyline from a0 to a1, clockwise radians. +func Arc(path *ui.Path, cx, cy, r float32, a0, a1 float64, move bool) { + n := max(2, int(math.Ceil(math.Abs(a1-a0)/(math.Pi/48)))) + for i := 0; i <= n; i++ { + x, y := Polar(cx, cy, r, a0+(a1-a0)*float64(i)/float64(n)) + if i == 0 && move { + path.MoveTo(x, y) + } else { + path.LineTo(x, y) + } + } +} + +// Polar returns the point r from center at angle a. +func Polar(cx, cy, r float32, a float64) (float32, float32) { + return cx + r*float32(math.Sin(a)), cy - r*float32(math.Cos(a)) +} + +// Sector returns a ring slice; zero r0 makes a wedge. +func Sector(cx, cy, r0, r1 float32, a0, a1 float64) *ui.Path { + var path ui.Path + Arc(&path, cx, cy, r1, a0, a1, true) + if r0 > 0 { + Arc(&path, cx, cy, r0, a1, a0, false) + } else { + path.LineTo(cx, cy) + } + path.Close() + return &path +} + +// Rule draws a pixel-aligned 1 DIP horizontal line at y. +func Rule(p *ui.Painter, x0, x1, y float32, c ui.Color) { + yy := ruleY(p, y) + p.Line(x0, yy, x1, yy, 1, c) +} + +// AxisY draws grid lines and tick labels left of plot. +func AxisY(p *ui.Painter, plot ui.Rect, s Linear, ticks []float64, label func(float64) string, size float32, k theme.Tokens) { + for _, t := range ticks { + y := s.Map(t) + Rule(p, plot.X, plot.X+plot.W, y, k.Border) + txt := label(t) + w, h := p.MeasureText(0, ui.Span{Text: txt, Size: size}) + p.Text(plot.X-w-6, y-h/2, txt, size, k.TextMuted) + } +} + +// AxisX draws a baseline and labels centered at xs. +func AxisX(p *ui.Painter, plot ui.Rect, xs []float32, labels []string, size float32, k theme.Tokens) { + Rule(p, plot.X, plot.X+plot.W, plot.Y+plot.H, k.ControlBorder) + right := float32(math.Inf(-1)) + for i, x := range xs { + w, _ := p.MeasureText(0, ui.Span{Text: labels[i], Size: size}) + at := min(max(x-w/2, plot.X-12), plot.X+plot.W+12-w) + // Labels that would overlap the last one drawn are skipped. + if at < right+6 { + continue + } + p.Text(at, plot.Y+plot.H+6, labels[i], size, k.TextMuted) + right = at + w + } +} + +// Nearest returns the closest point within reach, or -1. +func Nearest(n int, at func(i int) (float32, float32), x, y, reach float32, byX bool) int { + best, dist := -1, reach*reach + for i := range n { + px, py := at(i) + d := (px - x) * (px - x) + if !byX { + d += (py - y) * (py - y) + } + if d <= dist { + best, dist = i, d + } + } + return best +} + +// Columns keeps first, lowest, highest and last per pixel column. +func Columns(n int, x func(i int) float32, y func(i int) float64) []int { + var out []int + for i := 0; i < n; { + col := math.Floor(float64(x(i))) + lo, hi, j := i, i, i + for ; j < n && math.Floor(float64(x(j))) == col; j++ { + if y(j) < y(lo) { + lo = j + } + if y(j) > y(hi) { + hi = j + } + } + out = append(out, i) + for _, k := range []int{min(lo, hi), max(lo, hi), j - 1} { + if k != out[len(out)-1] { + out = append(out, k) + } + } + i = j + } + return out +} diff --git a/internal/chart_test.go b/internal/chart_test.go new file mode 100644 index 0000000..f8eca08 --- /dev/null +++ b/internal/chart_test.go @@ -0,0 +1,101 @@ +package internal + +import ( + "fmt" + "math" + "testing" + "time" + + "mujicaui/theme" +) + +func TestNiceAndTicks(t *testing.T) { + for _, tc := range []struct { + lo, hi float64 + n int + nlo, nhi, stp float64 + }{ + {0, 97, 5, 0, 100, 20}, + {-3.2, 7.9, 4, -5, 10, 5}, + {0.012, 0.087, 5, 0, 0.1, 0.02}, + {5, 5, 4, 4, 6, 0.5}, + } { + lo, hi, step := Nice(tc.lo, tc.hi, tc.n) + if math.Abs(lo-tc.nlo) > 1e-9 || math.Abs(hi-tc.nhi) > 1e-9 || math.Abs(step-tc.stp) > 1e-9 { + t.Errorf("Nice(%v, %v, %d) = %v %v %v", tc.lo, tc.hi, tc.n, lo, hi, step) + } + } + if got := fmt.Sprint(Ticks(-5, 10, 5)); got != "[-5 0 5 10]" { + t.Errorf("ticks %s", got) + } + if FormatTick(0.30000000000000004, 0.1) != "0.3" || FormatTick(1500, 500) != "1500" || FormatTick(-1e-17, 0.5) != "0.0" { + t.Error("FormatTick") + } +} + +func TestNicePanics(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic for an inverted domain") + } + }() + Nice(2, 1, 4) +} + +func TestTimeTicks(t *testing.T) { + lo := time.Date(2026, 10, 5, 9, 7, 0, 0, time.UTC) + ticks, layout := TimeTicks(lo, lo.Add(2*time.Hour), 4) + if layout != "15:04" || len(ticks) != 4 || ticks[0].Format("15:04") != "09:30" || ticks[3].Format("15:04") != "11:00" { + t.Fatalf("ticks %v layout %s", ticks, layout) + } +} + +func TestLinearAndBand(t *testing.T) { + s := Linear{D0: 0, D1: 10, R0: 100, R1: 0} + if s.Map(5) != 50 || s.Invert(25) != 7.5 { + t.Fatal("Linear") + } + b := Band{N: 4, R0: 0, R1: 200, Pad: 0.5} + if b.Step() != 50 || b.Width() != 25 || b.Start(1) != 62.5 || b.Center(3) != 175 { + t.Fatal("Band") + } +} + +func TestPaletteContrast(t *testing.T) { + for _, k := range []theme.Tokens{theme.Light(), theme.Dark()} { + pal := Palette(k) + seen := map[[3]uint8]bool{} + for i, c := range pal { + if r := theme.Contrast(c, k.Surface); r < 3 { + t.Errorf("dark=%v color %d contrast %.2f", k.Dark, i, r) + } + seen[[3]uint8{c.R, c.G, c.B}] = true + } + if len(pal) != 6 || len(seen) != 6 { + t.Errorf("dark=%v palette not six distinct colors", k.Dark) + } + } +} + +func TestNearest(t *testing.T) { + pts := [][2]float32{{0, 0}, {10, 10}, {20, 0}} + at := func(i int) (float32, float32) { return pts[i][0], pts[i][1] } + if Nearest(3, at, 9, 2, 30, false) != 1 || Nearest(3, at, 18, 50, 30, true) != 2 || Nearest(3, at, 100, 100, 5, false) != -1 { + t.Fatal("Nearest") + } +} + +func TestColumnsBounded(t *testing.T) { + const n = 100_000 + x := func(i int) float32 { return float32(i) * 400 / n } + y := func(i int) float64 { return math.Sin(float64(i)) } + got := Columns(n, x, y) + if len(got) > 4*400+4 || got[0] != 0 || got[len(got)-1] != n-1 { + t.Fatalf("%d points kept, first %d last %d", len(got), got[0], got[len(got)-1]) + } + for i := 1; i < len(got); i++ { + if got[i] <= got[i-1] { + t.Fatal("indices out of order") + } + } +} diff --git a/line_chart.go b/line_chart.go new file mode 100644 index 0000000..44a09c2 --- /dev/null +++ b/line_chart.go @@ -0,0 +1,159 @@ +package mujica + +import ( + "math" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// LineChartOptions configure a LineChart. +type LineChartOptions struct { + Frame ChartFrame + // X places point i at ascending X[i]; nil means i. + X []float64 + // Times makes a time axis; set X or Times. + Times []time.Time + // Format writes readout values; nil uses six digits. + Format func(v float64) string +} + +// LineChart draws series as lines; NaN breaks them. +func LineChart(c *ui.Context, series []ChartSeries, opts LineChartOptions) ChartResult { + n := chartCheckSeries(series) + ch := newChart(c, opts.Frame) + ax := chartMemo(ch, "x", [3]string{chartID(opts.X), chartID(opts.Times), chartID(series)}, func() chartX { return newChartX(n, opts.X, opts.Times) }) + lo, hi, ok := chartYRange(ch, series, false, nil) + if !ok { + n = 0 + } + tops := make([][]float64, len(series)) + for i, s := range series { + tops[i] = s.Values + } + return chartLines(ch, chartLineData{series: series, tops: tops, ax: ax, lo: lo, hi: hi, n: n, format: opts.Format}) +} + +// chartYRange is the memoized y domain of visible series. +func chartYRange(ch *chart, series []ChartSeries, zero bool, tops [][]float64) (lo, hi float64, ok bool) { + d := chartMemo(ch, "y", chartSeriesID(ch, series)+chartID(tops), func() [3]float64 { + src := series + if tops != nil { + src = make([]ChartSeries, len(series)) + for i, s := range series { + src[i] = ChartSeries{Name: s.Name, Values: tops[i]} + } + } + lo, hi, ok := chartYDomain(src, ch.hidden, zero) + if !ok { + return [3]float64{} + } + return [3]float64{lo, hi, 1} + }) + return d[0], d[1], d[2] == 1 +} + +// chartLineData is what line and area charts draw. +type chartLineData struct { + series []ChartSeries + tops, bases [][]float64 + ax chartX + lo, hi float64 + n int + format func(float64) string +} + +func chartLines(ch *chart, d chartLineData) ChartResult { + c, k := ch.c, Tokens(ch.c) + pal := internal.Palette(k) + size := FontSize(c, theme.CaptionSize) + keys := make([]chartKey, len(d.series)) + for i, s := range d.series { + keys[i] = chartKey{Name: s.Name, Color: pal[i%len(pal)], Shape: i} + } + var ticks []float64 + var step float64 + lo, hi := d.lo, d.hi + if d.n > 0 { + lo, hi, step = internal.Nice(lo, hi, 4) + ticks = internal.Ticks(lo, hi, step) + } + geom := func(r ui.Rect) (ui.Rect, internal.Linear, internal.Linear) { + plot := chartInset(r, 52, 26) + return plot, d.ax.scale(plot), internal.Linear{D0: lo, D1: hi, R0: float64(plot.Y + plot.H), R1: float64(plot.Y)} + } + spec := chartSpec{n: d.n, keys: keys, toggle: true} + spec.pick = func(r ui.Rect, x, y float32) int { + plot, xs, _ := geom(r) + if !(ui.Rect{X: plot.X - 6, Y: plot.Y, W: plot.W + 12, H: plot.H}).Contains(x, y) { + return -1 + } + return d.ax.nearest(xs.Invert(x)) + } + spec.readout = func(i int) string { + parts := []string{d.ax.label(i)} + for _, s := range d.series { + if !ch.hidden(s.Name) { + parts = append(parts, s.Name+" "+chartValue(c, s.Values[i], d.format)) + } + } + return strings.Join(parts, " · ") + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + plot, xs, ys := geom(r) + internal.AxisY(p, plot, ys, ticks, func(v float64) string { return internal.FormatTick(v, step) }, size, k) + tx, tl := d.ax.ticks(plot) + internal.AxisX(p, plot, tx, tl, size, k) + x := func(i int) float32 { return xs.Map(d.ax.vals[i]) } + pt := func(i int, v float64) (float32, float32) { return internal.Snap(p, x(i)), internal.Snap(p, ys.Map(v)) } + for si, s := range d.series { + if ch.hidden(s.Name) { + continue + } + col, top := keys[si].Color, d.tops[si] + chartRuns(top, x, func(idx []int) { + var line ui.Path + for j, i := range idx { + if j == 0 { + line.MoveTo(pt(i, top[i])) + } else { + line.LineTo(pt(i, top[i])) + } + } + if d.bases != nil { + fill := line + for j := len(idx) - 1; j >= 0; j-- { + fill.LineTo(pt(idx[j], max(lo, min(hi, d.bases[si][idx[j]])))) + } + fill.Close() + p.FillPath(&fill, col.Alpha(0.22)) + } + p.StrokePath(&line, 2, col) + }) + // Sparse markers name each series by shape, not only color. + every := max(1, int(float32(d.n)/max(plot.W/48, 1))) + for i := 0; i < d.n; i += every { + if !math.IsNaN(top[i]) { + internal.Marker(p, si, x(i), ys.Map(top[i]), 7, col) + } + } + } + if active < 0 { + return + } + ax0 := internal.Snap(p, x(active)) + p.Line(ax0, plot.Y, ax0, plot.Y+plot.H, 1, k.TextMuted) + for si, s := range d.series { + if v := d.tops[si][active]; !ch.hidden(s.Name) && !math.IsNaN(v) { + internal.Marker(p, si, ax0, ys.Map(v), 13, k.Surface) + internal.Marker(p, si, ax0, ys.Map(v), 9, keys[si].Color) + } + } + } + res, _ := ch.build(spec) + return res +} diff --git a/line_chart_test.go b/line_chart_test.go new file mode 100644 index 0000000..a933b4d --- /dev/null +++ b/line_chart_test.go @@ -0,0 +1,194 @@ +package mujica + +import ( + "math" + "strings" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +type chartHarness struct { + res ChartResult + changes int + disabled bool + build func(c *ui.Context) ChartResult +} + +func (h *chartHarness) view(c *ui.Context) { + Use(c, Settings{Mode: Light}) + ui.Column(c).Padding(16).Width(480).Disabled(h.disabled).Children(func() { + h.res = h.build(c) + if h.res.Changed() { + h.changes++ + } + }) +} + +// chartReadout returns the readout line, the text after the plot. +func chartReadout(tt *ui.Tester) string { + texts := tt.Texts() + return texts[len(texts)-1] +} + +func lineSeries() []ChartSeries { + return []ChartSeries{ + {Name: "Pews", Values: []float64{3, 5, math.NaN(), 4, 8}}, + {Name: "Candles", Values: []float64{5, 2, 6, 7, 1}}, + } +} + +func TestLineChartKeyboardReadout(t *testing.T) { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return LineChart(c, lineSeries(), LineChartOptions{Frame: ChartFrame{Label: "Chapel"}}) + }} + tt := ui.NewTester(h.view, 520, 420) + if !strings.Contains(chartReadout(tt), "arrow keys") { + t.Fatalf("hint %q", chartReadout(tt)) + } + tabTo(t, tt, "Chapel") + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "1 · Pews 5 · Candles 2" || h.res.Point != 1 || h.changes != 2 { + t.Fatalf("readout %q point %d", got, h.res.Point) + } + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "2 · Pews no value · Candles 6" { + t.Fatalf("gap readout %q", got) + } + if a := tt.Announcements(); len(a) == 0 || a[len(a)-1] != "2 · Pews no value · Candles 6" { + t.Fatalf("announcements %q", a) + } + tt.Key(0, ui.KeyEnd) + tt.Key(0, ui.KeyRight) + if h.res.Point != 4 { + t.Fatalf("End then Right: %d", h.res.Point) + } + tt.Key(0, ui.KeyEscape) + if h.res.Point != -1 { + t.Fatalf("Escape kept point %d", h.res.Point) + } +} + +func TestLineChartHoverAndToggle(t *testing.T) { + var toggled string + h := &chartHarness{build: func(c *ui.Context) ChartResult { + r := LineChart(c, lineSeries(), LineChartOptions{Frame: ChartFrame{Label: "Chapel"}, X: []float64{0, 10, 20, 30, 40}}) + if s, ok := r.Toggled(); ok { + toggled = s + } + return r + }} + tt := ui.NewTester(h.view, 520, 420) + b := h.res.Element.Bounds() + // The plot spans 52..W-12; x 30 is three quarters across. + px := b.X + 52 + (b.W-64)*0.75 + tt.Move(px, b.Y+b.H/2) + if got := chartReadout(tt); got != "30 · Pews 4 · Candles 7" { + t.Fatalf("hover readout %q", got) + } + if err := tt.Click("Candles"); err != nil { + t.Fatal(err) + } + tt.Move(px, b.Y+b.H/2) + if got := chartReadout(tt); got != "30 · Pews 4" || toggled != "Candles" { + t.Fatalf("hidden series still read: %q toggled %q", got, toggled) + } +} + +func TestLineChartTimeAxisAndStates(t *testing.T) { + t0 := time.Date(2026, 10, 5, 9, 0, 0, 0, time.UTC) + times := []time.Time{t0, t0.Add(time.Hour), t0.Add(2 * time.Hour), t0.Add(3 * time.Hour), t0.Add(4 * time.Hour)} + status := DataReady + var series []ChartSeries + var heights []float32 + h := &chartHarness{build: func(c *ui.Context) ChartResult { + r := LineChart(c, series, LineChartOptions{Frame: ChartFrame{Label: "Chapel", Status: status}, Times: times[:len(series[0].Values)]}) + return r + }} + series = lineSeries() + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "Chapel") + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); !strings.HasPrefix(got, "2026-10-05 10:00:00 · ") { + t.Fatalf("time readout %q", got) + } + heights = append(heights, h.res.Element.Bounds().H) + for _, st := range []DataStatus{DataLoading, DataFailed} { + status = st + tt.Frame() + heights = append(heights, h.res.Element.Bounds().H) + } + if !tt.HasText("Retry") || heights[0] != heights[1] || heights[1] != heights[2] { + t.Fatalf("states changed size: %v", heights) + } + status, series = DataReady, []ChartSeries{{Name: "A", Values: []float64{math.NaN()}}} + tt.Frame() + if !tt.HasText("No data") { + t.Fatalf("all-missing chart: %q", tt.Texts()) + } +} + +func TestLineChartDisabledIgnoresKeys(t *testing.T) { + h := &chartHarness{disabled: true, build: func(c *ui.Context) ChartResult { + return LineChart(c, lineSeries(), LineChartOptions{Frame: ChartFrame{Label: "Chapel"}}) + }} + tt := ui.NewTester(h.view, 520, 420) + for range 4 { + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + } + if h.res.Point != -1 { + t.Fatalf("disabled chart moved to %d", h.res.Point) + } +} + +func TestLineChartBadOptions(t *testing.T) { + for name, build := range map[string]func(c *ui.Context){ + "lengths": func(c *ui.Context) { + LineChart(c, []ChartSeries{{Name: "a", Values: []float64{1}}, {Name: "b"}}, LineChartOptions{Frame: ChartFrame{Label: "x"}}) + }, + "order": func(c *ui.Context) { + LineChart(c, lineSeries(), LineChartOptions{Frame: ChartFrame{Label: "x"}, X: []float64{0, 2, 1, 3, 4}}) + }, + "no label": func(c *ui.Context) { LineChart(c, lineSeries(), LineChartOptions{}) }, + "duplicate": func(c *ui.Context) { + LineChart(c, []ChartSeries{{Name: "a"}, {Name: "a"}}, LineChartOptions{Frame: ChartFrame{Label: "x"}}) + }, + } { + func() { + defer func() { + if recover() == nil { + t.Errorf("%s: no panic", name) + } + }() + ui.NewTester(func(c *ui.Context) { Use(c, Settings{}); build(c) }, 300, 300) + }() + } +} + +func TestLineChartLarge(t *testing.T) { + vals := make([]float64, 100_000) + for i := range vals { + vals[i] = math.Sin(float64(i) / 500) + } + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return LineChart(c, []ChartSeries{{Name: "Wave", Values: vals}}, LineChartOptions{Frame: ChartFrame{Label: "Tide"}}) + }} + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "Tide") + tt.Key(0, ui.KeyEnd) + if h.res.Point != 99_999 || !strings.HasPrefix(chartReadout(tt), "99999 · Wave ") { + t.Fatalf("End: %d %q", h.res.Point, chartReadout(tt)) + } +} + +func TestLineChartSnapshot(t *testing.T) { + snapshot(t, "line_chart", 520, 340, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + LineChart(c, lineSeries(), LineChartOptions{Frame: ChartFrame{Label: "Chapel", Height: 240}}) + }) + }) +} diff --git a/list.go b/list.go index 32205b0..439d023 100644 --- a/list.go +++ b/list.go @@ -75,7 +75,7 @@ func (v ListView) Changed() bool { return v.changed } // Submitted reports Enter or a double click on an item. func (v ListView) Submitted() bool { return v.submitted } -// Retried reports a click on the retry action of a failed load. +// Retried reports a click on a failed load's retry. func (v ListView) Retried() bool { return v.retry } // List shows n items, building only those in view, as rows or a grid. diff --git a/messages_charts1.go b/messages_charts1.go new file mode 100644 index 0000000..e207570 --- /dev/null +++ b/messages_charts1.go @@ -0,0 +1,30 @@ +package mujica + +func init() { + addMessages(map[string][2]string{ + "chart.empty": {"No data", "暂无数据"}, + "chart.hint": {"Focus the chart and use the arrow keys to read values", "聚焦图表后用方向键读取数值"}, + "chart.missing": {"no value", "无数值"}, + "pie_chart.other": {"Other", "其他"}, + "pie_chart.total": {"Total", "总计"}, + "scatter_chart.size": {"size", "大小"}, + "scatter_chart.selected": {"selected", "已选"}, + "calendar_heatmap.prev": {"Previous year", "上一年"}, + "calendar_heatmap.next": {"Next year", "下一年"}, + "calendar_heatmap.less": {"Less", "少"}, + "calendar_heatmap.more": {"More", "多"}, + "box_plot.readout": {"%s · median %s · quartiles %s–%s · whiskers %s–%s · %d outliers", "%s · 中位数 %s · 四分位 %s–%s · 须线 %s–%s · 离群点 %d 个"}, + "waterfall_chart.running": {"running total", "累计"}, + "funnel_chart.readout": {"%s · %s · %s of the stage before · %s of the first", "%s · %s · 较上一阶段 %s · 占首阶段 %s"}, + "bullet_chart.actual": {"Actual", "实际"}, + "bullet_chart.target": {"Target", "目标"}, + "bullet_chart.band": {"Range %d: %s–%s", "区间 %d:%s–%s"}, + "chart.back": {"Back", "返回"}, + "chart.opens": {"Enter opens", "回车展开"}, + "sankey_chart.in": {"in", "流入"}, + "sankey_chart.out": {"out", "流出"}, + "network_graph.readout": {"%s · %d links: %s", "%s · %d 条连线:%s"}, + "realtime_chart.pause": {"Pause", "暂停"}, + "realtime_chart.resume": {"Resume", "继续"}, + }) +} diff --git a/network_graph.go b/network_graph.go new file mode 100644 index 0000000..c9f368e --- /dev/null +++ b/network_graph.go @@ -0,0 +1,263 @@ +package mujica + +import ( + "fmt" + "log/slog" + "math" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// GraphNode is a node placed at X, Y unless forced. +type GraphNode struct { + ID, Label string + X, Y float64 +} + +// GraphEdge joins two nodes by ID. +type GraphEdge struct{ From, To string } + +// NetworkGraphOptions configure a NetworkGraph. +type NetworkGraphOptions struct { + Frame ChartFrame + // Force lays nodes out by a simple force simulation. + Force bool +} + +// NetworkGraphState holds node positions, zoom and pan. +type NetworkGraphState struct { + pos map[string][2]float64 + lo, hi [2]float64 + layout string + zoom float32 + panX float32 + panY float32 + drag string + dragging bool +} + +// Position returns where node id is, in layout units. +func (s *NetworkGraphState) Position(id string) (x, y float64, ok bool) { + p, ok := s.pos[id] + return p[0], p[1], ok +} + +// Zoom returns the view's scale, 1 when fitted. +func (s *NetworkGraphState) Zoom() float32 { return max(s.zoom, 0) } + +// ResetView fits the graph again. +func (s *NetworkGraphState) ResetView() { s.zoom, s.panX, s.panY = 1, 0, 0 } + +// networkForceLimit bounds the nodes the O(n²) force layout takes. +const networkForceLimit = 500 + +// NetworkGraph draws nodes and edges; drag, pan and zoom. +func NetworkGraph(c *ui.Context, s *NetworkGraphState, nodes []GraphNode, edges []GraphEdge, opts NetworkGraphOptions) ChartResult { + at := map[string]int{} + for i, n := range nodes { + if _, dup := at[n.ID]; dup || n.ID == "" || n.Label == "" { + panic("mujica: NetworkGraph nodes need unique IDs and labels") + } + at[n.ID] = i + } + links := make([][2]int, len(edges)) + for i, e := range edges { + f, okf := at[e.From] + t, okt := at[e.To] + if !okf || !okt { + panic("mujica: NetworkGraph edge ends must be node IDs") + } + links[i] = [2]int{f, t} + } + if opts.Force && len(nodes) > networkForceLimit { + panic("mujica: NetworkGraph Force takes at most 500 nodes") + } + if s.zoom == 0 { + s.zoom = 1 + } + if key := chartID(nodes) + chartID(edges) + fmt.Sprint(opts.Force); s.layout != key { + s.layout, s.pos = key, networkLayout(nodes, links, opts.Force) + // The view fits the layout; dragging does not refit. + s.lo, s.hi = [2]float64{math.Inf(1), math.Inf(1)}, [2]float64{math.Inf(-1), math.Inf(-1)} + for _, p := range s.pos { + s.lo, s.hi = [2]float64{min(s.lo[0], p[0]), min(s.lo[1], p[1])}, [2]float64{max(s.hi[0], p[0]), max(s.hi[1], p[1])} + } + slog.Debug("mujica: network_graph layout", "nodes", len(nodes)) + } + ch := newChart(c, opts.Frame) + k := Tokens(c) + pal := internal.Palette(k) + size := FontSize(c, theme.CaptionSize) + lo, hi := s.lo, s.hi + // screen maps a layout point into r, zoomed and panned. + screen := func(r ui.Rect, p [2]float64) (float32, float32) { + span := max(hi[0]-lo[0], hi[1]-lo[1], 1e-9) + fit := float64(min(r.W, r.H)-48) / span + cx, cy := (lo[0]+hi[0])/2, (lo[1]+hi[1])/2 + x := float32((p[0]-cx)*fit)*s.zoom + r.X + r.W/2 + s.panX + y := float32((p[1]-cy)*fit)*s.zoom + r.Y + r.H/2 + s.panY + return x, y + } + unit := func(r ui.Rect) float64 { + return max(hi[0]-lo[0], hi[1]-lo[1], 1e-9) / float64(min(r.W, r.H)-48) / float64(s.zoom) + } + pt := func(r ui.Rect, i int) (float32, float32) { return screen(r, s.pos[nodes[i].ID]) } + spec := chartSpec{n: len(nodes)} + spec.readout = func(i int) string { + var near []string + for _, l := range links { + switch i { + case l[0]: + near = append(near, nodes[l[1]].Label) + case l[1]: + near = append(near, nodes[l[0]].Label) + } + } + return fmt.Sprintf(msg(c, "network_graph.readout"), nodes[i].Label, len(near), strings.Join(near, ", ")) + } + spec.pick = func(r ui.Rect, x, y float32) int { + return internal.Nearest(len(nodes), func(i int) (float32, float32) { return pt(r, i) }, x, y, 12, false) + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + p.Clip(r, 0, func() { + for _, l := range links { + x0, y0 := pt(r, l[0]) + x1, y1 := pt(r, l[1]) + var line ui.Path + line.MoveTo(internal.Snap(p, x0), internal.Snap(p, y0)).LineTo(internal.Snap(p, x1), internal.Snap(p, y1)) + w, col := float32(1.25), k.ControlBorder + if active == l[0] || active == l[1] { + w, col = 2.5, k.Text + } + p.StrokePath(&line, w, col) + } + for i, n := range nodes { + x, y := pt(r, i) + internal.Marker(p, 0, x, y, 14, k.Surface) + internal.Marker(p, 0, x, y, 11, pal[i%len(pal)]) + if i == active { + var ring ui.Path + ring.Circle(internal.Snap(p, x), internal.Snap(p, y), 10) + p.StrokePath(&ring, 2, k.Text) + } + chartText(p, n.Label, x, y+9, size, k.Text, 0.5, 0) + } + }) + } + res, plot := ch.build(spec) + if plot == nil || plot.IsDisabled() { + return res + } + hit := func(x, y float32) string { + b := plot.Bounds() + if i := spec.pick(ui.Rect{W: b.W, H: b.H}, x, y); i >= 0 { + return nodes[i].ID + } + return "" + } + networkInput(plot, s, ch.st.focus, nodes, unit, hit) + return res +} + +// networkInput drags, pans, zooms and moves the focused node. +func networkInput(plot *ui.Element, s *NetworkGraphState, focus int, nodes []GraphNode, unit func(ui.Rect) float64, hit func(x, y float32) string) { + b := plot.Bounds() + r := ui.Rect{W: b.W, H: b.H} + move := func(id string, dx, dy float32) { + p := s.pos[id] + s.pos[id] = [2]float64{p[0] + float64(dx)*unit(r), p[1] + float64(dy)*unit(r)} + } + zoom := func(f float32) { s.zoom = max(0.25, min(8, s.zoom*f)) } + if dx, dy, held := plot.Dragged(); held { + if !s.dragging { + x, y, _ := plot.PointerPosition() + s.dragging, s.drag = true, hit(x, y) + } + if s.drag != "" { + move(s.drag, dx, dy) + } else { + s.panX, s.panY = s.panX+dx, s.panY+dy + } + } else if s.dragging { + s.dragging = false + slog.Debug("mujica: network_graph drag", "node", s.drag) + } + plot.HandleInput(func(ev ui.InputEvent) bool { + if ev.Kind != ui.InputScroll || ev.DY == 0 || plot.IsDisabled() { + return false + } + if ev.DY < 0 { + zoom(1.2) + } else { + zoom(1 / 1.2) + } + return true + }) + switch { + case plot.Shortcut(0, ui.KeyEqual), plot.Shortcut(ui.Shift, ui.KeyEqual): + zoom(1.2) + case plot.Shortcut(0, ui.KeyMinus): + zoom(1 / 1.2) + case plot.Shortcut(0, ui.Key0): + s.ResetView() + } + if focus < 0 || focus >= len(nodes) { + return + } + for key, d := range map[ui.Key][2]float32{ui.KeyLeft: {-12, 0}, ui.KeyRight: {12, 0}, ui.KeyUp: {0, -12}, ui.KeyDown: {0, 12}} { + if plot.Shortcut(ui.Shift, key) { + move(nodes[focus].ID, d[0], d[1]) + } + } +} + +// networkLayout uses X, Y, or fixed force steps. +func networkLayout(nodes []GraphNode, links [][2]int, force bool) map[string][2]float64 { + pos := make([][2]float64, len(nodes)) + for i, n := range nodes { + pos[i] = [2]float64{n.X, n.Y} + if force { + a := 2 * math.Pi * float64(i) / float64(len(nodes)) + pos[i] = [2]float64{math.Cos(a), math.Sin(a)} + } + } + if force && len(nodes) > 1 { + ideal := math.Sqrt(4.0 / float64(len(nodes))) + for step := range 300 { + heat := 0.1 * (1 - float64(step)/300) + move := make([][2]float64, len(nodes)) + for i := range pos { + for j := range pos { + if i == j { + continue + } + dx, dy := pos[i][0]-pos[j][0], pos[i][1]-pos[j][1] + d := max(math.Hypot(dx, dy), 1e-6) + f := ideal * ideal / d + move[i][0], move[i][1] = move[i][0]+dx/d*f, move[i][1]+dy/d*f + } + } + for _, l := range links { + dx, dy := pos[l[0]][0]-pos[l[1]][0], pos[l[0]][1]-pos[l[1]][1] + d := max(math.Hypot(dx, dy), 1e-6) + f := d * d / ideal + move[l[0]][0], move[l[0]][1] = move[l[0]][0]-dx/d*f, move[l[0]][1]-dy/d*f + move[l[1]][0], move[l[1]][1] = move[l[1]][0]+dx/d*f, move[l[1]][1]+dy/d*f + } + for i, m := range move { + d := max(math.Hypot(m[0], m[1]), 1e-9) + pos[i][0] += m[0] / d * min(d, heat) + pos[i][1] += m[1] / d * min(d, heat) + } + } + } + out := make(map[string][2]float64, len(nodes)) + for i, n := range nodes { + out[n.ID] = pos[i] + } + return out +} diff --git a/network_graph_test.go b/network_graph_test.go new file mode 100644 index 0000000..7b45133 --- /dev/null +++ b/network_graph_test.go @@ -0,0 +1,101 @@ +package mujica + +import ( + "math" + "testing" + + "github.com/egoist/mygo/ui" +) + +var graphNodes = []GraphNode{{"a", "Abbot", 0, 0}, {"b", "Prior", 10, 0}, {"c", "Cellarer", 10, 10}, {"d", "Novice", 0, 10}} +var graphEdges = []GraphEdge{{"a", "b"}, {"a", "c"}, {"c", "d"}} + +func TestNetworkGraphReadoutAndKeys(t *testing.T) { + var s NetworkGraphState + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return NetworkGraph(c, &s, graphNodes, graphEdges, NetworkGraphOptions{Frame: ChartFrame{Label: "House"}}) + }} + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "House") + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "Abbot · 2 links: Prior, Cellarer" { + t.Fatalf("readout %q", got) + } + x0, y0, _ := s.Position("a") + tt.Key(ui.Shift, ui.KeyRight) + if x, y, _ := s.Position("a"); x <= x0 || y != y0 { + t.Fatalf("Shift+Right left the node at %v,%v", x, y) + } + tt.Key(0, ui.KeyEqual) + if s.Zoom() < 1.19 { + t.Fatalf("zoom %v", s.Zoom()) + } + tt.Key(0, ui.Key0) + if s.Zoom() != 1 { + t.Fatalf("reset zoom %v", s.Zoom()) + } +} + +func TestNetworkGraphDragNodeAndPan(t *testing.T) { + var s NetworkGraphState + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return NetworkGraph(c, &s, graphNodes, graphEdges, NetworkGraphOptions{Frame: ChartFrame{Label: "House"}}) + }} + tt := ui.NewTester(h.view, 520, 420) + b := h.res.Element.Bounds() + // The 10×10 layout fits 240-48 DIPs, centered in the plot. + cx, cy := b.X+b.W/2, b.Y+120 + ax, ay := cx-96, cy-96 + tt.Press(ax, ay) + tt.Move(ax+20, ay) + tt.Move(ax+48, ay) + tt.Release(ax+48, ay) + if x, y, _ := s.Position("a"); math.Abs(x-2.5) > 0.2 || math.Abs(y) > 0.01 { + t.Fatalf("dragged node to %v,%v", x, y) + } + tt.Press(cx, cy) // the empty middle pans + tt.Move(cx+30, cy+10) + tt.Release(cx+30, cy+10) + if x, _, _ := s.Position("b"); x != 10 { + t.Fatalf("panning moved a node: %v", x) + } + if got := s.panX; got != 30 { + t.Fatalf("pan %v", got) + } +} + +func TestNetworkGraphForceLayout(t *testing.T) { + pos := networkLayout(graphNodes, [][2]int{{0, 1}, {0, 2}, {2, 3}}, true) + again := networkLayout(graphNodes, [][2]int{{0, 1}, {0, 2}, {2, 3}}, true) + for id, p := range pos { + if again[id] != p || math.IsNaN(p[0]) { + t.Fatalf("layout not deterministic for %s", id) + } + } + d := func(a, b string) float64 { return math.Hypot(pos[a][0]-pos[b][0], pos[a][1]-pos[b][1]) } + if d("c", "d") >= d("b", "d") { + t.Fatalf("linked nodes not closer: %v vs %v", d("c", "d"), d("b", "d")) + } +} + +func TestNetworkGraphBad(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic for an unknown edge end") + } + }() + var s NetworkGraphState + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + NetworkGraph(c, &s, graphNodes, []GraphEdge{{"a", "z"}}, NetworkGraphOptions{Frame: ChartFrame{Label: "x"}}) + }, 300, 300) +} + +func TestNetworkGraphSnapshot(t *testing.T) { + snapshot(t, "network_graph", 520, 320, func(c *ui.Context) { + var s NetworkGraphState + ui.Column(c).Padding(16).Children(func() { + NetworkGraph(c, &s, graphNodes, append(graphEdges, GraphEdge{"b", "d"}, GraphEdge{"b", "c"}), NetworkGraphOptions{Frame: ChartFrame{Label: "House"}, Force: true}) + }) + }) +} diff --git a/pie_chart.go b/pie_chart.go new file mode 100644 index 0000000..7024b6b --- /dev/null +++ b/pie_chart.go @@ -0,0 +1,146 @@ +package mujica + +import ( + "fmt" + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// ChartSlice is one share of a PieChart or FunnelChart. +type ChartSlice struct { + Label string + Value float64 +} + +// PieChartOptions configure a PieChart. +type PieChartOptions struct { + Frame ChartFrame + // Donut cuts out the middle and writes the total there. + Donut bool + // MinAngle merges two or more narrower slices into Other. + MinAngle float64 + Format func(v float64) string +} + +// PieChart shows shares as slices labeled with percents. +func PieChart(c *ui.Context, slices []ChartSlice, opts PieChartOptions) ChartResult { + if opts.MinAngle < 0 || opts.MinAngle >= 360 { + panic("mujica: PieChart MinAngle must be in [0, 360)") + } + ch := newChart(c, opts.Frame) + k := Tokens(c) + pal := internal.Palette(k) + size := FontSize(c, theme.CaptionSize) + parts := chartMemo(ch, "parts", [2]any{chartID(slices), opts.MinAngle}, func() []ChartSlice { + return pieMerge(slices, opts.MinAngle, msg(c, "pie_chart.other")) + }) + total := 0.0 + for _, s := range parts { + total += s.Value + } + n := len(parts) + if total == 0 { + n = 0 + } + keys := make([]chartKey, len(parts)) + for i, s := range parts { + keys[i] = chartKey{Name: s.Label, Color: pal[i%len(pal)], Shape: i} + } + // angle returns slice i's start and end, clockwise. + angle := func(i int) (float64, float64) { + a := 0.0 + for j := range i { + a += parts[j].Value + } + return 2 * math.Pi * a / total, 2 * math.Pi * (a + parts[i].Value) / total + } + geom := func(r ui.Rect) (cx, cy, r0, r1 float32) { + r1 = min(r.W, r.H)/2 - 8 + if opts.Donut { + r0 = r1 * 0.58 + } + return r.X + r.W/2, r.Y + r.H/2, r0, r1 + } + share := func(i int) string { return fmt.Sprintf("%.1f%%", 100*parts[i].Value/total) } + spec := chartSpec{n: n, keys: keys} + spec.readout = func(i int) string { + return parts[i].Label + " · " + chartValue(c, parts[i].Value, opts.Format) + " · " + share(i) + } + spec.pick = func(r ui.Rect, x, y float32) int { + cx, cy, r0, r1 := geom(r) + d := float32(math.Hypot(float64(x-cx), float64(y-cy))) + if d < r0 || d > r1 { + return -1 + } + a := math.Atan2(float64(x-cx), float64(cy-y)) + if a < 0 { + a += 2 * math.Pi + } + for i := range parts { + if a0, a1 := angle(i); a >= a0 && a < a1 { + return i + } + } + return -1 + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + cx, cy, r0, r1 := geom(r) + for i := range parts { + a0, a1 := angle(i) + if a1 <= a0 { + continue + } + grow := float32(0) + if i == active { + grow = 6 + } + p.FillPath(internal.Sector(cx, cy, r0, r1+grow, a0, a1), keys[i].Color) + p.StrokePath(internal.Sector(cx, cy, r0, r1+grow, a0, a1), 1.5, k.Surface) + // Wide slices carry their shape and percent. + if a1-a0 > 0.38 { + mx, my := internal.Polar(cx, cy, (r0+r1)/2+float32(chartBool(r0 == 0))*r1*0.12, (a0+a1)/2) + ink := chartInk(k, keys[i].Color) + internal.Marker(p, i, mx, my-8, 9, ink) + chartText(p, share(i), mx, my+2, size, ink, 0.5, 0) + } + } + if opts.Donut { + chartText(p, chartValue(c, total, opts.Format), cx, cy, FontSize(c, theme.H3Size), k.Text, 0.5, 0.75) + chartText(p, msg(c, "pie_chart.total"), cx, cy+4, size, k.TextMuted, 0.5, 0) + } + } + res, _ := ch.build(spec) + return res +} + +// pieMerge folds two or more narrow slices into other. +func pieMerge(slices []ChartSlice, minAngle float64, other string) []ChartSlice { + total := 0.0 + for _, s := range slices { + if s.Value < 0 || math.IsNaN(s.Value) || math.IsInf(s.Value, 0) || s.Label == "" { + panic("mujica: PieChart slices need a label and a finite value ≥ 0") + } + total += s.Value + } + var keep []ChartSlice + small, rest := 0, 0.0 + for _, s := range slices { + if total > 0 && s.Value/total*360 < minAngle { + small++ + rest += s.Value + } + } + for _, s := range slices { + if small < 2 || total == 0 || s.Value/total*360 >= minAngle { + keep = append(keep, s) + } + } + if small >= 2 { + keep = append(keep, ChartSlice{Label: other, Value: rest}) + } + return keep +} diff --git a/pie_chart_test.go b/pie_chart_test.go new file mode 100644 index 0000000..addb559 --- /dev/null +++ b/pie_chart_test.go @@ -0,0 +1,82 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +var pieSlices = []ChartSlice{{"Wax", 50}, {"Oil", 30}, {"Myrrh", 12}, {"Salt", 4}, {"Ash", 4}} + +func TestPieMerge(t *testing.T) { + got := pieMerge(pieSlices, 20, "Other") + if fmt.Sprint(got) != "[{Wax 50} {Oil 30} {Myrrh 12} {Other 8}]" { + t.Fatalf("merge 20°: %v", got) + } + if got := pieMerge(pieSlices[:4], 20, "Other"); len(got) != 4 { + t.Fatalf("a single narrow slice merged: %v", got) + } +} + +func TestPieChartReadoutAndHover(t *testing.T) { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return PieChart(c, pieSlices, PieChartOptions{Frame: ChartFrame{Label: "Stores"}, Donut: true, MinAngle: 20}) + }} + tt := ui.NewTester(h.view, 520, 420) + if !tt.HasText("Other") { + t.Fatalf("legend lacks Other: %q", tt.Texts()) + } + tabTo(t, tt, "Stores") + tt.Key(0, ui.KeyEnd) + if got := chartReadout(tt); got != "Other · 8 · 8.0%" { + t.Fatalf("readout %q", got) + } + b := h.res.Element.Bounds() + plotTop := b.Y + 38 // below the one-line legend + cy := plotTop + 120 + tt.Move(b.X+b.W/2+60, cy-40) // upper right: the first slice + if got := chartReadout(tt); got != "Wax · 50 · 50.0%" { + t.Fatalf("hover %q", got) + } + tt.Key(0, ui.KeyEscape) + tt.Move(b.X+b.W/2, cy) // the hole + if h.res.Point != -1 { + t.Fatalf("hole picked %d", h.res.Point) + } +} + +func TestPieChartBad(t *testing.T) { + for _, s := range [][]ChartSlice{{{"a", -1}}, {{"", 1}}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%v: no panic", s) + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + PieChart(c, s, PieChartOptions{Frame: ChartFrame{Label: "x"}}) + }, 300, 300) + }() + } + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return PieChart(c, []ChartSlice{{"a", 0}}, PieChartOptions{Frame: ChartFrame{Label: "x"}}) + }} + if tt := ui.NewTester(h.view, 300, 300); !tt.HasText("No data") { + t.Fatal("zero total is not empty") + } +} + +func TestPieChartSnapshot(t *testing.T) { + snapshot(t, "pie_chart", 640, 320, func(c *ui.Context) { + ui.Row(c).Padding(16).Gap(16).Children(func() { + ui.Column(c).Width(296).Children(func() { + PieChart(c, pieSlices, PieChartOptions{Frame: ChartFrame{Label: "Pie", Height: 220}}) + }) + ui.Column(c).Width(296).Children(func() { + PieChart(c, pieSlices, PieChartOptions{Frame: ChartFrame{Label: "Donut", Height: 220}, Donut: true, MinAngle: 20}) + }) + }) + }) +} diff --git a/radar_chart.go b/radar_chart.go new file mode 100644 index 0000000..d78b869 --- /dev/null +++ b/radar_chart.go @@ -0,0 +1,141 @@ +package mujica + +import ( + "math" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// RadarChartOptions configure a RadarChart. +type RadarChartOptions struct { + Frame ChartFrame + // Max is the outer ring's value; 0 means automatic. + Max float64 + Format func(v float64) string +} + +// RadarChart draws series as polygons over three or more axes. +func RadarChart(c *ui.Context, axes []string, series []ChartSeries, opts RadarChartOptions) ChartResult { + if n := chartCheckSeries(series); len(axes) < 3 || n != len(axes) && len(series) > 0 || opts.Max < 0 { + panic("mujica: RadarChart needs three or more axes, one value per axis and Max ≥ 0") + } + ch := newChart(c, opts.Frame) + k := Tokens(c) + pal := internal.Palette(k) + size := FontSize(c, theme.CaptionSize) + keys := make([]chartKey, len(series)) + top := opts.Max + for i, s := range series { + keys[i] = chartKey{Name: s.Name, Color: pal[i%len(pal)], Shape: i} + for _, v := range s.Values { + if v < 0 { + panic("mujica: RadarChart values must be ≥ 0") + } + if !ch.hidden(s.Name) && opts.Max == 0 && !math.IsNaN(v) { + top = max(top, v) + } + } + } + n := len(axes) + if top == 0 { + n = 0 + } + var step float64 + if n > 0 && opts.Max == 0 { + _, top, step = internal.Nice(0, top, 4) + } else if n > 0 { + _, _, step = internal.Nice(0, top, 4) + } + geom := func(r ui.Rect) (cx, cy, rad float32) { + return r.X + r.W/2, r.Y + r.H/2 + 4, min(r.W/2-70, r.H/2-24) + } + angle := func(i int) float64 { return 2 * math.Pi * float64(i) / float64(len(axes)) } + spec := chartSpec{n: n, keys: keys, toggle: len(series) > 1} + spec.readout = func(i int) string { + parts := []string{axes[i]} + for _, s := range series { + if !ch.hidden(s.Name) { + parts = append(parts, s.Name+" "+chartValue(c, s.Values[i], opts.Format)) + } + } + return strings.Join(parts, " · ") + } + spec.pick = func(r ui.Rect, x, y float32) int { + cx, cy, rad := geom(r) + if math.Hypot(float64(x-cx), float64(y-cy)) > float64(rad)+16 { + return -1 + } + return internal.Nearest(len(axes), func(i int) (float32, float32) { return internal.Polar(cx, cy, rad, angle(i)) }, x, y, 2*rad+32, false) + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + cx, cy, rad := geom(r) + for _, t := range internal.Ticks(step, top, step) { + var ring ui.Path + for i := range axes { + x, y := internal.Polar(cx, cy, rad*float32(t/top), angle(i)) + if i == 0 { + ring.MoveTo(x, y) + } else { + ring.LineTo(x, y) + } + } + ring.Close() + p.StrokePath(&ring, 1, k.Border) + chartText(p, internal.FormatTick(t, step), cx-4, cy-rad*float32(t/top), size, k.TextMuted, 1, 0.5) + } + for i, a := range axes { + x, y := internal.Polar(cx, cy, rad, angle(i)) + w := float32(1) + if i == active { + w = 2 + } + var spoke ui.Path + spoke.MoveTo(cx, cy).LineTo(x, y) + p.StrokePath(&spoke, w, k.ControlBorder) + lx, ly := internal.Polar(cx, cy, rad+10, angle(i)) + ax := 0.5 + 0.5*float32(math.Sin(angle(i))) + col := k.TextMuted + if i == active { + col = k.Text + } + chartText(p, a, lx, ly, size, col, 1-ax, 0.5+0.5*float32(math.Cos(angle(i)))) + } + for si, s := range series { + if ch.hidden(s.Name) { + continue + } + var poly ui.Path + pt := func(i int) (float32, float32) { + v := s.Values[i] + if math.IsNaN(v) { + v = 0 + } + return internal.Polar(cx, cy, rad*float32(v/top), angle(i)) + } + for i := range axes { + if i == 0 { + poly.MoveTo(pt(i)) + } else { + poly.LineTo(pt(i)) + } + } + poly.Close() + p.FillPath(&poly, keys[si].Color.Alpha(0.16)) + p.StrokePath(&poly, 2, keys[si].Color) + for i := range axes { + x, y := pt(i) + sz := float32(7) + if i == active { + sz = 11 + } + internal.Marker(p, si, x, y, sz, keys[si].Color) + } + } + } + res, _ := ch.build(spec) + return res +} diff --git a/radar_chart_test.go b/radar_chart_test.go new file mode 100644 index 0000000..fde7651 --- /dev/null +++ b/radar_chart_test.go @@ -0,0 +1,71 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +var radarAxes = []string{"Voice", "Latin", "Chant", "Organ", "Bells"} + +func radarSeries() []ChartSeries { + return []ChartSeries{ + {Name: "Agnès", Values: []float64{8, 6, 9, 4, 7}}, + {Name: "Clare", Values: []float64{5, 9, 6, 8, 3}}, + } +} + +func TestRadarChartReadout(t *testing.T) { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return RadarChart(c, radarAxes, radarSeries(), RadarChartOptions{Frame: ChartFrame{Label: "Skills"}}) + }} + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "Skills") + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "Latin · Agnès 6 · Clare 9" { + t.Fatalf("readout %q", got) + } + b := h.res.Element.Bounds() + cx, cy := b.X+b.W/2, b.Y+38+120+4 + tt.Key(0, ui.KeyEscape) + tt.Move(cx, cy-60) // straight up: the first axis + if got := chartReadout(tt); got != "Voice · Agnès 8 · Clare 5" { + t.Fatalf("hover %q", got) + } + if err := tt.Click("Clare"); err != nil { + t.Fatal(err) + } + tt.Move(cx, cy-60) + if got := chartReadout(tt); got != "Voice · Agnès 8" { + t.Fatalf("hidden series read: %q", got) + } +} + +func TestRadarChartBad(t *testing.T) { + for name, build := range map[string]func(c *ui.Context){ + "two axes": func(c *ui.Context) { + RadarChart(c, radarAxes[:2], nil, RadarChartOptions{Frame: ChartFrame{Label: "x"}}) + }, + "negative": func(c *ui.Context) { + RadarChart(c, radarAxes[:3], []ChartSeries{{Name: "a", Values: []float64{1, -1, 2}}}, RadarChartOptions{Frame: ChartFrame{Label: "x"}}) + }, + } { + func() { + defer func() { + if recover() == nil { + t.Errorf("%s: no panic", name) + } + }() + ui.NewTester(func(c *ui.Context) { Use(c, Settings{}); build(c) }, 300, 300) + }() + } +} + +func TestRadarChartSnapshot(t *testing.T) { + snapshot(t, "radar_chart", 520, 340, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + RadarChart(c, radarAxes, radarSeries(), RadarChartOptions{Frame: ChartFrame{Label: "Skills"}}) + }) + }) +} diff --git a/realtime_chart.go b/realtime_chart.go new file mode 100644 index 0000000..559f7be --- /dev/null +++ b/realtime_chart.go @@ -0,0 +1,121 @@ +package mujica + +import ( + "log/slog" + "math" + "sort" + "time" + + "github.com/egoist/mygo/ui" +) + +// RealtimeBuffer keeps the latest samples of named series. +type RealtimeBuffer struct { + names []string + limit int + times []time.Time + vals [][]float64 +} + +// NewRealtimeBuffer keeps up to capacity samples of the named series. +func NewRealtimeBuffer(capacity int, names ...string) *RealtimeBuffer { + if capacity < 2 || len(names) == 0 { + panic("mujica: RealtimeBuffer needs a capacity of 2 or more and a series name") + } + return &RealtimeBuffer{names: names, limit: capacity, vals: make([][]float64, len(names))} +} + +// Append adds one sample per series at a non-decreasing t. +func (b *RealtimeBuffer) Append(t time.Time, values ...float64) { + if len(values) != len(b.names) || len(b.times) > 0 && t.Before(b.times[len(b.times)-1]) { + panic("mujica: RealtimeBuffer.Append needs one value per series and a time not before the last") + } + b.times = append(b.times, t) + for i, v := range values { + b.vals[i] = append(b.vals[i], v) + } + // Old samples are dropped in blocks, so appends stay cheap. + if len(b.times) >= 2*b.limit { + drop := len(b.times) - b.limit + b.times = append([]time.Time(nil), b.times[drop:]...) + for i := range b.vals { + b.vals[i] = append([]float64(nil), b.vals[i][drop:]...) + } + } +} + +// Len is how many samples the buffer keeps. +func (b *RealtimeBuffer) Len() int { return min(len(b.times), b.limit) } + +// RealtimeChartOptions configure a RealtimeChart. +type RealtimeChartOptions struct { + Frame ChartFrame + // Window is the time shown up to the newest sample. + Window time.Duration + Format func(v float64) string +} + +// RealtimeChartState holds whether the view is paused, and where. +type RealtimeChartState struct { + Paused bool + end time.Time +} + +// RealtimeChart shows a fixed window ending at the newest sample. +func RealtimeChart(c *ui.Context, s *RealtimeChartState, buf *RealtimeBuffer, opts RealtimeChartOptions) ChartResult { + if opts.Window <= 0 { + panic("mujica: RealtimeChart needs a positive Window") + } + u := Density(c).Unit() + var res ChartResult + wrap := ui.Column(c).Gap(u * 2).MinWidth(0) + wrap.Children(func() { + label := msg(c, "realtime_chart.pause") + if s.Paused { + label = msg(c, "realtime_chart.resume") + } + if b := Button(c, label, ButtonOptions{Variant: Secondary, Disabled: wrap.IsDisabled()}).AlignSelf(ui.Start); b.Clicked() && !b.IsDisabled() { + s.Paused, res.value = !s.Paused, true + slog.Debug("mujica: realtime_chart pause", "paused", s.Paused) + } + times := buf.times[max(0, len(buf.times)-buf.limit):] + last := time.Time{} + if len(times) > 0 { + last = times[len(times)-1] + } + if !s.Paused || s.end.IsZero() { + s.end = last + } + from := s.end.Add(-opts.Window) + i0 := sort.Search(len(times), func(i int) bool { return !times[i].Before(from) }) + i1 := sort.Search(len(times), func(i int) bool { return times[i].After(s.end) }) + off := len(buf.times) - len(times) + ch := newChart(c, opts.Frame) + series := make([]ChartSeries, len(buf.names)) + tops := make([][]float64, len(buf.names)) + for i, name := range buf.names { + series[i] = ChartSeries{Name: name, Values: buf.vals[i][off+i0 : off+i1]} + tops[i] = series[i].Values + } + n := i1 - i0 + var ax chartX + if n > 0 { + ax = chartMemo(ch, "x", [2]any{chartID(times[i0:i1]), s.end}, func() chartX { + a := newChartX(n, nil, times[i0:i1]) + a.d0, a.d1 = float64(from.UnixNano())/1e9, float64(s.end.UnixNano())/1e9 + if a.d1 == a.d0 { + a.d0 -= 1 + } + return a + }) + } + lo, hi, ok := chartYRange(ch, series, false, nil) + if !ok || math.IsNaN(lo) { + n = 0 + } + r := chartLines(ch, chartLineData{series: series, tops: tops, ax: ax, lo: lo, hi: hi, n: n, format: opts.Format}) + res.Point, res.changed, res.retry, res.toggled = r.Point, r.changed, r.retry, r.toggled + }) + res.Element = wrap + return res +} diff --git a/realtime_chart_test.go b/realtime_chart_test.go new file mode 100644 index 0000000..ab71e08 --- /dev/null +++ b/realtime_chart_test.go @@ -0,0 +1,86 @@ +package mujica + +import ( + "math" + "strings" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +var rtStart = time.Date(2026, 10, 5, 9, 0, 0, 0, time.UTC) + +func TestRealtimeBufferTrims(t *testing.T) { + b := NewRealtimeBuffer(100, "a") + for i := range 100_000 { + b.Append(rtStart.Add(time.Duration(i)*time.Second), float64(i)) + } + if b.Len() != 100 || len(b.times) >= 200 || b.vals[0][len(b.vals[0])-1] != 99_999 { + t.Fatalf("kept %d samples, %d stored", b.Len(), len(b.times)) + } + defer func() { + if recover() == nil { + t.Fatal("no panic for a sample back in time") + } + }() + b.Append(rtStart, 1) +} + +func TestRealtimeChartWindowAndPause(t *testing.T) { + buf := NewRealtimeBuffer(1000, "Bell", "Organ") + var st RealtimeChartState + values := 0 + h := &chartHarness{build: func(c *ui.Context) ChartResult { + r := RealtimeChart(c, &st, buf, RealtimeChartOptions{Frame: ChartFrame{Label: "Sound"}, Window: 10 * time.Second}) + if r.ValueChanged() { + values++ + } + return r + }} + tt := ui.NewTester(h.view, 520, 440) + if !tt.HasText("No data") { + t.Fatalf("empty buffer: %q", tt.Texts()) + } + for i := range 30 { + buf.Append(rtStart.Add(time.Duration(i)*time.Second), float64(i), float64(2*i)) + } + tt.Frame() + tabTo(t, tt, "Sound") + tt.Key(0, ui.KeyHome) + if got := chartReadout(tt); got != "2026-10-05 09:00:19 · Bell 19 · Organ 38" { + t.Fatalf("window start %q", got) + } + if err := tt.Click("Pause"); err != nil || !st.Paused || values != 1 { + t.Fatalf("pause: %v %v %d", err, st.Paused, values) + } + for i := 30; i < 40; i++ { + buf.Append(rtStart.Add(time.Duration(i)*time.Second), float64(i), 0) + } + tt.Frame() + tabTo(t, tt, "Sound") + tt.Key(0, ui.KeyEnd) + if got := chartReadout(tt); !strings.HasPrefix(got, "2026-10-05 09:00:29 ·") { + t.Fatalf("paused view moved: %q", got) + } + _ = tt.Click("Resume") + tabTo(t, tt, "Sound") + tt.Key(0, ui.KeyEnd) + if got := chartReadout(tt); !strings.HasPrefix(got, "2026-10-05 09:00:39 ·") || st.Paused { + t.Fatalf("resumed view %q", got) + } +} + +func TestRealtimeChartSnapshot(t *testing.T) { + buf := NewRealtimeBuffer(200, "Bell", "Organ") + for i := range 60 { + x := float64(i) + buf.Append(rtStart.Add(time.Duration(i)*time.Second), 5+3*math.Sin(x/5), 4+2*math.Sin(x/3+1)) + } + snapshot(t, "realtime_chart", 520, 380, func(c *ui.Context) { + var st RealtimeChartState + ui.Column(c).Padding(16).Children(func() { + RealtimeChart(c, &st, buf, RealtimeChartOptions{Frame: ChartFrame{Label: "Sound"}, Window: 30 * time.Second}) + }) + }) +} diff --git a/sankey_chart.go b/sankey_chart.go new file mode 100644 index 0000000..edfe561 --- /dev/null +++ b/sankey_chart.go @@ -0,0 +1,235 @@ +package mujica + +import ( + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// SankeyNode is a stage that flow passes through. +type SankeyNode struct{ ID, Label string } + +// SankeyLink carries Value from node From to node To. +type SankeyLink struct { + From, To string + Value float64 +} + +// SankeyChartOptions configure a SankeyChart. +type SankeyChartOptions struct { + Frame ChartFrame + Format func(v float64) string +} + +// sankeyLayout puts nodes in columns by longest path. +type sankeyLayout struct { + col []int + in, out []float64 + cols int + from, to []int +} + +func sankeyPlace(nodes []SankeyNode, links []SankeyLink) sankeyLayout { + at := map[string]int{} + for i, n := range nodes { + if n.ID == "" || n.Label == "" { + panic("mujica: SankeyChart nodes need an ID and a Label") + } + if _, dup := at[n.ID]; dup { + panic("mujica: SankeyChart has two nodes " + n.ID) + } + at[n.ID] = i + } + l := sankeyLayout{col: make([]int, len(nodes)), in: make([]float64, len(nodes)), out: make([]float64, len(nodes))} + for _, e := range links { + f, okf := at[e.From] + t, okt := at[e.To] + if !okf || !okt || f == t || !(e.Value > 0) || math.IsInf(e.Value, 0) { + panic("mujica: SankeyChart links need known ends and a positive value") + } + l.from, l.to = append(l.from, f), append(l.to, t) + l.out[f] += e.Value + l.in[t] += e.Value + } + // Relax columns; more passes than nodes means a cycle. + for pass := 0; ; pass++ { + if pass > len(nodes) { + panic("mujica: SankeyChart links form a cycle") + } + moved := false + for i := range links { + if l.col[l.to[i]] < l.col[l.from[i]]+1 { + l.col[l.to[i]], moved = l.col[l.from[i]]+1, true + } + } + if !moved { + break + } + } + for i := range nodes { + l.cols = max(l.cols, l.col[i]+1) + } + return l +} + +// SankeyChart draws flows; reading a mark highlights its paths. +func SankeyChart(c *ui.Context, nodes []SankeyNode, links []SankeyLink, opts SankeyChartOptions) ChartResult { + ch := newChart(c, opts.Frame) + l := chartMemo(ch, "layout", [2]string{chartID(nodes), chartID(links)}, func() sankeyLayout { return sankeyPlace(nodes, links) }) + k := Tokens(c) + pal := internal.Palette(k) + size := FontSize(c, theme.CaptionSize) + val := func(v float64) string { return chartValue(c, v, opts.Format) } + size1 := func(i int) float64 { return max(l.in[i], l.out[i]) } + // geom returns node boxes and link ends. + geom := func(r ui.Rect) (boxes []ui.Rect, y0, y1 []float32, scale float32) { + const gap, w = 10, 12 + plot := ui.Rect{X: r.X + 8, Y: r.Y + 6, W: r.W - 16, H: r.H - 12} + most, count := 0.0, 0 + for col := range l.cols { + sum, n := 0.0, 0 + for i := range nodes { + if l.col[i] == col { + sum, n = sum+size1(i), n+1 + } + } + if sum > most { + most, count = sum, n + } + } + scale = (plot.H - gap*float32(max(count-1, 0))) / float32(max(most, 1e-9)) + boxes = make([]ui.Rect, len(nodes)) + step := (plot.W - w) / float32(max(l.cols-1, 1)) + next := make([]float32, l.cols) + for i := range nodes { + h := max(float32(size1(i))*scale, 2) + boxes[i] = ui.Rect{X: plot.X + step*float32(l.col[i]), Y: plot.Y + next[l.col[i]], W: w, H: h} + next[l.col[i]] += h + gap + } + outAt, inAt := make([]float32, len(nodes)), make([]float32, len(nodes)) + for i := range links { + y0, y1 = append(y0, boxes[l.from[i]].Y+outAt[l.from[i]]), append(y1, boxes[l.to[i]].Y+inAt[l.to[i]]) + outAt[l.from[i]] += float32(links[i].Value) * scale + inAt[l.to[i]] += float32(links[i].Value) * scale + } + return + } + // ribbon returns link i's top edge at t and thickness. + ribbon := func(boxes []ui.Rect, y0, y1 []float32, scale float32, i int, t float32) (x, y, h float32) { + a, b := boxes[l.from[i]], boxes[l.to[i]] + s := t * t * (3 - 2*t) + return a.X + a.W + (b.X-a.X-a.W)*t, y0[i] + (y1[i]-y0[i])*s, float32(links[i].Value) * scale + } + n := len(nodes) + len(links) + if len(links) == 0 { + n = 0 + } + spec := chartSpec{n: n} + spec.readout = func(i int) string { + if i < len(nodes) { + return nodes[i].Label + " · " + msg(c, "sankey_chart.in") + " " + val(l.in[i]) + " · " + msg(c, "sankey_chart.out") + " " + val(l.out[i]) + } + e := links[i-len(nodes)] + return nodes[l.from[i-len(nodes)]].Label + " → " + nodes[l.to[i-len(nodes)]].Label + " · " + val(e.Value) + } + spec.pick = func(r ui.Rect, x, y float32) int { + boxes, y0, y1, scale := geom(r) + for i, b := range boxes { + if (ui.Rect{X: b.X - 4, Y: b.Y, W: b.W + 8, H: b.H}).Contains(x, y) { + return i + } + } + for i := range links { + a, b := boxes[l.from[i]], boxes[l.to[i]] + if x < a.X+a.W || x > b.X { + continue + } + _, top, h := ribbon(boxes, y0, y1, scale, i, (x-a.X-a.W)/(b.X-a.X-a.W)) + if y >= top && y <= top+max(h, 4) { + return len(nodes) + i + } + } + return -1 + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + boxes, y0, y1, scale := geom(r) + lit := sankeyLit(l, len(nodes), active) + for i := range links { + var band ui.Path + const steps = 24 + for s := 0; s <= steps; s++ { + x, y, _ := ribbon(boxes, y0, y1, scale, i, float32(s)/steps) + if s == 0 { + band.MoveTo(x, y) + } else { + band.LineTo(x, y) + } + } + for s := steps; s >= 0; s-- { + x, y, h := ribbon(boxes, y0, y1, scale, i, float32(s)/steps) + band.LineTo(x, y+h) + } + band.Close() + alpha := float32(0.4) + if lit != nil && !lit[len(nodes)+i] { + alpha = 0.12 + } + p.FillPath(&band, pal[l.from[i]%len(pal)].Alpha(alpha)) + if active == len(nodes)+i { + p.StrokePath(&band, 1.5, k.Text) + } + } + for i, b := range boxes { + col := pal[i%len(pal)] + if lit != nil && !lit[i] { + col = col.Mix(k.Surface, 0.6) + } + p.Fill(b, col, 1) + if i == active { + p.Stroke(ui.Rect{X: b.X - 2, Y: b.Y - 2, W: b.W + 4, H: b.H + 4}, k.Text, 2, 1.5) + } + if l.col[i] == l.cols-1 { + chartText(p, nodes[i].Label, b.X-6, b.Y+b.H/2, size, k.Text, 1, 0.5) + } else { + chartText(p, nodes[i].Label, b.X+b.W+6, b.Y+b.H/2, size, k.Text, 0, 0.5) + } + } + } + res, _ := ch.build(spec) + return res +} + +// sankeyLit marks everything on paths through active; nil means all. +func sankeyLit(l sankeyLayout, nodes, active int) []bool { + if active < 0 { + return nil + } + lit := make([]bool, nodes+len(l.from)) + var walk func(node int, down bool) + walk = func(node int, down bool) { + lit[node] = true + for i := range l.from { + if down && l.from[i] == node && !lit[nodes+i] { + lit[nodes+i] = true + walk(l.to[i], true) + } + if !down && l.to[i] == node && !lit[nodes+i] { + lit[nodes+i] = true + walk(l.from[i], false) + } + } + } + if active < nodes { + walk(active, true) + walk(active, false) + return lit + } + i := active - nodes + lit[active] = true + walk(l.to[i], true) + walk(l.from[i], false) + return lit +} diff --git a/sankey_chart_test.go b/sankey_chart_test.go new file mode 100644 index 0000000..056c1b5 --- /dev/null +++ b/sankey_chart_test.go @@ -0,0 +1,81 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +var sankeyNodes = []SankeyNode{{"tithe", "Tithes"}, {"alms", "Alms"}, {"fund", "Fund"}, {"roof", "Roof"}, {"bread", "Bread"}, {"bells", "Bells"}} +var sankeyLinks = []SankeyLink{ + {"tithe", "fund", 60}, {"alms", "fund", 30}, {"alms", "bread", 10}, + {"fund", "roof", 50}, {"fund", "bells", 40}, +} + +func TestSankeyPlaceStable(t *testing.T) { + l := sankeyPlace(sankeyNodes, sankeyLinks) + if fmt.Sprint(l.col) != "[0 0 1 2 1 2]" || l.cols != 3 || l.in[2] != 90 || l.out[1] != 40 { + t.Fatalf("layout %+v", l) + } + lit := sankeyLit(l, len(sankeyNodes), 0) // Tithes: its fund, roof and bells, not alms + if !lit[2] || !lit[3] || !lit[5] || lit[1] || lit[4] || !lit[6] || lit[7] { + t.Fatalf("lit from Tithes %v", lit) + } + lit = sankeyLit(l, len(sankeyNodes), 6+3) // the fund → roof link + if !lit[0] || !lit[1] || !lit[3] || lit[5] || lit[6+4] { + t.Fatalf("lit from fund → roof %v", lit) + } +} + +func TestSankeyChartReadout(t *testing.T) { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return SankeyChart(c, sankeyNodes, sankeyLinks, SankeyChartOptions{Frame: ChartFrame{Label: "Money"}}) + }} + tt := ui.NewTester(h.view, 560, 440) + tabTo(t, tt, "Money") + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "Fund · in 90 · out 90" { + t.Fatalf("node %q", got) + } + tt.Key(0, ui.KeyEnd) + if got := chartReadout(tt); got != "Fund → Bells · 40" { + t.Fatalf("link %q", got) + } + tt.Key(0, ui.KeyEscape) + b := h.res.Element.Bounds() + tt.Move(b.X+8+4, b.Y+10) // the first node, at the top left + if got := chartReadout(tt); got != "Tithes · in 0 · out 60" { + t.Fatalf("hover %q", got) + } +} + +func TestSankeyChartBad(t *testing.T) { + for name, links := range map[string][]SankeyLink{ + "cycle": {{"tithe", "fund", 1}, {"fund", "tithe", 1}}, + "unknown": {{"tithe", "nowhere", 1}}, + "zero": {{"tithe", "fund", 0}}, + } { + func() { + defer func() { + if recover() == nil { + t.Errorf("%s: no panic", name) + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + SankeyChart(c, sankeyNodes, links, SankeyChartOptions{Frame: ChartFrame{Label: "x"}}) + }, 300, 300) + }() + } +} + +func TestSankeyChartSnapshot(t *testing.T) { + snapshot(t, "sankey_chart", 560, 320, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + SankeyChart(c, sankeyNodes, sankeyLinks, SankeyChartOptions{Frame: ChartFrame{Label: "Money"}}) + }) + }) +} diff --git a/scatter_chart.go b/scatter_chart.go new file mode 100644 index 0000000..99764f8 --- /dev/null +++ b/scatter_chart.go @@ -0,0 +1,162 @@ +package mujica + +import ( + "fmt" + "log/slog" + "math" + "slices" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// ScatterPoint is one dot; Size sets a bubble's area. +type ScatterPoint struct{ X, Y, Size float64 } + +// ScatterGroup is named points sharing color and shape. +type ScatterGroup struct { + Name string + Points []ScatterPoint +} + +// ScatterKey names point Point of group Group. +type ScatterKey struct{ Group, Point int } + +// ScatterChartOptions configure a ScatterChart. +type ScatterChartOptions struct { + Frame ChartFrame + // Bubbles maps Size to dot area, 4–18 DIPs across. + Bubbles bool + Format func(v float64) string +} + +type scatterDrag struct { + on bool + x0, y0, x1, y1 float32 +} + +// ScatterChart plots groups; box drag, Enter or Space selects. +func ScatterChart(c *ui.Context, selected *[]ScatterKey, groups []ScatterGroup, opts ScatterChartOptions) ChartResult { + ch := newChart(c, opts.Frame) + k := Tokens(c) + pal := internal.Palette(k) + size := FontSize(c, theme.CaptionSize) + keys := make([]chartKey, len(groups)) + var marks []ScatterKey + b := [6]float64{math.Inf(1), math.Inf(-1), math.Inf(1), math.Inf(-1), math.Inf(1), math.Inf(-1)} + for gi, g := range groups { + keys[gi] = chartKey{Name: g.Name, Color: pal[gi%len(pal)], Shape: gi} + if g.Name == "" || ch.hidden(g.Name) { + continue + } + for pi, pt := range g.Points { + if math.IsNaN(pt.X) || math.IsNaN(pt.Y) || pt.Size < 0 { + panic("mujica: ScatterChart points need finite X, Y and Size ≥ 0") + } + marks = append(marks, ScatterKey{gi, pi}) + b = [6]float64{min(b[0], pt.X), max(b[1], pt.X), min(b[2], pt.Y), max(b[3], pt.Y), min(b[4], pt.Size), max(b[5], pt.Size)} + } + } + var xs, ys [3]float64 + if len(marks) > 0 { + // A margin keeps dots off the plot edges. + px, py := (b[1]-b[0])*0.06, (b[3]-b[2])*0.06 + xs[0], xs[1], xs[2] = internal.Nice(b[0]-px, b[1]+px, 4) + ys[0], ys[1], ys[2] = internal.Nice(b[2]-py, b[3]+py, 4) + } + pt := func(m ScatterKey) ScatterPoint { return groups[m.Group].Points[m.Point] } + geom := func(r ui.Rect) (ui.Rect, internal.Linear, internal.Linear) { + plot := chartInset(r, 52, 26) + return plot, internal.Linear{D0: xs[0], D1: xs[1], R0: float64(plot.X), R1: float64(plot.X + plot.W)}, + internal.Linear{D0: ys[0], D1: ys[1], R0: float64(plot.Y + plot.H), R1: float64(plot.Y)} + } + radius := func(m ScatterKey) float32 { + if !opts.Bubbles || b[5] <= 0 { + return 4 + } + return 2 + 7*float32(math.Sqrt(pt(m).Size/b[5])) + } + toggle := func(m ScatterKey) { + if i := slices.Index(*selected, m); i >= 0 { + *selected = slices.Delete(slices.Clone(*selected), i, i+1) + } else { + *selected = append(slices.Clone(*selected), m) + } + ch.res.value = true + slog.Debug("mujica: scatter_chart select", "count", len(*selected)) + } + spec := chartSpec{n: len(marks), keys: keys, toggle: len(groups) > 1} + spec.readout = func(i int) string { + m, p := marks[i], pt(marks[i]) + s := fmt.Sprintf("%s · x %s · y %s", groups[m.Group].Name, chartValue(c, p.X, opts.Format), chartValue(c, p.Y, opts.Format)) + if opts.Bubbles { + s += " · " + msg(c, "scatter_chart.size") + " " + chartValue(c, p.Size, opts.Format) + } + if slices.Contains(*selected, m) { + s += " · " + msg(c, "scatter_chart.selected") + } + return s + } + spec.pick = func(r ui.Rect, x, y float32) int { + _, sx, sy := geom(r) + return internal.Nearest(len(marks), func(i int) (float32, float32) { return sx.Map(pt(marks[i]).X), sy.Map(pt(marks[i]).Y) }, x, y, 14, false) + } + spec.activate = func(i int) { toggle(marks[i]) } + drag := ui.Local(ch.res.Element, "mujica.scatter.drag", func() scatterDrag { return scatterDrag{} }) + box := *drag + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + plot, sx, sy := geom(r) + internal.AxisY(p, plot, sy, internal.Ticks(ys[0], ys[1], ys[2]), func(v float64) string { return internal.FormatTick(v, ys[2]) }, size, k) + var tx []float32 + var tl []string + for _, t := range internal.Ticks(xs[0], xs[1], xs[2]) { + tx, tl = append(tx, sx.Map(t)), append(tl, internal.FormatTick(t, xs[2])) + } + internal.AxisX(p, plot, tx, tl, size, k) + for i, m := range marks { + x, y, rad := sx.Map(pt(m).X), sy.Map(pt(m).Y), radius(m) + internal.Marker(p, m.Group, x, y, 2*rad, keys[m.Group].Color.Alpha(0.85)) + if slices.Contains(*selected, m) || i == active { + var ring ui.Path + ring.Circle(internal.Snap(p, x), internal.Snap(p, y), rad+3+2*float32(chartBool(i == active))) + p.StrokePath(&ring, 1.5, k.Text) + } + } + if box.on { + p.StrokeDashed(scatterRect(box, r.X, r.Y), k.Text, 0, 1) + } + } + res, plot := ch.build(spec) + if plot != nil && !plot.IsDisabled() { + x, y, _ := plot.PointerPosition() + if _, _, held := plot.Dragged(); held { + if !drag.on { + *drag = scatterDrag{on: true, x0: x, y0: y} + } + drag.x1, drag.y1 = x, y + } else if drag.on { + if pb := plot.Bounds(); max(abs32(drag.x1-drag.x0), abs32(drag.y1-drag.y0)) > 4 { + _, sx, sy := geom(ui.Rect{W: pb.W, H: pb.H}) + in := scatterRect(*drag, 0, 0) + var picked []ScatterKey + for _, m := range marks { + if in.Contains(sx.Map(pt(m).X), sy.Map(pt(m).Y)) { + picked = append(picked, m) + } + } + *selected, res.value = picked, true + slog.Debug("mujica: scatter_chart box", "count", len(picked)) + } + *drag = scatterDrag{} + } + } + return res +} + +func scatterRect(d scatterDrag, ox, oy float32) ui.Rect { + return ui.Rect{X: ox + min(d.x0, d.x1), Y: oy + min(d.y0, d.y1), W: abs32(d.x1 - d.x0), H: abs32(d.y1 - d.y0)} +} + +func abs32(v float32) float32 { return max(v, -v) } diff --git a/scatter_chart_test.go b/scatter_chart_test.go new file mode 100644 index 0000000..713b57c --- /dev/null +++ b/scatter_chart_test.go @@ -0,0 +1,82 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +var scatterGroups = []ScatterGroup{ + {Name: "Monks", Points: []ScatterPoint{{1, 2, 4}, {3, 5, 9}, {6, 4, 1}}}, + {Name: "Nuns", Points: []ScatterPoint{{2, 7, 16}, {8, 9, 2}}}, +} + +func TestScatterChartKeyboardSelect(t *testing.T) { + var sel []ScatterKey + values := 0 + h := &chartHarness{build: func(c *ui.Context) ChartResult { + r := ScatterChart(c, &sel, scatterGroups, ScatterChartOptions{Frame: ChartFrame{Label: "Choir"}, Bubbles: true}) + if r.ValueChanged() { + values++ + } + return r + }} + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "Choir") + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeySpace) + if fmt.Sprint(sel) != "[{0 1}]" || values != 1 { + t.Fatalf("Space selected %v (%d events)", sel, values) + } + if got := chartReadout(tt); got != "Monks · x 3 · y 5 · size 9 · selected" { + t.Fatalf("readout %q", got) + } + tt.Key(0, ui.KeyEnter) + if len(sel) != 0 { + t.Fatalf("Enter did not unselect: %v", sel) + } +} + +func TestScatterChartBoxSelect(t *testing.T) { + var sel []ScatterKey + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return ScatterChart(c, &sel, scatterGroups, ScatterChartOptions{Frame: ChartFrame{Label: "Choir"}}) + }} + tt := ui.NewTester(h.view, 520, 420) + b := h.res.Element.Bounds() + top := b.Y + 38 + // Nice domains: x 0..10 over 52..W-12; y 0..10 over top+8..top+214. + x := func(v float32) float32 { return b.X + 52 + (b.W-64)*v/10 } + y := func(v float32) float32 { return top + 8 + 206*(1-v/10) } + tt.Press(x(0.5), y(6)) + tt.Move(x(4), y(4)) + tt.Move(x(6.5), y(1.5)) + tt.Release(x(6.5), y(1.5)) + if fmt.Sprint(sel) != "[{0 0} {0 1} {0 2}]" { + t.Fatalf("box chose %v", sel) + } +} + +func TestScatterChartBad(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic for negative size") + } + }() + var sel []ScatterKey + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ScatterChart(c, &sel, []ScatterGroup{{Name: "a", Points: []ScatterPoint{{1, 1, -1}}}}, ScatterChartOptions{Frame: ChartFrame{Label: "x"}}) + }, 300, 300) +} + +func TestScatterChartSnapshot(t *testing.T) { + snapshot(t, "scatter_chart", 520, 340, func(c *ui.Context) { + sel := []ScatterKey{{1, 0}} + ui.Column(c).Padding(16).Children(func() { + ScatterChart(c, &sel, scatterGroups, ScatterChartOptions{Frame: ChartFrame{Label: "Choir"}, Bubbles: true}) + }) + }) +} diff --git a/sparkline.go b/sparkline.go new file mode 100644 index 0000000..7048ebe --- /dev/null +++ b/sparkline.go @@ -0,0 +1,170 @@ +package mujica + +import ( + "log/slog" + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// SparklineKind is how a Sparkline draws its values. +type SparklineKind int + +const ( + SparklineLine SparklineKind = iota + SparklineBar + SparklineArea +) + +// SparklineOptions configure a Sparkline; Frame.Height 0 means 28 DIPs. +type SparklineOptions struct { + Frame ChartFrame + Kind SparklineKind + // Width is the plot width; 0 means 96 DIPs. + Width float32 + Format func(v float64) string +} + +// Sparkline is an inline chart without axes. +func Sparkline(c *ui.Context, values []float64, opts SparklineOptions) ChartResult { + f := opts.Frame + if f.Label == "" || f.Height < 0 || opts.Width < 0 || opts.Kind > SparklineArea { + panic("mujica: Sparkline needs a Label, sizes ≥ 0 and a known Kind") + } + if f.Height == 0 { + f.Height = 28 + } + w := opts.Width + if w == 0 { + w = 96 + } + k := Tokens(c) + u := Density(c).Unit() + col := internal.Palette(k)[0] + size := FontSize(c, theme.CaptionSize) + lo, hi := math.Inf(1), math.Inf(-1) + last := -1 + for i, v := range values { + if !math.IsNaN(v) { + lo, hi, last = min(lo, v), max(hi, v), i + } + } + res := ChartResult{Point: -1} + res.Element = ui.Row(c).Gap(u * 2).AlignItems(ui.Center) + st := ui.Local(res.Element, "mujica.sparkline", func() chartState { return chartState{focus: -1, last: -1} }) + res.Element.Children(func() { + if f.Status == DataLoading || f.Status == DataFailed || last < 0 { + box := ui.Row(c).Size(w, f.Height).AlignItems(ui.Center).Gap(u) + box.Children(func() { + switch f.Status { + case DataLoading: + Spinner(c, SpinnerOptions{Size: 14, Label: msg(c, "list.loading")}) + case DataFailed: + ui.Text(c, dataError(c, f.Error)).FontSize(size).TextColor(k.Danger).SingleLine().Grow(1).MinWidth(0) + res.retry = iconAction(c, icons.Must("refresh-cw"), msg(c, "list.retry")).Clicked() + default: + empty := f.Empty + if empty == "" { + empty = msg(c, "chart.empty") + } + ui.Text(c, empty).FontSize(size).TextColor(k.TextMuted).SingleLine() + } + }) + st.focus = -1 + return + } + if lo == hi { + lo, hi = lo-1, hi+1 + } + if opts.Kind == SparklineBar { + lo, hi = min(lo, 0), max(hi, 0) + } + plot := ui.Box(c).Size(w, f.Height).Shrink(0).Focusable().Label(f.Label).Role(ui.RoleGroup) + internal.Ring(plot, k.Focus, theme.ControlRadius) + n := len(values) + x := func(r ui.Rect, i int) float32 { return r.X + 3 + (r.W-6)*float32(i)/float32(max(n-1, 1)) } + ys := func(r ui.Rect) internal.Linear { + return internal.Linear{D0: lo, D1: hi, R0: float64(r.Y + r.H - 3), R1: float64(r.Y + 3)} + } + if !plot.IsDisabled() { + to := st.focus + switch { + case plot.Shortcut(0, ui.KeyLeft): + to = max(st.focus-1, 0) + case plot.Shortcut(0, ui.KeyRight): + to = min(st.focus+1, n-1) + case plot.Shortcut(0, ui.KeyHome): + to = 0 + case plot.Shortcut(0, ui.KeyEnd): + to = n - 1 + case plot.Shortcut(0, ui.KeyEscape): + to = -1 + } + if to != st.focus { + st.focus = to + if to >= 0 { + c.Announce(chartValue(c, values[to], opts.Format)) + } + slog.Debug("mujica: sparkline focus", "label", f.Label, "mark", to) + } + } + active := -1 + if px, _, over := plot.PointerPosition(); over && !plot.IsDisabled() { + active = max(0, min(n-1, int(math.Round(float64((px-3)/(w-6)*float32(max(n-1, 1))))))) + } else if plot.Focused() { + active = st.focus + } + res.Point = active + plot.Draw(func(p *ui.Painter, r ui.Rect) { + s := ys(r) + if opts.Kind == SparklineBar { + bw := max((r.W-6)/float32(n)-1, 1) + for i, v := range values { + if math.IsNaN(v) { + continue + } + a, b := s.Map(0), s.Map(v) + cx := x(r, i) + p.Fill(ui.Rect{X: cx - bw/2, Y: min(a, b), W: bw, H: max(abs32(a-b), 1)}, col, 0) + } + } else { + chartRuns(values, func(i int) float32 { return x(r, i) }, func(idx []int) { + var line ui.Path + for j, i := range idx { + px, py := internal.Snap(p, x(r, i)), internal.Snap(p, s.Map(values[i])) + if j == 0 { + line.MoveTo(px, py) + } else { + line.LineTo(px, py) + } + } + if opts.Kind == SparklineArea { + fill := line + fill.LineTo(internal.Snap(p, x(r, idx[len(idx)-1])), r.Y+r.H-3).LineTo(internal.Snap(p, x(r, idx[0])), r.Y+r.H-3).Close() + p.FillPath(&fill, col.Alpha(0.22)) + } + p.StrokePath(&line, 1.5, col) + }) + } + // Diamond: last value. Ring: the value being read. + p.FillPath(internal.Diamond(internal.Snap(p, x(r, last)), internal.Snap(p, s.Map(values[last])), 7), k.Text) + if active >= 0 && !math.IsNaN(values[active]) { + var ring ui.Path + ring.Circle(internal.Snap(p, x(r, active)), internal.Snap(p, s.Map(values[active])), 4) + p.StrokePath(&ring, 1.5, k.Text) + } + }) + shown := last + if active >= 0 { + shown = active + } + ui.Text(c, chartValue(c, values[shown], opts.Format)).FontSize(size).TextColor(k.Text).SingleLine().Role(ui.RoleStatus) + }) + res.changed = res.Point != st.last + st.last = res.Point + return res +} diff --git a/sparkline_test.go b/sparkline_test.go new file mode 100644 index 0000000..b8bdbbd --- /dev/null +++ b/sparkline_test.go @@ -0,0 +1,78 @@ +package mujica + +import ( + "math" + "testing" + + "github.com/egoist/mygo/ui" +) + +var sparkValues = []float64{3, 5, 4, math.NaN(), 7, 6, 9} + +func TestSparklineEndValueAndKeys(t *testing.T) { + kind := SparklineLine + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return Sparkline(c, sparkValues, SparklineOptions{Frame: ChartFrame{Label: "Bells"}, Kind: kind}) + }} + tt := ui.NewTester(h.view, 300, 200) + if got := chartReadout(tt); got != "9" { + t.Fatalf("end value %q", got) + } + r, _ := tt.Find("Bells") + if r.H < 28 || r.W != 96 { + t.Fatalf("sparkline box %v", r) + } + tabTo(t, tt, "Bells") + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "5" || h.res.Point != 1 { + t.Fatalf("read %q at %d", got, h.res.Point) + } + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "no value" { + t.Fatalf("missing %q", got) + } + for _, kind = range []SparklineKind{SparklineBar, SparklineArea} { + tt.Frame() + tt.Move(r.X+r.W-2, r.Y+r.H/2) + if got := chartReadout(tt); got != "9" || h.res.Point != 6 { + t.Fatalf("kind %d hover %q", kind, got) + } + } +} + +func TestSparklineStates(t *testing.T) { + status := DataLoading + var vals []float64 + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return Sparkline(c, vals, SparklineOptions{Frame: ChartFrame{Label: "Bells", Status: status}}) + }} + tt := ui.NewTester(h.view, 300, 200) + status = DataFailed + tt.Frame() + if err := tt.Click("Retry"); err != nil { + t.Fatal(err) + } + status = DataReady + tt.Frame() + if !tt.HasText("No data") { + t.Fatalf("empty %q", tt.Texts()) + } + defer func() { + if recover() == nil { + t.Fatal("no panic without a label") + } + }() + ui.NewTester(func(c *ui.Context) { Use(c, Settings{}); Sparkline(c, vals, SparklineOptions{}) }, 100, 100) +} + +func TestSparklineSnapshot(t *testing.T) { + snapshot(t, "sparkline", 420, 80, func(c *ui.Context) { + ui.Row(c).Padding(16).Gap(24).Children(func() { + for _, k := range []SparklineKind{SparklineLine, SparklineBar, SparklineArea} { + Sparkline(c, sparkValues, SparklineOptions{Frame: ChartFrame{Label: "Bells"}, Kind: k}) + } + }) + }) +} diff --git a/sunburst.go b/sunburst.go new file mode 100644 index 0000000..6ee6712 --- /dev/null +++ b/sunburst.go @@ -0,0 +1,155 @@ +package mujica + +import ( + "fmt" + "log/slog" + "math" + "slices" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// SunburstOptions configure a Sunburst. +type SunburstOptions struct { + Frame ChartFrame + // Depth is the number of rings; 0 means 3. + Depth int + Format func(v float64) string +} + +// sunArc is one drawn segment of a ring. +type sunArc struct { + path []string + node ChartNode + ring int + a0, a1 float64 + color int +} + +// Sunburst draws descendants of *path as rings; branches drill in. +func Sunburst(c *ui.Context, path *[]string, root ChartNode, opts SunburstOptions) ChartResult { + if opts.Depth < 0 { + panic("mujica: Sunburst Depth must be ≥ 0") + } + depth := opts.Depth + if depth == 0 { + depth = 3 + } + chartCheckTree(root) + chartDescend(root, *path) + k := Tokens(c) + u := Density(c).Unit() + size := FontSize(c, theme.CaptionSize) + pal := internal.Palette(k) + var res ChartResult + wrap := ui.Column(c).Gap(u * 2).MinWidth(0) + wrap.Children(func() { + res.value = chartPath(c, root.Name, path, wrap.IsDisabled()) + node := chartDescend(root, *path) + sum := node.total() + var arcs []sunArc + var walk func(n ChartNode, at []string, ring int, a0, a1 float64, color int) + walk = func(n ChartNode, at []string, ring int, a0, a1 float64, color int) { + total, width := n.total(), a1-a0 + for i, ch := range n.Children { + v := ch.total() + if v <= 0 { + continue + } + span := width * v / total + col := color + if ring == 0 { + col = i + } + arc := sunArc{path: append(slices.Clone(at), ch.Name), node: ch, ring: ring, a0: a0, a1: a0 + span, color: col} + arcs = append(arcs, arc) + if ring+1 < depth { + walk(ch, arc.path, ring+1, arc.a0, arc.a1, col) + } + a0 += span + } + } + if sum > 0 { + walk(node, nil, 0, 0, 2*math.Pi, 0) + } + geom := func(r ui.Rect) (cx, cy, hole, ring float32) { + rad := min(r.W, r.H)/2 - 6 + hole = rad * 0.3 + return r.X + r.W/2, r.Y + r.H/2, hole, (rad - hole) / float32(depth) + } + ch := newChart(c, opts.Frame) + spec := chartSpec{n: len(arcs)} + spec.readout = func(i int) string { + a := arcs[i] + s := fmt.Sprintf("%s · %s · %.1f%%", strings.Join(a.path, " › "), chartValue(c, a.node.total(), opts.Format), 100*a.node.total()/sum) + if len(a.node.Children) > 0 { + s += " · " + msg(c, "chart.opens") + } + return s + } + spec.pick = func(r ui.Rect, x, y float32) int { + cx, cy, hole, ring := geom(r) + d := float32(math.Hypot(float64(x-cx), float64(y-cy))) + a := math.Atan2(float64(x-cx), float64(cy-y)) + if a < 0 { + a += 2 * math.Pi + } + for i, arc := range arcs { + r0 := hole + ring*float32(arc.ring) + if d >= r0 && d < r0+ring && a >= arc.a0 && a < arc.a1 { + return i + } + } + return -1 + } + spec.activate = func(i int) { + if len(arcs[i].node.Children) > 0 { + *path = append(slices.Clone(*path), arcs[i].path...) + res.value = true + slog.Debug("mujica: sunburst drill", "path", strings.Join(*path, "/")) + } + } + // color fades outer rings, keeping 3:1 against Surface. + color := func(a sunArc) ui.Color { + col := pal[a.color%len(pal)] + if faded := col.Mix(k.Surface, 0.18*float32(a.ring)); theme.Contrast(faded, k.Surface) >= 3 { + return faded + } + return col + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + cx, cy, hole, ring := geom(r) + for i, a := range arcs { + r0 := hole + ring*float32(a.ring) + col := color(a) + p.FillPath(internal.Sector(cx, cy, r0, r0+ring, a.a0, a.a1), col) + p.StrokePath(internal.Sector(cx, cy, r0, r0+ring, a.a0, a.a1), 1.5, k.Surface) + if i == active { + p.StrokePath(internal.Sector(cx, cy, r0+2, r0+ring-2, a.a0, a.a1), 2, chartInk(k, col)) + } + } + // Labels go on top where arcs are long enough. + for _, a := range arcs { + r0 := hole + ring*float32(a.ring) + col := color(a) + if mid := float64(r0+ring/2) * (a.a1 - a.a0); mid > 44 { + x, y := internal.Polar(cx, cy, r0+ring/2, (a.a0+a.a1)/2) + chartText(p, chartFit(p, a.node.Name, min(float32(mid)*0.8, ring*1.25), size), x, y, size, chartInk(k, col), 0.5, 0.5) + } + } + chartText(p, chartFit(p, node.Name, hole*2-8, size), cx, cy, size, k.TextMuted, 0.5, 1) + chartText(p, chartValue(c, sum, opts.Format), cx, cy+2, FontSize(c, theme.BodySize), k.Text, 0.5, 0) + } + r, plot := ch.build(spec) + if plot != nil && !plot.IsDisabled() && plot.Shortcut(0, ui.KeyBackspace) && len(*path) > 0 { + *path, res.value = (*path)[:len(*path)-1], true + } + res.Point, res.changed, res.retry = r.Point, r.changed, r.retry + }) + res.Element = wrap + return res +} diff --git a/sunburst_test.go b/sunburst_test.go new file mode 100644 index 0000000..e65d9c4 --- /dev/null +++ b/sunburst_test.go @@ -0,0 +1,64 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestSunburstReadoutAndDrill(t *testing.T) { + var path []string + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return Sunburst(c, &path, chartTree(), SunburstOptions{Frame: ChartFrame{Label: "Rooms"}}) + }} + tt := ui.NewTester(h.view, 560, 440) + tabTo(t, tt, "Rooms") + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "Library › Psalters · 30 · 34.1%" { + t.Fatalf("readout %q", got) + } + tt.Key(0, ui.KeyLeft) + tt.Key(0, ui.KeySpace) + if fmt.Sprint(path) != "[Library]" || !tt.HasText("Abbey") { + t.Fatalf("drill %v", path) + } + if err := tt.Click("Abbey"); err != nil || len(path) != 0 { + t.Fatalf("breadcrumb back: %v %v", err, path) + } + b := h.res.Element.Bounds() + plotTop := b.Y + b.H - 20 - 8 - 240 + cx, cy := b.X+b.W/2, plotTop+120 + tt.Key(0, ui.KeyEscape) + tt.Move(cx+50, cy-30) // inner ring, upper right: Library + if got := chartReadout(tt); got != "Library · 40 · 45.5% · Enter opens" { + t.Fatalf("hover %q", got) + } + tt.Move(cx-48*0.866, cy-48*0.5) // inner ring at 300°: Garden spans 266°–348° + if got := chartReadout(tt); got != "Garden · 20 · 22.7% · Enter opens" { + t.Fatalf("hover at 300° %q", got) + } +} + +func TestSunburstBad(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic for duplicate children") + } + }() + var path []string + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + Sunburst(c, &path, ChartNode{Name: "r", Children: []ChartNode{{Name: "a", Value: 1}, {Name: "a", Value: 2}}}, SunburstOptions{Frame: ChartFrame{Label: "x"}}) + }, 300, 300) +} + +func TestSunburstSnapshot(t *testing.T) { + snapshot(t, "sunburst", 560, 360, func(c *ui.Context) { + var path []string + ui.Column(c).Padding(16).Children(func() { + Sunburst(c, &path, chartTree(), SunburstOptions{Frame: ChartFrame{Label: "Rooms", Height: 260}}) + }) + }) +} diff --git a/testdata/snapshots/darwin/area_chart-dark.png b/testdata/snapshots/darwin/area_chart-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..26128f55099cbef8291767e32fe8dbc80655fca1 GIT binary patch literal 18845 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

    Drib?#Z-9kT_(TD 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/area_chart-light.png b/testdata/snapshots/darwin/area_chart-light.png new file mode 100644 index 0000000000000000000000000000000000000000..101392a5d071cccfa830dc4ef215f3709dde0934 GIT binary patch literal 18427 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 Jmvv4FO#qX`@xA~6 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/bar_chart-dark.png b/testdata/snapshots/darwin/bar_chart-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..118d3936d7a7a60b1c658be6543cd3a6dc1e4b62 GIT binary patch literal 19288 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/bullet_chart-dark.png b/testdata/snapshots/darwin/bullet_chart-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..82f62d53158279bd114f5245de5376417eeb2431 GIT binary patch literal 11624 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%0DiZT#eZ__ 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

    !(S?A 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

    7m1@5f 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 BpP~Q& literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/network_graph-light.png b/testdata/snapshots/darwin/network_graph-light.png new file mode 100644 index 0000000000000000000000000000000000000000..90c1640590b92510ea0514840695577b66dd1b9b GIT binary patch literal 14812 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

    S$WdASVYYt1-}r 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 k|J@QP=K3=x0FjFVuoRM0=$N-bRg zz#kwbDx~6`cDm}NplrSlcR7d%>kU)>i$n`mUk#HU$cpo|4G=Glq*pa(r8yNtm~|YH zXj8Aduu`F`SlF5sxQ!J~h!vj-Ma$*iWkp7^wH+Cjl|up#8{iKs=_>4AB@LC6BmD64 zwikW#nz4g6$o`b}=LWi+*OFEU6

    &cP&JS8^8j9?E>HepbP+r{t*A~hkxea(GPmF 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 C*Khp* literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/sankey_chart-dark.png b/testdata/snapshots/darwin/sankey_chart-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..29ad59c59c5191bebed36a8976643ea3567e7fde GIT binary patch literal 13436 zcmeHu1yEdFnRx0G!P)TLxQ_YaCdiy;10p1kr3RPKyVH2+PE%X@_pH= zsoAQ3W_D|9s^*@z&Xu~yp7XqRt2^wyyc7x|AtDqM6pA!ZLJ11$#TzInXc71q&re=! zjvGNiafnMxh^lKM@lbG7vs^E^OD$zg+jFlAieg3(y1X z1Rlr*3)7qg&hCC?M1Tn7tkJhrYGjt_P|@rE*`KfC%R+A3r@>Z<;+>-Lc2sACV-hBc zomV5V28k5=pF`r2`L5%0i{Q53h;1Pa6mWtCL{B~uh!%xvT;Ff8-IHGHcY6Mm0tQO_ zkNn3Gn4~E1;6L8=xUbQX;?leqPLO`YH;in#*ea#X`DA`FcXCBMZGlu?eyremY1*Fc zDeNN?^ev+r`H+;jjs0=A8sssk6$>N%OG>lI3zc^z>v+$OJa(O0nZDXeqM2tj9~x^ycJ zR6MSZ2x2-fUD1_L*#N5emGC@{T^AZ6|O|Y(FY5VS?sWp+ad>fpZ zR!?W&`z_F+2{b0Yt^ob}eT3Lx*!Z&2vN9Jxr{W>qOWCR0ZFQM=r?dN@#+4`FLd*Jv z9FdPhix9Y#IdBK^UX@G$@C6|(EZyiJB=MfIILf+{H#5z~3W1<6Evs>P_A+C?m_70} z06L<#!l#9Xap-f%L#49q2zTSd*6!#r!9tt{U{o$LB70F==8o#_e2zVmQ4AgsAfc8R zvbqa-gRkZ*e7F3?S$r-0ZJ(+um{=&Qma=f8e?c9rXaCOiUG{B{tNtDteIGSg`-@Xo z%}c2$A_PESWF`!LK_(Gzl|LJxCpk--L54BBlLc3dW0I3tfq%>T3K5W5ml=_e;^Zd* z4={qE{Yvh(Cz$OX^Ej8s)WpFB8onUIM*=8aSuu{XV2Dvw%GYX$|A;073Og$LkXbZX zEi`$}C;ZS#*J2wpomQKH2gJ|Nu;^r)AvLMCG6=WF(z^~BK5@Gk?$K;3gHiRRL~Xk8 z(sGENV$sEbu{1yrAjVV7mneklR%KO1tzF1%RiVCRneD_Ftpr_dW>y@DNnMqXsx4DL zOO(&Y^#~klVIQx<^4Y*yXYFYOKytO#QR?adPl{rqdTJY&TlkNU0;z~$e@baJqWMn_ zZZ7W0DTOTFhKlb~OA-5tKgJ5~9=tPNAGA0#2BFs=)HF;rxN%>&x?|-ZIv}Ui zC}&nP<6B)bC>Wc3=sIr4RWW{+?)kz1{}PUS(fESScJ;}~sJQ8^>7wAGVKSYgj%kj! zYJ_`x3d8~!I9N$vm;mOZb(}}(_nG%cL_2_S@w^ZTv@lXk!2+pcz(v7>_g!hb>ZJhGOKg;_tb{(6&JpV#$F+)E^QT5v^7mGiLru5@ebRBwU>a6D}ig<^-SQ*<*jrPku*}z&kmydO-kp zTRZ;^Tl139TM~|yFLYcq5|uD3KOnf{ad=#`O9_CIDGK*=^Wfdt#4XV7`OhM$+=1t@ zq@5vu(J>L`m+tdT1Xdyg$a0_9u=W09Sug9S@paCtBLdUEi30*g zOJL~$vB{8}5V(M1Nm99pJ^t_%UH*P8+r*AXf~Lf<6D~!s&rct+cC%J^uNo_U{$TH1 zX@|ljho0bhN$*2)S6K}zE@oT0p3P^MEp!!HrU}&Wc=9Swe(iC1SV=Tp)dFf?Lg4l} zTFi+delXewW6>%g0Jtjko5~zD^PFcMk4_#YV@m*v;(5UmC}D(3hMWak=5mDwH7ZQt zR3Tk>MJpTTQMzDdIk~z={UJR5tucO|)o;c8o$1_Hmlx&gNB~l;8iR-QDcw6zlh1?P z_8Mqy%rK+}HH-w4pUMSz5KA}@Xg?V#N(~=n>BRgoe|@*sTS;c^2yRGxY;xFD0`v%y z9Kw0{xY^#BiiI+6p4BM`VN}1O5_$1U%E$`PgjdEP`>cRK$EwUC`xY*6CjWLOme{@b zmKET%lV^E;zV+$*>Pd^fzJ43}KP)W;#L8zst`D59+iyvg@=(^Va&q@`#(i{}x`tFk zD%rJbRq7k-b)2IKF*&I$fWI*)YYJAuDjv&jKTMuOV>;GZoWA^d25$Du;`zP+D#%}7 zRb@QZY5uwEyuZfwdvUXX8gYXVm2Fh|CwMR)5#IgvV@MT_?2*?|X;djIt$cR6P^C2d z$I42bEysNb38({P2+kZOBAt;r?PVKo2)MiJp}RDWapZ)!qps{KXZZMaUTKQn?6xjilR%a*pyT3A?;N+Hp8 zahi*YVCKj3_8M7c(D&YYL|XmE)TZfE|7e!wT*Yu|+h=@5KWE4BIN`ZbTv0P^l&0{_ z`W>>Qq2WpsYyM$IqwRc0zuQ7nB3s*?xK4XlT%A!=O_4)A4d)bNAAZJd-A!xhP^BLS z&@z+buelOZl1GK*)+=d+iFNy|WL?p73QbHF^%ZbYdG~hK_TDF{6`d~pSwCBBuwa3F zy}T0u9D>V?xf#=#Swx^>&YQp_=Q#L|7bP+YC5Ku5OabqA3)oksH2~-Moq}i|qs#`J z%y;QUn>%VZ>6E^55?_B?I7x(p)({njw7htF@ujd$-$GT1DN<-F9cb9!UPMi#HO_bL ztEv+tzFOL?a)+kZ}Ju(AWfLPOy;Ch8~OnKMth+@P76!Oe8j@A!x*EF&=C0- z%I3AclOlALNz*~4_Cob1x|fn!g%I{U7+LbUsd$)TUs{#lf8 zfKfq8GIEMxbdwKRtoOQOryX0LQ##S+Zw^zUS{kN)*fBc4tJ1QUpB>Vj1y3!8lGx7T z9;I``{hBijaGjuF6|FGwy$oLPDW#;DKy67~zO`uPRIuaG*Hy}D+c`qKPst=>wdja!bEiz8aku0pD8idQAU$3KOCaEFJ7yO}GvrVSsn_W9g*?t34bMbNp03lb?jq~k~mk;~@{nk6?PRvEW`x$|IA z_s69s0~vHmteb%3q#-@l8LeR}Ld++8+1GXXN(}skVtI*)4E#y7N<%VL1&K2^lykpy zmjl`bh}_rE%@~KBc=;65FfE;I=5sEMiCL){PgnR5zD)&^q?WN9`HDP(Z)x&ud6zt6 z3sgvx3Svnh1wVPE(A`*S?Nf_*rK zt8L_L+yEGE?+O@dMy&2dF}riaD8QZ?FJr`OQ%B|nEz7hjVJ%C}qzio$ym>2}*`kk4 z)8CU)L+N8b)UST)(s%L6SpcsJ;4yzbh$hoLd2nk4ZTAa4?pm(gWo|=1ht*mlY@cd; z#}Cp?pbf#Z#-?U{#1`RYLsAF;Bdr%eM;Iyy9*Z^88(7+{Hx^0rLB9%h^8BmVBa7HR zD9UmIi1Jk49zIC-CB82-zHb=!2Pk?{QNsC!l+G{|>n4dOp(0IfHZ^s;BC^qeJZ+2mHD1V$a-PCGF)V61f}!Fqk@AU=ovei9#5~a59eM zC2{Y8b}KS(PoEIcoz+2IjqoVZoiB$tIW^4^-f9=$E3(}T)6FP9drw9DethfcRX0XT zFgt3FHHW(iku!%#oidOn23?L94 zGl_m-p*cWO^1)E~XpAwD@*lPqn7<5@%pW(aAN*x${?pX`uQn{O7a7vcZlI!m3m>=T zv}I~KyxVep6$=jt9I=y`5jg)=HB1tbylWjYcu`{IQ+77fC|gyOU`guv z!CG;3|G1q+{ZCLv0~cRb0?-wV`)gTsNq6_n;0efK3ctJi2E`xy#zb!J;&Iqm89rK6wl~_<^&W^PR>3@Q z+~(arc!(>;`G^)p47!;^VQ^uT2`G^SAA#5(&qk%3103Iu-)- z{bV~ z{LT`dYiuH5+#)ft)$xH&T+3;;8{`%a_U>`_=^A1zsWG$)9RT zW!boYvrMOI=ubt6ms0-Xw_E#n>j|b;yTX@8f?Q<=F)yz(dAHAN4qrE6(*?pdH`O;a zwWBlF2QFed_z{t+=aKh?R->Pz^$d{F5I#+zM}<9!AhY(FQNUs;A@rylXsPtP=g5T@ z(5U=PJTk!yoq^7agdAOJt+PW+pyYB5CkIXII;^jPEjyOSMio5_qA&^5;`95bp z|Kg3(UO?h1Uj*JgB_n(HJE%WR4PQ(|<8dE*-VhAeP7lwx8RSuuZFmF#?@x}!NPjxhQC>czZL_?$v!kb_X}@()NL8*kd;5OT7kS^=4sR&SG<|-QGs>bfX~IRF=i_rE2`m~{+Tp$ma+3EAU zKh9>VN+<%YyzV;|4s~riTu-JC!NuH_tYhLKfv5=o^b0!&NE*#jjm=SC`98Zm-oER% ziS)#Ir6HcsQc_o3)OhnPscmtfuR(U@_NQ{+bz3d3G7^m@?qHbFO=MGjV|#~(K2^MV z_Omzp8*voOg1sR`z69vttG`oSWfuAb(M79AUgV&{@?n^}O)w?QoX5}M zkeSyW7lp667v`^gyf@18X-5kY`Eqv!r#J3kq#X`bw_{oielRByWVzf( zjWq0S)iK$he>|Y?Q0v-JTX~tW?!1!Sd@E}?xMJ$SJo5Grfy}>>tAbhDUGh1f)vT0K^(OAmLW z(q|;mVMHhBrz6dO$O%>)T%UZQzZ>mxU4F9(?5nK+x|o=%$E1nGj*pgYC#Th}cs7Fi z65-?f+#b86<_bv$&1PFvN83S2KCL`!uW~d;4ZN=I|r@SU0+O6F~XA>+eW5 z^>#J70)>V~C&h#!kvORX@0tCjvGO{HNoK|D++<)dR`sL;@3N2g=SQC2c7|%Cafad*e52V)-Xj3Mc{HKsG!{#BeILrH!x{?DZ}yRD;S$AKIc-ureiKbZr_Iw z;f16fm-`QDk&IH~vhYNZi5IhyDmgkW9dT@GNFkaiS0?(0&o|Q3IjdMNH1ff6I+u`4 zMz{VPkjj{O`3r-BL^x@?qq}Ue-t~^@pk0Chxr4-;#TnGXX6jv`K=cvQz&GryiF8xQ zDoXS+B>gT2KV{E0OKwggEf=CGiG+UdJRvI3AL5I(0;y-ru9t|TM50GQLUf+G;@L)E z@r%r-oATVk8XG}=Q;QKHzByY(zfmfu+aDKCzn~+C*8M@_Lu$aKaa$8hI+p&+b?SHS zt(RUg>|8H|anerWT=()8V^CkPStyIA@bWdT59N~(V^zQSa*BvAB107Gk4p0{w7v&& zo?&vf1C0;GzVFR3501=RN^VqK`gBRYrQ}i(_=T#AxEG5y4E|E9f$1yBF-1LZP zHEM&e|K*pM2mw zTi_J&s_0?Qp}|>{xCJ%1=Soz$%tdnF>-!nqaiU^+bAr}!QIW%N!wqi$IBm-j$GC8d ziB~N2hn(rCrk3A^$LScJdI4<4>S*$((P#mTK&&d+7FWFi*{#w+giBd;ervm4;8l%x zoVK2h891IYkjL?{&(fBR4GZ4kYG9>guB3ei^QoM?CcLNE0OkF`Sa^xQ#zajp%ihJ* zIGN#XO!K-)DyHZJ&t`8+(E(+$v1;NwZd3U97mA%T`zsI1pFXe-wrjrgCx`c^dPV+! z@=E55zKKamE$&liK&pjz>JyJ9-8NWi~bUAAIupji92Hmtq=ApMwwp~a20wXat9Qmkxyokw-X zxLZXdh<|KhsYk3zC*!w0$W3chb?>wHkqfUG_r;N2G3KHeU?)|bZCck#dgsRnLMbWGeFUcd(`jX;_1Fcw zlcVG5r2{2}aOX$fmTh63TLcW}0i)q$CWB?@Kdf+vkKLkSy1lt(@f5O^bo!*UR#7)+ zKv7m!)$SF*R9n+Xl_$v0%??Tc8mTEN-t6w7wYM*7GEEi7GE}XQQ^>~64JyyM9&ypQ zS#e|iHiT5Z=M}yMHqVm~Cgn>%agQt7#0ci3v@aVCcv@xt$}uHz9$%R3m_os0fb0RB`v8#PI>`hp}DR z31Z^Oo+n%wx&w?xjV1HE_M{l?DfdN5g}sqGCz<-F^K)9ypSLMm-5|-u{hz-h7^>W1 zY;J_Vltj)TB;cCt_gKB>eFs+(`xnY$zjk*bfS~{^KlORhzhJJ6e`R>HuyE6smgV(p z#$y$)uJx=1fs`a&?epccAjozk3c=JkK=#H#cDyjYsA%h%3RcV4)tAxHd3l)PF98_V z^KDDxT`uDb2v%Hov!_3v*^KDPg4dB!p5nujl5GFf@2I_IydrQNP<*E(+y$p_+Vz9< zvFk^Ow86>4(PgEL^2*SMY$2I*nAS>bYu)!4aaGLvG$6PA>6{K5Dea7IgPQpT{#2ZQ zyMWH5qAlF5-K_fhdNzfpfy2@wZKq?{Klptk#@vcM5)KI@2f9N4dv5!DR`mJf$I~h* z{DgMiBlWaT?aRLc+g${I6)o}(G@y*}c2dN4DmBdR5AH4jxJvele4{r1)uPF zh@+cAh*HW&D|R&P>zgOeCL z8Hr?Vvx`ZvaaJQt@)pfBIs4PMZm|$|4>noBH9`^b{ivu>0k>H*bMuScAGC)Vx`msY zPW)31&Le%a@n2V2WSH^r^cYOk1V+zG0(PrTZ`!2S#d>aD$&HSVw3;%aHgbu2cZ9@b zeNZEZpFlcm5>*l|v#^k<*4x*j%8OO>d+g{Abob92rq*sW<>KOWt>i#QWJ%JIUP>ST zKFeW#fG;i{FnNwlK`7)DT0QnNDW`Df%#HO21sorr(}0nbLgxJ419XwPOeP5<8#g;A z7vavvmruQf7x*d@i_Lz~sGQCda^?%eRjTOYsd3PL-W{H#3YjTSs(q*}I$cg8glOW1 z!UB3L1aZo+y!`ao;l!sm=OatuV6f{pEe8kJ+?EnxwdHLO01UNziy`{M|yZt%QB!X_O5W|-LkS?$VlZUxhZWlSAU-pheuc5jpI5Xo(!$4bJ z?Ox{{+6EqO<&D|t3;{m`iMm55pt~=GibZn{kkBh1VPvmg@vB*V7J41d-=d|%|oFgs*sM)p*F2X@!=T7qhrB`=871jg^ynj zmBiA(Dp8+&)#AxqLPb{A@*@7KbIIpqa*mk7-S~bu8Fwqk^EAg}i~)i;aqXCU`mM34 zAsW?Zs>e*k*;?0q%Vuzs^udSnFAH%rh&orQtxrOtE2NMzwhs9uv9W$gfPtItc;q?H z4SMzfm}{n(e0JMNjnR<31mkkh+AhlJtUuJaN90jNIL0sGIh;u#SgB-)E|mw_MrQUCX5T zj$ILN$VgB)vNOg7Z8!{iRi)kg=hbzFXJlwAHJPZ)Og@tfL>My4#qqrfSF^zMh?%an z;Iyajt<)f&(SB2besvq`enY7hmv%`pH_K7ObmL`|zU{glj|olRJD;*56$VBIMz2)S zHoTCw_gda^>zaoagg(q1db6kFiW4i|+U-Xx&J(w(=Bw}E;2k>eW4!pGZS#g+LOs&J zna59nFVy?%1B$A8zf$TIb&5Q2hiT; z!25vt`sQIc?6iiPaZ}&R0~;`D&1S7pH=$1lOzuk=F6+48;tzbU9AVM(9dM4})vZrQ z4*zY{j#$`v>%1j`3zW6&PneNDY7(JVtUfsnLW~`>dc1}_$QQGJ`0TTVwF{qXWS;p> z(d%-JIy`N%ATayGwMDS2;7SgU^TCEWZpJ1HwtS8Ns|*vxmH5tN3({o83&3PC>!eQy zs(|C^M9VjW!0(jw(lv&X^cH&t{n6kR*AoMK1TnMsDg|@`Bg$db=XmiOSb=q|9o|dH z+^ookbsEyAHE^gtjLIs**i+99`(uc-m1jhbqR^w)!{_+|-|Ge_RqnzgA&9~s3VRml zsHtkNq*BO*#siymqTkaky6$}Gwcy0(fBIstn%9UF zeM3oGjxtV?M#VZSm zOoW(z4`G%SBes=_M4ywR1t+;9x>g70i?c#+fowVoCMJ%8l8v$=@!{F>2P#8#_*Y{7 zc7%~xAffx_=e%6xMJ(z2SfPitVRvdbw87nQU`^=l31y&`>LC>}MVth-qUI*Em5nNA zQ`t`bUEd(tm@tRuY>_id+UsOU3Nx92XW;TTboYSqT_=h_4lR-lxyP!Q_|WGck_;`i zEJ5zDyWd!l1;$pJe41hR9Qe77w=FS|`2k<@5e*Pfli=;Rb>jS4{#Y+z_xoNmvCStl z_>9p@rs(IC1$deBj0LIm`2DLg4|bpw>=?fn@xFDt1D9 z;_WYUikPe!z3x|)+&hO<8>F!?o{!;$V?9wM-K(+P`Er%^IFyE_cj;_%lq&^ibs)a}2_mE**U%1K`8fMCy>IO`( z3qv~6-%_j3RB3GWuT#seN61t!{Yd>toau}bwY-gqOE@%JQ&%LIE@W8N`F^LR!$6V8 zZHVS9@wJ-eST8q&t;&!!mxs>CtSF|vp<{&B4*)hizDGlj(LuOZ2r5f@&P|H7Z3!od zzL#soh896Pzb_2AU zu;0svrK@G#VJ~LPdTrM>A`D!*Yt>!3IBkdx?^z`>fhbR2sXj$2g>f6Q*!w zbI^~Ed;y|#KS8DfFmav7U;VnJ*7~9b2f;dtSuOle?Ed5q5X2#4)oiaFKJRGn+jq8a zv??2?h`9L?xEEYP0+vH*ilbr(*l(*rkUhf0I#YSs3oWgK1ip3v-5cLglXafxj~Zrn zCpg^~w~~e3eq&jj;zcE;v5acW+VK=}C)uQcKxW(&7`RszdL8E%O|C93O9pM}o3#uP zQ(TUF8+2i*S|M%gsi!)$eO=PWlZ=sBS<56ugqQ-thTu3uTJN^^`1t5wyoM#qUJ4eE z7}SXQ`|t2AuG;a)4BJrk_Df2=)qB>Tem&!Roi{GMg^YzMvehVLTvYpE=c>cWi*(fo zy!?S4Ks&Tu(YBCD+KnmBQt6411S~kT@S#Dl*^CoDsMRPuJ+UV+46XRNw<`SxgE{sM z_a@0=B0e51LOgaWyYr3u)2jUOy-iu}3eB)}i69+6ESTskcdAtv*Q=5cNr}LqyzD|j zF+JUk^i=Yw2n19__tTc%3_VS8TR=h$LFC}-7ZOy^s7($Rz1-S*PSP8$EgMt`_&KY_ z;G(S?0>@yKXnDE#qC%P<+Kaj4djoKYChstULQF^97F8vguMX!=w|B0re(sQH>&xZ{1yyyoSA}B1w8Zyq=Vue`l$6?jsMAEMWAhL2C(Swm z9)S<@Lhals*X(%Yzqx@Hum$PP#=~O1_X_1V=3;ce*^|HXkK`5ggI48q<`Gqynx^UN zR~y1vqDiPNeM^X^T>1e@I)Ca2{Dj)5F88&KsdihBK?5v;IDoGvDd#elfrwhBDE6&D-zh0ig zNz#!`?n4Vt)M;^lh;ARcZaFzZgwA=o61L5Gm_2uKmI|nC8Pn`WMlb=QEh2~A;;c9# zuC->_DN^7HK3Sp0aDQ%Tu%0;*2>c#{he&NO9v=j`@%Fa17=_C@$eo_1jaJa?vt(E2txo=g#NR@U|bdJ#7?Brlwkz5?TMTv}!+7NA| z!d#p8>)?;C%Nna=vP9s$P6o46)R-0;Z&Z=HhZq>fbecCx16u`MF25CO{wRij<)2Th z03!Tp6SnUJpS66lTI_*mYzj_g8#Jl&ay$rZ?XQCk>ZL}brR``i59qb9e$NHh>fOSR za7BM!(*IB_Z#$dybd&cgO_{dP*=330dX1dZqpG4TxvwvAxEx(<^Q`Qnc;4m|XExzZ zHh`r^p$X&&LDXA0ap*hHTp{M~`otL_TP>Htky|qPkSh6PSX7Z$TdLY%{4nq8vdM-j zui(y{yw4IG&8f{~iWHFzPESe5(o|EFCYi{c!tp%a{8r(nOj|^+%jh7;A2L*yK5vsy zs#}?RZ+N8YPR!=b+y>V;XeH#f<+*jBsbCB~k?KbV0R8$0@PIPRE^LDjCO0$*%uGzhLRPHxmP4zs-jkgh%TAAG7;y*N$f)7swfuP4cAmxgp6 zTZ}X(Pu>z_c1(Z_;p|$Nsw4bA;^!QjvMqJfU#*l!<{%wcH5Yfml0yU0=zy`YPlY;7 zdqF+Tv*J=6PmewHt;jE4ta&3rA&A@xLrG(k9@+7nOH%4WK||Y;J*&iXZqy3KiPa X$az*g75DtFA}Hy%@)A{IAN>Cp;2uiq literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/sankey_chart-light.png b/testdata/snapshots/darwin/sankey_chart-light.png new file mode 100644 index 0000000000000000000000000000000000000000..706817aaba4d6f4ea9c9d95a95bc6bd1eff40265 GIT binary patch literal 13005 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 Yam4FT->-uFO$AC?QbD3h?6d!W1MJX%VE_OC literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/scatter_chart-dark.png b/testdata/snapshots/darwin/scatter_chart-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..35cea091b9d39e3ec1380d592b6ce7d81a2d6d07 GIT binary patch literal 13704 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/sparkline-light.png b/testdata/snapshots/darwin/sparkline-light.png new file mode 100644 index 0000000000000000000000000000000000000000..e17c6295e8e87aefccd0d809376b3432419f7edb GIT binary patch literal 2901 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 BXW9S& literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/sunburst-dark.png b/testdata/snapshots/darwin/sunburst-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..4c8c9f62c138add7dc21bbb706ff12aa3ba22b45 GIT binary patch literal 27106 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®+0C zLuFnDO6#gFshWb^e)eTbeOj775Sh=Mf^k|MraTZRxCQE zgQEjA70DDUfvCv*8458N`BfOwUCHMJN#9Mcr^+cROXc&h}k9RsnGxY{4@p7qOV^80D zUTk}iV-1iRH?yRPw~P!!Z#IK^Qpr)~s-cZG1svgPdu!X<`&t^lrtHZnau*VE6c_@r zh@LdWN7NsK?oB0aQNho^=U{@VtM;qeY04GAUi{B>-)zocL=00oCzMP~yfvT37Rl4n z+Edxu6LYdnQZ2U?kBY1|_+mu7vy=2!%{H}=>~xY;^_#ha3v@u8jvRy{|Ddy#D#ZMw zDs88|pF}_Rs23u%@X6KS_WAjhu^1OD_7fpiFIEViR-+Fd6Vsp+wylS!n%s-DNe3?< zeNxsmN5uqwftEWGV0me|aLBci-9TgOE7)~U%!%ifCHku}kyI&J^rpt>6HCZH~J)E09`P96+<6S+0XNh=zjI!+rR(E>)XJ0yh8SMT&wg2Flu3=Z;c^PBU{; zW4B5B*#<)m-}^M%SZDG$gvCft#zz^wDvoVvYaaJ!cdf224$VvY<+cBX$J@EtHdr|S zI1<2yEpx0}cEbo)@vf*eshX9Qm;3!z7!IIV@95YVP|>mQW8_75;+|8n`YG{uaxxZoR9&#P%y&f;CjO+y(Q$rw~uYgV7S zN0h-g>YSlVW&3c zv9f?V?3knH2U$AM?K(T7JLd1P^?$sL`h+< zl0&t+lS4K^nVcy#oe4-E#-b&PQ@-@_QU545X<(;t6?ECX6f9xZQ@($hphh(~L!qi_ zDs!_LZIZAi2;}WEkUzWP{kyb!Mlv%03A1!E*C*^J#U>U`;iOFn{j%%VL6vsFh)^f5p>oH_dGQXT?Fdr>Tw?G zu^v!n`%Wg?0ttWw%8;Cvqp$9PTT?q_L>PO{>q2I}4MO(|)BB75sfz*Mvo+gVg%BuD zL7l>`w*EChio$?mhVG5Oe*n2a+@AJms+Os~dVvOs&G`AYM}7`}UcZ%5I~#LHGU9MN zT{mkFJ`2@+*~wWc({05Iz5Cs%I1%SUsOWe=c^glGaIT7()Bsue>$ggH8wX%z#Ol{~ zc*(JH2DWD>1l*+2^ICngMox1j?NMQ~&AJQ^jtAb_uHp{6N&IZ-h`idi0Y+_#&AtUp zgjzh__4>S}f*N@hefgj+BrxAPf^ud*;p?=Vop!Loy@?jBeE{-@AwLXxl6DBuC~w;? zEb=mFEeJ08Alm*)Ez@0i{`^+AH8F8}zT9H;+Nw^+k-SW;hUo}P^Kvy(q;vfIHs>%` z-^`%n^aAR`mbOKlmVko;#tjFpw0a(%x7rWH)K;Zkjq-bzOpricW_R7L8kwNPAYTQa#_n z!Q^DOn5juGB64DLGXAP;hgTYfi?zPk3n_vErR(b$iQy&lsL0MOAFCSI!%f;9 z5j0zpMqEuKM?c23IF7&bR|-f=u%&=w zkM6_sG6cOtEaNjHK^c3%)r#<*_8>!isi58F4eFpx*l@Wkq+XRl;FQ)+CmN*SZ)(8h zY^y#I-9S3UsG6B305LB6k$i>xjXp^}gxt?YA<|u3sPE*FNCzWAuB1$7KRCjR(%-En zhM7CFibJNNzbR-+HZt+p*@fRo70T7jAqUY=Ak-!)(qhI!?LBAgr6^vm6~O8>P_b*# zQq=N+kKYYMrYDzAJ1#%zEr9LmU_kUi>iRCbUU6X;u~pc43EV1GT_xYGGVzh~`hRu* zdDJ->Notu^1?@h0Zodr<(PLD^g>!;BjX0C_V#NWRH|Xv@XEu%p;{CB-ILQ!gHd3v` zKouj>Qsr}%)-|3?SBQ>c4d#J{*t8Wg5DDlHeEuBk5PxBxSb3wc=#u*88o|Hb^FDd< zQy&=*ah>+@U6R=Ha+6V2M`s>0;_rq+q`yBD%|7}1_{^&8Jj9)Xo4ZzWn)y-H-s0~I uI`L@%4KG_YtR4~>EWJPS|6UEnRveiI~u>S$r(6eFy literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/sunburst-light.png b/testdata/snapshots/darwin/sunburst-light.png new file mode 100644 index 0000000000000000000000000000000000000000..297c87154c230bb56ce7a15a51477b56164abe54 GIT binary patch literal 26863 zcmeFYWmjBV6E)gcaCf(c-~@Mfcemg!!5xA_aCd@hLL{{GBhk-7i?V9_Wg zDx~V3d9rLPtD=De{d;I-9xJW8hzgUHPL%9JmfiONjDqh}ox!GKt7H>$V#S6NoGGPa zc^P?jUyxpYF^i^rij*frf-)bY683QUjPXSglt=?^D+EHNr|*!_iB4}pW*>z)c@rS! zyyIHEs_9zYC&*nYp@0-Zfjm5RumO(+pb3IY0$@qNfc}vGUwiO^R*<}xJg);f89CL= zGE|8E(oti1-ihF1NkPjSEu6dD#+VNpABOuMJn`tj4tWC&ouMmU+UAt$+OleDmcF7N z6{RixR;;#g~^?@Cos5eoZ+YVE=v9r8$AK-gOULY-D+PPNrE|$Xh$LoGmA3dQO&>m^xn~ zGZP+01Dupg4Sf0<2zh2ON68w6EqP|-P6_oz3}_e_-b~i^Zf{paRZEoZU&%lho+|Zp zc{NIJ4@I^V6qx8ABNqA^p2_DDKhl$qR&d*v^!l?9+j1iA&@fiKd}UpUkn?^tbd zYN|MS9**l=TU#TG8y*^JD=E2teUWdJk3-$;?CcAt`Xb-1NY(Cn!>yAG1;2MKyGMaC zHD?|5{(3|_kRZuojrDoi9R9Rx5jYxpOAQqtRtIeq>tJej+Do`(Zl}s)FGhvWahCVylPGK!a1H7Z+_J)*&Q_rQoYW$hAqq zt8$l;@5y1><mT)awTg++=d zq%LfG@N*PH6sOOBMp6dD?>$X zIosnK-J&4Y>(rh6vN}{s`yG`vK>Q~R-c7Ff3x2`=ikZ7!Bj=e;lkaK{1i%WuH}n7NH+Z(O7B^6k;4R%hE20fu@`jCrOmInoDi}Q& z15W%vnOZt(;>0(K86J_wn_ZWlBsC!Y;g#T(tINZw70k zhT*e{3Eq#Wr?J3bRo%h*{!AICN ziHo;bp(Ru8<8e$nKF}rc$4T|%*toK z(r|=n@*sCR#T_o3pMhW<)x`EQWDl#swTP8x*_lDtbewJH;My#Ic zO389TYHx0Yqvf^VTe&aT$PD*yv(ie^EQ?P%d0<6AkyZ=Z{f-X z)oSYgn$`Ks`hp9na598(D_Es@y7v25o_FXCs?yv1$F^*gvJ)s+;erowzi#96^Dj1c zdH2}Qn=p)V$VXv9@qY>%QmC}Y__ubc+lAmNcIMI3FRoqf8R_{~6=~lN8q6yhCckeC z(H!Fmn?cGZo6f8dtJ>11*Uf2y2Qbd78h?UGHtPoO}l|N3C4^JP(;7ubji{U;lMRDMhWmFMvJ#^Xrk zG~P^14#Q)o=8AUUOmTGapo%C#%q7sWdo0+>;vrJ>y)bF0m=9xu`pYyu z7|9?rt*p3|os?UfwwsYCK8P2qNt~i3O9@UoLAd9A7q>qoGi7Y2{>EI+hL*18^*>Hr zfy1(-!>C(Vw=5I6pDu}fw3@xOH}&+M4mjbxQOHj)E6zgM1voa45;$JgiJVvZ{V=vQ zZ1|8xN-3&g`=2^SaY&|;ara@QPhk+!_*{chc%D2By3WJ#t8{a3^DRVnbnrPaC&s#5 zU$bun|k3{zJUE(h2q3OQ>LtWe-zLCnGT-O z2r(%PikkUl)mR>l4k-E`X@N|YmUgSROP!&O?cd+sX|J7TcB=#t3B)r>p@3XyN{>0vWx_e zu!YjZs%J)_`FFqF-omfgncWiNIA@w3Dt6jMF?Yljpminn3g5WRuy_+|HxtU@GQ>@+p_-7jyVvbU=<{f4 zDU@c?uXm+&MJ`8LxI99)89V$@E66DdwP`m>wx_o(~GvbW!ITzUcx^ zxAe5?&KQ>4qz8A>^7pu%xW4_7z1s6OBWF7Ms*$_LxHI(rLBw^5sbu8agComgAlh z%N%|%mCP9@hrJ*9;nv=B7kiQ)$7_UD-TId|gaZmafhf-=^wj&Q|1@M^5R)0}Xu;IJ z%N&pNH;GQ_PgZU>yWg1Oi!gU4%Gnp5n(H`_UG7|=DV$t97P}D?9d*4OZJwRnY*p=r z5ah5kXv_)<*6zw(+DQnwmFjl4?*`6KknJq-^%qdqhc-rPpVvb^I#%g;4iGQYYD1jg z^{%^B->vnZ`TS|G=&)#m82M3xsh+-fZ?bYjb9<=MC)MwIJWtm`Lr#6u5%@H>$KrI0 ztfF8aQ$BX(ICWd)_j(!d%c1S;ZBjsGYpW`g@BMscY#hl;3ncXtx#@g&=j!!D*03z) zl>UIDk4Q{>?FC)cy6+Y_*!=`;qJ@`r7t94r6$$vWz~yok_=|r~5}!O-b+n60L{Xru;m8%$&;OGkMevCTN{W=8Oz5Q&gL8Hpkdo8C}e5hT&T_&xFTa|kNrR5MA zpMBMNB`$<}W+aXjftN_efYF7 zYJ;fL^TL2|wRBK-+lMaMSe*Pc6kpA7oenp9&eq?Luv7~fF*P^qw&CFJ-v+%uWHk6{ zvwsF%-Sv5+{rDL5=KW{BdsnbgnvibEwIWc4eVePCr_rcphBH`rzLLuAS2ny=IzbOz>Pw9~;&|%^j!+O3k%giR2w$H**u=%u|Q)a39m+ zarPb#Dda-A(X5)IxSKHH>Oru1&dfKw(6>6bJwqk+Q(}QhX85|AvC3MiKzJ(Z=C8pp zxmEu7lnkk==`y$JP!V0M4WHOj97-j9NX4W{1ksmNQN+YB#Nyac#awabmvZ*q5c@>z zE#SCWetBh`Z^opZb0LqLF0c_#_-yR+qe!Ai+Ed1&1Wo(`K(4*4Ts%*x{#+PaKt!Q5 zq+%bR@+hfkY55vg7>>J)+hSGbp=zL3WNwp&+E!KCm{-~;On0)h?egU}Ecr}aTc-J4 zv#H)>Z~we4*}~$_{t5Ag)gW^t$%}A7MO8(u1dsca^j_wzCGIZYq=Ch_^NX*hXwH~=Eql?e1y=`06bm)6oNNZ;AbI#<@ zoZD?UjQ)Mk3H6zPZMN23fu@?^<9QF$Y)-RHCFsedqo+ukImtwqu{BjsLs_2wP(eoV1-NZ&hlz*ScTKa4c-6p5b*K#@9 z1#==a^O77mWj+Lqy9<&0Yd5%(qeSaXGQ=lQ;qF2Y$*pPqMxWLQKYDVtU256@1g*~I zsy7toS=kh?{LmxvG?1Ph?;KBvheW6p=mn36c*z3`-r?$4~{~P;$DIN z=?nEJkQb}^^dy=?T8ZvS(LREKQ zfCLC^SzZ3gDf^K8jmXTB{^x#HOFz}!IAB`m-NA{TQ0pG0ks-X$u)!q&WA+#}+duH* zuUQ{(Btwe}fMUHdij@8<2+#3E(8HxLC1K3yPAlx0j= zGM-DrrxMQ!dm}OP+MG0{s!DszXso=bVQ)sY& zPnydBl0T*MPx*X`wLriE{8H>KeGh4Lh9IFR(lHVNNpJ5^CUz&~jq9NOv12wvqjV(Y zSbS3tQb>;elv*Tzl=E4pWV<3Ls!d9me|_UAa04lQ>8ey}ytJWlQ(05=?oIkHb2!i> zapW~tMYDY_j$T$07dR;CJ=7>K7BlDgUx~fCiX&g;-grN8eJtP4OQEKa5MpG>VDfPn zpKC?WsrBkzjsJlU6neH^=_&>xn;c$xRwy+^OjqpP!l*)j>1uBSc#z z?fJ8G!14eoWuV2T0=se&yR4XX(-b_L7@vSxfi14LWbdB_@SpTuY&hz^)hLR)EEfM+ zGSV7?Ejc@lgy?TEoIeBmt&Rvm)`v&Uk~bU`Q^qI>wV{pyEz@zee1`Q zCpz;C+ZzHcF#BhX@`q}R%Fto-JX%bsx3jS*2JJiYRLNJzAQY+4XP z*_tNe&>nbv%;rYI5BGmM>qF6pdPht#wzpQ=0T&h~=p7VS@p@U447zXL8MEOQ1`& z=8&bo;MG0#e*9YnV9-E3J*7L$v~)r6%iVH=7%B1AM+2w|N=fF&-WI(niBgKP1<)2a zLOw2XO@1U;alWs$vT%$=2EyeFyX1-qifOqVFwNrtGQv={k-_vYK@fo?xl|!W_btb1 zVli{>UxhgmZhZ*~`ZjH&IO`eNDBIjL9^in9_@7Hol1*pzP)!U!iY(^Y!gD_XFm6nO*EQN}gM(u#UtNX-DQMN) zH7AMJwCjRXLx4Z7fp0Gh^LHB;>MvLNU%a5@7yfOC0fKm%g1w*cLS~E@iyOZM(L5DS z;(O|z#){Fx#4q}8N$#!bj;dGT>FCgfbcl7}H;;x(KfByuWeR09Y_l|WdTv|B-$t(< z)ZxfW)c77e!u{=hF@ky4Uj~$=wC&hUOT->|v#J|N-~ED6LnqA46&sh;t_w1Y?R)nQ zRR+7&rh?01@!gydZm@{gMyBVAP8O2V_zZ?tQ#}_71FmpwU7|Rnmij{fq9!8X{z2EqaRPI6KB)G5AMu%0x#@DUV1FPB8qkhk3pdc}$cupV zl;2D~nzK8#F}eCky-GKsn4<+mD2{YGG6@GAK@(nphYQZ z8K5V-gSyJ`~;gceSj)2CtDY0E4T70Jj|QKu`QxkQB& zbIL<|TlDbSd;7D=#lT6;RePij zh``JX$(6umTl6_Fam@Q}gq>mAlXpeL&uqgAR2mwE|9LxP!G0C+PMd3O!CnWk{O>`u z*f0%iaeYQsKFnTBLTLOM3niu4BKCu80^ckV=tWfUN8KSrhr?d%UV~)MIyXgHlgY~1 zP1;{d(#~a{P6Cx!)=S&31ZmJ%JP3s4CB?Qfrp(D8*k_aYTU{Pk!@IxNR;+HxEO4i% zyZngEd0QzJLK9s-AHk6qVIl}Q`8%$dZc`I$HkWbbXd#U`cl$>OOub>E^K%hnCW=e;|7r6yNo?Xp zc~CjFiK7eV!g$V+CC6gfFD0$5Irzi{fmStTL6pmjGZ_Tg3Rw^VUC14RiO+-Jmtbq# zi$0+~dSd-CTF#s)Z50Dgu297l0eMCV{nZC0mW{^r0!|4R!;PAVRj=7dBUW|Z7u!>H zJ*R|CJM^I+7ZucW_lI2)pjZ6-Trz^}dz9YshcwohgDc4$)lv+W@!OvCr({%kfySP@2nbocMa zECPuXn*W3m5+sTvZpaK`1*XP>mOPFzm(bMGSD+N6P$kjJsjIBA$OHNjmmICtK+*Wa zNW`|$q%Jeh_Lu?=f%@Ji`W#f@=f+T78j(+`4>dzSZV%Q!x*!iduv~|v7M{X3-MMn$ za`Bq(qw*-EQN5v8Uj#o`tTqmZ8oz_W0e&0&eO#kp1rfRA36MmtXCgQX$MaiflUf2lPhn2L77x- z@lU^(ZChk-Z_^8%Zf&f5wO7;^B%Sw8B?Cx!3~)4&+3Se{NW$L7nm7pN`rhW2q8th zgs4260IJcj%dPmUt$13;t5Od{OUwT3cQkRK$>C=_?W_*zie$--8P3HO6N?5Condx?;`FgMq>Hp8UXm#1$#7eL5|KR z;$xfTg)Bq0{m`pO$E^8fec0>jDCiWLTm=p3qd4s(e#hyjSL2*uA%QdMDi6G0n=A`+ zBB6cszRI01Da1rB+zH~*g`1py)w_{Vv{1G_D;;V0I0L>e{+`gHgyS7c2sipv;`vi) zqkHyHBWc)o#0w?_F%yPR`#=DocfV3u!VF$0R!kt2xq%BUu9bbf`UF4Or?1vt^Y*2w z);au)|s-2OBAvArEwmZaAEC5t?wleQyb+Zf{ggH4zMKs3RA9A%idh1+N<4 z+GX4vv21h<^si>;dmWP|drtz|eVF0~TR$A{(SZRh>ROC#?h)w&?DKk8f(U0t7*nva z;u@by;>CeNVapjowozq;ab(VvDG|Y-JXbK%l<42idRfk^cPk|6$sx-GlFQtcVuN6S z6J9+kg(NbmOCc+)kQo$=|MPpzv@8;=QZl%Np5ir}FbakWP*(Mpu-~*M#p6-hw6-sN zia%i$02uu?qIWt3<$mwX02YcSzxGmRu~(FIN*2ej;gz^s&BU(P@Zmj7M&HLu1+b1_ zJC^zT$L*{k3(?bnh46_RaiCOKFbF1qd5QaW{p|htk`ublQy$LToA{I5*qe8d{+glF zU5*Arsc}@*o78L7tL{LyvN=EPk|g$Dn}q@Tf4A^(*{w^0vMEykzOXu#+?T$x5^t|B zHQr%mXYo7`uuGvp6jifH3pV(D>Wz=Fd)>-i&R9fO{V1x}8fWP5|eeEu5)tAXx!=Mr|)d63W1A-2hbx-`^Isi~p9UMERe;YLVK?<$6Q5+$Es-fA*)jkvBz|FZwyG8Vr z!fIax`QZ#9y=6DyeOgN_W^R~g57S;bNMF9{xe#FgHGy|l@zhx-4hZ;;*`OBPC(en4 zzxml#M$SK}4l9zt>Pko4@yl*LKp{sdx$l5eE~nVo(&+WL5NLWN8B-4G+Y~PXx`qY6 zpL>}Xl-t{yF%6k|4rXQMOV#wrLgOFe*1Oi{v}MBrsJtFiNk-BpRKNhin0`c3k)3*% zf;Hx4&_Bn_P;*q#xTyk3?y{nrQ{8;*Wg$b1 z$U_z#QX~49l+#Yu`{D~S=@7*32AtQV^=D>dGZPwS`*^zh%u|BNRviSKsM%_Ey_7(j2&-hCxl}Q)Z~tB8a9HcCedTpKIH)y6Zp89_xY3Osy4kQ z$~B^^NV7}0x2Ay@@H!M*uG!(6=32#3_v(`dg{`PX+&M~gZ?!FoJ&bUifrFXRm-Q)J7LCU!gzE2`>1hej0{ej9(xmiWM z`80(XCV(@+XT>lQkkQx$K$yIxdw9nXrAJPxf198mn3UFpqLR+s8bisGm`EJ}@Oyh{!!e>YeP(!v z8D0eaXo}%Nli))XL$b65PG#RFTO&+?<5JIkNmyc#DN!f7IA?wR8;Cevk?xV^(&3=g z!B`JM$jkc9#>M!hmk@tZmOfmTrV!~Tfpl12Hbl>+7mo_tjz(N)5~Hga@!HjKjb${t zE1ki|l(B*>*QAB1j)~YYU>*`!LSfzSP{PeCb+t9d!#U%sf{NcNL_)O1-u0ihKksZ% zs^$vR*>g?gd?hJq9TWM^TJdInF8e*Nb(+_ALzzbvj4XnrHX;nhNOg8TtQj&+zCMA) zEV5?C@(FkgY-CCpkY_e#ovwa~jMXt_B;6AXY_P4{1aOL1~M_L_wks@Qlsd%M*yH_cn2smVLH9&QWsO@eDU!lDK@cGjcv@ZGUo)e!BHka~=E<@Uc-Aj~JVU5>42> zr4i5X^bSq5=KU|#Z)yO4q^9z3;vEQ{b3R~zu<$U|y9-f;r|P`8b1!v_CJq7HwPHW@ zwn-?-V%O6T09kF;rj(p8JO;f&m8XN*P9fRTe8D_Hyic(hCC-eT!HQo2H0%A13;bTi zeW#wcuPzy9PacIgj~c~Y>O;y@snBq$+L_T|vDJQ_4nCg3mu(Wa>PuFW-a6`*prvZZ z@n$8|JmAaFdd%+*SX#Qp%PDv&8%MXsUSj)rvA2MTlQYqpJqVsA{64xxIek+DA_zdF ze5yZTzp9?9jej2U z1^o1hnD)w0!g5@+jR=yx{bPk`+hRyiy$~F3BpKhl&;z8zwGUqDD2OlYw88Zyz2% zD-boCkbA~D?fy*}69z(*9MIjF^6FFY6Xt~qL+X+eYRBf0;ucjsqhadQMqym9`*;M| zt0CE7%i@wl?v?2CCC7_PZWjZ@y^CS{A{7WIkjp^tOE!wMamVC}GXF!$GPlPJCJ9xD zoOppREB;_a`>C#?LEzXizQNjjBG(YNj@k1el)-w5;`*WY0z>j&0|P@Fa|{6LS9Ast z_9rIAR|@W~ZT0Re>xAUviC8 zCAz4(iQ?lSa~tNdcxVH6Vf-+tm>(%NIpxmb|HfwG-|wh#RJpCupNK&S54eBMFz$F3 zO+-U~`xT!<6Tut6e%zX|{F4gkX=Cw&^Mt%K0^(x>rN~x$+M@%Z%M-kG zy*8r-?d;zb3{VKcyj_*A`4|wTgY@eOLM6!6&X5wJUXNdRY61)3Hr5~jlH+58NJds= zqHV4SV}FxF{eV^_*1>6wcU%*gdX}1cWP7qU{nQ(4d%JTzFtab2XO1)9{b*k@4NpTi z37uzF(lK@R#T7EoXxJB|?i1aE^fww|LFJY1S=Qy@#;>r`YviNb$p5g?Q4Y} zq;P4IZ-2)t9`1*N0n+a1`;d&7L$o!Mi{I=2kC7n&Lw4;5P#Uue&?j$Yn&&9}5;ia{p6Px{p||9Nb?L+>vrB9Lf()pUIy$j(1Y>&9~j zW>(C0f5WxeoO+1A;+;&vNP6zVCc639koL1(LPNmiv8x&xckGH*-`DI`D2zElA#P@PK@U2a}$sRgTCzGYXQWdk&V!lS?TG2drJiHwA~6V+KH z2?w{&L*1&%sE_=t@25sDWmWP%Pv{%;FRvQ~PuY<)LR`mydEx)1ycxum5*?sUj zYYgHcIjW|L=?#W2_+IyD;;%i=MC|r|sjOs_TN#;~{^kblkZOVE3?&pkt@lWhbB@LR zD@D`4BVxTF;LBhV$a{H|8{3bVT~TJXX^9R-5eP~e8tc^!$|q8@fA?HomY9#+r@6{(u}S9JeRJ9xr;f3 zMEorx8cpnCx~Zg3N5*MvZnQjHD*V3kReF2^2XjS&%IU7_*?8HJn1sAo*4x>>XRq!_ z{mrzEf*Bm}$!)DHr|apckND-Vr50lFC;v2=CgbK{A%!tCZUcwMR}6ocRPgY3JG_O8 zZ#~{RIl-CMv-`PN?EvU*VpCfb5$=$O+2*Uap7|5G8j;P*;N|WepC!y+l^Ba^N~pOj&BPu^whIbCht9<$dWsq1P@;&* zXVFK;Ef{D0EyCzn@XHf4G!x3~7HEKGw#!F-B+bHs!Yk~Fp{nkJM5zEO-A-pNO7;)7 zqft@rhYu+@AySjFlj#||FKDs6Tn|${>0-e+_!uJQi z)sQQXz^5Dpia(m0k9+^h9voBS!Y6Jt=%_4eb+LSY z->fNzeD3plryb~fxOZb<`;Y>B_ou2=zHx+s7YU^hRL{qyO#gIRhHv}0^_f3uc z(pGI|EB<$U0ZmyIP-5WP@v*cx+YgR0&ayro^wx?A0xZ5Ry8;C5d>J5c^tYeduEuUG z`ZgZV>Kc(MviMige+^C&0iX=Hoi`D4g%>6i8ke04RDIN%&lCX4Dx1T|8c7ju2GSYX!argt#wD6laN4j*rKD@rAA=+b>%TzwyJEB>-fj969tiN~2L#s;DZy}riigJ3kR+4*NR85;zW;=d zfo7u4WIT(%*jd|PA{J*Vri`JK$irvU(NWh?M`3J)fzTbkP>mW`CMP9h4a_kL%?7&r zE@tiht7K6&Btj)K_wc|F!$@wQ*dB{%{6IwUgdQA|PmqUm!A!%S5!h1$I;`_Kc$YhN zkvr_B2w50qZx{&?1y}%1-Cjju{cZ^ zACW7PAjPjJ%m{V+J04y-=El}-<7X$(EUy`J>sSKOveG&^Xpl9PmHaeTCsAxtFS=xA zD86-9+eAcYMw*S|^FaovYM;@l|7DGx3Q0``C7q_m?|!V40|*v`h)@^ z?-B#K)oezR4Q9j*g@Gwd`eh*RiYlCP^eTMkc;s$|8B6e(Cwd zzFu4IEd>TnPTB+~N?zt9dQmgmi7WFSlPTN|x$keMh=Yh9I-Na=tOY&><8~nmi}lrD zCFC}&1^YnGZi%{WyMxGL+vx$nk_hcH`SqTc%U6_@P2FX#|$>s(iiE>7xI0b zM*sMFdwABNQK{PT)^nDZ7yta+X6G6Hy)^%!Rr@uzmWnaf2AkH)04E*cNL3d`YCX|z zX^Nhw)zmG+ehF$=u>h*4+2Imo%Fpw~ZZ}H>H-zHJJ=;q|-q7%3-j-)}=;}!Wr0KAq znW0Z+N)v_D@l5$X*^4UE1^pCiRT0s&!H9~r2-@)r`lE5z#^A7g$79O60Ol=ze(l=J ziBh~QDTf5!62C7i(Sf1Sw(idwBO~FarkM7a?R{6z2^qd?ZxqVPcgL03DTdHY0~5mJ zbEeZ*vAvX{F5^*!|IP1sdxGEuL-d*QzBI}Wh;oJ7?(tG~wzdbJBqB zRW26X5TEj2r$fX~Nh_zXxiX^Yr>XPYI;Sn)?su!PN2^rr4#{?PW?o}DSdgm@b)Vkq zvKtoGdA!bLnWcm!$r6AiIAlyg(881)=UlDwg323FHjibCPITcVV6Q?qzk-rwT_$RJeB?;+(oDT7KTe<3&p$7C?b$PO>ck?K;bv&G2UZi? zGKJDtj%nq%1?pTFnM@MiH`Jdb-Jy^Q1wo>siAqX~NmeYCd~t|`xqjv13w6Id(6rhM z`bvn~FmIFi5q)=e7ZnSu-DqIpLkB+<=Wpf5-J9dLrB)Ys35me`{7o&Louvj$+tX4{ zlZ(NR99A7PaorgNr0UXGoFNxNf!O2INPBjfl;&A@>` zL)Cd`Yz)HqnM|i41r+o$oPr-lT5OYbp_w0!b6FyUP7F7uy9;wX*-`z>2n(;ymI8v4 z33n~QX10HIXGkc*mDcAiQC(lxR}h|d+0{H)Oa)khX-FFuXv)xoc;7W38GdT}ujmWbw{Q#orc;EJ1K1+?? zw4W(Qo}FnWVB|lWzZvm^4-Z9HKNn2V2%5r`QQrvq-P0UAiIkrxKWPzHR1I2Hm(_w) zP^`AKqS4Q?-n?17(yHkZmkl%t`O;adWo}B5*fwlb_0m;{=YD~65|4k9xGsi@AC}qB zokEQ;IgK>C-L872pg42ByrWW9Mf!jp^fS4@GI^9{Yos)_#-2O~iBVSuVQFW6HpNU8 zd=eGHAM&4cP9P;K3L~(C&TIq1N$ccwhZ(4-hf*8!`?GEYl9-b;bl)DpFHF?Sn>^EL z%N;Q}1>w$?d+^-|b5eE- zry0tHNpf9G%D1Y829;9qj{@vuXsyEGgo%r4<^4$Sag<32ZfVt}E6K^8h$5s7T=dSW zJ=ugxU8;W_V}LV04#!^R^2kQ3uLkv-=8yy>9z=#(rn9AUVpaC{CM{xjp#Aw`<`_v} z1Fpwcs#GAEb~L0s=3=>YP=vL!WI9aI#0)|5+}zq3pC0wsZH>n0BRhnj&-Ye;a6iD; zm?UUekZga)bjSJ&2%01e>9-a%(pk#-8nP<+vTk$xScb36coJ|k{gsTpnuT*x8b!C> z&DHluh(=>oNKz1Lc;f>;Z||hJ{1$;C7Wcl5`5$zipwK4MJ+g@(#W9#LrsC>w^Reyn zEw#&?2AhdoCf^-RagjzW$8x?l1rCLQ!aQZ4{9tlzpnA!J6cgCvlzj*zg#wr)8QDL; z{=q0lFh07+L&n)X0SQ$uJU5JCA46XMwF88bIdzb|>Wlkr>VTEIxGa8p-0$I+x+i4~ zrqb2@1WfLu@3nE^2CvBO!&>@vy3i6o%O)Su_;ojQ5rENjR`p` z)5apBlsMR=`tEmhsJu*po`ewj_6R%18I%S3{@ z;b3EJs_%4b{f)|bX`Y8HbzigjD6tmnby0v=$(~_#X-Yd5-p5DDq$jMBMjbA`(eM-o*Q!+FXohD;vNo}4@ zp*}uVMLOeX&o6D~Dx;qtGw5yB*bc659M-u64quV;ESQtSYj4YoK7m{uJRS5KXnaki z?D&^db+teC&F&EH2D`b+r+@qn_pDBBb?^w)`a!{BG;)a&i6YNXkw}7r{I8vwa2%4cK_A)`>n<%g;UG?#(TjxB{F!VK_5V= zA}q3(kG2s%VRC;i7!&ZVK@#C@0!}5;RBs2NsPd;a7B>Q|@ zbjdw#Ivb4C*)(!U<*(4uJvNIJA0o*jfx!so{1(2ygbkZPRT@W|uWU)w;hW)maGyJ= zu91|8mVbt^&NCs*;Nkt3&U@7IMXIk8#q@S8dij9s1fK8JnGa#DJ~&=57ZVktL;PlhwcjlynwoWF z1780_l#yPz*7pz|OQle|oS0~1FDEp6UFEx9aTu(vtj6uamatFvuFledPOulm}E=v(_9#j9I~ zWkr^Q$qFUR@X_4Pq_hUbN;xfwPCGW@6Q^j&+g+~*rzG|R<%>CWA(a_bQ^(PC>x%k{ z1RT`VRu00FO-KSibhI2r8ZAmaCK+&4u*YRJ04S@Y0ykn84*e_Rwt7BYH z{k~M`gRJzyuq)++ycp=5t2rOW>`I+ciS z-4qW!uUnrEdp(HCu(68^L>j_4x*LinO ztvtuY75AOrMQJXM(DC_S7}wU1rj0bc6Wi*1&#{fkAUaTm$vqp^UYCaRX@?kdc)QEL zl6!!eCdIoVlFs_>0E}j{biMHhqX{EXr1iU^2qrE{d3+bSJoF9s8mc+CqgHDR3^iFU zf8)^<=s-v16Ya@$w}&51WB}ep`2;~Sk7~Kqf07VACdZWz#@K4&;6BVhL`CDg&GoqQ z)H60g|9I1g^UCY&u>KfR{OXcWV0WECD$MeAJ%g!K<8t072kl^+-Q1bi1JN|er>^;4 z-&D{hOC3R)*dCLp&L^q+%1c1oq_V{OdfSKb{Pq>sfU;^sygbbpzNqu!;z?7j&l^@u zDQg}7!)d^GJ;m{5sDDNp>!=LQ`v&IMc=7@FDk_RBP`7R5(|yK1Y6}RxO2Vn zF5_Bm zEd@6BmA^(+l!NoAiio*8x2v4&3W}a2nxr4i!u>+iS4EM+l3MHPuu4q*wL|dcnE`(W zLP+4@a|oML1y`wC8}fQM`MQWt=dR>nR9>1CAFm#wf(;*y0OLX=zSwZtM&M@%DHJOXDXt}@xVw9TLyNmZi@QT9!M$j3 z*HEmu7m5_kP2021y8qyw4>wus{gCYSX7AZE&pb2p&d#wa9|RHw`04i}esK4DGC4b3 z7U;$h0^8$a^(X|Q~#++E~U^jtc)wDoj8VgzgZ3s*{tJB5JR z_~3$S*O{cfSwI4|N2e%*bz9wnc9KT3Pr*QdYOV}mZ1O#cVjhHb#^fpZ^9nE$J)baJ9NTc_&ptl zfy)C1@l*xlHW7c2S(CmBQ zYE}Ktvs6NoUkL-uGzklxw^?NtOU)$=)T}Q?OkisMy(c~(rA8XSoJujFD&~0>4~xYa zjg(r8_-Dfe_w@PGeszs_=QH)0wpSe`VPB~zm(bEs^xo&v`gm_iPs??aCmYjJ&M5@_ z&*h9YgI1I^B9AosqXu_6Zq|awYArMC4YclA^vRm}dQ`*X*)uBTRs{As_e$kiG)_}0 zbW_~0qFj==JMv{)x^3}g2*0(r_@))N=IJ;azzbvMizfabcYkRqw;&oft<|qSTD_%) zeF&bt8_Aiv?IbcN^N@Ufz6kl$Ck8OpzMdXY5kDY*k#MrUOTG2wZITQicTkuCY4DZN zeEs4E`BH-Zrg#Eb?Y^a^oass3ak*vjF-RK9#Ry=QRMx_21SdTT0KNa}aA>>K+&Vco zr(vrr47EU@>Mqcjsgq%);wf{Xx|mFBeMG88Y~{29Mzun(#4jwl(3Ep>a-$MTeUmFTEkjr5q%+ka8>u){P#(4`w?@yPcu{kEj zG9lj7Et|lNF_!O0fdCpCg`tk`_g~UezAbxApE#pSN^qb}ziRxNl6y1m;K>Hy-7#UO zObWt1eb;_9oN#J0b#3qcU5(}P7vx}=A#0oHu}k}nYP?m8s2XowlU?@k;?Vc;+bcH5 z>Fg?E$M2l_eK_{8kLJxeDGzO4=xGf-pd$2;qaS=jSl;z|7NLSKHR*9quKF?t2XCkS zG-C>3EU2qXof}L1w4vC!rbq;0S2esCNfU-A(E9o_?G`XcyC`*Yv`GTS<3+DERqawEnnC5qV43 zNfcV&cGnjmyOhbh$C8lu*smctK_M50%et?ptNkbXjn<+O{B=mtt+ObXr5m4kJCjY7 zZ5_7Pej4=d$NXGFo&@i0?W8~jLa$x`2(?p|zrxzjLaz0n7~nPPrlwQJ-!K!ve~O@5 zMg@WWw34{kE^={i_EO*MF?gS6rlxqxTV1gQdv3lj552mG}v_>rm?Egcr&?U%7<1(U4_@7wT zjDw}Y71x;@LuGq=hRe<+We#E0J->P;BGSIUAhHS$sJTdwo!BlKyW8|?QrOj!@Vi(g zhzj{8d=d$0a$hIwspc=&uKg(CK%ivvLH=ns6x{s*uaCl{@)^gIv-g~GJUwtJIp)3F z%@8pv%8EA$W*QNrlam%@uh|d|%$LDT+enMV`*s|vwJn{gBPPSWu~p`fs_CVi3+jw*hJnCE32 zR>3BFZ?1O9H5MGh`qG+*HZ4^S1;?ZFvSc&4I+=i9^9{6`b5li1w{hFPHhxZxWk1&p zO(#zu62GlzF5#6RivM+cjexydpDc3X*M+Ff8Od>gNfsSEr{-#0l>Ixy+ zQGxGGn{8*Av1NGF^Z+^uVI9+HP2%LiF5rC^k#lL&wD*pFV6Vd5I~`M9 z-Qv2H=S%GV$(mX@j_Ok1CZh_P_c?^@<)q@WYi?tS6iOJty>&d>f1vhvc=l}5Sci&^ zh-x|oHEC&mEp$31v)OVfFi8L8Ne!b}u{`nU39R6=rcFg@4N{p`pEr0f50LfJ_cA{T z>p7>Fy{+ZDp>Tbq*k!NUcK(Gp!S(zZlZI)}LWKl<&cy1(pZvii8f*!|Ui#6HjE)ic zh?ICB@sBD19+@J3PbA*h;f&(+vUMhf@Rq_GUGvJf7b#@am2neH<(xNOY<){GI6o`h z2Y3cPE2{Y7UD{?64SWMps|Af}W9@~elI!lN_z7?`jTlmDKz6JymEQY9v~B|`B7CvN ze4z78K(6D$=pRggm9MK?&E*#h;vX}kLEHwLAL-wRDu5spiJvx#i0@UE<(n#p7K{q` z$YB0z{lDgCG0Y)vHMTEcLVq3DGKOmg)}cCAE#Z{`epq z{uvHBgy>&gZuO<4G?!DJD|aQmH+JP*(Q~guS-+pL21xQEd1@Q|wQ*K$?1?S1n)`B& zoC_rW%>UiV$+k#e@dbrk{}})9SS>_5ru|BFmhLvTizz1i<`#KE%98?RJ`JHemPB2n ztG{wX3+$sPj}lnal|s$od&M_yxek}(uUO>ODo7vTP(4pY?$sbY%p&XZ6XBmt9n|p> zfGqF4xGlClW+zUZ1;>a9pAEdS$RQZFlC$~?z^k-Rhu^rQI% z&NgIk{ru>qu=9+>I;r)xy`c9OJ{*Q4wMPRMK#v#teDQRuUG}v0*ciyJeo3H{Z@}9K zj()zkZ1}4-KeAq2xnD(5M`WxWGKa(ai0mnC^j{`AiH{b(9b6ZHFblMDD)fjFPS^2% z(IO3=uAR9o7OSUl=2x_QG7hlft>q1fqYOHrF%#&a74DSp(sNQO=+ZQ|r*3sd)Pl0A zoh$hlzEx|a>^AS>iU5DceS7l=4_l<5W&91{hn{Mnv`qqIIA#MI7r1RJ@DO2!HstmQ zW$RR+KemqjVdJ4h7ln+~@P_20guW8PGlWI}jhzM${MDTZ2CXn)L9!ng1jUE7+<>4U zMr_x#fkbBP%~@ifB&mec)qvl@+91iy%1C%gZ0LXZHTDNL0W@q{jjhVZGt!2_t_HPD zT4k#rqLlGM`(!#FIFhc4enxBk6DmEJ{E0?5_KPfkSy@6s>$TT zG@l;6 zC3KPAH-vdmk>|Owg`2P}(9ZkUa*D*4AL_H(DAjZY8Hs_8uCs$P6~b8HA!SqVEqH| zU_bFm?~3n(aNx{IbEBYjJj+Q^P{0F9^qmmz4}XdUk7zu3<1%ipqe2|T5ib#d?D3of zj{T&E_b${7G64GYXk#N@)+m|t+KH0CH?@{}C~ri#1?r1^|C@P}b#vZ2e1a!hQjH8w zEVWG|Bw&)~>PrP{TMPK@h!5aB%VX9#I%K;CnuT+j5Wpn;+0Gi4o&DK7az$xIJ9 zQr9lSu8d&Lo`swy;xye*O;@(R84NN(2|7TRi314|`_YngfHstC2-jl4vxi;ywbSaK z%*x;S{L6Lxs}THO^8Ekb{wvM>)2{y!X~n2O1SBKRoV8Y<_^D+}MhAn;_-nJ|f@I|cKe z#ud}yKMHFdUXR=OPK?W>;1Vz^ylivVfvhkeUA9CnTwRLYEUqk*OVWM>JqkvDjQxy| z8TeK%Cr;vj^Mlx0Q1guYzRnQe-qEMaUpsT1MqJZ_wh$r8~k`tTt@O-9{3@kX>O;gLO z4t2^S>^1{rcR2O54eFF8_=)4CPq{|vNS3G6TaSvb?e$sBHx0R{hjChKGn&13USHh} zG^Yve9mVgU85zaqbC=?YqoGSyctbLa`(4j)otyMnw{urbdZqnKJ7Tl(l7A}xh%bxc zn~L61p%NDqv^ni|NRuU@Jft+=9xRekEhK#K;G5|OELvbtTxMowTbn4vvi8(F7Tn`LwOc?Jz)oDwG#=XL>CM_Xgpa_lT%$!E3qCE zev&bqah>MHA4(}K%)ceTourx6Bwkb4RCuVfIMZBC?$^-y`c7bnr+uWPs`NPkgKf3~ zzZshVM7+&5dg~!m2@W0TB1~a0B9#%8sGZ3<=Lv}2u-u;OwI9KHyO%X_C5 zr|Xn|7!q5hYT}Yt{w>+XsCE!GnAerJmTMed1vH051m?fFYC0|IW2{qHLQFOvPT9MM znoI9JmJZFMsaowjCpVz0!Z>+ydwU1rBfu#ZD;$6S$1X=zsZ&X5I-ko6MDu{%95hS zC#rg5Fb+K!jTt=%Tu=y}99gor9t2l6d_H}s2>ohyDaE-E-(Bcnc1E_8VbzNG?Ed;C zN?S_z-#MNy3AwG}3-)Z7Z;pgz#y5-AAvOH(*L;HFWb)OPG*In7I)~${_@I)Cf{Oe$ z)Ae+6q7=qwB+r)HD8&8OeB!luHy2ps*%FlY&mE2&Ubf%T1r9Lxb4URA1o*e9N3;3d zXCtPGA$*Wx)hvGUUG{Rx{bE=vtgw^;;%j39HW^T57>OPMHv+T~%5fQtM6=bc(ml){D+U<#Ux;WTNM9`)CV6@>de>89?sF^91^0 znV6#7*{#_bTg_1EpiQ$at2zXM&qj;rN)teDlD}xd#s1Q_EtXZ3UncQHufw@bCSUOC zP9Cdm1HB=Bw6ZprPWeXjXwc1t5@9A$@XqHU;I z0CKOJz3^V*?Rg*Nv{m{dm+w&a((FozO76lqV47 z8_uNI3NnSEG53+LDMoMn{W~-agavJ037#7yv~CO?8t$E6rw#EDyrb)Xab5OFgGK0> zy0t5*yD&hCH0-UmRSA2N0)JXfBu{9!vy&4(0He=4NKa3H>mJGpvO+{zGsTj_2T?bG z$!Tjzk%FvdziTI(C%cji=Tgwv&U`&1q9mfEB(kS)sMU#YkXtBB!jvZfRo9rvZv$v+ z2IDL$joj>buX0fkuxpbj$6nR~{*;hLh)-%{*0XQF6yY!!`kpk9r}^>r)=|Cnuc8TF zU{wlJl@f_!k4bprmW%Qm-@umQ7H%|JobKC55iU03yJd};NK%MzhWc%Zfe|Iub(*()L$bh=vD7VnlIZm`T zdaAb_1r^pcy)Q>~b!hh)arF>7FC{nIa?BM-f?Zszn{ow}NM@(!flfqc=NDI4zu)2Z zjprY*u(IpGeB|Xk!s=#mVgXgjb0I;&C|7s)=$3+ll5vMePndHhe9WX;L?n7cc2V#J z4(55|L<+m%j~{y`9AB$iPaezb+wr$-6epmt&J;)1&D{^yiwW*Y3Oifc#SApIa*`{3 z8zK{Q>LG$CQ8B8`eOo@`6_{lUS5{Ifph5>d0(rr(t(6gEr}j+G;a<(&j{?!6UjVR| zg1y?>s~W0w7btmI`g_=lPDUp!hBGFXXWQ=*4^>80rc8_BqcMdpR^PUN!Np#m40M|= z4IXXvZIzv}p8ovIaXA`*1M1h|W4}AQIJ2N0c4(Qk;3CBbttEEL{)%twZtRs;tkL*+ zRQ1hS529NLF8%&}NoFdprRC-hKcV>3_Q6$6%_~?K4jr!uub;d~*Z9w$PS;0ndjuPF zPPt-}YviCY>RPlRiKU+%&OB>L=jBf}t9m=JM z%006yjTd3wlv+%K$t?)9bZ}>pwt~sI8Gcxvzd($#xIG77^+oE5zAII){n+-_dF^aq zN_0t-J;iw>jwWn5%V0|NkFQM6p$P)E6Y_`pR&J)j6kp&!`?h{kAq{yn9%AA=`J=U> zwWIw;(@@;d1(M`N0l)_A$}<4PvQ(d(?wuDcV3CAbd*<77uW>OVvuta#b+*~ zSW)Ol9+4w2iIRW@l*Rw`Nq4*GO})dSO}*)3Z@I6bXFZ3ssi_^)9c8U$HEr+8CrGH+ zo+Qb>@)!ZisWiXO99ZN9B+ zqndJo)_{S51r`>Da0w|Di&6ASmdGT^5mDBsNr;7orIxYzg{6ZwK@ncNN>?ym44S_7~bJJI_IPZzhZ+qmpO|n5kF(3xwBsC%3THo%j+4jA?hbu9@ z+u;Om4-IK@t~9u>)K@N|6anQ01vgT^8F8VoHU3lb+~Sh3>yZ+x=QLLkZItDh?)hXH z3LoefWVP%x^n57BvSdX+g6KiztY!7~OMTUwa%hDq3ZtmgIUQ$o@*7M&;S^UfV^v;R zA~j4;6AUU^fBw4i{mjr3G?EQsOK|}hf%BE$x&&v zT4rOTPH5O#yIAx0Yqb8wh#0jVVMiM>sWGwWE$~l{G1l7PF%6YEpghPnyz=pb-dDGp zqKHF7tia|fZmX1m9q!^HJYBCa<8@i>aj-d@am=6UyE}e27h_`T=M1Yo9V4TTN8Om- zX(I_#r09}StMqoGjk`>e_>Ck2i-O}ewMryYcBb0-6JHnX$jQAXESd=HF+6pzwL5rLiUUB+ZW{w7Z%=X~#{d&A^d=e{Rf2R)8KX z-Qyd$e7asw7h#Et^H8H_DQd^9c-^y0?mNE0_{jIjUbTt*@0^e;z=a#108%IvJ}Sh4)sSy59Fm)q`rWR0{#y?W9Nzh literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/treemap-dark.png b/testdata/snapshots/darwin/treemap-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..18f2d90dc0148fc109878615fdf83757bbdc6d6f GIT binary patch literal 15168 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 f8z=OX{Q=4Cqru%>f;#~k4bYe0 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 0 { + kids = append(kids, ch) + } + } + slices.SortStableFunc(kids, func(a, b ChartNode) int { return cmp.Compare(b.total(), a.total()) }) + sum := node.total() + values := make([]float64, len(kids)) + for i, ch := range kids { + values[i] = ch.total() + } + ch := newChart(c, opts.Frame) + tiles := func(r ui.Rect) []ui.Rect { return squarify(values, r) } + spec := chartSpec{n: len(kids)} + spec.readout = func(i int) string { + s := fmt.Sprintf("%s · %s · %.1f%%", kids[i].Name, chartValue(c, values[i], opts.Format), 100*values[i]/sum) + if len(kids[i].Children) > 0 { + s += " · " + msg(c, "chart.opens") + } + return s + } + spec.pick = func(r ui.Rect, x, y float32) int { + for i, t := range tiles(r) { + if t.Contains(x, y) { + return i + } + } + return -1 + } + spec.activate = func(i int) { + if len(kids[i].Children) > 0 { + *path = append(slices.Clone(*path), kids[i].Name) + res.value = true + slog.Debug("mujica: treemap drill", "path", strings.Join(*path, "/")) + } + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + for i, t := range tiles(r) { + bg := pal[i%len(pal)] + p.Fill(t, bg, 2) + p.Stroke(t, k.Surface, 2, 2) + if i == active { + p.Stroke(ui.Rect{X: t.X + 3, Y: t.Y + 3, W: t.W - 6, H: t.H - 6}, chartInk(k, bg), 1, 2) + } + // Labels show only where tiles have room. + if t.W >= 36 && t.H >= 22 { + ink := chartInk(k, bg) + chartText(p, chartFit(p, kids[i].Name, t.W-12, size), t.X+6, t.Y+5, size, ink, 0, 0) + if t.H >= 40 { + chartText(p, chartFit(p, chartValue(c, values[i], opts.Format), t.W-12, size), t.X+6, t.Y+22, size, ink, 0, 0) + } + } + } + } + r, plot := ch.build(spec) + if plot != nil && !plot.IsDisabled() && plot.Shortcut(0, ui.KeyBackspace) && len(*path) > 0 { + *path, res.value = (*path)[:len(*path)-1], true + } + res.Element, res.Point, res.changed, res.retry = r.Element, r.Point, r.changed, r.retry + }) + res.Element = wrap + return res +} diff --git a/treemap_test.go b/treemap_test.go new file mode 100644 index 0000000..4abeacb --- /dev/null +++ b/treemap_test.go @@ -0,0 +1,89 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +func chartTree() ChartNode { + return ChartNode{Name: "Abbey", Children: []ChartNode{ + {Name: "Library", Children: []ChartNode{{Name: "Psalters", Value: 30}, {Name: "Maps", Value: 10}}}, + {Name: "Kitchen", Value: 25}, + {Name: "Garden", Children: []ChartNode{{Name: "Herbs", Value: 12}, {Name: "Vines", Value: 8}}}, + {Name: "Cell of a very long-winded brother", Value: 3}, + }} +} + +func TestSquarifyFills(t *testing.T) { + rects := squarify([]float64{6, 6, 4, 3, 2, 2, 1}, ui.Rect{W: 600, H: 400}) + area := float32(0) + for _, r := range rects { + area += r.W * r.H + if r.W <= 0 || r.H <= 0 { + t.Fatalf("empty tile %v", r) + } + } + if area < 600*400-1 || area > 600*400+1 { + t.Fatalf("tiles cover %v of %v", area, 600*400) + } +} + +func TestTreemapDrillAndBack(t *testing.T) { + var path []string + values := 0 + h := &chartHarness{build: func(c *ui.Context) ChartResult { + r := Treemap(c, &path, chartTree(), TreemapOptions{Frame: ChartFrame{Label: "Rooms"}}) + if r.ValueChanged() { + values++ + } + return r + }} + tt := ui.NewTester(h.view, 560, 440) + tabTo(t, tt, "Rooms") + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != "Library · 40 · 45.5% · Enter opens" { + t.Fatalf("readout %q", got) + } + tt.Key(0, ui.KeyEnter) + if fmt.Sprint(path) != "[Library]" || values != 1 || !tt.HasText("Library") { + t.Fatalf("drill path %v events %d", path, values) + } + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyEnter) // a leaf stays + if fmt.Sprint(path) != "[Library]" { + t.Fatalf("leaf drilled: %v", path) + } + tt.Key(0, ui.KeyBackspace) + if len(path) != 0 { + t.Fatalf("Backspace kept %v", path) + } + path = []string{"Garden"} + tt.Frame() + if err := tt.Click("Back"); err != nil || len(path) != 0 { + t.Fatalf("Back: %v %v", err, path) + } +} + +func TestTreemapBadPath(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("no panic for an unknown path") + } + }() + path := []string{"Nowhere"} + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + Treemap(c, &path, chartTree(), TreemapOptions{Frame: ChartFrame{Label: "x"}}) + }, 300, 300) +} + +func TestTreemapSnapshot(t *testing.T) { + snapshot(t, "treemap", 560, 340, func(c *ui.Context) { + var path []string + ui.Column(c).Padding(16).Children(func() { + Treemap(c, &path, chartTree(), TreemapOptions{Frame: ChartFrame{Label: "Rooms"}}) + }) + }) +} diff --git a/waterfall_chart.go b/waterfall_chart.go new file mode 100644 index 0000000..e7bf0b7 --- /dev/null +++ b/waterfall_chart.go @@ -0,0 +1,125 @@ +package mujica + +import ( + "math" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// WaterfallKind says how a step's bar is drawn. +type WaterfallKind int + +const ( + // WaterfallDelta adds Value to the running total. + WaterfallDelta WaterfallKind = iota + // WaterfallSubtotal shows the running total; its Value must be zero. + WaterfallSubtotal + // WaterfallTotal shows the final total; Value must be zero. + WaterfallTotal +) + +// WaterfallStep is one bar of a WaterfallChart. +type WaterfallStep struct { + Label string + Value float64 + Kind WaterfallKind +} + +// WaterfallChartOptions configure a WaterfallChart. +type WaterfallChartOptions struct { + Frame ChartFrame + Format func(v float64) string +} + +// WaterfallChart builds a total from rises and falls. +func WaterfallChart(c *ui.Context, steps []WaterfallStep, opts WaterfallChartOptions) ChartResult { + from, to := make([]float64, len(steps)), make([]float64, len(steps)) + run, lo, hi := 0.0, 0.0, 0.0 + for i, s := range steps { + if s.Label == "" || math.IsNaN(s.Value) || math.IsInf(s.Value, 0) || s.Kind != WaterfallDelta && s.Value != 0 || s.Kind > WaterfallTotal { + panic("mujica: WaterfallChart steps need a label, a finite value, and zero for totals") + } + if s.Kind == WaterfallDelta { + from[i], to[i], run = run, run+s.Value, run+s.Value + } else { + from[i], to[i] = 0, run + } + lo, hi = min(lo, from[i], to[i]), max(hi, from[i], to[i]) + } + ch := newChart(c, opts.Frame) + k := Tokens(c) + size := FontSize(c, theme.CaptionSize) + var step float64 + if len(steps) > 0 { + pad := (hi - lo) * 0.12 + lo, hi, step = internal.Nice(lo-pad*chartBool(lo < 0), hi+pad, 4) + } + val := func(v float64) string { return chartValue(c, v, opts.Format) } + signed := func(v float64) string { + if v >= 0 { + return "+" + val(v) + } + return "−" + val(-v) + } + geom := func(r ui.Rect) (ui.Rect, internal.Band, internal.Linear) { + plot := chartInset(r, 52, 26) + return plot, internal.Band{N: len(steps), R0: plot.X, R1: plot.X + plot.W, Pad: 0.3}, + internal.Linear{D0: lo, D1: hi, R0: float64(plot.Y + plot.H), R1: float64(plot.Y)} + } + spec := chartSpec{n: len(steps)} + spec.readout = func(i int) string { + if steps[i].Kind != WaterfallDelta { + return steps[i].Label + " · " + val(to[i]) + } + return steps[i].Label + " · " + signed(steps[i].Value) + " · " + msg(c, "waterfall_chart.running") + " " + val(to[i]) + } + spec.pick = func(r ui.Rect, x, y float32) int { + plot, band, _ := geom(r) + if !plot.Contains(x, y) { + return -1 + } + return min(len(steps)-1, int((x-plot.X)/band.Step())) + } + spec.draw = func(p *ui.Painter, r ui.Rect, active int) { + plot, band, ys := geom(r) + internal.AxisY(p, plot, ys, internal.Ticks(lo, hi, step), func(v float64) string { return internal.FormatTick(v, step) }, size, k) + var xs []float32 + var names []string + for i, s := range steps { + xs, names = append(xs, band.Center(i)), append(names, s.Label) + } + internal.AxisX(p, plot, xs, names, size, k) + internal.Rule(p, plot.X, plot.X+plot.W, ys.Map(0), k.ControlBorder) + for i, s := range steps { + a, b := ys.Map(from[i]), ys.Map(to[i]) + bar := ui.Rect{X: band.Start(i), Y: min(a, b), W: band.Width(), H: max(abs32(a-b), 1)} + col, shape, text := internal.Palette(k)[5], 1, val(to[i]) + switch { + case s.Kind != WaterfallDelta: + case s.Value >= 0: + col, shape, text = k.Success, 3, signed(s.Value) + default: + col, shape, text = k.Danger, 4, signed(s.Value) + } + p.Fill(bar, col, 1) + internal.Marker(p, shape, bar.X+bar.W/2, bar.Y-14+(bar.H+28)*float32(chartBool(s.Kind == WaterfallDelta && s.Value < 0)), 8, col) + ty, ay := bar.Y-22, float32(1) + if s.Kind == WaterfallDelta && s.Value < 0 { + ty, ay = bar.Y+bar.H+22, 0 + } + chartText(p, text, bar.X+bar.W/2, ty, size, k.Text, 0.5, ay) + if i+1 < len(steps) { + y := internal.Snap(p, ys.Map(to[i])) + p.Line(bar.X+bar.W, y, band.Start(i+1), y, 1, k.TextMuted) + } + if i == active { + p.Stroke(ui.Rect{X: bar.X - 2, Y: bar.Y - 2, W: bar.W + 4, H: bar.H + 4}, k.Text, 2, 1.5) + } + } + } + res, _ := ch.build(spec) + return res +} diff --git a/waterfall_chart_test.go b/waterfall_chart_test.go new file mode 100644 index 0000000..70c9b7d --- /dev/null +++ b/waterfall_chart_test.go @@ -0,0 +1,54 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +var waterfallSteps = []WaterfallStep{ + {Label: "Tithes", Value: 12}, + {Label: "Repairs", Value: -5}, + {Label: "Q1", Kind: WaterfallSubtotal}, + {Label: "Alms", Value: 4}, + {Label: "Year", Kind: WaterfallTotal}, +} + +func TestWaterfallChartReadout(t *testing.T) { + h := &chartHarness{build: func(c *ui.Context) ChartResult { + return WaterfallChart(c, waterfallSteps, WaterfallChartOptions{Frame: ChartFrame{Label: "Ledger"}}) + }} + tt := ui.NewTester(h.view, 520, 420) + tabTo(t, tt, "Ledger") + want := []string{"Tithes · +12 · running total 12", "Repairs · −5 · running total 7", "Q1 · 7", "Alms · +4 · running total 11", "Year · 11"} + for i, w := range want { + tt.Key(0, ui.KeyRight) + if got := chartReadout(tt); got != w { + t.Fatalf("step %d: %q, want %q", i, got, w) + } + } +} + +func TestWaterfallChartBad(t *testing.T) { + for _, s := range []WaterfallStep{{Label: "x", Value: 3, Kind: WaterfallTotal}, {Value: 1}, {Label: "x", Kind: 9}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%+v: no panic", s) + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + WaterfallChart(c, []WaterfallStep{s}, WaterfallChartOptions{Frame: ChartFrame{Label: "x"}}) + }, 300, 300) + }() + } +} + +func TestWaterfallChartSnapshot(t *testing.T) { + snapshot(t, "waterfall_chart", 520, 320, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + WaterfallChart(c, waterfallSteps, WaterfallChartOptions{Frame: ChartFrame{Label: "Ledger"}}) + }) + }) +} From 3676cfc2c5ac67d2b29df132852543b1e5a2c345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 5 Oct 2026 14:35:41 -0400 Subject: [PATCH 11/13] Calendar: components 421-440 --- agenda_view.go | 149 +++++++ agenda_view_test.go | 95 +++++ attendee_list.go | 4 +- attendee_list_test.go | 82 ++++ availability_picker.go | 180 +++++++++ availability_picker_test.go | 108 +++++ calendar_day_view.go | 50 +++ calendar_day_view_test.go | 79 ++++ calendar_events.go | 66 +++- calendar_month_view.go | 248 ++++++++++++ calendar_month_view_test.go | 171 ++++++++ calendar_time_grid.go | 369 ++++++++++++++++++ calendar_week_view.go | 80 ++++ calendar_week_view_test.go | 175 +++++++++ countdown.go | 103 +++++ countdown_test.go | 69 ++++ cron_editor.go | 346 ++++++++++++++++ cron_editor_test.go | 136 +++++++ current_time_indicator.go | 51 +++ current_time_indicator_test.go | 79 ++++ docs/components/421-calendar-month-view.md | 57 +++ docs/components/422-calendar-week-view.md | 58 +++ docs/components/423-calendar-day-view.md | 53 +++ docs/components/424-agenda-view.md | 53 +++ docs/components/425-year-view.md | 52 +++ docs/components/426-event-chip.md | 47 +++ docs/components/427-event-editor.md | 49 +++ docs/components/428-event-popover.md | 52 +++ docs/components/429-current-time-indicator.md | 44 +++ docs/components/430-recurrence-editor.md | 46 +++ docs/components/431-availability-picker.md | 49 +++ docs/components/432-timezone-select.md | 46 +++ docs/components/433-reminder-picker.md | 45 +++ docs/components/434-attendee-list.md | 44 +++ docs/components/435-week-picker.md | 47 +++ docs/components/436-duration-picker.md | 46 +++ docs/components/437-cron-editor.md | 51 +++ docs/components/438-relative-time.md | 42 ++ docs/components/439-countdown.md | 44 +++ docs/components/440-stopwatch.md | 44 +++ duration_picker.go | 100 +++++ duration_picker_test.go | 87 +++++ event_chip.go | 17 +- event_chip_test.go | 125 ++++++ event_editor.go | 171 ++++++++ event_editor_test.go | 112 ++++++ event_popover.go | 114 ++++++ event_popover_test.go | 110 ++++++ example_calendar_test.go | 262 +++++++++++++ examples/gallery/pages_calendar.go | 45 ++- examples/gallery/pages_calendar_code.go | 253 ++++++++++++ examples/gallery/pages_calendar_parts.go | 217 ++++++++++ examples/gallery/pages_calendar_time.go | 128 ++++++ examples/gallery/pages_calendar_views.go | 194 +++++++++ internal/calendar.go | 9 + messages_calendar.go | 195 +++++++++ recurrence_editor.go | 223 +++++++++++ recurrence_editor_test.go | 133 +++++++ relative_time.go | 75 ++++ relative_time_test.go | 83 ++++ reminder_picker.go | 73 ++++ reminder_picker_test.go | 82 ++++ stopwatch.go | 124 ++++++ stopwatch_test.go | 63 +++ .../snapshots/darwin/agenda_view-dark.png | Bin 0 -> 26814 bytes .../snapshots/darwin/agenda_view-light.png | Bin 0 -> 25698 bytes .../snapshots/darwin/attendee_list-dark.png | Bin 0 -> 30519 bytes .../snapshots/darwin/attendee_list-light.png | Bin 0 -> 29369 bytes .../darwin/availability_picker-dark.png | Bin 0 -> 7875 bytes .../darwin/availability_picker-light.png | Bin 0 -> 7630 bytes .../darwin/calendar_day_view-dark.png | Bin 0 -> 32359 bytes .../darwin/calendar_day_view-light.png | Bin 0 -> 31078 bytes .../darwin/calendar_month_view-dark.png | Bin 0 -> 42135 bytes .../darwin/calendar_month_view-light.png | Bin 0 -> 41092 bytes .../darwin/calendar_week_view-dark.png | Bin 0 -> 46786 bytes .../darwin/calendar_week_view-light.png | Bin 0 -> 45395 bytes testdata/snapshots/darwin/countdown-dark.png | Bin 0 -> 5897 bytes testdata/snapshots/darwin/countdown-light.png | Bin 0 -> 5826 bytes .../snapshots/darwin/cron_editor-dark.png | Bin 0 -> 35900 bytes .../snapshots/darwin/cron_editor-light.png | Bin 0 -> 34297 bytes .../darwin/current_time_indicator-dark.png | Bin 0 -> 858 bytes .../darwin/current_time_indicator-light.png | Bin 0 -> 865 bytes .../snapshots/darwin/duration_picker-dark.png | Bin 0 -> 3462 bytes .../darwin/duration_picker-light.png | Bin 0 -> 3274 bytes testdata/snapshots/darwin/event_chip-dark.png | Bin 0 -> 7091 bytes .../snapshots/darwin/event_chip-light.png | Bin 0 -> 6859 bytes .../snapshots/darwin/event_editor-dark.png | Bin 0 -> 83344 bytes .../snapshots/darwin/event_editor-light.png | Bin 0 -> 80253 bytes .../snapshots/darwin/event_popover-dark.png | Bin 0 -> 31225 bytes .../snapshots/darwin/event_popover-light.png | Bin 0 -> 31503 bytes .../darwin/recurrence_editor-dark.png | Bin 0 -> 17827 bytes .../darwin/recurrence_editor-light.png | Bin 0 -> 17147 bytes .../snapshots/darwin/relative_time-dark.png | Bin 0 -> 4585 bytes .../snapshots/darwin/relative_time-light.png | Bin 0 -> 4344 bytes .../snapshots/darwin/reminder_picker-dark.png | Bin 0 -> 14345 bytes .../darwin/reminder_picker-light.png | Bin 0 -> 13709 bytes testdata/snapshots/darwin/stopwatch-dark.png | Bin 0 -> 13802 bytes testdata/snapshots/darwin/stopwatch-light.png | Bin 0 -> 13224 bytes .../snapshots/darwin/timezone_select-dark.png | Bin 0 -> 4974 bytes .../darwin/timezone_select-light.png | Bin 0 -> 4713 bytes .../snapshots/darwin/week_picker-dark.png | Bin 0 -> 5021 bytes .../snapshots/darwin/week_picker-light.png | Bin 0 -> 4814 bytes testdata/snapshots/darwin/year_view-dark.png | Bin 0 -> 77157 bytes testdata/snapshots/darwin/year_view-light.png | Bin 0 -> 74500 bytes timezone_select.go | 208 ++++++++++ timezone_select_test.go | 98 +++++ week_picker.go | 96 +++++ week_picker_test.go | 76 ++++ year_view.go | 168 ++++++++ year_view_test.go | 108 +++++ 110 files changed, 7335 insertions(+), 23 deletions(-) create mode 100644 agenda_view.go create mode 100644 agenda_view_test.go create mode 100644 attendee_list_test.go create mode 100644 availability_picker.go create mode 100644 availability_picker_test.go create mode 100644 calendar_day_view.go create mode 100644 calendar_day_view_test.go create mode 100644 calendar_month_view.go create mode 100644 calendar_month_view_test.go create mode 100644 calendar_time_grid.go create mode 100644 calendar_week_view.go create mode 100644 calendar_week_view_test.go create mode 100644 countdown.go create mode 100644 countdown_test.go create mode 100644 cron_editor.go create mode 100644 cron_editor_test.go create mode 100644 current_time_indicator.go create mode 100644 current_time_indicator_test.go create mode 100644 docs/components/421-calendar-month-view.md create mode 100644 docs/components/422-calendar-week-view.md create mode 100644 docs/components/423-calendar-day-view.md create mode 100644 docs/components/424-agenda-view.md create mode 100644 docs/components/425-year-view.md create mode 100644 docs/components/426-event-chip.md create mode 100644 docs/components/427-event-editor.md create mode 100644 docs/components/428-event-popover.md create mode 100644 docs/components/429-current-time-indicator.md create mode 100644 docs/components/430-recurrence-editor.md create mode 100644 docs/components/431-availability-picker.md create mode 100644 docs/components/432-timezone-select.md create mode 100644 docs/components/433-reminder-picker.md create mode 100644 docs/components/434-attendee-list.md create mode 100644 docs/components/435-week-picker.md create mode 100644 docs/components/436-duration-picker.md create mode 100644 docs/components/437-cron-editor.md create mode 100644 docs/components/438-relative-time.md create mode 100644 docs/components/439-countdown.md create mode 100644 docs/components/440-stopwatch.md create mode 100644 duration_picker.go create mode 100644 duration_picker_test.go create mode 100644 event_chip_test.go create mode 100644 event_editor.go create mode 100644 event_editor_test.go create mode 100644 event_popover.go create mode 100644 event_popover_test.go create mode 100644 example_calendar_test.go create mode 100644 examples/gallery/pages_calendar_code.go create mode 100644 examples/gallery/pages_calendar_parts.go create mode 100644 examples/gallery/pages_calendar_time.go create mode 100644 examples/gallery/pages_calendar_views.go create mode 100644 internal/calendar.go create mode 100644 messages_calendar.go create mode 100644 recurrence_editor.go create mode 100644 recurrence_editor_test.go create mode 100644 relative_time.go create mode 100644 relative_time_test.go create mode 100644 reminder_picker.go create mode 100644 reminder_picker_test.go create mode 100644 stopwatch.go create mode 100644 stopwatch_test.go create mode 100644 testdata/snapshots/darwin/agenda_view-dark.png create mode 100644 testdata/snapshots/darwin/agenda_view-light.png create mode 100644 testdata/snapshots/darwin/attendee_list-dark.png create mode 100644 testdata/snapshots/darwin/attendee_list-light.png create mode 100644 testdata/snapshots/darwin/availability_picker-dark.png create mode 100644 testdata/snapshots/darwin/availability_picker-light.png create mode 100644 testdata/snapshots/darwin/calendar_day_view-dark.png create mode 100644 testdata/snapshots/darwin/calendar_day_view-light.png create mode 100644 testdata/snapshots/darwin/calendar_month_view-dark.png create mode 100644 testdata/snapshots/darwin/calendar_month_view-light.png create mode 100644 testdata/snapshots/darwin/calendar_week_view-dark.png create mode 100644 testdata/snapshots/darwin/calendar_week_view-light.png create mode 100644 testdata/snapshots/darwin/countdown-dark.png create mode 100644 testdata/snapshots/darwin/countdown-light.png create mode 100644 testdata/snapshots/darwin/cron_editor-dark.png create mode 100644 testdata/snapshots/darwin/cron_editor-light.png create mode 100644 testdata/snapshots/darwin/current_time_indicator-dark.png create mode 100644 testdata/snapshots/darwin/current_time_indicator-light.png create mode 100644 testdata/snapshots/darwin/duration_picker-dark.png create mode 100644 testdata/snapshots/darwin/duration_picker-light.png create mode 100644 testdata/snapshots/darwin/event_chip-dark.png create mode 100644 testdata/snapshots/darwin/event_chip-light.png create mode 100644 testdata/snapshots/darwin/event_editor-dark.png create mode 100644 testdata/snapshots/darwin/event_editor-light.png create mode 100644 testdata/snapshots/darwin/event_popover-dark.png create mode 100644 testdata/snapshots/darwin/event_popover-light.png create mode 100644 testdata/snapshots/darwin/recurrence_editor-dark.png create mode 100644 testdata/snapshots/darwin/recurrence_editor-light.png create mode 100644 testdata/snapshots/darwin/relative_time-dark.png create mode 100644 testdata/snapshots/darwin/relative_time-light.png create mode 100644 testdata/snapshots/darwin/reminder_picker-dark.png create mode 100644 testdata/snapshots/darwin/reminder_picker-light.png create mode 100644 testdata/snapshots/darwin/stopwatch-dark.png create mode 100644 testdata/snapshots/darwin/stopwatch-light.png create mode 100644 testdata/snapshots/darwin/timezone_select-dark.png create mode 100644 testdata/snapshots/darwin/timezone_select-light.png create mode 100644 testdata/snapshots/darwin/week_picker-dark.png create mode 100644 testdata/snapshots/darwin/week_picker-light.png create mode 100644 testdata/snapshots/darwin/year_view-dark.png create mode 100644 testdata/snapshots/darwin/year_view-light.png create mode 100644 timezone_select.go create mode 100644 timezone_select_test.go create mode 100644 week_picker.go create mode 100644 week_picker_test.go create mode 100644 year_view.go create mode 100644 year_view_test.go diff --git a/agenda_view.go b/agenda_view.go new file mode 100644 index 0000000..e3401c1 --- /dev/null +++ b/agenda_view.go @@ -0,0 +1,149 @@ +package mujica + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// AgendaViewOptions configure an AgendaView. +type AgendaViewOptions struct { + // Location is the zone days are cut in; required. + Location *time.Location + // Version must change when events change in place. + Version int + // From is the first day listed; zero means today. + From Date + // Days is how many days are listed; zero means 30. + Days int + // Today is marked; zero uses the system clock. + Today Date + Hour12 bool + Disabled bool + Label string +} + +// agendaRow is a day heading (ev < 0) or event. +type agendaRow struct { + day Date + ev int +} + +// AgendaView lists events by day, building only visible rows. +func AgendaView(c *ui.Context, events []CalendarEvent, opts AgendaViewOptions) CalendarViewResult { + loc := eventLocation("AgendaView", opts.Location) + if opts.Days < 0 { + panic("mujica: AgendaView Days is negative") + } + days := opts.Days + if days == 0 { + days = 30 + } + eventsCheck("AgendaView", events) + k := Tokens(c) + d := Density(c) + today := datetimeToday(c, opts.Today) + from := opts.From + if from.IsZero() { + from = today + } + datetimeCheckDate("AgendaView From", from) + label := opts.Label + if label == "" { + label = msg(c, "agenda_view.label") + } + r := CalendarViewResult{} + root := ui.Column(c).Grow(1).MinHeight(0).Role(ui.RoleGroup).Label(label).Disabled(opts.Disabled) + r.Element = root + rows := eventsDerived(root, "agenda-rows", events, opts.Version, eventDayStart(from, loc), eventDayStart(from.AddDays(days), loc), + func(hits []int) []agendaRow { return agendaRows(events, hits, from, days, loc) }) + state := ui.Local(root, "agenda-list", func() *ui.ListState { return &ui.ListState{} }) + st := *state + st.Key = func(i int) any { return rows[i] } + st.Header = func(i int) bool { return rows[i].ev < 0 } + st.Label = func(i int) string { + if rows[i].ev < 0 { + return datetimeDayLabel(c, rows[i].day) + } + return events[rows[i].ev].Title + } + root.Children(func() { + list := ui.List(c, st, len(rows), func(i int) { + row := rows[i] + if row.ev < 0 { + h := ui.Row(c).MinHeight(d.ControlHeight()).AlignItems(ui.Center).Gap(d.Unit() * 2).PaddingX(d.Unit() * 3).Background(k.Background).Role(ui.RoleColumnHeader) + h.Children(func() { + t := ui.Text(c, datetimeDayLabel(c, row.day)).Font(theme.SerifFont).TextColor(k.Text) + if row.day == today { + t.Bold().TextColor(k.AccentText) + ui.Text(c, msg(c, "agenda_view.today")).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.AccentText) + } + }) + h.DrawOver(func(p *ui.Painter, rr ui.Rect) { internal.Rule(p, rr.X, rr.X+rr.W, rr.Y+rr.H-1, k.Ornament) }) + return + } + if agendaItem(c, events[row.ev], loc, opts.Hour12) && !root.IsDisabled() { + r.opened = events[row.ev].ID + } + }).Grow(1).MinHeight(d.ControlHeight() * 4).FocusGroup(ui.Vertical) + list.Children(func() { + if len(rows) == 0 { + ui.Text(c, fmt.Sprintf(msg(c, "agenda_view.empty"), days)).TextColor(k.TextMuted).Padding(d.Unit() * 3) + } + }) + }) + return r +} + +// agendaRows flattens the span into headed days. +func agendaRows(events []CalendarEvent, hits []int, from Date, days int, loc *time.Location) []agendaRow { + buckets := make([][]int, days) + for _, h := range hits { + ev := events[h] + first := max(0, monthDays(ev.Start.In(loc), from)*-1) + last := min(days-1, -monthDays(ev.End.Add(-time.Nanosecond).In(loc), from)) + for i := first; i <= last; i++ { + buckets[i] = append(buckets[i], h) + } + } + var out []agendaRow + for i, b := range buckets { + if len(b) > 0 { + out = append(out, agendaRow{from.AddDays(i), -1}) + for _, h := range b { + out = append(out, agendaRow{from.AddDays(i), h}) + } + } + } + return out +} + +// agendaItem is one event row; it reports a click. +func agendaItem(c *ui.Context, ev CalendarEvent, loc *time.Location, hour12 bool) bool { + k := Tokens(c) + d := Density(c) + when := eventTimeText(c, ev, loc, hour12) + b := ui.ButtonBase(c).MinHeight(d.ControlHeight()).Justify(ui.Start).Gap(d.Unit() * 3).PaddingX(d.Unit() * 3).Label(ev.Title + ", " + when) + internal.Ring(b, k.Focus, theme.ControlRadius) + if b.Hovered() { + b.Background(k.SurfaceHover) + } + col := eventColor(k, ev.Color) + b.Children(func() { + ui.Text(c, when).Width(d.ControlHeight() * 3.5).Shrink(0).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).FontFeatures("tnum") + ui.Box(c).Size(8, 8).Shrink(0).Draw(func(p *ui.Painter, r ui.Rect) { + p.FillPath(internal.Diamond(r.X+r.W/2, r.Y+r.H/2, r.W), col) + }) + ui.Column(c).Grow(1).Shrink(1).Children(func() { + ui.Text(c, ev.Title).TextColor(k.Text).SingleLine().Ellipsis("…") + if ev.Location != "" { + ui.Text(c, ev.Location).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine().Ellipsis("…") + } + }) + }) + return b.Clicked() +} diff --git a/agenda_view_test.go b/agenda_view_test.go new file mode 100644 index 0000000..630c7bd --- /dev/null +++ b/agenda_view_test.go @@ -0,0 +1,95 @@ +package mujica + +import ( + "fmt" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func agendaTester(events []CalendarEvent, opts AgendaViewOptions, opened *[]string) *ui.Tester { + opts.Location, opts.Today = calTokyo, calendarToday + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Height(500).Children(func() { + if id, ok := AgendaView(c, events, opts).Opened(); ok { + *opened = append(*opened, id) + } + }) + }, 600, 520) +} + +func TestAgendaViewGroupsByDay(t *testing.T) { + evs := []CalendarEvent{calEvent("b", 7, 14, 0, 60), calEvent("a", 7, 9, 0, 30), calEvent("c", 9, 10, 0, 60), calEvent("old", 1, 9, 0, 60)} + evs[0].Location = "Rehearsal hall" + var opened []string + tt := agendaTester(evs, AgendaViewOptions{}, &opened) + texts := tt.Texts() + idx := func(s string) int { + for i, x := range texts { + if x == s { + return i + } + } + return -1 + } + d7, a, b, d9, c := idx("Wednesday, October 7, 2026"), idx("Event a, 09:00 – 09:30"), idx("Event b, 14:00 – 15:00"), idx("Friday, October 9, 2026"), idx("Event c, 10:00 – 11:00") + if d7 < 0 || !(d7 < a && a < b && b < d9 && d9 < c) || tt.HasText("Event old") || !tt.HasText("Rehearsal hall") { + t.Fatalf("order %d %d %d %d %d in %v", d7, a, b, d9, c, texts) + } + _ = tt.Click("Event b, 14:00 – 15:00") + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if len(opened) != 2 || opened[0] != "b" || opened[1] != "c" { + t.Fatalf("opened %v", opened) + } +} + +func TestAgendaViewMultiDayEmptyAndDisabled(t *testing.T) { + trip := calEvent("t", 6, 20, 0, 26*60) + var opened []string + tt := agendaTester([]CalendarEvent{trip}, AgendaViewOptions{Days: 3}, &opened) + if !tt.HasText("Tuesday, October 6, 2026") || !tt.HasText("Wednesday, October 7, 2026") { + t.Fatalf("a multi-day event lists on each day: %v", tt.Texts()) + } + tt = agendaTester(nil, AgendaViewOptions{Days: 7}, &opened) + if !tt.HasText("No events in the next 7 days.") { + t.Fatal("no empty state") + } + tt = agendaTester([]CalendarEvent{calEvent("a", 6, 9, 0, 30)}, AgendaViewOptions{Disabled: true}, &opened) + _ = tt.Click("Event a, 09:00 – 09:30") + if len(opened) != 0 { + t.Fatal("disabled agenda opened") + } + defer func() { + if recover() == nil { + t.Fatal("expected panic") + } + }() + agendaTester(nil, AgendaViewOptions{Days: -1}, &opened) +} + +func TestAgendaViewLargeData(t *testing.T) { + var evs []CalendarEvent + base := time.Date(2026, time.October, 5, 0, 0, 0, 0, calTokyo) + for i := range 100000 { + s := base.Add(time.Duration(i%(365*24)) * time.Hour) + evs = append(evs, CalendarEvent{ID: fmt.Sprint(i), Title: "E", Start: s, End: s.Add(30 * time.Minute)}) + } + var opened []string + tt := agendaTester(evs, AgendaViewOptions{Days: 365}, &opened) + if n := len(tt.Texts()); n > 200 { + t.Fatalf("built %d labels", n) + } +} + +func TestAgendaViewSnapshot(t *testing.T) { + evs := []CalendarEvent{calEvent("a", 5, 9, 0, 30), calEvent("b", 5, 14, 0, 60), calEvent("c", 7, 10, 0, 60), calEvent("d", 8, 18, 0, 120)} + evs[1].Location, evs[1].Color, evs[3].Color = "Rehearsal hall", EventInfo, EventSuccess + snapshot(t, "agenda_view", 520, 420, func(c *ui.Context) { + ui.Column(c).Padding(16).Height(420).Children(func() { + AgendaView(c, evs, AgendaViewOptions{Location: calTokyo, Today: calendarToday}) + }) + }) +} diff --git a/attendee_list.go b/attendee_list.go index 32b3173..a1a8568 100644 --- a/attendee_list.go +++ b/attendee_list.go @@ -46,7 +46,7 @@ type AttendeeListResult struct { // Removed returns the index of the attendee the user removed. func (r AttendeeListResult) Removed() (int, bool) { return r.removed, r.removed >= 0 } -// AttendeeList shows invitees with their reply, in words and an icon, and a reply summary. +// AttendeeList shows invitees, their replies and a summary. func AttendeeList(c *ui.Context, attendees []Attendee, opts AttendeeListOptions) AttendeeListResult { k := Tokens(c) d := Density(c) @@ -71,7 +71,7 @@ func AttendeeList(c *ui.Context, attendees []Attendee, opts AttendeeListOptions) ui.Text(c, msg(c, "attendee_list.empty")).TextColor(k.TextMuted) } for i, a := range attendees { - ui.Row(c).Key(i).MinHeight(d.ControlHeight()).Gap(d.Unit()*2).AlignItems(ui.Center).Role(ui.RoleListItem).Children(func() { + ui.Row(c).Key(i).MinHeight(d.ControlHeight()).Gap(d.Unit() * 2).AlignItems(ui.Center).Role(ui.RoleListItem).Children(func() { Avatar(c, a.Name, AvatarOptions{Size: 28}) ui.Column(c).Grow(1).Shrink(1).Children(func() { name := a.Name diff --git a/attendee_list_test.go b/attendee_list_test.go new file mode 100644 index 0000000..1f9b350 --- /dev/null +++ b/attendee_list_test.go @@ -0,0 +1,82 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +var calAttendees = []Attendee{ + {Name: "Sakiko Togawa", Email: "sakiko@court.example", Status: AttendeeAccepted, Organizer: true}, + {Name: "Mutsumi Wakaba", Status: AttendeeTentative}, + {Name: "Uika Misumi", Email: "uika@court.example", Status: AttendeeDeclined, Optional: true}, + {Name: "Nyamu Yuutenji", Status: AttendeePending}, +} + +func attendeeTester(list *[]Attendee, opts AttendeeListOptions) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if i, ok := AttendeeList(c, *list, opts).Removed(); ok { + *list = append((*list)[:i:i], (*list)[i+1:]...) + } + }, 480, 400) +} + +func TestAttendeeListStatusesAndSummary(t *testing.T) { + list := append([]Attendee(nil), calAttendees...) + tt := attendeeTester(&list, AttendeeListOptions{}) + for _, s := range []string{"1 accepted · 1 maybe · 1 declined · 1 awaiting", "Sakiko Togawa · Organizer", + "Uika Misumi · Optional", "Accepted", "Maybe", "Declined", "Awaiting reply", "uika@court.example"} { + if !tt.HasText(s) { + t.Fatalf("missing %q in %v", s, tt.Texts()) + } + } + if tt.HasText("Remove Mutsumi Wakaba") { + t.Fatal("remove buttons without Removable") + } +} + +func TestAttendeeListRemoveKeyboardAndOrganizer(t *testing.T) { + list := append([]Attendee(nil), calAttendees...) + tt := attendeeTester(&list, AttendeeListOptions{Removable: true}) + if tt.HasText("Remove Sakiko Togawa") { + t.Fatal("the organizer cannot be removed") + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if len(list) != 3 || list[0].Name != "Sakiko Togawa" || list[1].Name != "Uika Misumi" { + t.Fatalf("keyboard remove left %v", list) + } + _ = tt.Click("Remove Uika Misumi") + if len(list) != 2 || !tt.HasText("1 accepted · 0 maybe · 0 declined · 1 awaiting") { + t.Fatalf("click remove left %v", list) + } +} + +func TestAttendeeListDisabledEmptyInvalid(t *testing.T) { + list := append([]Attendee(nil), calAttendees...) + tt := attendeeTester(&list, AttendeeListOptions{Removable: true, Disabled: true}) + _ = tt.Click("Remove Mutsumi Wakaba") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if len(list) != 4 { + t.Fatal("disabled list removed someone") + } + empty := []Attendee{} + if tt := attendeeTester(&empty, AttendeeListOptions{}); !tt.HasText("No attendees yet.") { + t.Fatal("no empty state") + } + defer func() { + if recover() == nil { + t.Fatal("expected panic on bad status") + } + }() + bad := []Attendee{{Name: "X", Status: 7}} + attendeeTester(&bad, AttendeeListOptions{}) +} + +func TestAttendeeListSnapshot(t *testing.T) { + snapshot(t, "attendee_list", 420, 260, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { AttendeeList(c, calAttendees, AttendeeListOptions{Removable: true}) }) + }) +} diff --git a/availability_picker.go b/availability_picker.go new file mode 100644 index 0000000..b7dc491 --- /dev/null +++ b/availability_picker.go @@ -0,0 +1,180 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strconv" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// AvailabilityPerson is another person's free slots, [day][slot]. +type AvailabilityPerson struct { + Name string + Free [][]bool +} + +// AvailabilityPickerOptions configure an AvailabilityPicker. +type AvailabilityPickerOptions struct { + // Days are the grid's columns; required. + Days []Date + // From and To are hours; zero means 9 to 18. + From, To int + // SlotMinutes must divide an hour; zero means 30. + SlotMinutes int + // Others are counted as free per slot. + Others []AvailabilityPerson + Hour12 bool + Disabled bool + Label string +} + +// availabilityDrag is a paint stroke: the value being painted. +type availabilityDrag struct { + active bool + paint bool +} + +// AvailabilityPicker paints free slots and counts others' overlap. +func AvailabilityPicker(c *ui.Context, mine *[][]bool, opts AvailabilityPickerOptions) ChoiceResult { + from, to := opts.From, opts.To + if from == 0 && to == 0 { + from, to = 9, 18 + } + slot := timeGridSlot("AvailabilityPicker", opts.SlotMinutes) + if len(opts.Days) == 0 || from < 0 || to > 24 || to <= from || slot > 60 { + panic(fmt.Sprintf("mujica: AvailabilityPicker needs days and hours 0 <= %d < %d <= 24", from, to)) + } + slots := (to - from) * 60 / slot + availabilityCheck("value", *mine, len(opts.Days), slots) + for _, p := range opts.Others { + availabilityCheck(p.Name, p.Free, len(opts.Days), slots) + } + k := Tokens(c) + d := Density(c) + label := opts.Label + if label == "" { + label = msg(c, "availability_picker.label") + } + gutter := d.ControlHeight() * 1.8 + rowH := float32(theme.MinHitSize) + headH := d.ControlHeight() + changed := false + set := func(day, s int, v bool) { + if (*mine)[day][s] != v { + (*mine)[day][s], changed = v, true + } + } + grid := ui.Column(c).Focusable().Role(ui.RoleTable).Label(label).Disabled(opts.Disabled) + internal.Ring(grid, k.Focus, theme.ControlRadius) + drag := ui.Local(grid, "availability-drag", func() availabilityDrag { return availabilityDrag{} }) + cursor := ui.Local(grid, "availability-cursor", func() [2]int { return [2]int{} }) + if !grid.IsDisabled() { + b := grid.Bounds() + px, py, _ := grid.PointerPosition() + cw := (b.W - gutter) / float32(len(opts.Days)) + day, s := int((px-gutter)/max(cw, 1)), int((py-headH)/rowH) + inside := px >= gutter && py >= headH && day < len(opts.Days) && s < slots + if _, _, pressing := grid.Dragged(); pressing && inside { + if !drag.active { + *drag = availabilityDrag{true, !(*mine)[day][s]} + *cursor = [2]int{day, s} + } + set(day, s, drag.paint) + } else if !pressing { + drag.active = false + } + for key, dd := range map[ui.Key][2]int{ui.KeyLeft: {-1, 0}, ui.KeyRight: {1, 0}, ui.KeyUp: {0, -1}, ui.KeyDown: {0, 1}} { + if grid.Shortcut(0, key) { + *cursor = [2]int{max(0, min(len(opts.Days)-1, cursor[0]+dd[0])), max(0, min(slots-1, cursor[1]+dd[1]))} + } + } + if grid.Shortcut(0, ui.KeySpace) || grid.Shortcut(0, ui.KeyEnter) { + set(cursor[0], cursor[1], !(*mine)[cursor[0]][cursor[1]]) + } + } + focused := grid.FocusVisible() || grid.Focused() && !drag.active + grid.Children(func() { + ui.Row(c).Height(headH).Children(func() { + ui.Box(c).Width(gutter).Shrink(0) + for _, day := range opts.Days { + ui.Text(c, msg(c, "calendar.weekday_"+strconv.Itoa(int(day.Weekday())))+" "+strconv.Itoa(day.Day)).Grow(1).Basis(0). + TextAlign(ui.Center).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Role(ui.RoleColumnHeader) + } + }) + for s := range slots { + m := from*60 + s*slot + ui.Row(c).Height(rowH).Role(ui.RoleRow).Children(func() { + hour := "" + if m%60 == 0 { + hour = timeText(c, TimeOfDay{m / 60, 0, 0}, timeConfig{hour12: opts.Hour12}) + } + ui.Text(c, hour).Width(gutter).Shrink(0).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).FontFeatures("tnum") + for di, day := range opts.Days { + free := 0 + for _, p := range opts.Others { + if p.Free[di][s] { + free++ + } + } + availabilityCell(c, day, m, (*mine)[di][s], free, len(opts.Others), focused && *cursor == [2]int{di, s}, opts.Hour12) + } + }) + } + }) + if changed { + slog.Debug("mujica: availability_picker change") + } + return ChoiceResult{Element: grid, changed: changed} +} + +func availabilityCheck(name string, v [][]bool, days, slots int) { + if len(v) != days { + panic(fmt.Sprintf("mujica: AvailabilityPicker %s has %d days, want %d", name, len(v), days)) + } + for _, row := range v { + if len(row) != slots { + panic(fmt.Sprintf("mujica: AvailabilityPicker %s has %d slots, want %d", name, len(row), slots)) + } + } +} + +// availabilityCell shows one slot's choice and free count. +func availabilityCell(c *ui.Context, day Date, m int, mine bool, free, others int, cursor, hour12 bool) { + k := Tokens(c) + text := datetimeDayLabel(c, day) + " " + timeText(c, TimeOfDay{m / 60, m % 60, 0}, timeConfig{hour12: hour12}) + if mine { + text += ", " + msg(c, "availability_picker.mine") + } + if others > 0 { + text += ", " + fmt.Sprintf(msg(c, "availability_picker.others"), free, others) + } + everyone := mine && others > 0 && free == others + cell := ui.Box(c).Grow(1).Basis(0).MinWidth(0).FillHeight().Center().Role(ui.RoleCell).Label(text).BorderWidth(0, 0, theme.BorderWidth, theme.BorderWidth).BorderColor(k.Border) + if mine { + cell.Background(k.Selection) + } + cell.Draw(func(p *ui.Painter, r ui.Rect) { + if others > 0 && free > 0 { + h := (r.H - 4) * float32(free) / float32(others) + p.Fill(ui.Rect{X: r.X + 2, Y: r.Y + r.H - 2 - h, W: 3, H: h}, k.Info, 1) + } + if mine { + internal.Mark(p, ui.Rect{X: r.X + r.W - 16, Y: r.Y + 2, W: 12, H: 12}, "check", k.AccentText) + } + if cursor { + datetimeSelectedMark(p, r, k.Focus) + } + }) + cell.Children(func() { + if others > 0 && free > 0 { + t := ui.Text(c, strconv.Itoa(free)).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).FontFeatures("tnum") + if everyone { + t.Bold().TextColor(k.AccentText) + } + } + }) +} diff --git a/availability_picker_test.go b/availability_picker_test.go new file mode 100644 index 0000000..86f47a3 --- /dev/null +++ b/availability_picker_test.go @@ -0,0 +1,108 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func availabilityGrid(days, slots int) [][]bool { + v := make([][]bool, days) + for i := range v { + v[i] = make([]bool, slots) + } + return v +} + +var availabilityDays = []Date{oct(12), oct(13), oct(14)} + +func availabilityTester(v *[][]bool, opts *AvailabilityPickerOptions, n *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + o := *opts + o.Days, o.From, o.To = availabilityDays, 9, 12 + ui.Column(c).Padding(16).Children(func() { + if AvailabilityPicker(c, v, o).Changed() { + *n++ + } + }) + }, 560, 360) +} + +func TestAvailabilityPickerPaintDrag(t *testing.T) { + v, n := availabilityGrid(3, 6), 0 + tt := availabilityTester(&v, &AvailabilityPickerOptions{}, &n) + a, _ := tt.Find("Monday, October 12, 2026 09:00") + b, _ := tt.Find("Monday, October 12, 2026 10:30") + calDrag(tt, a.X+a.W/2, a.Y+a.H/2, b.X+b.W/2, b.Y+b.H/2) + for s := range 6 { + if v[0][s] != (s <= 3) { + t.Fatalf("painted %v", v[0]) + } + } + if n == 0 || !tt.HasText("Monday, October 12, 2026 10:00, you are free") { + t.Fatal("no change or label") + } + // Starting on a free slot erases. + calDrag(tt, a.X+a.W/2, a.Y+a.H/2, a.X+a.W/2, a.Y+a.H*1.5) + if v[0][0] || v[0][1] || !v[0][2] { + t.Fatalf("erase stroke %v", v[0]) + } +} + +func TestAvailabilityPickerOthersAndKeyboard(t *testing.T) { + v, n := availabilityGrid(3, 6), 0 + free := availabilityGrid(3, 6) + free[1][0] = true + other := availabilityGrid(3, 6) + other[1][0], other[1][1] = true, true + opts := &AvailabilityPickerOptions{Others: []AvailabilityPerson{{Name: "Mutsumi", Free: free}, {Name: "Uika", Free: other}}} + tt := availabilityTester(&v, opts, &n) + if !tt.HasText("Tuesday, October 13, 2026 09:00, 2 of 2 others free") || !tt.HasText("Tuesday, October 13, 2026 09:30, 1 of 2 others free") { + t.Fatalf("overlap counts: %v", tt.Texts()) + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeySpace) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if !v[1][0] || !v[1][1] || n != 2 { + t.Fatalf("keyboard toggles %v", v[1]) + } +} + +func TestAvailabilityPickerDisabledAndInvalid(t *testing.T) { + v, n := availabilityGrid(3, 6), 0 + tt := availabilityTester(&v, &AvailabilityPickerOptions{Disabled: true}, &n) + a, _ := tt.Find("Monday, October 12, 2026 09:00") + calDrag(tt, a.X+a.W/2, a.Y+a.H/2, a.X+a.W/2, a.Y+a.H*2.5) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeySpace) + if v[0][0] || n != 0 { + t.Fatal("disabled picker painted") + } + for _, bad := range []*AvailabilityPickerOptions{{SlotMinutes: 7}, {Others: []AvailabilityPerson{{Name: "X", Free: availabilityGrid(2, 6)}}}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%+v: expected panic", bad) + } + }() + w := availabilityGrid(3, 6) + availabilityTester(&w, bad, &n) + }() + } +} + +func TestAvailabilityPickerSnapshot(t *testing.T) { + v := availabilityGrid(3, 6) + v[0][1], v[0][2], v[1][2] = true, true, true + free := availabilityGrid(3, 6) + free[0][2], free[1][2], free[2][0] = true, true, true + snapshot(t, "availability_picker", 520, 300, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + AvailabilityPicker(c, &v, AvailabilityPickerOptions{Days: availabilityDays, From: 9, To: 12, + Others: []AvailabilityPerson{{Name: "Mutsumi", Free: free}}}) + }) + }) +} diff --git a/calendar_day_view.go b/calendar_day_view.go new file mode 100644 index 0000000..a1856ab --- /dev/null +++ b/calendar_day_view.go @@ -0,0 +1,50 @@ +package mujica + +import ( + "time" + + "github.com/egoist/mygo/ui" +) + +// CalendarDayViewOptions configure a CalendarDayView. +type CalendarDayViewOptions struct { + // Location is the zone the day is cut in; required. + Location *time.Location + // Version must change when events change in place. + Version int + // SlotMinutes is the grid step; zero means 30. + SlotMinutes int + // Today is marked; zero uses the system clock. + Today Date + // Now places the current-time line; zero uses the system clock. + Now time.Time + Hour12 bool + Disabled bool + Label string +} + +// CalendarDayView shows one day's time grid. +func CalendarDayView(c *ui.Context, day *Date, events []CalendarEvent, opts CalendarDayViewOptions) CalendarViewResult { + datetimeCheckDate("CalendarDayView day", *day) + if day.IsZero() { + panic("mujica: CalendarDayView needs a day") + } + cfg := timeGridConfig{name: "calendar_day_view", loc: eventLocation("CalendarDayView", opts.Location), version: opts.Version, + slot: timeGridSlot("CalendarDayView", opts.SlotMinutes), today: datetimeToday(c, opts.Today), now: opts.Now, hour12: opts.Hour12} + eventsCheck("CalendarDayView", events) + title := datetimeDayLabel(c, *day) + label := opts.Label + if label == "" { + label = title + } + r := CalendarViewResult{} + root := ui.Column(c).Gap(Density(c).Unit()).Role(ui.RoleGroup).Label(label).Disabled(opts.Disabled) + r.Element = root + root.Children(func() { + calendarViewHeader(c, title, msg(c, "calendar_day_view.prev"), msg(c, "calendar_day_view.next"), func(dir int) { + *day = day.AddDays(dir) + }) + timeGrid(c, root, []Date{*day}, events, cfg, &r) + }) + return r +} diff --git a/calendar_day_view_test.go b/calendar_day_view_test.go new file mode 100644 index 0000000..8ffa166 --- /dev/null +++ b/calendar_day_view_test.go @@ -0,0 +1,79 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func dayViewTester(day *Date, events []CalendarEvent, opts CalendarDayViewOptions, changes *[]CalendarChange) *ui.Tester { + opts.Location, opts.Today = calTokyo, calendarToday + opts.Now = time.Date(2026, time.October, 14, 10, 30, 0, 0, calTokyo) + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if ch, ok := CalendarDayView(c, day, events, opts).Changed(); ok { + *changes = append(*changes, ch) + } + }, 600, 900) +} + +func TestCalendarDayViewOverlapSideBySide(t *testing.T) { + day := oct(14) + evs := []CalendarEvent{calEvent("a", 14, 9, 0, 120), calEvent("b", 14, 9, 30, 60), calEvent("c", 14, 10, 0, 60), calEvent("d", 14, 12, 0, 30)} + var ch []CalendarChange + tt := dayViewTester(&day, evs, CalendarDayViewOptions{}, &ch) + a, _ := tt.Find("Event a, 09:00 – 11:00") + b, _ := tt.Find("Event b, 09:30 – 10:30") + c, _ := tt.Find("Event c, 10:00 – 11:00") + d, _ := tt.Find("Event d, 12:00 – 12:30") + if !(a.X < b.X && b.X < c.X) || a.W > d.W/2 || d.X != a.X { + t.Fatalf("three overlapping events need three columns, the lone one the full width: %v %v %v %v", a, b, c, d) + } +} + +func TestCalendarDayViewNavigationSlotAndDisabled(t *testing.T) { + day := oct(14) + var ch []CalendarChange + tt := dayViewTester(&day, nil, CalendarDayViewOptions{SlotMinutes: 15}, &ch) + if !tt.HasText("Wednesday, October 14, 2026") { + t.Fatalf("title %v", tt.Texts()[:4]) + } + _ = tt.Click("Schedule, Wednesday, October 14, 2026") + tt.Key(0, ui.KeyEnter) + if len(ch) != 1 || ch[0].End.Sub(ch[0].Start) != 15*time.Minute { + t.Fatalf("15-minute slot create %+v", ch) + } + _ = tt.Click("Next day") + if day != oct(15) { + t.Fatalf("day %v", day) + } + d := oct(14) + ch = nil + tt = dayViewTester(&d, nil, CalendarDayViewOptions{Disabled: true}, &ch) + _ = tt.Click("Schedule, Wednesday, October 14, 2026") + tt.Key(0, ui.KeyEnter) + _ = tt.Click("Previous day") + if len(ch) != 0 || d != oct(14) { + t.Fatal("disabled day view reacted") + } + defer func() { + if recover() == nil { + t.Fatal("expected panic without a day") + } + }() + zero := Date{} + dayViewTester(&zero, nil, CalendarDayViewOptions{}, &ch) +} + +func TestCalendarDayViewSnapshot(t *testing.T) { + day := oct(14) + evs := []CalendarEvent{calEvent("a", 14, 9, 0, 120), calEvent("b", 14, 9, 30, 60), calEvent("c", 14, 10, 0, 60), calEvent("d", 14, 12, 0, 30)} + evs[1].Color, evs[2].Color = EventInfo, EventSuccess + snapshot(t, "calendar_day_view", 560, 860, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + CalendarDayView(c, &day, evs, CalendarDayViewOptions{Location: calTokyo, Today: calendarToday, + Now: time.Date(2026, time.October, 14, 10, 30, 0, 0, calTokyo)}) + }) + }) +} diff --git a/calendar_events.go b/calendar_events.go index 6599680..cf624e0 100644 --- a/calendar_events.go +++ b/calendar_events.go @@ -22,7 +22,7 @@ const ( EventNeutral ) -// CalendarEvent is one entry of the calendar views. End is exclusive. +// CalendarEvent is one entry of the views; End is exclusive. type CalendarEvent struct { ID string Title string @@ -46,7 +46,7 @@ const ( CalendarCreate ) -// CalendarChange is a move, resize or new event a view asks the caller to apply. +// CalendarChange is a move, resize or creation to apply. type CalendarChange struct { Kind CalendarChangeKind ID string @@ -54,7 +54,7 @@ type CalendarChange struct { AllDay bool } -// CalendarViewResult is a calendar view and what the user asked of it. +// CalendarViewResult is a view and what the user asked. type CalendarViewResult struct { Element *ui.Element opened string @@ -76,7 +76,7 @@ func (r CalendarViewResult) Changed() (CalendarChange, bool) { // DayChosen returns the day the user activated. func (r CalendarViewResult) DayChosen() (Date, bool) { return r.day, !r.day.IsZero() } -// eventPalette maps EventColor to tokens that keep 3:1 on Surface in both themes. +// eventPalette maps EventColor to tokens at 3:1 on Surface. func eventPalette(k theme.Tokens) [6]ui.Color { return [6]ui.Color{k.AccentText, k.Info, k.Success, k.Warning, k.Danger, k.TextMuted} } @@ -100,24 +100,25 @@ func eventsCheck(name string, events []CalendarEvent) { } } -// eventsIndex caches the events overlapping a span, rebuilt only when data or span change. -type eventsIndex struct { +// eventsCache holds data derived from events overlapping a span. +type eventsCache[T any] struct { first *CalendarEvent n int version int from, to time.Time - hits []int + value T + valid bool } -// eventsIn returns the indexes of events overlapping [from, to), by start time. -func eventsIn(e *ui.Element, events []CalendarEvent, version int, from, to time.Time) []int { - ix := ui.Local(e, "mujica.events.index", func() *eventsIndex { return &eventsIndex{} }) +// eventsDerived rebuilds build(hits) only when events or span change. +func eventsDerived[T any](e *ui.Element, key string, events []CalendarEvent, version int, from, to time.Time, build func(hits []int) T) T { + cache := ui.Local(e, key, func() *eventsCache[T] { return &eventsCache[T]{} }) var first *CalendarEvent if len(events) > 0 { first = &events[0] } - if c := *ix; c.first == first && c.n == len(events) && c.version == version && c.from.Equal(from) && c.to.Equal(to) && c.hits != nil { - return c.hits + if x := *cache; x.valid && x.first == first && x.n == len(events) && x.version == version && x.from.Equal(from) && x.to.Equal(to) { + return x.value } hits := []int{} for i, ev := range events { @@ -132,14 +133,15 @@ func eventsIn(e *ui.Element, events []CalendarEvent, version int, from, to time. } return x.End.After(y.End) }) - **ix = eventsIndex{first, len(events), version, from, to, hits} - return hits + v := build(hits) + **cache = eventsCache[T]{first, len(events), version, from, to, v, true} + return v } // eventSpan is a placed interval, in any unit. type eventSpan struct{ from, to float64 } -// eventColumns lays out overlapping spans side by side: each gets a column and its cluster's width. +// eventColumns gives overlapping spans side-by-side columns and cluster widths. func eventColumns(spans []eventSpan) (col, cols []int) { col, cols = make([]int, len(spans)), make([]int, len(spans)) order := make([]int, len(spans)) @@ -179,7 +181,7 @@ func eventColumns(spans []eventSpan) (col, cols []int) { return col, cols } -// eventDayStart is midnight of d in loc; a missing midnight resolves to the day's first instant. +// eventDayStart is d's first instant in loc. func eventDayStart(d Date, loc *time.Location) time.Time { return time.Date(d.Year, d.Month, d.Day, 0, 0, 0, 0, loc) } @@ -195,6 +197,38 @@ func eventTimeText(c *ui.Context, ev CalendarEvent, loc *time.Location, hour12 b return text } +// eventShift moves ev by days, keeping wall time. +func eventShift(c *ui.Context, ev CalendarEvent, days int, loc *time.Location) (CalendarChange, string) { + s, e := ev.Start.In(loc), ev.End.In(loc) + ch := CalendarChange{Kind: CalendarMove, ID: ev.ID, AllDay: ev.AllDay} + if ev.AllDay { + ch.Start, ch.End = eventDayStart(DateOf(s).AddDays(days), loc), eventDayStart(DateOf(e).AddDays(days), loc) + return ch, "" + } + day := DateOf(s).AddDays(days) + wall := TimeOfDay{s.Hour(), s.Minute(), s.Second()} + at, n := dateTimeResolve(day, wall, loc) + if p := eventWallProblem(c, day, wall, loc, n); p != "" { + return ch, p + } + ch.Start, ch.End = at, at.Add(ev.End.Sub(ev.Start)) + return ch, "" +} + +// eventWallProblem reports a wall time DST skips or repeats. +func eventWallProblem(c *ui.Context, day Date, wall TimeOfDay, loc *time.Location, n int) string { + key := "" + switch { + case n == 0: + key = "date_time_picker.gap" + case n > 1: + key = "date_time_picker.ambiguous" + default: + return "" + } + return fmt.Sprintf(msg(c, key), day.String()+" "+fmt.Sprintf("%02d:%02d", wall.Hour, wall.Minute), loc.String()) +} + // eventLocation panics without a caller zone; views never assume UTC. func eventLocation(name string, loc *time.Location) *time.Location { if loc == nil { diff --git a/calendar_month_view.go b/calendar_month_view.go new file mode 100644 index 0000000..2d8a72b --- /dev/null +++ b/calendar_month_view.go @@ -0,0 +1,248 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strconv" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// CalendarMonthViewOptions configure a CalendarMonthView. +type CalendarMonthViewOptions struct { + // Location is the zone days are cut in; required. + Location *time.Location + // Version must change when events change in place. + Version int + WeekStart WeekStart + // MaxPerDay is rows shown before "+N"; zero means 3. + MaxPerDay int + // Today is marked; zero uses the system clock. + Today Date + Hour12 bool + Disabled bool + Label string +} + +// monthDrag is the event id a month view chip drags. +type monthDrag string + +// monthDay is one cell's rows of side-by-side events. +type monthDay struct { + rows [][]int + n int +} + +// CalendarMonthView shows a month of events; drags reschedule them. +func CalendarMonthView(c *ui.Context, month *YearMonth, events []CalendarEvent, opts CalendarMonthViewOptions) CalendarViewResult { + loc := eventLocation("CalendarMonthView", opts.Location) + if month.IsZero() || month.Month < time.January || month.Month > time.December { + panic(fmt.Sprintf("mujica: CalendarMonthView month %v is not valid", *month)) + } + if opts.MaxPerDay < 0 { + panic("mujica: CalendarMonthView MaxPerDay is negative") + } + maxRows := opts.MaxPerDay + if maxRows == 0 { + maxRows = 3 + } + eventsCheck("CalendarMonthView", events) + k := Tokens(c) + d := Density(c) + today := datetimeToday(c, opts.Today) + first := calendarFirstWeekday(c, opts.WeekStart) + start := Date{month.Year, month.Month, 1} + start = start.AddDays(-((int(start.Weekday()) - int(first) + 7) % 7)) + label := opts.Label + if label == "" { + label = datetimeMonthTitle(c, month.Year, month.Month) + } + r := CalendarViewResult{} + root := ui.Column(c).Gap(d.Unit() * 2).Role(ui.RoleGroup).Label(label).Disabled(opts.Disabled) + r.Element = root + problem := ui.Local(root, "month-view-problem", func() string { return "" }) + more := ui.Local(root, "month-view-more", func() Date { return Date{} }) + days := eventsDerived(root, "month-view-days", events, opts.Version, eventDayStart(start, loc), eventDayStart(start.AddDays(42), loc), + func(hits []int) []monthDay { return monthLayout(events, hits, start, loc) }) + disabled := func() bool { return root.IsDisabled() } + apply := func(ch CalendarChange, p string) { + *problem = p + if p == "" && !disabled() { + slog.Debug("mujica: calendar_month_view move", "id", ch.ID, "start", ch.Start) + r.change = &ch + } + } + root.Children(func() { + ui.Row(c).AlignItems(ui.Center).Gap(d.Unit()).Children(func() { + if iconAction(c, icons.Must("chevron-left"), msg(c, "calendar.prev_month")).Clicked() && !disabled() { + *month = YearMonth{start.AddDays(7).AddMonths(-1).Year, start.AddDays(7).AddMonths(-1).Month} + } + ui.Text(c, datetimeMonthTitle(c, month.Year, month.Month)).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)). + TextColor(k.Text).Grow(1).TextAlign(ui.Center) + if iconAction(c, icons.Must("chevron-right"), msg(c, "calendar.next_month")).Clicked() && !disabled() { + *month = YearMonth{start.AddDays(7).AddMonths(1).Year, start.AddDays(7).AddMonths(1).Month} + } + }) + ui.Row(c).Children(func() { + for i := range 7 { + wd := (int(first) + i) % 7 + ui.Text(c, msg(c, "calendar.weekday_"+strconv.Itoa(wd))).Grow(1).Basis(0).TextAlign(ui.Center). + FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Label(msg(c, "calendar.weekday_long_"+strconv.Itoa(wd))) + } + }) + ui.Column(c).Border(theme.BorderWidth, k.Border).Dividers(theme.BorderWidth, k.Border).FocusGroup(ui.Horizontal | ui.Vertical).Children(func() { + for w := range 6 { + ui.Row(c).Dividers(theme.BorderWidth, k.Border).Children(func() { + for i := range 7 { + at := w*7 + i + day := start.AddDays(at) + monthCell(c, day, *month, today, days[at], events, maxRows, loc, opts, &r, more, apply) + } + }) + } + }) + datetimeError(c, *problem) + }) + return r +} + +// monthLayout buckets events per day, concurrent ones side by side. +func monthLayout(events []CalendarEvent, hits []int, start Date, loc *time.Location) []monthDay { + out := make([]monthDay, 42) + for i := range out { + from, to := eventDayStart(start.AddDays(i), loc), eventDayStart(start.AddDays(i+1), loc) + var idx []int + var spans []eventSpan + for _, h := range hits { + ev := events[h] + if ev.Start.Before(to) && ev.End.After(from) { + idx = append(idx, h) + spans = append(spans, eventSpan{float64(max(ev.Start.Unix(), from.Unix())), float64(min(ev.End.Unix(), to.Unix()))}) + } + } + col, _ := eventColumns(spans) + for j, h := range idx { + if col[j] == 0 || len(out[i].rows) == 0 { + out[i].rows = append(out[i].rows, []int{h}) + } else { + last := len(out[i].rows) - 1 + out[i].rows[last] = append(out[i].rows[last], h) + } + } + out[i].n = len(idx) + } + return out +} + +// monthCell draws one day: number, chips and "+N". +func monthCell(c *ui.Context, day Date, month YearMonth, today Date, lay monthDay, events []CalendarEvent, maxRows int, + loc *time.Location, opts CalendarMonthViewOptions, r *CalendarViewResult, more *Date, apply func(CalendarChange, string)) { + k := Tokens(c) + d := Density(c) + cell := ui.Column(c).Grow(1).Basis(0).MinWidth(0).MinHeight(d.ControlHeight() * 3.5).Padding(d.Unit()).Gap(d.Unit()).Clip() + if id, ok := ui.Drop[monthDrag](cell); ok && !cell.IsDisabled() { + for _, ev := range events { + if ev.ID == string(id) { + apply(eventShift(c, ev, monthDays(ev.Start.In(loc), day), loc)) + } + } + } + if _, over := ui.DragOver[monthDrag](cell); over { + cell.Background(k.Selection) + cell.DrawOver(func(p *ui.Painter, rr ui.Rect) { datetimeSelectedMark(p, rr, k.Focus) }) + } + cell.Children(func() { + fg := k.Text + if day.Month != month.Month { + fg = k.TextMuted + } + num := ui.ButtonBase(c).Size(theme.MinHitSize, theme.MinHitSize).Radius(theme.MinHitSize / 2).Label(datetimeDayLabel(c, day)) + internal.Ring(num, k.Focus, theme.MinHitSize/2) + if day == today { + num.Background(k.Selection).Border(theme.BorderWidth, k.AccentText) + } else if num.Hovered() { + num.Background(k.SurfaceHover) + } + num.Children(func() { + t := ui.Text(c, strconv.Itoa(day.Day)).TextColor(fg).FontSize(FontSize(c, theme.CaptionSize)).FontFeatures("tnum") + if day == today { + t.Bold() + } + }) + if num.Clicked() && !num.IsDisabled() { + r.day = day + } + shown := 0 + for i, row := range lay.rows { + if i >= maxRows { + break + } + ui.Row(c).Gap(d.Unit() / 2).Children(func() { + for _, h := range row { + monthChip(c, events[h], loc, opts, r, apply) + shown++ + } + }) + } + if hidden := lay.n - shown; hidden > 0 { + b := ui.ButtonBase(c).MinHeight(theme.MinHitSize).Justify(ui.Start).PaddingX(d.Unit()).Radius(theme.ControlRadius). + Label(calendarCount(c, "calendar_month_view.more_label", hidden)) + internal.Ring(b, k.Focus, theme.ControlRadius) + if b.Hovered() { + b.Background(k.SurfaceHover) + } + b.Children(func() { + ui.Text(c, fmt.Sprintf(msg(c, "calendar_month_view.more"), hidden)).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.AccentText) + }) + if b.Clicked() && !b.IsDisabled() { + *more = day + } + open := *more == day + ui.PopoverBase(c, b, &open, func(panel *ui.Element) { + overlayStyle(c, panel, overlayEnter(c, panel)) + _, wh := c.Size() + panel.Padding(d.Unit() * 2).Gap(d.Unit()).MinWidth(d.ControlHeight() * 6).MaxHeight(wh / 2) + ui.Text(c, datetimeDayLabel(c, day)).Font(theme.SerifFont).TextColor(k.Text) + ui.Scroll(c).Shrink(1).Children(func() { + ui.Column(c).Gap(d.Unit()).Children(func() { + for _, row := range lay.rows { + for _, h := range row { + monthChip(c, events[h], loc, opts, r, apply) + } + } + }) + }) + }) + if !open && *more == day { + *more = Date{} + } + } + }) +} + +// monthChip is a draggable chip; Alt+arrows move it. +func monthChip(c *ui.Context, ev CalendarEvent, loc *time.Location, opts CalendarMonthViewOptions, r *CalendarViewResult, apply func(CalendarChange, string)) { + chip := EventChip(c, ev, EventChipOptions{Location: loc, Hour12: opts.Hour12, Inline: true}).Grow(1).Basis(0).MinWidth(theme.MinHitSize) + if chip.IsDisabled() { + return + } + chip.Drag(monthDrag(ev.ID)) + if chip.Clicked() { + r.opened = ev.ID + } + for key, days := range map[ui.Key]int{ui.KeyLeft: -1, ui.KeyRight: 1, ui.KeyUp: -7, ui.KeyDown: 7} { + if chip.Shortcut(ui.Alt, key) { + apply(eventShift(c, ev, days, loc)) + } + } +} + +// monthDays counts calendar days from t's day to day. +func monthDays(t time.Time, day Date) int { + return int(day.civil().Sub(DateOf(t).civil()).Hours() / 24) +} diff --git a/calendar_month_view_test.go b/calendar_month_view_test.go new file mode 100644 index 0000000..e955450 --- /dev/null +++ b/calendar_month_view_test.go @@ -0,0 +1,171 @@ +package mujica + +import ( + "fmt" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +type monthProbe struct { + month YearMonth + events []CalendarEvent + opts CalendarMonthViewOptions + opened []string + changes []CalendarChange + days []Date + disabled bool +} + +func (p *monthProbe) tester() *ui.Tester { + if p.month.IsZero() { + p.month = YearMonth{2026, time.October} + } + p.opts.Location, p.opts.Today = calTokyo, calendarToday + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + o := p.opts + o.Disabled = p.disabled + r := CalendarMonthView(c, &p.month, p.events, o) + if id, ok := r.Opened(); ok { + p.opened = append(p.opened, id) + } + if ch, ok := r.Changed(); ok { + p.changes = append(p.changes, ch) + } + if d, ok := r.DayChosen(); ok { + p.days = append(p.days, d) + } + }, 1000, 900) +} + +func TestCalendarMonthViewOverflowAndPopover(t *testing.T) { + p := &monthProbe{} + for i := range 5 { + p.events = append(p.events, calEvent(fmt.Sprint(i), 14, 8+2*i, 0, 60)) + } + tt := p.tester() + if !tt.HasText("+2") || tt.HasText("Event 3") { + t.Fatalf("3 rows then +2 expected: %v", tt.Texts()) + } + _ = tt.Click("2 more events") + if !tt.HasText("Event 4") { + t.Fatal("+N should list the hidden events") + } + _ = tt.Click("Event 4, 16:00 – 17:00") + if len(p.opened) != 1 || p.opened[0] != "4" { + t.Fatalf("opened %v", p.opened) + } +} + +func TestCalendarMonthViewOverlapSideBySide(t *testing.T) { + p := &monthProbe{events: []CalendarEvent{calEvent("a", 14, 9, 0, 120), calEvent("b", 14, 10, 0, 60), calEvent("c", 14, 15, 0, 60)}} + tt := p.tester() + a, _ := tt.Find("Event a, 09:00 – 11:00") + b, _ := tt.Find("Event b, 10:00 – 11:00") + cc, _ := tt.Find("Event c, 15:00 – 16:00") + if a.Y != b.Y || b.X <= a.X || cc.Y <= a.Y { + t.Fatalf("overlapping events should share a row: %v %v %v", a, b, cc) + } +} + +func TestCalendarMonthViewDragAndKeys(t *testing.T) { + p := &monthProbe{events: []CalendarEvent{calEvent("a", 14, 9, 30, 60)}} + tt := p.tester() + chip, _ := tt.Find("Event a, 09:30 – 10:30") + target, _ := tt.Find(datetimeTestLabel(oct(16))) + tt.Press(chip.X+10, chip.Y+5) + for i := 1; i <= 4; i++ { + f := float32(i) / 4 + tt.Move(chip.X+10+(target.X+20-chip.X-10)*f, chip.Y+5+(target.Y+40-chip.Y-5)*f) + } + tt.Release(target.X+20, target.Y+40) + want := time.Date(2026, time.October, 16, 9, 30, 0, 0, calTokyo) + if len(p.changes) != 1 || !p.changes[0].Start.Equal(want) || p.changes[0].End.Sub(p.changes[0].Start) != time.Hour { + t.Fatalf("drop gave %+v", p.changes) + } + _ = tt.Click("Event a, 09:30 – 10:30") + tt.Key(ui.Alt, ui.KeyDown) + if len(p.changes) != 2 || !p.changes[1].Start.Equal(time.Date(2026, time.October, 21, 9, 30, 0, 0, calTokyo)) { + t.Fatalf("Alt+Down gave %+v", p.changes) + } +} + +func TestCalendarMonthViewDSTGapReported(t *testing.T) { + ny, err := time.LoadLocation("America/New_York") + if err != nil { + t.Fatal(err) + } + ev := CalendarEvent{ID: "g", Title: "Early", Start: time.Date(2026, time.March, 7, 2, 30, 0, 0, ny)} + ev.End = ev.Start.Add(time.Hour) + p := &monthProbe{month: YearMonth{2026, time.March}, events: []CalendarEvent{ev}} + p.opts.Location = ny + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if ch, ok := CalendarMonthView(c, &p.month, p.events, CalendarMonthViewOptions{Location: ny, Today: Date{2026, time.March, 1}}).Changed(); ok { + p.changes = append(p.changes, ch) + } + }, 1000, 900) + _ = tt.Click("Early, 02:30 – 03:30") + tt.Key(ui.Alt, ui.KeyRight) + if len(p.changes) != 0 || !tt.HasText("2026-03-08 02:30 does not exist in America/New_York") { + t.Fatalf("gap not reported: %v", tt.Texts()) + } +} + +func TestCalendarMonthViewNavigationDayAndDisabled(t *testing.T) { + p := &monthProbe{events: []CalendarEvent{calEvent("a", 14, 9, 0, 60)}} + tt := p.tester() + _ = tt.Click(datetimeTestLabel(oct(20))) + _ = tt.Click("Next month") + if len(p.days) != 1 || p.days[0] != oct(20) || p.month != (YearMonth{2026, time.November}) { + t.Fatalf("day %v month %v", p.days, p.month) + } + p.month, p.disabled = YearMonth{2026, time.October}, true + tt.Frame() + _ = tt.Click("Next month") + _ = tt.Click("Event a, 09:00 – 10:00") + tt.Key(ui.Alt, ui.KeyRight) + if p.month != (YearMonth{2026, time.October}) || len(p.opened) != 0 || len(p.changes) != 0 { + t.Fatal("disabled view reacted") + } +} + +func TestCalendarMonthViewLargeDataAndInvalid(t *testing.T) { + p := &monthProbe{} + base := time.Date(2000, 1, 1, 9, 0, 0, 0, calTokyo) + for i := range 100000 { + s := base.Add(time.Duration(i) * 3 * time.Hour) + p.events = append(p.events, CalendarEvent{ID: fmt.Sprint(i), Title: "E", Start: s, End: s.Add(time.Hour)}) + } + tt := p.tester() + if n := len(tt.Texts()); n > 800 { + t.Fatalf("built %d labels for one month", n) + } + for _, bad := range []func(){ + func() { q := &monthProbe{events: []CalendarEvent{{ID: "x", Start: base, End: base}}}; q.tester() }, + func() { q := &monthProbe{opts: CalendarMonthViewOptions{MaxPerDay: -1}}; q.tester() }, + } { + func() { + defer func() { + if recover() == nil { + t.Error("expected panic") + } + }() + bad() + }() + } +} + +func TestCalendarMonthViewSnapshot(t *testing.T) { + m := YearMonth{2026, time.October} + evs := []CalendarEvent{calEvent("1", 6, 9, 0, 60), calEvent("2", 14, 9, 0, 120), calEvent("3", 14, 10, 0, 30), + calEvent("4", 14, 13, 0, 30), calEvent("5", 14, 15, 0, 30), calEvent("6", 14, 17, 0, 30), calEvent("7", 22, 18, 0, 60)} + evs[1].Color, evs[2].Color, evs[6].Color = EventInfo, EventSuccess, EventWarning + snapshot(t, "calendar_month_view", 900, 860, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + CalendarMonthView(c, &m, evs, CalendarMonthViewOptions{Location: calTokyo, Today: calendarToday}) + }) + }) +} diff --git a/calendar_time_grid.go b/calendar_time_grid.go new file mode 100644 index 0000000..3b241bc --- /dev/null +++ b/calendar_time_grid.go @@ -0,0 +1,369 @@ +package mujica + +import ( + "fmt" + "log/slog" + "math" + "strconv" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// timeGridConfig is what the week and day views share. +type timeGridConfig struct { + name string + loc *time.Location + version int + slot int + today Date + now time.Time + hour12 bool +} + +// timeGesture is a drag in progress on the time grid. +type timeGesture struct { + active bool + kind CalendarChangeKind + id string + day int + anchor int + dx, dy float32 + cur int +} + +// timeGridDay is one column's timed and all-day events. +type timeGridDay struct { + timed []timePlaced + allDay []int +} + +type timePlaced struct { + ev int + from, to int + col, cols int +} + +// timeGridSlot checks and defaults the slot length. +func timeGridSlot(name string, slot int) int { + if slot == 0 { + return 30 + } + if slot < 0 || 60%slot != 0 && slot%60 != 0 { + panic(fmt.Sprintf("mujica: %s SlotMinutes %d must divide an hour", name, slot)) + } + return slot +} + +// timeGrid draws day columns and turns gestures into changes. +func timeGrid(c *ui.Context, root *ui.Element, days []Date, events []CalendarEvent, cfg timeGridConfig, r *CalendarViewResult) { + k := Tokens(c) + d := Density(c) + hourH := d.ControlHeight() * 2 + slotH := hourH * float32(cfg.slot) / 60 + g := *ui.Local(root, "time-grid-gesture", func() *timeGesture { return &timeGesture{} }) + morning := func() []int { + v := make([]int, len(days)) + for i := range v { + v[i] = 8 * 60 / cfg.slot + } + return v + } + cursor := ui.Local(root, "time-grid-cursor", morning) + if len(*cursor) != len(days) { + *cursor = morning() + } + problem := ui.Local(root, "time-grid-problem", func() string { return "" }) + scroll := ui.Local(root, "time-grid-scroll", func() *ui.ScrollState { return &ui.ScrollState{Y: hourH * 8} }) + lay := eventsDerived(root, "time-grid-layout", events, cfg.version, eventDayStart(days[0], cfg.loc), + eventDayStart(days[len(days)-1].AddDays(1), cfg.loc), func(hits []int) []timeGridDay { return timeGridLayout(events, hits, days, cfg.loc) }) + apply := func(ch CalendarChange, p string) { + *problem = p + if p == "" && !root.IsDisabled() { + slog.Debug("mujica: "+cfg.name+" change", "kind", ch.Kind, "id", ch.ID, "start", ch.Start, "end", ch.End) + r.change = &ch + } + } + gutter := d.ControlHeight() * 1.6 + ui.Row(c).Children(func() { + ui.Box(c).Width(gutter).Shrink(0) + for _, day := range days { + wd := msg(c, "calendar.weekday_"+strconv.Itoa(int(day.Weekday()))) + b := ui.ButtonBase(c).Grow(1).Basis(0).MinHeight(theme.MinHitSize).Gap(d.Unit()).Radius(theme.ControlRadius).Label(datetimeDayLabel(c, day)) + internal.Ring(b, k.Focus, theme.ControlRadius) + if day == cfg.today { + b.Background(k.Selection) + } else if b.Hovered() { + b.Background(k.SurfaceHover) + } + b.Children(func() { + ui.Text(c, wd).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + t := ui.Text(c, strconv.Itoa(day.Day)).TextColor(k.Text).FontFeatures("tnum") + if day == cfg.today { + t.Bold().TextColor(k.AccentText) + } + }) + if b.Clicked() && !b.IsDisabled() { + r.day = day + } + } + }) + ui.Row(c).BorderWidth(0, 0, theme.BorderWidth, 0).BorderColor(k.Border).Children(func() { + ui.Text(c, msg(c, "calendar_week_view.all_day")).Width(gutter).Shrink(0).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted). + Padding(d.Unit()) + for i, day := range days { + cell := ui.Column(c).Grow(1).Basis(0).MinWidth(0).MinHeight(theme.MinHitSize).Padding(d.Unit() / 2).Gap(d.Unit() / 2) + if id, ok := ui.Drop[monthDrag](cell); ok && !cell.IsDisabled() { + for _, ev := range events { + if ev.ID == string(id) { + apply(eventShift(c, ev, monthDays(ev.Start.In(cfg.loc), day), cfg.loc)) + } + } + } + cell.Children(func() { + for _, h := range lay[i].allDay { + monthChip(c, events[h], cfg.loc, CalendarMonthViewOptions{Hour12: cfg.hour12}, r, apply) + } + }) + } + }) + ui.Scroll(c).TrackScroll(*scroll).Height(hourH * 9).Children(func() { + ui.Row(c).Children(func() { + ui.Column(c).Width(gutter).Shrink(0).Children(func() { + for h := range 24 { + ui.Text(c, timeText(c, TimeOfDay{h, 0, 0}, timeConfig{hour12: cfg.hour12})).Height(hourH). + FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).FontFeatures("tnum").PaddingX(d.Unit()) + } + }) + for i, day := range days { + timeColumn(c, i, day, lay[i], events, cfg, hourH, slotH, g, &(*cursor)[i], r, apply) + } + }) + }) + datetimeError(c, *problem) +} + +// timeGridLayout places each day's events in minutes with side-by-side columns. +func timeGridLayout(events []CalendarEvent, hits []int, days []Date, loc *time.Location) []timeGridDay { + out := make([]timeGridDay, len(days)) + for i, day := range days { + from, to := eventDayStart(day, loc), eventDayStart(day.AddDays(1), loc) + var spans []eventSpan + for _, h := range hits { + ev := events[h] + if !ev.Start.Before(to) || !ev.End.After(from) { + continue + } + if ev.AllDay || ev.End.Sub(ev.Start) >= 24*time.Hour { + out[i].allDay = append(out[i].allDay, h) + continue + } + a, b := 0, 24*60 + if !ev.Start.Before(from) { + a = timeWallMinutes(ev.Start.In(loc)) + } + if ev.End.Before(to) { + b = timeWallMinutes(ev.End.In(loc)) + } + b = max(b, a+1) + out[i].timed = append(out[i].timed, timePlaced{ev: h, from: a, to: b}) + spans = append(spans, eventSpan{float64(a), float64(b)}) + } + col, cols := eventColumns(spans) + for j := range out[i].timed { + out[i].timed[j].col, out[i].timed[j].cols = col[j], cols[j] + } + } + return out +} + +func timeWallMinutes(t time.Time) int { return t.Hour()*60 + t.Minute() } + +// timeColumn draws one day: lines, events, preview and cursor. +func timeColumn(c *ui.Context, i int, day Date, lay timeGridDay, events []CalendarEvent, cfg timeGridConfig, hourH, slotH float32, + g *timeGesture, cursor *int, r *CalendarViewResult, apply func(CalendarChange, string)) { + k := Tokens(c) + slots := 24 * 60 / cfg.slot + col := ui.Box(c).Grow(1).Basis(0).MinWidth(0).Height(hourH*24).Focusable(). + Role(ui.RoleGroup).Label(fmt.Sprintf(msg(c, "calendar_week_view.column"), datetimeDayLabel(c, day))).BorderWidth(0, 0, 0, theme.BorderWidth).BorderColor(k.Border) + disabled := col.IsDisabled() + slotOf := func(y float32) int { return max(0, min(slots-1, int(y/slotH))) } + if !disabled { + switch { + case col.Shortcut(0, ui.KeyUp): + *cursor = max(0, *cursor-1) + case col.Shortcut(0, ui.KeyDown): + *cursor = min(slots-1, *cursor+1) + case col.Shortcut(0, ui.KeyEnter): + apply(timeCreate(c, day, *cursor, *cursor+1, cfg)) + } + _, py, _ := col.PointerPosition() + dx, dy, pressing := col.Dragged() + if pressing && !g.active { + *g = timeGesture{active: true, kind: CalendarCreate, day: i, anchor: slotOf(py - dy), cur: slotOf(py)} + } + if g.active && g.kind == CalendarCreate && g.day == i { + if pressing { + g.dx, g.dy = g.dx+dx, g.dy+dy + g.cur = slotOf(py) + } else { + a, b := min(g.anchor, g.cur), max(g.anchor, g.cur)+1 + if math.Abs(float64(g.dy)) >= 4 { + apply(timeCreate(c, day, a, b, cfg)) + } + *cursor = g.anchor + *g = timeGesture{} + } + } + } + focused := col.Focused() + cur := *cursor + creating := g.active && g.kind == CalendarCreate && g.day == i + ga, gb := min(g.anchor, g.cur), max(g.anchor, g.cur)+1 + col.Draw(func(p *ui.Painter, rr ui.Rect) { + for h := 1; h < 24; h++ { + internal.Rule(p, rr.X, rr.X+rr.W, rr.Y+float32(h)*hourH, k.Border) + } + if focused { + box := ui.Rect{X: rr.X + 2, Y: rr.Y + float32(cur)*slotH + 1, W: rr.W - 4, H: slotH - 2} + p.Fill(box, k.Selection, theme.ControlRadius) + datetimeSelectedMark(p, box, k.Focus) + } + if creating { + box := ui.Rect{X: rr.X + 2, Y: rr.Y + float32(ga)*slotH, W: rr.W - 4, H: float32(gb-ga) * slotH} + p.Fill(box, k.Selection, theme.ControlRadius) + p.StrokeDashed(box, k.AccentText, theme.ControlRadius, theme.BorderWidth) + } + }) + col.Children(func() { + now := cfg.now + if now.IsZero() { + now = c.Now() + } + for _, pl := range lay.timed { + timeChip(c, i, pl, events[pl.ev], cfg, hourH, slotH, g, r, apply) + } + if day == DateOf(now.In(cfg.loc)) { + CurrentTimeIndicator(c, CurrentTimeIndicatorOptions{Location: cfg.loc, Day: day, Now: cfg.now, Hour12: cfg.hour12}) + } + }) +} + +// timeChip places an event; drag moves, bottom edge resizes. +func timeChip(c *ui.Context, i int, pl timePlaced, ev CalendarEvent, cfg timeGridConfig, hourH, slotH float32, + g *timeGesture, r *CalendarViewResult, apply func(CalendarChange, string)) { + from, to := float32(pl.from)*hourH/60, float32(pl.to)*hourH/60 + mine := g.active && g.id == ev.ID && g.day == i + snap := func(v float32) int { return int(math.Round(float64(v/slotH))) * cfg.slot } + var shiftY, growY float32 + if mine && g.kind == CalendarMove { + shiftY = float32(snap(g.dy)) * hourH / 60 + } + if mine && g.kind == CalendarResize { + growY = float32(snap(g.dy)) * hourH / 60 + } + box := ui.Box(c).Key(ev.ID).Absolute().Top(from + shiftY).Height(max(to-from+growY, theme.MinHitSize)). + LeftPercent(100 * float32(pl.col) / float32(pl.cols)).WidthPercent(100 / float32(pl.cols)).Padding(1) + box.Children(func() { + chip := EventChip(c, ev, EventChipOptions{Location: cfg.loc, Hour12: cfg.hour12, Selected: mine, Inline: to-from < hourH*0.75}).Fill() + handle := ui.Box(c).Absolute().Left(0).Right(0).Bottom(0).Height(6).Cursor(ui.CursorResizeNS).Label(fmt.Sprintf(msg(c, "calendar_week_view.resize"), ev.Title)) + if chip.IsDisabled() { + return + } + if chip.Clicked() && !mine { + r.opened = ev.ID + } + for key, dm := range map[ui.Key]int{ui.KeyUp: -cfg.slot, ui.KeyDown: cfg.slot} { + if chip.Shortcut(ui.Alt, key) { + apply(timeMove(c, ev, 0, dm, cfg)) + } + if chip.Shortcut(ui.Alt|ui.Shift, key) { + apply(timeResize(c, ev, dm, cfg)) + } + } + for key, dd := range map[ui.Key]int{ui.KeyLeft: -1, ui.KeyRight: 1} { + if chip.Shortcut(ui.Alt, key) { + apply(timeMove(c, ev, dd, 0, cfg)) + } + } + for _, part := range []struct { + e *ui.Element + kind CalendarChangeKind + }{{chip, CalendarMove}, {handle, CalendarResize}} { + dx, dy, ok := part.e.Dragged() + switch { + case ok && (!g.active && (dx != 0 || dy != 0) || mine && g.kind == part.kind): + if !g.active { + *g = timeGesture{active: true, kind: part.kind, id: ev.ID, day: i} + } + g.dx, g.dy = g.dx+dx, g.dy+dy + case !ok && mine && g.kind == part.kind: + dm := snap(g.dy) + if part.kind == CalendarResize { + if dm != 0 { + apply(timeResize(c, ev, dm, cfg)) + } + } else if dd := int(math.Round(float64(g.dx / max(chip.Bounds().W*float32(pl.cols), 1)))); dm != 0 || dd != 0 { + apply(timeMove(c, ev, dd, dm, cfg)) + } + *g = timeGesture{} + } + } + }) +} + +// timeCreate makes an event over slots [a, b). +func timeCreate(c *ui.Context, day Date, a, b int, cfg timeGridConfig) (CalendarChange, string) { + s, sn := timeAt(day, a*cfg.slot, cfg.loc) + e, en := timeAt(day, b*cfg.slot, cfg.loc) + if p := eventWallProblem(c, timeDay(day, a*cfg.slot), timeWall(a*cfg.slot), cfg.loc, sn); p != "" { + return CalendarChange{}, p + } + if p := eventWallProblem(c, timeDay(day, b*cfg.slot), timeWall(b*cfg.slot), cfg.loc, en); p != "" { + return CalendarChange{}, p + } + return CalendarChange{Kind: CalendarCreate, Start: s, End: e}, "" +} + +// timeMove shifts ev by days and minutes of wall time. +func timeMove(c *ui.Context, ev CalendarEvent, days, minutes int, cfg timeGridConfig) (CalendarChange, string) { + s := ev.Start.In(cfg.loc) + day := DateOf(s).AddDays(days) + m := timeWallMinutes(s) + minutes + at, n := timeAt(day, m, cfg.loc) + if p := eventWallProblem(c, timeDay(day, m), timeWall(m), cfg.loc, n); p != "" { + return CalendarChange{}, p + } + return CalendarChange{Kind: CalendarMove, ID: ev.ID, Start: at, End: at.Add(ev.End.Sub(ev.Start))}, "" +} + +// timeResize moves ev's end by minutes of wall time. +func timeResize(c *ui.Context, ev CalendarEvent, minutes int, cfg timeGridConfig) (CalendarChange, string) { + e := ev.End.In(cfg.loc) + day, m := DateOf(e), timeWallMinutes(e)+minutes + at, n := timeAt(day, m, cfg.loc) + if p := eventWallProblem(c, timeDay(day, m), timeWall(m), cfg.loc, n); p != "" { + return CalendarChange{}, p + } + if !at.After(ev.Start) { + return CalendarChange{}, msg(c, "calendar_week_view.too_short") + } + return CalendarChange{Kind: CalendarResize, ID: ev.ID, Start: ev.Start, End: at}, "" +} + +// timeAt resolves minute m of day as wall time. +func timeAt(day Date, m int, loc *time.Location) (time.Time, int) { + return dateTimeResolve(timeDay(day, m), timeWall(m), loc) +} + +func timeDay(day Date, m int) Date { + return day.AddDays(int(math.Floor(float64(m) / (24 * 60)))) +} + +func timeWall(m int) TimeOfDay { + m = ((m % (24 * 60)) + 24*60) % (24 * 60) + return TimeOfDay{m / 60, m % 60, 0} +} diff --git a/calendar_week_view.go b/calendar_week_view.go new file mode 100644 index 0000000..bf24605 --- /dev/null +++ b/calendar_week_view.go @@ -0,0 +1,80 @@ +package mujica + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// CalendarWeekViewOptions configure a CalendarWeekView. +type CalendarWeekViewOptions struct { + // Location is the zone days are cut in; required. + Location *time.Location + // Version must change when events change in place. + Version int + WeekStart WeekStart + // SlotMinutes is the grid step; zero means 30. + SlotMinutes int + // Today is marked; zero uses the system clock. + Today Date + // Now places the current-time line; zero uses the system clock. + Now time.Time + Hour12 bool + Disabled bool + Label string +} + +// CalendarWeekView shows *week as a time grid; drags edit events. +func CalendarWeekView(c *ui.Context, week *Date, events []CalendarEvent, opts CalendarWeekViewOptions) CalendarViewResult { + datetimeCheckDate("CalendarWeekView week", *week) + if week.IsZero() { + panic("mujica: CalendarWeekView needs a week") + } + cfg := timeGridConfig{name: "calendar_week_view", loc: eventLocation("CalendarWeekView", opts.Location), version: opts.Version, + slot: timeGridSlot("CalendarWeekView", opts.SlotMinutes), today: datetimeToday(c, opts.Today), now: opts.Now, hour12: opts.Hour12} + eventsCheck("CalendarWeekView", events) + first := calendarFirstWeekday(c, opts.WeekStart) + start := week.AddDays(-((int(week.Weekday()) - int(first) + 7) % 7)) + days := make([]Date, 7) + for i := range days { + days[i] = start.AddDays(i) + } + title := weekViewTitle(c, start, start.AddDays(6)) + label := opts.Label + if label == "" { + label = title + } + r := CalendarViewResult{} + root := ui.Column(c).Gap(Density(c).Unit()).Role(ui.RoleGroup).Label(label).Disabled(opts.Disabled) + r.Element = root + root.Children(func() { + calendarViewHeader(c, title, msg(c, "calendar_week_view.prev"), msg(c, "calendar_week_view.next"), func(dir int) { + *week = week.AddDays(7 * dir) + }) + timeGrid(c, root, days, events, cfg, &r) + }) + return r +} + +// calendarViewHeader is the title row with previous and next buttons. +func calendarViewHeader(c *ui.Context, title, prev, next string, step func(dir int)) { + k := Tokens(c) + ui.Row(c).AlignItems(ui.Center).Gap(Density(c).Unit()).Children(func() { + if b := iconAction(c, icons.Must("chevron-left"), prev); b.Clicked() && !b.IsDisabled() { + step(-1) + } + ui.Text(c, title).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).TextColor(k.Text).Grow(1).TextAlign(ui.Center) + if b := iconAction(c, icons.Must("chevron-right"), next); b.Clicked() && !b.IsDisabled() { + step(1) + } + }) +} + +// weekViewTitle names a span of days. +func weekViewTitle(c *ui.Context, a, b Date) string { + return fmt.Sprintf(msg(c, "calendar_week_view.title"), datetimeMonthName(c, a.Month), a.Day, datetimeMonthName(c, b.Month), b.Day, b.Year) +} diff --git a/calendar_week_view_test.go b/calendar_week_view_test.go new file mode 100644 index 0000000..63a5ea4 --- /dev/null +++ b/calendar_week_view_test.go @@ -0,0 +1,175 @@ +package mujica + +import ( + "fmt" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +type weekProbe struct { + week Date + events []CalendarEvent + opts CalendarWeekViewOptions + changes []CalendarChange + opened []string + disabled bool +} + +func (p *weekProbe) tester() *ui.Tester { + if p.week.IsZero() { + p.week = oct(14) + } + p.opts.Location, p.opts.Today = calTokyo, calendarToday + p.opts.Now = time.Date(2026, time.October, 14, 10, 30, 0, 0, calTokyo) + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + o := p.opts + o.Disabled = p.disabled + r := CalendarWeekView(c, &p.week, p.events, o) + if ch, ok := r.Changed(); ok { + p.changes = append(p.changes, ch) + } + if id, ok := r.Opened(); ok { + p.opened = append(p.opened, id) + } + }, 1100, 900) +} + +func calDrag(tt *ui.Tester, x0, y0, x1, y1 float32) { + tt.Press(x0, y0) + for i := 1; i <= 4; i++ { + f := float32(i) / 4 + tt.Move(x0+(x1-x0)*f, y0+(y1-y0)*f) + } + tt.Release(x1, y1) +} + +func calAt(t *testing.T, h, m int, day int) time.Time { + t.Helper() + return time.Date(2026, time.October, day, h, m, 0, 0, calTokyo) +} + +func TestCalendarWeekViewDragCreateAndKeyboardCreate(t *testing.T) { + p := &weekProbe{} + tt := p.tester() + col, ok := tt.Find("Schedule, " + datetimeTestLabel(oct(15))) + if !ok { + t.Fatal("no column") + } + hourH := float32(72) + // Drag 9:00 to 10:30; the visible top is 8:00. + y9 := col.Y + hourH + 5 + calDrag(tt, col.X+20, y9, col.X+20, y9+hourH*1.5) + if len(p.changes) != 1 || p.changes[0].Kind != CalendarCreate || !p.changes[0].Start.Equal(calAt(t, 9, 0, 15)) || !p.changes[0].End.Equal(calAt(t, 11, 0, 15)) { + t.Fatalf("drag create %+v", p.changes) + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if len(p.changes) != 2 || !p.changes[1].Start.Equal(calAt(t, 9, 30, 15)) || !p.changes[1].End.Equal(calAt(t, 10, 0, 15)) { + t.Fatalf("keyboard create %+v", p.changes) + } +} + +func TestCalendarWeekViewMoveResizeAndOverlap(t *testing.T) { + p := &weekProbe{events: []CalendarEvent{calEvent("a", 14, 9, 0, 60), calEvent("b", 14, 9, 30, 60)}} + tt := p.tester() + a, _ := tt.Find("Event a, 09:00 – 10:00") + b, _ := tt.Find("Event b, 09:30 – 10:30") + if b.X <= a.X || b.X-a.X < a.W/2 || b.Y <= a.Y { + t.Fatalf("overlapping events should sit side by side: %v %v", a, b) + } + calDrag(tt, a.X+10, a.Y+20, a.X+10, a.Y+20+72) + if len(p.changes) != 1 || p.changes[0].Kind != CalendarMove || !p.changes[0].Start.Equal(calAt(t, 10, 0, 14)) || !p.changes[0].End.Equal(calAt(t, 11, 0, 14)) { + t.Fatalf("move %+v", p.changes) + } + h, _ := tt.Find("Resize Event b") + calDrag(tt, h.X+10, h.Y+3, h.X+10, h.Y+3+36) + if len(p.changes) != 2 || p.changes[1].Kind != CalendarResize || !p.changes[1].End.Equal(calAt(t, 11, 0, 14)) { + t.Fatalf("resize %+v", p.changes) + } + _ = tt.Click("Event a, 09:00 – 10:00") + if len(p.opened) != 1 { + t.Fatalf("click should open: %v", p.opened) + } + tt.Key(ui.Alt, ui.KeyRight) + tt.Key(ui.Alt, ui.KeyDown) + tt.Key(ui.Alt|ui.Shift, ui.KeyUp) + if len(p.changes) != 5 || !p.changes[2].Start.Equal(calAt(t, 9, 0, 15)) || !p.changes[3].Start.Equal(calAt(t, 9, 30, 14)) || + !p.changes[4].End.Equal(calAt(t, 9, 30, 14)) { + t.Fatalf("keyboard changes %+v", p.changes[2:]) + } +} + +func TestCalendarWeekViewAllDayWeekStartAndNav(t *testing.T) { + ev := calEvent("h", 16, 0, 0, 24*60) + ev.AllDay, ev.Title = true, "Holiday" + p := &weekProbe{events: []CalendarEvent{ev}, opts: CalendarWeekViewOptions{WeekStart: WeekStartMonday}} + tt := p.tester() + if !tt.HasText("October 12 – October 18, 2026") || !tt.HasText("All day") || !tt.HasText("Holiday") { + t.Fatalf("texts %v", tt.Texts()[:12]) + } + _ = tt.Click("Holiday, All day") + tt.Key(ui.Alt, ui.KeyRight) + if len(p.changes) != 1 || !p.changes[0].Start.Equal(calAt(t, 0, 0, 17)) || !p.changes[0].AllDay { + t.Fatalf("all-day move %+v", p.changes) + } + _ = tt.Click("Next week") + if p.week != oct(21) { + t.Fatalf("week %v", p.week) + } +} + +func TestCalendarWeekViewDisabledAndInvalid(t *testing.T) { + p := &weekProbe{events: []CalendarEvent{calEvent("a", 14, 9, 0, 60)}, disabled: true} + tt := p.tester() + a, _ := tt.Find("Event a, 09:00 – 10:00") + calDrag(tt, a.X+10, a.Y+20, a.X+10, a.Y+92) + _ = tt.Click("Event a, 09:00 – 10:00") + tt.Key(ui.Alt, ui.KeyDown) + _ = tt.Click("Next week") + if len(p.changes) != 0 || len(p.opened) != 0 || p.week != oct(14) { + t.Fatal("disabled week view reacted") + } + for _, opts := range []CalendarWeekViewOptions{{SlotMinutes: 7}, {SlotMinutes: -15}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%+v: expected panic", opts) + } + }() + q := &weekProbe{opts: opts} + q.tester() + }() + } +} + +func TestCalendarWeekViewLargeData(t *testing.T) { + p := &weekProbe{} + base := time.Date(2000, 1, 1, 9, 0, 0, 0, calTokyo) + for i := range 100000 { + s := base.Add(time.Duration(i) * 3 * time.Hour) + p.events = append(p.events, CalendarEvent{ID: fmt.Sprint(i), Title: "E", Start: s, End: s.Add(time.Hour)}) + } + tt := p.tester() + if n := len(tt.Texts()); n > 400 { + t.Fatalf("built %d labels for one week", n) + } +} + +func TestCalendarWeekViewSnapshot(t *testing.T) { + w := oct(14) + evs := []CalendarEvent{calEvent("1", 12, 9, 0, 60), calEvent("2", 14, 9, 0, 120), calEvent("3", 14, 9, 30, 60), + calEvent("4", 15, 13, 0, 90), calEvent("5", 16, 10, 0, 45)} + evs[1].Color, evs[2].Color, evs[3].Color = EventInfo, EventSuccess, EventWarning + h := calEvent("h", 13, 0, 0, 24*60) + h.AllDay, h.Title = true, "Holiday" + evs = append(evs, h) + snapshot(t, "calendar_week_view", 1000, 860, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + CalendarWeekView(c, &w, evs, CalendarWeekViewOptions{Location: calTokyo, Today: calendarToday, + Now: time.Date(2026, time.October, 14, 10, 30, 0, 0, calTokyo)}) + }) + }) +} diff --git a/countdown.go b/countdown.go new file mode 100644 index 0000000..4afc585 --- /dev/null +++ b/countdown.go @@ -0,0 +1,103 @@ +package mujica + +import ( + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// CountdownFormat chooses how the time left reads. +type CountdownFormat int + +const ( + // CountdownClock reads 01:02:03, with days as "2d" first. + CountdownClock CountdownFormat = iota + // CountdownWords reads "1 h 2 min 3 s". + CountdownWords +) + +// CountdownOptions configure a Countdown. +type CountdownOptions struct { + Format CountdownFormat + // Now fixes the clock and stops updates. + Now time.Time + Label string +} + +// CountdownResult is the countdown and its finish. +type CountdownResult struct { + Element *ui.Element + finished bool +} + +// Finished reports reaching zero, once per deadline. +func (r CountdownResult) Finished() bool { return r.finished } + +// Countdown shows the time left, ticking each second while shown. +func Countdown(c *ui.Context, deadline time.Time, opts CountdownOptions) CountdownResult { + if opts.Format < CountdownClock || opts.Format > CountdownWords { + panic(fmt.Sprintf("mujica: Countdown Format %d out of range", opts.Format)) + } + k := Tokens(c) + now := opts.Now + live := now.IsZero() + if live { + now = c.Now() + } + left := max(deadline.Sub(now), 0) + shown := left.Truncate(time.Second) + if left%time.Second != 0 { + shown += time.Second + } + label := opts.Label + if label == "" { + label = msg(c, "countdown.label") + } + text := CountdownText(c, shown, opts.Format) + e := ui.Text(c, text).Font(theme.MonoFont).FontSize(FontSize(c, theme.H2Size)).TextColor(k.Text).FontFeatures("tnum"). + Label(label + ", " + CountdownText(c, shown, CountdownWords)) + r := CountdownResult{Element: e} + fired := ui.Local(e, "countdown-fired", func() time.Time { return time.Time{} }) + switch { + case left == 0 && !fired.Equal(deadline): + *fired, r.finished = deadline, true + slog.Debug("mujica: countdown finished", "deadline", deadline) + c.Announce(fmt.Sprintf(msg(c, "countdown.done"), label)) + case left > 0 && live: + c.After(left % time.Second) + if left%time.Second == 0 { + c.After(time.Second) + } + } + if left == 0 { + e.TextColor(k.AccentText) + } + return r +} + +// CountdownText formats a non-negative duration in whole seconds. +func CountdownText(c *ui.Context, d time.Duration, f CountdownFormat) string { + s := int(d / time.Second) + days, h, m, sec := s/86400, s%86400/3600, s%3600/60, s%60 + if f == CountdownClock { + t := fmt.Sprintf("%02d:%02d:%02d", h, m, sec) + if days > 0 { + t = fmt.Sprintf(msg(c, "countdown.days_clock"), days) + " " + t + } + return t + } + out := "" + for i, v := range []int{days, h, m, sec} { + if v > 0 || i == 3 && out == "" { + if out != "" { + out += " " + } + out += fmt.Sprintf(msg(c, []string{"countdown.d", "countdown.h", "countdown.m", "countdown.s"}[i]), v) + } + } + return out +} diff --git a/countdown_test.go b/countdown_test.go new file mode 100644 index 0000000..470b2e0 --- /dev/null +++ b/countdown_test.go @@ -0,0 +1,69 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func TestCountdownFormatsAndFinishesOnce(t *testing.T) { + deadline := time.Date(2026, time.October, 5, 12, 0, 0, 0, calTokyo) + now, n := deadline.Add(-(26*time.Hour + 3*time.Minute + 4*time.Second + 500*time.Millisecond)), 0 + format := CountdownClock + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if Countdown(c, deadline, CountdownOptions{Now: now, Format: format}).Finished() { + n++ + } + }, 400, 120) + if !tt.HasText("Time left, 1 d 2 h 3 min 5 s") { + t.Fatalf("label %v", tt.Texts()) + } + var clock, words string + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + clock, words = CountdownText(c, 26*time.Hour+3*time.Minute+5*time.Second, CountdownClock), CountdownText(c, 0, CountdownWords) + }, 10, 10) + if clock != "1d 02:03:05" || words != "0 s" { + t.Fatalf("formats %q %q", clock, words) + } + format = CountdownWords + now = deadline.Add(time.Second) + tt.Frame() + tt.Frame() + if n != 1 || !tt.HasText("Time left, 0 s") { + t.Fatalf("finished %d times, %v", n, tt.Texts()) + } + if a := tt.Announcements(); len(a) != 1 || a[0] != "Time left: time is up." { + t.Fatalf("announcements %q", a) + } + deadline = deadline.Add(time.Minute) + now = deadline + tt.Frame() + if n != 2 { + t.Fatal("a new deadline should finish again") + } +} + +func TestCountdownInvalidFormat(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("expected panic") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + Countdown(c, time.Now(), CountdownOptions{Format: 7}) + }, 10, 10) +} + +func TestCountdownSnapshot(t *testing.T) { + deadline := time.Date(2026, time.October, 5, 12, 0, 0, 0, calTokyo) + snapshot(t, "countdown", 320, 140, func(c *ui.Context) { + ui.Column(c).Padding(16).Gap(8).Children(func() { + Countdown(c, deadline, CountdownOptions{Now: deadline.Add(-(3*time.Hour + 25*time.Second))}) + Countdown(c, deadline, CountdownOptions{Now: deadline.Add(-90 * time.Second), Format: CountdownWords}) + }) + }) +} diff --git a/cron_editor.go b/cron_editor.go new file mode 100644 index 0000000..cf36e19 --- /dev/null +++ b/cron_editor.go @@ -0,0 +1,346 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strconv" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// CronSchedule is a parsed five-field cron expression. +type CronSchedule struct { + fields [5]uint64 + tokens [5]string + // domAny and dowAny note a "*" day field. + domAny, dowAny bool +} + +// CronProblem is what is wrong with a cron field. +type CronProblem int + +const ( + CronFieldCount CronProblem = iota + CronEmptyItem + CronBadStep + CronNotNumber + CronOutOfRange + CronBackwards +) + +// CronError locates a problem in a cron expression. +type CronError struct { + // Field is 0 to 4, or -1 for the count. + Field int + Problem CronProblem + // Text is the offending part. + Text string +} + +var cronProblemKeys = [...]string{"cron_editor.err_count", "cron_editor.err_empty", "cron_editor.err_step", "cron_editor.err_number", + "cron_editor.err_range", "cron_editor.err_backwards"} + +func (e *CronError) Error() string { + return fmt.Sprintf("cron field %d: problem %d at %q", e.Field+1, e.Problem, e.Text) +} + +var cronBounds = [5][2]int{{0, 59}, {0, 23}, {1, 31}, {1, 12}, {0, 7}} + +var cronNames = [5][]string{3: {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"}, + 4: {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"}} + +// ParseCron parses standard five-field cron with names. +func ParseCron(expr string) (CronSchedule, error) { + parts := strings.Fields(expr) + var s CronSchedule + if len(parts) != 5 { + return s, &CronError{-1, CronFieldCount, strconv.Itoa(len(parts))} + } + for f, part := range parts { + s.tokens[f] = part + for _, item := range strings.Split(part, ",") { + bits, err := cronItem(f, strings.ToUpper(item)) + if err != nil { + err.Field = f + return CronSchedule{}, err + } + s.fields[f] |= bits + } + } + if s.fields[4]&(1<<7) != 0 { + s.fields[4] |= 1 + } + s.domAny, s.dowAny = parts[2] == "*", parts[4] == "*" + return s, nil +} + +// cronItem parses one list item into a bit set. +func cronItem(f int, item string) (uint64, *CronError) { + lo, hi := cronBounds[f][0], cronBounds[f][1] + if item == "" { + return 0, &CronError{Problem: CronEmptyItem} + } + rng, step := item, 1 + if i := strings.IndexByte(item, '/'); i >= 0 { + n, err := strconv.Atoi(item[i+1:]) + if err != nil || n < 1 { + return 0, &CronError{Problem: CronBadStep, Text: item[i+1:]} + } + rng, step = item[:i], n + } + a, b := lo, hi + switch { + case rng == "*": + case strings.Contains(rng, "-"): + x, y, _ := strings.Cut(rng, "-") + var e *CronError + if a, e = cronValue(f, x); e != nil { + return 0, e + } + if b, e = cronValue(f, y); e != nil { + return 0, e + } + if a > b { + return 0, &CronError{Problem: CronBackwards, Text: rng} + } + default: + var e *CronError + if a, e = cronValue(f, rng); e != nil { + return 0, e + } + if step == 1 { + b = a + } + } + var bits uint64 + for v := a; v <= b; v += step { + bits |= 1 << v + } + return bits, nil +} + +func cronValue(f int, s string) (int, *CronError) { + for i, n := range cronNames[f] { + if s == n { + return i + cronBounds[f][0], nil + } + } + v, err := strconv.Atoi(s) + if err != nil { + return 0, &CronError{Problem: CronNotNumber, Text: s} + } + if v < cronBounds[f][0] || v > cronBounds[f][1] { + return 0, &CronError{Problem: CronOutOfRange, Text: s} + } + return v, nil +} + +// CronRun is one upcoming run; Repeated marks a DST repeat. +type CronRun struct { + At time.Time + Repeated bool +} + +// Next returns up to n runs within five years. +func (s CronSchedule) Next(t time.Time, loc *time.Location, n int) []CronRun { + var out []CronRun + w := t.In(loc) + day := DateOf(w) + for i := 0; i < 5*366 && len(out) < n; i, day = i+1, day.AddDays(1) { + if !s.dayMatches(day) { + continue + } + for h := 0; h < 24 && len(out) < n; h++ { + if s.fields[1]&(1< 1}) + } + } + } + return out +} + +// dayMatches applies cron's either-day-field rule. +func (s CronSchedule) dayMatches(d Date) bool { + if s.fields[3]&(1< hi { + problem = fmt.Sprintf(msg(c, "duration_picker.range"), DurationText(c, opts.Min), DurationText(c, hi)) + } + if edited && problem == "" && total != *value && !col.IsDisabled() { + slog.Debug("mujica: duration_picker change", "from", *value, "to", total) + *value, *seen, changed = total, total, true + } + datetimeError(c, problem) + }) + return ChoiceResult{Element: col, changed: changed} +} + +func durationParts(v time.Duration) [3]float64 { + return [3]float64{float64(v / time.Hour), float64(v % time.Hour / time.Minute), float64(v % time.Minute / time.Second)} +} + +// DurationText words a duration, as "1 h 30 min". +func DurationText(c *ui.Context, v time.Duration) string { + p := durationParts(v) + s := "" + for i, key := range []string{"duration_picker.hours_unit", "duration_picker.minutes_unit", "duration_picker.seconds_unit"} { + if p[i] > 0 || i == 1 && s == "" && p[2] == 0 { + if s != "" { + s += " " + } + s += fmt.Sprintf("%d %s", int(p[i]), msg(c, key)) + } + } + return s +} diff --git a/duration_picker_test.go b/duration_picker_test.go new file mode 100644 index 0000000..391f708 --- /dev/null +++ b/duration_picker_test.go @@ -0,0 +1,87 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func durationTester(v *time.Duration, opts *DurationPickerOptions, n *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if DurationPicker(c, v, *opts).Changed() { + *n++ + } + }, 640, 200) +} + +func TestDurationPickerEditsFields(t *testing.T) { + v, n := 90*time.Minute, 0 + opts := &DurationPickerOptions{Seconds: true} + tt := durationTester(&v, opts, &n) + _ = tt.Click("Hours") + tt.Key(0, ui.KeyUp) + _ = tt.Click("Seconds") + tt.Command("selectAll") + tt.Type("45") + tt.Key(0, ui.KeyEnter) + if v != 2*time.Hour+30*time.Minute+45*time.Second || n != 2 { + t.Fatalf("value %v (%d)", v, n) + } +} + +func TestDurationPickerRangeReported(t *testing.T) { + v, n := 30*time.Minute, 0 + opts := &DurationPickerOptions{Min: 15 * time.Minute, Max: 2 * time.Hour} + tt := durationTester(&v, opts, &n) + _ = tt.Click("Hours") + tt.Key(0, ui.KeyUp) + if v != 90*time.Minute || n != 1 { + t.Fatalf("1 h 30 min should fit the range: %v", v) + } + tt.Key(0, ui.KeyUp) + if v != 90*time.Minute || !tt.HasText("Choose a duration from 15 min to 2 h.") { + t.Fatalf("over Max accepted: %v %v", v, tt.Texts()) + } + _ = tt.Click("Minutes") + tt.Command("selectAll") + tt.Type("0") + tt.Key(0, ui.KeyEnter) + if v != 2*time.Hour || n != 2 || tt.HasText("Choose a duration") { + t.Fatalf("fixing the minutes: %v", v) + } + if tt.HasText("Seconds") { + t.Fatal("seconds field without Seconds") + } +} + +func TestDurationPickerDisabledAndInvalid(t *testing.T) { + v, n := time.Hour, 0 + tt := durationTester(&v, &DurationPickerOptions{Disabled: true}, &n) + _ = tt.Click("Hours") + tt.Key(0, ui.KeyUp) + if v != time.Hour || n != 0 { + t.Fatal("disabled picker changed") + } + for _, c := range []struct { + v time.Duration + opts DurationPickerOptions + }{{30 * time.Second, DurationPickerOptions{}}, {0, DurationPickerOptions{Min: time.Hour, Max: time.Minute}}, {-time.Minute, DurationPickerOptions{}}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%v %+v: expected panic", c.v, c.opts) + } + }() + durationTester(&c.v, &c.opts, &n) + }() + } +} + +func TestDurationPickerSnapshot(t *testing.T) { + v := 2*time.Hour + 15*time.Minute + 30*time.Second + snapshot(t, "duration_picker", 640, 80, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { DurationPicker(c, &v, DurationPickerOptions{Seconds: true}) }) + }) +} diff --git a/event_chip.go b/event_chip.go index 51acf51..cb81b1c 100644 --- a/event_chip.go +++ b/event_chip.go @@ -14,13 +14,13 @@ type EventChipOptions struct { // Location is the zone the time shows in; required. Location *time.Location Hour12 bool - // Inline puts time and title on one line. + // Inline puts the start time and title on one line. Inline bool Selected bool Disabled bool } -// EventChip is a clickable event block: color stripe, time and title, truncated to fit. +// EventChip is a clickable, truncating event block. func EventChip(c *ui.Context, ev CalendarEvent, opts EventChipOptions) *ui.Element { loc := eventLocation("EventChip", opts.Location) k := Tokens(c) @@ -32,7 +32,7 @@ func EventChip(c *ui.Context, ev CalendarEvent, opts EventChipOptions) *ui.Eleme title = msg(c, "event_chip.untitled") } b := ui.ButtonBase(c).MinHeight(theme.MinHitSize).MinWidth(theme.MinHitSize).Justify(ui.Start).AlignItems(ui.Start). - Radius(theme.ControlRadius).Padding(d.Unit(), d.Unit()*2).PaddingX(d.Unit()*2).Gap(d.Unit()). + Radius(theme.ControlRadius).Padding(d.Unit(), d.Unit()*2).PaddingX(d.Unit() * 2).Gap(d.Unit()). Label(title + ", " + when).Disabled(opts.Disabled).Clip() internal.Ring(b, k.Focus, theme.ControlRadius) bg := col.Alpha(0.14).Over(k.Surface) @@ -60,7 +60,7 @@ func EventChip(c *ui.Context, ev CalendarEvent, opts EventChipOptions) *ui.Eleme b.Children(func() { small := FontSize(c, theme.CaptionSize) if opts.Inline { - ui.Text(c, when).FontSize(small).TextColor(k.TextMuted).SingleLine().Shrink(0).FontFeatures("tnum") + ui.Text(c, eventStartText(c, ev, loc, opts.Hour12)).FontSize(small).TextColor(k.TextMuted).SingleLine().Shrink(0).FontFeatures("tnum") } ui.Text(c, title).FontSize(small).Bold().TextColor(k.Text).SingleLine().Ellipsis("…").Shrink(1) if !opts.Inline { @@ -69,3 +69,12 @@ func EventChip(c *ui.Context, ev CalendarEvent, opts EventChipOptions) *ui.Eleme }) return b } + +// eventStartText is the start time alone, or "All day". +func eventStartText(c *ui.Context, ev CalendarEvent, loc *time.Location, hour12 bool) string { + if ev.AllDay { + return msg(c, "event_chip.all_day") + } + s := ev.Start.In(loc) + return timeText(c, TimeOfDay{s.Hour(), s.Minute(), 0}, timeConfig{hour12: hour12}) +} diff --git a/event_chip_test.go b/event_chip_test.go new file mode 100644 index 0000000..ba6fbf7 --- /dev/null +++ b/event_chip_test.go @@ -0,0 +1,125 @@ +package mujica + +import ( + "strings" + "testing" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +var calTokyo = func() *time.Location { + loc, err := time.LoadLocation("Asia/Tokyo") + if err != nil { + panic(err) + } + return loc +}() + +// calEvent is an event on calendarToday's month in Tokyo. +func calEvent(id string, day, h, m, mins int) CalendarEvent { + s := time.Date(2026, time.October, day, h, m, 0, 0, calTokyo) + return CalendarEvent{ID: id, Title: "Event " + id, Start: s, End: s.Add(time.Duration(mins) * time.Minute)} +} + +func TestEventChipShowsZoneTimeAndClicks(t *testing.T) { + ev := calEvent("a", 6, 9, 30, 90) + ev.Start, ev.End = ev.Start.UTC(), ev.End.UTC() + n := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if EventChip(c, ev, EventChipOptions{Location: calTokyo}).Clicked() { + n++ + } + }, 300, 200) + if !tt.HasText("09:30 – 11:00") || !tt.HasText("Event a") { + t.Fatalf("chip should show Tokyo wall time: %v", tt.Texts()) + } + label := "Event a, 09:30 – 11:00" + _ = tt.Click(label) + tt.Key(0, ui.KeyEnter) + if n != 2 { + t.Fatalf("clicks %d", n) + } +} + +func TestEventChipTruncatesAndAllDay(t *testing.T) { + ev := calEvent("b", 6, 0, 0, 24*60) + ev.AllDay, ev.Title = true, strings.Repeat("Long title ", 20) + var w float32 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Width(120).Children(func() { + w = EventChip(c, ev, EventChipOptions{Location: calTokyo, Inline: true}).Bounds().W + }) + }, 300, 200) + tt.Frame() + if w > 120 || !tt.HasText("All day") { + t.Fatalf("width %v texts %v", w, tt.Texts()) + } +} + +func TestEventChipDisabledAndInvalid(t *testing.T) { + ev := calEvent("c", 6, 9, 0, 30) + n := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if EventChip(c, ev, EventChipOptions{Location: calTokyo, Disabled: true}).Clicked() { + n++ + } + }, 300, 200) + _ = tt.Click("Event c, 09:00 – 09:30") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if n != 0 { + t.Fatal("disabled chip clicked") + } + for _, f := range []func(){ + func() { EventChip(nil, ev, EventChipOptions{}) }, + func() { ev.Color = 9; eventColor(theme.Light(), ev.Color) }, + } { + func() { + defer func() { + if recover() == nil { + t.Error("expected panic") + } + }() + f() + }() + } +} + +func TestEventPaletteContrast(t *testing.T) { + for _, k := range []theme.Tokens{theme.Light(), theme.Dark()} { + for i, col := range eventPalette(k) { + if r := theme.Contrast(col, k.Surface); r < 3 { + t.Errorf("dark=%v color %d contrast %.2f", k.Dark, i, r) + } + } + } +} + +func TestEventColumns(t *testing.T) { + col, cols := eventColumns([]eventSpan{{0, 2}, {1, 3}, {1.5, 2.5}, {2, 4}, {5, 6}}) + want := []int{0, 1, 2, 0, 0} + wantN := []int{3, 3, 3, 3, 1} + for i := range want { + if col[i] != want[i] || cols[i] != wantN[i] { + t.Fatalf("columns %v of %v", col, cols) + } + } +} + +func TestEventChipSnapshot(t *testing.T) { + evs := []CalendarEvent{calEvent("1", 6, 9, 0, 60), calEvent("2", 6, 13, 0, 30), calEvent("3", 6, 15, 0, 45)} + evs[1].Color, evs[2].Color = EventSuccess, EventWarning + snapshot(t, "event_chip", 420, 150, func(c *ui.Context) { + ui.Row(c).Padding(16).Gap(8).Children(func() { + EventChip(c, evs[0], EventChipOptions{Location: calTokyo}) + EventChip(c, evs[1], EventChipOptions{Location: calTokyo, Selected: true}) + EventChip(c, evs[2], EventChipOptions{Location: calTokyo, Inline: true}) + }) + }) +} diff --git a/event_editor.go b/event_editor.go new file mode 100644 index 0000000..66ce4da --- /dev/null +++ b/event_editor.go @@ -0,0 +1,171 @@ +package mujica + +import ( + "log/slog" + "slices" + "strings" + "time" + + "github.com/egoist/mygo/ui" +) + +// EventEditorOptions configure an EventEditor. +type EventEditorOptions struct { + // Location is the zone times are edited in; required. + Location *time.Location + Hour12 bool + WeekStart WeekStart + Disabled bool + Label string +} + +// EventEditorResult is the editor and its save or cancel. +type EventEditorResult struct { + Element *ui.Element + saved bool + canceled bool +} + +// Saved reports a valid draft written to the event. +func (r EventEditorResult) Saved() bool { return r.saved } + +// Canceled reports that the user discarded the draft. +func (r EventEditorResult) Canceled() bool { return r.canceled } + +// eventEditorState is the draft and whether Save was tried. +type eventEditorState struct { + draft CalendarEvent + tried bool + origin string +} + +// EventEditor edits a copy of *ev; Save checks and writes. +func EventEditor(c *ui.Context, ev *CalendarEvent, opts EventEditorOptions) EventEditorResult { + loc := eventLocation("EventEditor", opts.Location) + d := Density(c) + label := opts.Label + if label == "" { + label = msg(c, "event_editor.label") + } + r := EventEditorResult{} + root := ui.Column(c).Gap(d.Unit() * 4).Role(ui.RoleGroup).Label(label).Disabled(opts.Disabled) + r.Element = root + st := ui.Local(root, "event-editor", func() *eventEditorState { return nil }) + if *st == nil || (*st).origin != ev.ID { + *st = &eventEditorState{draft: eventCopy(*ev), origin: ev.ID} + } + s := *st + dr := &s.draft + problems := eventEditorProblems(c, *dr, s.tried) + root.Children(func() { + FormField(c, msg(c, "event_editor.title"), FormFieldOptions{Required: true, Error: problems["title"]}, func() *ui.Element { + return TextInput(c, &dr.Title, TextInputOptions{Label: msg(c, "event_editor.title"), Disabled: opts.Disabled, Error: problems["title"]}).Input + }) + Checkbox(c, &dr.AllDay, msg(c, "event_editor.all_day"), CheckboxOptions{Disabled: opts.Disabled}) + ui.Row(c).Gap(d.Unit() * 3).Wrap().AlignItems(ui.Start).Children(func() { + for _, f := range []struct { + key string + t *time.Time + }{{"event_editor.starts", &dr.Start}, {"event_editor.ends", &dr.End}} { + FormField(c, msg(c, f.key), FormFieldOptions{Error: problems[f.key]}, func() *ui.Element { + if dr.AllDay { + day := DateOf(f.t.In(loc)) + r := DatePicker(c, &day, DatePickerOptions{Label: msg(c, f.key), WeekStart: opts.WeekStart, Disabled: opts.Disabled}) + if r.Changed() { + *f.t = eventDayStart(day, loc) + } + return r.Input + } + return DateTimePicker(c, f.t, DateTimePickerOptions{Location: loc, Hour12: opts.Hour12, MinuteStep: 5, + WeekStart: opts.WeekStart, Label: msg(c, f.key), Disabled: opts.Disabled}).Element + }) + } + }) + FormField(c, msg(c, "event_editor.where"), FormFieldOptions{}, func() *ui.Element { + return TextInput(c, &dr.Location, TextInputOptions{Label: msg(c, "event_editor.where"), Disabled: opts.Disabled}).Input + }) + FormField(c, msg(c, "event_editor.guests"), FormFieldOptions{Description: msg(c, "event_editor.guests_help")}, func() *ui.Element { + names := make([]string, len(dr.Attendees)) + for i, a := range dr.Attendees { + names[i] = a.Name + } + p := TagsInput(c, &names, TagsInputOptions{Label: msg(c, "event_editor.guests"), Disabled: opts.Disabled}) + if p.Changed() { + dr.Attendees = eventAttendees(dr.Attendees, names) + } + return p.Input + }) + if len(dr.Attendees) > 0 { + AttendeeList(c, dr.Attendees, AttendeeListOptions{Disabled: opts.Disabled}) + } + FormField(c, msg(c, "event_editor.reminders"), FormFieldOptions{}, func() *ui.Element { + return ReminderPicker(c, &dr.Reminders, ReminderPickerOptions{Disabled: opts.Disabled}).Element + }) + var rec RecurrenceResult + FormField(c, msg(c, "recurrence_editor.repeat"), FormFieldOptions{}, func() *ui.Element { + rec = RecurrenceEditor(c, &dr.Repeat, RecurrenceEditorOptions{Start: DateOf(dr.Start.In(loc)), WeekStart: opts.WeekStart, Disabled: opts.Disabled}) + return rec.Element + }) + datetimeFooter(c, func() { + if Button(c, msg(c, "calendar.cancel"), ButtonOptions{Variant: Secondary}).Clicked() && !root.IsDisabled() { + slog.Debug("mujica: event_editor cancel", "id", ev.ID) + *st, r.canceled = nil, true + } + if Button(c, msg(c, "event_editor.save"), ButtonOptions{}).Clicked() && !root.IsDisabled() { + s.tried = true + if len(eventEditorProblems(c, *dr, true)) == 0 && rec.Problem() == "" { + slog.Debug("mujica: event_editor save", "id", ev.ID) + out := eventCopy(*dr) + if out.AllDay { + first, last := DateOf(out.Start.In(loc)), DateOf(out.End.Add(-time.Nanosecond).In(loc)) + out.Start, out.End = eventDayStart(first, loc), eventDayStart(last.AddDays(1), loc) + } + *ev, r.saved = out, true + } else { + slog.Debug("mujica: event_editor invalid", "id", ev.ID) + } + } + }) + }) + return r +} + +// eventEditorProblems checks a draft once Save was tried. +func eventEditorProblems(c *ui.Context, ev CalendarEvent, tried bool) map[string]string { + p := map[string]string{} + if !tried { + return p + } + if strings.TrimSpace(ev.Title) == "" { + p["title"] = msg(c, "event_editor.need_title") + } + if ev.Start.IsZero() { + p["event_editor.starts"] = msg(c, "event_editor.need_start") + } + if !ev.End.After(ev.Start) { + p["event_editor.ends"] = msg(c, "event_editor.end_order") + } + return p +} + +// eventAttendees keeps known attendees and adds new ones. +func eventAttendees(old []Attendee, names []string) []Attendee { + out := make([]Attendee, 0, len(names)) + for _, n := range names { + i := slices.IndexFunc(old, func(a Attendee) bool { return a.Name == n }) + if i >= 0 { + out = append(out, old[i]) + } else { + out = append(out, Attendee{Name: n}) + } + } + return out +} + +// eventCopy clones an event's slices for a draft. +func eventCopy(ev CalendarEvent) CalendarEvent { + ev.Attendees = slices.Clone(ev.Attendees) + ev.Reminders = slices.Clone(ev.Reminders) + ev.Repeat.Weekdays = slices.Clone(ev.Repeat.Weekdays) + return ev +} diff --git a/event_editor_test.go b/event_editor_test.go new file mode 100644 index 0000000..0c14ffe --- /dev/null +++ b/event_editor_test.go @@ -0,0 +1,112 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +type editorProbe struct { + ev CalendarEvent + saves, cancels int + disabled bool +} + +func (p *editorProbe) tester() *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Scroll(c).Fill().Padding(16).Children(func() { + r := EventEditor(c, &p.ev, EventEditorOptions{Location: calTokyo, Disabled: p.disabled}) + if r.Saved() { + p.saves++ + } + if r.Canceled() { + p.cancels++ + } + }) + }, 900, 1400) +} + +func TestEventEditorValidatesAndSaves(t *testing.T) { + p := &editorProbe{ev: CalendarEvent{ID: "n", Start: calAt(t, 9, 0, 14), End: calAt(t, 9, 0, 13)}} + tt := p.tester() + _ = tt.Click("Save") + if p.saves != 0 || !tt.HasText("Enter a title.") || !tt.HasText("The end must be after the start.") { + t.Fatalf("invalid draft saved: %v", tt.Texts()) + } + _ = tt.Click("Title") + tt.Type("Masquerade") + _ = tt.Click("Location") + tt.Type("Hall") + _ = tt.Click("Guests") + tt.Type("Mutsumi") + tt.Key(0, ui.KeyEnter) + _ = tt.Click("15 minutes before") + _ = tt.Click("2026-10-13 09:00 JST") + _ = tt.Click(datetimeTestLabel(oct(14))) + _ = tt.Click("Time: Hours") + tt.Key(0, ui.KeyUp) + _ = tt.Click("Confirm") + if p.ev.Title != "" { + t.Fatal("the caller's event changed before Save") + } + _ = tt.Click("Save") + ev := p.ev + if p.saves != 1 || ev.Title != "Masquerade" || ev.Location != "Hall" || len(ev.Attendees) != 1 || ev.Attendees[0].Name != "Mutsumi" || + len(ev.Reminders) != 1 || !ev.End.Equal(calAt(t, 10, 0, 14)) { + t.Fatalf("saved %+v", ev) + } +} + +func TestEventEditorAllDayRepeatCancel(t *testing.T) { + p := &editorProbe{ev: calEvent("e", 14, 9, 0, 60)} + tt := p.tester() + _ = tt.Click("All day") + _ = tt.Click("Does not repeat") + _ = tt.Click("Weekly") + _ = tt.Click("Save") + if p.saves != 1 || !p.ev.AllDay || p.ev.Repeat.Unit != RepeatWeekly || p.ev.Repeat.Weekdays[0] != time.Wednesday || + !p.ev.Start.Equal(calAt(t, 0, 0, 14)) || !p.ev.End.Equal(calAt(t, 0, 0, 15)) { + t.Fatalf("saved %+v", p.ev) + } + _ = tt.Click("Title") + tt.Type(" draft") + _ = tt.Click("Cancel") + if p.cancels != 1 || p.ev.Title != "Event e" { + t.Fatalf("cancel kept %q", p.ev.Title) + } + tt.Frame() + _ = tt.Click("Save") + if p.ev.Title != "Event e" { + t.Fatal("canceled draft came back") + } +} + +func TestEventEditorDisabled(t *testing.T) { + p := &editorProbe{ev: calEvent("e", 14, 9, 0, 60), disabled: true} + tt := p.tester() + _ = tt.Click("Title") + tt.Type("x") + _ = tt.Click("Save") + _ = tt.Click("Cancel") + if p.saves != 0 || p.cancels != 0 || p.ev.Title != "Event e" { + t.Fatal("disabled editor acted") + } + defer func() { + if recover() == nil { + t.Fatal("expected panic without Location") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + EventEditor(c, &p.ev, EventEditorOptions{}) + }, 10, 10) +} + +func TestEventEditorSnapshot(t *testing.T) { + ev := calRichEvent() + snapshot(t, "event_editor", 760, 1100, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { EventEditor(c, &ev, EventEditorOptions{Location: calTokyo}) }) + }) +} diff --git a/event_popover.go b/event_popover.go new file mode 100644 index 0000000..bbb243f --- /dev/null +++ b/event_popover.go @@ -0,0 +1,114 @@ +package mujica + +import ( + "log/slog" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// EventPopoverOptions configure an EventPopover. +type EventPopoverOptions struct { + // Location is the zone times show in; required. + Location *time.Location + Hour12 bool + // ReadOnly hides the edit and delete actions. + ReadOnly bool + Disabled bool +} + +// EventPopoverResult is the popover and the action the user chose. +type EventPopoverResult struct { + Element *ui.Element + edit bool + del bool +} + +// Edit reports a click on Edit. +func (r EventPopoverResult) Edit() bool { return r.edit } + +// Delete reports a click on Delete. +func (r EventPopoverResult) Delete() bool { return r.del } + +// EventPopover summarizes an event beside anchor while *open. +func EventPopover(c *ui.Context, anchor *ui.Element, open *bool, ev CalendarEvent, opts EventPopoverOptions) EventPopoverResult { + loc := eventLocation("EventPopover", opts.Location) + k := Tokens(c) + d := Density(c) + var r EventPopoverResult + if *open && (opts.Disabled || anchor.IsDisabled()) { + slog.Debug("mujica: event_popover close", "disabled", true) + *open = false + } + r.Element = ui.PopoverBase(c, anchor, open, func(panel *ui.Element) { + overlayStyle(c, panel, overlayEnter(c, panel)) + ww, wh := c.Size() + panel.Margin(d.Unit(), 0, 0, 0).Padding(d.Unit() * 4).Gap(d.Unit() * 2).Width(min(d.ControlHeight()*9, ww-16)).MaxHeight(wh - 16). + Role(ui.RoleDialog).Label(ev.Title) + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + ui.Box(c).Size(10, 10).Shrink(0).Draw(func(p *ui.Painter, rr ui.Rect) { + p.FillPath(internal.Diamond(rr.X+rr.W/2, rr.Y+rr.H/2, rr.W), eventColor(k, ev.Color)) + }) + ui.Text(c, ev.Title).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).TextColor(k.Text).Grow(1).Shrink(1) + if iconAction(c, icons.Must("x"), msg(c, "event_popover.close")).Clicked() { + *open = false + } + }) + ui.Scroll(c).Shrink(1).Children(func() { + ui.Column(c).Gap(d.Unit() * 2).Children(func() { + for _, line := range eventPopoverLines(c, ev, loc, opts.Hour12) { + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Start).Children(func() { + ui.Icon(c, icons.Must(line[0])).Size(16, 16).TextColor(k.TextMuted) + ui.Text(c, line[1]).TextColor(k.Text).Grow(1).Shrink(1) + }) + } + }) + }) + if opts.ReadOnly { + return + } + datetimeFooter(c, func() { + if Button(c, msg(c, "event_popover.delete"), ButtonOptions{Variant: Danger}).Clicked() { + slog.Debug("mujica: event_popover delete", "id", ev.ID) + r.del, *open = true, false + } + if Button(c, msg(c, "event_popover.edit"), ButtonOptions{Variant: Secondary}).Clicked() { + slog.Debug("mujica: event_popover edit", "id", ev.ID) + r.edit, *open = true, false + } + }) + }) + return r +} + +// eventPopoverLines lists icon and text pairs for the summary. +func eventPopoverLines(c *ui.Context, ev CalendarEvent, loc *time.Location, hour12 bool) [][2]string { + s := ev.Start.In(loc) + lines := [][2]string{{"clock", datetimeDayLabel(c, DateOf(s)) + " · " + eventTimeText(c, ev, loc, hour12)}} + if ev.Location != "" { + lines = append(lines, [2]string{"house", ev.Location}) + } + if ev.Repeat.Unit != RepeatNone { + lines = append(lines, [2]string{"refresh-cw", RecurrenceSummary(c, ev.Repeat)}) + } + if len(ev.Attendees) > 0 { + var names []string + for _, a := range ev.Attendees { + names = append(names, a.Name) + } + lines = append(lines, [2]string{"user", calendarCount(c, "event_popover.guests", len(names)) + ": " + strings.Join(names, ", ")}) + } + if len(ev.Reminders) > 0 { + var rs []string + for _, d := range ev.Reminders { + rs = append(rs, ReminderText(c, d)) + } + lines = append(lines, [2]string{"bell", strings.Join(rs, msg(c, "recurrence_editor.list_sep"))}) + } + return lines +} diff --git a/event_popover_test.go b/event_popover_test.go new file mode 100644 index 0000000..cbd1ec2 --- /dev/null +++ b/event_popover_test.go @@ -0,0 +1,110 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func calRichEvent() CalendarEvent { + ev := calEvent("r", 14, 19, 0, 120) + ev.Title, ev.Location, ev.Color = "Masquerade rehearsal", "Rehearsal hall", EventInfo + ev.Attendees = calAttendees[:2] + ev.Reminders = []time.Duration{15 * time.Minute, time.Hour} + ev.Repeat = Recurrence{Unit: RepeatWeekly, Interval: 1, Weekdays: []time.Weekday{time.Wednesday}} + return ev +} + +type popoverProbe struct { + open bool + opts EventPopoverOptions + edits, deletes int +} + +func (p *popoverProbe) tester() *ui.Tester { + p.opts.Location = calTokyo + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(16).Children(func() { + b := Button(c, "Details", ButtonOptions{Variant: Secondary}) + if b.Clicked() { + p.open = true + } + r := EventPopover(c, b, &p.open, calRichEvent(), p.opts) + if r.Edit() { + p.edits++ + } + if r.Delete() { + p.deletes++ + } + }) + }, 600, 500) +} + +func TestEventPopoverSummaryAndActions(t *testing.T) { + p := &popoverProbe{} + tt := p.tester() + _ = tt.Click("Details") + for _, s := range []string{"Masquerade rehearsal", "Wednesday, October 14, 2026 · 19:00 – 21:00", "Rehearsal hall", + "Weekly on Wednesday", "2 guests: Sakiko Togawa, Mutsumi Wakaba", "15 minutes before, 1 hour before"} { + if !tt.HasText(s) { + t.Fatalf("missing %q in %v", s, tt.Texts()) + } + } + _ = tt.Click("Edit") + if p.edits != 1 || p.open { + t.Fatal("Edit should report and close") + } + _ = tt.Click("Details") + tt.Key(0, ui.KeyTab) + _ = tt.Click("Delete") + if p.deletes != 1 || p.open { + t.Fatal("Delete should report and close") + } + _ = tt.Click("Details") + tt.Key(0, ui.KeyEscape) + if p.open { + t.Fatal("Escape should close") + } +} + +func TestEventPopoverReadOnlyAndDisabled(t *testing.T) { + p := &popoverProbe{opts: EventPopoverOptions{ReadOnly: true}} + tt := p.tester() + _ = tt.Click("Details") + if tt.HasText("Edit") || tt.HasText("Delete") || !tt.HasText("Rehearsal hall") { + t.Fatal("read-only popover shows actions") + } + p.opts.ReadOnly, p.opts.Disabled = false, true + tt.Frame() + if p.open || tt.HasText("Rehearsal hall") { + t.Fatal("disabling should close the popover") + } + defer func() { + if recover() == nil { + t.Fatal("expected panic without Location") + } + }() + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + open := true + EventPopover(c, ui.Box(c), &open, calRichEvent(), EventPopoverOptions{}) + }, 10, 10) +} + +func TestEventPopoverSnapshot(t *testing.T) { + snapshot(t, "event_popover", 460, 400, func(c *ui.Context) { + ui.Row(c).Padding(16).Children(func() { + b := Button(c, "Details", ButtonOptions{Variant: Secondary}) + // Open once the anchor is laid out. + frames := ui.Local(c.Root(), "frames", func() int { return 0 }) + *frames++ + if *frames == 1 { + c.Invalidate() + } + open := *frames > 1 + EventPopover(c, b, &open, calRichEvent(), EventPopoverOptions{Location: calTokyo}) + }) + }) +} diff --git a/example_calendar_test.go b/example_calendar_test.go new file mode 100644 index 0000000..badbc93 --- /dev/null +++ b/example_calendar_test.go @@ -0,0 +1,262 @@ +package mujica_test + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func exampleEvents(loc *time.Location) []mujica.CalendarEvent { + start := time.Date(2026, time.October, 14, 9, 0, 0, 0, loc) + return []mujica.CalendarEvent{ + {ID: "rehearsal", Title: "Rehearsal", Start: start, End: start.Add(2 * time.Hour), Location: "Hall"}, + {ID: "fitting", Title: "Fitting", Start: start.Add(time.Hour), End: start.Add(90 * time.Minute), Color: mujica.EventInfo}, + } +} + +func ExampleCalendarMonthView() { + loc := time.Local + events := exampleEvents(loc) + month := mujica.YearMonth{Year: 2026, Month: time.October} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CalendarMonthView(c, &month, events, mujica.CalendarMonthViewOptions{Location: loc}) + if ch, ok := r.Changed(); ok { + fmt.Println("move", ch.ID, "to", ch.Start) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCalendarWeekView() { + loc := time.Local + events := exampleEvents(loc) + week := mujica.Date{Year: 2026, Month: time.October, Day: 14} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CalendarWeekView(c, &week, events, mujica.CalendarWeekViewOptions{Location: loc, SlotMinutes: 15}) + if ch, ok := r.Changed(); ok && ch.Kind == mujica.CalendarCreate { + fmt.Println("new event", ch.Start, ch.End) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCalendarDayView() { + loc := time.Local + events := exampleEvents(loc) + day := mujica.Date{Year: 2026, Month: time.October, Day: 14} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if id, ok := mujica.CalendarDayView(c, &day, events, mujica.CalendarDayViewOptions{Location: loc}).Opened(); ok { + fmt.Println("open", id) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleAgendaView() { + loc := time.Local + events := exampleEvents(loc) + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + opts := mujica.AgendaViewOptions{Location: loc, From: mujica.Date{Year: 2026, Month: time.October, Day: 12}, Days: 14} + if id, ok := mujica.AgendaView(c, events, opts).Opened(); ok { + fmt.Println("open", id) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleYearView() { + loc := time.Local + events := exampleEvents(loc) + year := 2026 + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if day, ok := mujica.YearView(c, &year, events, mujica.YearViewOptions{Location: loc}).DayChosen(); ok { + fmt.Println("go to", day) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleEventChip() { + loc := time.Local + ev := exampleEvents(loc)[0] + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.EventChip(c, ev, mujica.EventChipOptions{Location: loc}).Clicked() { + fmt.Println("open", ev.ID) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleEventEditor() { + loc := time.Local + ev := exampleEvents(loc)[0] + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.EventEditor(c, &ev, mujica.EventEditorOptions{Location: loc}) + if r.Saved() { + fmt.Println("saved", ev.Title, ev.Start) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleEventPopover() { + loc := time.Local + ev := exampleEvents(loc)[0] + open := false + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + chip := mujica.EventChip(c, ev, mujica.EventChipOptions{Location: loc}) + if chip.Clicked() { + open = true + } + r := mujica.EventPopover(c, chip, &open, ev, mujica.EventPopoverOptions{Location: loc}) + if r.Delete() { + fmt.Println("delete", ev.ID) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCurrentTimeIndicator() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + ui.Box(c).Size(200, 240).Children(func() { + mujica.CurrentTimeIndicator(c, mujica.CurrentTimeIndicatorOptions{Location: time.Local}) + }) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleRecurrenceEditor() { + rule := mujica.Recurrence{Unit: mujica.RepeatWeekly, Interval: 1, Weekdays: []time.Weekday{time.Monday}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.RecurrenceEditor(c, &rule, mujica.RecurrenceEditorOptions{Start: mujica.Date{Year: 2026, Month: time.October, Day: 5}}) + if r.Changed() && r.Problem() == "" { + fmt.Println(mujica.RecurrenceSummary(c, rule)) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleAvailabilityPicker() { + days := []mujica.Date{{Year: 2026, Month: time.October, Day: 12}, {Year: 2026, Month: time.October, Day: 13}} + mine := [][]bool{make([]bool, 18), make([]bool, 18)} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.AvailabilityPicker(c, &mine, mujica.AvailabilityPickerOptions{Days: days}).Changed() { + fmt.Println("availability changed") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleTimezoneSelect() { + zone := "Asia/Shanghai" + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.TimezoneSelect(c, &zone, mujica.TimezoneSelectOptions{}).Changed() { + fmt.Println("zone", zone) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleReminderPicker() { + reminders := []time.Duration{15 * time.Minute} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ReminderPicker(c, &reminders, mujica.ReminderPickerOptions{Max: 3}).Changed() { + fmt.Println("reminders", reminders) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleAttendeeList() { + people := []mujica.Attendee{{Name: "Sakiko", Status: mujica.AttendeeAccepted, Organizer: true}, {Name: "Mutsumi"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if i, ok := mujica.AttendeeList(c, people, mujica.AttendeeListOptions{Removable: true}).Removed(); ok { + people = append(people[:i], people[i+1:]...) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleWeekPicker() { + var week mujica.Date + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.WeekPicker(c, &week, mujica.WeekPickerOptions{WeekStart: mujica.WeekStartMonday, Clearable: true}).Changed() { + fmt.Println("week of", week) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleDurationPicker() { + length := 90 * time.Minute + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + opts := mujica.DurationPickerOptions{Min: 15 * time.Minute, Max: 8 * time.Hour} + if mujica.DurationPicker(c, &length, opts).Changed() { + fmt.Println("length", length) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCronEditor() { + expr := "0 9 * * MON-FRI" + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.CronEditor(c, &expr, mujica.CronEditorOptions{Location: time.Local}).Changed() { + if _, err := mujica.ParseCron(expr); err == nil { + fmt.Println("schedule", expr) + } + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleRelativeTime() { + posted := time.Date(2026, time.October, 5, 9, 0, 0, 0, time.Local) + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.RelativeTime(c, posted, mujica.RelativeTimeOptions{Location: time.Local}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCountdown() { + deadline := time.Date(2026, time.December, 31, 23, 59, 59, 0, time.Local) + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.Countdown(c, deadline, mujica.CountdownOptions{}).Finished() { + fmt.Println("happy new year") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleStopwatch() { + var sw mujica.StopwatchState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.Stopwatch(c, &sw, mujica.StopwatchOptions{}).Changed() { + fmt.Println("laps", len(sw.Laps)) + } + } + ui.Render(view, 400, 300, 1) +} diff --git a/examples/gallery/pages_calendar.go b/examples/gallery/pages_calendar.go index 32f9be8..fef821f 100644 --- a/examples/gallery/pages_calendar.go +++ b/examples/gallery/pages_calendar.go @@ -1,3 +1,46 @@ package main -var calendarPages = []page{} +const calCategory = "Calendar" + +var calendarPages = []page{ + {ID: "421", Name: "CalendarMonthView", ZhName: "月视图", Category: calCategory, Demo: calMonthDemo, Code: calCalendarMonthViewCode, + Keys: "Tab reaches day numbers and event chips; arrows move between them; Enter opens; Alt+Left/Right moves an event a day, Alt+Up/Down a week; Escape closes the +N list."}, + {ID: "422", Name: "CalendarWeekView", ZhName: "周视图", Category: calCategory, Demo: calWeekDemo, Code: calCalendarWeekViewCode, + Keys: "Tab reaches a day column; Up/Down move the slot cursor, Enter creates a one-slot event; on a chip Alt+Up/Down moves by a slot, Alt+Left/Right by a day, Alt+Shift+Up/Down resizes."}, + {ID: "423", Name: "CalendarDayView", ZhName: "日视图", Category: calCategory, Demo: calDayDemo, Code: calCalendarDayViewCode, + Keys: "As the week view: Up/Down and Enter in the column, Alt with arrows on a chip."}, + {ID: "424", Name: "AgendaView", ZhName: "日程列表", Category: calCategory, Demo: calAgendaDemo, Code: calAgendaViewCode, + Keys: "Tab enters the list; Up/Down move between events; Enter opens."}, + {ID: "425", Name: "YearView", ZhName: "年视图", Category: calCategory, Demo: calYearDemo, Code: calYearViewCode, + Keys: "Tab enters the days; arrows move by day and week, PageUp/PageDown by month, across years; Enter chooses."}, + {ID: "426", Name: "EventChip", ZhName: "事件块", Category: calCategory, Demo: calChipDemo, Code: calEventChipCode, + Keys: "Tab focuses the chip; Enter or Space activates it."}, + {ID: "427", Name: "EventEditor", ZhName: "事件编辑器", Category: calCategory, Demo: calEditorDemo, Code: calEventEditorCode, + Keys: "Tab moves through the fields; each field keeps its own keys; Save and Cancel are buttons."}, + {ID: "428", Name: "EventPopover", ZhName: "事件浮层", Category: calCategory, Demo: calPopoverDemo, Code: calEventPopoverCode, + Keys: "Enter on the chip opens it; Tab reaches Close, Delete and Edit; Escape closes."}, + {ID: "429", Name: "CurrentTimeIndicator", ZhName: "当前时间线", Category: calCategory, Demo: calNowDemo, Code: calCurrentTimeIndicatorCode, + Keys: "Not focusable; screen readers read the time from its label."}, + {ID: "430", Name: "RecurrenceEditor", ZhName: "重复规则编辑器", Category: calCategory, Demo: calRecurrenceDemo, Code: calRecurrenceEditorCode, + Keys: "Tab moves between the repeat select, interval, weekdays and end choices; each control keeps its own keys."}, + {ID: "431", Name: "AvailabilityPicker", ZhName: "空闲时段选择", Category: calCategory, Demo: calAvailabilityDemo, Code: calAvailabilityPickerCode, + Keys: "Tab focuses the grid; arrows move the cursor; Space or Enter toggles the slot."}, + {ID: "432", Name: "TimezoneSelect", ZhName: "时区选择", Category: calCategory, Demo: calTimezoneDemo, Code: calTimezoneSelectCode, + Keys: "Enter, Space or Down opens; type to search; Up/Down move; Enter chooses; Escape closes."}, + {ID: "433", Name: "ReminderPicker", ZhName: "提醒选择", Category: calCategory, Demo: calReminderDemo, Code: calReminderPickerCode, + Keys: "Tab enters the list; Up/Down move; Space toggles."}, + {ID: "434", Name: "AttendeeList", ZhName: "参与者列表", Category: calCategory, Demo: calAttendeeDemo, Code: calAttendeeListCode, + Keys: "Tab reaches each remove button; Enter removes."}, + {ID: "435", Name: "WeekPicker", ZhName: "周选择器", Category: calCategory, Demo: calWeekPickerDemo, Code: calWeekPickerCode, + Keys: "Enter, Space or Down opens; arrows move; Enter picks the week; Escape closes."}, + {ID: "436", Name: "DurationPicker", ZhName: "时长选择器", Category: calCategory, Demo: calDurationDemo, Code: calDurationPickerCode, + Keys: "Tab moves between hours, minutes and seconds; Up/Down step; type digits and Enter."}, + {ID: "437", Name: "CronEditor", ZhName: "Cron 编辑器", Category: calCategory, Demo: calCronDemo, Code: calCronEditorCode, + Keys: "Type in the expression field; errors and the next runs update as you type."}, + {ID: "438", Name: "RelativeTime", ZhName: "相对时间", Category: calCategory, Demo: calRelativeDemo, Code: calRelativeTimeCode, + Keys: "Not focusable; the exact time is in its label and tooltip."}, + {ID: "439", Name: "Countdown", ZhName: "倒计时", Category: calCategory, Demo: calCountdownDemo, Code: calCountdownCode, + Keys: "Not focusable; reaching zero is announced."}, + {ID: "440", Name: "Stopwatch", ZhName: "秒表", Category: calCategory, Demo: calStopwatchDemo, Code: calStopwatchCode, + Keys: "Tab reaches Start/Pause, Lap and Reset; Enter or Space presses."}, +} diff --git a/examples/gallery/pages_calendar_code.go b/examples/gallery/pages_calendar_code.go new file mode 100644 index 0000000..949e14d --- /dev/null +++ b/examples/gallery/pages_calendar_code.go @@ -0,0 +1,253 @@ +package main + +// Code snippets mirror example_calendar_test.go. +const ( + calCalendarMonthViewCode = `func exampleEvents(loc *time.Location) []mujica.CalendarEvent { + start := time.Date(2026, time.October, 14, 9, 0, 0, 0, loc) + return []mujica.CalendarEvent{ + {ID: "rehearsal", Title: "Rehearsal", Start: start, End: start.Add(2 * time.Hour), Location: "Hall"}, + {ID: "fitting", Title: "Fitting", Start: start.Add(time.Hour), End: start.Add(90 * time.Minute), Color: mujica.EventInfo}, + } +} + +loc := time.Local +events := exampleEvents(loc) +month := mujica.YearMonth{Year: 2026, Month: time.October} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CalendarMonthView(c, &month, events, mujica.CalendarMonthViewOptions{Location: loc}) + if ch, ok := r.Changed(); ok { + fmt.Println("move", ch.ID, "to", ch.Start) + } +} +ui.Render(view, 400, 300, 1)` + calCalendarWeekViewCode = `func exampleEvents(loc *time.Location) []mujica.CalendarEvent { + start := time.Date(2026, time.October, 14, 9, 0, 0, 0, loc) + return []mujica.CalendarEvent{ + {ID: "rehearsal", Title: "Rehearsal", Start: start, End: start.Add(2 * time.Hour), Location: "Hall"}, + {ID: "fitting", Title: "Fitting", Start: start.Add(time.Hour), End: start.Add(90 * time.Minute), Color: mujica.EventInfo}, + } +} + +loc := time.Local +events := exampleEvents(loc) +week := mujica.Date{Year: 2026, Month: time.October, Day: 14} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CalendarWeekView(c, &week, events, mujica.CalendarWeekViewOptions{Location: loc, SlotMinutes: 15}) + if ch, ok := r.Changed(); ok && ch.Kind == mujica.CalendarCreate { + fmt.Println("new event", ch.Start, ch.End) + } +} +ui.Render(view, 400, 300, 1)` + calCalendarDayViewCode = `func exampleEvents(loc *time.Location) []mujica.CalendarEvent { + start := time.Date(2026, time.October, 14, 9, 0, 0, 0, loc) + return []mujica.CalendarEvent{ + {ID: "rehearsal", Title: "Rehearsal", Start: start, End: start.Add(2 * time.Hour), Location: "Hall"}, + {ID: "fitting", Title: "Fitting", Start: start.Add(time.Hour), End: start.Add(90 * time.Minute), Color: mujica.EventInfo}, + } +} + +loc := time.Local +events := exampleEvents(loc) +day := mujica.Date{Year: 2026, Month: time.October, Day: 14} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if id, ok := mujica.CalendarDayView(c, &day, events, mujica.CalendarDayViewOptions{Location: loc}).Opened(); ok { + fmt.Println("open", id) + } +} +ui.Render(view, 400, 300, 1)` + calAgendaViewCode = `func exampleEvents(loc *time.Location) []mujica.CalendarEvent { + start := time.Date(2026, time.October, 14, 9, 0, 0, 0, loc) + return []mujica.CalendarEvent{ + {ID: "rehearsal", Title: "Rehearsal", Start: start, End: start.Add(2 * time.Hour), Location: "Hall"}, + {ID: "fitting", Title: "Fitting", Start: start.Add(time.Hour), End: start.Add(90 * time.Minute), Color: mujica.EventInfo}, + } +} + +loc := time.Local +events := exampleEvents(loc) +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + opts := mujica.AgendaViewOptions{Location: loc, From: mujica.Date{Year: 2026, Month: time.October, Day: 12}, Days: 14} + if id, ok := mujica.AgendaView(c, events, opts).Opened(); ok { + fmt.Println("open", id) + } +} +ui.Render(view, 400, 300, 1)` + calYearViewCode = `func exampleEvents(loc *time.Location) []mujica.CalendarEvent { + start := time.Date(2026, time.October, 14, 9, 0, 0, 0, loc) + return []mujica.CalendarEvent{ + {ID: "rehearsal", Title: "Rehearsal", Start: start, End: start.Add(2 * time.Hour), Location: "Hall"}, + {ID: "fitting", Title: "Fitting", Start: start.Add(time.Hour), End: start.Add(90 * time.Minute), Color: mujica.EventInfo}, + } +} + +loc := time.Local +events := exampleEvents(loc) +year := 2026 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if day, ok := mujica.YearView(c, &year, events, mujica.YearViewOptions{Location: loc}).DayChosen(); ok { + fmt.Println("go to", day) + } +} +ui.Render(view, 400, 300, 1)` + calEventChipCode = `func exampleEvents(loc *time.Location) []mujica.CalendarEvent { + start := time.Date(2026, time.October, 14, 9, 0, 0, 0, loc) + return []mujica.CalendarEvent{ + {ID: "rehearsal", Title: "Rehearsal", Start: start, End: start.Add(2 * time.Hour), Location: "Hall"}, + {ID: "fitting", Title: "Fitting", Start: start.Add(time.Hour), End: start.Add(90 * time.Minute), Color: mujica.EventInfo}, + } +} + +loc := time.Local +ev := exampleEvents(loc)[0] +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.EventChip(c, ev, mujica.EventChipOptions{Location: loc}).Clicked() { + fmt.Println("open", ev.ID) + } +} +ui.Render(view, 400, 300, 1)` + calEventEditorCode = `func exampleEvents(loc *time.Location) []mujica.CalendarEvent { + start := time.Date(2026, time.October, 14, 9, 0, 0, 0, loc) + return []mujica.CalendarEvent{ + {ID: "rehearsal", Title: "Rehearsal", Start: start, End: start.Add(2 * time.Hour), Location: "Hall"}, + {ID: "fitting", Title: "Fitting", Start: start.Add(time.Hour), End: start.Add(90 * time.Minute), Color: mujica.EventInfo}, + } +} + +loc := time.Local +ev := exampleEvents(loc)[0] +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.EventEditor(c, &ev, mujica.EventEditorOptions{Location: loc}) + if r.Saved() { + fmt.Println("saved", ev.Title, ev.Start) + } +} +ui.Render(view, 400, 300, 1)` + calEventPopoverCode = `func exampleEvents(loc *time.Location) []mujica.CalendarEvent { + start := time.Date(2026, time.October, 14, 9, 0, 0, 0, loc) + return []mujica.CalendarEvent{ + {ID: "rehearsal", Title: "Rehearsal", Start: start, End: start.Add(2 * time.Hour), Location: "Hall"}, + {ID: "fitting", Title: "Fitting", Start: start.Add(time.Hour), End: start.Add(90 * time.Minute), Color: mujica.EventInfo}, + } +} + +loc := time.Local +ev := exampleEvents(loc)[0] +open := false +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + chip := mujica.EventChip(c, ev, mujica.EventChipOptions{Location: loc}) + if chip.Clicked() { + open = true + } + r := mujica.EventPopover(c, chip, &open, ev, mujica.EventPopoverOptions{Location: loc}) + if r.Delete() { + fmt.Println("delete", ev.ID) + } +} +ui.Render(view, 400, 300, 1)` + calCurrentTimeIndicatorCode = `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + ui.Box(c).Size(200, 240).Children(func() { + mujica.CurrentTimeIndicator(c, mujica.CurrentTimeIndicatorOptions{Location: time.Local}) + }) +} +ui.Render(view, 400, 300, 1)` + calRecurrenceEditorCode = `rule := mujica.Recurrence{Unit: mujica.RepeatWeekly, Interval: 1, Weekdays: []time.Weekday{time.Monday}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.RecurrenceEditor(c, &rule, mujica.RecurrenceEditorOptions{Start: mujica.Date{Year: 2026, Month: time.October, Day: 5}}) + if r.Changed() && r.Problem() == "" { + fmt.Println(mujica.RecurrenceSummary(c, rule)) + } +} +ui.Render(view, 400, 300, 1)` + calAvailabilityPickerCode = `days := []mujica.Date{{Year: 2026, Month: time.October, Day: 12}, {Year: 2026, Month: time.October, Day: 13}} +mine := [][]bool{make([]bool, 18), make([]bool, 18)} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.AvailabilityPicker(c, &mine, mujica.AvailabilityPickerOptions{Days: days}).Changed() { + fmt.Println("availability changed") + } +} +ui.Render(view, 400, 300, 1)` + calTimezoneSelectCode = `zone := "Asia/Shanghai" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.TimezoneSelect(c, &zone, mujica.TimezoneSelectOptions{}).Changed() { + fmt.Println("zone", zone) + } +} +ui.Render(view, 400, 300, 1)` + calReminderPickerCode = `reminders := []time.Duration{15 * time.Minute} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ReminderPicker(c, &reminders, mujica.ReminderPickerOptions{Max: 3}).Changed() { + fmt.Println("reminders", reminders) + } +} +ui.Render(view, 400, 300, 1)` + calAttendeeListCode = `people := []mujica.Attendee{{Name: "Sakiko", Status: mujica.AttendeeAccepted, Organizer: true}, {Name: "Mutsumi"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if i, ok := mujica.AttendeeList(c, people, mujica.AttendeeListOptions{Removable: true}).Removed(); ok { + people = append(people[:i], people[i+1:]...) + } +} +ui.Render(view, 400, 300, 1)` + calWeekPickerCode = `var week mujica.Date +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.WeekPicker(c, &week, mujica.WeekPickerOptions{WeekStart: mujica.WeekStartMonday, Clearable: true}).Changed() { + fmt.Println("week of", week) + } +} +ui.Render(view, 400, 300, 1)` + calDurationPickerCode = `length := 90 * time.Minute +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + opts := mujica.DurationPickerOptions{Min: 15 * time.Minute, Max: 8 * time.Hour} + if mujica.DurationPicker(c, &length, opts).Changed() { + fmt.Println("length", length) + } +} +ui.Render(view, 400, 300, 1)` + calCronEditorCode = `expr := "0 9 * * MON-FRI" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.CronEditor(c, &expr, mujica.CronEditorOptions{Location: time.Local}).Changed() { + if _, err := mujica.ParseCron(expr); err == nil { + fmt.Println("schedule", expr) + } + } +} +ui.Render(view, 400, 300, 1)` + calRelativeTimeCode = `posted := time.Date(2026, time.October, 5, 9, 0, 0, 0, time.Local) +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.RelativeTime(c, posted, mujica.RelativeTimeOptions{Location: time.Local}) +} +ui.Render(view, 400, 300, 1)` + calCountdownCode = `deadline := time.Date(2026, time.December, 31, 23, 59, 59, 0, time.Local) +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.Countdown(c, deadline, mujica.CountdownOptions{}).Finished() { + fmt.Println("happy new year") + } +} +ui.Render(view, 400, 300, 1)` + calStopwatchCode = `var sw mujica.StopwatchState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.Stopwatch(c, &sw, mujica.StopwatchOptions{}).Changed() { + fmt.Println("laps", len(sw.Laps)) + } +} +ui.Render(view, 400, 300, 1)` +) diff --git a/examples/gallery/pages_calendar_parts.go b/examples/gallery/pages_calendar_parts.go new file mode 100644 index 0000000..fa08df4 --- /dev/null +++ b/examples/gallery/pages_calendar_parts.go @@ -0,0 +1,217 @@ +package main + +import ( + "fmt" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +var calColors = []string{"Accent", "Info", "Success", "Warning", "Danger", "Neutral"} + +func calChipDemo(c *ui.Context, log func(string)) { + type state struct { + color string + inline, selected, disabled bool + } + s := ui.Local(c.Root(), "426", func() state { return state{color: "Accent"} }) + dtSection(c, "EventChip", func() { + dtControls(c, func() { + mujica.Select(c, &s.color, calOptions(calColors), mujica.SelectOptions{Label: "Color"}) + mujica.Checkbox(c, &s.inline, "Inline", mujica.CheckboxOptions{}) + mujica.Checkbox(c, &s.selected, "Selected", mujica.CheckboxOptions{}) + mujica.Checkbox(c, &s.disabled, "Disabled", mujica.CheckboxOptions{}) + }) + ev := calSample()[0] + for i, n := range calColors { + if n == s.color { + ev.Color = mujica.EventColor(i) + } + } + ui.Box(c).Width(240).Children(func() { + if mujica.EventChip(c, ev, mujica.EventChipOptions{Location: time.Local, Inline: s.inline, Selected: s.selected, Disabled: s.disabled}).Clicked() { + log("clicked " + ev.Title) + } + }) + }) +} + +func calEditorDemo(c *ui.Context, log func(string)) { + type state struct { + ev mujica.CalendarEvent + disabled bool + } + s := ui.Local(c.Root(), "427", func() state { return state{ev: calSample()[0]} }) + dtSection(c, "EventEditor", func() { + dtControls(c, func() { mujica.Checkbox(c, &s.disabled, "Disabled", mujica.CheckboxOptions{}) }) + r := mujica.EventEditor(c, &s.ev, mujica.EventEditorOptions{Location: time.Local, Disabled: s.disabled}) + if r.Saved() { + log(fmt.Sprintf("saved %q %s, %d guests", s.ev.Title, s.ev.Start.Format("Jan 2 15:04"), len(s.ev.Attendees))) + } + if r.Canceled() { + log("canceled") + } + }) +} + +func calPopoverDemo(c *ui.Context, log func(string)) { + type state struct { + open, readOnly, disabled bool + } + s := ui.Local(c.Root(), "428", func() state { return state{} }) + dtSection(c, "EventPopover", func() { + dtControls(c, func() { + mujica.Checkbox(c, &s.readOnly, "Read-only", mujica.CheckboxOptions{}) + mujica.Checkbox(c, &s.disabled, "Disabled", mujica.CheckboxOptions{}) + }) + ev := calSample()[0] + ev.Attendees = []mujica.Attendee{{Name: "Sakiko", Status: mujica.AttendeeAccepted, Organizer: true}, {Name: "Mutsumi"}} + ev.Reminders = []time.Duration{15 * time.Minute} + ui.Box(c).Width(240).Children(func() { + chip := mujica.EventChip(c, ev, mujica.EventChipOptions{Location: time.Local, Disabled: s.disabled}) + if chip.Clicked() { + s.open = true + log("opened popover") + } + r := mujica.EventPopover(c, chip, &s.open, ev, mujica.EventPopoverOptions{Location: time.Local, ReadOnly: s.readOnly, Disabled: s.disabled}) + if r.Edit() { + log("edit " + ev.ID) + } + if r.Delete() { + log("delete " + ev.ID) + } + }) + }) +} + +func calNowDemo(c *ui.Context, log func(string)) { + dtSection(c, "CurrentTimeIndicator", func() { + k := mujica.Tokens(c) + ui.Box(c).Size(320, 240).Border(1, k.Border).Children(func() { + mujica.CurrentTimeIndicator(c, mujica.CurrentTimeIndicatorOptions{Location: time.Local}) + }) + }) +} + +func calRecurrenceDemo(c *ui.Context, log func(string)) { + type state struct { + rule mujica.Recurrence + disabled bool + } + s := ui.Local(c.Root(), "430", func() state { return state{} }) + dtSection(c, "RecurrenceEditor", func() { + dtControls(c, func() { mujica.Checkbox(c, &s.disabled, "Disabled", mujica.CheckboxOptions{}) }) + r := mujica.RecurrenceEditor(c, &s.rule, mujica.RecurrenceEditorOptions{Start: mujica.DateOf(time.Now()), Disabled: s.disabled}) + if r.Changed() { + log(mujica.RecurrenceSummary(c, s.rule) + strings.TrimSpace(" "+r.Problem())) + } + }) +} + +func calAvailabilityDemo(c *ui.Context, log func(string)) { + type state struct { + mine, theirs [][]bool + days []mujica.Date + others, frozen bool + } + s := ui.Local(c.Root(), "431", func() state { + today := mujica.DateOf(time.Now()) + grid := func(seed int) [][]bool { + g := make([][]bool, 5) + for i := range g { + g[i] = make([]bool, 18) + for j := range g[i] { + g[i][j] = (i*7+j*3+seed)%4 == 0 + } + } + return g + } + days := []mujica.Date{today, today.AddDays(1), today.AddDays(2), today.AddDays(3), today.AddDays(4)} + return state{mine: grid(2), theirs: grid(1), days: days, others: true} + }) + dtSection(c, "AvailabilityPicker", func() { + dtControls(c, func() { + mujica.Checkbox(c, &s.others, "Show Mutsumi", mujica.CheckboxOptions{}) + mujica.Checkbox(c, &s.frozen, "Disabled", mujica.CheckboxOptions{}) + }) + var others []mujica.AvailabilityPerson + if s.others { + others = []mujica.AvailabilityPerson{{Name: "Mutsumi", Free: s.theirs}} + } + if mujica.AvailabilityPicker(c, &s.mine, mujica.AvailabilityPickerOptions{Days: s.days, Others: others, Disabled: s.frozen}).Changed() { + n := 0 + for _, d := range s.mine { + for _, v := range d { + if v { + n++ + } + } + } + log(fmt.Sprintf("%d free slots", n)) + } + }) +} + +func calTimezoneDemo(c *ui.Context, log func(string)) { + type state struct { + zone string + disabled bool + } + s := ui.Local(c.Root(), "432", func() state { return state{zone: "Asia/Shanghai"} }) + dtSection(c, "TimezoneSelect", func() { + dtControls(c, func() { mujica.Checkbox(c, &s.disabled, "Disabled", mujica.CheckboxOptions{}) }) + if mujica.TimezoneSelect(c, &s.zone, mujica.TimezoneSelectOptions{Disabled: s.disabled}).Changed() { + log("zone " + s.zone) + } + }) +} + +func calReminderDemo(c *ui.Context, log func(string)) { + type state struct { + v []time.Duration + max string + disabled bool + } + s := ui.Local(c.Root(), "433", func() state { return state{v: []time.Duration{15 * time.Minute}, max: "0"} }) + dtSection(c, "ReminderPicker", func() { + dtControls(c, func() { + mujica.Select(c, &s.max, calOptions([]string{"0", "2", "3"}), mujica.SelectOptions{Label: "Max (0 = any)"}) + mujica.Checkbox(c, &s.disabled, "Disabled", mujica.CheckboxOptions{}) + }) + if limit := calAtoi(s.max); limit > 0 && len(s.v) > limit { + s.v = s.v[:limit] + } + if mujica.ReminderPicker(c, &s.v, mujica.ReminderPickerOptions{Max: calAtoi(s.max), Disabled: s.disabled}).Changed() { + log(fmt.Sprint("reminders ", s.v)) + } + }) +} + +func calAttendeeDemo(c *ui.Context, log func(string)) { + type state struct { + list []mujica.Attendee + removable bool + } + people := func() []mujica.Attendee { + return []mujica.Attendee{{Name: "Sakiko Togawa", Status: mujica.AttendeeAccepted, Organizer: true}, + {Name: "Mutsumi Wakaba", Status: mujica.AttendeeTentative}, {Name: "Uika Misumi", Status: mujica.AttendeeDeclined}, + {Name: "Nyamu Yuutenji", Email: "nyamu@example.com"}} + } + s := ui.Local(c.Root(), "434", func() state { return state{list: people(), removable: true} }) + dtSection(c, "AttendeeList", func() { + dtControls(c, func() { + mujica.Checkbox(c, &s.removable, "Removable", mujica.CheckboxOptions{}) + if mujica.Button(c, "Reset", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.list = people() + log("reset") + } + }) + if i, ok := mujica.AttendeeList(c, s.list, mujica.AttendeeListOptions{Removable: s.removable}).Removed(); ok { + log("removed " + s.list[i].Name) + s.list = append(s.list[:i:i], s.list[i+1:]...) + } + }) +} diff --git a/examples/gallery/pages_calendar_time.go b/examples/gallery/pages_calendar_time.go new file mode 100644 index 0000000..78c432a --- /dev/null +++ b/examples/gallery/pages_calendar_time.go @@ -0,0 +1,128 @@ +package main + +import ( + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func calWeekPickerDemo(c *ui.Context, log func(string)) { + type state struct { + week mujica.Date + weekStart string + disabled bool + } + s := ui.Local(c.Root(), "435", func() state { return state{weekStart: "Locale"} }) + dtSection(c, "WeekPicker", func() { + dtControls(c, func() { + if mujica.Select(c, &s.weekStart, calOptions(calWeekStarts), mujica.SelectOptions{Label: "Week start"}).Changed() { + s.week = mujica.Date{} + log("week start " + s.weekStart + ", value cleared") + } + mujica.Checkbox(c, &s.disabled, "Disabled", mujica.CheckboxOptions{}) + }) + opts := mujica.WeekPickerOptions{WeekStart: calWeekStart(s.weekStart), Clearable: true, Disabled: s.disabled} + if mujica.WeekPicker(c, &s.week, opts).Changed() { + log("week of " + s.week.String()) + } + }) +} + +func calDurationDemo(c *ui.Context, log func(string)) { + type state struct { + v time.Duration + seconds, disabled bool + } + s := ui.Local(c.Root(), "436", func() state { return state{v: 90 * time.Minute} }) + dtSection(c, "DurationPicker", func() { + dtControls(c, func() { + mujica.Checkbox(c, &s.seconds, "Seconds", mujica.CheckboxOptions{}) + mujica.Checkbox(c, &s.disabled, "Disabled", mujica.CheckboxOptions{}) + }) + opts := mujica.DurationPickerOptions{Seconds: s.seconds, Min: 15 * time.Minute, Max: 8 * time.Hour, Disabled: s.disabled} + if mujica.DurationPicker(c, &s.v, opts).Changed() { + log("duration " + s.v.String()) + } + }) +} + +func calCronDemo(c *ui.Context, log func(string)) { + type state struct { + expr string + disabled bool + } + s := ui.Local(c.Root(), "437", func() state { return state{expr: "*/15 9-17 * * MON-FRI"} }) + dtSection(c, "CronEditor", func() { + dtControls(c, func() { mujica.Checkbox(c, &s.disabled, "Disabled", mujica.CheckboxOptions{}) }) + if mujica.CronEditor(c, &s.expr, mujica.CronEditorOptions{Location: time.Local, Disabled: s.disabled}).Changed() { + if _, err := mujica.ParseCron(s.expr); err != nil { + log("invalid: " + s.expr) + } else { + log("schedule " + s.expr) + } + } + }) +} + +func calRelativeDemo(c *ui.Context, log func(string)) { + type state struct{ at time.Time } + s := ui.Local(c.Root(), "438", func() state { return state{at: time.Now()} }) + dtSection(c, "RelativeTime", func() { + dtControls(c, func() { + for _, b := range []struct { + label string + d time.Duration + }{{"Now", 0}, {"5 minutes ago", -5 * time.Minute}, {"In 3 hours", 3 * time.Hour}, {"40 days ago", -40 * 24 * time.Hour}} { + if mujica.Button(c, b.label, mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.at = time.Now().Add(b.d) + log("time set: " + b.label) + } + } + }) + mujica.RelativeTime(c, s.at, mujica.RelativeTimeOptions{Location: time.Local}) + }) +} + +func calCountdownDemo(c *ui.Context, log func(string)) { + type state struct { + deadline time.Time + words bool + } + s := ui.Local(c.Root(), "439", func() state { return state{deadline: time.Now().Add(10 * time.Second)} }) + dtSection(c, "Countdown", func() { + dtControls(c, func() { + if mujica.Button(c, "Restart 10 s", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.deadline = time.Now().Add(10 * time.Second) + log("restarted") + } + mujica.Checkbox(c, &s.words, "Words", mujica.CheckboxOptions{}) + }) + format := mujica.CountdownClock + if s.words { + format = mujica.CountdownWords + } + if mujica.Countdown(c, s.deadline, mujica.CountdownOptions{Format: format}).Finished() { + log("finished") + } + }) +} + +func calStopwatchDemo(c *ui.Context, log func(string)) { + type state struct { + sw mujica.StopwatchState + disabled bool + } + s := ui.Local(c.Root(), "440", func() state { return state{} }) + dtSection(c, "Stopwatch", func() { + dtControls(c, func() { mujica.Checkbox(c, &s.disabled, "Disabled", mujica.CheckboxOptions{}) }) + if mujica.Stopwatch(c, &s.sw, mujica.StopwatchOptions{Disabled: s.disabled}).Changed() { + state := "paused" + if s.sw.Running() { + state = "running" + } + log(state + ", " + mujica.StopwatchText(s.sw.Elapsed(time.Now()))) + } + }) +} diff --git a/examples/gallery/pages_calendar_views.go b/examples/gallery/pages_calendar_views.go new file mode 100644 index 0000000..b7b627b --- /dev/null +++ b/examples/gallery/pages_calendar_views.go @@ -0,0 +1,194 @@ +package main + +import ( + "fmt" + "strconv" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +// calSample is demo events around today in the local zone. +func calSample() []mujica.CalendarEvent { + now := time.Now() + day := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local) + at := func(d, h, m, mins int) (time.Time, time.Time) { + s := day.AddDate(0, 0, d).Add(time.Duration(h)*time.Hour + time.Duration(m)*time.Minute) + return s, s.Add(time.Duration(mins) * time.Minute) + } + mk := func(id, title string, color mujica.EventColor, d, h, m, mins int) mujica.CalendarEvent { + s, e := at(d, h, m, mins) + return mujica.CalendarEvent{ID: id, Title: title, Color: color, Start: s, End: e, Location: "Rehearsal hall"} + } + evs := []mujica.CalendarEvent{ + mk("1", "Rehearsal", mujica.EventAccent, 0, 9, 0, 120), mk("2", "Costume fitting", mujica.EventInfo, 0, 10, 0, 60), + mk("3", "Lunch", mujica.EventSuccess, 0, 12, 30, 60), mk("4", "Lyrics review", mujica.EventWarning, 1, 14, 0, 90), + mk("5", "Press", mujica.EventDanger, 2, 16, 0, 45), mk("6", "Sound check", mujica.EventNeutral, 3, 18, 0, 60), + mk("7", "Encore notes", mujica.EventInfo, 0, 15, 0, 30), mk("8", "Stage walk", mujica.EventAccent, 0, 17, 0, 30), + } + holiday := mk("9", "Masquerade", mujica.EventAccent, 4, 0, 0, 24*60) + holiday.AllDay, holiday.Start = true, day.AddDate(0, 0, 4) + holiday.End = holiday.Start.AddDate(0, 0, 1) + return append(evs, holiday) +} + +// calApply applies and logs a view change. +func calApply(evs *[]mujica.CalendarEvent, ch mujica.CalendarChange, log func(string)) { + switch ch.Kind { + case mujica.CalendarCreate: + id := fmt.Sprint(len(*evs) + 100) + *evs = append(*evs, mujica.CalendarEvent{ID: id, Title: "New event", Start: ch.Start, End: ch.End}) + log("created " + ch.Start.Format("Jan 2 15:04") + " – " + ch.End.Format("15:04")) + return + } + for i := range *evs { + if (*evs)[i].ID == ch.ID { + (*evs)[i].Start, (*evs)[i].End = ch.Start, ch.End + } + } + verb := "moved" + if ch.Kind == mujica.CalendarResize { + verb = "resized" + } + log(fmt.Sprintf("%s %s to %s – %s", verb, ch.ID, ch.Start.Format("Jan 2 15:04"), ch.End.Format("15:04"))) +} + +// calViewResult logs what a view reported and applies its change. +func calViewResult(r mujica.CalendarViewResult, evs *[]mujica.CalendarEvent, version *int, log func(string)) { + if id, ok := r.Opened(); ok { + log("opened " + id) + } + if d, ok := r.DayChosen(); ok { + log("day " + d.String()) + } + if ch, ok := r.Changed(); ok { + calApply(evs, ch, log) + *version++ + } +} + +var calWeekStarts = []string{"Locale", "Sunday", "Monday", "Saturday"} + +func calWeekStart(s string) mujica.WeekStart { + for i, n := range calWeekStarts { + if n == s { + return mujica.WeekStart(i) + } + } + panic("gallery: unknown week start " + s) +} + +func calMonthDemo(c *ui.Context, log func(string)) { + type state struct { + month mujica.YearMonth + events []mujica.CalendarEvent + version, maxRows int + weekStart, maxStr string + disabled bool + } + s := ui.Local(c.Root(), "421", func() state { + now := time.Now() + return state{month: mujica.YearMonth{Year: now.Year(), Month: now.Month()}, events: calSample(), weekStart: "Locale", maxStr: "3"} + }) + dtSection(c, "CalendarMonthView", func() { + dtControls(c, func() { + mujica.Select(c, &s.weekStart, calOptions(calWeekStarts), mujica.SelectOptions{Label: "Week start"}) + mujica.Select(c, &s.maxStr, calOptions([]string{"1", "2", "3", "4"}), mujica.SelectOptions{Label: "Rows per day"}) + mujica.Checkbox(c, &s.disabled, "Disabled", mujica.CheckboxOptions{}) + }) + s.maxRows = calAtoi(s.maxStr) + r := mujica.CalendarMonthView(c, &s.month, s.events, mujica.CalendarMonthViewOptions{Location: time.Local, Version: s.version, + WeekStart: calWeekStart(s.weekStart), MaxPerDay: s.maxRows, Disabled: s.disabled}) + calViewResult(r, &s.events, &s.version, log) + }) +} + +func calWeekDemo(c *ui.Context, log func(string)) { + type state struct { + week mujica.Date + events []mujica.CalendarEvent + version int + slot string + hour12 bool + disabled bool + } + s := ui.Local(c.Root(), "422", func() state { + return state{week: mujica.DateOf(time.Now()), events: calSample(), slot: "30"} + }) + dtSection(c, "CalendarWeekView", func() { + dtControls(c, func() { + mujica.Select(c, &s.slot, calOptions([]string{"15", "30", "60"}), mujica.SelectOptions{Label: "Slot minutes"}) + mujica.Checkbox(c, &s.hour12, "12-hour", mujica.CheckboxOptions{}) + mujica.Checkbox(c, &s.disabled, "Disabled", mujica.CheckboxOptions{}) + }) + slot := calAtoi(s.slot) + r := mujica.CalendarWeekView(c, &s.week, s.events, mujica.CalendarWeekViewOptions{Location: time.Local, Version: s.version, + SlotMinutes: slot, Hour12: s.hour12, Disabled: s.disabled}) + calViewResult(r, &s.events, &s.version, log) + }) +} + +func calDayDemo(c *ui.Context, log func(string)) { + type state struct { + day mujica.Date + events []mujica.CalendarEvent + version int + disabled bool + } + s := ui.Local(c.Root(), "423", func() state { return state{day: mujica.DateOf(time.Now()), events: calSample()} }) + dtSection(c, "CalendarDayView", func() { + dtControls(c, func() { mujica.Checkbox(c, &s.disabled, "Disabled", mujica.CheckboxOptions{}) }) + r := mujica.CalendarDayView(c, &s.day, s.events, mujica.CalendarDayViewOptions{Location: time.Local, Version: s.version, Disabled: s.disabled}) + calViewResult(r, &s.events, &s.version, log) + }) +} + +func calAgendaDemo(c *ui.Context, log func(string)) { + type state struct { + events []mujica.CalendarEvent + days string + } + s := ui.Local(c.Root(), "424", func() state { return state{events: calSample(), days: "7"} }) + dtSection(c, "AgendaView", func() { + dtControls(c, func() { + mujica.Select(c, &s.days, calOptions([]string{"1", "7", "30"}), mujica.SelectOptions{Label: "Days"}) + }) + days := calAtoi(s.days) + ui.Column(c).Height(420).Children(func() { + if id, ok := mujica.AgendaView(c, s.events, mujica.AgendaViewOptions{Location: time.Local, Days: days}).Opened(); ok { + log("opened " + id) + } + }) + }) +} + +func calYearDemo(c *ui.Context, log func(string)) { + type state struct { + year int + events []mujica.CalendarEvent + } + s := ui.Local(c.Root(), "425", func() state { return state{year: time.Now().Year(), events: calSample()} }) + dtSection(c, "YearView", func() { + if d, ok := mujica.YearView(c, &s.year, s.events, mujica.YearViewOptions{Location: time.Local}).DayChosen(); ok { + log("day " + d.String()) + } + }) +} + +func calAtoi(s string) int { + n, err := strconv.Atoi(s) + if err != nil { + panic(err) + } + return n +} + +func calOptions(values []string) []mujica.SelectOption[string] { + out := make([]mujica.SelectOption[string], len(values)) + for i, v := range values { + out[i] = mujica.SelectOption[string]{Value: v, Label: v} + } + return out +} diff --git a/internal/calendar.go b/internal/calendar.go new file mode 100644 index 0000000..1b6164d --- /dev/null +++ b/internal/calendar.go @@ -0,0 +1,9 @@ +package internal + +import "github.com/egoist/mygo/ui" + +// Rule draws a pixel-aligned 1 DIP horizontal line at y. +func Rule(p *ui.Painter, x0, x1, y float32, c ui.Color) { + yy := ruleY(p, y) + p.Line(x0, yy, x1, yy, 1, c) +} diff --git a/messages_calendar.go b/messages_calendar.go new file mode 100644 index 0000000..af24774 --- /dev/null +++ b/messages_calendar.go @@ -0,0 +1,195 @@ +package mujica + +import ( + "fmt" + + "github.com/egoist/mygo/ui" +) + +// calendarCount formats a count, using "_one" for one. +func calendarCount(c *ui.Context, key string, n int) string { + if n == 1 { + key += "_one" + } + return fmt.Sprintf(msg(c, key), n) +} + +func init() { + addMessages(map[string][2]string{ + "event_chip.all_day": {"All day", "全天"}, + "event_chip.untitled": {"(No title)", "(无标题)"}, + + "attendee_list.label": {"Attendees", "参与者"}, + "attendee_list.summary": {"%d accepted · %d maybe · %d declined · %d awaiting", "%d 人接受 · %d 人待定 · %d 人拒绝 · %d 人未回复"}, + "attendee_list.empty": {"No attendees yet.", "暂无参与者。"}, + "attendee_list.organizer": {"Organizer", "组织者"}, + "attendee_list.optional": {"Optional", "可选"}, + "attendee_list.remove": {"Remove %s", "移除 %s"}, + "attendee_list.pending": {"Awaiting reply", "未回复"}, + "attendee_list.accepted": {"Accepted", "已接受"}, + "attendee_list.tentative": {"Maybe", "待定"}, + "attendee_list.declined": {"Declined", "已拒绝"}, + + "recurrence_editor.label": {"Recurrence", "重复规则"}, + "recurrence_editor.repeat": {"Repeat", "重复"}, + "recurrence_editor.none": {"Does not repeat", "不重复"}, + "recurrence_editor.daily": {"Daily", "每天"}, + "recurrence_editor.weekly": {"Weekly", "每周"}, + "recurrence_editor.monthly": {"Monthly", "每月"}, + "recurrence_editor.yearly": {"Yearly", "每年"}, + "recurrence_editor.custom": {"Custom", "自定义"}, + "recurrence_editor.every": {"Every", "每"}, + "recurrence_editor.interval": {"Interval", "间隔"}, + "recurrence_editor.unit": {"Unit", "单位"}, + "recurrence_editor.days": {"days", "天"}, + "recurrence_editor.weeks": {"weeks", "周"}, + "recurrence_editor.months": {"months", "个月"}, + "recurrence_editor.years": {"years", "年"}, + "recurrence_editor.on_days": {"On days", "重复于"}, + "recurrence_editor.ends": {"Ends", "结束"}, + "recurrence_editor.forever": {"Never", "永不"}, + "recurrence_editor.after": {"After", "次数"}, + "recurrence_editor.until": {"On date", "截止日期"}, + "recurrence_editor.count": {"Occurrences", "重复次数"}, + "recurrence_editor.until_date": {"End date", "结束日期"}, + "recurrence_editor.no_days": {"Choose at least one day.", "请至少选择一天。"}, + "recurrence_editor.bad_count": {"Repeat at least once.", "重复次数至少为 1。"}, + "recurrence_editor.bad_until": {"The end date must not precede the start.", "结束日期不能早于开始日期。"}, + "recurrence_editor.never": {"Does not repeat", "不重复"}, + "recurrence_editor.every_n": {"Every %d %s", "每 %d %s"}, + "recurrence_editor.on": {" on %s", ",于%s"}, + "recurrence_editor.list_sep": {", ", "、"}, + "recurrence_editor.times": {", %d times", ",共 %d 次"}, + "recurrence_editor.times_one": {", %d time", ",共 %d 次"}, + "recurrence_editor.until_text": {", until %v", ",至 %v"}, + + "reminder_picker.label": {"Reminders", "提醒"}, + "reminder_picker.at_start": {"At start", "开始时"}, + "reminder_picker.minutes": {"%d minutes before", "提前 %d 分钟"}, + "reminder_picker.minutes_one": {"%d minute before", "提前 %d 分钟"}, + "reminder_picker.hours": {"%d hours before", "提前 %d 小时"}, + "reminder_picker.hours_one": {"%d hour before", "提前 %d 小时"}, + "reminder_picker.days": {"%d days before", "提前 %d 天"}, + "reminder_picker.days_one": {"%d day before", "提前 %d 天"}, + "reminder_picker.weeks": {"%d weeks before", "提前 %d 周"}, + "reminder_picker.weeks_one": {"%d week before", "提前 %d 周"}, + + "calendar_month_view.more": {"+%d", "+%d"}, + "calendar_month_view.more_label": {"%d more events", "另有 %d 项"}, + "calendar_month_view.more_label_one": {"%d more event", "另有 %d 项"}, + + "current_time_indicator.label": {"Now, %s", "当前时间 %s"}, + + "calendar_week_view.all_day": {"All day", "全天"}, + "calendar_week_view.prev": {"Previous week", "上一周"}, + "calendar_week_view.next": {"Next week", "下一周"}, + "calendar_week_view.title": {"%[1]s %[2]d – %[3]s %[4]d, %[5]d", "%[5]d年%[1]s%[2]d日 – %[3]s%[4]d日"}, + "calendar_week_view.resize": {"Resize %s", "调整 %s 的时长"}, + "calendar_week_view.too_short": {"An event must end after it starts.", "结束时间须晚于开始时间。"}, + "calendar_week_view.column": {"Schedule, %s", "%s 日程"}, + "calendar_day_view.prev": {"Previous day", "前一天"}, + "calendar_day_view.next": {"Next day", "后一天"}, + + "agenda_view.label": {"Agenda", "日程"}, + "agenda_view.today": {"Today", "今天"}, + "agenda_view.empty": {"No events in the next %d days.", "未来 %d 天没有日程。"}, + + "year_view.events": {"%d events", "%d 项日程"}, + "year_view.events_one": {"%d event", "%d 项日程"}, + + "event_popover.close": {"Close", "关闭"}, + "event_popover.edit": {"Edit", "编辑"}, + "event_popover.delete": {"Delete", "删除"}, + "event_popover.guests": {"%d guests", "%d 位参与者"}, + "event_popover.guests_one": {"%d guest", "%d 位参与者"}, + + "week_picker.label": {"Week", "周"}, + "week_picker.placeholder": {"Select week", "选择周"}, + + "duration_picker.label": {"Duration", "时长"}, + "duration_picker.hours": {"Hours", "小时数"}, + "duration_picker.minutes": {"Minutes", "分钟数"}, + "duration_picker.seconds": {"Seconds", "秒数"}, + "duration_picker.hours_unit": {"h", "小时"}, + "duration_picker.minutes_unit": {"min", "分"}, + "duration_picker.seconds_unit": {"s", "秒"}, + "duration_picker.range": {"Choose a duration from %s to %s.", "请选择 %s 至 %s 之间的时长。"}, + + "timezone_select.label": {"Time zone", "时区"}, + "timezone_select.placeholder": {"Select time zone", "选择时区"}, + "timezone_select.search": {"Search city or offset", "搜索城市或偏移"}, + "timezone_select.empty": {"No matching time zone.", "没有匹配的时区。"}, + "timezone_select.common": {"Common", "常用"}, + "timezone_select.all": {"All time zones", "全部时区"}, + + "availability_picker.label": {"Availability", "空闲时段"}, + "availability_picker.mine": {"you are free", "你有空"}, + "availability_picker.others": {"%d of %d others free", "其他 %[2]d 人中 %[1]d 人有空"}, + + "event_editor.label": {"Event", "日程"}, + "event_editor.title": {"Title", "标题"}, + "event_editor.all_day": {"All day", "全天"}, + "event_editor.starts": {"Starts", "开始"}, + "event_editor.ends": {"Ends", "结束"}, + "event_editor.where": {"Location", "地点"}, + "event_editor.guests": {"Guests", "参与者"}, + "event_editor.guests_help": {"Type a name and press Enter.", "输入姓名后按回车。"}, + "event_editor.reminders": {"Reminders", "提醒"}, + "event_editor.save": {"Save", "保存"}, + "event_editor.need_title": {"Enter a title.", "请输入标题。"}, + "event_editor.need_start": {"Choose a start.", "请选择开始时间。"}, + "event_editor.end_order": {"The end must be after the start.", "结束须晚于开始。"}, + + "cron_editor.expression": {"Expression", "表达式"}, + "cron_editor.label": {"Cron schedule", "Cron 表达式"}, + "cron_editor.next": {"Next runs", "下次运行"}, + "cron_editor.never": {"No run in the next five years.", "未来五年内不会运行。"}, + "cron_editor.repeated": {"repeated hour, first run", "重复时段,取首次"}, + "cron_editor.minute": {"Minute", "分钟"}, + "cron_editor.hour": {"Hour", "小时"}, + "cron_editor.dom": {"Day of month", "日"}, + "cron_editor.month": {"Month", "月"}, + "cron_editor.dow": {"Day of week", "星期"}, + "cron_editor.err_count": {"Use five fields, not %s.", "需要 5 个字段,而不是 %s 个。"}, + "cron_editor.err_empty": {"an empty list item", "列表项为空"}, + "cron_editor.err_step": {"step %q must be a positive number", "步长 %q 须为正整数"}, + "cron_editor.err_number": {"%q is not a number", "%q 不是数字"}, + "cron_editor.err_range": {"%s is outside %d–%d", "%s 超出 %d–%d"}, + "cron_editor.err_backwards": {"range %s runs backwards", "范围 %s 起止颠倒"}, + "cron_editor.field_error": {"%s: %s.", "%s:%s。"}, + "cron_editor.invalid": {"Invalid", "无效"}, + "cron_editor.any": {"Every value", "任意"}, + "cron_editor.every": {"Every %s", "每 %s"}, + "cron_editor.every_in": {"Every %s in %s", "%[2]s 内每 %[1]s"}, + + "relative_time.now": {"just now", "刚刚"}, + "relative_time.ago": {"%s ago", "%s前"}, + "relative_time.in": {"in %s", "%s后"}, + "relative_time.minutes": {"%d minutes", "%d 分钟"}, + "relative_time.minutes_one": {"%d minute", "%d 分钟"}, + "relative_time.hours": {"%d hours", "%d 小时"}, + "relative_time.hours_one": {"%d hour", "%d 小时"}, + "relative_time.days": {"%d days", "%d 天"}, + "relative_time.days_one": {"%d day", "%d 天"}, + "relative_time.months": {"%d months", "%d 个月"}, + "relative_time.months_one": {"%d month", "%d 个月"}, + "relative_time.years": {"%d years", "%d 年"}, + "relative_time.years_one": {"%d year", "%d 年"}, + + "countdown.label": {"Time left", "剩余时间"}, + "countdown.done": {"%s: time is up.", "%s:时间到。"}, + "countdown.days_clock": {"%dd", "%d天"}, + "countdown.d": {"%d d", "%d 天"}, + "countdown.h": {"%d h", "%d 小时"}, + "countdown.m": {"%d min", "%d 分"}, + "countdown.s": {"%d s", "%d 秒"}, + + "stopwatch.label": {"Stopwatch", "秒表"}, + "stopwatch.start": {"Start", "开始"}, + "stopwatch.pause": {"Pause", "暂停"}, + "stopwatch.resume": {"Resume", "继续"}, + "stopwatch.lap": {"Lap", "计次"}, + "stopwatch.reset": {"Reset", "复位"}, + "stopwatch.lap_n": {"Lap %d", "第 %d 圈"}, + }) +} diff --git a/recurrence_editor.go b/recurrence_editor.go new file mode 100644 index 0000000..a7bd8b7 --- /dev/null +++ b/recurrence_editor.go @@ -0,0 +1,223 @@ +package mujica + +import ( + "fmt" + "log/slog" + "math" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// RepeatUnit is how often a rule repeats; zero never does. +type RepeatUnit int + +const ( + RepeatNone RepeatUnit = iota + RepeatDaily + RepeatWeekly + RepeatMonthly + RepeatYearly +) + +// RepeatEnd says when a recurrence stops. +type RepeatEnd int + +const ( + RepeatForever RepeatEnd = iota + RepeatCount + RepeatUntil +) + +// Recurrence repeats every Interval units, on Weekdays when weekly. +type Recurrence struct { + Unit RepeatUnit + Interval int + Weekdays []time.Weekday + End RepeatEnd + Count int + Until Date +} + +// RecurrenceEditorOptions configure a RecurrenceEditor. +type RecurrenceEditorOptions struct { + // Start is the first occurrence; Until must not precede it. + Start Date + WeekStart WeekStart + Disabled bool + Label string +} + +// RecurrenceResult is the editor, its change and its problem. +type RecurrenceResult struct { + Element *ui.Element + changed bool + problem string +} + +// Changed reports whether the user changed the rule this frame. +func (r RecurrenceResult) Changed() bool { return r.changed } + +// Problem explains why the rule cannot be saved. +func (r RecurrenceResult) Problem() string { return r.problem } + +const recurrenceCustom = 5 + +// RecurrenceEditor edits a repeat rule and when it ends. +func RecurrenceEditor(c *ui.Context, rule *Recurrence, opts RecurrenceEditorOptions) RecurrenceResult { + recurrenceCheck(*rule) + d := Density(c) + k := Tokens(c) + before := recurrenceKey(*rule) + r := RecurrenceResult{} + label := opts.Label + if label == "" { + label = msg(c, "recurrence_editor.label") + } + r.Element = ui.Column(c).Gap(d.Unit() * 3).Role(ui.RoleGroup).Label(label).Disabled(opts.Disabled) + custom := ui.Local(r.Element, "recurrence-custom", func() bool { return rule.Interval > 1 }) + r.Element.Children(func() { + mode := int(rule.Unit) + if *custom && rule.Unit != RepeatNone { + mode = recurrenceCustom + } + modes := []SelectOption[int]{} + for i, key := range []string{"none", "daily", "weekly", "monthly", "yearly", "custom"} { + modes = append(modes, SelectOption[int]{Value: i, Label: msg(c, "recurrence_editor."+key)}) + } + if Select(c, &mode, modes, SelectOptions{Label: msg(c, "recurrence_editor.repeat"), Disabled: opts.Disabled}).Changed() { + *custom = mode == recurrenceCustom + switch { + case *custom: + rule.Unit = max(rule.Unit, RepeatDaily) + rule.Interval = max(rule.Interval, 2) + default: + rule.Unit, rule.Interval = RepeatUnit(mode), 1 + if mode == int(RepeatNone) { + *rule = Recurrence{} + } + } + if rule.Unit == RepeatWeekly && len(rule.Weekdays) == 0 && !opts.Start.IsZero() { + rule.Weekdays = []time.Weekday{opts.Start.Weekday()} + } + } + if rule.Unit == RepeatNone { + return + } + if *custom { + ui.Row(c).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, msg(c, "recurrence_editor.every")) + ui.Box(c).Width(d.ControlHeight() * 4).Children(func() { + n := float64(rule.Interval) + if NumberInput(c, &n, NumberInputOptions{Min: 1, Max: 999, Label: msg(c, "recurrence_editor.interval"), Disabled: opts.Disabled}).Changed() && !math.IsNaN(n) { + rule.Interval = int(n) + } + }) + units := []SelectOption[RepeatUnit]{} + for u := RepeatDaily; u <= RepeatYearly; u++ { + units = append(units, SelectOption[RepeatUnit]{Value: u, Label: msg(c, recurrenceUnitKeys[u])}) + } + Select(c, &rule.Unit, units, SelectOptions{Label: msg(c, "recurrence_editor.unit"), Disabled: opts.Disabled}) + }) + } + if rule.Unit == RepeatWeekly { + first := calendarFirstWeekday(c, opts.WeekStart) + items := []ToggleItem[time.Weekday]{} + for i := range 7 { + wd := time.Weekday((int(first) + i) % 7) + items = append(items, ToggleItem[time.Weekday]{Value: wd, Label: msg(c, fmt.Sprintf("calendar.weekday_%d", wd)), + Name: msg(c, fmt.Sprintf("calendar.weekday_long_%d", wd))}) + } + ToggleGroup(c, &rule.Weekdays, items, ToggleGroupOptions{Multiple: true, AllowEmpty: true, Label: msg(c, "recurrence_editor.on_days"), Disabled: opts.Disabled}) + } + ends := []RadioItem[RepeatEnd]{{Value: RepeatForever, Label: msg(c, "recurrence_editor.forever")}, + {Value: RepeatCount, Label: msg(c, "recurrence_editor.after")}, {Value: RepeatUntil, Label: msg(c, "recurrence_editor.until")}} + ui.Row(c).Gap(d.Unit() * 3).AlignItems(ui.Center).Wrap().Children(func() { + if RadioGroup(c, &rule.End, ends, RadioGroupOptions{Horizontal: true, Label: msg(c, "recurrence_editor.ends"), Disabled: opts.Disabled}).Changed() { + if rule.End == RepeatCount && rule.Count == 0 { + rule.Count = 10 + } + if rule.End == RepeatUntil && rule.Until.IsZero() && !opts.Start.IsZero() { + rule.Until = opts.Start.AddMonths(1) + } + } + switch rule.End { + case RepeatCount: + ui.Box(c).Width(d.ControlHeight() * 4).Children(func() { + n := float64(rule.Count) + if NumberInput(c, &n, NumberInputOptions{Min: 1, Max: 999, Label: msg(c, "recurrence_editor.count"), Disabled: opts.Disabled}).Changed() && !math.IsNaN(n) { + rule.Count = int(n) + } + }) + case RepeatUntil: + DatePicker(c, &rule.Until, DatePickerOptions{Label: msg(c, "recurrence_editor.until_date"), Min: opts.Start, Disabled: opts.Disabled}) + } + }) + r.problem = recurrenceProblem(c, *rule, opts.Start) + ui.Text(c, RecurrenceSummary(c, *rule)).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Role(ui.RoleStatus) + datetimeError(c, r.problem) + }) + if after := recurrenceKey(*rule); after != before && !r.Element.IsDisabled() { + slog.Debug("mujica: recurrence_editor change", "rule", after) + r.changed = true + } + return r +} + +var recurrenceUnitKeys = [...]string{"", "recurrence_editor.days", "recurrence_editor.weeks", "recurrence_editor.months", "recurrence_editor.years"} + +func recurrenceKey(r Recurrence) string { return fmt.Sprintf("%v", r) } + +// recurrenceCheck panics on rules no editor can show. +func recurrenceCheck(r Recurrence) { + if r.Unit < RepeatNone || r.Unit > RepeatYearly || r.End < RepeatForever || r.End > RepeatUntil || r.Interval < 0 || r.Count < 0 { + panic(fmt.Sprintf("mujica: Recurrence %+v is out of range", r)) + } + if r.Unit != RepeatNone && r.Interval == 0 { + panic("mujica: Recurrence repeats with Interval 0") + } + datetimeCheckDate("Recurrence Until", r.Until) +} + +// recurrenceProblem explains why a rule cannot be saved. +func recurrenceProblem(c *ui.Context, r Recurrence, start Date) string { + switch { + case r.Unit == RepeatNone: + return "" + case r.Unit == RepeatWeekly && len(r.Weekdays) == 0: + return msg(c, "recurrence_editor.no_days") + case r.End == RepeatCount && r.Count < 1: + return msg(c, "recurrence_editor.bad_count") + case r.End == RepeatUntil && (r.Until.IsZero() || !start.IsZero() && r.Until.Compare(start) < 0): + return msg(c, "recurrence_editor.bad_until") + } + return "" +} + +// RecurrenceSummary describes a rule in the window's language. +func RecurrenceSummary(c *ui.Context, r Recurrence) string { + if r.Unit == RepeatNone { + return msg(c, "recurrence_editor.never") + } + s := fmt.Sprintf(msg(c, "recurrence_editor.every_n"), r.Interval, msg(c, recurrenceUnitKeys[r.Unit])) + if r.Interval == 1 { + s = msg(c, []string{"", "recurrence_editor.daily", "recurrence_editor.weekly", "recurrence_editor.monthly", "recurrence_editor.yearly"}[r.Unit]) + } + if r.Unit == RepeatWeekly && len(r.Weekdays) > 0 { + var days []string + for _, wd := range r.Weekdays { + days = append(days, msg(c, fmt.Sprintf("calendar.weekday_long_%d", wd))) + } + s += fmt.Sprintf(msg(c, "recurrence_editor.on"), strings.Join(days, msg(c, "recurrence_editor.list_sep"))) + } + switch r.End { + case RepeatCount: + s += calendarCount(c, "recurrence_editor.times", r.Count) + case RepeatUntil: + s += fmt.Sprintf(msg(c, "recurrence_editor.until_text"), r.Until) + } + return s +} diff --git a/recurrence_editor_test.go b/recurrence_editor_test.go new file mode 100644 index 0000000..1f93803 --- /dev/null +++ b/recurrence_editor_test.go @@ -0,0 +1,133 @@ +package mujica + +import ( + "slices" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +type recurrenceProbe struct { + rule Recurrence + opts RecurrenceEditorOptions + changes int + problem string + summary string + disabled bool +} + +func (p *recurrenceProbe) tester() *ui.Tester { + p.opts.Start = oct(5) + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + o := p.opts + o.Disabled = p.disabled + r := RecurrenceEditor(c, &p.rule, o) + if r.Changed() { + p.changes++ + } + p.problem = r.Problem() + p.summary = RecurrenceSummary(c, p.rule) + }, 720, 520) +} + +func recurrencePick(t *testing.T, tt *ui.Tester, label string) { + t.Helper() + if err := tt.Click("Repeat"); err != nil { + t.Fatal(err) + } + if err := tt.Click(label); err != nil { + t.Fatal(err) + } +} + +func TestRecurrenceEditorPresets(t *testing.T) { + p := &recurrenceProbe{} + tt := p.tester() + recurrencePick(t, tt, "Weekly") + if p.rule.Unit != RepeatWeekly || p.rule.Interval != 1 || !slices.Equal(p.rule.Weekdays, []time.Weekday{time.Monday}) || p.changes != 1 { + t.Fatalf("weekly preset %+v", p.rule) + } + _ = tt.Click("Wednesday") + if p.summary != "Weekly on Monday, Wednesday" { + t.Fatalf("summary %q", p.summary) + } + for _, c := range []struct { + label string + unit RepeatUnit + }{{"Daily", RepeatDaily}, {"Monthly", RepeatMonthly}, {"Yearly", RepeatYearly}} { + recurrencePick(t, tt, c.label) + if p.rule.Unit != c.unit || p.rule.Interval != 1 { + t.Fatalf("%s gave %+v", c.label, p.rule) + } + } + recurrencePick(t, tt, "Does not repeat") + if p.rule.Unit != RepeatNone || p.summary != "Does not repeat" { + t.Fatalf("none gave %+v", p.rule) + } +} + +func TestRecurrenceEditorCustomAndEnds(t *testing.T) { + p := &recurrenceProbe{rule: Recurrence{Unit: RepeatDaily, Interval: 1}} + tt := p.tester() + recurrencePick(t, tt, "Custom") + if p.rule.Interval != 2 || !tt.HasText("Every") { + t.Fatalf("custom %+v", p.rule) + } + _ = tt.Click("Interval") + tt.Key(0, ui.KeyUp) + _ = tt.Click("After") + if p.rule.Interval != 3 || p.rule.End != RepeatCount || p.rule.Count != 10 || p.summary != "Every 3 days, 10 times" { + t.Fatalf("custom count %+v %q", p.rule, p.summary) + } + _ = tt.Click("On date") + if p.rule.End != RepeatUntil || p.rule.Until != (Date{2026, time.November, 5}) || p.problem != "" { + t.Fatalf("until %+v %q", p.rule, p.problem) + } +} + +func TestRecurrenceEditorProblems(t *testing.T) { + p := &recurrenceProbe{rule: Recurrence{Unit: RepeatWeekly, Interval: 1, Weekdays: []time.Weekday{time.Monday}}} + tt := p.tester() + _ = tt.Click("Monday") + if len(p.rule.Weekdays) != 0 || p.problem != "Choose at least one day." || !tt.HasText("Choose at least one day.") { + t.Fatalf("no-day problem %+v %q", p.rule, p.problem) + } + p.rule = Recurrence{Unit: RepeatDaily, Interval: 1, End: RepeatUntil, Until: Date{2026, time.September, 1}} + tt.Frame() + if p.problem != "The end date must not precede the start." { + t.Fatalf("until problem %q", p.problem) + } + for _, bad := range []Recurrence{{Unit: 9}, {Unit: RepeatDaily}, {Interval: -1}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%+v: expected panic", bad) + } + }() + q := &recurrenceProbe{rule: bad} + q.tester() + }() + } +} + +func TestRecurrenceEditorDisabled(t *testing.T) { + p := &recurrenceProbe{rule: Recurrence{Unit: RepeatWeekly, Interval: 1, Weekdays: []time.Weekday{time.Monday}}, disabled: true} + tt := p.tester() + _ = tt.Click("Repeat") + _ = tt.Click("Daily") + _ = tt.Click("Friday") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeySpace) + if p.rule.Unit != RepeatWeekly || len(p.rule.Weekdays) != 1 || p.changes != 0 { + t.Fatalf("disabled editor changed: %+v", p.rule) + } +} + +func TestRecurrenceEditorSnapshot(t *testing.T) { + r := Recurrence{Unit: RepeatWeekly, Interval: 2, Weekdays: []time.Weekday{time.Monday, time.Thursday}, End: RepeatCount, Count: 8} + snapshot(t, "recurrence_editor", 640, 280, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { RecurrenceEditor(c, &r, RecurrenceEditorOptions{Start: oct(5)}) }) + }) +} diff --git a/relative_time.go b/relative_time.go new file mode 100644 index 0000000..eb91cfa --- /dev/null +++ b/relative_time.go @@ -0,0 +1,75 @@ +package mujica + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" +) + +// RelativeTimeOptions configure a RelativeTime. +type RelativeTimeOptions struct { + // Location is the tooltip's zone; required. + Location *time.Location + // Now fixes the clock and stops updates. + Now time.Time + Hour12 bool +} + +// RelativeTime shows t as "3 minutes ago", refreshing while shown. +func RelativeTime(c *ui.Context, t time.Time, opts RelativeTimeOptions) *ui.Element { + loc := eventLocation("RelativeTime", opts.Location) + now := opts.Now + if now.IsZero() { + now = c.Now() + c.After(relativeTimeNext(now.Sub(t))) + } + text := RelativeTimeText(c, now.Sub(t)) + w := t.In(loc) + exact := DateOf(w).String() + " " + timeText(c, TimeOfDay{w.Hour(), w.Minute(), 0}, timeConfig{hour12: opts.Hour12}) + " " + w.Format("MST") + return ui.Text(c, text).Label(text + ", " + exact).Tooltip(exact).FontFeatures("tnum") +} + +// RelativeTimeText words d ago (positive) or ahead (negative). +func RelativeTimeText(c *ui.Context, d time.Duration) string { + past := d >= 0 + if !past { + d = -d + } + var key string + var n int + switch { + case d < 45*time.Second: + return msg(c, "relative_time.now") + case d < 45*time.Minute: + key, n = "minutes", max(1, int(d/time.Minute)) + case d < 22*time.Hour: + key, n = "hours", max(1, int(d/time.Hour)) + case d < 26*24*time.Hour: + key, n = "days", max(1, int(d/(24*time.Hour))) + case d < 320*24*time.Hour: + key, n = "months", max(1, int(d/(30*24*time.Hour))) + default: + key, n = "years", max(1, int(d/(365*24*time.Hour))) + } + unit := calendarCount(c, "relative_time."+key, n) + if past { + return fmt.Sprintf(msg(c, "relative_time.ago"), unit) + } + return fmt.Sprintf(msg(c, "relative_time.in"), unit) +} + +// relativeTimeNext is how long until the wording may change. +func relativeTimeNext(d time.Duration) time.Duration { + if d < 0 { + d = -d + } + step := time.Hour + switch { + case d < 2*time.Minute: + step = time.Second + case d < 2*time.Hour: + step = time.Minute + } + return step - d%step +} diff --git a/relative_time_test.go b/relative_time_test.go new file mode 100644 index 0000000..8501255 --- /dev/null +++ b/relative_time_test.go @@ -0,0 +1,83 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func TestRelativeTimeWording(t *testing.T) { + var en, zh []string + cases := []time.Duration{10 * time.Second, -90 * time.Second, 3 * time.Minute, 5 * time.Hour, -25 * time.Hour, 40 * 24 * time.Hour, 800 * 24 * time.Hour} + for _, loc := range []Locale{EnUS, ZhCN} { + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{Locale: loc}) + var out []string + for _, d := range cases { + out = append(out, RelativeTimeText(c, d)) + } + if loc == EnUS { + en = out + } else { + zh = out + } + }, 10, 10) + } + wantEn := []string{"just now", "in 1 minute", "3 minutes ago", "5 hours ago", "in 1 day", "1 month ago", "2 years ago"} + wantZh := []string{"刚刚", "1 分钟后", "3 分钟前", "5 小时前", "1 天后", "1 个月前", "2 年前"} + for i := range cases { + if en[i] != wantEn[i] || zh[i] != wantZh[i] { + t.Fatalf("%v: %q %q", cases[i], en[i], zh[i]) + } + } +} + +func TestRelativeTimeRefreshFollowsDistance(t *testing.T) { + for _, c := range []struct{ d, next time.Duration }{ + {10*time.Second + 300*time.Millisecond, 700 * time.Millisecond}, + {5*time.Minute + 20*time.Second, 40 * time.Second}, + {3*time.Hour + 15*time.Minute, 45 * time.Minute}, + {-(90 * time.Second), 1 * time.Second}, + } { + if got := relativeTimeNext(c.d); got != c.next { + t.Errorf("%v: next %v, want %v", c.d, got, c.next) + } + } +} + +func TestRelativeTimeShowsExactTimeAndStopsWhenHidden(t *testing.T) { + at := time.Date(2026, time.October, 5, 9, 0, 0, 0, time.UTC) + shown := true + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if shown { + RelativeTime(c, at, RelativeTimeOptions{Location: calTokyo, Now: at.Add(3 * time.Hour)}) + } + }, 300, 100) + if !tt.HasText("3 hours ago, 2026-10-05 18:00 JST") { + t.Fatalf("texts %v", tt.Texts()) + } + shown = false + tt.Frame() + if tt.HasText("ago") { + t.Fatal("hidden text remains") + } + defer func() { + if recover() == nil { + t.Fatal("expected panic without Location") + } + }() + ui.NewTester(func(c *ui.Context) { Use(c, Settings{}); RelativeTime(c, at, RelativeTimeOptions{}) }, 10, 10) +} + +func TestRelativeTimeSnapshot(t *testing.T) { + at := time.Date(2026, time.October, 5, 9, 0, 0, 0, calTokyo) + snapshot(t, "relative_time", 260, 120, func(c *ui.Context) { + ui.Column(c).Padding(16).Gap(8).Children(func() { + RelativeTime(c, at, RelativeTimeOptions{Location: calTokyo, Now: at.Add(20 * time.Second)}) + RelativeTime(c, at, RelativeTimeOptions{Location: calTokyo, Now: at.Add(-2 * time.Hour)}) + RelativeTime(c, at, RelativeTimeOptions{Location: calTokyo, Now: at.Add(72 * time.Hour)}) + }) + }) +} diff --git a/reminder_picker.go b/reminder_picker.go new file mode 100644 index 0000000..9d7c761 --- /dev/null +++ b/reminder_picker.go @@ -0,0 +1,73 @@ +package mujica + +import ( + "fmt" + "log/slog" + "slices" + "time" + + "github.com/egoist/mygo/ui" +) + +// ReminderPickerOptions configure a ReminderPicker. +type ReminderPickerOptions struct { + // Choices are the lead times offered; empty uses defaults. + Choices []time.Duration + // Max limits how many are set; zero means any. + Max int + Disabled bool + Label string +} + +var reminderDefaults = []time.Duration{0, 5 * time.Minute, 15 * time.Minute, 30 * time.Minute, time.Hour, 24 * time.Hour, 7 * 24 * time.Hour} + +// ReminderPicker toggles reminder lead times, kept in choice order. +func ReminderPicker(c *ui.Context, value *[]time.Duration, opts ReminderPickerOptions) ChoiceResult { + choices := opts.Choices + if len(choices) == 0 { + choices = reminderDefaults + } + for i, d := range choices { + if d < 0 || d%time.Minute != 0 || slices.Contains(choices[:i], d) { + panic(fmt.Sprintf("mujica: ReminderPicker choice %v is negative, sub-minute or repeated", d)) + } + } + for _, d := range *value { + if !slices.Contains(choices, d) { + panic(fmt.Sprintf("mujica: ReminderPicker value %v is not a choice", d)) + } + } + if opts.Max < 0 || opts.Max > 0 && len(*value) > opts.Max { + panic(fmt.Sprintf("mujica: ReminderPicker Max %d is negative or below the value", opts.Max)) + } + full := opts.Max > 0 && len(*value) >= opts.Max + items := make([]ToggleItem[time.Duration], len(choices)) + for i, d := range choices { + items[i] = ToggleItem[time.Duration]{Value: d, Label: ReminderText(c, d), Disabled: full && !slices.Contains(*value, d)} + } + label := opts.Label + if label == "" { + label = msg(c, "reminder_picker.label") + } + r := ToggleGroup(c, value, items, ToggleGroupOptions{Multiple: true, AllowEmpty: true, Vertical: true, Label: label, Disabled: opts.Disabled}) + if r.Changed() { + slices.SortFunc(*value, func(a, b time.Duration) int { return slices.Index(choices, a) - slices.Index(choices, b) }) + slog.Debug("mujica: reminder_picker change", "value", *value) + } + return r +} + +// ReminderText words a lead time, as "15 minutes before". +func ReminderText(c *ui.Context, d time.Duration) string { + switch { + case d == 0: + return msg(c, "reminder_picker.at_start") + case d%(7*24*time.Hour) == 0: + return calendarCount(c, "reminder_picker.weeks", int(d/(7*24*time.Hour))) + case d%(24*time.Hour) == 0: + return calendarCount(c, "reminder_picker.days", int(d/(24*time.Hour))) + case d%time.Hour == 0: + return calendarCount(c, "reminder_picker.hours", int(d/time.Hour)) + } + return calendarCount(c, "reminder_picker.minutes", int(d/time.Minute)) +} diff --git a/reminder_picker_test.go b/reminder_picker_test.go new file mode 100644 index 0000000..69f1abf --- /dev/null +++ b/reminder_picker_test.go @@ -0,0 +1,82 @@ +package mujica + +import ( + "slices" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func reminderTester(v *[]time.Duration, opts ReminderPickerOptions, n *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if ReminderPicker(c, v, opts).Changed() { + *n++ + } + }, 640, 200) +} + +func TestReminderPickerTogglesInChoiceOrder(t *testing.T) { + v, n := []time.Duration{}, 0 + tt := reminderTester(&v, ReminderPickerOptions{}, &n) + _ = tt.Click("1 day before") + _ = tt.Click("15 minutes before") + _ = tt.Click("At start") + if !slices.Equal(v, []time.Duration{0, 15 * time.Minute, 24 * time.Hour}) || n != 3 { + t.Fatalf("value %v (%d)", v, n) + } + _ = tt.Click("15 minutes before") + if !slices.Equal(v, []time.Duration{0, 24 * time.Hour}) { + t.Fatalf("untoggle left %v", v) + } +} + +func TestReminderPickerMaxKeyboardDisabled(t *testing.T) { + v, n := []time.Duration{time.Hour}, 0 + tt := reminderTester(&v, ReminderPickerOptions{Max: 2}, &n) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeySpace) + _ = tt.Click("1 week before") + _ = tt.Click("5 minutes before") + if !slices.Equal(v, []time.Duration{0, time.Hour}) { + t.Fatalf("Max ignored: %v", v) + } + d := []time.Duration{} + tt = reminderTester(&d, ReminderPickerOptions{Disabled: true}, &n) + _ = tt.Click("At start") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeySpace) + if len(d) != 0 { + t.Fatal("disabled picker changed") + } +} + +func TestReminderTextAndInvalid(t *testing.T) { + var got []string + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{Locale: ZhCN}) + got = []string{ReminderText(c, time.Minute), ReminderText(c, 2*time.Hour), ReminderText(c, 14*24*time.Hour)} + }, 10, 10) + if !slices.Equal(got, []string{"提前 1 分钟", "提前 2 小时", "提前 2 周"}) { + t.Fatalf("texts %q", got) + } + for _, opts := range []ReminderPickerOptions{{Choices: []time.Duration{30 * time.Second}}, {Choices: []time.Duration{0, 0}}, {Max: -1}} { + func() { + defer func() { + if recover() == nil { + t.Errorf("%+v: expected panic", opts) + } + }() + v := []time.Duration{} + reminderTester(&v, opts, new(int)) + }() + } +} + +func TestReminderPickerSnapshot(t *testing.T) { + v := []time.Duration{15 * time.Minute, 24 * time.Hour} + snapshot(t, "reminder_picker", 300, 330, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { ReminderPicker(c, &v, ReminderPickerOptions{}) }) + }) +} diff --git a/stopwatch.go b/stopwatch.go new file mode 100644 index 0000000..9fc6e24 --- /dev/null +++ b/stopwatch.go @@ -0,0 +1,124 @@ +package mujica + +import ( + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// StopwatchState is the caller's run and laps. +type StopwatchState struct { + running bool + since time.Time + base time.Duration + // Laps are the elapsed times at each lap, oldest first. + Laps []time.Duration +} + +// Elapsed returns the time measured at now. +func (s *StopwatchState) Elapsed(now time.Time) time.Duration { + if s.running { + return s.base + now.Sub(s.since) + } + return s.base +} + +// Running reports whether the stopwatch is counting. +func (s *StopwatchState) Running() bool { return s.running } + +// StopwatchOptions configure a Stopwatch. +type StopwatchOptions struct { + // Now fixes the clock and stops ticking. + Now time.Time + Disabled bool + Label string +} + +// Stopwatch measures time with laps, ticking while running and shown. +func Stopwatch(c *ui.Context, s *StopwatchState, opts StopwatchOptions) ChoiceResult { + k := Tokens(c) + d := Density(c) + now := opts.Now + live := now.IsZero() + if live { + now = c.Now() + } + label := opts.Label + if label == "" { + label = msg(c, "stopwatch.label") + } + changed := false + col := ui.Column(c).Gap(d.Unit() * 3).Role(ui.RoleGroup).Label(label).Disabled(opts.Disabled) + act := func(what string, fn func()) { + if col.IsDisabled() { + return + } + fn() + changed = true + slog.Debug("mujica: stopwatch "+what, "elapsed", s.Elapsed(now)) + } + col.Children(func() { + el := s.Elapsed(now) + ui.Text(c, StopwatchText(el)).Font(theme.MonoFont).FontSize(FontSize(c, theme.H1Size)).TextColor(k.Text).FontFeatures("tnum"). + Label(label + ", " + StopwatchText(el)) + ui.Row(c).Gap(d.Unit() * 2).Children(func() { + start, variant := "stopwatch.start", Primary + if s.running { + start, variant = "stopwatch.pause", Secondary + } else if el > 0 { + start = "stopwatch.resume" + } + if Button(c, msg(c, start), ButtonOptions{Variant: variant}).Clicked() { + act("toggle", func() { + if s.running { + s.base, s.running = s.Elapsed(now), false + } else { + s.since, s.running = now, true + } + }) + } + if Button(c, msg(c, "stopwatch.lap"), ButtonOptions{Variant: Secondary, Disabled: !s.running}).Clicked() { + act("lap", func() { s.Laps = append(s.Laps, s.Elapsed(now)) }) + } + if Button(c, msg(c, "stopwatch.reset"), ButtonOptions{Variant: Ghost, Disabled: s.running || el == 0 && len(s.Laps) == 0}).Clicked() { + act("reset", func() { *s = StopwatchState{} }) + } + }) + if len(s.Laps) > 0 { + ui.Column(c).Role(ui.RoleList).Children(func() { + for i := len(s.Laps) - 1; i >= 0; i-- { + split := s.Laps[i] + if i > 0 { + split -= s.Laps[i-1] + } + row := ui.Row(c).MinHeight(d.ControlHeight()).AlignItems(ui.Center).Gap(d.Unit() * 4).Role(ui.RoleListItem) + row.DrawOver(func(p *ui.Painter, r ui.Rect) { internal.Rule(p, r.X, r.X+r.W, r.Y+r.H-1, k.Border) }) + row.Children(func() { + ui.Text(c, fmt.Sprintf(msg(c, "stopwatch.lap_n"), i+1)).Width(d.ControlHeight() * 2).TextColor(k.TextMuted) + ui.Text(c, StopwatchText(split)).Font(theme.MonoFont).FontFeatures("tnum").TextColor(k.Text).Grow(1) + ui.Text(c, StopwatchText(s.Laps[i])).Font(theme.MonoFont).FontFeatures("tnum").TextColor(k.TextMuted) + }) + } + }) + } + }) + if s.running && live { + c.After(100*time.Millisecond - s.Elapsed(now)%(100*time.Millisecond)) + } + return ChoiceResult{Element: col, changed: changed} +} + +// StopwatchText formats elapsed time as 01:02.3, with hours when needed. +func StopwatchText(d time.Duration) string { + t := int(d / (100 * time.Millisecond)) + h, m, s, tenth := t/36000, t%36000/600, t%600/10, t%10 + if h > 0 { + return fmt.Sprintf("%d:%02d:%02d.%d", h, m, s, tenth) + } + return fmt.Sprintf("%02d:%02d.%d", m, s, tenth) +} diff --git a/stopwatch_test.go b/stopwatch_test.go new file mode 100644 index 0000000..8709593 --- /dev/null +++ b/stopwatch_test.go @@ -0,0 +1,63 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func TestStopwatchStartLapPauseReset(t *testing.T) { + var s StopwatchState + now := time.Date(2026, time.October, 5, 9, 0, 0, 0, time.UTC) + n, disabled := 0, false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if Stopwatch(c, &s, StopwatchOptions{Now: now, Disabled: disabled}).Changed() { + n++ + } + }, 500, 500) + _ = tt.Click("Start") + now = now.Add(12*time.Second + 340*time.Millisecond) + tt.Frame() + if !tt.HasText("00:12.3") || !s.Running() { + t.Fatalf("running %v", tt.Texts()) + } + _ = tt.Click("Lap") + now = now.Add(5 * time.Second) + _ = tt.Click("Lap") + if len(s.Laps) != 2 || !tt.HasText("Lap 2") || !tt.HasText("00:05.0") { + t.Fatalf("laps %v %v", s.Laps, tt.Texts()) + } + _ = tt.Click("Pause") + now = now.Add(time.Minute) + tt.Frame() + if s.Running() || s.Elapsed(now) != 17340*time.Millisecond || !tt.HasText("Resume") { + t.Fatalf("paused at %v", s.Elapsed(now)) + } + tt.Key(0, ui.KeyEnter) + now = now.Add(time.Hour) + tt.Frame() + if !tt.HasText("1:00:17.3") { + t.Fatalf("resumed by keyboard: %v", tt.Texts()) + } + _ = tt.Click("Pause") + _ = tt.Click("Reset") + if s.Elapsed(now) != 0 || len(s.Laps) != 0 || n != 7 { + t.Fatalf("reset %v laps %v changes %d", s.Elapsed(now), s.Laps, n) + } + disabled = true + tt.Frame() + _ = tt.Click("Start") + if s.Running() { + t.Fatal("disabled stopwatch started") + } +} + +func TestStopwatchSnapshot(t *testing.T) { + now := time.Date(2026, time.October, 5, 9, 0, 0, 0, time.UTC) + s := StopwatchState{base: 83*time.Second + 400*time.Millisecond, Laps: []time.Duration{31 * time.Second, 62*time.Second + 500*time.Millisecond}} + snapshot(t, "stopwatch", 420, 260, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { Stopwatch(c, &s, StopwatchOptions{Now: now}) }) + }) +} diff --git a/testdata/snapshots/darwin/agenda_view-dark.png b/testdata/snapshots/darwin/agenda_view-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..4cba669035f3337723f2995dbaf2e5a3242a9762 GIT binary patch literal 26814 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

    kZTj4^pmyKP(s=2rp2F{4P!3N zu6rDa4)@+3J1dQJeM!1*w-B$sD>_;vGEd1TecFKjVw+0J)!wO;ZD(lZMmdh$UHC7C zI}fk7)L@q2tw8%y$gE{!Mb%h5)trL^5FQp5--qcqiyhi3uPgKO zU0bXZjjKcsR}QE#p%)hyQ(t#)iGe=LR=7*^V_9Qk7eZP2qSr2x^64e=BP2}8Zpf7cwv^! zp21OVcBjpDQs!V>#?O}aSgK}HN6)u?BT>ilt09Ye<;+!mOH8vc?D89Lg?GHz{Xdyn zzvp;(y(cGUB~?n>+bH2IRi1TgzIe6jt;WQJ#)XcJd35W{*#^O}^?h_}nxOZ6o=W|< z4K%)OqhuqeXF2{A&o9$3`6iN+S5h9AakLthr46}3Q7DVs>z&4s4e1E$YUiM9^Q0bo zf!5rnW0&TMp)SbsU(T6yl&NY7jHG2G4Uoq<+V5qyfGmCrt*b=F@xU*$F@)Q~~PxGH#OIhbKa;+C; z+PXRge!00nRwV}c?T+hNKUp%8fj&fIOGzTisB7o;0DccgvGcoA6JCYjHivfIl)(}D zTCSh@6`cMma7Ep~QZ^{W2RSvN1&sO>Ki^#=Q~${0`KB^b^2wR}aLT8T%*xQ1B`z_Y zH5bJAejp%vc-)<2itpB}loZ#|sj|4(e_EO|8)7=Nc^uhe6i2+8i>)>le6tJVd*Ro_ zDV9)LF6_HULu2!npW%D`)KvQ5!1(#`;|_D(mf*R8H;tuLHx>#tT|p(~8*%BVh!3p2 zeg3URdUiYeJ|j$wJ*i|oI1fq7b>-g6-68XoM{SRHsL$4bJ~y;~g@;X6#D}R3xJ0a^ z%Y%3H7ABurW&3ovgQtid1a;W+Y=TopehAP|le`e9^x2ouU}58xcIB09DLHIhFPv(l zUUo@dx)d<~l1W2yu?+7H(LEXu#D2gqF+sFZqG(dR$aXPN3Jon;5No!xtt7;`c>)#* zsatIhJikJtg@p6ay|?e9q%2X=uzrca%Jt=evF_`Wo{d`G-|bgtoPI2&mDjt~5?3v( zwa!3L<;oF?0LS8Ct+lqr)#aXeQ!Uy%b`39J|LvMXYh>A_fcZor;cqgd@Vo_hc+O0w zg>vGgw22Anr?*dZy0Gy7?w|SI`&wE~?zr-0X#EuC-_+DUvB&2B0U?F?&+HlcAI5X% z%X=MlBT4}Rfu!k?t_w`@R0GlB6#qW{H5Opt2FJbGg?|U819Xos6h-@Ho(&6&Hw**N zcVkj~1O5B-pKFKcUN?$?5E?wd-1LOU&HF?H_*Q+=c>g~BH5MQw@9pPJc>du@7zW5K XV(c{S;k&ngE(K);b@^)9*YExVwgLTV literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/agenda_view-light.png b/testdata/snapshots/darwin/agenda_view-light.png new file mode 100644 index 0000000000000000000000000000000000000000..6d5ab809b467860ec48e4c25760e6d71ed756097 GIT binary patch literal 25698 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/attendee_list-dark.png b/testdata/snapshots/darwin/attendee_list-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..6f044e5fac73cf02c5ea5f5744bef18afcfc8533 GIT binary patch literal 30519 zcmdRVV|Qd<^k#LE?%1}Ij@>akwr$%sI!T8W+qP}ncG9tJ{_8hu<{Qksm{qq{Ro%K( z_neJq?|t@j!sKPe;9+oJ0002Igt)LG0Pw8<^n`!{1D!c$UXBC+Tt6j*1(n@1&NCs^ z(Zq0vk8teW@a*x_jys=7pneU6_^tp%j( zZ0KafxN)7!e`g;P{n_lsb}ge$NQ~&0CD_O>&W~FARD^%PGB>dex9t?0f2U||=g8Ia z>vj|Ljo-+?pRM$jC!~4ry%5NyeKVwwl4N811((UTDXvGjd1r7+3(3}@mthBSCBCgXX{t)5$6M9^!C8OGE%5t{TX?FfMz zqxm^8$si2>Q8eA#K3&m5U7Q&u#KmQnuDUuU-ZK zjG0H>-diFoGLn{-x>p3D+Wp|pSyLy(fb(|Sel2I|@FkVM$xs|z<^3}g3)N|TGj8q| zULp*`ge4>#rtU48R58E;7^w~%CKAh`0#mTCe@JKP8|SDgX<_gjnRM1Tf8rDV?dU%+q+#ft=9DN_}J3Ki%HMgp>rk!NBUMFYRo?5Fb zZ9O>5e0xHP{|0DMO;VzKF}J9zbG$`EM|&OQ#)wC*^}d;}I1d2N&{|*1Gu-`T_xuwZ zuvLB=?h{IiyJBqw{-GhLLMze-T+Yq3sd+o!sq0Ik;B zVXa>J>DyG)d68A~C0Q}wH^9hrQEry4!e}`Qrr|g>^*6vLs!xb#3-a~zfEaK#?v>1j zZn9I11RJLT`8Q;K69M;1WT`K}KmN!lVRYYaIW)T+D>*Ld-?=`!%iQx~db20+8jqz< zDOiZgL&f!Z;AHJJ9QW{)dPL4lZ* z9o{LYYXfWzsusiPZ2(Jbofl6Mm09|)l|Ux1xKqUYZ$MS~8Z&-c7$H`&cRc$)=JB(6a!N#EX}e zQQKT(+$C250J~M&;<7$-?Ln;6F0&mmhe=EQ!*WIr>bO#{%wd0)prX$|7fIW7=c?Il z_1a&!F(^9$qHy>XlZLxB>S9{ydkUEQ`RQe+X-iG6PDZ3CVJ%PB3>SE^qN-LPJmnW1s0D$(#=Hja06f-@r`Rf=uKp-Yv&t8A|7b?U=pfhn zdR9bd+#L`9kw;f$VQ^=o3Ur~if`Y?UtR4s6W&QaEczaVGx;I@}*=ZR$tm7SQ(^m^& z>&ir{rP9H^2)?Yi50i=x}nG*xsDvF=0rOe zI{sVUvx$ev;$sx@4^J-3vNB`lmx*9?g6!=P+cmT(A0KUG_Uas=!HCGl>;eEfe$tm#l`a}Gc{#)k>hCzT_=u6dcngZEPJL!>=V23{ zfA-g~%q^#Lv((g|=`&)%D_VBY{ajg_6Hts?QGBLZJ|0D&M;QY5I}`S+mWmvOk9yfRJC zMYcLlJbHlt@X_)Td(Ns}d1>K+w)F-G`I;+y#3$+K0DxTifq#z35V7q!MCruQH#mp9 zjxEfo8z-Oh6?k0&JNj0WIaUctYRbwgQf>hG@XyV;a7nly{W(_7XI&ldz$(TFiK{h) z%_jBcVu{~6_;e?9i|pd#rIqE$@UKv7X|#A4Z--=QgE{qBkrf*qZW%t5ys~~2T6H6$ z@PzZd)MaI>laoahqH_io)*F4T^^tJ*_s$K#%xI7uuQBep^;LMtDk2AKQ&t%Z#?+p#03Yi%~TO8@{)dfEUAv`)}tT>~5- zXVB2mV@@zNtqg_$h#4k~1vj)Zv!kNn@td?guk1B>{)nr}b@e+UAV;C}c05afs6;;D z40qLBEcw%volSx)&PR-d#fgiau2y*W@Vum`EU^FIfFTn`go>KdZ<=RKs6g#*AI!~D z$k~Nb5SH&&ZMNJoDyWDYth@ZX6`b6QG@C+jm2MMtw8TlnG@s$($jg;YY(i--rF`Nq z?1PUwulg@~7}Ty*6+?rjX=!eJ_Yx@b&k9*WEI61XHZ)zT80ZYY);>I<2%e7rcIM)I zM#_x^AfjaOi%Ex7kzu2uWaz#g9B?pNTjwl1NZcajv7x2&<#68@aTsk;(5>3!{Wg66 z587SCge^+agb90*t@Gh)NEG_jWvaoBt zYb(SBa(_a;$bnET7(!MMso>ZI8jw@jxw$crk}HS`6)eJ_C-aD1K5B?_d}6!aGUWB= zC?c6$oz_)#2hB!iDYCSS3+W@|JE+IYHn zP8!WQ!o+~Lcf>m0HO?ugBDDfPC&qj(jm^^I_56vT2!LW_ z;#%BdYGPI^`fd%82o9}0AUinM7bEE^_S(llQ(j!C(y2A}wV!FLPBMH26X&RVV~;xD z-$Q_i&G})`=KRoHv&!OTx2mq8qokxpIqkHQj4Ji}$X54*985rSsGb`!9s;blS5I~- zWtV$kGirPRjH8kaWjG z2#BFdXEQtGLyY@}2#9$WI~Bkzwj)u!eSY7KQ&b7RO{a|RKiKk0VKx0jnJV1oaV5xr zaO?h_$&Zh>`>$x!cwk76aPQ#7AWOjKSD!hv`tgx3(vKiwDPjS2@t1%WeGohDT@P>RPXHy4TK4v{qwe)SIG-X+|D+&S+Yum zA|%KjJY5jHq;t4b1i*fSgK`}|SI9F7GLl#Zq`!lP3)e}E%$*uXRe7aKm=n-lZ;U4n zLo8Y}5$LdoSKKI6dOjhf?Oy{URmFdZ#GCOIh|ux~^~%pw=#s?SIv3h~I94RuY{$ir z_8BO2mM!5N-2MwJ1r4;=J_zfnWGE8bn_p-T3;!vI(ui>Jq57{dVdy0AM4z|x>G2$I z@*%EZyfje-6ih=$vv3LvOpJ{Wa=8DET=MhOooyEsl>8muTVGq>j=yqBgb5a+K(;zN z-QH(j;8#F1VOEi;jGeT#I`Y2mMRG-Qy$Z&cX6%Jf@*}tY!i4^RQtLg*1>#2wseVov zh$$7fAv$AUa{iT6v9h#1ym`JlbSIsJLAb_drzXBZwu~wI*Z;$26D2k^wcplqtJA6; zEI?jfJ@WEAUR^q*wY4^h;x3br0J!Ys!$$*3>u99vYmGXv;5>bNjJ|wDy2}?97ZLDR zN=tHL;?uvT=zo@U>wY|v0KVe|#`AepUV8Sl80hvfk{1WD}3Ct?i1a?+p1-`D{`; z-J;;)0vbkTN4d=MC>_d>L1(?j zW7w-3`fD~!oUE;tE3t#xYZw6}^e4ICOcX)E&>`i*l3hRyln4sF-pZJuv7XPcek~SH zw6MHwk+?@jjkXP28+hfX(kA!;wzSF`Z zHW@8{{wYAy!LQ^b4p4d@Zf(J1HA9E|d~Xi@`Ci>48zE^{X0^kl z&J;>{%uFXVU?@zRG;*#k^1ZAMCb&X-UR`gr>UaG;1x7@vpc1gt`(kPn0wC~EsY#!F zrf-)oKy*zO*IEz$;qAk!F%dp?ni6qCDJzmc>~dU=Zm?z4f$-_wQJIO_ z_MDIrF{szM@-gk29DFl_@@-laX<&Mpl9ttdGvuNa$O5vly!>c9evi+Mm+>o?rYBaL zQ(+aAL=!#R76+wQ+o!(1T`?+)Su?~?2*~$_tDgY^Eoi7O`=d%UG)}+4JE6PkA-q3N zRiw0a@R7sz`v%>o4T3KD#a}J9nOs~N8?BOB+c;1p1~3`In{B_SxQ|-vm|qm7jfD)u zqZ)%#OBHNvK7d}pjTR3z35lD9o6h2?fsC+lUcW~qcpruK1|y=8g`SzBqQjk3CCcZ> zUo*>-6JrrP1muMES1V1rL9(dV-@&!<5b!xYXqjPn5%_Za5r2LbL867g+0fyD(cFKhY%lAamIr<|j0?JmZ#?q4Db2kmsSaq5hZ%!{4*VH^;b_zcQ(2F5nEX|$&J)QGP_v7Ft3BO|yKI>3K< zdH&|^0Xbq2lR?ME&hG1_XR3Bf*Wx4<5rtq98oI8I)oA8q4$2Z&HTrA&_&%~?z4=Nj zC7pn`0XL|31Thc(x4QKS~XArOUg*BbsMn`hu2VNyJ-fC~` z<~C~`i?R8<@&Xcp-URCX31AgoXX4*384N4B#dUIWBYLMvlBrmdPpiQdaGM?uRs#z| zQE%J+;`K_5bb4u#Eg>PHYWsdOD*Z`QYrX2-ljX6GAsXQqRq09HUQgcl`hKCH>CEo; zhvxS7Dv4O}0i#g2^z>9(-KNLSAY&yZQg*dsSj;_k>$PtHadF9)lTf;RF^@-+dsg0= z>byM5waA*LCRdQQP7_(?!F~KXJ;%3~j~2`8Eatm+96dsTS#3COntVZ*O>1tKlv=eCn9V0Xn(~$?*b85;|Td(-D$d^<8~C8w&%^Q|U`yV*_f;#(__cMoRTV&oxzGVx7IkONcGWkEG3sA^u-2! z)bB@?XHf3LP2+xAu4WRz($}J`J29xYXDAm5Qa#}#UR+nI3T+m%jjxG{-tR!c6~UDc zjhgwqIsO!9bCf#>4uCnerFZU5=iMql0WbDBr$Nh+KB8N4?G~x&cSv`HyObU7GmlSL zBcq^28cZuorbT5H03h>Ul7{r_+~A#~<1M@03jy6Boy-j`aL~|i#pxKNg_DxuF+9Kw z=jqGG)bChvV%*G&VUVG*PGS6+8R(z>2(JfIm(FzpAR~ocy2G@0oTA$)Df?TIu&D9hnc5@e-LzdnGKP zsy?kVGxF7KZI6@R zoR_a4ly##9U(D{)FQHA#4NA=o!cG)9gA#`^ScW}!HkUp@g{DXJ9_TF@&?X=VTFiZD zVm&s_jP$qs$_2& zCxpq#&BWRR`*vLsjzkn{pRgDpy{rKKpjR_WZV#-(tg_6Mgg)arAIc~xX-R|n^!mE& z(5d*4LrF==i-VG`;)-*g@8A2{{vMQkQ`b!SA#-PAVL?YnCuV~`HZcVbpw;9E6;hx; zg8E0py~~Azb)1%lHKg0dHS4D8K9H1058kXBS5`LG#jACOi=$TcDN3+Y)Y@8DS5}nS zzY0pq*5KEdZQd`3D!mX1J_888{U=05*{w^1H&r?wG~@?pRaQO>#@_K%p^ek~sB zPl+mQ<4IGb@!~cY_^?OA5(RTwpp`TVxajib_$0c_r?blow@XtIX*@GaOYir64*;O+ z_3$X@&6me#7dSOVFC!C`Wyl(|>1wJ<57#d$`onE*#{Rh7LZe)b-r}G+F-Zl1>Fnj; zI=gr{^v7g)6f-lkwA6GHqnTVfSAaA{wa(Ma{IAKiwO4*%hAtyNJ@-eNP$^lUd8-2e zpsD#RSva@7ZRe_;P+0g<(el%JsJ`~&Y#MY^ARaF&8V8IGY0qTA!r5|sGJWdXc-2L- z;yl>L2MI;U<(5-UUL8*QA0u}Gqq+R0>Bbw!38{|c>tPXFHp@H{jrvS*UJ5#3?UPg3 zwud%#+x3#*E0RC3X@suKesL{;#@gW4uE>=DuflYo-<7R}_AMf!` zEOm~vQe%AJU0?s$)i8%snUw4{W%b(5gY25^G#UAmgh^CX7rj3RAA1Q}vqWZo0N$VP z2&E~E#tLe7YK@+4F5VFElm;a>#yzl5+sT}@b8-WGr#?DH-HS4x^m}tof z+?;DBF59P@4d;tA$;PIKWhv%08qdaSxG2H*P-_4LV{d zxT%}Pu<4bUW}dz%|g)R6omx59gu=ZvEuIs?EE&*_KSxyUuUN%g$Y&46}lZjJ(4zEU#Jsq|qc zZ>`InE($B?Mf!ca`)Y=_H8(%c#5i+wqsh(nDhyf!v+QA{#VHDuW5r1XEj8$Rd&v?Z zH8ik(2P0nkX1!k5yEJqfKiyqbTI%NFz~kb5r6*EYe@O3_xK5Bnm?Tc7shQ#e1z}@@ zude5Jd~ANT{^ql|w4+zV&NgpUvx%i?G+KcUDaCq^xpp`zy=D|t-{ot$xo-YQ|_uJ(8kWd(8~AA zQ?&c@8xt3ovGL!hu14_sXJKd;^An*m|1ChQ$b;O3_tI z#lmuQ!V&4mvgFsm`R|ZUO^uQSN|m=tLbjFW{Jf8T*WD;*d~TkdMe=!%WGVMYs$}$s zHPd)nrqg%cbmfe!D^7z1da3HpR3N-UKif)qVU-5$F%I_brn>6-CS+td++zl#rjlHF zSHbJ)C5z655KJc5OJ^!64<4H1pk6cK2A?aqAW~D1$?-cC#V^y0@U{W)WOp_h&!P~g zX1cGlNAT&ed~{|J-?`2Pr7(hj`CvxVC-DJrC zfE>fNJ=`Z4E$%Eh#w9}k^C3_4EngxG*YDF|;v0U@AwQxW$D$#mAL$m~3in+N(ZmZkGDz#Sy+dwd()y(;wrUK@Nr7S*F+EdS@E56Rm`V6uLCF7Lw;@>Im_4cHraHM?~DxY%Pf4 zLq>lQ=tDWeKCn3n%aNa^;t*`NBy08e(j&kral`T|1;s^rOB9nCYBWR@{~r7>9G)dD zCrH}ja)dV-9mZ4ga*Bakd*Rq#@#@;aIMv-_za9{ZZLMe135spu*QJkz)#ApuRJSoV zs0inh|c$5QvIAhIRHN-H?cIzPHicW}Lk zob|Z;m_gIxLKvmi%s9(7OZXfentZO0Md430w``nWp36z;-PgpAnAz>5MH@ebg$ss~ zb!-KpKO;Z@2Gz&NbIqo0-+QoFkgug=q)~4LL;a@`f0+GJ=XDSB zg;>>K!u9@>B2mC>1#^UdENjuL82(k^TM#XDuw>uDhNpuHPLeuMZlQQ(!8}{z`jsLd z16B3>U}ViCusq5rx(l}U0Eut$m_6F*4?RUE8FYGp2-Wc)y#m9-= zcNybi<)2VwhWvF(eMqUo@6KC+x364oxa$>p-M2I|dc*I3B|rrS01#0u&Fg+a{p%eX ziY!l&$vy@j0gpo$`C{XjFZeX)Onwny)6~I=!)xmU=YY)?_ZI~EkpQAEcy*^8VD`a7rGnG*bsU-+ahV7MVkAw^jj+5JJp>Y;_p%E3dL$LZLk-tm{-{s8d7{EF9vM84Cu;Q6Ul^o1CPjH8;0tO^uINQmlA=Ay84(9To46 zi_KDFx(Qts%AWaACF51B!bI(?~dK20nRd_R=mrcGrYEYadQX_SB~pn-}1Q zLkF7^hsp~l_3&aL?#pP(u8pv%Yd9dB);w*6N#)ty#O8|!C)k>3dT^+_aokT>PUY4D zX7UQsqQPVQWXUiVBUfl(Wz7w6jQ!0>8z+fA13Q2elX9;r7%ESK;|%ei62DEVL=`<^ z2-f~%`;JcCbq3$mIk-_d4zkWTMBU!kg=-)*IT951(E_oUWNY8Xs%ExLiuW;$PCPOa z>M6TTg%EZ3?H!eZ*wJ2xBe&jBZ9N4Cq-W9*+9s#(Z(6h)PP#57FmR)OS{)mfDGIfH zG$t3;PSSVWF-r>Cu!cJaYRU0-pYtC$s)LxCt?SOS+))ugnoaUL$#DxlIJH}8k#SVpwe4;HVEgY356))H+3>$BcycQm|*a} zXgvurX=JCbe6%N=`bx?|3mF`=;m88XU^M7Y^6z7Q8bb)?bUC!JQs_{`mI`r1R!DEX zSbR)JG>wrnLj<7L@geewll7(efPQ04EkbdL`Xp&Gv#luyb}oz&Q3aZzD(20S(dD4!b=yGWBt{u*%7#fJlI@+vbbf z&Vd%GAsQP`p`Mm*VP&zjz^2Ss)#Y&(t$u6h2RR*7`C#n!Lep%8FTbUL7lzFZfA4Fi|@+xQ3?+&h`5DtzO;e=d=C{) zJpVSJDTG(LShJgOJ{Q_0>(ryu7!n`=o?Sk=Ks09&qt4uOaD+;dStPvk@%XSz2I^x8vKXVE?cC*R3 z@xJ{0iAMVWRD`nEyJ&cp?X*Xm@}0&C#2CDW9K|JZT~?8=x2*+(YkPgTW7ow~?{74z zD*2F-NPDy>uWb=7D7nbC{++JQM-(E_bZ>#$mt8_$!_36BMs_NUGp9!ytygLT}8~g)g55k5wVfC0!1c!16 zh%OG!AaO5_<_63=zwRF7&GFHbt|Kow%+7v`AyZg>U{&w%-@K1^36b7hjK+YTp2!PIEc16b~?)S{KXNPJv2I%4vNXZvR|ul zEliKNOH3b?eRPEYGe~GYI!`HqeEBXWo6W{%+R5Ta4*-DEgQyH)!$>q2fLGr(#yBe}#85y?m3$->f2jEhWv9_AzL8`tqJ&AVctq zw&C&kQq#dsMp*P2=HfZO(XS7*bd;qD7JEfHuXgyD$@uhN;_KxFGh13(D5vEHbODRK z1QkY4B9gxWN-FIdYU}WOwuTa7o3KR9#n(6-li?tLiG(g0Rx89YJ znd$Yt=T%rSx$O0uK{GA>PbATu`kRvRb4j7O#`IAlXg+eLu@Z0SWOvHtE>p#Ct~HfYt>)mH5~YOl5tQ(tB;S!DNGN0z3zTS>iB zOs%Nw+=~G6>8GbGEIrAchQ;H{x_-%xB9MdW=1UWsonXgM;l%7?e`>@?63>-NLLA*%q5kMu%m*sX8lItmdMc36tE^1v_nKWGasac+sAT{&@8d@V&ig_=X>m zMXG}gQF>l=W0_MeM-qFAyEwZAj~5+5nwFW-n*-9PDSKyAQ==f#!d5^CH>e^)30qlR zHR)r1Ef>}~DXYq@t;&rxG3VG(43f}#lW!HB`AdmvB;~|{KAOkH9~h$K>Kax>K`|X2 z#^t;lIR?YoH)lB7v08*R{9v4h4iyXl{A}|vFl0)r$bGU48n;sD{K3^Oj1QIzJzf%e zzCtl1jP!0>-Zt|m+|r@0e-weTozl2?ZMw+?T3Muy3Jyn;Oe$ll_(V=P6Ell zp<6%J8Y%=4kK5zcyCXef9^^rwaAT6FQY9PB|Nbg=u$MOaFV}Y~tBhn7AIv~V^0Wdw z7WDP%(_8YUj#3-haEe*<+rx#l7S_}qo%MH`#n;KS)@9$mVZl+(iz zgK;IJ$WfD%ht~5TP7&3=JzP#16soen*r(-)r6BJ*wzOh*@&Km~Ci%}ql|ta*!d1WRhj_vm?23V#306X;P(i+Z7e)3hvd~qQ zSYHV^mBfmZL5Q{q8#=Mf@ANRO2;|h4pJ^IO4s~v9QOhB=(9v}hJfjBYs9ezo5|z}o z9afH%E@2#k%;-1RaDsEYFb$!amR1TbF7~JIa|%fO1vN7fYIe__9+8g^TicU-B83NC zxF9}}xZXIolL?w7Q!LQFe~8z7Pq!z9+@pu25-T+wB z&S29us`Bf*+iPd1#l=|VR0530ju6?IGL8T-%n+X zO1r+Ft=&(z{wx4bF=usg{YT6Focp~R6OKT$Eqs7LiQT?-OA--AnAn@U&By-lQt8K* zBH4DW0HL;TfS%sHV!DYHt0cNl<8@ao!5v%P?=slYM438yn|^rj@BNLj@syu+S2Jm# zJm%BAQ?axoThIQ68mC`JLnr=@@oV12s%!J%>@`ZOy_@iFw{JZq1l56UTNsnoXGN+r zPSpIwX8jlAe=)%2#4a4_kHAK}Hx4KZJ5iF31cl84R5SN+GAY^x%7dun+xlawM zjEZ9O#N%Rmh%T+2o%3)qXQi$#bh-MMZ(2kV-#2u@>)a4F&h7THmXSJZvC4^AwWZ!= zzBOf&&M~QND<#$apdxe5vf=b4qn!of=?*+21=Kiw&Bnhsx%%kbM-oR8RlYZEBj9JE zqM~DbM68 z<$|<_$HZ5lLsU{#S*$=cXo9YW5?6Cpf+QFtO)OPdmzzw21O>;XLmPW-+x8^Ef-oYSB>J+8T3f$CGaLaOCrS>rQd9(D*zL zBx05SguP`&t?f(~!asOX<<0Vmt+mvGn z6Kh>iSv+VwSK^G43K94-s*kZk`DX!hsXW;(^qOvG69T9rvhTnP`PYIKC9QB!PYTvE z^KuTskTQ)x`M<|;xh>>c)D}X^3y$*5J3xBSrgA#96blnn*_*WdDH&Zjp1&cf`DIw| z`~VFjzDh2dFw+ynNQ4A2jwT#aQdlZMuD~Unxq|+GCe`l8w5owy`_Sl&R0l6TU0dFmk~NtIwaV(^|-R>nPFAA zzk*87aeipwf(aUPp@$&n8qYZYqo+qGqM)U3_A3dWgepf~!l0vj_bcOy%*vYD;@wuH zO32$~u0UjDX0~^(Ik;OVg6gCpi9J5xj1$U*f)HBNNli~(TT^E@XzYA5=zVV~jqjhI ztFMjDy%q{`@W}s8hSa6Y-`l@>-^sAcK!M@pp2^&*NTKHFo_T_3S$}tiF?sKRV~~=e z@RHWR{Yz?mYAmPppwS)eQb9k^JMOvN78a=@v zSTSOBKofjtrYn0YW5dkOF32SZRDJ?KU&h1oyEQb@41Bn> z`g-1_fU$cER5`ql$>DWy8-Rak`+wK_bQ__%;;(d^^pl3V&YCM%Swz`R~1j^+;iGdlriF6OJ zSg!WoIe+*EOG$&3Mydz;L5+|^{`{MFuRsbaW+$lOr4E~dMUYor9MSj#-HxHTt2n#-`U$qbBld{|H~EgG%Wqt@_Xlx_Rfv>=eD~(2yv}%=Q?o;SXlc%fYL~HfJNQMP z!I_er?)^SeeQ7)O_IT-S&%ktW*!ul$Pkydg0f@K8<}{>yE-Ft&Pj6?3`TSbK)}GU& zfD(oVA^62~oLy8O4<0`%KHVZlgp@>|<+OJi_Wnk-Oi!rC!GAf5g039919KI zDp!%Hroh#fZ2&SE^8~ilHwA+!-ajS11-3f4N$%#e4M|CH@x22CD<8XJXeBo zXpN75afy*rT54c0Wy*}5n%WAw7({CCOj4Ft=P_|yNmG%+<(z~>$kb;};s3ZU46B{h zcN#U0D-2$(Souj`eK562OKA5LKkVDgXqL_E7c83Z-DVJ#nhG5&4(fd^FJI;B=kdF! zR<)67;JnkRf9G;nN90Z#Q)8w?64O_d?udpoC*e8D!4DW}#za%dhBQcJv$oZrceiZkf?V?@b0$j|m^d zVu6)?vrbx?Uv`AW>Cl#*l$q&v;)=o}&`;OOK?wMp&g0k+`Z5)SJxqTf7Rn9zrh%En z2Kl0HVUd%Rw4<<8ViFUfnK3ET(8y}8cPU|Gfoh|HJ2baEvs7^LtoKK_?D=$AnIyJl zFCU8eB=}|DqRUH0`YA4#vQs2id5eJ#+VKhN>{75$-ZDMCmZqma{I;1=)O}@@zpPA} z#vP4uZnC$pPh2fowy?q3SwBB3s^a_&DsUnT-RIW1!%_-X@H(|VdD*W950@D*rPpzI zad4<_cXxLQ!T|60SxeBi%`48BWIgwrIruLoKEtpCA^a8BqPU5Q4fOI~IWRf3u^_;G zA1rU(NXpx-yK?h3urqUFI3oU4gUHP6R3weylWI z3YQv7lsq`nvzBW~1+8DWoQzH0nIX7)wmj1Q=dcIkhuJ(X4&%w(pt7>G6xZ;2INQgC z1^J`?`QWI!zduk$M*TN%_-0!`QWgF2X7#7fMqZ^vI^UMXbnW>yKr0ojEmP^kmF)GD z7bV;6T#+wUd}b*}M9#j}@C>i}U7R8mth2Ien+o=^URGLc5wwh*fb@QX7^Xv_VXC_c zax9(s^?Z;F75_(K?W&+K&bnDGHcUWJ;6%? zyC_&*@4d9r0OBS1zlC#or8ZVYu9^H&Bq*fdK^QV=w>5e1VZ2}v*(b8W2K)P^ z5rlpXYx710lEJM$ltzr9hx#Dv)B$0~bF3aAk9R_r1H-3dpa9YN?8%P=NJQASFIZOg zyJu4hYM{Ll>DZw$GdAubA$Dp>NXuNA`B#EPTi=@tiP#DNNL6^K9y2ZxoI9&>+TgRPF$y1VtH(GwK|wG- zE@|MEV--tBl76TyVDau_Jvgp;IU72wy*fI7%Z|KA?YT8w2Ck0AXG3whz_l0qm|1+Y zO96=t>y)XrQfFg{K1`a^ck9!^uKbHvrk7#N8Jen;_ifepb5#w~-oJ~OI8mb4HaV~< zWaxIpT&rpIyaw9h`-|J{old3Lb9-AJGS;_%5U%5PlIlF|TxC95G16I($O)V{RN&z+ zGUYY|h*HTCC2E&)Ks2*uR7DC|tY-7x3J~oj(pIndG`nKG{$#%Z;hTf~@g2J$5z;X$ z4gk>f-}b}*=pZxDEZrc=2p!#I51>2usEd`E*%5@r8npfGo5)U++PWGZh2b5{%<^@x zh_Dzi+(Ezdm%Xn&-V1S8c$8Z3RmI%wOG$S(agcc+o_Vhl3KB@3Xpy z5gfel!Cm+gIojVw_s2>YDPffweUr6Th?0ID%07upE0wz(fBFl(+FQh+Yq?zn0)9kk zt1p2LX)x%kPTn!sZvz8nvQxb((&b$w;f&5MSBaeSk6#w0WeCITZ3-}AB;-LF!49d+Qg*mV|`P+ z`m1nK8?-wt1B;+Wl-e}>es=HaZPw7=e&;#Y~T>f<F}FKDp^56_y7r1V8EBr71vH4N89uHgYO1@ zCuukuGA_|zV0d^QNv#mALJ-|-N!U=_3Sa(^If|BHn2v&ViN6l*PZ6XEiNl@W@+Q{X~?m*C7u&5N|};q<@;)}H}>LW_7g4qIOR_O zh$Di#-cMqSK(NoZW|pE@y3u+Dil4nl0jNcC>B?$q-FwaaixjP@z+i)W!XT9Knc_c* znq46Vxl59tH2ddb)Mj>QCRBw8ZTW6MG8{4@=9TTRY6Y8tNO1+qtVH5~$mv z8;;LTdE$|^%;seV98dlDFRi{oO?aTrt5ORW&o8>-KA*YlD8k-FFKo4|T+h*UU^LAiqZlB1@sIp>Bpvb)jZX8Y&K=v@Ye% z>3X1HZs&=d`GxwtryCm0lIP}P0|ylrmcSuAhG&|gAYxl9PCXTh$-w-H{*E7jwk)-F z6n>Y#_){6Zoi|&eOs#_3@i1k?UsAJ5n<%+BL*zT%YyC?qSH8hs*>-u~odm#x?EecH zkSxR9%ne{Ws_c$SQo51&pZ4A|D30ju6CETt1cyKf?iSo#g1fsD+}$Bqupk4$0|W@} z?hxE1xCD1+kioX|f9t)wbwA#_wV$?Xis}Mtrstf~=jrEXO$#gfY%`22;AR&p{w9W6 zN54(XVoKAZHzw3xupcL93t9Q{W>WT2k_x+A!KV<<1G4qH9J7Q~E78&F<2wNR98Y~N z2{1Y#pXabm`HW&=S*1e=3c6!d{j4c)Bh7$Blw&wYUqcA##a@MWPPJmDB=J5ZzT^HWWmE`Nj4h6!F#57 zRbirq-*nKvgXGE>oU<_&4*&B*I78{qh+CjthTDjWm^CSmVECo}tA(8yc@m_>A0t_| zU`Ey=i9ZebD7r{R#!^jHLc+%ZFDH;hxhuZdILHs`k#zzzwUPh9l9chq5flDF;{Q9K zr2p^l)0UvT7XVK($;U%w> zyD&P%!`{Zep1ii2#E{nIAU7SaniDfiBUSRb>CMlRp&p(@?Fc^h%gt90*C~JT4|g?c zf+Rxq*J2tcJfnf#M8T1fqfRS46ImV2KdKl16e=49l7qTis*=OPPK(C7ObeF3_8|st zyYiV2C{KRY63kVgAr)!W@7|C5Kuni7Qg40eUenlku&^Mjt^Ez09of);jJg+4W=-V3G%`R_;-6(PJ+@ zF#Wyee`cy0-7K)KT#I62@QvoGM}|>v!K1oFu^}D^+D_$wP|USyY2PI_{8^OYiq}Ga~I4S4I^f?`4~-hzKmQF zF;FPk$MU3MFvQHK0SRl=n<+lKrGZWPtpKz`v_Lh1WSy^PgTQXeWGTsqrz$*_bRSM^ zDoYneyH80du8Sn_VQ1_xxrUsX&2tP1AuK)sPQ5sGP`J|--w-Bf;ao(hJ&2lyVXHfL zWn3W+2IS}Eu+(nD#r^(^u`nO&XMT`L%H&k$f_Q3B+sCWDhvrY(z^yL3v*_!^C@l`@ zMk}W4(E0=d=;QCv>x-U^KiBmnZe3YgMn-&oXEPU3`b&I1))PhybiL)3!Q*Kf!qFp%grdD>a$2o@*YGz!H)D<+DLd(Z)`7)``@I=wDETK zvkDD2nLa!eO0>V%c|E<;plT~GCjaQCGZAr5Ehx~An5 zeoO1kbo`v0m?>NGFd>iC7psbe3i+;1rEn?gs$9!$D4s-zU|*k;5pvh&=GoIVzPpQq zt*wRGY6|Gj$c%xqG6CpEK_3?n2lDqVQlE2E8{LQcZsee|B`pmNY!^slN5}X8gmEhL zw?Sh|I&z#+U%aEZ@+Uto^2XrcNe<4bE|PbDRwusSbMi3@jRIHXZTo2I*yzwur^kMX z{%asGJ6IP!e0&eK9jwBeOL3Wr&^ zo4_W$k|h8rj9+X!9sH{A+3}4BUOuJP0HX#QukNe)whpf8y25 zXzJ$gEWyI7lRzk$kIx&sdB+w{q1wvIml^Q!zQoJXTG=Q2RUG?fglV=*q)>%ycHw&k zx>lJi!4DCdC|h6S3gp_EUKE)Ts8S1R{KVm*c$(KLr{%0bF>c=kn(J z-IU4wKMOoa_wCj4w6MicW8}8!MdZfQ`|X1o4nV4H+S3<-v0DGoq(yqNeP6uj-)t3W z=lM$h?~+__Eb4<#9lZ4N^^tij~ zcp;xjqEM}RQ&FYl8!(1#EAFRjqlrB~5{Lz^&N?Dle^k zh7Pr<>P!-2|A2p-==+aCIrv#XrBofd_(* z10tiL$-8_d+Z=Wa5E5G`HUs?qQ%q!JB$ z-akR*=SVckE)4gu^VcZzj*E@1kRsY>SvbVz=UR``&W@G(;`uWfaZK)3)s*p3c?y}? z{U&j$((4a=He>gPa)sD-vw$TFHDVK=(Eus*X$Ptqqb&ohWnjfg7N;SZCO4$ca+GnhM|9 z_qUcLh!-k`#>RXSQxApgzsYFud>-;HR6E>SeXP4IsHtIA)o1+L?78BV(q#U&?dhpE zaylX4lb?CE;=xMsKCr3?#3^-{_DI{BTHE;CTHcpvtatcn!-o7&D{1vO&Zq8tOU0fp zNXaqiw@9Y^cHviK%`!784o-pFeqXh!$=~3YXk{QPDd!A`2H8uQ^JkP+ET^U}d^Usv zp(=%Hvc=QT+q3k+N| z=NXxqu^*jm`!??wCr*A2b-;la69{}%X8;3aL|U5mS4oe)fhTDI@XmI#yp+NEb0b-i^MqVArK8&3*3IsL{Fl z3v=X{oofsa`p)KnUH*mgTx;F0U}8DP z<<5SQ?~V;=ytOtbbwCr!)QVlMbx>50=7Z=Siwuu;4mK6X&&yI(ypK*^L!=f6V97-a zHlT4DWOKp<|8s=gv^?dPYN1&i%n6`@R$W3b#Gi!mSZb*a)=y7O5Q;Vxj?1t+c3S2VMWD+ zG1{lJ+_*aWl@{JpN#)zCj8j?$PG`)6T54V8|+xO&I8Bc>4x z)Ra~4aI+j*Sr$_&uv2nvSA|&`c*s@BR!#iGxGQp01&zbCtTQ zS=MV+2Q)yK3@O>F9wKuJhVc|qWVl1=D$`)Bs`mlC@Q#I8yt(2yqV=n%h|)X?lfwA z5g$4{NF_FVw3@uGu91o(Mv+oe?OB`Kp}eE4ncz0P{hMe0$eXZIvm1Gd6S;VIv0RUT z3`3HMX!jWr7z=+sp^LeeDZ8djmcSjAs$k?m#Q1FgYy4U&r?c8+vOd8`r?5pQZv$k~oI}u}K$fF12?PDlG z{T<$w<({g6GD^AoQzb&)<(R=sbzOS@ZKU_Fgx@dU7~Y_BN96ozH<0XAPKIqk zqXC(OS8bGjOD1~FvsR{QZOyy{e1~!;D(GJz9{I z;Kc%%+5|^r9wB-`R+<;IKJ+ z!-~p#1c`(&{$aNRw8=A1;Jd$~3RyeZa+`OXfV!OrjYb2WD+Qxpsh^UX3X=7LRypar zr{~Q2`oCq$PWos0nsazyE;xQFg|xl>?M^a%VibuYHWb$hBsGbGRAem55vi=K!-F(w=N8Di7bNXUl<*=D1 zXm1}R=%qJ4w1yTpzR}+wB(SXL$pA*7!2D*_SXZo@?ua4On(^HVAJ3D6W0HPa5`492 z50(Re%h}spyzaTSMq?m?S?)aoakUnkZaDwFuUDCCW@_MKiyj_RSvj2J&-Q(%&*-S4 z9$gU~?Rla9`^z9LR&>kmZU<9&6nt+3o?`SglLtiMp|!AqD_{CfC)yxzYcrs{j{0j^ zDW~anubizp5u06rgaFR$qsWtT*#@wdf!MVUerb=%q^&zDfr@OUwwzP<-O9Cp_6suX z8onjNnCQ)#r5IWzhElq;VLVz#12_m_zdrf31Kc) zR{Brd+bD@qBMWBafTsi}v6sPA$!CeKSlAZua+GS4)Bb_i2EIivQOp$ZOW-CWT=TrT zPs!z46mv&PHW5bq6GfU|xp5(c5X=as^u3)occY_9GAN-ERZ(^uCFqx8w(`c2vn{O~ zkqZ(eD6bJF2ije{P{M2PlK#&s!N|EABc`X;{LDQ8NS$^(OR|<~2*I${dx1i38Tp#(wbnK;Y@oQmzhVo7IfMI&@{p6caK$jC zfxD5z-|AZadLLK`Q9CS}a_j%2$pEkV$UynaI2;-#H(I*9zO8y!esja4gl3{v@}_s> zT$vOR#3bTjzkjo|j~_&v6lGq^?!I)c1UtuIq629aS!-BHMBhRnoOO8pPz-3GP8RzS zutwL@yU()4f2ffmaM9Bi7#=R$Xq39;8o4NAx4e&M$xX{x$0|O36|{F~ouB(Ux1{C# z)Hf|?z_hiLytiovY?|lAg`T_yv5LhpmbLgVM)pJ6*Ue}0{fu%!Veq?5Iwt3WU zyNzGI@9>dxigcf2wRbFK)N~&Y*K&8qsLM_H31$nuqJjxf+c>QS1amzJA>EI$ZtBhy zMjh+G#Rst*Q6)V@-j?9ND7bqJW=uOo)^Uv>{2{RnAKw`o5f6M2>dJYajv9n@0*`5*(ePr^?z? zD~EH2Y2Pows6K26@i!IM#9#i^8%B;y_MM$6Q9ST_ zY;stDp0rh%POlkzDr-g%4d=;n#n9PWxyQp(#`5wP>q%w>MG_Kwa~$kxU#xYB&MYk6 zVJ8LPM%jfmNpg!3%W*=t$!8YfOr;%T+vZu5A!0WWOOHcx(h4NRMIRl_SLj$d zSf<|#ruSRe8+5#fRZ%i}IbP_pJzVhQ<_^Ib4C3~z7teEdJG}FlB9K7z(b8PN?PB8M zoZ6_jdJ{PgJsQ>R>p++}tgnw{s+ZXY-KAOX9;PpG5^;SV*sm*Agq)ni_Bk7g6@zj5 zb|qvgBn{}wnQ*n{<$h;#)3e0Q^c;jI9iim?LdaK*uJw&y zz2Li6Rc>*??85Nn6F92*%kS>!?KWNgQvv_>@^)9-?e%u3O>^6=0G6vT)TO~8U{4Bz7oGR!An-|bCm{4Z}plsNWR zTmC}O8?c;V=jT9)Fz?5l0N0jwATsSBa~GvBblglxUbdl0%q=mK@ST;#KKsFqQ9Q31dBRi+Ko!9M>J>#;XdU1Is6p(|V+#|j=UEw!6xF*Y-^NV&N2 zu@^U+8k_VnIGYr>>pXYsB2NT7|e%z`*H5iD17VXX02 zM;piW(P?rTBX#RA;2b<$(S(EOshNeSnb)Q#=7)QPDUa9qto}=#+D20=@sQuHQ}m7a z!eba0pUG$Ng(>7eMgvJr8m6FPr3LBf1w4>pPet3?xx=A%?!HrF-8r|OM@Q4taUN6v zD5OE7ZVfFjFAX(qZbcY>j3|wwGBY&nNCcb*sOUU+xOfD(c*F;Xi84QX%@p|-@{_O; z^)q>l;6dYQWfi@@hrY>>*{@9POgsLnN;B4RhdvboA$pxdLvpgC-m?%mkge2bc5Es0 z+IKDmv<2MHt+%yYN~Qh%Yvq~lJcc2`3N*^O?55BZWTO51v~#@bxPShMT)L$^Rtpa) z&47wl8SZc~i5LsUlqhURBdSbM8mu8ILb5-nOi2}u6RtYtBc%*`Wy8P!sHroydJ4FH zeQmxeKly%73%6$Ix43k+*e1eA>y&bbnb!H)`D%2=bzfMiXJ4YIKlM!l7r&#&u{*wEtI2Gm`4vKes?8$qI#E+IwygBg`WN(`c^%!xK9I@Cd;E~7!5w{R;#D_ z>+Lfgr9{}FI?a?#J&>>|gg9N@xQ2+qnjzq~b~ly&@sqQ>X^w4Xaq`CEVF2^?Mk*0|rbzG?T;z1G$BmDgYJFGrVY7$OiX z6tlSixLAUqn~$`UN!ZCrF-D!MwVvR~YI4}3` zJs``cN#mKcQOHvfCg!jOs`a0ShL(qLP6lc&q3e-`%&HSC93%@AU50>NCR}#i@Xsh* zp8?$;1NfY-QIrb%4}qvRR|TrAXv#=NQ~fS<0~S~wxq)zVSKcCO~}tWna@ z$PN@c{sWOWTPTVUz9<=H^ZQ$YrZAVD zHw5Cv<6pMVgXIc)(=n|1vkupX-T#AHV*p}!n}WX^2(w(F$tC1X?8;a^d0($zO?xM(oO#_4N_|nYZ~-voTquDb?p5PNG2VLb-+x z0@wfZB%alW{_%O;3)Es?JS`Y1OHaxb`gs9~`?R$C&(`nw0R4g>2=g--4B7HZeJ5d} zL#>X9EQyh+NUdtSuBVOm-yHH;?tcg_*mw*Ia1XYwegX_gm5v-lsDMA=#k;ZTA9=kt zxYLG_MAGWJi>y+V+_(aYq%-B(fPtTrz1;eqZSWpvBd*`e{BmtkX(g^OksiU{P_ps_ zG;8CkFSjcRI~`o5uW1}}uKo8B@3r+A1u68#{SCDB^Wn?Y$jDc@cK0Cb)U#K_#O(iq z&d;@L-lxh8_P_078h1W2C4C2><9?A1 zB-cAw>mB>uU`)!Yd}lpe;`f%sL4Ge_)#~oNdgx~V&Wbn)CH3wK+R#tJ4-^CwO6tmv@%znku@U`i=N#KrDO9RD^kN@BhC5NVv zN?18CCy76>J^>u=bF&S95;gH9x<*x-aTF*bKBK*B5y0)CLr->2px??dj=P zJa*tR-FRAIDgJP41SeQcX%xbe8)R|rl>9Vcf_~ap9g+i>VKs18@24sG?72ZdG8;6f zV!K)J@fUw3ds^@um5vRiL%=*CV`io#bcw{Kg$XMwuP?&;>$K$07%ZwmgE=S9M z7S@tMA)khan{c+W9Zn=D+v@peTS0x8)5<1-6KHWDo_n5f|Rp6RScf6K_9(;1t~HcMQrt@<^_`h-fOW$)r5M5yH=nO zeUcUuk8H4NcXK{K^vZUV!D_<@`c`fB*#rceFJHHo5m8o%hHN zvobJ*M<756CQ0#8%Gm2%VL$+d9RCD)Os1V=WcaeU8+`Ruj)cX!`R;FNX-0YZ>T}S) z=?~ir8Z~3r7fO{OYg~SLzN+eo#K>2p-yVpc+jQOfKzn<(+k7_Yv{0$LC$OA3xh)hQ zgaT4AZp^7Pc}~~}tfL#6?V}dnOqbEv7jpmGSRt|=9jiu%OWyN{hq8P9lVFi+>%bpy zP%9A%K*z%6@xY3&gmcS^tI5TBr_wBG1^pA|q&!jj%Ra#UOtjzC+1AY2=5m=2q(ozQu3e+X zNP2hxqn$Zl{pU>0E7%GL ztt5goX%k0aY3^lz)>ayp&nXnsbSg= z5TwwoW*3Pf6|~cp$>2#+5$CDID5Tx8fj5$cYQ<>YsAp?IxOcoRdpEDxI9gdvw32p`aQNOQ|NfcDbH40(?)i7}6chgNzFLc<-LP>hz$5iBJr=+G@_6DIpvBXe zFrcR6YUbt=kOdx+$D-R$2_Fb>@hOq8@dK}Y)Jj{@hdVn&?hbbeKe))#B(uKw#%JvQ zNfWZ$OIaL@2Dn;7L#RS7H!`UE&*t~c^eG!a?f==-lm_#nx~%U~?8hy;>bVSOr2NKu ztd%^@KahK``XdJ$8+*IUzLB0)W1GAPsC)Fv71#nnpvSW{ctIo9PjhHy8*9=!nhs_b zguK%t+%LmD=Ed&KS;H^eD&g@xe_iTn(}LQm|Gd37)b`e)RoA?(lh~}r zqHn->(S9B%PPD~8vw3|mj%^SDdQ(|Z5ePuPGekUFOZdR!30PIro1FVwY)*lS6fH?HzlySInDsAT zB^5k4AmVa5n<+_A*epzlxHVIa%&c`VS_Mn+PTW0G!HTCo_vVUid7emWz+Kmxrin>ND(fKg%mdUv_+4 zH`W2?%(E|qiN$9rIun^xeA%H+y+i{uB)Gou(T(~jq@}Y{eZkRONN{qsrDFZL<&t+| zVJ%FlP+Hi=G7X>~^ybE#G=Wge*Spy&{Xo6z?YE;W5z?HEFwv5}+k1w&i4y4w5qDDn z9l3c0J_ZFhH`6B5#63DZN&{0i2mc(d`V034csLDC4h(4SRjz&|O{$-Dc;{9qQoxIJ zz2oll1=(H0aZ>|u|Bs9qd4?3~-{Gva&C|VocyNfU!!$mxs1Un1O)cni#^Xrki5Z^| z3EU}4Klf8nGsD@zDd$i#8+HT&RTY5tiU5VJ#jXzLi>~I|dB6_Mv)>84-5tcAKW@Ne z$`4YV5Cm;+ZEVzEU=gx!%jG9+HMxytN!{BkqCrf^HJdsV<)kr4R{JJA2iKo<`FsGVwYk3W9NCm~JrsCi15AST=O4y; zT9w6&ALkaF*naT+Kln$K+;x>wo<;^y!Fha6a21V;p|G)zW*kY#$aM;VTKejW-H+(R z&4Om{@|JCdV(R9%Jzig$JQ``#(o-% z3eY(r<7X(DK;A z&v48ks>ENd;P`nJL&G-cAoJs`V;>RFX1BigG@mF3fx34;x})o>l4~%4&(2uXX&(X2 znqvA%WL!W~N-7x8I7oZHWnl%pe-?F}-@iiKpB9_O($kFL#ikNOm;`)|p5ijStQ9id zoi}c`X(wG4%UP|1jC3@%1kT*-nOK6lB!#^fi>(vD8~$snf0R(|7-N9LXC^+btDZjm zph+mi6{XDu)ee+^lRJ*|eXh+qA%%19+m#^RnsiW320lpi3bme^fxj}SOPE+IkP$rW zdWF&)=V^-`D!|l!Od-$+y``GK~a`8W3(L1+$U$5{PudyFF`5ti&FXyqIsO@CfyP>b=T0ily(ZBv3hlQap-R{t^fo-P-w)E zUqS@hEfBIgGJpq^g+(Riu$JiY=G6EJ7h+4cjLj~ron-5Og;D3!iJBetW9&;i~r z4X0L__t{ABVz(doTTSL;Js49vs13@)^&-iJRtp)coeq=(B>KkQZ2ZUtedl(9<<>IkyfD>jo#X!pLL_)okKR9W&(eR1|W%fXDXy zy#}817P$Y?cR}1la_Yc5rodv{@iM})gctXq|BRFNjWF%okjYe`n(lSb;-FIQO3=vEJi3T&ZRTRI2j`QIfEceE?S^fGG`xai)!8#q^V0m1Ck(Pcm*Q%DI76Oq);;)>^l;^JQcd- zO$|G z@7(dyFY?JA1Jnewg|il0Z*EGYwuJ0~b#HJ@&}Gy$W?vmm|4Rtjqk_kY|KB@kR? zd;H|$0(BsEdm|9%V~FTq*TrR$m4$v$W#tkLl(H4uXy{#HHos4CjcAwouz+e&fhrkM zgQU(&PCs30AcryoIHwKsR+gSu0>SSiVeI4Ed?^oz4l#gdt%qPFtufjxtqgnF7U6ug zbsde-Ck^>$Y?xV^Ia}1JnB$yN{f{{VE9$(wu>cE+g8cv!9Lhm5;m$j|sc^@Ze%3Lh zH0}k0QNT}DD1e2pC(_Epg9VG5v6;ZqRg}`+tg z{{OOEM9USbG2p7DYs^il80m)>8xPJ_y)w>JZ38&p+R6~dKMd|=n9Tix_rFaa|0iu1 zZOY$IUM7`D(17Q%l3`vqonZ|qnpKC9oR}aAEcRe{{@=s@z2nfv>pAF1REyRPa&0iF U2geo10|O6|l~R(d6gLU|A0agEasU7T literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/attendee_list-light.png b/testdata/snapshots/darwin/attendee_list-light.png new file mode 100644 index 0000000000000000000000000000000000000000..ff96bc26614abe59d55abbe94803882f63f71787 GIT binary patch literal 29369 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/availability_picker-dark.png b/testdata/snapshots/darwin/availability_picker-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..2e92e34212cfdee58695acd4ce668d53f9b559d0 GIT binary patch literal 7875 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 Pe~N?1D1(coj9>j5aWb9z literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/calendar_day_view-dark.png b/testdata/snapshots/darwin/calendar_day_view-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..e3c891e5db6beec6322b9eddb4f72a717a74ee49 GIT binary patch literal 32359 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 aGTN3L9PYfF#r}c(Ps$4F@};uoLH`F1rG(=E literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/calendar_day_view-light.png b/testdata/snapshots/darwin/calendar_day_view-light.png new file mode 100644 index 0000000000000000000000000000000000000000..6e4983df65b442f1329999810d0e3d1045ed1f9d GIT binary patch literal 31078 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/calendar_month_view-dark.png b/testdata/snapshots/darwin/calendar_month_view-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..5819be76e91d354955d5680ee67693296c02aa8c GIT binary patch literal 42135 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/calendar_week_view-dark.png b/testdata/snapshots/darwin/calendar_week_view-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..6be02c2c424a642487a7477b15380a6b111a6b58 GIT binary patch literal 46786 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/calendar_week_view-light.png b/testdata/snapshots/darwin/calendar_week_view-light.png new file mode 100644 index 0000000000000000000000000000000000000000..65583a1a4c08d347ac499498b408aa390cf5b7cc GIT binary patch literal 45395 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/countdown-light.png b/testdata/snapshots/darwin/countdown-light.png new file mode 100644 index 0000000000000000000000000000000000000000..daf8755721b7c251ee5b75bc54f1a84fe131e115 GIT binary patch literal 5826 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 O0V;}`3gvPZA^!vLDc?!} literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/cron_editor-dark.png b/testdata/snapshots/darwin/cron_editor-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..433762c6343a3188f827f46683d9fc89437c0099 GIT binary patch literal 35900 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 W-_sNh(cuReaES>?3zqZi`2IJi9i4Fi literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/cron_editor-light.png b/testdata/snapshots/darwin/cron_editor-light.png new file mode 100644 index 0000000000000000000000000000000000000000..e8b898b7154a49b553703bbbe6edf90f9cde708a GIT binary patch literal 34297 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 i7u^4jSIH}N-~R%wXr=uC literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/current_time_indicator-dark.png b/testdata/snapshots/darwin/current_time_indicator-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..892631aad7d4da85cfa71aa7a200c1149a120335 GIT binary patch literal 858 zcmeAS@N?(olHy`uVBq!ia0vp^AAooP2NRIoyR*!Qfq_}k)5S5QV$Pduid+p20;~ZO zZJS@n`l!91@1w?_GHVSFPsi_nQ|@oGnRb6#rku;aNrqe(9GH1cNF!_;@&fOr#cyAs z^we^laTf23Bhu%d>V2%fb-`>4Z?5z03-NbJGmvyA3|1X~8Gfa`@5_~9TV%kXt-*c6 zb;=20g{59obD2`5%5|KaIq$V~b&1}&r5zB#zte$z5MyL_nk?;8CP?5_Z@DDxqtPs>EgG$FCVVGUH)nXcVF_3)|0ryGi%Y$;+OHQml{tdnN26SeuVEcWkjV4h*{boFyt=akR{090i& A<^TWy literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/current_time_indicator-light.png b/testdata/snapshots/darwin/current_time_indicator-light.png new file mode 100644 index 0000000000000000000000000000000000000000..56daacdf3180606b136e5eb9cc9ffa441c072a86 GIT binary patch literal 865 zcmeAS@N?(olHy`uVBq!ia0vp^AAooP2NRIoyR*!Qfq_}W)5S5QV$Pduid+p20;~ZO zZ96VL`FlQb6Gz!>bpzipHntWar+Rf$d7Q8Hh5)HvYq49z3 zE)xqF_zp^5*vr5ac#!o%#k-3OJXd9zMQ%^J({;7utg^O8LStmw%kTfwmTirXySIWB z9vOD37h)&xQaj30`xwXez07ZVXZl@uR_3zPhPB^>&&tPz{@>7T z7Fzf(=+)zgU%x5lDM=Q8Eh(=nl-!;p9JTd^-eUtLbN%y&O_R4q#@pXpZ}$2}{FCw^ zdH%vPHVf|yUiK+gJA2vp#ln|z<$u^rE^KD)H9F-Q_)X)B#-H|nCz2Bg4dPRdzsm9~ zdv@sZmy3Ku=d6_p z!$^Bk8LrqpyqH^>8ynh3mTZt7+{uHB4DDiZyN0g~T(5tlqp{YB_sAKlpqn#Zrd7_8 zlm4qBH`7?mf@dYA(}#hVY}MKE^!3Q7(#q9LUzYnS0xEVo_YxAAA6}*RNzF-gdhRE; z3EBBt+(F;aPP?#hmU7zZVtKUCq2D?`9GqXCU4K1^1N<=~6G8>_09gM6X>{qE?cSqz zzA3R5EqYUKn{VtB@N_#{Z7#Eqg&ZxU72LW+XXuUi8H_wr#Y0jrBqg$hwCJg9_ZFNC z-s~_alVMI4>lxP;_5Hd(catxj>q@d{R*&ezkc0J~6nG%ARffW7MiNirP%GXXBb^H0 zSMLBl0RbfhnT-VhG@|za2*cu!V@E|7vNeC<|FS6wk+h=DDE5Eg6B9jSc9d|e-ghre z;!t{Q#82nLny+XxXz+gotcgk~u|it7o6^#~v$v5iYnxuR%-wGt7TU{x#=|L}#K_Jf zC5M%imns;^x^wH}jY_aH)cubnKHcarC#QzFMv=fk_Vu;3CH}^0q+|^L(C_{Z;Vtht zy(27)FF!KMU%b}{2BX^9I@`IT%;aa;_4Ui05z6c9*O-~>Bap}upOi1zqO>3YdsIAI z%E#cg<@V03RZXs_>OFnxB1^`A7-hIwSyjiLQBhm1YJEcd(Sq#MeLUNGQ|?uA=3o|) zi6x1HoJbpc6k9xp7fDWbR92c9R`#;qwmDJCl8i~hTdBVWD8N9$q(@kLX@~J=A9c}Q z`-Pj`JtW477;R#ySTLU;HDTo?^AS!0n%-uGK{yaf46osC!9nz*FJlFo+h8<45m6Z{hUiz2rrr`Q4&7(5`2M zMD8k`si^6LiwdG zi4;tF*S%7GCdXbz!E9{Rjp?F)^n4Ki{J9mJDsE;ymYzY~)>!!QV{(RT#R)fEV*NhI z&#$&KN(LfQmd{uJIl8T_Z5Wxo^My+X0bWa3M8v)mDy_PW$%xf_SUY>ap!nh(`)I!{ zFHhq!b-8dcwZZF2uWLHwcvB3-dcnO$iRF!=#{N+b=FZ7Fp$2n<(XT4yqfbOy@+64m zS$0xnUsH8_OQ9pFLf<{8-4fITuO3fXOf^R{>{Xurui8E z!Sl>bp%n$-#@rz}Pl6|9kMiO%0x{vQI{52X?ltc3FV0GU^=0&|YAD$;Mm^hpv0Q&IlLmHEv z`rrPTORR7MYbWsqRD4dzUZHsM2)|T(Ts9aMNqp}Dfz}z6H|h6EI`%DPyL{e zX2vOtAB;_mLtI<@kcMA;DD$&(ZsQDoz^&YoEegs#WV?f+HAWpgjvUi1+5B#1YDXSl z;=TkQ6Vb@+L%{l4 zQ-Te;W&>u6n9kXbESoJ3-!X`=`Z_IygFa|?A#9z<+}+ZC8YQV6I6GF{8a{54d5=`* zyO!VncJ8b^*qV*q?tx>~)Xd1;2_YVyikSsZJV*EZJikD%7Fy?FWEok*DvlC_v%=&R z;}NrC>z~z$CXeG4X@3=RHYf{N_MZT8!&CX~vNdpAf_xWxp!=ME`vyfI6Q$I&@u**M z4Z?7_TuSyYjmW1Q6;P=q&Vus0UGOe|;|t|16MkZgf4Xf3MhNZJj-q0q6UQ&D*{)e^ z)ZqR$&js><;yEC0F%NdWoe#Xbp54sNtQGV1c7!i~z@FV} zY{|;zC&+s-3)p>{SGq*lM@PF%<{5z%fCa`TnW^alqV*yjvCZGALpOL9ze~wsW-_gd zKxN@!!B(a6g1lU%WrYWX@7{gls-eEtUD2DSvyN$c!e)XdY30BXEn!!yQfXL=2X(OJ zmG0dQ^KRm1?#?2~AVkvJwc zTU?ZW&-v@DU@(hcHDXi}C8AkY%pQNv z=`mzVQ*k3bpv^9Sk#41Co#4yf2w$KEw7O`bmSxCZ6@Qq&dHotz)LukNoy&eHiQtmZ zm{AOqOmBAIV?Wg$vr{{kvevkiZF^Lwd-%vD}_6h#hv%P7&)ZEc#|ah&wzMEgC? zxl7b@w^*i7uE8ZRO2RsLp%J6ILe8;+K;0qGc`UNNW*70&RL{GaX#ivK{)~D#LdcN1 zZsX9<!tf#g*L zf#M-2pQ4i=)m)>3R8&dcLXuuxVi1e7vr~0-ya#ry%{APMenVH>;}v|stI?kHdNnF8 zSR}~wWtva~>-=e3%=W3r4fFc}0c&3}Oq`sOmMk+GIOq*I=#RSq9st&O8W4b?=fZe& z|F~(u(8;D&{7x22Jq1gJ@5+3z1+vRBr~gbeq3;2-qiEEg7WLYn!{Mpe7x^jJ1h$)) zwo3-KIt`MN73@5m+Mb>gwOb@6YXyS z6GP6JhSV=C0w_b|w)-c>gzJn6?ZTJzZsTJL{}ugzt^c1cD5ZVO2{P^Bqw%Ky4+BaP c=T12t06eDk1Nng*4!8(&6D#97ut&oG04T2aU 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/event_chip-dark.png b/testdata/snapshots/darwin/event_chip-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..d19dfbc508b0bf23b35b19d2bf65992777b2ffba GIT binary patch literal 7091 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 F{{``Ps>lEU literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/event_chip-light.png b/testdata/snapshots/darwin/event_chip-light.png new file mode 100644 index 0000000000000000000000000000000000000000..50ac79d95632fad3ef7be42cc82dcb3a46801e1e GIT binary patch literal 6859 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 Q_P-OYD60mpk~aVFU#YB7!2kdN literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/event_editor-dark.png b/testdata/snapshots/darwin/event_editor-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..5678325531cb55fd697693e076eb1c51b3bcb5f1 GIT binary patch literal 83344 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%0DFpn5YoYDKA8TpOKs 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 D@f1hN literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/event_editor-light.png b/testdata/snapshots/darwin/event_editor-light.png new file mode 100644 index 0000000000000000000000000000000000000000..ac2de163c5e30bec530c8ce3b2769e1389e14663 GIT binary patch literal 80253 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

    -)6`H4QajUqj|f+Vh5fbI#y2q$Tq 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 B<2V2S literal 0 HcmV?d00001 diff --git a/timezone_select.go b/timezone_select.go new file mode 100644 index 0000000..c66fd90 --- /dev/null +++ b/timezone_select.go @@ -0,0 +1,208 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strings" + "sync" + "time" + _ "time/tzdata" // zones resolve offline, without the system database + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// TimezoneSelectOptions configure a TimezoneSelect. +type TimezoneSelectOptions struct { + // Zones are the IANA names offered; empty uses built-ins. + Zones []string + // Common are pinned first; empty uses a built-in short list. + Common []string + // Now dates the offsets; zero uses the system clock. + Now time.Time + Disabled bool + Label string +} + +var timezoneCommon = []string{"UTC", "Asia/Shanghai", "Asia/Tokyo", "Europe/London", "Europe/Paris", "America/New_York", "America/Los_Angeles"} + +var timezoneWorld = []string{"Pacific/Honolulu", "America/Anchorage", "America/Los_Angeles", "America/Denver", "America/Chicago", + "America/Mexico_City", "America/New_York", "America/Toronto", "America/Bogota", "America/Lima", "America/Caracas", + "America/Santiago", "America/Halifax", "America/St_Johns", "America/Sao_Paulo", "America/Argentina/Buenos_Aires", + "Atlantic/Azores", "UTC", "Europe/London", "Europe/Dublin", "Europe/Lisbon", "Africa/Lagos", "Europe/Paris", + "Europe/Berlin", "Europe/Madrid", "Europe/Rome", "Europe/Amsterdam", "Europe/Stockholm", "Europe/Warsaw", + "Africa/Cairo", "Africa/Johannesburg", "Europe/Athens", "Europe/Helsinki", "Europe/Kyiv", "Europe/Istanbul", + "Asia/Jerusalem", "Europe/Moscow", "Asia/Riyadh", "Africa/Nairobi", "Asia/Tehran", "Asia/Dubai", "Asia/Kabul", + "Asia/Karachi", "Asia/Tashkent", "Asia/Kolkata", "Asia/Kathmandu", "Asia/Dhaka", "Asia/Yangon", "Asia/Bangkok", + "Asia/Jakarta", "Asia/Ho_Chi_Minh", "Asia/Shanghai", "Asia/Hong_Kong", "Asia/Taipei", "Asia/Singapore", + "Asia/Manila", "Australia/Perth", "Asia/Seoul", "Asia/Tokyo", "Australia/Darwin", "Australia/Adelaide", + "Australia/Brisbane", "Australia/Sydney", "Pacific/Guam", "Pacific/Noumea", "Pacific/Auckland", "Pacific/Fiji", + "Pacific/Chatham", "Pacific/Tongatapu", "Pacific/Kiritimati"} + +var timezoneCache sync.Map + +// timezoneLoad resolves an IANA name once or panics. +func timezoneLoad(name string) *time.Location { + if v, ok := timezoneCache.Load(name); ok { + return v.(*time.Location) + } + loc, err := time.LoadLocation(name) + if err != nil { + panic(fmt.Sprintf("mujica: TimezoneSelect zone %q: %v", name, err)) + } + timezoneCache.Store(name, loc) + return loc +} + +// TimezoneOffset formats a zone's offset at t, as "UTC+09:00". +func TimezoneOffset(loc *time.Location, t time.Time) string { + _, off := t.In(loc).Zone() + sign := "+" + if off < 0 { + sign, off = "−", -off + } + return fmt.Sprintf("UTC%s%02d:%02d", sign, off/3600, off%3600/60) +} + +// TimezoneSelect searches zones by name or offset into *zone. +func TimezoneSelect(c *ui.Context, zone *string, opts TimezoneSelectOptions) ChoiceResult { + zones, common := opts.Zones, opts.Common + if len(zones) == 0 { + zones = timezoneWorld + } + if len(common) == 0 { + common = timezoneCommon + } + for _, z := range append(append([]string{}, zones...), common...) { + timezoneLoad(z) + } + if *zone != "" { + timezoneLoad(*zone) + } + now := opts.Now + if now.IsZero() { + now = c.Now() + } + k := Tokens(c) + d := Density(c) + label := opts.Label + if label == "" { + label = msg(c, "timezone_select.label") + } + old := *zone + col := ui.Column(c).Width(d.ControlHeight() * 9).Gap(d.Unit()).AlignItems(ui.Stretch).Disabled(opts.Disabled) + open := ui.Local(col, "timezone-open", func() bool { return false }) + query := ui.Local(col, "timezone-query", func() string { return "" }) + hi := ui.Local(col, "timezone-highlight", func() int { return 0 }) + shown := ui.Local(col, "timezone-shown", func() int { return -1 }) + text := "" + if *zone != "" { + text = TimezoneOffset(timezoneLoad(*zone), now) + " · " + timezoneName(*zone) + } + col.Children(func() { + field := datetimeField(c, ui.Row(c), false, false) + field.Children(func() { + t := datetimeTrigger(c, text, msg(c, "timezone_select.placeholder"), "clock").Label(label).Description(text) + if !t.IsDisabled() && (t.Clicked() || !*open && t.Shortcut(0, ui.KeyDown)) { + *open, *query, *hi = !*open, "", 0 + } + }) + datetimePopup(c, field, open, false, func() { + list := timezoneFilter(zones, common, *query, now) + in := TextInput(c, query, TextInputOptions{Placeholder: msg(c, "timezone_select.search"), Label: msg(c, "timezone_select.search")}) + in.Input.AutoFocus() + if in.Changed() { + *hi = 0 + } + if !in.Input.IsDisabled() { + switch { + case in.Input.Shortcut(0, ui.KeyDown): + *hi = min(*hi+1, len(list)-1) + case in.Input.Shortcut(0, ui.KeyUp): + *hi = max(*hi-1, 0) + case in.Submitted() && len(list) > 0: + *zone, *open = list[*hi].name, false + } + } + defer func() { *shown = *hi }() + _, wh := c.Size() + ui.Scroll(c).MaxHeight(min(d.ControlHeight()*8, wh/2)).Children(func() { + if len(list) == 0 { + ui.Text(c, msg(c, "timezone_select.empty")).TextColor(k.TextMuted).Padding(d.Unit() * 2) + } + for i, z := range list { + if i == 0 || z.common != list[i-1].common { + key := "timezone_select.all" + if z.common { + key = "timezone_select.common" + } + ui.Text(c, msg(c, key)).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Padding(d.Unit(), d.Unit()*2) + } + if timezoneRow(c, z, i == *hi, i == *hi && *hi != *shown, z.name == *zone) { + *zone, *open = z.name, false + } + } + }) + }) + }) + changed := *zone != old + if changed { + slog.Debug("mujica: timezone_select change", "from", old, "to", *zone) + } + return ChoiceResult{Element: col, changed: changed} +} + +type timezoneEntry struct { + name, offset string + common bool +} + +// timezoneFilter matches names and offsets, common zones first. +func timezoneFilter(zones, common []string, query string, now time.Time) []timezoneEntry { + q := strings.ToLower(strings.TrimSpace(strings.ReplaceAll(query, " ", "_"))) + var out []timezoneEntry + add := func(names []string, isCommon bool) { + for _, z := range names { + off := TimezoneOffset(timezoneLoad(z), now) + if q == "" || strings.Contains(strings.ToLower(z), q) || strings.Contains(strings.ToLower(off), q) { + out = append(out, timezoneEntry{z, off, isCommon}) + } + } + } + add(common, true) + add(zones, false) + return out +} + +// timezoneName is a zone's city part, readable. +func timezoneName(z string) string { + return strings.ReplaceAll(z, "_", " ") +} + +// timezoneRow draws one zone; it reports a click. +func timezoneRow(c *ui.Context, z timezoneEntry, highlighted, reveal, chosen bool) bool { + k := Tokens(c) + d := Density(c) + b := ui.ButtonBase(c).MinHeight(d.ControlHeight()).Justify(ui.Start).Gap(d.Unit() * 3).PaddingX(d.Unit() * 2).Radius(theme.ControlRadius). + Label(z.offset + " " + timezoneName(z.name)) + internal.Ring(b, k.Focus, theme.ControlRadius) + switch { + case chosen || highlighted: + b.Background(k.Selection) + case b.Hovered(): + b.Background(k.SurfaceHover) + } + if reveal { + b.ScrollIntoView() + } + b.Children(func() { + ui.Text(c, z.offset).Width(d.ControlHeight() * 2.4).Shrink(0).FontFeatures("tnum").TextColor(k.TextMuted) + ui.Text(c, timezoneName(z.name)).TextColor(k.Text).Grow(1).Shrink(1).SingleLine().Ellipsis("…") + if chosen { + ui.Box(c).Size(16, 16).Shrink(0).Draw(func(p *ui.Painter, r ui.Rect) { internal.Mark(p, r, "check", k.AccentText) }) + } + }) + return b.Clicked() && !b.IsDisabled() +} diff --git a/timezone_select_test.go b/timezone_select_test.go new file mode 100644 index 0000000..084a170 --- /dev/null +++ b/timezone_select_test.go @@ -0,0 +1,98 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +var tzNow = time.Date(2026, time.July, 1, 12, 0, 0, 0, time.UTC) + +func timezoneTester(zone *string, opts *TimezoneSelectOptions, n *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + o := *opts + o.Now = tzNow + ui.Column(c).Padding(16).Children(func() { + if TimezoneSelect(c, zone, o).Changed() { + *n++ + } + }) + }, 520, 640) +} + +func TestTimezoneSelectSearchByNameAndOffset(t *testing.T) { + zone, n := "", 0 + tt := timezoneTester(&zone, &TimezoneSelectOptions{}, &n) + _ = tt.Click("Time zone") + if !tt.HasText("Common") || !tt.HasText("UTC+09:00 Asia/Tokyo") || !tt.HasText("UTC−04:00 America/New York") { + t.Fatalf("summer offsets and sections: %v", tt.Texts()[:12]) + } + tt.Type("kolk") + if !tt.HasText("UTC+05:30 Asia/Kolkata") || tt.HasText("UTC+09:00 Asia/Tokyo") { + t.Fatalf("name search: %v", tt.Texts()) + } + tt.Key(0, ui.KeyEnter) + if zone != "Asia/Kolkata" || n != 1 || !tt.HasText("UTC+05:30 · Asia/Kolkata") { + t.Fatalf("Enter picked %q", zone) + } + _ = tt.Click("Time zone") + tt.Type("+12:45") + tt.Key(0, ui.KeyEnter) + if zone != "Pacific/Chatham" { + t.Fatalf("offset search picked %q", zone) + } +} + +func TestTimezoneSelectKeysCommonClickEmpty(t *testing.T) { + zone, n := "UTC", 0 + tt := timezoneTester(&zone, &TimezoneSelectOptions{Common: []string{"Europe/Paris"}, Zones: []string{"Asia/Tokyo", "Europe/Paris"}}, &n) + _ = tt.Click("Time zone") + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if zone != "Asia/Tokyo" || n != 1 { + t.Fatalf("Down then Enter picked %q", zone) + } + _ = tt.Click("Time zone") + _ = tt.Click("UTC+02:00 Europe/Paris") + if zone != "Europe/Paris" { + t.Fatalf("click picked %q", zone) + } + _ = tt.Click("Time zone") + tt.Type("atlantis") + if !tt.HasText("No matching time zone.") { + t.Fatal("no empty state") + } +} + +func TestTimezoneSelectDisabledAndInvalid(t *testing.T) { + zone, n := "UTC", 0 + tt := timezoneTester(&zone, &TimezoneSelectOptions{Disabled: true}, &n) + _ = tt.Click("Time zone") + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyDown) + if tt.HasText("Common") { + t.Fatal("disabled select opened") + } + defer func() { + if recover() == nil { + t.Fatal("expected panic for an unknown zone") + } + }() + bad := "Mars/Olympus" + timezoneTester(&bad, &TimezoneSelectOptions{}, &n) +} + +func TestTimezoneOffsetHalfHours(t *testing.T) { + if got := TimezoneOffset(timezoneLoad("America/St_Johns"), tzNow); got != "UTC−02:30" { + t.Fatalf("offset %q", got) + } +} + +func TestTimezoneSelectSnapshot(t *testing.T) { + zone := "Asia/Shanghai" + snapshot(t, "timezone_select", 420, 80, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { TimezoneSelect(c, &zone, TimezoneSelectOptions{Now: tzNow}) }) + }) +} diff --git a/week_picker.go b/week_picker.go new file mode 100644 index 0000000..d01665a --- /dev/null +++ b/week_picker.go @@ -0,0 +1,96 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" +) + +// WeekPickerOptions configure a WeekPicker. +type WeekPickerOptions struct { + WeekStart WeekStart + // Min and Max bound the chosen week's days. + Min, Max Date + // Today is marked; zero uses the system clock. + Today Date + Clearable bool + Disabled bool + Label string +} + +// WeekPicker chooses a week; *value is its first day. +func WeekPicker(c *ui.Context, value *Date, opts WeekPickerOptions) ChoiceResult { + datetimeCheckDate("WeekPicker value", *value) + datetimeCheckBounds("WeekPicker", opts.Min, opts.Max) + first := calendarFirstWeekday(c, opts.WeekStart) + weekOf := func(d Date) Date { return d.AddDays(-((int(d.Weekday()) - int(first) + 7) % 7)) } + if !value.IsZero() && weekOf(*value) != *value { + panic(fmt.Sprintf("mujica: WeekPicker value %v does not start a week", *value)) + } + d := Density(c) + today := datetimeToday(c, opts.Today) + label := opts.Label + if label == "" { + label = msg(c, "week_picker.label") + } + enabled := func(x Date) bool { + w := weekOf(x) + return w.AddDays(6).within(opts.Min, Date{}) && w.within(Date{}, opts.Max) + } + col := ui.Column(c).Width(d.ControlHeight() * 8).Gap(d.Unit()).AlignItems(ui.Stretch).Disabled(opts.Disabled) + open := ui.Local(col, "week-picker-open", func() bool { return false }) + cursor := ui.Local(col, "week-picker-cursor", func() Date { return Date{} }) + hover := ui.Local(col, "week-picker-hover", func() Date { return Date{} }) + old := *value + text := "" + if !value.IsZero() { + text = weekViewTitle(c, *value, value.AddDays(6)) + } + col.Children(func() { + field := datetimeField(c, ui.Row(c), false, false) + field.Children(func() { + t := datetimeTrigger(c, text, msg(c, "week_picker.placeholder"), "calendar").Label(label).Description(text) + if !t.IsDisabled() && (t.Clicked() || !*open && t.Shortcut(0, ui.KeyDown)) { + *open, *hover = !*open, Date{} + *cursor = *value + if cursor.IsZero() { + *cursor = today + } + } + if opts.Clearable && !value.IsZero() { + if b := iconAction(c, icons.Must("x"), msg(c, "calendar.clear")); b.Clicked() && !b.IsDisabled() { + *value = Date{} + } + } + }) + datetimePopup(c, field, open, false, func() { + band := *hover + if band.IsZero() { + band = *cursor + } + picked, hovered := calendarMonth(c, cursor, calendarConfig{ + chosen: func(x Date) bool { return !value.IsZero() && weekOf(x) == *value }, + inRange: func(x Date) bool { return weekOf(x) == weekOf(band) }, + enabled: enabled, + today: today, + weekStart: opts.WeekStart, + autoFocus: true, + }) + if hovered != *hover { + *hover = hovered + c.Invalidate() + } + if !picked.IsZero() { + *value, *open = weekOf(picked), false + } + }) + }) + changed := *value != old + if changed { + slog.Debug("mujica: week_picker change", "from", old, "to", *value) + } + return ChoiceResult{Element: col, changed: changed} +} diff --git a/week_picker_test.go b/week_picker_test.go new file mode 100644 index 0000000..d8c3d8f --- /dev/null +++ b/week_picker_test.go @@ -0,0 +1,76 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func weekPickerTester(v *Date, opts *WeekPickerOptions, n *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + o := *opts + o.Today, o.Label = calendarToday, "Sprint" + ui.Column(c).Padding(16).Children(func() { + if WeekPicker(c, v, o).Changed() { + *n++ + } + }) + }, 480, 480) +} + +func TestWeekPickerPicksWeekStart(t *testing.T) { + v, n := Date{}, 0 + opts := &WeekPickerOptions{} + tt := weekPickerTester(&v, opts, &n) + _ = tt.Click("Sprint") + _ = tt.Click(datetimeTestLabel(oct(15))) + if v != oct(11) || n != 1 || !tt.HasText("October 11 – October 17, 2026") { + t.Fatalf("Sunday-start week of Oct 15: %v %v", v, tt.Texts()) + } + v, opts.WeekStart = oct(12), WeekStartMonday + tt.Frame() + _ = tt.Click("Sprint") + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if v != oct(19) || n != 2 { + t.Fatalf("Monday-start keyboard pick %v", v) + } +} + +func TestWeekPickerBoundsClearDisabled(t *testing.T) { + v, n := oct(11), 0 + opts := &WeekPickerOptions{Min: oct(4), Max: oct(24), Clearable: true} + tt := weekPickerTester(&v, opts, &n) + _ = tt.Click("Sprint") + _ = tt.Click(datetimeTestLabel(oct(26))) + _ = tt.Click(datetimeTestLabel(oct(2))) + if v != oct(11) || n != 0 { + t.Fatalf("out-of-range week chosen: %v", v) + } + tt.Key(0, ui.KeyEscape) + _ = tt.Click("Clear") + if !v.IsZero() || n != 1 { + t.Fatalf("clear left %v", v) + } + opts.Disabled = true + tt.Frame() + _ = tt.Click("Sprint") + if tt.HasText("October 2026") { + t.Fatal("disabled picker opened") + } + defer func() { + if recover() == nil { + t.Fatal("expected panic for a mid-week value") + } + }() + mid := oct(14) + weekPickerTester(&mid, &WeekPickerOptions{}, &n) +} + +func TestWeekPickerSnapshot(t *testing.T) { + v := oct(11) + snapshot(t, "week_picker", 400, 80, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { WeekPicker(c, &v, WeekPickerOptions{Today: calendarToday, Clearable: true}) }) + }) +} diff --git a/year_view.go b/year_view.go new file mode 100644 index 0000000..812c48d --- /dev/null +++ b/year_view.go @@ -0,0 +1,168 @@ +package mujica + +import ( + "fmt" + "strconv" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// YearViewOptions configure a YearView. +type YearViewOptions struct { + // Location is the zone days are cut in; required. + Location *time.Location + // Version must change when events change in place. + Version int + WeekStart WeekStart + // Today is marked; zero uses the system clock. + Today Date + Disabled bool + Label string +} + +// YearView shows twelve months with busy-day dots. +func YearView(c *ui.Context, year *int, events []CalendarEvent, opts YearViewOptions) CalendarViewResult { + loc := eventLocation("YearView", opts.Location) + if *year < 1 { + panic(fmt.Sprintf("mujica: YearView year %d is not valid", *year)) + } + eventsCheck("YearView", events) + d := Density(c) + today := datetimeToday(c, opts.Today) + first := Date{*year, time.January, 1} + label := opts.Label + if label == "" { + label = strconv.Itoa(*year) + } + r := CalendarViewResult{} + root := ui.Column(c).Gap(d.Unit() * 3).Role(ui.RoleGroup).Label(label).Disabled(opts.Disabled) + r.Element = root + counts := eventsDerived(root, "year-view-counts", events, opts.Version, eventDayStart(first, loc), eventDayStart(first.AddMonths(12), loc), + func(hits []int) map[Date]int { + m := map[Date]int{} + for _, h := range hits { + ev := events[h] + for day := DateOf(ev.Start.In(loc)); eventDayStart(day, loc).Before(ev.End); day = day.AddDays(1) { + m[day]++ + } + } + return m + }) + cursor := ui.Local(root, "year-view-cursor", func() Date { return Date{} }) + if cursor.Year != *year { + *cursor = Date{*year, today.Month, min(today.Day, 28)} + } + root.Children(func() { + calendarViewHeader(c, strconv.Itoa(*year), msg(c, "calendar.prev_year"), msg(c, "calendar.next_year"), func(dir int) { + *year += dir + }) + grid := ui.Row(c).Wrap().AlignItems(ui.Start).Gap(d.Unit() * 4).FocusGroup(ui.Horizontal | ui.Vertical) + moved := false + if !grid.IsDisabled() { + for key, days := range map[ui.Key]int{ui.KeyLeft: -1, ui.KeyRight: 1, ui.KeyUp: -7, ui.KeyDown: 7} { + if grid.Shortcut(0, key) { + *cursor, moved = cursor.AddDays(days), true + } + } + for key, months := range map[ui.Key]int{ui.KeyPageUp: -1, ui.KeyPageDown: 1} { + if grid.Shortcut(0, key) { + *cursor, moved = cursor.AddMonths(months), true + } + } + if moved && cursor.Year != *year { + *year = cursor.Year + } + } + grid.Children(func() { + for m := time.January; m <= time.December; m++ { + if day, ok := yearMonth(c, *year, m, counts, today, *cursor, moved, opts.WeekStart); ok && !grid.IsDisabled() { + r.day, *cursor = day, day + } + } + }) + }) + return r +} + +// yearMonth draws one small month and reports a day clicked. +func yearMonth(c *ui.Context, year int, m time.Month, counts map[Date]int, today, cursor Date, focus bool, ws WeekStart) (Date, bool) { + k := Tokens(c) + cell := theme.MinHitSize + first := calendarFirstWeekday(c, ws) + start := Date{year, m, 1} + lead := (int(start.Weekday()) - int(first) + 7) % 7 + var picked Date + ui.Column(c).Width(cell * 7).Gap(2).Children(func() { + ui.Text(c, datetimeMonthName(c, m)).Font(theme.SerifFont).TextColor(k.Text).Bold() + ui.Row(c).Children(func() { + for i := range 7 { + wd := (int(first) + i) % 7 + ui.Text(c, msg(c, "calendar.weekday_"+strconv.Itoa(wd))).Width(cell).TextAlign(ui.Center). + FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + } + }) + last := start.AddMonths(1).AddDays(-1).Day + for w := 0; w*7 < lead+last; w++ { + ui.Row(c).Children(func() { + for i := range 7 { + n := w*7 + i - lead + 1 + if n < 1 || n > last { + ui.Box(c).Size(cell, cell) + continue + } + day := Date{year, m, n} + busy := counts[day] + text := datetimeDayLabel(c, day) + if busy > 0 { + text += ", " + calendarCount(c, "year_view.events", busy) + } + b := ui.ButtonBase(c).Size(cell, cell).Radius(theme.ControlRadius).Label(text).Column() + internal.Ring(b, k.Focus, theme.ControlRadius) + if day == cursor && focus { + b.Focus() + } + switch { + case day == today: + b.Background(k.Selection) + case b.Hovered(): + b.Background(k.SurfaceHover) + } + dots := yearDots(busy) + b.Draw(func(p *ui.Painter, r ui.Rect) { + x0 := r.X + r.W/2 - float32(dots*5-2)/2 + for j := range dots { + p.Fill(ui.Rect{X: x0 + float32(j)*5, Y: r.Y + r.H - 6, W: 3, H: 3}, k.AccentText, 1.5) + } + }) + b.Children(func() { + t := ui.Text(c, strconv.Itoa(n)).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.Text).FontFeatures("tnum") + if day == today { + t.Bold().TextColor(k.AccentText) + } + }) + if b.Clicked() { + picked = day + } + } + }) + } + }) + return picked, !picked.IsZero() +} + +// yearDots maps an event count to one to three dots. +func yearDots(n int) int { + switch { + case n == 0: + return 0 + case n <= 2: + return 1 + case n <= 5: + return 2 + } + return 3 +} diff --git a/year_view_test.go b/year_view_test.go new file mode 100644 index 0000000..6a42408 --- /dev/null +++ b/year_view_test.go @@ -0,0 +1,108 @@ +package mujica + +import ( + "fmt" + "testing" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +func yearViewTester(year *int, events []CalendarEvent, opts YearViewOptions, days *[]Date) *ui.Tester { + opts.Location, opts.Today = calTokyo, calendarToday + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{Mode: Light}) + if d, ok := YearView(c, year, events, opts).DayChosen(); ok { + *days = append(*days, d) + } + }, 900, 1200) +} + +func TestYearViewDensityMarks(t *testing.T) { + var evs []CalendarEvent + for i := range 4 { + evs = append(evs, calEvent(fmt.Sprint(i), 14, 9+i, 0, 30)) + } + evs = append(evs, calEvent("x", 20, 9, 0, 30)) + year := 2026 + var days []Date + tt := yearViewTester(&year, evs, YearViewOptions{}, &days) + tt.SetPreferences(ui.Preferences{ReduceMotion: true, TextScale: 1}) + if !tt.HasText("Wednesday, October 14, 2026, 4 events") || !tt.HasText("Tuesday, October 20, 2026, 1 event") { + t.Fatalf("labels lack counts: %v", tt.Texts()[:5]) + } + img := tt.Image() + dotsAt := func(label string) int { + r, _ := tt.Find(label) + n, prev := 0, false + for x := int(r.X); x < int(r.X+r.W); x++ { + on := datetimeNear(img.RGBAAt(x, int(r.Y+r.H-5)), theme.Light().AccentText) + if on && !prev { + n++ + } + prev = on + } + return n + } + if a, b, z := dotsAt("Wednesday, October 14, 2026, 4 events"), dotsAt("Tuesday, October 20, 2026, 1 event"), dotsAt(datetimeTestLabel(oct(21))); a != 2 || b != 1 || z != 0 { + t.Fatalf("dots %d %d %d", a, b, z) + } + if yearDots(6) != 3 { + t.Fatal("6 events should show three dots") + } +} + +func TestYearViewClickKeysAndYearChange(t *testing.T) { + year := 2026 + var days []Date + tt := yearViewTester(&year, nil, YearViewOptions{}, &days) + _ = tt.Click(datetimeTestLabel(Date{2026, time.March, 3})) + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if len(days) != 2 || days[0] != (Date{2026, time.March, 3}) || days[1] != (Date{2026, time.March, 11}) { + t.Fatalf("days %v", days) + } + _ = tt.Click(datetimeTestLabel(Date{2026, time.December, 31})) + tt.Key(0, ui.KeyRight) + if year != 2027 || !tt.Focused(datetimeTestLabel(Date{2027, time.January, 1})) { + t.Fatalf("crossing the year: %d", year) + } + _ = tt.Click("Previous year") + if year != 2026 { + t.Fatalf("year %d", year) + } +} + +func TestYearViewDisabledAndInvalid(t *testing.T) { + year := 2026 + var days []Date + tt := yearViewTester(&year, nil, YearViewOptions{Disabled: true}, &days) + _ = tt.Click(datetimeTestLabel(oct(3))) + _ = tt.Click("Next year") + if len(days) != 0 || year != 2026 { + t.Fatal("disabled year view reacted") + } + defer func() { + if recover() == nil { + t.Fatal("expected panic for year 0") + } + }() + zero := 0 + yearViewTester(&zero, nil, YearViewOptions{}, &days) +} + +func TestYearViewSnapshot(t *testing.T) { + var evs []CalendarEvent + for i := range 40 { + evs = append(evs, calEvent(fmt.Sprint(i), 1+i%28, 9+i%5, 0, 30)) + } + year := 2026 + snapshot(t, "year_view", 680, 960, func(c *ui.Context) { + ui.Column(c).Padding(16).Children(func() { + YearView(c, &year, evs, YearViewOptions{Location: calTokyo, Today: calendarToday}) + }) + }) +} From 0b936c940fde9fc91b68892d5c03b44e26616e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 5 Oct 2026 14:38:18 -0400 Subject: [PATCH 12/13] Terminal & Code: components 321-340 --- breakpoint_list.go | 126 ++++++ breakpoint_list_test.go | 114 ++++++ call_stack.go | 140 +++++++ call_stack_test.go | 104 +++++ code_shared.go | 176 +++++++++ code_viewer.go | 253 ++++++++++++ code_viewer_test.go | 151 ++++++++ command_history.go | 119 ++++++ command_history_test.go | 117 ++++++ completion_menu.go | 129 +++++++ completion_menu_test.go | 103 +++++ debug_toolbar.go | 141 +++++++ debug_toolbar_test.go | 113 ++++++ docs/components/321-terminal.md | 52 +++ docs/components/322-terminal-tabs.md | 52 +++ docs/components/323-terminal-search.md | 48 +++ docs/components/324-command-history.md | 50 +++ docs/components/325-log-viewer.md | 48 +++ docs/components/326-process-list.md | 50 +++ docs/components/327-code-viewer.md | 46 +++ docs/components/328-minimap.md | 45 +++ docs/components/329-find-widget.md | 51 +++ docs/components/330-search-panel.md | 51 +++ docs/components/331-problems-panel.md | 49 +++ docs/components/332-output-panel.md | 48 +++ docs/components/333-symbol-outline.md | 53 +++ docs/components/334-completion-menu.md | 50 +++ docs/components/335-debug-toolbar.md | 48 +++ docs/components/336-breakpoint-list.md | 49 +++ docs/components/337-call-stack.md | 52 +++ docs/components/338-variables-panel.md | 49 +++ docs/components/339-hex-viewer.md | 44 +++ docs/components/340-flamegraph.md | 50 +++ example_code_test.go | 276 +++++++++++++ examples/gallery/pages_code.go | 244 +++++++++++- examples/gallery/pages_code_debug.go | 238 ++++++++++++ examples/gallery/pages_code_snippets.go | 230 +++++++++++ examples/gallery/pages_code_tools.go | 264 +++++++++++++ find_widget.go | 181 +++++++++ find_widget_test.go | 117 ++++++ flamegraph.go | 276 +++++++++++++ flamegraph_test.go | 143 +++++++ hex_viewer.go | 157 ++++++++ hex_viewer_test.go | 115 ++++++ log_viewer.go | 130 +++++++ log_viewer_test.go | 129 +++++++ messages_code.go | 101 +++++ minimap.go | 134 +++++++ minimap_test.go | 116 ++++++ output_panel.go | 93 +++++ output_panel_test.go | 118 ++++++ problems_panel.go | 194 ++++++++++ problems_panel_test.go | 106 +++++ process_list.go | 185 +++++++++ process_list_test.go | 124 ++++++ search_panel.go | 202 ++++++++++ search_panel_test.go | 129 +++++++ symbol_outline.go | 235 ++++++++++++ symbol_outline_test.go | 107 ++++++ terminal.go | 308 +++++++++++++++ terminal_search.go | 77 ++++ terminal_search_test.go | 105 +++++ terminal_state.go | 361 ++++++++++++++++++ terminal_tabs.go | 181 +++++++++ terminal_tabs_test.go | 122 ++++++ terminal_test.go | 192 ++++++++++ .../snapshots/darwin/breakpoint_list-dark.png | Bin 0 -> 8797 bytes .../darwin/breakpoint_list-light.png | Bin 0 -> 8592 bytes testdata/snapshots/darwin/call_stack-dark.png | Bin 0 -> 16607 bytes .../snapshots/darwin/call_stack-light.png | Bin 0 -> 15794 bytes .../snapshots/darwin/code_viewer-dark.png | Bin 0 -> 16193 bytes .../snapshots/darwin/code_viewer-light.png | Bin 0 -> 15572 bytes .../snapshots/darwin/command_history-dark.png | Bin 0 -> 13577 bytes .../darwin/command_history-light.png | Bin 0 -> 13177 bytes .../snapshots/darwin/completion_menu-dark.png | Bin 0 -> 14386 bytes .../darwin/completion_menu-light.png | Bin 0 -> 15566 bytes .../snapshots/darwin/debug_toolbar-dark.png | Bin 0 -> 2158 bytes .../snapshots/darwin/debug_toolbar-light.png | Bin 0 -> 2145 bytes .../snapshots/darwin/find_widget-dark.png | Bin 0 -> 9014 bytes .../snapshots/darwin/find_widget-light.png | Bin 0 -> 8713 bytes testdata/snapshots/darwin/flamegraph-dark.png | Bin 0 -> 13502 bytes .../snapshots/darwin/flamegraph-light.png | Bin 0 -> 13200 bytes testdata/snapshots/darwin/hex_viewer-dark.png | Bin 0 -> 15629 bytes .../snapshots/darwin/hex_viewer-light.png | Bin 0 -> 14906 bytes testdata/snapshots/darwin/log_viewer-dark.png | Bin 0 -> 27349 bytes .../snapshots/darwin/log_viewer-light.png | Bin 0 -> 26128 bytes testdata/snapshots/darwin/minimap-dark.png | Bin 0 -> 1549 bytes testdata/snapshots/darwin/minimap-light.png | Bin 0 -> 1589 bytes .../snapshots/darwin/output_panel-dark.png | Bin 0 -> 7462 bytes .../snapshots/darwin/output_panel-light.png | Bin 0 -> 7084 bytes .../snapshots/darwin/problems_panel-dark.png | Bin 0 -> 23450 bytes .../snapshots/darwin/problems_panel-light.png | Bin 0 -> 22802 bytes .../snapshots/darwin/process_list-dark.png | Bin 0 -> 15261 bytes .../snapshots/darwin/process_list-light.png | Bin 0 -> 14823 bytes .../snapshots/darwin/search_panel-dark.png | Bin 0 -> 21859 bytes .../snapshots/darwin/search_panel-light.png | Bin 0 -> 21072 bytes .../snapshots/darwin/symbol_outline-dark.png | Bin 0 -> 13607 bytes .../snapshots/darwin/symbol_outline-light.png | Bin 0 -> 13268 bytes testdata/snapshots/darwin/terminal-dark.png | Bin 0 -> 11844 bytes testdata/snapshots/darwin/terminal-light.png | Bin 0 -> 11584 bytes .../snapshots/darwin/terminal_search-dark.png | Bin 0 -> 8269 bytes .../darwin/terminal_search-light.png | Bin 0 -> 7606 bytes .../snapshots/darwin/terminal_tabs-dark.png | Bin 0 -> 5920 bytes .../snapshots/darwin/terminal_tabs-light.png | Bin 0 -> 5571 bytes .../snapshots/darwin/variables_panel-dark.png | Bin 0 -> 8891 bytes .../darwin/variables_panel-light.png | Bin 0 -> 8556 bytes variables_panel.go | 158 ++++++++ variables_panel_test.go | 115 ++++++ 108 files changed, 8733 insertions(+), 1 deletion(-) create mode 100644 breakpoint_list.go create mode 100644 breakpoint_list_test.go create mode 100644 call_stack.go create mode 100644 call_stack_test.go create mode 100644 code_shared.go create mode 100644 code_viewer.go create mode 100644 code_viewer_test.go create mode 100644 command_history.go create mode 100644 command_history_test.go create mode 100644 completion_menu.go create mode 100644 completion_menu_test.go create mode 100644 debug_toolbar.go create mode 100644 debug_toolbar_test.go create mode 100644 docs/components/321-terminal.md create mode 100644 docs/components/322-terminal-tabs.md create mode 100644 docs/components/323-terminal-search.md create mode 100644 docs/components/324-command-history.md create mode 100644 docs/components/325-log-viewer.md create mode 100644 docs/components/326-process-list.md create mode 100644 docs/components/327-code-viewer.md create mode 100644 docs/components/328-minimap.md create mode 100644 docs/components/329-find-widget.md create mode 100644 docs/components/330-search-panel.md create mode 100644 docs/components/331-problems-panel.md create mode 100644 docs/components/332-output-panel.md create mode 100644 docs/components/333-symbol-outline.md create mode 100644 docs/components/334-completion-menu.md create mode 100644 docs/components/335-debug-toolbar.md create mode 100644 docs/components/336-breakpoint-list.md create mode 100644 docs/components/337-call-stack.md create mode 100644 docs/components/338-variables-panel.md create mode 100644 docs/components/339-hex-viewer.md create mode 100644 docs/components/340-flamegraph.md create mode 100644 example_code_test.go create mode 100644 examples/gallery/pages_code_debug.go create mode 100644 examples/gallery/pages_code_snippets.go create mode 100644 examples/gallery/pages_code_tools.go create mode 100644 find_widget.go create mode 100644 find_widget_test.go create mode 100644 flamegraph.go create mode 100644 flamegraph_test.go create mode 100644 hex_viewer.go create mode 100644 hex_viewer_test.go create mode 100644 log_viewer.go create mode 100644 log_viewer_test.go create mode 100644 messages_code.go create mode 100644 minimap.go create mode 100644 minimap_test.go create mode 100644 output_panel.go create mode 100644 output_panel_test.go create mode 100644 problems_panel.go create mode 100644 problems_panel_test.go create mode 100644 process_list.go create mode 100644 process_list_test.go create mode 100644 search_panel.go create mode 100644 search_panel_test.go create mode 100644 symbol_outline.go create mode 100644 symbol_outline_test.go create mode 100644 terminal.go create mode 100644 terminal_search.go create mode 100644 terminal_search_test.go create mode 100644 terminal_state.go create mode 100644 terminal_tabs.go create mode 100644 terminal_tabs_test.go create mode 100644 terminal_test.go create mode 100644 testdata/snapshots/darwin/breakpoint_list-dark.png create mode 100644 testdata/snapshots/darwin/breakpoint_list-light.png create mode 100644 testdata/snapshots/darwin/call_stack-dark.png create mode 100644 testdata/snapshots/darwin/call_stack-light.png create mode 100644 testdata/snapshots/darwin/code_viewer-dark.png create mode 100644 testdata/snapshots/darwin/code_viewer-light.png create mode 100644 testdata/snapshots/darwin/command_history-dark.png create mode 100644 testdata/snapshots/darwin/command_history-light.png create mode 100644 testdata/snapshots/darwin/completion_menu-dark.png create mode 100644 testdata/snapshots/darwin/completion_menu-light.png create mode 100644 testdata/snapshots/darwin/debug_toolbar-dark.png create mode 100644 testdata/snapshots/darwin/debug_toolbar-light.png create mode 100644 testdata/snapshots/darwin/find_widget-dark.png create mode 100644 testdata/snapshots/darwin/find_widget-light.png create mode 100644 testdata/snapshots/darwin/flamegraph-dark.png create mode 100644 testdata/snapshots/darwin/flamegraph-light.png create mode 100644 testdata/snapshots/darwin/hex_viewer-dark.png create mode 100644 testdata/snapshots/darwin/hex_viewer-light.png create mode 100644 testdata/snapshots/darwin/log_viewer-dark.png create mode 100644 testdata/snapshots/darwin/log_viewer-light.png create mode 100644 testdata/snapshots/darwin/minimap-dark.png create mode 100644 testdata/snapshots/darwin/minimap-light.png create mode 100644 testdata/snapshots/darwin/output_panel-dark.png create mode 100644 testdata/snapshots/darwin/output_panel-light.png create mode 100644 testdata/snapshots/darwin/problems_panel-dark.png create mode 100644 testdata/snapshots/darwin/problems_panel-light.png create mode 100644 testdata/snapshots/darwin/process_list-dark.png create mode 100644 testdata/snapshots/darwin/process_list-light.png create mode 100644 testdata/snapshots/darwin/search_panel-dark.png create mode 100644 testdata/snapshots/darwin/search_panel-light.png create mode 100644 testdata/snapshots/darwin/symbol_outline-dark.png create mode 100644 testdata/snapshots/darwin/symbol_outline-light.png create mode 100644 testdata/snapshots/darwin/terminal-dark.png create mode 100644 testdata/snapshots/darwin/terminal-light.png create mode 100644 testdata/snapshots/darwin/terminal_search-dark.png create mode 100644 testdata/snapshots/darwin/terminal_search-light.png create mode 100644 testdata/snapshots/darwin/terminal_tabs-dark.png create mode 100644 testdata/snapshots/darwin/terminal_tabs-light.png create mode 100644 testdata/snapshots/darwin/variables_panel-dark.png create mode 100644 testdata/snapshots/darwin/variables_panel-light.png create mode 100644 variables_panel.go create mode 100644 variables_panel_test.go diff --git a/breakpoint_list.go b/breakpoint_list.go new file mode 100644 index 0000000..1aab2b1 --- /dev/null +++ b/breakpoint_list.go @@ -0,0 +1,126 @@ +package mujica + +import ( + "fmt" + "log/slog" + "path" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// Breakpoint stops at File:Line when Condition holds. +type Breakpoint struct { + ID string + File string + Line int + Enabled bool + Condition string +} + +// BreakpointListOptions configure a BreakpointList. +type BreakpointListOptions struct { + Disabled bool +} + +// BreakpointListResult fields hold breakpoint IDs. +type BreakpointListResult struct { + Element *ui.Element + Toggled, Edited, Opened string +} + +type breakpointEdit struct{ id, draft string } + +// BreakpointList lists breakpoints with toggles and conditions. +func BreakpointList(c *ui.Context, bps *[]Breakpoint, opts BreakpointListOptions) BreakpointListResult { + if bps == nil { + panic("mujica: BreakpointList needs breakpoints") + } + seen := map[string]bool{} + for _, b := range *bps { + if b.ID == "" || seen[b.ID] { + panic("mujica: Breakpoint IDs must be set and unique") + } + seen[b.ID] = true + } + k := Tokens(c) + d := Density(c) + u := d.Unit() + var res BreakpointListResult + res.Element = codePanel(c).Disabled(opts.Disabled).Label(msg(c, "breakpoint_list.label")) + edit := ui.Local(res.Element, "breakpoint_list.edit", func() breakpointEdit { return breakpointEdit{} }) + disabled := res.Element.IsDisabled() + if disabled { + edit.id = "" + } + res.Element.Children(func() { + if len(*bps) == 0 { + codeCaption(c, msg(c, "breakpoint_list.empty")).Padding(u * 4) + return + } + ScrollArea(c, nil, ScrollAreaOptions{}, func() { + for i := range *bps { + b := &(*bps)[i] + ui.Column(c).Key(b.ID).Padding(u, u*2).Gap(u).BorderWidth(0, 0, theme.BorderWidth, 0).BorderColor(k.Border).Children(func() { + ui.Row(c).MinHeight(d.ControlHeight()).Gap(u * 2).AlignItems(ui.Center).Children(func() { + on := b.Enabled + Checkbox(c, &on, "", CheckboxOptions{Disabled: opts.Disabled}).Label(fmt.Sprintf(msg(c, "breakpoint_list.enable"), path.Base(b.File), b.Line)) + if on != b.Enabled && !disabled { + b.Enabled, res.Toggled = on, b.ID + slog.Debug("mujica: breakpoint_list toggle", "id", b.ID, "enabled", on) + } + if breakpointLocation(c, *b).Clicked() && !disabled { + res.Opened = b.ID + slog.Debug("mujica: breakpoint_list open", "id", b.ID) + } + if iconAction(c, icons.Must("funnel"), fmt.Sprintf(msg(c, "breakpoint_list.edit"), path.Base(b.File), b.Line)).Clicked() && !disabled { + *edit = breakpointEdit{b.ID, b.Condition} + } + }) + switch { + case edit.id == b.ID: + in := TextInput(c, &edit.draft, TextInputOptions{Placeholder: msg(c, "breakpoint_list.placeholder"), Label: msg(c, "breakpoint_list.condition")}) + in.Input.AutoFocus() + if in.Input.Shortcut(0, ui.KeyEscape) { + edit.id = "" + } else if in.Submitted() && !disabled { + b.Condition, res.Edited, edit.id = edit.draft, b.ID, "" + slog.Debug("mujica: breakpoint_list condition", "id", b.ID) + } + case b.Condition != "": + codeMono(c, fmt.Sprintf(msg(c, "breakpoint_list.when"), b.Condition)).TextColor(k.Warning).Padding(0, 0, 0, 28) + } + }) + } + }).Grow(1) + }) + return res +} + +// breakpointLocation is a button opening the location. +func breakpointLocation(c *ui.Context, b Breakpoint) *ui.Element { + k := Tokens(c) + d := Density(c) + e := ui.ButtonBase(c).Grow(1).MinWidth(0).MinHeight(theme.MinHitSize).Justify(ui.Start).Gap(d.Unit()*2).Padding(0, d.Unit()). + Radius(theme.ControlRadius).Label(fmt.Sprintf("%s:%d", b.File, b.Line)) + internal.Ring(e, k.Focus, theme.ControlRadius) + if e.Hovered() { + e.Background(k.SurfaceHover) + } + fg := k.Text + if !b.Enabled { + fg = k.TextMuted + } + return e.Children(func() { + // A filled dot is enabled, a ring disabled. + dot := ui.Box(c).Size(10, 10).Radius(5).Shrink(0).Role(ui.RoleNone).Border(theme.BorderWidth, k.Danger) + if b.Enabled { + dot.Background(k.Danger) + } + ui.Text(c, path.Base(b.File)).TextColor(fg).SingleLine() + codeCaption(c, fmt.Sprintf("%s:%d", path.Dir(b.File), b.Line)).MinWidth(0) + }) +} diff --git a/breakpoint_list_test.go b/breakpoint_list_test.go new file mode 100644 index 0000000..0b02a10 --- /dev/null +++ b/breakpoint_list_test.go @@ -0,0 +1,114 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +type breakpointProbe struct { + bps []Breakpoint + disabled bool + toggled, edited, opened []string +} + +func (p *breakpointProbe) view(c *ui.Context) { + Use(c, Settings{}) + r := BreakpointList(c, &p.bps, BreakpointListOptions{Disabled: p.disabled}) + r.Element.Height(300) + for _, e := range []struct { + id string + out *[]string + }{{r.Toggled, &p.toggled}, {r.Edited, &p.edited}, {r.Opened, &p.opened}} { + if e.id != "" { + *e.out = append(*e.out, e.id) + } + } +} + +func newBreakpointProbe() *breakpointProbe { + return &breakpointProbe{bps: []Breakpoint{ + {ID: "a", File: "court/seal.go", Line: 12, Enabled: true}, + {ID: "b", File: "court/ledger.go", Line: 40, Enabled: false, Condition: "n > 3"}, + }} +} + +func TestBreakpointListToggleAndOpen(t *testing.T) { + p := newBreakpointProbe() + tt := ui.NewTester(p.view, 520, 320) + if err := tt.Click("Enable ledger.go:40"); err != nil { + t.Fatal(err) + } + if !p.bps[1].Enabled || len(p.toggled) != 1 || p.toggled[0] != "b" { + t.Fatalf("toggle: %+v %v", p.bps[1], p.toggled) + } + if err := tt.Click("court/seal.go:12"); err != nil { + t.Fatal(err) + } + if len(p.opened) != 1 || p.opened[0] != "a" { + t.Fatalf("opened %v", p.opened) + } + if !tt.HasText("when n > 3") { + t.Fatalf("condition not shown: %q", tt.Texts()) + } +} + +func TestBreakpointListEditCondition(t *testing.T) { + p := newBreakpointProbe() + tt := ui.NewTester(p.view, 520, 320) + if err := tt.Click("Edit condition of seal.go:12"); err != nil { + t.Fatal(err) + } + if !tt.Focused("Condition") { + t.Fatal("editor did not take the focus") + } + tt.Type("i == 7") + tt.Key(0, ui.KeyEnter) + if p.bps[0].Condition != "i == 7" || len(p.edited) != 1 { + t.Fatalf("condition %q edited %v", p.bps[0].Condition, p.edited) + } + _ = tt.Click("Edit condition of ledger.go:40") + tt.Type("x") + tt.Key(0, ui.KeyEscape) + if p.bps[1].Condition != "n > 3" { + t.Fatalf("Escape kept %q", p.bps[1].Condition) + } +} + +func TestBreakpointListKeyboardToggle(t *testing.T) { + p := newBreakpointProbe() + tt := ui.NewTester(p.view, 520, 320) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeySpace) + if p.bps[0].Enabled { + t.Fatal("Space did not disable the first breakpoint") + } +} + +func TestBreakpointListDisabledAndDuplicate(t *testing.T) { + p := newBreakpointProbe() + p.disabled = true + tt := ui.NewTester(p.view, 520, 320) + _ = tt.Click("Enable ledger.go:40") + _ = tt.Click("court/seal.go:12") + if p.bps[1].Enabled || len(p.opened) != 0 { + t.Fatal("disabled list changed") + } + defer func() { + if recover() == nil { + t.Fatal("duplicate IDs did not panic") + } + }() + p = newBreakpointProbe() + p.bps[1].ID = "a" + ui.NewTester(p.view, 520, 320) +} + +func TestBreakpointListSnapshot(t *testing.T) { + snapshot(t, "breakpoint_list", 460, 170, func(c *ui.Context) { + p := ui.Local(c.Root(), "snap", newBreakpointProbe) + ui.Column(c).Padding(12).Children(func() { + BreakpointList(c, &(*p).bps, BreakpointListOptions{}).Element.Height(146) + }) + }) +} diff --git a/call_stack.go b/call_stack.go new file mode 100644 index 0000000..4a060d5 --- /dev/null +++ b/call_stack.go @@ -0,0 +1,140 @@ +package mujica + +import ( + "fmt" + "log/slog" + "path" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" +) + +// StackFrame is one call of a thread's stack, innermost first. +type StackFrame struct { + ID, Name, File string + Line int +} + +// DebugThread is a thread and its stack. +type DebugThread struct { + ID, Name string + Frames []StackFrame +} + +// CallStackState is the current frame and folded threads. +type CallStackState struct { + // Current is the chosen frame's ID. + Current string + // Collapsed holds folded thread IDs. + Collapsed ui.Selection[string] + rows ui.ListState + selected int + flat []callRow + seen string + folds int + started bool +} + +type callRow struct{ thread, frame int } + +// CallStackOptions configure a CallStack. +type CallStackOptions struct { + Disabled bool +} + +// CallStack lists frames by thread; choosing sets Current. +func CallStack(c *ui.Context, threads []DebugThread, s *CallStackState, opts CallStackOptions) ChoiceResult { + if s == nil { + panic("mujica: CallStack needs a state") + } + s.flat = s.flat[:0] + at := -1 + for ti, t := range threads { + s.flat = append(s.flat, callRow{ti, -1}) + if s.Collapsed.Has(t.ID) { + continue + } + for fi, f := range t.Frames { + if f.ID == s.Current { + at = len(s.flat) + } + s.flat = append(s.flat, callRow{ti, fi}) + } + } + // Choose the row again after outside changes. + if !s.started || s.seen != s.Current || s.folds != s.Collapsed.Len() || s.selected >= len(s.flat) { + s.started, s.seen, s.selected, s.folds = true, s.Current, at, s.Collapsed.Len() + } + d := Density(c) + var res ChoiceResult + res.Element = codePanel(c).Disabled(opts.Disabled) + disabled := res.Element.IsDisabled() + res.Element.Children(func() { + if len(threads) == 0 { + codeCaption(c, msg(c, "call_stack.empty")).Padding(d.Unit() * 4) + return + } + was := s.selected + s.rows.Selected = &s.selected + s.rows.Key = func(i int) any { return s.flat[i] } + s.rows.Label = func(i int) string { return callLabel(threads, s.flat[i]) } + list := codeRows(c, &s.rows, len(s.flat), func(i int) { callRowView(c, threads, s, s.flat[i], disabled) }) + if disabled { + s.selected = was + return + } + if s.selected < 0 || s.selected >= len(s.flat) { + return + } + r := s.flat[s.selected] + t := threads[r.thread] + switch { + case r.frame >= 0 && s.selected != was: + s.Current = t.Frames[r.frame].ID + s.seen, res.changed = s.Current, true + slog.Debug("mujica: call_stack frame", "thread", t.ID, "depth", r.frame) + case r.frame < 0 && (list.Submitted() || + !s.Collapsed.Has(t.ID) && list.Shortcut(0, ui.KeyLeft) || s.Collapsed.Has(t.ID) && list.Shortcut(0, ui.KeyRight)): + callFold(s, t.ID) + } + }) + return res +} + +func callFold(s *CallStackState, id string) { + if s.Collapsed.Has(id) { + s.Collapsed.Remove(id) + } else { + s.Collapsed.Add(id) + } + slog.Debug("mujica: call_stack fold", "thread", id, "folded", s.Collapsed.Has(id)) +} + +func callLabel(threads []DebugThread, r callRow) string { + t := threads[r.thread] + if r.frame < 0 { + return t.Name + } + f := t.Frames[r.frame] + return fmt.Sprintf("%s %s:%d", f.Name, path.Base(f.File), f.Line) +} + +func callRowView(c *ui.Context, threads []DebugThread, s *CallStackState, r callRow, disabled bool) { + t := threads[r.thread] + if r.frame < 0 { + chev, key := "chevron-down", "search_panel.fold" + if s.Collapsed.Has(t.ID) { + chev, key = "chevron-right", "search_panel.unfold" + } + if iconAction(c, icons.Must(chev), fmt.Sprintf(msg(c, key), t.Name)).Clicked() && !disabled { + callFold(s, t.ID) + } + ui.Text(c, t.Name).FontWeight(600).SingleLine().Grow(1).MinWidth(0) + codeCaption(c, fmt.Sprintf(msg(c, "call_stack.frames"), len(t.Frames))).Shrink(0) + return + } + f := t.Frames[r.frame] + codeMono(c, f.Name).Grow(1).MinWidth(0).Margin(0, 0, 0, 20) + codeCaption(c, fmt.Sprintf("%s:%d", path.Base(f.File), f.Line)).Shrink(0) +} diff --git a/call_stack_test.go b/call_stack_test.go new file mode 100644 index 0000000..ff3610e --- /dev/null +++ b/call_stack_test.go @@ -0,0 +1,104 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func callStackSample() []DebugThread { + return []DebugThread{ + {ID: "t1", Name: "main", Frames: []StackFrame{ + {"f1", "court.Seal", "court/seal.go", 14}, + {"f2", "court.Decree", "court/decree.go", 88}, + {"f3", "main.main", "main.go", 9}, + }}, + {ID: "t2", Name: "herald worker", Frames: []StackFrame{{"f4", "herald.Run", "herald/run.go", 31}}}, + } +} + +type callProbe struct { + threads []DebugThread + s CallStackState + disabled bool + changed int +} + +func (p *callProbe) view(c *ui.Context) { + Use(c, Settings{}) + r := CallStack(c, p.threads, &p.s, CallStackOptions{Disabled: p.disabled}) + r.Element.Height(320) + if r.Changed() { + p.changed++ + } +} + +func TestCallStackChooseFrame(t *testing.T) { + p := &callProbe{threads: callStackSample(), s: CallStackState{Current: "f1"}} + tt := ui.NewTester(p.view, 460, 340) + if p.s.selected != 1 { + t.Fatalf("current frame row %d, want 1", p.s.selected) + } + if err := tt.Click("court.Decree"); err != nil { + t.Fatal(err) + } + if p.s.Current != "f2" || p.changed != 1 { + t.Fatalf("current %q changed %d", p.s.Current, p.changed) + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDown) + if p.s.Current != "f3" || p.s.selected != 4 { + t.Fatalf("keys: current %q row %d", p.s.Current, p.s.selected) + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDown) + if p.s.Current != "f4" { + t.Fatalf("keys did not pass the thread header: %q", p.s.Current) + } +} + +func TestCallStackFoldThread(t *testing.T) { + p := &callProbe{threads: callStackSample(), s: CallStackState{Current: "f4"}} + tt := ui.NewTester(p.view, 460, 340) + if err := tt.Click("Fold main"); err != nil { + t.Fatal(err) + } + if tt.HasText("court.Seal") || !tt.HasText("herald.Run") || p.s.Current != "f4" { + t.Fatalf("fold: %q current %q", tt.Texts(), p.s.Current) + } + if !tt.HasText("depth 3") { + t.Fatal("thread header lacks its count") + } +} + +func TestCallStackCallerSetsCurrent(t *testing.T) { + p := &callProbe{threads: callStackSample()} + tt := ui.NewTester(p.view, 460, 340) + p.s.Current = "f3" + tt.Frame() + if p.s.selected != 3 || p.changed != 0 { + t.Fatalf("row %d changed %d", p.s.selected, p.changed) + } +} + +func TestCallStackDisabledAndEmpty(t *testing.T) { + p := &callProbe{threads: callStackSample(), s: CallStackState{Current: "f1"}, disabled: true} + tt := ui.NewTester(p.view, 460, 340) + _ = tt.Click("court.Decree") + if p.s.Current != "f1" { + t.Fatal("disabled stack changed frame") + } + tt = ui.NewTester((&callProbe{}).view, 460, 340) + if !tt.HasText("Not paused") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestCallStackSnapshot(t *testing.T) { + snapshot(t, "call_stack", 420, 230, func(c *ui.Context) { + p := ui.Local(c.Root(), "snap", func() *callProbe { return &callProbe{threads: callStackSample(), s: CallStackState{Current: "f2"}} }) + ui.Column(c).Padding(12).Children(func() { + CallStack(c, (*p).threads, &(*p).s, CallStackOptions{}).Element.Height(206) + }) + }) +} diff --git a/code_shared.go b/code_shared.go new file mode 100644 index 0000000..9a99563 --- /dev/null +++ b/code_shared.go @@ -0,0 +1,176 @@ +package mujica + +import ( + "math" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// codeSize is the design size of code and terminal text. +const codeSize float32 = 13 + +// codeFont is the scaled monospace code font. +func codeFont(c *ui.Context) ui.Font { + return ui.Font{Family: theme.MonoFont, Size: FontSize(c, codeSize)} +} + +// codeMono is a single-line monospace text. +func codeMono(c *ui.Context, s string) *ui.Element { + return ui.Text(c, s).Font(theme.MonoFont).FontSize(FontSize(c, codeSize)).SingleLine() +} + +// codeCaption is muted caption text. +func codeCaption(c *ui.Context, s string) *ui.Element { + return ui.Text(c, s).FontSize(FontSize(c, theme.CaptionSize)).TextColor(Tokens(c).TextMuted).SingleLine() +} + +// codeTokenColor colors a syntax token kind. +func codeTokenColor(k theme.Tokens, kind internal.TokenKind) ui.Color { + switch kind { + case internal.TokKeyword: + return k.AccentText + case internal.TokString: + return k.Success + case internal.TokNumber: + return k.Warning + case internal.TokComment: + return k.TextMuted + case internal.TokType: + return k.Info + } + return k.Text +} + +// codeAnsiColor maps a terminal color onto the theme. +func codeAnsiColor(k theme.Tokens, a internal.AnsiColor) ui.Color { + switch a.Kind { + case internal.AnsiRGB: + return ui.RGB(a.R, a.G, a.B) + case internal.AnsiIndexed: + if a.Index < 16 { + base := [8]ui.Color{k.TextMuted, k.Danger, k.Success, k.Warning, k.Info, k.AccentText, k.Info.Mix(k.Success, 0.5), k.Text} + return base[a.Index%8] + } + if a.Index >= 232 { + v := uint8(8 + 10*int(a.Index-232)) + return ui.RGB(v, v, v) + } + i := int(a.Index) - 16 + step := func(n int) uint8 { + if n == 0 { + return 0 + } + return uint8(55 + 40*n) + } + return ui.RGB(step(i/36), step(i/6%6), step(i%6)) + } + return ui.Color{} +} + +// codeAnsiSpans turns ANSI text into themed spans. +func codeAnsiSpans(c *ui.Context, line string) []ui.Span { + k := Tokens(c) + parts, _ := internal.ParseAnsi(line, internal.AnsiStyle{}) + spans := make([]ui.Span, 0, len(parts)) + for _, p := range parts { + s := ui.Span{Text: p.Text, Color: codeAnsiColor(k, p.Style.FG), Underline: p.Style.Underline, Strikethrough: p.Style.Strike, Italic: p.Style.Italic} + if p.Style.Bold { + s.Weight = 700 + } + if bg := codeAnsiColor(k, p.Style.BG); bg.A > 0 { + s.Background = bg.Alpha(0.3) + } + spans = append(spans, s) + } + return spans +} + +// codeMatchSpans marks each query match in text. +func codeMatchSpans(c *ui.Context, text, query string) []ui.Span { + if query == "" { + return []ui.Span{{Text: text}} + } + k := Tokens(c) + lower, q := strings.ToLower(text), strings.ToLower(query) + var spans []ui.Span + for { + i := strings.Index(lower, q) + if i < 0 { + break + } + if i > 0 { + spans = append(spans, ui.Span{Text: text[:i]}) + } + spans = append(spans, ui.Span{Text: text[i : i+len(q)], Background: k.Selection, Underline: true, DecorationColor: k.AccentText, Weight: 600}) + text, lower = text[i+len(q):], lower[i+len(q):] + } + if text != "" { + spans = append(spans, ui.Span{Text: text}) + } + return spans +} + +// codePanel is a framed surface holding a code tool. +func codePanel(c *ui.Context) *ui.Element { + k := Tokens(c) + return ui.Column(c).MinHeight(0).Background(k.Surface).Border(theme.BorderWidth, k.Border).Radius(theme.ControlRadius).Clip() +} + +// codeHeader is a panel's top strip of tools. +func codeHeader(c *ui.Context, fn func()) *ui.Element { + k := Tokens(c) + u := Density(c).Unit() + return ui.Row(c).Shrink(0).MinHeight(theme.MinHitSize+2*u).Padding(u, u*2).Gap(u*2).AlignItems(ui.Center). + BorderWidth(0, 0, theme.BorderWidth, 0).BorderColor(k.Border).Children(fn) +} + +// codeSelectMark draws a chosen row's diamond. +func codeSelectMark(c *ui.Context, on bool) { + k := Tokens(c) + ui.Box(c).Size(8, 8).Shrink(0).Role(ui.RoleNone).Draw(func(p *ui.Painter, r ui.Rect) { + if on { + p.FillPath(internal.Diamond(internal.Snap(p, r.X+r.W/2), internal.Snap(p, r.Y+r.H/2), r.W), k.AccentText) + } + }) +} + +// codeRows builds a growing virtual list with marks. +func codeRows(c *ui.Context, s *ui.ListState, n int, row func(i int)) *ui.Element { + d := Density(c) + restore := dataSelectTheme(c, 0) + defer restore() + e := ui.List(c, s, n, func(i int) { + ui.Row(c).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*2).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + codeSelectMark(c, s.Selected != nil && *s.Selected == i) + row(i) + }) + }) + k := Tokens(c) + internal.Ring(e, k.Focus, theme.ControlRadius) + return e.Grow(1).MinHeight(d.ControlHeight() * 3) +} + +// codeBadge is a kind letter in a framed square. +func codeBadge(c *ui.Context, letter string, col ui.Color) { + ui.Box(c).Size(18, 18).Shrink(0).Center().Radius(theme.ControlRadius).Border(theme.BorderWidth, col). + Role(ui.RoleNone).Children(func() { + ui.Text(c, letter).Font(theme.MonoFont).FontSize(FontSize(c, 11)).FontWeight(700).TextColor(col) + }) +} + +// codeRule draws a pixel-aligned 1 DIP line. +func codeRule(p *ui.Painter, x0, x1, y float32, c ui.Color) { + s := float64(p.Scale()) + yy := float32((math.Floor(float64(y)*s) + 0.5) / s) + p.Line(x0, yy, x1, yy, 1, c) +} + +// codeTextWidth returns the width of s in the code font. +func codeTextWidth(c *ui.Context, s string) float32 { + w, _ := c.MeasureText(0, ui.Span{Text: s, Font: theme.MonoFont, Size: FontSize(c, codeSize)}) + return w +} diff --git a/code_viewer.go b/code_viewer.go new file mode 100644 index 0000000..cfa9001 --- /dev/null +++ b/code_viewer.go @@ -0,0 +1,253 @@ +package mujica + +import ( + "fmt" + "log/slog" + "runtime" + "slices" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// CodeViewerOptions configure a CodeViewer. +type CodeViewerOptions struct { + // Language picks the highlighting; empty is plain. + Language string + // Label names the view for assistive technology. + Label string + Disabled bool +} + +// CodeViewerState is a CodeViewer's current line, selection, folds and place. +type CodeViewerState struct { + // Selection holds the selected line indices. + Selection ui.Selection[int] + // Folded holds the first lines of folded blocks. + Folded ui.Selection[int] + rows ui.ListState + cursor int + shown []int + inBlock []bool + ends []int + data *string + n int + lang string + folds int + started bool +} + +// Line returns the current line index, or -1. +func (s *CodeViewerState) Line() int { + if s.cursor < 0 || s.cursor >= len(s.shown) { + return -1 + } + return s.shown[s.cursor] +} + +// Visible returns the first and last lines in view. +func (s *CodeViewerState) Visible() (first, last int) { + a, b := s.rows.Visible() + if len(s.shown) == 0 || a < 0 { + return 0, -1 + } + return s.shown[min(a, len(s.shown)-1)], s.shown[min(max(b, a), len(s.shown)-1)] +} + +// ScrollTo brings line to the top. +func (s *CodeViewerState) ScrollTo(line int) { + row, _ := slices.BinarySearch(s.shown, line) + s.rows.ScrollTo(row, ui.Start) +} + +// GoTo makes line current, unfolding and scrolling to it. +func (s *CodeViewerState) GoTo(line int) { + for start := range s.Folded.All() { + if start < line && line <= s.ends[start] { + s.Folded.Remove(start) + } + } + s.folds = -1 + s.Selection.Clear() + s.Selection.Add(line) + s.started, s.cursor = true, -2-line // resolved to a row once the rows are known +} + +// CodeViewer is a read-only, foldable, virtualized code view. +func CodeViewer(c *ui.Context, lines []string, s *CodeViewerState, opts CodeViewerOptions) ChoiceResult { + if s == nil { + panic("mujica: CodeViewer needs a state") + } + if !s.started { + s.started, s.cursor = true, -1 + } + codeViewerPrepare(lines, s, opts.Language) + k := Tokens(c) + d := Density(c) + var res ChoiceResult + res.Element = codePanel(c).Disabled(opts.Disabled) + res.Element.Children(func() { + if len(lines) == 0 { + codeCaption(c, msg(c, "code_viewer.empty")).Padding(d.Unit() * 4) + return + } + digits := len(fmt.Sprint(len(lines))) + gutter := codeTextWidth(c, strings.Repeat("9", digits)) + s.rows.Selected = &s.cursor + s.rows.Selection = &s.Selection + s.rows.Key = func(i int) any { return s.shown[i] } + s.rows.Label = func(i int) string { return fmt.Sprintf("%d %s", s.shown[i]+1, lines[s.shown[i]]) } + restore := dataSelectTheme(c, 0) + list := ui.List(c, &s.rows, len(s.shown), func(i int) { + li := s.shown[i] + ui.Row(c).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*2, 0, 0).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + codeSelectMark(c, i == s.cursor) + if s.ends[li] > li { + label := msg(c, "code_viewer.fold") + if s.Folded.Has(li) { + label = msg(c, "code_viewer.unfold") + } + chev := "chevron-down" + if s.Folded.Has(li) { + chev = "chevron-right" + } + if iconAction(c, icons.Must(chev), fmt.Sprintf(label, li+1)).Clicked() && !res.Element.IsDisabled() { + codeViewerToggle(s, li) + } + } else { + ui.Box(c).Size(theme.MinHitSize, theme.MinHitSize).Shrink(0) + } + codeMono(c, fmt.Sprint(li+1)).Width(gutter).TextAlign(ui.End).TextColor(k.TextMuted).Shrink(0) + codeViewerLine(c, k, opts.Language, lines[li], s.inBlock[li]) + }) + }) + restore() + list.Grow(1).MinHeight(d.ControlHeight() * 3).Label(opts.Label) + internal.Ring(list, k.Focus, theme.ControlRadius) + if list.Changed() { + res.changed = true + slog.Debug("mujica: code_viewer line", "line", s.Line()) + } + codeViewerKeys(c, list, lines, s) + }) + return res +} + +// codeViewerKeys copies the selection and folds with Left and Right. +func codeViewerKeys(c *ui.Context, list *ui.Element, lines []string, s *CodeViewerState) { + if list.IsDisabled() { + return + } + copyMods := ui.Cmd + if runtime.GOOS != "darwin" { + copyMods = ui.Ctrl + } + line := s.Line() + switch { + case list.Shortcut(copyMods, ui.KeyC): + picked := slices.Sorted(s.Selection.All()) + if len(picked) == 0 && line >= 0 { + picked = []int{line} + } + out := make([]string, len(picked)) + for i, l := range picked { + out[i] = lines[l] + } + c.WriteClipboard(strings.Join(out, "\n")) + slog.Debug("mujica: code_viewer copy", "lines", len(out)) + case list.Shortcut(0, ui.KeyLeft) && line >= 0 && s.ends[line] > line && !s.Folded.Has(line): + codeViewerToggle(s, line) + case list.Shortcut(0, ui.KeyRight) && line >= 0 && s.Folded.Has(line): + codeViewerToggle(s, line) + } +} + +func codeViewerToggle(s *CodeViewerState, line int) { + if s.Folded.Has(line) { + s.Folded.Remove(line) + } else { + s.Folded.Add(line) + } + s.folds = -1 + slog.Debug("mujica: code_viewer fold", "line", line, "folded", s.Folded.Has(line)) +} + +// codeViewerLine draws one line's syntax tokens. +func codeViewerLine(c *ui.Context, k theme.Tokens, lang, line string, inBlock bool) { + toks, _ := internal.Highlight(lang, line, inBlock) + spans := make([]ui.Span, len(toks)) + for i, t := range toks { + spans[i] = ui.Span{Text: t.Text, Color: codeTokenColor(k, t.Kind), Italic: t.Kind == internal.TokComment} + } + ui.RichText(c, spans...).Font(theme.MonoFont).FontSize(FontSize(c, codeSize)).SingleLine().Grow(1).MinWidth(0) +} + +// codeViewerPrepare rescans code and folds when they change. +func codeViewerPrepare(lines []string, s *CodeViewerState, lang string) { + var first *string + if len(lines) > 0 { + first = &lines[0] + } + if s.data != first || s.n != len(lines) || s.lang != lang { + s.data, s.n, s.lang, s.folds = first, len(lines), lang, -1 + s.inBlock = slices.Grow(s.inBlock[:0], len(lines))[:len(lines)] + in := false + for i, l := range lines { + s.inBlock[i] = in + _, in = internal.Highlight(lang, l, in) + } + s.ends = codeViewerFolds(lines, s.ends) + } + if s.folds == s.Folded.Len() { + return + } + s.folds = s.Folded.Len() + s.shown = s.shown[:0] + for i := 0; i < len(lines); i++ { + s.shown = append(s.shown, i) + if s.Folded.Has(i) { + i = s.ends[i] + } + } + if s.cursor <= -2 { + s.cursor = max(slices.Index(s.shown, -2-s.cursor), 0) + s.rows.ScrollIntoView(s.cursor) + } + s.cursor = min(s.cursor, len(s.shown)-1) +} + +// codeViewerFolds returns each line's indented block end. +func codeViewerFolds(lines []string, ends []int) []int { + ends = slices.Grow(ends[:0], len(lines))[:len(lines)] + indent := func(l string) int { + if strings.TrimSpace(l) == "" { + return -1 + } + return len(l) - len(strings.TrimLeft(l, " \t")) + } + type open struct{ line, indent int } + var stack []open + last := -1 + for i, l := range lines { + ends[i] = i + in := indent(l) + if in < 0 { + continue + } + for len(stack) > 0 && stack[len(stack)-1].indent >= in { + top := stack[len(stack)-1] + stack = stack[:len(stack)-1] + ends[top.line] = last + } + stack = append(stack, open{i, in}) + last = i + } + for _, o := range stack { + ends[o.line] = last + } + return ends +} diff --git a/code_viewer_test.go b/code_viewer_test.go new file mode 100644 index 0000000..8e493c2 --- /dev/null +++ b/code_viewer_test.go @@ -0,0 +1,151 @@ +package mujica + +import ( + "fmt" + "strings" + "testing" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" +) + +var codeViewerSample = []string{ + "package court", + "", + "// Seal stamps a decree.", + "func Seal(d string) int {", + "\tif d == \"\" {", + "\t\treturn 0", + "\t}", + "\treturn 42", + "}", +} + +func codeViewerTester(lines []string, s *CodeViewerState, disabled bool) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + CodeViewer(c, lines, s, CodeViewerOptions{Language: "go", Label: "Source", Disabled: disabled}).Element.Height(400) + }, 520, 420) +} + +func TestCodeViewerFoldRanges(t *testing.T) { + ends := codeViewerFolds(codeViewerSample, nil) + if ends[3] != 7 || ends[4] != 5 || ends[0] != 0 || ends[8] != 8 { + t.Fatalf("fold ends %v", ends) + } +} + +func TestCodeViewerFoldsAndNumbers(t *testing.T) { + s := &CodeViewerState{} + tt := codeViewerTester(codeViewerSample, s, false) + if !tt.HasText("9") || !tt.HasText("\treturn 42") { + t.Fatalf("texts %q", tt.Texts()) + } + if err := tt.Click("Fold line 4"); err != nil { + t.Fatal(err) + } + if tt.HasText("\treturn 42") || !tt.HasText("}") || len(s.shown) != 5 { + t.Fatalf("fold kept %d lines: %q", len(s.shown), tt.Texts()) + } + if err := tt.Click("Unfold line 4"); err != nil { + t.Fatal(err) + } + if len(s.shown) != 9 { + t.Fatalf("unfold shows %d lines", len(s.shown)) + } +} + +func TestCodeViewerKeysCurrentLineAndCopy(t *testing.T) { + s := &CodeViewerState{} + tt := codeViewerTester(codeViewerSample, s, false) + for !tt.Focused("Source") { + tt.Key(0, ui.KeyTab) + } + tt.Key(0, ui.KeyDown) + tt.Key(ui.Shift, ui.KeyDown) + tt.Key(ui.Shift, ui.KeyDown) + tt.Key(ui.Cmd, ui.KeyC) + if want := "package court\n\n// Seal stamps a decree."; tt.Clipboard() != want { + t.Fatalf("copied %q", tt.Clipboard()) + } + tt.Key(0, ui.KeyDown) + if s.Line() != 3 { + t.Fatalf("current line %d, want 3", s.Line()) + } + tt.Key(0, ui.KeyLeft) + if !s.Folded.Has(3) || len(s.shown) != 5 { + t.Fatal("Left did not fold the block") + } + tt.Key(0, ui.KeyRight) + if s.Folded.Has(3) { + t.Fatal("Right did not unfold the block") + } +} + +func TestCodeViewerGoToOpensFold(t *testing.T) { + s := &CodeViewerState{} + tt := codeViewerTester(codeViewerSample, s, false) + _ = tt.Click("Fold line 4") + s.GoTo(7) + tt.Frame() + if s.Line() != 7 || s.Folded.Has(3) { + t.Fatalf("GoTo gave line %d folded %v", s.Line(), s.Folded.Has(3)) + } +} + +func TestCodeViewerHighlightColors(t *testing.T) { + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{Mode: Light}) + k := Tokens(c) + kw, str := codeTokenColor(k, internal.TokKeyword), codeTokenColor(k, internal.TokString) + if kw != k.AccentText || str != k.Success { + t.Errorf("keyword %v string %v", kw, str) + } + }, 10, 10) +} + +func TestCodeViewerHundredThousandLines(t *testing.T) { + lines := make([]string, 100_000) + for i := range lines { + lines[i] = fmt.Sprintf("x%d := %d // line", i, i) + } + s := &CodeViewerState{} + tt := codeViewerTester(lines, s, false) + rows := 0 + for _, t := range tt.Texts() { + if strings.HasPrefix(t, "x") { + rows++ + } + } + if rows == 0 || rows > 40 { + t.Fatalf("built %d rows of 100000", rows) + } + s.GoTo(99_998) + tt.Frame() + if !tt.HasText("x99998 := 99998 // line") { + t.Fatal("GoTo did not scroll to the end") + } +} + +func TestCodeViewerDisabledFold(t *testing.T) { + s := &CodeViewerState{} + tt := codeViewerTester(codeViewerSample, s, true) + _ = tt.Click("Fold line 4") + if s.Folded.Len() != 0 { + t.Fatal("disabled viewer folded") + } +} + +func TestCodeViewerSnapshot(t *testing.T) { + snapshot(t, "code_viewer", 480, 300, func(c *ui.Context) { + s := ui.Local(c.Root(), "snap", func() *CodeViewerState { + s := &CodeViewerState{} + s.GoTo(5) + return s + }) + ui.Column(c).Padding(12).Children(func() { + CodeViewer(c, codeViewerSample, *s, CodeViewerOptions{Language: "go"}).Element.Height(276) + }) + }) +} diff --git a/command_history.go b/command_history.go new file mode 100644 index 0000000..d469546 --- /dev/null +++ b/command_history.go @@ -0,0 +1,119 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" +) + +// HistoryEntry is one command a shell ran. +type HistoryEntry struct { + Command string + Time time.Time + ExitCode int +} + +// CommandHistoryState is the filter and place of a CommandHistory. +type CommandHistoryState struct { + Query string + rows ui.ListState + selected int + shown []int + query string + n int + ran bool +} + +// CommandHistoryOptions configure a CommandHistory. +type CommandHistoryOptions struct { + Disabled bool +} + +// CommandHistoryResult carries the entry to replay. +type CommandHistoryResult struct { + Element *ui.Element + // Replayed is the entry to run again, or nil. + Replayed *HistoryEntry +} + +// CommandHistory lists commands newest first with search and replay. +func CommandHistory(c *ui.Context, entries []HistoryEntry, s *CommandHistoryState, opts CommandHistoryOptions) CommandHistoryResult { + if s == nil { + panic("mujica: CommandHistory needs a state") + } + var res CommandHistoryResult + res.Element = codePanel(c).Disabled(opts.Disabled) + disabled := res.Element.IsDisabled() + replay := func(i int) { + if disabled { + return + } + e := entries[i] + res.Replayed = &e + slog.Debug("mujica: command_history replay", "index", i) + } + res.Element.Children(func() { + codeHeader(c, func() { + SearchInput(c, &s.Query, SearchInputOptions{Disabled: opts.Disabled, Placeholder: msg(c, "command_history.search")}).Element.Grow(1) + }) + commandHistoryFilter(entries, s) + if len(s.shown) == 0 { + text := msg(c, "command_history.empty") + if len(entries) > 0 { + text = msg(c, "command_history.none") + } + codeCaption(c, text).Padding(Density(c).Unit() * 4) + return + } + s.rows.Selected = &s.selected + s.rows.Key = func(i int) any { return s.shown[i] } + s.rows.Label = func(i int) string { return entries[s.shown[i]].Command } + list := codeRows(c, &s.rows, len(s.shown), func(i int) { + e := entries[s.shown[i]] + commandHistoryRow(c, e) + if iconAction(c, icons.Must("refresh-cw"), fmt.Sprintf(msg(c, "command_history.replay"), e.Command)).Clicked() { + replay(s.shown[i]) + } + }) + if list.Submitted() && s.selected >= 0 && s.selected < len(s.shown) { + replay(s.shown[s.selected]) + } + }) + return res +} + +// commandHistoryFilter refilters when entries or query change. +func commandHistoryFilter(entries []HistoryEntry, s *CommandHistoryState) { + if s.ran && s.n == len(entries) && s.query == s.Query { + return + } + s.ran, s.n, s.query = true, len(entries), s.Query + s.shown = s.shown[:0] + q := strings.ToLower(strings.TrimSpace(s.Query)) + for i := len(entries) - 1; i >= 0; i-- { + if q == "" || strings.Contains(strings.ToLower(entries[i].Command), q) { + s.shown = append(s.shown, i) + } + } + s.selected = min(s.selected, len(s.shown)-1) +} + +func commandHistoryRow(c *ui.Context, e HistoryEntry) { + k := Tokens(c) + ui.Column(c).Grow(1).MinWidth(0).Children(func() { + codeMono(c, e.Command) + ui.Row(c).Gap(Density(c).Unit() * 2).Children(func() { + if !e.Time.IsZero() { + codeCaption(c, e.Time.Format("15:04:05")) + } + if e.ExitCode != 0 { + codeCaption(c, fmt.Sprintf(msg(c, "command_history.exit"), e.ExitCode)).TextColor(k.Danger) + } + }) + }) +} diff --git a/command_history_test.go b/command_history_test.go new file mode 100644 index 0000000..1f5f599 --- /dev/null +++ b/command_history_test.go @@ -0,0 +1,117 @@ +package mujica + +import ( + "fmt" + "strings" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func commandHistorySample() []HistoryEntry { + at := time.Date(2026, 10, 5, 9, 0, 0, 0, time.UTC) + return []HistoryEntry{ + {Command: "git status", Time: at}, + {Command: "go test ./...", Time: at.Add(time.Minute), ExitCode: 1}, + {Command: "go build", Time: at.Add(2 * time.Minute)}, + } +} + +func commandHistoryTester(entries []HistoryEntry, s *CommandHistoryState, disabled bool, got *[]string) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := CommandHistory(c, entries, s, CommandHistoryOptions{Disabled: disabled}) + r.Element.Grow(1) + if r.Replayed != nil { + *got = append(*got, r.Replayed.Command) + } + }, 420, 320) +} + +func TestCommandHistoryNewestFirstAndReplay(t *testing.T) { + s := &CommandHistoryState{} + var got []string + tt := commandHistoryTester(commandHistorySample(), s, false, &got) + first, _ := tt.Find("go build") + last, _ := tt.Find("git status") + if first.Y >= last.Y { + t.Fatal("newest command is not on top") + } + if !tt.HasText("exit 1") { + t.Fatal("failed command shows no exit code") + } + if err := tt.Click("Run git status again"); err != nil { + t.Fatal(err) + } + tt.ClickAt(first.X, first.Y+2) + tt.ClickAt(first.X, first.Y+2) + if len(got) != 2 || got[0] != "git status" || got[1] != "go build" { + t.Fatalf("replayed %q", got) + } +} + +func TestCommandHistorySearchAndKeys(t *testing.T) { + s := &CommandHistoryState{} + var got []string + tt := commandHistoryTester(commandHistorySample(), s, false, &got) + tt.Key(0, ui.KeyTab) + tt.Type("go ") + if tt.HasText("git status") || !tt.HasText("go build") || !tt.HasText("go test ./...") { + t.Fatalf("filter shows %q", tt.Texts()) + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if len(got) != 1 || got[0] != "go test ./..." { + t.Fatalf("keyboard replay %q", got) + } + s.Query = "zzz" + tt.Frame() + if !tt.HasText("No matching commands") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestCommandHistoryDisabledAndEmpty(t *testing.T) { + var got []string + tt := commandHistoryTester(commandHistorySample(), &CommandHistoryState{}, true, &got) + _ = tt.Click("Run git status again") + if len(got) != 0 { + t.Fatalf("disabled replayed %q", got) + } + tt = commandHistoryTester(nil, &CommandHistoryState{}, false, &got) + if !tt.HasText("No commands yet") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestCommandHistoryLargeIsVirtual(t *testing.T) { + entries := make([]HistoryEntry, 100_000) + for i := range entries { + entries[i].Command = fmt.Sprintf("echo %d", i) + } + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + CommandHistory(c, entries, &CommandHistoryState{}, CommandHistoryOptions{}) + }, 420, 320) + rows := 0 + for _, s := range tt.Texts() { + if strings.HasPrefix(s, "echo ") { + rows++ + } + } + if !tt.HasText("echo 99999") || rows == 0 || rows > 60 { + t.Fatalf("built %d rows of 100000", rows) + } +} + +func TestCommandHistorySnapshot(t *testing.T) { + snapshot(t, "command_history", 420, 240, func(c *ui.Context) { + s := ui.Local(c.Root(), "snap", func() *CommandHistoryState { return &CommandHistoryState{} }) + ui.Column(c).Padding(12).Height(240).Children(func() { + CommandHistory(c, commandHistorySample(), *s, CommandHistoryOptions{}).Element.Grow(1) + }) + }) +} diff --git a/completion_menu.go b/completion_menu.go new file mode 100644 index 0000000..60c6ab9 --- /dev/null +++ b/completion_menu.go @@ -0,0 +1,129 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// Completion is one candidate of a CompletionMenu. +type Completion struct { + Label string + Kind SymbolKind + Detail string + // Doc describes the chosen candidate below the list. + Doc string +} + +// CompletionMenuState is the highlighted candidate and place of a CompletionMenu. +type CompletionMenuState struct { + Selected int + rows ui.ListState + pending ui.Key +} + +// CompletionMenuOptions configure a CompletionMenu. +type CompletionMenuOptions struct { + Disabled bool +} + +// CompletionMenuResult carries the accepted candidate. +type CompletionMenuResult struct { + Element *ui.Element + Accepted *Completion +} + +// completionRows is how many candidates show before the list scrolls. +const completionRows = 8 + +// CompletionMenu shows candidates under the editor anchor. +func CompletionMenu(c *ui.Context, anchor *ui.Element, open *bool, items []Completion, s *CompletionMenuState, opts CompletionMenuOptions) CompletionMenuResult { + if anchor == nil || open == nil || s == nil { + panic("mujica: CompletionMenu needs an anchor, open and a state") + } + for _, it := range items { + if it.Kind < SymbolFunction || it.Kind > SymbolModule { + panic("mujica: Completion kind out of range") + } + } + var res CompletionMenuResult + if opts.Disabled || anchor.IsDisabled() || len(items) == 0 { + *open = false + } + if !*open { + return res + } + s.Selected = max(0, min(s.Selected, len(items)-1)) + accept := func(i int) { + it := items[i] + res.Accepted = &it + *open = false + slog.Debug("mujica: completion_menu accept", "index", i) + } + move := func(d int) { + s.Selected = (s.Selected + d + len(items)) % len(items) + s.rows.ScrollIntoView(s.Selected) + } + // Take the menu keys before the editor does. + anchor.HandleInput(func(ev ui.InputEvent) bool { + if ev.Kind != ui.InputKeyDown || ev.Mods != 0 || !*open || anchor.IsDisabled() { + return false + } + switch ev.Key { + case ui.KeyDown, ui.KeyUp, ui.KeyTab, ui.KeyEnter, ui.KeyEscape: + s.pending = ev.Key + return true + } + return false + }) + key := s.pending + s.pending = 0 + switch key { + case ui.KeyDown: + move(1) + case ui.KeyUp: + move(-1) + case ui.KeyTab, ui.KeyEnter: + accept(s.Selected) + return res + case ui.KeyEscape: + *open = false + slog.Debug("mujica: completion_menu close") + return res + } + k := Tokens(c) + d := Density(c) + b := anchor.Bounds() + overlayLayer(c, open) + res.Element = ui.PopoverBase(c, anchor, open, func(panel *ui.Element) { + overlayStyle(c, panel, overlayAnchored(c, panel, b)) + panel.Margin(4, 0, 0, 0).Padding(d.Unit()).Width(popoverWide(c, 360)).MaxHeight(popoverRoom(c, b)). + Label(msg(c, "completion_menu.label")).Role(ui.RoleList) + chosen := s.Selected + s.rows.Selected = &chosen + s.rows.Label = func(i int) string { return items[i].Label } + restore := dataSelectTheme(c, 0) + list := ui.List(c, &s.rows, len(items), func(i int) { + it := items[i] + ui.Row(c).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*2).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + codeSelectMark(c, i == s.Selected) + codeBadge(c, symbolBadges[it.Kind], k.AccentText) + codeMono(c, it.Label).Grow(1).MinWidth(0) + if it.Detail != "" { + codeCaption(c, it.Detail).MinWidth(0).Shrink(1) + } + }) + }).MaxHeight(d.ControlHeight() * completionRows).Shrink(1) + restore() + if list.Changed() && chosen >= 0 { + accept(chosen) + } + if doc := items[s.Selected].Doc; doc != "" { + ui.Text(c, doc).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Padding(d.Unit()*2). + BorderWidth(theme.BorderWidth, 0, 0, 0).BorderColor(k.Border).Shrink(0) + } + }) + return res +} diff --git a/completion_menu_test.go b/completion_menu_test.go new file mode 100644 index 0000000..1ebe98a --- /dev/null +++ b/completion_menu_test.go @@ -0,0 +1,103 @@ +package mujica + +import ( + "strings" + "testing" + + "github.com/egoist/mygo/ui" +) + +func completionSample() []Completion { + return []Completion{ + {Label: "Seal", Kind: SymbolMethod, Detail: "func(d Decree) error", Doc: "Seal stamps a decree."}, + {Label: "Search", Kind: SymbolFunction, Detail: "func(q string) []Decree"}, + {Label: "Season", Kind: SymbolConstant, Detail: "= 4"}, + } +} + +type completionProbe struct { + text string + open bool + s CompletionMenuState + disabled bool + accepted []string +} + +func (p *completionProbe) view(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(16).Children(func() { + in := TextInput(c, &p.text, TextInputOptions{Label: "Code"}) + if in.Changed() { + p.open = strings.HasPrefix(strings.ToLower(p.text), "se") + } + r := CompletionMenu(c, in.Input, &p.open, completionSample(), &p.s, CompletionMenuOptions{Disabled: p.disabled}) + if r.Accepted != nil { + p.accepted = append(p.accepted, r.Accepted.Label) + p.text = r.Accepted.Label + } + }) +} + +func TestCompletionMenuKeys(t *testing.T) { + p := &completionProbe{} + tt := ui.NewTester(p.view, 480, 400) + tt.Key(0, ui.KeyTab) + tt.Type("se") + if !p.open || !tt.HasText("Seal") || !tt.HasText("Seal stamps a decree.") { + t.Fatalf("menu did not open: %q", tt.Texts()) + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDown) + if p.s.Selected != 0 { + t.Fatalf("Down wrapped to %d, want 0", p.s.Selected) + } + tt.Key(0, ui.KeyUp) + tt.Key(0, ui.KeyTab) + if len(p.accepted) != 1 || p.accepted[0] != "Season" || p.open { + t.Fatalf("accepted %v open %v", p.accepted, p.open) + } + if !tt.Focused("Code") { + t.Fatal("accepting moved the focus away from the editor") + } +} + +func TestCompletionMenuEnterClickEscape(t *testing.T) { + p := &completionProbe{} + tt := ui.NewTester(p.view, 480, 400) + tt.Key(0, ui.KeyTab) + tt.Type("se") + tt.Key(0, ui.KeyEnter) + if len(p.accepted) != 1 || p.accepted[0] != "Seal" { + t.Fatalf("Enter accepted %v", p.accepted) + } + p.open = true + tt.Frame() + if err := tt.Click("Search"); err != nil { + t.Fatal(err) + } + if len(p.accepted) != 2 || p.accepted[1] != "Search" { + t.Fatalf("click accepted %v", p.accepted) + } + p.open = true + tt.Frame() + tt.Key(0, ui.KeyEscape) + if p.open || len(p.accepted) != 2 { + t.Fatalf("Escape: open %v accepted %v", p.open, p.accepted) + } +} + +func TestCompletionMenuDisabledClosed(t *testing.T) { + p := &completionProbe{open: true, disabled: true} + tt := ui.NewTester(p.view, 480, 400) + if p.open || tt.HasText("Search") { + t.Fatal("disabled menu shows") + } +} + +func TestCompletionMenuSnapshot(t *testing.T) { + snapshot(t, "completion_menu", 420, 260, func(c *ui.Context) { + p := ui.Local(c.Root(), "snap", func() *completionProbe { return &completionProbe{text: "se", open: true} }) + (*p).view(c) + }) +} diff --git a/debug_toolbar.go b/debug_toolbar.go new file mode 100644 index 0000000..01d88fd --- /dev/null +++ b/debug_toolbar.go @@ -0,0 +1,141 @@ +package mujica + +import ( + "fmt" + "log/slog" + "runtime" + + "github.com/egoist/mygo/ui" +) + +// DebugState is where a debug session is. +type DebugState int + +const ( + DebugStopped DebugState = iota + DebugRunning + DebugPaused +) + +// DebugAction is what the user asked the debugger to do. +type DebugAction int + +const ( + DebugNone DebugAction = iota + // DebugContinue resumes a paused session or starts a stopped one. + DebugContinue + DebugPause + DebugStepOver + DebugStepInto + DebugStepOut + DebugRestart + DebugStop +) + +// DebugToolbarOptions configure a DebugToolbar. +type DebugToolbarOptions struct { + Disabled bool +} + +// DebugToolbarResult carries the requested action. +type DebugToolbarResult struct { + Element *ui.Element + Action DebugAction +} + +// debugIcon draws a toolbar glyph in a 24-unit box. +func debugIcon(body string) *ui.SVG { + return ui.MustParseSVG([]byte(`` + body + ``)) +} + +var debugIcons = map[DebugAction]*ui.SVG{ + DebugContinue: debugIcon(``), + DebugPause: debugIcon(``), + DebugStepOver: debugIcon(``), + DebugStepInto: debugIcon(``), + DebugStepOut: debugIcon(``), + DebugRestart: debugIcon(``), + DebugStop: debugIcon(``), +} + +// debugShortcut is an action's key, as in common IDEs. +type debugShortcut struct { + mods ui.Modifiers + key ui.Key + name string +} + +func debugShortcuts() map[DebugAction]debugShortcut { + cmd := "Ctrl" + if runtime.GOOS == "darwin" { + cmd = "⌘" + } + return map[DebugAction]debugShortcut{ + DebugContinue: {0, ui.KeyF5, "F5"}, + DebugPause: {0, ui.KeyF6, "F6"}, + DebugStepOver: {0, ui.KeyF10, "F10"}, + DebugStepInto: {0, ui.KeyF11, "F11"}, + DebugStepOut: {ui.Shift, ui.KeyF11, "Shift+F11"}, + DebugRestart: {ui.Cmd | ui.Shift, ui.KeyF5, cmd + "+Shift+F5"}, + DebugStop: {ui.Shift, ui.KeyF5, "Shift+F5"}, + } +} + +// DebugEnabled reports whether action applies in state. +func DebugEnabled(state DebugState, a DebugAction) bool { + switch a { + case DebugContinue: + return state != DebugRunning + case DebugPause: + return state == DebugRunning + case DebugStepOver, DebugStepInto, DebugStepOut: + return state == DebugPaused + case DebugRestart, DebugStop: + return state != DebugStopped + } + return false +} + +// DebugToolbar shows debugger actions enabled by state. +func DebugToolbar(c *ui.Context, state DebugState, opts DebugToolbarOptions) DebugToolbarResult { + if state < DebugStopped || state > DebugPaused { + panic("mujica: DebugState out of range") + } + keys := debugShortcuts() + var res DebugToolbarResult + res.Element = Toolbar(c, ToolbarOptions{Label: msg(c, "debug_toolbar.label")}, func() { + first := DebugContinue + if state == DebugRunning { + first = DebugPause + } + for _, a := range []DebugAction{first, DebugStepOver, DebugStepInto, DebugStepOut, DebugRestart, DebugStop} { + name := msg(c, debugKeys[a]) + if a == DebugContinue && state == DebugStopped { + name = msg(c, "debug_toolbar.start") + } + on := DebugEnabled(state, a) && !opts.Disabled + b := ToolbarButton(c, name, ToolbarButtonOptions{Icon: debugIcons[a], Disabled: !on}) + b.Tooltip(fmt.Sprintf("%s (%s)", name, keys[a].name)) + if b.Clicked() && on && !b.IsDisabled() { + res.Action = a + } + } + }).Disabled(opts.Disabled) + if res.Action == DebugNone && !res.Element.IsDisabled() { + for _, a := range []DebugAction{DebugContinue, DebugPause, DebugStepOver, DebugStepInto, DebugStepOut, DebugRestart, DebugStop} { + if k := keys[a]; DebugEnabled(state, a) && c.Shortcut(k.mods, k.key) { + res.Action = a + break + } + } + } + if res.Action != DebugNone { + slog.Debug("mujica: debug_toolbar action", "action", res.Action, "state", state) + } + return res +} + +var debugKeys = map[DebugAction]string{ + DebugContinue: "debug_toolbar.continue", DebugPause: "debug_toolbar.pause", DebugStepOver: "debug_toolbar.stepOver", + DebugStepInto: "debug_toolbar.stepInto", DebugStepOut: "debug_toolbar.stepOut", DebugRestart: "debug_toolbar.restart", DebugStop: "debug_toolbar.stop", +} diff --git a/debug_toolbar_test.go b/debug_toolbar_test.go new file mode 100644 index 0000000..be2afe1 --- /dev/null +++ b/debug_toolbar_test.go @@ -0,0 +1,113 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func debugTester(state *DebugState, disabled bool, got *[]DebugAction) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if a := DebugToolbar(c, *state, DebugToolbarOptions{Disabled: disabled}).Action; a != DebugNone { + *got = append(*got, a) + } + }, 480, 120) +} + +func TestDebugEnabledRules(t *testing.T) { + cases := []struct { + state DebugState + on []DebugAction + }{ + {DebugStopped, []DebugAction{DebugContinue}}, + {DebugRunning, []DebugAction{DebugPause, DebugRestart, DebugStop}}, + {DebugPaused, []DebugAction{DebugContinue, DebugStepOver, DebugStepInto, DebugStepOut, DebugRestart, DebugStop}}, + } + for _, tc := range cases { + n := 0 + for a := DebugContinue; a <= DebugStop; a++ { + if DebugEnabled(tc.state, a) { + n++ + } + } + if n != len(tc.on) { + t.Fatalf("state %d enables %d actions, want %d", tc.state, n, len(tc.on)) + } + for _, a := range tc.on { + if !DebugEnabled(tc.state, a) { + t.Fatalf("state %d disables %d", tc.state, a) + } + } + } +} + +func TestDebugToolbarClicksFollowState(t *testing.T) { + state := DebugPaused + var got []DebugAction + tt := debugTester(&state, false, &got) + for _, name := range []string{"Step over", "Step into", "Step out", "Continue"} { + if err := tt.Click(name); err != nil { + t.Fatal(err) + } + } + want := []DebugAction{DebugStepOver, DebugStepInto, DebugStepOut, DebugContinue} + if len(got) != 4 || got[0] != want[0] || got[3] != want[3] { + t.Fatalf("actions %v", got) + } + state = DebugRunning + tt.Frame() + _ = tt.Click("Step over") + if err := tt.Click("Pause"); err != nil { + t.Fatal(err) + } + if len(got) != 5 || got[4] != DebugPause { + t.Fatalf("running: actions %v", got) + } + state = DebugStopped + tt.Frame() + if _, ok := tt.Find("Start"); !ok { + t.Fatal("stopped toolbar does not offer Start") + } +} + +func TestDebugToolbarShortcuts(t *testing.T) { + state := DebugPaused + var got []DebugAction + tt := debugTester(&state, false, &got) + tt.Key(0, ui.KeyF10) + tt.Key(ui.Shift, ui.KeyF11) + tt.Key(ui.Shift, ui.KeyF5) + state = DebugStopped + tt.Frame() + tt.Key(0, ui.KeyF10) + tt.Key(0, ui.KeyF5) + want := []DebugAction{DebugStepOver, DebugStepOut, DebugStop, DebugContinue} + if len(got) != len(want) { + t.Fatalf("actions %v, want %v", got, want) + } + for i := range want { + if got[i] != want[i] { + t.Fatalf("actions %v, want %v", got, want) + } + } +} + +func TestDebugToolbarDisabled(t *testing.T) { + state := DebugPaused + var got []DebugAction + tt := debugTester(&state, true, &got) + _ = tt.Click("Continue") + tt.Key(0, ui.KeyF10) + if len(got) != 0 { + t.Fatalf("disabled toolbar acted: %v", got) + } +} + +func TestDebugToolbarSnapshot(t *testing.T) { + snapshot(t, "debug_toolbar", 340, 70, func(c *ui.Context) { + ui.Row(c).Padding(12).Children(func() { + DebugToolbar(c, DebugPaused, DebugToolbarOptions{}) + }) + }) +} diff --git a/docs/components/321-terminal.md b/docs/components/321-terminal.md new file mode 100644 index 0000000..9c06f2c --- /dev/null +++ b/docs/components/321-terminal.md @@ -0,0 +1,52 @@ +# 321 Terminal · 终端 + +## 用途 + +显示终端网格:调用方把 PTY 输出写入 `TerminalState.Write`,组件解析 ANSI 样式(`internal.ParseAnsi`)、光标移动与清屏,保留滚动缓冲,支持鼠标选择复制,并把键盘输入编码后交给调用方写回 PTY。PTY 本身由调用方提供。 + +## 最小示例 + +```go +var term mujica.TerminalState +term.Write("\x1b[1m~/court\x1b[0m $ ls\r\n\x1b[34mdecrees\x1b[0m ledger.txt\r\n$ ") +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Terminal(c, &term, mujica.TerminalOptions{ + Input: func(data string) { fmt.Printf("to pty: %q\n", data) }, + Resized: func(cols, rows int) { fmt.Println("pty size", cols, rows) }, + }).Size(380, 200) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func Terminal(c *ui.Context, s *TerminalState, opts TerminalOptions) *ui.Element`。`TerminalState` 零值是 80×24 空屏,由调用方持有;`Write(data)` 写入输出(须在界面线程,例如经 `Window.Update`),`Resize(cols, rows)`、`Lines()`、`LineText(i)`、`Select(a, b)`、`Selection()`、`ScrollBack(n)`、`Offset()`、`Cursor()`、`Size()` 供程序读取与控制。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Input` | `func(data string)` | nil | 用户输入编码后的字节:文字原样,Enter 为 `\r`,退格 `\x7f`,方向键 `ESC [ A–D`,Ctrl+字母为控制码。 | +| `Resized` | `func(cols, rows int)` | nil | 网格尺寸随元素大小变化时回调,用于同步 PTY 窗口大小。 | +| `Scrollback` | `int` | 1000 | 滚动缓冲最多保留的行数;负数 panic。 | +| `Label` | `string` | 内置“终端” | 无障碍名称。 | +| `Disabled` | `bool` | false | 不接收任何输入。 | + +## 状态 + +默认(Surface 底、细边框)、聚焦(外侧 2 DIP 焦点环,光标为 AccentText 实心块并反白字符)、未聚焦(光标只描边)、选择(Selection 背景)、回看滚动缓冲(隐藏光标)、输入法组合(光标处显示带下划线的组合文字)、禁用。 + +## 事件 + +`Input`:每次按键、输入文字或粘贴;`Resized`:网格尺寸变化。复制写入系统剪贴板。 + +## 键盘操作 + +- 焦点在终端时,文字、Enter、Backspace、Tab、Shift+Tab、Escape、方向键、Home/End、Delete、PageUp/PageDown 与 Ctrl+字母都发送给 PTY。 +- 复制:macOS 上 Cmd+C,其他平台 Ctrl+Shift+C(复制选中文字);粘贴:Cmd+V / Ctrl+Shift+V。 +- Shift+PageUp / Shift+PageDown:翻看滚动缓冲;滚轮同样可用;任意输入回到底部。 + +## 限制 + +- 状态机覆盖常用序列:SGR 样式、CUU/CUD/CUF/CUB、CHA、CUP、ED(0/1/2/3)、EL、CR/LF/BS/TAB 与 OSC(忽略)。其余 CSI 序列只记录 Debug 日志后忽略;不支持备用屏幕、滚动区域、鼠标上报与宽字符占两格。 +- 需要完整终端仿真时请使用 MyGo 的 `plugins/terminal`(基于 libghostty-vt)。 +- 字形用 `ui.Shape` 逐格排布并按行缓存,等宽字体由系统回退决定。 diff --git a/docs/components/322-terminal-tabs.md b/docs/components/322-terminal-tabs.md new file mode 100644 index 0000000..47e9d2d --- /dev/null +++ b/docs/components/322-terminal-tabs.md @@ -0,0 +1,52 @@ +# 322 TerminalTabs · 终端标签 + +## 用途 + +管理多个终端的标签:切换、重命名、关闭;仍有进程运行(`Busy`)的终端关闭前弹出确认。 + +## 最小示例 + +```go +tabs := []mujica.TerminalTab{{ID: "a", Title: "zsh"}, {ID: "b", Title: "build", Busy: true}} +active := "a" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.TerminalTabs(c, &tabs, &active, mujica.TerminalTabsOptions{}, func(id string) { + ui.Text(c, "terminal "+id) + }) + if r.Closed != "" { + fmt.Println("close pty", r.Closed) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func TerminalTabs(c *ui.Context, tabs *[]TerminalTab, active *string, opts TerminalTabsOptions, content func(id string)) TerminalTabsResult`。`*tabs` 与 `*active` 由调用方持有,组件直接修改:重命名改 `Title`,关闭删除元素并把 `active` 移到相邻标签。`active` 不是任何标签 ID 时 panic。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `TerminalTab.ID` | `string` | 必填 | 稳定标识,也是事件值。 | +| `TerminalTab.Title` | `string` | 必填 | 标签文字。 | +| `TerminalTab.Busy` | `bool` | false | 进程仍在运行:显示小圆点并在关闭前确认。 | +| `Disabled` | `bool` | false | 不响应切换、重命名与关闭。 | +| `content` | `func(id string)` | 必填 | 构建当前标签的内容。 | + +## 状态 + +当前标签(Selection 背景、粗体与底部 AccentText 线)、悬停、键盘焦点环、正在运行(圆点与无障碍描述“进程运行中”)、重命名输入框、关闭确认对话框、无标签时的空状态、禁用。 + +## 事件 + +`Changed`:当前标签变化;`Renamed`:被重命名的标签 ID;`Closed`:被关闭的标签 ID(调用方应关闭对应 PTY)。 + +## 键盘操作 + +- ←/→、Home/End:在标签间移动并切换。 +- F2 或双击:重命名;Enter 确认,Escape 取消。 +- Delete:关闭焦点所在标签;运行中的标签先确认,确认框默认聚焦“取消”。 + +## 限制 + +- 不提供新建按钮与拖动排序;新建由调用方向 `*tabs` 追加。 diff --git a/docs/components/323-terminal-search.md b/docs/components/323-terminal-search.md new file mode 100644 index 0000000..36c840b --- /dev/null +++ b/docs/components/323-terminal-search.md @@ -0,0 +1,48 @@ +# 323 TerminalSearch · 终端搜索 + +## 用途 + +在终端的滚动缓冲与屏幕中查找文字,显示匹配数,上下跳转并把当前匹配滚动到可见处。 + +## 最小示例 + +```go +var term mujica.TerminalState +term.Write("build ok\r\nerror: missing seal\r\n") +var search mujica.TerminalSearchState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + ui.Column(c).Gap(8).Children(func() { + mujica.TerminalSearch(c, &term, &search, mujica.TerminalSearchOptions{}) + mujica.Terminal(c, &term, mujica.TerminalOptions{}).Height(160) + }) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func TerminalSearch(c *ui.Context, term *TerminalState, s *TerminalSearchState, opts TerminalSearchOptions) ChoiceResult`。匹配在查询或终端内容变化时重算一次,不逐帧计算;匹配结果写入 `term`,由同一 `TerminalState` 的 `Terminal` 绘制下划线,当前匹配加框。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `TerminalSearchState.Query` | `string` | "" | 查找文字,不区分大小写。 | +| `TerminalSearchState.Current` | `int` | 0 | 当前匹配序号,从 0 开始。 | +| `Disabled` | `bool` | false | 不能输入与跳转。 | + +## 状态 + +无查询、有匹配(“第 n 项,共 m 项”)、无匹配(“无匹配”)、禁用;终端中其余匹配为 AccentText 下划线,当前匹配加 AccentText 框。 + +## 事件 + +`Changed()`:查询变化或跳到另一匹配。 + +## 键盘操作 + +- Enter / Shift+Enter:下一项 / 上一项;macOS 上 Cmd+G / Shift+Cmd+G,其他平台 F3 / Shift+F3。 +- 上一项、下一项按钮可用 Tab 到达。 + +## 限制 + +- 只做纯文字匹配,不支持正则与整词;跨行文字不会匹配。 diff --git a/docs/components/324-command-history.md b/docs/components/324-command-history.md new file mode 100644 index 0000000..69be25f --- /dev/null +++ b/docs/components/324-command-history.md @@ -0,0 +1,50 @@ +# 324 CommandHistory · 命令历史 + +## 用途 + +按时间倒序列出执行过的命令,可搜索,并通过回调重新运行。 + +## 最小示例 + +```go +history := []mujica.HistoryEntry{{Command: "git status"}, {Command: "go test ./...", ExitCode: 1}} +var state mujica.CommandHistoryState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CommandHistory(c, history, &state, mujica.CommandHistoryOptions{}) + r.Element.Height(240) + if r.Replayed != nil { + fmt.Println("run", r.Replayed.Command) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func CommandHistory(c *ui.Context, entries []HistoryEntry, s *CommandHistoryState, opts CommandHistoryOptions) CommandHistoryResult`。列表虚拟化,筛选只在条目数或查询变化时重算。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `HistoryEntry.Command` | `string` | 必填 | 命令文字。 | +| `HistoryEntry.Time` | `time.Time` | 零值不显示 | 执行时间。 | +| `HistoryEntry.ExitCode` | `int` | 0 | 非零时显示“退出码 n”。 | +| `CommandHistoryState.Query` | `string` | "" | 搜索文字,不区分大小写。 | +| `Disabled` | `bool` | false | 不能搜索与重放。 | + +## 状态 + +默认、选中(Selection 背景与菱形标记)、失败命令(Danger 退出码)、无历史、无匹配、禁用。 + +## 事件 + +`Replayed`:要重新运行的条目,没有则为 nil。 + +## 键盘操作 + +- Tab 依次到达搜索框与列表;↑/↓、Home/End 选择;输入字母按命令定位。 +- Enter 或双击:重放当前条目;每行的重放按钮可用 Tab 到达。 + +## 限制 + +- 只追加或整体替换 `entries` 会被识别;原地修改中间条目后请传入新切片。 diff --git a/docs/components/325-log-viewer.md b/docs/components/325-log-viewer.md new file mode 100644 index 0000000..720a92e --- /dev/null +++ b/docs/components/325-log-viewer.md @@ -0,0 +1,48 @@ +# 325 LogViewer · 日志查看器 + +## 用途 + +显示日志:按级别过滤、跟随尾部、关键字高亮,十万行也只构建可见行。 + +## 最小示例 + +```go +lines := []mujica.LogLine{{Level: mujica.LogInfo, Text: "court opened"}, {Level: mujica.LogError, Text: "seal missing"}} +var state mujica.LogViewerState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.LogViewer(c, lines, &state, mujica.LogViewerOptions{}).Element.Height(240) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func LogViewer(c *ui.Context, lines []LogLine, s *LogViewerState, opts LogViewerOptions) ChoiceResult`。新追加的行增量过滤;级别变化时重新过滤一次,不逐帧计算。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `LogLine.Level` | `LogLevel` | `LogDebug` | `LogDebug`、`LogInfo`、`LogWarn`、`LogError`;越界 panic。 | +| `LogLine.Time`, `Text` | `time.Time`, `string` | — | 时间(零值不显示)与内容。 | +| `LogViewerState.Hidden` | `[4]bool` | 全显示 | 被隐藏的级别。 | +| `LogViewerState.Query` | `string` | "" | 高亮关键字,不区分大小写。 | +| `LogViewerState.Follow` | `bool` | 首次为 true | 跟随尾部;向上滚动后 MyGo 暂停跟随,滚回底部恢复。 | +| `Disabled` | `bool` | false | 不能改过滤与跟随。 | + +## 状态 + +级别按钮按下表示显示;级别同时用文字(DEBUG/INFO/WARN/ERROR)与颜色区分;高亮为 Selection 背景、粗体与下划线;无日志空状态;禁用。 + +## 事件 + +`Changed()`:级别过滤或跟随开关变化。 + +## 键盘操作 + +- Tab 依次到达级别按钮、高亮输入框、跟随按钮与日志列表;Space 切换按钮。 +- 列表中方向键、PageUp/PageDown、Home/End 滚动。 + +## 限制 + +- 只识别向末尾追加;替换为更短的切片会重新过滤。 +- 高亮不过滤行,只标出匹配。 diff --git a/docs/components/326-process-list.md b/docs/components/326-process-list.md new file mode 100644 index 0000000..d0523e5 --- /dev/null +++ b/docs/components/326-process-list.md @@ -0,0 +1,50 @@ +# 326 ProcessList · 进程列表 + +## 用途 + +以表格列出进程,可按名称、PID、CPU、内存排序;结束进程前必须确认,确认后通过结果交给调用方执行。 + +## 最小示例 + +```go +procs := []mujica.Process{{PID: 7, Name: "archivist", CPU: 42, Memory: 50 << 20}, {PID: 9, Name: "herald", CPU: 3, Memory: 8 << 20}} +var state mujica.ProcessListState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ProcessList(c, procs, &state, mujica.ProcessListOptions{}) + r.Element.Height(240) + if r.End != nil { + fmt.Println("kill", r.End.PID) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ProcessList(c *ui.Context, procs []Process, s *ProcessListState, opts ProcessListOptions) ProcessListResult`。排序只在切片或排序方式变化时进行;刷新数据请传入新切片。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Process.PID`, `Name` | `int`, `string` | — | 进程号与名称;PID 是行的稳定键。 | +| `Process.CPU` | `float64` | 0 | 占用百分比。 | +| `Process.Memory` | `uint64` | 0 | 常驻内存字节数,显示为 KB/MB/GB。 | +| `ProcessListState.Sort` | `ui.SortOrder` | CPU 降序 | 列为 `name`、`pid`、`cpu`、`memory`,其他值 panic。 | +| `Disabled` | `bool` | false | 不能排序与结束进程。 | + +## 状态 + +选中行(Selection 背景与菱形)、排序列箭头、确认对话框(默认聚焦“取消”)、无进程、禁用。 + +## 事件 + +`End`:用户确认要结束的进程,没有则为 nil。 + +## 键盘操作 + +- Tab 到达表格;↑/↓、Home/End 选择;Delete 结束所选进程(先确认)。 +- 点击列头排序,再点反向;每行结束按钮可用 Tab 到达。 + +## 限制 + +- 组件不发送信号,只回报确认结果。 diff --git a/docs/components/327-code-viewer.md b/docs/components/327-code-viewer.md new file mode 100644 index 0000000..b91d213 --- /dev/null +++ b/docs/components/327-code-viewer.md @@ -0,0 +1,46 @@ +# 327 CodeViewer · 代码查看器 + +## 用途 + +只读代码视图:行号、基础语法着色(`internal.Highlight`)、按缩进折叠、当前行、选择复制;大文件只构建可见行。 + +## 最小示例 + +```go +lines := []string{"func Seal(d string) int {", "\treturn len(d)", "}"} +var state mujica.CodeViewerState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CodeViewer(c, lines, &state, mujica.CodeViewerOptions{Language: "go"}).Element.Height(240) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func CodeViewer(c *ui.Context, lines []string, s *CodeViewerState, opts CodeViewerOptions) ChoiceResult`。块注释状态与折叠范围在代码变化时扫描一次。`s.Line()` 返回当前行,`s.GoTo(line)` 跳转并展开遮住它的折叠,`s.Visible()` 返回可见行范围,`s.ScrollTo(line)` 只滚动;`s.Selection` 保存选中行,`s.Folded` 保存折叠起始行。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Language` | `string` | ""(纯文本) | `go`、`javascript`、`typescript`、`python`、`json`、`shell`、`sql`。 | +| `Label` | `string` | "" | 无障碍名称。 | +| `Disabled` | `bool` | false | 不能折叠。 | + +## 状态 + +当前行(Selection 背景与菱形)、选中行(Selection 背景)、可折叠行(向下箭头)、已折叠(向右箭头)、空代码、禁用。关键字 AccentText、字符串 Success、数字 Warning、类型 Info、注释 TextMuted 斜体。 + +## 事件 + +`Changed()`:当前行或选择变化。 + +## 键盘操作 + +- ↑/↓、Home/End:移动当前行;Shift+方向键扩展选择;Cmd/Ctrl+A 全选。 +- Cmd+C(macOS)/ Ctrl+C:复制选中行,未选则复制当前行。 +- ←:折叠当前行开始的块;→:展开。折叠按钮可用 Tab 到达。 + +## 限制 + +- 折叠按缩进推断,不解析语法;空行不结束块。 +- 只读,不提供编辑与行内(字符级)选择。 diff --git a/docs/components/328-minimap.md b/docs/components/328-minimap.md new file mode 100644 index 0000000..60a0a9e --- /dev/null +++ b/docs/components/328-minimap.md @@ -0,0 +1,45 @@ +# 328 Minimap · 代码缩略图 + +## 用途 + +以细条绘制代码缩略图,框出编辑器可见区域;点击或拖动跳转,键盘可移动。 + +## 最小示例 + +```go +lines := []string{"package court", "", "func Seal() {}", "func Herald() {}"} +view := mujica.MinimapView{Top: 0, Visible: 2} +draw := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.Minimap(c, lines, &view, mujica.MinimapOptions{Language: "go"}).Changed() { + fmt.Println("scroll editor to", view.Top) + } +} +ui.Render(draw, 400, 300, 1) +``` + +## 参数 + +`func Minimap(c *ui.Context, lines []string, view *MinimapView, opts MinimapOptions) ChoiceResult`。`MinimapView{Top, Visible}` 是编辑器当前首行与可见行数,由调用方与编辑器同步(可用 `CodeViewerState.Visible` 与 `ScrollTo`)。每行 2 DIP、每字符 1 DIP;文件比缩略图高时缩略图随视图滚动,只绘制可见的行。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Language` | `string` | "" | 着色语言,同 CodeViewer。 | +| `Width` | `float32` | 96 | 宽度(DIP);负数 panic。 | +| `Disabled` | `bool` | false | 不能跳转。 | + +## 状态 + +可见区为 Selection 半透明填充加 AccentText 边框;聚焦时外侧焦点环;禁用。 + +## 事件 + +`Changed()`:用户移动了视图,读取 `view.Top`。 + +## 键盘操作 + +- Tab 聚焦;↑/↓ 移动一行,PageUp/PageDown 移动一屏,Home/End 到开头与结尾。 + +## 限制 + +- 缩略图按行独立着色,不跟踪跨行的块注释。 diff --git a/docs/components/329-find-widget.md b/docs/components/329-find-widget.md new file mode 100644 index 0000000..2617d9b --- /dev/null +++ b/docs/components/329-find-widget.md @@ -0,0 +1,51 @@ +# 329 FindWidget · 查找替换 + +## 用途 + +在文本中查找与替换:区分大小写、整词、正则表达式,显示匹配数并上下跳转。 + +## 最小示例 + +```go +text := "the seal and the seal" +state := mujica.FindState{Query: "seal", Replacement: "signet", ShowReplace: true} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.FindWidget(c, &text, &state, mujica.FindWidgetOptions{}).Replaced > 0 { + fmt.Println(text) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func FindWidget(c *ui.Context, text *string, s *FindState, opts FindWidgetOptions) FindWidgetResult`。匹配在文本、查询或选项变化时重算;`s.Matches()` 返回各匹配的字节范围。替换直接修改 `*text`。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `FindState.Query`, `Replacement` | `string` | "" | 查找与替换文字;正则模式下替换支持 `$1` 分组。 | +| `MatchCase`, `WholeWord`, `Regex` | `bool` | false | 区分大小写、整词、正则。 | +| `ShowReplace` | `bool` | false | 展开替换行。 | +| `Current` | `int` | 0 | 当前匹配。 | +| `ReadOnly` | `bool` | false | 隐藏替换。 | +| `Disabled` | `bool` | false | 不能输入与替换。 | + +## 状态 + +选项按钮按下状态、匹配计数、无匹配、正则错误(Danger 文字说明具体错误)、替换按钮在无匹配时禁用、禁用。 + +## 事件 + +`Moved`:查询、选项或当前匹配变化;`Replaced`:本帧替换的数量。 + +## 键盘操作 + +- Enter / Shift+Enter:下一项 / 上一项;macOS Cmd+G,其他平台 F3。 +- 替换输入框中 Enter:替换当前项。 +- Tab 依次到达展开按钮、查找框、上下按钮、三个选项与替换控件。 + +## 限制 + +- 使用 Go 的 RE2 正则语法,不支持回溯引用。 +- 不在编辑器中绘制高亮,调用方用 `Matches()` 自行标记。 diff --git a/docs/components/330-search-panel.md b/docs/components/330-search-panel.md new file mode 100644 index 0000000..c9dc6e9 --- /dev/null +++ b/docs/components/330-search-panel.md @@ -0,0 +1,51 @@ +# 330 SearchPanel · 多文件搜索 + +## 用途 + +展示多文件搜索结果:按文件分组、可折叠,匹配预览带高亮;提供包含与排除模式输入。 + +## 最小示例 + +```go +results := []mujica.SearchFileResult{{Path: "court/seal.go", Matches: []mujica.SearchMatch{{Line: 12, Text: "func Seal() {", Start: 5, End: 9}}}} +state := mujica.SearchPanelState{Query: "seal"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.SearchPanel(c, results, &state, mujica.SearchPanelOptions{}) + r.Element.Height(280) + if r.Opened != nil { + fmt.Println("open", r.Opened.Path, r.Opened.Line) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func SearchPanel(c *ui.Context, results []SearchFileResult, s *SearchPanelState, opts SearchPanelOptions) SearchPanelResult`。搜索由调用方执行:查询或模式变化时 `Changed` 为 true,完成后传入新的 `results`。行列表虚拟化。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `SearchFileResult.Path` | `string` | 必填 | 文件路径,也是折叠键。 | +| `SearchMatch.Line`, `Text` | `int`, `string` | — | 行号与行文字。 | +| `SearchMatch.Start`, `End` | `int` | — | 匹配在 `Text` 中的字节范围;越界 panic。 | +| `SearchPanelState.Query`, `Include`, `Exclude` | `string` | "" | 查询与包含、排除模式(格式由调用方解释)。 | +| `Status`, `Error` | `DataStatus`, `string` | `DataReady` | 搜索中或失败。 | +| `Disabled` | `bool` | false | 不能输入、折叠与打开。 | + +## 状态 + +结果摘要、文件标题(折叠箭头与匹配数)、匹配行(Selection 背景与粗体下划线标出匹配)、选中行(Selection 与菱形)、搜索中、失败(可重试)、未输入、无结果、禁用。 + +## 事件 + +`Changed`:查询或模式变化,或点击重试;`Opened`:用户打开的匹配(路径与行号)。 + +## 键盘操作 + +- Tab 依次到达查询、包含、排除与结果列表。 +- ↑/↓ 选择;Enter 或双击:打开匹配,或折叠/展开文件;文件行上 ← 折叠、→ 展开。 + +## 限制 + +- 长行只显示匹配前 40 个字节。 diff --git a/docs/components/331-problems-panel.md b/docs/components/331-problems-panel.md new file mode 100644 index 0000000..cea7623 --- /dev/null +++ b/docs/components/331-problems-panel.md @@ -0,0 +1,49 @@ +# 331 ProblemsPanel · 问题面板 + +## 用途 + +列出错误、警告与信息,按文件分组并按行列排序,可按级别过滤,打开问题时回调跳转。 + +## 最小示例 + +```go +problems := []mujica.Problem{{Severity: mujica.ProblemError, File: "court/seal.go", Line: 12, Col: 5, Message: "undefined: Decree"}} +var state mujica.ProblemsPanelState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ProblemsPanel(c, problems, &state, mujica.ProblemsPanelOptions{}) + r.Element.Height(240) + if r.Opened != nil { + fmt.Println("go to", r.Opened.File, r.Opened.Line) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func ProblemsPanel(c *ui.Context, problems []Problem, s *ProblemsPanelState, opts ProblemsPanelOptions) ProblemsPanelResult`。分组排序只在数据、过滤或折叠变化时进行。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Problem.Severity` | `ProblemSeverity` | `ProblemError` | `ProblemError`、`ProblemWarning`、`ProblemInfo`;越界 panic。 | +| `Problem.File`, `Line`, `Col` | `string`, `int` | — | 位置。 | +| `Problem.Message`, `Source` | `string` | — | 说明与来源(如编译器名)。 | +| `ProblemsPanelState.Hidden` | `[3]bool` | 全显示 | 被隐藏的级别。 | +| `Disabled` | `bool` | false | 不能过滤、折叠与打开。 | + +## 状态 + +级别按钮带图标与计数;问题行用不同形状的图标(圆叉、三角、圆 i)与颜色共同标识级别,并有无障碍名称;选中行 Selection 与菱形;无问题;禁用。 + +## 事件 + +`Opened`:用户打开的问题。 + +## 键盘操作 + +- Tab 到达级别按钮与列表;↑/↓ 选择;Enter 或双击打开问题,在文件行上折叠/展开;← 折叠、→ 展开。 + +## 限制 + +- 同一文件的问题按行、列排序,文件按路径排序。 diff --git a/docs/components/332-output-panel.md b/docs/components/332-output-panel.md new file mode 100644 index 0000000..5349439 --- /dev/null +++ b/docs/components/332-output-panel.md @@ -0,0 +1,48 @@ +# 332 OutputPanel · 输出面板 + +## 用途 + +显示多个输出通道之一,跟随尾部,支持 ANSI 颜色;清空请求通过结果交给调用方。 + +## 最小示例 + +```go +channels := []mujica.OutputChannel{{Name: "Build", Lines: []string{"compiling court", "\x1b[32mok\x1b[0m"}}} +var state mujica.OutputPanelState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.OutputPanel(c, channels, &state, mujica.OutputPanelOptions{}) + r.Element.Height(240) + if r.Cleared != "" { + channels[state.Channel].Lines = nil + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func OutputPanel(c *ui.Context, channels []OutputChannel, s *OutputPanelState, opts OutputPanelOptions) OutputPanelResult`。通道为空或 `Channel` 越界时 panic。行列表虚拟化。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `OutputChannel.Name`, `Lines` | `string`, `[]string` | — | 通道名与内容,行内可含 ANSI 样式。 | +| `OutputPanelState.Channel` | `int` | 0 | 当前通道。 | +| `OutputPanelState.Follow` | `bool` | 首次为 true | 跟随尾部。 | +| `Disabled` | `bool` | false | 不能切换、清空与改跟随。 | + +## 状态 + +通道下拉、跟随按钮按下、清空按钮、无输出、禁用。 + +## 事件 + +`Changed`:切换了通道;`Cleared`:要清空的通道名,调用方清空其 `Lines`。 + +## 键盘操作 + +- Tab 到达通道下拉、跟随按钮、清空按钮与输出列表;下拉中方向键选择。 + +## 限制 + +- 只渲染 SGR 样式,其余控制序列原样保留(与 `internal.ParseAnsi` 一致)。 diff --git a/docs/components/333-symbol-outline.md b/docs/components/333-symbol-outline.md new file mode 100644 index 0000000..f04dbfa --- /dev/null +++ b/docs/components/333-symbol-outline.md @@ -0,0 +1,53 @@ +# 333 SymbolOutline · 符号大纲 + +## 用途 + +以树显示文件中的符号,带类型标记,可筛选,并跟随编辑器光标选中所在符号。 + +## 最小示例 + +```go +symbols := []mujica.Symbol{{Name: "Court", Kind: mujica.SymbolType, Line: 3, EndLine: 40, Children: []mujica.Symbol{ + {Name: "Seal", Kind: mujica.SymbolMethod, Line: 10, EndLine: 20}, +}}} +var state mujica.SymbolOutlineState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.SymbolOutline(c, symbols, &state, mujica.SymbolOutlineOptions{CursorLine: 12}) + r.Element.Height(240) + if r.Jumped != nil { + fmt.Println("go to line", r.Jumped.Line) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func SymbolOutline(c *ui.Context, symbols []Symbol, s *SymbolOutlineState, opts SymbolOutlineOptions) SymbolOutlineResult`。符号树在数据变化时编号一次。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Symbol.Name`, `Detail` | `string` | — | 名称与补充说明(如签名)。 | +| `Symbol.Kind` | `SymbolKind` | `SymbolFunction` | 函数 f、方法 m、类型 T、接口 I、字段 p、变量 v、常量 c、模块 M;越界 panic。 | +| `Symbol.Line`, `EndLine` | `int` | — | 所在行范围,从 1 开始。 | +| `SymbolOutlineState.Query` | `string` | "" | 筛选文字;匹配项与其祖先保留并自动展开。 | +| `CursorLine` | `int` | 0(不跟随) | 变化时选中包含该行的最内层符号并展开祖先。 | +| `Disabled` | `bool` | false | 不能跳转。 | + +## 状态 + +类型以字母徽记加颜色区分;选中行 Selection 与菱形;筛选高亮;无符号;禁用。 + +## 事件 + +`Jumped`:用户要跳转的符号。 + +## 键盘操作 + +- Tab 到达筛选框与树;↑/↓ 移动,→ 展开或进入子项,← 折叠或回到父项;输入字母按名称定位。 +- Enter 或双击:跳转到符号。 + +## 限制 + +- 光标跟随只在 `CursorLine` 变化时生效,之后用户可自由移动选择。 diff --git a/docs/components/334-completion-menu.md b/docs/components/334-completion-menu.md new file mode 100644 index 0000000..cbc27a1 --- /dev/null +++ b/docs/components/334-completion-menu.md @@ -0,0 +1,50 @@ +# 334 CompletionMenu · 补全菜单 + +## 用途 + +在编辑器下方显示补全候选:类型徽记、详情与说明;方向键选择,Tab 或 Enter 接受,焦点始终留在编辑器。 + +## 最小示例 + +```go +text := "se" +open := true +items := []mujica.Completion{{Label: "Seal", Kind: mujica.SymbolMethod, Detail: "func()"}, {Label: "Search", Kind: mujica.SymbolFunction}} +var state mujica.CompletionMenuState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + in := mujica.TextInput(c, &text, mujica.TextInputOptions{Label: "Code"}) + if r := mujica.CompletionMenu(c, in.Input, &open, items, &state, mujica.CompletionMenuOptions{}); r.Accepted != nil { + text = r.Accepted.Label + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func CompletionMenu(c *ui.Context, anchor *ui.Element, open *bool, items []Completion, s *CompletionMenuState, opts CompletionMenuOptions) CompletionMenuResult`。`anchor` 是编辑器元素(如 `InputResult.Input`);打开期间组件替换它的 `HandleInput` 以先拿到菜单按键。候选为空、禁用或编辑器禁用时自动关闭。列表虚拟化,最多显示 8 行后滚动;窗口下方空间不足时在上方弹出。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Completion.Label` | `string` | 必填 | 候选文字。 | +| `Completion.Kind` | `SymbolKind` | `SymbolFunction` | 类型徽记;越界 panic。 | +| `Completion.Detail`, `Doc` | `string` | "" | 右侧详情与当前候选的说明。 | +| `CompletionMenuState.Selected` | `int` | 0 | 当前候选。 | +| `Disabled` | `bool` | false | 关闭菜单。 | + +## 状态 + +当前候选 Selection 背景与菱形;弹层 160 ms 淡入(减少动画时直接显示)。 + +## 事件 + +`Accepted`:被接受的候选,同时 `*open` 置为 false。 + +## 键盘操作 + +- ↓/↑:循环移动;Tab 或 Enter:接受;Escape:关闭。点击候选也接受。 + +## 限制 + +- 打开期间编辑器自身设置的 `HandleInput` 会被覆盖。 diff --git a/docs/components/335-debug-toolbar.md b/docs/components/335-debug-toolbar.md new file mode 100644 index 0000000..7560c0b --- /dev/null +++ b/docs/components/335-debug-toolbar.md @@ -0,0 +1,48 @@ +# 335 DebugToolbar · 调试工具栏 + +## 用途 + +调试会话的继续/暂停、单步跳过、单步进入、单步跳出、重启与停止,按会话状态禁用不适用的按钮,并注册常用快捷键。 + +## 最小示例 + +```go +state := mujica.DebugPaused +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + switch mujica.DebugToolbar(c, state, mujica.DebugToolbarOptions{}).Action { + case mujica.DebugContinue: + state = mujica.DebugRunning + case mujica.DebugStop: + state = mujica.DebugStopped + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func DebugToolbar(c *ui.Context, state DebugState, opts DebugToolbarOptions) DebugToolbarResult`。`DebugEnabled(state, action)` 给出禁用规则:运行中只能暂停、重启、停止;暂停时可继续、单步、重启、停止;停止时只能“开始”(`DebugContinue`)。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `state` | `DebugState` | — | `DebugStopped`、`DebugRunning`、`DebugPaused`;越界 panic。 | +| `Disabled` | `bool` | false | 全部按钮与快捷键无效。 | + +## 状态 + +运行中第一个按钮显示暂停,否则显示继续(停止时名为“开始”);不适用的按钮禁用;按钮悬停、按下、焦点环与带快捷键的提示。 + +## 事件 + +`Action`:本帧请求的 `DebugAction`,无则为 `DebugNone`。 + +## 键盘操作 + +- F5 继续/开始,F6 暂停,F10 单步跳过,F11 单步进入,Shift+F11 单步跳出,Cmd/Ctrl+Shift+F5 重启,Shift+F5 停止(窗口内全局,焦点控件优先处理)。 +- 工具栏是一个 Tab 停靠点,←/→ 在按钮间移动。 + +## 限制 + +- 快捷键固定,不可配置;同一窗口只放一个调试工具栏。 +- 图标为自绘 SVG。 diff --git a/docs/components/336-breakpoint-list.md b/docs/components/336-breakpoint-list.md new file mode 100644 index 0000000..488efca --- /dev/null +++ b/docs/components/336-breakpoint-list.md @@ -0,0 +1,49 @@ +# 336 BreakpointList · 断点列表 + +## 用途 + +列出断点:启用开关、跳到源码位置、行内编辑条件断点。 + +## 最小示例 + +```go +bps := []mujica.Breakpoint{{ID: "a", File: "court/seal.go", Line: 12, Enabled: true}, {ID: "b", File: "main.go", Line: 9, Condition: "n > 3"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.BreakpointList(c, &bps, mujica.BreakpointListOptions{}) + r.Element.Height(200) + if r.Toggled != "" || r.Edited != "" { + fmt.Println("sync breakpoints with the debugger") + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func BreakpointList(c *ui.Context, bps *[]Breakpoint, opts BreakpointListOptions) BreakpointListResult`。组件直接修改 `*bps` 中的 `Enabled` 与 `Condition`;ID 为空或重复时 panic。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Breakpoint.ID` | `string` | 必填 | 稳定标识。 | +| `Breakpoint.File`, `Line` | `string`, `int` | — | 位置。 | +| `Breakpoint.Enabled` | `bool` | false | 是否启用。 | +| `Breakpoint.Condition` | `string` | "" | 条件表达式,非空时显示“当 …”。 | +| `Disabled` | `bool` | false | 不能修改与跳转。 | + +## 状态 + +启用为实心圆点,停用为空心圆点并降低文字色;条件以 Warning 等宽文字显示;编辑中的输入框;无断点;禁用。 + +## 事件 + +`Toggled`、`Edited`、`Opened`:本帧被切换、改条件、要打开的断点 ID。 + +## 键盘操作 + +- Tab 依次到达复选框、位置按钮与编辑条件按钮;Space 切换启用;Enter 打开位置。 +- 条件输入框:Enter 确认,Escape 取消。 + +## 限制 + +- 不提供删除与新增;由调用方修改 `*bps`。 diff --git a/docs/components/337-call-stack.md b/docs/components/337-call-stack.md new file mode 100644 index 0000000..a5a2b69 --- /dev/null +++ b/docs/components/337-call-stack.md @@ -0,0 +1,52 @@ +# 337 CallStack · 调用栈 + +## 用途 + +按线程分组显示调用栈帧,标出当前帧;选择帧即切换当前帧。 + +## 最小示例 + +```go +threads := []mujica.DebugThread{{ID: "t1", Name: "main", Frames: []mujica.StackFrame{ + {ID: "f1", Name: "court.Seal", File: "court/seal.go", Line: 14}, + {ID: "f2", Name: "main.main", File: "main.go", Line: 9}, +}}} +state := mujica.CallStackState{Current: "f1"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CallStack(c, threads, &state, mujica.CallStackOptions{}) + r.Element.Height(200) + if r.Changed() { + fmt.Println("show frame", state.Current) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func CallStack(c *ui.Context, threads []DebugThread, s *CallStackState, opts CallStackOptions) ChoiceResult`。调用方修改 `s.Current` 时选中行随之移动。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `DebugThread.ID`, `Name` | `string` | — | 线程标识与名称。 | +| `StackFrame.ID`, `Name`, `File`, `Line` | `string`, `int` | — | 帧标识、函数名与位置,最内层在前。 | +| `CallStackState.Current` | `string` | "" | 当前帧 ID。 | +| `CallStackState.Collapsed` | `ui.Selection[string]` | 空 | 折叠的线程 ID。 | +| `Disabled` | `bool` | false | 不能切换与折叠。 | + +## 状态 + +线程标题(折叠箭头与栈深度)、当前帧(Selection 背景与菱形)、未暂停空状态、禁用。 + +## 事件 + +`Changed()`:用户选了另一帧,读取 `s.Current`。 + +## 键盘操作 + +- Tab 到达列表;↑/↓ 移动,到达帧即切换当前帧;线程行上 Enter 折叠/展开,← 折叠、→ 展开。 + +## 限制 + +- 不区分线程的运行状态;需要时写入线程名。 diff --git a/docs/components/338-variables-panel.md b/docs/components/338-variables-panel.md new file mode 100644 index 0000000..c68a88c --- /dev/null +++ b/docs/components/338-variables-panel.md @@ -0,0 +1,49 @@ +# 338 VariablesPanel · 变量面板 + +## 用途 + +以树显示调试变量,可展开结构,标出自上次停止以来变化的值,并在行内修改叶子变量的值。 + +## 最小示例 + +```go +vars := []mujica.Variable{{Name: "decree", Value: "{…}", Children: []mujica.Variable{{Name: "id", Value: "42", Changed: true}}}, {Name: "count", Value: "7"}} +var state mujica.VariablesPanelState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.VariablesPanel(c, vars, &state, mujica.VariablesPanelOptions{}) + r.Element.Height(200) + if r.Edited != nil { + fmt.Println("set", r.Edited.Path, "=", r.Edited.Value) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func VariablesPanel(c *ui.Context, vars []Variable, s *VariablesPanelState, opts VariablesPanelOptions) VariablesPanelResult`。变量按名称以点连接成路径作为键,同层重名 panic。修改值通过结果交给调用方写回调试器并传入新值。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `Variable.Name`, `Value`, `Type` | `string` | — | 名称、显示值与类型。 | +| `Variable.Changed` | `bool` | false | 值自上次停止后变化。 | +| `Variable.Children` | `[]Variable` | nil(叶子) | 成员;非 nil 时可展开。 | +| `Disabled` | `bool` | false | 不能编辑。 | + +## 状态 + +变化的值以菱形标记、粗体与 AccentText 显示并带无障碍描述“已变化”;编辑中的输入框;选中行 Selection;无变量;禁用。 + +## 事件 + +`Edited`:新值与变量路径。 + +## 键盘操作 + +- Tab 到达树;↑/↓ 移动,→ 展开,← 折叠。 +- 叶子上 Enter、F2 或双击:编辑;Enter 确认,Escape 取消。 + +## 限制 + +- 子项不支持按需加载;需要时调用方在展开后补充 `Children`。 diff --git a/docs/components/339-hex-viewer.md b/docs/components/339-hex-viewer.md new file mode 100644 index 0000000..3a4a448 --- /dev/null +++ b/docs/components/339-hex-viewer.md @@ -0,0 +1,44 @@ +# 339 HexViewer · 十六进制查看器 + +## 用途 + +以偏移、十六进制与 ASCII 三列对照显示字节;两列共享同一选择与光标,只构建可见行。 + +## 最小示例 + +```go +data := []byte("MUJICA court ledger\x00\x01") +var state mujica.HexViewerState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.HexViewer(c, data, &state, mujica.HexViewerOptions{}).Element.Height(160) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func HexViewer(c *ui.Context, data []byte, s *HexViewerState, opts HexViewerOptions) ChoiceResult`。每行 16 字节;`s.Selection()` 返回选中范围;光标或锚点越界 panic。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `HexViewerState.Cursor`, `Anchor` | `int` | 0 | 光标字节与 Shift 选择的起点。 | +| `Disabled` | `bool` | false | 不能移动与选择。 | + +## 状态 + +选中字节在两列都显示 Selection 背景,光标字节在两列都加 AccentText 框;不可打印字节显示为点;聚焦时外侧焦点环;空数据;禁用。 + +## 事件 + +`Changed()`:光标或选择变化。 + +## 键盘操作 + +- Tab 聚焦;←/→ 移动一字节,↑/↓ 移动一行,Home/End 到行首行尾;加 Shift 扩展选择。 +- Cmd+C(macOS)/ Ctrl+C:以空格分隔的十六进制复制选中字节。 +- 点击任一列选择字节,Shift+点击扩展。 + +## 限制 + +- 只读,不支持编辑与搜索。 diff --git a/docs/components/340-flamegraph.md b/docs/components/340-flamegraph.md new file mode 100644 index 0000000..21f12c8 --- /dev/null +++ b/docs/components/340-flamegraph.md @@ -0,0 +1,50 @@ +# 340 Flamegraph · 火焰图 + +## 用途 + +以层叠框绘制性能剖析:点击放大子树,搜索高亮匹配帧,悬停或键盘移动时显示并朗读耗时读数。 + +## 最小示例 + +```go +root := &mujica.FlameNode{Name: "main", Value: 100, Children: []mujica.FlameNode{ + {Name: "court.Seal", Value: 60}, {Name: "ledger.Write", Value: 30}, +}} +var state mujica.FlamegraphState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Flamegraph(c, root, &state, mujica.FlamegraphOptions{Unit: "ms"}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`func Flamegraph(c *ui.Context, root *FlameNode, s *FlamegraphState, opts FlamegraphOptions) ChoiceResult`。帧宽按耗时占比;放大的帧占满宽度,祖先以淡色整宽显示。子帧耗时之和大于父帧或出现负值时 panic。帧颜色按名称取自主题调色板(AccentText、Info、Success、Warning、加深的 Ornament、TextMuted,均对 Surface 至少 3:1)。 + +| 字段 | 类型 | 默认值 | 含义 | +| --- | --- | --- | --- | +| `FlameNode.Name`, `Value`, `Children` | `string`, `float64`, `[]FlameNode` | — | 帧名、含子帧的总耗时与子帧。 | +| `FlamegraphState.Zoom`, `Focus` | `[]int` | nil(根) | 放大与键盘焦点所在帧的子序号路径。 | +| `FlamegraphState.Query` | `string` | "" | 搜索高亮。 | +| `Unit` | `string` | "" | 读数中的单位。 | +| `Status`, `Error` | `DataStatus`, `string` | `DataReady` | 加载中或失败,与图同高显示。 | +| `Disabled` | `bool` | false | 不能放大与移动。 | + +## 状态 + +帧为浅色底加同色边框与名称;搜索匹配加 AccentText 粗框,其余帧变淡;焦点帧带焦点环;读数行显示名称、耗时与占比;加载、失败、无数据。 + +## 事件 + +`Changed()`:放大或焦点变化(失败状态下点击“重试”也为 true)。 + +## 键盘操作 + +- Tab 聚焦图表;↑ 到父帧,↓ 到第一个子帧,←/→ 在兄弟帧间移动;Enter 放大当前帧,Escape 缩小一级。 +- 读数随焦点更新并通过屏幕阅读器朗读。 + +## 限制 + +- 窄于 1 DIP 的帧不绘制,窄于 24 DIP 的帧不写名称;用键盘可到达所有帧。 +- 帧行高 28 DIP,窄帧的点击区域可能小于 28 DIP,请用键盘或先放大。 diff --git a/example_code_test.go b/example_code_test.go new file mode 100644 index 0000000..10451d2 --- /dev/null +++ b/example_code_test.go @@ -0,0 +1,276 @@ +package mujica_test + +import ( + "fmt" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func ExampleTerminal() { + var term mujica.TerminalState + term.Write("\x1b[1m~/court\x1b[0m $ ls\r\n\x1b[34mdecrees\x1b[0m ledger.txt\r\n$ ") + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Terminal(c, &term, mujica.TerminalOptions{ + Input: func(data string) { fmt.Printf("to pty: %q\n", data) }, + Resized: func(cols, rows int) { fmt.Println("pty size", cols, rows) }, + }).Size(380, 200) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleTerminalTabs() { + tabs := []mujica.TerminalTab{{ID: "a", Title: "zsh"}, {ID: "b", Title: "build", Busy: true}} + active := "a" + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.TerminalTabs(c, &tabs, &active, mujica.TerminalTabsOptions{}, func(id string) { + ui.Text(c, "terminal "+id) + }) + if r.Closed != "" { + fmt.Println("close pty", r.Closed) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleTerminalSearch() { + var term mujica.TerminalState + term.Write("build ok\r\nerror: missing seal\r\n") + var search mujica.TerminalSearchState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + ui.Column(c).Gap(8).Children(func() { + mujica.TerminalSearch(c, &term, &search, mujica.TerminalSearchOptions{}) + mujica.Terminal(c, &term, mujica.TerminalOptions{}).Height(160) + }) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCommandHistory() { + history := []mujica.HistoryEntry{{Command: "git status"}, {Command: "go test ./...", ExitCode: 1}} + var state mujica.CommandHistoryState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CommandHistory(c, history, &state, mujica.CommandHistoryOptions{}) + r.Element.Height(240) + if r.Replayed != nil { + fmt.Println("run", r.Replayed.Command) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleLogViewer() { + lines := []mujica.LogLine{{Level: mujica.LogInfo, Text: "court opened"}, {Level: mujica.LogError, Text: "seal missing"}} + var state mujica.LogViewerState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.LogViewer(c, lines, &state, mujica.LogViewerOptions{}).Element.Height(240) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleProcessList() { + procs := []mujica.Process{{PID: 7, Name: "archivist", CPU: 42, Memory: 50 << 20}, {PID: 9, Name: "herald", CPU: 3, Memory: 8 << 20}} + var state mujica.ProcessListState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ProcessList(c, procs, &state, mujica.ProcessListOptions{}) + r.Element.Height(240) + if r.End != nil { + fmt.Println("kill", r.End.PID) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCodeViewer() { + lines := []string{"func Seal(d string) int {", "\treturn len(d)", "}"} + var state mujica.CodeViewerState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CodeViewer(c, lines, &state, mujica.CodeViewerOptions{Language: "go"}).Element.Height(240) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMinimap() { + lines := []string{"package court", "", "func Seal() {}", "func Herald() {}"} + view := mujica.MinimapView{Top: 0, Visible: 2} + draw := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.Minimap(c, lines, &view, mujica.MinimapOptions{Language: "go"}).Changed() { + fmt.Println("scroll editor to", view.Top) + } + } + ui.Render(draw, 400, 300, 1) +} + +func ExampleFindWidget() { + text := "the seal and the seal" + state := mujica.FindState{Query: "seal", Replacement: "signet", ShowReplace: true} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.FindWidget(c, &text, &state, mujica.FindWidgetOptions{}).Replaced > 0 { + fmt.Println(text) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleSearchPanel() { + results := []mujica.SearchFileResult{{Path: "court/seal.go", Matches: []mujica.SearchMatch{{Line: 12, Text: "func Seal() {", Start: 5, End: 9}}}} + state := mujica.SearchPanelState{Query: "seal"} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.SearchPanel(c, results, &state, mujica.SearchPanelOptions{}) + r.Element.Height(280) + if r.Opened != nil { + fmt.Println("open", r.Opened.Path, r.Opened.Line) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleProblemsPanel() { + problems := []mujica.Problem{{Severity: mujica.ProblemError, File: "court/seal.go", Line: 12, Col: 5, Message: "undefined: Decree"}} + var state mujica.ProblemsPanelState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ProblemsPanel(c, problems, &state, mujica.ProblemsPanelOptions{}) + r.Element.Height(240) + if r.Opened != nil { + fmt.Println("go to", r.Opened.File, r.Opened.Line) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleOutputPanel() { + channels := []mujica.OutputChannel{{Name: "Build", Lines: []string{"compiling court", "\x1b[32mok\x1b[0m"}}} + var state mujica.OutputPanelState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.OutputPanel(c, channels, &state, mujica.OutputPanelOptions{}) + r.Element.Height(240) + if r.Cleared != "" { + channels[state.Channel].Lines = nil + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleSymbolOutline() { + symbols := []mujica.Symbol{{Name: "Court", Kind: mujica.SymbolType, Line: 3, EndLine: 40, Children: []mujica.Symbol{ + {Name: "Seal", Kind: mujica.SymbolMethod, Line: 10, EndLine: 20}, + }}} + var state mujica.SymbolOutlineState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.SymbolOutline(c, symbols, &state, mujica.SymbolOutlineOptions{CursorLine: 12}) + r.Element.Height(240) + if r.Jumped != nil { + fmt.Println("go to line", r.Jumped.Line) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCompletionMenu() { + text := "se" + open := true + items := []mujica.Completion{{Label: "Seal", Kind: mujica.SymbolMethod, Detail: "func()"}, {Label: "Search", Kind: mujica.SymbolFunction}} + var state mujica.CompletionMenuState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + in := mujica.TextInput(c, &text, mujica.TextInputOptions{Label: "Code"}) + if r := mujica.CompletionMenu(c, in.Input, &open, items, &state, mujica.CompletionMenuOptions{}); r.Accepted != nil { + text = r.Accepted.Label + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleDebugToolbar() { + state := mujica.DebugPaused + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + switch mujica.DebugToolbar(c, state, mujica.DebugToolbarOptions{}).Action { + case mujica.DebugContinue: + state = mujica.DebugRunning + case mujica.DebugStop: + state = mujica.DebugStopped + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleBreakpointList() { + bps := []mujica.Breakpoint{{ID: "a", File: "court/seal.go", Line: 12, Enabled: true}, {ID: "b", File: "main.go", Line: 9, Condition: "n > 3"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.BreakpointList(c, &bps, mujica.BreakpointListOptions{}) + r.Element.Height(200) + if r.Toggled != "" || r.Edited != "" { + fmt.Println("sync breakpoints with the debugger") + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCallStack() { + threads := []mujica.DebugThread{{ID: "t1", Name: "main", Frames: []mujica.StackFrame{ + {ID: "f1", Name: "court.Seal", File: "court/seal.go", Line: 14}, + {ID: "f2", Name: "main.main", File: "main.go", Line: 9}, + }}} + state := mujica.CallStackState{Current: "f1"} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CallStack(c, threads, &state, mujica.CallStackOptions{}) + r.Element.Height(200) + if r.Changed() { + fmt.Println("show frame", state.Current) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleVariablesPanel() { + vars := []mujica.Variable{{Name: "decree", Value: "{…}", Children: []mujica.Variable{{Name: "id", Value: "42", Changed: true}}}, {Name: "count", Value: "7"}} + var state mujica.VariablesPanelState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.VariablesPanel(c, vars, &state, mujica.VariablesPanelOptions{}) + r.Element.Height(200) + if r.Edited != nil { + fmt.Println("set", r.Edited.Path, "=", r.Edited.Value) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleHexViewer() { + data := []byte("MUJICA court ledger\x00\x01") + var state mujica.HexViewerState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.HexViewer(c, data, &state, mujica.HexViewerOptions{}).Element.Height(160) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleFlamegraph() { + root := &mujica.FlameNode{Name: "main", Value: 100, Children: []mujica.FlameNode{ + {Name: "court.Seal", Value: 60}, {Name: "ledger.Write", Value: 30}, + }} + var state mujica.FlamegraphState + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Flamegraph(c, root, &state, mujica.FlamegraphOptions{Unit: "ms"}) + } + ui.Render(view, 400, 300, 1) +} diff --git a/examples/gallery/pages_code.go b/examples/gallery/pages_code.go index 028688b..9f9be1e 100644 --- a/examples/gallery/pages_code.go +++ b/examples/gallery/pages_code.go @@ -1,3 +1,245 @@ package main -var codePages = []page{} +import ( + "fmt" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +const codeCategory = "Terminal & Code" + +var codePages = []page{ + {ID: "321", Name: "Terminal", ZhName: "终端", Category: codeCategory, Demo: codeTerminalDemo, Code: codeTerminalCode, + Keys: "Focused: keys and text go to the PTY; Ctrl+letters send control codes; Cmd+C/V (Ctrl+Shift+C/V elsewhere) copy and paste; Shift+PageUp/PageDown scroll back; drag selects."}, + {ID: "322", Name: "TerminalTabs", ZhName: "终端标签", Category: codeCategory, Demo: codeTerminalTabsDemo, Code: codeTerminalTabsCode, + Keys: "Left/Right, Home/End switch tabs; F2 or double-click renames (Enter saves, Escape cancels); Delete closes, asking first while a process runs."}, + {ID: "323", Name: "TerminalSearch", ZhName: "终端搜索", Category: codeCategory, Demo: codeTerminalSearchDemo, Code: codeTerminalSearchCode, + Keys: "Enter / Shift+Enter go to the next / previous match; Cmd+G (F3 elsewhere) too."}, + {ID: "324", Name: "CommandHistory", ZhName: "命令历史", Category: codeCategory, Demo: codeCommandHistoryDemo, Code: codeCommandHistoryCode, + Keys: "Up/Down choose; Enter or double-click replays; typing in the list jumps by command."}, + {ID: "325", Name: "LogViewer", ZhName: "日志查看器", Category: codeCategory, Demo: codeLogViewerDemo, Code: codeLogViewerCode, + Keys: "Space toggles a level or Follow; arrows, PageUp/PageDown, Home/End scroll the log."}, + {ID: "326", Name: "ProcessList", ZhName: "进程列表", Category: codeCategory, Demo: codeProcessListDemo, Code: codeProcessListCode, + Keys: "Up/Down choose; Delete ends the chosen process after confirming; click a header to sort, again to reverse."}, + {ID: "327", Name: "CodeViewer", ZhName: "代码查看器", Category: codeCategory, Demo: codeCodeViewerDemo, Code: codeCodeViewerCode, + Keys: "Up/Down move the current line; Shift extends; Cmd/Ctrl+C copies; Left folds, Right unfolds."}, + {ID: "328", Name: "Minimap", ZhName: "代码缩略图", Category: codeCategory, Demo: codeMinimapDemo, Code: codeMinimapCode, + Keys: "Up/Down move a line, PageUp/PageDown a screen, Home/End to the ends; click or drag jumps."}, + {ID: "329", Name: "FindWidget", ZhName: "查找替换", Category: codeCategory, Demo: codeFindWidgetDemo, Code: codeFindWidgetCode, + Keys: "Enter / Shift+Enter next / previous match; Enter in the replace field replaces the current match."}, + {ID: "330", Name: "SearchPanel", ZhName: "多文件搜索", Category: codeCategory, Demo: codeSearchPanelDemo, Code: codeSearchPanelCode, + Keys: "Up/Down choose; Enter opens a match or folds a file; Left folds, Right unfolds a file."}, + {ID: "331", Name: "ProblemsPanel", ZhName: "问题面板", Category: codeCategory, Demo: codeProblemsDemo, Code: codeProblemsPanelCode, + Keys: "Space toggles a severity; Up/Down choose; Enter opens a problem or folds a file; Left/Right fold and unfold."}, + {ID: "332", Name: "OutputPanel", ZhName: "输出面板", Category: codeCategory, Demo: codeOutputDemo, Code: codeOutputPanelCode, + Keys: "Tab reaches the channel menu, Follow and Clear; arrows choose a channel in the open menu."}, + {ID: "333", Name: "SymbolOutline", ZhName: "符号大纲", Category: codeCategory, Demo: codeSymbolDemo, Code: codeSymbolOutlineCode, + Keys: "Up/Down move; Right opens, Left closes; Enter or double-click jumps; typing jumps by name."}, + {ID: "334", Name: "CompletionMenu", ZhName: "补全菜单", Category: codeCategory, Demo: codeCompletionDemo, Code: codeCompletionMenuCode, + Keys: "While typing: Down/Up move, Tab or Enter accepts, Escape closes; the editor keeps the focus."}, + {ID: "335", Name: "DebugToolbar", ZhName: "调试工具栏", Category: codeCategory, Demo: codeDebugDemo, Code: codeDebugToolbarCode, + Keys: "F5 continue, F6 pause, F10 step over, F11 step into, Shift+F11 step out, Cmd/Ctrl+Shift+F5 restart, Shift+F5 stop; Left/Right inside the toolbar."}, + {ID: "336", Name: "BreakpointList", ZhName: "断点列表", Category: codeCategory, Demo: codeBreakpointDemo, Code: codeBreakpointListCode, + Keys: "Space toggles; Enter on a location opens it; the condition field saves with Enter, cancels with Escape."}, + {ID: "337", Name: "CallStack", ZhName: "调用栈", Category: codeCategory, Demo: codeCallStackDemo, Code: codeCallStackCode, + Keys: "Up/Down choose a frame; Enter folds a thread; Left/Right fold and unfold."}, + {ID: "338", Name: "VariablesPanel", ZhName: "变量面板", Category: codeCategory, Demo: codeVariablesDemo, Code: codeVariablesPanelCode, + Keys: "Up/Down move; Right opens, Left closes; Enter, F2 or double-click edits a leaf; Enter saves, Escape cancels."}, + {ID: "339", Name: "HexViewer", ZhName: "十六进制查看器", Category: codeCategory, Demo: codeHexDemo, Code: codeHexViewerCode, + Keys: "Arrows move by byte and row; Shift extends; Home/End go to the row ends; Cmd/Ctrl+C copies hex."}, + {ID: "340", Name: "Flamegraph", ZhName: "火焰图", Category: codeCategory, Demo: codeFlamegraphDemo, Code: codeFlamegraphCode, + Keys: "Up parent, Down first child, Left/Right siblings; Enter zooms in, Escape zooms out; the readout is announced."}, +} + +// codeDemoCheck is a switch that logs its changes. +func codeDemoCheck(c *ui.Context, v *bool, label string, log func(string)) { + if mujica.Switch(c, v, label, mujica.SwitchOptions{}).Changed() { + log(fmt.Sprintf("%s: %v", label, *v)) + } +} + +func codeDemoControls(c *ui.Context, fn func()) { + ui.Row(c).Gap(16).Wrap().AlignItems(ui.Center).Margin(0, 0, 16, 0).Children(fn) +} + +func codeTerminalDemo(c *ui.Context, log func(string)) { + type state struct { + term mujica.TerminalState + line string + disabled bool + } + s := ui.Local(c.Root(), "321", func() *state { + s := &state{} + s.term.Write("Welcome to the \x1b[1;35mcourt\x1b[0m shell. Type and press Enter.\r\n$ ") + return s + }) + st := *s + codeDemoControls(c, func() { + codeDemoCheck(c, &st.disabled, "Disabled", log) + if mujica.Button(c, "Clear screen", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + st.term.Write("\x1b[2J\x1b[H$ ") + log("clear screen") + } + }) + // A tiny echo shell stands in for the PTY. + mujica.Terminal(c, &st.term, mujica.TerminalOptions{Disabled: st.disabled, + Input: func(data string) { + log(fmt.Sprintf("input %q", data)) + for _, r := range data { + switch r { + case '\r': + st.term.Write("\r\n" + codeShell(st.line) + "$ ") + st.line = "" + case 0x7f: + if st.line != "" { + st.line = st.line[:len(st.line)-1] + st.term.Write("\b \b") + } + default: + if r >= ' ' { + st.line += string(r) + st.term.Write(string(r)) + } + } + } + }, + Resized: func(cols, rows int) { log(fmt.Sprintf("resized %d×%d", cols, rows)) }, + }).Size(640, 260) +} + +// codeShell answers a few commands for the demo terminal. +func codeShell(line string) string { + switch f := strings.Fields(line); { + case len(f) == 0: + return "" + case f[0] == "ls": + return "\x1b[34mchronicles\x1b[0m decrees.txt \x1b[32mseal.sh\x1b[0m\r\n" + case f[0] == "echo": + return strings.Join(f[1:], " ") + "\r\n" + case f[0] == "date": + return time.Now().Format(time.RFC1123) + "\r\n" + } + return "\x1b[31m" + line + ": command not found\x1b[0m\r\n" +} + +func codeTerminalTabsDemo(c *ui.Context, log func(string)) { + type state struct { + tabs []mujica.TerminalTab + active string + next int + disabled bool + } + s := ui.Local(c.Root(), "322", func() *state { + return &state{tabs: []mujica.TerminalTab{{ID: "1", Title: "zsh"}, {ID: "2", Title: "build", Busy: true}, {ID: "3", Title: "logs"}}, active: "1", next: 4} + }) + st := *s + codeDemoControls(c, func() { + codeDemoCheck(c, &st.disabled, "Disabled", log) + if mujica.Button(c, "New terminal", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + id := fmt.Sprint(st.next) + st.next++ + st.tabs = append(st.tabs, mujica.TerminalTab{ID: id, Title: "shell " + id}) + st.active = id + log("new " + id) + } + }) + r := mujica.TerminalTabs(c, &st.tabs, &st.active, mujica.TerminalTabsOptions{Disabled: st.disabled}, func(id string) { + ui.Text(c, "Terminal "+id+" content").TextColor(mujica.Tokens(c).TextMuted) + }) + r.Element.Width(560) + if r.Changed { + log("active " + st.active) + } + if r.Renamed != "" { + log("renamed " + r.Renamed) + } + if r.Closed != "" { + log("closed " + r.Closed) + } +} + +func codeTerminalSearchDemo(c *ui.Context, log func(string)) { + type state struct { + term mujica.TerminalState + search mujica.TerminalSearchState + disabled bool + } + s := ui.Local(c.Root(), "323", func() *state { + s := &state{} + for i := range 60 { + if i%9 == 4 { + s.term.Write(fmt.Sprintf("[%02d] \x1b[31merror\x1b[0m: seal %d missing\r\n", i, i)) + } else { + s.term.Write(fmt.Sprintf("[%02d] ledger page %d copied\r\n", i, i)) + } + } + return s + }) + st := *s + codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) }) + ui.Column(c).Width(600).Gap(8).Children(func() { + if mujica.TerminalSearch(c, &st.term, &st.search, mujica.TerminalSearchOptions{Disabled: st.disabled}).Changed() { + log(fmt.Sprintf("query %q, match %d", st.search.Query, st.search.Current+1)) + } + mujica.Terminal(c, &st.term, mujica.TerminalOptions{}).Height(220) + }) +} + +func codeCommandHistoryDemo(c *ui.Context, log func(string)) { + type state struct { + entries []mujica.HistoryEntry + s mujica.CommandHistoryState + disabled bool + } + s := ui.Local(c.Root(), "324", func() *state { + at := time.Date(2026, 10, 5, 9, 0, 0, 0, time.UTC) + var e []mujica.HistoryEntry + for i, cmd := range []string{"git pull", "go build ./...", "go test ./...", "make seal", "ls -la", "git status"} { + e = append(e, mujica.HistoryEntry{Command: cmd, Time: at.Add(time.Duration(i) * time.Minute)}) + } + e[3].ExitCode = 2 + return &state{entries: e} + }) + st := *s + codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) }) + r := mujica.CommandHistory(c, st.entries, &st.s, mujica.CommandHistoryOptions{Disabled: st.disabled}) + r.Element.Size(480, 300) + if r.Replayed != nil { + log("replay " + r.Replayed.Command) + st.entries = append(st.entries, mujica.HistoryEntry{Command: r.Replayed.Command, Time: time.Now()}) + } +} + +func codeLogViewerDemo(c *ui.Context, log func(string)) { + type state struct { + lines []mujica.LogLine + s mujica.LogViewerState + disabled bool + } + s := ui.Local(c.Root(), "325", func() *state { + at := time.Date(2026, 10, 5, 9, 0, 0, 0, time.UTC) + lines := make([]mujica.LogLine, 100_000) + words := []string{"ledger synced", "seal applied", "herald dispatched", "archive rotated"} + for i := range lines { + lines[i] = mujica.LogLine{Time: at.Add(time.Duration(i) * time.Second), Level: mujica.LogLevel(i % 7 % 4), Text: fmt.Sprintf("%s #%d", words[i%4], i)} + } + return &state{lines: lines} + }) + st := *s + codeDemoControls(c, func() { + codeDemoCheck(c, &st.disabled, "Disabled", log) + if mujica.Button(c, "Append line", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + st.lines = append(st.lines, mujica.LogLine{Time: time.Now(), Level: mujica.LogWarn, Text: fmt.Sprintf("late seal #%d", len(st.lines))}) + log("append") + } + }) + r := mujica.LogViewer(c, st.lines, &st.s, mujica.LogViewerOptions{Disabled: st.disabled}) + r.Element.Size(720, 360) + if r.Changed() { + log(fmt.Sprintf("hidden %v, follow %v", st.s.Hidden, st.s.Follow)) + } +} diff --git a/examples/gallery/pages_code_debug.go b/examples/gallery/pages_code_debug.go new file mode 100644 index 0000000..a6e91a2 --- /dev/null +++ b/examples/gallery/pages_code_debug.go @@ -0,0 +1,238 @@ +package main + +import ( + "fmt" + "strings" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func codeSymbolDemo(c *ui.Context, log func(string)) { + type state struct { + s mujica.SymbolOutlineState + cursor float64 + disabled bool + } + s := ui.Local(c.Root(), "333", func() *state { return &state{cursor: 15} }) + st := *s + codeDemoControls(c, func() { + codeDemoCheck(c, &st.disabled, "Disabled", log) + ui.Text(c, fmt.Sprintf("Cursor line %.0f", st.cursor)) + if mujica.Slider(c, &st.cursor, mujica.SliderOptions{Min: 1, Max: 34, Step: 1}).Changed() { + log(fmt.Sprintf("cursor %.0f", st.cursor)) + } + }) + symbols := []mujica.Symbol{ + {Name: "Decree", Kind: mujica.SymbolType, Line: 6, EndLine: 9, Detail: "struct", Children: []mujica.Symbol{ + {Name: "ID", Kind: mujica.SymbolField, Line: 7, EndLine: 7, Detail: "int"}, + {Name: "Title", Kind: mujica.SymbolField, Line: 8, EndLine: 8, Detail: "string"}, + }}, + {Name: "Seal", Kind: mujica.SymbolFunction, Line: 13, EndLine: 21, Detail: "(d Decree) (string, error)"}, + {Name: "Herald", Kind: mujica.SymbolFunction, Line: 23, EndLine: 31, Detail: "(ds []Decree) int"}, + } + r := mujica.SymbolOutline(c, symbols, &st.s, mujica.SymbolOutlineOptions{CursorLine: int(st.cursor), Disabled: st.disabled}) + r.Element.Size(420, 320) + if r.Jumped != nil { + log(fmt.Sprintf("jump to %s, line %d", r.Jumped.Name, r.Jumped.Line)) + } +} + +func codeCompletionDemo(c *ui.Context, log func(string)) { + type state struct { + text string + open bool + s mujica.CompletionMenuState + disabled bool + } + s := ui.Local(c.Root(), "334", func() *state { return &state{} }) + st := *s + codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) }) + all := []mujica.Completion{ + {Label: "Seal", Kind: mujica.SymbolFunction, Detail: "func(d Decree) (string, error)", Doc: "Seal stamps a decree with the royal wax."}, + {Label: "Search", Kind: mujica.SymbolFunction, Detail: "func(q string) []Decree"}, + {Label: "Season", Kind: mujica.SymbolConstant, Detail: "= 4"}, + {Label: "Herald", Kind: mujica.SymbolFunction, Detail: "func(ds []Decree) int"}, + {Label: "Decree", Kind: mujica.SymbolType, Detail: "struct", Doc: "Decree is an order of the court."}, + } + word := st.text[strings.LastIndexAny(st.text, " .(")+1:] + var items []mujica.Completion + for _, it := range all { + if word != "" && strings.HasPrefix(strings.ToLower(it.Label), strings.ToLower(word)) { + items = append(items, it) + } + } + ui.Column(c).Width(420).Gap(8).Children(func() { + ui.Text(c, "Type “se” or “de” to see suggestions.").TextColor(mujica.Tokens(c).TextMuted) + in := mujica.TextInput(c, &st.text, mujica.TextInputOptions{Label: "Code", Placeholder: "court.", Disabled: st.disabled}) + if in.Changed() { + st.open = len(items) > 0 + } + r := mujica.CompletionMenu(c, in.Input, &st.open, items, &st.s, mujica.CompletionMenuOptions{Disabled: st.disabled}) + if r.Accepted != nil { + st.text = st.text[:len(st.text)-len(word)] + r.Accepted.Label + log("accept " + r.Accepted.Label) + } + }) +} + +func codeDebugDemo(c *ui.Context, log func(string)) { + type state struct { + dbg mujica.DebugState + disabled bool + } + s := ui.Local(c.Root(), "335", func() *state { return &state{dbg: mujica.DebugPaused} }) + st := *s + names := []string{"Stopped", "Running", "Paused"} + codeDemoControls(c, func() { + codeDemoCheck(c, &st.disabled, "Disabled", log) + ui.Text(c, "State: "+names[st.dbg]) + }) + a := mujica.DebugToolbar(c, st.dbg, mujica.DebugToolbarOptions{Disabled: st.disabled}).Action + switch a { + case mujica.DebugNone: + return + case mujica.DebugContinue, mujica.DebugRestart: + st.dbg = mujica.DebugRunning + case mujica.DebugPause, mujica.DebugStepOver, mujica.DebugStepInto, mujica.DebugStepOut: + st.dbg = mujica.DebugPaused + case mujica.DebugStop: + st.dbg = mujica.DebugStopped + } + log(fmt.Sprintf("action %d, now %s", a, names[st.dbg])) +} + +func codeBreakpointDemo(c *ui.Context, log func(string)) { + type state struct { + bps []mujica.Breakpoint + disabled bool + } + s := ui.Local(c.Root(), "336", func() *state { + return &state{bps: []mujica.Breakpoint{ + {ID: "1", File: "court/seal.go", Line: 14, Enabled: true}, + {ID: "2", File: "court/ledger.go", Line: 40, Condition: "n > 3"}, + {ID: "3", File: "main.go", Line: 9, Enabled: true}, + }} + }) + st := *s + codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) }) + r := mujica.BreakpointList(c, &st.bps, mujica.BreakpointListOptions{Disabled: st.disabled}) + r.Element.Size(480, 240) + for _, e := range []struct{ what, id string }{{"toggled", r.Toggled}, {"condition", r.Edited}, {"open", r.Opened}} { + if e.id != "" { + log(e.what + " " + e.id) + } + } +} + +func codeCallStackDemo(c *ui.Context, log func(string)) { + type state struct { + s mujica.CallStackState + disabled bool + } + s := ui.Local(c.Root(), "337", func() *state { return &state{s: mujica.CallStackState{Current: "f1"}} }) + st := *s + codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) }) + threads := []mujica.DebugThread{ + {ID: "t1", Name: "main", Frames: []mujica.StackFrame{ + {ID: "f1", Name: "court.Seal", File: "court/seal.go", Line: 14}, + {ID: "f2", Name: "court.Herald", File: "court/seal.go", Line: 27}, + {ID: "f3", Name: "main.main", File: "main.go", Line: 9}, + }}, + {ID: "t2", Name: "ledger writer", Frames: []mujica.StackFrame{{ID: "f4", Name: "ledger.Flush", File: "ledger/write.go", Line: 51}}}, + } + r := mujica.CallStack(c, threads, &st.s, mujica.CallStackOptions{Disabled: st.disabled}) + r.Element.Size(440, 300) + if r.Changed() { + log("frame " + st.s.Current) + } +} + +func codeVariablesDemo(c *ui.Context, log func(string)) { + type state struct { + vars []mujica.Variable + s mujica.VariablesPanelState + disabled bool + } + s := ui.Local(c.Root(), "338", func() *state { + return &state{vars: []mujica.Variable{ + {Name: "d", Type: "court.Decree", Value: "{…}", Children: []mujica.Variable{ + {Name: "ID", Value: "42", Type: "int", Changed: true}, + {Name: "Title", Value: `"Of seals"`, Type: "string"}, + }}, + {Name: "i", Value: "2", Type: "int", Changed: true}, + {Name: "err", Value: "nil", Type: "error"}, + }} + }) + st := *s + codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) }) + r := mujica.VariablesPanel(c, st.vars, &st.s, mujica.VariablesPanelOptions{Disabled: st.disabled}) + r.Element.Size(440, 260) + if r.Edited != nil { + log(fmt.Sprintf("set %s = %s", r.Edited.Path, r.Edited.Value)) + codeDemoSet(st.vars, strings.Split(r.Edited.Path, "."), r.Edited.Value) + } +} + +// codeDemoSet writes value at the dotted path. +func codeDemoSet(vars []mujica.Variable, path []string, value string) { + for i := range vars { + if vars[i].Name != path[0] { + continue + } + if len(path) == 1 { + vars[i].Value, vars[i].Changed = value, true + return + } + codeDemoSet(vars[i].Children, path[1:], value) + } +} + +func codeHexDemo(c *ui.Context, log func(string)) { + type state struct { + s mujica.HexViewerState + disabled bool + } + s := ui.Local(c.Root(), "339", func() *state { return &state{} }) + st := *s + codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) }) + data := []byte(strings.Join(codeDemoSource, "\n")) + r := mujica.HexViewer(c, data, &st.s, mujica.HexViewerOptions{Disabled: st.disabled}) + r.Element.Size(720, 300) + if r.Changed() { + a, b := st.s.Selection() + log(fmt.Sprintf("bytes %d..%d", a, b)) + } +} + +func codeFlamegraphDemo(c *ui.Context, log func(string)) { + type state struct { + s mujica.FlamegraphState + status string + disabled bool + } + s := ui.Local(c.Root(), "340", func() *state { return &state{status: "Ready"} }) + st := *s + codeDemoControls(c, func() { + codeDemoCheck(c, &st.disabled, "Disabled", log) + opts := []mujica.SelectOption[string]{{Value: "Ready", Label: "Ready"}, {Value: "Loading", Label: "Loading"}, {Value: "Failed", Label: "Failed"}} + if mujica.Select(c, &st.status, opts, mujica.SelectOptions{Label: "Status"}).Changed() { + log("status " + st.status) + } + }) + root := &mujica.FlameNode{Name: "main", Value: 240, Children: []mujica.FlameNode{ + {Name: "court.Herald", Value: 150, Children: []mujica.FlameNode{ + {Name: "court.Seal", Value: 110, Children: []mujica.FlameNode{{Name: "wax.Melt", Value: 70}, {Name: "ink.Dry", Value: 25}}}, + {Name: "ledger.Write", Value: 30}, + }}, + {Name: "archive.Load", Value: 60, Children: []mujica.FlameNode{{Name: "json.Decode", Value: 45}}}, + {Name: "gc", Value: 20}, + }} + status := map[string]mujica.DataStatus{"Ready": mujica.DataReady, "Loading": mujica.DataLoading, "Failed": mujica.DataFailed}[st.status] + ui.Column(c).Width(680).Children(func() { + if mujica.Flamegraph(c, root, &st.s, mujica.FlamegraphOptions{Unit: "ms", Status: status, Error: "Profile could not be read", Disabled: st.disabled}).Changed() { + log(fmt.Sprintf("zoom %v focus %v", st.s.Zoom, st.s.Focus)) + } + }) +} diff --git a/examples/gallery/pages_code_snippets.go b/examples/gallery/pages_code_snippets.go new file mode 100644 index 0000000..3cff0a4 --- /dev/null +++ b/examples/gallery/pages_code_snippets.go @@ -0,0 +1,230 @@ +package main + +// Snippets are the bodies of the Example functions in example_code_test.go. + +const codeTerminalCode = `var term mujica.TerminalState +term.Write("\x1b[1m~/court\x1b[0m $ ls\r\n\x1b[34mdecrees\x1b[0m ledger.txt\r\n$ ") +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Terminal(c, &term, mujica.TerminalOptions{ + Input: func(data string) { fmt.Printf("to pty: %q\n", data) }, + Resized: func(cols, rows int) { fmt.Println("pty size", cols, rows) }, + }).Size(380, 200) +} +ui.Render(view, 400, 300, 1)` + +const codeTerminalTabsCode = `tabs := []mujica.TerminalTab{{ID: "a", Title: "zsh"}, {ID: "b", Title: "build", Busy: true}} +active := "a" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.TerminalTabs(c, &tabs, &active, mujica.TerminalTabsOptions{}, func(id string) { + ui.Text(c, "terminal "+id) + }) + if r.Closed != "" { + fmt.Println("close pty", r.Closed) + } +} +ui.Render(view, 400, 300, 1)` + +const codeTerminalSearchCode = `var term mujica.TerminalState +term.Write("build ok\r\nerror: missing seal\r\n") +var search mujica.TerminalSearchState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + ui.Column(c).Gap(8).Children(func() { + mujica.TerminalSearch(c, &term, &search, mujica.TerminalSearchOptions{}) + mujica.Terminal(c, &term, mujica.TerminalOptions{}).Height(160) + }) +} +ui.Render(view, 400, 300, 1)` + +const codeCommandHistoryCode = `history := []mujica.HistoryEntry{{Command: "git status"}, {Command: "go test ./...", ExitCode: 1}} +var state mujica.CommandHistoryState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CommandHistory(c, history, &state, mujica.CommandHistoryOptions{}) + r.Element.Height(240) + if r.Replayed != nil { + fmt.Println("run", r.Replayed.Command) + } +} +ui.Render(view, 400, 300, 1)` + +const codeLogViewerCode = `lines := []mujica.LogLine{{Level: mujica.LogInfo, Text: "court opened"}, {Level: mujica.LogError, Text: "seal missing"}} +var state mujica.LogViewerState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.LogViewer(c, lines, &state, mujica.LogViewerOptions{}).Element.Height(240) +} +ui.Render(view, 400, 300, 1)` + +const codeProcessListCode = `procs := []mujica.Process{{PID: 7, Name: "archivist", CPU: 42, Memory: 50 << 20}, {PID: 9, Name: "herald", CPU: 3, Memory: 8 << 20}} +var state mujica.ProcessListState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ProcessList(c, procs, &state, mujica.ProcessListOptions{}) + r.Element.Height(240) + if r.End != nil { + fmt.Println("kill", r.End.PID) + } +} +ui.Render(view, 400, 300, 1)` + +const codeCodeViewerCode = `lines := []string{"func Seal(d string) int {", "\treturn len(d)", "}"} +var state mujica.CodeViewerState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CodeViewer(c, lines, &state, mujica.CodeViewerOptions{Language: "go"}).Element.Height(240) +} +ui.Render(view, 400, 300, 1)` + +const codeMinimapCode = `lines := []string{"package court", "", "func Seal() {}", "func Herald() {}"} +view := mujica.MinimapView{Top: 0, Visible: 2} +draw := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.Minimap(c, lines, &view, mujica.MinimapOptions{Language: "go"}).Changed() { + fmt.Println("scroll editor to", view.Top) + } +} +ui.Render(draw, 400, 300, 1)` + +const codeFindWidgetCode = `text := "the seal and the seal" +state := mujica.FindState{Query: "seal", Replacement: "signet", ShowReplace: true} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.FindWidget(c, &text, &state, mujica.FindWidgetOptions{}).Replaced > 0 { + fmt.Println(text) + } +} +ui.Render(view, 400, 300, 1)` + +const codeSearchPanelCode = `results := []mujica.SearchFileResult{{Path: "court/seal.go", Matches: []mujica.SearchMatch{{Line: 12, Text: "func Seal() {", Start: 5, End: 9}}}} +state := mujica.SearchPanelState{Query: "seal"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.SearchPanel(c, results, &state, mujica.SearchPanelOptions{}) + r.Element.Height(280) + if r.Opened != nil { + fmt.Println("open", r.Opened.Path, r.Opened.Line) + } +} +ui.Render(view, 400, 300, 1)` + +const codeProblemsPanelCode = `problems := []mujica.Problem{{Severity: mujica.ProblemError, File: "court/seal.go", Line: 12, Col: 5, Message: "undefined: Decree"}} +var state mujica.ProblemsPanelState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.ProblemsPanel(c, problems, &state, mujica.ProblemsPanelOptions{}) + r.Element.Height(240) + if r.Opened != nil { + fmt.Println("go to", r.Opened.File, r.Opened.Line) + } +} +ui.Render(view, 400, 300, 1)` + +const codeOutputPanelCode = `channels := []mujica.OutputChannel{{Name: "Build", Lines: []string{"compiling court", "\x1b[32mok\x1b[0m"}}} +var state mujica.OutputPanelState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.OutputPanel(c, channels, &state, mujica.OutputPanelOptions{}) + r.Element.Height(240) + if r.Cleared != "" { + channels[state.Channel].Lines = nil + } +} +ui.Render(view, 400, 300, 1)` + +const codeSymbolOutlineCode = `symbols := []mujica.Symbol{{Name: "Court", Kind: mujica.SymbolType, Line: 3, EndLine: 40, Children: []mujica.Symbol{ + {Name: "Seal", Kind: mujica.SymbolMethod, Line: 10, EndLine: 20}, +}}} +var state mujica.SymbolOutlineState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.SymbolOutline(c, symbols, &state, mujica.SymbolOutlineOptions{CursorLine: 12}) + r.Element.Height(240) + if r.Jumped != nil { + fmt.Println("go to line", r.Jumped.Line) + } +} +ui.Render(view, 400, 300, 1)` + +const codeCompletionMenuCode = `text := "se" +open := true +items := []mujica.Completion{{Label: "Seal", Kind: mujica.SymbolMethod, Detail: "func()"}, {Label: "Search", Kind: mujica.SymbolFunction}} +var state mujica.CompletionMenuState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + in := mujica.TextInput(c, &text, mujica.TextInputOptions{Label: "Code"}) + if r := mujica.CompletionMenu(c, in.Input, &open, items, &state, mujica.CompletionMenuOptions{}); r.Accepted != nil { + text = r.Accepted.Label + } +} +ui.Render(view, 400, 300, 1)` + +const codeDebugToolbarCode = `state := mujica.DebugPaused +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + switch mujica.DebugToolbar(c, state, mujica.DebugToolbarOptions{}).Action { + case mujica.DebugContinue: + state = mujica.DebugRunning + case mujica.DebugStop: + state = mujica.DebugStopped + } +} +ui.Render(view, 400, 300, 1)` + +const codeBreakpointListCode = `bps := []mujica.Breakpoint{{ID: "a", File: "court/seal.go", Line: 12, Enabled: true}, {ID: "b", File: "main.go", Line: 9, Condition: "n > 3"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.BreakpointList(c, &bps, mujica.BreakpointListOptions{}) + r.Element.Height(200) + if r.Toggled != "" || r.Edited != "" { + fmt.Println("sync breakpoints with the debugger") + } +} +ui.Render(view, 400, 300, 1)` + +const codeCallStackCode = `threads := []mujica.DebugThread{{ID: "t1", Name: "main", Frames: []mujica.StackFrame{ + {ID: "f1", Name: "court.Seal", File: "court/seal.go", Line: 14}, + {ID: "f2", Name: "main.main", File: "main.go", Line: 9}, +}}} +state := mujica.CallStackState{Current: "f1"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.CallStack(c, threads, &state, mujica.CallStackOptions{}) + r.Element.Height(200) + if r.Changed() { + fmt.Println("show frame", state.Current) + } +} +ui.Render(view, 400, 300, 1)` + +const codeVariablesPanelCode = `vars := []mujica.Variable{{Name: "decree", Value: "{…}", Children: []mujica.Variable{{Name: "id", Value: "42", Changed: true}}}, {Name: "count", Value: "7"}} +var state mujica.VariablesPanelState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.VariablesPanel(c, vars, &state, mujica.VariablesPanelOptions{}) + r.Element.Height(200) + if r.Edited != nil { + fmt.Println("set", r.Edited.Path, "=", r.Edited.Value) + } +} +ui.Render(view, 400, 300, 1)` + +const codeHexViewerCode = `data := []byte("MUJICA court ledger\x00\x01") +var state mujica.HexViewerState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.HexViewer(c, data, &state, mujica.HexViewerOptions{}).Element.Height(160) +} +ui.Render(view, 400, 300, 1)` + +const codeFlamegraphCode = `root := &mujica.FlameNode{Name: "main", Value: 100, Children: []mujica.FlameNode{ + {Name: "court.Seal", Value: 60}, {Name: "ledger.Write", Value: 30}, +}} +var state mujica.FlamegraphState +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.Flamegraph(c, root, &state, mujica.FlamegraphOptions{Unit: "ms"}) +} +ui.Render(view, 400, 300, 1)` diff --git a/examples/gallery/pages_code_tools.go b/examples/gallery/pages_code_tools.go new file mode 100644 index 0000000..16357dc --- /dev/null +++ b/examples/gallery/pages_code_tools.go @@ -0,0 +1,264 @@ +package main + +import ( + "fmt" + "strings" + + "github.com/egoist/mygo/ui" + + mujica "mujicaui" +) + +func codeProcessListDemo(c *ui.Context, log func(string)) { + type state struct { + procs []mujica.Process + s mujica.ProcessListState + disabled bool + } + s := ui.Local(c.Root(), "326", func() *state { + return &state{procs: []mujica.Process{ + {PID: 101, Name: "chancellor", CPU: 3.5, Memory: 200 << 20}, {PID: 7, Name: "archivist", CPU: 42.1, Memory: 50 << 20}, + {PID: 330, Name: "herald", CPU: 0.2, Memory: 2 << 30}, {PID: 412, Name: "scribe", CPU: 12.8, Memory: 96 << 20}, + }} + }) + st := *s + codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) }) + r := mujica.ProcessList(c, st.procs, &st.s, mujica.ProcessListOptions{Disabled: st.disabled}) + r.Element.Size(560, 260) + if r.End != nil { + log(fmt.Sprintf("end %s (PID %d)", r.End.Name, r.End.PID)) + var kept []mujica.Process + for _, p := range st.procs { + if p.PID != r.End.PID { + kept = append(kept, p) + } + } + st.procs = kept + } +} + +var codeDemoSource = strings.Split(`package court + +import "errors" + +// Decree is an order of the court. +type Decree struct { + ID int + Title string +} + +/* Seal stamps a decree + with the royal wax. */ +func Seal(d Decree) (string, error) { + if d.Title == "" { + return "", errors.New("untitled decree") + } + for i := 0; i < 3; i++ { + d.ID += i + } + return "sealed: " + d.Title, nil +} + +func Herald(ds []Decree) int { + n := 0 + for _, d := range ds { + if _, err := Seal(d); err == nil { + n++ + } + } + return n +}`, "\n") + +func codeCodeViewerDemo(c *ui.Context, log func(string)) { + type state struct { + s mujica.CodeViewerState + lang string + disabled bool + } + s := ui.Local(c.Root(), "327", func() *state { return &state{lang: "go"} }) + st := *s + codeDemoControls(c, func() { + codeDemoCheck(c, &st.disabled, "Disabled", log) + langs := []mujica.SelectOption[string]{{Value: "go", Label: "Go"}, {Value: "", Label: "Plain"}} + if mujica.Select(c, &st.lang, langs, mujica.SelectOptions{Label: "Language"}).Changed() { + log("language " + st.lang) + } + if mujica.Button(c, "Go to line 20", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + st.s.GoTo(19) + log("go to 20") + } + }) + r := mujica.CodeViewer(c, codeDemoSource, &st.s, mujica.CodeViewerOptions{Language: st.lang, Label: "Source", Disabled: st.disabled}) + r.Element.Size(600, 360) + if r.Changed() { + log(fmt.Sprintf("line %d", st.s.Line()+1)) + } +} + +func codeMinimapDemo(c *ui.Context, log func(string)) { + type state struct { + s mujica.CodeViewerState + view mujica.MinimapView + lines []string + disabled bool + } + s := ui.Local(c.Root(), "328", func() *state { + var lines []string + for range 12 { + lines = append(lines, codeDemoSource...) + } + return &state{lines: lines} + }) + st := *s + codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) }) + first, last := st.s.Visible() + st.view = mujica.MinimapView{Top: first, Visible: max(last-first+1, 1)} + ui.Row(c).Gap(8).Height(360).AlignItems(ui.Stretch).Children(func() { + mujica.CodeViewer(c, st.lines, &st.s, mujica.CodeViewerOptions{Language: "go"}).Element.Width(520) + if mujica.Minimap(c, st.lines, &st.view, mujica.MinimapOptions{Language: "go", Disabled: st.disabled}).Changed() { + st.s.ScrollTo(st.view.Top) + log(fmt.Sprintf("jump to line %d", st.view.Top+1)) + } + }) +} + +func codeFindWidgetDemo(c *ui.Context, log func(string)) { + type state struct { + text string + s mujica.FindState + readOnly, disabled bool + } + s := ui.Local(c.Root(), "329", func() *state { + return &state{text: "The seal of the court; seals are kept sealed. Seal 42 and seal 7.", s: mujica.FindState{Query: "seal"}} + }) + st := *s + codeDemoControls(c, func() { + codeDemoCheck(c, &st.readOnly, "Read-only", log) + codeDemoCheck(c, &st.disabled, "Disabled", log) + }) + ui.Column(c).Width(620).Gap(12).Children(func() { + r := mujica.FindWidget(c, &st.text, &st.s, mujica.FindWidgetOptions{ReadOnly: st.readOnly, Disabled: st.disabled}) + if r.Moved { + log(fmt.Sprintf("%d matches, at %d", len(st.s.Matches()), st.s.Current+1)) + } + if r.Replaced > 0 { + log(fmt.Sprintf("replaced %d", r.Replaced)) + } + var spans []ui.Span + at := 0 + for i, m := range st.s.Matches() { + spans = append(spans, ui.Span{Text: st.text[at:m[0]]}) + sp := ui.Span{Text: st.text[m[0]:m[1]], Background: mujica.Tokens(c).Selection, Underline: true} + if i == st.s.Current { + sp.Weight = 700 + } + spans = append(spans, sp) + at = m[1] + } + spans = append(spans, ui.Span{Text: st.text[at:]}) + ui.RichText(c, spans...) + }) +} + +func codeSearchPanelDemo(c *ui.Context, log func(string)) { + type state struct { + s mujica.SearchPanelState + results []mujica.SearchFileResult + disabled bool + } + s := ui.Local(c.Root(), "330", func() *state { return &state{s: mujica.SearchPanelState{Query: "seal"}} }) + st := *s + codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) }) + // The demo searches its own two files. + files := map[string][]string{"court/seal.go": codeDemoSource, "docs/ledger.md": {"# Ledger", "The seal is kept by the chancellor.", "Seals expire after a year."}} + if st.results == nil || st.s.Query != "" && len(st.results) == 0 { + st.results = codeDemoSearch(files, st.s.Query, st.s.Include, st.s.Exclude) + } + r := mujica.SearchPanel(c, st.results, &st.s, mujica.SearchPanelOptions{Disabled: st.disabled}) + r.Element.Size(560, 380) + if r.Changed { + st.results = codeDemoSearch(files, st.s.Query, st.s.Include, st.s.Exclude) + log(fmt.Sprintf("search %q include %q exclude %q", st.s.Query, st.s.Include, st.s.Exclude)) + } + if r.Opened != nil { + log(fmt.Sprintf("open %s:%d", r.Opened.Path, r.Opened.Line)) + } +} + +// codeDemoSearch finds q in the demo files. +func codeDemoSearch(files map[string][]string, q, include, exclude string) []mujica.SearchFileResult { + out := []mujica.SearchFileResult{} + if q == "" { + return out + } + for _, path := range []string{"court/seal.go", "docs/ledger.md"} { + if include != "" && !strings.Contains(path, strings.Trim(include, "*")) || exclude != "" && strings.Contains(path, strings.Trim(exclude, "*")) { + continue + } + f := mujica.SearchFileResult{Path: path} + for i, line := range files[path] { + if at := strings.Index(strings.ToLower(line), strings.ToLower(q)); at >= 0 { + f.Matches = append(f.Matches, mujica.SearchMatch{Line: i + 1, Text: line, Start: at, End: at + len(q)}) + } + } + if len(f.Matches) > 0 { + out = append(out, f) + } + } + return out +} + +func codeProblemsDemo(c *ui.Context, log func(string)) { + type state struct { + s mujica.ProblemsPanelState + disabled bool + } + s := ui.Local(c.Root(), "331", func() *state { return &state{} }) + st := *s + codeDemoControls(c, func() { codeDemoCheck(c, &st.disabled, "Disabled", log) }) + problems := []mujica.Problem{ + {Severity: mujica.ProblemError, File: "court/seal.go", Line: 12, Col: 5, Message: "undefined: Decree", Source: "compiler"}, + {Severity: mujica.ProblemWarning, File: "court/seal.go", Line: 30, Col: 2, Message: "unused variable wax", Source: "vet"}, + {Severity: mujica.ProblemInfo, File: "docs/ledger.md", Line: 4, Col: 1, Message: "line is longer than 80", Source: "lint"}, + {Severity: mujica.ProblemError, File: "main.go", Line: 9, Col: 14, Message: "missing return", Source: "compiler"}, + } + r := mujica.ProblemsPanel(c, problems, &st.s, mujica.ProblemsPanelOptions{Disabled: st.disabled}) + r.Element.Size(620, 320) + if r.Opened != nil { + log(fmt.Sprintf("go to %s:%d:%d", r.Opened.File, r.Opened.Line, r.Opened.Col)) + } +} + +func codeOutputDemo(c *ui.Context, log func(string)) { + type state struct { + channels []mujica.OutputChannel + s mujica.OutputPanelState + disabled bool + } + s := ui.Local(c.Root(), "332", func() *state { + var build []string + for i := range 300 { + build = append(build, fmt.Sprintf("compiling unit %d of 300", i+1)) + } + return &state{channels: []mujica.OutputChannel{{Name: "Build", Lines: build}, + {Name: "Tests", Lines: []string{"\x1b[32mPASS\x1b[0m court/seal", "\x1b[31mFAIL\x1b[0m court/ledger: expected 3 seals", "\x1b[1mok\x1b[0m 2 of 3 packages"}}}} + }) + st := *s + codeDemoControls(c, func() { + codeDemoCheck(c, &st.disabled, "Disabled", log) + if mujica.Button(c, "Write line", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + ch := &st.channels[st.s.Channel] + ch.Lines = append(ch.Lines, fmt.Sprintf("line %d", len(ch.Lines)+1)) + log("write to " + ch.Name) + } + }) + r := mujica.OutputPanel(c, st.channels, &st.s, mujica.OutputPanelOptions{Disabled: st.disabled}) + r.Element.Size(560, 300) + if r.Changed { + log("channel " + st.channels[st.s.Channel].Name) + } + if r.Cleared != "" { + st.channels[st.s.Channel].Lines = nil + log("cleared " + r.Cleared) + } +} diff --git a/find_widget.go b/find_widget.go new file mode 100644 index 0000000..97f8629 --- /dev/null +++ b/find_widget.go @@ -0,0 +1,181 @@ +package mujica + +import ( + "fmt" + "log/slog" + "regexp" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" +) + +// FindState is a FindWidget's query, options and current match. +type FindState struct { + Query, Replacement string + // MatchCase, WholeWord and Regex refine the query. + MatchCase, WholeWord, Regex bool + // ShowReplace opens the replace row. + ShowReplace bool + // Current is the chosen match, from 0. + Current int + matches [][]int + err string + key findKey +} + +type findKey struct { + text, query string + matchCase, word, regex bool + ran bool +} + +// Matches returns the byte ranges of matches. +func (s *FindState) Matches() [][2]int { + out := make([][2]int, len(s.matches)) + for i, m := range s.matches { + out[i] = [2]int{m[0], m[1]} + } + return out +} + +// FindWidgetOptions configure a FindWidget. +type FindWidgetOptions struct { + // ReadOnly hides replacing. + ReadOnly bool + Disabled bool +} + +// FindWidgetResult is a FindWidget and what happened in this frame. +type FindWidgetResult struct { + Element *ui.Element + // Moved reports navigation; Replaced counts replacements. + Moved bool + Replaced int +} + +// FindWidget finds and replaces in *text. +func FindWidget(c *ui.Context, text *string, s *FindState, opts FindWidgetOptions) FindWidgetResult { + if text == nil || s == nil { + panic("mujica: FindWidget needs text and a state") + } + k := Tokens(c) + u := Density(c).Unit() + var res FindWidgetResult + res.Element = codePanel(c).Padding(u * 2).Gap(u * 2).Disabled(opts.Disabled) + disabled := res.Element.IsDisabled() + findRun(*text, s) + res.Element.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + if !opts.ReadOnly { + chev := "chevron-right" + if s.ShowReplace { + chev = "chevron-down" + } + if iconAction(c, icons.Must(chev), msg(c, "find_widget.toggleReplace")).Clicked() && !disabled { + s.ShowReplace = !s.ShowReplace + } + } + r := SearchInput(c, &s.Query, SearchInputOptions{Find: true, Matches: len(s.matches), Current: &s.Current, Disabled: opts.Disabled}) + r.Element.Grow(1).MinWidth(0) + changed := r.Changed() || r.Moved() + for _, o := range []struct { + on *bool + short string + key string + }{{&s.MatchCase, "Aa", "find_widget.case"}, {&s.WholeWord, "ab", "find_widget.word"}, {&s.Regex, ".*", "find_widget.regex"}} { + if Toggle(c, o.on, o.short, ToggleOptions{Label: msg(c, o.key), Disabled: opts.Disabled}).Tooltip(msg(c, o.key)).Changed() { + changed = true + } + } + if changed { + findRun(*text, s) + res.Moved = true + slog.Debug("mujica: find_widget move", "matches", len(s.matches), "current", s.Current) + } + }) + if s.err != "" { + ui.Text(c, fmt.Sprintf(msg(c, "find_widget.invalid"), s.err)).TextColor(k.Danger).Role(ui.RoleStatus). + FontSize(FontSize(c, 12)) + } + if !s.ShowReplace || opts.ReadOnly { + return + } + ui.Row(c).Gap(u*2).AlignItems(ui.Center).Padding(0, 0, 0, 28+u*2).Children(func() { + in := TextInput(c, &s.Replacement, TextInputOptions{Placeholder: msg(c, "find_widget.replace"), Label: msg(c, "find_widget.replace"), Disabled: opts.Disabled}) + in.Element.Grow(1).MinWidth(0) + none := len(s.matches) == 0 + if (Button(c, msg(c, "find_widget.replaceOne"), ButtonOptions{Variant: Secondary, Disabled: none || opts.Disabled}).Clicked() || in.Submitted()) && !none && !disabled { + res.Replaced = findReplace(text, s, false) + } + if Button(c, msg(c, "find_widget.replaceAll"), ButtonOptions{Variant: Secondary, Disabled: none || opts.Disabled}).Clicked() && !disabled { + res.Replaced = findReplace(text, s, true) + } + }) + }) + return res +} + +// findPattern compiles the query with its options. +func findPattern(s *FindState) (*regexp.Regexp, error) { + q := s.Query + if !s.Regex { + q = regexp.QuoteMeta(q) + } + if s.WholeWord { + q = `\b(?:` + q + `)\b` + } + if !s.MatchCase { + q = "(?i)" + q + } + return regexp.Compile(q) +} + +// findRun refinds matches when inputs change. +func findRun(text string, s *FindState) { + key := findKey{text, s.Query, s.MatchCase, s.WholeWord, s.Regex, true} + if key == s.key { + return + } + s.key, s.err, s.matches = key, "", nil + if s.Query != "" { + re, err := findPattern(s) + if err != nil { + s.err = err.Error() + } else { + for _, m := range re.FindAllStringSubmatchIndex(text, -1) { + if m[1] > m[0] { + s.matches = append(s.matches, m) + } + } + } + } + s.Current = max(0, min(s.Current, len(s.matches)-1)) +} + +// findReplace replaces one or all matches. +func findReplace(text *string, s *FindState, all bool) int { + re, err := findPattern(s) + if err != nil { + panic("mujica: FindWidget replaced with an invalid pattern") + } + targets := s.matches + if !all { + targets = s.matches[s.Current : s.Current+1] + } + out := []byte{} + last := 0 + for _, m := range targets { + out = append(out, (*text)[last:m[0]]...) + if s.Regex { + out = re.ExpandString(out, s.Replacement, *text, m) + } else { + out = append(out, s.Replacement...) + } + last = m[1] + } + *text = string(append(out, (*text)[last:]...)) + findRun(*text, s) + slog.Debug("mujica: find_widget replace", "count", len(targets)) + return len(targets) +} diff --git a/find_widget_test.go b/find_widget_test.go new file mode 100644 index 0000000..5a94aef --- /dev/null +++ b/find_widget_test.go @@ -0,0 +1,117 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func findTester(text *string, s *FindState, opts FindWidgetOptions, replaced *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + *replaced += FindWidget(c, text, s, opts).Replaced + }, 640, 200) +} + +func TestFindWidgetOptions(t *testing.T) { + text := "Seal the seal; sealing wax. SEAL" + s := &FindState{Query: "seal"} + n := 0 + tt := findTester(&text, s, FindWidgetOptions{}, &n) + if len(s.Matches()) != 4 || !tt.HasText("1 of 4") { + t.Fatalf("plain matches %d", len(s.Matches())) + } + if err := tt.Click("Match case"); err != nil { + t.Fatal(err) + } + if len(s.Matches()) != 2 { + t.Fatalf("case-sensitive matches %d, want 2", len(s.Matches())) + } + _ = tt.Click("Whole word") + if len(s.Matches()) != 1 || s.Matches()[0][0] != 9 { + t.Fatalf("whole-word matches %v", s.Matches()) + } + _ = tt.Click("Match case") + _ = tt.Click("Whole word") + _ = tt.Click("Regular expression") + s.Query = `seal(ing)?` + tt.Frame() + if len(s.Matches()) != 4 || s.Matches()[2] != [2]int{15, 22} { + t.Fatalf("regex matches %v", s.Matches()) + } +} + +func TestFindWidgetInvalidRegex(t *testing.T) { + text := "abc" + s := &FindState{Query: "a(", Regex: true} + n := 0 + tt := findTester(&text, s, FindWidgetOptions{}, &n) + if len(s.Matches()) != 0 || !tt.HasText("Invalid pattern: error parsing regexp: missing closing ): `(?i)a(`") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestFindWidgetReplace(t *testing.T) { + text := "one cat, two cat, red cat" + s := &FindState{Query: "cat", Replacement: "owl", ShowReplace: true, Current: 1} + n := 0 + tt := findTester(&text, s, FindWidgetOptions{}, &n) + if err := tt.Click("Replace"); err != nil { + t.Fatal(err) + } + if text != "one cat, two owl, red cat" || n != 1 { + t.Fatalf("replace one gave %q (%d)", text, n) + } + if err := tt.Click("Replace all"); err != nil { + t.Fatal(err) + } + if text != "one owl, two owl, red owl" || n != 3 || len(s.Matches()) != 0 { + t.Fatalf("replace all gave %q (%d)", text, n) + } + text, s.Query, s.Regex, s.Replacement = "a1 b2", `([a-z])(\d)`, true, "$2$1" + tt.Frame() + _ = tt.Click("Replace all") + if text != "1a 2b" { + t.Fatalf("regex replace gave %q", text) + } +} + +func TestFindWidgetKeysAndReadOnly(t *testing.T) { + text := "x y x y x" + s := &FindState{} + n := 0 + tt := findTester(&text, s, FindWidgetOptions{ReadOnly: true}, &n) + if tt.HasText("Replace all") { + t.Fatal("read-only widget offers replace") + } + tt.Key(0, ui.KeyTab) + tt.Type("x") + tt.Key(0, ui.KeyEnter) + if s.Current != 1 || !tt.HasText("2 of 3") { + t.Fatalf("Enter went to %d", s.Current) + } +} + +func TestFindWidgetDisabled(t *testing.T) { + text := "cat" + s := &FindState{Query: "cat", Replacement: "dog", ShowReplace: true} + n := 0 + tt := findTester(&text, s, FindWidgetOptions{Disabled: true}, &n) + _ = tt.Click("Replace all") + _ = tt.Click("Match case") + if text != "cat" || s.MatchCase { + t.Fatalf("disabled widget changed %q case=%v", text, s.MatchCase) + } +} + +func TestFindWidgetSnapshot(t *testing.T) { + snapshot(t, "find_widget", 640, 130, func(c *ui.Context) { + st := ui.Local(c.Root(), "snap", func() *FindState { + return &FindState{Query: "seal", Replacement: "signet", ShowReplace: true, WholeWord: true} + }) + text := "the seal and the seal" + ui.Column(c).Padding(12).Children(func() { + FindWidget(c, &text, *st, FindWidgetOptions{}) + }) + }) +} diff --git a/flamegraph.go b/flamegraph.go new file mode 100644 index 0000000..e3e3673 --- /dev/null +++ b/flamegraph.go @@ -0,0 +1,276 @@ +package mujica + +import ( + "fmt" + "hash/fnv" + "log/slog" + "slices" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// FlameNode is a profile frame; Value includes children. +type FlameNode struct { + Name string + Value float64 + Children []FlameNode +} + +// FlamegraphState holds zoom and focus paths and the search. +type FlamegraphState struct { + Zoom, Focus []int + Query string + said string +} + +// FlamegraphOptions configure a Flamegraph. +type FlamegraphOptions struct { + // Unit follows values in the readout, as "ms". + Unit string + // Status shows loading or failure in place of the graph. + Status DataStatus + Error string + Disabled bool +} + +// flameRow is a frame row's height, a full hit target. +const flameRow = theme.MinHitSize + +// flamegraphPalette colors frames at 3:1 on Surface. +func flamegraphPalette(k theme.Tokens) []ui.Color { + // Ornament alone is too faint on ivory. + return []ui.Color{k.AccentText, k.Info, k.Success, k.Warning, k.Ornament.Mix(k.Text, 0.2), k.TextMuted} +} + +// Flamegraph draws a zoomable, searchable profile. +func Flamegraph(c *ui.Context, root *FlameNode, s *FlamegraphState, opts FlamegraphOptions) ChoiceResult { + if s == nil { + panic("mujica: Flamegraph needs a state") + } + k := Tokens(c) + d := Density(c) + var res ChoiceResult + res.Element = codePanel(c).Disabled(opts.Disabled) + res.Element.Children(func() { + codeHeader(c, func() { + SearchInput(c, &s.Query, SearchInputOptions{Placeholder: msg(c, "flamegraph.search"), Disabled: opts.Disabled}).Element.Grow(1) + }) + if root == nil || opts.Status != DataReady { + ui.Column(c).Height(flameRow * 6).Children(func() { + res.changed = dataPlaceholder(c, opts.Status, opts.Error, msg(c, "flamegraph.empty"), msg(c, "flamegraph.empty")) + }) + return + } + flameCheck(root) + if flameAt(root, s.Zoom) == nil { + s.Zoom = nil + } + if flameAt(root, s.Focus) == nil { + s.Focus = nil + } + q := strings.ToLower(strings.TrimSpace(s.Query)) + depth := flameDepth(root) + g := ui.Box(c).Height(float32(depth)*flameRow).Shrink(0).Margin(d.Unit()*2, d.Unit()*3, 0, d.Unit()*3).Focusable().Label(msg(c, "flamegraph.label")) + internal.Ring(g, k.Focus, theme.ControlRadius) + hover := ui.Local(g, "flamegraph.hover", func() []int { return nil }) + zoom, focus := s.Zoom, s.Focus + if !g.IsDisabled() { + if flameInput(c, g, root, s, hover) { + res.changed = true + } + } + b := g.Bounds() + g.Draw(func(p *ui.Painter, r ui.Rect) { + if r.W != b.W { + c.Invalidate() + } + flamePaint(p, r, k, root, zoom, focus, q, g.Focused(), FontSize(c, theme.CaptionSize)) + }) + readout := s.Focus + if *hover != nil { + readout = *hover + } + text := flameReadout(c, root, readout, opts.Unit) + ui.Text(c, text).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Padding(d.Unit(), d.Unit()*3). + Role(ui.RoleStatus).Shrink(0).SingleLine() + if g.Focused() && text != s.said { + s.said = text + c.Announce(text) + } + }) + return res +} + +// flameInput zooms, moves focus and tracks hover. +func flameInput(c *ui.Context, g *ui.Element, root *FlameNode, s *FlamegraphState, hover *[]int) bool { + b := g.Bounds() + x, y, over := g.PointerPosition() + *hover = nil + if over && b.W > 0 { + *hover = flameHit(root, s.Zoom, x/b.W, int(y/flameRow)) + } + changed := false + zoomTo := func(path []int) { + s.Zoom, s.Focus, changed = slices.Clone(path), slices.Clone(path), true + slog.Debug("mujica: flamegraph zoom", "depth", len(path)) + } + if g.Clicked() && *hover != nil { + zoomTo(*hover) + } + f := s.Focus + switch { + case g.Shortcut(0, ui.KeyEnter): + zoomTo(f) + case g.Shortcut(0, ui.KeyEscape) && len(s.Zoom) > 0: + zoomTo(s.Zoom[:len(s.Zoom)-1]) + case g.Shortcut(0, ui.KeyUp) && len(f) > 0: + s.Focus, changed = f[:len(f)-1], true + case g.Shortcut(0, ui.KeyDown): + if n := flameAt(root, f); len(n.Children) > 0 { + s.Focus, changed = append(slices.Clone(f), 0), true + } + case g.Shortcut(0, ui.KeyLeft) && len(f) > 0 && f[len(f)-1] > 0: + s.Focus, changed = append(slices.Clone(f[:len(f)-1]), f[len(f)-1]-1), true + case g.Shortcut(0, ui.KeyRight) && len(f) > 0 && f[len(f)-1] < len(flameAt(root, f[:len(f)-1]).Children)-1: + s.Focus, changed = append(slices.Clone(f[:len(f)-1]), f[len(f)-1]+1), true + } + return changed +} + +// flameCheck panics on impossible values. +func flameCheck(n *FlameNode) { + sum := 0.0 + for i := range n.Children { + flameCheck(&n.Children[i]) + sum += n.Children[i].Value + } + if n.Value < 0 || sum > n.Value*(1+1e-9) { + panic("mujica: FlameNode " + n.Name + " has a negative value or children larger than itself") + } +} + +func flameAt(root *FlameNode, path []int) *FlameNode { + n := root + for _, i := range path { + if i < 0 || i >= len(n.Children) { + return nil + } + n = &n.Children[i] + } + return n +} + +func flameDepth(n *FlameNode) int { + d := 0 + for i := range n.Children { + d = max(d, flameDepth(&n.Children[i])) + } + return d + 1 +} + +// flameSpan returns a frame's fractional left and width. +func flameSpan(root *FlameNode, zoom, path []int) (x, w float64) { + if len(path) <= len(zoom) { + return 0, 1 + } + z := flameAt(root, zoom) + x, w = 0, 1 + n := z + for _, i := range path[len(zoom):] { + for j := range i { + x += w * n.Children[j].Value / max(n.Value, 1e-12) + } + w *= n.Children[i].Value / max(n.Value, 1e-12) + n = &n.Children[i] + } + return x, w +} + +// flameHit finds the frame at fx in row. +func flameHit(root *FlameNode, zoom []int, fx float32, row int) []int { + if row < len(zoom) { + return slices.Clone(zoom[:row]) + } + path := slices.Clone(zoom) + for len(path) < row { + n := flameAt(root, path) + next := -1 + for i := range n.Children { + x, w := flameSpan(root, zoom, append(path, i)) + if float64(fx) >= x && float64(fx) < x+w { + next = i + } + } + if next < 0 { + return nil + } + path = append(path, next) + } + if x, w := flameSpan(root, zoom, path); float64(fx) < x || float64(fx) >= x+w { + return nil + } + return path +} + +func flameColor(k theme.Tokens, name string) ui.Color { + h := fnv.New32a() + h.Write([]byte(name)) + pal := flamegraphPalette(k) + return pal[h.Sum32()%uint32(len(pal))] +} + +// flamePaint draws visible frames with search and focus marks. +func flamePaint(p *ui.Painter, r ui.Rect, k theme.Tokens, root *FlameNode, zoom, focus []int, q string, focused bool, size float32) { + var walk func(n *FlameNode, path []int) + walk = func(n *FlameNode, path []int) { + fx, fw := flameSpan(root, zoom, path) + w := float32(fw) * r.W + if w < 1 { + return + } + box := ui.Rect{X: internal.Snap(p, r.X+float32(fx)*r.W), Y: r.Y + float32(len(path))*flameRow, W: internal.Snap(p, w) - 1, H: flameRow - 2} + col := flameColor(k, n.Name) + face := col.Mix(k.Surface, 0.78) + match := q != "" && strings.Contains(strings.ToLower(n.Name), q) + above := len(path) < len(zoom) + if q != "" && !match || above { + face, col = k.Surface, k.Border + } + p.Fill(box, face, 2) + p.Stroke(box, col, 2, 1) + if match { + p.Stroke(box, k.AccentText, 2, 2) + } + if focused && slices.Equal(path, focus) { + internal.FocusRing(p, box, 2, k.Focus) + } + if box.W > 24 { + fg := k.Text + if above || q != "" && !match { + fg = k.TextMuted + } + p.Clip(box, 2, func() { p.Text(box.X+6, box.Y+(box.H-size*1.3)/2, n.Name, size, fg) }) + } + for i := range n.Children { + if len(path) < len(zoom) && i != zoom[len(path)] { + continue + } + walk(&n.Children[i], append(slices.Clone(path), i)) + } + } + walk(root, nil) +} + +// flameReadout names a frame's time and share. +func flameReadout(c *ui.Context, root *FlameNode, path []int, unit string) string { + n := flameAt(root, path) + if n == nil { + return msg(c, "flamegraph.hint") + } + share := 100 * n.Value / max(root.Value, 1e-12) + return fmt.Sprintf(msg(c, "flamegraph.readout"), n.Name, n.Value, unit, share) +} diff --git a/flamegraph_test.go b/flamegraph_test.go new file mode 100644 index 0000000..ff6cda6 --- /dev/null +++ b/flamegraph_test.go @@ -0,0 +1,143 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +func flameSample() *FlameNode { + return &FlameNode{Name: "main", Value: 100, Children: []FlameNode{ + {Name: "court.Seal", Value: 60, Children: []FlameNode{ + {Name: "wax.Melt", Value: 40}, + {Name: "ink.Dry", Value: 15}, + }}, + {Name: "ledger.Write", Value: 30}, + }} +} + +type flameProbe struct { + root *FlameNode + s FlamegraphState + opts FlamegraphOptions + changed int +} + +func (p *flameProbe) view(c *ui.Context) { + Use(c, Settings{}) + if Flamegraph(c, p.root, &p.s, p.opts).Changed() { + p.changed++ + } +} + +func TestFlamegraphPaletteContrast(t *testing.T) { + for _, k := range []theme.Tokens{theme.Light(), theme.Dark()} { + for i, col := range flamegraphPalette(k) { + if r := theme.Contrast(col, k.Surface); r < 3 { + t.Errorf("dark=%v color %d contrast %.2f < 3", k.Dark, i, r) + } + } + } +} + +func TestFlamegraphClickZoomAndEscape(t *testing.T) { + p := &flameProbe{root: flameSample(), opts: FlamegraphOptions{Unit: "ms"}} + tt := ui.NewTester(p.view, 600, 300) + g, _ := tt.Find("Flame graph") + // Row 1, at 30% of the width, is court.Seal. + tt.ClickAt(g.X+g.W*0.3, g.Y+flameRow*1.5) + if len(p.s.Zoom) != 1 || p.s.Zoom[0] != 0 || p.changed != 1 { + t.Fatalf("zoom %v changed %d", p.s.Zoom, p.changed) + } + if x, w := flameSpan(p.root, p.s.Zoom, []int{0, 0}); x != 0 || w < 0.66 || w > 0.67 { + t.Fatalf("wax.Melt spans %v+%v of the zoomed width", x, w) + } + if !tt.HasText("court.Seal: 60.0 ms, 60.0% of total") { + t.Fatalf("readout %q", tt.Texts()) + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEscape) + if len(p.s.Zoom) != 0 { + t.Fatalf("Escape left zoom %v", p.s.Zoom) + } +} + +func TestFlamegraphKeyboardReadout(t *testing.T) { + p := &flameProbe{root: flameSample(), opts: FlamegraphOptions{Unit: "ms"}} + tt := ui.NewTester(p.view, 600, 300) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyTab) + if !tt.Focused("Flame graph") { + t.Fatal("Tab did not reach the graph") + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyRight) + if len(p.s.Focus) != 2 || p.s.Focus[1] != 1 { + t.Fatalf("focus %v", p.s.Focus) + } + want := "ink.Dry: 15.0 ms, 15.0% of total" + if !tt.HasText(want) { + t.Fatalf("readout %q", tt.Texts()) + } + found := false + for _, a := range tt.Announcements() { + found = found || a == want + } + if !found { + t.Fatalf("readout not announced: %q", tt.Announcements()) + } + tt.Key(0, ui.KeyUp) + tt.Key(0, ui.KeyEnter) + if len(p.s.Zoom) != 1 { + t.Fatalf("Enter zoomed to %v", p.s.Zoom) + } +} + +func TestFlamegraphSearchAndStates(t *testing.T) { + p := &flameProbe{root: flameSample(), s: FlamegraphState{Query: "wax"}} + tt := ui.NewTester(p.view, 600, 300) + if hit := flameHit(p.root, nil, 0.2, 2); len(hit) != 2 || flameAt(p.root, hit).Name != "wax.Melt" { + t.Fatalf("hit %v", hit) + } + _ = tt + p = &flameProbe{opts: FlamegraphOptions{Status: DataFailed, Error: "profile unreadable"}} + tt = ui.NewTester(p.view, 600, 300) + if !tt.HasText("profile unreadable") { + t.Fatalf("texts %q", tt.Texts()) + } + p = &flameProbe{} + tt = ui.NewTester(p.view, 600, 300) + if !tt.HasText("No profile") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestFlamegraphInvalidAndDisabled(t *testing.T) { + p := &flameProbe{root: flameSample(), opts: FlamegraphOptions{Disabled: true}} + tt := ui.NewTester(p.view, 600, 300) + g, _ := tt.Find("Flame graph") + tt.ClickAt(g.X+g.W*0.3, g.Y+flameRow*1.5) + if len(p.s.Zoom) != 0 { + t.Fatal("disabled graph zoomed") + } + defer func() { + if recover() == nil { + t.Fatal("children above their parent did not panic") + } + }() + bad := &FlameNode{Name: "x", Value: 1, Children: []FlameNode{{Name: "y", Value: 2}}} + ui.NewTester((&flameProbe{root: bad}).view, 600, 300) +} + +func TestFlamegraphSnapshot(t *testing.T) { + snapshot(t, "flamegraph", 560, 200, func(c *ui.Context) { + p := ui.Local(c.Root(), "snap", func() *flameProbe { + return &flameProbe{root: flameSample(), s: FlamegraphState{Focus: []int{0, 1}}, opts: FlamegraphOptions{Unit: "ms"}} + }) + ui.Column(c).Padding(12).Children(func() { (*p).view(c) }) + }) +} diff --git a/hex_viewer.go b/hex_viewer.go new file mode 100644 index 0000000..7bce36c --- /dev/null +++ b/hex_viewer.go @@ -0,0 +1,157 @@ +package mujica + +import ( + "fmt" + "log/slog" + "runtime" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// hexPerRow is how many bytes a row shows. +const hexPerRow = 16 + +// HexViewerState is the cursor and selection anchor. +type HexViewerState struct { + // Anchor is where a Shift selection started. + Cursor, Anchor int + rows ui.ListState +} + +// Selection returns the selected byte range, start inclusive, end exclusive. +func (s *HexViewerState) Selection() (start, end int) { + return min(s.Cursor, s.Anchor), max(s.Cursor, s.Anchor) + 1 +} + +// HexViewerOptions configure a HexViewer. +type HexViewerOptions struct { + Disabled bool +} + +// HexViewer shows bytes as synced hex and ASCII columns. +func HexViewer(c *ui.Context, data []byte, s *HexViewerState, opts HexViewerOptions) ChoiceResult { + if s == nil { + panic("mujica: HexViewer needs a state") + } + n := len(data) + if n > 0 && (s.Cursor < 0 || s.Cursor >= n || s.Anchor < 0 || s.Anchor >= n) { + panic("mujica: HexViewer cursor outside the data") + } + k := Tokens(c) + d := Density(c) + cw := codeTextWidth(c, strings.Repeat("0", hexPerRow*3)) / (hexPerRow * 3) + var res ChoiceResult + frame := codePanel(c).Focusable().Disabled(opts.Disabled).Label(msg(c, "hex_viewer.label")) + res.Element = frame + internal.Ring(frame, k.Focus, theme.ControlRadius) + move := func(to int, extend bool) { + to = max(0, min(to, n-1)) + if to == s.Cursor && (extend || s.Anchor == to) { + return + } + s.Cursor = to + if !extend { + s.Anchor = to + } + s.rows.ScrollIntoView(to / hexPerRow) + res.changed = true + slog.Debug("mujica: hex_viewer select", "cursor", s.Cursor, "anchor", s.Anchor) + } + if n > 0 && !frame.IsDisabled() { + hexKeys(c, frame, data, s, move) + } + a, b := s.Selection() + frame.Description(fmt.Sprintf(msg(c, "hex_viewer.at"), s.Cursor, b-a)) + frame.Children(func() { + if n == 0 { + codeCaption(c, msg(c, "hex_viewer.empty")).Padding(d.Unit() * 4) + return + } + rows := (n + hexPerRow - 1) / hexPerRow + ui.List(c, &s.rows, rows, func(r int) { + start := r * hexPerRow + end := min(start+hexPerRow, n) + ui.Row(c).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*3).Gap(cw * 2).AlignItems(ui.Center).Children(func() { + codeMono(c, fmt.Sprintf("%08x", start)).TextColor(k.TextMuted).Shrink(0) + hexColumn(c, s, data, start, end, cw, true, move) + hexColumn(c, s, data, start, end, cw, false, move) + }) + }).Grow(1).MinHeight(d.ControlHeight() * 3) + }) + return res +} + +// hexColumn draws a row's hex or ASCII with marks. +func hexColumn(c *ui.Context, s *HexViewerState, data []byte, start, end int, cw float32, hex bool, move func(int, bool)) { + k := Tokens(c) + var b strings.Builder + step := cw + if hex { + step = 3 * cw + } + for i := start; i < end; i++ { + if hex { + fmt.Fprintf(&b, "%02x ", data[i]) + } else if data[i] >= 0x20 && data[i] < 0x7f { + b.WriteByte(data[i]) + } else { + b.WriteByte('.') + } + } + box := ui.Box(c).Shrink(0).Width(step * hexPerRow).Cursor(ui.CursorText) + lo, hi := s.Selection() + // A hex mark covers the two digits. + mark := step + if hex { + mark = 2 * cw + } + box.Draw(func(p *ui.Painter, r ui.Rect) { + for i := max(lo, start); i < min(hi, end); i++ { + x := r.X + float32(i-start)*step + p.Fill(ui.Rect{X: x - 1, Y: r.Y, W: mark + 2, H: r.H}, k.Selection, 2) + } + if s.Cursor >= start && s.Cursor < end { + x := r.X + float32(s.Cursor-start)*step + p.Stroke(ui.Rect{X: x - 1, Y: r.Y, W: mark + 2, H: r.H}, k.AccentText, 2, 1.5) + } + }) + if box.Clicked() && !box.IsDisabled() { + x, _, _ := box.PointerPosition() + move(start+min(int(x/step), end-start-1), box.ClickModifiers()&ui.Shift != 0) + } + box.Children(func() { codeMono(c, strings.TrimRight(b.String(), " ")) }) +} + +// hexKeys moves, extends and copies the selection. +func hexKeys(c *ui.Context, frame *ui.Element, data []byte, s *HexViewerState, move func(int, bool)) { + copyMods := ui.Cmd + if runtime.GOOS != "darwin" { + copyMods = ui.Ctrl + } + for _, mods := range []ui.Modifiers{0, ui.Shift} { + ext := mods == ui.Shift + switch { + case frame.Shortcut(mods, ui.KeyRight): + move(s.Cursor+1, ext) + case frame.Shortcut(mods, ui.KeyLeft): + move(s.Cursor-1, ext) + case frame.Shortcut(mods, ui.KeyDown): + move(s.Cursor+hexPerRow, ext) + case frame.Shortcut(mods, ui.KeyUp): + move(s.Cursor-hexPerRow, ext) + case frame.Shortcut(mods, ui.KeyHome): + move(s.Cursor/hexPerRow*hexPerRow, ext) + case frame.Shortcut(mods, ui.KeyEnd): + move(s.Cursor/hexPerRow*hexPerRow+hexPerRow-1, ext) + } + } + if frame.Shortcut(copyMods, ui.KeyC) { + a, b := s.Selection() + c.WriteClipboard(fmt.Sprintf("% x", data[a:b])) + slog.Debug("mujica: hex_viewer copy", "bytes", b-a) + } +} diff --git a/hex_viewer_test.go b/hex_viewer_test.go new file mode 100644 index 0000000..609c656 --- /dev/null +++ b/hex_viewer_test.go @@ -0,0 +1,115 @@ +package mujica + +import ( + "strings" + "testing" + + "github.com/egoist/mygo/ui" +) + +type hexProbe struct { + data []byte + s HexViewerState + disabled bool + changed int +} + +func (p *hexProbe) view(c *ui.Context) { + Use(c, Settings{}) + r := HexViewer(c, p.data, &p.s, HexViewerOptions{Disabled: p.disabled}) + r.Element.Height(300) + if r.Changed() { + p.changed++ + } +} + +func TestHexViewerColumns(t *testing.T) { + p := &hexProbe{data: []byte("Court seal\x00\x01 ledger of the realm")} + tt := ui.NewTester(p.view, 760, 320) + for _, s := range []string{"00000000", "00000010", "43 6f 75 72 74 20 73 65 61 6c 00 01 20 6c 65 64", "Court seal.. led"} { + if !tt.HasText(s) { + t.Fatalf("missing %q in %q", s, tt.Texts()) + } + } +} + +func TestHexViewerKeysSelectAndCopy(t *testing.T) { + p := &hexProbe{data: []byte("0123456789abcdefGHIJ")} + tt := ui.NewTester(p.view, 760, 320) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + tt.Key(ui.Shift, ui.KeyRight) + tt.Key(ui.Shift, ui.KeyRight) + if a, b := p.s.Selection(); a != 1 || b != 4 { + t.Fatalf("selection %d..%d", a, b) + } + tt.Key(ui.Cmd, ui.KeyC) + if tt.Clipboard() != "31 32 33" { + t.Fatalf("copied %q", tt.Clipboard()) + } + tt.Key(0, ui.KeyDown) + if p.s.Cursor != 19 || p.s.Anchor != 19 { + t.Fatalf("Down clamped to %d", p.s.Cursor) + } + tt.Key(0, ui.KeyHome) + if p.s.Cursor != 16 { + t.Fatalf("Home gave %d", p.s.Cursor) + } +} + +func TestHexViewerClickSyncsColumns(t *testing.T) { + p := &hexProbe{data: []byte("0123456789abcdef")} + tt := ui.NewTester(p.view, 760, 320) + r, _ := tt.Find("0123456789abcdef") + cw := r.W / 16 + tt.ClickAt(r.X+cw*5.5, r.Y+r.H/2) + if p.s.Cursor != 5 || p.changed != 1 { + t.Fatalf("ASCII click chose %d", p.s.Cursor) + } + h, _ := tt.Find("30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66") + tt.ClickAt(h.X+cw*3*9+cw, h.Y+h.H/2) + if p.s.Cursor != 9 { + t.Fatalf("hex click chose %d", p.s.Cursor) + } +} + +func TestHexViewerLargeIsVirtual(t *testing.T) { + p := &hexProbe{data: make([]byte, 1_600_000)} + tt := ui.NewTester(p.view, 760, 320) + rows := 0 + for _, s := range tt.Texts() { + if len(s) == 8 && strings.Trim(s, "0123456789abcdef") == "" { + rows++ + } + } + if rows == 0 || rows > 40 { + t.Fatalf("built %d of 100000 rows", rows) + } +} + +func TestHexViewerDisabledAndBadCursor(t *testing.T) { + p := &hexProbe{data: []byte("abc"), disabled: true} + tt := ui.NewTester(p.view, 760, 320) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + if p.s.Cursor != 0 { + t.Fatal("disabled viewer moved") + } + defer func() { + if recover() == nil { + t.Fatal("cursor outside data did not panic") + } + }() + ui.NewTester((&hexProbe{data: []byte("a"), s: HexViewerState{Cursor: 4}}).view, 760, 320) +} + +func TestHexViewerSnapshot(t *testing.T) { + snapshot(t, "hex_viewer", 720, 170, func(c *ui.Context) { + p := ui.Local(c.Root(), "snap", func() *hexProbe { + return &hexProbe{data: []byte("MUJICA\x00\x01court ledger\nseal: 42\xff\xfe"), s: HexViewerState{Cursor: 9, Anchor: 6}} + }) + ui.Column(c).Padding(12).Children(func() { + HexViewer(c, (*p).data, &(*p).s, HexViewerOptions{}).Element.Height(146) + }) + }) +} diff --git a/log_viewer.go b/log_viewer.go new file mode 100644 index 0000000..33099db --- /dev/null +++ b/log_viewer.go @@ -0,0 +1,130 @@ +package mujica + +import ( + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// LogLevel is a log line's severity. +type LogLevel int + +const ( + LogDebug LogLevel = iota + LogInfo + LogWarn + LogError +) + +// LogLine is one entry of a LogViewer. +type LogLine struct { + Time time.Time + Level LogLevel + Text string +} + +// LogViewerState is a LogViewer's filters, highlight and place. +type LogViewerState struct { + // Hidden levels are filtered out. + Hidden [4]bool + // Query is highlighted in the shown lines. + Query string + // Follow keeps the newest line in view; it starts on. + Follow bool + rows ui.ListState + shown []int + scanned int + hidden [4]bool + started bool +} + +// LogViewerOptions configure a LogViewer. +type LogViewerOptions struct { + Disabled bool +} + +// LogViewer shows filtered, highlighted log lines, virtualized. +func LogViewer(c *ui.Context, lines []LogLine, s *LogViewerState, opts LogViewerOptions) ChoiceResult { + if s == nil { + panic("mujica: LogViewer needs a state") + } + if !s.started { + s.started, s.Follow = true, true + } + var res ChoiceResult + res.Element = codePanel(c).Disabled(opts.Disabled) + res.Element.Children(func() { + codeHeader(c, func() { + for lv := LogDebug; lv <= LogError; lv++ { + on := !s.Hidden[lv] + if Toggle(c, &on, logViewerName(c, lv), ToggleOptions{Disabled: opts.Disabled}).Changed() { + s.Hidden[lv] = !on + res.changed = true + slog.Debug("mujica: log_viewer level", "level", lv, "shown", on) + } + } + SearchInput(c, &s.Query, SearchInputOptions{Disabled: opts.Disabled, Placeholder: msg(c, "log_viewer.highlight")}).Element.Grow(1).MinWidth(0) + was := s.Follow + if Toggle(c, &s.Follow, msg(c, "log_viewer.follow"), ToggleOptions{Disabled: opts.Disabled}).Changed() { + res.changed = true + slog.Debug("mujica: log_viewer follow", "on", s.Follow) + if s.Follow && !was { + s.rows.ScrollToEnd() + } + } + }) + logViewerFilter(lines, s) + if len(s.shown) == 0 { + codeCaption(c, msg(c, "log_viewer.empty")).Padding(Density(c).Unit() * 4) + return + } + s.rows.FollowEnd = s.Follow + s.rows.Key = func(i int) any { return s.shown[i] } + s.rows.Label = func(i int) string { return lines[s.shown[i]].Text } + d := Density(c) + ui.List(c, &s.rows, len(s.shown), func(i int) { + logViewerRow(c, lines[s.shown[i]], s.Query) + }).Grow(1).MinHeight(d.ControlHeight()*3).Padding(d.Unit(), 0) + }) + return res +} + +// logViewerFilter extends or redoes the shown lines. +func logViewerFilter(lines []LogLine, s *LogViewerState) { + if s.hidden != s.Hidden || s.scanned > len(lines) { + s.hidden, s.scanned, s.shown = s.Hidden, 0, s.shown[:0] + } + for i := s.scanned; i < len(lines); i++ { + lv := lines[i].Level + if lv < LogDebug || lv > LogError { + panic("mujica: LogLine level out of range") + } + if !s.Hidden[lv] { + s.shown = append(s.shown, i) + } + } + s.scanned = len(lines) +} + +func logViewerName(c *ui.Context, lv LogLevel) string { + return msg(c, [...]string{"log_viewer.debug", "log_viewer.info", "log_viewer.warn", "log_viewer.error"}[lv]) +} + +func logViewerRow(c *ui.Context, l LogLine, query string) { + k := Tokens(c) + d := Density(c) + col := [...]ui.Color{k.TextMuted, k.Info, k.Warning, k.Danger}[l.Level] + ui.Row(c).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*3).Gap(d.Unit() * 3).AlignItems(ui.Center).Children(func() { + if !l.Time.IsZero() { + codeMono(c, l.Time.Format("15:04:05.000")).TextColor(k.TextMuted).Shrink(0) + } + ui.Text(c, fmt.Sprintf("%-5s", logViewerName(c, l.Level))).Font(theme.MonoFont).FontSize(FontSize(c, codeSize)). + FontWeight(700).TextColor(col).SingleLine().Shrink(0) + ui.RichText(c, codeMatchSpans(c, l.Text, query)...).Font(theme.MonoFont).FontSize(FontSize(c, codeSize)). + SingleLine().Grow(1).MinWidth(0) + }) +} diff --git a/log_viewer_test.go b/log_viewer_test.go new file mode 100644 index 0000000..7d8c01c --- /dev/null +++ b/log_viewer_test.go @@ -0,0 +1,129 @@ +package mujica + +import ( + "fmt" + "strings" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func logViewerLines(n int) []LogLine { + at := time.Date(2026, 10, 5, 9, 0, 0, 0, time.UTC) + lines := make([]LogLine, n) + for i := range lines { + lines[i] = LogLine{Time: at.Add(time.Duration(i) * time.Millisecond), Level: LogLevel(i % 4), Text: fmt.Sprintf("event %d", i)} + } + return lines +} + +func logViewerTester(lines *[]LogLine, s *LogViewerState, disabled bool) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + LogViewer(c, *lines, s, LogViewerOptions{Disabled: disabled}).Element.Height(400) + }, 760, 420) +} + +func logViewerRows(tt *ui.Tester) int { + n := 0 + for _, s := range tt.Texts() { + if strings.HasPrefix(s, "event ") { + n++ + } + } + return n +} + +func TestLogViewerHundredThousandLines(t *testing.T) { + lines := logViewerLines(100_000) + s := &LogViewerState{} + tt := logViewerTester(&lines, s, false) + if !tt.HasText("event 99999") { + t.Fatal("follow did not start at the tail") + } + if n := logViewerRows(tt); n == 0 || n > 40 { + t.Fatalf("built %d rows of 100000", n) + } + // Hiding a level refilters every line once. + if err := tt.Click("ERROR"); err != nil { + t.Fatal(err) + } + if len(s.shown) != 75_000 || tt.HasText("event 99999") { + t.Fatalf("shown %d after hiding ERROR", len(s.shown)) + } + if n := logViewerRows(tt); n > 40 { + t.Fatalf("built %d rows after filtering", n) + } +} + +func TestLogViewerFollowsAppends(t *testing.T) { + lines := logViewerLines(50) + s := &LogViewerState{} + tt := logViewerTester(&lines, s, false) + lines = append(lines, LogLine{Level: LogInfo, Text: "event fresh"}) + tt.Frame() + if !tt.HasText("event fresh") || len(s.shown) != 51 { + t.Fatalf("appended line not followed; shown %d", len(s.shown)) + } + if err := tt.Click("Follow"); err != nil { + t.Fatal(err) + } + if s.Follow { + t.Fatal("Follow toggle did not turn off") + } + tt.Scroll(300, 200, 0, -2000) + lines = append(lines, LogLine{Level: LogInfo, Text: "event later"}) + tt.Frame() + if tt.HasText("event later") { + t.Fatal("paused viewer jumped to the new line") + } +} + +func TestLogViewerHighlight(t *testing.T) { + lines := []LogLine{{Level: LogWarn, Text: "disk nearly full"}} + s := &LogViewerState{Query: "FULL"} + tt := logViewerTester(&lines, s, false) + if !tt.HasText("disk nearly full") || !tt.HasText("WARN") { + t.Fatalf("texts %q", tt.Texts()) + } + var spans []ui.Span + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + spans = codeMatchSpans(c, "disk nearly full", "FULL") + }, 10, 10) + if len(spans) != 2 || spans[1].Text != "full" || !spans[1].Underline || spans[1].Background.A == 0 { + t.Fatalf("highlight spans %+v", spans) + } +} + +func TestLogViewerDisabledAndEmpty(t *testing.T) { + lines := logViewerLines(8) + s := &LogViewerState{} + tt := logViewerTester(&lines, s, true) + _ = tt.Click("ERROR") + if s.Hidden[LogError] { + t.Fatal("disabled viewer changed its filter") + } + var none []LogLine + tt = logViewerTester(&none, &LogViewerState{}, false) + if !tt.HasText("No log lines") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestLogViewerSnapshot(t *testing.T) { + snapshot(t, "log_viewer", 640, 230, func(c *ui.Context) { + s := ui.Local(c.Root(), "snap", func() *LogViewerState { return &LogViewerState{Query: "seal"} }) + at := time.Date(2026, 10, 5, 9, 0, 0, 0, time.UTC) + lines := []LogLine{ + {at, LogDebug, "loading ledger index"}, + {at.Add(12 * time.Millisecond), LogInfo, "court opened by the chancellor"}, + {at.Add(40 * time.Millisecond), LogWarn, "seal of decree 41 is faded"}, + {at.Add(91 * time.Millisecond), LogError, "seal of decree 42 missing"}, + } + ui.Column(c).Padding(12).Children(func() { + LogViewer(c, lines, *s, LogViewerOptions{}).Element.Height(206) + }) + }) +} diff --git a/messages_code.go b/messages_code.go new file mode 100644 index 0000000..3f210e4 --- /dev/null +++ b/messages_code.go @@ -0,0 +1,101 @@ +package mujica + +func init() { + addMessages(map[string][2]string{ + "terminal.label": {"Terminal", "终端"}, + "terminal_search.label": {"Find in terminal", "在终端中查找"}, + "terminal_tabs.label": {"Terminals", "终端"}, + "terminal_tabs.empty": {"No terminals open", "没有打开的终端"}, + "terminal_tabs.confirm": {"Close “%s”?", "关闭“%s”?"}, + "terminal_tabs.busy": {"A process is still running in this terminal and will be ended.", "此终端中仍有进程在运行,关闭后将结束它。"}, + "terminal_tabs.close": {"Close", "关闭"}, + "terminal_tabs.running": {"Process running", "进程运行中"}, + "terminal_tabs.rename": {"Terminal name", "终端名称"}, + "terminal_tabs.closeTab": {"Close %s", "关闭 %s"}, + "command_history.search": {"Search history", "搜索历史"}, + "command_history.empty": {"No commands yet", "暂无命令"}, + "command_history.none": {"No matching commands", "没有匹配的命令"}, + "command_history.replay": {"Run %s again", "重新运行 %s"}, + "command_history.exit": {"exit %d", "退出码 %d"}, + "log_viewer.highlight": {"Highlight", "高亮关键字"}, + "log_viewer.follow": {"Follow", "跟随"}, + "log_viewer.empty": {"No log lines", "没有日志"}, + "log_viewer.debug": {"DEBUG", "调试"}, + "log_viewer.info": {"INFO", "信息"}, + "log_viewer.warn": {"WARN", "警告"}, + "log_viewer.error": {"ERROR", "错误"}, + "process_list.empty": {"No processes", "没有进程"}, + "process_list.name": {"Name", "名称"}, + "process_list.pid": {"PID", "PID"}, + "process_list.cpu": {"CPU", "CPU"}, + "process_list.memory": {"Memory", "内存"}, + "process_list.actions": {"End", "结束"}, + "process_list.end": {"End %s", "结束 %s"}, + "process_list.confirm": {"End “%s” (PID %d)?", "结束“%s”(PID %d)?"}, + "process_list.warning": {"Unsaved work in this process will be lost.", "该进程中未保存的内容将会丢失。"}, + "process_list.endButton": {"End process", "结束进程"}, + "code_viewer.empty": {"No code", "没有代码"}, + "code_viewer.fold": {"Fold line %d", "折叠第 %d 行"}, + "code_viewer.unfold": {"Unfold line %d", "展开第 %d 行"}, + "minimap.label": {"Minimap", "代码缩略图"}, + "minimap.range": {"Lines %d to %d of %d", "第 %d 至 %d 行,共 %d 行"}, + "find_widget.toggleReplace": {"Toggle replace", "切换替换"}, + "find_widget.case": {"Match case", "区分大小写"}, + "find_widget.word": {"Whole word", "全字匹配"}, + "find_widget.regex": {"Regular expression", "正则表达式"}, + "find_widget.invalid": {"Invalid pattern: %s", "表达式无效:%s"}, + "find_widget.replace": {"Replace with", "替换为"}, + "find_widget.replaceOne": {"Replace", "替换"}, + "find_widget.replaceAll": {"Replace all", "全部替换"}, + "search_panel.include": {"Files to include", "包含的文件"}, + "search_panel.exclude": {"Files to exclude", "排除的文件"}, + "search_panel.idle": {"Type to search in files", "输入内容以在文件中搜索"}, + "search_panel.none": {"No results", "没有结果"}, + "search_panel.summary": {"%d results in %d files", "%d 个结果,位于 %d 个文件"}, + "search_panel.fold": {"Fold %s", "收起 %s"}, + "search_panel.unfold": {"Unfold %s", "展开 %s"}, + "problems_panel.errors": {"Errors %d", "错误 %d"}, + "problems_panel.warnings": {"Warnings %d", "警告 %d"}, + "problems_panel.infos": {"Info %d", "信息 %d"}, + "problems_panel.error": {"Error", "错误"}, + "problems_panel.warning": {"Warning", "警告"}, + "problems_panel.info": {"Info", "信息"}, + "problems_panel.empty": {"No problems", "没有问题"}, + "problems_panel.at": {"Ln %d, Col %d", "第 %d 行,第 %d 列"}, + "output_panel.channel": {"Output channel", "输出通道"}, + "output_panel.clear": {"Clear output", "清空输出"}, + "output_panel.empty": {"No output", "没有输出"}, + "symbol_outline.filter": {"Filter symbols", "筛选符号"}, + "symbol_outline.empty": {"No symbols", "没有符号"}, + "completion_menu.label": {"Suggestions", "补全建议"}, + "debug_toolbar.label": {"Debug", "调试"}, + "debug_toolbar.start": {"Start", "开始"}, + "debug_toolbar.continue": {"Continue", "继续"}, + "debug_toolbar.pause": {"Pause", "暂停"}, + "debug_toolbar.stepOver": {"Step over", "单步跳过"}, + "debug_toolbar.stepInto": {"Step into", "单步进入"}, + "debug_toolbar.stepOut": {"Step out", "单步跳出"}, + "debug_toolbar.restart": {"Restart", "重启"}, + "debug_toolbar.stop": {"Stop", "停止"}, + "breakpoint_list.label": {"Breakpoints", "断点"}, + "breakpoint_list.empty": {"No breakpoints", "没有断点"}, + "breakpoint_list.enable": {"Enable %s:%d", "启用 %s:%d"}, + "breakpoint_list.edit": {"Edit condition of %s:%d", "编辑 %s:%d 的条件"}, + "breakpoint_list.condition": {"Condition", "条件"}, + "breakpoint_list.placeholder": {"Break when expression is true", "表达式为真时中断"}, + "breakpoint_list.when": {"when %s", "当 %s"}, + "call_stack.empty": {"Not paused", "未暂停"}, + "call_stack.frames": {"depth %d", "深度 %d"}, + "variables_panel.empty": {"No variables", "没有变量"}, + "variables_panel.value": {"Value", "值"}, + "variables_panel.changed": {"Changed", "已变化"}, + "hex_viewer.label": {"Hex view", "十六进制视图"}, + "hex_viewer.empty": {"No bytes", "没有数据"}, + "hex_viewer.at": {"Offset %d, %d bytes selected", "偏移 %d,已选 %d 字节"}, + "flamegraph.search": {"Highlight frames", "高亮帧"}, + "flamegraph.empty": {"No profile", "没有性能数据"}, + "flamegraph.label": {"Flame graph", "火焰图"}, + "flamegraph.hint": {"Point at a frame, or focus the graph and use the arrows", "指向一帧,或聚焦图表后用方向键"}, + "flamegraph.readout": {"%s: %.1f %s, %.1f%% of total", "%s:%.1f %s,占总计 %.1f%%"}, + }) +} diff --git a/minimap.go b/minimap.go new file mode 100644 index 0000000..3ba6490 --- /dev/null +++ b/minimap.go @@ -0,0 +1,134 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// MinimapView is the editor's first line and line count. +type MinimapView struct{ Top, Visible int } + +// MinimapOptions configure a Minimap. +type MinimapOptions struct { + // Language colors the strokes as CodeViewer does. + Language string + // Width is the map's width in DIPs; zero is 96. + Width float32 + Disabled bool +} + +// Line height and character width on the map. +const ( + minimapLine float32 = 2 + minimapChar float32 = 1 +) + +// Minimap draws code small and moves the visible frame. +func Minimap(c *ui.Context, lines []string, view *MinimapView, opts MinimapOptions) ChoiceResult { + if view == nil { + panic("mujica: Minimap needs a view") + } + if opts.Width < 0 || view.Visible < 0 || view.Top < 0 { + panic("mujica: Minimap width, Top and Visible must not be negative") + } + k := Tokens(c) + w := opts.Width + if w == 0 { + w = 96 + } + n := len(lines) + var res ChoiceResult + move := func(top int) { + top = max(0, min(top, n-view.Visible)) + if top != view.Top { + view.Top = top + res.changed = true + slog.Debug("mujica: minimap move", "top", top) + } + } + e := ui.Box(c).Width(w).Shrink(0).MinHeight(theme.MinHitSize*2).Focusable().Clip().Cursor(ui.CursorPointer). + Background(k.Surface).Border(theme.BorderWidth, k.Border).Radius(theme.ControlRadius).Disabled(opts.Disabled). + Label(msg(c, "minimap.label")).Description(fmt.Sprintf(msg(c, "minimap.range"), min(view.Top+1, n), min(view.Top+view.Visible, n), n)) + res.Element = e + h := e.Bounds().H + offset := minimapOffset(n, *view, h) + if !e.IsDisabled() { + if _, _, held := e.Dragged(); held { + _, y, _ := e.PointerPosition() + move(int((y+offset)/minimapLine) - view.Visible/2) + } + switch { + case e.Shortcut(0, ui.KeyDown): + move(view.Top + 1) + case e.Shortcut(0, ui.KeyUp): + move(view.Top - 1) + case e.Shortcut(0, ui.KeyPageDown): + move(view.Top + max(view.Visible, 1)) + case e.Shortcut(0, ui.KeyPageUp): + move(view.Top - max(view.Visible, 1)) + case e.Shortcut(0, ui.KeyHome): + move(0) + case e.Shortcut(0, ui.KeyEnd): + move(n) + } + } + internal.Ring(e, k.Focus, theme.ControlRadius) + v := *view + e.Draw(func(p *ui.Painter, r ui.Rect) { + if r.H != h { + c.Invalidate() + } + p.Clip(r, theme.ControlRadius, func() { + off := minimapOffset(n, v, r.H) + first := int(off / minimapLine) + for i := first; i < n && float32(i-first)*minimapLine < r.H+minimapLine; i++ { + y := internal.Snap(p, r.Y+float32(i)*minimapLine-off) + minimapStrokes(p, k, opts.Language, lines[i], r.X+6, y, r.X+r.W-6) + } + fy := internal.Snap(p, r.Y+float32(v.Top)*minimapLine-off) + frame := ui.Rect{X: r.X + 1, Y: fy, W: r.W - 2, H: max(internal.Snap(p, float32(v.Visible)*minimapLine), 4)} + p.Fill(frame, k.Selection.Alpha(0.55), 0) + p.Stroke(frame, k.AccentText, 0, 1) + }) + }) + return res +} + +// minimapOffset scrolls a tall map with the view. +func minimapOffset(n int, v MinimapView, h float32) float32 { + total := float32(n) * minimapLine + if total <= h || n <= v.Visible { + return 0 + } + return float32(v.Top) / float32(n-v.Visible) * (total - h) +} + +// minimapStrokes draws a line's tokens as short bars, skipping blanks. +func minimapStrokes(p *ui.Painter, k theme.Tokens, lang, line string, x0, y, x1 float32) { + line = strings.ReplaceAll(line, "\t", " ") + toks, _ := internal.Highlight(lang, line, false) + col := 0 + for _, t := range toks { + runes := []rune(t.Text) + start := -1 + for i, r := range append(runes, ' ') { + if r != ' ' && start < 0 { + start = i + } + if r == ' ' && start >= 0 { + x := x0 + float32(col+start)*minimapChar + if x < x1 { + p.Fill(ui.Rect{X: x, Y: y, W: min(float32(i-start)*minimapChar, x1-x), H: minimapLine * 0.7}, codeTokenColor(k, t.Kind).Alpha(0.75), 0) + } + start = -1 + } + } + col += len(runes) + } +} diff --git a/minimap_test.go b/minimap_test.go new file mode 100644 index 0000000..c538fd0 --- /dev/null +++ b/minimap_test.go @@ -0,0 +1,116 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +func minimapLines(n int) []string { + lines := make([]string, n) + for i := range lines { + lines[i] = fmt.Sprintf("\tvalue%d := compute(%d) // note", i, i) + } + return lines +} + +func minimapTester(lines []string, v *MinimapView, disabled bool, moves *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := Minimap(c, lines, v, MinimapOptions{Language: "go", Disabled: disabled}) + r.Element.Height(200) + if r.Changed() { + *moves++ + } + }, 200, 220) +} + +func TestMinimapClickAndDragJump(t *testing.T) { + v := &MinimapView{Visible: 20} + moves := 0 + tt := minimapTester(minimapLines(80), v, false, &moves) + // y=100 is line 50; centered, top is 40. + tt.Press(40, 100) + if v.Top != 40 { + t.Fatalf("press moved top to %d, want 40", v.Top) + } + tt.Move(40, 150) + tt.Release(40, 150) + if v.Top != 60 { + t.Fatalf("drag clamped top to %d, want 60 (80-20)", v.Top) + } + if moves < 2 { + t.Fatalf("Changed reported %d times", moves) + } +} + +func TestMinimapKeys(t *testing.T) { + v := &MinimapView{Visible: 20} + moves := 0 + tt := minimapTester(minimapLines(500), v, false, &moves) + tt.Key(0, ui.KeyTab) + if !tt.Focused("Minimap") { + t.Fatal("Tab did not focus the minimap") + } + tt.Key(0, ui.KeyPageDown) + tt.Key(0, ui.KeyDown) + if v.Top != 21 { + t.Fatalf("PageDown+Down gave %d", v.Top) + } + tt.Key(0, ui.KeyEnd) + if v.Top != 480 { + t.Fatalf("End gave %d", v.Top) + } + tt.Key(0, ui.KeyHome) + if v.Top != 0 { + t.Fatalf("Home gave %d", v.Top) + } +} + +func TestMinimapScrollsWhenTaller(t *testing.T) { + if off := minimapOffset(1000, MinimapView{Top: 980, Visible: 20}, 200); off != 1800 { + t.Fatalf("offset at the end %v, want 1800", off) + } + if off := minimapOffset(50, MinimapView{Top: 10, Visible: 20}, 200); off != 0 { + t.Fatalf("short map offset %v", off) + } +} + +func TestMinimapDisabled(t *testing.T) { + v := &MinimapView{Visible: 20} + moves := 0 + tt := minimapTester(minimapLines(80), v, true, &moves) + tt.Press(40, 100) + tt.Release(40, 100) + if v.Top != 0 || moves != 0 { + t.Fatalf("disabled minimap moved to %d", v.Top) + } +} + +func TestMinimapNegativePanics(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("negative Visible did not panic") + } + }() + minimapTester(nil, &MinimapView{Visible: -1}, false, new(int)) +} + +func TestMinimapSnapshot(t *testing.T) { + snapshot(t, "minimap", 140, 220, func(c *ui.Context) { + v := ui.Local(c.Root(), "snap", func() *MinimapView { return &MinimapView{Top: 12, Visible: 24} }) + ui.Column(c).Padding(12).Children(func() { + Minimap(c, codeMinimapSnapshotLines(), *v, MinimapOptions{Language: "go"}).Element.Height(196) + }) + }) +} + +func codeMinimapSnapshotLines() []string { + var lines []string + for i := range 12 { + lines = append(lines, codeViewerSample...) + lines = append(lines, fmt.Sprintf("// section %d", i), "") + } + return lines +} diff --git a/output_panel.go b/output_panel.go new file mode 100644 index 0000000..e7c00df --- /dev/null +++ b/output_panel.go @@ -0,0 +1,93 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// OutputChannel is a named stream of ANSI lines. +type OutputChannel struct { + Name string + Lines []string +} + +// OutputPanelState is the channel, following and place. +type OutputPanelState struct { + Channel int + // Follow keeps the newest line in view; it starts on. + Follow bool + rows ui.ListState + shown int + started bool +} + +// OutputPanelOptions configure an OutputPanel. +type OutputPanelOptions struct { + Disabled bool +} + +// OutputPanelResult is an OutputPanel and what happened in this frame. +type OutputPanelResult struct { + Element *ui.Element + // Cleared names a channel to clear. + Changed bool + Cleared string +} + +// OutputPanel shows one channel, following its tail. +func OutputPanel(c *ui.Context, channels []OutputChannel, s *OutputPanelState, opts OutputPanelOptions) OutputPanelResult { + if s == nil || len(channels) == 0 { + panic("mujica: OutputPanel needs a state and a channel") + } + if s.Channel < 0 || s.Channel >= len(channels) { + panic("mujica: OutputPanel Channel out of range") + } + if !s.started { + s.started, s.Follow, s.shown = true, true, s.Channel + } + var res OutputPanelResult + res.Element = codePanel(c).Disabled(opts.Disabled) + disabled := res.Element.IsDisabled() + res.Element.Children(func() { + codeHeader(c, func() { + options := make([]SelectOption[int], len(channels)) + for i, ch := range channels { + options[i] = SelectOption[int]{Value: i, Label: ch.Name} + } + if Select(c, &s.Channel, options, SelectOptions{Label: msg(c, "output_panel.channel"), Disabled: opts.Disabled}).Changed() { + res.Changed = true + slog.Debug("mujica: output_panel channel", "channel", s.Channel) + } + ui.Spacer(c) + was := s.Follow + if Toggle(c, &s.Follow, msg(c, "log_viewer.follow"), ToggleOptions{Disabled: opts.Disabled}).Changed() && s.Follow && !was { + s.rows.ScrollToEnd() + } + if iconAction(c, icons.Must("trash-2"), msg(c, "output_panel.clear")).Disabled(opts.Disabled).Clicked() && !disabled { + res.Cleared = channels[s.Channel].Name + slog.Debug("mujica: output_panel clear", "channel", s.Channel) + } + }) + if s.shown != s.Channel { + s.shown, s.rows = s.Channel, ui.ListState{} + } + lines := channels[s.Channel].Lines + if len(lines) == 0 { + codeCaption(c, msg(c, "output_panel.empty")).Padding(Density(c).Unit() * 4) + return + } + d := Density(c) + s.rows.FollowEnd = s.Follow + s.rows.Label = func(i int) string { return lines[i] } + ui.List(c, &s.rows, len(lines), func(i int) { + ui.Row(c).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*3).AlignItems(ui.Center).Children(func() { + ui.RichText(c, codeAnsiSpans(c, lines[i])...).Font(theme.MonoFont).FontSize(FontSize(c, codeSize)).Grow(1).MinWidth(0) + }) + }).Grow(1).MinHeight(d.ControlHeight()*3).Padding(d.Unit(), 0) + }) + return res +} diff --git a/output_panel_test.go b/output_panel_test.go new file mode 100644 index 0000000..e6cad68 --- /dev/null +++ b/output_panel_test.go @@ -0,0 +1,118 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +type outputProbe struct { + channels []OutputChannel + s OutputPanelState + disabled bool + changed int + cleared []string +} + +func (p *outputProbe) view(c *ui.Context) { + Use(c, Settings{}) + r := OutputPanel(c, p.channels, &p.s, OutputPanelOptions{Disabled: p.disabled}) + r.Element.Height(300) + if r.Changed { + p.changed++ + } + if r.Cleared != "" { + p.cleared = append(p.cleared, r.Cleared) + for i := range p.channels { + if p.channels[i].Name == r.Cleared { + p.channels[i].Lines = nil + } + } + } +} + +func newOutputProbe() *outputProbe { + var build []string + for i := range 200 { + build = append(build, fmt.Sprintf("compile unit %d", i)) + } + return &outputProbe{channels: []OutputChannel{{"Build", build}, {"Tests", []string{"\x1b[32mPASS\x1b[0m court", "\x1b[31mFAIL\x1b[0m ledger"}}}} +} + +func TestOutputPanelFollowsTail(t *testing.T) { + p := newOutputProbe() + tt := ui.NewTester(p.view, 520, 320) + if !tt.HasText("compile unit 199") || tt.HasText("compile unit 0") { + t.Fatal("panel did not start at the tail") + } + p.channels[0].Lines = append(p.channels[0].Lines, "linked") + tt.Frame() + if !tt.HasText("linked") { + t.Fatal("new output not followed") + } +} + +func TestOutputPanelSwitchAndClear(t *testing.T) { + p := newOutputProbe() + tt := ui.NewTester(p.view, 520, 320) + if err := tt.Click("Build"); err != nil { + t.Fatal(err) + } + if err := tt.Click("Tests"); err != nil { + t.Fatal(err) + } + if p.s.Channel != 1 || p.changed != 1 || !tt.HasText("PASS court") { + t.Fatalf("channel %d changed %d texts %q", p.s.Channel, p.changed, tt.Texts()) + } + if err := tt.Click("Clear output"); err != nil { + t.Fatal(err) + } + if len(p.cleared) != 1 || p.cleared[0] != "Tests" || !tt.HasText("No output") { + t.Fatalf("cleared %v", p.cleared) + } +} + +func TestOutputPanelAnsiColors(t *testing.T) { + var spans []ui.Span + var ok ui.Color + ui.NewTester(func(c *ui.Context) { + Use(c, Settings{Mode: Light}) + ok = Tokens(c).Success + spans = codeAnsiSpans(c, "\x1b[1;32mPASS\x1b[0m court") + }, 10, 10) + if len(spans) != 2 || spans[0].Color != ok || spans[0].Weight != 700 || spans[1].Color.A != 0 { + t.Fatalf("spans %+v", spans) + } +} + +func TestOutputPanelDisabledAndBadChannel(t *testing.T) { + p := newOutputProbe() + p.disabled = true + tt := ui.NewTester(p.view, 520, 320) + _ = tt.Click("Clear output") + if len(p.cleared) != 0 { + t.Fatal("disabled panel cleared") + } + defer func() { + if recover() == nil { + t.Fatal("channel out of range did not panic") + } + }() + p = newOutputProbe() + p.s.Channel = 5 + ui.NewTester(p.view, 520, 320) +} + +func TestOutputPanelSnapshot(t *testing.T) { + snapshot(t, "output_panel", 520, 200, func(c *ui.Context) { + p := ui.Local(c.Root(), "snap", func() *outputProbe { + p := newOutputProbe() + p.s.Channel = 1 + return p + }) + ui.Column(c).Padding(12).Children(func() { + OutputPanel(c, (*p).channels, &(*p).s, OutputPanelOptions{}).Element.Height(176) + }) + }) +} diff --git a/problems_panel.go b/problems_panel.go new file mode 100644 index 0000000..5602f75 --- /dev/null +++ b/problems_panel.go @@ -0,0 +1,194 @@ +package mujica + +import ( + "cmp" + "fmt" + "log/slog" + "slices" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" +) + +// ProblemSeverity ranks a Problem. +type ProblemSeverity int + +const ( + ProblemError ProblemSeverity = iota + ProblemWarning + ProblemInfo +) + +// Problem is one diagnostic. +type Problem struct { + Severity ProblemSeverity + File string + Line, Col int + Message, Source string +} + +// ProblemsPanelState is a ProblemsPanel's filters, folded files and place. +type ProblemsPanelState struct { + // Hidden severities are filtered out. + Hidden [3]bool + // Collapsed holds folded file paths. + Collapsed ui.Selection[string] + rows ui.ListState + selected int + flat []problemRow + data *Problem + n, folded int + hidden [3]bool + started bool +} + +// problemRow is a file header or a problem. +type problemRow struct { + file string + problem int +} + +// ProblemsPanelOptions configure a ProblemsPanel. +type ProblemsPanelOptions struct { + Disabled bool +} + +// ProblemsPanelResult carries the problem opened. +type ProblemsPanelResult struct { + Element *ui.Element + Opened *Problem +} + +// ProblemsPanel lists diagnostics grouped by file. +func ProblemsPanel(c *ui.Context, problems []Problem, s *ProblemsPanelState, opts ProblemsPanelOptions) ProblemsPanelResult { + if s == nil { + panic("mujica: ProblemsPanel needs a state") + } + if !s.started { + s.started, s.selected = true, -1 + } + var counts [3]int + for _, p := range problems { + if p.Severity < ProblemError || p.Severity > ProblemInfo { + panic("mujica: Problem severity out of range") + } + counts[p.Severity]++ + } + var res ProblemsPanelResult + res.Element = codePanel(c).Disabled(opts.Disabled) + disabled := res.Element.IsDisabled() + res.Element.Children(func() { + codeHeader(c, func() { + for sv := ProblemError; sv <= ProblemInfo; sv++ { + on := !s.Hidden[sv] + name := fmt.Sprintf(msg(c, problemsKeys[sv]), counts[sv]) + if Toggle(c, &on, name, ToggleOptions{Icon: icons.Must(problemsIcons[sv]), Disabled: opts.Disabled}).Changed() { + s.Hidden[sv] = !on + slog.Debug("mujica: problems_panel filter", "severity", sv, "shown", on) + } + } + }) + problemsGroup(problems, s) + if len(s.flat) == 0 { + codeCaption(c, msg(c, "problems_panel.empty")).Padding(Density(c).Unit() * 4) + return + } + s.rows.Selected = &s.selected + s.rows.Key = func(i int) any { return s.flat[i] } + s.rows.Label = func(i int) string { + if r := s.flat[i]; r.problem >= 0 { + return problems[r.problem].Message + } + return s.flat[i].file + } + list := codeRows(c, &s.rows, len(s.flat), func(i int) { problemsRow(c, problems, s, s.flat[i], disabled) }) + if disabled || s.selected < 0 { + return + } + r := s.flat[s.selected] + switch { + case list.Submitted() && r.problem >= 0: + p := problems[r.problem] + res.Opened = &p + slog.Debug("mujica: problems_panel open", "line", p.Line) + case list.Submitted(), + r.problem < 0 && !s.Collapsed.Has(r.file) && list.Shortcut(0, ui.KeyLeft), + r.problem < 0 && s.Collapsed.Has(r.file) && list.Shortcut(0, ui.KeyRight): + problemsFold(s, r.file) + } + }) + return res +} + +var ( + problemsKeys = [3]string{"problems_panel.errors", "problems_panel.warnings", "problems_panel.infos"} + problemsIcons = [3]string{"circle-x", "triangle-alert", "info"} +) + +func problemsFold(s *ProblemsPanelState, file string) { + if s.Collapsed.Has(file) { + s.Collapsed.Remove(file) + } else { + s.Collapsed.Add(file) + } + s.folded = -1 + slog.Debug("mujica: problems_panel fold", "folded", s.Collapsed.Has(file)) +} + +// problemsGroup regroups when data or filters change. +func problemsGroup(problems []Problem, s *ProblemsPanelState) { + var first *Problem + if len(problems) > 0 { + first = &problems[0] + } + if s.data == first && s.n == len(problems) && s.folded == s.Collapsed.Len() && s.hidden == s.Hidden { + return + } + s.data, s.n, s.folded, s.hidden = first, len(problems), s.Collapsed.Len(), s.Hidden + var idx []int + for i, p := range problems { + if !s.Hidden[p.Severity] { + idx = append(idx, i) + } + } + slices.SortStableFunc(idx, func(a, b int) int { + pa, pb := problems[a], problems[b] + return cmp.Or(cmp.Compare(pa.File, pb.File), cmp.Compare(pa.Line, pb.Line), cmp.Compare(pa.Col, pb.Col)) + }) + s.flat = s.flat[:0] + for j, i := range idx { + f := problems[i].File + if j == 0 || problems[idx[j-1]].File != f { + s.flat = append(s.flat, problemRow{f, -1}) + } + if !s.Collapsed.Has(f) { + s.flat = append(s.flat, problemRow{f, i}) + } + } + s.selected = min(s.selected, len(s.flat)-1) +} + +func problemsRow(c *ui.Context, problems []Problem, s *ProblemsPanelState, r problemRow, disabled bool) { + k := Tokens(c) + if r.problem < 0 { + chev, key := "chevron-down", "search_panel.fold" + if s.Collapsed.Has(r.file) { + chev, key = "chevron-right", "search_panel.unfold" + } + if iconAction(c, icons.Must(chev), fmt.Sprintf(msg(c, key), r.file)).Clicked() && !disabled { + problemsFold(s, r.file) + } + ui.Text(c, r.file).FontWeight(600).SingleLine().Grow(1).MinWidth(0) + return + } + p := problems[r.problem] + col := [3]ui.Color{k.Danger, k.Warning, k.Info}[p.Severity] + ui.Icon(c, icons.Must(problemsIcons[p.Severity])).Size(16, 16).Shrink(0).TextColor(col).Margin(0, 0, 0, 28). + Label(msg(c, [3]string{"problems_panel.error", "problems_panel.warning", "problems_panel.info"}[p.Severity])) + ui.Text(c, p.Message).SingleLine().Grow(1).MinWidth(0) + if p.Source != "" { + codeCaption(c, p.Source).Shrink(0) + } + codeCaption(c, fmt.Sprintf(msg(c, "problems_panel.at"), p.Line, p.Col)).FontFeatures("tnum").Shrink(0) +} diff --git a/problems_panel_test.go b/problems_panel_test.go new file mode 100644 index 0000000..2ecf38d --- /dev/null +++ b/problems_panel_test.go @@ -0,0 +1,106 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func problemsSample() []Problem { + return []Problem{ + {ProblemWarning, "court/seal.go", 30, 2, "unused variable wax", "vet"}, + {ProblemError, "court/seal.go", 12, 5, "undefined: Decree", "compiler"}, + {ProblemInfo, "docs/ledger.md", 4, 1, "line is long", "lint"}, + } +} + +type problemsProbe struct { + problems []Problem + s ProblemsPanelState + disabled bool + opened []Problem +} + +func (p *problemsProbe) view(c *ui.Context) { + Use(c, Settings{}) + r := ProblemsPanel(c, p.problems, &p.s, ProblemsPanelOptions{Disabled: p.disabled}) + r.Element.Height(360) + if r.Opened != nil { + p.opened = append(p.opened, *r.Opened) + } +} + +func TestProblemsPanelGroupsSortedByLine(t *testing.T) { + p := &problemsProbe{problems: problemsSample()} + tt := ui.NewTester(p.view, 640, 380) + if !tt.HasText("Errors 1") || !tt.HasText("Warnings 1") || !tt.HasText("Info 1") { + t.Fatalf("counts missing: %q", tt.Texts()) + } + a, _ := tt.Find("undefined: Decree") + b, _ := tt.Find("unused variable wax") + if a.Y >= b.Y { + t.Fatal("problems are not sorted by line within the file") + } + if len(p.s.flat) != 5 || p.s.flat[0].file != "court/seal.go" || p.s.flat[3].file != "docs/ledger.md" { + t.Fatalf("rows %v", p.s.flat) + } +} + +func TestProblemsPanelFilterAndOpen(t *testing.T) { + p := &problemsProbe{problems: problemsSample()} + tt := ui.NewTester(p.view, 640, 380) + if err := tt.Click("Warnings 1"); err != nil { + t.Fatal(err) + } + if tt.HasText("unused variable wax") || !tt.HasText("undefined: Decree") { + t.Fatalf("filter kept warnings: %q", tt.Texts()) + } + r, _ := tt.Find("undefined: Decree") + tt.ClickAt(r.X+10, r.Y+r.H/2) + tt.ClickAt(r.X+10, r.Y+r.H/2) + if len(p.opened) != 1 || p.opened[0].Line != 12 || p.opened[0].Col != 5 { + t.Fatalf("opened %v", p.opened) + } +} + +func TestProblemsPanelKeyboardFold(t *testing.T) { + p := &problemsProbe{problems: problemsSample()} + tt := ui.NewTester(p.view, 640, 380) + for range 4 { + tt.Key(0, ui.KeyTab) + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyLeft) + if !p.s.Collapsed.Has("court/seal.go") || tt.HasText("undefined: Decree") { + t.Fatal("Left did not fold the file") + } + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if len(p.opened) != 1 || p.opened[0].Message != "undefined: Decree" { + t.Fatalf("Enter opened %v", p.opened) + } +} + +func TestProblemsPanelDisabledAndEmpty(t *testing.T) { + p := &problemsProbe{problems: problemsSample(), disabled: true} + tt := ui.NewTester(p.view, 640, 380) + _ = tt.Click("Errors 1") + _ = tt.Click("Fold court/seal.go") + if p.s.Hidden[ProblemError] || p.s.Collapsed.Len() != 0 { + t.Fatal("disabled panel changed") + } + tt = ui.NewTester((&problemsProbe{}).view, 640, 380) + if !tt.HasText("No problems") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestProblemsPanelSnapshot(t *testing.T) { + snapshot(t, "problems_panel", 600, 240, func(c *ui.Context) { + s := ui.Local(c.Root(), "snap", func() *ProblemsPanelState { return &ProblemsPanelState{} }) + ui.Column(c).Padding(12).Children(func() { + ProblemsPanel(c, problemsSample(), *s, ProblemsPanelOptions{}).Element.Height(216) + }) + }) +} diff --git a/process_list.go b/process_list.go new file mode 100644 index 0000000..73b608e --- /dev/null +++ b/process_list.go @@ -0,0 +1,185 @@ +package mujica + +import ( + "cmp" + "fmt" + "log/slog" + "slices" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// Process is one row of a ProcessList. +type Process struct { + PID int + Name string + // CPU is percent of one core; Memory is resident bytes. + CPU float64 + Memory uint64 +} + +// ProcessListState is a ProcessList's sort, selection and pending end. +type ProcessListState struct { + // Sort is by name, pid, cpu or memory. + Sort ui.SortOrder + rows ui.ListState + selected int + order []int + sorted ui.SortOrder + data *Process + n int + confirm bool + ending Process + started bool +} + +// ProcessListOptions configure a ProcessList. +type ProcessListOptions struct { + Disabled bool +} + +// ProcessListResult carries a confirmed end request. +type ProcessListResult struct { + Element *ui.Element + // End is the confirmed process to end, or nil. + End *Process +} + +// ProcessList is a sortable process table with confirmed ending. +func ProcessList(c *ui.Context, procs []Process, s *ProcessListState, opts ProcessListOptions) ProcessListResult { + if s == nil { + panic("mujica: ProcessList needs a state") + } + if !s.started { + s.started, s.selected, s.Sort = true, -1, ui.SortOrder{Column: "cpu", Descending: true} + } + processListSort(procs, s) + k := Tokens(c) + var res ProcessListResult + res.Element = codePanel(c).Disabled(opts.Disabled) + disabled := res.Element.IsDisabled() + if disabled { + s.confirm = false + } + ask := func(p Process) { + if !disabled { + s.ending, s.confirm = p, true + } + } + res.Element.Children(func() { + if len(procs) == 0 { + codeCaption(c, msg(c, "process_list.empty")).Padding(Density(c).Unit() * 4) + return + } + cols := []ui.TableColumn{ + {Title: msg(c, "process_list.name"), ID: "name", Sortable: true, MinWidth: 120}, + {Title: msg(c, "process_list.pid"), ID: "pid", Width: 80, Align: ui.End, Sortable: true}, + {Title: msg(c, "process_list.cpu"), ID: "cpu", Width: 90, Align: ui.End, Sortable: true}, + {Title: msg(c, "process_list.memory"), ID: "memory", Width: 100, Align: ui.End, Sortable: true}, + {Title: msg(c, "process_list.actions"), ID: "end", Width: 56, Fixed: true, Align: ui.Center}, + } + s.rows.Sort = &s.Sort + s.rows.Selected = &s.selected + s.rows.Key = func(i int) any { return procs[s.order[i]].PID } + s.rows.Label = func(i int) string { return procs[s.order[i]].Name } + restore := dataSelectTheme(c, 0) + table := ui.Table(c, &s.rows, cols, len(procs), func(row, col int) { + p := procs[s.order[row]] + switch col { + case 0: + ui.Row(c).Gap(Density(c).Unit() * 2).AlignItems(ui.Center).Children(func() { + codeSelectMark(c, s.selected == row) + ui.Text(c, p.Name).SingleLine() + }) + case 1: + codeMono(c, fmt.Sprint(p.PID)) + case 2: + codeMono(c, fmt.Sprintf("%.1f%%", p.CPU)) + case 3: + codeMono(c, processListBytes(p.Memory)) + case 4: + if iconAction(c, icons.Must("x"), fmt.Sprintf(msg(c, "process_list.end"), p.Name)).Clicked() { + ask(p) + } + } + }).Grow(1).MinHeight(Density(c).ControlHeight() * 4) + restore() + internal.Ring(table, k.Focus, theme.ControlRadius) + if table.Changed() { + processListSort(procs, s) + } + if table.Shortcut(0, ui.KeyDelete) && s.selected >= 0 && s.selected < len(procs) { + ask(procs[s.order[s.selected]]) + } + }) + if s.confirm { + r := AlertDialog(c, &s.confirm, AlertDialogOptions{ + Title: fmt.Sprintf(msg(c, "process_list.confirm"), s.ending.Name, s.ending.PID), + Description: msg(c, "process_list.warning"), + ConfirmLabel: msg(c, "process_list.endButton"), + }) + if r.Confirmed && !disabled { + p := s.ending + res.End = &p + slog.Debug("mujica: process_list end", "pid", p.PID) + } + } + return res +} + +// processListSort reorders when data or sort change. +func processListSort(procs []Process, s *ProcessListState) { + var first *Process + if len(procs) > 0 { + first = &procs[0] + } + if s.data == first && s.n == len(procs) && s.sorted == s.Sort && len(s.order) == len(procs) { + return + } + s.data, s.n, s.sorted = first, len(procs), s.Sort + s.order = s.order[:0] + for i := range procs { + s.order = append(s.order, i) + } + by := func(a, b int) int { + pa, pb := procs[a], procs[b] + switch s.Sort.Column { + case "name": + return strings.Compare(strings.ToLower(pa.Name), strings.ToLower(pb.Name)) + case "pid": + return cmp.Compare(pa.PID, pb.PID) + case "cpu": + return cmp.Compare(pa.CPU, pb.CPU) + case "memory": + return cmp.Compare(pa.Memory, pb.Memory) + case "": + return 0 + } + panic("mujica: ProcessList sorts by name, pid, cpu or memory, not " + s.Sort.Column) + } + slices.SortStableFunc(s.order, func(a, b int) int { + if s.Sort.Descending { + return by(b, a) + } + return by(a, b) + }) + slog.Debug("mujica: process_list sort", "by", s.Sort.Column, "descending", s.Sort.Descending) +} + +func processListBytes(b uint64) string { + const unit = 1024 + switch { + case b >= unit*unit*unit: + return fmt.Sprintf("%.1f GB", float64(b)/(unit*unit*unit)) + case b >= unit*unit: + return fmt.Sprintf("%.1f MB", float64(b)/(unit*unit)) + case b >= unit: + return fmt.Sprintf("%.0f KB", float64(b)/unit) + } + return fmt.Sprintf("%d B", b) +} diff --git a/process_list_test.go b/process_list_test.go new file mode 100644 index 0000000..a8a89cf --- /dev/null +++ b/process_list_test.go @@ -0,0 +1,124 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func processListSample() []Process { + return []Process{ + {PID: 101, Name: "chancellor", CPU: 3.5, Memory: 200 << 20}, + {PID: 7, Name: "archivist", CPU: 42.1, Memory: 50 << 20}, + {PID: 330, Name: "Herald", CPU: 0.2, Memory: 2 << 30}, + } +} + +func processListTester(procs []Process, s *ProcessListState, disabled bool, ended *[]int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := ProcessList(c, procs, s, ProcessListOptions{Disabled: disabled}) + r.Element.Height(300) + if r.End != nil { + *ended = append(*ended, r.End.PID) + } + }, 560, 340) +} + +func processListOrder(procs []Process, s *ProcessListState) []int { + var out []int + for _, i := range s.order { + out = append(out, procs[i].PID) + } + return out +} + +func TestProcessListSortsByCPUThenMemory(t *testing.T) { + procs := processListSample() + s := &ProcessListState{} + var ended []int + tt := processListTester(procs, s, false, &ended) + if got := processListOrder(procs, s); got[0] != 7 || got[2] != 330 { + t.Fatalf("default CPU order %v", got) + } + if err := tt.Click("Memory"); err != nil { + t.Fatal(err) + } + if got := processListOrder(procs, s); got[0] != 7 || got[2] != 330 || s.Sort.Descending { + t.Fatalf("memory ascending %v", got) + } + _ = tt.Click("Memory") + if got := processListOrder(procs, s); got[0] != 330 { + t.Fatalf("memory descending %v", got) + } + if !tt.HasText("2.0 GB") || !tt.HasText("42.1%") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestProcessListEndAsksFirst(t *testing.T) { + procs := processListSample() + s := &ProcessListState{} + var ended []int + tt := processListTester(procs, s, false, &ended) + if err := tt.Click("End Herald"); err != nil { + t.Fatal(err) + } + if len(ended) != 0 || !tt.HasText("End “Herald” (PID 330)?") { + t.Fatalf("ended %v before confirmation", ended) + } + if err := tt.Click("End process"); err != nil { + t.Fatal(err) + } + if len(ended) != 1 || ended[0] != 330 { + t.Fatalf("ended %v", ended) + } +} + +func TestProcessListKeyboardEnd(t *testing.T) { + procs := processListSample() + s := &ProcessListState{} + var ended []int + tt := processListTester(procs, s, false, &ended) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDelete) + if !tt.HasText("End “archivist” (PID 7)?") { + t.Fatalf("Delete did not ask for the chosen row: %q", tt.Texts()) + } + tt.Key(0, ui.KeyEscape) + if len(ended) != 0 { + t.Fatal("Escape ended the process") + } +} + +func TestProcessListDisabledAndEmpty(t *testing.T) { + var ended []int + tt := processListTester(processListSample(), &ProcessListState{}, true, &ended) + _ = tt.Click("End Herald") + if tt.HasText("End process") { + t.Fatal("disabled list asked to end a process") + } + tt = processListTester(nil, &ProcessListState{}, false, &ended) + if !tt.HasText("No processes") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestProcessListBadSortPanics(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("unknown sort column did not panic") + } + }() + processListSort(processListSample(), &ProcessListState{Sort: ui.SortOrder{Column: "owner"}}) +} + +func TestProcessListSnapshot(t *testing.T) { + snapshot(t, "process_list", 560, 220, func(c *ui.Context) { + s := ui.Local(c.Root(), "snap", func() *ProcessListState { return &ProcessListState{} }) + ui.Column(c).Padding(12).Children(func() { + ProcessList(c, processListSample(), *s, ProcessListOptions{}).Element.Height(196) + }) + }) +} diff --git a/search_panel.go b/search_panel.go new file mode 100644 index 0000000..6e14471 --- /dev/null +++ b/search_panel.go @@ -0,0 +1,202 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" +) + +// SearchMatch is a hit; Start and End index Text. +type SearchMatch struct { + Line int + Text string + Start, End int +} + +// SearchFileResult is a file and its hits. +type SearchFileResult struct { + Path string + Matches []SearchMatch +} + +// SearchPanelState is a SearchPanel's query, patterns, folded files and place. +type SearchPanelState struct { + Query, Include, Exclude string + // Collapsed holds the paths of folded files. + Collapsed ui.Selection[string] + rows ui.ListState + selected int + flat []searchRow + data *SearchFileResult + n, folded int + started bool +} + +type searchRow struct{ file, match int } + +// SearchPanelOptions configure a SearchPanel. +type SearchPanelOptions struct { + // Status shows a search in progress or failed. + Status DataStatus + Error string + Disabled bool +} + +// SearchOpen is a hit the user opened. +type SearchOpen struct { + Path string + Line int +} + +// SearchPanelResult is a SearchPanel and what happened in this frame. +type SearchPanelResult struct { + Element *ui.Element + // Changed asks the caller to search again. + Changed bool + Opened *SearchOpen +} + +// SearchPanel shows search results grouped by file. +func SearchPanel(c *ui.Context, results []SearchFileResult, s *SearchPanelState, opts SearchPanelOptions) SearchPanelResult { + if s == nil { + panic("mujica: SearchPanel needs a state") + } + if !s.started { + s.started, s.selected = true, -1 + } + d := Density(c) + var res SearchPanelResult + res.Element = codePanel(c).Disabled(opts.Disabled) + disabled := res.Element.IsDisabled() + res.Element.Children(func() { + ui.Column(c).Shrink(0).Padding(d.Unit() * 2).Gap(d.Unit() * 2).Children(func() { + res.Changed = SearchInput(c, &s.Query, SearchInputOptions{Disabled: opts.Disabled}).Changed() + ui.Row(c).Gap(d.Unit() * 2).Children(func() { + for _, f := range []struct { + v *string + key string + }{{&s.Include, "search_panel.include"}, {&s.Exclude, "search_panel.exclude"}} { + r := TextInput(c, f.v, TextInputOptions{Placeholder: msg(c, f.key), Label: msg(c, f.key), Disabled: opts.Disabled}) + r.Element.Grow(1).MinWidth(0) + res.Changed = res.Changed || r.Changed() + } + }) + }) + if res.Changed { + slog.Debug("mujica: search_panel query", "query", s.Query, "include", s.Include, "exclude", s.Exclude) + } + searchPanelFlatten(results, s) + if len(results) == 0 || opts.Status != DataReady { + text := msg(c, "search_panel.idle") + if s.Query != "" { + text = msg(c, "search_panel.none") + } + res.Changed = dataPlaceholder(c, opts.Status, opts.Error, text, text) || res.Changed + return + } + total := 0 + for _, f := range results { + total += len(f.Matches) + } + codeCaption(c, fmt.Sprintf(msg(c, "search_panel.summary"), total, len(results))).Padding(0, d.Unit()*3, d.Unit(), d.Unit()*3) + s.rows.Selected = &s.selected + s.rows.Key = func(i int) any { return s.flat[i] } + s.rows.Label = func(i int) string { return searchPanelLabel(results, s.flat[i]) } + list := codeRows(c, &s.rows, len(s.flat), func(i int) { searchPanelRow(c, results, s, s.flat[i], disabled) }) + if list.Submitted() && !disabled && s.selected >= 0 { + r := s.flat[s.selected] + f := results[r.file] + if r.match < 0 { + searchPanelFold(s, f.Path, !s.Collapsed.Has(f.Path)) + } else { + res.Opened = &SearchOpen{Path: f.Path, Line: f.Matches[r.match].Line} + slog.Debug("mujica: search_panel open", "line", res.Opened.Line) + } + } + if !disabled && s.selected >= 0 && s.flat[s.selected].match < 0 { + path := results[s.flat[s.selected].file].Path + switch { + case list.Shortcut(0, ui.KeyLeft): + searchPanelFold(s, path, true) + case list.Shortcut(0, ui.KeyRight): + searchPanelFold(s, path, false) + } + } + }) + return res +} + +func searchPanelFold(s *SearchPanelState, path string, fold bool) { + if fold { + s.Collapsed.Add(path) + } else { + s.Collapsed.Remove(path) + } + s.folded = -1 + slog.Debug("mujica: search_panel fold", "folded", fold) +} + +// searchPanelFlatten relists rows when results or folds change. +func searchPanelFlatten(results []SearchFileResult, s *SearchPanelState) { + var first *SearchFileResult + if len(results) > 0 { + first = &results[0] + } + if s.data == first && s.n == len(results) && s.folded == s.Collapsed.Len() { + return + } + s.data, s.n, s.folded = first, len(results), s.Collapsed.Len() + s.flat = s.flat[:0] + for fi, f := range results { + s.flat = append(s.flat, searchRow{fi, -1}) + if !s.Collapsed.Has(f.Path) { + for mi := range f.Matches { + s.flat = append(s.flat, searchRow{fi, mi}) + } + } + } + s.selected = min(s.selected, len(s.flat)-1) +} + +func searchPanelLabel(results []SearchFileResult, r searchRow) string { + f := results[r.file] + if r.match < 0 { + return f.Path + } + m := f.Matches[r.match] + return fmt.Sprintf("%d %s", m.Line, strings.TrimSpace(m.Text)) +} + +func searchPanelRow(c *ui.Context, results []SearchFileResult, s *SearchPanelState, r searchRow, disabled bool) { + k := Tokens(c) + f := results[r.file] + if r.match < 0 { + chev, key := "chevron-down", "search_panel.fold" + if s.Collapsed.Has(f.Path) { + chev, key = "chevron-right", "search_panel.unfold" + } + if iconAction(c, icons.Must(chev), fmt.Sprintf(msg(c, key), f.Path)).Clicked() && !disabled { + searchPanelFold(s, f.Path, !s.Collapsed.Has(f.Path)) + } + ui.Icon(c, icons.Must("file-text")).Size(16, 16).Shrink(0).TextColor(k.TextMuted) + ui.Text(c, f.Path).FontWeight(600).SingleLine().Grow(1).MinWidth(0) + codeCaption(c, fmt.Sprint(len(f.Matches))).Shrink(0) + return + } + m := f.Matches[r.match] + if m.Start < 0 || m.End > len(m.Text) || m.Start > m.End { + panic("mujica: SearchMatch range outside its Text") + } + codeMono(c, fmt.Sprint(m.Line)).Width(codeTextWidth(c, "99999")).TextColor(k.TextMuted).Shrink(0).Margin(0, 0, 0, 28) + from := max(0, m.Start-40) + before := strings.TrimLeft(m.Text[from:m.Start], " \t") + if from > 0 { + before = "…" + before + } + spans := []ui.Span{{Text: before}, {Text: m.Text[m.Start:m.End], Background: k.Selection, Underline: true, DecorationColor: k.AccentText, Weight: 600}, {Text: m.Text[m.End:]}} + ui.RichText(c, spans...).SingleLine().Grow(1).MinWidth(0) +} diff --git a/search_panel_test.go b/search_panel_test.go new file mode 100644 index 0000000..23e9102 --- /dev/null +++ b/search_panel_test.go @@ -0,0 +1,129 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func searchPanelSample() []SearchFileResult { + return []SearchFileResult{ + {Path: "court/seal.go", Matches: []SearchMatch{{Line: 12, Text: "func Seal(d Decree) {", Start: 5, End: 9}, {Line: 30, Text: "\treturn Seal(next)", Start: 8, End: 12}}}, + {Path: "docs/ledger.md", Matches: []SearchMatch{{Line: 4, Text: "The seal is kept by the chancellor.", Start: 4, End: 8}}}, + } +} + +type searchPanelProbe struct { + results []SearchFileResult + s SearchPanelState + opts SearchPanelOptions + changed int + opened []SearchOpen +} + +func (p *searchPanelProbe) view(c *ui.Context) { + Use(c, Settings{}) + r := SearchPanel(c, p.results, &p.s, p.opts) + r.Element.Height(400) + if r.Changed { + p.changed++ + } + if r.Opened != nil { + p.opened = append(p.opened, *r.Opened) + } +} + +func TestSearchPanelGroupsAndOpens(t *testing.T) { + p := &searchPanelProbe{results: searchPanelSample()} + tt := ui.NewTester(p.view, 560, 420) + if !tt.HasText("3 results in 2 files") || !tt.HasText("court/seal.go") { + t.Fatalf("texts %q", tt.Texts()) + } + r, _ := tt.Find("12") + tt.ClickAt(r.X+60, r.Y+r.H/2) + tt.ClickAt(r.X+60, r.Y+r.H/2) + if len(p.opened) != 1 || p.opened[0] != (SearchOpen{"court/seal.go", 12}) { + t.Fatalf("opened %v", p.opened) + } + if err := tt.Click("Fold court/seal.go"); err != nil { + t.Fatal(err) + } + if tt.HasText("12") || !tt.HasText("docs/ledger.md") { + t.Fatalf("fold kept hits: %q", tt.Texts()) + } + _ = tt.Click("Unfold court/seal.go") + if !tt.HasText("30") { + t.Fatal("unfold did not show the hits") + } +} + +func TestSearchPanelQueryAndPatternsReport(t *testing.T) { + p := &searchPanelProbe{} + tt := ui.NewTester(p.view, 560, 420) + if !tt.HasText("Type to search in files") { + t.Fatalf("texts %q", tt.Texts()) + } + tt.Key(0, ui.KeyTab) + tt.Type("seal") + tt.Key(0, ui.KeyTab) + tt.Type("*.go") + if p.changed != 2 || p.s.Query != "seal" || p.s.Include != "*.go" { + t.Fatalf("changed %d query %q include %q", p.changed, p.s.Query, p.s.Include) + } + if !tt.HasText("No results") { + t.Fatal("empty search with a query says nothing") + } +} + +func TestSearchPanelKeyboard(t *testing.T) { + p := &searchPanelProbe{results: searchPanelSample()} + tt := ui.NewTester(p.view, 560, 420) + for range 5 { + tt.Key(0, ui.KeyTab) + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyLeft) + if !p.s.Collapsed.Has("court/seal.go") { + t.Fatal("Left on a file did not fold it") + } + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if len(p.opened) != 1 || p.opened[0].Line != 30 { + t.Fatalf("Enter opened %v", p.opened) + } +} + +func TestSearchPanelStatusAndDisabled(t *testing.T) { + p := &searchPanelProbe{opts: SearchPanelOptions{Status: DataFailed, Error: "index unavailable"}} + tt := ui.NewTester(p.view, 560, 420) + if !tt.HasText("index unavailable") { + t.Fatalf("texts %q", tt.Texts()) + } + p = &searchPanelProbe{results: searchPanelSample(), opts: SearchPanelOptions{Disabled: true}} + tt = ui.NewTester(p.view, 560, 420) + _ = tt.Click("Fold court/seal.go") + if p.s.Collapsed.Len() != 0 { + t.Fatal("disabled panel folded") + } +} + +func TestSearchPanelBadRangePanics(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("match outside its text did not panic") + } + }() + p := &searchPanelProbe{results: []SearchFileResult{{Path: "a", Matches: []SearchMatch{{Text: "ab", Start: 1, End: 9}}}}} + ui.NewTester(p.view, 560, 420) +} + +func TestSearchPanelSnapshot(t *testing.T) { + snapshot(t, "search_panel", 520, 300, func(c *ui.Context) { + s := ui.Local(c.Root(), "snap", func() *SearchPanelState { return &SearchPanelState{Query: "seal", Include: "*.go, *.md"} }) + ui.Column(c).Padding(12).Children(func() { + SearchPanel(c, searchPanelSample(), *s, SearchPanelOptions{}).Element.Height(276) + }) + }) +} diff --git a/symbol_outline.go b/symbol_outline.go new file mode 100644 index 0000000..e82bba1 --- /dev/null +++ b/symbol_outline.go @@ -0,0 +1,235 @@ +package mujica + +import ( + "log/slog" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// SymbolKind is what a Symbol declares. +type SymbolKind int + +const ( + SymbolFunction SymbolKind = iota + SymbolMethod + SymbolType + SymbolInterface + SymbolField + SymbolVariable + SymbolConstant + SymbolModule +) + +// Symbol is a declaration spanning Line to EndLine, from 1. +type Symbol struct { + Name, Detail string + Kind SymbolKind + Line, EndLine int + Children []Symbol +} + +// SymbolOutlineState is a SymbolOutline's filter, open symbols and choice. +type SymbolOutlineState struct { + Query string + outline ui.OutlineState[int] + cursor int + nodes []symbolNode + roots []int + data *Symbol + n int + line int + started bool +} + +type symbolNode struct { + sym *Symbol + parent int + kids []int +} + +// SymbolOutlineOptions configure a SymbolOutline. +type SymbolOutlineOptions struct { + // CursorLine chooses its symbol when it changes; 0 is off. + CursorLine int + Disabled bool +} + +// SymbolOutlineResult carries the symbol to jump to. +type SymbolOutlineResult struct { + Element *ui.Element + Jumped *Symbol +} + +var symbolBadges = [...]string{"f", "m", "T", "I", "p", "v", "c", "M"} + +// SymbolOutline shows a filterable symbol tree. +func SymbolOutline(c *ui.Context, symbols []Symbol, s *SymbolOutlineState, opts SymbolOutlineOptions) SymbolOutlineResult { + if s == nil { + panic("mujica: SymbolOutline needs a state") + } + if !s.started { + s.started, s.cursor = true, -1 + } + symbolIndex(symbols, s) + k := Tokens(c) + d := Density(c) + var res SymbolOutlineResult + res.Element = codePanel(c).Disabled(opts.Disabled) + disabled := res.Element.IsDisabled() + res.Element.Children(func() { + codeHeader(c, func() { + SearchInput(c, &s.Query, SearchInputOptions{Placeholder: msg(c, "symbol_outline.filter"), Disabled: opts.Disabled}).Element.Grow(1) + }) + q := strings.ToLower(strings.TrimSpace(s.Query)) + keep := symbolFilter(s, q) + roots := symbolKept(s.roots, keep) + if len(roots) == 0 { + codeCaption(c, msg(c, "symbol_outline.empty")).Padding(d.Unit() * 4) + return + } + follow := opts.CursorLine != s.line + s.line = opts.CursorLine + if follow { + symbolFollow(s, opts.CursorLine, keep) + } + s.outline.List.Selected = &s.cursor + s.outline.List.Label = func(i int) string { return s.nodes[s.outline.Item(i)].sym.Name } + children := func(i int) []int { + if len(s.nodes[i].kids) == 0 { + return nil + } + if q != "" { + s.outline.Open.Add(i) + } + return symbolKept(s.nodes[i].kids, keep) + } + restore := dataSelectTheme(c, 0) + e := ui.Outline(c, &s.outline, roots, children, func(i int) { + sym := s.nodes[i].sym + if sym.Kind < SymbolFunction || sym.Kind > SymbolModule { + panic("mujica: Symbol kind out of range") + } + ui.Row(c).MinHeight(d.ControlHeight() - 2*c.Theme().Space(1)).Gap(d.Unit() * 2).AlignItems(ui.Center).Grow(1).MinWidth(0).Children(func() { + codeBadge(c, symbolBadges[sym.Kind], [...]ui.Color{k.AccentText, k.AccentText, k.Info, k.Info, k.TextMuted, k.TextMuted, k.Warning, k.Success}[sym.Kind]) + ui.RichText(c, codeMatchSpans(c, sym.Name, q)...).SingleLine().MinWidth(0) + if sym.Detail != "" { + codeCaption(c, sym.Detail).MinWidth(0) + } + ui.Spacer(c) + codeSelectMark(c, s.cursor >= 0 && s.cursor < s.outline.Rows() && s.outline.Item(s.cursor) == i) + }) + }) + restore() + e.Grow(1).MinHeight(d.ControlHeight() * 3) + internal.Ring(e, k.Focus, theme.ControlRadius) + if follow && s.cursor >= 0 { + s.outline.List.ScrollIntoView(s.cursor) + } + if !disabled && s.cursor >= 0 && s.cursor < s.outline.Rows() && e.Submitted() { + sym := *s.nodes[s.outline.Item(s.cursor)].sym + res.Jumped = &sym + slog.Debug("mujica: symbol_outline jump", "line", sym.Line) + } + }) + return res +} + +// symbolIndex numbers the symbols depth first when the tree changes. +func symbolIndex(symbols []Symbol, s *SymbolOutlineState) { + var first *Symbol + if len(symbols) > 0 { + first = &symbols[0] + } + if s.data == first && s.n == len(symbols) { + return + } + s.data, s.n, s.nodes, s.roots = first, len(symbols), s.nodes[:0], s.roots[:0] + var walk func(list []Symbol, parent int) []int + walk = func(list []Symbol, parent int) []int { + var ids []int + for i := range list { + id := len(s.nodes) + s.nodes = append(s.nodes, symbolNode{sym: &list[i], parent: parent}) + s.nodes[id].kids = walk(list[i].Children, id) + ids = append(ids, id) + } + return ids + } + s.roots = walk(symbols, -1) +} + +// symbolFilter marks matches and ancestors; nil keeps all. +func symbolFilter(s *SymbolOutlineState, q string) []bool { + if q == "" { + return nil + } + keep := make([]bool, len(s.nodes)) + for i, n := range s.nodes { + if strings.Contains(strings.ToLower(n.sym.Name), q) { + for j := i; j >= 0 && !keep[j]; j = s.nodes[j].parent { + keep[j] = true + } + } + } + return keep +} + +func symbolKept(ids []int, keep []bool) []int { + if keep == nil { + return ids + } + var out []int + for _, id := range ids { + if keep[id] { + out = append(out, id) + } + } + return out +} + +// symbolFollow opens and chooses the innermost symbol spanning line. +func symbolFollow(s *SymbolOutlineState, line int, keep []bool) { + best := -1 + for i, n := range s.nodes { + if keep != nil && !keep[i] { + continue + } + if n.sym.Line <= line && line <= max(n.sym.EndLine, n.sym.Line) { + best = i + } + } + if best < 0 { + return + } + for p := s.nodes[best].parent; p >= 0; p = s.nodes[p].parent { + s.outline.Open.Add(p) + } + s.cursor = symbolRow(s, best, keep) + slog.Debug("mujica: symbol_outline follow", "line", line) +} + +// symbolRow returns the row the shown node id is at. +func symbolRow(s *SymbolOutlineState, id int, keep []bool) int { + row := 0 + var walk func(ids []int) bool + walk = func(ids []int) bool { + for _, n := range symbolKept(ids, keep) { + if n == id { + return true + } + row++ + if s.outline.Open.Has(n) && walk(s.nodes[n].kids) { + return true + } + } + return false + } + if walk(s.roots) { + return row + } + return -1 +} diff --git a/symbol_outline_test.go b/symbol_outline_test.go new file mode 100644 index 0000000..106bb33 --- /dev/null +++ b/symbol_outline_test.go @@ -0,0 +1,107 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func symbolSample() []Symbol { + return []Symbol{ + {Name: "Court", Kind: SymbolType, Line: 3, EndLine: 40, Detail: "struct", Children: []Symbol{ + {Name: "Seal", Kind: SymbolMethod, Line: 10, EndLine: 20, Detail: "(d Decree) error"}, + {Name: "ledger", Kind: SymbolField, Line: 5, EndLine: 5}, + }}, + {Name: "Herald", Kind: SymbolFunction, Line: 44, EndLine: 60}, + {Name: "MaxSeals", Kind: SymbolConstant, Line: 1, EndLine: 1}, + } +} + +type symbolProbe struct { + symbols []Symbol + s SymbolOutlineState + opts SymbolOutlineOptions + jumped []string +} + +func (p *symbolProbe) view(c *ui.Context) { + Use(c, Settings{}) + r := SymbolOutline(c, p.symbols, &p.s, p.opts) + r.Element.Height(320) + if r.Jumped != nil { + p.jumped = append(p.jumped, r.Jumped.Name) + } +} + +func TestSymbolOutlineFollowsCursor(t *testing.T) { + p := &symbolProbe{symbols: symbolSample(), opts: SymbolOutlineOptions{CursorLine: 12}} + tt := ui.NewTester(p.view, 400, 340) + if !tt.HasText("Seal") || p.s.cursor < 0 || p.s.nodes[p.s.outline.Item(p.s.cursor)].sym.Name != "Seal" { + t.Fatalf("cursor at line 12 did not choose Seal: %q", tt.Texts()) + } + p.opts.CursorLine = 50 + tt.Frame() + if name := p.s.nodes[p.s.outline.Item(p.s.cursor)].sym.Name; name != "Herald" { + t.Fatalf("line 50 chose %q", name) + } +} + +func TestSymbolOutlineFilter(t *testing.T) { + p := &symbolProbe{symbols: symbolSample()} + tt := ui.NewTester(p.view, 400, 340) + tt.Key(0, ui.KeyTab) + tt.Type("led") + if !tt.HasText("Court") || !tt.HasText("ledger") || tt.HasText("Herald") || tt.HasText("Seal") { + t.Fatalf("filter shows %q", tt.Texts()) + } + tt.Key(ui.Cmd, ui.KeyA) + tt.Type("zz") + if !tt.HasText("No symbols") { + t.Fatalf("texts %q", tt.Texts()) + } +} + +func TestSymbolOutlineJumpByKeyboard(t *testing.T) { + p := &symbolProbe{symbols: symbolSample()} + tt := ui.NewTester(p.view, 400, 340) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if len(p.jumped) != 1 || p.jumped[0] != "Herald" { + t.Fatalf("jumped %v", p.jumped) + } + tt.Key(0, ui.KeyUp) + tt.Key(0, ui.KeyRight) + if !tt.HasText("Seal") { + t.Fatal("Right did not open Court") + } +} + +func TestSymbolOutlineDisabledAndBadKind(t *testing.T) { + p := &symbolProbe{symbols: symbolSample(), opts: SymbolOutlineOptions{Disabled: true}} + tt := ui.NewTester(p.view, 400, 340) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if len(p.jumped) != 0 { + t.Fatal("disabled outline jumped") + } + defer func() { + if recover() == nil { + t.Fatal("bad kind did not panic") + } + }() + ui.NewTester((&symbolProbe{symbols: []Symbol{{Name: "x", Kind: 99}}}).view, 400, 340) +} + +func TestSymbolOutlineSnapshot(t *testing.T) { + snapshot(t, "symbol_outline", 360, 260, func(c *ui.Context) { + p := ui.Local(c.Root(), "snap", func() *symbolProbe { + return &symbolProbe{symbols: symbolSample(), opts: SymbolOutlineOptions{CursorLine: 12}} + }) + ui.Column(c).Padding(12).Children(func() { + SymbolOutline(c, (*p).symbols, &(*p).s, (*p).opts).Element.Height(236) + }) + }) +} diff --git a/terminal.go b/terminal.go new file mode 100644 index 0000000..deee353 --- /dev/null +++ b/terminal.go @@ -0,0 +1,308 @@ +package mujica + +import ( + "log/slog" + "math" + "runtime" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// TerminalOptions configure a Terminal. +type TerminalOptions struct { + // Input receives what the user types, encoded for the PTY. + Input func(data string) + // Resized reports a new grid size for the PTY. + Resized func(cols, rows int) + // Scrollback caps lines kept above; zero keeps 1000. + Scrollback int + Label string + Disabled bool +} + +// terminalPad is the space around the grid in DIPs. +const terminalPad float32 = 6 + +// terminalCtrl maps letter keys to their Ctrl codes. +var terminalCtrl = map[ui.Key]byte{ui.KeyA: 1, ui.KeyB: 2, ui.KeyC: 3, ui.KeyD: 4, ui.KeyE: 5, ui.KeyF: 6, ui.KeyG: 7, + ui.KeyH: 8, ui.KeyI: 9, ui.KeyJ: 10, ui.KeyK: 11, ui.KeyL: 12, ui.KeyM: 13, ui.KeyN: 14, ui.KeyO: 15, ui.KeyP: 16, + ui.KeyQ: 17, ui.KeyR: 18, ui.KeyS: 19, ui.KeyT: 20, ui.KeyU: 21, ui.KeyV: 22, ui.KeyW: 23, ui.KeyX: 24, ui.KeyY: 25, ui.KeyZ: 26} + +// terminalKeys are the sequences of keys that type no text. +var terminalKeys = map[ui.Key]string{ui.KeyEnter: "\r", ui.KeyBackspace: "\x7f", ui.KeyTab: "\t", ui.KeyEscape: "\x1b", + ui.KeyUp: "\x1b[A", ui.KeyDown: "\x1b[B", ui.KeyRight: "\x1b[C", ui.KeyLeft: "\x1b[D", ui.KeyHome: "\x1b[H", ui.KeyEnd: "\x1b[F", + ui.KeyDelete: "\x1b[3~", ui.KeyPageUp: "\x1b[5~", ui.KeyPageDown: "\x1b[6~"} + +// terminalCell size and baseline for the code font. +func terminalMetrics(f ui.Font) (cw, ch, base float32) { + m := f.Metrics() + g := ui.Shape("M", f) + cw = f.Size * 0.6 + if len(g) > 0 { + cw = g[0].Advance + } + ch = float32(math.Ceil(float64((m.Ascent + m.Descent + m.LineGap) * 1.15))) + return cw, ch, (ch-m.Ascent-m.Descent)/2 + m.Ascent +} + +// Terminal draws a TerminalState and sends input to the PTY. +func Terminal(c *ui.Context, s *TerminalState, opts TerminalOptions) *ui.Element { + if s == nil { + panic("mujica: Terminal needs a TerminalState") + } + if opts.Scrollback < 0 { + panic("mujica: Terminal Scrollback is negative") + } + s.init() + if opts.Scrollback > 0 { + s.limit = opts.Scrollback + } + k := Tokens(c) + font := codeFont(c) + cw, ch, base := terminalMetrics(font) + label := opts.Label + if label == "" { + label = msg(c, "terminal.label") + } + e := ui.Box(c).Focusable().Cursor(ui.CursorText).Clip().Label(label).Background(k.Surface). + Border(theme.BorderWidth, k.Border).Radius(theme.ControlRadius).Disabled(opts.Disabled).MinHeight(ch * 4) + b := e.Bounds() + if b.W > 0 { + cols := max(int((b.W-2*terminalPad)/cw), 1) + rows := max(int((b.H-2*terminalPad)/ch), 1) + if cols != s.cols || rows != s.rows { + s.Resize(cols, rows) + slog.Debug("mujica: terminal resize", "cols", cols, "rows", rows) + if opts.Resized != nil { + opts.Resized(cols, rows) + } + } + } + send := func(data string) { + s.offset, s.selOn, s.preedit = 0, false, "" + if opts.Input != nil { + opts.Input(data) + } + } + cell := func(x, y float32) TerminalPos { + col := max(0, min(int((x-terminalPad)/cw), s.cols-1)) + row := max(0, min(int((y-terminalPad)/ch), s.rows-1)) + return TerminalPos{Line: len(s.back) - s.offset + row, Col: col} + } + anchor := ui.Local(e, "terminal.anchor", func() TerminalPos { return TerminalPos{} }) + e.HandleInput(func(ev ui.InputEvent) bool { + if e.IsDisabled() { + return false + } + switch ev.Kind { + case ui.InputKeyDown: + return terminalKey(c, s, ev, send) + case ui.InputText: + send(ev.Text) + return true + case ui.InputCompose: + s.preedit = ev.Text + return true + case ui.InputScroll: + s.scrolled -= ev.DY / ch + n := int(s.scrolled) + s.scrolled -= float32(n) + s.ScrollBack(n) + return true + case ui.InputPointerDown: + if ev.Button != 0 { + return false + } + e.Focus() + *anchor = cell(ev.X, ev.Y) + s.selOn = false + return true + case ui.InputPointerMove: + if e.Pressed() { + s.Select(*anchor, cell(ev.X, ev.Y)) + } + return true + } + return false + }) + cy := float32(s.cy+s.offset) * ch + e.TextCaret(ui.Rect{X: terminalPad + float32(s.cx)*cw, Y: terminalPad + cy, W: cw, H: ch}) + focused := e.Focused() + internal.Ring(e, k.Focus, theme.ControlRadius) + e.Draw(func(p *ui.Painter, r ui.Rect) { + if r.W != b.W || r.H != b.H { + // Laid out at another size: rebuild to fit the grid. + c.Invalidate() + } + terminalPaint(p, r, s, k, font, cw, ch, base, focused) + }) + return e +} + +// terminalKey encodes a key, handling copy, paste and scrollback. +func terminalKey(c *ui.Context, s *TerminalState, ev ui.InputEvent, send func(string)) bool { + clip := ui.Super + if runtime.GOOS != "darwin" { + clip = ui.Ctrl | ui.Shift + } + switch { + case ev.Mods == clip && ev.Key == ui.KeyC: + if t := s.Selection(); t != "" { + c.WriteClipboard(t) + slog.Debug("mujica: terminal copy", "runes", len([]rune(t))) + } + return true + case ev.Mods == clip && ev.Key == ui.KeyV: + if t := c.ReadClipboard(); t != "" { + send(t) + } + return true + case ev.Mods == ui.Shift && (ev.Key == ui.KeyPageUp || ev.Key == ui.KeyPageDown): + n := s.rows - 1 + if ev.Key == ui.KeyPageDown { + n = -n + } + s.ScrollBack(n) + return true + case ev.Mods == ui.Ctrl && terminalCtrl[ev.Key] != 0: + send(string([]byte{terminalCtrl[ev.Key]})) + return true + } + if seq, ok := terminalKeys[ev.Key]; ok && ev.Mods&^ui.Shift == 0 { + if ev.Key == ui.KeyTab && ev.Mods == ui.Shift { + seq = "\x1b[Z" + } + send(seq) + return true + } + return false +} + +// terminalPaint draws the visible rows, marks and cursor. +func terminalPaint(p *ui.Painter, r ui.Rect, s *TerminalState, k theme.Tokens, font ui.Font, cw, ch, base float32, focused bool) { + ox, oy := r.X+terminalPad, r.Y+terminalPad + top := len(s.back) - s.offset + for row := range s.rows { + li := top + row + cells := s.line(li) + y := oy + float32(row)*ch + for col := 0; col < len(cells); { + st := cells[col].st + end := col + 1 + for end < len(cells) && cells[end].st == st { + end++ + } + fg, bg := codeAnsiColor(k, st.FG), codeAnsiColor(k, st.BG) + if fg.A == 0 { + fg = k.Text + } + if st.Inverse { + if bg.A == 0 { + bg = k.Surface + } + fg, bg = bg, fg + } + if st.Dim { + fg = fg.Alpha(0.6) + } + x0 := ox + float32(col)*cw + if bg.A > 0 { + p.Fill(ui.Rect{X: x0, Y: y, W: float32(end-col) * cw, H: ch}, bg, 0) + } + for i := col; i < end; i++ { + if s.selected(TerminalPos{li, i}) { + p.Fill(ui.Rect{X: ox + float32(i)*cw, Y: y, W: cw, H: ch}, k.Selection, 0) + } + } + terminalRun(p, s, cells[col:end], st, font, x0, y+base, cw, fg) + if st.Underline || st.Strike { + ly := y + base + 2 + if st.Strike { + ly = y + ch/2 + } + codeRule(p, x0, x0+float32(end-col)*cw, ly, fg) + } + col = end + } + for mi, m := range s.matches { + if m.pos.Line != li { + continue + } + mr := ui.Rect{X: ox + float32(m.pos.Col)*cw, Y: y, W: float32(m.n) * cw, H: ch} + codeRule(p, mr.X, mr.X+mr.W, y+ch-1, k.AccentText) + if mi == s.current { + p.Stroke(mr, k.AccentText, 1, 1.5) + } + } + } + if s.offset > 0 || s.cy >= s.rows { + return + } + cr := ui.Rect{X: ox + float32(s.cx)*cw, Y: oy + float32(s.cy)*ch, W: cw, H: ch} + if s.cx >= s.cols { + cr.X = ox + float32(s.cols-1)*cw + } + if s.preedit != "" { + g := terminalShape(s, s.preedit, font) + p.Glyphs(g, cr.X, cr.Y+base, k.AccentText) + codeRule(p, cr.X, cr.X+float32(len([]rune(s.preedit)))*cw, cr.Y+ch-1, k.AccentText) + return + } + if !focused { + p.Stroke(cr, k.AccentText, 0, 1) + return + } + p.Fill(cr, k.AccentText, 0) + if c := min(s.cx, s.cols-1); s.screen[s.cy][c].r > ' ' { + p.Glyphs(terminalShape(s, string(s.screen[s.cy][c].r), font), cr.X, cr.Y+base, k.Surface) + } +} + +// terminalRun draws same-style cells, one glyph per cell. +func terminalRun(p *ui.Painter, s *TerminalState, cells []terminalCell, st internal.AnsiStyle, font ui.Font, x, y, cw float32, fg ui.Color) { + runes := make([]rune, len(cells)) + blank := true + for i, cell := range cells { + runes[i] = cell.r + if cell.r == 0 { + runes[i] = ' ' + } else if cell.r != ' ' { + blank = false + } + } + if blank { + return + } + if st.Bold { + font.Weight = 700 + } + font.Italic = st.Italic + p.Glyphs(terminalShape(s, string(runes), font), x, y, fg) +} + +// terminalShape shapes text into cells, cached across frames. +func terminalShape(s *TerminalState, text string, f ui.Font) []ui.Glyph { + key := string(rune(f.Weight)) + string(rune(int(f.Size*4))) + text + if f.Italic { + key = "i" + key + } + if g, ok := s.shaped[key]; ok { + return g + } + if s.shaped == nil || len(s.shaped) > 4096 { + s.shaped = map[string][]ui.Glyph{} + } + g := ui.Shape(text, f) + cw := f.Size * 0.6 + if m := ui.Shape("M", ui.Font{Family: f.Family, Size: f.Size}); len(m) > 0 { + cw = m[0].Advance + } + for i := range g { + g[i].X = float32(g[i].Cluster) * cw + } + s.shaped[key] = g + return g +} diff --git a/terminal_search.go b/terminal_search.go new file mode 100644 index 0000000..c7bba0a --- /dev/null +++ b/terminal_search.go @@ -0,0 +1,77 @@ +package mujica + +import ( + "log/slog" + "strings" + + "github.com/egoist/mygo/ui" +) + +// TerminalSearchState is a search through a terminal's scrollback and screen. +type TerminalSearchState struct { + Query string + // Current is the chosen match, from 0. + Current int + query string + version int + ran bool +} + +// TerminalSearchOptions configure a TerminalSearch. +type TerminalSearchOptions struct { + Disabled bool +} + +// TerminalSearch finds Query in term and shows the current match. +func TerminalSearch(c *ui.Context, term *TerminalState, s *TerminalSearchState, opts TerminalSearchOptions) ChoiceResult { + if term == nil || s == nil { + panic("mujica: TerminalSearch needs a terminal and a state") + } + term.init() + fresh := terminalSearchRun(term, s) + r := SearchInput(c, &s.Query, SearchInputOptions{Find: true, Matches: len(term.matches), Current: &s.Current, + Disabled: opts.Disabled, Label: msg(c, "terminal_search.label")}) + var res ChoiceResult + res.Element = r.Element + if r.Changed() { + s.Current = 0 + terminalSearchRun(term, s) + res.changed = true + } + if r.Moved() { + res.changed = true + } + if res.changed || fresh { + term.current = s.Current + if s.Current < len(term.matches) { + term.reveal(term.matches[s.Current].pos.Line) + } + slog.Debug("mujica: terminal_search move", "matches", len(term.matches), "current", s.Current) + } + return res +} + +// terminalSearchRun refinds matches; it reports a new query. +func terminalSearchRun(term *TerminalState, s *TerminalSearchState) bool { + if s.ran && s.query == s.Query && s.version == term.version { + return false + } + fresh := !s.ran || s.query != s.Query + s.ran, s.query, s.version = true, s.Query, term.version + term.matches = term.matches[:0] + q := []rune(strings.ToLower(s.Query)) + if len(q) > 0 { + for i := range term.Lines() { + line := []rune(strings.ToLower(term.LineText(i))) + for col := 0; col+len(q) <= len(line); col++ { + if string(line[col:col+len(q)]) == string(q) { + term.matches = append(term.matches, terminalMatch{TerminalPos{i, col}, len(q)}) + col += len(q) - 1 + } + } + } + } + s.Current = max(0, min(s.Current, len(term.matches)-1)) + term.current = s.Current + return fresh +} diff --git a/terminal_search_test.go b/terminal_search_test.go new file mode 100644 index 0000000..584e293 --- /dev/null +++ b/terminal_search_test.go @@ -0,0 +1,105 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +func terminalSearchTester(term *TerminalState, s *TerminalSearchState, opts TerminalSearchOptions, moves *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Children(func() { + if TerminalSearch(c, term, s, opts).Changed() { + *moves++ + } + Terminal(c, term, TerminalOptions{}).Size(400, 120) + }) + }, 420, 220) +} + +func terminalSearchFill() *TerminalState { + term := &TerminalState{} + term.Resize(40, 5) + for i := range 30 { + if i%10 == 3 { + term.Write(fmt.Sprintf("step %d: Error found\r\n", i)) + } else { + term.Write(fmt.Sprintf("step %d: ok\r\n", i)) + } + } + return term +} + +func TestTerminalSearchCountsAndJumps(t *testing.T) { + term := terminalSearchFill() + s := &TerminalSearchState{} + moves := 0 + tt := terminalSearchTester(term, s, TerminalSearchOptions{}, &moves) + tt.Key(0, ui.KeyTab) + tt.Type("error") + if len(term.matches) != 3 || !tt.HasText("1 of 3") { + t.Fatalf("matches %d, texts %q", len(term.matches), tt.Texts()) + } + first := term.matches[0].pos.Line + top := len(term.back) - term.Offset() + if first < top || first >= top+5 { + t.Fatalf("match line %d not on screen from %d", first, top) + } + tt.Key(0, ui.KeyEnter) + if s.Current != 1 || !tt.HasText("2 of 3") { + t.Fatalf("Enter moved to %d", s.Current) + } + tt.Key(ui.Shift, ui.KeyEnter) + tt.Key(ui.Shift, ui.KeyEnter) + if s.Current != 2 { + t.Fatalf("Shift+Enter twice from 1 gave %d, want 2 (wraps)", s.Current) + } + if line := term.matches[2].pos.Line; line < len(term.back)-term.Offset() { + t.Fatalf("current match line %d above the view", line) + } + if moves < 4 { + t.Fatalf("Changed reported %d times", moves) + } +} + +func TestTerminalSearchFollowsNewOutput(t *testing.T) { + term := terminalSearchFill() + s := &TerminalSearchState{Query: "error"} + moves := 0 + tt := terminalSearchTester(term, s, TerminalSearchOptions{}, &moves) + term.Write("late error\r\n") + tt.Frame() + if len(term.matches) != 4 { + t.Fatalf("%d matches after new output, want 4", len(term.matches)) + } +} + +func TestTerminalSearchNoMatchAndDisabled(t *testing.T) { + term := terminalSearchFill() + s := &TerminalSearchState{Query: "zebra"} + moves := 0 + tt := terminalSearchTester(term, s, TerminalSearchOptions{Disabled: true}, &moves) + if !tt.HasText("No matches") || len(term.matches) != 0 { + t.Fatalf("texts %q", tt.Texts()) + } + tt.Key(0, ui.KeyTab) + tt.Type("ok") + if s.Query != "zebra" || moves != 0 { + t.Fatalf("disabled search changed to %q", s.Query) + } +} + +func TestTerminalSearchSnapshot(t *testing.T) { + snapshot(t, "terminal_search", 420, 170, func(c *ui.Context) { + st := ui.Local(c.Root(), "snap", func() [2]any { + return [2]any{terminalSearchFill(), &TerminalSearchState{Query: "error", Current: 1}} + }) + term, s := (*st)[0].(*TerminalState), (*st)[1].(*TerminalSearchState) + ui.Column(c).Padding(12).Gap(8).Children(func() { + TerminalSearch(c, term, s, TerminalSearchOptions{}) + Terminal(c, term, TerminalOptions{}).Height(96) + }) + }) +} diff --git a/terminal_state.go b/terminal_state.go new file mode 100644 index 0000000..e3930fb --- /dev/null +++ b/terminal_state.go @@ -0,0 +1,361 @@ +package mujica + +import ( + "log/slog" + "strconv" + "strings" + "unicode/utf8" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" +) + +// terminalCell is one grid character; zero is blank. +type terminalCell struct { + r rune + st internal.AnsiStyle +} + +// TerminalPos is a cell; Line counts from the oldest line. +type TerminalPos struct{ Line, Col int } + +func (a TerminalPos) before(b TerminalPos) bool { + return a.Line < b.Line || a.Line == b.Line && a.Col < b.Col +} + +// TerminalState is the screen; zero is an empty 80×24 grid. +type TerminalState struct { + cols, rows int + screen [][]terminalCell + back [][]terminalCell + cx, cy int + style internal.AnsiStyle + pending string + limit int + // offset is how far the view scrolled back. + offset int + scrolled float32 + sel [2]TerminalPos + selOn bool + matches []terminalMatch + current int + version int + shaped map[string][]ui.Glyph + preedit string +} + +type terminalMatch struct { + pos TerminalPos + n int +} + +func (s *TerminalState) init() { + if s.screen == nil { + s.Resize(80, 24) + } + if s.limit == 0 { + s.limit = 1000 + } +} + +// Size returns the grid's columns and rows. +func (s *TerminalState) Size() (cols, rows int) { + s.init() + return s.cols, s.rows +} + +// Cursor returns the cursor's column and row on the screen. +func (s *TerminalState) Cursor() (col, row int) { return s.cx, s.cy } + +// Resize sets the grid size, keeping the cursor in view. +func (s *TerminalState) Resize(cols, rows int) { + if cols < 1 || rows < 1 { + panic("mujica: TerminalState size must be at least 1×1") + } + if s.limit == 0 { + s.limit = 1000 + } + old := s.screen + // Lines above a falling-off cursor go to the scrollback. + for drop := s.cy - (rows - 1); drop > 0 && len(old) > 0; drop-- { + s.pushBack(old[0]) + old = old[1:] + s.cy-- + if s.offset > 0 { + s.offset++ + } + } + s.screen = make([][]terminalCell, rows) + for y := range rows { + s.screen[y] = make([]terminalCell, cols) + if y < len(old) { + copy(s.screen[y], old[y]) + } + } + s.cols, s.rows = cols, rows + s.cx, s.cy = min(s.cx, cols-1), min(max(s.cy, 0), rows-1) + s.version++ +} + +// Write feeds PTY output; call it on the UI thread. +func (s *TerminalState) Write(data string) { + s.init() + data = s.pending + data + s.pending = "" + for i := 0; i < len(data); { + b := data[i] + switch { + case b == 0x1b: + n, ok := s.escape(data[i:]) + if !ok { + s.pending = data[i:] + s.version++ + return + } + i += n + case b == '\r': + s.cx = 0 + i++ + case b == '\n': + s.lineFeed() + i++ + case b == '\b': + s.cx = max(s.cx-1, 0) + i++ + case b == '\t': + s.cx = min((s.cx/8+1)*8, s.cols-1) + i++ + case b < 0x20 || b == 0x7f: + i++ + default: + r, n := utf8.DecodeRuneInString(data[i:]) + s.put(r) + i += n + } + } + s.version++ +} + +func (s *TerminalState) put(r rune) { + if s.cx >= s.cols { + s.cx = 0 + s.lineFeed() + } + s.screen[s.cy][s.cx] = terminalCell{r, s.style} + s.cx++ +} + +func (s *TerminalState) lineFeed() { + if s.cy < s.rows-1 { + s.cy++ + return + } + s.pushBack(s.screen[0]) + copy(s.screen, s.screen[1:]) + s.screen[s.rows-1] = make([]terminalCell, s.cols) + if s.offset > 0 { + s.offset = min(s.offset+1, len(s.back)) + } +} + +func (s *TerminalState) pushBack(line []terminalCell) { + s.back = append(s.back, line) + if over := len(s.back) - s.limit; over > 0 { + s.back = s.back[over:] + s.offset = min(s.offset, len(s.back)) + s.selOn = false + } +} + +// escape runs the sequence at d; false means incomplete. +func (s *TerminalState) escape(d string) (int, bool) { + if len(d) < 2 { + return 0, false + } + switch d[1] { + case '[': + case ']': + // OSC ends with BEL or ST; nothing to draw. + if end := strings.IndexAny(d, "\a"); end >= 0 { + return end + 1, true + } + if end := strings.Index(d, "\x1b\\"); end >= 0 { + return end + 2, true + } + return 0, false + default: + return 2, true + } + j := 2 + for j < len(d) && (d[j] < 0x40 || d[j] > 0x7e) { + j++ + } + if j >= len(d) { + return 0, false + } + params, final := d[2:j], d[j] + if final == 'm' { + _, s.style = internal.ParseAnsi(d[:j+1], s.style) + return j + 1, true + } + s.control(params, final) + return j + 1, true +} + +// control applies a CSI cursor or erase command. +func (s *TerminalState) control(params string, final byte) { + args := strings.Split(params, ";") + arg := func(i, def int) int { + if i >= len(args) || args[i] == "" { + return def + } + v, err := strconv.Atoi(args[i]) + if err != nil { + return def + } + return v + } + switch final { + case 'A': + s.cy = max(s.cy-max(arg(0, 1), 1), 0) + case 'B': + s.cy = min(s.cy+max(arg(0, 1), 1), s.rows-1) + case 'C': + s.cx = min(s.cx+max(arg(0, 1), 1), s.cols-1) + case 'D': + s.cx = max(min(s.cx, s.cols-1)-max(arg(0, 1), 1), 0) + case 'G': + s.cx = min(max(arg(0, 1), 1), s.cols) - 1 + case 'H', 'f': + s.cy = min(max(arg(0, 1), 1), s.rows) - 1 + s.cx = min(max(arg(1, 1), 1), s.cols) - 1 + case 'J': + s.eraseDisplay(arg(0, 0)) + case 'K': + s.eraseLine(s.cy, arg(0, 0)) + default: + slog.Debug("mujica: terminal unsupported sequence", "params", params, "final", string(final)) + } +} + +func (s *TerminalState) eraseLine(y, mode int) { + line := s.screen[y] + from, to := 0, s.cols + switch mode { + case 0: + from = min(s.cx, s.cols) + case 1: + to = min(s.cx+1, s.cols) + } + clear(line[from:to]) +} + +func (s *TerminalState) eraseDisplay(mode int) { + switch mode { + case 0: + s.eraseLine(s.cy, 0) + for y := s.cy + 1; y < s.rows; y++ { + clear(s.screen[y]) + } + case 1: + s.eraseLine(s.cy, 1) + for y := range s.cy { + clear(s.screen[y]) + } + default: + for y := range s.rows { + clear(s.screen[y]) + } + if mode == 3 { + s.back, s.offset = nil, 0 + } + } +} + +// Lines counts scrollback and screen lines. +func (s *TerminalState) Lines() int { + s.init() + return len(s.back) + s.rows +} + +func (s *TerminalState) line(i int) []terminalCell { + if i < len(s.back) { + return s.back[i] + } + return s.screen[i-len(s.back)] +} + +// LineText returns line i without trailing blanks. +func (s *TerminalState) LineText(i int) string { + var b strings.Builder + for _, cell := range s.line(i) { + r := cell.r + if r == 0 { + r = ' ' + } + b.WriteRune(r) + } + return strings.TrimRight(b.String(), " ") +} + +// Select marks the cells from a to b. +func (s *TerminalState) Select(a, b TerminalPos) { + if b.before(a) { + a, b = b, a + } + s.sel, s.selOn = [2]TerminalPos{a, b}, true +} + +// Selection returns the selected text, lines joined by newlines. +func (s *TerminalState) Selection() string { + if !s.selOn { + return "" + } + a, b := s.sel[0], s.sel[1] + var out []string + for y := a.Line; y <= b.Line && y < s.Lines(); y++ { + cells := s.line(y) + from, to := 0, len(cells) + if y == a.Line { + from = min(a.Col, len(cells)) + } + if y == b.Line { + to = min(b.Col+1, len(cells)) + } + var sb strings.Builder + for _, cell := range cells[from:max(to, from)] { + r := cell.r + if r == 0 { + r = ' ' + } + sb.WriteRune(r) + } + out = append(out, strings.TrimRight(sb.String(), " ")) + } + return strings.Join(out, "\n") +} + +func (s *TerminalState) selected(p TerminalPos) bool { + return s.selOn && !p.before(s.sel[0]) && !s.sel[1].before(p) +} + +// ScrollBack moves the view n lines up; negative goes down. +func (s *TerminalState) ScrollBack(n int) { + s.init() + s.offset = max(0, min(s.offset+n, len(s.back))) +} + +// Offset returns how many lines the view is scrolled back. +func (s *TerminalState) Offset() int { return s.offset } + +// reveal scrolls so that line shows on screen. +func (s *TerminalState) reveal(line int) { + top := len(s.back) - s.offset + switch { + case line < top: + s.offset = len(s.back) - line + case line >= top+s.rows: + s.offset = max(0, len(s.back)-(line-s.rows+1)) + } +} diff --git a/terminal_tabs.go b/terminal_tabs.go new file mode 100644 index 0000000..fbc4c87 --- /dev/null +++ b/terminal_tabs.go @@ -0,0 +1,181 @@ +package mujica + +import ( + "fmt" + "log/slog" + "slices" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// TerminalTab is one terminal of a TerminalTabs. +type TerminalTab struct { + ID, Title string + // Busy asks for confirmation before closing. + Busy bool +} + +// TerminalTabsOptions configure TerminalTabs. +type TerminalTabsOptions struct { + Disabled bool +} + +// TerminalTabsResult is TerminalTabs and what happened in this frame. +type TerminalTabsResult struct { + Element *ui.Element + // Renamed and Closed hold a tab ID. + Changed bool + Renamed string + Closed string +} + +type terminalTabsState struct { + editing, draft, closing string + confirm bool +} + +// TerminalTabs shows renamable, closable terminal tabs. +func TerminalTabs(c *ui.Context, tabs *[]TerminalTab, active *string, opts TerminalTabsOptions, content func(id string)) TerminalTabsResult { + if tabs == nil || active == nil || content == nil { + panic("mujica: TerminalTabs needs tabs, active and content") + } + at := slices.IndexFunc(*tabs, func(t TerminalTab) bool { return t.ID == *active }) + if len(*tabs) > 0 && at < 0 { + panic("mujica: TerminalTabs active is not a tab ID") + } + k := Tokens(c) + u := Density(c).Unit() + var res TerminalTabsResult + res.Element = ui.Column(c).MinHeight(0).Disabled(opts.Disabled) + st := ui.Local(res.Element, "terminal_tabs", func() terminalTabsState { return terminalTabsState{} }) + disabled := res.Element.IsDisabled() + if disabled { + st.editing, st.confirm = "", false + } + remove := func(id string) { + i := slices.IndexFunc(*tabs, func(t TerminalTab) bool { return t.ID == id }) + if i < 0 { + return + } + *tabs = slices.Delete(*tabs, i, i+1) + if *active == id && len(*tabs) > 0 { + *active = (*tabs)[min(i, len(*tabs)-1)].ID + res.Changed = true + } + res.Closed = id + slog.Debug("mujica: terminal_tabs close", "id", id) + } + askClose := func(t TerminalTab) { + if t.Busy { + st.closing, st.confirm = t.ID, true + return + } + remove(t.ID) + } + res.Element.Children(func() { + strip := ui.ScrollHorizontal(c).Shrink(0).MinWidth(0).Padding(theme.FocusGap+theme.FocusWidth, theme.FocusGap+theme.FocusWidth, 0, theme.FocusGap+theme.FocusWidth) + strip.Draw(func(p *ui.Painter, r ui.Rect) { p.Fill(ui.Rect{X: r.X, Y: r.Y + r.H - 1, W: r.W, H: 1}, k.Border, 0) }) + strip.Children(func() { + idx := max(at, 0) + base := ui.TabsBase(c, &idx, len(*tabs)) + base.List.Gap(u).Label(msg(c, "terminal_tabs.label")) + base.List.Children(func() { + for i, t := range *tabs { + rename := func(title string) { + (*tabs)[i].Title = title + res.Renamed = t.ID + slog.Debug("mujica: terminal_tabs rename", "id", t.ID) + } + terminalTabsTab(c, base.Tab(i), t, i == at, st, rename, askClose, disabled) + } + }) + if base.List.Changed() && !disabled { + *active = (*tabs)[idx].ID + res.Changed = true + slog.Debug("mujica: terminal_tabs select", "id", *active) + } + }) + if len(*tabs) == 0 { + codeCaption(c, msg(c, "terminal_tabs.empty")).Padding(u * 4) + return + } + ui.Column(c).Grow(1).MinHeight(0).Padding(u*2, 0, 0, 0).Children(func() { content(*active) }) + }) + if st.confirm { + title := "" + for _, t := range *tabs { + if t.ID == st.closing { + title = t.Title + } + } + r := AlertDialog(c, &st.confirm, AlertDialogOptions{Title: fmt.Sprintf(msg(c, "terminal_tabs.confirm"), title), + Description: msg(c, "terminal_tabs.busy"), ConfirmLabel: msg(c, "terminal_tabs.close")}) + if r.Confirmed && !disabled { + remove(st.closing) + } + } + return res +} + +// terminalTabsTab builds one tab with title and close. +func terminalTabsTab(c *ui.Context, tab *ui.Element, t TerminalTab, on bool, st *terminalTabsState, rename func(string), askClose func(TerminalTab), disabled bool) { + k := Tokens(c) + d := Density(c) + u := d.Unit() + tab.MinHeight(d.ControlHeight()).Padding(0, u, 0, u*3).Gap(u).AlignItems(ui.Center).Radius(theme.ControlRadius, theme.ControlRadius, 0, 0).Label(t.Title) + if t.Busy { + tab.Description(msg(c, "terminal_tabs.running")) + } + fg := k.TextMuted + switch { + case on: + tab.Background(k.Selection).FontWeight(600) + fg = k.Text + case tab.Hovered(): + tab.Background(k.SurfaceHover) + fg = k.Text + } + internal.Ease(tab, Motion(c, theme.StateDuration), fg) + tab.FocusRing(false).DrawOver(func(p *ui.Painter, r ui.Rect) { + if on { + p.Fill(ui.Rect{X: r.X, Y: r.Y + r.H - 2, W: r.W, H: 2}, k.AccentText, 0) + } + if tab.FocusVisible() { + internal.FocusRing(p, r, theme.ControlRadius, k.Focus) + } + }) + if !disabled && st.editing == "" && (tab.DoubleClicked() || tab.Shortcut(0, ui.KeyF2)) { + st.editing, st.draft = t.ID, t.Title + } + if !disabled && tab.Shortcut(0, ui.KeyDelete) { + askClose(t) + } + tab.Children(func() { + if st.editing == t.ID { + in := TextInput(c, &st.draft, TextInputOptions{Label: msg(c, "terminal_tabs.rename")}) + in.Element.Width(u * 36) + in.Input.AutoFocus() + switch { + case in.Input.Shortcut(0, ui.KeyEscape): + st.editing = "" + case in.Submitted() && strings.TrimSpace(st.draft) != "": + rename(strings.TrimSpace(st.draft)) + st.editing = "" + tab.Focus() + } + return + } + ui.Text(c, t.Title).SingleLine() + if t.Busy { + ui.Box(c).Size(6, 6).Shrink(0).Role(ui.RoleNone).Background(k.AccentText).Radius(3) + } + if iconAction(c, icons.Must("x"), fmt.Sprintf(msg(c, "terminal_tabs.closeTab"), t.Title)).Clicked() && !disabled { + askClose(t) + } + }) +} diff --git a/terminal_tabs_test.go b/terminal_tabs_test.go new file mode 100644 index 0000000..e3964c9 --- /dev/null +++ b/terminal_tabs_test.go @@ -0,0 +1,122 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +type terminalTabsProbe struct { + tabs []TerminalTab + active string + disabled bool + changed int + renamed, closed []string +} + +func (p *terminalTabsProbe) view(c *ui.Context) { + Use(c, Settings{}) + r := TerminalTabs(c, &p.tabs, &p.active, TerminalTabsOptions{Disabled: p.disabled}, func(id string) { + ui.Text(c, "Content of "+id) + }) + if r.Changed { + p.changed++ + } + if r.Renamed != "" { + p.renamed = append(p.renamed, r.Renamed) + } + if r.Closed != "" { + p.closed = append(p.closed, r.Closed) + } +} + +func newTerminalTabsProbe() *terminalTabsProbe { + return &terminalTabsProbe{tabs: []TerminalTab{{ID: "a", Title: "zsh"}, {ID: "b", Title: "build", Busy: true}, {ID: "c", Title: "logs"}}, active: "a"} +} + +func TestTerminalTabsSwitch(t *testing.T) { + p := newTerminalTabsProbe() + tt := ui.NewTester(p.view, 600, 400) + if err := tt.Click("logs"); err != nil { + t.Fatal(err) + } + if p.active != "c" || !tt.HasText("Content of c") || p.changed != 1 { + t.Fatalf("active %q changed %d", p.active, p.changed) + } + tt.Key(0, ui.KeyLeft) + if p.active != "b" { + t.Fatalf("Left gave %q", p.active) + } +} + +func TestTerminalTabsRename(t *testing.T) { + p := newTerminalTabsProbe() + tt := ui.NewTester(p.view, 600, 400) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyF2) + tt.Key(ui.Cmd, ui.KeyA) + tt.Type("server") + tt.Key(0, ui.KeyEnter) + if p.tabs[0].Title != "server" || len(p.renamed) != 1 || p.renamed[0] != "a" { + t.Fatalf("title %q renamed %v", p.tabs[0].Title, p.renamed) + } + // Escape cancels a rename. + tt.Key(0, ui.KeyF2) + tt.Type("x") + tt.Key(0, ui.KeyEscape) + if p.tabs[0].Title != "server" || !tt.HasText("server") { + t.Fatalf("Escape kept %q", p.tabs[0].Title) + } +} + +func TestTerminalTabsCloseIdleAndBusy(t *testing.T) { + p := newTerminalTabsProbe() + tt := ui.NewTester(p.view, 600, 400) + if err := tt.Click("Close zsh"); err != nil { + t.Fatal(err) + } + if len(p.tabs) != 2 || p.active != "b" || p.closed[0] != "a" { + t.Fatalf("after closing idle: tabs %v active %q", p.tabs, p.active) + } + if err := tt.Click("Close build"); err != nil { + t.Fatal(err) + } + if len(p.tabs) != 2 || !tt.HasText("Close “build”?") { + t.Fatalf("busy tab closed without asking: %v", p.tabs) + } + if err := tt.Click("Cancel"); err != nil { + t.Fatal(err) + } + if len(p.tabs) != 2 { + t.Fatal("Cancel closed the tab") + } + _ = tt.Click("Close build") + if err := tt.Click("Close"); err != nil { + t.Fatal(err) + } + if len(p.tabs) != 1 || p.active != "c" || len(p.closed) != 2 { + t.Fatalf("after confirm: tabs %v active %q closed %v", p.tabs, p.active, p.closed) + } +} + +func TestTerminalTabsDisabled(t *testing.T) { + p := newTerminalTabsProbe() + p.disabled = true + tt := ui.NewTester(p.view, 600, 400) + _ = tt.Click("logs") + _ = tt.Click("Close zsh") + if p.active != "a" || len(p.tabs) != 3 { + t.Fatalf("disabled tabs changed: active %q tabs %d", p.active, len(p.tabs)) + } +} + +func TestTerminalTabsSnapshot(t *testing.T) { + snapshot(t, "terminal_tabs", 460, 120, func(c *ui.Context) { + p := ui.Local(c.Root(), "snap", newTerminalTabsProbe) + ui.Column(c).Padding(12).Children(func() { + TerminalTabs(c, &(*p).tabs, &(*p).active, TerminalTabsOptions{}, func(id string) { + codeMono(c, "~/court $ make seal") + }) + }) + }) +} diff --git a/terminal_test.go b/terminal_test.go new file mode 100644 index 0000000..88cad6b --- /dev/null +++ b/terminal_test.go @@ -0,0 +1,192 @@ +package mujica + +import ( + "runtime" + "strings" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestTerminalStateText(t *testing.T) { + var s TerminalState + s.Resize(10, 3) + s.Write("hello\r\nwor") + s.Write("ld\x1b[31m!\x1b[0m") + if got := s.LineText(0); got != "hello" { + t.Fatalf("line 0 %q", got) + } + if got := s.LineText(1); got != "world!" { + t.Fatalf("line 1 %q", got) + } + if st := s.screen[1][5].st; st.FG.Index != 1 || st.FG.Kind == 0 { + t.Fatalf("'!' style %+v, want red", st) + } + if st := s.screen[1][4].st; st.FG.Kind != 0 { + t.Fatalf("'d' style %+v, want default", st) + } +} + +func TestTerminalStateCursorAndErase(t *testing.T) { + var s TerminalState + s.Resize(10, 3) + s.Write("abcdef\x1b[3D") + if x, _ := s.Cursor(); x != 3 { + t.Fatalf("cursor after 3D at %d, want 3", x) + } + s.Write("\x1b[K") + if got := s.LineText(0); got != "abc" { + t.Fatalf("after erase-to-end %q", got) + } + s.Write("\x1b[2;4HX") + if got := s.LineText(1); got != " X" { + t.Fatalf("after CUP %q", got) + } + s.Write("\x1b[2J") + if s.LineText(0) != "" || s.LineText(1) != "" { + t.Fatal("2J left text") + } + // A sequence split across writes completes on the next one. + s.Write("\x1b[") + s.Write("1;1Hz") + if got := s.LineText(0); got != "z" { + t.Fatalf("split CUP gave %q", got) + } +} + +func TestTerminalStateScrollback(t *testing.T) { + var s TerminalState + s.Resize(8, 2) + for _, l := range []string{"one", "two", "three", "four"} { + s.Write(l + "\r\n") + } + if s.Lines() != 5 || s.LineText(0) != "one" || s.LineText(3) != "four" { + t.Fatalf("lines %d: %q %q", s.Lines(), s.LineText(0), s.LineText(3)) + } + s.ScrollBack(10) + if s.Offset() != 3 { + t.Fatalf("offset %d, want the 3 scrollback lines", s.Offset()) + } + s.ScrollBack(-1) + if s.Offset() != 2 { + t.Fatalf("offset %d after scrolling down one", s.Offset()) + } +} + +func TestTerminalStateWrapsLongLines(t *testing.T) { + var s TerminalState + s.Resize(4, 3) + s.Write("abcdefg") + if s.LineText(0) != "abcd" || s.LineText(1) != "efg" { + t.Fatalf("wrapped %q %q", s.LineText(0), s.LineText(1)) + } +} + +func terminalTester(s *TerminalState, opts *TerminalOptions, typed *[]string) *ui.Tester { + opts.Input = func(d string) { *typed = append(*typed, d) } + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + Terminal(c, s, *opts).Size(400, 200) + }, 420, 220) +} + +func TestTerminalInputAndResize(t *testing.T) { + var s TerminalState + var typed []string + var size [2]int + opts := TerminalOptions{Resized: func(cols, rows int) { size = [2]int{cols, rows} }} + tt := terminalTester(&s, &opts, &typed) + if size[0] < 30 || size[1] < 5 { + t.Fatalf("resize reported %v for a 400×200 view", size) + } + if cols, rows := s.Size(); cols != size[0] || rows != size[1] { + t.Fatalf("state %d×%d, reported %v", cols, rows, size) + } + tt.Key(0, ui.KeyTab) + if !tt.Focused("Terminal") { + t.Fatal("Tab did not focus the terminal") + } + tt.Type("ls") + tt.Key(0, ui.KeyEnter) + tt.Key(ui.Ctrl, ui.KeyC) + tt.Key(0, ui.KeyUp) + want := []string{"ls", "\r", "\x03", "\x1b[A"} + if strings.Join(typed, "|") != strings.Join(want, "|") { + t.Fatalf("typed %q, want %q", typed, want) + } +} + +func TestTerminalSelectCopyPaste(t *testing.T) { + var s TerminalState + var typed []string + tt := terminalTester(&s, &TerminalOptions{}, &typed) + s.Write("alpha beta") + tt.Frame() + cw, _, _ := terminalMetrics(ui.Font{Family: "monospace", Size: 13}) + y := float32(terminalPad + 5) + tt.Press(terminalPad+1+cw*0.5, y) + tt.Move(terminalPad+1+cw*4.5, y) + tt.Release(terminalPad+1+cw*4.5, y) + if got := s.Selection(); got != "alpha" { + t.Fatalf("selection %q, want alpha", got) + } + mod := ui.Super + if runtime.GOOS != "darwin" { + mod = ui.Ctrl | ui.Shift + } + tt.Key(mod, ui.KeyC) + if tt.Clipboard() != "alpha" { + t.Fatalf("clipboard %q", tt.Clipboard()) + } + tt.SetClipboard("echo hi") + tt.Key(mod, ui.KeyV) + if len(typed) != 1 || typed[0] != "echo hi" { + t.Fatalf("paste sent %q", typed) + } +} + +func TestTerminalDisabledSendsNothing(t *testing.T) { + var s TerminalState + var typed []string + tt := terminalTester(&s, &TerminalOptions{Disabled: true}, &typed) + tt.Key(0, ui.KeyTab) + tt.Type("x") + tt.Key(0, ui.KeyEnter) + if len(typed) != 0 { + t.Fatalf("disabled terminal sent %q", typed) + } +} + +func TestTerminalScrollbackKeys(t *testing.T) { + var s TerminalState + var typed []string + tt := terminalTester(&s, &TerminalOptions{}, &typed) + for range 40 { + s.Write("line\r\n") + } + tt.Frame() + tt.Key(0, ui.KeyTab) + tt.Key(ui.Shift, ui.KeyPageUp) + if s.Offset() == 0 { + t.Fatal("Shift+PageUp did not scroll back") + } + tt.Type("q") + if s.Offset() != 0 { + t.Fatal("typing did not return to the bottom") + } +} + +func TestTerminalSnapshot(t *testing.T) { + snapshot(t, "terminal", 420, 160, func(c *ui.Context) { + s := ui.Local(c.Root(), "snap", func() *TerminalState { + s := &TerminalState{} + s.Resize(50, 7) + s.Write("\x1b[1m~/court\x1b[0m $ ls\r\n\x1b[34mchronicles\x1b[0m decrees.txt \x1b[32mrun.sh\x1b[0m\r\n") + s.Write("\x1b[33mwarning:\x1b[0m ledger is \x1b[7mlocked\x1b[0m\r\n\x1b[31merror\x1b[0m: missing seal\r\n\x1b[1m~/court\x1b[0m $ ") + return s + }) + ui.Column(c).Padding(12).Children(func() { + Terminal(c, *s, TerminalOptions{}).Height(136) + }) + }) +} diff --git a/testdata/snapshots/darwin/breakpoint_list-dark.png b/testdata/snapshots/darwin/breakpoint_list-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..e11b0a072a9b2618d99c6334f9485f9c0ffe8a3b GIT binary patch literal 8797 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 OKv`Zxu1>}(>VE*6OZ*7{ literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/breakpoint_list-light.png b/testdata/snapshots/darwin/breakpoint_list-light.png new file mode 100644 index 0000000000000000000000000000000000000000..43ac81e00eb452f2a1a0edb9a933ec234f859585 GIT binary patch literal 8592 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

    Y$wvxD3s$BI#Q#$da)tkr%aqqA-P#rJy3MBmRc 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 XlFu1uYz(L^Bs4jxPm)z2~ zWZ;oo?bYn*nb+CuyP7+rX)y2;6y+2dDJ)^H@&z3|f$Tgq6d(gXnQS2crdfH4K4Yg%Zw=kPb#G(>;wQB!<~F5Z20W?8+8flzpLPv*JuWb%^w+3 zD^;bDsEIVe=?F&`eLrBpiXOIibabk9vMI3(0V|d&FSK%b;dVeiiNd4&%qe9fF4YQZ zI9}w^?2jTLED3Q>aIBD#f`@RpN9%maMZp7}7&iJ1oMCn@7B>44;wZoVLH+#s^NtVk z|90a)|Bf@sFaevp!~WlBphm3=c?KqUoH>ho!y5?0FXIDOCRf#Dtm1PcEvQ3dk|PJ) zx2At;Yf`1o;5PW#F46L@>7;qMxs@WpllmbY3`xp+cU=R1iu2#M(zG|TlZrEW8D_SO zy$%Ka3Lh>Rrcd&GyL~0p<9^+X$M=^)E|((s)G1?9s74(=y?n2bi^E0BkTQ{HP`y~j zps4S|#2&#!5(>M)l4<{zvwY^rR;*lsK+aFw#zb-j#S zsQhr;AI6r+!46EXOFYC)M7VURjEI{G8~Qt{_Bedzpj%tl(n7|>HDcOW5}3BIwAAFO zkW{X!qN>^hd5u5YaBy~U2|Q?XQpzN#Q>QzdTPQ8h=W{-!A*HY|yIN{2=6Z*K_xHJ0 zcQCNi2L>fG(NCQYJEBj+bNC5XuPx*XRb!(#H6$}e_iIzhbHV|%J4qIw5KB>kTzQ> zqM@Mf`i!7lG;0Xz8a1hLj&2zM8{&mXDn#O)}N2gmPw?fX>3&1`q9(6jNxoHA28t| zORnyOhC=Hw^owm_eIZgc(9l!SQOHLmg`1RMGRp5NYE^LK->Er|+$w&ROw-cTSgTXi z1^o?bFcFp^ks=;|< zyxFxbaFm6Ac;d4(_*Imx*=;s1Up_KEI`4~*Q3ssT4eUbJZpxzRx9Tc81X38Ss3IeS zn~i-m1X7V7W(cI*a*n5~?-JWH^Os0TY>F0NM5*NA%Z#3skAr$GEa(2HmDk>9a?&R; zk?%gl-r>`JiM~I3ezBd7?S4kPxyh*Yhleig6Tv-b8l`j0AMRM1n&W4h+8mVHYFkvw z;my}_zSSOF{`VV@cR+t;qoJX;IyYlGd-V4*=16`pCJsWZnuu z&U2&6iGkfTCL7_m)fi`vg3OinR{J;Ay_41)27f1-wHdIRt`GXhROv8p;6>x|+sajo z=RGz%-Obo;TR=87+02`! z+~oDbB-TctB|W--TF0o=>H53_4Sn_0aVI~<*-a0c1zV>5rd`OF^dslWGnfu_tLG`} z);cEFLgl|MIl?3j-LfLp$Nzi+&)-70M@NWX9y<;SvR^e&5WV7d_-=AP&OFY!IW`Ex z9*b_*)YsKet3IBxIxs{kSCz8i+8qMzNWU?$=0UT z!Tl}M_kw#gy{FTW5zN9ZJHoWT8kDZBqtWay6FfIuS=VE-*~hV(c4%rSazmfUR(W&t zXunD<+Vzh8<=I{Zt%T6eZh1Rpv(^NsOk=j^*(iTQ$O_ss{&(CC&oS5ChShQGhT*Yk zy~l{#f)l~ws7-4}Z$OvT=}}4K1-e1Ro9tHW&o6~{%q{ErJ5T&^r(byD{QA|%c7N?* z>W}wc#m>phy#9`^TWRfZ0D47>lZBIlHg%TWI8%f++zuzCNG1CUz1F5 z@(#3W{nD9|cZKZBxKCScR@%;2$P**OKAE)j2|p1KO&QM_Rtd@p*~>aF#a3NKq!G~n z5GF|n9^dAMyf1zxZK1RXSSanP$?@;FaK{%Kc|YEEIy?#EZ$5ti=VMrYT)-YWRj|@? z{H?e$Vj^7j_e2z-=pjPc`AHFXgz_gg==Wllk5AqW;J;M`{7+56J=gfm>~{c#J<$4k z$=)1hVFJ-eAd`TRKriJ+lE9Fds`yFSci7xzr4)0yhif*5L|oiRNh6t`5n5IhOjBek zg&|_|Nfr82M~efA$LM=A16YU-$22KIaN_(SG1Ki}qdh3hN-!qSgVbKxGN z`{O8%HZ~4+c4){MhkKAF|2=B;t@EjkSE)IkDyTQXI;OZ3v@qXUOg;e?>i4boXf2wd z0R*L7irOvedfemeebhCKCpkukOCg8B{XC6bQEUy=3sB zdV0;}WFmjLBi}f8&JWbo^^fpb7KJX>kt(%va|zttTPj3J;DaTLRs8B_Lf{@3oy^rW zHPuitY|(9++J;v4qDxgF_4U|E6xicP4(Er52NE~ESj&}_m5v)NE3;r7s^s-wK34Dd z@0E3dh=3#8obmiRPZy#Otk%ciR^PiLhQ0xW|NI223~f(R7y`c2LVeS$dmynMBm+qE zeUl&`4wnp6RkhV#(ibqu{h*QZGQ;SHGdnIlTtFP*I(@2i`&vhD?UHovi^Md<9ZL?f z1(vFfa+N+TCUWd z{YpYgJJ2`bX{ihV$ltiO;hGSpCuI2Ub);uEgRS+dejMyVjxbn;p9fFJ9%ij_2UqND zD`p|?aaAK%4UeWjDd_e?g=ut~tn=#PKy1;Nd;wAE)j5ts+lm{Lj0GzR*&TRRRh#|& z*Vti2R3qGf$$&vZ`7yv{pr<52*hXjIP=y>m*qFYV;6zGdDCdc3n+7l??dr0`kAiZm zCEsCTDTrfc1vY2vUG^a1+sD`o{|E)jufv_!mWJI~8-I7y&IE4% zh4Q5TgVOgUdyqQa9#ZHRsX%i!T!V&YMmpL~muDux;rfgV0sGMdWH)7Wk*UO>Jh3DS zadmWjS=cDu_8)I72=|So{@+R1C}3(~p@-jI5TKor-ISV29xvGjYTd)Y2zPok4^172 zUG)Ori*sB-GjmN_u$RMJcn4Rvv7OjUsrHD#0@>Ae=H~1SvJ(P?n4bfQ0M@oP2^2oe z^jc>yztU5idF=DzK>JRDCJDpl=}hYdcZO22u`f>d;(^$g#Mo9tXyE;Trpt2(?tN8t zJ}PdJlexL`(e9Tc@q)UE%6cbv0=o~nLzY}9$;enMPt^ z+a2S7oirF58D^hbB(&wAc)3;(NJkJsFB6N!8be^6I<_R39;yMAh5K$5vklaEPO9mC z7BI*YURt5bKm8It;DHj0sHv%bD=6b&X?k*E9dvOxDGwVmoWL%dIbdt&ls;@eM;Zd~ zY;8pWfffw1jV&w$*H*|L*DMk%WT=v3i3GNvVv!%aEm~eQNe*>^WLVKCC^wjPQug+> zM%F4c81uK6b2$^eL9MOH6pfDKGg6fCU_t$%1Ek`(ld=`bLRfjPCL;5V zNltFoyd!Q}`!`@aTC}%+pPJ)({N-Gv6xCu41J-`)a5Uchx}wL_OJh zdQ!ZwP$v_mCEdNwciRm#|oUE#UfCr7iLPPt<%!>Ns?33G?XcS?~MpeX#^SNxO1gW zVq>Yb(GE3wek2S8fQAMqx6?5B%gPEYeYJ_+TkBf{czQCgbu5S(8sO?mJo4;wb_I7n zNt;KktF7JSKKzNE{(3mjtwgm_n{0Y!rlEzS4WDyn!L$D~#_y^ODm*j0VR@v(myZL_ zA?4H=;H|Fu<|}unT=6ECIk3`U}8JbJFGHDdAr4wfZ3Opp`AO(LnH>hKXtY0dmL0E&l55 z4}P-9chZ^ML71s4d4Be|c6`q}{Qw*4`$NWOw#+dwQ2SCG6F`KO);~ZE`|$jrcvs`| zCl|Nl*C^Z6U6bm>g}TelS?2}ZB2rhM9Ze0;KJt*5i5`o{cEyUWhW zVvVjSy10V@ct0rcgS>W+A$Np^oxa0;=U}@$XQXIZ3`M}wm$%IJcA3Sp7ZDb~Sb*1K zanjZ11CMfrP}u?q)N%~@(eo{&{Hd)4G)P6^>FH_M?y@SZ-H^5H=kBuorj5y6$#Cu5*5CJVYauuIhnYO@TZcqh@ zLqacVFDJM^^6C^tRc0rLl-^aZ#btilu>Z+o#<=~hNR>KVa4fC5rJx@)!v?6`xn8%AYwbXM)vQ<{LUU2zSdmM46<26XJ@fUT1e_`L7zEN-G zG`NQSs=2cJJ@v1m$>fuE_8r@PM>+D-rT(qOu^sO8=+~$$-vHr_nVF|6Hoi>x@Dj0^ zZr&0#;UkMsnbH}fkji?nZ`7_30FgLV@$T-ybk;Xho+?q=RFUc~LGg?9o$hh3nG@y7 z)YR05{5N@es4u$ZmeEyhHa!7)^G#|w}zF5biuv$<&c$z-W(B&qoc#+%W=4r+H zi1|dB2IHs}i|W&FaX<*A0z%n6SyjXmgGvj={DA3xo$j|FgLug}bUn(XDwRxF>z zy#Xz}1a3ULNf>0k<( zpW3eOM(Rh9XmwshPU9=o3npf!-he%>J#RIM@73|gJn@(El$KI{Qv2g$F?E9U&8eTQ z;Igzck|=0*5!Aj;XlbdddBD2k0N2;aD~|I&`2@AXClyTF%x%0!ll)x#D9E{A_5OOH09;vF!LHLUC@Yjq1&E+?;MKmrp0^6Eb5ly5x0Uw1SX(=V z;o{+UD7f}|K=%7CKDRNgyXWsZ8r#DICIp!}!hJ6zc2H0G`|YfA*yt0gE}x#hF=4_$ zI=Dy=nd8pYdFbT0{SW_b0{}XZ<;I9@+x)pt->b5Yl5UAtVu=+1iTMW3)(51dM$mxG zw_oh6RFIMOYQR6%<$$v!-uH}7Jiy(+8L5ow?{E47K@R)D#*Bouhas#Go3{7%W3@Ck zBmjtbi7HhV-xj~E_BDymC;#Z=a7=MBZq3E|bYb4{n}OO_CYFqthI!(cd%Q_=wyS0& z)KFp!1o42|e3D4RXE!RokCCL9jm}|}RoG}EVI$#gZtrO6xXAl_Q;ed^-pqD=aXYs# zUq@40z>brGPq01|>w*VXwM@lKHQ;koAxmUQ&FEo&k!MsGFm>4qiQs15n44P2AiPtw zkO{l3*wRXxy=uOGuClPSxT}Hac=~Fdbz{Hp^1t#s5ZFW9eH|^&q@NRAB22^l3ll37 zBkIe05(C8?z^5&%@x-b09qMW-$ zt*n9izWpMV92}m+p-PviT873?z-tpAv}{o zzrCQNh>D60v}^KHnj{M7&;Q!QA0_xL7su3)PZ4fp*6a_=V} zef|K}x4$lSdexly^}Z7C&qrv0C1C91s+3$cy&dXVWJ)9@v4c^4Y4I(h&`JR(rbeob zTkwkB>c^m-g>VoC3d z(22pxK<@UEmJ4Ao=fV^Dzc&a4FxxV~H;pKEPfb$cNA#2@f){#sX0cQ4|TzO?k#g7Y4j#Aq_z zPA8_NE6=sIs-~%`W@c<=Zp}A?>`Ha1VGD~AO>Sm(2CAUA+icLU4`6K0CjPTD1tWQB zW5G~U{i!WJJrkLIe0=PuAP(bEM^DLD+O{m{jhwTFY1GByI=Uo7n#|P5yLc3JbQEP9 zicU-BLeOjAxti+MZJ?RkYxz@};c1u}85x}79~8zYP~}WO-7V8S@g4mN=^`0gR&eG1 z;4SWf!f3OO*!2YsCtg|nE5UX=Q0S166lmeK2OSX|LRHh>vynTfXcs@9s>SMgvtAWI zA($jQJlMv4+dCAxAsQ@Zz1mWDuRUIiw+O@{owGUe7iL6_NN!~T+L?gZLlYE>&46CI zBp4hETzv89N5=V|qF?==q$E~tLMBM=+?W(rbf4}RDJEo*qfvnm5GadcHfg*TbA>=r z-R*fdEi8;(-44c8p=HZfT{SkpQ9$u!~C1R&^U0blwWJ@zR^(OvWDgVx#f~hMR=r$Cqi? zvFaHbb|p5cz>_k?+qJC{qr)j_XCqTF|465A4BN^Org5eO$-^cq76WhRxdRq&dlm^$ zBc}8YN4%n6`?;!X&lyC)3xCjejHA%7<~OUoB+>D1^a^GVgTcY91ZD&=45}j_vlC*> zKM8K#8a8;pHj?D8wCJB*-560A@ltia()78kEpFbgZnM|XTKUN6*jiROecvSi6Nm17 zxx8b7NrBMfmAO2F-m$tCN~%7)#!*z_wjm(h$9|nRh%V`yoE_Au@|A|y?+R{2l5$Kw zQsu9Mrk-{S!#TDOpThI>>i~QqjgPs$s(yK+T4Gg3vo}{CDe5_`I5J`e0eUhzd2C8r zYDywm;fD+#JtI0>MrsZ-KOVnd+WKF$tQ@U?unyGoF%sR<$EI!E z1p~Kh!gOGc(`|G)gI=!{2m3ByUQW6gMkHN+t&N}C>)(#14)yZ%v5Y0`NLepk;_x9O zr5`-OK4f){@lIOyUJq?9s4rA#WNmGqph0ChH>r6_Ll9`70e#d;HT!MvkO=}joV=snvi}`Bi9(OeM_c*VP@d=%8vEjY1w@^#;)&l%okfo zk{l5wFZqCjmMp!No&;Whz9cJ+fVeneadA$ML0}j%JOi&|?S0s?>m5uoQlEm0QnsOj zfJ_+P-y&{Pa`Fdqz3=FDb`^#b4&mTarASbUhj4h@W-zK;RoJj^JEdw?W~rM@n~2Pi zw5pD8InTJxQ2aB3LYkmT%qW#J<7-KL4vAyPc)`TFSGREpuM`;rts+ zicWPSh*Xt`mmSE+MXEVp!yk0SuQ2=5=4W41!pvwXRY+xN;Q)Acy^p0dUAEY?=s*4B z4x0-i50vzmm5h=;3Ao$6zvaBuC*lS&53N}^c5PN@Rz7~J-?g%&D5s8)4BepX)^NRJ z+cDNX(lehnsm!d5%0w{quU9k5RpqRH3R)5glwLCVkp#H&)-LU*@m*P2o>>|N&wd_i zJR`nb9A8Hv-PL75O_^Hd^*T0U6fAKeu<{*%4Fs(TtgWy4)G4r_vA=DJqlZrESs$_> z>+&FD!zpN^jAbHY#O>%4c`4_B_gIi;gR#(35U#6k79H3Hee!(FZ+LOo5)h`0n^7qGKXHT>X#!5Ou41ZB$ zIM|S(>_-Zrpi|XefKWe4R#`8jpqfu{k^pa$uk?~YI2?vC3(lIw(NnL3pUjuxEmssi z0fpI*=g>KrhR;h-CjifQD9;J%Zscn>ukyIEi=ky49AwydtAlL|Kr5} zbum_NiB+s$m;~KAW`N&wX*tuSO#&SmHiVc+0SyT#FfYc6nz7mUg1Ya;(u+@h4TL3) zD!f&nG<$;%n|9<}sTIos{17e(g4q%}cm02P%m1|ef8C(}r`kbePx>^W=T0xfJ!hV8 zB}V^sQ*IHHHb;fNnU}SK0%5L;(0e4<_?GoG?@Ad&ZlZXUn8>a!ewiQNKNy#)zhtMj z?fu`u!R*x37;N4}VBfz)&tDww>mwF?-GybKxL5&21ev~l6g#mHYVy#m)Y|;B_4?_f zrR4XL24NY1AAgOiDMqRXr@c)~*zL%cGdlE^GY`&w;@e-M2yo--sl5&V9nz;*B?Orn zYqrMHp&G5A$Kd?R1E#NU5z(tc8)jU3=%TBjE^I8UDD zcOREyYP2PnDb3=?miGX?T3do0mTXi>w42F<=tRqor#9=IZZ7XOu7<7P3zst?&6X62 z6uo7jvuoyFHV;n(8COl&ZLb5SWg0p*ea}N_muA&4bUHqteJ$p?+uJW~$9zkg`8PSa z2^jLZcs?gfHl4YFjuvlLeyCx?qBE9Myyu^LHxe>guY-h^wY+y9MlhqX_a{6xg%4*9 z;5Obbm`g1*e*E|f!Y!wUd8#)|HPZ30`k3sPRxx4j{*@)b9`^(jA~i(7G^9t7gK^k< zZ%it&%|IyIG!gDQX z_-o8jtDO|F^DdlvTb&N4gt`{=a2R_vqC+bqTF4HUjziqW;S>lNulgJ&k^K3yp$ zDF!NxmEc>%lU)5k+pS#G{uYkec>7m z@7JHqqSm7exq5A9WbnZli2LKC^4Xa;1L+d*g;!T}p~~*=-nLP}4#i5?OojpP;97W6 zAt9H(8Gd9iQ3D%cb)ZOr%4{L|P*y5kVuC(L&_v%KvT&2_T{Zp4$A87Ap1@PcmZHks z4bNkIyW64D$9r=Hy4I)7OBpM`8~)m__jE|-~c z_-(m7Jjp_7MjRm!m-UBQF8uf*33!Xr@;(0K{dpkRb#EMQz0iZuH#7mX-aba~Yf)A@ zi6_o(^*N8xy5*E<3FhH>y~nSfJ3OVlQec`3BSHq->p9IHQMR$c2J;G&~%bt8u=+g3kjTXya#rvG1egxL5D*l^xz>l zdHiyYjZBn}A!m22;Lk`>yXf zE(R6S<;~4S`omY~FCSAm@bhcc&C4{PBXn8i{_fX>`W*Ips=csit>ufz|KvTTZ_q!` zj~aD-_zgF@?73b@OmIMN?R$HvZBFXydA`*?(?#l(|0bc}An}zNjU0w%!dx zdK0aYZF@G)d%XH=>EM}lwk|ufC}&ozT0Or7ZK$=#ll2-bY(}}5)$+diMp<>Ny;|3) z?CKzMwpQwMP4Bdc>plKEq*u!rhbaDeE`_Fh+P%2w%6a;yW-FB_mTw!VuC5SLc_;jlzmfE_VCGO3}bdm@#tF;Rsjog{<+2yaB-QTFtpJK&QwKjZ@*E@Rz zO-CGq`VIR22YYe{njEZ6n6|Z5eUQ=EP5li5B04HqQF zIjtuf+e`%N*~99h(KHJAbaQj_>sIf%_5;Me!(=yn&{&d35_V@!L*sBIp_os1xnDWI zj?~lXM{Y^UF0@p3e9kE(Jn>M+EGDZsB(}1Wbe+Xj%#4LR2Ljb|$F&1l2}*J4;3Mwj z`Dqk9?j4=k_jZ#gB8nbbe=r2+>40!?S+Xh!e?s8EJAn#vKh?+~v?p}nbw>&5>l$L6 zTfBC5E41sygbit=vrTO4)U&d}PUb~cZ9K$&e`U!Wi)?^=H2xAT>5%KfIU9#>{JhgG z{V<$cW_R1CPef4FzOv<}MnUgwWn%*h;Pxjtz@G{qAA*g+AKe*nzV=uRXs}w83@yHrq7@vEXD z!!a)F=YO|)h{!s^_lWjfe)ki%D=S&Uw77n6zDrqVm%}fao}iufuCkV!lYr-V z5C{YV_c(!s7H~zOxj7FXv3@xs{`!1t@TB&IuE zeOXDYfQ1Axbn)Gyi-iR)9UWZeNtxExTfaM^JRr6Ce3bML;frmH%*@Qh($Y$0X~SRM z3Q~G%N?Lj!D-A`qp02rtMI6BjEj_)Oh6Xt!qlKB7&%+dx*Q9cXlS<>hw*6{H_<*U0 z*L5v}0`JZ^guH%c>hJvQyl0j%z8C$5#Wu8U)h7#7&N>`Si`7fk{yIzVSmzm{8mGWX=|4u8ai3wcGpaMcC5xHg- zfkBT?+77iJ$X8X_tpb6Pw6uy1%{|V0;R`q(K~C{iM=NVDpSl}YH22Hic|NQuWfM!r zIax=CR?LQZKfAXN_K2{)Hqh_02w+@1zVyta+2YFKV*4>Nxo71^to9p1o)m937_!^W zJlxRQar{05Y8VutNXYb|7xEV!@>%UJKXxDQkTYiwXGs|a{FAoTj}eu zk~upx7T6d;2Cy}|%E#O~*fRk6_^ift_y)W@PfD|qVOgy_FOJ*9xqm+$?j`Hz%F5BF z`S*km*&(7{r6wnLKZC*F3zS4H8EQU^4h;u~$HzY>VGPx-*CK^@6p*E5CklYSjl&5- zTsrJ!hKs3{tOO@`eUId|w775EM;keMZ^0oif2_RDglcN)8d=z}@=>wt)};MX0v-oX zKPoh_%3}2mJsb?QyzXa>5LbcXNHuqHapw~TvH>ZtX0loPI3B(^o0R8MV|9x_K*kpy zOaPN%_v76R)bG>tZ=s@WTOwC6%0WIpyqp@C8uQbD1`0OQ%OYo3F^ZnLI#5ka%Y!?Q z*PE@I8xlZ$ac*5s`YQA4vak15Lc}m`Jgo#P-hHUZ)Sd?wFk$d(Wo2PwWg+nNDOVzY zycF$j7cv`MR))3SxDpQQ>+8$6yezc3q|LXa*9HRpq#bK%V1fExbCR>Y{T1-b{n7I9 zrqZ%Z@&nR;X};yvB0mHH4OG5*0RiLyWdUcNee4NBD1eO(txB=aq#qM4FFA94!@Vnm z_C`%bbrpxRkHdCs!Nf#e#}h07rraP2vikhAyr@DSrQvP__8b%UQm#?v#(w-|IJj>fSpfR9pI zy0?AKo|2N1Od-SK+p}0(TiY!+XC~#zo;fx$l7-DI*V*})l$7*2t%3nz8cx#7i~IJ+ z^!)nzdBcNHp>oFMVPiz+XnB4p)bFsRV>~=t)VrK;*gBlf8ksu90AQhEgEm7jjO6t!Ia}N&`I=YdfQN0z|Zh{b8RlHyN5->hg$+YP3 zILP5iNn`+L9|h6Ei^Iz1_D6x$Wzj6g2Pf`Ru*m$b7QFm$%pMAPM+#|sQ;#Nc3+}?b;6kC zi4ZHjs0bUtGC!G20?(Cwdb%e`3`tL!lLuVnZA&JZ`$~G+>ZYZog@=X7cqkaSxFB$z zHtlQ2XcAHSGVE+20${=>VLm~vi}WT?v>z#Dhlv(`_{SdB(5H7_>T?UpnI?aLtP&kv)j+mgjsb8%FC$yo4h;3PH~mm({+itC z+3x)*ZQN3gy>c;`Y6E1(g42t^Z)d+-T51Ic^TdLKTqSUD(3LcE)ySt?{_ayyQu1eE z@GHP^@KxAIK>CcDf>_{gk}~njXc3mV(8TMTqUb-4^N)6PbgV#&@F+CwT|cTH;EXw! zf_k=Y2I%|V1ep|3DJ?MPTRrB;ZXUd>uqX4sb+bj0MCOz~qN&YP#-BcghaaW}eMmis zj?&k!YEUExHi0@4dm|N-cZ7T*QDRE4GNdx7Y!t$qv*?|Djo%PqC}gf41(L}H^EaR0 z1^m!H{Orv2GHU(b8gF7w6!h*s0XUPlkwUlW|1F&QF?}PXZs+sy{k8wDN`Zmc(!v4# zNn|sRm|y-UuQQqdggYZ63Q;}nn_*EzClaUTW{Q@2YMSQZp>IFeOxL7qWN zn-@c@Zl}j}x@MZCZ5177t4BK1kV-EK`@gg&)PR?4_7B1*B&g|Kxw26H8;tVa26T1# z)tpQSP}i70S$n-tr?i;c>*W&bHxAF*y%|f1VX&d~#P9yF2*v7eOw^;vNK2zbD=RVj z-eoZx3HflPQ4DVk?x!vEo(M=Yh9c!-ZYoG)aD$cFeMT1@i|UWlbB&0LjCwTSQCeAV zj*ViIOC2Vzg98dMH8pMR?9SIG@LQy18b7=gw=7$WABruwOW#dyRPW6ZE_?iA zm~XrKxPueOsj2Bn`)uv~uZdVP+TzppGf=AEe_76Y8h*I`@B9X2H+gOkYThB4>%Ay4 zNpr5|p8x-~D{H84A`6E?Xt=V2N-`(GROkTXg2ZCWn;S54W zNz)g_7tw+JsEuMLg32cweZl`fh~)oGZGH~pdA__E+wJ$f_LgDBy|WDoH<{oby2ryi zgc24b=cX}-T3=%(?F$?&63ji}4ROT52`0f}%mEv-Nd&!jwNsLkws#dp2}brA!=j0x zU%57oGuBebpo)2&13janu2fZ3-5nmjx&6b3@!=&tkI&6LIRyPkOfsdXqnm0K`D4zO zE-v{o2Hib8Xlee|>wfV$zI*k+_naDH%|H`;pR8*a=5(=id6|F?MnLcphKK%97J9)T zC@eBXMuS#ZFn~EX;3+qt265E0Ggv*nyXmf7&pV@~DFqofV(A(p3NEP98wk^*K_M|D zYKfuK#iRepPB6cd|Km&--9lubHG2Q<7iV-ZD7SV*s+k?++Buk9+#9gbY_v}FWxx#h&eSWPJ<+E8QW-=NNq2iles zRjDCPI_D7Q7c9lazBzJ{<2L&^g_@ohaQFp@S>Ho68*BTdqtM^KZBEpUW;fvpYky{+ zjr{JjlbSLrQ2dFohc3I7sKa646cuf)IsE%HJOTgq_x(?-qpG7zikj|^3|b_3F9&Iyngq^SZ{V{w%M}V+4ZvonDh_ z)h}uB@k(hg$D&74nPz4?bJSy`R#umz%mT-dEwb}pROw!-TSjU68;_6JK7t#DadFXl ztGh5hkW48z#ONN_??kR~zS z=Vs+7NnR5=<{!{0-=~(;Rqwi!mt54uD~eyY>+g+&9zLsNMWDvDJ3LpM#q7-(?gktXzkt4ZRt?oNg@|FUkZw<7IdzDU;BBsw$ZDi zTFfnu0{&$R3E;LY2%TOuz68&%ZgUBI#T6~h7sClJ^?yhU={~%m9-^bSTdcV&wG2${ z;$M%M`wRdk#)iR+qQi1UQ#N6mhKs71)5mNQscn+T@uqB%1+chSy`a!0B%DRb%PV;6 z#}$XHr^84zrE#V4CXeU6wXBMcl-t%t(W-dPfQT5 zhKEbVneWY5|H@YXW6rX~aJ`Ojshi8h4s=o$NO^eR`jJWr2!*a)Zeslkz*y{%W7do$ zJPqhh7i%0l>q@5EqA7It#&zEvu?>{Fx5SRSbF$X{kBcQAd?llu?oyE||8)BJlL~R{s7T zm9s`>>k1+uJh7A&1)#$-EW*^6Q8`tOvnE!*bmdZ-7Ajwix6gp?P;D(8Q;jP84}_yg zg@Q)+X^_EhQVzQ2yN|DrS}?8yYqPcB;jd zPAT2@gGMn*mGZDV7gjnu-@a+#WutaI6;(H@8TDRiPq++D>Rx;y6{%B22sas0%AJR} ztK(oXoiHuV;lD+o4seP^AblngCo9a&9lv}*Hj9WR`3^R@zoo5A?{9arQ2%t5fA3mf zvK|jyT8)j3orT=wwg$1Ddo#A*g7$*R!126+zQb7tBvn! zxw~g(Z3Jy1%{WO`iEwh}=*iBzx6aoSWZdfQx$%mD$&>L=0P;4ibeNeVgSsp%6-4S}$<7sQyLYvJzrn?j}dtgMWOCx+Q)2A@!y{UVse`|AV)ocpa-DQ zyY$D}`(5f&h?%7{9KiNg*~v)g7SWl&@2%YcQR4oo;TNYJaq6&cMP@rE7oVgj84+2& zB-HO&aB5cO1Qs@acfe|Ka~ksqvwB&XMH#`^KW7Fmi3ohtU2X?EatbNH8Ih{3-VF4b zv;LC*G0oqRaW_Ac6ive?0KMSkN)`c)MhF2C$mJ3p%tDmT z&f@%e-#^W_*5K4?*X*&hYAf*zcV%c+m)TRSI=a<_|8qa_cHN+pqpj_7>M!uJPM09Z zhyQMQHJag(A1{_FG4cnA?&@DZ7?JOqdF0QYf3Dwb_>u>V1W>ndmEvTE8 zf01$kdmGwYyUXi?lx8M^j2v8&Wnj04u%C{gu@^o8`2cRFG+u4!7 zG!;ZDa=#k5_a82K%dN)C@vkp4r0KgLjehs~>UpntEp3I)xo~{zyTjA_FD8C+<{(d| zpQWa}?R~Ge$8PQ9Uxd@@YBYd^8W>9wIsYSjaEKZ{_#@^vukE*oD&aah>bZw?EnVMU zf76>bhM2%h36TRs^xDoH9c_ZPCY^dNS9-AT-(9S&OPZRPNQ_}xrKYB*=NHTSZM=c= zspRmY^^3>uyFFi^6Y~;ZCsvum!lCo{0+_C^*RbydZ&#}Q;9y}V)Af;&a`y>+)K?&8 z(|D*SdAxgnk^TZIN5nyKm57B!FN3R+;IfJe_SG8zQCM&WT8*XuNo3k=Q+T-EjQayk3^-|I#zB0;2Akhb76-ZcG>gFm| zciZSl-MTq<8%`d$d(wPrF6Z#BTGdpR#^>BUu_~QbAjD(_iov3l}{{?K-wn_j1 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/call_stack-light.png b/testdata/snapshots/darwin/call_stack-light.png new file mode 100644 index 0000000000000000000000000000000000000000..e0aa6b8e77d63a4112865184a9edff9e08b7ab32 GIT binary patch literal 15794 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/code_viewer-light.png b/testdata/snapshots/darwin/code_viewer-light.png new file mode 100644 index 0000000000000000000000000000000000000000..c40631d39dc0478ab799618e39b2b3c416eaa1b6 GIT binary patch literal 15572 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 O0i?wh#HvJ$0{;i%6p?NK literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/command_history-light.png b/testdata/snapshots/darwin/command_history-light.png new file mode 100644 index 0000000000000000000000000000000000000000..4012a1dd1f8c7bbf0f5332c9e6c9772d4fbf11e1 GIT binary patch literal 13177 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 z zsf)2-L0A}mmjw?Ui40KyI-2@)COQ82;9GYM6pZbC5<qbTyCK^QpZq773JxRgJTH2W#TrGP~{`1M88SPAYdPIOIGkd}K z-ZO09@(s85U8$ZSdwq3I4s<0?{ga|14|@_K;G(*kv8iE?jF@w3s$k?#UrR>*8rOFa z=oxZiKQ~>YD;SFn2Lle4eZ^&OCMrsbT?LP>VTM@Y@|XR^y_^oy!mH<4GRhX(j^L-Y zj_NpfCe6qb>SeeIocQpN3cE|UThB*vmeiGRN+fj1%98UNFyXj+(%|AwNND+s+4P## zKs1XTW-tLii+fB3UPsqd*D6J~y~|fmO6)^BKeyy=tgWpb42@2?J}BWPCg+DjSBwdv z5QU`i0Gixml<-dP1dP}J#9N%B6^j1@6u%k#??Lgh6SyYpFX&fi=aeFZnRS`7$HKg5 zd}7{LRPFH*w)C{#+n3grvq#AIoR_L!liuf4tJfd@0K*x4%Ts`IveNk0E2Dgc8aE;@ zzl<&ELvY}d-({dqM6lPNKgGtH3X28nH)RjVgo-*U70{JTarWh3KqI49=hnp~g|M9J znlE9=grQRVCsO}ZWZ^a0l`j+#GS!)!;zBfERtGrP-g&i#Q%sQJ6W3tPwMg1Dk!N>q& zXXh-CPlle>@V4u7N}}k>igJeqH67iv#-l)+^{L{B*v;R%gA%*Cs%y!~WCw*o6K=R)qxVlZ$7IhuQ;Vk^}+) zpfD8BwHZIcy`py~2I%{DaXQmU(E<FEnB;{pvh|6tCOECgt)@z1^Q1<8aD^N?9jCHL21W)%tLa2-glj*P61 zL}zX34z(S@8lKM<65+LhvAY4`Ntt|L)V~ny|L_0blfVi-@OjjUqJ$b#+KkvSvJQ-o z?*9zKC0}}(g3I&`>vaee`DM83h{SgC2vzt|U+n*9?V16acvsHil9pCmbMa~_%iNQ^ zkgWp#$X8vx?Lk~9XfM*0TX)&KVG{{{H0M{EE9 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/completion_menu-dark.png b/testdata/snapshots/darwin/completion_menu-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..d1dcdfe6b30a0309404d9580fa5d328f807bc9f6 GIT binary patch literal 14386 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/debug_toolbar-dark.png b/testdata/snapshots/darwin/debug_toolbar-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..0090c932f12a886b220c200c8ebde955581a0357 GIT binary patch literal 2158 zcmbuBX;2af8^_UQi@fm6Ra)^XkJf9;BS}rXQd6_dLQ6Zm%1BZ>BozyfJW?|>a|0=l z^7a)nGB7H%*46UJi%=1dSd~<;06Aiv{r=AEJMYYIp80)yX8s?Z|C4_>*iT)>Pz3-0 zsQVxEJ^}zJ9o=+akn-l-Q7L^30Dv6*y*-bn;(1dUhjqC>Z(ZYZ67|=-zou%zW4sv# zK%Hubp7U8r$_2nY-@1>rcb}Re-kMwZ_XXzFjOeR`7S!dM#^Kw`_aY7js;MW$5666} zK8DP>^w~CNc1NCSQD63A1t zdwsS?;|5fG^Z$X(6ff{*j6x*?>R-W!#ggRYVr{rpY`iA0axc~xlzqQ{SJ#<(3camO zu^l#NDlY$?;-!rJw#7@-@*u7-_A5OL{)lHCU}b?D2<_Jh-J%1JE6$`omf!rYbUo`4 zMR5VgRNJ@%-VpXt++?fwgSzCWmWy%^WbV8`1z~d9P;|_VqRm~wiC}f>^!WDD!Wr&7 zo_Y3+8PM~w4vyL1yU!_EOLqD4(i>k8_K*eExWE2NvUDx_BJ_e3!JQyVA=nKQLzW7_nl5vI=*N#MmMlxp%5yQ4OWGd)596P9JITTbIwWIA%7cx6Qp@) zdO8gPNic*YY)W`YGrqxtzvdNaRkw^A+tJ{1X(fwYC7)yYS!* zMF$F96_BbQJ_NuIqQi$i9KQ-FV(@C`QcnFPo0)ml_~-CKN%zUbL^SuPn@P+#KZr7-aVjIPbySl7%x5g%>eLy|KI==nYzP`=Pqqa6yS9d#I zf+Ie5m#1@DiFGJ{)}4FZt;y+@b+FOO(o(JFGcAAokw;iM)E@t4XHT15sLga0!P(y4 z#oqq88w{17kmS!_=Fu#ztZdVfvAkzccPYCGLVS9jqOiQSVb(X+l7aoU1D`*To))Y` zPg!FH?7}f012)ih1r(J#_cayWOJT4mYnQZ@fo8uEI~0rV%yzYlH0ZltTw)B;Qe~7J zyVq!{UpiE8s{eD#FGYx-Y?mk|hXY{l^r~_~(`ZMDQ{J)hO=a;nuJGM2V^T;flN%)y ze?f+pJ}Cs_fdj}xaq6`7w0W4~xj;a|jMbuogV^}r@h>{a zM#SpK7^UO1TCbf;E`QN_K1uDY!^=fa;Yyo2w zxpzCEHTvwwn+96hBtZ?X>$G#^IgE)Jq38yi!7rJuFdhmF)AK7P4$^2oxZBaDB5eP9@GFxc3984cDWP=7$RC?4TB-cYy!u~H5cUxay zpl7{&Dvcf9GXB8Q>zxtTrDriqQ6@e8yU z7SYSwm(BR&Pd4)yp~wN`PGp9>cqbr+ktqFZ%fTu05GNxfs%!5BnmT zm?U7xxewU-vGM4^r|jsyaM>%&TasvS6r-!+_=D=dt)3};dOaJS14jqHw+s++pz^B$ zPH@c_*GFY4wxW6G${@TNzLMW8zP8C=!VTr3F`( zm#cccaoOkB4!p4w@Qcy}1!#QRmS6c#vyt0azP;rbBGgk;R5-5N`Xgp$>wiaI$D>M? oDwyjnvG~`LCdRQP^NIn$yiVK1#lH~$ELzfZ7tEBrL}Z=>sNEC2ui literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/debug_toolbar-light.png b/testdata/snapshots/darwin/debug_toolbar-light.png new file mode 100644 index 0000000000000000000000000000000000000000..77eaa79692dbc95a66bf8f5e6d97d272fecf1985 GIT binary patch literal 2145 zcmbuBc`zIL7RR-vwZ(E>Rkf9>v{kBA`;ywZG-_{ZNp+=ERBfq{Qlu!cl$4TGQ*v8% zQ7KYeD@C_Z+)!IAvD6Ytg)9|u^ZtJ`@4b05-#PQ0GjnFnocaCE=VYA+y8xsQN{fk! z0o+_2y~V_K`HH-=X!FZd{cw!4BWF>e~BB1_FRh4~&^3n@lP4}+9@UN{j z;+{D;x&<+^h|5MTk8~FTif*XPjs$wa?AEQdKW%N#pcl8`*j5xWgr9;#0p%OWBZdm% zcF#`gyxk>uC;xw`vPa9^Oz2r2-%7b0|NT`|b5V51Hyg>c36rm`m%D!p4?>h%d+8Jn z*o3A{g*VIZ+&F3*y1p&nm#vtix_3q5l}dexWNiDp+ca3PVb188NKNnjV@kcqv%FjT z?;yJ7K5;>=YLaQ<2QwA3j(CH#o^)H^X6-wJvWoQY=2j0XrXAuI@;)4sds3X&CEhvC zc&M1OBx#qQl*O~nVwOM>XMpOc6-3Y?-4euF5m@!09?-jFL2C>;&328kF9rr`I~r=+ zi^$_6g4l50e%2n)|03igIxJ#~Sj+IS+?_IwwiUd5M5>9cGK-pcnyb*e6pOXwds@z( zsx?3b2FeW;oNXA_uo!iZd5!tbkQ<}xgHld#|9%mbM=yI4nEmGM>Z|Tih`Y!vEbOZF(3j05i>Geb*k3tCf>GqTUAhUZgjkjd4A=9Wb2vfnkWsHx)% zixJZ%CQQa?J37yK@y$p`<&z5>RO~2o=VxM@dM{(_joC@=3wp2Tgs6jv5r1`a)+aSs zq~+j16P#ULRz|^Tgx9_tHd~vZ{!PSbDhs0310axFXUYixs48GlU%!SQB83r6t-^RM z>`$MgbJ7_I7l+^}iz|?Di^+cX&wqTe+DQ>qBs2+`lerrYiJ29fKybN$U1>Td6BC7F z?-`X4RKE8F?Y0&kd6yYrww|E!v}!(j3yMb6*K&SVk%%s)e*Qb0j5uN3F@^+4mK?;J zb%ujuiyY=o;`=l{ z1Oj>vfGXd_g8N+$r*A;p&cH(U-r5I(MZtqbui`m8zOQ^VJzs~?*y!UYN>;2b9+4&c z`nH{QF~eW>IsScsa>!Ztx7w{>{-j}jW1|XnA%<$18sd+-hJ1k8 zPS1aQK#^>8b2EEw2*-Z@lTk+bk|NaA$T*a;#NpvW2A?Nhxedw$Ib$#l)vZgQq2&dU%`H%?;HW3tyAQN){Gz=wkzWD`hVzk zLYh`T0n~)%Ml9;a5+3@4HidjaBF)cZMnV_R>!nj>>@A=mEln`obl+b123l8l5nC66 zts7pc3G;mL*u&v&a&ZXs+G)T5R^e1>=G)dJk;KiJC)Y7m)vuR}$5K=4!ukU+hJfE+ z=0N=YSQ`~}l08}^d$3t=y-ZxvDbdFL#%Nu5R(XSy*83w&){Wl*V~9SKl2BXA{$nIZ z5#39N#%`#lC)W2vzp$yz{_5wF)WWR>`;z$U%9D4h_TIm}q(ri?fXJcPS4Unrpf37F zejcucvAOlEo8vsM^t0?lxhl{KNM>$ z4sVWkPu@nQ=NA^<5Di4IT-qg1n_8QC+WyhH&QWLJrpd+HOoiFayG}ZGOf7s5L}0ju zH*GGNA}Y=-I!RpcBCevxq?JMSxcXK6MifXoqwJo=b2L46wexd3MUbwL<)K&b>4%6r^=Qekdwaur sGWYUQwf?=} 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 DbkWx< literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/find_widget-light.png b/testdata/snapshots/darwin/find_widget-light.png new file mode 100644 index 0000000000000000000000000000000000000000..7f8bfa421ea775cea83dc1b2e797ede40303b685 GIT binary patch literal 8713 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 RfaY-kG7^g7m7<1z{|l>)bdUf5 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/flamegraph-dark.png b/testdata/snapshots/darwin/flamegraph-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..9da9b695006367835255ea129c9df83f51956c9c GIT binary patch literal 13502 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/flamegraph-light.png b/testdata/snapshots/darwin/flamegraph-light.png new file mode 100644 index 0000000000000000000000000000000000000000..6a9f5c8c53f2d5e7de57ebcb43f1ba3ae074f430 GIT binary patch literal 13200 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/hex_viewer-dark.png b/testdata/snapshots/darwin/hex_viewer-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..3296b9283dc06b32674e019575b55ee57c125bf2 GIT binary patch literal 15629 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 C07*{( literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/hex_viewer-light.png b/testdata/snapshots/darwin/hex_viewer-light.png new file mode 100644 index 0000000000000000000000000000000000000000..d01870b820081a59c296149be6f0e913364bbfab GIT binary patch literal 14906 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/gMeSm~+cxrKV(YhfKQXs+M zyZy&L1i=ETt;KQg5ul}Y719;N{bssvY5C8qOzgLl(38?mU%_~aT?#>0K^ktI@Ssh^ zTw4v;j1`bty>x!5XEt=5*rKmbOr2o!t^RqYk=u@;rR5wi@Q$MuHi)5+9lq4q@PnR~ zwk6ixxNRdoD@z!*t*Q#A#`ysD^DWbS@2nJ?R?Cc!kC!?QALy;3NXlQRd~Gx>%2rWQ zu$Er>3|KkMC~eOoO;@B(k~=?lg=~S;{;#(b3Nk?ajs$QJDLxIWrMkXYw!aQi8dv3Km0D|v#cB&xih~iFS6GP^kWNp_&WVv5c z!crcZ)i_L&Wy57SdDGo=Ce>8ICgRPpL;@Z?c)(W@PW}|llu&+lE*@zGC^~_~@&X-k z2d`8A8f}6c0{0`E1M8`&$k$W?d+0j0Pb;kESA?5e?j%MA*9Qm(xX52H8y3;WRqtw` ze}{w>K_*PfPQ(HhTCD=DGAH5-ad$&E} z26R{8qqTR)$Vd&63F2A_bRWe#l4<;!h0XR`at*?^0|f+ghU|?S&CN_YME@>knhsVC zphU_802r3i%;Ms6h5O>aQi5-|xk0%TiA285xfE2xEDinABRf3r^H&Q74p?VEkf(A^ zDgoL_oPMsT{#e@N*r+dQySGSauo6j{MS2HM&}c^kwCO|)-&bBTZ27JdbWU0tL>mW1 zB_$9qC<++=1|Tm`Q9D4|Sci>RpjUv3bHDd9%WwA6r9IM$*d&a5-^rm=f|Rp6Sni-7RznkOpz)e6wArj@a6wx% zU9o0sP6-*cfyg{NZGOvrXmT)0rqB^(IVtT1rhYsB^!R|`;riB%FUn{F4F6TNwL-(A z1wvy9M-E5@tcLZ~kn@R@N)-NA9Qnq;eP(7^1v7=1k0>uMh$sDAUhbLcq31ft29u3esAD9Qv8%f%KH(v^nk@RYV2vav?oTF(z-jPba{<~a-3Af%(pvSSMTc^ zpsAUx^4a+O+SQ_Nx@WmicCRZmGIGOI*1ny?4m2xuf?Tos(mXF(*y8N|xj83wpNZO8 zNx^0;2tSek&c5}3O8k)N-CnW_0@d-4wib>)yG|7y*;+C?g05CD(0dyK=@Hgn8> zEg=&GXJ%y1Bqqa~!KlqJX*jzu>)=%oly^gcK_X(;43=3!B{&2G^tb14Z*a8k&$YZZ zO%Ls92jQ(Qt#bOLAVAfIrGEz#e}0ekqkiFU;p3%`ni)TVrq_^@$VBu&%PmZa?)ar9 zu6#b{$Pq6W5@m&OAzQ#<(donE~j1TUTlz5)(eyIeqKgieR-P}D0O}V?*MipuC zis_5VmpqYyyn^sSEPYXu6J*V~=^g@V8UNBd{T0kSRVE07$p=u>5j(ZJ`zN1?9-!nt zJj)At6x*8-VPay|tP@y@+T7Vm-F-pUM?8O>zmaGXMgX>_+m0KJ+Dm-6#=BEv*B1i- zDWlHoz(*h;4B7R<3bivr|74wbWhG-qjo}RQot|D@YpV=s#pCDYWsDDZz6^9w23%xC z5BKRpP-#?E^hN2V2IIDo5Z|}VOhk@#Rek+93R*q3zppFusxd0{(GZ_4Yt(|eL)rM; zOv1NLYr65EsWtbCPrp=h!MLi*%94j9(>Riw;;ZXMEa>PyA7wH8{Y%Mm$hrRd-%NBn z2CPjF+uPf-c&mY86k9}b^s6f=YBjPnG{EN1Md23i{`vV~8i%i%x~CZ1D=}nVq*ZZR zYEE7nl0rzsTZw!*eb@;u(qGi>u!brmTfLw3w^s|Z&4iDUV)DP5qE<5eKI0Nt)kZe& z*;uys_t`g>-{th*5`?@ffNMEo-0K*K_ZYTK{TxNz4J-kIqgq!~1``~SLrIqdlj%7Y zr+SyH&ztiL!`Hj6D1~@S(<9>47N(%O#_Gz{33I%J9;EKZYs(g86WE8_LC2qRk@<;C z&kuvb&g4X1f$3-A%smka9zhBKu(Bz(ti5cnL)zs1r@)Gl>WiN#SvV6Di}41rGw|_8 zfc(ed?6y7KPm1&wDWOrQc=L}FO5ZWk%))%yORA2%mda|KO}Ef61(^kFp*w$GS3$pb zbo8p^&6HJF`x6C5a`7F2vF_p{#qma5&G~b{;r;|tw2d^T?Ldzkxhk>nR#2D2q=i?6 z21#tQ5_FcIvoXb7&f8n`y7HEjbl7uqvtYqS6A3#*@kx}C9+c#@%cHaH7Bau zSVJSaIG$^B_zT=<(^M?%Z&k$7YL?*Z$-!5|N*JlnvXyD`mvdf5+ZI7}XbC*zr$1ya zc8iBy3Od<;q+{87WOlKXS>a)@4iDXw8lqx2p;x#lO~YFyASVp(o+Mivu<@ zlKWUz5lJH*4xOetnzJ|W6lBL{211x47DncI3B^>-Y;B$7n_10f^sGl&2%>dr4ZV*g zF5fA*(a=27$WFQc@PxX$U4ZAkqcmnwLyzf2G#kCn`Jk(+YiM}x+S9&o$rUL_TVrr> zSiQ<*5cF{9(-RG1g5X%ogMn%U+4yqonhfa;aJYAARaTxTM|*kv3i-UC*V)6hryeLS?qe3DEp$>y7$^~z4c+z$lYkQBz8E;gzV4;o9UA21Hw)TQe4EmiXU85aCWjaYIQ*b}y{-6;~Z-J7XnV@K%6sVtevJ8rR5)beU| zWu?ZXB>^@?=AM51S2M!QQyWuT@Lo^=i(*+|HA;G~a-MrG8yjzlbD(A*0~=3Qr!NKJ z_qk4r{UW^1@+>QRl^<+oVI12L2-|+qjspr7>vUsIMj#Qk%R_OwnLHzllM5Bi%~jva ziY~f;`NcV`G&}5GV<3lGTJ4YzBEYTN#4Hah24#%FDMQ(w_jp&(iL;KK#)uLmhkAC3Gq>u%-k0fM&}CMkqT7kp%nivGf-ryd@z zAK$-^+Ik#n_;Id5VP$Ivp>20!EDMT2)@PkyuZjO-WA<27box9^(G09E248b4>SyH) z!r^fjGz#L%%0}XK1vT1?xE_Z7SW zqDkC=&&0^lPVc)rylfJBI<`N+6BEo1WWG#PUE*^a{Pg+4`u64c)45Q{JMl+VV$& zx&(&C>Q&rGsR{LkHF-&zYps*x%9a-CO{Su|AfCv9FH)oLFT70V=Nnfgc4DsG@sU?z z&>u>yx8L1M+&{(7+_a_S_$$k(iF0-$Q4C{I48sMmwpHX5E6Thb?S)j0m5(*| z21xidiah^y@BMTC4Fc#duC$WVOunX>obCsnD(n91`K#*{*ihx4hbI4ve^A65%ID#9 zoA5haP9B@-&h(!D1S|eN`HJv=Lyrz`17JZ%%XO%|Z}7s^o@v?aGfD@*OIhCU^7MJM zhEe7h?%kDSws#W+0?!G%ftPQB5ztNlpT2ye2&SP{kx!gEq|Ar_YN{u;k~!oPFI#-F z>{c)4?S~5&TSbo3{s?EiXS!pMPh5}svU2U=wSZqALhLY3`!6zE6m6LI~Nyd zwUOP<$%Kn0rHmC7UDLOM=MorjVi*Wuf@b>! z4AVM3Lt`9TIdwPoPW#VGdCT-c*BH2@eSH!--U!I(-?qsa1w;40N7NEGLI#MHqT{UO z#}%b1&rh!~qost)bNY?5AI|dA8*6qo&q+1i58jcrY%q*QrD0FkwNxn3c$MNEw_+km zv4^qS7jnA~Sg#yv9a_fF79_zy`yzu3Q+GvtoJaFQn7-wKc-^0EKCEP}p{X|cY0Rc0 z`>*-3(B@=v0zAneZ;kK846t(!?|t}663FV|Ygdi^^_ExK;U-g4J0?F&t>A~NM%e!S z>AEsYUg4QQ&+itTV0d{>4}E*X>Y9C>`%|7?6-_CDwevOmYjbz3-ix}{$JQc`-{tEC z(NhK{r!js15QAaI&DzWRIiab^X6;$6AWW##;hu3||9kXcEB-_6QOh%zwY4=#tqXBl z>QB8NY1-0jE z-AWgz()kwBCC%z2>Ti*!`FN<$2p)dV^~dc!O9#6S zOt`ZaUF$tM3OrGOa5Wo^qBLnskBJkFcVI~DGibMzE0fzj@#|6Z`LDUTda?jsKCcU6 zbaeEU2wpDY;V8-cMfY|p>G%Q`qPe3L)75f@3U@?2c;#%mRJl3jtP2AC8M9vOuKeB3 zFT$;+W)=Z?7Sa1%n)Hf44#KXL(a$#Bfj32lgqYlJ(GC!GwbA*Ij|w`^;a=#}FVZ(CYI(HYQq!wQI?ndR-Vnw+oh2lG1yV~c%x_`g}|w` zcf;|%0qX*xKm5+JL#H1<6&-$=~H zghCqHKs=(y?Ggb4$J%|Ym7}S>?4;KtuekmV`i|B^(XG~5(=w_r7e}?a>afo5dqaP~ zI6TdySL5d#q7urjz=5(5Hp+fWg>A*+XhHD)`)k_f zGynS-2X}^!w&9H^1J2Xb-9^Hd~BJ5@Q=ABoO)YkVf#hoHdZ_W(X}weZRsmqnW?fP*SP$aaL08W zoJzU;CjZ#;<`oqc)_?T8FaFT{qL-n-oGa{R33`kup8Q3g$iGX2@A6HOVm9j;)5XsW zfgCqPJt=ATVMvnE=qYp!7F&FX*|_vhTOYP~{Q{#zsV+_Jf{6VGMm`!c!OIPDiPsx= z!fI0owmF{LHU}wvUs@N3cqBEsghXKQ)<33${B>e*Rf-zf)YE6g;^6dnUI>^+SXU^2 zF%9v+>0JlCn!kB32JW#!tRiN+BQT=}700Jvj=$%%o_)h9&*_S=_0Ca_eV(#`@uN2% z>psbE{1|lq#io3#S6|yBtISNEp;7+8XvNEVjSM%+p?WJv zu8p4e2gaN{Hr44mLjbt>MiB5A5WqAQn}j|kt@s&Nccb~)DUyw{z^W@T(|h?{ZCBpn z**~;4RO?4t$<2LJwIGjeh`2Z!8LxLm>xjtjFdPKKhx?I{b6wqKq%i-3O6^o8{Rvi- zVHW{U|5WD#14F}XEdgI}IG0*kGKTA}^hHEsV4E-3`1rWnSt}b6Pxs@V!H$3%D{-Mr8r-JXApO1y78SpPw;x;gK`izNX#QHuQ1k=lWZIk z;iuxpBl1Nv&Do{5Rh8*P9^uRUzUQlmfYrN2V9LX_UjuojDDEE^SsioCU}@Z{Eu^ZD z8NDH%IFWX!0r5vZzqrYARf=5rFho7=XDM0w3FHi7O6WiNL(UIZGb~Vzt~Hf zfBP^9C&r7UiTx^NqkY!3)GFZeL#y+3Qagf6nElaj|?=fE4+APtT zpc&^`V{;b{TiH<|k0@1DPxuRPd~qU{F5ljGj5cRi=+~S44o?;^OO$f>{GT8*siM-Ute;K# z?P^E`-1q+GQ6|N8>uIKBrxAM1e4j)K08sW%aPBvF%Zjm;6RVohY3}pvT+y8AM+M? z%=?r*as6jOX<7v|{bfbvmZ_NyzWnVsLnI40@Noy2Sh0EpdVlndt4DE)E+N-#3Hd*i zi#8snjPpgLsqL?cGI^`tu}2Rtvi|ai-w!sOB4!^ro%R;L>>MypZ&X}doLyfTy1gaG z!@Ss=HpVkzpf^P%PKIEI85ntT`OVrTa$<+ii}&OMD@e&>X1Qw@38Q$y^kOC+VS`1G z?mv%@Tx>iYr=HR-=HufduebnWHR^-JNGsDPMJ(E$pd`KE2s!_M;mzcq`iwj{N_U$BP5rdupRG-Vf zZ#`hGyNEe%dHEP+kyq;}V(rXeyB(0f>P2>kwfyH9=P}ShDWV*vv)&P{LCeWT*e5@- zX)DN~GJd#EB?3Qq(J#M{^Fq+;E{=R|#e2}Wc}qhMp!#KVvxTN6XqUcpl;O&-OHECO zeLlXxC^%yZ=HmQ>W=WWdY2;n_H5hPMZ4gdBD!UsT$aYu)22hA2qMX{=Vp12;o`G1| z-;!vHIn|FFWo|Y#%3R`@bY+whDT@u_cUv)G6?n2S3GWYBX36lVO57rpyw$8Vnk!&Z zSoims`qvt3Du|vn7FT6AGJfe~R0zFrSGT~Yh}Gak2@qv2PYJpeb4_nPZiLArwRLJ~ z3}n{4QyYvEaMev{0-qg>*~V9Fy=*5LDl*{`FYp@qT?T-`SoygsBl~WtjQ%vfs|bEW zti`8Sr%Ctbq`Y#Zf&f=!G>)6zk`sM>LruzMyZ*=U?*0AUq#HZ6Z`~u~GV)40DdPkR z+~e`%B*L_bla`Z@*a25!XGOrf!I%&Vias4iOC=>{F^ppyf)=Nwv`)kKU=F>=8RvK06Y!=MIk()GRN;#=T;T!pO|>}Mm9Cxw#vB5 zEm*R|U9PhAQ?es6?Bwjs+K*8L(6wd1vBg}@sBS)iHjeiGg24%-vPdyL;!aHZ=>af~ z^c8*1{J|RK#R2BL1f0h4T7i5m$wXMDD6Y6OG~o2W$yfZL9XY( zsA6L6Ka2D5qlx=l(<#esrEM+)_pW%=$UQIp*C}kPi3yzHZOcD-xbuF>5nG9A#vjCq z%WI-4(JT@=g7Vq$4OkvmK>5up{N1^iy<8mZr5xb5t}V^XYvpO<~bh7y{js zN(L@>TB49#-)(e>#UR9;L<1$W8C8OUSpuXs;*@YXFSDGP4w{-?-{z{Sj+hW<(lBW| zI_4S%M%{J?4%-SZRp}My{HhMA41i$bpqELkISsBQn zDKMXozEY=CI~S(2{+PztLF}qD`-Dv+> zq5pPWb+e0!RhiXE!iW^tZnCQmvyFGcCFs*70JlnNOl(1SDd0e^b%F}jO zYag6g6MR?~(w<}C;o=;7eIeD*_=g2oQ)3sy=<4b!%~SgFDH`4h30XPaeH11H*w`*5rMkdl3`7P7*-qx`$zM;DvW0P5E*naZT9_CaIh#MS zM}I;ZOgE$bIIrDC>VNPTF-$xUEFg^+-;n)$zr(IEbRs{Nf-GHNdq$U~ZLDVG@yfh8 z4L|H6v)%c9?=Gj=Ga@g+Nr4Q;i@O=P7ftVUU`ZmBjoPAtciw7 zf!_fMkhAP4%;VQ~-|m7q)Yx4m_``yK&q@}}=f-U;&Tj-0^Y3?4jM)4E#nzx7Qq#0( zEF@d)gI;F4s}B}`^mNB(;D3z|*f{q<)gbg}E;&(4zC2vjGaSEnRX0LPHaAx-)p*4D zW67;GmLM}?dfeY0zT?`6nzEJ(Uk8V#E2E4J$99mD?tIJ-0Z;a3gVWwgtiri zIQuEc@6ygMAP@Xp#`Ko`}%|SZ5&p=)!HT`@S|d&liT5Vd0@IO-&7a_9*?# zG$k6E!n{xGdHOA`GnS%5pW>unpJI69G7Z0p_L_Smc;mM*`L*ATO?D3K9gLlv?M896 z<@3qsN~cgd*q>gA7tN11xF$~zUV;6iIqG?xH)w3`e!RB;nIc=ScSXU)HV*RQm@q zve~le+VS@b2)ZBV8mT%tPaa+xy}dX~gE04rVi>LJC^rI!aV;zfbe@7#5O-S<-WePD z-5$d2%`g)WYY*A?fbO@mI1Xz__=DBy8Vo*s3w#~l@7X$$Vk591Eqq zKM}p&xBCub9KIarYDeOKn6a#bW8Cd{dcn@?Nj!|_7{F$8nMR$idodm|w8-Jh&&!1- zqM>Hm7%a=;gbCZT!}A_=aW{MK3jZazpB2_1tZ}qh|E*RQfc(y*S=83Xrm49( zAI;Z|zDWaC~rg&zNci%Iv!2#7gm{zeCR@ zXLiT{rtwj7x}{FC)?62`AK6>&*1X26^Tsn=zKW@TRrjqyb-S$i#+aHagN6TIoH|9} zW2oHc8E-E7-%5;tk_|#u1h{v>qMwVPw9y2H6$*V&U_QdU4}x;0|HP#r8Vu1PTjA~H z8{kTw;+~dx*ypw@Hz7_e{tH=|3+3EtJjcrvyJ&0@lMaS;xwRge@NU=p;yD{LpD@yR zk-R@}E58C_J|oa)bHl1aJtNADS~_XS{0o|*F)ZQdAs5gL_D)g!7b8|yA$*@oHQKwi zfooY0VYEQ@c$Hmn_k#Uu#N&lP{LT471?^*)h!_U?C9aOk`46)*RU)=I#8^}IP_th! zwED3H(MuVl<<*S40@Gq>7$dwC2>I>#z>Lw1UN<*eRN;^BY6JJ&(&6LXfjnO}TLgum zX0Ni<^NmI7^Kf#kudn2_ADVOHH4+|N3D~#UkpBEK7w!6cadoLi23Ha_3W|9Av8SW( zwK?ZZ$L~MA|NMPiMcDj+syp-Je?3T#eE;{Q{qzXCl}PgqXWu+u|J&f5)mS~UVh`{UK?8cF_~{a5U6IXrV;Awe>LN!BQ2f0zAHEe zT1t_jPdPX|5H71C;`6dG3jX@=v4TVl5&DGq*1 z^o1fX@y{5QSH@v`Y-R^Qn|c4T)HH%ahRBgB0XNr+c%s9yswzbvLmBCz^TGn!{D+I* zDE|~4=p#&P>Tt|TyJF^_-}A?K%DJdIMCOh*Q5f`J7^7oW#!VYA;~v0uyW{VL1FW8$ zPo#uK3MK*#eOOThTD=0Lbkp0y2E*p9il=-x%|N_30bZY4cOd5M1ma)yWro-0`mA2u zf1ajI8@GBNFfPQ*#PX5F67W1!#ASMGE=ckPD_x2>{|;%G@5srySI&_P4NceA`xw}r z*!hBpj>y$ei-5REg%#Z`;LAyS%N^w)Q+*4Mj0dIGD!Q73KgdJyn2cr?7jd6-BfnDR zpY;$@Qx_E%(*QBq*-eLuBkSu4zY=ueW@Kc<;IfD!oNqMM)YnJX8@p!Jh;CyNl~?!( z<+F&FzR3bSA4pCRQh$F#BuxFi8B2X+%nbe;F^Gh?`3dwa%^@E%{snJ@`e-*QB75DS zzgaTW0qro}Qy|s*m+uF1F@1e~J3Fr%x?4Y<>6pCAK-B;-8`;qk@;?>dmlU$^-v&9X zRtHU?qLEb6jEKi)PLd;AV~LAi(|WriUx-vtP>fhz`H7y2nOUFss>3q%HDVYCrzAdm zOH(ti#BKl3a$;}y>~VCNApPXzq~G42las4qj)OT{sKi>6$<2*}rH1X|!ZG>UYw&L! zDfqQVk>p;lw5-g>C+_-&aDI3u=*CDHA#AZL^_gjxKSB3qHaa)3U3~dym@M$&I{lb;j){)7v8&7QA}=*n zOF1EGkMj5kv79B*ybo?OIXMQK=Bd5SSITkyOOg`V_Q>YV58OQof&szF7!)H}%nB$f+wXtqoR_BHpau-Xh3G9Zat&T~C#u z!%P*dg}jpp6W^ZSk0x*v5~5)?Zob(W9KTe|8mc3K#sxm~y0mpPbg_cy@@b%i8-&U1 zQ?DDzo6feFGu|~#*kB8b{m>W{P0jlqskaADW)7<<1}1>0$ECj@Z#;|9UXRc1QgqRM z7;;+qn=#D4OkDviBUW^%cwSqPMTbt7^XCU6&v*rT2OG!5xw+!`V~}rmC!Xz(0&R8m zBwo?4G)Z#QSY;aYNn;v^st1pbId~FMkZ|AbwxSQ>M=f?syJn`GO^r|f-AFw$c~u4d z9%OMC<^G^wH!4gu#dJME{*k%5a8uJ=UiUZ3A0BVq-QDfa&Y|03EeVyO3^x5f>6P6+7+=2xa)etq+Q2MV7PNCcQ#+DZCWD$NJ z3Lo&x4`uBdg|ED>0vyQX8Y(KE2-{~zZOkWv=^PxY=1ZozxW53%H0_RmLcZ~)dhgMd_sUzRb923$ns@n4j!%`2Ok}^x*alyhJQF;Zs=;=dppbx z6nm+wQ@uT${=x(XJXUv+=3Lad`0+J!Yt$>5POdB#pQMgP>VSCyMYei?It7$Lad@G7m7st4Q6Sp(N-oeiI_HK-_eGz`^DpSW0 zPn*i&Xs9(gI>D+D`p zaz#jpo@(5rXY#1GF&D6NI1=Hr@;D-?s~4=Uu7d9-P&#DF%geh1A&-%fsEdnQ(DvmE zo_e7C?Ul1Ow-RYhac3pPwR2VlL)x$3X~`SV2w$<+J8r z?m4RyZ7r=qk~Ntef`xDP3icZ24Z1AN&reDj99FpE){B+(190zp9UL5dd_HtM+7k&Z zz9+xC5?fB^_)

    W+z~3(HmV`tBCTkKX4Gs&rfNX?EOC-W{4EbVhRTrvu$nxve!ez zZ4PjOJoM{Kz|-swk#;ri-odE(+(GdHUqApb1_3j(p*=Aoi_aZO;z7ow_FEb}eoB zj756?bak(KuzLwJGJIcN`uUpOz_?iBUKaZqdV1}?zBeNAwmH~C9ezF+Z~Q-Zw^%{X zgDso#7iRd}-bVuEw=>q97SG1=q^93Z%?%87?{#$|i&IloK9^RMSr8FaT=^Ax);%4{ zry<~vq{WOzkY}zRD=MNG8irR_ha{=LOm32E@O}e(wnfOTVX? z@7=0u*|2rAJPiON*3=73B z+69r&iY9%^ic3ztjI#FQc0W5buUuWNH1Rp+vSHnz)O;Pu6`5x~NLNGW`#1b-rD2!O z+FI)?47+l9^n52{c`mM(M5mtP+Izia-t-&!d=RKlwSYJ(<;u!-1N_o+zQ@V_d8@6j zN*p)!V13PbLox9%xKo;unVH-Ph2aZx(TZjq?ei4k(n`BuINxXcXnZ(h~2&vsVB3K^(+%SOZ0tlt@DK;Tj}xPI!{lXnAz?@a+MtWSzU06kz-v+hi3~#Amh+K&djYc8 zA46k6HU_pI9e;Q!Tm_@FFhe>DcGQ3=Tb-30BW{eOsjKwq&Q4ZFhUYdY0jhFSBz`W$ zUidc36P-nB#KU^}t1Bxjrlx50+-!WYjZQW;>vfdn`8%qhynb|2P}`(F)z6YabM`U? zDlB;_tn#8HXIDa9ZS59^)r5mn&)69<qraSm9}-gIc6SKH+nl7XK8WRsCT(dje`ys z6TNYjAVe-My<;AeAm~4%;CGyfm%be_8a}hNB}t`kX8)eG#t+|L zZ>uOM;IJOq8l5k>C*lpVmDCK>&;qM|35<>`V-1@+)vlhiZVY(;vDMEf{(%Z9_!jq- znnbSE*dQyACrzouPYGZ7W!`E!RgMbks(LjvEG#TQz2%Zlkz1S8YIo4z(a6Y}NGk-z zYwEEdMBJf_I=oIRoSX3IW84laYinz!-@cKOG(-$iSoR(qSdN3!Dv?*IK1CNR-dZ&1 z-kjo^J2*520Gu^66vRQ8e((ZPijCblmwor2?edRp()}KXV%-}>0zhqLTKal?ZpQnbQQKPv(3C(?o>aAa6QSZ_2`8UOHBwS!_!N;rjgeE?AdC zBR1*p+NTD;^OgJC1E!PBo=sqxuy&0REm$_Gv&N{c+2joirT+!}sKw(HcP^J>m_;VQ z>B7WL|6_>Dp<~90pBo;_&2+L8rv$?C3NLx6nv)^h&%p0-JEn=e$iQ2}4vP2h-dRm$ z4Vw}urL#YSp5^I>Bt8K{#JjqNp$@wkg5pCu{wI82W@_C!4YYT`M#0vT9_akOETx@K z8!9phhm0w+z`v2Ztzx;t$=5&g7?qW8A?rRXgF8dvADio3;K%51jV%y9d`~^Fl;D1? zYRT#N`?FD=kno9-y8{n$V2Tg*5pQB2_(m;W3%wBHydJUHMXXus>jN=@(_Vz&NzH2`V-EfJAdjx#O7UJwoO)K;AFtIwJ zZj`Jbu}l-?bC#y{Z*%?4%@U{^-ZkY()LDHkD%zQ@n(R>p5on&)twHJiJX4XVLYH;7 z;jYest*@V{-!iAKuh;YXrcX&(kYnNVB`hM)XFtstDia~!I~hH_m*#V0AHRfCT_g;I zJ2D(7qylZiv$oj+PPKehzg@3_U*gF`QU}@3{_b8PMoIomPfzg>kkOY}T}Y|;oBprp z#T5~(2?he(OG#NKOn^g^EcEIx{NMfgOQ?6@M0!*QxPW#HU{{l|R0skZ&YnZ)Ff=0ka zhZU5M*-Aa$FZR7FpWWo;LsewIsTu%{a5Lkq8!r<`j7hJq1^Oe@Sx&@AE#6MYLNH#s z_5#$z-$7)-^(kZtwSF&FbyZCcm(Ax;Vu4RUl>2<~S_cgnJ4KS@7Nv-J-A+e}R)Ls# zA>?EzWF{xzWmuPvyAGxR8o*t~isU5#_m$M^D0~o`d5s>lb2Y7DEbcb6T$8cCu}1R( zz2SJ}JFzb)#K!Xhin7 zOQR6!VKv#e>M?pvWJg#Z9lgI!mn69lNKO;6-QrP^sbLOBA?UQe{@&c&+&e8UNuio1 z%qZ56#mOkN(hhetZ-FFCHTnq6es zi9qHyHk7zLG2c(1Z0@6Q9v4Jl5UyrQV0&dkiv@_!jUdnTK+cE6k0Q`6U9wK_m?AR!5zan>hF zS6J*lRF5+ZZMhZDhfFVhLtyJSVx4t4g**J4izmAUC*uET_dq1Ta9I`cYD~abF z?Szrh#y;}79jw*#Z2V%~utHQEm_^f7HpEr+_W02ogA}W z??vs^86~Y5boGfq#A*Cqgm1jL#?z|YYrV3MgziTYsib})V*9JBF)RJrIz2eSY4a#K zc|*t}3j{3>TNUqqZTa0h<7gz6lA<}0!?hXTZ`kU5Tp*JW)h=tct5YKzJ^w3Ldu#vM z2+%cW90gS?#9e?e*u6?2Jn`^wUU^X^?&x|~# z^aXgY#=z2Yu`f)XuX&0=#7MF09Tda7UB1(y`UK6|y2+1w*70tOo^_oOr)#XttyLBk zDVEGX10ma}u6Izlrq)1Fra_S?R|Iu6JxDDAE)RUzH12Y5-X_TV!-dZu705l4D`Hmh zy`I&Rul38xGcC;R6}YJ3^*xJG?m8cEn&N8PoAr0)k@4ptYjjH(ZW*NSx;0vq` z7$Cb?8H#67$6{itI$erL$Yp(ait2ajS@$~6@SyUmHfY0rd&W~QR#5sHYf+~ggU96L z=qQH3#mT)O;udy2OqOEm1Id$!AQo}?yS8@rdZ`4(QI&6uCc{%zgoG!K1%?lj4qjel z4o=g{*i8Uspr`UQ8?ZtEF<7+LkT)i-4mz;CY|>1|8t%=VxKDfG(1?Udv{_ ze3KCHv~6I2#&e_nyGZ^mVq0ftyOmlV)Ev-tyV69o=U0I zx5FIftir4wb6eX!Qv$V`BYb{-e!u+Yz;<71u}{y>&+Z;D3z29;gUT6#F3P}%O)|mQ z1QCiy6?gZwHa9%+{_hWG%SHySklX2=-|b$cB5zN(`{N=tsBiXxcNcwqJAhX-6{e$` zePiH;+GO3I8JN$b=I?>_we~pKvD2GEWA!M3-sT4dW6O{@Mw~{ z==ISEke{90nhy*bYW^ahKRbh->S&cneO}MIp+HcX3QJw24L53no}v_10`;j!|2;0kN@P!pgF{EpMtNCLldGbM`IBXyXfG#gt(U7p zbV8uh$tP1ZuZOJkun!X2X<7Zp9O-$P{Vv4XXZC8TGBinF#y4YpjFRgG$6iE;9$haC z+CcNs%38C>UCvegrYGKUjl#Zs43}a!`$BPUJh#*96KNt+QKyH9t5GRNW+5fC%dP0w zl2oa`(OA^;a|2!mdxHpwK?I1Z`m2~#RSx0dgiF=y&aSQo&Gu~KBV)EOOUsnBhw%{+ zuWl>>G{A)gMMXtUE-rbwixMk?z|*Rd9w!AKd_qD~USanm0S&LBL_eOIwzlWnD-V0_ z@o$CTD*fZ0H(zkqBh3iWY(`TB2?+^?c-RLin-=!BOGv7=rsif3#7}bIqn#atom~YK z^Op4#CGHNm_(KsLaXhN{(f`MklJBSgEru$^EJHHh9BmNs*1Iw8wx`bBG_n3`H56N> z&+P;T-FiS*ZyK`^n$EpQxgV`q$$SJFK!y$j8U^7^CtN0v-X2U!Bc!CIkn!I&X1Lu- zpP1)9ZUEAB`mzPAwA}B+%KZ*q-atj8!k3d-d~qhA9ET4dq%@G(xw%(r$wQ?J?oS^d zpo@ixk*=|hgbgYJsX;F`6gx-9fXgn#)t1ZRc5Luc4SMmcbt-@<@-1wTQW{15f#Gh| zsbyk90govs0YmS86q3!Cq^6^@w`C$jed^lH&(+qxJtN6+X{qo_^=# zV^W3-F=b_DMh}?cfQbkRBT(v~TM5N0!&H>*va7Tp33>#+j>LP|Ekx`gK=*MBaB~j7 zJ$7hFdT^m%e#CNM9u-=pWEl;R{ePI1IL*>HwOlODV4-Xnd0<_ zH#K>9cqk9WWrOa#QY=b!h)xsRL7G`xLTEyMD6rSlF)eSl->nMs%F0S=M6%2TmYm4z z{I#{J%ZiFBWEg|Xp?Mr7{L72|w%60I@ge=rtA}qtz(%fQ{j48~lK1mwt;cS9QU#&A z;BJCU0@}su<3{qAH7^-;BbLzW_=CR3tcTo}IQE>OT38x+|Ew~~Lgt?1($4mrO-5GW z(kL?xePZg+$Mtmt?pnw~#ZswX)>YP7M@WRu>G5&BPB?VtfPF!~^LNWhwJ)@5&xVf;<{mD5W!?~w0 z+28o(p-Dr%fb98!h@m1_qh{*;unP|O-ra*tm@(-q)yc^KO~=ojSNoP~FW$6In=f0Djj*4w<7Dq1+B+;YIcE4*8ea65?vU0Sw7nAF?LZM z{q)QW)r9eJhUE1X$+t+TpOcxA;&wepAki-jwe4;?M>OSKW?Kl_*9^d#z@7l`OHR+# z`vowy#BxnO#YeOwkT%*s2-%y{V$kS{m5qz+``pbn;N5r;S$6Bx^xHYF*Ga^|0TksT z)9oIE|GYL|{_QcdLQPn*AjN@#$DHOx?f`<^`CXG^~BPzu&{HZO>SF-|>LbP*+#C z3%v1e63o$ATNhtqX}NR~^ged9p{|?UI}{*7H+tE9UO8t}7T6Uw1U)ZWS^LB_4!PWI zA8uB!=hmP9twG4Mx!}%rKWE(Va}xL9VjSj9Qn9VB&ad_M6qm<~E@-5_@S1sc#^=;k z)a*8#b7H$uBrmew>N39&CeM{$Dm05uD%k0|zXH9>H#XdFO3>cwT<{l3z!oylsskp z+&RHCfhit=PJ8`~`Yt%AUI5*AQ&uF4-|yAa)6VX+dBhO;z{`cQCSlqS8u&dyjUYWk zg;roY_doJ{MYq;YPHA#Q;(0%yBtk(@ZdvFJ#}{fw(Mgj@1Re~bzB)8%AvolnmZmxK z_}zpeQHPNx0Cm8$?kg1y?edtvMNc#a1|UE14(3zTdiKYOrTJ8!H3lzJlmqfE@Y-o>?gLn-a&*WFN5g)Ex38!f zU!=*jm&#N>&&X4xfITm_ogPWCSkia+zX1iN?^Q^l>Hl{j!plt@ClxF$s6JNC0|%%m z&mG(j8J8jO7Ma`*j*gCXwX6y8%Mw$P+1c4N$^k5&w>Svnx=jb?8ubbGRG_ky?ue5@ z06(l&t#>?3W^nDsu!xidAY^a@NP)ccL_E=?17I600 z%h$J^Y${j4?g6D76P46d2(SW=6$M-e+zm5mj|kn3mXN`J2=|S>)>1F<^Y!TzIh}rs z{!N~-qn9`T28BnbOYkyMgH!`#bzZgVs^?nJDu}MfjnMm33TSHk<=#)g_7bi9L!5gf z6t)hU)>WM5YNONl0fAJXw*sL$-VLH~1=0-{$X=TVlxKTa^Ja05zMiDmAs?{(VXcG& z1?aap=J|S%CeipAx4Alu%0T>1t6HEnnA(94?nz4x&$(bs4oiiufb#=r1Oj~*^^%v= z4VI#IL2y&yi-?fM0|T%m;ZFuvt|Qp@^)R!U6+bp82nP(0Apn;^CP09BjngLK9DT_c zIs=Wxk#VQg4;WrG6%+(t_VE%2u%G#83kJ+@tC+z5{8{=ZJ<^6NE%SP&XTcDunVct2f&F)M)}0_L^sS6}++06R7=2+gih> zW54*bD8Ote_Trce77lJ8kPBMswiU=0bbo(8q>R7%2V^xAiP`_DMI>1CH;+N#5z8|_ z!askJJsAI)BDnt!*7om>8-NW1f}CX|8elIy3_BsnzYFE6%>Nw}t+^(O@x)O286lZA z+Ji~w)5&+eKlDH?mtzJ5x>j)poLmMyDXHJ|%#n1_mGwv;><4Q1zNE)0cPi(-Uo8N+Sr*8*Ufb2LGLM@7Wq&4Jk@;If+oZ4mee9SbV5JG)S6%}ir8an*~!bhh>_Fu3TK#9 zi!D*DMJ@vkjP#=6zRy~kaWyp}JpSJOdIQmQk<`*P%2OyfJ~_oi8`!~%w^Pr{tbqr7KYE`Q(a4 zncg2k1ozQ_Y7Km3GNFo!dT%j~haC^$^YCzC=V&NaY*10n!xUaCudstQtH}&m-WOGG z9Sujvw=6z14f>QTFzK~-C$xGYEj8Jtov->f>yUSfLaz|9pOuWPr=|yun~RIaUt*c; zpCusj@15U=U}85XlowJ_QYN`R%k`#-y?p!#tycLt*ZM0Y!=0ZZkvWU+6tC9tOoj{- z50xUG3X+Q>V?G%d7eQID_`y;7D~bt9f47KtYje9^;NRNQv?Re!+!cW-@^<<8!I0Cj z+>O7^Td<0Xok~x~=NvY)Uad7q94)s4Pn}>`EyL`}>v@rftAtO@1%ELPi`(h_`GXk+ zT(jbqInxliZ!JdlMm%uWE~=ZhTQoTD{+?Hjb60xYI7 zJU(!al(v}zl0;#caxGz^UDp+F(1p&#+zcCLKb7cP{4tE3rWGE9L&$T{sxBB>T}ZW{ zB|{JRg+&W;$G-AeCrB%Z`r0G&OY|z|ax&(D0oCIkH6VZp1R7zNxXOH}EH(ej3hwgr z^7Zj)Z|B3l5K;0M9@=+}Y9Pms=zrdR#SRF_9UULX7H+g(9{X!1;_cmv84o)O1bPpl z=L0%*-&W(t<8C?JMm({g72X{U}zzaN-VGA1@#y`K?OfV7D@2>f%Du zcn#_HX6RRX6#d*vdpj{&NoQfQbuvx6uu+Gdoo{-IzkOg3PC;{F)w2b9(72lud1!b- z^U;ZU7u_@sbDzTl?W*wejvvovAZ2LIVF|XQ#?$Arvg)6_M4?lLFURv-xzp}$hLHW# zERbMdT=iya-HscCp!(LI2TpJl`;{$tOT%=BHn+(mlw~r zG>UZB=E=P}%_{HoJ+IFV=e9JIY>uZ^XR&U~tpmP+T&`j2YOm5mx*9^dZja{=B_w*9 znlo&K|NNZ1=-Xru4~vlE`zxTYn2Grbf5Nh1utog4akOElGXZ(yQPPLd_dGZmWB1A9 zQ_M<*!HUH8h)9^=(hC124B_kP1~27b(0;2X&uYXy9|VGU@!f!Qz?Hw$kW9ABY1tWy4R%Nyb9kS$D3p*TR$aDahyP)SjGnG-7td9u%=5oopm=@U}Ys6TBf zoDCA}glYFn6?@AqSCZ;&?4UVag^lVbO$>1ypJPrg2l-)TKa;g_Ui;1;qMB-WIpkbb z+vd7$0(g|0$DA_F#(qwfcy{8Zx=!k zYq1esy1O^NZAz_oWsH5%c;cuI-+N!@uTT&vsp~U1mF;&;_Y?ecVBd9jXGgp0K~+U1GIl@) zeneqUWUSp6dWGbz+uz2mOY#Sz#*Aeh|7plir(==F2fN{G- zD|dy^V{3J79;?}^93CfTBj6XN*Mm$$Vd3!vl9;jzKaV|U#tou8vR!2w8l$`0$Mps; z8NHLZ7I-yS*x>m1hUsh(KGT6K&2GE)c3!oYeqz=M*nZ+G_(@nVPtPsLhz;M>7SDG*Jx&Ov-i$0EiK%@9=Zh%!f9{SoA#od>WG?cQ($Us#_7blVBFC1kFV@djdDv1 zlrV^>9{S+&w}zmJnu_3NAl*ouOigQnJ@eq^%6H9)V;~1s4`3D|`ni`?L0RVY^#~s} zd~|fjIKvaNO&R(lwUO!eHRNRflqhgFrAwPj^Zl-4XQ z5ZpD|i3MQB46YEo;AB_xS)A-uR?0xXS8;Q3$yY10v^2ZDMaH4~#L-YE=@m6LI+~J{ zg#15R`O2U;)^6Ppf+R>FKyZf;7~GvO1a}A?GPp}{2r|JPf_rcXZV4{IoxxoP3+^)L z?Y;N+4)_2Z5x2tQayKB1Y?S6Z$cdciw=fS#9mCM)GR%ke>aj#U1eahxfy z0FWnOuh5tG_=Xr=_L0&f-2-BbI0k646$f!ey0w)`0P=eQ0Req|auk%n)6+2NxhoUX zmAjTjnEUGP)+zKcc*Zk{`BKnv!*j<+w$W?H%FXQx-hC}L8hyf`|1tgNuUkmYb?bYr zv7OYGc>pTE_M%uPFm8;TnzFt(Pj74#1a`Twuz6iw`xPr-$oZxSqM#~mWkTSHgOW$cE9|3!t9|TW)Ttn%!EN)Fez`jqFke=ek*cd?v3ovhcWQ1UWP61-er6pHH$Hm^k2$kN!;Wa}pqF9oL>wJi!8CD&3IiiPU~X(MP@*yJ zNmeVuUnAzs6Kee?RTl4;hU@MXSO%+b!w@5 zWkNQFHjk~~uI;malWICKhnuKtFCUwIhZPM`5wYU0*90_;UOyJaT+7OfmVWNYvnK8B z?lv2)>w0^)v^L2Rq%9FNIvp)F5#zs*q{2Byz!{0m3_&tqm*kfUrIC=s>68r8hZ`tJ$BY|jhW`i4) zPGA0ZYOrybdIA3}zN@*pu{W~5b(Xv=&qajwV710hCuXlwlgr@>Q6@vNyw=7tm@f7m zl|^|;4pVXS;bC!K%M`K!>=y^yKy^hI3V~Ro+4`0;O{mz++c2hDyUfDOm$V%(Wq@^y zI*ktq3kBPLynQ$?qCM#~pPwVfqAV{hWoBbYigowBJapgOXmHY*o2$CLiYDc{w75G7 zaM}(@Y?oD+Sg%{z)h?aMDRhvNAK>BP3F#3JDJZ=gWSjcPs-=X@MhM_Yqqc?X6Wg6w zeI_Y!kBIhJ_Ybgh0kB2D8ak&=LFrGgyJvSkni}^sAds~Mzn_IPtu!%iun{pyWaZCv z5}Zo2uMeUcdbjWy2y}t46$-ib8LJq*gL+px@8o1;FNCsEGBG7oyXfdID^MB{ar7s_Q0n|~b!W!IV4uKQJ+m=J&L z-n=m=JHS1k>|pl3(kG8+=-K+2vsCifh2s08sB-(o>GSG`8BTJ4j*=_7isiVwsufX= z*w7LjFr`kDdStHLFKe}RyAmU>0vac_BexC587q7V3 z2N(I1y77(kUh*GW7nh1pt)+U^U3x#4!<1%zR;Rjd$b3|EIhaTnt_U0ifuJ4?a8F0K zOt+mvkn(q7TYLKzU{bpsAv+JErWO|0R3MSFc9t=yN%c@PgOPvjDhleD^4kFtNNcGl z;uU2Q&ddchYtq70_s*7M%)8O4Zd}EBnt+^_WS;d^J8k zfqTapv(tiGx6L81>roxvtY4p)l%$oVV!?E6#n>4`yCl4w$^V)G2OU2FU#kqlcdV9H z@VQ6JJRk*AC$ZdK?J*}F_`RgVf_3&RgklsHsGDx$??PFOd1gYXfR;!ZP7}Q=o*AFn z)EIoO<$3Zej5L!?e6yjIWG~_R84TGmVd=s`1Y(;F5+yG~WNLz6@0wA3?A;(J2!w!ziWs3jIicFhEK|x)BrOUq=u02n1A9^AnJP06ojz zn&o|c?o`Xia{9J|iHblN3zQ3_Wn~$uR-JNVg4AyOeeaPYyR1rgH@`r5OaskcU$&&H zO-|1<;h;}WPOY3^e~N`;@;*R?qUc zCtEmSx=e2*ZC)6g1OH|tJv%)ul{+SS+-gWPJvUcWTDsVKmHMkzt!VOl{=~4=qW1Neti%d=b5Nrt3Bq zKrtmP#ktX}qCGC}fogO`B45BQvL_YK9LoGv9BL^d;7#uWqlWLd(F~eWurAEtnNtD% zgmvRjkc7MFEh^i5by&~Xt1^}sFi1~3gYGJ+#ccXs{x=TA{$L@ppJCDeS*Evmiz^XI zB-f=v^AMaAB1v!bf52SV_Q^>9uO!=lk1sw-ApM0BqG{vpO!uzP#Rt4D*0#vee)sNK zegk?*<=0AAF;#p58*4&+Nkal=x1tyIO!a=7<>gp};+2FdDk@?1Pnp#4-{+$~_5C(< zr4TDF`3Apbx5e{;A^Odu$98~p4`Nv0C=K&}$QJ(h5AydbT7{t+Jm(i&{X-=pD5_@L zPYP#T3?@31z`UXky2a`A4iVcC?Hct9dd>YaD;oui#lk{d0)s?%^nbtf$fY~_pP{PP z7*F{bwhh7HS0}|+K)F@K^_)L^>K#!fI>u|mcACostvyq98r@$Ey zNp{%g~S9zn!Xi`7H;BW$)!X4-`ayoc{Bdf8&WzohNNY zr4i_uW_<&I73MjefS{jNAjo3k_@X1xQ6V2xH6-x|cGekQS9}y5`u%mb2<`7D4qobu zLVsapPz5*yypbNAxmktG^*2LjrN{l0RaHD1Q{kG-lpN#9eUrZ^Bq^cS3x;q4iUKh< zQbBV$I6m9-8E3OKHFdU~UCyRK?w+78I5!4Sc7f#veeU7GMZQAEXjt!D?z_$WKKolF z!}5WA2rG-o_$WHSNZL<%0O(4tYzdi=)y)Q*n+V2fV-`~)&VZ#~FEBDM4@#7pZ(h5= zyNZ$}q|5c8T6qP9OM1=jfvKrXNrOubT)u-e)M3o;7 zgS6I_Gpl|gSZP@z`^LQ2Hj6smDS8Y)bew)r%7u8&72kLA+u?1yNL`i)rKA^=AhYpt ziaBX*45sbGR&z21but~9ZcFtHSe{R~{-ht4X!dsN>SebwN8t`KJi2<)msgti)9S?N z&VZj#+P!5ax49P?^?aqliPX>wg@@0H2vhK6_Y5cuZC?2YC$V0{$HvkK;}bVP@18YP zRzf&1hp)7q`7dV+pJ*%FfBU{n1=l#DXJgxj!{0ai2^b_J2MMfJaG>3>gFH)@_(>wA zvQ>aD;mpwqaQpf|j;t72cK>XRtg`Gr;AXxtb=PW*jJ+v_e6^+05`Gg}`W} zb!K$Z6nD0&rKTmX1;K!Cm5m3J_NF|EpPEB)Qikr|g%=RUl9634*uspe(~;ofmr z^#bGjP}(-n_-uzMd=g42M18DcXZPK|MP6IGD~->dd|#hzUtgGzmHzV2M?$tw4h|`1 zW>ziB3x&UaB~+@KZtiu5YesNZIo=tLkL5yfc)whhT8!+Y1kp-0H7Z35I0saYO%~a? z)<%UBmI1-c#s>e~tc8M?7Y#TBwha_h=jH@cqpNg|4ki{CnHx>0PrAEOCbn_FT#xo7 zhN~POp~*>wXbE!pV?S2rw38BAsA`>axgd zw!+5;DR;OPC@;G@o|^hb0?eAbyQj=Uy^2I)ConPPg*n031R@NsPybFETTs{wQ-I+v zLL_p3<X|AnBeI2f3u2M9ax=S*aB!E5&VquAFdl%AcZN2UYkagT`g--yl z0!!OA4kcy-ffjt|+pVpQr)mPa2cjnmv8E_l=N~%}i*{iex(~Zb1;_2CZo)cFbBfn( z**Q;BR*rMX*m7NdncTo94(>}8aKTvlng`tNcb%uj^0%qatm&Ba>!Zap5Lq+$uS6I>L&!f@j;7u{JMR*B`iDi0C zsu1X`?++Obo+-ULwNRG6K__C$b--I3?CjuPTh9)sF+L>?e0G$r^0tj~zRspdOIzE- zYzrCJActmg$y~(y#s+pMqbHR14^6#wzP~TR74OrZMfB2$UEc8ihy9V zFXUdlUFbU@!Ag@GCE78}+W4h3EM1`N^a2f1t_Fdfo?#_#@&c@)_lhjT`a=HQKraSw zRd6otRZv2b)@Qwj_aq;*U^i!7mW+%=$Y?a@s4rg}uh2J}MTX2KIj_Nsrv{;Ojfjtn z2mq+MV)M`XXL-J=Mp>Hd>UlJ&xw<2Ht5{euyGp*%*3wWETJ*z$bACTMnW#`!j3yv< z9d<>^p4FmS`rG8j=Bk&y)Y}wKhk_znI`NTf3&G!a%1%JQ(i0^@M!*74M~cc45@QGK zY{-P2(W_P%b`X%H?~g9B$M^!@uN8G5%G@aR0+qjF^!1J-!1>sza2d>_KXp7#IAG4* zV!y~72C%vp#mSfZOROM6FVVKlFPZ*pxI~$3jM@tcsXm0%KWB|wt7CKG<3GInJnFx= z7>bPzylV4kviyl18{VeqV!1DX>3?agEqD`C(KImJZ(OCla98)ExHy87M^?VcbG?U! zfdLKGpTq0AGCe(b-1+8stutgTuMsLHuckJ>vJ%~%m6j3-Kz79zs@mNp0Dz40?E1N0 z_4DVlZgz!$iA>JasHsmxQQR+04n3pJE6q`0U?rQHoWxIlvAIbwhIR!QCeG1UHT6RU zXNQ|ZA?tu|3#G)jm*n_IaXY{)0KIWKHD*)+M#fQs0s`kdXYJ$NENOMWKJ$Y#T}vTC zeZLLrBO@=C&OKdRE~cjwQBiLyP`U`rfLwB?QW?-Wke46a8{kt@iv>C@-q@%?l(Lj& z#IAO7xAvN1z}XfS*dgKJ(7SqrF7*5JpPqOOg2UfM@Y?+16I1sNWikIjl`@|g2q3BF z(q5+O=nkcGHSHegHA~?qJH2L=X>h$iS`?;u$%bd{;f^D;=F2v+D@9>AwrKePODpv6 zJEaPUP?ToTZ4d_0o{3AD>B#mIf#ffgKdI4qVSX2N$QpDX;~Dtv)&+NHP^>tioV92O z-nyXn9H&yxhX`}Lt6`I(Bgvf|j+=coZ%sv=V*19E`-a@9?aAn`c*^ror` zt+=d=RPaNEclC7NtO~ylsFY2s{QM0n4OS$Qd-r2$$lxYPG(J{MC6R;;p{%Cn^uX@Y zGvCSt@5`ZvF1O5s>|=LfU2SIO>b#&`JhH_wZ!3R38luex-IsJVG(XPl8mhjn6|$=8idT0bLc-JfwPxv(e&Mvw)l+!nKP zcys})*iy5d{&>+u`va2q?fD#`(~tL~YKd`iak23VqTXAsr;=+D=v({E!M#e~)A#qi zK-3&xl=)){deu}leGt_-Ekgs)k3Vv96m0f=H#RrEi?MAvN@k3A_%Zmk#S|2vMoNi% z*}oF9oC%E9e>{~&x3sh#vzYX|1FNF7{_(K1B#yy^VvhcKe0aea@U1o~vDfSBQrK<0 ze9VHI!>3SHSN9T7c390?k_aYxNp7?_KQCx{`iQ{O-}6T^20$M?JktEKGRgfDfz91r zFN9;quRYmDWS8l(rO9QQH)lg&vzQg9&J?&4Ry*}ib;qX$-E4iNPBJYOF z$;a7$L#Qcuu%M9!7!nq+HvZa88p?=4r*0u;1y;=p4Ej&4+|&Ih&UX+1EGWwQZNMI% ztPt=mrN2*;m5-f97=YBy>sk`AFYAuriaWgRUU%V1o5XWEp4j^g<5^!`gXmdU=vgA8 z4FQ8v1H`o*okAlsEb>CD0-mujbKe05w6QS=EE}4MuQMX{xYL{0-hlm2 zcQ-wKcYc?W2wu|Q=4V~qhK~V;WJ(y)D&OIISd^mGH7-LVBL_1TNAL8>QT{;fqUGA9rlQ&qj?n-WTK*#hrWCRit{GHW&g@QJ?H$S(C=4wPpkI> zAEhY0$d6XrS=9@1^hQ@+o~f1VLmCWQB1)Op)~G=YB{{_d+h?1bn@vNsZyvS!{bBTc zJmdoIqkus3P0-Q6O--+|a37B9SyxQ1-;P8=neQV_Z8)LNrxH)yk5@mnxtAmU6@}aLp$q>8M(ZiQB$*9RLTJK zAzTMU*;wW(FOn`z#|1n*zBKwjkP}EYD@${vyiis3^!C1wrW6BG2EN`U+nyn};h-zF zpe}hJnW#AG2?@Ec;*eI9iu8gWx?ZGi?zMQ^^xnVARXu2}%Mg`_hYrsZEbs9O@Ygee zK#G~79(V3~zL93br+r_(vRzW-nA3qkX&JP-vWNS3ofp=8+l`*52(Jv^d0$_luGkP^8x~rqpYv&rL_Tl9-xUM-$!jb2)50~!_)7=y9d$I>NQ}WPx@0QZEKt1 z=l3*ndg+Q_GJZHLENtn#?HAD1k)3_A{@jeS?Y7a0Ap@KpL2L}*adt~``i&-2EfM%{ z)U(gVfOgo780cfc2zxG@K2rE@0?gTmS}##y3tA?;QcY({99vDIAH64KlG&2HN-EcU z6WwQ$n!AU66m{s?Zo(Nw5jf6h+JAQ# zE|tsjv2wC|N>)y8cQ;|LynN&xB#6(os&4j|c2|L-^!Qup@Dc;eDmg-?7mo|JOy8!j9QeK}Ji#6SZ`@5C(YH z2h9>@?+)8d1ER@x6*LKQOc(Zl4i-Jg6|z3uoa!0&$nTe*Qn literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/minimap-dark.png b/testdata/snapshots/darwin/minimap-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..f9dfd84a10598864a6b7229bad9497bf4953fc29 GIT binary patch literal 1549 zcmeAS@N?(olHy`uVBq!ia0vp^JwSYig9%9L>fD>hz`%ON)5S5QV$Pen2fah0WsaZU zQy#m=U7+Knii?VgKyQTL%T*_j{t(~6og}tMh(k!zNiRmEqm83+#TloTvVW|*3}RQh zsQPiRxe5rXZCS-3-Zs~A`%LTa*XHhge$Tr2`Dg3=!gKGf@(ttbo>#y7^6*d3=Cg&4 zA?1G-t97(^U`HYTN|IThmSm#_!ROA3u&?ym)Z>;r{vdD`P5@ zj!MtAlaZ_W`_EUkD@pCLev3rZocI~DUr9^E&6q9Z^o5t_drxYMz-fN*)VRNuOCDXR z|G(YD^tW!%nX~I3$WCAX?B3o$?L``s#P#y_)~yVC7&_^9tY27YB9HDldpY0x^CLn# zSGY2WJy>^1HilMV)-kr#(F)WMpqUJCxIg)Bn)q9NSL8 zCk{)b1WsP~nwRoV;M`BA-#?lBS26k*MSGqQ?tT8 z;l*$K|43b5zlBqA-u_!tg)MbXA6oKO`DcAV@F7Djk&}OlbnkCUjhwNi_DF%TmdHx& zo9mV(>2AL~*KcL0U0B$4{kuC>hW)fCw+fqa|MtBXe#?PkSBqUPXtEmA zx4fojkH>k+wfr!^>=tTP8eK}>0iq+)Kb4zBXhuHA=&(~Y06)Bch_$L3E zhWPiVkJfwm#ie@9cxADF-`6-*0nMC=I&rH1ofY-DUVc>3IllNQi=xo9#}|v5ZoHdQ z)6skGx7+gnCGGr~Ule(7%i2BJ&Yvm3DgWtqyGc&@w*5`h|9x63)FIO5v5djb%i`(H zcTKn7bto`T%yLk1zP@|nTYH_teHV)M8JO&oUf87D^qd% z_q(<`FTeh=V_$NCX0-12yLYAJ3wK#=`f|vlQvK`OiJV(cxv%XEY(74ONceE7g%^2_P1s`?4BGiFbkJa1!9j$2q%x=W;^>Qx6-$$55fA5D9F zqFib5q!mjhdtG|q8PVr{n$t-oFXMWV^X~ogT-1%MCSL69@k=RDS}ZI%_rwbqH%y_l zmo9DU4?Qb_I_9PP2BKRj`;4dBP4d4g0!(39Hz%9SdG~6L*dnkUO=3e0u4)ncb@HC< zYBe4f28n%BwoRC@vE+qtY0mr*_xYL{Gbc;?naFfmX=FHk*&Y4PukeHXrka>L-0$K( zTzt=JE^q5P%W;YIp4Clai&`@jqdEqTiVNgkI_1+P3t8nqmf^0ilGdEodf#(+#pzYu zwfB5~`DEStdj9(N=fB+pMSeGb`2JtoDMByoa8h~6He0(rKQ4aYuC&}gG3Zs&{VlU= v3|<%?uXckE<&Cv=)^p=OJxkwMKS!fp)H}nVxGa%)z4*}Q$iB}uH3`5 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/minimap-light.png b/testdata/snapshots/darwin/minimap-light.png new file mode 100644 index 0000000000000000000000000000000000000000..e061ab9125e2f867cf0ddd943186c24cf4e0c746 GIT binary patch literal 1589 zcmeAS@N?(olHy`uVBq!ia0vp^JwSYig9%9L>fD>hz`**))5S5QV$Penz8)d5636?C z;_pp2KgAKX<U8R zr^aNbDZ7nY+yoAZ2^T%P^Xze)^mDuNXXn0tzaw_Oa^1EW_RoLLH~wdF{MP?}o`MJa zq9!W{DJfz_mokM;8l5aG+%Vtk?c0A=e`fkE_kBC%c;J;QSN?r|UtcP&H_tLWJ!`74 z=GN`iEBAf;zxlbZqI%jd_bEZOmoMHsaUdsWmATP^DYJTgdHwpdm&VyiUH*E;zx|b` z{G0zjc5QyU-NW=~4fnp!ADx4+P1SA!tM9%(yv=bNk4nU zeb;vGGh3z3t}Bc4iU zIFU&oRdkLoemcb&LM^_#^QS=Xx$4D}-abY)YYx9@DPeJMod_jiYOr4*{-aa{Th*|mT%NBn1xS4@!LDC=J z{OW%ATX9E}=FA8)&E=BCvo=n@+>`#x{mYR{>>Iwhv6UEESgzAo)}E6-hx^>l2Z`3= zcdS0<&-pOr@rC;?VhdWErw8{1p6GTmn%DBQV#}POjw6u|>gKTO-FbJXro-*|-iw`` zE&M+pIy1fHlmB$PoyFx)`=4)$jb+DuQ|`DN!yp>>bn^Hgn*3o2SJkA)b|(vOr@WuZ z75{R(TI&2Gb}MIn_heeVJJ^rgaPkaKcVo^djv)qDh(x_Gul~M%mVp3!!5_T~D#6^1 zHi6%5a=z{J*q$frtPpVPA=k0V3VpNef9$+Jse8c#an^^2U&a(XZ(3icx1;h)M@fT6 z`H%HnQ5|B7S~C;}j;eCg6-gF!I%S=`^U}++HyxKuUp4QT;`=qHy)Ii!37xxrcHP~* zrfa|{Zl7~{K3L0@~ozh=^2Bx`2_i`kQ6@b+NgQu&X%Q~loCIC&F#tHxc literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/output_panel-dark.png b/testdata/snapshots/darwin/output_panel-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..09d8585cd84a571a98a75143e2eadb06dd4464a0 GIT binary patch literal 7462 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/output_panel-light.png b/testdata/snapshots/darwin/output_panel-light.png new file mode 100644 index 0000000000000000000000000000000000000000..c95ef87614f1412c6e64bce3e7c73b43ebfd4f80 GIT binary patch literal 7084 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/process_list-dark.png b/testdata/snapshots/darwin/process_list-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a784437f0036296ee75754e11984b3bc1c55036c GIT binary patch literal 15261 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/process_list-light.png b/testdata/snapshots/darwin/process_list-light.png new file mode 100644 index 0000000000000000000000000000000000000000..79711b44a0c000c5b67f468e15deb9c5af97dc7d GIT binary patch literal 14823 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

    F}^5H#c`ds5v}b4)8`B+aq2OA0MBrEFw`< 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/search_panel-light.png b/testdata/snapshots/darwin/search_panel-light.png new file mode 100644 index 0000000000000000000000000000000000000000..ac992e55eac780543915730b797119adf0ee0ece GIT binary patch literal 21072 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/symbol_outline-dark.png b/testdata/snapshots/darwin/symbol_outline-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..b68cba4023df1bbe5eee231ce682689b91b8493f GIT binary patch literal 13607 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 ZCqN3GeOXINax4J+l9g1Fs1h>{{vX&w#8ChM literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/symbol_outline-light.png b/testdata/snapshots/darwin/symbol_outline-light.png new file mode 100644 index 0000000000000000000000000000000000000000..d46e177ec47a1db5c992f374c7354c2ab826b44d GIT binary patch literal 13268 zcmch71ymf*x8`7Ba1S;(2?Uqm?(Xgo2u|?e4DRj(3lQ8PxVr~;cX#)l{Qhru&)MC# zXWyQ;JJmBi-F>R7?yY;j@7ApfRg{-NK_ox~001ablA_800F*i83k!sX+zG4V$^`&e z)1*X&R9(}L)7@0DG?qHfOfZw^&@pvMDKUULex=armE~pHxY&8xRSac%3iTDWFYekj zH)RF2WoJ2=nRU0$2SrGvu-LeZO}=3{K)i^&Zv&Wi^fBnZ)>oNi`iRu%(j}jH+xrD} z`5n#VV^{@FuSQH#7Iiex0RTY*!*vvN_z;*Ls7-*q52qlA6!kypk~`c#l*3)P!p6GA zamw60n;LNs0H~w|`gJ-uIp82~G&F4LzV%GF?&bG~0NA6Wu>gR1k_7!FyVlDb`pwEB zRb~S14gy1z${;-*e|<+g-Q|d&_q@mToIizq5#eaCJ<1ec=X<}!bN=K)991%p5_bGO zHabC^b1f^RB$Qc~z50cD3j_ebV8@wU!gZaeG*lKcbKX(+D5=KWZI_CM)+18^0C)|G z*lKF_59_ND-eI}zd0}LVDGaRLj2$_8iu0M!f_5ZgaBbN$&l%O!ZX-^=|AeJ$Nph1 ze9d;b&}P~_MD)*}KRbIf0;emug)xlUue{Oy-8KJpn8LR%D{whH8`%}fz*KGsYon3! zWWUrCPv)zgU-k^jC0{!x1`)O6HvLEb-dC+%%EQcGkDPC(R-^;Fz|V&ew7jkT@XudvfWG@uK`YJ zp;Adr`Hf!C{Pl#Y#LDWkt7yMtMT@6K#hb<2YfOk;mFlCh{GXmrDm}_YZBpRf?ZJT* z^UQFh%qMCkoMcrE^;;>>i2#!PUz_un1r={%+T`A5Y=0msGeT)gTPkgIta14|A}eX< zaOyRIL4eQvZIY5#xSNk}0rcHRm%$Eq6GRk=a-(H&u*$LqMUDytHirgNMGb`^qQw@r z3Ljt!b#|ums2o|ct+uss&e41Fug$HYMejE_98BKI>8#3VEu0e77So*slb{QywLNN6 z-nt)*a-a*FAt_`H3^(iR?9pFka61OwFg_Fv(&ifXCnP4!T7E8htDT*gz{tXxnKfr| zIh|IWvvXUXu(yxTmmlPD-FFh|42zD#M}CyQ4Xmz?AS$wLeR~UbaMbycCKbo4q1(0L zkfqhsaHzeLy{sF)fJuPC&uC%P%m7{mug`B#P)gAV3-697P^Mm2bXc>W4Gz$0l%$=p zKRrH;N~Taax%6lGp^8{p?f#iIn6@1Ha&dzuDeE58y|bBN$MgPM|Kiz+rk6^5O${rt zb8n(TJBixbbO4rD_qb()<5OK=^*Su3TWD!XTm!;Zzg#}Y&lq)PK1_L^t9O{+dii0OTMB`-M*4V8*p+jTl!hk=To zs4^V3L8DRu@O7x$*Wjp_+#-Yxz{!1HxblsY;Rw0 z5>{;SwRhtJ{rqq|SXf}Tg_La{zn{fsd84Wh;4ZZ=Wcz; z(oYCLYn6zXpVM4pve}h=7%+q!V&=fHUNKT^)T?tvoa6y$Xu9{|kLi{}5eGI?7-KWe zgW-%!c*tgTS1yEY+K-nqP?w|uX%_1f*R; zl)f%3I7eItJRT!x;Q;}r^{Hs(Ax2$bWJpIA+>EN4n-t~jYe;mK?Aot>55rz4TGVEJ zdum}}C+-YwwIHmF0Rd0Zbq3JsK`0hq=Z<|VCFYR;S}d@@Lr6t!Mscmu>niCat)5zC z3J*Ex-IB!Six0e%D+2>Ri`HY^$y&Kimdkle$I8lK?Lf-DJ?I2iSb3&vulYFFLC9wy<|5R5WTxtFFc+OZ8Kyu%$yI^SoJQszfP^5 zoCM{uNECVAoV;Dd4vP1RLQGZ9xlCD2cM}(Hee-bfN{ahkjmRex`tS&G{|R$*!q?Yk z!)i_OT#V>_ytf{cSWVBm%F2D!jZTRiVT%r}y=aR&^%j&kidJ34< zESNL(^hDtk;V%7}^16stK#a~hj~xsU35qzsQNqD3k(S8}i|(JY*_@3ebh&Y75B5iI z`d;ft3Pg(?Sp3tVu7vRs{WqKYb-nHCbzDfZQ%K9#Hg8`iuiwT;cl}WyCU9WF$b)-p0O-ya!{vebE7+Zzx9DdV+VH(}=jIh^JzL-q?t zGKwEA(3u+H9Vl&2S@$34;qtkyZd@(>d5&j zBy>;uxCWl}>@=-`;9bhjx*~Y5{?;A-ubROSHG?wJG2`F=k(DegnbB-7VOhS?w*rtQ zWVD5kZiq&^AuE7M(F%dUoGDbRgN@^3Ui+bVs;g)J;} ztI6L*%=T4i{CYaB?xCgv87XP;j^~05;k}6A1Z>~QS6W1YffA9*`T3E^NLK9%PT-8m z%!3ArO+LS~-P^OVS%~Lq`Ml-qWi{U+FO^hSKb_@|8i0*ieu!dTgjclB=0Qtq*E#hk zm1UJZr|5G_^+*jTZKyzZQ230mHu=>z?`SvDm`}U%9`-CIxTu#tQW4)IPr*@1#YIGf zo?gYSh$toWej$^>q}nGB?A}?NSIFKwasr_iY&{><)>Y6Eta*0sClZ6-x!1Obly7=($L!01yu<>iy9%q;FChF;^d1*zx=7|3`7b@WX zNjOfnO%RWmXz9aSWiQ5iwvTj{$iza?Fz%r7Eg#}w6g~*ChX~>Q4^b(&mDBpf{#n@x z+t%-2F>A2R=KiS|KO~04VrRhk*$>5sx^FM|ulH2e6ZgN(^ISFLN7Y7;NdaMj0cw(6 zQFPx5Ys)Ia8nWM;DE(a2u`g4T*7GPUtD9A~4G+7^@zXh)eGiNCJ5gOs30ntOS_xJQ zZefm+GT?aWi7P+|K`7^E5@&k>INfbGHC>X=z%nV(WtcN5z%C zGyBeZDDOdT1aDn`*L{4DM!7B$qNmGq!zVJbHv&G(WsS6YsXXQR z1*(;17XhvZI%__E%i`j1Usrv~_Ec|Acy`c8a<-|ZqYkwluGM!VyPn}?C@6mBib&j% zfLJ`|IkQ5?Cvp$9%1GWg@aybYS;nK+Fi~|{X(_fIixab8-#yqaUKh3cubeDtF~5a> zt=4?HI}0Kkt2mnbmduf3Fvs9h(W!Shb14|yy zQABSRw!Y)z3+(Lv-%mq|ii^M7RWj1juGM%LeE%Mmm$35HYA0EC=RtDCd)(xAaAQq&{E=gO3K^UACWC%(NNd4&s&gdx zbLGGC5bmGJx+Plb?SzcHR~x4Wzf`#n2aQn(Xz8dcD=TYKt|JY}$hZ*A;}W)7_0fT& zvqhi)R8d4O-<^r}Sd~7;XUKD2tm`vK8GxTDvkqRpFC?Op5))LDl5w|p%2v-mwcz|6 zDh0jfbX0(1mB>sw@5-H20U$8X)PShRoLIz`EMLr8r8%rP%`M?TNqj3gSY2LM@HV# z_D{BWPV~Ru=Ijj9mz5H4ueK+@+>LYq+SdgEg0#W3iB6@zT+4W4B?FS{DL*DA^XoQj zcB`XO9rR~eI5oW;8=9)r_}5H9<`wH@=$z=BPSBu?7Knt-*?eq|<%h+Vv69D|o5)0Z z37Outjj3+r7o3r%;mPr_l25lpiYfXiA+;Bw1FkL-8)oB1g_M8|O3+t)! zH}b7j(%ittxiam<$+79krGWjjgxzt&9AWO>NSc`}b5I5m3o~0_GC_~+R{e!*-Dh_X zq=u#&&SoJ9oQxCM70yp|eQ^=q&Pz>9%u7uCYEkq!>#tnY!z4?GNr<;ELc%oOUm^B| z*~v-r1f&bSk?NB1Yz99DOi|NT_58?uP|s?%N8c0QEdBGrRS&rv_9Pw~;G-E)p%M`h zIS{n{o_(ncQQ%kfS|1fULQqi9N;~0Vl-N>LQyo$BXO^6&+aa0p$_){fIIvOGeDoXF zNU8zfvV=NsF^Hun_xJD8t52<9fh^kJ8Fx|CU{~1XW!R+zO+tg4d*<5>s6BGb+A{3X za`@%;xSF}Qp{ZK=V|-^e5CjBq!$z9hB!UWDgf^A2}JYu{b4*z5@s}#tQ#iQ`@tv~^)JkYRla0-4sJM2imduDRx z;^JXREuEgevi^>AT{OHfllbM!q>TyfL?C-`p4wqP*HMg=UAUH4igAJX{DUqPU zK|{(5U2=`%LOGSh#IslcD@|Q-w20~Pfl>UAh@4t?U=Q7?gBiL)|pAt}f zi1)cZ|4`pw()f>;i=obJ8>o~NDr|c=#6}Rc2b#FBFo9tgz*mw|C31S%3l3f$B^6W` z6BFYkBmFaGP)t_{*K94B=3W;D0YR!D@5Q*>ISQssaU2n@Owq|U@UkVkadurW2pONn zybyql`;WlqXCG(8U8PCR;WPD3&^>(=dJO1WX=sto5F-jPUcQpw?Lak z0M7&YVNoF^Y7PzLGM1UuYYT>fH zu9Hin8yPifuj9sibG&bMjZOc>ZHfdme7EEP@7ZV_HqASa)$96yy$ zp~W+^q*jFR@cl*cUW4yU=HGHe$q%S9UcDDKfhsC0`yvGMO;}leB*GwKL?ZLP2@=*Q zIh}S3E2|}v)}yYXsj4LxCasakrMj*^-m|qMCAlr)R=no&qX~jiYFNCgX3_FbNd6eWz7q*$l_JyI z@2F2`C-k4_iTRxZWEptCWVMCA#;1FxJzB=jjqWGZY0T^`Fr=bC??%>tluzl|xS|AgDt;_u%dQas z_z`*1^F|nKgjW%HcQ%?TwbV2X4KZ58*i{! zV!tg^sApLX4t-Zzn0+auy;*-{+XZu$68k(voQn~85~vA2qIYxmbc zZ)LlS&C+#mU)h>y|LF=2?$PPt;T{j)XC_4hgSSNzFndi(@Ev7JS}GJklm2*n+EK;J z(^Nj=J?9k>6@2h*gwN`23SO0_wV@$Eph5xx)>A}8gpco;%0R<_Hc<)&#uN)dlsi&M zR~t6hJt4J`t2q!3;HsEH0>Tq6VBL2TSF-QyuKugbKry%)f8mS_T~*eEKWD7Nj04Lf zx?9xmR^%x$N3UUWGzH>zf)H*xgM9KktIvE&J zIo@RDng_nrPfyR#BuIy<=Adv=VoI5P_wO~;O3^__xIcJ+h3=f}LKMHDW=|6i1*NKwTaHnFr3_+8;;Bj@BqPV#q*uSe5H4f?}THSEcdqXvBG;l z=l;N8f>w&Aj&&L=U`icb@h_t*D#}q=-*0YgY-nn1U`XL%f;)b)8d51j=Rs(^KGABHzY!e>2P>SMSJ8BS(ILdzm~|M7h|<5v^U2D^#O!V@bBegfue z{7Db&uuw%x>`+nHkAdR2;l1^z&!6H4tEOIiCO~5J%1Eq#}xrcemLGSIEqaYt&y`TFd)RWBoY(hqloRR>+5T)QkiZ~ zMEav`7Km&2Tkl|@H*WcwZQvJt}*<2k)NcJ zOJnJt2P#-j&(16^j!#>PM?^+6!wY=vGcqxmCeCvI^paB)dXWB85eaFypohZ4e%4@M z-*s9$ZFt=|x|q7j*6L<#kv04#t^H6K+WMwDrufH?ik!BibSLDi>*w2HMho`3`$r}! zGl*C2;NVE-U7j!-*ID0>40UZsuSGy34KQqWy zc*=6Rm^^c6^h`2P+`|;1!-UKVP_kR4$P*3m#3zrGG07995n%no7#E{4!vaiTShg8B zQ$79Ujb+oB5N`boVDD&RHLo!bXJc+w2vXqWGxaV1oDvkS&y)P#&ozj)dc)NyQY8lJ zgWOIf_Q&b;b#(MZVEn~%@d#bc$YUk9sV1|e^Qr^8nORvW%wO2n`@+`OHyXamkju)w zW;>_Kjmm{mfunS*w9{zVDD~o!*6|9tP-#Z(ZSoa}l8U*+Rd`p$d=DVi5v`JnOg%?dqB6p4;eP7n{ULqSC zbMGYF2if2#jS4Ue+aj%sWC%eB0iTjFz~5NZ$M&r~aqn%R8TV&lIV(d>|BDM(0BQ*pEotn)Mp8~^kjRMr`x_DR*lzY-UXB4f zNuqvyZ|YMXyEWgZC=9nXGV%*N`9r2}F;qTM$NkdB{nhWGeeq_<>dJZkH%y~}tpmSY_|UfPreCi5?j8In>W_ZQzuk_SfR`A&*u=rG%2by#4Gaz> z1>PJsEgxI|6{r7a2eU4T+M>1&y=pfTiUH;2x$4Svoi;lP$zOq)g*Pg<5q5&Xu>V}; ztm9qtI#J&(bIEX6lI1)19ozz~qbCZA7sCa!o&WZPG*)sL z%MKYJAta=9UtBwO4=-Nv_Oh~vn;~D%#cc8C_`wkd_nGwxW_B({&A=PdJ@fWdsNtkC zI=W{{PVp+~&=bBZ zQTSYyD-q9ig)vFQh?m963U^@m@IpoL%JK>Y`P|^~$$}JZPHE|Ltz2k!HY1(Kg@#)r zNqO|+$_B-oG7U~>sMH54>A8yNguy;DQ&Wr2+Qu$T-Y?=#PRl)^

    Cb73}P-RS)zT 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/terminal-light.png b/testdata/snapshots/darwin/terminal-light.png new file mode 100644 index 0000000000000000000000000000000000000000..31dc61419fed425b9677d79f8a0ab6240ca4aeef GIT binary patch literal 11584 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¨b&c+nHi4|R~|{%|60H%KDz}u!_e^9)^1&_ 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/terminal_search-light.png b/testdata/snapshots/darwin/terminal_search-light.png new file mode 100644 index 0000000000000000000000000000000000000000..0af80e02ad0dbd7cc07b3d4d7bc08213f17d16bd GIT binary patch literal 7606 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 %o`| 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 H&4T|2@Mvn0 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/variables_panel-light.png b/testdata/snapshots/darwin/variables_panel-light.png new file mode 100644 index 0000000000000000000000000000000000000000..a28c2ba4800838c52d142a3fd75322ce8dac63d9 GIT binary patch literal 8556 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 literal 0 HcmV?d00001 diff --git a/variables_panel.go b/variables_panel.go new file mode 100644 index 0000000..6e94759 --- /dev/null +++ b/variables_panel.go @@ -0,0 +1,158 @@ +package mujica + +import ( + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// Variable is a debugged value; Changed marks new values. +type Variable struct { + Name, Value, Type string + Changed bool + Children []Variable +} + +// VariablesPanelState is the open rows, choice and edit. +type VariablesPanelState struct { + outline ui.OutlineState[string] + cursor int + byPath map[string]*Variable + kids map[string][]string + roots []string + data *Variable + n int + editing string + draft string + started bool +} + +// VariablesPanelOptions configure a VariablesPanel. +type VariablesPanelOptions struct { + Disabled bool +} + +// VariableEdit is a typed value for a dotted Path. +type VariableEdit struct{ Path, Value string } + +// VariablesPanelResult carries a committed edit. +type VariablesPanelResult struct { + Element *ui.Element + Edited *VariableEdit +} + +// VariablesPanel shows an editable variable tree. +func VariablesPanel(c *ui.Context, vars []Variable, s *VariablesPanelState, opts VariablesPanelOptions) VariablesPanelResult { + if s == nil { + panic("mujica: VariablesPanel needs a state") + } + if !s.started { + s.started, s.cursor = true, -1 + } + variablesIndex(vars, s) + k := Tokens(c) + d := Density(c) + var res VariablesPanelResult + res.Element = codePanel(c).Disabled(opts.Disabled) + disabled := res.Element.IsDisabled() + if disabled { + s.editing = "" + } + res.Element.Children(func() { + if len(vars) == 0 { + codeCaption(c, msg(c, "variables_panel.empty")).Padding(d.Unit() * 4) + return + } + s.outline.List.Selected = &s.cursor + s.outline.List.Label = func(i int) string { return s.byPath[s.outline.Item(i)].Name } + children := func(p string) []string { return s.kids[p] } + restore := dataSelectTheme(c, 0) + e := ui.Outline(c, &s.outline, s.roots, children, func(p string) { + v := s.byPath[p] + ui.Row(c).MinHeight(d.ControlHeight() - 2*c.Theme().Space(1)).Gap(d.Unit() * 2).AlignItems(ui.Center).Grow(1).MinWidth(0).Children(func() { + codeMono(c, v.Name).TextColor(k.Info).Shrink(0) + if s.editing == p { + in := TextInput(c, &s.draft, TextInputOptions{Label: msg(c, "variables_panel.value")}) + in.Element.Grow(1).MinWidth(0) + in.Input.AutoFocus() + switch { + case in.Input.Shortcut(0, ui.KeyEscape): + s.editing = "" + case in.Submitted() && !disabled: + res.Edited = &VariableEdit{Path: p, Value: s.draft} + s.editing = "" + slog.Debug("mujica: variables_panel edit", "path", p) + } + return + } + variablesValue(c, v) + }) + }) + restore() + e.Grow(1).MinHeight(d.ControlHeight() * 3) + internal.Ring(e, k.Focus, theme.ControlRadius) + if disabled || s.editing != "" || s.cursor < 0 || s.cursor >= s.outline.Rows() { + return + } + p := s.outline.Item(s.cursor) + if len(s.kids[p]) == 0 && s.byPath[p].Children == nil && (e.Submitted() || e.Shortcut(0, ui.KeyF2)) { + s.editing, s.draft = p, s.byPath[p].Value + slog.Debug("mujica: variables_panel editing", "path", p) + } + }) + return res +} + +// variablesValue shows a value, marking changed ones. +func variablesValue(c *ui.Context, v *Variable) { + k := Tokens(c) + if v.Changed { + ui.Box(c).Size(7, 7).Shrink(0).Role(ui.RoleNone).Draw(func(p *ui.Painter, r ui.Rect) { + p.FillPath(internal.Diamond(r.X+r.W/2, r.Y+r.H/2, r.W), k.AccentText) + }) + } + val := codeMono(c, v.Value).MinWidth(0) + if v.Changed { + val.FontWeight(700).TextColor(k.AccentText).Description(msg(c, "variables_panel.changed")) + } + ui.Spacer(c) + if v.Type != "" { + codeCaption(c, v.Type).Shrink(0) + } +} + +// variablesIndex keys variables by dotted path. +func variablesIndex(vars []Variable, s *VariablesPanelState) { + var first *Variable + if len(vars) > 0 { + first = &vars[0] + } + if s.data == first && s.n == len(vars) && s.byPath != nil { + return + } + s.data, s.n = first, len(vars) + s.byPath, s.kids = map[string]*Variable{}, map[string][]string{} + var walk func(list []Variable, prefix string) []string + walk = func(list []Variable, prefix string) []string { + paths := []string{} + for i := range list { + p := list[i].Name + if prefix != "" { + p = prefix + "." + p + } + if _, dup := s.byPath[p]; dup { + panic("mujica: duplicate variable path " + p) + } + s.byPath[p] = &list[i] + if list[i].Children != nil { + s.kids[p] = walk(list[i].Children, p) + } + paths = append(paths, p) + } + return paths + } + s.roots = walk(vars, "") +} diff --git a/variables_panel_test.go b/variables_panel_test.go new file mode 100644 index 0000000..67bd40c --- /dev/null +++ b/variables_panel_test.go @@ -0,0 +1,115 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func variablesSample() []Variable { + return []Variable{ + {Name: "decree", Type: "court.Decree", Value: "{…}", Children: []Variable{ + {Name: "id", Value: "42", Type: "int", Changed: true}, + {Name: "title", Value: `"Of seals"`, Type: "string"}, + }}, + {Name: "count", Value: "7", Type: "int"}, + } +} + +type variablesProbe struct { + vars []Variable + s VariablesPanelState + disabled bool + edits []VariableEdit +} + +func (p *variablesProbe) view(c *ui.Context) { + Use(c, Settings{}) + r := VariablesPanel(c, p.vars, &p.s, VariablesPanelOptions{Disabled: p.disabled}) + r.Element.Height(300) + if r.Edited != nil { + p.edits = append(p.edits, *r.Edited) + } +} + +func TestVariablesPanelExpandAndChanged(t *testing.T) { + p := &variablesProbe{vars: variablesSample()} + tt := ui.NewTester(p.view, 460, 320) + if tt.HasText("title") { + t.Fatal("children shown before expanding") + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyRight) + if !tt.HasText("title") || !tt.HasText("42") { + t.Fatalf("Right did not expand: %q", tt.Texts()) + } + if !p.s.byPath["decree.id"].Changed { + t.Fatal("changed flag lost") + } +} + +func TestVariablesPanelEditLeaf(t *testing.T) { + p := &variablesProbe{vars: variablesSample()} + tt := ui.NewTester(p.view, 460, 320) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnd) + tt.Key(0, ui.KeyF2) + if !tt.Focused("Value") { + t.Fatal("F2 did not open the editor") + } + tt.Key(ui.Cmd, ui.KeyA) + tt.Type("8") + tt.Key(0, ui.KeyEnter) + if len(p.edits) != 1 || p.edits[0] != (VariableEdit{"count", "8"}) { + t.Fatalf("edits %v", p.edits) + } + // Enter on a branch does not edit it. + tt.Key(0, ui.KeyHome) + tt.Key(0, ui.KeyEnter) + if tt.Focused("Value") { + t.Fatal("a branch opened the editor") + } +} + +func TestVariablesPanelEscapeAndDisabled(t *testing.T) { + p := &variablesProbe{vars: variablesSample()} + tt := ui.NewTester(p.view, 460, 320) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnd) + tt.Key(0, ui.KeyEnter) + tt.Type("x") + tt.Key(0, ui.KeyEscape) + if len(p.edits) != 0 || tt.Focused("Value") { + t.Fatal("Escape committed") + } + p = &variablesProbe{vars: variablesSample(), disabled: true} + tt = ui.NewTester(p.view, 460, 320) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyF2) + if tt.Focused("Value") { + t.Fatal("disabled panel opened the editor") + } +} + +func TestVariablesPanelDuplicatePanics(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("duplicate names did not panic") + } + }() + variablesIndex([]Variable{{Name: "a"}, {Name: "a"}}, &VariablesPanelState{}) +} + +func TestVariablesPanelSnapshot(t *testing.T) { + snapshot(t, "variables_panel", 420, 180, func(c *ui.Context) { + p := ui.Local(c.Root(), "snap", func() *variablesProbe { + p := &variablesProbe{vars: variablesSample()} + p.s.outline.Open.Add("decree") + return p + }) + ui.Column(c).Padding(12).Children(func() { + VariablesPanel(c, (*p).vars, &(*p).s, VariablesPanelOptions{}).Element.Height(156) + }) + }) +} From 847612f244fabebc34807020656b9b78c80bdeb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 5 Oct 2026 14:38:42 -0400 Subject: [PATCH 13/13] Merge fixes: one Rule, ArtifactKind, CommandRun and abs32 across groups --- artifact_card.go | 9 --------- command_block.go | 11 ----------- internal/calendar.go | 9 --------- internal/chart.go | 6 ------ internal/display.go | 6 ++++++ scatter_chart.go | 2 -- 6 files changed, 6 insertions(+), 37 deletions(-) delete mode 100644 internal/calendar.go diff --git a/artifact_card.go b/artifact_card.go index 1bf76d4..87d84fe 100644 --- a/artifact_card.go +++ b/artifact_card.go @@ -10,15 +10,6 @@ import ( "mujicaui/theme" ) -// ArtifactKind is what an artifact holds; zero is ArtifactCode. -type ArtifactKind int - -const ( - ArtifactCode ArtifactKind = iota - ArtifactDocument - ArtifactWeb -) - // ArtifactCardOptions configure an ArtifactCard. Title is required. type ArtifactCardOptions struct { Kind ArtifactKind diff --git a/command_block.go b/command_block.go index 194e807..8d0c87f 100644 --- a/command_block.go +++ b/command_block.go @@ -12,17 +12,6 @@ import ( "mujicaui/theme" ) -// CommandRun is a command and its output from the caller. -type CommandRun struct { - Command string - // Output may hold ANSI escapes. - Output string - ExitCode int - Duration time.Duration - // Running hides ExitCode and Duration behind a live mark. - Running bool -} - // CommandBlockOptions configure a CommandBlock. type CommandBlockOptions struct { // Prompt precedes the command; empty means "$". diff --git a/internal/calendar.go b/internal/calendar.go deleted file mode 100644 index 1b6164d..0000000 --- a/internal/calendar.go +++ /dev/null @@ -1,9 +0,0 @@ -package internal - -import "github.com/egoist/mygo/ui" - -// Rule draws a pixel-aligned 1 DIP horizontal line at y. -func Rule(p *ui.Painter, x0, x1, y float32, c ui.Color) { - yy := ruleY(p, y) - p.Line(x0, yy, x1, yy, 1, c) -} diff --git a/internal/chart.go b/internal/chart.go index 30286b9..47df0ea 100644 --- a/internal/chart.go +++ b/internal/chart.go @@ -189,12 +189,6 @@ func Sector(cx, cy, r0, r1 float32, a0, a1 float64) *ui.Path { return &path } -// Rule draws a pixel-aligned 1 DIP horizontal line at y. -func Rule(p *ui.Painter, x0, x1, y float32, c ui.Color) { - yy := ruleY(p, y) - p.Line(x0, yy, x1, yy, 1, c) -} - // AxisY draws grid lines and tick labels left of plot. func AxisY(p *ui.Painter, plot ui.Rect, s Linear, ticks []float64, label func(float64) string, size float32, k theme.Tokens) { for _, t := range ticks { diff --git a/internal/display.go b/internal/display.go index 3a00828..76a35ab 100644 --- a/internal/display.go +++ b/internal/display.go @@ -6,6 +6,12 @@ import ( "github.com/egoist/mygo/ui" ) +// Rule draws a pixel-aligned 1 DIP horizontal line at y. +func Rule(p *ui.Painter, x0, x1, y float32, c ui.Color) { + yy := ruleY(p, y) + p.Line(x0, yy, x1, yy, 1, c) +} + // ruleY moves y to where a 1 DIP line fills whole device pixels. func ruleY(p *ui.Painter, y float32) float32 { s := float64(p.Scale()) diff --git a/scatter_chart.go b/scatter_chart.go index 99764f8..1703011 100644 --- a/scatter_chart.go +++ b/scatter_chart.go @@ -158,5 +158,3 @@ func ScatterChart(c *ui.Context, selected *[]ScatterKey, groups []ScatterGroup, func scatterRect(d scatterDrag, ox, oy float32) ui.Rect { return ui.Rect{X: ox + min(d.x0, d.x1), Y: oy + min(d.y0, d.y1), W: abs32(d.x1 - d.x0), H: abs32(d.y1 - d.y0)} } - -func abs32(v float32) float32 { return max(v, -v) }

    fEr_S4SeJ7 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/event_popover-light.png b/testdata/snapshots/darwin/event_popover-light.png new file mode 100644 index 0000000000000000000000000000000000000000..67ff2e40644ee1c0abfd5ce2d553a35f1d3c29b8 GIT binary patch literal 31503 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 TaUD458uC)=)$?KrJ)i#tB0$;` literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/recurrence_editor-dark.png b/testdata/snapshots/darwin/recurrence_editor-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..fc99a37f741295b772f99a634fe56f411890ad16 GIT binary patch literal 17827 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 Nk(E-CtPnQ}{BM&wC@la0 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/recurrence_editor-light.png b/testdata/snapshots/darwin/recurrence_editor-light.png new file mode 100644 index 0000000000000000000000000000000000000000..200edd4c1e3e352d507848fb4870cc2265015e36 GIT binary patch literal 17147 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/relative_time-dark.png b/testdata/snapshots/darwin/relative_time-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a915c4b4e8b7bab2d51282e200b30f9a73a1e293 GIT binary patch literal 4585 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/relative_time-light.png b/testdata/snapshots/darwin/relative_time-light.png new file mode 100644 index 0000000000000000000000000000000000000000..ed172f42624c84576afd56b967e44de7502cb6ca GIT binary patch literal 4344 zcmcgwhc_Hd*WVB%O4P76qD5b2^%g{n-ibt8UG$nKdX2Jrw6$3!gdnWmO9-n)7oslF zS!A_Gu)(|U|L}g_IrrQ%bIzRk&D?u`_ud(pp}qzcIfxtp08nXZsu=?SckU9#f%k|A z8hQQ51OTAv)>2b84a_^h1idshV5fq1sB@u>SISraoTIyT zmP3xy@W*-LrxzVFajPSDVlLqtbYgWeKpJBEXOszdMA=Evk^dKy7}^+3u0#V(0b$`M zAOhG$i+y=zrGe(t@HKm>smax&0_i*%goUN0frKq2qQ(%GfAieh`mp!10gL^jrW#>l zavEZK7Pa?-r?R4g##2V@*AOIEgA{ON*&+%Cm+7(B`un(SZR;$4tU8E7T~B|(u9o1z z=9fszd3hOO`QU@Bmx9h>ufpA>iF#b3mP+I?8=D6~*t3?(E}}7^18Xa#v5}2PuEWE_ zsSs+ph(`MrB6tdiot4)^0E>>?;UQjDv$u1+z6pBuYs~?$ySwY-cRt!4n$ij;*v*?w zRbAc5fgUPIXJ%^J+}NlsdhafgaEmsd2UAl2S9j@j{;UMdQWev9$`U+q3rnRpcFg)) z81QQw%ZJ%3Aonu!@aS!<$P5cpboF#i!N36-2b5`ATG!ux4!DhBxB9uA+~>U4Pm#R( zKsXY)IzN9Gpv#jqg0inW0eo!Tyy??0Xl&x8d)x0yr=PiUBC(fkY5ln7^ERSoj@)1T z2|;uy=p`l1s8ZHGeG}FH~t3lZE>JQ)pF>cQntDUl200Gp|@Q|Xdz$6 zp7(2qX_R3adU{S*0hl9e=p_mhcw&kzHv&D;NM)D1g~-V*W)yy`9HB|-pPiNL=l;`g zUsnNBb^-Uy*Wuh>Q;G-(hwS7RnUrB`7f1*z9zM*z*`M3o@|Ba5n?I1}8Ms1U6XFNx zLup^vI`{y<#gh5}15ztB-Z+0;*KFOp#z3bK0R*M+T;69OFFhrDW?2aU#8EP<L5^*{;}Y)z|O_#I#mc1?=19sNevXo}4wT6(q_YcLxmsSW1&gNk|0a z?}p$>kqFQo08DLqhJ}q`*Z&;Zcu8R$8m3ezzGT%-^uiE$URP$RKR(v;%W$34n&W+f z!ti6q+cemNA3qC#44oMNSTV*$ho6t&Vs4AY=%5NaRr<(UhN3ATj?-&bMRD`Ae<2bgiP*fGmRG>MjZd5=QR;_5vP8f zoL4-esWXwBEC+e>B^6P@F_rd%E02e2(UlHRWzFQr4=ziK{)UmJgLQ^u+~^&`NMh{> z3C7RQ?=3EeCSSzyHtJTe(YLA2((h=}sF+GjOc-UgWuleCFiSkTpa$~c)(FO05`eME52m&%2-0b%Zh7bYP#*n|z?Du8%H{6@ z;q=}Ag>Ts!VeAOqoNOcOab{|4YSJsHy6$DpIQ-p3H(nE~xKaoKTEH|?p>4s$fNJZG zCdq(53ABANF`@DNluI;pJYgR%|8A2PJ2L~00w*Hyhi?I|U0qS-<+@M(mWPM`Ikwl3 z>acYQOrBkS)zQ}?z|UWGx;nGCXvV`_rX`~nO#Gw7oRKmoM=Dr0B}K0YdNB0^Ila#U z(=KIQX5$bM@%EOE$SLj1mw&r6DkcABy8|I!c1VuZSW7yV6bf`S&N_DJO)iBsg0C(ZPp zB94DssW-Q_N(FfIrZ+@<_oEk(PAf?3+(BwWM_32DuvF-U&zoY@AN-IPH)9eBk#bsZ-?STAVH&mR zyA$E)XCC#{*Fj11db=EnJiW$K$3&}Q6gnNfGYMsUZOmcUKtE4c@A^ExTwy6BOuUcH zlZ#GE$34302m)YWWYqgG^C~5`ud2K}3uTvJVso!>RksX$brtG&vfoz+jfH3B zG%S#)@e&FgaViJz&h|>Ks+81=Mvg|ys!oDT*WbKwtFLQr4-~~;%(>`{e5W4d#n^AX z()pS+Ir9Mkh~LQ6)*hKCb+YLS{wA;f=q#!{)S%Tw9hd~tqAFc# z4CB+_GtFXpFxF1J>)R`%w84<-DqY^x_UVWJ3_TiQV! zdTdGAH>2=o|J(K`f;Q$Ed+6D2g&`jo=!!hvBsV8KN=Aj?y~60CuC6dbpjWh^KArl} zi!Tk86LY>#*ga5~^WNm)F62msR4{vxZw7ajPeUtJI z6TFmudL=YlVZVsOiUPb$hLLUHYmvw}MDW0t)g-H5fp zWDYrjvZ+}*C~9ub#62aB$Oc~nB8v{ ze}yi7!hHrq3et0z=jR)3Z#;?{!0>uM&U3ULP)SN=sHVCAp7DVP4C!>*7arh3jUoSP zxFydwUXJh@w2@x@(9s@oGOHJ{=~OW{HZ?aPv{kv8{^F1xUiKb&r8IixH<7Jj=Iits zUzOgjgza%cR}H}6N~P5!5`d}s+y$9OMdc0&=>_o7e*9tbwqNBtB0IM1WYHLfTPK{C z!-v)lnMf$O*`gvLQ9Mq4(YR=l(MMA5P30oi;@HmQ-h<)*N%qp|vLU(j@rZD)iF_9SomzTN59Nj?;KCTxZRQX-?^u{uINY5_V?s71k zjAfe*lcf!YG8blM&aJHIXP}&%x+!9x&dFpmi?^$EljS&4Qua)ek;2qU3_IDnrJbYG zYi4Z%kocdAKL@Zm+@sD7doVL;PPlicUq2+UmaI@|<)QggD5@NV0`m)r1Cvc0znNBF zpOn{Tx(*u;qjiGja@4&vWkaLC+PEA}a~;ex<7+#6mzGB6-dbs-0i`^0`=^`K>t0&4 z|HjT{BuCu=+B{TsoZ(#*e0z67b6y<*I!zVY3NqMm5rX|iZq9I zdcek<{r|b&OV}(uAj1Y~J0v}B4z^YfR#vtjt3HH_it*p^-`$sG(#n9>>`HrD zg$cg7ZAKwWr(prwH+LJ_u;cmA3ckO|$p?y=$#pJ01$L1kq*0M?xg;?m@62sK*4FN> z%(~CPHDag8*M-j=prL=~DxaNQ z8gk=uJzwWg%n7fyqE&`c0warVf#psuOZx>15$?&X7`o!`;BP{GwOACBo>iYwf$$~{sl`%v^NiG@tM{Hn?OqPWj5BD!2?Tn@0DMbX1~Gf#fDpgR9|%*o319a8XOv#OMZma$+vggTW z+p)R%=q6p(K)^6r3V!{1z3naX3JB_lf$xne!I@*ug_wd4(-;(N4YY?H< zq-$ER;rAX+7;`;uD4?-Y#`=mMmF4kVK^QwQ8akUSfNNyf%gYZHHBrxuz%g%?PR#ZO#e1JvUjb; zmG>?1cM(Bjj;XwmzMi1PrUdR|k!u%@bVKpA7S7&XbZrD~lrGN`mv=xIiIFoZDx$DQ z$r%~p$Uh$kib2QDNn2f9Nrf{of;Z{{gTSX1g<=^P$MYRJdbP5oo92#neH5(7PiI}rAKmmhEXs- zCk6V#0mG)Dtj&#=;viGG3?45nHQO65f&GQRI(>Z}r@ti%RH&))bemk@NQ*48__a-f z5F~PPcwLFJ4<>x>?J)x~V6mxmG5tB+IguKjbTK< zYZKa%7EaYPTGnRWi&z*iX#4?cz;Qg(;PBL^NFKSPaJPFFlt}#SqkDJf+P{H+?=eWB zjwGL6Qd-LG!)H7jQ3HqgHH3MK47%yiKxQXrZ~qZOt3&DI{x{TVnB)naCO1cE@$v0D z7Z#S5s?@!WVcqj?%}MpYqP9+UYPdP}9bAs@E|SC})4a5=;L!^=wo7>5z2pDTVd`{b zF<`VGgZ@qL=Wl;cbcyd67%zN09b2?_5<#OoCC|otnYIGr;D!dYym6;fH#Ym@$DH4P z8iLViTn(L3Q~0f4RuYewHQW@4GuU#Ae`vE9K$T^OCm$bQFO^uZCZX5@TWf9)Q>kET zoV0#(l__x-SM<49w<<&~ub~m8bG6pr$*KBmZGYEr9GkqF!69xZ_?6|1wF%2*Y8sL5 zPcokH+@#R?^Y6i3ECrt zjKT)_dJCRMMc2HMgfa9+(W~}X(MJ_(K;Lg>hR5}WQubIKcE5@9LdTAHZ~8Wf5l~T5 z_dAVtrE{oIf^;Ry+sa0vxKVG5P28& zCd`3EnV)aS;urI95AWV6tX-=+!s||;d63b*n{q9Uf8hrk{^UL!=)d9ZtvX z+p3(kozr#G!{S@EeNL!iHr}SikxJ5jUe{D%N*E;6J1DENBL(s);9F9wPWo(}{`WR3 z?jJV`;=lCdaujIof_bWIYMiTUbiFCF3JT618}3Wx<>l226sGvRgAnxynMW-?eBv~l zsB~UDCE+6u%*#4C+}kBwEPCuyyP-JMHEgyjXlz8VZ6#kw7OE!-92~!K;zmZ*^tAmq zaIj+}xSSoI%`t#_P4+KxuK9j1U*3vvSwQe*TI_~N*V8~fA^)T481a?|H)Q?dMgBi+ z7NVEN)u8e5@p037tv+>?=k~(w-p#WUe=gj=zlQbU7M(0Hc6pz$1GwS;F-EOyUWJme z-P;z790$?WJ z6R~G-tFq|rPYwOIbo8VrD-F*}chYK4j1SjGPvymrv#5)KG^5E$1id}Q+BXL?*d1)( zjP{7yRUhoLX@An!xiae)X~2AXvE;k0mdts_=xFUKOG=#WCHD$qFXv?2ViF?Sg?$Wr z>XYBQMoEMk8o1_Whn~JB>~!8N&yjBZ{AthOY9E$Tci2DF2=P&O6}?3v85I@@@c4Kk z<#gF|9xARV=*wwT&M%C?TU#o}&8S(Usd{!3p!ia?J9#iu!V3V=&oIH2)0N3DcsgQe z-e1))F}U*Px7q{n-B>2?5!u9aP-3OFOkr=RNLRhTt@fO9w$iUXt){c(xuVThesjh+Eba+}Mr*$12X9{<7;H*ocLZ#PVGdqR4B+8nk#+`8((n0yD=al_X<)|?P$NBTpb+w@ zs{m%B=cn_&5MY|M2y5xyNS@bJzrFz!tKb&I*_Ga@uZN@86Pz!?WLeCUD=O7I?^V>j zrMhm(k(kMA$})QQ*o963nWcE2C}Xp~{jvFKl164LupLsrCK&%Mv{JwD$1RKjq2WnrPQ znXoPxrFON^nzR8yuB|mFXec>vlz{FQ3;q-PKb~@PPNp=$0lq|?%)cWtMgo96L;*!W zCCJaoale>JBji*uZ7v>cNU1wkfN8Dlo)o1KZVK0AB;a zY`W<&HP-QN@VAXQJtJXO?~|4uczkN!KY+nxn-mo6UXGVLk}_WNq^VIdp1o{l>9!1c zKbf#MB+E+4rM=sI7#!%{qo`;igmtqn`~G1evHJOU#;&)wzSkr0#UYkYFEmM#uk|HC z-^&r;aWEAyjEY{{fJ^<>ZM14sUrMfKR+wgWwQg)|bO6pRF*|7eonQYdw7#N`i5H2N zk`f+_(Pwn-8^l5$^gDlcwdBZMk0gC4$#Epr{9=uNXXwC-99jnIh{`ZoA$znd2&eYEZsBKo*Z6x%Y|{$0-ANvkc`bOT%QX2V5# zHqW(3iGpgKl0QW*s_JJ6HlpHUEbo6d-uHy3xW>nygFq)`PhNw$^6?B2Vu~u1HY=yy zb;ib`+(G*L_Qy|moN#bY8>C-D+#LmROzI1 zcA^ITMLt%t845qc!+Cgl+3~*dsCuF%-h)6TNh?Cgt;u3p88Y5a&(4<~B(Ull$^O^G zVko11r+ZI=#%>A)cyw2-^-8wt>IozB%f8ETQpVEK^zN6Rr*+d-Prl=LvCA^`YHsq- zM)x-wRhm{)1#yC3>mdl5l|?DST(EeYcFR`Cp%@VGztya*qC;?`YY{S;YH{~hw zxXjCVbYwJN#n{*BSl{ApEFxlHf}nu_EWT9=Y)(tSF5s3KX&a_;f7S{E55ME^oIJT`PqZV5&uwXpWyR%6vTr7*GSKqKM5SDVRd7unrn zJuEr>fe`gWUGJs~35e|}u5cg6=X(|tlHQ?W*$vA9Ru&M5=tmo^%|W2}!Wo5>NJtXC zMox|_V>F%ufkVv>f`?l(C6xIOnwlC{gsq@Qc2$$50xB64qay+O%g~|_exS@pkac{q zH*WCgBV3Qn>yD*!Rt?v>2o9sJL_(f5A0J)6reJ{pdroFfnEEH*bxLK!4TPv$yN<2K zTw+aI){pynhKVLYRSbjCCHe+)=izSQb$mBC_B*rmcw)I}%Ng4Ia|CTQjeBs}o;DCN ze>$_c_a$&g*@jnB?I+tsDVs+D|RQq{Z@L9&jfCXJO6Elyok)qn+( zNxVD^lh4CRpGvT)cxu#ovrr=n2f2ID_^XqhM7V<6+6XaxMrk^+ahFjv++kJUS^Knq z4=*=28d1?rW~N3^5S(+Os*(~T#y9?1#=_#yh7~iSqt4ZpjVTFQA24KyHZIg|KVP-T zpAkRQN5B03{ZCh)geoHyO;br08xI%d)M83A*H0)5mH<80x~6UF$(=qv!GyxpWIuON zHgs@J1|7u!pMazxSt$LaO0ZNS&mQJlcwj_P3> z1|sN}M9z3SImh-kF)J~06VyXPvZ9E8cBW%pb3p{s`Lp}n0so!v$#M4-FVxP|@*wq> zg0!+SQ}D0dA8iSmvs1B(DqKS=B+9h+uC6pR4}CR7&_oU6t%Zh9x=c*&xVSvLGR$;N z)s>YW$_S57Y`ctXcpVZ~$Ap^Q^q5F@xc6^|4+`;4NLyU4bbUz3SC4jVt-h6?jkPaO zlgB~soW`U7DC+h{l0?l01E>Z=&XB{asWy6t*G*07US?r3e$O+JrZ3ZB2_yUUaEp?##YhQMr(uzLmcwgkga{8|`PE9gx)$NCo;w z0fzCdqON>sM-}>TXX|!x)a&K*s%(92!(UEkA18^bo6b4(weFWXZ5vbl`Gu8?s!jk2 ztVAE@v>YfWIB>s1C+y7oxkeSQ<6GAGx~En5*Ved5xCOqpWO96Bg_xn3Hqg>y}89YG_#}~n3}sb@NDlS6ceK-RbopMn0lZj$*#?qb(3#bS1ql2 zDv>=wkfE@&psA)+b!2AsD|kl&QCvQ+AM^Q@Rs@kvl!YZ@0dpQas1ujgA7zSsK6BO# zOhFU4`s3`zOAJ#~x+W+n(;*N7(XHDFQ1Vs=g18nYRPQijWm!c|i2fu#-{fwH08-$G zJf0*si=U0oEH%3(^bP&w6L}<4>98Xzv#^2(@oit&8e=;0dGmDkbTo_6vKUsd$k;z_ zqk@EfB-~{7D=*cf-Ml@o*>)?vURtN4u$b4;BANOvHnpeuAB_Ejiy^CKWVryS#h1 z_WTOh+1Z+yn0e7wFvi72Dtn^h!x9urk~2v5EtqoDugBz5C|T4-&+6c)B}Pc$8~+CK zjL$f@HPz7YE64K6g;SUw&BJYwn>$RtK}St%!@%+_C?A_Wiuh6k>gz|;NvX6~?e~vO z17D;%IYyYXOMVSus;VZ>^ytge?(TuPd2Ub7n$I)U^z_pQYZvqWsR|#`p^%33^xV;J zq7j75u@bc;-=hP3UHaPviJ|pa>Z6Rxj+Kmahmr!VJ~lQ|paDyZ>+ZA<^w-H2B8cjA z)4}`O^-2YFz4kfx3I(5h54iWAh*Rv0=d1TFXyiI@LQ^XzK6UD-TC;_PH3y@@HaDb2 z#<4>qEtlNr0w>60(&Xd{DQ9gr^M8~^ zSCM>yhi5hWoFVFPdQLUnA#WO-9DoQ?c}sAk*Nj0-RB5%~#2tit>W;|VebaVR*wX`d zhL_cYSe7UN2U1W|cHAAHasVq7+}IXRJ)GNWWo6_ChJ<97l;}`<9`}sy1>N6Q9@~`E zP@LHXLB<~&Clz9YGBp>uKjRpWnHBa1!Qn%4_SxP)9qb;Kw;fF4JG`0kb<+fb_D9Ni z_8)Y0=Y^kl*uRySRrb9h1?oo*C`Gu)Fj@~|4h)FJYtij+2{tsz1{&MDo^KS~T|5RyfddLud{-C;q-XVNtG55ytJ*Ub< zJ9_%C#0ECF$6m6{rd8OijLg@E8*gk}eBpPGdV~PIwq8{g=w}$U|7KwMXXoJP;O4np z_COH)FNHQ5#mgh%>f-X~Giw6$qx&6CcRINSHaq(k1hSlE@O3mtQAGArpw)cb1^^~I zD=aU$H9b9YG{10Pv*f%zaZ=$J5ZeZksZ2~CNy{gyenMU;cS2H;%j~lJ7TlYM#5=^oHovv zwwJR%_rAX2`g0fTL4TjyPB^r?dkb%)Os~zJ5M*~g)m>w$mfw1bsZ8^StJVIZbYbB> zdLnc@YpF9YC^@;ZdtE@|JsjM2MV9B}MAecQ%7%k=SlFQJi`};^-Z1eKbr;2M1DXX)@9s8cMvQ2hO1a_jX(FZRO$MOyrI?;1FME85mTTAF_)1 z)YVN9OOKl06m<_{rF91Ujh(4z$BE0c*QaNm!MVQn_G3L*t9({Qo$@huw4e6kLSxXv zg6^BuU~?!DR)VE;?FS#T&&g?N&Q4RGznAYFw>U8~-*h6nE-q-MMM{quvOG7~#D%jX ze#r-lAGy?4)5vVJW3!WvUEy7^$2RUmsrXrZ%ODWP3=w@qjz{3$KQ+XxU9qEOBVMu6 z;2@JND(W1if>_(yvdC28=UaP8F|m=Uj~Pv_Hli3^eg!WZ=_T9SCct@1O>Krj7l)t5 zgJ)hDCJRQbtgNi}x9pCWNaY+p9uI1;bq);N0V|HYB7Oo!Ac_E#sOd0@GA)ihUTIBj?H&<{yZ3t} zeM%xOEUf(_6fp;b6G4GyyR(Ic3w034#bst|%c~OE%#3U$*w)lCEiQ+V@0x}2pfi%= zHHd+6n14w}z4Ts%%nEQ=78|#e0R!ph&qEqr%Sd|l=7-T9u{Di^L7K=XEG(?VG-aW5 zua5J#q0Bn1_#9N5`!!nqb;oGV)#%_;ZXhL_(gfi^`v-3Z6BzC6?L`%1vf4IpU6w^YblVIXIB5i@9Hulgp{8%Y#7^W(yz63QMi6DBYMCw`%HKQSc3<(%pl? z->ZNkl&g)w`g1=pndrcz zxuzRj&#`O5fG8Uc!VtzF>Q&_p7JuO)B*i1-=6y`ii&RsaHuL#l?eQ)&E{@$u7-ngK z`w@1vU&Dmjk24%c=zl5K;0bTzY_`Pu9t9+%93wGSC9*h1MoULmR8n$s7|ZB>5s*K> zCj7nCacAg960hT;x?n25Ym(KhrGxwGbEtL%IT(^PS)d}7Qr(h~p-%YudBRyhk2iF} z{PS?edOajVVQg&W<-@*p%J(2~7r4J62W5n_(>y~C+gBq_mc=C;*SK_*m3Q{IUkm5+ z>8dLHJ^_NTA}O1t^s&k$2s5-{x`x?PQfFp*dTaeqB1g$idv9}7C`aHGd5k3d+PVQn zHs8R2;O(M4$S7;k$NbvMQLHxn6?IeYjyIv5wvO?nFfs#}# zEg!kY?m-!;zP!X>ZieCH$%7g)qNH0*P)ujS(M9HNXDjJ7qgR~;HERT&^qRa^P!a}%GvIfayA zYsd9&hneUVNW01BU^wSflZ%%-@7DJ=*v+Qo#?6aI^<)2bjxjE7b79?Ta&V@EqvK#^ zpdzbAg2jo{q?8oB6IxkLO?dHZ;1TWnV}Q!H14cP*?~T^{=fVC?&d$sANtNz{Oa|X+ z%oduRZv+M0cB$_ZUaR$f9 zhBwgL`(XyR9SX8eSkGmLY*5P+_@4L#m6X&J`T(8Z)k7t*d%YjW_lstuSM?t5;$>kB z8bsll`4UUbYhkv718%sukDV2H+oLI0SJzkXgO=qQ+S*pRaFM$^s~JjLhVw|?1D znV8o8WB?nE^oGQMHAy)aK9Y1NQhzR~Dgpi31;XF25-!ZtyP{R)bFeM{j_C(PG236g z#&|LPJXFfiP-NIMVenI0Cx8uc9xw4yEu&Yp>^x~BCir1p!^yw$msUo^mKdU>7W@6x zjb(BL{K>4X7eY^QklzSnu&)4#MG&5=8ZMRdo{+GvuFkUb={}{RLfKmE41L&0ZIqZom_aNIKIQd?oMs6&;nJy8S)$l>PgEr6K=I zEA5dP@&mHh-&S}@2|X=CAy?TClxq2xeFw?W&7XQ3=aKPO)&AeS`H%;wVoQAEdEyh;^IY#)vGH!W9 zxLijrFHD~ucmI)dbycq{p6zk-ga*M!i1-h_~&5^)qF8PK_+p_jAp;Q++w9obwW6Qnc--%)bXq7%>F)DP8cG ze`=0w3E;iTL!>N__4Gsp{UNnnJ-d8gVb$IEF(zR3#n(1(MfNQ!5)Ma5LhIG5dG9h=Fw#Qv znW3X&RdaJkKyXCSrl_;j-SOjbSVgNY4)Ru??JCW3W7Ez99FO?KODF&*@h$AWQ~6P- z;r_tpgL}CPXy!_d=-AtRapK`&J3m@QgQ@(fzebv17z&1eb4N{`=hEM}BPySQ$A%4J z@m(p76wofnE5jr8U7m`4I=Qm^kShlQB_@_19u}MPpBwU94<8;`f$xOlD@saKhnDc& z@4nD|v}N=>7*4!z3?k&T@$~pPcek7{qZSV*dAHJ%qN}P}6zx0M|M9&UrKUPi$X=-O ztlFWi131sw)wxW!;SzX;ePNvv;16prpRsDItD{K~t8Z5H^mG-0>Q%bko~wK$X0Lo# z_fVRK`s(fVIr`!vuZ-+`p8O+^>+w%|^_aeQjn=d2dXdC}@+AEFoHn^$_hr`nJS!S{ z)(^7)peUW>?oAEw<0Y_o)mK$jZM5ncyaMfv5P1zqOsQ+%9b?5;j920wR5~K>IxU=3 z2#O6ya1nX#hX@M+?D>KXhV2axGtxO%^oZ$uxBN3U=GQ;9v#^*NDXlQf-EAPbowda2 z-(#_daeae`&e|Wj;BvLVIA#dED1aPjFjt;IVSm9^;{fBvy24%7)&Xjq1Fi{|M6Wnf z*o}S^e1E0v{PtgIMbJT0?Y6btwW|n)WSH%r7gjrbj9oG3fKUmNfi-f}EyEx4t>4cq zra->a<8XzG5&l#=W)shBr4WgX&_}K@F*^x1-NO(8rtFIhe(X* z^74I_csK*|4n0n2DU<)iT4&nv^5|~`S~)p1qb$>}-~3L}rarG{^u3n{swzsFpWc@& z<^6;fPgs8G-ZJ!V@!|DSqLO0wN{k6XD)I&`(*mQMj-u(09)7wzs@pzVI5XZ~z64-e zLqj8##~Tx*psAU$fKyXf2jusssc~I~_+R1aCZ8NlY3%}kSD24?u2S^JG3&QOY&jdbnfOwwE$W@RKuGOaxF%OPn@Q;${ zv4TB)pNIbu610-)BNR65Ht1iQQ?3w~hXYMaRE?%L@i~gk(Y!qRhKB?7NLDsBY{n98 zM)fZxx6+)MA3gxA4e)5sFt4<QwL=9-$e;8XxCqgMP-93f2|PlScmON4i0yU#*~v)a zmYK0^{NKg+GJ?H>nru8>r*pUH>*Gh=824FtAB51+&v(BJ4Y%7DFG`%7Db%`2eFe-a za%H`OE|?-NwOuCw%2EG36&?*2tl7E&?^-Q_#wK+(e2;)KgFEh)U^+kCbLvI_5Gp;a z4ooz(Hodl)g_Y+Qimbj$8Y@kq-zPsXsl~*)RaKKSGl9>1%D^rTPIPs4#Zy&%w%=%M z3ETq81oG5W+p%$lx%CGL%}LQQ-i$}&^FQp6L4a%g>X?Kp0`JtF2HSR^5s4okA)JH8 zs6#?r94f_FSjd-_Dw?72T;o=N9|rj0HomUY8G{J}7M76a=BH&bP1H|-OM9}twK6yg z2VzJguo*HkK<);Yb_P!IN=C8CkzN?0%C(-W@n#Vt&n+-Q zT++Fidds_pehv?=DuxLW$u}!b&&|;S2ma!qMAVv!D8sKN_7x{~>I9(!pN2f=SQLRx zDvLU=0ekW|gXmMi+z>sf0Ix#2cpWPhm%Cv~=`qb8rAR)1TVr`7Swp)J> zBls?aD@WrNS%3$ON!jE0fzf*7d@EyRMI(o*u(XymJkABHtVxf{T&m``{cQgRGErMf zLeo)NTx;nErqwoaT~Z+HAK8R&aYQhoh9>csw8|?VoTp~S6*ZOlrxt>KrTrQ#A|UkE z5uZc(WV*kX^d3JuR)bk(*AsWM+^*C zp4GzQJX{M}Utfbzu8^MIdA=R|Yq}#Uz*ms4QgRi~(HE;qtYBV3}8Pl1u4 zWIZ&jwYaE0dYtx+-fn4SLW#dU=x_29f(w8b2_WNB5}gwLpQM#1eVM((AQ?F7s>sPH z!R22?KY{??9w-(V2BDjdnbG?5xoHb=ym{hPl-{QR$H{$o-l(pY*7AfFQz@B;E700_ zL%zbKawt^xu{YXTVq+22etG7B{mE1;#1mvFj#Qn1YL5CWB_-kCy@u;xAPig0T0O~!9*gxxT~uq0V-L0D1>h>2r`5$`A`kcSUh>B-SSlmV@j-R z{)F%pT7(-^RA*h>9H^^OMX1eK6Dwpt+tMk$c!+>OeY8xWr|52;3zyBI=l?{J0OmGO zM+Nz9b3ld|+^X@EZ8k!PcZH0M9_3gd&cl-c5LHX~_|} zS8{rM@aCBH>hf_}4B@Aft+{Pvn=9uXCMI_Xf!pf&#l*4-+Pc=>)cBZAt4tW?qe!^pjzi-D9*vzDOI^K6gDLrR%*sNm>T@;K)=fzP9l} znV)fvd>Li4K;M3sl`RChhbn?tj93?qS&4d`XK%~?(;QcoYDt7-G^AwK+B9f~Wg@K@ zc09qMTwXFQd-h!Tjo2*HH9Mfh+)R$mvQmLYDHT*vncl1^Db(P29g!0?*Ezc^4G#_% z(e6yoMj4O&ehN7(L)Z7v*XN<7jQlP9Fo}OP%KLeD?1cpFKdEnRm9RtbD*3cC(cK0u zVsqTmRw}2`Z}j2$@?$0FU&wVCrBE=X2nPNAdKUD&d5zoc9Q^8$slKRL6r-Rh1%ohN z9S4Jjf}c9~H)H0<{NMTDSH>dM-+mGxwSPtVLgq&)uyFZxJUet6Uc}7nkCtc`RiCsw z9lwMmACm5Z`xk?#a)k&%kkz{8(e$zTYc`#{&N*~|Pegb-n`Ct~zM8y#hS?DqR$@*_dv@b&js?E|u&?E^l*r`&{nb7T;&AnJCw zd}$_n10jR|-@iH%@G{cUY64n@!^F4*$84v?F_+ZP*{@L-yP%1R9eLo;vB`}-T;b;0IiYp<&kTm8FY!mHS{WeCf%TxT3*&*IYL{E&i$9@s0vr+az?~(4|Uz z0p$+~ff^d&@q@M>>a6^>;`esnEREKMh<3EuND^>6Kq2GTW7to5R@S=eMbqRNq_wpJ zP5gmL7;O52iAZ`?9$#dqqJK>9^cXf2|@zQ^A(0D(tVgQlx zuplDu>K`ZPXFu*5KVfyX)~R%RRaZ3gTzcJ`lQFM>&t@vK#X~Y>oAsQ8ra;T*bHpe`v6zs7peQ$k?ky|;p++XpZ<*vSbyzq-OnA%T=C=VnZmT5HAV;& zn}!P;Lfz05D%!Csn*tmuFA!Uv;val9w61 zTn7BQfo#8%V%~f_0MFk1hWNuJmkv5O%JW22$xA+4#h$8rcr6sA!%) zn4e_l6i?313Oa5-)>ww4bQ1A7HD_n9v(qbj?88!th$Bb_n^tI3*cNHX1(GpXhn(^y zC{a#f8fv=kTsNDB!NFU!@mbz=M5=VEQaOb?JK(7PYKiT$gGX|pW_|t&|5R+(SCPRWExqA#k2-NZex1#?1BPrhR+HNBo|N5aJ98F zGc$&@kH(1Pl#t54t}ZTvy=2G0Zs@OURG5dmTrH9Q_+3#VVcSX#Zx{vz68gTen-Cc4 z9eP@Ebf{4PE8~O-_IYOxu6PR~+_oJY9~&5%^|9;&JqWC%ThwS`kz~6w;&Tj5b#yHC z^^LX5Eg1@ucTG5SJw$&=V49|+^yzMqyy0=%g&&`)*l_E3$wbI@bms=V<12J$_A&u}{?D z@A&2Wh1b*bA8QknWY5jmuY5h7%d)<|o^u8W8ni#T{qV~)ODbkdsJi&BSyBSi@jp1z z)Y`hfUf)|u7bM>0uK1P7Lt~n3VwSviaTmb8H_vIiVqv3iC}v!_JutA)(?e|&If4bg zrL)oFsMU>;>)dgD=5;l`zh>nFKp{u0Zi2s?RF(gPBC zoT{^}-1|0u!_gW&g85XPl-c1SnUkfKyb>73#F7IWEtkVAXNsX=Ch&G-QQ<*-oreNR z40Y;=;RT$I4)L4UKF-5ig>)`G4-NHRi`UE0Uu)YYXtr}I>U!JPyTt>A3n8`stArVUh zbl;)=v?ES$_bDvgFC}5p1qBV6N{WM-22xVY2#l%3*u>_nQ(P|AO4f|L%ZfN(9Q8xC zw&Gx=vML4nxPzTLL+2m4ZXBnAD~QYX?$=vT&?Q?W_PsN+b(fnLlcO?Tk#COUrqw?8 zz618a*gt>9B^~;HwR;J?Tp#snYko5_`<UKHGTzUFia7gQ4F3y~@uGl!?mTtlvw54- z)V*gC zCt%Tpu_xU0w`GTrK!SDf;1=A12Y0sw2<{r(9Xf;t0t5&i+#$HT1rP2t?(Xi;bMyV= zy{T94)qGX+&(w5v-|oIN_nx!QK6|gV_6}B7ltOz+@Dc<9p~*;#e*l4=Faj@GWCY+0 zZN-Ht2*jx>BQB!qp1i++q!A4xKsv?}#r*V)1GQQVn~28)Y=ZduMV7VcMaVO$6y-Ox zv^?PAO4Pl&00w7`qAxga2voI{i2^9PDcU6@N3AfAN1-oiDG`7Buqpa|eX7OOekbI? zvGi_oU>dXgGZ&Ff(^NTPUTu1eoSQr`k2{{=e^fMTYAo_pli?u`}?tr|u~jodR0+lK6L_^0irW*b-x`?~uPR z8AJv2cV=;1EJ=$S%E!ldg8OIg$Ac6_1qG>GlT^H(G>6}7v}tw1w`p1vt6sH$<&5N3VA<^lfDJd!D z!>K4Q^%fTweNR?RHA!b%e6B{bdPoI4JJTD96yAkjsZlW-nMJ&@NZEs{~W|q`eylv(0BS{8i>|)+XYrCgL$O)`YmB5BrS3 zq6Ja3-`^wn32*Q1NtjQUvrRifQ&VkmaW{8&3079*7OZ>^w5|d(Vou z94BaXDI$NHrRi5tfg`Rk3*W_c1fn@Po;%y8&&_Ji&CTT(&_n2)U0k5;4cQ$__VxGO z-I7qM;^N{{mVlL*UPnLhZ~b8djc_wl)7q*k>Nh@nD=T|zmFdOBOl#+w{L^0N7d_^w zd^lj%)`|+t!CjX{y+OZbTtR&5^tf$wuf=zcYY-FmK z$PqcHxK!gKx7_~h;NZaBm1XDRJ>cU+n8;R^mMAFiNK$QQXSGg~vMBv!i4)qQ^ip4Q z>nYI|8CMR&PoyGRYoe0Ri3g*6Z%)-R%1R1O-DdJrQty|V^nD)=%px@yr$$FtPp)C5 zOLb0p{6-yS!Qx-c8S?HJ=aG<~tb7;w(JQD#9ZgL9y6)+#U~xP=n#&m{%wT9+S!H&D z-M4wqeGLMV_?kCq%vI&(=vrObnqv_}?;4!U&yh%*BET<^&uK8#Hiz{)H%{Z2^fU9W z3=MvLuq(X@42)j#xza_T_ze%ld}IxAP7Amr`>u|b@m@LXsP#ij$O2A_0Et~Q@y_-( z85o(KzHgYvsQkJ&I!|?1dOky1TbnRJK5jt*4K2)sO;f=JpTyg?VVHm{I28TP`oXN} znYz@L7Jj%@_7-4Q!3%g*B6OSIX!#lI6a z#4rpYi*K>;hy#!Qik0veP`d>$sUU0ry#CtN9n7H@E6L!0AM7pCu>Mv^UD*?(JxmA> ze~g*fIJ0WGKUH>eVn1{r_qaYDh3S*->^+%paN&DPelwQC0K`FrcJA=9j0}fa)#$_8 zu*moBWf;A~4ASz_EnZiUx-5(xtI0*Zj3+;~AcA-LaFdF7cs1 zw|xg;9ekFs?(S8F@>j5|>|^b%y^AK&*w|FNzt7jDp2d$&j7t!>!2D>CPQCZR`3`$a zi(cIt+J+?gR*Kt%qItHU_Vo+B7b~&HgUy&P5k)bBO{}bJj4T;j!w9)Qeo6y^l2_nf zz6v7^4F-zSTnGH7Vcj(!)&xly$YeU!*HKYnU^?`uq-8bO8P8LCB|1bps37yM#(srO z1&hJWEo~2GM+OzAh!p7H6lxW|ef6rK=%>+$uB8ui?Q*%y0O4}!8Vc@fpV2X`pv&HD?ej1A_d|pKb;#}s2f^O8Zd<^)>K8MA(d-wKaA-s;$kZu+RmT!X&1Zlk3635MFbN$gjhtuR^mg~4%#0?t-#%$)xtf@oUTL+}=HyiOyziTx`bmtAeqOyNT5z<8f{q?5M7KX*&dqd@ zU77~V?0TZ9ITQJ6?4qU?rc?NiLqTC@ZFWX$Yf~?Hy3F)^`+X8uF{z-pyT$hNdZ(MM z)MK@%(o&c=JR;4_y^JVe!vY?kh2U3KbJBkQ=+@Wgb`;`qy55_}DdOJ5kOm>) z?C*46~n>y=5(0Fo}?B`^-!^>}AVv4Gx2#E>0CHxrwdq?kfM$Y_&HbVd2C? zbfc?XG>e;ybCp=aUade0_ghY8#`Sq-=1ADd!)mCHnOUyGi5FNj)oH=U=RSgz&(M-r zPOpcX%e6KjX9fiwLr4(F+&)q~W&_*50#LYYv{+bB-WsicjX8=a)@$CKc_|gBLfu~= z_0z)QX9Qs$O({u6aq;BTRG`~V-?yFd?~LqWxpGudNEjrF$Q@ZZ0LAp<`~aW-Okd1o<$*NqepfsOD=R4I*%9C|oUmp957 z)8`D=6#XHs`nHy}|G>4^Id}9NkCX%$1Ep14MCy#oY_{ zoFI!UPeg^MAy9|%yBp5xyQ>~r-}#t4OU+y9?qn@v!}K|D zat_no_2gtZD_BWf{0HF1Q4F`0U+j?Cd1z?3dA|0pU~6iRA0sKRPZiH$QR9gfS2S%s*Fu5Ryy=xA*n9ZUlH<`yFvcG&1B z7d!g`Zu8#mWK%)GE)Z7HFKsU_(A)zl4i8JVhE09$2Csni4ML~h+<4gC-28&n2n>&q z?MBGU90AYxvFBt-N1S(^FDg^@gUYM16lL-mmnFxI8b?VP@sL@jA_l3Ng)**e zmzcZUk&F)w5u@@>TyWUh=*?q~4K=Ysmr82GNVwU((wt`=zc_cs!din;X1EK9iS@u>lX=-h08*PA z-Kn=!t1C^57k>@<92uE0a43?ew>@!Juh^`^TwC{3TwO_BEf$*VLpKTI{@!ajHb;+H z((HW8hu}wM*vT;5rmo}dOPHdluAZ0vg2I7^h&oy(LpoRPXL-3yLrIm1D+cd{Xx^fd z+wL1M@}|$=NF@t{f&yBC2c|ZUrDcJx+c6FX5jsOOMSyFDx#J`b!iEb*$%~c5W0fhW zva<3iA~_T+iu|_@twP8rBc7+))u~XhZ$DTutpQU2dfWQ3&(Go3@ zy72$@V_$!8&B=`ozo6&yYyQ-0A(6Q}jmxn@OFI(YE*n#y?0LM}V*NU=DI3k&FJt!WFlx87naTw{+eP0dTcv)z=WbiT<*=PZ>Si?#dNem9{xr5?`Xda)+ZSu$LD>iF(TwyN2voQwXD|N?u4jS4VYX3CGn{Dl(8`vb>ZHs|@oVfG+Jrmp ziXL5VX2QyivtSECDK`{%&+}qkEOw2O-Y!mM@z1&6&-;HWwG&uAa}TU}s$&+2iTx`2 zTizCn&@E+QPKk)Fevhf-&yv{sDjCU*@h@I^Y)g|9ds+#63M6@-zWtEzwPy9YVhMoR zooVcMuy+(U1b)$2INB0=A;;&TCJ-=B{63Y8jbVOKQmC>|% z8Od%(B1B_#Rd$STw84(x<4{KpwQ7$jevwZd_(&LEjp3itW^MgpifoBL%GbTS;@mWe z#7sxniMPwNJgLx<wg#To`XrAIZP=Y_8|#Rx3fD4XSbK#Qk>v*0Tcm+?+fAnc>haSDbhho6RobQ$px) z;T^=sQ?M~DC`sY7`pSiNyel=ivw)Yw8^LP4!9}MVehQg4P95kZ+JPdgvDd09QeJs< zYXtpEsdH7K9oDfh1ARAjvAIX_sF%P6vqZRx&)pLCj1uV!h#;t3E)}h5zK7i`J-j6k zLnlkO9;nr)uiI=5lNZ2qs+tl>Y%M_vy|LF5?R&MOctMopL@$K6F#E78%WrfQd}f+^ z;!xN@YPxF2 zmL_qVyI1YGvYK%wr9GcATE3JUdA=B}Th{sj1%W;h@{)TrdRc)LOQQ3{0B{^uR$$My<5WU3~wH(&Zi58ncNL)0Snw`GlAi!3&$%hQGL zKJRZd)#Z)^JX0^YCns2GUH$EgX_<*EalYNt;~?{+OX>Mr&_%jihr8>pyp8CHtaD`! z4Wq$~{hhgsNhJmZ`7{JWTT6oGhAAtTAKO{Y4Y*Qd-#Iu1^(vFvR~60ksUED4e?5_A<(`To;Ei69det%cYD4{mCOp1U62Wup|9nI&a*rheI zRuO*YBKx2wk`b6eVq~uXfwkC~(3Xl+1xiooNd~}d9keyu`G_W2LRd8zCp*iEGRAxG zKxn32S?WM&&qwDOiwi6GsW+JvQSyqT6w2d4a)25HoCwkGyzAs@z3)>QX)XD z!X(9dq%(Bj0Sxk`AJ%^)%VSd!-E3}o_&hVMqpyVyO5ff|M{}m<-f(wVY%ahHfY^kpD}NlT zEsuhcX^BypK=4BcLu86P)O3>FxVbq8Cq{8uHuBB*e@l)`#Z?QGZ>q_3t=&hXKpN_d zg%V##iSl5&`cR2ad1b!QXTd|tBlWizlsabw6Vtfdc^3;i zq!YguW(+)!RLp2a1c5ZA=G+!mtz@JW8AHfuG0|-9P+H5$91cu$ZPLv|Ti9e`$#Dma`^`XL|pvY%#0(& zhA@ZoZh&I*(Yp&*MDz$eTi-{Ns736ZAElW=(#yz*D-CiwJp7Lxh!mv88bus_rvxz{ z@q_{!>Sj=2P=-E7e}iSNA4I>xS@iFXPwr-aR@^C>n0TkO8?Xk}JV@F2 zx$^1wm z>n&~f#1y?|605T|X7oh9fG}BDKdRv;b?ne4hqv!+L->gU{w}WiH~hIS7Wr*fDJQGv zWcpgViPn8)jN(RhzC?};yuZ*0-x=SsXosX5_b39$2f*<`5P`TVI3CB7KOn*gT%oaV zx>9IUL@Xd6Iita6I}h#^BNa?bdAK?@Tzq^K3HM)Uk1yGkKKeMabKZP%2j_?50oa6- zlarX=J-eiYMB!Te&He&p>r(f;NbV(CO5FGFs#;pi34emv;~H2}QgW&BitJ_!N?0Fn zY($}y%I|c({i2h$Hk-qHhu$17uYYFC?I2`mu=zFd1>F)dO?2-&2)x?l)3jHnUmx|`^N-$d8UsPrZ;wF$H&G_PcC+6RPGdR2tmST zn;w`lrfc14sHo>sp5K1(*_mn0?$p$91>fqWK0!h!LVuB9Z7!F@=_I12cCp&Uuz!#Y z*dT?Ep#nGMozr6g3f>dYTupb8X0z|vCawAGSMm}{EKIPzBIsA*RzQ z#i7a9?3+(On}fPk{L3fq@86fFl4J#9oP}%D)>q@4us;Pgd7oH**yix!GmnV$m64%C z(410K7#u{|WT~!oLVua;zBzDY!RDBdft82uiqGaYB)SsA$*?yDJrP0xO_eNwc^&9i z2Rqkn<_Ol-1iHICI-}k&EH=H;%<}MfPDPU!j*@C3V89yP8v_#n;`T8m`1bA&plZiA zHeq23GIx;tl9H3Nt0y4r_?Yv<1(eVRNJ7GeVdae7(#MPoae5XARxQKgpv~_uW%V8& zwf7GQz{c#nX3`$72njwxSvo6c6snN3@ z($u`EsZX%AwdL~Y%f3ulf%Zm6`ZFbEjfJPZd`ZF%oJ7H6F43w-_h@MrX7#z%VMK3q zGOsEvb=wbLh-c9i(cV?Xj2LwFBXBwjQ>`!Ni1c5`yDWYJu5oNM3GlKJBO%y1gcKw|ypHiL9n3#>i!D3P;2 zSUhv!u&tHmz673Hru}xhEmjed_fz^?=$x(10x3vYOUu@F3TY6Dm-p)vi%*{tQd5}| zsXy4;FYnKcKLOp`JbR~JaxjAx+F=;>4b|UYG&Cdx(5*+lNGsE>cXsk1_$}}32>xE= zymM6C&VC`>gh)@El3K!Cbuh}8qMQ62wakbWzb7IsWWIr%)&g}^GFL*k$>Jukn_4hU zUso3km&@(9ay+@1ZXg@;6dzIUcGlOIH(uMXNu~w`@qx%_ zEe5(3gvbw@92@dV6h#_Ae?SJfeLW4!(rT}w(g~MY2N$by5;hzv{^3=c^4kRY&bD}} z4xXISfP~)z-$X~bM>RcH6@=XFT9!FwU@xrf*y;>99rv2UB{jDt~EK!2N_tS5Q(6_cZc=-5` z%IkgggeNmgbb^(k*B_S4Zie;KImIzsN-9x`A5ee%zz1B9-z$yx~=AEi{p-L1!K!q+(1&MlM-43QpLk&&p7AK`RX>R-qutEdGoulnIQirLAeg$%%&cs;X@b;qDU0C*2upFR6gduJu7#8B86be}~k7^k;0y z?NcA8evGblbl`=bLZ`B6^I<5uQpRJq!C}VS$Q| z<9+KK$N|M56%@s2%L-B&7#w89m)A#e^6_boWrz<+KH1yt(!>cob^+>U6v^MYIXPov zW3TpLc!PK{dRHUfKTGwdZDHGqF)`Q|7cP{PwOi{t#Xo-zTr-`?-yU^H)m4|CcPr;7 z?oo2#;R3Po?2fcGO}EY>Rr~@X3up+ZXDEuu^c|#>%d@0g?t?^=M(;`y7N<2fnLpNvf#McD>^D#1&Bel5j|9zd;%HK z)WA+4B5jS3ryfpaH{PEHtvs6R>OKtj=4(^dGSFk14<*vie|*Kg_YBl|v{3IolUP=k zLxc`%Z|A4;D2P_4(w@Q_<^K;lC## z{ecqx;MI(a^;%1T7v%SG_bsIdHn2>)-MgzKkxHZu4LlZ{VZ znJpevn#0A1TfP<)TKV2=q>m70?Rj1wpR{zQRaU|!u>dUDUi!K{Pbu~0?wQtQB?FyD zSZ;8P%gO1Aenf`3zWBz5U5(UH_V`l93sTs4-mn<8{Nveh(e170>zQMedElwP4ZLVC z4;RwP+#pLWo0vQB;RdI>l8TD4gr)FMp;qj0s6ExamQ?%Q6$$m51KqoESq_mv*TZ>s z=dV4i+@%W+FDwYIAFe8+Mf1=q+*0^GHoJ=Y4?ZoIwlV`iAzecF!-u})8AH(L`S~Qu zz&j!#-!UKPQB!^B$i3o1vlk==a!lqGU+;w5;(b!E_HK1duigq~D=jZ?#-=SGc}w#q z=l5RlIRh>Z4vSvZeD5d|4=o4N0rqVlfL&K0XokCf4`P80>E>+b>%EmoSENij9K&N3 z`l6y^Ij&3d4C;@1^{aWQ0@bi0O+|`GToyftt3#iRS~HKEBt@0I+|7al%ZyiAz_(85 zdV2a>EYa?ao0JfZ+L;BP>8Ko(&=9%JL2X87gt(npK3DnAl_+8IAGK?&Bj=RWJp>}% zyEe^klV?!mG}*3^5TmR!XT+{ z#NfN%b3j76BQBogA|sODDs`eAMf0{RJ-(q zryidY(4Fnv{xKCC58CXR@N&WU*xkF;*M~4EaaO?LEKl*_$;I<7bXVuPv4F5XbW)ui zd*apk6GvWN0e$QyptZoYi{Yx{&*isswT%7ic0O1@5kF+2J1r|UBym79>Yyqz$u-NxXfO|(M~7^q69H@3y1l( z=R;VX9t008E7eF-G6MwD5ya!`QI(9D;>=8n_^!>&i>TWu(3E*7&rv;TtEs4=U&{ znjP)tf1h1kJO?2QtO8-4fz~}THPzwf6el?36uZ&~mLsQ5BH&r!{M42(t|FM0v#<*&S=Q;l9CyVXt z+lJei7%>2l0~S;-etC5vRwE;?pn%Kxwk1#~}t5WYj7SoVJ zm)M}=c_sJmq5du_y{Bqygh z*5i@t<8uBDtNB$<6d`+k#6&@>An$J#Rk|llU z4Yd{X=$iCtox*MYsQi(Q#AJ46b}`l1 z0v3dSXrO)7p4uO&VIUD|<>q6#cH)GQ+uU*i%>MN(x_!dykS?Q$A-&NLu#w~3idC7G zrCWOiV}HCESeowde28wzWdG0BRwYPuJ%+kj#hj3Ac?{r`xS+#mzorq;fRnPgEWTaZ!J;8QlX`iCDDz z+{Ml3*8H+MoARJ{dG}F2Ep_;CYsCy}8Mw(*PKt~M|InvhcT=8qhMq&Gomuu|_$^2=Z#ke4{ARu+-G)uuBlfk5(B_8=m@ z)c3vW&3z6r$gIQS2C{*g!uQ&MRifSvP~CrivdRbxp6K4Vu|v(<-XSBE)7W3AS_&F? z^y}FWdg>kF_sDSD=Ihw9LjblDi_rb0n;K)4PM?61UGdr)GC%nH z9o64Y;l|E>d!?CfSf=5#=L?ipEQFq_Vu_La9dzjx{#0S^Iy|D))Yb|4hiEJTeu?PK zi~&@^xky|rKIOFXl^@fPBw1O^=~pAE<%?Do7ucp3PR`X`ck2o!^_#JJVMMNc3su=Z z2jP;OO%pMP2B3b%W_vI3`t{Vmq~zX5dmi`lUH2~t5gj{Z3NiHH<7pxa8Hr%V0^1$V zeYnTg3m_oGV30r0`joBzkU2h7T(BIw?Yh)qeq^}|xqcIu8HD;-jR9qp;+OZ2v+=VT ze)Jxo$Q8xNlARk;Tja(RQb1)wqOJV3&442ejYpoE&BggI5!rs?pCa;`TQN?~0{U(5 z;(~Yyt>$l|?5g;vlby=Nd2wgog41;ey3HJ%SGrN>f84-lf83OLHlq8wTx|NEpSg6I z!XScL4+V%-a+<_#Ym?PU3OII0xet0L*`VSlfcJ5#f85Y-vJ{+ut>C3(b6qtDZlHGaz-vRdr;DN`L&eTb^ByAGXG<)@ z(hAQWR;J;oR524vdC9En^}`{fyyZ^a2->5;Yk`T6C+Ictj&w zQz$KI_Sqk}&=0pvy4u}(tI7l3(Mr_5`Bvw1J}@Yj=c#r6)}?BrrULpjG9OdKG3_nFcYq^qr9}n$Nu+G zak>59lq)k7$ILpON_wy+B_5>=G{rgNm!=yK?!%OJxnBH*rgdF*A0Y0tT7(h9hBfpB zkyNRGqHABzSR>w$UVLzUKdIF$&$}J<8o3G|RV4B&_1DfV$NJ(Z8`;9xN5xGYb&4Nh zgR&-*LmR8{szAB-FQncYqr!q45iRpf(T}X99{~i^Q?8B&ZgTr9OF2FH4Zap-Y$2_#i;YwP+Hu_!W7qPYRU4!GG%D%A1K`EhS%^sc3M!-RpK! zLgP`fpKvP?{I&@o~U5j@Y+d(dfpvCJMZ>qghtt4 z7nGFTY{dJ^Q>(D8`TrN<@lw=J*#7=n1^~4{e{9w#eOXOB7ShKHd{1hz|DJeop#3AU z$^pqW4JYN%w(ZNC2ogb{tMLiKlf-+@ouPxqzCKxVU%v33HB*z0zi`$T<;q-NZHRc+ z8N>|GoJOh?n*nw6n)PUGjIA^ITgS;cz6;rfI@Qz9gGpIaB{M*KHa)#wlSO@WmbSgJ zh1M)xRl)puIFIx8&mQSkKorY-k<#FG^+*d}7P(}0+G6y+5nX==Nd1|aMt~lRM!HE{ zZtG;lU=&y5dJx#zX+m8&X`BuD@FC>b1urmQJUQ^@4ymjA@ROC*Q_%Y6BGKFVt?QHM zLrU+hLEVYi!$0T=jtK>HiYUlpVP0M+byJ>RvjQPu(&2nPAg@5+hBCc-p?H;ZPQsTP zM3lxI|CL3Y{UrvUj`78$roO7S>B*Epd5-EnY^Qw9Vzgl9c4a6R$IM92oWO18AcwO0 zw9?c`b@oI>q|KOGDZzQAy-SS&_5{=&{=(ihBeK`BKaRI{iD}pZ0Crco*w9!X4Y%c(bY|HU1b5mwZ3VPU{EOCrK>kQ`US44>u1s#f!CPxRN)omUU~G=(p!A%7DV2P8ezkT>KKI+f z5iDa9`6}jsY#2@~^fSw!r|K0l6bjA8VTh}$eQ9J=!^`^)1X4_UJb1d`59~yE1Q{Y| zB$+sZNJh-encMd9+So#8evz;CsJe=EVv_FR_Ci5v_}AJCfJkB2kHt6V7Zo9b_#t{^ z?8KnsTbEDQV`{*35fJW2@FHXOz>&dPrFyylCPgn1zx2nKAO~&4;XVhE3AKKf^cr?K zzd1uNjJ;%E-e0YS6@kK=JVT|LjLds6F@RMKYC@q+&YhT5`7>h$`jXwGFtC9rH-#jJ7fni~!z+ZnkCeWnR6ftCDYjw7=D$$nMs zMkymB$0Nb!s;Vj--IS}tg@}$-YK24)sBGKZcjv=p)EgA+*`-6&=VH>KP0l7f1O^v- zD>2K>T^^{=1kGa&vAfKqLc7^Yf;SmXJ^)O`ba_Tq(h@| zRkat{^ZejO&#RqkgGVF%w6|`D^K$avu)?AE<+eZI;YI2?ROk$fq(!q4O zTIN7dBhnw)>8K~g6E2iiBbnDq2}TCUw5~kd0;szH)K53%3y=|4?0?8p2T&w1X8^rm zK;xr54^iSsvn`x*wp@_tuVyTkjR^)OPR>c&90-R!4^XZIf&S{gdgGLTgW-ztmwb_y z7A`8{llJ9biS2*RC5G{2oh!#|ty|C5;7o`JPtb$lQzg56LCVPF5@K0J* zmw~}oVss=X1+De%nHt2{>~nEP&cOJfLYR$>HwPM!QhA6{Gc(@(as?-XTKR6#eB7}A zBtak(!q+(e=OO&R{#SkU|HN|tgYW+T^Qj$z)DA}ju@1*__069y{J}>u5{lv_q6T07 E7YlO)VgLXD literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/stopwatch-dark.png b/testdata/snapshots/darwin/stopwatch-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..0808f83d343204f610a022d18eafffd9ed393854 GIT binary patch literal 13802 zcmeHtWl&sQv}K17=n&iqo)BCT92yDkmf-I0?hxGF8+UiN4(S3;zHB-sHc2;el|kmObYA z2mpYsMnYIX(KY=jGe&pd16M~-rhh&+aX2!zi^U z+1cANwJ_7WX|JdM%mU)&rGxw>4{f4(`<9o`LJHt|zF{P4%x>qBijUkH7`XVA%0mp1 z5Wzpz;Z}RDA|1r#rld4$C_z_CqJKU)sP`5D|8{zo#_i%tR#w~DdDY9BFVv-GW_DK8 zle7Nu1xSr8Nt@PLNkZVFs+_d*c=MzoCFRda5%y%Kp+BX^9FLPBdwYGZiGi74UJeiF zi4M4qvc$5Y8LT2~*ANI6qBedCcY8O-%A^~``l~jedI8~~A19Q}x z?0W@NZ~EY{;$I9a2C=cRaT(GbHdJ%{J5bJ@!o3%&8zHf80PSu)8W6q9lyefsO`f@m z=!eHsNr1e90;*13M0w)i0MuYBL~nyUozty<#h`K8R%K%Ul1a0j(*6x6_d;s~i9nJ| zkF_wHf0dLTlOhWkfa<6a*3gX6EM+nb7!e2zQ6#O;jqib(&p`?9L4) zk$m^He-7Hm67#lmP;kmC#J&f>{rWpNxh9eSR{tyhu;i)a`^PH;C!)VNw8%PdenrgxgNY zX#233;oAnet0$j=Ku*mYeQWj@bKm9h@$0jTXlRD;r(?`WQH{ETaPa(uabXd$_;Q!N zS)4e_B2?{mKMx2{sahEvHE-PZp`tqN*Gb(VkH9|>UjCjpNpw`vC$xZ37u_sEiH(Ft zNs1K-NKZcsY5TzHa)Yci+X?u+jhmm@CcL~5*=J4fY~Z2B;e1t$)|VBNMEOXnBqkQe zYF1ZoSt zEHPr?sDRQ#!j*=~^Tcj@y>X0tw8HO-Bp0~HKguZo5Qw(prp&$m0 z)6lqy5)n`T*$GXI&$B8E#i9BV86PKVJeHrGt!u&|%oBikAK1%K%i^O+CZy)(*6OeN z?wC_qW;NgYqN__v#wcH-qy7)88SafOhYmk+xgkW@tjG`P!ctvZnV2y)2xzd(@$h zl3tIcqZzzfadUkqc~jiC5|#b^LG7gn&l17VYmI-C@rs9UM!kH&0~nxdS`4u;Nk~nl zQNqE+#zp(cnY}+eeuzyqYm<~*Sh$rx(uJBkFx5@}%3q#V6%ZW`#M5HBG5FSJ&1|{Yf`9b{FTW0KljnL6)Q74cA5zxpkwPUiae4ZC)w)%lD zgEO;B*U->d2NEmr2}a+@PUmcb?Noaz;5`YlXB83Iu{9B6j^BF9ug@x6^ zh$K=;v69JF(1nGB4z1&h2uJ3O6%cz5fMMSo9zm% zNcbOmCwt$Mw#6u2j0`~ixr4Oi@6Lz`15+0DjDu6Pss@kpAC2aO5Nw{->CVyZFPjCV zloOMZ!r8CuDRu>ib=obTRoa;hzT#`-K^p2BatGTS)fP76iYOMs4i4ad^6ZF5AIadK z)_yX~$;s)gt)1#W?O|cIfw(IP%sHzLOG;iodG!i~L_(v@hzp%k<~o|{WyeQl-T8#l zx-vjMivuz2%E+$GVDmL@;@5i;&)$Y>{ zR9xMqDFxiNcsCual5hdoIK13mJ4AK{uf7l)J9n_vZJw9jv9V2Y5Zv^WF152Y?(5Zb z?f4s3FMP(uB--Or@+*>={5Bw$Ngj*3w?DlLA=!i<#WFH{i-;P7;v)QWd4=K;U^%y# zpcA5DsF*lr$jqe0$>=> z(v;B;pWU%Rai3hMtCQ0#or=v}FIMk_C_a^~k4GKOd(l|m z754RhL3hcM91-s?Et#bM(;E?S#cxNfp|fVoaqF!y(N7Utot9SmIxJN!-JgYLru7U0 z!*Ljuo3%98hu?$7_h+_8aKo(KYClTnO{Nt(#q%dF$0dLV7^shG{hKNKMT6sAezraS zdgE=;1A!e2BfTFUw(3p++JW!^QCU27W>V60;UP+j?S+-%=V{zDeCzU7R>Yy=TRbz` zPwywBMnbB_Ot7>bruyqvHg~28DozRUZ#fK^Qw4LXtBX^HkHq2s)l=8hM^VK5#OD60DKcZ3>=7M!0C!*sb9mXjcyvoHsYU|EXNF*_DCk zQ!P!n#sMD(RqoDy;IfuXcech zc*&%2dRk^d@QUk^Y>6DH*&-ptgw8IU-g^EeDI=iJCbJ=3(nx=b-}q7VfB^7&@cXIl z1tX^A%vc1JFt0J5AblgBQHuu+u&gZhP+U!7 zU*~hikhEb*37$qb<7XC+!Y0JjU!#$fKL{<2mmEQ(%bNDHVG*-4GjTavwOAq|#=5?w zPCi}fi?tk7MQiO16s}eph*wMZmZqkryrvgKysl;^7FqCb9V2}D=I0ijW$0YyG&9{NzXo|DYr97s~1Z$@h#S}S#PJ= zv@H8QJQ$DtqLRye{lf++x*+j)Go@qCMi>0+f%VIKST!odAMW3gE7s{R_#=k)x~8E< zzfSGi=8%QCZrfD^@+{g>F1gaRDDy-4M{Pap{EWN>I#S)~RwE4i+{2aqf32cWj(qVd zle>w}oBv&_S3c_9^52~BmWHyNzP*c=pu_@h!TtLFJ;sBa3@MikPa!8)QQ`2NoJB)s zW24RS$dZGzT+?x;b%jaON#lw&^mxf(#@a&@TIZwzEmcxP3Q<)+@0I}yce8Ev^Tv#f z9uep+ANb8kC09RnPVlo#@C?PHPXwD7Z{ht$t$uq10R6vrXrrlaJ3NilqBxg`eF$}f z?_aO>f^FuQw$AHyEKDoRl^Hx*hh{~q_*SKp-N`<(kkh#Lnp@59gB%eW(f;wN4Wys^ z={kM`&e=v8e$$r6R-ksqhWQB2b6aL9s`D3l+Ob`uEqYwYvfnQCD*)DW`Y!WDHToo7 z*5j4pls=pAT`tD^=z^?*9nb!7Z?cX7|G;ETdt^MZcqr$yi66W-r+J}8Zh4d*KekOu;g-h3wqP{RWP0omw)|8ygXF1fFVY3blb z3>Xut_v&9xIm$~`ut&KvA(W%%6Hcqd^0F95?8^GySHg9JcSpt`XSK&$^by_5cN1#yLbQX zm%wSpQ`o`ibuY6 zy5C@JcX3%}ua3MD$d-6?{wOJE+WYxK{6DA$>6sjp9#mS10{0ao@uS;xp&zqSzFL_T zXc92n9GbTFzSw?o=kR!x zq*qwJ%0k$YNKSQegIGk>d#YK*Py$qMMR&nr&4Mf|D|figQ|2_8=zuG?GUQ}rDu6lf zsqDLVHa>|0@ciCkwE^FA=NZWk9xW6lmv`|-HYVUZh3}QMuK3W~Eg*V)f*=8SP zrfDk>$n&SnD_2Y(cIIv9LqllGOB~lPVf-FK`mPkwBOOc2cPCA-qq?t<1^wNiEu$*5 zxW^l{pmF6yQqD^T2?Z?Fm*b@4{bAKNQKUX*r}IVyq8<{wn;}~@Y0Ar65N&Akl@zldCtSGZG9kd%)YOs^URd2+-`1Awk*p|0bJVk3i`O{d z&+0NUA?D92RyOR}(%K!WqqQ5>{`E7rI}f>I+!iE$o@W^?u=7A|q6KCgC84Hfk@?Aq zqx@ElRG$*VSku@$I*{rj*XgkA5mWTy)mOwGPlM0c=L-JrbqXsVo2*dQ8F^xxAZ?AI z;g|M&o^1L~X$P0nnR;*hxi=GgbmEjfEX=l}t8QhIMtq(JuH*Xznaoa1eE!UvUFf)F zohuxjBxef)1C1$UI58egsU-8%^Q>EQCQUH}KPw+TEtuA*vN~fK=<1%0RLL${vfoNJ zEst>x51!TNP2)56ue4JTle3ELBoYwH{ZO>a7*;t*CE^B! z9;{dCxnZevk5?cvz=*S}lGsFe9go6T+}Ze*f@gFdCO*mK%>J5R!S5F&{GV`-mwGM9 z4b81beC~OLr!&`og%oZ!RuMD(qH%V(M&GPtBv!HLQ7N!|eySJ`AyPRpng0r^;CL-iN?Qd>M_x(vRWF3`M z(%vA$j^VK!TI;=Hj#koZ$PAX|CF-?vaWRM{i_2Y*5&l8Z|3Y2(jXjw6c$U|oD0g%? z%2=EH7Yl4`koAuZ$(|UH;K2jj%I(;}iyG&7;m=D;gU*ZEjFvw=O2oG+)sWR5)SW(nu0|i|45PkpST{x7 zjr)if{V1DA*r;SgJB3z+gi|aBMos?Yn)u^;L&p}<6FaU{J;Ccl2@c^sp^p_8CiyXR zeR$y49S+PXC<#RhMDswuf4tYn7gfL(IP2&zq;x>@Fyw~fcOi~@w(%GXXx{{BA->G~ znG8a2T~_ru`teOroEkmg{;s5rI{@xi)y(E)T({hZi3hjAs1r9grR7{SS>i0)vpa|^ zV}D;YDIMCv8|U$;m9ZJ3k?2u1b{i?>o}rDT4>-dp1av;I@Yc=Ud+W*?4drVWf==&~ zNSrF(aP-}SJvLA*WLf{90abl8&3T9Ns50^szs+eex zOd=v`-0%fnMU8oJg#;K;;12?FjPQhE;0o`q@kmkP)2JR?`bRwe3VO?40MVm@#Poc+S1_{OrNWx%nwepS&7)A*Ebk{ zp9oi4afNOJ{2AtAmGek;FJ74Fc6(=~IIg(=37aq3ujz*Q z`Lyd{^2;~ry}ONMsA4)*G^;)-^`Nj-p4ZxNzSTZ}A?Rh*`oYG>&$RV&>H3f=th+8Q z-r0tjIYs6`84oS!{csl#i%b;k!eqyu)0&ZLU}tvT;>F?9&8&=E@gzSx5am4*%6t9C zz1D~RxbWm;iZApsGPTfShNYX9Uk=pHTGLB&>-#h)z_X@BOQq7KgEaS>U(;ASKMP*G zX#Tz?iN*8qtf5iHlByxlRdR<$mZ!H8>i9On!=pBrd-GVa4a)&qCg@sKUDRALBEu1T zPTA|?nIJ5ek|+Y5yQ)-`q=SsZh#+gg;}OiX;6@hXfjlq|-M#4qHF9*vFODJNE+^hw z_e00&>{Rdq_MqG?oY7Qd<^H(B(`e?oS($6B+U*r4;^3nK7n)0 zR)T+OcwJsH<>~Qr_b{rmGwe8VB_UNl>%C24oHL@C%kq@d8WxvEo|(I$;nX}At6}P$ z?k13&;EBvP{FJvlBtQq*0OEQON86aP`@Xpem1dLQq4KTA3eszk zrhf#*<Ri6v|}BGO-baQ_)FMp2!a)J2`W;yZ~$$t)@Mul z^2M$+;(vZt=xU4+Yu_&ZI{NNR28tmbL^b^HG;NbL64U#}aAv21aptB-tCTnSx7Wc} z_!HN{qI+}8)IMvApx#&X=7J&vqdvEasyap5=|dDw6J+iT_CK?)54+jeO6*Sd7ZyV~ zlPp^_e_^4Kv-wYC!tH;v{Q%&>piSH`wW*rkZ$KmYyDZfD$Z(LK_HJ79_bv^g68vO= z4)+UglkfD3e;8V8SM9<(xBGWcm(!k57%q24<5$Yz6(@jsVSc%1PZFu2J(u-qj(o`s z%3+dR8onR;lsPHAM$5~*K~b8Zuyj1dlD46rkpgWdh7{cr3AbL&6yW^`QQCY5eM9Ts__P()CgCt+ChhY;Ak{6XayY#csdN`gqD> z-og1qmVnQ4@X^5p7blUzdM)yioH=z=Uv1D3&1zg%h*^Br*=gs<6AUOY^Wv*O*E}!vqhD#tl@o8(ci!O=CIZg z8}G4kwfOS<5G3POmRowzyI%*)S=5^rMZ6or?q5VmUGD0}%a9cUnz5><@0Blk)OBk< z+$=W0bR+YfkBWc4o*LG>(fz2u-0+s3VG)=^>inf_mZ5H_H0|T^U7R6@v*LGK-z>Id zx{@-G%lSo1{RlAU_H%ctbdYo*{yML4-t5kDYX|Hs*13mBl*!%vAu*gF6__)UszN1) zf4HR^P3XZ`*DX|6>i}ypBNP-bFkfogeN5H+sZz1X%3?_?NbPJVC?j*6IC>aQ86-T4 zWR*yqD$VC+38||y*tl6)vyw3%Cl^C(o2ifJctqV^q4^GULpe`*+TmmzsBNr#sTkVq z`%<7Vxkj(k8X|c-wQJP3El<4_p3D;c@&Fot^W6j<@$MsX5b13}v7*dIZLPvfXWrXq z>Dmuh1a4Pb`yZ00n!Gy@c-aq+j&+l(DU!%Sa1Pm%loa_I(!PMb4m8aVw&{R5?j@tp z={%h*KDk(8a0Lf`rDoe?AJ^%JBvvsc;oaD{* z9ood9X=Y{-K>_h>{y@RS>uG`I3H(Pi(yrh^QEK$F^685Ywz0QJzd3LF(T&hP|Wm2>y1*>Nj&%pu+<~ zTM(dLjQVeKg32p0^htf)d(?z));O_qe>ieK`!Olg5)zJ$5!^LI>slBXv?4&4fEq^g z5)BRD&K|AUvJnel&YZR!5-NChCO^v6q!bFkOBJ+ZqZ?q2aW``@_|o76jk|erklKjF zg4jqc`J*4q545zr!+@`GgF?Ld?2n+w5*+sSZ#_l%%mM_9ruo9cW)80h~2@5Md(f%V{=CnERZp6@@HV~79{fpUv z@ig2gfTK7Qw^oVb(qfo0Ludoedzoo^sU*9XVoS^3ssmp_pH&{P`~KDa%n`WBuCmU& zLXWC8m4Lh8ul8gG$i=SG;5Bq`r5#SmN%{(moIfcT-d%+n_}Oia;4dmEDqXtGO&7Hf zH8rwxaEJj@QyZRI4-N=Vk`vfTa}T*%Rx?SQKM~rQ5u7Z+rAlX#;_RE++^#^J=jP^{ zERN0ojE+)c4=)eeYQ&y-nm-g}Rfw;4BnlSdn`}pDvkP{;Yzdc0OvQ-={0SgNdf+1P-BPrPH42a#!6GlsX`We#@K!%^8VS+TzC_#T(;tIX6sU> zR;yNXnK%1!>{fzd1e6iboKJs!kthTqQK3#yq%~RzyPN#=LIvZDhQe-QR~G*Mp5O~3 zIN(yPm`q4Y-mL$&)G0A-o}ni8x$V|?44--Mxkw1IJUG3M`4gWpxgTBe;Wo}tc8^K9Vs#>aUQUA1V zPmhA&FIZxETf6%sQnsjXJleQU6^!M=DsI#~jU_QMxO_kTW|}rewg?g%Pxn_1%z~eB z?UqwZxXzm|K&esBx*n`GWVWAbWkj`gSzgi1PHWSo@5AMNF&bF3 z9DG8aqioUp#b|amu8PCk<|{rA0?O89#pMSi48i+%x9EZvb6#|@GYZrR*#Od-=KAA~ z(f}O0B3UAQtcyQJq{0(JBOQiIE>k?LEZ%RMiKLcS3EtCfM7`7&Sv8yy{IuTAM?kz! zD{W~bz(bUhB58pW_+B3wSBv!ejN)x@LL@C_=oZ&tMSXiM-60jO^o|K>U+=54X<(Ov zkEzlx)aI3W{?AFopwnb-AC{mWjUrN@;Qr>8>BG;mS=lJmDlQOBVkBIq)7I$z>s^l9-o3jG^Atm_!$3l~ zahWu&{~Y8ViH17d;kCPw2>YwwkH3A2Me^Wm!l6iw=KJTct4Xm8>_wsbM}k#Rn5 ztdZ0C$+3*P2*Tpl3uJm#MEcDtqwQRl>=r$RR+thQkhMVtfzC|-6)zpq{(4(ZN06MT}EZ*0gKFM)Ufmo6|RNxm*-ZP6lG{ zI(Lo~HP*iJQJ4;r-5Nl$XlU72DXt0lW`-uaTAKWe+BEVc`}Stbn*6=2yq^6L`_-1d zGEH#w2QC2LZA{h92}o1Te(G6s^Sb*3y7!UTwx5p9kS%IpoJYRA@N{^>kCk6&e62>; z4_{ALZ*C|s&6fAFb23R(>S}GC+%97|&iv+%kP(D*idMZc+&AGRC1ttnH(bO#+Ft8B z&`(?j@@eZ*J}33RTCc|YsfIEY#?@xMF9PTTa_Ng5yXz|^Et+=6 z?&D-G^E36x=|UVfD{4=D$s?Vr_;?^va*D)Z{Y^~kwQ-Ksh7@MA?z`ZTnsX_>Z_ib) zvLH*bqPf|zt7t@}DnjGTF2Qa{NVApNxU1a=YDCw^)pD{(E1tkot&G z2Rw}v*R&giCTpCVSBUQnyOx-1hB;N5RTSx2_|Al|al_kwjFsIFoUs4yv-&>LI@}jA z+BO!SL!|_ASpSqY@Zsi`U}L>j2WVoUZqWaK+ehucxNIaU&@qiQn}q760SdXxD0GWv9T>WGQ^AG&??WbbcDl zQbf>?jJB+`$)vW&oB~sV`tRY@!+7$CH`zF}iLZ-L!0eVM8R#H4aP>5|>9D%19cf~u zv_^J(rqGDTR(lAaSh`P;_M#K4NP8%6qJHe(ovZITmx(G9j9yw?Zk@c3M6CQ7m|NQF zF$J$}=g95lW`x6cNE;o#|4yl_H1=;D30d2~W_Q6A~JPj?+`9zo3W=4%7Sj&5|}qrmwmLpB)FX zEYk-YSY7ivh9%EYseRAf)k>_KW-cl?!!`ekgUg)dH zF)cCtRg5p`EGZDj3i6|{$L{)$E)a9u^iB6Gf~DmIjAaJ}>&)?rQC z|9s_n`PPQ;H>xgT_1lFvM*wF4$d~xPW;%iBTu2Eg#E3_VlCnVm_CqW|hU`Y~U-T>+ zLmLjiA;Z7DpHT?9>zfF>b_v&ovkdjfYin5t#G*q@@%Y?ZfqwYL7QCZ#AE~})7lp`D zSp})rsL`kIVT1c>3Cw4!_~rb_=*L759v(Q)Qy#8$PdXY+u5smnITeS>CTkPC?oZgV z$iDrcNH3Ev9`+I4ftR;vNF*CqS?aG$fDJ&k!TWj7;zt$G+y35{nN>ey$TtI%GfIXx zOi!+E4u4J>8`+nuJly1*bugM2R;}R$i)%~W#}J`Yr^_P88}_O{06d}I#4?<<2&Pt9LGJf|Qdh$uh`m${t}>Pw${<|RHd z{5^hW%{UG(K%FpL9j`!BBIjdMz*T4L-rS0R>545}Jc;=1&FHt@Ull@`jOx*nASY=gC8JIf7hd<(K@VbdycP_qyS+M*P((Nx`~Od-Dt; zaDng4mc(x2b9r8)9G1gDtWMMf7P#t#h+wg#iSd%P_B26`h?3hBr(v4E&xdKf2H zkeQoNCIgQ!vv{iG6%uUcvv^)8yWF|sd_KDR#%YuJB0t`k56e|NFQPLd(}hR8>?wB! z5!=T0X3<1u#0x4FLh$MZI6f)!e8@x$6EhydNhFKj>vs?P4m5*QLGjaLQl9Q}s)tL> zVNE-KWj{`7MMSoy5<%RJ0OL71%DC@ChXgckd$peKN1JxBs#d=4T)K(|0dqKB*gJ}w z4NuyA)6;pva$i}*y6Sc$#k53%8W|G$yzeRf)OV*7gyz%bmj3o1;D$Zo!0HvKASZ4} z_1?v7FRh)-K-L+y-0kR5`W>Ch<%e+nO(rb(Z;L%Bw?cEuxMKX!$L%6gjkIuE)Ec$& zl+^v1?^`|~5(vy2(hwloIx<(Uk0;p9)4PlGz>T-Jf z6Kqx1<)Z;)VWO$Jnc@}AEE87unGkm~A$|KWanpm%eStW`UXID;EK2rwrwY{AQ3gkL z`sg7edYAX2OZ#zc;E}G0*BvHH%W~GW3IkM~F<$VNtMYuNQtj}-gsd|e|W3>+K~(I4UHOD%Nyxw)m$DbwDIsuulnEvce; zlXE`R%Qi1ZH>Ks)tCFXjh;V`&0fm%(M%(soEWth6b@abSXM}|ixh2q94Mocdm z#-nqd_Iuv?XZg&Q;R;?0H0*8o1(jb_~?tvbCo{U9h#X`$X^ zCgy>fn5?pK(zw~6U9Z6{Cr#K`n@cXYBz2fGZ}*AsUVU_b$fVTd$k-B-K{jT%KA zol|xDVT$?pK}40c6*3jd9K(j0)>vz5f59s9gSvm5ZmDcwNp4@rB?^=aOpMo;Kfiin zYmXm^E-3>$Hfd+4vM}#HhBUEDXc6;m-)r|LsVK8G)!&V0HaOq6!LDwFfZy<=*{NT< zTJ)D;FUo{Sk2j!6z zUX4vQ7Rrb9GE2Z{&JO+Uo%*ZF@JtSyLMv$JsiriKh=M|F4xE8EDIRZ|c*zV;ED;)P zxyP$}T#K9>5i*6HP2@R2oxMvLM=>U14CSa)DpBn65JC!fQJl z5JR4fb+;N+%(4a!4>*1|!`DI8tHYL$g3`~Utst=&^-Qj$|7~JW9+YE|Fhm_z`xP%E zJe=SCNl^nFHo%e~NoWgMO-P2F9aIe=Mh6uY!ge-Tm38FMnvkXc^<=!y%rZl<^+u;l zM^uq_03pX~QdvM7eA>?^rA?1%GW~ zOboa(;pL0IbbT&RqbeAeKTk2An;SPbHy)~V7EI_J24a~liZ>cbW*8n9pL&o*7j$y^ z5fJ0-zfpqpV%u|nDz_I^$guh7z^^Se_4KLG)q^a+-u}WC1e{UoE7%6+#G8x{r)|Lt za4tmC(v)RWOI9c+C#fW;C_kg)RjuITq@`ddJC7SL(9gXt$9zXqgpsbVgDLcZtqVNo z#JQgz8R^K~LDiE{`FaK-T~ejidF6>I?`#k>tL8c&Kb}GYwT__l+1$*mhQRzfw<1z{ z&XD%2cKh$-F@2-$tsOpUTL(LKth6XkH&=_YZlmiWK?6Qi|S^+g%2Z!t&RfQGR-FNab zP#AZ^-?q8(2r(uTd#wLJ(KIf<@`k!WB{D z0NxwbucHni>R*Uut<9}1HDJa1RdZtcnu4%xqKCAt?cM4&RUdJFg`cjBfb6e08HwNz zXlsO-t!j6}8`;?!oTk0n`%Wp={(Mtf20nz0k{fjI>aM7$)Th;&>vXw@+)&%lXkSfO-~?9F zP@9{XGoRN^Cnh$Q$)d$XauPc%Xf){*$WboSsjl(vDx6LuC2@Pu)O?bc3UAt-D4?cY ze?Z9z{a)c6usU^tWF{o^7xY1iR>@iRWO6gMdCeeqX`<-i6z3@q+iqj@Y`sT2i_2*z zf~KM(EK-Ay)?87f1qXajb#$D~-^ENlMG!Z>Jd};*vXlAsg0DiBXdZm0GV!#FmQk+%Rj-$AMMVgNdARq;XGez^Nbl&^>> zho5)OUUEvyb3Mx9%OxrwOW$kpzAucLq%C{6tzUV34ZoX#-zO4UGOaILQk37x(D%43 ze3=Z$$;ilF(gg_rp8v86YaC+@{@3?xerXz)=?8b(l&~&E7Iw@;iy<4B7xvtmt5dini=a58inO@Y{Q0)JY|2qiSEowPW d#~1++07UiQzR`Vqp898HBt&F|D+P7^{s(}=)^Pv; literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/stopwatch-light.png b/testdata/snapshots/darwin/stopwatch-light.png new file mode 100644 index 0000000000000000000000000000000000000000..b513e4c5f20964516565f42c2e8a3dfc210dc618 GIT binary patch literal 13224 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/timezone_select-dark.png b/testdata/snapshots/darwin/timezone_select-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..f226c091441ea469bf8932ef1f7216731844317d GIT binary patch literal 4974 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/week_picker-dark.png b/testdata/snapshots/darwin/week_picker-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..1221b30d45fa2e96fa0fc9e8e11d243ad16e3636 GIT binary patch literal 5021 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/week_picker-light.png b/testdata/snapshots/darwin/week_picker-light.png new file mode 100644 index 0000000000000000000000000000000000000000..74305e3375a3f27f2927002ea549253cfa03dfa8 GIT binary patch literal 4814 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/year_view-light.png b/testdata/snapshots/darwin/year_view-light.png new file mode 100644 index 0000000000000000000000000000000000000000..442d9b1aa05b60572c5c2bec1bd182dcf7255823 GIT binary patch literal 74500 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/radar_chart-dark.png b/testdata/snapshots/darwin/radar_chart-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..aa910f8b08b271df52eb607023263756ac7efb85 GIT binary patch literal 30389 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/radar_chart-light.png b/testdata/snapshots/darwin/radar_chart-light.png new file mode 100644 index 0000000000000000000000000000000000000000..3ce2f9753d34937b03bd241f71b51a23efa3e85a GIT binary patch literal 29501 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 H1ONX66Qs%w>$yP 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

    #8u}@+JLfL>r*%BVnuc>fD9hfJlrr6VO4s`;7Vu zeH^H4`ua09*mQahnJ{3ye6&K`BKjgkLs~rPR$v40UEwV)P1R!Ux!x8NUpybOPsd<$ zck2ZWY;j-zJQzWhXg(!uBgtd-JjH3C>8^On#$OMx%ib9puF!mPriH5`>0y#!cc5?Tfvyj!xpV35rl ztzY!?J~?}*Vl@(zBOSVtm)Ue;0QU}f-FlX%V3_THHeD?_elaF>9;tibVte5ux*Udc zblG_0qu(-2ZVlN|hp4BdrKKfi5I54RQYvfRe@h9CN~COdJAIBf(^9h;?)vEJ0Zma+ z*>j5LqIb6|KOWYoJwH5-*N9Khh(8n_sc4F8w97~g1!x5ST$Ln@L;hFf4>v^# zW&{kB^V)FnND|J}=;&$p-x}21rQIQKM{%_qVKp4EFXt``lgA<&=`Vc*d3%}r^cA(> z`*2lNwWw!N&mz%{>BI`vM`*7#n2LUSnH&4Hac)+mlrGuF_L%=@&YDuR>KJ!onyyu!s92f9ZkUdZ5|7i_Ps zV-RL9VrT2syl`7|3uyQ79Vw-YTKNHzP0qFTEH%FcZP!cL`;OkqN?Ay)7GG%|oWMXI z!*MjidyROS4su9>qU>Tgu#FvcPkiSX;(8Wtc2kQ8CnjSVTYP=F{viv8cgHoF5ff`Jl`Qa?1<%cPc}W+l-4Dmih~=B?p>6n8l>ce( z1oOPs>J!hb7Uh=-PpYLPvef%;Z0L{jM2%Nh*R=;U&r5`WfV1;ccfVn#$RO|!9(>-Y zm3Z0S)!Uvks9Vz53zz+`{T&-YR>Oo$&VZ)?{E_DJJ?s-4jB}GtB;jiUv^jV3h$P+; zQZi*^rh@JZjKZK^+oNtB*6jF#a*XBVuzSNI$-d~0eWh%R^cbj}+< z87us3M+{OwSdn&wiQt?B!r5zd2Q(FerHLcTCrA;8>65C#aCZWT{nS~+2PWN$zpW7nAb%#miFrKv^ z%#bD~R5FZD{z1U&{##B~AfSo`ItJ39drRALD7=4sN%-W`u$W;cVCWbRZF%u8Zf~au zp?-)qEAfs-xaMH^hXfW*Y4>KD_eoBY-6t@#NGGReMClq?fB`uHDzjERB( literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/calendar_heatmap-dark.png b/testdata/snapshots/darwin/calendar_heatmap-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..75a10e3e5cca93a0292968d600b8a8faf9e1efed GIT binary patch literal 18785 zcmd?QRdgiHt}bY1yUomYo0-{dW@c_PGjp5SZZk78Guv%uW@culTmA2S_PKY>yv)qQ zteKm!R#sM4WrRXfe3BxiFnL)qco=LLARr)k32|XXARrKRARu5cC=kFM&zy}kARq|} z31I^oN@!f&EsR>B<#_`IF_+sjMSCP6ls`|WIArT*3?8?xKNbIR#-d}T))4tt z@jBx<)m@~Jn6gB*d~^)K4i|%;x^(y6op@EN!7||r7CuS_DV90(IG^^6ge*9tx&t-2 z=GT#X^d8?EixdW~+q==g`JeCJN!jJkn+qx{^Yaz*qrB@IU;-`bD)m&Xcc%+D=Oi3_ z0G75KQ*t}PL}yZ%E-{FOate+k8AKyG27Y)&%NI;YP&LZEadPuxFVWIB(+=Lu!qt8} zU?Vd!28Q0kNV;W_6AK_Z+=ho88|(aznX1_w3$f_b)=3mDkRNq)h+tx~vbODJb{Q|p zm}+iqFJBS+0a%O>vKjc?j>3Qu)rJptCpQ~|F1BF9>1=p%d0zHywBuPcN|rwuTrFiED*YFT z@PR^oS>@)A5f1h#d~&K^*7;3$Fu_ z<=R0I`&!d5Z!DTm$?G`wS^X__!i3ntK9<+ZtjgBR!m_<`#w{A>teL!c`f{iR$d~x^ z__)KTv+L=$s7NneYqen$`=bC_&B7Y-^%)LlbpuvaRo7t3RozW@cr%`SmR`EX0<~PU z_Ft#_l?rS$Zo_wPSlGIi6+;QFgu1Glb_lvN-4r;gy3?$HdENd$sPN=n{69!t|v#UDho4e^@ zCUd;wA@dcdDH#JvAQsU$l)mV*>jadZJO{2#MNn&Dp-5&;S6SJiv8UOMTStBXZGZqh z9i^qYdH*_M;D0w?Bt*dg2zYE3GkSwzy~geT{^kEmR{;>YrD3(@@t}{;Fc!+gD>Ivs z*5TeBi9!84k#HJL*zk^U<@Z={Tv6fP{vINMrqjpETlun{E*)b`3=}kUy|`ScVFj-5 z(`rcdf^VM-i_qZCf>tjCFfiA!*^Cdeg2;!Manm1Z*f_>~qXS;QtPLFY$38rS4SaS` z#@U(DIBE9-Ds6ekCv2@PhrHSr7G-c$Y0|zd-+2pfW3qp*H(Rcaml8E!lKqTEiVv%u z@$GtNp=EB*uZO*h3jeT))(s&PSFoo%oQ~#O{hU0XHt!yYc~2Fy2AO&T^g98aiO*+9 zH5LEXQqodynbHO2%V(=Jzgl>AG@iz1+|g|6C{w7E#3GSxs* zf24dl77=ia*l&F*B7_hj#C@mr!kF%7?2lwM^+4MB-06?k+m2FHm_twjV4qVGf-1u= zl$X1qJv$CxzHg4l+ED%snD;lj_$i>vb`=$sG&gQMhnNyXr`48VU1>-w^lN|qY%UJY zFE4K{Lfl0al%S5DS*jM9@_Kk4iM2lw^z7JKCese0pQ>I~(al(@Ca9@iZ2JDZ!hpmP zkx9>6TGeo@IRHH{vc+Kgj`_yoMg(Or$)zQ^Ec4z0g8{7U-8aX%|-GV*D9dg>8%5 zg{X@xe$y+V2r1&bw|nyySy{Xjk5627wPfL`^}F)usDFGc-!l;hc zrj@m&YfXJA(!96xz7|bnk}>08hN1b5mX|+(498?2;fMyyvGhjg2Rd1VU>Xx2ff?6g zgZ8#|Q(4%Zwl>6vP?yCF_^V6Ai0|r=z2b$6;BvQe5>sHQ{Oh<&h2a@JA1MQ2|?H z150BAE+@L7IiqMjSfC6%0yJEXLg@-;E4jhmzQe${IniE5CMrx&dW4dUwa$8?rO=69 zDn72du7dmhzD7g-?saX7+~yWOGDmGg9`XeTG|aUr7A9(90zNn1*$JP`d^P?>}*#T z=RLa?z%tp8k!Ulsy<%(BXD+d&p99-YM{)w9=Z6-kCT z?;e&~3LPcNjqO-e*l4}?x*$q}j{fuaC^ZEf!u8TSbVutYDpP5TviAls&^Q$IZd+SM zc)Qz2^BR#KFkhN-*nrWiTgz6sT+8d2tvcL=C2_VIZAs_jSoJGhTX{Xnbm)LlFqo{g z#1s#n>&Qs2%|>`3wx-fhD+en}co(OSBvqn5FhpsGzaWMfB(oBVGYWC+`{3I?+P%pU z`k~1f#)RC&FqaEel6g+I(dYW^tOG>U;e<0JkR8p?s$B(47Mz$~8-A?WAA{URgqR_m zx|Fu^Bv7M225}=s6WKjK^svjklr>bGS-o+Tv#UBbO#37T)oDABv*eJ)QWy=V!^%`e~~f> zD`+iz$iKK!Pf54D3`YIBI)2*N;ElP(CwOt_uFwDYn0K;j@1@{lJdlx*lQI`Ez9#*G z#L{?OJ~%8+Z?<{&!09D%!nT(D`6~!Z>jHdxaU(F>_9Gg6y339ugJA2(#=t?#Q%v7} zMELXBD^m0uQ=LzTz0!uO3?Ypk$G4DvU?6M}82}#jHsQyOQkS1NdC33z`j%Y%8ub)A zvX8YA(`PCT4m1yQmcO-07e9vS^qT)ZR27Y25JpN(J~b5KN&f;o6;EAKDOCT6l(1NS z5So(7Iy62{%1TmR-|qP^8>Fq4e7rF=DTK+G}+tz z_Rhea$y7G4~58|Q0!0B33Cf`q(ye|%!1Y! z*xH4V0+d?&Z0`nYhtG~VdkjxH0kVWhXkkKV91EefMXYy1Iz2tX*%~-jLWYw35#)lLIH@(Yb`Bj)A?OWZ18> zz4qYLB-lmO$@K{c=nt|)ehIWQf(SgZf{(s}{4ZZEv5@qLxlMY6$xKdAGo!Iu&2A=# zNG#8uTK47!1FbXRXqTqJ;NVSsZ81-7LlP1#1adMqS*mzopfU@vG?gEXKXQtTO^1y@ zfHXDNYGfL7p8veT9*wuzJpknGYam%BO?QR!JzTdwsdlX!FwhUWZrfQa2?VM{YI1zV> zabpKE6SPHSgP;)dGXboo>4#|dAk}4}(@R_pX4V&YYBeL_VbXPZ8@SuRVWfggDZj@`+Ym??_>qz{JK8LuWW}F7rFq# zr!Kdwk+ayAAf5HK+A36hd^8)|zfGMJOpylV!LOF5Km^lggiq7dtf7Ude*UvxvM^St zXb!NG67JxK5M$_~4X#f3TprrX(=EPF2;-HGFK@Tl!ZIiYi7LM6-MXu z8M6nuXTJBdCI*)uHTjplNMal3edxfZHak;Tfnph^+=Zq*xs$!q4@BWo z-sZW{H0&($CjekgSO1bGb8l(Q3y6-&BSXpGPmf>83ksBoFmQP*o$AV61ZZ(5<_imzfHF}$JTJX9kWAa2mt>IUOj*rUoYZL2}HOne>dG`iJznJC9$_-E9d* z7$7p}Y_VZeP4fHfB;mc07{M*CZEx;swEs8-tY3Y`2KrQKE^@2aUHAGZIE^H9Lw~YY z=rf$Qwsryxw7X7Tz{50TcMpx!0LQ)bn-oCT0p<)qUx8w&fmze-DY6PYxABwT8AUgSXCy)9<#>GKhq$Cd_e z94b2=X|pSN_~~Y~-4cgO@}1$TR+}zHPEr?{k=&t|r@>Kl!?LuM;Oe70+jM%7|7W(a z%)}R`y~m2byHWs|MBywoyA8}4jxv=>e#yva-|ijn6~J@NeBaq+CSdnk`Jh4#58Q`j z79=AtHo4~?99!~Tsc|__d*iD>TU=sid#tR+UA_5i)y~8{VWCR<%1ug3?c{Pm;?mYr zR>bb~;7k-OEkp9can#h&EL7AwIN`p24t(nc{_G}Szq*o^lt}Nn+iZ6%S0|<{FJbDb zi%+;8|1E(MKj$2W00IQCh@OTQWuOGUIr0>;+1&;5RBNkizO8utyc~9-;)rQj_bOSN zS0#G2jV*dWJ&9-R>>`yf`yWq$NdiJuC)ZJ;tMcxfPG0JA@V?;9F#Jp%ofz2c>rUR7 zEFPR~ZlAG1vs7tSU6rV4Ra8F87eL_R-Pw5!_Wo2n^|9B;+NscB4e+r5E+TyzPBa20 zduUoTE;lgHGwtUlCiC2qDji9@1bkH9S9NLp=}yUOu>E9ou9E-iDtB}y-x5n;WX-k2 z$V|K`NnbzTX01vl*wP~2=OtL$%Z7wF6T4xxX4`K;vL%?a7~BX2y>^E?Dod~{+m-i| zULjBu&#r_A+Y^8@%6K%{jn$}HdXmHSz7aN2UADUs~aAB&8 z>@Zna811&7muuYo^BWvIslrS~j3P1<$3M)k9O;FLb%z#iQ{P0&gk&2PZ|jC3SiA=ApQWS(uLKw)C% zr~4dwcXbZ-^?_cWt>iC*Y4c2-ja4oMX;5zfOEza18H5B8^YHC^0)&o%U>+sNXGxF~ zsS35L);c>X?n8xt^~1aU(N$7b(QEX>+Q~K!1Ofs?Vb}9Q;vdx@{q#;2<3JCroI2@} zh1lOw&zXZ1ITca8UdOxZ8AsF4d_IS=ow#shXkv359bcu2+Rr|+FI|nw|NI*B))mlS zp5F%bbj`=ZVLYNczON`zE-SA7W|rw?59$FogeqCM+bt)xl~N^ZZA2eQuTnOn zF+Y=zBp7AFi0Krj&Qx~Fvi3)qx4OE}IOP%Yg0g?dZcsGX!^7hN9zLIxnOPANo zjEZi3BYG{!u7G;J#PIETQ=wADCTHj3WK@%6H2yoQW0vO#vBQ+Kl~gVHd-3BjQWYwd zW?@A#RAn|OF>9j@TAgEz7K2-5ws?^r^VGwMF#1w=D}me?O30tVu_2XMU1iqq)tfzH zG$gp6Tk?2z==0wMccGoAE<}=oU#?~DQ@vHNVhF83RZB3wuCP+Cw#N%*6y!_0C2{-m z=3Wpcr`A-9d-ZtgGF!nDg)cqtI1obeV@F&L(epX$E|aQKcozDmF$;5ES%{x&Maif^ zia&WtzG*RgsjNNgb^67qi$3%F3ZZ>;N`iWe?!?CdJajY5s}xS!KNADcKpFX&*17^a zLFG$&ryoY3lOTtr9m9%3ZG4AsLZWaV7%Ptp5fxt*$*fPD*{zkb0o^~1!ttT+K63ev zjw37D3#|^BeW2ne3_6FKs&)4PwowS`)Au}6%L;V~YiOwcvC7a;?18t-&-$E|?GNL# zAdJLZ1DdtDqd!0!w>Bd(AmUAmVw zKc4k38K?<@_WwsR#D5aM|9Q}B-@soHdbl1E%fGk|OwM$E6Z?w&#shtYh5-k@P>D6M zoZoMVttEi4g{gv930(BONW%`mq*)_wo^zDqXR^;_>PA^yQ<_A}NlEP`yWn zYk(5$#%9|KId5`x$K7Z5n52}hhyGc4b@xs79{FOGjfd5TTK3wbqN3t#k*%+#wPSq0 ze)p{B#ln*7<2Qsxp4*4hveB*g9W(*NMHY6x)|+%KpDx-_p}(>kHS@dT(?=QDPuL$B zp^Rb#Y}EIK(c%W8yLaWIW)5>>P0}Rz zikTS=$fEbyA-32d_HVLjPea5Ql?Me(6HmD&HXUou814v z-M>2P7jf%}-LZla)9s-UA$O1oW{wCV>sv1TM;R094ri_Fgdl>br9?K0(1u6R(rx1L z{?W)Be`eSiBaV7f;?Zn;*uO`FO{xX4au(l=b)C{Es7jlR%W%$hs+{G3jiz4(Pg&ub zQ3#x=5C>Dq_IMu&fNu0OC>1#+Wa;lYtfLBnkQD2`a^UetRAC`=MRa@2-i!NFgT$CJ zG>~IyNxT*A4fzr>GH52B{T%imS5CH_jI2}a)imoS*zPV*v;6q7eYKyoHS>uisK%(p zrJRL*Oi>a9y|Z>UE!n7d``n=<978fo(=EStyveB zD$Q-Yc9yy$*zUoTC4cP@GWH1!7rE8Mf9n(cD?EH_@g%Dh6!^OqXgJxU@N2=R!qd_4 zVYHoFi(-oK#)ZjYwA^}!lc3A2V?WaW^e~?GfByLN#!O>T>qu4{6DzMy`}oO?M>4%* zSLc^r#Oxd_?Cn!WJ3nsn!vQ_t`}XR6LqojjnM0D%ks423MOGUq8^?an|M6#mv1_+@XSi8J#TB_{Rw&6 zPfBkGB3v)L*PL&i?#f;%XmlxIxi-kS|Amwx6%~iO=i~_Fg2B`WZIaFA-~csoBTXOK z69(vU@Lb=~ERLaJ=hADY6!op6V+b#aSPb6RBnpmYh6 zFk&Epwj!0M3-7C*@U+wJ4@28G@*yw*3OcIssfn=Lzi1kimlH@wwSkv8S$Oc-Gr@c` zIac?6@-n$N{lX!5@I9XQTY|;f7%X!RlR8ndkFVmmUO|%0rH(!%G$L239_szYBk-Cg{=eK6m z))fr}#SVX|?*LTTutQXPy$Hfm8gV07FSz~PB=Zy>U-W0YlC{)cDLyppsUgX|uL z{jbiHj|rK!jo<;j03OoDRAi@R`P5(NXe3=tj%z<%W4yjX0>YrKwby4ge2;7Sx7aqc z#;3(arzbDf#s-5u_AWNI%dhMFn0y{@eGaHZJH$Fl{PX>Q8pMWPl2j!eWKx_%;eH+) zga9R}q?M)z(>fYk-49HS2E7n^)b>F-v_X#n~rKf-f&6LyI!Q2LEUX(-ws{ErB6cZs%oCAs?1BodZAUuS=91UfodXIH5BNu`avA7VJ?0xb1yAZl(9!+BjA8dr~aw})habvPBrWz&( z>o{gPpX*Nih8|UnS7LH{y~%-toZ;L-`BFj_1a}WbAmlcoLT5ut4m>kgMA$XMs7A&w zoD^a2j1$#8=m^RyC~LO0)-5`lwVT|py>_9H#Kd28x@~nndr4VJ^6_{-QTsscewXNK zN>2x4Wexx=^8t-)54?09-=tIdP2fO+Yv8AAZMUwgko$f)yPn39Lp3Ws`_W zQ^is(5kUS3NBNUV+JvxOQ3O#YGZTJ-eOpZ^HF2iO9E^E*feS};UcL=|{7_fx56_?a6{W2r8b>q|NrLS5+KBj0lXWy9 zm)k9bJjWRl3$*S+%^})9a7>&YB^8f5Q8E5DpTM0gxW`8l3(a z19c@(5(X`wE=t6MjEk@v5@5#XH&*5`p27Ve7NApY^SZ0Ir4jgZ=m7JBz_Y)lh`6l9Mt>eg-WNWGxkeFj$~iUavsK z4lXCXlLSi;vku&e5v&cSPV5MX6Vx{@Q`jDXicv@;;GI}AJ48zku}N4RWSJdl3?Z%+ z4_@RS0(#)l|MUh5xnqnEI?!)t$`uHi$-Gg9WjMT{!3^jWbv>0X7@7r&B)Khj&MJJb z;Zp?4Sq<5*I{M?K_a0b2wKqjGj9{V0;YjzS8k&1Wjb>O6#|dv zaQJ@J$c~L^sMq>!aek3;5Pd2;Ju9opbBaB(wiG3z2vyGQDPQN#WCBx*A+7f7;3)ca z?-tEQWS6xsLj8ndqURw4tJBjNz1WRr)@F){mqeNlYd(X17WvFuUBrkXh$N-sc9oB-nR zN`c03Z2LzYNX9nL6e_4T&TIeyxgwAL;QWa7#l->I&}g(OMMSTKh0RU3g#KX8J>>w3 zN2S1D0O;CfhT?8->vADj_uQ7Zk$voIbxfkk_)?p2HfB`M8tgHTgvt@MJkoM zCPb$UqLC!zYWEK^IGrYS3~a+y|>25m~&0|V9~fU+cLH)7NE$jMk^*sbWI zxVTr|W}}(k719!MRSWYzukNKZV?s>K#uBm;&>4%aT)5bDkqS!C$A9t0sr+Wv0pK(IeHiW;IW>{H%_v#~s=LQ5lKd z&WDLSz_Z84$0gBe5=tl`UVyb$4boghavx`gHSoFJH#pr=kSFMk=>|rVxtT-UwH~<1!FZmSz{%N}S$k zg@1m;x3za}Z0OsBDE#$mm^z-{Yo)g#KPoFn4}4FLp}zK<0Z&393p8y*{EZXk!;~=t z|F5-0?7*)&S62arOjF#Rt@@zdK-o2N>d_Jix3!VT5vG>i7|fz0lzS8+aw$7=e7^mc{Vxn zywSC1BsRdOo*#d?+f2G|K4|08``qb0W?+ON{y%68Oh}SRpK&)E7KNJmv%;5g#>cf1% z{zLb*u4JG?>-oMEy^*QObT9G}2zYDrc-VLB#I!8?%&fGcIO;yzG*e8`O8J7~q8aC^ zJLbB$`Lydv3u4iN1v3Ce$6QN*(MO;qcJTK85XbTV~_LQD@A8xEIhkPIa$7&Sy)KP$7$fdqUY-pRxq`fhwBe*F~}>DQiDY;=r1v< zNEkWU!3%+|by3%5(5{lm3AroOLT8;PH$U0&I%#AKj-A*loJeOYOOWIuS%Yl~ZPmhX z{VIO8K-G)dEm!bj4X+mEKT*qv3F;^tzn*S8mv~b47K*>ofh8h!oH&*2|9n%rcNtpN zvpj3#KSz;02LEh^G3^xz-l1t3mT&QFv7=azevuW@m-rr6naL_Kok#375nDw!l3m8N66_g~uX{+OTXg3d!8y0q+O2t#`=w`0^ zmZBLSCq4$=&o@pt=0`)2g=*yY&kK~f3-mkV$=v>_cKRbUeBuX;^y*V zc5-gZk2ZR*W&Rx1QVq7_v=pA(TgFytQ79zY&u$oqfIfLl1T80WZ&gf~mF;)Y$oJ?S zz^%~bir6iGjg+tVb6>Q{$iqXSg{cBxpM{6q9lUS0o$ISfHC9-@Lu~sMo`pq=>+6D0 z5({UXUui9RTiRw!A9sQzMEh$hXga)|qIcf~#Ye;U-#g%0O?8VgApTwZfGLN#Sv&`L z!385^9+aEFO>Q(l_~CJ9>&yS9Y(7$*{Z;#+7tL(jwct>w!;!m`Lhswty-n|*A?jD+ z9ne`{ZxQ656*S6?19+Rewzpuxa!;ddGxaVf2Te3--ppseqxY7fWaBa1=-t<-m@GXd zXzdsk5`$qLGPklY*WUTF+|%Q=_q=fmkFV}&M&}(bUYwL5YSqR!JaWCGm5w@|oA?ha zql67XVPR3l>-uPZ_q%(+2W$=Ge^HNtC@U>nN8@=fSMB8FEEZfQb)`YCRbAopbD^vH z{8LtCU?JMFFU%H@{z<0%_2|JuWRpAQcK z^gUjAj~}FoOG>Zn)*QTZi?(5wee-yO)AR1Q_?XPaA%T3nm?0zMdnzY!Li%@2%#JA} zQMMEn{M*SdTwa&=0sd?bWu1rjdj6l7MV)t=`6sjEm0AEwrSLbLbBtn!&UiJnj^yz=_?|69vwzxW=^2}! zd#<_Nd?ui6xxG>b30`74e(wCC^sok4x3=bR37uHMn7vLTMM{0l>?twGKz+&TiG8of@l;JqQD`ddzQP}q^We1BF)nI%!bGb z#Ogm%u#wQf$puj{OTfzV;Dkduj5|V+mK{IPQfI z{x>Y1`hTltZ0BCUjPVVFPB!}9?DcH?os|I-&h{HS*<5H=iiUlXbsLl9V@HGPg6_7foy6=$+x|o+V-xCbj3q1ZfBRLjPcQzsd^VdaW^x0 zyI%wmd8Y&{8KV<(7S2w=#Hdf@_svh78imRLbPG0MXjjfifO4gyHB?%N4?prQ75cF&> zuCzA2g z-Zndxsy9gDQz9=nb{{{R+Diz{_4mKc$sQfDvzWhod83YzJf3quo49efN8K(=TRP8x zzdCkJczt^cOeq;>K81`*`{t9zRBAYjZM^Cy6i^)uMfCP`-sWB0R@UZH#*A{@Y$x&u znJnJ@e)}{31dFzEii|hIFw@q&)^zOO?uq$DWWo6Xgv1FYMst3-AJ**FQtSV7^*4McXY&=V{!9gqZ0TTt9aN@vc z4^Jwz+q5=M4O3Vv>xyP8bvY=F?Sow9;V=T9OM0~$=@^gZqM4W$|^3NuoJ zC#&nT{mlXt6x1;*H8&TKStk?8b2}P!i-M&g=;!Swjz~mm-Z-m4H8M$UWj0$O6`Ck1 z>;%t5H}Nv2R#s*yb`+{iIu7{F#$17F|B#27Euzue@b>!pnqQeS7y^Qu&6{hfwUt%RAVO5I_HBEcq*y zG8mY!g0kB$LT+%)oM|?xCsylOE86Mvcz08#)Md6g5IMc6yN<7~E6yZtW_H)h^?iU_ zU|?bHZoRT=7h6);n5a3O^c?{K7QRrH|2t!@#F}*Xq-`vRSZ%%@1)@ntNk+Zjh`sc;%vd&b7)4)3BfnF=fHt8b5hB4 zD!bin;L>hdOWxT!bHHHX1itK6(iNCVi$?F9ACO%6^Ox`9T|AQDNgZix*?nK4C918^ ztm3NBf(o5|-0#vSSRPN{5Y0sTnl}?8T z9?`v%sOE0ZXIWkN9|6!ud>)4b4?aN(E-FP_{KLwE@_URpJyvbHyoNf5i$hmNIKz5% z^O3NSm=6lI#8H*PFi=R+Z}`fp3L=+Lh|zmxw=jY7A}Ud$Yq;px;fP#L=Wemu8oC;p zL{edKlC9d&@)SI7_bCe|%xRjRp8cy7r43D8emwZOqERj{I5@bnV!yh-cv}tR`KNdl zGB>ZAy&+FrJ{D=sDJ4LFzv45r>jxZ;bZ@Hgv>?A7ldB~m;4c&O*9d^VE|lW{?ktte zK!8IGCl)$^XC31ZuzTPBxsrR&EQ`9a*rcSAi2trL+8&z~S72jRrp6wP$J$ZOXvmPt zvTEY#>sc!pglK@9@ojDV{?h1@)2^hfsH!~L`^lHzg(DLLcx%V5U@VTLPgp^bGG^$F z)UhGBX`bj3$*!cJnx)3SqKF6q5acB65x|YNr}b!W^k$PPM~5s##G` zgiarLJ??ZpzSzfrq7MY&^L@#4mk5Ax;Ml)5n>X7S7@nV%yxPpwBK~fWKV#ISjwmQw ztTa~tXEvD67&^-V#7ler#1weBB=~e?qDmt@6}l zU(1Qx0UsXSHX6?A?MIX-tifIl1(gd=I(=d!!y#Ghr}2Gg!;c`rtB1tU{t+d%_+qQZ zl~sBNfT0oAZ|06eh7ghZ4zN_%*7fp)KhGCz;%cc8@Ojx>O%}hby~XmaKOc+ZUz%Z0 zHh=|xArhWzKs9n@J~_s}W}pRmWJwi#GGIn>brNZlIwa@*0{Z%$lLL^=4l$rcn0Lyl zC0S(y^`yz_i-K61#lUP3cCJWyVP4nOciBBYDTotJG`>xu{;5ZQ>L}=KE`BonjJd` zq{}q;$l-$5?fJTPPa*(vGBuXfRdn&PQ?FIKN{6#m#G%lYpe=eUFP)DWQ-&?wdm&gR zaO}>xcgJZKXXbcE2n7P+`D=p{O@&p7EE;FGK5&il0m9Huo-lo4&>pv+K|y?2W-oK} z6uTHDo6X!`TSc`(zEZt|P$+4a8&4QYr!|WJ8MnpaB(HgEYi8CX`^Ex&BvCcpdv|#T zpbCwfZ^MjxowAVu@tdVWDVmyI+^VS9Ow5j_H}S>3onEW}WL-OiSBCVEOC2x>f`FWJ zcI!KFLPy<{k&=xJ3-8Eqy^HM}eeU{s9&X7FYlFIei9(S4@xGrJfw4|YWzLTi>=|em zgLsMbxX#-rn@d596Gw)Vl!c9h$7(8S65q5kze=T+Xk1VfiOWVxM&+S4 zQ7L6zLE!K0Z8g2r?whEEdvqqO^xhO)gtZf=WxQzn{9vi}XAMk4L;Ry3fxkCws>>?V zQ#o1r*i6LJte$^6c|?#maPhw6j0Q69USFS=PPL8=8!u$8ZAC>zD<`S}_+yXT%#EA4 z(72+M4OkGJhK5bH?v}UDj81r24_fO7#A-AzUh_Vnc*cn;R&16oE+*o3*UThYn~jF) z9K;!$p&YmfJH+@+sfKwZ*;p?uI_t&>YAS}9qP)F~)Q%Q*@;P-CAg-+m2M47iVc%g? z(pR*VwCJTIDHIrglq{UMTz$X{-7Jjh>es7Bs-XkAm*?60M7%`)yTUhze(08pLN=#NA+31lES&&48QwKV5HaM+@2 zBTfuW?%)X-I#XGiZgF%)5IkNQQ!7Ni@n2zn@$remz9{y5RCtmVMVL@;c4+P2DFJNO zC8bYhbT>HM_;-6<^K(RRQMBl&(-c#a-SsVWfYVQ`*XeJZ!l#cotG^aPV+hEY`Lx(x-z=a!V4Ff87Egeg($rheTl(neudsutg6l|~R^;s_=4zW%`2 z$@~1|as5hDOYUesnP98eP|!q2#S~u>Fgg2pE1uMGb2&ej*c%*HF;@QmB#BBAY+|L^ z4AEcX;k@@mE=Ll`w^4u9co5NSXjP>TF?krB@*>B`>%(@e2;LSr(*s*Hc?(fBKj7sX-ifcKW9X1n?+^&oWvbG-d zNpE^^c$T%A^x6}il%B5{SQiE*x1b* z657W*C1ZpJpMtJ>*tBR&C-p|tm`(;N%mGf2npjuB386HkKG!pMaln3FK8v8>*N11o zgn@kvZu-P#>F>1&%f{7X5T=iJH(Byat7cp=KH<}&BRejxkK5jKEA$9^;OV~~LwgFY zWnKZbSY2WIDZi#{nbZHrB)65`o^jmfLiIAU-FL4ZeOa(G#;iMaYiUN7zMgn;;@n@` z#DNv^nY{M_FMQ9)#_sL<-Yy@uy0=iCaen^h+w(KdDL(kT`_+GS-utU93(vf`X>4@= z#*Wrsf=82kCBI)vHE-U$`perJaWQ(QpD#*~IQIPa%(MOlr|y2&di?v)cI|l?8yH&{ z6di6X7I1R<*Io4XRO(94PWS%*e?Gt5Tq4QB!g54j7%2Zky&*tG?p=u$ubOZy10y5j z$9C4|<+8kt7nK)YeOdJ=RY6hlzw+d-?qO`4An-HY8(1~5aDZ#5QHrFH_;0HKJraV$ q*lC8~AxQZ{xzM5i4U!M-*%)Fvb}zfSNqrjw5O})!xvXKqhR4GmRWde3Clf0akb(fWV-(NLj^6Ru8+ z&Ny#5gC>P*#onk}{N*&rGfYe-J?E3vkFxq`YIF$(8mPp%e2U`G&;CqYX7T~Msp>|t z6s!$X7Z)B*2i%i@1N`hK!AZQmi3L+(DB{3ZjoktrFk+<7{~J^Ud?y z;hKh4zIbp&$&EuI;BlLjV6h%#Lp}iZ_WP5A2fZ!8M2H|jwI_tQKC4DL4$UNVh9X!t z+Q-FE2Uu7&JJf94cuC#hQY(T)8RanSU09 z>#Q8cCv}?;Vc)JJr=vD{|9|Zk%1eFB1xKTb>** zn}0WR{aA>D>+lV91^jkQA5UsBilG}lbyOX#HRCl67@l$}Dk{&Hg<>{2L9VT{iAFNC{{CB)SR&>uUfw;$72DgL zMM8lOjz-LW&O^MLO%N--)d}0C{w|h`!_8on>Fo%T(p-A=+!3Ts}QQeK}=)6^>z(x1;^u|a2 z769(om#1_mCrq9RJW)vxi?rcC?O)7z_!<&(qfDLk|`Yh42%>pGl} z(x~ySX$*fAzJ~QO`#e9_0K9Ty2}xywf&dSM5Hrbw2s!;IF)oCGTvYy|H!6tN$fvHXMwErEPEbt49f zP}>Kg)$p=c_5~iI*Tv?><_6^_RuLvrh`-Hi#{?9iE;x8xR+g^bCbzGz027?n{(CJF z#PJDGaVSyS7763~7b1v%7w)}OLCT`L9=4s@{08Lpje;V#w+UkOZjZq$Hk^)VjB8T z59(Q&+opTd-eBBJuF@GL5!0XES@6kMDR}?jk?WD>J}y3kQqPAdH+D<8Z|YE4VASX% z51T&OLSzs%0hjfu$R9i(5g%_PJPa${-JcZdsvKkXbol@dSGE1ST_TPj$uDJSsb*LUMG*#DPWWEDG`)Q5|CX2>KeM-xLJIr<2?sH*%xJ0 z6;zDWUF+WIxFZF#$L@tbT`s@cs|8cSmtqkX6p zC2OQD`^h7_nEhI5y;)875KaL)>)KZ&tiK1I2NVRK>+6ee9j{CbI_$TALSVc<#XN62 z58kF9gFVs26`}fL&KS_dvp*&eeNsCgqJLXh=~IO-Y?RAMDb&p6Yx-6U8>bC?JcG-9 zC;hEd;?m$kyI9^gdq#^U4w66xeMQnQKj&{N(+dVqZDY-;R{Iybt$BGMM}iMQBFsW` zm9`s1IhhhEvHKv|sn_5-AGa^#%%cO`Uh{AFx0$r-y*V!iP5{?>TWA+6wd>uH4Mi#w zbhsV2hG+qvCeaso?L$5%=noskt-oRuep1RRQH9@!dyO(AR%o_a7M6BHh!AtSHK}d7 z&zm!ai|@?r%mln39JI%Y=6t_I0Sjyd&k+ZI12u*tI)1VH?(B6`PFNu~P94=hieCZL?;sswxE}0*r*<9k6zQuyoO<5zDH-O+D%Ms^a7H=> z>1|q|^%oKPtdLlTg+?>sL>($*+gX}BIyh-`T5`L((ABimq{d0E5R6f$+4p(^0qf(rbC5~ z+Q2uN`LMYe4?#1_gN)gr{c`90@S7^_#xXj(Yx7EUaNd#~s2>*|7O|~&xcP#9VtzVh z*^q%Wq24vwwmiL1V{_OTSsrPHzPO^bI$ramK;g4*_c@8uB_t?bQ})mbh3jn};fO`Cw<#6(nEL29~xCbQae4RbZqG?nvc zp!|^_O19_42BZAsh}E>YoD7~y_j&a;O6DyY-`vBFC)u#z+-x_ylk9j`dAYSGe1K=9 z@xx?8!%zf#dBn;h8!-b`{M|UDT}!qH~*HfXZ$o{*o$&eK`}{o3aqQgiGBptu znE&tl1=n&_>y^e5jU{c@61cK>f6Y&s@{=CqA=}+t&*zFAx-nkQ<0q%*yTSHXq)@@z z`nL7}J3$Cx8@H8-Y=JKK;~g8`rYN`=(8Bz1M|9e)YeJF-of!EKf!op9Y*JsoexaZs z&*E_%IVsWQauc4TUuieGIhmU$7bge7o-CkHx5}<^J=%ch@~ z{U4qVy9-givR!?9Vhz&#rFiT`B2%rAF6BZCCkgW`C1Wfc8R0&6%W7?IplHVG0TS>8 z=1)|kUOsI;!!qOj>YX*_d2Rc#Zm`S*A6sI!DjPNlq54YESK1;eFdAS>N zrOIY;0cC$<+II5CZ z4OvQL=};I$)sb*8N|kB6S_##M(}Ttx!W@{dn5_|bNom0q8Y3KaC!i6a8EEL9-7g09 ze4oh|@T$$F-IcjOOZJ|3l*x2wdtK18ItQA8#M)TF0cgq}*xq5t-2|h&t%gAPa1Z?zOF< zl%c(X;hwMCJ~lZu)G4^u=$p0K%zRk2#5c3%NNnYDTBnoOF*1>`a4_w&h6Fhr3!H^E zOq-U@+P4$QZkqhV%lc&L9<@c5PYou?BV++6)+2UdaYnQQ6ATk#Bn~va{1J_Z)`L5U zOEdL*m121dXC7XNS%~mb!9-Bkm$yVHVFz+e5dKBUMPek-K_XWq@xKBBdS5S}IIA|b zTOBQoe0ERmI(4r_!}i0?6f)3V!m6+I#hf8H2%H@o?a-6qq&@pPdL#@ay+S}fdVM)c z+=LkF`u>U|`6m&`jlr~h_PU;!XzWuEQ4&!!n66D6eO!DxXeR8m8!%_X$e;zSv3TB+ zq1O6i2v811T7<(g_5?f3p5qlu^Eq#2?bIzYNE#u^W0?^mgoNlHqB z9C9S3D4fDq*RmveqXAAZ0URQ{B=~e$3hUgwdCM?}T=^p2OfMcAQB7^b4Aru?!7RX* zi4CKg+Ts=c^8EVz`1<)dzuhjh>8{ER9WyhX{QiMyz$bYTrJk@nO1w;bjZfuQZ7Q%g zFcxepmFsQV>)KtUCl<-khY(WG@x;WrRa4c?lms;Mr{F9;*`!5Ax+%pDAvDmIyq zI%(MxHY(dGRJDb)1q6U&gpi?xF~N~S<<1@#E0^k;F|NG5wjx1vL#XEwczOKsO~#mm z>cI#$NEfC;lU}cAy~ADTWh!5Y43eOae8}2eU+2DuJUKh+!(Y-301p5~+0atZ5TE^c zW7-Dl4?qr#7;5L_pw+p5#zmpB7dBdofpAeCJ-kF#%saJ{UXET$CayXR%Acqy-Ogy- zZ@U`{n*bZP7(3FkVWoe*-&=oHjvi##48*{>njcGSKY>C;N+lpw+^yWlR3(ZK$*E^+ z2=(gY)m`$-w$U5TuLV{D1NR_!GUaoWbiMDy0ZD>c(4YiNfudxvWVMz`*&GCkK^muy zpl8lBD2M{Zf0k@G4l&INYn+2_(bM{3igSF>q{vkXI^D4HA+LvNgIx28^AzzV9Sv`F z0H0ubZBTq)W}+7L)yT!9L8LNegrr^E8Udsan3xz^Hr`XGchU0EAd3b0kv7q`jPeesh%(J2wAK66bzVVN!PS^!B{soFI!JSN@mr zA3W-su|I~WMp_s3S&u+52ZJj_Oy55sa3@1KUK@5=Vg+??vfVIzW`%|jVd88KR-4^i zj3N34>NspfIhczBj-tyxY0jjYpo$eGAy}B5*c+mDUAq_E7%d~HtyH2c9mMis-D&+T zxI?7}dVB8Ds*j`wWHcVHd&d_FM$7~tuU#8zgev31qEet_FxtxmSI2!8my6P%$xnt| zT3K%Dw7hg}Z|rOg@{h4oNNqh|#iv1Juxzhmvz}vzFm5squZ3jVS*Gu5p;#i3r%00k z`GAi$2c?g7V9%ZG+nldjQXo2`An=@DQ;F;bZW@S~f;>Pzu)eeTyv0aJ1cic)ij9UR zMue0^r|0;%8DfAH9Tw9Kt7-LWW!4y%7r&ci)|4UWBk*A@kSZcCCDVQ1^Yrw>4x7%X z+kAAim(oBzN^x=fhbbdA;k%+{4Ur+;v)@~}ddJRV&Mtd94xt_)Vb@Dz)bgaKmnY~k zX!nAQgk}fCTHIPrA*8;{!S#nHfeMMyTQl2@PHaX)qkhKlF2|?v`D%TGxgH$f@r`w_ z5;mHU(HgiXQX`U4nUTeEy#UPmnuT&Lr?XX~S4#mup`n!wlV}X3p|XWanlaij!StB^ zGRktlALU7cT@0$^(Rf_f4{qzj|#5 zKZzD7v2vP%I)U9EDBQCy4|ek3Z+j7JSfTABv^0rV)Q54R@_#n`jP*at6YJl^!b?@cxT|>{@oCbibnW zio?ckt(S@Kht5WT7}1zFjOI5)g6#;@86 z9sn(RW%KV>T_2&8OG**}-TG5`y8=P@6i7qHFk!Oq^J@!^zA}o5niP_<2eZ&({sAGY z?ekJ==vQ5$lRoe^J6iOuitzVL2A};7&i+Kg+`%5ox>xFC3bvbxcR7pEF(1P%LCSSA z$>#pjN!4ZOB&b`cdvp9!6yYIxlL)TVXU?K#fim4cNb5WLTztk38gzC6j&PCVy_oY7 zI~`fGQxsi+3Gg5(sTK0p$uo08opSL>81Cy^?_MLCN|baky$Uunab7@e(oX4Sk=a!R zMumt8^-q#e2>}|6HQ%WgSC{w8EXh8UJXO0AP$mb5&9gZHGMO_U;u2&l^-ZxI9ijm?XoXJd zB5Qql-Dx7i+w_2Pp^YfyOBo!d!q;IM3&T286`+e-slV9R~ zqFYsGdKW#b+quiuAJ7$$P4H%~BY)ef@e!uftN)A*%toWq)~3OrpAij)bsj2uY0eKTF#birqK$;BW;l&vY-0iiqZR~5CCXJR&!W6tKA79IWLu8g!q$cy6BF3%DAH9l$>L^u5t5%P85piS|x>@Fz0a10jU+8=nqS6x)X6# z5>ayDE#UX@E)$&0XbKLLrgx7r552l;nS`_ZaDPHxfOliU!hKeyW|gG2C2}+uu4~hs zb0W)vxAD7udanwtt3GszBkxo6ltR>(pk#U1E8Vs{5pCjwO3#u~=c_xm_-#$z$@^B1 z?B+}oj)}UatD#g~t2p-f91V6`XTMX^R-e0(`Gbz}L3si#O>NIz1v|KRUnXZJw&%N} zK|*ius~Ak|U~Eso5zx#HH4I{NEE}Ki^uD=YrstZF1mVr-s6nO*nh)+DR3SPorY?Pu zb-N<#uZtEk!E!_w@b4xsrcRc+yS6;MjwplHPq#v%=5p%Hq!-%;>z6gV6H>>}e&b28 zSYG^gUoKgwSkz9e8-|b*5|9%aC`6vnlEcL#Zu6TDXf*Rf;9xNS zepMyvr6!DpqY&j{F$W9p4>e}0*%E7JM>hNiC8ZapLG>3Ygku~_UHO&fihBFn!WAhhl zhnxaLF^ScEEj00|lT1n9!nRP)FU_i=ilVa0peCYJa!*Jd`N;U{u(7#5tpXEN~`6j9uxernVi$0}1&(@ZVzkhro=e%u+c&UQJ)( z&nbOf{0&lu!-huz9j_yVy4w#2jZLB#h~wgiUm4+GdN1>0t;iacF0}Q02KDx-t2rAsCa7-N+THs!X?-Xlv}>Nx zS($Z98+r;)YyhvX{GEsm>#tUbVVBA*$cCj^tU-KUG?T=F`VuUNKVe!&HyS+H>!(k| zMf*RK6rM8Jnh+9=vWd~gkRjmX* zkq9;}9G(`CGD9fl_IG~UeTGD}9MW^@yTKUE0=zwM^e^$C$M&_?fdL6;3eV@3*%)qXV~Uwn|5W%&|F?f%xi^jl8NL8>&jJKv}gz-Gu*6C=}QE!UdHR)@XJTX$IKrY zKYbt^aIUu`X!(m@h~Hnz5#@Uq8)A|r!V2XJRi0N4T5(K{30V={zPdacv#zEeVjAmt z?b++w>u7su%$l!o?DGxnH>~-pC;G0TlRc>h6#K?i>x5hsPWuTjmE8CcCYsziUPBe+ zu){&?$Z!N88Sc6Q3+9+tm`Ij?vILT*OYJ71H|K^`v(NFc@EKNBcU`VxVg*AtLfQe` zy(|olmpjdzI3R2nr%@#p1l=@`vR3icl$Fb?D!g31u!1$T;@uZ@1HW}$)0de-^ zu}_kun=q2DTxGjfo3JL(u!u0j93lMJn+a}L-!Us;uq$2E^4wfJ<*8(_Y}CX5YK#1W zL>P|M+SF&YxNxNLmoy{6z6I5Vd;FzArpT^&!5j17ItTcu7JfYih#NEMv;V$&Wf-2f;!Cnk(@(hgR0b&!k zc7tI^26yP{uv?%xMVouox?+tFGG(iKF@oAJxWyHZ#>MfMzH_u1hpdh$$%$Ld`2VL? z&uSc;cXf={o{e^SabM8gEa+`Gw&=Wpzj>IYrZ3t>dkfUIv}jyZTnH|9g>2S!Hu~;g zCmuQ17Zy@15oqh^(w}mR$o_*|P}dCUL0M;%u+mbRoY>K*sHl+i)iKkylh@)&E zN?sL3EVs~V$P04HqTWEvu|)#+w>{2~If6(4H&mt}HBq|Ct^{SeB?;XlH*B~w4#;X> zu_SO;Pvh_t{`BYS8nZ#>bmIle*L;hUD{-hX7ppCy5NTfP{2kAz>7OxiRvr$^90Uy+ zLfUHq7n?B-EDvAhB8Qd?h83#GpD6$gI*Ov?B4EqXNs#US2bzJhuyTPr;40z~NkmS@ zW-8tz(gr=<+e2R_DTmRhNn|qHRQH)U@UR)c`VDubKce@8$;9wkQb67y3GveIH}C^T zTGNf)6EIiZYc5(W70FK6(mL^$7mP1~Dj*DZ9_RHzusz;4L|H zyeh|-Y7$=~#*s-~eOc_Rib+_8iCwP3ikHuz?Y}({^=lm%L|P;`3l52TPj7YQ}p;WXb{QLB3Qk_XYPR zw?}pp=J-n%pM@wv)`is#f44EVY|?+4VNQ+0kGA(;UZlfXeT0{89gB(W=vCjToGU)k z77tAb$MRVc!Fq+adW5e%%>@ED#)ihs0z(wXUZK{6$WMCVI8{h7egL72YSe#|+XH8v z!m6U(cy)16cXZCrpK>YZzc`sfVxe#QZ4-I$vt38GnT}90t=LaFrK(QwYtvu!yMpGkM6_)>+hkc>bh(yBbWLM`+Knd zSn(BGRBu?29w{8cmjKc3K;*2~%e~+M_`uktb^7!s>*%VtBGO@4WGGOgk?Cu-#8P{m z$Kr;L%%Oyg4Cz zFm~!w1_m?y2!cKa4aa+tbB7$v2 z)g7zS!_?*TvRX{;C6Z`y_sfBdMbWa<=NQ+7r_yDZUn_mrD`_^8JgSa*r_7vg|!Nn9LSoGf?EZ zL9r3n6db?kFMbU$h92ZLBUNkuJ&2*N-x#6HOI^!q__IA+fh7~p;%9}~Cf^vMs(QI>-GgH)>BCn@}@ zA>ADH!|V28&6U|N7erAsQt$6%SFZ-#c>I z8YvCrm{ggm;dB#>WDKE@U@bbGh0k%8h+Sj;OoF8S82j~5h-SmMEf-d3tV?r|EOSZR zZMs_t<}jvQ*gJlneBWarPp*Xc35o~7@7#YA>|Mv@w39`+0S^wi#76imJps-d9B_n+VED;TOJ(RL`Lk!|34#A6+wSlj}*<{Ug z)5$7gy%!B%386yFHqlyeKt9M`eg|i;NBz~6KlZV6_DG{pYjHScassIyo5&otmUzz| z=JxuRSC6~ubd8<99ka)g5_znQ$-0|yWa5RSfwAUnJdSq8I_s@QlrcdRqD^+|@{aj} zq}=IGswe&oUh#ycT-EGq6BKHDKgS|!YezY>EJq^8K#`cy*Z6Hmvb5M<^xx{TL*;|f z_IfV@MYG(mtC!04G_u%A_3|?CNA-3QaL1vkf0z$1kH^C z{fX*aox9FWf0En2^A1Qji6^x zAQRY++5ZM%&%_L!Id~)5wN5l(F`I6*J7+6m2v+2qiHZp* z-P*P;z|Bkz)iZWBlP!@L+=R!37q|-IobLeaTx?yT;usb}t^!x6352awR2@Y&=yyit zRpF$M1H2Hw`r^grD$!xI0S@2S*0j%8R>DWZDR&h_P;-`3mmjl*)V^*e1(P&I@H1Z7 z$JV0g{dga%sLMsE9K>sD@ja<8%+foF|8NW$lC8l3)5tWt{j7gi;;F;a0Ojz!sg zQd8kxl~??gRDR7?{{Asab`6LXh=hm<9Di_V(^xPF^-V_nY{NNAc`Oqh4G- z?WVQ|+xyVA{oMQ_NU%i$0_b=!(J@ikk6RGL#l-(#KKOs=}SwGXG9OT^pg_1S{198M{1Y>wi|}@b0(lQxnM? zoDU5CNkYY3O@7oWyg)*tUXCfdfL23fZC8KW>0zy4VbSg4LVEJxCCfK?!6(4%b2EHF z9Rd#ZiI@l?@Fx<|XAvQ&|H_x1Z%`hLHwIO`m!5nCF}&AADO*+E`&WyA?sgZ0Wozy0 z7QXH}HLT!m=tpV|C5OVm4H1IzHO>vD=Cg^dJS+ssSh^9VGY^F<1v}yghGRHUqiA%Q zOK(DiWYV~NUh7yRmybg~6Q9K5vV)w{21^%~fdA;lU20T}OB$@R z&ul$l)i;Ongd=_4^{i=7q9Lyy?4O*vybFv)r>Z_afi(^AcZd*34v}Bnjbdm$ljqTi z8O7iMFh35~7(!2S(yqvkI=2#(9Ybf@rU?--aWfy^d0P0%o>2G*Y<^ti^_D5Nc?CXx|##zo<(OlH&5;id+P*7bKRR$5qhUq=W3IFBG)$(JlYrsxL6#Zec` zR*;~C2_yixm<1FSbsVgoRaY-o>Mbj7Q=w6iQFz~^+tr#VZa$#{>0c{%d1sAgho(Xg@(Xv} zC9TQty%+@qiGlafp8e4YbS3@Gdr>O_zhdJOh&FElBH#@B|!9`o?t zFC^gx=QS#jNhv+dCC$3H7HcA&uwj-LQf{B4Qm4+$Bn3FXVN=sGo-R03l2Z~J^e%$(5f-`@S+9p^)i&C3enyJ=lZPJcO`WEN#vEco1Ze0y3jf(&PwVRWYlx z?@h%D**tH(guYwX&EZP@l8J=ViQf}w_IvVzCJ1@gZQWYgI*v~%TKz$LZ(M_F7{+ZH zIx~Y;&rPv{38yE&eEw84ON|m{PAtD~6Fqpoecgf1HCj{*~()j^PLpqLaszHNR$q4Qfyew$Yp}>7fk?z+Q2*!8|GzBYaw0i9 zJwLU+FxFzt9()^Q;^Ql~R9ZfFZS3vHZL4d0IMi*tQ;4Gezyww!)F2y@_DOIhMqS>9 z%@#Q-w3JFz7{tiRu)QxW%}=vG|6-$0Yuj8miIL?m%s5={9-G7R<-|i61SM|ERcVo# z;hfG#*vtBP4tQ-*(3@!HXxLYuM@6dUX;09styc1`o_&D!bGIco>t~UWasU-1a*~xU!E-GdfWze*s z#|~z7b)}8BO)E_++S}eZkheEFebKfw(XvvIlb>~6@K1K=3E{$`x1LdhdftM>)$Ai4 zLWrCYDuPiDpXgX@zH+X$lBcJq#Gu5*-o>6h*HiLM%e(gckNMgu69NJPqp!Q=@tIgy zXvNk_niUJ`y4Ew5WF)oA*8N}lCpEJiTGpx)4JzR#o&_G z!9)6m+JmT$i%LVkA@qk^vk+CvF8`oyQ$$36DMjMu=dQqWXsg8v7jgrvgSBNRG3Vpg zg2zDjjly5!LW)JPizD24@`jE(&+w;VL%%t{jTZ2)^XH6;{6AaZ&JwM+1}nJrcZu;A9Xv8t~lF#qSwrBNWx6K0002r?Wa=8N@h=B zIvIxExE8G%F_CpT-ML*wt&NrUjI9o&cH_0;v?8OpUyhg0GORzy-%%Ol&G4DvwO?Ni z;TQ`m3+1a7swoV|AH&#jA`5~FJTrZ_dxF}OT!SP7Q5DrBla=XwDggx8=*QK(+R&MI zJ!Y7Vz;>GgmO0RLgy7 zjusCO=nqW>@>~wN^n9_nYJOs!gpG3RPCXC67{2Q(6UEr_Voay!m9#D`C5c6g@@mC6S3>vd5N)f5 zF&ox0-roLxq61Sv=sj??ExO6JK89z7hXuh@?2WUuyn4*E4xU+bu}WL7PbVQW{``E` zXSWRZY}xMN>!G*lzA-!kg6c+zvu<a<~zY zPIDvhQ!s?=kWFq?dxg!$DThre!j2KTAX=HKR~#8TkfzC_q^gPwq5Y*ks+I3aJTsPtVVC@}D={+&a4m zS)&g3GBRE#;%|m;_$V#mR~|S!Ha8cmq*Zjzn!iDDFM3WK+q=5BB8zldyit(S1^_a( zrstO%Ty7RZ2tBxD($Rf58hFmPw)9t9IBb>94F|>Jm(hyGQ*OpkDHUW@iWoE+#ZpVr ztTVRZz6Nw~dbSuIU^zj+YP~5o(5Qd{*U>Sf@zo|QA)aEH|kLx=FknO!!!F>X&3HowR%)HLbq7tcVu zuBZDcy&k49nW~PtnK_n9W4y(As%*VZ-}Pr9qABmfWuA?ZyKgjEiO z)xwQ`l)mdzZ()Wgl_;^m#b;z>6w1TCaT1p*&)50SO+XVPL-v}K z!^@0Hw?Kk+=${|1H1OD*E-#3G)D4+)1e3it&TiNoJ|MG-^kd_k%P!_K>eYCgV}tfD zr**k^PW+z5b{;oNTkW)%HMSI?{d=f49@(>8UX7BR+=GumWN1v%^yHRDuJGXT*RE^& z`o%-rI&j&^>_=WP_sv21+xp7sVkNE0$kcsc{?HHAuFfwI5Ef+M$TyUEzVD4>~_wot>Gj=JEn+0YLvT5?OI+e4 z$RD@glNhPg3Q7&pU5{C1xLGXH1nwV=C7Mx zaBWV1U;MKUmrB&Zekl$W=7Kf-;=q%^+jMc(K8FqW6`ELlH#~SDK7S86;LkL+Rqv`^ z&*4prZL2neS}TQ*IW}lRog27;sp`QTWRa>(nPF4S7x6E3qh_e#p#2!iw&i=-BFYvt z?>Y94l08h3$~1Q`Z_xxHtNXfluQa~=pr6_vd3<|M(_xp3l4D4gAww}at_{YB-`mp? z^=L}&x2-FiQO2W36E7$zTDG|-v6{{S53$wm>aINtltM)ytcX8S}IIdDyJS!cZGj+r-v9Au?Cxi*qCT2|6)8R< z``F&wPaHUw!fvz@X@NPRw^ZjeIrt*r>)f5kCd&9Wuarr=@rpD$K$oUXtwx1DS>>6f z$3&8blRm+grBQ1grdm|Nuj%zXXW<)VPn9@wxqK+0iY^_bnTHW3P8praw4W*wgT3z4 z($-P2ZcN~y*#d|!k^^>3w}D{N%=ZRPZWbhiSQ~w;!aHlL!=_Ah85&^WI1-2ME}kwY zOM#Mwvw`Sr>uRZK@+3n`Rp0Jad+kZ$lmL3uy%ZEQqIpPsE|pA8K|x9Xf)TD73ou#* z{Z$((iNwts2;zV>f8(UUll5pJJ?Ow=WD4>i9`OMbv*aV|II@IsG<8u<<+k)9dexwp z{fBU-u;gq#_2S(3&8hk2{X0)L@9MmhUK){amYSA_{qiC7bEMFKdH(8$KN~t;1z|HJ zR>-|#_gE+5C^(oL zA4QMof1ZARt~!zP_>4r85bhCiP!qV`V5F8&XF=UKcUH-qDi;+F)2DZqE}B5z zHqa1G1!l9W>3jqV5~>3`A3Cy7!;B+URTY5Uc~0{*jsu*QbQ8M%B%8$56U$So@Y?96 zgA@r_(!@2j>*)}}3NM>=Cq@BGhh>;9Pmq-00V`WKPt96Fq?MA>A;ituC5ZBGTOEiv zCpauDtPmH+p)O2rYfP^wHy>WU`@D&u@EWvb;rgBSVxVEW^5oKoq2BmeboSwVqsi@1 z*H%9%w|Lq}Vl>XUs`Iu~oleziPWwZ@d*_Q5hn+^9qa5fsT|I_l@``<^SZ-K6rK*|= z@A<^=Eago^NE``T4oE@5DQQc~N*{o0v^nIgW|Ilz!;faMpRI&NeR|Uptx_Ncj5)*~ zv`IxM;#KIN&usvA?`R$)J>fxX{KbXZvx}5n2NYuC9tW`Jm~hKqee;loS#Nh01l|`2 zH(9cnlGfBn+&Sp`lNb?vy4StE204rftmG%Z>Ak!(jH=OLT4&U-v{s{NvRI7dkGRoL zhtqVrJs#xc@8t(YU;>w0%m8=3qK(3Wnv)k>s>T*|=D`aw3r>06S7kJhEupqcYj0z# zP1Z$J(sUS;nSz{a^|9af9^^|Wr;%%pydXzw13HD%u&-RwO*FC>F_~HS?%exP9Qxp4 zL0VFHte6+bTQbebB?iG+jCGpqWDhdASMJQ#MhC5=OS5BM*A-eI+XL zY6OG}d$nNM0eA<9k^B-gj1F%?2?Ko^`ndg{dW-PiE>HAddiU|aI_q~Up+|-LQz0-A p3B`8Z5rrTlqY(ek*KMIdc(B9T5P|21s)oOVNr}sgRf_2Q|6gI;WJUl0 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/funnel_chart-dark.png b/testdata/snapshots/darwin/funnel_chart-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..0457c86b06af5838e9a75ce0da99eda5b8745abf GIT binary patch literal 17621 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 RlmoyYQ6VY8a(*4Z{|4yx#dH7w literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/gauge-dark.png b/testdata/snapshots/darwin/gauge-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..3abc39ec6ed4a17ba401a0d109d20441b9c02adc GIT binary patch literal 30567 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 S!@7UXqa>&HwnD}v@c#h;C(=^@ literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/gauge-light.png b/testdata/snapshots/darwin/gauge-light.png new file mode 100644 index 0000000000000000000000000000000000000000..fb55f171d2d6b1d1304a3fd79cbe4e9bfd628f79 GIT binary patch literal 30341 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/heatmap_chart-dark.png b/testdata/snapshots/darwin/heatmap_chart-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..1bd7b9e640acbc88638e71c7e901970d8ba89909 GIT binary patch literal 16948 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%0A; zW)wj0M#gwMy}S*$*O?WCCn5=Q)3VWUTnipATux>^Rsga-Trz(B@;K-%gf&@0o5)T_ zAz=_}XIvs8-$QrJ4rj?(VME!@Pz=E+|0dUEN!PC=wRIOdp=+ZZcx)D9web8CZB?ad=9K2@3`a%{pn$^ye z17-znSM{)A4ZO{-ZvM&iD(l8IYu^>$;pwHv)dM&KFCRT$KHe|nvKc^3oiM^&$OP`nH zk1X&|6-ye6!#mPUQP^#Vq5i=iIPao_cK9~S6Lgg<>EqAAB08fNDN9}a`7;550gX1g zeEQhb%dT;<#bP31VK>^xKRLOQM=kpIW}`|HQO|J-Do$i(PXp?W4m+Avi` z%or5UVf+{#@p3^DB-hCxj%Q2KZS&u{C@v@jbU3`0h1hZMC26xeT@VIKZdb3|noULh zfYDwf__;l*@3j^HDq&t>M+o*he5v$5-yH^e|0h6IE-@oQIP_dwyzICfqF_nn|Y(_kyBpfi`Y z_7V(&`Eqlm5|&&70;t@+fnrONT9AB3c9O*7!(@wVR?Y&4B0(V8oPM<9Y7&bOKF`#t zd`CJ_ExFxXw`kA+=g4S7J`Qr5;zF&ce58AYN4|e)(U?_CP^UgPga{t&={ae0ZsU8l zHxz6aUZi(;V+Zt+68F1OwvmzcyOz!O2>2swfGhZsWran0+s*_e7Jo*hhaC9T*QzSN|2WF$6v0#3`T$Jj1x_cCs$Rh7@eqE3`1qT8I+|0@O z3fgxXHSjH{{sUfLnGG8v2c9bQ(#EThmg445m9Fb z_uKiO)BAB$^LkFsXxu@BT*Z=2iS!uSeLDYKkVyeSf@1~4O3hSa4^9t{H--R!xBnNM zG$^iCj71TtGVMr5#*BXX+yyfklLA?hB1w+VEmr;V>jErzHXHQ7U8@%Cbvpt@^*=%`?CdZ{LSEr^xK%BgIl? z%}ianAAcnrc8H7TR?5w9W7NE+Ox*|0mu^|V(F2cn_HIT?#ZH(CGV3&EPCTh|y?8D9 zXfqz?^NJ50m#r_KQDJ(uL#=<})Q(u=a#92xW_pwi7|NtE6G#$UpC2iguvnu-)~kq# z&la(}wYyD3jDNme@g!?H?YuIfs<8AQfPr^kH5{kK1(@JIM-h+)8U`Z7`IBi$BiKMaPcyMaxeVF^5NFUx%Ul-V9Mx+-A5lOYFu34gYUY+*3#uq zP9Y&Tn~O(6gSR*XtiKEJJN7?4c+v;%qQJ0YI=;tZQ}8A;J9x>u9HgC%zjeIgzzZ~7)gVt~@jA~w1$~avnXA^*Xwch5OeHN< z&)=W4^aveG}o+IUu%Qqr1qkn6`y~>wImKuboN06O*f>Ya@$Uq zr7wP7JZ9hBZxQjNHz22uSZmO`x)g|qO~vxmPq|H@SR4|wdf)@Ry*uH?5Vk9Z)jdw6 zM+(c90s{khJzU8){WgV)B66{wSgT%S!7E)n79A3fOe7r`5T457UFcx*aGrZAKpt_ZE5r)#BMicQIiij$7V3<*w?Vl?yK(XS^T|CjI^U2O4f`T2>Y+ddc zXMww48M+)278y=YgY$lOY1=StXsmBEqtT&8h5-%IxBav!@?eT!^lIF71qXf!fRGp- zQi-2eBO*|!sA^_%)x2J8%H8ss82fG8pkGore@X;2s0IqajVfE4r()J(}hWkg}U^?=i7BY$<+9zg2fLT zoW2-LQ2@Q6n>7*STZzjNQHy8mbDB8$@{=HZAVX<>*=ya~*Pv+-UPJ^1E>2L#{rqf` zUm|&4uUeK;mB=oa)65z)wYWI1x1U?aOtjecJ|6KtHf)Wun z&ev;f4%;f-sdmah-zI-_dv?}S3j#YWHq!jSLPX16Z#%*JD~I)1#K$1GHR{(0xwz)Vn;NNbuVIy^Y-FLrVzL|ELC$Ta^euqFZX|Da;?5IPR z%1-6-+-~PUb|=yu-tagEc?Vl7*PNgL)aXT`nIxj1-r35d=4J@O)-&krfyMbgrE2pE zEuf2+qQk>z`;EgI?ewlC@&d-qa)%c?v{LPJf9d<8u^BIq*{=b^=LhL<%VDnVQ#Pui z!eXDR2Q5+%>n$Rk`6M`Va);6vU{7VY>Uw`{=CM#Q9ZsfgF8NknO)GdYYtUIClF61P zk0J^-C~9b1*VpIHXnmbwtVFqO?wAe*5e#r}rMO zl9JliW}%ns(5df}H5TKLj~@RwpOdI?S3n+qp(%by?|L zP9Eu=Mds$ae<`f2G3hZql`Yo^Zd6HL2#%e%*J`2z0}p9aOlUQpybfx= zd6`b8L!wY#oJ_hMQ~&{xymRMR1q)X)fIbk={AR>!ZTm;xdT~0$EF0Caec(f7i#^lX0z_6Cvh|L^B^-=%&j^=^l6xwBX{V~00%$R7~XUI5#Hb%sgSo>Sr_x$tE zwkIq4cxneH*X~4<>o%X}yNLH7&jOR+;ay5699M*F@l(bRK;Q3iu>5Nzc=tV3k`7w0 z^qqK4tZp!RZc`vWfp6h@r?Zo#;?A`a-@a0dff!2ylbDySsaEcXxM}1Pe}ZhoF~>yE{QH1a}V>+}-E?-g`YW z-7~#2ruWeIV8b2^pGE6e8fKdOa}Mun1dtc%nzC_mf4Y)A{OwA2;!6cZd>05AX8B zQ!_VXDg4mR^D&xzn-T-E2qLkVxCXo-9KwH-J=C%rr~waC`$eJSc{d@S&|~H>C*Ml@ z#PNlfFrXOA62OLl10VghAGq3onnQy~T##7U6O%pxT5M&WN0}&fVt(Y?If|4l&xSVXAYcZ!ca|ip}Q_ z7%Q~K_nye1$XQHl)9!o&&jex2wZyYL27uCw`l7|o`;K??rAq7H$vw5%gZlG-lGeik zgnJ#!0}sTv>y&R}EM`VpnG(-=)i)X0-+L9DWL%j;s(i3Rd-f$Z$0E{0_&RoGVuwQ* zJKNujUj6>bZ1?v5!JK0?wxU84c(m6z#3kTzlZh|TRjq>yBiqtuJ-|N z!9Lv@lr)c>V(pn>-dq%_Bz;j=658lgPRkx8qkEAXd&o7q(PQjRlacjHeJCkp49nZw zN5X(m?O~bujpqPSzRPp~uk*)MqLrONKB{FtDzSAG<=>J5kDH1zX<5JaTe6R3VxwZV z0tQRv3=y#qL=cfk`Z0Rl^oHxSXO8l;N@tr)EF*dUDkodvU%}stDI7~-Nl43|oVZq4 zs@9aXn*{x1hKRkRg{SJ8QU3sX2kCbrI&H7j7dfL2{+-mp^J`0Mi_17ZCjYtz;y9^aZGs6pqvZj$1hIXTtJ%9g z%?fs};hErIyXd7MPz2Dy!^OnrsLuV_t-zJPij$`c4)E7L&cLMGxi)t->IzOrItDeF z{Eqp`i*O9e^BEWy5d4SG-$nnk$MIRF<%?RIufADwh{VA_k;jqM=6B+5D^8Eg?J!fg zrha{1%-~QJevW8JCt_ZQgr6`Sq4G;?qt3lZ`kSW8WL=hk2`hd=zu;nO9e`DClE<2@ zZnrM^dmY3wiZ0$&ioJ9ghj4oCb!ltlanQ<=(Kh8g+TO?D*36Tgo3WEee+_d~mWu_K zmV9Kjya1`(aWic)MIpNg?H~PQ z^${W77rcpPi0OaaXm%fQIl_tVVnbusk>(BPyg1ye9ecWMuD&_T(6>9k^Ht#FlMAuz zJG$z4%;*=DduPB$@hYV!@z%kfTO%l9qrz8)GVRmo35?YFk z&Ncj=j^{LU;I}uzIjY|VME-U`muxY|k5)OOjIpejXWmCNTw~K^*0=!ax_`J=xXO$- zOGBO*YQDhk=ztLaMh(snU`P-%w;kxdNr*1eI$gVe5%&$eTOS$Ae3^rC&T-bY-!463 zVv^U>LZH~Z+BdkaEu8)h&3lr9PR%Rjgapr(@2iY|`}Q%l85>4fZPv|_&MpTo-{3TV_Rl1H38*GwGX?Yd;vCt@;`Rn*u!uO!c2G|Q%|-eQ2DKXq*9;JIlj-VCy&xYKrc$h9miD6REz&1Wp7l+aW*S5mKt z-nYA}BVW=w*_T*7D!fBOP#mr8n9v{9bX-zGmSs1JT6%gbG6{2-WpWZ^GWYZxYugZ# zrp0<^O@z=F(akrInU=L+c4Qp25VJ6C?WTS`xHfdA5QDvrYy5;@_aHIga0z&3%b`%4q;(B1{VF`kJqt}tq&@l9;b2GI9U8G8@Ysh z?44WLplBWm{Lg;J-_5+1j`dtdib^(&ON3!o4`OEOA3A0{INWWkj#YIJSQz147#$wX zK<)i3D-Q?}f%k)tV$O$xAk6s-AjCHk6%tg8_x#830|Iw4cgi%55o4^k0~P`67oI7c zzNA;Hz5}`Ws{(V1Uj{P9T*2#=U~ivJoko8I!Y@%ifQXKPE)ealukdho@^NhI5#B#!Ch4q)YjR+E!MYZr$h(%CV#!O@@egfQdbGA>p2g_d8&I4;aMxVuU!j29~aLKZ=e$&gHfl>lv%hC1Pk=;VmHM3~jamgGm zM)P|)xv*EpAX1o#?Zr=CcQ&G)kVfY=)!k0^eU_`_xO;l8yQ~}NyykL~0H$_5jp&JE zfG2)hvBf2#-23IpxJ_Z`hRkuFt`5r$ch(X++)e&=GnhN>^u0eOwm$ExXqf#yK0bRC zV2DNsfiT)Fi^(~9pe@V4+g6ID8}1fTEKi%(?!HP(P>x};AX{ZIFY{Z{Npu!7^P?{$ zZBu`elL4bLbMz->I~U$;$l}{QsN0Yhl4g1i$WTje@vFLL?7ws^;WjGryt46s@{_4H zPW>6N{(%^=hphaI5EZdVckc7p=mg@IJ&6#5JJ**XG{iR|3xAFBzX0h!@btfQqS6MK z5VCRK4HF^2hVToBD6|+`)Ohr@%z!vBxL`S)u@|}n&GtorgCkee>P((2e)E^mU$Uvj z%&v`X0fjd#(fz_eSu5#Cb$%feTXG{>BpvB_nI84Y!xfqIdE_{Ur?yF-aD;!+wzmvR zwC>&Cq4~e0^1uJ$OeV&_k5BtWc0+*?t)0=8(iRV3b;IjFXSM5IC>xmAb5mR2V zu{07}zC)ZvbbFgr+i#&jg*~eKE$+ngKmqQrlS;;QI5J+u$(_`qfXxVD7RzrdT~MF5 zUm?cg&>w|oR8}Eg@k#^G7GXt59fjZGhAvH1jpr3M3Uzp98Ln!crL3HGn>RP6M4Cw& zHZFL5ORkOxai0rnnFXn1za|UR?D>i3nCpRxJu=VAk{Y?5T;#0Uw!EA@b3mIoP~OfeC}d3DpMSut27i%o71 zyYtLqms*RIC^rXTmPh>~XJfKtd6~a1dDW7{>U>99AV_N@d5_CwxO0{06M1Hp6cl45 zc^kDBGM^cM6K#oowVkbB!elxaIuvio(a6WL8x5h#Bs8@3IlNhtVpBzw3+f#bVo99C zf-e>nXmXh>ZZj>X5_WbYSqXbqVr=fd%l9KoVa0phol~(z=y40iD{X%7(CWRHB~d#G z1@Dj(CjJ2lIYJtYL=ACYPCgd1VL(f(w21rF+|QkN3@ReC_{gfe47W@OM>%0Bfuf z8l@XEB|+!bYOp%r=|EM+T@kNn5z78{kvkXhiXY(;G;Sgk`?m}4E07}%5;*=J2diKO z@_Hl@BA_AW8{zRV>U)7BEdz~!Q-yc1*-x_3D58@$QcHxiR2+AOck){zIjsCj%f78W z=^QPcu|=Qz^6dnt3Pcwxo!VwQr=W=$vtP-G4KAvck&vO~^I4yjQ=b^ctmGFIh*5)$ z*ElY~q(6G$LjLx0P~)w^O0%EERD+z@&kMecSb_E&e`9^)jf3IjR&9QtXXoPGniUQY zf{dS$L7^vo!p2q0$}TUzd>|{yGur;^G4z2`y%gKzjdQI|&pn?oD3wxNaRm11jcBcQ z8{$7Ahg5&&8>3BGHU-P)wy$Rl9S6von22^O-tCESP&0bHA)Ynm zIMvQqx0v2fj3~a(!5oMe_5v7s(t$`Mh=7jVdi)0SA3}8HHHd(_hr5rLn+oOmjk(Qxg42HpS>(Vf?;~sZ z?sBb8^EHPXZf!iQ(vXozDNJ^c*lklz9y}XtdX8OJTTe2z)BqWK!U620?ckK1()z`k zf=SWo2`DcpE27HJ?b)RH|1t(wnh<$D66w)l^l}-EeF2mK&6IsMNx?@RG?@jH=Zv zC1lgBEDtAP^4!mQzLr<#SEk7_pVq|aVp28y&BXu$-1`b-@9_HK>zSC=r2fLXIBsuU zP%%#I-DId*nxoVG>9lNF>*YTgH5q}-{Drvh8u{}!$(g3VKQyvUSRZ;kOAtcifMLCM_@FUmpAeZnRc!1=&4`KoqhQ-@T8%3gwlM;YB*Py zn3485jg1`88;S<`{JZn}nMa#K;yjAR)`I=nX{XHvGPbRVb4>Vyy;64TC1;&cLFXEl z+IVw{5DTtRLpIyhhC9=KXxT5idWm-9E99Vw@eBAoq5;O!=Ve3aI^JMrWXrF?dF+SwYV5(qO$!#g!~k_(?Gx7?G6^R}Z5 zp5qExCPRb#I1S%_i0&e9t=JA6E|{}XC3V?$Ss#t2!%xMViKg?5qD#m&r&b39)f?~9 ztEFgO8SGu=aqV2Zm?R48mZr7NOx{JlN+vYZ+S&-qj$sbJ7gWkqmKs8NBMiL!`5Fdp zgNE}pe(ydTY1JgZLiiitA;2Ld^uge=@qY)qFw5|lDvy9_xugKRflhuqtJdd+ifu|& zVY(NwO;eLk-EX#Em=LX57@K~-#$aa_HW6t{q`e&44UtJ?Li!H;2`4PBWJo29o)*m3 zMMC%ZX^_XX>|n9Qy=;X!i;pfN>z1-%o9|@o<`1`mPxnpm)r`yNl*^Y_Amlf_p^aU&5ENOJdQ(AQOG~szv`xOCAj_|Pwqqm2?NJ#CjBfSQzystR8!{2 zu;X5-alKPc8OBUUFDa?u!51jke}iC1^$J84LE|Xinpb2MgBnA)9RIt$yJD2V5H1uw z@T-Bq#qdtv%ehvg%ukF_W_hspR_ok>+)oTx%!d3;Z--t^F)_VPgIP(zkjCCY=R&|k z_p5NR9*sSCSj)s9MB=wGg1}`nmgA*-Ob_`@zO}=HzT`GBo$`em^T&R*#O-A& zu}~wtzgIM9IoY_2w9pxyot`bm)~XnCoFkn+<_z3(M6gH%zY09(Ck@Gy<#sg8*Y$IGQXqo z6IXo&`eLLClFxcnLa|z?p;viP;^s4%J{{Y5v~i&I#p`>aRQxEeRXP;paTBz|W&Asg z_ysM<9@TfY)=cCa0rZ7f5P&M1T@qSnyO8`9*4Qi1GXmhFxRp*96FNf1NKvSEW1Go^ z#1z|1@|8*YpO_KcnOQ|Zt9t;cmrlc{#iMs9IvslV?gH9)1SvTC=oTHxa&gzRDKp7^ zFzK0LJ8K)wp+}D!wVwgsYlO0sSGLWpi$5=8>a$NXl*!;U(@+DEC6;(tAQ?Qq1`P|g z^0C8&$R**qzskyaogD+(D6c1NDtYmmm-zi3yIc2EWyI7wANOB|XvIu@HosLL7l)PU zK5e`VY#(E``8*`s#JQt+xo?+*Cy0=oZ)a!OVUI=*CXBJkW}H=pvH4x~EhMXuuyp!s zsmYax;XPa{-u`q#OS||P*fQ`ZVlbRA24C<#D{OjtB(2pkJS-C_htJuuGmP(Y@K>J# zKRwCL*wf|6j*l1_o7>`fXcCF@mCTX_Z)2p?X$R6+xwpQUz3z+I&a4C)F&$wRKJ0bA>pql<&b@~;oY+{67R+FO;R%+5%eJeSLql-9gRG6I%H>8n-TPb>jT{95WDc&4 z1or9}qEN{93DJ<{7QIiqV?{p70lJO2?b8!E`%}Up%l1qo&#SI=<)U(MLDx)Vysa~e zDP)zBlE1>F9Ox=STM8O^6^7G&#hXlq(=JDhmT<@tCM(PgL6`^vi2g4`<6D~Rqx3e; zWscxvc5e0Yw!b}!$fFv0|L=^{zc+&al=5|h?o-@{Yl4q6ZUe6#Gh2Obj^W+4G!5wk ztA=~>(4!zl5-7+@r7;v8Zs?iauGXLN4@`^7qo=F}rcH#LD}b)gt6d!zm`z zDI;)RjTF$d(AE5?Lj7tc3~R}qH!_n;4qEr}W{!L9WIcARy_462kM?jUyVd6vEQJI3 z0wd%w77T*>&)xjw0jz$g+^h()>oZnu@oX+I)OnPMP$|9QY3Ork6ELte{9<>Oku7BS zZQ@LZXJ66oWPS0Wb8a9VPdw=dJsmA`Dl1iChx*N( z-icc?K^2AM*}ZQ@gMBS02hGO_waT`~{dn=RUJV=_?FK@>wW$eV#56X0--Vj(c&Zu- zbwFk%2tfltQM*@q;P-&$2UqxyQ#7hv(5$ zi)`hVM0PLa!YThM`qrg{+X_ z`1)%kfzD=r&aEoEjq}H7eG9ydr-kF*3Y{y}9~KQsw40ln3Hg`bM6d-rTP&8;>t&L1 zEc~2?Zbl7S9)HdA&F+xHub;+mY@GawPC^pNQ%{Lcoj$s$rGS}95K|NsXKHQj#Jw5g z5~-ZN+zfZ<`gj=^Ipmmg4O^Vq&Q)8~uQz;?5{urT;PbfJb2AHrK!v6I1gvP8;bwnM z!^4|bu=tjUpEN6rF?5n}x80?|dJ$Cva;06)%w0}&(rfUP&CVS$n~L`oo2|<9Bw2|r zqU(l&eNA8_7qj8)(-S9Uem{OOjycz{M7zAi)yH%5?w^5=NO!^CKlQO% z3sh34>#2I=+lxbyYx`sot?aF@x%dx#t1&IIR(Na{6DPM-f9M@IFnHh|IDU*4RzQ>< zVb|kPB&JCkqt6j6bX~a9`=*(bQs>hyBOU)y)IfB+&t|Dze|C$Z;ZM(!y8K&W^bfV7O;XOv$_`AR-6J*Xq~Px{qoW_;V;ivuqoJGq3Iv=T z<+U!uU;W~#7^wZj-C$?{3MS^IY`vGMF9u@MNBUD(RcnuCanJp+%4jvTzwDtA=Jfk> z>Ggi6x>uSEU5VV^kGoSmn|z1i5if-@(?CSKHR^Me`9Cq0vAV7g4K{nM`)GjoQyU z-uw7%5TGAv)5*T2by|~cc6Vl6vI9ORc-+Kh%dQ#N-pG)EDd)GYFhJw|_?6LqxlLC^ zhtH43#yOEI>Av#iaR5>hx$ZcBb7~~FLO-=TQ5KE~uMV(W&gJG!9A7W?-nlQwB{q`a$7p6N8aOI`(S}}M=lVc zl1M=^?BOkr zmPEe~%v&YcK6}`jZY#D$EBqmDeRp)kQ?7m%Ot3d;K^|}vSHYX3YqlL$)C!iQmd<;G z>h}B@P5UKN1~PW;JADBN13QXDE=^<$&(9L^U#0>~H`w&B0`eb9#C$YuqE;DN zc@K+vcjCMTUp)W$38tutPk|k)&z+{d@oBxnd7M(I-#b4ud<@N~(Iu~rPYHXJ`^4l+ z3V0i7VI@iKQezJ^Wm)l1M#jRf#g8?iPA_04Qxup*36u@{JgZ|aYs^a^2~iWb`@OXo zhc28*T~E{S#1)<+UtV>=8Nx!{p#R6)&>UJ&@JLT?H}TMGIZI2&;@b9v8X;C8(i*fR zWpS;sLT11vYTc@RVa+R8zoZDglC1(fDL%)!w5B%!M;*$}Aw!;;_3ZT?JjXwrFt@Ol zTbv?k(iW_XZMdpV;LM(=kaU8@cOs~Ui`85!c5mZ06UB?BC>1PTSTkz;pG(RiPn$ad z%P(io?SzN?-n+Z3ofB!c08SfweX1rQGkDnRNdOQ6iR@L^#x2=Y5n7boL`!E#0&57B z?9}Webp~!p7VltuB*mmS{u9G%v^Qsdv`@>*LXJW{HV?alR8~X<>ZKVt>8}Ifi_deK z7j>3uCu>RaNCZ}2&a%g@HMO;~xx6>H*@FsSsxQm+9F(wj7X}lx;rLC^-VhgKya|01 zqf@-^jhVoHhJ+KY8K00gMY<0|2U-k``;n{RM~d3^^7hi&(n5&Y!_v}Jr#vd+2SmgV zQoPxJcDJaCv43+BU=d(7vV0((Cf$cZ2jjxXuRmPd#LqP~wJ3ISn-r)+E?myvUcJV^ zNcdg#8xx6^3GlGA-r2_xnRUd8OYBPV6x9m$@f2%PhWwHlYguv57})gk_K9(bR;5w1 zH@C0-k!CL+8xtMlO&w7(uer5*Xt`rJr#M$-c}5bf_}S$BO6D>DlFk}>g})DG%I5Re zXCxa8CVAM5LXiOxL{Z9=2_+0aAk7r zpoFil-z-I?858JU6fqW&k&(W!szypip5{(N+QJ7MnK4{MpD}OizIeul&6yI~5}Ny! zxU<>+KzTN8Vx%}nWF~3GuBTy34*F>G*f7fxtvy9yd*RpZ;q~ZTK|lAS7a~V&{3UE1 z91Q}B5E~Jz&6QF({D1{(V=Gauh!Rt>2I{x%1AHD1xocTFphSqq3lV0c45PX4MH7_c z2jdpv&qX`xfEdq-7n4k&eH+|F6kZ7`dSko=S?; z0AwqMh&WyJ%TXjWUkNrk+ckqbcwov-(_9J4KL!nN+OJe6b(?11cd8%~XUS9IC%b#N zIV{#dhnI$>7DJmP54ShPwZfpr9ryjEe7xCJ;;AWF*jLJ``v(xwAW@6SFc8f?*5Ftdhz48N;GRAXY|`0Fbh6*|j>zlr{YL+h;*2Xwy=jP-M}bu|2LGhE)HkBLJ-gPRC(${D_#{Rz_ z@4j9@+@e1V6AP1L%ScE{jC}et68H!9Vxow9K~gV70l|u}Vcs9wCwKY`8)I6V(w}bO zpiu5+F29xsm1?OnQdh2+0m^<8He0pHlCglByYb)OpIyMEbCt7e__)$bARN4!>gwFG zlWEO05FS>WA=(}0(#(N+fY<3~XWt|`VOn(cc}H6j?9l6*E6D)~(%?V8GFayYzdnY< zy$=!%x+>i^+kwT>LrczIar1CX418Z=&}{k zS>Hp$CfwQEzUx9@6@K!2;{L>~m!-#(B`-*#kiPte$QW6}8vo(KyID_K4HzWRs0v_nQ!^kMCw8ZZc&x*xo_u(ZeP zr=p?)YiMo>Jhku0-EkAtKF#>!xx=5=hd20pVbZo|XmuS5K`bW|laSUL1ZFFOs$swy zm#Qi2`k<$vdne+Cw;6}Ava+85p&f!OtgIQn`B48^G2AMTsuXFn`}gZgT1$%9?=3cr znRgvw?#^hj>kAM$7IBO#sk_0nwYhcSoPwg4_}z$tMPFqMst%|~k;=dG=4N_-OOC1j zmg{cx%+F)2HQp!wvv`Vp7FWH+TJ|SSTW!yV@7;!Ntvh-)xCi;)V&r{aXNRsk`)*M8 zc*b^_GVi&z$kJ>&aw8H$RArK*JxFx?Yt3w357m##U7C0BvhcykTtynf#9Nl=OM(1% z#n8om9v+T+jZ*)sTMX})?)V^EmNb+BiPD)xM_YmUhgV5*MeDii0~+k~b|%SFbVjvI zBs9k7wpd$OKilw3daL84DL2g1R6~tY*$1=*D8LOF%9HCz4pN26ex*NTIwTSBKa7EX zf9kE{HxWYgy7Np+OT)y*`X(8y;w6ItOiPF5x7+nqKK8l z=222Y^CDB!g4*X|k}HVuwgi-1Cj| zCZDrIjWh=Xfi$=w^nl@Ki|g(e?%So6&cbto@6WReFE|SQ5CEW8R!;7!cYK;gq9nIF z*U#rVnvujM^p5i7N&2v6{<3n)=9aw{&tk+mJ(ZHyUF#5vK`D55ijj>U`-=<}yL_pN z;poIF=lD5s#Qb683YUP);XAzOYXxxDAB|IHzA>@`9&~bKJyB zjy#!wxxttFJ_F3Ao`pWI-aja+*NHv-3Buo0O1}_LrgqzTn>$Vwv-61D>>kCdm$G{W zYKbESb~$DC8ILS$iGz9GH0wTF7K!9CaRzwmONWREgQu+O(y*`gU16>XYRUpWmsr@Y ziD`&2aCoQ}cKGd_*=;I2v!}2}L;)4o8aRKFQAO&NNey7~n(he_n~ zPfI@$ImkYX{z7#=tRusX`Rb7{_$etT6*(as_Vnsg!1Ui*GmJumN4x|<5^16(@(BfA zM@Pp@jO^WO+zJUs|BW{XO?-WYUa%*}c6#P=!~DJG#WPmXQ0O8U7Zm)+x<|78jdr16F z-eUS9FTO`Vc3hRXrfWqQjh8pS8~@G8FV~~q8=2A>eVUfwO)hTf0vWgSpVGQ9xI1KV zeLImExEa(3X%KMhH-m0)*-k~|OUpc&WgcC=CH!}yr&QDXrXFf^VIT}X`z98gjIGai z_=er>)XGz0Q(D2iNz7R+C0S`SR@3Q`*bE5Y-o6-93SqlN!dPV}4B9@y65a21tzd|6 zT&)T7Ly6)P&+PtpGv{avVX>8Ci(B;ogrHw#zf)3@hC|I(J65Hk(y~~!ht6rPn(0*> zuZX7|OV=f4qDOQ%OI1sje=VB}v#w+k;N#+7DSuR>9r`!49lB(cb$tn)8VNMd#%DBh ziO6cl7lE<W2AzLr}6i zU$n)5jjg4tn@8bw6beMwMnJ=lTVS*!6OJVmEd7RI0{hOXC#A;*3Gp=jSQdblP8l=r>{S z$FNq9S`Loavzr(uk}W=~2^GO;&~RUhq@=_O-*P-BxsJ9LY(1b8Qr?7jVtF#}VYv2W zFD)&H7Wp&8E5zeu+0EHKA~N>k@|@50_jvl1%`)Heo2$V0ci8TJO_37$nA!BE)mqiV z#*no;`SM1cv25;#q0&k&ZeD&@4)K*d7=o^Oz2LL*aN|Fokq-1?g^XO}aH?fMO3Qh3 z0`v=2k6t`qX7P27@D2eS@=rPcX2~&<#=E05AoDXm^H(N;66&{Jt+b{|hYCWGUHO5m zp0*wz{+mB{V^h|337GpYA71WG)_Q**{kEB+IR!|BO7IH(wa9CCPco8nlGro7eUaR^^_W$K+T~d>r8aVU zQx!a$)7BbGf;{d;CIe>WW@3;C62!&48Ef$^Go?2)3d3K%1CuOPp;?#=oHEWq?j0?Q zm20cKHfUqbJ6p?s*W8^h*WAzCqSDiKX3Pq{6oGR`jf0O6PL*eOq!(iYN25NMPq$US zlO2Ky|5g2!9=;x|FP0jX5(agcBuTJ@q$F-7dr={nURq~kF%@bxE!Ta&c#p|gCiPjN z)$`fdz=2St_|P-WTd3XsspSrGQK_z1NSpexbcTnI?QlLB1rlR-`*en)ud9gGij-PD%RRo4Vf~ZuIXl+qvCU2E=TMHl6P0MQ^(2tGIv=j=b)ilTUnsj7zCev5>F(dW{1wLaR#V#jB5<; zW`3w&u zMo4iX%WeJ`a#EZ1{Z*$-5~VzePP$Ay?$Ee+pw^(y%VRQ~>>o$-dFHN|b<}E;+l^XA zif58QqScq%r{tpK1*BR?p{2R|pX?Q%GIg7aX!997%zEPyFLH2aWe&p;-L)lGxD@WE z{HSoH{&A=~W<>BCVNV~Qhr5S`m+0?<8g;h|eTcbU(ifxI)ni&CoasqtLz-%IB9`47 zZ?D*|B9rO!XoZf`*R>UlosEs1^Ze#NQ3#zZchQ&)1i4#lLRiiyhgqAf(0 zCP_NOfvxdrnc@Tb5-YHWNfyuY<(TmI$@VrZW&jkiqMa-tR(AS+J5)%EQ{Qh~y?b?k z8Rcq=(72b*Y# zptBHm#wtxZi0q3G!=yqavqKrSbWF)r>q0viIs2Y0d)KQEzDAx20su>?3h+-UT(UN=q6F0 zV>YuM_H%M7BX&Er?HkX`@20MVnhytQxN{pSjwoRs(pD|l=9A{{`@2Qagbr*nYrEl? zv4!YYHZGRwD%eZ7BRmnoD9GsmTyG1?L9vqLTRQ~ypa`lEet6=5>dqPKc5pjb$%e#2 zoac|nK-*@CG(@_czr9s(fgXtb2mDJxD^+BN2{C6Z=aJ;MN{StuwVZ{Ig{U38+d_ZP z1Cinvpz|DH&KqX)7?Sdr%g5CVwure+3r-k!gTp>DnZ>IA6lf=#?_QTZOH7e%J#GY$ZXuG<{QP0BrpmgC60|dh)(#pKWZf)mL zpI9@okP(TsQUR2wOL~nn@cUtdhy<}aqa{;_`PAy><#hB6Prutyd(1h(d%BOj`8QN@uys9bH6RDI{{xpK(FgPl)e^fntmJUso$ny z5a8x(`*^P~H~e`hh)j4|WQmxJWUms?gMF%kRYYgdoGG755;gLJ6)e>UMMg!9EnjLl zf9pGtJgBCJdy)FKIa?QRKr&RanA#Jz$z1;|v#wo;k{}fZQfwAD0Y!$B8FlJxl{9=b z7Q$;BXgmD;XD+zDIy`=hR$g#DGmCe%Ve9zL2t;08c>a*ZB%Y3wVb8WYxR%HmCsV?x zVbJNGHEM*FtGK)CM}tldM1JghrsF6rDv=-{N6q@QxHh*oF-xo=yQjXN&_d(D@A(TL?1yHanVrzej! z>|@5|2A7PfaGXr$u1~!u?)|?D*3VBv7ejg5J)#gyw)bQpvJsn2e9EhebK^@>Hf%Vt z1OnQRa?B!wb7PI*RtrTtgKC~+5exY&ZZ+qK18B5LA6oE5#AL$G!cC{&)bh_*MKQK% zj?1;Z#s%9X%p^%v{6d$*p?QD=dzvgCV|HV#hosIsObidq{(e4rVe8XxA>Xndjx+Va zgu8^rr4{)u6yjv*x;cxs4JDt|Vp!wbUz#;4r)bTo56?&@^%XqDxZH@{Tum=aU!F^< zbK@#{D{Mbx1i2J7tJ9*y?Yp+@56`HV*4MUQ)G7$z65@hcBF`X3@#v~u2z&md z82|$O)zA#=XCwhkmoV7WxVA%fQnGjFcO|uxoOGMgd#vk^7uvzi5G_0^f0}#h7Pdo> z;lSy@JTsT{rl*+c8@JoCC=D#kk2C6X#-O6~eB=}bBvHy=a$L_NXDfs!{txYqS)tXNa}Ot% zCr`2M6ba!i##?LxdKulCV?BlMQ3L#%avO-5sJ@>?P3xHuXpNs?EHIj3`)XBfw&U{= zFz%n^g&xbvc<+KOE0CRCs((^~} z^yTLWF_)ymqSmnL=mf#K#2zaPTu8A4!_dY#_m;~#m``#Wwcd|O;8T89c~Y4E8bKm6 zF*8B_K4BuH2vPobbLE!*^GS~6v>4ehIm1Iav$peZE`o|Ftpt0l5n2&ny1wYWwAc*K z(npQ%$?KsEcXLDE$G`8O>tdpN-h=k~GCEYw*l46=QSs_|YhzKoM?%S^^(5+!H_Yr3 z6%j4oUAR;?!^5tKky}aORrY+-%fyk96_>T{NUu1)rdS=;`^-+rhC(8E2(jMHnA=7Uz0TYA^ivFvvap_{BsMd^!s1ZlCc(N;R{(6cm3EjV7 z3g1Bn7~D#12LpEX(kYsG0=>JL$I~-aShal;ifeDM-k$?Yk0YVxN5`uehf_rdxcbA6X?!nz10t5(d!Gkp3IE}k>aCZxSJD;3$ z-}`aL{qe>~K@ls|}( z;ztCF3#yX}x2wm25I}Di#79JsMaTm?ktp7Dg$)u)x{Q2oqm&Ug+lXdUwaeBW`IWz8 z!XLYIVh=h5IdnDZ^) z2V;mpC^LOZlG(Xth31~?ms}f^Xh&Y{&#kiX8yu6>H!PkC|M>Sz2`=0stptFcQd&^eh zql)I9hWc7MbY-f4kcLifU5Ak`F#h06OK1>#cz7%? zKgK`5o<>uW_%G!2sb*%Td$A+tLJhAy1@z5*1%C9bVK!^ITckmH;x-7=zU zk9DOSQxl_qz_Qo->&H?R)RQqo2E=i0%u+uOUD~k!tn?OaS64K-HyIahwwJePoEDaj z|1U=PSn)%R2}wGh&%`*hbamraz0<1Cp6*l0%g=iARxAX-Jr>v^y=YkH;~l{2Vw3#8 z(4vPk^$;g}KJlI9upjNb*@r2O85EI}6kS#(5)OTy?{HjEUB>F(xx()|GyeDiJ^P3` zoG#)Y?D3a>|AkJb-vqc6*!r>5LcDkBDIg@y6^zjp0_J>%57?%z-dRjqi9^B@IY%H1 zj{hiG>O42J6DegWx%7+evBhrCq7FI&k@ve*2kN$Q|Nbm#^GUrtU$>*}v1>lTcmTT- z4)CWLS>s1ur4}_;@tPu?$x&0>L>>&K=yIsb7O6PF<9~Var!gS`{&)zhddhEQ2HYqx zZ%3i}x@3(OoiUi=3gWE9>~)3~(92 zA^vGUky$WIGXHm?pG*d+(P&aduvWQM@SdRrU>WdzIsvXVC`he0B{ z@Z@DNArTg0_(1dg1nr^%HePEBZ1;5005Qg|XRCbAI}2aEx6uG$K|;hNXh{Ef}GDeJkjJL2a<+|2aBSO;F#yww#vHm+ntoyw~z-bz1=zu5CFgOEGxTiKWbG{ z#Y@jgJyBs*`UmqM6DdVm#+%Q%D01bFYq?E8QE6#oVOQUt!MYt)l_#ifjcogyzrqF% z;1(vVoLuIcvQq7BaCJGvqnw<3Utd>#03Ln{=;FH}e!E?nmiv#B2dx;-Yw7(o@wA@0 z%5v%+FdrOzgeQqkz<7iY%EZl0-c2Q$H2v29DK3B*UI6j_8XwCAl<%{%a*re=gC8Scng6=@}D24O19hM0ad%P{8UwWF1>t??q3WY0zv zOrPmHu{jR)m^X;(@=>|jkK07K4y|AFG{y3VseKs)!EB7{xO}N&M*H<`M}$R# z6`}y57vK_qmv#IvKkKp`__Sz^~gwv_!mNjGys=P3=`11!PS+Jde<;VLVpF5 z=vXS{uM-3584E_HrjVvlvex-fE(1U?h!?ka%>i;`a%|$>x-yC%R1>rJ4Of@J2D4`6P968f&C6^Bh|Ikj@JDEx<@5F!m1d&hl;@;BxiavJY|4&Sl`LQVd zl@w5Ur-<3de+9iDi|hSl{|E7#pcjA5dJneoH<|qZ0Iw32<2`nhkmJ2-BJ`==`yTsW z-C3tWw3d^fN&njmBEkZ!=>8WD@qh9V?-#O=H&}R-Oj3IB^-jX;4K9lwj70ybm~zyi z1@}6<{|H(5Yk-=xPHCb?;m;z250Jh-x3^sIby*S?|4Qj!C#XsP3#2kiUl)z(fAG4Z zvYwljHqykOjDE&U#eZHlbK!Fhf3@F~v!%H0-$?0PlySxu1u7eZTDO}oFHdJ@o1X&E z#`dHr^J!&ZeV|&bf(dS4)9W~Y9g+9%_laSdK#qAm2kZAtxfs{ufUdQZOn;!zjJo=5 z-f#vpIZ2zL@|oR&VP!uo{k!@4^{`s7Qsc%bCV&HR7GKNMC`NeB2Jr4(Ot&J0Ntp-}0u7&6&J=uDTD22ukDD?|12 z?frA(Cl*@rEpsaJj|W!~QdKL*SB#&ZL&E2{>^X}qEas=Pk;y0*fAHdu?tc@Gdj61r zcR|=-=r`*Rba32j%%|lnHy6N|zr{N{@%fvaxDjB6maLXpT={6*n43kg?Q?OIO^g{K zMt-9?_gQ1uV8yHK^f5SSOJ!vm_M3z*zm$z|GDd%d@bvx%t*;^hEP!UXejTDL)o#$8_)H(^mlq zvE|9QrJ}BS;)K!fymm-V_RP%G!9Y#x*W1>ViSgavd|>-DTpV0(!?LmmD=Qbdm7xE~ z6s70XRdOh9D!B~s5^@PTR&Is8#te5)T?~l{Jdf1pZlKcyF`;`I&1i~EElB^6=Pp5L zh;Ec2*F%XPU;Oi;LcP0}O7w@PE7z-k9c!Eqpr}aOI|boC8u@3(>ba=hYV#)(B!2&o zfBwtt|M%q_Ns7yW$$?+jmmWM%nomv&CY4G;OGWNc3jNqqf5Qey!*?Ipf9sAq zc5=Iu>b%{|Hnt{s<9*D7M2h&|1fj|z003_`c#`7g6DbDrcO2z`m}g)fZ6?P1tqqP> z{b&1`E#DtYeIFk;rT=3{p%apTI!n2%?V}W*-^1vFE9TbLgdoabe)xzNSn!mHQh<1T z33HS5{k;TDEj>Mz#qsHfo)G#~Rq7;5Qr1r+*|HU; zc76;dbtI`#Q*brpuZ_($7U1n2jP2|y-WD397YJ>oc^St((HmN`QzO0=UqFb0P8CQ2 zR)XGBP=&6ycyAVMQ>6@|*pwT5`TKXsegeO*B$ld+9rL!SEjF*8tFAvUdF|~SzRA$U zM0jU!dA|yU&Y#A)x3;tnUWj_x_nVSJemHzIFvDUBdTSjyeR{YEPLRpkZ`?TbgBpPF4_z}}Do&c7( z7u&4S?Vf-+=ZkE@Lj%Kxm;E*Si+58{KgFCE0iQ_YL$93LOqJ5Bs?c5)yIkCEzWAT4 zECWC}I0#yRuq?f^;OqHpnSNA}vH)RTa8PG~Z9njU@%aCfIdf@Ql}go$s+gLK#XnFl zKCZOY&Ag(# z4m;Gi(sntSqW^#(3j^VHI8!}oMSoCbU^Ph64*G%OMolfgskKeGvn>o}(d9(zFCkI0QOhIJmhJ7g&Cm)#-&DE!+ z@Ty~2KG=?hBHsDy=5pIryb2_3K#h_9P`V#CptLXb-Z)?Blp^KRsauC(-U7HkU93^_LeuIKsEYATgd&Qxn^tqOUYb)wIU97PH$oGR}J45++r`XmmRbI7xR#}hHJN$0Tka9IaUNKwO!HGb_lA+iP+VB&r<`ByyNx(HF+;0^CKnE--^#w$Cj7dFE`%5F{S9~ zs8syQv9eQ4FO&pUPb&nc8$E}Bd>^@QqkE{eVn%N|9`uXVIzGCT9oZ34Cyf+%cIh~hdgd77c(n1377t|Koh`F=SiFsNb5 z$Vu6!IXAm9K(E9w^KhG2&=w2ns8S3!z)H-#o|#I?RgG|*U=RSs2`(+o%{8&I3UYpY zsN00Emdj!HEt@;`MS7p9i)B)v!Dx8h$43&+p*B6DS{b9I)5Ar8Evj#-sw@rE4|-s3YujJ7sa7Dec0*8xPA{LI=82J~08K(lUnK0#Yg*Pi zpJO02t3SwEeG|$W-9J3GsJTRml>K?cZ^u`iSGw>iS9DfMw%yq>BLhE|=SEb`v<8X15 zKhNRU;%M706&Xck?bV@**O?AV(&Y8>#7v4Wn<8exe#;%JMUj~!D&M3;`aDCb7+qya zRh|+pd4kpMdsjDC7q`JC3`%P9ir)$gJ%%JnFteGtYbHp2O?^TQH3qv6tuC}wRvVsf zs*EBBJ~*t&m<^b4V8cfh?i{bT`P$3CL?P5Tmy+s$b?b2nKlIUqN49IdxhaxgPv44t zv9l9STM=jU^sL>DO^BxBOV_ttZs+Tr_sx$l*QD0o$3&1deM9bdMAyVq#WwBmtYc#` zN8@V!a_h`VU2%ATr#Ch#^mydS;a}9Zo!YmJ>;2vab{>?cnuDE#ixZkAMY+J^Iout1 z$@5v%*VnT648{Ovs54+=Y_b=AP@iX0%eirq!CynQeQ|!i6;_Jb`YS~G`Y=I5&Oaui z;rv)pRl`ctVZ_Y}00165K1_{&f;uN=WkuCRB&?06f2a&Qe0s_lA&C9hiu8szKV4Dwe zGE2^jd;X}|RLGW+VYy6}0{ZfzvGthLfkqKx`EgIT==8Etl5x6IV}3WXd-~^;>xa86 ztE<u0>-Hm1mxNp1E{?ySq z>@ZRvQIUNUwH#;y8-Nr(FF<0Kyn~0W*m21dX5Jwi!MII?(G7D8C@K1YeB2nneeC_fybG|+H;zVBjP{AZj`Cv2U(dgp(YQ+<5^sq;o_w4E{;t$Xyfd@>_5s7 z>Ef!4IN93+U0!gUr-u>&`Q?IgrN@EwhBCvAC-R=li;b+tTS@gqgg;IpE0Lkwc^ua> ztY}$3Y6#{=ckG|}shWP!l5;!MW*s;)&OAh0e6|YDFKLasXzwv3=E)E=ZtEE;kvjjr z{1SJ>)!k9hbDP2QleluJ8fVve&blM(!G7%6&CQz-dpj-B0+r{V+0jfU@kl9ShR@r4 zgq$_}AK{f$0dN~<{On-(Z>D;a3pngiE(Cq7&(qEf+_uJwi}U!`=aO+XXO zU}I$sn-dsyLCp0Yo{D8#o{}SWzmkisPeo?3 zKqAHStusxt+=JClj<@So?6n(g+y`9tvFn4%e{>=y3>d#A@p+6klDZEZ&A|n2F}+FB zx6E|?e#SzE?6hNdJ4@7xlihh^eSk)7>+bYJlV6W-aY-KkKLZ=!Da;`)IN@7Q)2I%AOe|I*{bfr&uZVVR9s*dW^267)Avhp3VbF;c5Nf z2jamrV_#u>M;2FVMV=r$3mNr(El@gU^NAsG51GGQe+Z1$O zkJ#|s5jKW2zYCL>b966M3GItRK@cfh>|rYQQpn-52_>h4k`LLnHRLozO=sZLb+GNz$i_2y6yk3_am1)bU!RyyA{G`L1Lm#(APnHhDG zh4=4+wAV3$Ga}9aBq!4Xe6X{{lwC}_hdx1XEvWm3DSCiG1@>7w$9QSUEpiUz^rf_t zNZy>nlqbKrUB?ud-*R2$nG-U-KlNLr3YMGfnwd}~6>`_Q6Q7hA#5Kg-1dEiaeE z_}6SUO(Iq9*k@rr<%Q|WXXxb58r)+hNNK;~)%6u)`h||6 z|8s#M$p*LJ#Y`zLFRx)PpS=L&JY|r0hgpx@ri7Lt2A7CE@6zh>yMsK5vS&D4&8XC;7iJo^rl5Uq>^!|MO6?(AIIv-_^RN{u)BZ-stHR%P z=3myQoAK+D7Vwh^>%w0aOGRMBlBL{(=15}nb}!4tN+O{}iLH-|`^7Nc!0uAKZ{4e` zFS?QVO`OfAjlS$y{_8I*dz*_Z9#>5xHLo)&^Q}x&>_Acw$X90R;%mkf-YtYL%~6>= zbzWN+HCzlv)`Cz;p)3km4Q zw*5?5f=o}mKF!wktd^io%E-uku=O<&b(U2gB;vDyt$}Y=zY`;;A~_pzqd3v<7|&lS zbkE8>=@$!y(f#5bVyRjgyH9~RCWyw|%<2b|;B40{qWA=--F;rYs``!fmMG@3-dsia z#LP^BOyR30Su{evJd51gwhbxvzr|uGD{uqbL~Oy z#~QRb7@7=Gzka+fRnsw02R&P579l2*BcI>xDDDwI;7gw*nX{M^!%mXA(J)A6e}!+wU)h;0&VLje=*3rOWjW=3Ybc)W(){kD5k zqIagt_ZSvqd|YfyUYHgFdJtZ&MX*^`?`#iCu2<`il4TNRN+5cXWiEKefyW>e!v zF&lye`AfK1nHKwpRcq8PU}@^in49T{92ZreZZxar2*X0QQ~21)YePbe%@bMNgr)l> zx3b&2V3E8EgZ9svO=)d!qM&upTA3zx!IP&6DH5tC_&M$28y@zCP}Lq>`RM4D-zzV> z?0ax$*a1CSUS2CcPpT((SLt#ITB~Q0#N(+f0Je|g_BK1EJoCS_>A9JIfoE1|`}x+bcHrwd?6@=;8cP5@{vc{M}H7;$vd2{>uAh-@s27{>d)Phl__4OsBht@ zi*;>GW6xwfMUPs@=YA~xne4xFte=0_A)D7FY${2UE$AOX3m5PSJueI~Xm5%dcW#zT zhZ9pIsjrxlCdR?#2cCw8J)zlKw()7}f6>(3gF0HCj&cF`0q5A5T}QuK&` zRTkX&+~znq$%3h4-zRBpt9SR62ZX( zo9Ek{3E-eT>|ZBM*0<{o?^kE68{9r$-`hWJP^ZdC6A2yf!Cp8}RZ_lMfh@PW zpDZkX#2wAX7T|6xxPU~k?TqO&{or@koJ7kz(Jp?-F?2N2@OSf1(D0b+C5pCp1j_eFfH8bR^+ss&uOi$*NbOo zU^U(Ues$tAU!cO6k>*(~o8f*+v(DXNjm+$JTyc4*?@8q&oI3$P_q0B18$mts_qj2^ z6S3O3Ye=ic#eHjVVh^FDLCxg^z6|R6eG~Tn`SECW@lIlL5P0XnFEHEDQmaNP7ag_I zaALGJYI4wth$nA5vf0c!tR}y}z4NL<4{HoIa#n{=f2(9Nw9Mtn- zd}8BvE)qk8tw@k>VC=@w(9e`eJ^vLsh)IgZP0Ha{AP*aeJBK`io#q5dcnkY6`eo_& z=Tx=C!Su#Px6i3WSzwDA43QqJ^^a_mk#?(#HI^N5O>@J;xMabheHXA!yJfn;g;r?P zMzhP4UT}Oi(b7cv`X^-8j7Eq;EOMTuN@5T^qU{~ieec2r%t`O=?=bp>!{V}&2h5so zw_0yV*bN7Xk6~5OiSy0G-sP>c1^(PdO~yOmtB|=1w5R0GsElmE7^|4O1H{tY*B=Ha zFxPmz{kfgaU50kQdl&#j1{MZC2vYA)H%AE(@c~!fC0)%qX!$Hps9GxM|4im}lhcx7 z5wY5PsQBdnOyqeV8ELOutn_);Mbpv}1so48P$^}CD6kWZj`e$MEGBPQLTp!CC_16` z>+`J0dEhbg&=7=^W$$nGdZ!P|3uIjZ!RThq7sPj49>Qy`rteT*1Lm7=KB?Q@Pn`K%ZEpVlo|Mu43+lN#h7(i_}H#w z&|}F;(-ebuVO2q$>bDLj-Q}Mz~driD@p-WW0dgHk5@P}f3rRGHZrc`w+>wra}HOS z0~|e~7AyY?`cU=ZGz`Ou2RuzMSZsxf9{N0m8LX71((Jb7#K%b=fT!Axcldb5B2to9 zN@W!)(ay zOy7@}PwmlLTWfTjafTYJp->4@TaN|g{_aL;|3Oa2&tTyoX6{;PY#;1Eh^L`W5nN_- zAZ`+o74=4h_NFrrtNmM9ksUJgY}Rn$6!0^r_gp)?09{HxXv2TD@_O6peP$-=5vDax zL>j0?p=aYnL0X1VIlRAy|HN5KEkioIxD`xJ(relpcCJMH)CAb?NgJ%7x~O@_2k22 z?0~j5)<7aQYcYRkiPcpmEZOP2{YfV>k#HBM)dLl**7u(eAj^w)eNQj%uZ4tWtQufc zTrfd-YQn#)2Wr+s3_1g++RB*U9Mzsz3wq|BnrU=3956F#TMZj|c>Qc{Zh8CG08jS& zcV(hZDbX&A8dqKrY`AsR9S3zPum}41#BBKOP*79R>S?U7eKKDElnW+#aHj4efXhlz zv8q@yqf>8wetB|!S)~5B9NUr!0SU3f@X^U#aV+Ga+!F~6lY=sme(}mnKtzfmMY%L| zN6((AA3A3_C3&KqGY8A)j)E}u|G2@+$48h1UXt4#;D^3@BK>Z4LW-tP^+YhVxvdu< zMprPkdtAk&MmLjK5BzL*%V<X6AQHRuzinhD49vzm&&$D*U)2OH0?nbH(1_!QMNi&G{Hy+!E`SnyCz zfW=!&<7%xz4e@AT_dzv-uGz2=Yz9yw?f9p^l4XCLX>gt0S>N85A((&tL9saYy=lLN zZeQBQo*lP&;aak{TG^^JS<(s}y=FPbL;|Luo`SwVvvlQf4OPS#JV~r#KXEn>AJExk9%l?%Y7v7H7hBv0WW||;h zddrcKC5G~!>@wJ3+Y233TQAV|Gj-r;_9+WMl=eG zY{^1mA&YvhG}ECt0SAayUxbSj7T-$obu8LJXG;tBSUTq|OoJ_%4BT8CJWgUNk^0n}+l)IxZ9}okEWb(>PJvP`VEX zAe}&Wz-jE7V>|3k%k#*gUXRru!Q4V5CnM27TN7z-OBzEh9!e%opjLi$(_ALbFzzVF zrYQL10;!Opfs5If+>>2Q(U{5!Sy|jF{bs^`*TO9kz2cs;djlfq!9EHq8f@WF93<;q z+Llkp%9M&nw0F39*?n;VOFt4zSn+{eQZW(*)(r#=5=kGe5t?#y3zOWoo7lyWOK0{M zL;K!MQ6v4nrS7|sprpp&u!t!9*b@bH9LzaBhKWAGFaTIGCg`y=)-S82zOp(IvGG%< zptRIRDwjWD_>6FK=e|p~x-eFr+9&-&|EGfGz$r^ciTkU(p-dgRl#evNnRQ81QxswL zce?_L=+!1jJMc4*p;6H{Hozda$8Gom883aUut2bx-|d-qQqH?2>cr_;u4^6}E!NJ+wVFzNImHGL$zaUh zwya+4⁣BcYv(E?b$I-dtv14W{-^Fv#&yyh*PtT>Xc8`2X3mz9KhXpST+h|&ur**oErq zmA!Y*wZK!|_QPZ2!2d*rZkV2qh=>rG1QAw#?9A^uk43)|Afw7)u3+bB*4Ge(MgH7e zTcEL)s_a2mK|iL5q3z1kd9CtnOYMdR0s44|n*%=DVIx%b>Xi zpzL*)ji!7S`&xfNzqI6q%tQ>VGJ6v_Qay!~!v-!iM;&FfukhUJ8RJY)P>9k-9R4Ye zHGiCweoumvB9b=&q)Ta0 zBwGnxohl$l0a(}!k6Sz1R$qp!Ny;=f5>ytAG0QVb6e>w!Q{xt>&;k&9lJ^>Mfm{`+ zJuJ9M3x#Tl)2QQ{x$|_coSb)ZKvHSq~@zLsvYxJFIndO(k zgjBiI^qLHx5_ x&vE^itw!`bOa3=o5c#iL#2J4Bc;cbT3kV_O2jDee*jho3c~;Z literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/histogram-light.png b/testdata/snapshots/darwin/histogram-light.png new file mode 100644 index 0000000000000000000000000000000000000000..c8034032f15d11e8a5d3b2cb1a41b0b1c8bed107 GIT binary patch literal 12658 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

  • V-sydlq`xwM_$bE1$p|BHrjr3Ux0fQwPjF=3+EA0-?gmQ5>H+tt~^ zq}|U^O*VJmD`tz$*E$oId(9t2&jpN;jq-{Fo8KKJzY87k?|XUF)qk7TGNSDp zq{BU?`8A<1GQTN1j;X4`wYHJJ(TPh42^r{B_lfvoF%p#OJ@3Rn(*w%Pv8_l2Asu7hzpZu9>@iHZ>S&!5;Z4I@W&127t7;G&*t)C!hd;p4%tcQ7tuFj~Q(bJfB8}s2>p_Apdc5 z7cG*jpgb~kn85*xm@vUZ5399s8aZnGR|{i9OIq$S%Ssi?8Qy88hxW8e8!K_tMNO%d z!ZCzSfBzJ=#^5{}bY?>fG%=aGU2C+4ljUlQP&+k{8iVzf(=j&usfg5vGZg@U?d#8R z57Pgg_;&RpJkve8e)^{t@{x7^m{`MTf3&p!fBvsV;03`B@PThHM}b~Z`=206Nyv*= Iiy8#}H}KQ%od5s; literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/pull_request_card-light.png b/testdata/snapshots/darwin/pull_request_card-light.png new file mode 100644 index 0000000000000000000000000000000000000000..987ba2360e15d567f148c9b46740d48743bd3826 GIT binary patch literal 28065 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tR34JGRP+c98QLq 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 Ww8MHkARK@7w7j&6RHdY8@c#j?{1U_f literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/review_comment-dark.png b/testdata/snapshots/darwin/review_comment-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..508238e331eb39b43bcdee35a8f674b68360d0f9 GIT binary patch literal 27660 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 z

  • s|;d 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/conversation_item-light.png b/testdata/snapshots/darwin/conversation_item-light.png new file mode 100644 index 0000000000000000000000000000000000000000..cb33c94c911fe5d6f5cd593e4483066491f80545 GIT binary patch literal 9845 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 S7i3uhML|YYx?a*e{C@$^p>1aX literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/conversation_list-dark.png b/testdata/snapshots/darwin/conversation_list-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..493b24742e87ace160c3ca37309af0251b1b537a GIT binary patch literal 2666 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/conversation_search-light.png b/testdata/snapshots/darwin/conversation_search-light.png new file mode 100644 index 0000000000000000000000000000000000000000..8e4136f3a4af90c286f163cb8cc64c3066938189 GIT binary patch literal 13398 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 YheoG-Qdk7NU+96tJ5`x#=?`E32OFeNtpET3 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/cost_estimator-dark.png b/testdata/snapshots/darwin/cost_estimator-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..43d1f4127a1413e7340783586751ee1f1dec4b2f GIT binary patch literal 15580 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/cost_estimator-light.png b/testdata/snapshots/darwin/cost_estimator-light.png new file mode 100644 index 0000000000000000000000000000000000000000..8aa5c2c0787452ee4296c8b7cf2b3dbd06d23eaf GIT binary patch literal 14880 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/date_separator-dark.png b/testdata/snapshots/darwin/date_separator-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..907f6472a775bbb8ebeba5f89125e2dfbf8c699e GIT binary patch literal 5045 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/date_separator-light.png b/testdata/snapshots/darwin/date_separator-light.png new file mode 100644 index 0000000000000000000000000000000000000000..ab2d287950c7a4cce8b8794ca5af717158e4655d GIT binary patch literal 4820 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 I<5~270R2XAO8@`> literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/feedback_form-dark.png b/testdata/snapshots/darwin/feedback_form-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a14bcd5f704671348acc302d3a24bf3755bb5158 GIT binary patch literal 18504 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/feedback_form-light.png b/testdata/snapshots/darwin/feedback_form-light.png new file mode 100644 index 0000000000000000000000000000000000000000..14dbb88a572fbea7f43895d623d485bf58f40dfb GIT binary patch literal 17872 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 dFZ^JD22fUNGGw`MRu literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/project_knowledge_panel-dark.png b/testdata/snapshots/darwin/project_knowledge_panel-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..eb1eca7d0c70fd82443a6c71979227dad2aa23d1 GIT binary patch literal 18329 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/project_knowledge_panel-light.png b/testdata/snapshots/darwin/project_knowledge_panel-light.png new file mode 100644 index 0000000000000000000000000000000000000000..6efc4e71004ebec110efd74ab8e546ba0c5d60c9 GIT binary patch literal 17918 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 CtN^S4 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/project_list-dark.png b/testdata/snapshots/darwin/project_list-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..5a3ec140c018e6e420ee59407d556a2c4038677e GIT binary patch literal 12889 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/project_list-light.png b/testdata/snapshots/darwin/project_list-light.png new file mode 100644 index 0000000000000000000000000000000000000000..2fc92d8b747ee22a6270a8755ccc25d8911367a7 GIT binary patch literal 12229 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