From 96b6c1271d6d846c50fc65b89b401f89045b8e26 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 15:51:57 -0400 Subject: [PATCH] WIP components (as built) --- call_controls.go | 114 ++++++++ call_controls_test.go | 61 +++++ channel_list.go | 216 +++++++++++++++ channel_list_test.go | 67 +++++ chat_message.go | 85 ++++++ chat_message_test.go | 60 +++++ docs/components/401-channel-list.md | 42 +++ docs/components/402-chat-message.md | 41 +++ docs/components/403-unread-divider.md | 35 +++ docs/components/404-read-receipt.md | 36 +++ docs/components/405-member-list.md | 42 +++ docs/components/406-user-profile-card.md | 38 +++ docs/components/407-online-status.md | 35 +++ docs/components/408-status-setter.md | 38 +++ docs/components/409-call-controls.md | 41 +++ docs/components/410-video-call-grid.md | 39 +++ docs/components/411-incoming-call-dialog.md | 39 +++ docs/components/412-emoji-picker.md | 39 +++ docs/components/413-pinned-messages.md | 39 +++ docs/components/414-thread-panel.md | 40 +++ docs/components/415-mail-list.md | 39 +++ docs/components/416-mail-reader.md | 39 +++ docs/components/417-mail-composer.md | 43 +++ docs/components/418-recipient-input.md | 37 +++ docs/components/419-quoted-text.md | 36 +++ docs/components/420-snooze-picker.md | 38 +++ emoji_data.go | 71 +++++ emoji_picker.go | 197 ++++++++++++++ emoji_picker_test.go | 142 ++++++++++ example_messaging_test.go | 242 +++++++++++++++++ examples/gallery/pages_messaging.go | 199 +++++++++++++- examples/gallery/pages_messaging_calls.go | 75 ++++++ examples/gallery/pages_messaging_chat.go | 141 ++++++++++ examples/gallery/pages_messaging_mail.go | 179 ++++++++++++ examples/gallery/pages_messaging_people.go | 136 ++++++++++ examples/gallery/pages_messaging_test.go | 122 +++++++++ incoming_call_dialog.go | 91 +++++++ incoming_call_dialog_test.go | 93 +++++++ mail_composer.go | 213 +++++++++++++++ mail_composer_test.go | 187 +++++++++++++ mail_list.go | 139 ++++++++++ mail_list_test.go | 90 +++++++ mail_reader.go | 135 ++++++++++ mail_reader_test.go | 69 +++++ member_list.go | 192 +++++++++++++ member_list_test.go | 99 +++++++ messages_messaging.go | 255 ++++++++++++++++++ messaging_calls_test.go | 25 ++ messaging_icons.go | 15 ++ messaging_mail_test.go | 30 +++ messaging_people_test.go | 36 +++ messaging_regression_test.go | 47 ++++ messaging_small_test.go | 33 +++ online_status.go | 87 ++++++ online_status_test.go | 41 +++ pinned_messages.go | 73 +++++ pinned_messages_test.go | 47 ++++ quoted_text.go | 39 +++ quoted_text_test.go | 48 ++++ read_receipt.go | 90 +++++++ read_receipt_test.go | 38 +++ recipient_input.go | 179 ++++++++++++ recipient_input_test.go | 188 +++++++++++++ snooze_picker.go | 139 ++++++++++ snooze_picker_test.go | 121 +++++++++ status_setter.go | 137 ++++++++++ status_setter_test.go | 105 ++++++++ tags_input.go | 23 +- .../snapshots/darwin/call_controls-dark.png | Bin 0 -> 3916 bytes .../snapshots/darwin/call_controls-light.png | Bin 0 -> 3893 bytes .../snapshots/darwin/channel_list-dark.png | Bin 0 -> 11482 bytes .../snapshots/darwin/channel_list-light.png | Bin 0 -> 11163 bytes .../snapshots/darwin/chat_message-dark.png | Bin 0 -> 21420 bytes .../snapshots/darwin/chat_message-light.png | Bin 0 -> 20773 bytes .../snapshots/darwin/emoji_picker-dark.png | Bin 0 -> 20578 bytes .../snapshots/darwin/emoji_picker-light.png | Bin 0 -> 20646 bytes .../darwin/incoming_call_dialog-dark.png | Bin 0 -> 18098 bytes .../darwin/incoming_call_dialog-light.png | Bin 0 -> 19482 bytes .../snapshots/darwin/mail_composer-dark.png | Bin 0 -> 22432 bytes .../snapshots/darwin/mail_composer-light.png | Bin 0 -> 21872 bytes testdata/snapshots/darwin/mail_list-dark.png | Bin 0 -> 19374 bytes testdata/snapshots/darwin/mail_list-light.png | Bin 0 -> 18980 bytes .../snapshots/darwin/mail_reader-dark.png | Bin 0 -> 31488 bytes .../snapshots/darwin/mail_reader-light.png | Bin 0 -> 30452 bytes .../snapshots/darwin/member_list-dark.png | Bin 0 -> 16463 bytes .../snapshots/darwin/member_list-light.png | Bin 0 -> 15946 bytes .../snapshots/darwin/online_status-dark.png | Bin 0 -> 4014 bytes .../snapshots/darwin/online_status-light.png | Bin 0 -> 3889 bytes .../snapshots/darwin/pinned_messages-dark.png | Bin 0 -> 10904 bytes .../darwin/pinned_messages-light.png | Bin 0 -> 10571 bytes .../snapshots/darwin/quoted_text-dark.png | Bin 0 -> 11912 bytes .../snapshots/darwin/quoted_text-light.png | Bin 0 -> 11530 bytes .../snapshots/darwin/read_receipt-dark.png | Bin 0 -> 5167 bytes .../snapshots/darwin/read_receipt-light.png | Bin 0 -> 4883 bytes .../snapshots/darwin/recipient_input-dark.png | Bin 0 -> 9038 bytes .../darwin/recipient_input-light.png | Bin 0 -> 8766 bytes .../snapshots/darwin/snooze_picker-dark.png | Bin 0 -> 14366 bytes .../snapshots/darwin/snooze_picker-light.png | Bin 0 -> 13738 bytes .../snapshots/darwin/status_setter-dark.png | Bin 0 -> 10404 bytes .../snapshots/darwin/status_setter-light.png | Bin 0 -> 10179 bytes .../snapshots/darwin/thread_panel-dark.png | Bin 0 -> 23400 bytes .../snapshots/darwin/thread_panel-light.png | Bin 0 -> 23255 bytes .../snapshots/darwin/unread_divider-dark.png | Bin 0 -> 2694 bytes .../snapshots/darwin/unread_divider-light.png | Bin 0 -> 2604 bytes .../darwin/user_profile_card-dark.png | Bin 0 -> 17577 bytes .../darwin/user_profile_card-light.png | Bin 0 -> 17152 bytes .../snapshots/darwin/video_call_grid-dark.png | Bin 0 -> 12871 bytes .../darwin/video_call_grid-light.png | Bin 0 -> 13164 bytes thread_panel.go | 101 +++++++ thread_panel_test.go | 77 ++++++ unread_divider.go | 31 +++ unread_divider_test.go | 27 ++ user_profile_card.go | 77 ++++++ user_profile_card_test.go | 43 +++ video_call_grid.go | 107 ++++++++ video_call_grid_test.go | 43 +++ 116 files changed, 6484 insertions(+), 9 deletions(-) create mode 100644 call_controls.go create mode 100644 call_controls_test.go create mode 100644 channel_list.go create mode 100644 channel_list_test.go create mode 100644 chat_message.go create mode 100644 chat_message_test.go create mode 100644 docs/components/401-channel-list.md create mode 100644 docs/components/402-chat-message.md create mode 100644 docs/components/403-unread-divider.md create mode 100644 docs/components/404-read-receipt.md create mode 100644 docs/components/405-member-list.md create mode 100644 docs/components/406-user-profile-card.md create mode 100644 docs/components/407-online-status.md create mode 100644 docs/components/408-status-setter.md create mode 100644 docs/components/409-call-controls.md create mode 100644 docs/components/410-video-call-grid.md create mode 100644 docs/components/411-incoming-call-dialog.md create mode 100644 docs/components/412-emoji-picker.md create mode 100644 docs/components/413-pinned-messages.md create mode 100644 docs/components/414-thread-panel.md create mode 100644 docs/components/415-mail-list.md create mode 100644 docs/components/416-mail-reader.md create mode 100644 docs/components/417-mail-composer.md create mode 100644 docs/components/418-recipient-input.md create mode 100644 docs/components/419-quoted-text.md create mode 100644 docs/components/420-snooze-picker.md create mode 100644 emoji_data.go create mode 100644 emoji_picker.go create mode 100644 emoji_picker_test.go create mode 100644 example_messaging_test.go create mode 100644 examples/gallery/pages_messaging_calls.go create mode 100644 examples/gallery/pages_messaging_chat.go create mode 100644 examples/gallery/pages_messaging_mail.go create mode 100644 examples/gallery/pages_messaging_people.go create mode 100644 examples/gallery/pages_messaging_test.go create mode 100644 incoming_call_dialog.go create mode 100644 incoming_call_dialog_test.go create mode 100644 mail_composer.go create mode 100644 mail_composer_test.go create mode 100644 mail_list.go create mode 100644 mail_list_test.go create mode 100644 mail_reader.go create mode 100644 mail_reader_test.go create mode 100644 member_list.go create mode 100644 member_list_test.go create mode 100644 messages_messaging.go create mode 100644 messaging_calls_test.go create mode 100644 messaging_icons.go create mode 100644 messaging_mail_test.go create mode 100644 messaging_people_test.go create mode 100644 messaging_regression_test.go create mode 100644 messaging_small_test.go create mode 100644 online_status.go create mode 100644 online_status_test.go create mode 100644 pinned_messages.go create mode 100644 pinned_messages_test.go create mode 100644 quoted_text.go create mode 100644 quoted_text_test.go create mode 100644 read_receipt.go create mode 100644 read_receipt_test.go create mode 100644 recipient_input.go create mode 100644 recipient_input_test.go create mode 100644 snooze_picker.go create mode 100644 snooze_picker_test.go create mode 100644 status_setter.go create mode 100644 status_setter_test.go create mode 100644 testdata/snapshots/darwin/call_controls-dark.png create mode 100644 testdata/snapshots/darwin/call_controls-light.png create mode 100644 testdata/snapshots/darwin/channel_list-dark.png create mode 100644 testdata/snapshots/darwin/channel_list-light.png create mode 100644 testdata/snapshots/darwin/chat_message-dark.png create mode 100644 testdata/snapshots/darwin/chat_message-light.png create mode 100644 testdata/snapshots/darwin/emoji_picker-dark.png create mode 100644 testdata/snapshots/darwin/emoji_picker-light.png create mode 100644 testdata/snapshots/darwin/incoming_call_dialog-dark.png create mode 100644 testdata/snapshots/darwin/incoming_call_dialog-light.png create mode 100644 testdata/snapshots/darwin/mail_composer-dark.png create mode 100644 testdata/snapshots/darwin/mail_composer-light.png create mode 100644 testdata/snapshots/darwin/mail_list-dark.png create mode 100644 testdata/snapshots/darwin/mail_list-light.png create mode 100644 testdata/snapshots/darwin/mail_reader-dark.png create mode 100644 testdata/snapshots/darwin/mail_reader-light.png create mode 100644 testdata/snapshots/darwin/member_list-dark.png create mode 100644 testdata/snapshots/darwin/member_list-light.png create mode 100644 testdata/snapshots/darwin/online_status-dark.png create mode 100644 testdata/snapshots/darwin/online_status-light.png create mode 100644 testdata/snapshots/darwin/pinned_messages-dark.png create mode 100644 testdata/snapshots/darwin/pinned_messages-light.png create mode 100644 testdata/snapshots/darwin/quoted_text-dark.png create mode 100644 testdata/snapshots/darwin/quoted_text-light.png create mode 100644 testdata/snapshots/darwin/read_receipt-dark.png create mode 100644 testdata/snapshots/darwin/read_receipt-light.png create mode 100644 testdata/snapshots/darwin/recipient_input-dark.png create mode 100644 testdata/snapshots/darwin/recipient_input-light.png create mode 100644 testdata/snapshots/darwin/snooze_picker-dark.png create mode 100644 testdata/snapshots/darwin/snooze_picker-light.png create mode 100644 testdata/snapshots/darwin/status_setter-dark.png create mode 100644 testdata/snapshots/darwin/status_setter-light.png create mode 100644 testdata/snapshots/darwin/thread_panel-dark.png create mode 100644 testdata/snapshots/darwin/thread_panel-light.png create mode 100644 testdata/snapshots/darwin/unread_divider-dark.png create mode 100644 testdata/snapshots/darwin/unread_divider-light.png create mode 100644 testdata/snapshots/darwin/user_profile_card-dark.png create mode 100644 testdata/snapshots/darwin/user_profile_card-light.png create mode 100644 testdata/snapshots/darwin/video_call_grid-dark.png create mode 100644 testdata/snapshots/darwin/video_call_grid-light.png create mode 100644 thread_panel.go create mode 100644 thread_panel_test.go create mode 100644 unread_divider.go create mode 100644 unread_divider_test.go create mode 100644 user_profile_card.go create mode 100644 user_profile_card_test.go create mode 100644 video_call_grid.go create mode 100644 video_call_grid_test.go diff --git a/call_controls.go b/call_controls.go new file mode 100644 index 0000000..4d12d1a --- /dev/null +++ b/call_controls.go @@ -0,0 +1,114 @@ +package mujica + +import ( + "log/slog" + "runtime" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// CallState is what the caller's call reports. +type CallState struct { + Muted, CameraOff, Sharing bool +} + +// CallControlsOptions are the callbacks; every one is required. +type CallControlsOptions struct { + OnMute, OnCamera, OnShare func(on bool) + OnHangUp func() + Disabled bool +} + +type callKey struct { + key ui.Key + letter string + shift bool +} + +var ( + callMute = callKey{ui.KeyD, "D", false} + callCamera = callKey{ui.KeyE, "E", false} + callShare = callKey{ui.KeyS, "S", true} + callHangUp = callKey{ui.KeyH, "H", true} +) + +// pressed reports the shortcut anywhere in the window. +func (k callKey) pressed(c *ui.Context) bool { + mods := ui.Cmd + if k.shift { + mods |= ui.Shift + } + return c.Shortcut(mods, k.key) +} + +// String formats the platform’s shortcut label. +func (k callKey) String() string { + mac := runtime.GOOS == "darwin" + keys := []string{"Mod"} + if k.shift { + keys = append(keys, "Shift") + } + out := "" + for i, name := range append(keys, k.letter) { + face, _ := kbdKey(name, mac) + if i > 0 && !mac { + out += "+" + } + out += face + } + return out +} + +// CallControls provides call actions and window shortcuts. +func CallControls(c *ui.Context, st CallState, opts CallControlsOptions) *ui.Element { + if opts.OnMute == nil || opts.OnCamera == nil || opts.OnShare == nil || opts.OnHangUp == nil { + panic("mujica: CallControls needs every callback") + } + k := Tokens(c) + u := Density(c).Unit() + row := ui.Row(c).Gap(u*2).Padding(u*2, u*3).AlignItems(ui.Center).Radius(theme.CardRadius). + Background(k.Surface).Border(theme.BorderWidth, k.Border).FocusGroup(ui.Horizontal).Role(ui.RoleToolbar). + Label(msg(c, "call_controls.label")).Disabled(opts.Disabled) + live := !row.IsDisabled() + report := func(name string, on bool, fn func(bool)) { + slog.Debug("mujica: call_controls "+name, "on", on) + fn(on) + } + row.Children(func() { + toggle := func(off, on *ui.SVG, offKey, onKey string, state bool, key callKey, name string, fn func(bool)) { + icon, label := off, msg(c, offKey) + if state { + icon, label = on, msg(c, onKey) + } + b := mediaToggleAction(c, icon, label, state).Size(40, 40).Tooltip(label + " (" + key.String() + ")") + if live && b.Clicked() { + report(name, !state, fn) + } + } + toggle(mediaMic, msgMicOff, "call_controls.mute", "call_controls.unmute", st.Muted, callMute, "mute", opts.OnMute) + toggle(mediaCamera, msgVideoOff, "call_controls.cameraOff", "call_controls.cameraOn", st.CameraOff, callCamera, "camera", opts.OnCamera) + toggle(msgShare, msgShare, "call_controls.share", "call_controls.stopShare", st.Sharing, callShare, "share", opts.OnShare) + hang := Button(c, msg(c, "call_controls.hangUp"), ButtonOptions{Variant: Danger, Icon: msgHangUp}). + Tooltip(msg(c, "call_controls.hangUp") + " (" + callHangUp.String() + ")") + if live && hang.Clicked() { + slog.Debug("mujica: call_controls hang up") + opts.OnHangUp() + } + }) + if live { + switch { + case callMute.pressed(c): + report("mute", !st.Muted, opts.OnMute) + case callCamera.pressed(c): + report("camera", !st.CameraOff, opts.OnCamera) + case callShare.pressed(c): + report("share", !st.Sharing, opts.OnShare) + case callHangUp.pressed(c): + slog.Debug("mujica: call_controls hang up") + opts.OnHangUp() + } + } + return row +} diff --git a/call_controls_test.go b/call_controls_test.go new file mode 100644 index 0000000..4b2fa45 --- /dev/null +++ b/call_controls_test.go @@ -0,0 +1,61 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestCallControlsClicksAndShortcuts(t *testing.T) { + st := CallState{Muted: true} + var k callCalls + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).AlignItems(ui.Start).Children(func() { + CallControls(c, st, k.opts()) + Button(c, "Elsewhere", ButtonOptions{}) + }) + }, 500, 200) + for _, name := range []string{"Unmute", "Turn camera off", "Share screen", "Leave"} { + if err := tt.Click(name); err != nil { + t.Fatal(err) + } + } + if len(k.mute) != 1 || k.mute[0] || len(k.camera) != 1 || !k.camera[0] || len(k.share) != 1 || !k.share[0] || k.hang != 1 { + t.Fatalf("clicks %+v", k) + } + if err := tt.Click("Elsewhere"); err != nil { + t.Fatal(err) + } + tt.Key(ui.Cmd, ui.KeyD) + tt.Key(ui.Cmd, ui.KeyE) + tt.Key(ui.Cmd|ui.Shift, ui.KeyS) + tt.Key(ui.Cmd|ui.Shift, ui.KeyH) + if len(k.mute) != 2 || len(k.camera) != 2 || len(k.share) != 2 || k.hang != 2 { + t.Fatalf("shortcuts %+v", k) + } +} + +func TestCallControlsDisabled(t *testing.T) { + var k callCalls + o := k.opts() + o.Disabled = true + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + CallControls(c, CallState{}, o) + }, 500, 200) + _ = tt.Click("Mute") + tt.Key(ui.Cmd, ui.KeyD) + tt.Key(ui.Cmd|ui.Shift, ui.KeyH) + if len(k.mute) != 0 || k.hang != 0 { + t.Fatalf("disabled controls reported %+v", k) + } + mediaPanics(t, "no callbacks", func(c *ui.Context) { CallControls(c, CallState{}, CallControlsOptions{}) }) +} + +func TestCallControlsSnapshot(t *testing.T) { + var k callCalls + snapshot(t, "call_controls", 420, 120, func(c *ui.Context) { + ui.Column(c).Padding(20).AlignItems(ui.Start).Children(func() { CallControls(c, CallState{Muted: true, Sharing: true}, k.opts()) }) + }) +} diff --git a/channel_list.go b/channel_list.go new file mode 100644 index 0000000..f929c86 --- /dev/null +++ b/channel_list.go @@ -0,0 +1,216 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// Channel supplies channel or direct-conversation data. +type Channel struct { + ID, Name string + // Direct marks a private conversation, shown with the person's presence. + Direct bool + Presence Presence + Unread int + Muted bool + Pinned bool +} + +// ChannelGroup is a titled, collapsible section of channels. +type ChannelGroup struct { + ID, Title string + Channels []Channel +} + +// ChannelListOptions configure a ChannelList. +type ChannelListOptions struct { + // Height defaults to 360 DIP. + Height float32 + // Revision invalidates grouped rows after in-place data edits. + Revision int + Disabled bool +} + +type channelListKey struct{} + +type channelIndex struct{ group, item int } + +type channelListState struct { + list ui.ListState + folded map[string]bool + first *ChannelGroup + count, revision int + rows []channelIndex +} + +// ChannelList chooses a channel from collapsible, virtualized groups. +func ChannelList(c *ui.Context, selected *string, groups []ChannelGroup, opts ChannelListOptions) ChoiceResult { + if opts.Height < 0 { + panic("mujica: ChannelList Height must be nonnegative") + } + k := Tokens(c) + d := Density(c) + col := ui.Column(c).Disabled(opts.Disabled) + st := ui.Local(col, channelListKey{}, func() channelListState { + return channelListState{folded: map[string]bool{}} + }) + var first *ChannelGroup + if len(groups) > 0 { + first = &groups[0] + } + if st.rows == nil || st.first != first || st.count != len(groups) || st.revision != opts.Revision { + st.first, st.count, st.revision = first, len(groups), opts.Revision + channelRows(st, groups) + } + st.list.Key = func(i int) any { + r := st.rows[i] + if r.item < 0 { + return "group:" + groups[r.group].ID + } + return "channel:" + groups[r.group].Channels[r.item].ID + } + h := opts.Height + if h == 0 { + h = 360 + } + h = min(h, float32(len(st.rows))*d.ControlHeight()) + old := *selected + col.Children(func() { + ui.List(c, &st.list, len(st.rows), func(i int) { + r := st.rows[i] + g := groups[r.group] + if r.item < 0 { + open := !st.folded[g.ID] + if channelHeader(c, k, g, open) && !col.IsDisabled() { + st.folded[g.ID] = open + st.first = nil + st.count = -1 + c.Invalidate() + slog.Debug("mujica: channel_list fold", "group", g.ID, "open", !open) + } + return + } + ch := g.Channels[r.item] + if channelRow(c, k, ch, ch.ID == *selected) && !col.IsDisabled() { + *selected = ch.ID + } + }).Height(h).FocusGroup(ui.Vertical).Role(ui.RoleTree).Label(msg(c, "channel_list.label")) + }) + changed := *selected != old + if changed { + slog.Debug("mujica: channel_list select", "id", *selected) + } + return ChoiceResult{Element: col, changed: changed} +} + +func channelRows(st *channelListState, groups []ChannelGroup) { + seen, groupIDs := map[string]bool{}, map[string]bool{} + rows := []channelIndex{} + for gi, g := range groups { + if g.ID == "" || g.Title == "" || groupIDs[g.ID] { + panic("mujica: ChannelList needs unique group IDs and titles") + } + groupIDs[g.ID] = true + rows = append(rows, channelIndex{gi, -1}) + for _, ch := range g.Channels { + if ch.ID == "" || ch.Name == "" || seen[ch.ID] || ch.Unread < 0 { + panic("mujica: ChannelList needs unique channel IDs, names and nonnegative Unread") + } + ch.Presence.key() + seen[ch.ID] = true + } + if st.folded[g.ID] { + continue + } + for _, pinned := range []bool{true, false} { + for ci, ch := range g.Channels { + if ch.Pinned == pinned { + rows = append(rows, channelIndex{gi, ci}) + } + } + } + } + st.rows = rows +} + +func channelHeader(c *ui.Context, k theme.Tokens, g ChannelGroup, open bool) bool { + u := Density(c).Unit() + b := ui.ButtonBase(c).MinHeight(Density(c).ControlHeight()).Justify(ui.Start).Gap(u).Padding(0, u*2).Radius(theme.ControlRadius). + Label(g.Title).Role(ui.RoleTreeItem).TextColor(k.TextMuted).Transition(colorFade) + internal.Ring(b, k.Focus, theme.ControlRadius) + if b.Hovered() { + b.Background(k.SurfaceHover) + } + arrow := "chevron-down" + if !open { + arrow = "chevron-right" + } + b.Children(func() { + ui.Icon(c, icons.Must(arrow)).Size(14, 14) + ui.Text(c, g.Title).FontSize(FontSize(c, theme.CaptionSize)).FontWeight(600).SingleLine() + }) + if b.IsDisabled() { + return false + } + toggled := b.Clicked() + if open && b.Shortcut(0, ui.KeyLeft) || !open && b.Shortcut(0, ui.KeyRight) { + toggled = true + } + return toggled +} + +// channelRow is one channel button; true means it was chosen. +func channelRow(c *ui.Context, k theme.Tokens, ch Channel, on bool) bool { + d := Density(c) + u := d.Unit() + label := ch.Name + if ch.Unread > 0 { + label = fmt.Sprintf(msg(c, "channel_list.unread"), ch.Name, ch.Unread) + } + b := ui.ButtonBase(c).Key(ch.ID).MinHeight(d.ControlHeight()).Justify(ui.Start).Gap(u*2).Padding(0, u*2, 0, u*5). + Radius(theme.ControlRadius).Label(label).Role(ui.RoleTreeItem).Selected(on).Background(ui.Transparent). + TextColor(k.Text).Transition(colorFade) + internal.Ring(b, k.Focus, theme.ControlRadius) + switch { + case on: + b.Background(k.Selection).BorderWidth(0, 0, 0, 3).BorderColor(k.AccentText) + case b.Hovered(): + b.Background(k.SurfaceHover) + } + if ch.Muted && !on { + b.TextColor(k.TextMuted) + } + b.Children(func() { + ui.Box(c).Width(16).Center().Shrink(0).Children(func() { + if ch.Direct { + OnlineStatus(c, ch.Presence, OnlineStatusOptions{HideText: true, Size: 9}) + } else { + ui.Text(c, "#").TextColor(k.TextMuted) + } + }) + name := ui.Text(c, ch.Name).SingleLine().Grow(1).MinWidth(0) + if ch.Unread > 0 && !ch.Muted { + name.FontWeight(600) + } + if ch.Pinned { + ui.Icon(c, msgPin).Size(13, 13).TextColor(k.TextMuted).Label(msg(c, "channel_list.pinned")) + } + if ch.Muted { + ui.Icon(c, msgBellOff).Size(13, 13).TextColor(k.TextMuted).Label(msg(c, "channel_list.muted")) + } + if ch.Unread > 0 { + tone := BadgeAccent + if ch.Muted { + tone = BadgeNeutral + } + Badge(c, BadgeOptions{Count: ch.Unread, Tone: tone}, nil) + } + }) + return b.Clicked() +} diff --git a/channel_list_test.go b/channel_list_test.go new file mode 100644 index 0000000..166875a --- /dev/null +++ b/channel_list_test.go @@ -0,0 +1,67 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestChannelListSelectFoldAndOrder(t *testing.T) { + sel, n := "", 0 + tt := channelTester(&sel, false, &n) + if err := tt.Click("random, 120 unread"); err != nil { + t.Fatal(err) + } + if sel != "random" || n != 1 || !tt.HasText("99+") { + t.Fatalf("selected %q, changes %d", sel, n) + } + pinned, _ := tt.Find("rehearsal") + general, _ := tt.Find("general, 3 unread") + if pinned.Y >= general.Y { + t.Fatal("pinned channel not first") + } + if err := tt.Click("Direct messages"); err != nil { + t.Fatal(err) + } + if tt.HasText("Uika") { + t.Fatal("folded group still shows its channels") + } +} + +func TestChannelListKeyboard(t *testing.T) { + sel, n := "", 0 + tt := channelTester(&sel, false, &n) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if sel != "rehearsal" { + t.Fatalf("Down, Enter chose %q", sel) + } + tt.Key(0, ui.KeyUp) + tt.Key(0, ui.KeyLeft) + if tt.HasText("general") { + t.Fatal("Left on a header did not fold it") + } + tt.Key(0, ui.KeyRight) + if !tt.HasText("general") { + t.Fatal("Right did not unfold") + } +} + +func TestChannelListDisabledAndBad(t *testing.T) { + sel, n := "", 0 + tt := channelTester(&sel, true, &n) + _ = tt.Click("rehearsal") + if sel != "" || n != 0 { + t.Fatal("disabled list chose") + } + dup := []ChannelGroup{{ID: "a", Title: "A", Channels: []Channel{{ID: "x", Name: "x"}, {ID: "x", Name: "y"}}}} + mediaPanics(t, "duplicate", func(c *ui.Context) { ChannelList(c, &sel, dup, ChannelListOptions{}) }) +} + +func TestChannelListSnapshot(t *testing.T) { + sel := "general" + snapshot(t, "channel_list", 300, 300, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(260).Children(func() { ChannelList(c, &sel, channelTestGroups, ChannelListOptions{}) }) + }) +} diff --git a/chat_message.go b/chat_message.go new file mode 100644 index 0000000..1d24bc8 --- /dev/null +++ b/chat_message.go @@ -0,0 +1,85 @@ +package mujica + +import ( + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// ChatEntry is one message of a person-to-person chat. +type ChatEntry struct { + // ID is unique and stable; Author is required. + ID, Author string + Image *ui.Bitmap + Time time.Time + Text string + Edited bool + // Own marks the user's own messages, shown on the right. + Own bool +} + +// ChatMessageOptions configure a ChatMessage. +type ChatMessageOptions struct { + // Continued hides repeated author details. + Continued bool + // Reply builds a quoted message above the text, as QuoteReply. + Reply func() + // Reactions builds the reaction row below the text. + Reactions func() +} + +// chatMergeGap is how close two messages must be to merge. +const chatMergeGap = 5 * time.Minute + +// ChatContinues merges matching authors within five minutes. +func ChatContinues(prev, cur ChatEntry) bool { + d := cur.Time.Sub(prev.Time) + return prev.Author == cur.Author && prev.Own == cur.Own && d >= 0 && d < chatMergeGap +} + +// ChatMessage displays text, timestamps, edits and interaction slots. +func ChatMessage(c *ui.Context, m ChatEntry, opts ChatMessageOptions) *ui.Element { + if m.Author == "" { + panic("mujica: ChatMessage needs an Author") + } + k := Tokens(c) + u := Density(c).Unit() + role := MessageAssistant + if m.Own { + role = MessageUser + } + bo := MessageBubbleOptions{} + const avatar = 32 + if !opts.Continued { + bo.Name = m.Author + bo.Avatar = func() { Avatar(c, m.Author, AvatarOptions{Image: m.Image, Size: avatar}) } + } else { + bo.Avatar = func() { ui.Box(c).Width(avatar).Shrink(0) } + } + e := MessageBubble(c, role, bo, func() { + if opts.Reply != nil { + opts.Reply() + } + ui.Text(c, m.Text).Selectable().FocusRing(false).LineHeight(theme.LineHeight) + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + if !m.Time.IsZero() { + ui.Text(c, m.Time.Format(msg(c, "chat_message.time"))).FontSize(FontSize(c, theme.CaptionSize)). + TextColor(k.TextMuted).FontFeatures("tnum").SingleLine() + } + if m.Edited { + ui.Text(c, msg(c, "chat_message.edited")).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted). + Italic().SingleLine() + } + }) + if opts.Reactions != nil { + ui.Row(c).Gap(u).Wrap().Children(opts.Reactions) + } + }) + if opts.Continued { + e.Label(m.Author) + e.Margin(-u*2, 0, 0, 0) + } + return e +} diff --git a/chat_message_test.go b/chat_message_test.go new file mode 100644 index 0000000..745c5b0 --- /dev/null +++ b/chat_message_test.go @@ -0,0 +1,60 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func TestChatContinues(t *testing.T) { + at := time.Date(2026, 10, 5, 12, 0, 0, 0, time.UTC) + a := ChatEntry{Author: "Uika", Time: at} + for _, tc := range []struct { + b ChatEntry + want bool + }{ + {ChatEntry{Author: "Uika", Time: at.Add(time.Minute)}, true}, + {ChatEntry{Author: "Uika", Time: at.Add(6 * time.Minute)}, false}, + {ChatEntry{Author: "Mutsumi", Time: at.Add(time.Minute)}, false}, + {ChatEntry{Author: "Uika", Time: at.Add(-time.Minute)}, false}, + } { + if got := ChatContinues(a, tc.b); got != tc.want { + t.Errorf("%+v: %v", tc.b, got) + } + } +} + +func TestChatMessageSlotsAndMerge(t *testing.T) { + at := time.Date(2026, 10, 5, 21, 7, 0, 0, time.UTC) + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Width(500).Children(func() { + ChatMessage(c, ChatEntry{ID: "1", Author: "Uika", Time: at, Text: "Rehearsal at nine."}, ChatMessageOptions{ + Reply: func() { QuoteReply(c, "Sakiko", "When do we start?") }, + Reactions: func() { Tag(c, "👍 2", TagOptions{}) }, + }) + ChatMessage(c, ChatEntry{ID: "2", Author: "Uika", Time: at, Text: "Bring the masks.", Edited: true}, ChatMessageOptions{Continued: true}) + }) + }, 600, 400) + if mediaTextCount(tt, "U") != 1 || mediaTextCount(tt, "Assistant, Uika") != 1 { + t.Fatalf("continued message repeated the author: %v", tt.Texts()) + } + for _, s := range []string{"21:07", "(edited)", "When do we start?", "👍 2"} { + if !tt.HasText(s) { + t.Fatalf("no %q in %v", s, tt.Texts()) + } + } +} + +func TestChatMessageSnapshot(t *testing.T) { + at := time.Date(2026, 10, 5, 21, 7, 0, 0, time.UTC) + snapshot(t, "chat_message", 520, 340, func(c *ui.Context) { + ui.Column(c).Padding(20).Gap(8).Width(480).Children(func() { + ChatMessage(c, ChatEntry{Author: "Uika Misumi", Time: at, Text: "Rehearsal moves to nine."}, ChatMessageOptions{ + Reply: func() { QuoteReply(c, "Sakiko", "When do we start?") }}) + ChatMessage(c, ChatEntry{Author: "Uika Misumi", Time: at, Text: "Bring the masks.", Edited: true}, ChatMessageOptions{Continued: true}) + ChatMessage(c, ChatEntry{Author: "Me", Time: at, Text: "Understood.", Own: true}, ChatMessageOptions{}) + }) + }) +} diff --git a/docs/components/401-channel-list.md b/docs/components/401-channel-list.md new file mode 100644 index 0000000..c19fae9 --- /dev/null +++ b/docs/components/401-channel-list.md @@ -0,0 +1,42 @@ +# 401 ChannelList 频道列表 + +## 用途 + +展示频道与私信、未读计数、静音和置顶标记,支持折叠分组与频道选择。 + +## 最小示例 + +```go +groups := []mujica.ChannelGroup{{ID: "ch", Title: "Channels", Channels: []mujica.Channel{ + {ID: "general", Name: "general", Unread: 3}, + {ID: "rehearsal", Name: "rehearsal", Pinned: true}, +}}} +selected := "general" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ChannelList(c, &selected, groups, mujica.ChannelListOptions{}).Changed() { + _ = selected // show that channel + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`selected *string` 保存频道 ID;`groups []ChannelGroup` 提供分组。分组 ID、频道 ID 必须唯一,名称必填,`Unread` ≥ 0。`Direct`、`Presence`、`Muted`、`Pinned` 控制展示。`Height` 默认 360 DIP;`Disabled` 默认 false;`Revision` 默认 0,原地修改分组或频道数据后递增以刷新缓存。替换分组切片也会刷新。 + +## 状态 + +默认、聚焦和悬停状态沿用主题、密度与文字缩放;适用操作在自身或祖先禁用时停止处理。 + +## 事件 + +`Changed()` 表示选择 ID 发生变化;分组展开状态在组件内保存。 + +## 键盘操作 + +Tab 进入;上下方向键切换行;Enter / Space 选择或折叠;分组标题上的左、右方向键折叠、展开。 + +## 限制 + +业务连接、静音设置与置顶持久化由调用方维护。分组排序与校验在数据或 Revision 变化时进行,可见行由 MyGo List 构建。 diff --git a/docs/components/402-chat-message.md b/docs/components/402-chat-message.md new file mode 100644 index 0000000..6514ec7 --- /dev/null +++ b/docs/components/402-chat-message.md @@ -0,0 +1,41 @@ +# 402 ChatMessage 聊天消息 + +## 用途 + +展示连续聊天消息、发送时间、编辑标记,以及调用方提供的回复和回应插槽。 + +## 最小示例 + +```go +prev := mujica.ChatEntry{ID: "1", Author: "Uika", Time: time.Now(), Text: "Rehearsal at nine."} +m := mujica.ChatEntry{ID: "2", Author: "Uika", Time: time.Now(), Text: "Bring the masks.", Edited: true} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ChatMessage(c, prev, mujica.ChatMessageOptions{}) + mujica.ChatMessage(c, m, mujica.ChatMessageOptions{ + Continued: mujica.ChatContinues(prev, m), + Reactions: func() { mujica.Tag(c, "👍 2", mujica.TagOptions{}) }, + }) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`ChatEntry` 包含 `ID`、必填的 `Author`、`Image`、`Time`、`Text`、`Edited`、`Own`。`ChatMessageOptions.Continued` 默认 false;`Reply` 与 `Reactions` 为可选插槽。`ChatContinues(prev, cur)` 要求同一作者、相同 Own、间隔非负且小于五分钟。 + +## 状态 + +状态由调用方数据控制;浅深主题、密度与文字缩放随窗口设置变化。适用插槽操作沿用控件焦点和禁用状态。 + +## 事件 + +插槽中的按钮、链接和回应事件由调用方处理。 + +## 键盘操作 + +可选文字支持选择复制;插槽控件按 Tab 访问。 + +## 限制 + +调用方计算 Continued 或使用 ChatContinues;回复与回应的业务逻辑在插槽中实现。 diff --git a/docs/components/403-unread-divider.md b/docs/components/403-unread-divider.md new file mode 100644 index 0000000..acf022b --- /dev/null +++ b/docs/components/403-unread-divider.md @@ -0,0 +1,35 @@ +# 403 UnreadDivider 未读分隔线 + +## 用途 + +标记新消息开始位置,并朗读完整未读计数。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.UnreadDivider(c, 3) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`count int` 必须 ≥ 0;0 显示“新消息”,正值显示完整计数。 + +## 状态 + +状态由调用方数据控制;浅深主题、密度与文字缩放随窗口设置变化。适用插槽操作沿用控件焦点和禁用状态。 + +## 事件 + +纯展示,计数由调用方更新。 + +## 键盘操作 + +展示组件保持自然焦点序列。 + +## 限制 + +组件展示调用方提供的计数。 diff --git a/docs/components/404-read-receipt.md b/docs/components/404-read-receipt.md new file mode 100644 index 0000000..59938ff --- /dev/null +++ b/docs/components/404-read-receipt.md @@ -0,0 +1,36 @@ +# 404 ReadReceipt 已读回执 + +## 用途 + +通过勾选标记与文字展示发送进度,已读时显示多人头像。 + +## 最小示例 + +```go +readers := []mujica.AvatarItem{{Name: "Uika"}, {Name: "Mutsumi"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ReadReceipt(c, mujica.ReceiptRead, mujica.ReadReceiptOptions{Readers: readers}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`state ReceiptState` 为 `ReceiptSent`、`ReceiptDelivered`、`ReceiptRead`,零值表示已发送。`Readers []AvatarItem` 提供已读头像;`Max` 默认 3,必须 ≥ 0。 + +## 状态 + +状态由调用方数据控制;浅深主题、密度与文字缩放随窗口设置变化。适用插槽操作沿用控件焦点和禁用状态。 + +## 事件 + +纯展示,回执进度与读者由调用方更新。 + +## 键盘操作 + +展示组件保持自然焦点序列。 + +## 限制 + +已读数据由调用方提供;头像超过 Max 时显示剩余数量。 diff --git a/docs/components/405-member-list.md b/docs/components/405-member-list.md new file mode 100644 index 0000000..3c5b809 --- /dev/null +++ b/docs/components/405-member-list.md @@ -0,0 +1,42 @@ +# 405 MemberList 成员列表 + +## 用途 + +将成员分成在线、离线两组,展示头像、状态、角色并提供选择与打开事件。 + +## 最小示例 + +```go +var s mujica.MemberListState +members := []mujica.Member{ + {ID: "1", Name: "Sakiko", Presence: mujica.PresenceOnline, Role: "Leader"}, + {ID: "2", Name: "Umiri", Presence: mujica.PresenceOffline}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MemberList(c, &s, members, mujica.MemberListOptions{}); r.Opened != "" { + _ = r.Opened // show that member's profile + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`MemberListState` 保存 `Selected` 和滚动位置;`members []Member` 的 ID 唯一、姓名必填。`Image`、`Presence`、`Role` 控制展示。`Height` 默认 360 DIP;`Disabled` 默认 false。修改在线分组时替换成员切片,缓存仅在切片变化时重建。 + +## 状态 + +默认、聚焦和悬停状态沿用主题、密度与文字缩放;适用操作在自身或祖先禁用时停止处理。 + +## 事件 + +`Changed()` 表示选中成员变化;`Opened` 返回 Enter 或双击打开的成员 ID。 + +## 键盘操作 + +Tab 聚焦列表;上下方向键选择;Home / End 首尾;Enter 或双击打开成员。 + +## 限制 + +分组缓存依据切片身份与长度;成员数据变化后替换切片。 diff --git a/docs/components/406-user-profile-card.md b/docs/components/406-user-profile-card.md new file mode 100644 index 0000000..778b25b --- /dev/null +++ b/docs/components/406-user-profile-card.md @@ -0,0 +1,38 @@ +# 406 UserProfileCard 用户资料卡 + +## 用途 + +集中展示用户头像、姓名、在线状态、角色、自定义状态与操作插槽。 + +## 最小示例 + +```go +profile := mujica.UserProfile{Name: "Sakiko Togawa", Presence: mujica.PresenceBusy, Role: "Keyboard", Status: "In rehearsal"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.UserProfileCard(c, profile, mujica.UserProfileCardOptions{Actions: func() { + mujica.Button(c, "Message", mujica.ButtonOptions{}) + }}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`UserProfile.Name` 必填;`Image`、`Presence`、`Role`、`Status`、`About` 提供展示内容。`UserProfileCardOptions.Width` 默认 300 DIP,必须 ≥ 0;`Actions func()` 提供可选操作。 + +## 状态 + +状态由调用方数据控制;浅深主题、密度与文字缩放随窗口设置变化。适用插槽操作沿用控件焦点和禁用状态。 + +## 事件 + +操作由 `Actions` 插槽中的控件返回。 + +## 键盘操作 + +Tab 访问操作插槽;Enter / Space 激活按钮。 + +## 限制 + +业务动作、头像加载与个人资料更新由调用方处理。 diff --git a/docs/components/407-online-status.md b/docs/components/407-online-status.md new file mode 100644 index 0000000..8e59b96 --- /dev/null +++ b/docs/components/407-online-status.md @@ -0,0 +1,35 @@ +# 407 OnlineStatus 在线状态 + +## 用途 + +用圆形、月牙、横杠圆形和空心圆配合文字表示四种在线状态。 + +## 最小示例 + +```go +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.OnlineStatus(c, mujica.PresenceAway, mujica.OnlineStatusOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`p Presence` 的零值为离线,支持 `PresenceOnline`、`PresenceAway`、`PresenceBusy`、`PresenceOffline`。`HideText` 默认 false;隐藏文字时保留名称和提示。`Size` 默认 10 DIP,必须 ≥ 0。 + +## 状态 + +状态由调用方数据控制;浅深主题、密度与文字缩放随窗口设置变化。适用插槽操作沿用控件焦点和禁用状态。 + +## 事件 + +纯展示,在线状态由调用方更新。 + +## 键盘操作 + +展示组件保持自然焦点序列。 + +## 限制 + +在线状态由调用方提供;隐藏文字仍保留状态形状和无障碍名称。 diff --git a/docs/components/408-status-setter.md b/docs/components/408-status-setter.md new file mode 100644 index 0000000..7e1f96b --- /dev/null +++ b/docs/components/408-status-setter.md @@ -0,0 +1,38 @@ +# 408 StatusSetter 状态设置 + +## 用途 + +编辑自定义状态文字和表情,选择清除期限。 + +## 最小示例 + +```go +status := mujica.CustomStatus{Emoji: "🎻", Text: "Rehearsing"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.StatusSetter(c, &status, mujica.StatusSetterOptions{}).Changed() { + _ = status // publish it; clear it once status.Until passes + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`CustomStatus` 保存 `Emoji`、`Text`、`Until`;零 `Until` 表示持续保留。`Location` 默认 `time.Local`;`Disabled` 默认 false。清除选项为持续保留、30 分钟、1 小时、4 小时、当天结束、本周结束。 + +## 状态 + +默认、聚焦和悬停状态沿用主题、密度与文字缩放;适用操作在自身或祖先禁用时停止处理。 + +## 事件 + +`Changed()` 表示表情、文字或清除期限改变。调用方载入已有期限时显示实际时间,选择持续保留可清除期限。 + +## 键盘操作 + +Tab 访问表情、文字、期限和清除按钮;选择器用方向键移动、Enter 确认、Escape 关闭。 + +## 限制 + +Until 作为业务期限返回,调用方负责届时清除状态;组件保持空闲。 diff --git a/docs/components/409-call-controls.md b/docs/components/409-call-controls.md new file mode 100644 index 0000000..c0ad5dc --- /dev/null +++ b/docs/components/409-call-controls.md @@ -0,0 +1,41 @@ +# 409 CallControls 通话控制 + +## 用途 + +提供静音、摄像头、屏幕共享和挂断操作,状态由调用方回传。 + +## 最小示例 + +```go +st := mujica.CallState{} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CallControls(c, st, mujica.CallControlsOptions{ + OnMute: func(on bool) { st.Muted = on }, + OnCamera: func(off bool) { st.CameraOff = off }, + OnShare: func(on bool) { st.Sharing = on }, + OnHangUp: func() {}, // leave the call + }) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`CallState` 包含 `Muted`、`CameraOff`、`Sharing`。`OnMute`、`OnCamera`、`OnShare`、`OnHangUp` 均必填。摄像头回调参数表示是否关闭。`Disabled` 默认 false。 + +## 状态 + +默认、聚焦和悬停状态沿用主题、密度与文字缩放;适用操作在自身或祖先禁用时停止处理。 + +## 事件 + +每次操作调用对应回调一次;调用方回传更新后的 CallState。 + +## 键盘操作 + +Tab 进入工具栏;左右方向键移动;Enter / Space 激活。Cmd/Ctrl+D 静音,Cmd/Ctrl+E 摄像头,Cmd/Ctrl+Shift+S 共享,Cmd/Ctrl+Shift+H 挂断。 + +## 限制 + +通话、设备和屏幕采集由调用方处理;快捷键作用于当前窗口。 diff --git a/docs/components/410-video-call-grid.md b/docs/components/410-video-call-grid.md new file mode 100644 index 0000000..2d1b852 --- /dev/null +++ b/docs/components/410-video-call-grid.md @@ -0,0 +1,39 @@ +# 410 VideoCallGrid 视频通话宫格 + +## 用途 + +按宫格显示调用方提供的视频帧,标记正在发言和静音的参与者。 + +## 最小示例 + +```go +people := []mujica.CallParticipant{ + {ID: "1", Name: "Sakiko", Speaking: true}, // Frame: the latest decoded frame + {ID: "2", Name: "Uika", Muted: true}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.VideoCallGrid(c, people, mujica.VideoCallGridOptions{}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`people []CallParticipant` 的 ID 唯一、Name 必填;`Frame ui.ImageSource` 提供视频帧,`Image` 提供头像。`Muted`、`CameraOff`、`Speaking` 控制状态。`Columns` 默认 0,自动选择列数,必须 ≥ 0。 + +## 状态 + +状态由调用方数据控制;浅深主题、密度与文字缩放随窗口设置变化。适用插槽操作沿用控件焦点和禁用状态。 + +## 事件 + +纯展示,帧和参与者状态由调用方更新。 + +## 键盘操作 + +Tab 进入宫格;方向键移动参与者焦点并读取状态。 + +## 限制 + +视频解码、采集与帧更新由调用方处理,更新后调用 c.Invalidate()。 diff --git a/docs/components/411-incoming-call-dialog.md b/docs/components/411-incoming-call-dialog.md new file mode 100644 index 0000000..26290c3 --- /dev/null +++ b/docs/components/411-incoming-call-dialog.md @@ -0,0 +1,39 @@ +# 411 IncomingCallDialog 来电对话框 + +## 用途 + +显示语音或视频来电,提供接听、拒绝与可配置的初始焦点。 + +## 最小示例 + +```go +ringing := true +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.IncomingCallDialog(c, &ringing, mujica.IncomingCall{Caller: "Sakiko", Video: true}, mujica.IncomingCallOptions{ + OnAccept: func(video bool) {}, // join, with the camera on when video + OnDecline: func() {}, + }) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`open *bool` 控制显示;`IncomingCall.Caller` 必填,`Image` 为头像,`Video` 默认 false。`OnAccept func(video bool)` 与 `OnDecline func()` 必填。`FocusAccept` 默认 false,初始聚焦拒绝;`Disabled` 默认 false,禁用时关闭。 + +## 状态 + +默认、聚焦和悬停状态沿用主题、密度与文字缩放;适用操作在自身或祖先禁用时停止处理。 + +## 事件 + +接听调用 `OnAccept`,视频接听参数为 true;拒绝和 Escape 调用 `OnDecline`。完成后设置 `*open=false`。 + +## 键盘操作 + +默认焦点为拒绝;Tab 循环访问操作;Enter / Space 激活;Escape 拒绝;关闭后恢复焦点。 + +## 限制 + +来电数据和通话连接由调用方处理;点击遮罩保持来电显示;禁用关闭时回调保持静默。 diff --git a/docs/components/412-emoji-picker.md b/docs/components/412-emoji-picker.md new file mode 100644 index 0000000..a59a711 --- /dev/null +++ b/docs/components/412-emoji-picker.md @@ -0,0 +1,39 @@ +# 412 EmojiPicker 表情选择器 + +## 用途 + +按分类、搜索与最近使用选择表情,并给支持肤色的表情添加肤色修饰符。 + +## 最小示例 + +```go +var recent []string +tone := 0 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.EmojiPicker(c, mujica.EmojiPickerOptions{Recent: &recent, Tone: &tone}); r.Picked != "" { + _ = r.Picked // insert it + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`EmojiPickerOptions.Recent *[]string` 保存最近选择,选择时去重并保留最新 24 个;`Tone *int` 可选,范围 0–5;`Disabled` 默认 false。返回 `EmojiResult` 的命名字段 `Element` 与 `Picked`。 + +## 状态 + +默认、聚焦和悬停状态沿用主题、密度与文字缩放;适用操作在自身或祖先禁用时停止处理。 + +## 事件 + +`Picked` 是本帧选择的表情;选择时同时更新 Recent,肤色按钮更新 Tone。 + +## 键盘操作 + +Tab 访问搜索、肤色、分类、表情;方向键在组内移动;Enter / Space 选择。 + +## 限制 + +内置常用表情子集;对支持肤色的条目应用修饰符。 diff --git a/docs/components/413-pinned-messages.md b/docs/components/413-pinned-messages.md new file mode 100644 index 0000000..3d27874 --- /dev/null +++ b/docs/components/413-pinned-messages.md @@ -0,0 +1,39 @@ +# 413 PinnedMessages 置顶消息 + +## 用途 + +展示虚拟化置顶消息列表,发出跳转和取消置顶事件。 + +## 最小示例 + +```go +pins := []mujica.ChatEntry{{ID: "a", Author: "Sakiko", Text: "Rehearsal moves to nine."}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.PinnedMessages(c, pins, mujica.PinnedMessagesOptions{}) + if r.Unpinned != "" { + pins = pins[:0] // unpin it + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`pins []ChatEntry` 的 ID 与 Author 必填。`Height` 默认 320 DIP,必须 ≥ 0;`Disabled` 默认 false。返回 `PinnedMessagesResult`,包含命名字段 `Element`、`Jump`、`Unpinned`。 + +## 状态 + +默认、聚焦和悬停状态沿用主题、密度与文字缩放;适用操作在自身或祖先禁用时停止处理。 + +## 事件 + +`Jump` 和 `Unpinned` 返回本帧操作的消息 ID;调用方更新消息定位和置顶数据。 + +## 键盘操作 + +Tab 访问跳转与取消置顶;方向键移动;Enter / Space 激活。 + +## 限制 + +调用方维护置顶消息;列表行只构建可见部分。 diff --git a/docs/components/414-thread-panel.md b/docs/components/414-thread-panel.md new file mode 100644 index 0000000..99abd32 --- /dev/null +++ b/docs/components/414-thread-panel.md @@ -0,0 +1,40 @@ +# 414 ThreadPanel 话题侧栏 + +## 用途 + +在侧栏展示原消息与虚拟化回复列表,提供回复输入、发送和关闭。 + +## 最小示例 + +```go +open := true +root := mujica.ChatEntry{ID: "r", Author: "Sakiko", Text: "Set list for Friday?"} +var replies []mujica.ChatEntry +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.ThreadPanel(c, &open, root, replies, mujica.ThreadPanelOptions{}); r.Sent != "" { + replies = append(replies, mujica.ChatEntry{ID: r.Sent, Author: "Me", Text: r.Sent, Own: true}) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`open *bool` 控制显示;`root ChatEntry` 提供原消息,`replies []ChatEntry` 提供回复。`Width` 默认 360 DIP并受窗口宽度约束;`Disabled` 默认 false,禁用时关闭面板。回复 ID 必须稳定唯一。 + +## 状态 + +默认、聚焦和悬停状态沿用主题、密度与文字缩放;适用操作在自身或祖先禁用时停止处理。 + +## 事件 + +`Sent` 返回本帧发送的非空回复,发送后清空输入;关闭时设置 `*open=false`。 + +## 键盘操作 + +Tab 访问关闭、回复和发送;Enter 发送回复;Escape 关闭面板。 + +## 限制 + +回复发送和持久化由调用方完成;原消息区限高滚动,回复列表独立滚动。 diff --git a/docs/components/415-mail-list.md b/docs/components/415-mail-list.md new file mode 100644 index 0000000..758e294 --- /dev/null +++ b/docs/components/415-mail-list.md @@ -0,0 +1,39 @@ +# 415 MailList 邮件列表 + +## 用途 + +展示虚拟化邮件列表,包含未读粗体、星标、附件计数、多选与打开事件。 + +## 最小示例 + +```go +var s mujica.ListState[string] +mails := []mujica.MailItem{{ID: "1", From: "Sakiko", Subject: "Second act", Unread: true, Attachments: 1}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MailList(c, &s, mails, mujica.MailListOptions{}); r.Starred != "" { + mails[0].Starred = !mails[0].Starred + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`ListState[string]` 保存滚动与选择;`MailItem` 包含必填 ID、`From`、`Subject`、`Snippet`、`Time`、`Unread`、`Starred`、`Attachments`。`Height` 默认 420 DIP,必须 ≥ 0;`Disabled` 默认 false。 + +## 状态 + +默认、聚焦和悬停状态沿用主题、密度与文字缩放;适用操作在自身或祖先禁用时停止处理。 + +## 事件 + +`Changed()` 表示选择变化;`Opened` 返回打开的邮件 ID;`Starred` 返回请求切换星标的 ID。调用方更新数据。 + +## 键盘操作 + +上下方向键、Home / End 移动选择;Enter 或双击打开;S 请求星标;Cmd/Ctrl+A 全选;Cmd/Ctrl 点击切换单项,Shift 点击选择范围。 + +## 限制 + +星标、已读更新、邮件下载与打开由调用方处理;列表只构建可见行。 diff --git a/docs/components/416-mail-reader.md b/docs/components/416-mail-reader.md new file mode 100644 index 0000000..6f8283b --- /dev/null +++ b/docs/components/416-mail-reader.md @@ -0,0 +1,39 @@ +# 416 MailReader 邮件阅读器 + +## 用途 + +展示邮件头、纯文本或安全 Markdown 子集正文,以及附件操作。 + +## 最小示例 + +```go +m := mujica.Mail{From: "Sakiko", Subject: "Second act", Body: "The score is attached.\n> Can you send it?", + Attachments: []mujica.MailAttachment{{Name: "score.pdf", Size: 2048}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MailReader(c, m); r.Link != "" { + c.OpenURL(r.Link) + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`Mail.From`、`Subject` 必填;`To`、`Cc`、`Date`、`Body` 为邮件内容。`Format` 默认 `MailPlain`,也支持 `MailMarkdown`。`Attachments []MailAttachment` 提供名称、字节数和 MIME 类型。 + +## 状态 + +默认、聚焦和悬停状态沿用主题、密度与文字缩放;适用操作在自身或祖先禁用时停止处理。 + +## 事件 + +`Link` 返回安全链接;`Opened`、`Downloaded` 返回附件索引,无事件时为 -1。 + +## 键盘操作 + +Tab 访问链接、引用开关和附件;Enter / Space 激活;正文支持选择复制。 + +## 限制 + +MarkdownView 处理安全 Markdown 子集,HTML 展示为文字;链接和附件动作由调用方执行。 diff --git a/docs/components/417-mail-composer.md b/docs/components/417-mail-composer.md new file mode 100644 index 0000000..e046cf7 --- /dev/null +++ b/docs/components/417-mail-composer.md @@ -0,0 +1,43 @@ +# 417 MailComposer 邮件编辑器 + +## 用途 + +编辑收件人、抄送、密送、主题、正文和附件,将草稿交给调用方保存。 + +## 最小示例 + +```go +draft := mujica.MailDraft{To: []string{"uika@example.com"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.MailComposer(c, &draft, mujica.MailComposerOptions{ + OnSaveDraft: func(d mujica.MailDraft) {}, // store d + }) + if r.Sent { + draft = mujica.MailDraft{} + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`MailDraft` 保存 `To`、`Cc`、`Bcc`、`Subject`、`Body`、`Attachments`。`Contacts` 提供联系人。`OnSaveDraft func(MailDraft)` 必填,收到独立的切片副本;`OnAttach func()` 可选;`Disabled` 默认 false。 + +## 状态 + +载入含抄送、密送地址的草稿时自动显示对应字段;点击地址字段标签会聚焦编辑器。 + +默认、聚焦和悬停状态沿用主题、密度与文字缩放;适用操作在自身或祖先禁用时停止处理。 + +## 事件 + +`Sent` 表示发送请求,`Discarded` 表示舍弃请求。编辑后静置两秒调用 OnSaveDraft;手动保存立即回调。 + +## 键盘操作 + +Tab 访问字段与操作;Cmd/Ctrl+S 保存草稿;组件内 Cmd/Ctrl+Enter 发送;正文 Enter 换行。 + +## 限制 + +邮箱语法由 net/mail.ParseAddress 校验;实际发送、附件选择与存储由调用方处理;保存回调在界面线程运行。 diff --git a/docs/components/418-recipient-input.md b/docs/components/418-recipient-input.md new file mode 100644 index 0000000..5e79205 --- /dev/null +++ b/docs/components/418-recipient-input.md @@ -0,0 +1,37 @@ +# 418 RecipientInput 收件人输入 + +## 用途 + +通过标签输入收件人,校验邮箱格式并提供联系人建议。 + +## 最小示例 + +```go +var to []string +contacts := []mujica.Contact{{Name: "Uika Misumi", Email: "uika@example.com"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.RecipientInput(c, &to, mujica.RecipientInputOptions{Contacts: contacts, Label: "To"}) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`recipients *[]string` 保存邮箱标签。`Contacts []Contact` 提供 Name、Email;联系人数据变化时替换切片。`Label` 默认“收件人”;`Placeholder` 默认空;`Disabled` 默认 false。 + +## 状态 + +默认、聚焦和悬停状态沿用主题、密度与文字缩放;适用操作在自身或祖先禁用时停止处理。 + +## 事件 + +返回 `TagsInputParts`;`Changed()` 表示标签变化,`Input` 可用于焦点控制。 + +## 键盘操作 + +Enter 或分隔符提交标签;空输入 Backspace 删除末项;上下方向键移动联系人建议,Enter 选择,Escape 收起建议;Tab 可聚焦建议并显示焦点环。 + +## 限制 + +联系人姓名中的逗号和引号按邮件地址语法转义。建议最多显示 6 项;联系人匹配在查询或联系人、收件人数据变化时计算;业务邮箱可达性由调用方验证。 diff --git a/docs/components/419-quoted-text.md b/docs/components/419-quoted-text.md new file mode 100644 index 0000000..921d92b --- /dev/null +++ b/docs/components/419-quoted-text.md @@ -0,0 +1,36 @@ +# 419 QuotedText 引用文字 + +## 用途 + +折叠或展开引用文字,并去掉一层引用前缀。 + +## 最小示例 + +```go +open := false +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.QuotedText(c, "> Can you send the score?", &open) +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`text string` 提供引用文字,`open *bool` 控制展开。`QuoteStrip` 去掉每行一个 `>` 及其后一个空格。 + +## 状态 + +默认、聚焦和悬停状态沿用主题、密度与文字缩放;适用操作在自身或祖先禁用时停止处理。 + +## 事件 + +返回 `ChoiceResult`;`Changed()` 表示折叠状态变化。 + +## 键盘操作 + +Tab 聚焦开关;Enter / Space 展开或折叠;展开内容支持选择复制。 + +## 限制 + +文本按一层引用规则处理,嵌套引用继续保留标记。 diff --git a/docs/components/420-snooze-picker.md b/docs/components/420-snooze-picker.md new file mode 100644 index 0000000..5a8ee40 --- /dev/null +++ b/docs/components/420-snooze-picker.md @@ -0,0 +1,38 @@ +# 420 SnoozePicker 稍后提醒 + +## 用途 + +选择快捷提醒时间,或通过日期时间输入设定自定义提醒。 + +## 最小示例 + +```go +var until time.Time +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.SnoozePicker(c, &until, mujica.SnoozePickerOptions{}).Changed() { + _ = until // hide the mail until then + } +} +ui.Render(view, 400, 300, 1) +``` + +## 参数 + +`until *time.Time` 保存提醒时间。`Location` 默认 `time.Local`;`MorningHour` 默认 9,允许 0–23,其中 0 使用默认值;`Now` 默认使用当前帧时间,可传固定时间;`Disabled` 默认 false。`SnoozeChoices` 的 morning 参数直接接受 0–23。 + +## 状态 + +默认、聚焦和悬停状态沿用主题、密度与文字缩放;适用操作在自身或祖先禁用时停止处理。 + +## 事件 + +返回 `ChoiceResult`;`Changed()` 表示提醒时间改变。 + +## 键盘操作 + +Tab 进入;上下方向键选择快捷项;Enter / Space 激活;自定义时间沿用 DateTimePicker 的输入、确认和取消操作。 + +## 限制 + +组件返回时间,提醒调度与邮件隐藏由调用方处理;本地日期按日历构造以保留夏令时后的早晨时刻。 diff --git a/emoji_data.go b/emoji_data.go new file mode 100644 index 0000000..a0e7fc4 --- /dev/null +++ b/emoji_data.go @@ -0,0 +1,71 @@ +package mujica + +type emoji struct { + char, name string + toned bool +} + +// emojiCategory is a tab of the picker. +type emojiCategory struct { + key string + icon string + emojis []emoji +} + +// emojiTones are the Fitzpatrick modifiers, after the default yellow. +var emojiTones = []string{"", "\U0001F3FB", "\U0001F3FC", "\U0001F3FD", "\U0001F3FE", "\U0001F3FF"} + +var emojiCategories = []emojiCategory{ + {"emoji_picker.smileys", "😀", []emoji{ + {"😀", "grinning face", false}, {"😄", "smiling face with open mouth", false}, {"😂", "face with tears of joy", false}, + {"🙂", "slightly smiling face", false}, {"😉", "winking face", false}, {"😊", "smiling face with smiling eyes", false}, + {"😍", "smiling face with heart eyes", false}, {"😘", "face blowing a kiss", false}, {"🤔", "thinking face", false}, + {"😐", "neutral face", false}, {"🙄", "face with rolling eyes", false}, {"😴", "sleeping face", false}, + {"😎", "smiling face with sunglasses", false}, {"🤩", "star struck", false}, {"😢", "crying face", false}, + {"😡", "pouting face", false}, {"😱", "face screaming in fear", false}, {"🥳", "partying face", false}, + }}, + {"emoji_picker.people", "👋", []emoji{ + {"👋", "waving hand", true}, {"👍", "thumbs up", true}, {"👎", "thumbs down", true}, {"👏", "clapping hands", true}, + {"🙌", "raising hands", true}, {"🙏", "folded hands", true}, {"👌", "ok hand", true}, {"✌️", "victory hand", false}, + {"🤝", "handshake", false}, {"💪", "flexed biceps", true}, {"✍️", "writing hand", false}, {"👀", "eyes", false}, + {"🧑", "person", true}, {"👑", "crown", false}, {"🎭", "performing arts masks", false}, {"💃", "woman dancing", true}, + }}, + {"emoji_picker.nature", "🌹", []emoji{ + {"🌹", "rose", false}, {"🥀", "wilted flower", false}, {"🌸", "cherry blossom", false}, {"🌙", "crescent moon", false}, + {"⭐", "star", false}, {"🔥", "fire", false}, {"🌧️", "cloud with rain", false}, {"❄️", "snowflake", false}, + {"🐈‍⬛", "black cat", false}, {"🦇", "bat", false}, {"🐦‍⬛", "black bird", false}, {"🕊️", "dove", false}, + {"🍂", "fallen leaf", false}, {"🌲", "evergreen tree", false}, {"🌊", "water wave", false}, {"🌈", "rainbow", false}, + }}, + {"emoji_picker.food", "🍷", []emoji{ + {"🍷", "wine glass", false}, {"🥂", "clinking glasses", false}, {"☕", "hot beverage", false}, {"🍵", "teacup", false}, + {"🍰", "shortcake", false}, {"🍫", "chocolate bar", false}, {"🍓", "strawberry", false}, {"🍇", "grapes", false}, + {"🍎", "red apple", false}, {"🧀", "cheese wedge", false}, {"🥖", "baguette", false}, {"🍞", "bread", false}, + }}, + {"emoji_picker.activities", "🎻", []emoji{ + {"🎻", "violin", false}, {"🎹", "musical keyboard", false}, {"🎸", "guitar", false}, {"🥁", "drum", false}, + {"🎤", "microphone", false}, {"🎵", "musical note", false}, {"🎶", "musical notes", false}, {"🎉", "party popper", false}, + {"🏆", "trophy", false}, {"🎨", "artist palette", false}, {"♟️", "chess pawn", false}, {"🎬", "clapper board", false}, + }}, + {"emoji_picker.travel", "🏰", []emoji{ + {"🏰", "castle", false}, {"⛪", "church", false}, {"🗼", "tower", false}, {"🌃", "night with stars", false}, + {"🚂", "locomotive", false}, {"✈️", "airplane", false}, {"🚗", "automobile", false}, {"⛵", "sailboat", false}, + {"🗺️", "world map", false}, {"🏔️", "snow capped mountain", false}, {"🌅", "sunrise", false}, {"🎡", "ferris wheel", false}, + }}, + {"emoji_picker.objects", "🕯️", []emoji{ + {"🕯️", "candle", false}, {"🗝️", "old key", false}, {"📜", "scroll", false}, {"✉️", "envelope", false}, + {"📎", "paperclip", false}, {"📌", "pushpin", false}, {"📅", "calendar", false}, {"💡", "light bulb", false}, + {"🔔", "bell", false}, {"🔒", "locked", false}, {"💎", "gem stone", false}, {"⏳", "hourglass", false}, + }}, + {"emoji_picker.symbols", "❤️", []emoji{ + {"❤️", "red heart", false}, {"🖤", "black heart", false}, {"💔", "broken heart", false}, {"✨", "sparkles", false}, + {"✅", "check mark button", false}, {"❌", "cross mark", false}, {"❗", "exclamation mark", false}, {"❓", "question mark", false}, + {"💯", "hundred points", false}, {"♦️", "diamond suit", false}, {"⚜️", "fleur de lis", false}, {"🔺", "red triangle", false}, + }}, +} + +func emojiToned(e emoji, tone int) string { + if !e.toned || tone == 0 { + return e.char + } + return e.char + emojiTones[tone] +} diff --git a/emoji_picker.go b/emoji_picker.go new file mode 100644 index 0000000..a88830c --- /dev/null +++ b/emoji_picker.go @@ -0,0 +1,197 @@ +package mujica + +import ( + "fmt" + "log/slog" + "slices" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/internal" + "mujicaui/theme" +) + +// EmojiPickerOptions configure an EmojiPicker. +type EmojiPickerOptions struct { + // Recent stores up to 24 emoji, newest first. + Recent *[]string + // Tone stores the selected skin tone, from 0 through 5. + Tone *int + Disabled bool +} + +// EmojiResult exposes the element and this frame’s chosen emoji. +type EmojiResult struct { + Element *ui.Element + // Picked contains the chosen emoji, or an empty string. + Picked string +} + +// emojiRecentMax is how many recent emoji are kept. +const emojiRecentMax = 24 + +type emojiState struct { + tab int + query string + recent bool +} + +type emojiKey struct{} + +// EmojiPicker supports categories, search, history and skin tones. +func EmojiPicker(c *ui.Context, opts EmojiPickerOptions) EmojiResult { + if opts.Tone != nil && (*opts.Tone < 0 || *opts.Tone >= len(emojiTones)) { + panic("mujica: EmojiPicker Tone outside 0..5") + } + k := Tokens(c) + u := Density(c).Unit() + tone := 0 + if opts.Tone != nil { + tone = *opts.Tone + } + var r EmojiResult + col := ui.Column(c).Width(8*36+u*4).Gap(u*2).Padding(u*2).Radius(theme.PopupRadius).Background(k.Surface). + Border(theme.BorderWidth, k.Border).Role(ui.RoleGroup).Label(msg(c, "emoji_picker.label")).Disabled(opts.Disabled) + r.Element = col + recent := opts.Recent != nil && len(*opts.Recent) > 0 + st := ui.Local(col, emojiKey{}, func() emojiState { return emojiState{recent: recent} }) + if recent != st.recent { + if recent { + st.tab++ + } else { + st.tab = max(0, st.tab-1) + } + st.recent = recent + } + col.Children(func() { + TextInput(c, &st.query, TextInputOptions{Placeholder: msg(c, "emoji_picker.search"), Label: msg(c, "emoji_picker.search"), + Leading: func() { ui.Icon(c, icons.Must("search")).Size(14, 14).TextColor(k.TextMuted) }, Clearable: true}) + if opts.Tone != nil { + emojiToneRow(c, k, opts.Tone) + } + if strings.TrimSpace(st.query) == "" { + emojiTabs(c, k, &st.tab, recent) + } + ui.Scroll(c).Height(36*5 + u*2).Children(func() { + grid := ui.Row(c).Wrap().FocusGroup(ui.Horizontal | ui.Vertical).Role(ui.RoleList) + grid.Children(func() { + for _, e := range emojiShown(c, st, opts.Recent, recent) { + if s := emojiCell(c, k, e, tone); s != "" && !col.IsDisabled() { + r.Picked = s + } + } + }) + }) + }) + if r.Picked != "" { + if opts.Recent != nil { + rec := slices.DeleteFunc(slices.Clone(*opts.Recent), func(s string) bool { return s == r.Picked }) + *opts.Recent = slices.Insert(rec, 0, r.Picked)[:min(emojiRecentMax, len(rec)+1)] + } + slog.Debug("mujica: emoji_picker pick", "emoji", r.Picked) + } + return r +} + +func emojiShown(c *ui.Context, st *emojiState, recentList *[]string, recent bool) []emoji { + if q := strings.ToLower(strings.TrimSpace(st.query)); q != "" { + var out []emoji + for _, cat := range emojiCategories { + for _, e := range cat.emojis { + if strings.Contains(e.name, q) || strings.Contains(emojiLabel(c, e), q) { + out = append(out, e) + } + } + } + if len(out) == 0 { + ui.Text(c, msg(c, "emoji_picker.none")).TextColor(Tokens(c).TextMuted).Padding(Density(c).Unit() * 2) + } + return out + } + tab := st.tab + if recent { + if tab == 0 { + out := make([]emoji, len(*recentList)) + for i, s := range *recentList { + out[i] = emoji{char: s, name: s} + } + return out + } + tab-- + } + return emojiCategories[min(tab, len(emojiCategories)-1)].emojis +} + +// emojiTabs picks a category; Recent leads when there is history. +func emojiTabs(c *ui.Context, k theme.Tokens, tab *int, recent bool) { + type tabItem struct{ face, key string } + var tabs []tabItem + if recent { + tabs = append(tabs, tabItem{"🕘", "emoji_picker.recent"}) + } + for _, cat := range emojiCategories { + tabs = append(tabs, tabItem{cat.icon, cat.key}) + } + *tab = min(*tab, len(tabs)-1) + ui.Row(c).FocusGroup(ui.Horizontal).Role(ui.RoleTabList).BorderWidth(0, 0, 1, 0).BorderColor(k.Border).Children(func() { + for i, t := range tabs { + b := ui.ButtonBase(c).Key(t.key).Size(32, 32).Radius(theme.ControlRadius).Role(ui.RoleTab).Label(msg(c, t.key)). + Selected(i == *tab).Background(ui.Transparent).Tooltip(msg(c, t.key)) + internal.Ring(b, k.Focus, theme.ControlRadius) + switch { + case i == *tab: + b.Background(k.Selection).BorderWidth(0, 0, 2, 0).BorderColor(k.AccentText) + case b.Hovered(): + b.Background(k.SurfaceHover) + } + b.Children(func() { ui.Text(c, t.face).FontSize(FontSize(c, 16)) }) + if b.Clicked() && !b.IsDisabled() { + *tab = i + } + } + }) +} + +func emojiToneRow(c *ui.Context, k theme.Tokens, tone *int) { + ui.Row(c).Gap(2).AlignItems(ui.Center).FocusGroup(ui.Horizontal).Role(ui.RoleRadioGroup).Label(msg(c, "emoji_picker.tone")).Children(func() { + ui.Text(c, msg(c, "emoji_picker.tone")).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Margin(0, 6, 0, 0) + for i := range emojiTones { + b := ui.ButtonBase(c).Key(i).Size(theme.MinHitSize, theme.MinHitSize).Radius(theme.ControlRadius).Role(ui.RoleRadio). + Label(fmt.Sprintf(msg(c, "emoji_picker.toneN"), i)).Selected(i == *tone).Background(ui.Transparent) + internal.Ring(b, k.Focus, theme.ControlRadius) + if i == *tone { + b.Background(k.Selection).Border(theme.BorderWidth, k.AccentText) + } else if b.Hovered() { + b.Background(k.SurfaceHover) + } + b.Children(func() { ui.Text(c, emojiToned(emoji{char: "👋", toned: true}, i)).FontSize(FontSize(c, 15)) }) + if b.Clicked() && !b.IsDisabled() { + *tone = i + slog.Debug("mujica: emoji_picker tone", "tone", i) + } + } + }) +} + +func emojiCell(c *ui.Context, k theme.Tokens, e emoji, tone int) string { + s := emojiToned(e, tone) + b := ui.ButtonBase(c).Key(e.char).Size(36, 36).Radius(theme.ControlRadius).Label(emojiLabel(c, e)).Tooltip(emojiLabel(c, e)).Transition(colorFade) + internal.Ring(b, k.Focus, theme.ControlRadius) + if b.Hovered() || b.Focused() { + b.Background(k.SurfaceHover) + } + b.Children(func() { ui.Text(c, s).FontSize(FontSize(c, 20)) }) + if b.Clicked() { + return s + } + return "" +} + +func emojiLabel(c *ui.Context, e emoji) string { + if e.name == e.char { + return e.char + } + return msg(c, "emoji_picker.name_"+strings.ReplaceAll(e.name, " ", "_")) +} diff --git a/emoji_picker_test.go b/emoji_picker_test.go new file mode 100644 index 0000000..6a8155a --- /dev/null +++ b/emoji_picker_test.go @@ -0,0 +1,142 @@ +package mujica + +import ( + "slices" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestEmojiPickerPickSearchToneRecent(t *testing.T) { + var recent []string + tone := 0 + var picked []string + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if r := EmojiPicker(c, EmojiPickerOptions{Recent: &recent, Tone: &tone}); r.Picked != "" { + picked = append(picked, r.Picked) + } + }, 400, 500) + if err := tt.Click("People"); err != nil { + t.Fatal(err) + } + if err := tt.Click("Skin tone 3"); err != nil { + t.Fatal(err) + } + if err := tt.Click("thumbs up"); err != nil { + t.Fatal(err) + } + if len(picked) != 1 || picked[0] != "👍\U0001F3FD" || tone != 3 { + t.Fatalf("picked %q tone %d", picked, tone) + } + if err := tt.Click("Search emoji"); err != nil { + t.Fatal(err) + } + tt.Type("wine") + if err := tt.Click("wine glass"); err != nil { + t.Fatal(err) + } + if !slices.Equal(recent, []string{"🍷", "👍\U0001F3FD"}) { + t.Fatalf("recent %q", recent) + } + if err := tt.Click("Search emoji"); err != nil { + t.Fatal(err) + } + tt.Type("zzzz") + if !tt.HasText("No emoji found") { + t.Fatal("no empty search state") + } +} + +func TestEmojiPickerKeyboardAndDisabled(t *testing.T) { + var got string + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if r := EmojiPicker(c, EmojiPickerOptions{}); r.Picked != "" { + got = r.Picked + } + }, 400, 500) + if err := tt.Click("grinning face"); err != nil { + t.Fatal(err) + } + tt.Key(0, ui.KeyRight) + tt.Key(0, ui.KeyEnter) + if got != "😄" { + t.Fatalf("Right, Enter picked %q", got) + } + got = "" + off := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if r := EmojiPicker(c, EmojiPickerOptions{Disabled: true}); r.Picked != "" { + got = r.Picked + } + }, 400, 500) + _ = off.Click("grinning face") + if got != "" { + t.Fatal("disabled picker picked") + } + bad := 9 + mediaPanics(t, "tone", func(c *ui.Context) { EmojiPicker(c, EmojiPickerOptions{Tone: &bad}) }) +} + +func TestEmojiPickerSnapshot(t *testing.T) { + recent := []string{"🌹", "🍷"} + tone := 0 + snapshot(t, "emoji_picker", 360, 400, func(c *ui.Context) { + ui.Column(c).Padding(20).Children(func() { EmojiPicker(c, EmojiPickerOptions{Recent: &recent, Tone: &tone}) }) + }) +} + +func TestEmojiPickerKeepsCategoryAfterFirstPick(t *testing.T) { + var recent []string + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + EmojiPicker(c, EmojiPickerOptions{Recent: &recent}) + }, 400, 400) + if err := tt.Click("People"); err != nil { + t.Fatal(err) + } + if err := tt.Click("thumbs up"); err != nil { + t.Fatal(err) + } + if _, ok := tt.Find("waving hand"); !ok { + t.Fatal("first pick changed the category") + } + if err := tt.Click("Recent"); err != nil { + t.Fatal(err) + } + if _, ok := tt.Find("👍"); !ok { + t.Fatal("recent pick missing") + } +} + +func TestEmojiPickerChineseSearch(t *testing.T) { + picked := "" + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{Locale: ZhCN}) + if r := EmojiPicker(c, EmojiPickerOptions{}); r.Picked != "" { + picked = r.Picked + } + }, 400, 400) + if err := tt.Click("搜索表情"); err != nil { + t.Fatal(err) + } + tt.Type("小提琴") + if err := tt.Click("小提琴"); err != nil { + t.Fatal(err) + } + if picked != "🎻" { + t.Fatal("localized search did not choose violin") + } +} + +func TestEmojiPickerInitialHistory(t *testing.T) { + recent := []string{"🌹", "🍷"} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + EmojiPicker(c, EmojiPickerOptions{Recent: &recent}) + }, 400, 400) + if got := mediaTextCount(tt, "🌹"); got != 3 { + t.Fatalf("initial history rose occurrences=%d, want 3", got) + } +} diff --git a/example_messaging_test.go b/example_messaging_test.go new file mode 100644 index 0000000..8f93b6a --- /dev/null +++ b/example_messaging_test.go @@ -0,0 +1,242 @@ +package mujica_test + +import ( + mujica "mujicaui" + "time" + + "github.com/egoist/mygo/ui" +) + +func ExampleChannelList() { + groups := []mujica.ChannelGroup{{ID: "ch", Title: "Channels", Channels: []mujica.Channel{ + {ID: "general", Name: "general", Unread: 3}, + {ID: "rehearsal", Name: "rehearsal", Pinned: true}, + }}} + selected := "general" + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ChannelList(c, &selected, groups, mujica.ChannelListOptions{}).Changed() { + _ = selected // show that channel + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleChatMessage() { + prev := mujica.ChatEntry{ID: "1", Author: "Uika", Time: time.Now(), Text: "Rehearsal at nine."} + m := mujica.ChatEntry{ID: "2", Author: "Uika", Time: time.Now(), Text: "Bring the masks.", Edited: true} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ChatMessage(c, prev, mujica.ChatMessageOptions{}) + mujica.ChatMessage(c, m, mujica.ChatMessageOptions{ + Continued: mujica.ChatContinues(prev, m), + Reactions: func() { mujica.Tag(c, "👍 2", mujica.TagOptions{}) }, + }) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleUnreadDivider() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.UnreadDivider(c, 3) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleReadReceipt() { + readers := []mujica.AvatarItem{{Name: "Uika"}, {Name: "Mutsumi"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ReadReceipt(c, mujica.ReceiptRead, mujica.ReadReceiptOptions{Readers: readers}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMemberList() { + var s mujica.MemberListState + members := []mujica.Member{ + {ID: "1", Name: "Sakiko", Presence: mujica.PresenceOnline, Role: "Leader"}, + {ID: "2", Name: "Umiri", Presence: mujica.PresenceOffline}, + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MemberList(c, &s, members, mujica.MemberListOptions{}); r.Opened != "" { + _ = r.Opened // show that member's profile + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleUserProfileCard() { + profile := mujica.UserProfile{Name: "Sakiko Togawa", Presence: mujica.PresenceBusy, Role: "Keyboard", Status: "In rehearsal"} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.UserProfileCard(c, profile, mujica.UserProfileCardOptions{Actions: func() { + mujica.Button(c, "Message", mujica.ButtonOptions{}) + }}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleOnlineStatus() { + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.OnlineStatus(c, mujica.PresenceAway, mujica.OnlineStatusOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleStatusSetter() { + status := mujica.CustomStatus{Emoji: "🎻", Text: "Rehearsing"} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.StatusSetter(c, &status, mujica.StatusSetterOptions{}).Changed() { + _ = status // publish it; clear it once status.Until passes + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleCallControls() { + st := mujica.CallState{} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CallControls(c, st, mujica.CallControlsOptions{ + OnMute: func(on bool) { st.Muted = on }, + OnCamera: func(off bool) { st.CameraOff = off }, + OnShare: func(on bool) { st.Sharing = on }, + OnHangUp: func() {}, // leave the call + }) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleVideoCallGrid() { + people := []mujica.CallParticipant{ + {ID: "1", Name: "Sakiko", Speaking: true}, // Frame: the latest decoded frame + {ID: "2", Name: "Uika", Muted: true}, + } + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.VideoCallGrid(c, people, mujica.VideoCallGridOptions{}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleIncomingCallDialog() { + ringing := true + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.IncomingCallDialog(c, &ringing, mujica.IncomingCall{Caller: "Sakiko", Video: true}, mujica.IncomingCallOptions{ + OnAccept: func(video bool) {}, // join, with the camera on when video + OnDecline: func() {}, + }) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleEmojiPicker() { + var recent []string + tone := 0 + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.EmojiPicker(c, mujica.EmojiPickerOptions{Recent: &recent, Tone: &tone}); r.Picked != "" { + _ = r.Picked // insert it + } + } + ui.Render(view, 400, 300, 1) +} + +func ExamplePinnedMessages() { + pins := []mujica.ChatEntry{{ID: "a", Author: "Sakiko", Text: "Rehearsal moves to nine."}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.PinnedMessages(c, pins, mujica.PinnedMessagesOptions{}) + if r.Unpinned != "" { + pins = pins[:0] // unpin it + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleThreadPanel() { + open := true + root := mujica.ChatEntry{ID: "r", Author: "Sakiko", Text: "Set list for Friday?"} + var replies []mujica.ChatEntry + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.ThreadPanel(c, &open, root, replies, mujica.ThreadPanelOptions{}); r.Sent != "" { + replies = append(replies, mujica.ChatEntry{ID: r.Sent, Author: "Me", Text: r.Sent, Own: true}) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMailList() { + var s mujica.ListState[string] + mails := []mujica.MailItem{{ID: "1", From: "Sakiko", Subject: "Second act", Unread: true, Attachments: 1}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MailList(c, &s, mails, mujica.MailListOptions{}); r.Starred != "" { + mails[0].Starred = !mails[0].Starred + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMailReader() { + m := mujica.Mail{From: "Sakiko", Subject: "Second act", Body: "The score is attached.\n> Can you send it?", + Attachments: []mujica.MailAttachment{{Name: "score.pdf", Size: 2048}}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MailReader(c, m); r.Link != "" { + c.OpenURL(r.Link) + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleMailComposer() { + draft := mujica.MailDraft{To: []string{"uika@example.com"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.MailComposer(c, &draft, mujica.MailComposerOptions{ + OnSaveDraft: func(d mujica.MailDraft) {}, // store d + }) + if r.Sent { + draft = mujica.MailDraft{} + } + } + ui.Render(view, 400, 300, 1) +} + +func ExampleRecipientInput() { + var to []string + contacts := []mujica.Contact{{Name: "Uika Misumi", Email: "uika@example.com"}} + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.RecipientInput(c, &to, mujica.RecipientInputOptions{Contacts: contacts, Label: "To"}) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleQuotedText() { + open := false + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.QuotedText(c, "> Can you send the score?", &open) + } + ui.Render(view, 400, 300, 1) +} + +func ExampleSnoozePicker() { + var until time.Time + view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.SnoozePicker(c, &until, mujica.SnoozePickerOptions{}).Changed() { + _ = until // hide the mail until then + } + } + ui.Render(view, 400, 300, 1) +} diff --git a/examples/gallery/pages_messaging.go b/examples/gallery/pages_messaging.go index fcde9bd..c4c902a 100644 --- a/examples/gallery/pages_messaging.go +++ b/examples/gallery/pages_messaging.go @@ -1,3 +1,200 @@ package main -var messagingPages = []page{} +const messagingCategory = "Messaging & Mail" + +var messagingPages = []page{ + {ID: "401", Name: "ChannelList", ZhName: "频道列表", Category: messagingCategory, Demo: channelListDemo, + Keys: "Tab 进入;上下方向键切换行;Enter / Space 选择或折叠;分组标题上的左、右方向键折叠、展开。", Code: `groups := []mujica.ChannelGroup{{ID: "ch", Title: "Channels", Channels: []mujica.Channel{ + {ID: "general", Name: "general", Unread: 3}, + {ID: "rehearsal", Name: "rehearsal", Pinned: true}, +}}} +selected := "general" +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.ChannelList(c, &selected, groups, mujica.ChannelListOptions{}).Changed() { + _ = selected // show that channel + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "402", Name: "ChatMessage", ZhName: "聊天消息", Category: messagingCategory, Demo: chatMessageDemo, + Keys: "可选文字支持选择复制;插槽控件按 Tab 访问。", Code: `prev := mujica.ChatEntry{ID: "1", Author: "Uika", Time: time.Now(), Text: "Rehearsal at nine."} +m := mujica.ChatEntry{ID: "2", Author: "Uika", Time: time.Now(), Text: "Bring the masks.", Edited: true} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ChatMessage(c, prev, mujica.ChatMessageOptions{}) + mujica.ChatMessage(c, m, mujica.ChatMessageOptions{ + Continued: mujica.ChatContinues(prev, m), + Reactions: func() { mujica.Tag(c, "👍 2", mujica.TagOptions{}) }, + }) +} +ui.Render(view, 400, 300, 1)`}, + {ID: "403", Name: "UnreadDivider", ZhName: "未读分隔线", Category: messagingCategory, Demo: unreadDividerDemo, + Keys: "展示组件保持自然焦点序列。", Code: `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.UnreadDivider(c, 3) +} +ui.Render(view, 400, 300, 1)`}, + {ID: "404", Name: "ReadReceipt", ZhName: "已读回执", Category: messagingCategory, Demo: readReceiptDemo, + Keys: "展示组件保持自然焦点序列。", Code: `readers := []mujica.AvatarItem{{Name: "Uika"}, {Name: "Mutsumi"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.ReadReceipt(c, mujica.ReceiptRead, mujica.ReadReceiptOptions{Readers: readers}) +} +ui.Render(view, 400, 300, 1)`}, + {ID: "405", Name: "MemberList", ZhName: "成员列表", Category: messagingCategory, Demo: memberListDemo, + Keys: "Tab 聚焦列表;上下方向键选择;Home / End 首尾;Enter 或双击打开成员。", Code: `var s mujica.MemberListState +members := []mujica.Member{ + {ID: "1", Name: "Sakiko", Presence: mujica.PresenceOnline, Role: "Leader"}, + {ID: "2", Name: "Umiri", Presence: mujica.PresenceOffline}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MemberList(c, &s, members, mujica.MemberListOptions{}); r.Opened != "" { + _ = r.Opened // show that member's profile + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "406", Name: "UserProfileCard", ZhName: "用户资料卡", Category: messagingCategory, Demo: userProfileCardDemo, + Keys: "Tab 访问操作插槽;Enter / Space 激活按钮。", Code: `profile := mujica.UserProfile{Name: "Sakiko Togawa", Presence: mujica.PresenceBusy, Role: "Keyboard", Status: "In rehearsal"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.UserProfileCard(c, profile, mujica.UserProfileCardOptions{Actions: func() { + mujica.Button(c, "Message", mujica.ButtonOptions{}) + }}) +} +ui.Render(view, 400, 300, 1)`}, + {ID: "407", Name: "OnlineStatus", ZhName: "在线状态", Category: messagingCategory, Demo: onlineStatusDemo, + Keys: "展示组件保持自然焦点序列。", Code: `view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.OnlineStatus(c, mujica.PresenceAway, mujica.OnlineStatusOptions{}) +} +ui.Render(view, 400, 300, 1)`}, + {ID: "408", Name: "StatusSetter", ZhName: "状态设置", Category: messagingCategory, Demo: statusSetterDemo, + Keys: "Tab 访问表情、文字、期限和清除按钮;选择器用方向键移动、Enter 确认、Escape 关闭。", Code: `status := mujica.CustomStatus{Emoji: "🎻", Text: "Rehearsing"} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.StatusSetter(c, &status, mujica.StatusSetterOptions{}).Changed() { + _ = status // publish it; clear it once status.Until passes + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "409", Name: "CallControls", ZhName: "通话控制", Category: messagingCategory, Demo: callControlsDemo, + Keys: "Tab 进入工具栏;左右方向键移动;Enter / Space 激活。Cmd/Ctrl+D 静音,Cmd/Ctrl+E 摄像头,Cmd/Ctrl+Shift+S 共享,Cmd/Ctrl+Shift+H 挂断。", Code: `st := mujica.CallState{} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.CallControls(c, st, mujica.CallControlsOptions{ + OnMute: func(on bool) { st.Muted = on }, + OnCamera: func(off bool) { st.CameraOff = off }, + OnShare: func(on bool) { st.Sharing = on }, + OnHangUp: func() {}, // leave the call + }) +} +ui.Render(view, 400, 300, 1)`}, + {ID: "410", Name: "VideoCallGrid", ZhName: "视频通话宫格", Category: messagingCategory, Demo: videoCallGridDemo, + Keys: "Tab 进入宫格;方向键移动参与者焦点并读取状态。", Code: `people := []mujica.CallParticipant{ + {ID: "1", Name: "Sakiko", Speaking: true}, // Frame: the latest decoded frame + {ID: "2", Name: "Uika", Muted: true}, +} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.VideoCallGrid(c, people, mujica.VideoCallGridOptions{}) +} +ui.Render(view, 400, 300, 1)`}, + {ID: "411", Name: "IncomingCallDialog", ZhName: "来电对话框", Category: messagingCategory, Demo: incomingCallDialogDemo, + Keys: "默认焦点为拒绝;Tab 循环访问操作;Enter / Space 激活;Escape 拒绝;关闭后恢复焦点。", Code: `ringing := true +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.IncomingCallDialog(c, &ringing, mujica.IncomingCall{Caller: "Sakiko", Video: true}, mujica.IncomingCallOptions{ + OnAccept: func(video bool) {}, // join, with the camera on when video + OnDecline: func() {}, + }) +} +ui.Render(view, 400, 300, 1)`}, + {ID: "412", Name: "EmojiPicker", ZhName: "表情选择器", Category: messagingCategory, Demo: emojiPickerDemo, + Keys: "Tab 访问搜索、肤色、分类、表情;方向键在组内移动;Enter / Space 选择。", Code: `var recent []string +tone := 0 +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.EmojiPicker(c, mujica.EmojiPickerOptions{Recent: &recent, Tone: &tone}); r.Picked != "" { + _ = r.Picked // insert it + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "413", Name: "PinnedMessages", ZhName: "置顶消息", Category: messagingCategory, Demo: pinnedMessagesDemo, + Keys: "Tab 访问跳转与取消置顶;方向键移动;Enter / Space 激活。", Code: `pins := []mujica.ChatEntry{{ID: "a", Author: "Sakiko", Text: "Rehearsal moves to nine."}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.PinnedMessages(c, pins, mujica.PinnedMessagesOptions{}) + if r.Unpinned != "" { + pins = pins[:0] // unpin it + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "414", Name: "ThreadPanel", ZhName: "话题侧栏", Category: messagingCategory, Demo: threadPanelDemo, + Keys: "Tab 访问关闭、回复和发送;Enter 发送回复;Escape 关闭面板。", Code: `open := true +root := mujica.ChatEntry{ID: "r", Author: "Sakiko", Text: "Set list for Friday?"} +var replies []mujica.ChatEntry +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.ThreadPanel(c, &open, root, replies, mujica.ThreadPanelOptions{}); r.Sent != "" { + replies = append(replies, mujica.ChatEntry{ID: r.Sent, Author: "Me", Text: r.Sent, Own: true}) + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "415", Name: "MailList", ZhName: "邮件列表", Category: messagingCategory, Demo: mailListDemo, + Keys: "上下方向键、Home / End 移动选择;Enter 或双击打开;S 请求星标;Cmd/Ctrl+A 全选;Cmd/Ctrl 点击切换单项,Shift 点击选择范围。", Code: `var s mujica.ListState[string] +mails := []mujica.MailItem{{ID: "1", From: "Sakiko", Subject: "Second act", Unread: true, Attachments: 1}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MailList(c, &s, mails, mujica.MailListOptions{}); r.Starred != "" { + mails[0].Starred = !mails[0].Starred + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "416", Name: "MailReader", ZhName: "邮件阅读器", Category: messagingCategory, Demo: mailReaderDemo, + Keys: "Tab 访问链接、引用开关和附件;Enter / Space 激活;正文支持选择复制。", Code: `m := mujica.Mail{From: "Sakiko", Subject: "Second act", Body: "The score is attached.\n> Can you send it?", + Attachments: []mujica.MailAttachment{{Name: "score.pdf", Size: 2048}}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if r := mujica.MailReader(c, m); r.Link != "" { + c.OpenURL(r.Link) + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "417", Name: "MailComposer", ZhName: "邮件编辑器", Category: messagingCategory, Demo: mailComposerDemo, + Keys: "Tab 访问字段与操作;Cmd/Ctrl+S 保存草稿;组件内 Cmd/Ctrl+Enter 发送;正文 Enter 换行。", Code: `draft := mujica.MailDraft{To: []string{"uika@example.com"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + r := mujica.MailComposer(c, &draft, mujica.MailComposerOptions{ + OnSaveDraft: func(d mujica.MailDraft) {}, // store d + }) + if r.Sent { + draft = mujica.MailDraft{} + } +} +ui.Render(view, 400, 300, 1)`}, + {ID: "418", Name: "RecipientInput", ZhName: "收件人输入", Category: messagingCategory, Demo: recipientInputDemo, + Keys: "Enter 或分隔符提交标签;空输入 Backspace 删除末项;上下方向键移动联系人建议,Enter 选择,Escape 收起建议。", Code: `var to []string +contacts := []mujica.Contact{{Name: "Uika Misumi", Email: "uika@example.com"}} +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.RecipientInput(c, &to, mujica.RecipientInputOptions{Contacts: contacts, Label: "To"}) +} +ui.Render(view, 400, 300, 1)`}, + {ID: "419", Name: "QuotedText", ZhName: "引用文字", Category: messagingCategory, Demo: quotedTextDemo, + Keys: "Tab 聚焦开关;Enter / Space 展开或折叠;展开内容支持选择复制。", Code: `open := false +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + mujica.QuotedText(c, "> Can you send the score?", &open) +} +ui.Render(view, 400, 300, 1)`}, + {ID: "420", Name: "SnoozePicker", ZhName: "稍后提醒", Category: messagingCategory, Demo: snoozePickerDemo, + Keys: "Tab 进入;上下方向键选择快捷项;Enter / Space 激活;自定义时间沿用 DateTimePicker 的输入、确认和取消操作。", Code: `var until time.Time +view := func(c *ui.Context) { + mujica.Use(c, mujica.Settings{}) + if mujica.SnoozePicker(c, &until, mujica.SnoozePickerOptions{}).Changed() { + _ = until // hide the mail until then + } +} +ui.Render(view, 400, 300, 1)`}, +} diff --git a/examples/gallery/pages_messaging_calls.go b/examples/gallery/pages_messaging_calls.go new file mode 100644 index 0000000..f5fa3e5 --- /dev/null +++ b/examples/gallery/pages_messaging_calls.go @@ -0,0 +1,75 @@ +package main + +import ( + "fmt" + + "github.com/egoist/mygo/ui" + mujica "mujicaui" +) + +func callControlsDemo(c *ui.Context, log func(string)) { + type state struct { + call mujica.CallState + disabled bool + ended bool + } + s := ui.Local(c.Root(), "409", func() state { return state{} }) + mediaCheck(c, log, &s.disabled, "Disabled") + if mujica.Button(c, "Reconnect", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.ended = false + log("call joined") + } + mujica.CallControls(c, s.call, mujica.CallControlsOptions{ + Disabled: s.disabled || s.ended, + OnMute: func(on bool) { s.call.Muted = on; log(fmt.Sprintf("mute %v", on)) }, + OnCamera: func(off bool) { s.call.CameraOff = off; log(fmt.Sprintf("camera off %v", off)) }, + OnShare: func(on bool) { s.call.Sharing = on; log(fmt.Sprintf("sharing %v", on)) }, + OnHangUp: func() { s.ended = true; log("call left") }, + }) + ui.Text(c, fmt.Sprintf("Muted: %v; camera off: %v; sharing: %v; ended: %v", s.call.Muted, s.call.CameraOff, s.call.Sharing, s.ended)) +} + +func videoCallGridDemo(c *ui.Context, log func(string)) { + type state struct { + speaking, muted, cameraOff, frame bool + columns float64 + } + s := ui.Local(c.Root(), "410", func() state { return state{speaking: true, frame: true, columns: 2} }) + mediaCheck(c, log, &s.speaking, "Speaking") + mediaCheck(c, log, &s.muted, "Muted") + mediaCheck(c, log, &s.cameraOff, "Camera off") + mediaCheck(c, log, &s.frame, "Caller-provided frame") + if mujica.NumberInput(c, &s.columns, mujica.NumberInputOptions{Min: 0, Max: 3, Step: 1, Label: "Columns (0 = auto)"}).Changed() { + log(fmt.Sprintf("columns %.0f", s.columns)) + } + people := []mujica.CallParticipant{ + {ID: "1", Name: "Sakiko", Speaking: s.speaking, Muted: s.muted, CameraOff: s.cameraOff}, + {ID: "2", Name: "Uika", Muted: true}, {ID: "3", Name: "Mutsumi", CameraOff: true}, {ID: "4", Name: "Umiri"}, + } + if s.frame { + people[0].Frame = mediaBitmaps[0] + people[3].Frame = mediaBitmaps[1] + } + mujica.VideoCallGrid(c, people, mujica.VideoCallGridOptions{Columns: int(s.columns)}) +} + +func incomingCallDialogDemo(c *ui.Context, log func(string)) { + type state struct { + open, video, focusAccept, disabled bool + result string + } + s := ui.Local(c.Root(), "411", func() state { return state{video: true} }) + mediaCheck(c, log, &s.video, "Video call") + mediaCheck(c, log, &s.focusAccept, "Focus Accept") + mediaCheck(c, log, &s.disabled, "Disabled") + if mujica.Button(c, "Incoming call", mujica.ButtonOptions{Disabled: s.disabled}).Clicked() { + s.open = true + log("incoming call") + } + mujica.IncomingCallDialog(c, &s.open, mujica.IncomingCall{Caller: "Sakiko Togawa", Video: s.video}, mujica.IncomingCallOptions{ + Disabled: s.disabled, FocusAccept: s.focusAccept, + OnAccept: func(video bool) { s.result = fmt.Sprintf("Accepted, video: %v", video); log(s.result) }, + OnDecline: func() { s.result = "Declined"; log(s.result) }, + }) + ui.Text(c, s.result) +} diff --git a/examples/gallery/pages_messaging_chat.go b/examples/gallery/pages_messaging_chat.go new file mode 100644 index 0000000..586cf95 --- /dev/null +++ b/examples/gallery/pages_messaging_chat.go @@ -0,0 +1,141 @@ +package main + +import ( + "fmt" + "slices" + "time" + + "github.com/egoist/mygo/ui" + mujica "mujicaui" +) + +func chatMessageDemo(c *ui.Context, log func(string)) { + type state struct { + continued, edited, own, reply, reactions bool + reacted bool + } + s := ui.Local(c.Root(), "402", func() state { return state{continued: true, edited: true, reply: true, reactions: true} }) + mediaCheck(c, log, &s.continued, "Merge consecutive messages") + mediaCheck(c, log, &s.edited, "Edited") + mediaCheck(c, log, &s.own, "Own message") + mediaCheck(c, log, &s.reply, "Reply slot") + mediaCheck(c, log, &s.reactions, "Reaction slot") + at := time.Date(2026, 10, 5, 21, 7, 0, 0, time.Local) + mujica.ChatMessage(c, mujica.ChatEntry{Author: "Uika", Time: at, Text: "Rehearsal at nine.", Own: s.own}, mujica.ChatMessageOptions{}) + opts := mujica.ChatMessageOptions{Continued: s.continued} + if s.reply { + opts.Reply = func() { + if mujica.QuoteReply(c, "Sakiko", "When do we start?").Clicked() { + log("jump to quoted message") + } + } + } + if s.reactions { + opts.Reactions = func() { + if mujica.Toggle(c, &s.reacted, "Like", mujica.ToggleOptions{}).Changed() { + log(fmt.Sprintf("reaction %v", s.reacted)) + } + } + } + mujica.ChatMessage(c, mujica.ChatEntry{Author: "Uika", Time: at.Add(time.Minute), Text: "Bring the masks.", Own: s.own, Edited: s.edited}, opts) +} + +func unreadDividerDemo(c *ui.Context, log func(string)) { + count := ui.Local(c.Root(), "403", func() float64 { return 3 }) + if mujica.NumberInput(c, count, mujica.NumberInputOptions{Min: 0, Max: 999, Step: 1, Label: "Unread count"}).Changed() { + log(fmt.Sprintf("unread %.0f", *count)) + } + mujica.UnreadDivider(c, int(*count)) + inputSection(c, "Zero count", func() { mujica.UnreadDivider(c, 0) }) +} + +func readReceiptDemo(c *ui.Context, log func(string)) { + type state struct { + receipt mujica.ReceiptState + readers bool + max float64 + } + s := ui.Local(c.Root(), "404", func() state { return state{receipt: mujica.ReceiptRead, readers: true, max: 3} }) + items := []mujica.SelectOption[mujica.ReceiptState]{{Value: mujica.ReceiptSent, Label: "Sent"}, {Value: mujica.ReceiptDelivered, Label: "Delivered"}, {Value: mujica.ReceiptRead, Label: "Read"}} + if mujica.Select(c, &s.receipt, items, mujica.SelectOptions{Label: "Receipt"}).Changed() { + log(fmt.Sprintf("receipt %d", s.receipt)) + } + mediaCheck(c, log, &s.readers, "Reader avatars") + if mujica.NumberInput(c, &s.max, mujica.NumberInputOptions{Min: 1, Max: 4, Step: 1, Label: "Max avatars"}).Changed() { + log(fmt.Sprintf("max %.0f", s.max)) + } + opts := mujica.ReadReceiptOptions{Max: int(s.max)} + if s.readers { + opts.Readers = []mujica.AvatarItem{{Name: "Uika"}, {Name: "Mutsumi"}, {Name: "Umiri"}, {Name: "Nyamu"}} + } + mujica.ReadReceipt(c, s.receipt, opts) +} + +func emojiPickerDemo(c *ui.Context, log func(string)) { + type state struct { + recent []string + tone int + picked string + disabled bool + } + s := ui.Local(c.Root(), "412", func() state { return state{} }) + mediaCheck(c, log, &s.disabled, "Disabled") + if r := mujica.EmojiPicker(c, mujica.EmojiPickerOptions{Recent: &s.recent, Tone: &s.tone, Disabled: s.disabled}); r.Picked != "" { + s.picked = r.Picked + log("emoji " + r.Picked) + } + ui.Text(c, "Picked: "+s.picked) +} + +func pinnedMessagesDemo(c *ui.Context, log func(string)) { + type state struct { + pins []mujica.ChatEntry + disabled bool + jump string + } + newPins := func() []mujica.ChatEntry { + return []mujica.ChatEntry{{ID: "a", Author: "Sakiko", Text: "Rehearsal moves to nine."}, {ID: "b", Author: "Uika", Text: "Masks are in the hall."}} + } + s := ui.Local(c.Root(), "413", func() state { return state{pins: newPins()} }) + mediaCheck(c, log, &s.disabled, "Disabled") + if mujica.Button(c, "Restore pins", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.pins = newPins() + log("pins restored") + } + r := mujica.PinnedMessages(c, s.pins, mujica.PinnedMessagesOptions{Disabled: s.disabled, Height: 180}) + if r.Jump != "" { + s.jump = r.Jump + log("jump " + r.Jump) + } + if r.Unpinned != "" { + s.pins = slices.DeleteFunc(slices.Clone(s.pins), func(m mujica.ChatEntry) bool { return m.ID == r.Unpinned }) + log("unpin " + r.Unpinned) + } + ui.Text(c, "Jump target: "+s.jump) +} + +func threadPanelDemo(c *ui.Context, log func(string)) { + type state struct { + open, disabled bool + replies []mujica.ChatEntry + } + s := ui.Local(c.Root(), "414", func() state { + return state{open: true, replies: []mujica.ChatEntry{{ID: "1", Author: "Uika", Text: "Overture first."}}} + }) + mediaCheck(c, log, &s.disabled, "Disabled") + if mujica.Button(c, "Open thread", mujica.ButtonOptions{Disabled: s.disabled}).Clicked() { + s.open = true + log("thread opened") + } + before := s.open + ui.Row(c).Height(420).Children(func() { + r := mujica.ThreadPanel(c, &s.open, mujica.ChatEntry{ID: "root", Author: "Sakiko", Text: "Set list for Friday?"}, s.replies, mujica.ThreadPanelOptions{Disabled: s.disabled}) + if r.Sent != "" { + s.replies = append(s.replies, mujica.ChatEntry{ID: fmt.Sprint(len(s.replies) + 1), Author: "Me", Text: r.Sent, Own: true}) + log("reply sent") + } + }) + if before && !s.open { + log("thread closed") + } +} diff --git a/examples/gallery/pages_messaging_mail.go b/examples/gallery/pages_messaging_mail.go new file mode 100644 index 0000000..0e35654 --- /dev/null +++ b/examples/gallery/pages_messaging_mail.go @@ -0,0 +1,179 @@ +package main + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" + mujica "mujicaui" +) + +func mailListDemo(c *ui.Context, log func(string)) { + type state struct { + list mujica.ListState[string] + mails []mujica.MailItem + disabled, empty bool + opened string + } + s := ui.Local(c.Root(), "415", func() state { + return state{mails: []mujica.MailItem{ + {ID: "1", From: "Sakiko", Subject: "Second act", Snippet: "The score is attached.", Unread: true, Attachments: 2}, + {ID: "2", From: "Uika", Subject: "Costumes", Snippet: "Fittings on Thursday.", Starred: true}, + {ID: "3", From: "Umiri", Subject: "Venue", Snippet: "The hall is booked."}, + }} + }) + mediaCheck(c, log, &s.disabled, "Disabled") + mediaCheck(c, log, &s.empty, "Empty") + if mujica.Button(c, "Load 100,000 mails", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.mails = make([]mujica.MailItem, 100000) + for i := range s.mails { + s.mails[i] = mujica.MailItem{ID: fmt.Sprint(i), From: "Sender", Subject: fmt.Sprintf("Mail %d", i), Unread: i%2 == 0} + } + log("loaded 100,000 mails") + } + mails := s.mails + if s.empty { + mails = nil + } + r := mujica.MailList(c, &s.list, mails, mujica.MailListOptions{Disabled: s.disabled, Height: 240}) + if r.Changed() { + log(fmt.Sprintf("selected %d mails", s.list.Selection.Len())) + } + if r.Opened != "" { + s.opened = r.Opened + for i := range s.mails { + if s.mails[i].ID == r.Opened { + s.mails[i].Unread = false + break + } + } + log("open " + r.Opened) + } + if r.Starred != "" { + for i := range s.mails { + if s.mails[i].ID == r.Starred { + s.mails[i].Starred = !s.mails[i].Starred + break + } + } + log("star " + r.Starred) + } + ui.Text(c, "Opened: "+s.opened) +} + +func mailReaderDemo(c *ui.Context, log func(string)) { + type state struct{ markdown, attachments, disabled bool } + s := ui.Local(c.Root(), "416", func() state { return state{attachments: true} }) + mediaCheck(c, log, &s.markdown, "Safe Markdown") + mediaCheck(c, log, &s.attachments, "Attachments") + mediaCheck(c, log, &s.disabled, "Disabled actions") + m := mujica.Mail{From: "Sakiko Togawa", To: []string{"Uika Misumi"}, Cc: []string{"Umiri Yahata"}, Subject: "Second act", Date: time.Date(2026, 10, 5, 21, 7, 0, 0, time.Local), Body: "The score is attached.\n> Can you send it tonight?"} + if s.markdown { + m.Format = mujica.MailMarkdown + m.Body = "**Rehearsal** at nine. [Venue](https://example.com)\n\n" + } + if s.attachments { + m.Attachments = []mujica.MailAttachment{{Name: "score.pdf", Size: 2048}} + } + ui.Column(c).Disabled(s.disabled).Children(func() { + r := mujica.MailReader(c, m) + if r.Link != "" { + log("link " + r.Link) + } + if r.Opened >= 0 { + log(fmt.Sprintf("open attachment %d", r.Opened)) + } + if r.Downloaded >= 0 { + log(fmt.Sprintf("download attachment %d", r.Downloaded)) + } + }) +} + +func mailComposerDemo(c *ui.Context, log func(string)) { + type state struct { + draft mujica.MailDraft + disabled bool + saved string + } + s := ui.Local(c.Root(), "417", func() state { return state{draft: mujica.MailDraft{To: []string{"uika@example.com"}}} }) + mediaCheck(c, log, &s.disabled, "Disabled") + r := mujica.MailComposer(c, &s.draft, mujica.MailComposerOptions{ + Disabled: s.disabled, Contacts: messagingContacts, + OnSaveDraft: func(d mujica.MailDraft) { s.saved = d.Subject; log("draft saved") }, + OnAttach: func() { + s.draft.Attachments = append(s.draft.Attachments, mujica.MailAttachment{Name: fmt.Sprintf("score-%d.pdf", len(s.draft.Attachments)+1), Size: 2048}) + log("attachment added") + }, + }) + if r.Sent { + log("mail sent") + s.draft = mujica.MailDraft{} + } + if r.Discarded { + log("draft discarded") + s.draft = mujica.MailDraft{} + } + ui.Text(c, "Saved subject: "+s.saved) +} + +var messagingContacts = []mujica.Contact{{Name: "Uika Misumi", Email: "uika@example.com"}, {Name: "Umiri Yahata", Email: "umiri@example.com"}, {Name: "Sakiko Togawa", Email: "sakiko@example.com"}} + +func recipientInputDemo(c *ui.Context, log func(string)) { + type state struct { + to []string + disabled, contacts bool + } + s := ui.Local(c.Root(), "418", func() state { return state{contacts: true} }) + mediaCheck(c, log, &s.disabled, "Disabled") + mediaCheck(c, log, &s.contacts, "Contact suggestions") + contacts := messagingContacts + if !s.contacts { + contacts = nil + } + if mujica.RecipientInput(c, &s.to, mujica.RecipientInputOptions{Contacts: contacts, Label: "Recipients", Disabled: s.disabled}).Changed() { + log(fmt.Sprintf("recipients %d", len(s.to))) + } + if mujica.Button(c, "Clear recipients", mujica.ButtonOptions{Variant: mujica.Secondary, Disabled: s.disabled}).Clicked() { + s.to = nil + log("recipients cleared") + } + ui.Text(c, "Type a name or email; Enter or comma commits valid addresses.") +} + +func quotedTextDemo(c *ui.Context, log func(string)) { + type state struct { + open, disabled bool + text string + } + s := ui.Local(c.Root(), "419", func() state { return state{text: "> Can you send the score?\n> Thanks."} }) + mediaCheck(c, log, &s.disabled, "Disabled") + if mujica.TextArea(c, &s.text, mujica.TextAreaOptions{Label: "Quoted source", MinHeight: 80}).Changed() { + log("quote source edited") + } + ui.Column(c).Disabled(s.disabled).Children(func() { + if mujica.QuotedText(c, s.text, &s.open).Changed() { + log(fmt.Sprintf("quote expanded %v", s.open)) + } + }) +} + +func snoozePickerDemo(c *ui.Context, log func(string)) { + type state struct { + until time.Time + disabled bool + morning float64 + } + s := ui.Local(c.Root(), "420", func() state { return state{morning: 9} }) + mediaCheck(c, log, &s.disabled, "Disabled") + if mujica.NumberInput(c, &s.morning, mujica.NumberInputOptions{Min: 1, Max: 23, Step: 1, Label: "Morning hour"}).Changed() { + log(fmt.Sprintf("morning %.0f", s.morning)) + } + if mujica.SnoozePicker(c, &s.until, mujica.SnoozePickerOptions{Disabled: s.disabled, MorningHour: int(s.morning)}).Changed() { + log("snooze " + s.until.Format(time.RFC3339)) + } + if mujica.Button(c, "Clear snooze", mujica.ButtonOptions{Variant: mujica.Secondary, Disabled: s.disabled}).Clicked() { + s.until = time.Time{} + log("snooze cleared") + } + ui.Text(c, fmt.Sprint("Until: ", s.until)) +} diff --git a/examples/gallery/pages_messaging_people.go b/examples/gallery/pages_messaging_people.go new file mode 100644 index 0000000..4f68711 --- /dev/null +++ b/examples/gallery/pages_messaging_people.go @@ -0,0 +1,136 @@ +package main + +import ( + "fmt" + "slices" + + "github.com/egoist/mygo/ui" + mujica "mujicaui" +) + +func channelListDemo(c *ui.Context, log func(string)) { + type state struct { + selected string + disabled bool + revision int + groups []mujica.ChannelGroup + } + s := ui.Local(c.Root(), "401", func() state { + return state{groups: []mujica.ChannelGroup{ + {ID: "channels", Title: "Channels", Channels: []mujica.Channel{ + {ID: "general", Name: "general", Unread: 3}, {ID: "rehearsal", Name: "rehearsal", Pinned: true}, + {ID: "random", Name: "random", Unread: 120, Muted: true}, + }}, + {ID: "direct", Title: "Direct messages", Channels: []mujica.Channel{{ID: "uika", Name: "Uika", Direct: true, Presence: mujica.PresenceOnline}}}, + }} + }) + mediaCheck(c, log, &s.disabled, "Disabled") + before := s.groups[0].Channels[0] + mediaCheck(c, log, &s.groups[0].Channels[0].Muted, "Mute general") + mediaCheck(c, log, &s.groups[0].Channels[0].Pinned, "Pin general") + if before != s.groups[0].Channels[0] { + s.revision++ + } + if mujica.ChannelList(c, &s.selected, s.groups, mujica.ChannelListOptions{Disabled: s.disabled, Revision: s.revision}).Changed() { + log("channel " + s.selected) + } + ui.Text(c, "Selected: "+s.selected) +} + +func memberListDemo(c *ui.Context, log func(string)) { + type state struct { + list mujica.MemberListState + disabled, empty bool + members []mujica.Member + } + s := ui.Local(c.Root(), "405", func() state { + return state{members: []mujica.Member{ + {ID: "1", Name: "Sakiko", Presence: mujica.PresenceOnline, Role: "Leader"}, + {ID: "2", Name: "Uika", Presence: mujica.PresenceBusy, Role: "Vocal"}, + {ID: "3", Name: "Mutsumi", Presence: mujica.PresenceAway}, {ID: "4", Name: "Umiri", Presence: mujica.PresenceOffline}, + }} + }) + mediaCheck(c, log, &s.disabled, "Disabled") + mediaCheck(c, log, &s.empty, "Empty") + if mujica.Button(c, "Toggle Uika presence", mujica.ButtonOptions{Variant: mujica.Secondary}).Clicked() { + s.members = slices.Clone(s.members) + if s.members[1].Presence == mujica.PresenceOffline { + s.members[1].Presence = mujica.PresenceOnline + } else { + s.members[1].Presence = mujica.PresenceOffline + } + log("Uika presence changed") + } + members := s.members + if s.empty { + members = nil + } + r := mujica.MemberList(c, &s.list, members, mujica.MemberListOptions{Disabled: s.disabled, Height: 240}) + if r.Changed() { + log("member " + s.list.Selected) + } + if r.Opened != "" { + log("profile " + r.Opened) + } +} + +func userProfileCardDemo(c *ui.Context, log func(string)) { + type state struct { + presence mujica.Presence + actions, disabled bool + } + s := ui.Local(c.Root(), "406", func() state { return state{actions: true, presence: mujica.PresenceOnline} }) + mediaCheck(c, log, &s.actions, "Actions") + mediaCheck(c, log, &s.disabled, "Disable actions") + messagingPresence(c, log, &s.presence) + opts := mujica.UserProfileCardOptions{} + if s.actions { + opts.Actions = func() { + for _, action := range []string{"Message", "Call"} { + if mujica.Button(c, action, mujica.ButtonOptions{Disabled: s.disabled}).Clicked() { + log(action) + } + } + } + } + mujica.UserProfileCard(c, mujica.UserProfile{Name: "Sakiko Togawa", Presence: s.presence, Role: "Keyboard", Status: "In rehearsal", About: "Founder of the masquerade."}, opts) +} + +func onlineStatusDemo(c *ui.Context, log func(string)) { + type state struct { + presence mujica.Presence + hidden bool + } + s := ui.Local(c.Root(), "407", func() state { return state{presence: mujica.PresenceOnline} }) + mediaCheck(c, log, &s.hidden, "Hide text") + messagingPresence(c, log, &s.presence) + mujica.OnlineStatus(c, s.presence, mujica.OnlineStatusOptions{HideText: s.hidden}) + inputSection(c, "States", func() { + for p := mujica.PresenceOffline; p <= mujica.PresenceBusy; p++ { + mujica.OnlineStatus(c, p, mujica.OnlineStatusOptions{}) + } + }) +} + +func statusSetterDemo(c *ui.Context, log func(string)) { + type state struct { + status mujica.CustomStatus + disabled bool + } + s := ui.Local(c.Root(), "408", func() state { return state{} }) + mediaCheck(c, log, &s.disabled, "Disabled") + if mujica.StatusSetter(c, &s.status, mujica.StatusSetterOptions{Disabled: s.disabled}).Changed() { + log("status changed") + } + ui.Text(c, fmt.Sprintf("Text: %s; expires: %v", s.status.Text, s.status.Until)) +} + +func messagingPresence(c *ui.Context, log func(string), value *mujica.Presence) { + items := []mujica.SelectOption[mujica.Presence]{ + {Value: mujica.PresenceOnline, Label: "Online"}, {Value: mujica.PresenceAway, Label: "Away"}, + {Value: mujica.PresenceBusy, Label: "Busy"}, {Value: mujica.PresenceOffline, Label: "Offline"}, + } + if mujica.Select(c, value, items, mujica.SelectOptions{Label: "Presence"}).Changed() { + log(fmt.Sprintf("presence %d", *value)) + } +} diff --git a/examples/gallery/pages_messaging_test.go b/examples/gallery/pages_messaging_test.go new file mode 100644 index 0000000..e55faa0 --- /dev/null +++ b/examples/gallery/pages_messaging_test.go @@ -0,0 +1,122 @@ +package main + +import ( + "fmt" + "image/png" + "os" + "path/filepath" + "slices" + "strings" + "testing" + + "github.com/egoist/mygo/ui" + mujica "mujicaui" +) + +func messagingDemoTester(t *testing.T, id string, mode mujica.Mode) (*ui.Tester, *[]string) { + t.Helper() + i := slices.IndexFunc(messagingPages, func(p page) bool { return p.ID == id }) + if i < 0 { + t.Fatalf("missing 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(12).Children(func() { + messagingPages[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 TestMessagingDemosInteractAndLog(t *testing.T) { + cases := []struct{ id, click, event string }{ + {"401", "random, 120 unread", "channel random"}, + {"402", "Like", "reaction true"}, + {"403", "Unread count", "unread 7"}, + {"404", "Read", "receipt 0"}, + {"405", "Sakiko", "member 1"}, + {"406", "Message", "Message"}, + {"407", "Presence", "presence 3"}, + {"408", "Status text", "status changed"}, + {"409", "Mute", "mute true"}, + {"410", "Speaking", "Speaking = false"}, + {"411", "Incoming call", "Declined"}, + {"412", "grinning face", "emoji "}, + {"413", "Unpin Uika's message", "unpin b"}, + {"414", "Reply in thread", "reply sent"}, + {"415", "Star Second act", "star 1"}, + {"416", "Download score.pdf", "download attachment 0"}, + {"417", "Attach", "attachment added"}, + {"418", "Recipients", "recipients 1"}, + {"419", "Show quoted text (2 lines)", "quote expanded true"}, + {"420", "Tomorrow", "snooze "}, + } + if len(messagingPages) != len(cases) { + t.Fatalf("pages=%d, cases=%d", len(messagingPages), len(cases)) + } + for _, tc := range cases { + for _, mode := range []mujica.Mode{mujica.Light, mujica.Dark} { + t.Run(tc.id+mode.String(), func(t *testing.T) { + tt, events := messagingDemoTester(t, tc.id, mode) + if err := tt.Click(tc.click); err != nil { + t.Fatal(err) + } + switch tc.id { + case "403": + tt.Command("selectAll") + tt.Type("7") + tt.Key(0, ui.KeyEnter) + case "404": + if err := tt.Click("Sent"); err != nil { + t.Fatal(err) + } + case "407": + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + case "408": + tt.Type("Rehearsing") + case "411": + tt.Key(0, ui.KeyEnter) + case "414": + tt.Type("Second act") + tt.Key(0, ui.KeyEnter) + case "418": + tt.Type("guest@example.com") + tt.Key(0, ui.KeyEnter) + } + if !slices.ContainsFunc(*events, func(s string) bool { return strings.HasPrefix(s, tc.event) }) { + t.Fatalf("want %q, events %v", tc.event, *events) + } + }) + } + } +} + +func TestMessagingDemoCaptures(t *testing.T) { + dir := os.Getenv("MESSAGING_DEMO_DIR") + if dir == "" { + t.Skip("set MESSAGING_DEMO_DIR to export demos") + } + for _, p := range messagingPages { + if p.Category != "Messaging & Mail" || p.Code == "" || p.Keys == "" { + t.Fatalf("incomplete page %s", p.ID) + } + for _, mode := range []mujica.Mode{mujica.Light, mujica.Dark} { + tt, _ := messagingDemoTester(t, p.ID, mode) + f, err := os.Create(filepath.Join(dir, fmt.Sprintf("%s-%s.png", p.ID, mode))) + if err != nil { + t.Fatal(err) + } + if err := png.Encode(f, tt.Image()); err != nil { + t.Fatal(err) + } + if err := f.Close(); err != nil { + t.Fatal(err) + } + } + } +} diff --git a/incoming_call_dialog.go b/incoming_call_dialog.go new file mode 100644 index 0000000..93a6958 --- /dev/null +++ b/incoming_call_dialog.go @@ -0,0 +1,91 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// IncomingCall is who calls; Caller is required. +type IncomingCall struct { + Caller string + Image *ui.Bitmap + // Video offers answering with the camera on. + Video bool +} + +// IncomingCallOptions configure an IncomingCallDialog. +type IncomingCallOptions struct { + // FocusAccept focuses Accept instead of the default Decline. + FocusAccept bool + Disabled bool + // OnAccept answers; OnDecline refuses or handles Escape. + OnAccept func(video bool) + OnDecline func() +} + +// IncomingCallDialog presents call actions with configurable initial focus. +func IncomingCallDialog(c *ui.Context, open *bool, call IncomingCall, opts IncomingCallOptions) { + if call.Caller == "" || opts.OnAccept == nil || opts.OnDecline == nil { + panic("mujica: IncomingCallDialog needs Caller, OnAccept and OnDecline") + } + site, focus := overlaySite(c) + if opts.Disabled || site.IsDisabled() { + *open = false + } + if !*open { + focus.closed(c, site) + return + } + overlayLayer(c, open) + k := Tokens(c) + u := Density(c).Unit() + title := fmt.Sprintf(msg(c, "incoming_call_dialog.title"), call.Caller) + shown, accepted, video, declined, backClicked := true, false, false, false, false + panel := ui.DialogBase(c, &shown, func(back, panel *ui.Element) { + backClicked = back.Clicked() // a click outside neither answers nor refuses + p := overlayEnter(c, panel) + back.Background(overlayScrim(k).Alpha(p)).Padding(16) + dialogPanel(c, panel, 420, false, p) + panel.Role(ui.RoleAlertDialog).Label(title).AlignItems(ui.Center) + ui.Scroll(c).Shrink(1).FillWidth().Gap(u * 3).AlignItems(ui.Center).Children(func() { + Avatar(c, call.Caller, AvatarOptions{Image: call.Image, Size: 72}) + ui.Text(c, call.Caller).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).FontWeight(600).TextAlign(ui.Center) + kind := msg(c, "incoming_call_dialog.voice") + if call.Video { + kind = msg(c, "incoming_call_dialog.video") + } + ui.Text(c, kind).TextColor(k.TextMuted) + }) + ui.Row(c).Shrink(0).Gap(u*3).Wrap().Justify(ui.Center).Margin(u*2, 0, 0, 0).Children(func() { + decline := Button(c, msg(c, "incoming_call_dialog.decline"), ButtonOptions{Variant: Danger, Icon: msgHangUp, Label: msg(c, "incoming_call_dialog.decline")}) + accept := Button(c, msg(c, "incoming_call_dialog.accept"), ButtonOptions{Icon: msgPhone, Label: msg(c, "incoming_call_dialog.accept")}) + if opts.FocusAccept { + accept.AutoFocus() + } else { + decline.AutoFocus() + } + declined, accepted = decline.Clicked(), accept.Clicked() + if call.Video && Button(c, msg(c, "incoming_call_dialog.acceptVideo"), ButtonOptions{Variant: Secondary, Icon: mediaCamera, Label: msg(c, "incoming_call_dialog.acceptVideo")}).Clicked() { + accepted, video = true, true + } + }) + }) + focus.shown(panel) + if !shown && !accepted && !backClicked { + declined = true // Escape + } + switch { + case accepted: + *open = false + slog.Debug("mujica: incoming_call accept", "video", video) + opts.OnAccept(video) + case declined: + *open = false + slog.Debug("mujica: incoming_call decline") + opts.OnDecline() + } +} diff --git a/incoming_call_dialog_test.go b/incoming_call_dialog_test.go new file mode 100644 index 0000000..1f76ec1 --- /dev/null +++ b/incoming_call_dialog_test.go @@ -0,0 +1,93 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestIncomingCallDefaultFocusAndEscape(t *testing.T) { + open := false + accepted, declined := 0, 0 + opts := IncomingCallOptions{OnAccept: func(bool) { accepted++ }, OnDecline: func() { declined++ }} + tt := incomingTester(&open, opts, IncomingCall{Caller: "Uika"}) + if err := tt.Click("Ring"); err != nil { + t.Fatal(err) + } + if !tt.Focused("Decline") || !tt.HasText("Uika") { + t.Fatalf("Decline not focused: %v", tt.Texts()) + } + tt.Key(0, ui.KeyEnter) + if declined != 1 || open { + t.Fatalf("Enter on the default declined %d", declined) + } + open = true + tt.Frame() + tt.Key(0, ui.KeyEscape) + if declined != 2 || accepted != 0 || open { + t.Fatalf("Escape declined %d", declined) + } +} + +func TestIncomingCallFocusAcceptAndVideo(t *testing.T) { + open := true + var videos []bool + opts := IncomingCallOptions{FocusAccept: true, OnAccept: func(v bool) { videos = append(videos, v) }, OnDecline: func() {}} + tt := incomingTester(&open, opts, IncomingCall{Caller: "Sakiko", Video: true}) + if !tt.Focused("Accept") { + t.Fatal("Accept not focused") + } + if err := tt.Click("With video"); err != nil { + t.Fatal(err) + } + if len(videos) != 1 || !videos[0] || open { + t.Fatalf("accepted %v", videos) + } + mediaPanics(t, "no caller", func(c *ui.Context) { IncomingCallDialog(c, &open, IncomingCall{}, opts) }) +} + +func TestIncomingCallSnapshot(t *testing.T) { + open := true + opts := IncomingCallOptions{OnAccept: func(bool) {}, OnDecline: func() {}} + snapshot(t, "incoming_call_dialog", 520, 400, func(c *ui.Context) { + IncomingCallDialog(c, &open, IncomingCall{Caller: "Sakiko Togawa", Video: true}, opts) + }) +} + +func TestIncomingCallDisabledAncestorCloses(t *testing.T) { + open, disabled, events := true, false, 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Disabled(disabled).Children(func() { + IncomingCallDialog(c, &open, IncomingCall{Caller: "Caller"}, IncomingCallOptions{ + OnAccept: func(bool) { events++ }, OnDecline: func() { events++ }, + }) + }) + }, 400, 300) + disabled = true + tt.Frame() + tt.Key(0, ui.KeyEnter) + if open || events != 0 || tt.HasText("Decline") { + t.Fatalf("disabled dialog: open=%v events=%d", open, events) + } +} + +func TestIncomingCallSmallWindowKeyboardActions(t *testing.T) { + open, accepted := true, 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + IncomingCallDialog(c, &open, IncomingCall{Caller: "Caller", Video: true}, IncomingCallOptions{ + OnAccept: func(bool) { accepted++ }, OnDecline: func() {}, + }) + }, 280, 220) + tt.SetPreferences(ui.Preferences{ReduceMotion: true, TextScale: 1}) + tt.Key(0, ui.KeyTab) + r, ok := tt.Find("Accept") + if !ok || r.W < 28 || r.H < 28 || r.X < 0 || r.Y < 0 || r.X+r.W > 280 || r.Y+r.H > 220 { + t.Fatalf("accept bounds %+v", r) + } + tt.Key(0, ui.KeyEnter) + if open || accepted != 1 { + t.Fatalf("accept callbacks=%d open=%v", accepted, open) + } +} diff --git a/mail_composer.go b/mail_composer.go new file mode 100644 index 0000000..b0863be --- /dev/null +++ b/mail_composer.go @@ -0,0 +1,213 @@ +package mujica + +import ( + "fmt" + "log/slog" + "net/mail" + "slices" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// MailDraft is a mail being written. +type MailDraft struct { + To, Cc, Bcc []string + Subject, Body string + Attachments []MailAttachment +} + +// MailComposerOptions configure a MailComposer. +type MailComposerOptions struct { + Contacts []Contact + // OnSaveDraft saves rested edits or manual requests; required. + OnSaveDraft func(MailDraft) + // OnAttach asks the caller to pick files; nil hides Attach. + OnAttach func() + Disabled bool +} + +// MailComposerResult is the composer's element and this frame's events. +type MailComposerResult struct { + Element *ui.Element + // Sent requests sending; Discarded requests discarding the draft. + Sent, Discarded bool +} + +const mailSaveDelay = 2 * time.Second + +type composerState struct { + cc, bcc bool + dirty bool + edited time.Time + saved time.Time + last MailDraft + started bool +} + +type composerKey struct{} + +// MailComposer edits mail fields and reports draft save requests. +func MailComposer(c *ui.Context, d *MailDraft, opts MailComposerOptions) MailComposerResult { + if opts.OnSaveDraft == nil { + panic("mujica: MailComposer needs OnSaveDraft") + } + k := Tokens(c) + u := Density(c).Unit() + var r MailComposerResult + col := ui.Column(c).Gap(u * 3).Role(ui.RoleGroup).Label(msg(c, "mail_composer.label")).Disabled(opts.Disabled) + r.Element = col + st := ui.Local(col, composerKey{}, func() *composerState { return &composerState{} }) + s := *st + live := !col.IsDisabled() + if !live { + copy := composerCopy(*d) + d = © + } + if !s.started { + s.started, s.last = true, composerCopy(*d) + s.cc, s.bcc = len(d.Cc) > 0, len(d.Bcc) > 0 + } + s.cc = s.cc || len(d.Cc) > 0 + s.bcc = s.bcc || len(d.Bcc) > 0 + col.Children(func() { + field := func(key string, list *[]string, extra func()) { + ui.Row(c).Gap(u * 2).AlignItems(ui.Start).Children(func() { + label := ui.Text(c, msg(c, key)).Width(56).TextColor(k.TextMuted).Margin(u*2, 0, 0, 0).SingleLine() + parts := RecipientInput(c, list, RecipientInputOptions{Contacts: opts.Contacts, Label: msg(c, key), Disabled: opts.Disabled}) + parts.Element.Grow(1).MinWidth(0) + if label.Clicked() && !parts.Input.IsDisabled() { + parts.Input.Focus() + } + if extra != nil { + extra() + } + }) + } + field("mail_composer.to", &d.To, func() { + if !s.cc && Button(c, msg(c, "mail_composer.cc"), ButtonOptions{Variant: Ghost}).Clicked() { + s.cc = true + } + if !s.bcc && Button(c, msg(c, "mail_composer.bcc"), ButtonOptions{Variant: Ghost}).Clicked() { + s.bcc = true + } + }) + if s.cc { + field("mail_composer.cc", &d.Cc, nil) + } + if s.bcc { + field("mail_composer.bcc", &d.Bcc, nil) + } + TextInput(c, &d.Subject, TextInputOptions{Placeholder: msg(c, "mail_composer.subject"), Label: msg(c, "mail_composer.subject"), Disabled: opts.Disabled}) + if TextArea(c, &d.Body, TextAreaOptions{Label: msg(c, "mail_composer.body"), MinHeight: 160, Disabled: opts.Disabled}).Submitted() && + composerReady(*d) { + r.Sent = true + } + if len(d.Attachments) > 0 { + composerAttachments(c, k, d, opts.Disabled) + } + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ready := composerReady(*d) + if Button(c, msg(c, "mail_composer.send"), ButtonOptions{Icon: msgSend, Disabled: !ready}).Clicked() { + r.Sent = true + } + if opts.OnAttach != nil && Button(c, msg(c, "mail_composer.attach"), ButtonOptions{Variant: Secondary, Icon: msgPaperclip}).Clicked() { + slog.Debug("mujica: mail_composer attach") + opts.OnAttach() + } + ui.Box(c).Grow(1) + composerStatus(c, k, s) + if Button(c, msg(c, "mail_composer.discard"), ButtonOptions{Variant: Ghost, Icon: icons.Must("trash-2")}).Clicked() { + r.Discarded = true + } + }) + }) + if live && col.Shortcut(ui.Cmd, ui.KeyEnter) && composerReady(*d) { + r.Sent = true + } + if live { + composerAutosave(c, s, *d, opts.OnSaveDraft, col.Shortcut(ui.Cmd, ui.KeyS)) + } + if !live { + r.Sent, r.Discarded = false, false + } + if r.Sent || r.Discarded { + slog.Debug("mujica: mail_composer done", "sent", r.Sent) + } + return r +} + +func composerAutosave(c *ui.Context, s *composerState, d MailDraft, save func(MailDraft), now bool) { + if !composerSame(s.last, d) { + s.last, s.dirty, s.edited = composerCopy(d), true, c.Now() + } + if !s.dirty && !now { + return + } + if wait := mailSaveDelay - c.Now().Sub(s.edited); wait > 0 && !now { + c.After(wait) + return + } + s.dirty, s.saved = false, c.Now() + slog.Debug("mujica: mail_composer save draft") + save(composerCopy(d)) +} + +// composerStatus says whether the draft is saved. +func composerStatus(c *ui.Context, k theme.Tokens, s *composerState) { + text := "" + switch { + case s.dirty: + text = msg(c, "mail_composer.unsaved") + case !s.saved.IsZero(): + text = fmt.Sprintf(msg(c, "mail_composer.saved"), s.saved.Format("15:04")) + } + if text != "" { + ui.Text(c, text).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).Role(ui.RoleStatus) + } +} + +// composerAttachments lists attached files with remove buttons. +func composerAttachments(c *ui.Context, k theme.Tokens, d *MailDraft, disabled bool) { + ui.Row(c).Gap(Density(c).Unit() * 2).Wrap().Children(func() { + for i, a := range d.Attachments { + var v TagView + ui.Box(c).Key(fmt.Sprint(i, a.Name)).Children(func() { + v = Tag(c, a.Name, TagOptions{Icon: "file", Closable: true, Disabled: disabled}) + }) + if v.Closed { + d.Attachments = slices.Delete(slices.Clone(d.Attachments), i, i+1) + return + } + } + }) +} + +// composerReady reports at least one recipient and only valid addresses. +func composerReady(d MailDraft) bool { + if len(d.To)+len(d.Cc)+len(d.Bcc) == 0 { + return false + } + for _, list := range [][]string{d.To, d.Cc, d.Bcc} { + for _, a := range list { + if _, err := mail.ParseAddress(a); err != nil { + return false + } + } + } + return true +} + +func composerCopy(d MailDraft) MailDraft { + d.To, d.Cc, d.Bcc = slices.Clone(d.To), slices.Clone(d.Cc), slices.Clone(d.Bcc) + d.Attachments = slices.Clone(d.Attachments) + return d +} + +func composerSame(a, b MailDraft) bool { + return a.Subject == b.Subject && a.Body == b.Body && slices.Equal(a.To, b.To) && slices.Equal(a.Cc, b.Cc) && + slices.Equal(a.Bcc, b.Bcc) && slices.Equal(a.Attachments, b.Attachments) +} diff --git a/mail_composer_test.go b/mail_composer_test.go new file mode 100644 index 0000000..a842e4b --- /dev/null +++ b/mail_composer_test.go @@ -0,0 +1,187 @@ +package mujica + +import ( + "slices" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func TestMailComposerDisabledDefersSave(t *testing.T) { + draft := MailDraft{To: []string{"a@example.com"}} + disabled, saves := false, 0 + var state *composerState + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Disabled(disabled).Children(func() { + r := MailComposer(c, &draft, MailComposerOptions{OnSaveDraft: func(MailDraft) { saves++ }}) + state = *ui.Local(r.Element, composerKey{}, func() *composerState { panic("missing state") }) + }) + }, 600, 600) + if err := tt.Click("Subject"); err != nil { + t.Fatal(err) + } + tt.Type("Draft") + disabled = true + state.edited = time.Now().Add(-10 * time.Second) + tt.Frame() + if saves != 0 { + t.Fatalf("disabled save callbacks: %d", saves) + } + disabled = false + tt.Frame() + if saves != 1 { + t.Fatalf("resumed save callbacks: %d", saves) + } +} + +func TestMailComposerManualSaveAndFocus(t *testing.T) { + draft := MailDraft{To: []string{"a@example.com"}} + saves, sent := 0, 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if MailComposer(c, &draft, MailComposerOptions{OnSaveDraft: func(MailDraft) { saves++ }}).Sent { + sent++ + } + TextInput(c, new(string), TextInputOptions{Label: "Other"}) + }, 600, 700) + if err := tt.Click("Subject"); err != nil { + t.Fatal(err) + } + tt.Key(ui.Cmd, ui.KeyS) + if saves != 1 { + t.Fatalf("manual save callbacks: %d", saves) + } + if err := tt.Click("Other"); err != nil { + t.Fatal(err) + } + tt.Key(ui.Cmd, ui.KeyEnter) + if sent != 0 { + t.Fatalf("composer submitted from another field: %d", sent) + } +} + +func TestMailComposerAutosaveAndSend(t *testing.T) { + d := MailDraft{To: []string{"uika@example.com"}} + var saves []MailDraft + sent := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).Width(560).Children(func() { + if MailComposer(c, &d, MailComposerOptions{OnSaveDraft: func(m MailDraft) { saves = append(saves, m) }}).Sent { + sent++ + } + }) + }, 700, 700) + if err := tt.Click("Subject"); err != nil { + t.Fatal(err) + } + tt.Type("Second act") + if len(saves) != 0 || !tt.HasText("Unsaved changes") { + t.Fatal("saved before the draft rested") + } + tt.Key(ui.Cmd, ui.KeyS) + if len(saves) != 1 || saves[0].Subject != "Second act" { + t.Fatalf("Cmd+S saves %+v", saves) + } + if err := tt.Click("Cc"); err != nil { + t.Fatal(err) + } + if err := tt.Click("Message"); err != nil { + t.Fatal(err) + } + tt.Type("The score is attached.") + tt.Key(ui.Cmd, ui.KeyEnter) + if sent != 1 || d.Body != "The score is attached." { + t.Fatalf("sent %d body %q", sent, d.Body) + } +} + +func TestMailComposerNeedsRecipientsAndDisabled(t *testing.T) { + d := MailDraft{Subject: "x"} + sent := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if MailComposer(c, &d, MailComposerOptions{OnSaveDraft: func(MailDraft) {}}).Sent { + sent++ + } + }, 700, 700) + _ = tt.Click("Send") + tt.Key(ui.Cmd, ui.KeyEnter) + if sent != 0 { + t.Fatal("sent without recipients") + } + mediaPanics(t, "no save callback", func(c *ui.Context) { MailComposer(c, &d, MailComposerOptions{}) }) +} + +func TestMailComposerSnapshot(t *testing.T) { + d := MailDraft{To: []string{"Uika Misumi "}, Subject: "The second act", Body: "The score is attached.", + Attachments: []MailAttachment{{Name: "score.pdf", Size: 2048}}} + snapshot(t, "mail_composer", 600, 460, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(560).Children(func() { + MailComposer(c, &d, MailComposerOptions{OnSaveDraft: func(MailDraft) {}, OnAttach: func() {}}) + }) + }) +} + +func TestMailComposerAttachmentsAndAddressFields(t *testing.T) { + d := MailDraft{To: []string{"uika@example.com"}} + attachments, discards := 0, 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := MailComposer(c, &d, MailComposerOptions{OnSaveDraft: func(MailDraft) {}, OnAttach: func() { + d.Attachments = append(d.Attachments, MailAttachment{Name: "score.pdf", Size: 2048}) + attachments++ + }}) + if r.Discarded { + discards++ + } + }, 700, 700) + for _, label := range []string{"Cc", "Bcc", "Attach"} { + if err := tt.Click(label); err != nil { + t.Fatal(err) + } + } + if attachments != 1 || len(d.Attachments) != 1 { + t.Fatal("attachment callback did not update draft") + } + if err := tt.Click("Cc"); err != nil { + t.Fatal(err) + } + tt.Type("cc@example.com") + tt.Key(0, ui.KeyEnter) + if err := tt.Click("Bcc"); err != nil { + t.Fatal(err) + } + tt.Type("bcc@example.com") + tt.Key(0, ui.KeyEnter) + if !slices.Equal(d.Cc, []string{"cc@example.com"}) || !slices.Equal(d.Bcc, []string{"bcc@example.com"}) { + t.Fatal("address fields did not commit") + } + if err := tt.Click("Remove score.pdf"); err != nil { + t.Fatal(err) + } + if len(d.Attachments) != 0 { + t.Fatal("attachment removal failed") + } + if err := tt.Click("Discard"); err != nil { + t.Fatal(err) + } + if discards != 1 { + t.Fatalf("discard events=%d", discards) + } +} + +func TestMailComposerLoadedAddressFields(t *testing.T) { + d := MailDraft{} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + MailComposer(c, &d, MailComposerOptions{OnSaveDraft: func(MailDraft) {}}) + }, 700, 700) + d = MailDraft{Cc: []string{"cc@example.com"}, Bcc: []string{"bcc@example.com"}} + tt.Frame() + if !tt.HasText("cc@example.com") || !tt.HasText("bcc@example.com") { + t.Fatal("loaded recipients remain hidden") + } +} diff --git a/mail_list.go b/mail_list.go new file mode 100644 index 0000000..71e6f88 --- /dev/null +++ b/mail_list.go @@ -0,0 +1,139 @@ +package mujica + +import ( + "fmt" + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// MailItem supplies a unique ID and mail preview data. +type MailItem struct { + ID, From, Subject, Snippet string + Time time.Time + Unread, Starred bool + Attachments int +} + +// MailListOptions configure a MailList. +type MailListOptions struct { + // Height is the list's height; zero means 420. + Height float32 + Disabled bool +} + +// MailListResult is a MailList's element and this frame's events. +type MailListResult struct { + Element *ui.Element + changed bool + // Opened contains the ID activated by Enter or double-click. + Opened string + // Starred is the ID whose star the user toggled. + Starred string +} + +// Changed reports a new selection; s.Selection holds the chosen IDs. +func (r MailListResult) Changed() bool { return r.changed } + +// MailList virtualizes previews, selection and star actions. +func MailList(c *ui.Context, s *ListState[string], mails []MailItem, opts MailListOptions) MailListResult { + if opts.Height < 0 { + panic("mujica: MailList Height must not be negative") + } + h := opts.Height + if h == 0 { + h = 420 + } + k := Tokens(c) + u := Density(c).Unit() + small := FontSize(c, theme.CaptionSize) + var r MailListResult + box := ui.Column(c).Height(h).Disabled(opts.Disabled) + r.Element = box + box.Children(func() { + v := List(c, s, len(mails), ListOptions[string]{ + Key: func(i int) string { return mails[i].ID }, + Label: func(i int) string { return mailLabel(c, mails[i]) }, + Multiple: true, + Empty: msg(c, "mail_list.empty"), + }, func(i int) { + m := mails[i] + if m.ID == "" { + panic("mujica: MailList item without an ID") + } + ui.Box(c).Width(8).Shrink(0).Children(func() { + if m.Unread { + ui.Box(c).Size(8, 8).Radius(4).Background(k.AccentText) + } + }) + star := mediaToggleAction(c, icons.Must("star"), fmt.Sprintf(msg(c, "mail_list.star"), m.Subject), m.Starred) + if m.Starred { + star.TextColor(k.Warning) + } + if star.Clicked() && !star.IsDisabled() { + r.Starred = m.ID + } + ui.Column(c).Grow(1).MinWidth(0).Gap(2).Padding(u, 0).Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + from := ui.Text(c, m.From).SingleLine().Grow(1).MinWidth(0) + if m.Unread { + from.FontWeight(700) + } + if m.Attachments > 0 { + ui.Icon(c, msgPaperclip).Size(13, 13).TextColor(k.TextMuted).Label(fmt.Sprintf(msg(c, "mail_list.attachments"), m.Attachments)) + } + if !m.Time.IsZero() { + ui.Text(c, mailTime(c, m.Time)).FontSize(small).TextColor(k.TextMuted).FontFeatures("tnum").SingleLine() + } + }) + subj := ui.Text(c, m.Subject).SingleLine() + if m.Unread { + subj.FontWeight(700) + } + ui.Text(c, m.Snippet).FontSize(small).TextColor(k.TextMuted).SingleLine() + }) + }) + v.Element.Grow(1) + r.changed = v.Changed() + if v.Element.IsDisabled() { + return + } + if id, ok := s.Selected(); ok { + if v.Submitted() { + r.Opened = id + } + if v.Element.Shortcut(0, ui.KeyS) { + r.Starred = id + } + } + }) + if r.Opened != "" || r.Starred != "" { + slog.Debug("mujica: mail_list action", "opened", r.Opened, "starred", r.Starred) + } + return r +} + +// mailLabel reads a row: unread, starred, from, subject. +func mailLabel(c *ui.Context, m MailItem) string { + s := m.From + ", " + m.Subject + if m.Starred { + s = msg(c, "mail_list.starred") + ", " + s + } + if m.Unread { + s = msg(c, "mail_list.unread") + ", " + s + } + return s +} + +// mailTime shows today's mails by time, older ones by date. +func mailTime(c *ui.Context, t time.Time) string { + now := c.Now().In(t.Location()) + if y, m, d := t.Date(); y == now.Year() && m == now.Month() && d == now.Day() { + return t.Format("15:04") + } + return t.Format(msg(c, "mail_list.date")) +} diff --git a/mail_list_test.go b/mail_list_test.go new file mode 100644 index 0000000..5d50b59 --- /dev/null +++ b/mail_list_test.go @@ -0,0 +1,90 @@ +package mujica + +import ( + "strings" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestMailListSelectStarOpen(t *testing.T) { + var s ListState[string] + mails := mailTestItems(6) + var opened, starred []string + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + r := MailList(c, &s, mails, MailListOptions{}) + if r.Opened != "" { + opened = append(opened, r.Opened) + } + if r.Starred != "" { + starred = append(starred, r.Starred) + } + }, 600, 500) + if err := tt.Click("Subject 0"); err != nil { + t.Fatal(err) + } + r2, _ := tt.Find("Subject 2") + tt.ClickAtWith(ui.Cmd, r2.X+4, r2.Y+4) + if s.Selection.Len() != 2 || !s.Selection.Has("m0") || !s.Selection.Has("m2") { + t.Fatalf("selection %d", s.Selection.Len()) + } + if err := tt.Click("Star Subject 3"); err != nil { + t.Fatal(err) + } + tt.Key(0, ui.KeyS) + tt.Key(0, ui.KeyEnter) + if len(starred) != 2 || starred[0] != "m3" || len(opened) != 1 { + t.Fatalf("starred %v opened %v", starred, opened) + } + if _, ok := tt.Find("Unread, Sender 0, Subject 0"); !ok { + t.Fatal("unread not named") + } +} + +func TestMailListBuildsOnlyVisible(t *testing.T) { + var s ListState[string] + mails := mailTestItems(100000) + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + MailList(c, &s, mails, MailListOptions{}) + }, 600, 500) + tt.Frame() + built := 0 + for _, x := range tt.Texts() { + if strings.HasPrefix(x, "Subject ") { + built++ + } + } + if built == 0 || built > 40 { + t.Fatalf("built %d rows of 100000", built) + } +} + +func TestMailListDisabled(t *testing.T) { + var s ListState[string] + starred := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if MailList(c, &s, mailTestItems(3), MailListOptions{Disabled: true}).Starred != "" { + starred++ + } + }, 600, 400) + _ = tt.Click("Star Subject 0") + _ = tt.Click("Subject 1") + if starred != 0 || s.Selection.Len() != 0 { + t.Fatal("disabled list reacted") + } +} + +func TestMailListSnapshot(t *testing.T) { + mails := []MailItem{ + {ID: "1", From: "Sakiko Togawa", Subject: "Second act", Snippet: "The score is attached.", Unread: true, Attachments: 2}, + {ID: "2", From: "Uika Misumi", Subject: "Costumes", Snippet: "Fittings on Thursday.", Starred: true}, + {ID: "3", From: "Umiri Yahata", Subject: "Venue", Snippet: "The hall is booked."}, + } + snapshot(t, "mail_list", 480, 260, func(c *ui.Context) { + s := ui.Local(c.Root(), "mail", func() *ListState[string] { return &ListState[string]{} }) + ui.Column(c).Padding(20).Width(440).Children(func() { MailList(c, *s, mails, MailListOptions{Height: 220}) }) + }) +} diff --git a/mail_reader.go b/mail_reader.go new file mode 100644 index 0000000..7fd0968 --- /dev/null +++ b/mail_reader.go @@ -0,0 +1,135 @@ +package mujica + +import ( + "log/slog" + "strings" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// MailFormat selects plain text or safe Markdown. +type MailFormat int + +const ( + MailPlain MailFormat = iota + // MailMarkdown uses MarkdownView’s safe subset. + MailMarkdown +) + +// MailAttachment is a file sent with a mail. +type MailAttachment struct { + Name string + Size int64 + Type string +} + +// Mail supplies headers, body and attachments. +type Mail struct { + From string + To, Cc []string + Subject string + Date time.Time + Body string + Format MailFormat + Attachments []MailAttachment +} + +// MailReaderResult is a MailReader's element and this frame's events. +type MailReaderResult struct { + Element *ui.Element + // Link contains the activated URL, or an empty string. + Link string + // Opened and Downloaded are attachment indexes, -1 for none. + Opened, Downloaded int +} + +type mailQuotesKey struct{} + +// MailReader displays headers, body, folded quotes and attachments. +func MailReader(c *ui.Context, m Mail) MailReaderResult { + if m.From == "" || m.Subject == "" { + panic("mujica: MailReader needs From and Subject") + } + if m.Format != MailPlain && m.Format != MailMarkdown { + panic("mujica: unknown MailFormat") + } + k := Tokens(c) + u := Density(c).Unit() + r := MailReaderResult{Opened: -1, Downloaded: -1} + col := ui.Column(c).Gap(u * 4).MinWidth(0).Role(ui.RoleGroup).Label(m.Subject) + r.Element = col + small := FontSize(c, theme.CaptionSize) + col.Children(func() { + ui.Text(c, m.Subject).Font(theme.SerifFont).FontSize(FontSize(c, theme.H2Size)).FontWeight(600) + ui.Row(c).Gap(u * 3).AlignItems(ui.Start).Children(func() { + Avatar(c, m.From, AvatarOptions{Size: 36}) + ui.Column(c).Gap(2).Grow(1).MinWidth(0).Children(func() { + ui.Text(c, m.From).FontWeight(600).Selectable().FocusRing(false) + for _, line := range [][2]string{{"mail_reader.to", strings.Join(m.To, ", ")}, {"mail_reader.cc", strings.Join(m.Cc, ", ")}} { + if line[1] != "" { + ui.Text(c, msg(c, line[0])+" "+line[1]).FontSize(small).TextColor(k.TextMuted).Selectable().FocusRing(false) + } + } + }) + if !m.Date.IsZero() { + ui.Text(c, messagingDate(c, m.Date, "mail_reader.date")).FontSize(small).TextColor(k.TextMuted).FontFeatures("tnum").SingleLine() + } + }) + ui.Box(c).Height(1).Background(k.Border) + if m.Format == MailMarkdown { + if url, ok := MarkdownView(c, m.Body).Link(); ok { + r.Link = url + } + } else { + mailPlainBody(c, ui.Local(col, mailQuotesKey{}, func() map[string]bool { return map[string]bool{} }), m.Body) + } + if len(m.Attachments) > 0 { + ui.Text(c, msg(c, "mail_reader.attachments")).FontSize(small).FontWeight(600).TextColor(k.TextMuted) + ui.Row(c).Gap(u * 2).Wrap().Children(func() { + for i, a := range m.Attachments { + f := FileMessage(c, FileMessageOptions(a)) + f.Element.Key(i) + if f.Opened() { + r.Opened = i + } + if f.Downloaded() { + r.Downloaded = i + } + } + }) + } + }) + if r.Link != "" || r.Opened >= 0 || r.Downloaded >= 0 { + slog.Debug("mujica: mail_reader action", "opened", r.Opened, "downloaded", r.Downloaded) + } + return r +} + +// mailPlainBody shows plain text, folding each run of quoted lines. +func mailPlainBody(c *ui.Context, open *map[string]bool, body string) { + lines := strings.Split(body, "\n") + ui.Column(c).Gap(Density(c).Unit() * 2).MinWidth(0).Children(func() { + for i := 0; i < len(lines); { + j := i + quoted := strings.HasPrefix(lines[i], ">") + for j < len(lines) && strings.HasPrefix(lines[j], ">") == quoted { + j++ + } + chunk := strings.Join(lines[i:j], "\n") + ui.Box(c).Key(i).Children(func() { + if quoted { + // Fold state is kept per quote text. + o := (*open)[chunk] + QuotedText(c, chunk, &o) + (*open)[chunk] = o + } else if strings.TrimSpace(chunk) != "" { + ui.Text(c, strings.Trim(chunk, "\n")).Selectable().FocusRing(false).LineHeight(theme.LineHeight) + } + }) + i = j + } + }) +} diff --git a/mail_reader_test.go b/mail_reader_test.go new file mode 100644 index 0000000..03ff774 --- /dev/null +++ b/mail_reader_test.go @@ -0,0 +1,69 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func TestMailReaderPlainQuotesAndAttachments(t *testing.T) { + m := Mail{From: "Sakiko Togawa", To: []string{"Uika"}, Subject: "Second act", Body: "See the score.\n> Can you send the score?\n> Thanks", + Attachments: []MailAttachment{{Name: "score.pdf", Size: 2048}}} + opened := -1 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Width(500).Children(func() { + if r := MailReader(c, m); r.Opened >= 0 { + opened = r.Opened + } + }) + }, 600, 600) + if !tt.HasText("See the score.") || tt.HasText("Can you send the score?") || !tt.HasText("Show quoted text (2 lines)") { + t.Fatalf("texts %v", tt.Texts()) + } + if err := tt.Click("Show quoted text (2 lines)"); err != nil { + t.Fatal(err) + } + if !tt.HasText("Can you send the score?\nThanks") { + t.Fatalf("quote not unfolded: %v", tt.Texts()) + } + if err := tt.Click("score.pdf"); err != nil { + t.Fatal(err) + } + if opened != 0 { + t.Fatalf("opened %d", opened) + } +} + +func TestMailReaderMarkdownIsSafe(t *testing.T) { + m := Mail{From: "A", Subject: "B", Format: MailMarkdown, Body: "**Bold** and [the hall](https://example.com)\n\n"} + link := "" + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Width(500).Children(func() { + if r := MailReader(c, m); r.Link != "" { + link = r.Link + } + }) + }, 600, 400) + if err := tt.Click("the hall"); err != nil { + t.Fatal(err) + } + if link != "https://example.com" || len(tt.OpenedURLs()) != 0 { + t.Fatalf("link %q opened %v", link, tt.OpenedURLs()) + } + if !tt.HasText("") { + t.Fatal("HTML was not shown as text") + } + mediaPanics(t, "no subject", func(c *ui.Context) { MailReader(c, Mail{From: "A"}) }) +} + +func TestMailReaderSnapshot(t *testing.T) { + m := Mail{From: "Sakiko Togawa", To: []string{"Uika Misumi", "Mutsumi Wakaba"}, Cc: []string{"Umiri Yahata"}, Subject: "The second act", + Date: time.Date(2026, 10, 5, 21, 7, 0, 0, time.UTC), Body: "The score is attached.\nRehearsal is at nine.\n> Can you send it tonight?", + Attachments: []MailAttachment{{Name: "score.pdf", Size: 2 << 20}}} + snapshot(t, "mail_reader", 560, 420, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(520).Children(func() { MailReader(c, m) }) + }) +} diff --git a/member_list.go b/member_list.go new file mode 100644 index 0000000..259b02f --- /dev/null +++ b/member_list.go @@ -0,0 +1,192 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/icons" + "mujicaui/theme" +) + +// Member supplies a unique ID, name, presence and role. +type Member struct { + ID, Name string + Image *ui.Bitmap + Presence Presence + // Role, as "Owner"; empty shows none. + Role string +} + +// MemberListOptions configure a MemberList. +type MemberListOptions struct { + // Height is the list's height; zero means 360. + Height float32 + Disabled bool +} + +// MemberListState keeps a MemberList's place and choice. +type MemberListState struct { + rows ui.ListState + cursor int + // Selected is the chosen member's ID; empty is none. + Selected string + cache memberRows + looked string + lookedGen int +} + +type memberRows struct { + first *Member + n int + rows []int + online int + offline int + gen int +} + +// MemberListResult is a MemberList's element and this frame's events. +type MemberListResult struct { + Element *ui.Element + changed bool + // Opened contains the ID activated by Enter or double-click. + Opened string +} + +// Changed reports a new selection. +func (r MemberListResult) Changed() bool { return r.changed } + +// MemberList virtualizes online and offline groups. +func MemberList(c *ui.Context, s *MemberListState, members []Member, opts MemberListOptions) MemberListResult { + if opts.Height < 0 { + panic("mujica: MemberList Height must not be negative") + } + h := opts.Height + if h == 0 { + h = 360 + } + memberGroup(s, members) + k := Tokens(c) + d := Density(c) + rows := s.cache.rows + if s.looked != s.Selected || s.lookedGen != s.cache.gen { + s.looked, s.lookedGen, s.cursor = s.Selected, s.cache.gen, -1 + for i, r := range rows { + if s.Selected != "" && r >= 0 && members[r].ID == s.Selected { + s.cursor = i + break + } + } + } + s.rows.Selected = &s.cursor + s.rows.Header = func(i int) bool { return rows[i] < 0 } + s.rows.Key = func(i int) any { + if rows[i] < 0 { + return rows[i] + } + return members[rows[i]].ID + } + s.rows.Label = func(i int) string { + if rows[i] < 0 { + return memberHeader(c, s, rows[i]) + } + return members[rows[i]].Name + } + var r MemberListResult + box := ui.Column(c).Height(h).Disabled(opts.Disabled) + r.Element = box + box.Children(func() { + if len(rows) == 0 { + ui.Text(c, msg(c, "member_list.empty")).TextColor(k.TextMuted) + return + } + restore := dataSelectTheme(c, 0) + l := ui.List(c, &s.rows, len(rows), func(i int) { + if rows[i] < 0 { + ui.Row(c).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*3).AlignItems(ui.Center).Background(k.Surface).Children(func() { + ui.Text(c, memberHeader(c, s, rows[i])).FontSize(FontSize(c, theme.CaptionSize)).FontWeight(600).TextColor(k.TextMuted) + }) + return + } + m := members[rows[i]] + ui.Row(c).MinHeight(d.ControlHeight()).Padding(0, d.Unit()*3).Gap(d.Unit() * 2).AlignItems(ui.Center).Children(func() { + ui.Box(c).Shrink(0).Children(func() { + Avatar(c, m.Name, AvatarOptions{Image: m.Image, Size: 28}) + ui.Box(c).Absolute().Right(-2).Bottom(-2).Padding(1.5).Radius(6).Background(k.Surface).Children(func() { + OnlineStatus(c, m.Presence, OnlineStatusOptions{HideText: true, Size: 9}) + }) + }) + t := ui.Text(c, m.Name).SingleLine().Grow(1).MinWidth(0) + if m.Presence == PresenceOffline { + t.TextColor(k.TextMuted) + } + if m.Role != "" { + Badge(c, BadgeOptions{Text: m.Role, Tone: BadgeNeutral}, nil) + } + if i == s.cursor { + ui.Icon(c, icons.Must("check")).Size(14, 14).TextColor(k.AccentText) + } + }) + }) + restore() + l.Grow(1).Background(k.Surface).Border(theme.BorderWidth, k.Border).Radius(theme.ControlRadius).Padding(d.Unit()) + if l.IsDisabled() { + return + } + if l.Changed() && s.cursor >= 0 && rows[s.cursor] >= 0 { + s.Selected, r.changed = members[rows[s.cursor]].ID, true + s.looked = s.Selected + } + if l.Submitted() && s.cursor >= 0 && rows[s.cursor] >= 0 { + r.Opened = members[rows[s.cursor]].ID + } + }) + if r.changed || r.Opened != "" { + slog.Debug("mujica: member_list choose", "id", s.Selected, "opened", r.Opened) + } + return r +} + +func memberHeader(c *ui.Context, s *MemberListState, row int) string { + if row == -1 { + return fmt.Sprintf(msg(c, "member_list.online"), s.cache.online) + } + return fmt.Sprintf(msg(c, "member_list.offline"), s.cache.offline) +} + +// memberGroup rebuilds the sections only when members changed. +func memberGroup(s *MemberListState, members []Member) { + var first *Member + if len(members) > 0 { + first = &members[0] + } + if s.cache.rows != nil && s.cache.first == first && s.cache.n == len(members) { + return + } + seen := make(map[string]bool, len(members)) + on, off := []int{-1}, []int{-2} + for i, m := range members { + if m.ID == "" || m.Name == "" || seen[m.ID] { + panic("mujica: MemberList members need unique IDs and names: " + m.ID) + } + seen[m.ID] = true + m.Presence.key() + if m.Presence == PresenceOffline { + off = append(off, i) + } else { + on = append(on, i) + } + } + s.cache = memberRows{first: first, n: len(members), online: len(on) - 1, offline: len(off) - 1, gen: s.cache.gen + 1} + if len(on) > 1 { + s.cache.rows = append(s.cache.rows, on...) + } + if len(off) > 1 { + s.cache.rows = append(s.cache.rows, off...) + } + if s.cache.rows == nil { + s.cache.rows = []int{} + } + slog.Debug("mujica: member_list grouped", "online", s.cache.online, "offline", s.cache.offline) +} diff --git a/member_list_test.go b/member_list_test.go new file mode 100644 index 0000000..f8810cd --- /dev/null +++ b/member_list_test.go @@ -0,0 +1,99 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestMemberListGroupsAndChoose(t *testing.T) { + var s MemberListState + members := memberTestList(8) + opened := "" + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if r := MemberList(c, &s, members, MemberListOptions{}); r.Opened != "" { + opened = r.Opened + } + }, 400, 500) + if !tt.HasText("Online — 6") || !tt.HasText("Offline — 2") || !tt.HasText("Owner") { + t.Fatalf("texts %v", tt.Texts()) + } + on, _ := tt.Find("Member 1") + off, _ := tt.Find("Member 0") + if off.Y <= on.Y { + t.Fatal("offline member above the online section") + } + if err := tt.Click("Member 1"); err != nil { + t.Fatal(err) + } + if s.Selected != "m1" { + t.Fatalf("selected %q", s.Selected) + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if s.Selected != "m2" || opened != "m2" { + t.Fatalf("keyboard chose %q, opened %q", s.Selected, opened) + } +} + +func TestMemberListBuildsOnlyVisibleAndGroupsOnce(t *testing.T) { + var s MemberListState + members := memberTestList(100000) + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + MemberList(c, &s, members, MemberListOptions{}) + }, 400, 500) + gen := s.cache.gen + tt.Frame() + tt.Frame() + built := 0 + for _, x := range tt.Texts() { + if len(x) > 7 && x[:7] == "Member " { + built++ + } + } + if built == 0 || built > 60 || s.cache.gen != gen { + t.Fatalf("built %d rows, regrouped %d times", built, s.cache.gen-gen) + } +} + +func TestMemberListSnapshot(t *testing.T) { + members := []Member{{ID: "1", Name: "Sakiko Togawa", Presence: PresenceOnline, Role: "Leader"}, {ID: "2", Name: "Uika Misumi", Presence: PresenceBusy}, + {ID: "3", Name: "Mutsumi Wakaba", Presence: PresenceAway}, {ID: "4", Name: "Umiri Yahata", Presence: PresenceOffline}} + snapshot(t, "member_list", 340, 300, func(c *ui.Context) { + s := ui.Local(c.Root(), "members", func() *MemberListState { return &MemberListState{} }) + ui.Column(c).Padding(20).Width(300).Children(func() { MemberList(c, *s, members, MemberListOptions{Height: 260}) }) + }) +} + +func TestMemberListEmptyDisabledAndReplacement(t *testing.T) { + members := []Member{{ID: "1", Name: "One", Presence: PresenceOnline}} + var s MemberListState + disabled, events := true, 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Disabled(disabled).Children(func() { + r := MemberList(c, &s, members, MemberListOptions{}) + if r.Changed() || r.Opened != "" { + events++ + } + }) + }, 400, 400) + _ = tt.Click("One") + tt.Key(0, ui.KeyEnter) + if s.Selected != "" || events != 0 { + t.Fatal("disabled member changed") + } + disabled = false + members = []Member{{ID: "1", Name: "One", Presence: PresenceOffline}} + tt.Frame() + if !tt.HasText("Offline — 1") || tt.HasText("Online — 1") { + t.Fatal("replacement kept stale groups") + } + members = nil + tt.Frame() + if !tt.HasText("No members") { + t.Fatal("empty state missing") + } +} diff --git a/messages_messaging.go b/messages_messaging.go new file mode 100644 index 0000000..c479840 --- /dev/null +++ b/messages_messaging.go @@ -0,0 +1,255 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + "strconv" + "strings" + "time" +) + +func init() { + addMessages(map[string][2]string{ + "channel_list.label": {"Channels", "频道"}, + "channel_list.unread": {"%s, %d unread", "%s,%d 条未读"}, + "channel_list.pinned": {"Pinned", "已置顶"}, + "channel_list.muted": {"Muted", "已静音"}, + + "chat_message.time": {"15:04", "15:04"}, + "chat_message.edited": {"(edited)", "(已编辑)"}, + + "unread_divider.new": {"New", "新消息"}, + "unread_divider.count": {"%d new messages", "%d 条新消息"}, + + "read_receipt.sent": {"Sent", "已发送"}, + "read_receipt.delivered": {"Delivered", "已送达"}, + "read_receipt.read": {"Read", "已读"}, + "read_receipt.readBy": {"Read by %s", "%s 已读"}, + + "member_list.empty": {"No members", "没有成员"}, + "user_profile_card.label": {"User profile", "用户资料"}, + "recipient_input.label": {"Recipients", "收件人"}, + "member_list.online": {"Online — %d", "在线 — %d"}, + "member_list.offline": {"Offline — %d", "离线 — %d"}, + + "online_status.online": {"Online", "在线"}, + "online_status.away": {"Away", "离开"}, + "online_status.busy": {"Busy", "忙碌"}, + "online_status.offline": {"Offline", "离线"}, + + "status_setter.label": {"Status", "状态"}, + "status_setter.emoji": {"Choose an emoji", "选择表情"}, + "status_setter.text": {"Status text", "状态文字"}, + "status_setter.placeholder": {"What is your status?", "你现在的状态是?"}, + "status_setter.clearAfter": {"Clear after", "清除时间"}, + "status_setter.never": {"Don't clear", "不清除"}, + "status_setter.30m": {"30 minutes", "30 分钟"}, + "status_setter.1h": {"1 hour", "1 小时"}, + "status_setter.4h": {"4 hours", "4 小时"}, + "status_setter.today": {"Today", "今天"}, + "status_setter.week": {"This week", "本周"}, + "status_setter.clear": {"Clear status", "清除状态"}, + + "call_controls.label": {"Call controls", "通话控制"}, + "call_controls.mute": {"Mute", "静音"}, + "call_controls.unmute": {"Unmute", "取消静音"}, + "call_controls.cameraOff": {"Turn camera off", "关闭摄像头"}, + "call_controls.cameraOn": {"Turn camera on", "打开摄像头"}, + "call_controls.share": {"Share screen", "共享屏幕"}, + "call_controls.stopShare": {"Stop sharing", "停止共享"}, + "call_controls.hangUp": {"Leave", "挂断"}, + + "video_call_grid.label": {"Participants", "参与者"}, + "video_call_grid.speaking": {"speaking", "正在发言"}, + "video_call_grid.muted": {"muted", "已静音"}, + "video_call_grid.cameraOff": {"camera off", "摄像头已关闭"}, + + "incoming_call_dialog.title": {"%s is calling", "%s 来电"}, + "incoming_call_dialog.voice": {"Incoming voice call", "语音来电"}, + "incoming_call_dialog.video": {"Incoming video call", "视频来电"}, + "incoming_call_dialog.accept": {"Accept", "接听"}, + "incoming_call_dialog.acceptVideo": {"With video", "视频接听"}, + "incoming_call_dialog.decline": {"Decline", "拒绝"}, + + "emoji_picker.label": {"Emoji", "表情"}, + "emoji_picker.search": {"Search emoji", "搜索表情"}, + "emoji_picker.none": {"No emoji found", "没有找到表情"}, + "emoji_picker.tone": {"Skin tone", "肤色"}, + "emoji_picker.toneN": {"Skin tone %d", "肤色 %d"}, + "emoji_picker.recent": {"Recent", "最近使用"}, + "emoji_picker.smileys": {"Smileys", "表情"}, + "emoji_picker.people": {"People", "人物"}, + "emoji_picker.nature": {"Nature", "自然"}, + "emoji_picker.food": {"Food and drink", "食物"}, + "emoji_picker.activities": {"Activities", "活动"}, + "emoji_picker.travel": {"Places", "地点"}, + "emoji_picker.objects": {"Objects", "物品"}, + "emoji_picker.symbols": {"Symbols", "符号"}, + + "emoji_picker.name_grinning_face": {"grinning face", "笑脸"}, + "emoji_picker.name_smiling_face_with_open_mouth": {"smiling face with open mouth", "张嘴笑脸"}, + "emoji_picker.name_face_with_tears_of_joy": {"face with tears of joy", "笑哭"}, + "emoji_picker.name_slightly_smiling_face": {"slightly smiling face", "微笑"}, + "emoji_picker.name_winking_face": {"winking face", "眨眼"}, + "emoji_picker.name_smiling_face_with_smiling_eyes": {"smiling face with smiling eyes", "眉眼带笑"}, + "emoji_picker.name_smiling_face_with_heart_eyes": {"smiling face with heart eyes", "爱心眼睛"}, + "emoji_picker.name_face_blowing_a_kiss": {"face blowing a kiss", "飞吻"}, + "emoji_picker.name_thinking_face": {"thinking face", "思考"}, + "emoji_picker.name_neutral_face": {"neutral face", "面无表情"}, + "emoji_picker.name_face_with_rolling_eyes": {"face with rolling eyes", "翻白眼"}, + "emoji_picker.name_sleeping_face": {"sleeping face", "睡觉"}, + "emoji_picker.name_smiling_face_with_sunglasses": {"smiling face with sunglasses", "墨镜笑脸"}, + "emoji_picker.name_star_struck": {"star struck", "星星眼"}, + "emoji_picker.name_crying_face": {"crying face", "哭泣"}, + "emoji_picker.name_pouting_face": {"pouting face", "生气"}, + "emoji_picker.name_face_screaming_in_fear": {"face screaming in fear", "惊恐"}, + "emoji_picker.name_partying_face": {"partying face", "庆祝"}, + "emoji_picker.name_waving_hand": {"waving hand", "挥手"}, + "emoji_picker.name_thumbs_up": {"thumbs up", "赞"}, + "emoji_picker.name_thumbs_down": {"thumbs down", "踩"}, + "emoji_picker.name_clapping_hands": {"clapping hands", "鼓掌"}, + "emoji_picker.name_raising_hands": {"raising hands", "举双手"}, + "emoji_picker.name_folded_hands": {"folded hands", "合十"}, + "emoji_picker.name_ok_hand": {"ok hand", "好手势"}, + "emoji_picker.name_victory_hand": {"victory hand", "胜利手势"}, + "emoji_picker.name_handshake": {"handshake", "握手"}, + "emoji_picker.name_flexed_biceps": {"flexed biceps", "肌肉"}, + "emoji_picker.name_writing_hand": {"writing hand", "写字"}, + "emoji_picker.name_eyes": {"eyes", "眼睛"}, + "emoji_picker.name_person": {"person", "人物"}, + "emoji_picker.name_crown": {"crown", "王冠"}, + "emoji_picker.name_performing_arts_masks": {"performing arts masks", "戏剧面具"}, + "emoji_picker.name_woman_dancing": {"woman dancing", "跳舞"}, + "emoji_picker.name_rose": {"rose", "玫瑰"}, + "emoji_picker.name_wilted_flower": {"wilted flower", "枯萎的花"}, + "emoji_picker.name_cherry_blossom": {"cherry blossom", "樱花"}, + "emoji_picker.name_crescent_moon": {"crescent moon", "新月"}, + "emoji_picker.name_star": {"star", "星星"}, + "emoji_picker.name_fire": {"fire", "火"}, + "emoji_picker.name_cloud_with_rain": {"cloud with rain", "雨云"}, + "emoji_picker.name_snowflake": {"snowflake", "雪花"}, + "emoji_picker.name_black_cat": {"black cat", "黑猫"}, + "emoji_picker.name_bat": {"bat", "蝙蝠"}, + "emoji_picker.name_black_bird": {"black bird", "黑鸟"}, + "emoji_picker.name_dove": {"dove", "鸽子"}, + "emoji_picker.name_fallen_leaf": {"fallen leaf", "落叶"}, + "emoji_picker.name_evergreen_tree": {"evergreen tree", "常青树"}, + "emoji_picker.name_water_wave": {"water wave", "海浪"}, + "emoji_picker.name_rainbow": {"rainbow", "彩虹"}, + "emoji_picker.name_wine_glass": {"wine glass", "红酒杯"}, + "emoji_picker.name_clinking_glasses": {"clinking glasses", "碰杯"}, + "emoji_picker.name_hot_beverage": {"hot beverage", "热饮"}, + "emoji_picker.name_teacup": {"teacup", "茶杯"}, + "emoji_picker.name_shortcake": {"shortcake", "蛋糕"}, + "emoji_picker.name_chocolate_bar": {"chocolate bar", "巧克力"}, + "emoji_picker.name_strawberry": {"strawberry", "草莓"}, + "emoji_picker.name_grapes": {"grapes", "葡萄"}, + "emoji_picker.name_red_apple": {"red apple", "红苹果"}, + "emoji_picker.name_cheese_wedge": {"cheese wedge", "奶酪"}, + "emoji_picker.name_baguette": {"baguette", "法棍"}, + "emoji_picker.name_bread": {"bread", "面包"}, + "emoji_picker.name_violin": {"violin", "小提琴"}, + "emoji_picker.name_musical_keyboard": {"musical keyboard", "键盘"}, + "emoji_picker.name_guitar": {"guitar", "吉他"}, + "emoji_picker.name_drum": {"drum", "鼓"}, + "emoji_picker.name_microphone": {"microphone", "麦克风"}, + "emoji_picker.name_musical_note": {"musical note", "音符"}, + "emoji_picker.name_musical_notes": {"musical notes", "多个音符"}, + "emoji_picker.name_party_popper": {"party popper", "礼花"}, + "emoji_picker.name_trophy": {"trophy", "奖杯"}, + "emoji_picker.name_artist_palette": {"artist palette", "调色盘"}, + "emoji_picker.name_chess_pawn": {"chess pawn", "棋子"}, + "emoji_picker.name_clapper_board": {"clapper board", "场记板"}, + "emoji_picker.name_castle": {"castle", "城堡"}, + "emoji_picker.name_church": {"church", "教堂"}, + "emoji_picker.name_tower": {"tower", "塔"}, + "emoji_picker.name_night_with_stars": {"night with stars", "星夜"}, + "emoji_picker.name_locomotive": {"locomotive", "火车"}, + "emoji_picker.name_airplane": {"airplane", "飞机"}, + "emoji_picker.name_automobile": {"automobile", "汽车"}, + "emoji_picker.name_sailboat": {"sailboat", "帆船"}, + "emoji_picker.name_world_map": {"world map", "世界地图"}, + "emoji_picker.name_snow_capped_mountain": {"snow capped mountain", "雪山"}, + "emoji_picker.name_sunrise": {"sunrise", "日出"}, + "emoji_picker.name_ferris_wheel": {"ferris wheel", "摩天轮"}, + "emoji_picker.name_candle": {"candle", "蜡烛"}, + "emoji_picker.name_old_key": {"old key", "旧钥匙"}, + "emoji_picker.name_scroll": {"scroll", "卷轴"}, + "emoji_picker.name_envelope": {"envelope", "信封"}, + "emoji_picker.name_paperclip": {"paperclip", "回形针"}, + "emoji_picker.name_pushpin": {"pushpin", "图钉"}, + "emoji_picker.name_calendar": {"calendar", "日历"}, + "emoji_picker.name_light_bulb": {"light bulb", "灯泡"}, + "emoji_picker.name_bell": {"bell", "铃铛"}, + "emoji_picker.name_locked": {"locked", "锁"}, + "emoji_picker.name_gem_stone": {"gem stone", "宝石"}, + "emoji_picker.name_hourglass": {"hourglass", "沙漏"}, + "emoji_picker.name_red_heart": {"red heart", "红心"}, + "emoji_picker.name_black_heart": {"black heart", "黑心"}, + "emoji_picker.name_broken_heart": {"broken heart", "心碎"}, + "emoji_picker.name_sparkles": {"sparkles", "闪光"}, + "emoji_picker.name_check_mark_button": {"check mark button", "勾选"}, + "emoji_picker.name_cross_mark": {"cross mark", "叉号"}, + "emoji_picker.name_exclamation_mark": {"exclamation mark", "感叹号"}, + "emoji_picker.name_question_mark": {"question mark", "问号"}, + "emoji_picker.name_hundred_points": {"hundred points", "满分"}, + "emoji_picker.name_diamond_suit": {"diamond suit", "方块"}, + "emoji_picker.name_fleur_de_lis": {"fleur de lis", "鸢尾花纹"}, + "emoji_picker.name_red_triangle": {"red triangle", "红三角"}, + + "pinned_messages.title": {"Pinned messages (%d)", "置顶消息(%d)"}, + "pinned_messages.empty": {"No pinned messages", "没有置顶消息"}, + "pinned_messages.unpin": {"Unpin %s's message", "取消置顶 %s 的消息"}, + + "thread_panel.title": {"Thread", "话题"}, + "thread_panel.close": {"Close thread", "关闭话题"}, + "thread_panel.replies": {"%d replies", "%d 条回复"}, + "thread_panel.reply": {"Reply in thread", "在话题中回复"}, + "thread_panel.send": {"Send", "发送"}, + + "mail_list.empty": {"No mail", "没有邮件"}, + "mail_list.star": {"Star %s", "星标 %s"}, + "mail_list.starred": {"Starred", "已加星标"}, + "mail_list.unread": {"Unread", "未读"}, + "mail_list.attachments": {"%d attachments", "%d 个附件"}, + "mail_list.date": {"Jan 2", "1月2日"}, + + "mail_reader.to": {"To:", "收件人:"}, + "mail_reader.cc": {"Cc:", "抄送:"}, + "mail_reader.date": {"Mon, Jan 2 2006 15:04", "2006年1月2日 {weekday} 15:04"}, + "mail_reader.attachments": {"Attachments", "附件"}, + + "mail_composer.label": {"New message", "新邮件"}, + "mail_composer.to": {"To", "收件人"}, + "mail_composer.cc": {"Cc", "抄送"}, + "mail_composer.bcc": {"Bcc", "密送"}, + "mail_composer.subject": {"Subject", "主题"}, + "mail_composer.body": {"Message", "正文"}, + "mail_composer.send": {"Send", "发送"}, + "mail_composer.attach": {"Attach", "添加附件"}, + "mail_composer.discard": {"Discard", "舍弃"}, + "mail_composer.unsaved": {"Unsaved changes", "有未保存的更改"}, + "mail_composer.saved": {"Draft saved %s", "草稿已于 %s 保存"}, + + "recipient_input.invalid": {"%q is not an email address", "“%s”不是有效的邮箱地址"}, + "recipient_input.suggestions": {"Contacts", "联系人"}, + + "quoted_text.showOne": {"Show quoted text (1 line)", "显示引用内容(1 行)"}, + "quoted_text.show": {"Show quoted text (%d lines)", "显示引用内容(%d 行)"}, + "quoted_text.hide": {"Hide quoted text", "隐藏引用内容"}, + + "snooze_picker.label": {"Snooze until", "稍后提醒"}, + "snooze_picker.later": {"Later today", "今天稍晚"}, + "snooze_picker.tomorrow": {"Tomorrow", "明天"}, + "snooze_picker.weekend": {"This weekend", "本周末"}, + "snooze_picker.nextWeek": {"Next week", "下周"}, + "snooze_picker.custom": {"Pick date and time", "选择日期和时间"}, + "snooze_picker.set": {"Snooze", "设定提醒"}, + "snooze_picker.when": {"Mon 15:04", "{weekday} 15:04"}, + "status_setter.until": {"Mon 15:04", "{weekday} 15:04"}, + }) +} + +func messagingDate(c *ui.Context, date time.Time, key string) string { + weekday := msg(c, "calendar.weekday_long_"+strconv.Itoa(int(date.Weekday()))) + return strings.ReplaceAll(date.Format(msg(c, key)), "{weekday}", weekday) +} diff --git a/messaging_calls_test.go b/messaging_calls_test.go new file mode 100644 index 0000000..b2f205b --- /dev/null +++ b/messaging_calls_test.go @@ -0,0 +1,25 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" +) + +type callCalls struct { + mute, camera, share []bool + hang int +} + +func (k *callCalls) opts() CallControlsOptions { + return CallControlsOptions{OnMute: func(on bool) { k.mute = append(k.mute, on) }, OnCamera: func(on bool) { k.camera = append(k.camera, on) }, + OnShare: func(on bool) { k.share = append(k.share, on) }, OnHangUp: func() { k.hang++ }} +} + +func incomingTester(open *bool, opts IncomingCallOptions, call IncomingCall) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if Button(c, "Ring", ButtonOptions{}).Clicked() { + *open = true + } + IncomingCallDialog(c, open, call, opts) + }, 600, 500) +} diff --git a/messaging_icons.go b/messaging_icons.go new file mode 100644 index 0000000..e569df0 --- /dev/null +++ b/messaging_icons.go @@ -0,0 +1,15 @@ +package mujica + +var ( + msgBellOff = mediaSVG(``) + msgPin = mediaSVG(``) + msgPaperclip = mediaSVG(``) + msgMicOff = mediaSVG(``) + msgVideoOff = mediaSVG(``) + msgShare = mediaSVG(``) + msgPhone = mediaSVG(``) + msgHangUp = mediaSVG(``) + msgSpeaking = mediaSVG(``) + msgSend = mediaSVG(``) + msgClose = mediaSVG(``) +) diff --git a/messaging_mail_test.go b/messaging_mail_test.go new file mode 100644 index 0000000..a04aa60 --- /dev/null +++ b/messaging_mail_test.go @@ -0,0 +1,30 @@ +package mujica + +import ( + "fmt" + "time" + + "github.com/egoist/mygo/ui" +) + +func mailTestItems(n int) []MailItem { + at := time.Date(2026, 10, 1, 9, 0, 0, 0, time.UTC) + out := make([]MailItem, n) + for i := range out { + out[i] = MailItem{ID: fmt.Sprint("m", i), From: fmt.Sprint("Sender ", i), Subject: fmt.Sprint("Subject ", i), + Snippet: "A short preview", Time: at, Unread: i%2 == 0, Starred: i == 1, Attachments: i % 3} + } + return out +} + +var recipientContacts = []Contact{{Name: "Uika Misumi", Email: "uika@example.com"}, {Name: "Umiri Yahata", Email: "umiri@example.com"}, + {Name: "Sakiko Togawa", Email: "sakiko@example.com"}} + +func recipientTester(list *[]string) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).Width(400).Children(func() { + RecipientInput(c, list, RecipientInputOptions{Contacts: recipientContacts, Label: "To"}) + }) + }, 520, 400) +} diff --git a/messaging_people_test.go b/messaging_people_test.go new file mode 100644 index 0000000..a7d16b8 --- /dev/null +++ b/messaging_people_test.go @@ -0,0 +1,36 @@ +package mujica + +import ( + "fmt" + + "github.com/egoist/mygo/ui" +) + +var channelTestGroups = []ChannelGroup{ + {ID: "ch", Title: "Channels", Channels: []Channel{ + {ID: "general", Name: "general", Unread: 3}, + {ID: "rehearsal", Name: "rehearsal", Pinned: true}, + {ID: "random", Name: "random", Unread: 120, Muted: true}, + }}, + {ID: "dm", Title: "Direct messages", Channels: []Channel{{ID: "uika", Name: "Uika", Direct: true, Presence: PresenceOnline}}}, +} + +func channelTester(sel *string, disabled bool, n *int) *ui.Tester { + return ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Width(260).Children(func() { + if ChannelList(c, sel, channelTestGroups, ChannelListOptions{Disabled: disabled}).Changed() { + *n++ + } + }) + }, 320, 480) +} + +func memberTestList(n int) []Member { + out := make([]Member, n) + for i := range out { + out[i] = Member{ID: fmt.Sprint("m", i), Name: fmt.Sprint("Member ", i), Presence: Presence(i % 4)} + } + out[0].Role = "Owner" + return out +} diff --git a/messaging_regression_test.go b/messaging_regression_test.go new file mode 100644 index 0000000..ac25aa3 --- /dev/null +++ b/messaging_regression_test.go @@ -0,0 +1,47 @@ +package mujica + +import ( + "fmt" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestMessagingLargeListsBounded(t *testing.T) { + const count = 100000 + channels := make([]Channel, count) + pins := make([]ChatEntry, count) + for i := range count { + channels[i] = Channel{ID: fmt.Sprint(i), Name: fmt.Sprint("Channel ", i)} + pins[i] = ChatEntry{ID: fmt.Sprint(i), Author: "Author", Text: fmt.Sprint("Pinned ", i)} + } + for _, name := range []string{"channels", "pins"} { + t.Run(name, func(t *testing.T) { + selected := "" + groups := []ChannelGroup{{ID: "g", Title: "Group", Channels: channels}} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Height(280).Children(func() { + if name == "channels" { + ChannelList(c, &selected, groups, ChannelListOptions{Height: 240}) + } else { + PinnedMessages(c, pins, PinnedMessagesOptions{Height: 240}) + } + }) + }, 400, 300) + prefix := "Channel " + if name == "pins" { + prefix = "Pinned " + } + n := 0 + for _, text := range tt.Texts() { + if len(text) >= len(prefix) && text[:len(prefix)] == prefix { + n++ + } + } + if n == 0 || n > 60 { + t.Fatalf("built %d of %d", n, count) + } + }) + } +} diff --git a/messaging_small_test.go b/messaging_small_test.go new file mode 100644 index 0000000..384dae8 --- /dev/null +++ b/messaging_small_test.go @@ -0,0 +1,33 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + "testing" + "time" +) + +// mediaTextCount counts texts equal to s. +func mediaTextCount(tt *ui.Tester, s string) int { + n := 0 + for _, x := range tt.Texts() { + if x == s { + n++ + } + } + return n +} + +func TestMessagingChineseWeekdays(t *testing.T) { + date := time.Date(2026, 10, 6, 15, 4, 0, 0, time.UTC) + st := CustomStatus{Until: date} + var until time.Time + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{Locale: ZhCN}) + StatusSetter(c, &st, StatusSetterOptions{Location: time.UTC}) + SnoozePicker(c, &until, SnoozePickerOptions{Now: time.Date(2026, 10, 5, 10, 0, 0, 0, time.UTC), Location: time.UTC}) + MailReader(c, Mail{Subject: "Test", From: "a@example.com", Date: date}) + }, 900, 900) + if !tt.HasText("2026年10月6日 星期二 15:04") || !tt.HasText("星期二 15:04") || !tt.HasText("星期二 09:00") { + t.Fatalf("weekday texts=%v", tt.Texts()) + } +} diff --git a/online_status.go b/online_status.go new file mode 100644 index 0000000..f15f8a7 --- /dev/null +++ b/online_status.go @@ -0,0 +1,87 @@ +package mujica + +import ( + "fmt" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// Presence is a person's availability. The zero value is offline. +type Presence int + +const ( + PresenceOffline Presence = iota + PresenceOnline + PresenceAway + PresenceBusy +) + +func (p Presence) key() string { + switch p { + case PresenceOffline: + return "online_status.offline" + case PresenceOnline: + return "online_status.online" + case PresenceAway: + return "online_status.away" + case PresenceBusy: + return "online_status.busy" + } + panic(fmt.Sprintf("mujica: unknown Presence %d", int(p))) +} + +// OnlineStatusOptions configure an OnlineStatus. +type OnlineStatusOptions struct { + // HideText keeps the shape, accessible name and tooltip. + HideText bool + // Size is the shape's diameter; zero means 10. + Size float32 +} + +// OnlineStatus shows presence as a distinct shape plus its name. +func OnlineStatus(c *ui.Context, p Presence, opts OnlineStatusOptions) *ui.Element { + name := msg(c, p.key()) + if opts.Size < 0 { + panic("mujica: OnlineStatus Size must not be negative") + } + size := opts.Size + if size == 0 { + size = 10 + } + k := Tokens(c) + row := ui.Row(c).Gap(Density(c).Unit() * 1.5).AlignItems(ui.Center).Shrink(0).Role(ui.RoleStatus).Label(name) + if opts.HideText { + row.Tooltip(name) + } + row.Children(func() { + ui.Box(c).Size(size, size).Shrink(0).Draw(func(p2 *ui.Painter, r ui.Rect) { presencePaint(p2, k, p, r) }) + if !opts.HideText { + ui.Text(c, name).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine() + } + }) + return row +} + +func presencePaint(p *ui.Painter, k theme.Tokens, s Presence, r ui.Rect) { + cx, cy := internal.Snap(p, r.X+r.W/2), internal.Snap(p, r.Y+r.H/2) + rad := r.W / 2 + var disc ui.Path + disc.Circle(cx, cy, rad) + switch s { + case PresenceOnline: + p.FillPath(&disc, k.Success) + case PresenceAway: + p.FillPath(&disc, k.Warning) + var bite ui.Path + bite.Circle(cx-rad*0.45, cy-rad*0.45, rad*0.62) + p.FillPath(&bite, k.Surface) + case PresenceBusy: + p.FillPath(&disc, k.Danger) + p.Fill(ui.Rect{X: cx - rad*0.6, Y: cy - max(1, rad*0.18), W: rad * 1.2, H: max(2, rad*0.36)}, k.Surface, 0) + default: + p.StrokePath(&disc, max(1.5, rad*0.3), k.TextMuted) + } +} diff --git a/online_status_test.go b/online_status_test.go new file mode 100644 index 0000000..f77426d --- /dev/null +++ b/online_status_test.go @@ -0,0 +1,41 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestOnlineStatusTextAndShape(t *testing.T) { + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Row(c).Gap(12).Children(func() { + for _, p := range []Presence{PresenceOnline, PresenceAway, PresenceBusy, PresenceOffline} { + OnlineStatus(c, p, OnlineStatusOptions{}) + } + OnlineStatus(c, PresenceBusy, OnlineStatusOptions{HideText: true}).Key("hidden") + }) + }, 500, 80) + for _, s := range []string{"Online", "Away", "Offline"} { + if mediaTextCount(tt, s) != 2 { + t.Fatalf("%s seen %d times: %v", s, mediaTextCount(tt, s), tt.Texts()) + } + } + if mediaTextCount(tt, "Busy") != 3 { + t.Fatalf("Busy seen %d times", mediaTextCount(tt, "Busy")) + } + if _, ok := tt.Find("Busy"); !ok { + t.Fatal("hidden text not kept as the name") + } + mediaPanics(t, "bad presence", func(c *ui.Context) { OnlineStatus(c, Presence(9), OnlineStatusOptions{}) }) +} + +func TestOnlineStatusSnapshot(t *testing.T) { + snapshot(t, "online_status", 420, 60, func(c *ui.Context) { + ui.Row(c).Padding(20).Gap(16).Children(func() { + for _, p := range []Presence{PresenceOnline, PresenceAway, PresenceBusy, PresenceOffline} { + OnlineStatus(c, p, OnlineStatusOptions{}) + } + }) + }) +} diff --git a/pinned_messages.go b/pinned_messages.go new file mode 100644 index 0000000..3b167d4 --- /dev/null +++ b/pinned_messages.go @@ -0,0 +1,73 @@ +package mujica + +import ( + "fmt" + "log/slog" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// PinnedMessagesResult is the list's element and this frame's events. +type PinnedMessagesResult struct { + Element *ui.Element + // Jump requests navigation; Unpinned requests removing a pin. + Jump, Unpinned string +} + +// PinnedMessagesOptions configure a PinnedMessages. +type PinnedMessagesOptions struct { + // Height caps the list; zero means 320. + Height float32 + Disabled bool +} + +// PinnedMessages virtualizes pins and emits navigation or removal requests. +func PinnedMessages(c *ui.Context, pins []ChatEntry, opts PinnedMessagesOptions) PinnedMessagesResult { + if opts.Height < 0 { + panic("mujica: PinnedMessages Height must not be negative") + } + h := opts.Height + if h == 0 { + h = 320 + } + k := Tokens(c) + u := Density(c).Unit() + var r PinnedMessagesResult + col := ui.Column(c).Gap(u * 2).Role(ui.RoleGroup).Label(fmt.Sprintf(msg(c, "pinned_messages.title"), len(pins))). + Disabled(opts.Disabled) + r.Element = col + col.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ui.Icon(c, msgPin).Size(16, 16).TextColor(k.Ornament) + ui.Text(c, fmt.Sprintf(msg(c, "pinned_messages.title"), len(pins))).Font(theme.SerifFont).FontWeight(600) + }) + if len(pins) == 0 { + ui.Text(c, msg(c, "pinned_messages.empty")).TextColor(k.TextMuted) + return + } + state := ui.Local(col, "pinned.rows", func() ui.ListState { return ui.ListState{} }) + state.Key = func(i int) any { return pins[i].ID } + ui.List(c, state, len(pins), func(i int) { + m := pins[i] + if m.ID == "" || m.Author == "" { + panic("mujica: PinnedMessages entries need ID and Author") + } + ui.Row(c).MinHeight(Density(c).ControlHeight()).Gap(u).AlignItems(ui.Center).Children(func() { + if QuoteReply(c, m.Author, m.Text).Grow(1).MaxWidth(10000).Clicked() && !col.IsDisabled() { + r.Jump = m.ID + } + b := iconAction(c, msgPin, fmt.Sprintf(msg(c, "pinned_messages.unpin"), m.Author)) + if b.Clicked() && !b.IsDisabled() { + r.Unpinned = m.ID + } + }) + }).Height(min(h, float32(len(pins))*Density(c).ControlHeight())).Gap(u * 2).FocusGroup(ui.Vertical) + + }) + if r.Jump != "" || r.Unpinned != "" { + slog.Debug("mujica: pinned_messages", "jump", r.Jump, "unpin", r.Unpinned) + } + return r +} diff --git a/pinned_messages_test.go b/pinned_messages_test.go new file mode 100644 index 0000000..c35be4d --- /dev/null +++ b/pinned_messages_test.go @@ -0,0 +1,47 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestPinnedMessages(t *testing.T) { + pins := []ChatEntry{{ID: "a", Author: "Sakiko", Text: "Rehearsal moves to nine."}, {ID: "b", Author: "Uika", Text: "Masks are in the hall."}} + var jumps, unpins []string + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Width(420).Children(func() { + r := PinnedMessages(c, pins, PinnedMessagesOptions{}) + if r.Jump != "" { + jumps = append(jumps, r.Jump) + } + if r.Unpinned != "" { + unpins = append(unpins, r.Unpinned) + } + }) + }, 500, 400) + if !tt.HasText("Pinned messages (2)") { + t.Fatalf("texts %v", tt.Texts()) + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if err := tt.Click("Unpin Uika's message"); err != nil { + t.Fatal(err) + } + if len(jumps) != 1 || jumps[0] != "a" || len(unpins) != 1 || unpins[0] != "b" { + t.Fatalf("jumps %v unpins %v", jumps, unpins) + } + pins = nil + tt.Frame() + if !tt.HasText("No pinned messages") { + t.Fatal("no empty state") + } +} + +func TestPinnedMessagesSnapshot(t *testing.T) { + pins := []ChatEntry{{ID: "a", Author: "Sakiko", Text: "Rehearsal moves to nine."}, {ID: "b", Author: "Uika", Text: "Masks are in the hall."}} + snapshot(t, "pinned_messages", 440, 200, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(400).Children(func() { PinnedMessages(c, pins, PinnedMessagesOptions{}) }) + }) +} diff --git a/quoted_text.go b/quoted_text.go new file mode 100644 index 0000000..0d94fb2 --- /dev/null +++ b/quoted_text.go @@ -0,0 +1,39 @@ +package mujica + +import ( + "fmt" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// QuotedText folds or expands one level of quoted text. +func QuotedText(c *ui.Context, text string, open *bool) ChoiceResult { + body := QuoteStrip(text) + n := strings.Count(body, "\n") + 1 + k := Tokens(c) + u := Density(c).Unit() + title := fmt.Sprintf(msg(c, "quoted_text.show"), n) + if n == 1 { + title = msg(c, "quoted_text.showOne") + } + if *open { + title = msg(c, "quoted_text.hide") + } + return Collapsible(c, open, CollapsibleOptions{Title: title}, func() { + ui.Text(c, body).Selectable().FocusRing(false).TextColor(k.TextMuted).LineHeight(theme.LineHeight). + Padding(0, 0, 0, u*3).BorderWidth(0, 0, 0, 2).BorderColor(k.Border) + }) +} + +// QuoteStrip removes one quote prefix from each line. +func QuoteStrip(text string) string { + lines := strings.Split(strings.TrimRight(text, "\n"), "\n") + for i, l := range lines { + l = strings.TrimPrefix(l, ">") + lines[i] = strings.TrimPrefix(l, " ") + } + return strings.Join(lines, "\n") +} diff --git a/quoted_text_test.go b/quoted_text_test.go new file mode 100644 index 0000000..5aebed1 --- /dev/null +++ b/quoted_text_test.go @@ -0,0 +1,48 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestQuotedTextAndStrip(t *testing.T) { + if got := QuoteStrip("> a\n>b\n> > c"); got != "a\nb\n> c" { + t.Fatalf("strip %q", got) + } + open := false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + QuotedText(c, "> first\n> second", &open) + }, 400, 200) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if !open || !tt.HasText("first\nsecond") || !tt.HasText("Hide quoted text") { + t.Fatalf("not expanded: %v", tt.Texts()) + } + tt.Key(0, ui.KeySpace) + if open { + t.Fatal("Space did not fold") + } +} + +func TestQuotedTextSnapshot(t *testing.T) { + a, b := false, true + snapshot(t, "quoted_text", 420, 180, func(c *ui.Context) { + ui.Column(c).Padding(20).Gap(8).Children(func() { + QuotedText(c, "> Can you send the score?\n> Thanks", &a) + QuotedText(c, "> Rehearsal moves to nine.\n> Bring the masks.", &b) + }) + }) +} + +func TestQuotedTextSingleLineCopy(t *testing.T) { + open := false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + QuotedText(c, "> One line", &open) + }, 400, 200) + if !tt.HasText("Show quoted text (1 line)") { + t.Fatal("singular quote label missing") + } +} diff --git a/read_receipt.go b/read_receipt.go new file mode 100644 index 0000000..97885af --- /dev/null +++ b/read_receipt.go @@ -0,0 +1,90 @@ +package mujica + +import ( + "fmt" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// ReceiptState tracks delivery; its zero value means sent. +type ReceiptState int + +const ( + ReceiptSent ReceiptState = iota + ReceiptDelivered + ReceiptRead +) + +// ReadReceiptOptions configure a ReadReceipt. +type ReadReceiptOptions struct { + // Readers supplies avatars for the read state. + Readers []AvatarItem + // Max avatars show before "+N"; zero means 3. + Max int +} + +// ReadReceipt displays delivery marks, text and reader avatars. +func ReadReceipt(c *ui.Context, state ReceiptState, opts ReadReceiptOptions) *ui.Element { + if state < ReceiptSent || state > ReceiptRead || opts.Max < 0 { + panic(fmt.Sprintf("mujica: bad ReadReceipt state %d or Max %d", state, opts.Max)) + } + limit := opts.Max + if limit == 0 { + limit = 3 + } + k := Tokens(c) + u := Density(c).Unit() + word := msg(c, []string{"read_receipt.sent", "read_receipt.delivered", "read_receipt.read"}[state]) + label := word + if state == ReceiptRead && len(opts.Readers) > 0 { + names := make([]string, len(opts.Readers)) + for i, r := range opts.Readers { + names[i] = r.Name + } + label = fmt.Sprintf(msg(c, "read_receipt.readBy"), strings.Join(names, ", ")) + } + ink := k.TextMuted + if state == ReceiptRead { + ink = k.AccentText + } + row := ui.Row(c).Gap(u * 1.5).AlignItems(ui.Center).Shrink(0).Role(ui.RoleStatus).Label(label).Tooltip(label) + row.Children(func() { + ui.Box(c).Size(18, 12).Shrink(0).Draw(func(p *ui.Painter, r ui.Rect) { receiptChecks(p, r, state != ReceiptSent, ink) }) + ui.Text(c, word).FontSize(FontSize(c, theme.CaptionSize)).TextColor(ink).SingleLine() + if state != ReceiptRead || len(opts.Readers) == 0 { + return + } + ui.Row(c).Children(func() { + for i, r := range opts.Readers[:min(limit, len(opts.Readers))] { + cell := ui.Box(c).Key(i).Padding(1).Radius(9).Background(k.Background) + if i > 0 { + cell.Margin(0, 0, 0, -5) + } + cell.Children(func() { Avatar(c, r.Name, AvatarOptions{Image: r.Image, Size: 16}) }) + } + }) + if rest := len(opts.Readers) - limit; rest > 0 { + ui.Textf(c, "+%d", rest).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + } + }) + return row +} + +// receiptChecks draws one check, or two overlapping checks. +func receiptChecks(p *ui.Painter, r ui.Rect, double bool, col ui.Color) { + check := func(x float32) { + var path ui.Path + path.MoveTo(internal.Snap(p, x), internal.Snap(p, r.Y+r.H*0.55)) + path.LineTo(internal.Snap(p, x+r.H*0.35), internal.Snap(p, r.Y+r.H*0.9)) + path.LineTo(internal.Snap(p, x+r.H*0.95), internal.Snap(p, r.Y+r.H*0.15)) + p.StrokePath(&path, 1.6, col) + } + check(r.X) + if double { + check(r.X + r.H*0.5) + } +} diff --git a/read_receipt_test.go b/read_receipt_test.go new file mode 100644 index 0000000..1039dc8 --- /dev/null +++ b/read_receipt_test.go @@ -0,0 +1,38 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestReadReceiptStates(t *testing.T) { + readers := []AvatarItem{{Name: "Uika"}, {Name: "Mutsumi"}, {Name: "Umiri"}, {Name: "Nyamu"}} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Gap(8).AlignItems(ui.Start).Children(func() { + ReadReceipt(c, ReceiptSent, ReadReceiptOptions{}) + ReadReceipt(c, ReceiptDelivered, ReadReceiptOptions{}) + ReadReceipt(c, ReceiptRead, ReadReceiptOptions{Readers: readers, Max: 2}) + }) + }, 400, 160) + for _, s := range []string{"Sent", "Delivered", "+2"} { + if !tt.HasText(s) { + t.Fatalf("no %q in %v", s, tt.Texts()) + } + } + if _, ok := tt.Find("Read by Uika, Mutsumi, Umiri, Nyamu"); !ok { + t.Fatal("readers not named in full") + } + mediaPanics(t, "bad state", func(c *ui.Context) { ReadReceipt(c, ReceiptState(5), ReadReceiptOptions{}) }) +} + +func TestReadReceiptSnapshot(t *testing.T) { + snapshot(t, "read_receipt", 360, 130, func(c *ui.Context) { + ui.Column(c).Padding(20).Gap(10).AlignItems(ui.Start).Children(func() { + ReadReceipt(c, ReceiptSent, ReadReceiptOptions{}) + ReadReceipt(c, ReceiptDelivered, ReadReceiptOptions{}) + ReadReceipt(c, ReceiptRead, ReadReceiptOptions{Readers: []AvatarItem{{Name: "Uika Misumi"}, {Name: "Mutsumi Wakaba"}, {Name: "Umiri Yahata"}, {Name: "Nyamu"}}}) + }) + }) +} diff --git a/recipient_input.go b/recipient_input.go new file mode 100644 index 0000000..07dc88e --- /dev/null +++ b/recipient_input.go @@ -0,0 +1,179 @@ +package mujica + +import ( + "fmt" + "log/slog" + "net/mail" + "slices" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// Contact is a person RecipientInput can suggest. +type Contact struct { + Name, Email string +} + +// RecipientInputOptions configure a RecipientInput. +type RecipientInputOptions struct { + // Contacts supplies suggestions matched by name or address. + Contacts []Contact + Placeholder string + // Label names the field, as "To". + Label string + Disabled bool +} + +// recipientMax is how many suggestions show. +const recipientMax = 6 + +type recipientState struct { + query string + matchedOn string + matches []Contact + contacts *Contact + count int + added []string + hi int + dismissed string +} + +type recipientKey struct{} + +// RecipientInput validates addresses and offers contact suggestions. +func RecipientInput(c *ui.Context, recipients *[]string, opts RecipientInputOptions) TagsInputParts { + k := Tokens(c) + if opts.Label == "" { + opts.Label = msg(c, "recipient_input.label") + } + wrap := ui.Column(c).Disabled(opts.Disabled) + st := ui.Local(wrap, recipientKey{}, func() *recipientState { return &recipientState{hi: -1} }) + s := *st + // Suggestions are found again only when the typed text changes. + var first *Contact + if len(opts.Contacts) > 0 { + first = &opts.Contacts[0] + } + if q := strings.ToLower(strings.TrimSpace(s.query)); q != s.matchedOn || first != s.contacts || len(opts.Contacts) != s.count || !slices.Equal(s.added, *recipients) { + s.matchedOn, s.matches, s.hi = q, recipientFind(opts.Contacts, *recipients, q), -1 + s.contacts, s.count, s.added = first, len(opts.Contacts), slices.Clone(*recipients) + } + typed := s.query + var parts TagsInputParts + wrap.Children(func() { + parts = TagsInput(c, recipients, TagsInputOptions{ + Placeholder: opts.Placeholder, Label: opts.Label, Disabled: opts.Disabled, Query: &s.query, + Validate: func(tag string) string { + if s.hi >= 0 && tag == strings.TrimSpace(typed) { + return "" // replaced by the highlighted contact below + } + if _, err := mail.ParseAddress(tag); err != nil { + return fmt.Sprintf(msg(c, "recipient_input.invalid"), tag) + } + return "" + }, + }) + }) + parts.Element = wrap + in := parts.Input + live := !wrap.IsDisabled() + showing := live && len(s.matches) > 0 && s.dismissed != s.query && s.query != "" + if showing && in.Focused() { + switch { + case in.Shortcut(0, ui.KeyDown): + s.hi = min(len(s.matches)-1, s.hi+1) + case in.Shortcut(0, ui.KeyUp): + s.hi = max(-1, s.hi-1) + case in.Shortcut(0, ui.KeyEscape): + s.dismissed, s.hi = s.query, -1 + } + } + pick := func(ct Contact) { + addr := recipientFormat(ct) + if n := len(*recipients); n > 0 && (*recipients)[n-1] == strings.TrimSpace(typed) { + *recipients = (*recipients)[:n-1] // the raw text Enter added + } + if !slices.Contains(*recipients, addr) { + *recipients = append(slices.Clone(*recipients), addr) + } + s.query, s.hi = "", -1 + in.Focus() + slog.Debug("mujica: recipient_input pick", "count", len(*recipients)) + } + if live && in.Submitted() && s.hi >= 0 && s.hi < len(s.matches) { + pick(s.matches[s.hi]) + parts = TagsInputParts{Element: wrap, Input: in, changed: true} + } + if showing { + b := wrap.Bounds() + ui.Overlay(c, func() { + ww, wh := c.Size() + w := min(max(240, b.W), max(0, ww-8)) + h := min(float32(len(s.matches))*Density(c).ControlHeight()+16, max(0, wh-8)) + x, y := overlayPlace(c, b, w, h, 4) + panel := ui.Column(c).Absolute().Left(x).Top(y).Width(w).MaxHeight(h).Padding(4).Role(ui.RoleList). + Label(msg(c, "recipient_input.suggestions")) + overlayStyle(c, panel, overlayEnter(c, panel)) + panel.Children(func() { + ui.Scroll(c).Shrink(1).Padding(4).Children(func() { + for i, ct := range s.matches { + row := ui.ButtonBase(c).Key(ct.Email).MinHeight(Density(c).ControlHeight()).Justify(ui.Start).Gap(8).Padding(0, 8). + Radius(theme.ControlRadius).Role(ui.RoleListItem).Label(recipientFormat(ct)).FocusRing(false) + if i == s.hi || row.Hovered() { + row.Background(k.Selection) + } + if i == s.hi || row.FocusVisible() { + row.DrawOver(func(p *ui.Painter, r ui.Rect) { internal.FocusRing(p, r, theme.ControlRadius, k.Focus) }) + } + row.Children(func() { + Avatar(c, ct.Name, AvatarOptions{Size: 22}) + ui.Text(c, ct.Name).SingleLine() + ui.Text(c, ct.Email).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).SingleLine() + }) + if row.Clicked() && !row.IsDisabled() { + pick(ct) + parts.changed = true + } + } + }) + }) + if !in.Focused() && !panel.FocusWithin() { + panel.Invisible() + } + }) + } + return parts +} + +func recipientFind(contacts []Contact, added []string, q string) []Contact { + if q == "" { + return nil + } + var out []Contact + for _, ct := range contacts { + if len(out) == recipientMax { + break + } + if (strings.Contains(strings.ToLower(ct.Name), q) || strings.Contains(strings.ToLower(ct.Email), q)) && + !slices.Contains(added, recipientFormat(ct)) { + out = append(out, ct) + } + } + return out +} + +func recipientFormat(ct Contact) string { + if ct.Name == "" { + return ct.Email + } + plain := ct.Name + " <" + ct.Email + ">" + if _, err := mail.ParseAddress(plain); err == nil { + return plain + } + address := mail.Address{Name: ct.Name, Address: ct.Email} + return address.String() +} diff --git a/recipient_input_test.go b/recipient_input_test.go new file mode 100644 index 0000000..b86b04b --- /dev/null +++ b/recipient_input_test.go @@ -0,0 +1,188 @@ +package mujica + +import ( + "net/mail" + "slices" + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestRecipientInputRefreshesContacts(t *testing.T) { + var recipients []string + contacts := []Contact{{Name: "Alice", Email: "alice@example.com"}} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + RecipientInput(c, &recipients, RecipientInputOptions{Contacts: contacts, Label: "To"}) + }, 500, 300) + if err := tt.Click("To"); err != nil { + t.Fatal(err) + } + tt.Type("ali") + contacts = []Contact{{Name: "Alina", Email: "alina@example.com"}} + tt.Frame() + if !tt.HasText("Alina") || tt.HasText("Alice") { + t.Fatalf("stale contacts: %v", tt.Texts()) + } +} + +func TestRecipientInputPopupFitsWindow(t *testing.T) { + var recipients []string + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Absolute().Left(190).Top(220).Width(110).Children(func() { + RecipientInput(c, &recipients, RecipientInputOptions{Contacts: recipientContacts, Label: "To"}) + }) + }, 320, 280) + if err := tt.Click("To"); err != nil { + t.Fatal(err) + } + tt.Type("ui") + tt.SetPreferences(ui.Preferences{ReduceMotion: true, TextScale: 1}) + tt.Frame() + r, ok := tt.Find("Contacts") + if !ok || r.X < 0 || r.Y < 0 || r.X+r.W > 320 || r.Y+r.H > 280 { + t.Fatalf("popup bounds: %+v", r) + } +} + +func TestRecipientInputDisabledPreservesAddresses(t *testing.T) { + recipients := []string{"a@example.com"} + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Disabled(true).Children(func() { + RecipientInput(c, &recipients, RecipientInputOptions{Contacts: recipientContacts, Label: "To"}) + }) + }, 500, 300) + _ = tt.Click("To") + tt.Type("b@example.com,") + tt.Key(0, ui.KeyEnter) + _ = tt.Click("Remove a@example.com") + if !slices.Equal(recipients, []string{"a@example.com"}) { + t.Fatalf("disabled recipients: %v", recipients) + } +} + +func TestRecipientInputValidates(t *testing.T) { + var list []string + tt := recipientTester(&list) + if err := tt.Click("To"); err != nil { + t.Fatal(err) + } + tt.Type("nobody") + tt.Key(0, ui.KeyEnter) + if len(list) != 0 || !tt.HasText(`"nobody" is not an email address`) { + t.Fatalf("invalid address kept: %v %v", list, tt.Texts()) + } + tt.Command("selectAll") + tt.Type("guest@example.com,") + if !slices.Equal(list, []string{"guest@example.com"}) { + t.Fatalf("list %v", list) + } +} + +func TestRecipientInputSuggests(t *testing.T) { + var list []string + tt := recipientTester(&list) + if err := tt.Click("To"); err != nil { + t.Fatal(err) + } + tt.Type("yah") + if !tt.HasText("Umiri Yahata") || tt.HasText("Sakiko Togawa") { + t.Fatalf("suggestions %v", tt.Texts()) + } + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + if !slices.Equal(list, []string{"Umiri Yahata "}) { + t.Fatalf("list %v", list) + } + tt.Type("ui") + if err := tt.Click("Uika Misumi "); err != nil { + t.Fatal(err) + } + if len(list) != 2 || list[1] != "Uika Misumi " { + t.Fatalf("click pick %v", list) + } + tt.Type("sa") + tt.Key(0, ui.KeyEscape) + if tt.HasText("sakiko@example.com") { + t.Fatal("Escape did not hide suggestions") + } +} + +func TestRecipientInputSnapshot(t *testing.T) { + list := []string{"Uika Misumi ", "guest@example.com"} + snapshot(t, "recipient_input", 460, 120, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(420).Children(func() { + RecipientInput(c, &list, RecipientInputOptions{Contacts: recipientContacts, Label: "To"}) + }) + }) +} + +func TestRecipientInputQuotesDisplayNames(t *testing.T) { + var recipients []string + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + RecipientInput(c, &recipients, RecipientInputOptions{Label: "To", Contacts: []Contact{{Name: "Doe, Jane", Email: "jane@example.com"}}}) + }, 500, 300) + if err := tt.Click("To"); err != nil { + t.Fatal(err) + } + tt.Type("jane") + if err := tt.Click(`"Doe, Jane" `); err != nil { + t.Fatal(err) + } + if len(recipients) != 1 { + t.Fatalf("recipients=%v texts=%v", recipients, tt.Texts()) + } + addr, err := mail.ParseAddress(recipients[0]) + if err != nil || addr.Name != "Doe, Jane" || addr.Address != "jane@example.com" { + t.Fatalf("quoted address=%v error=%v", recipients, err) + } +} + +func TestRecipientInputTabShowsFocusRing(t *testing.T) { + var recipients []string + var focus ui.Color + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + focus = Tokens(c).Focus + ui.Column(c).Padding(20).Children(func() { + RecipientInput(c, &recipients, RecipientInputOptions{Contacts: recipientContacts, Label: "To"}) + }) + }, 500, 300) + tt.SetPreferences(ui.Preferences{ReduceMotion: true, TextScale: 1}) + if err := tt.Click("To"); err != nil { + t.Fatal(err) + } + tt.Type("ui") + tt.Key(0, ui.KeyTab) + label := "Uika Misumi " + if !tt.Focused(label) { + t.Fatal("Tab did not focus suggestion") + } + r, ok := tt.Find(label) + if !ok { + t.Fatal("suggestion missing") + } + pixels := 0 + img := tt.Image() + for y := int(r.Y) - 4; y < int(r.Y+r.H)+4; y++ { + for x := int(r.X) - 4; x < int(r.X+r.W)+4; x++ { + if x >= int(r.X) && x < int(r.X+r.W) && y >= int(r.Y) && y < int(r.Y+r.H) { + continue + } + pixel := img.RGBAAt(x, y) + if pixel.R == focus.R && pixel.G == focus.G && pixel.B == focus.B { + pixels++ + } + } + } + if pixels == 0 { + t.Fatal("keyboard suggestion has no focus ring") + } + tt.Key(0, ui.KeyEnter) + if len(recipients) != 1 { + t.Fatal("focused suggestion did not commit") + } +} diff --git a/snooze_picker.go b/snooze_picker.go new file mode 100644 index 0000000..49d933c --- /dev/null +++ b/snooze_picker.go @@ -0,0 +1,139 @@ +package mujica + +import ( + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// SnoozePickerOptions configure a SnoozePicker. +type SnoozePickerOptions struct { + // Location is the user's time zone; nil means local. + Location *time.Location + // MorningHour defaults to 9; valid values are 0–23. + MorningHour int + // Now defaults to the frame clock. + Now time.Time + Disabled bool +} + +// SnoozeChoice pairs a message key with a reminder time. +type SnoozeChoice struct { + Key string + At time.Time +} + +// SnoozeChoices returns localized-day shortcuts using morning hours. +func SnoozeChoices(now time.Time, morning int) []SnoozeChoice { + if morning < 0 || morning > 23 { + panic("mujica: SnoozeChoices morning outside 0..23") + } + day := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) + at := func(days int) time.Time { + return time.Date(day.Year(), day.Month(), day.Day()+days, morning, 0, 0, 0, now.Location()) + } + var out []SnoozeChoice + if later := now.Add(3 * time.Hour).Truncate(time.Hour); later.Day() == now.Day() { + out = append(out, SnoozeChoice{"snooze_picker.later", later}) + } + out = append(out, SnoozeChoice{"snooze_picker.tomorrow", at(1)}) + if wd := now.Weekday(); wd != time.Saturday && wd != time.Sunday { + out = append(out, SnoozeChoice{"snooze_picker.weekend", at(int(time.Saturday - wd))}) + } + monday := (8 - int(now.Weekday())) % 7 + if monday == 0 { + monday = 7 + } + return append(out, SnoozeChoice{"snooze_picker.nextWeek", at(monday)}) +} + +type snoozeState struct { + custom bool + pick time.Time +} + +type snoozeKey struct{} + +// SnoozePicker offers shortcuts and custom reminder times. +func SnoozePicker(c *ui.Context, until *time.Time, opts SnoozePickerOptions) ChoiceResult { + if opts.MorningHour < 0 || opts.MorningHour > 23 { + panic("mujica: SnoozePicker MorningHour outside 0..23") + } + loc := opts.Location + if loc == nil { + loc = time.Local + } + morning := opts.MorningHour + if morning == 0 { + morning = 9 + } + k := Tokens(c) + d := Density(c) + u := d.Unit() + now := opts.Now + if now.IsZero() { + now = c.Now() + } + now = now.In(loc) + old := *until + col := ui.Column(c).Width(300).Padding(u).FocusGroup(ui.Vertical).Role(ui.RoleList).Label(msg(c, "snooze_picker.label")). + Disabled(opts.Disabled) + st := ui.Local(col, snoozeKey{}, func() *snoozeState { return &snoozeState{} }) + s := *st + col.Children(func() { + row := func(name, when string, on bool) bool { + b := ui.ButtonBase(c).MinHeight(d.ControlHeight()).Justify(ui.Start).Gap(u*2).Padding(0, u*3).Radius(theme.ControlRadius). + Role(ui.RoleListItem).Label(name + ", " + when).Selected(on).Background(ui.Transparent).Transition(colorFade) + internal.Ring(b, k.Focus, theme.ControlRadius) + switch { + case on: + b.Background(k.Selection).BorderWidth(0, 0, 0, 3).BorderColor(k.AccentText) + case b.Hovered(): + b.Background(k.SurfaceHover) + } + b.Children(func() { + ui.Text(c, name).Grow(1).SingleLine() + ui.Text(c, when).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted).FontFeatures("tnum").SingleLine() + }) + return b.Clicked() && !b.IsDisabled() + } + for _, ch := range SnoozeChoices(now, morning) { + ui.Box(c).Key(ch.Key).Children(func() { + if row(msg(c, ch.Key), snoozeWhen(c, now, ch.At), until.Equal(ch.At)) { + *until, s.custom = ch.At, false + } + }) + } + ui.Box(c).Height(1).Margin(u, 0).Background(k.Border) + if row(msg(c, "snooze_picker.custom"), "", s.custom) { + s.custom = !s.custom + if s.pick.IsZero() { + s.pick = SnoozeChoices(now, morning)[0].At + } + } + if s.custom { + ui.Column(c).Gap(u * 2).Padding(u * 2).Children(func() { + DateTimePicker(c, &s.pick, DateTimePickerOptions{Location: loc, Min: now, Label: msg(c, "snooze_picker.custom"), Disabled: opts.Disabled}) + if Button(c, msg(c, "snooze_picker.set"), ButtonOptions{Disabled: !s.pick.After(now)}).Clicked() { + *until = s.pick + } + }) + } + }) + changed := !until.Equal(old) + if changed { + slog.Debug("mujica: snooze_picker set", "until", *until) + } + return ChoiceResult{Element: col, changed: changed} +} + +func snoozeWhen(c *ui.Context, now, t time.Time) string { + if t.Year() == now.Year() && t.YearDay() == now.YearDay() { + return t.Format("15:04") + } + return messagingDate(c, t, "snooze_picker.when") +} diff --git a/snooze_picker_test.go b/snooze_picker_test.go new file mode 100644 index 0000000..22a8d0e --- /dev/null +++ b/snooze_picker_test.go @@ -0,0 +1,121 @@ +package mujica + +import ( + "slices" + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func TestSnoozeChoicesPreserveWallHour(t *testing.T) { + loc, err := time.LoadLocation("America/New_York") + if err != nil { + t.Fatal(err) + } + for _, now := range []time.Time{ + time.Date(2026, 3, 7, 14, 0, 0, 0, loc), + time.Date(2026, 10, 31, 14, 0, 0, 0, loc), + } { + choices := SnoozeChoices(now, 9) + if at := choices[1].At; at.Hour() != 9 || at.Day() != now.AddDate(0, 0, 1).Day() { + t.Fatalf("tomorrow wall time: %v", at) + } + } +} + +func TestSnoozeChoices(t *testing.T) { + wed := time.Date(2026, 10, 7, 14, 20, 0, 0, time.UTC) + got := SnoozeChoices(wed, 9) + want := []SnoozeChoice{ + {"snooze_picker.later", time.Date(2026, 10, 7, 17, 0, 0, 0, time.UTC)}, + {"snooze_picker.tomorrow", time.Date(2026, 10, 8, 9, 0, 0, 0, time.UTC)}, + {"snooze_picker.weekend", time.Date(2026, 10, 10, 9, 0, 0, 0, time.UTC)}, + {"snooze_picker.nextWeek", time.Date(2026, 10, 12, 9, 0, 0, 0, time.UTC)}, + } + if !slices.Equal(got, want) { + t.Fatalf("choices %v", got) + } + late := SnoozeChoices(time.Date(2026, 10, 10, 22, 0, 0, 0, time.UTC), 9) + if len(late) != 2 || late[0].Key != "snooze_picker.tomorrow" { + t.Fatalf("Saturday night %v", late) + } +} + +func TestSnoozePickerChoose(t *testing.T) { + var until time.Time + n := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if SnoozePicker(c, &until, SnoozePickerOptions{Location: time.UTC}).Changed() { + n++ + } + }, 500, 600) + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyDown) + tt.Key(0, ui.KeyEnter) + now := time.Now().UTC() + tomorrow := time.Date(now.Year(), now.Month(), now.Day()+1, 9, 0, 0, 0, time.UTC) + later := now.Add(3 * time.Hour).Truncate(time.Hour) + want := tomorrow + if later.Day() != now.Day() { + want = SnoozeChoices(now, 9)[1].At + } + if !until.Equal(want) || n != 1 { + t.Fatalf("until %v, want %v", until, want) + } + if err := tt.Click("Pick date and time"); err != nil { + t.Fatal(err) + } + if !tt.HasText("Snooze") { + t.Fatal("custom picker not shown") + } + mediaPanics(t, "hour", func(c *ui.Context) { SnoozePicker(c, &until, SnoozePickerOptions{MorningHour: 30}) }) +} + +func TestSnoozePickerSnapshot(t *testing.T) { + until := time.Time{} + snapshot(t, "snooze_picker", 340, 260, func(c *ui.Context) { + ui.Column(c).Padding(20).Children(func() { + SnoozePicker(c, &until, SnoozePickerOptions{Location: time.UTC, Now: time.Date(2026, 10, 7, 14, 20, 0, 0, time.UTC)}) + }) + }) +} + +func TestSnoozePickerCustomCommitAndDisabled(t *testing.T) { + now := time.Date(2026, 10, 7, 14, 20, 0, 0, time.UTC) + var until time.Time + disabled, changes := false, 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + if SnoozePicker(c, &until, SnoozePickerOptions{Now: now, Location: time.UTC, Disabled: disabled}).Changed() { + changes++ + } + }, 500, 640) + for _, label := range []string{"Pick date and time", "2026-10-07 17:00 UTC", "Time: Hours"} { + if err := tt.Click(label); err != nil { + t.Fatal(err) + } + } + tt.Key(0, ui.KeyUp) + if err := tt.Click("Confirm"); err != nil { + t.Fatal(err) + } + if !until.IsZero() || changes != 0 { + t.Fatal("custom draft committed before Snooze") + } + if err := tt.Click("Snooze"); err != nil { + t.Fatal(err) + } + want := time.Date(2026, 10, 7, 18, 0, 0, 0, time.UTC) + if !until.Equal(want) || changes != 1 { + t.Fatalf("until=%v changes=%d", until, changes) + } + disabled = true + tt.Frame() + _ = tt.Click("Tomorrow") + tt.Key(0, ui.KeyEnter) + if !until.Equal(want) || changes != 1 { + t.Fatal("disabled snooze changed") + } +} diff --git a/status_setter.go b/status_setter.go new file mode 100644 index 0000000..1fb7b16 --- /dev/null +++ b/status_setter.go @@ -0,0 +1,137 @@ +package mujica + +import ( + "log/slog" + "time" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// CustomStatus stores content and an optional expiry. +type CustomStatus struct { + Emoji, Text string + Until time.Time +} + +// StatusSetterOptions configure a StatusSetter. +type StatusSetterOptions struct { + // Location defines day boundaries; nil uses local time. + Location *time.Location + Disabled bool +} + +var statusClear = []struct { + key string + after time.Duration +}{ + {"status_setter.never", 0}, {"status_setter.30m", 30 * time.Minute}, {"status_setter.1h", time.Hour}, + {"status_setter.4h", 4 * time.Hour}, {"status_setter.today", -1}, {"status_setter.week", -2}, +} + +type statusSetterState struct { + picking bool + clear int + until time.Time +} + +type statusSetterKey struct{} + +// StatusSetter edits *st's emoji and text, and when it clears. +func StatusSetter(c *ui.Context, st *CustomStatus, opts StatusSetterOptions) ChoiceResult { + loc := opts.Location + if loc == nil { + loc = time.Local + } + k := Tokens(c) + u := Density(c).Unit() + old := *st + col := ui.Column(c).Gap(u * 2).Role(ui.RoleGroup).Label(msg(c, "status_setter.label")).Disabled(opts.Disabled) + ss := ui.Local(col, statusSetterKey{}, func() *statusSetterState { return &statusSetterState{} }) + s := *ss + live := !col.IsDisabled() + if !live { + copy := *st + st = © + } + if !st.Until.Equal(s.until) { + s.until = st.Until + s.clear = 0 + if !st.Until.IsZero() { + s.clear = -1 + } + } + col.Children(func() { + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + face := st.Emoji + if face == "" { + face = "🙂" + } + b := ui.ButtonBase(c).Size(Density(c).ControlHeight(), Density(c).ControlHeight()).Radius(theme.ControlRadius). + Background(k.Surface).Border(theme.BorderWidth, k.ControlBorder).Label(msg(c, "status_setter.emoji")) + internal.Ring(b, k.Focus, theme.ControlRadius) + if b.Hovered() { + b.Background(k.SurfaceHover) + } + b.Children(func() { ui.Text(c, face).FontSize(FontSize(c, 18)) }) + if b.Clicked() && !b.IsDisabled() { + s.picking = !s.picking + } + if b.IsDisabled() { + s.picking = false + } + Popover(c, b, &s.picking, PopoverOptions{Label: msg(c, "emoji_picker.label")}, func() { + if e := EmojiPicker(c, EmojiPickerOptions{}); e.Picked != "" { + st.Emoji, s.picking = e.Picked, false + } + }) + TextInput(c, &st.Text, TextInputOptions{Placeholder: msg(c, "status_setter.placeholder"), Label: msg(c, "status_setter.text"), + Clearable: true, Disabled: opts.Disabled}).Element.Grow(1) + }) + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Children(func() { + ui.Text(c, msg(c, "status_setter.clearAfter")).TextColor(k.TextMuted).SingleLine().Shrink(0) + options := make([]SelectOption[int], len(statusClear)) + for i, o := range statusClear { + options[i] = SelectOption[int]{Value: i, Label: msg(c, o.key)} + } + ui.Box(c).Key(live).Children(func() { + if Select(c, &s.clear, options, SelectOptions{Label: msg(c, "status_setter.clearAfter"), Placeholder: messagingDate(c, st.Until.In(loc), "status_setter.until"), Disabled: !live}).Changed() { + st.Until = statusUntil(c.Now().In(loc), statusClear[s.clear].after) + } + }) + if !st.Until.IsZero() { + ui.Text(c, messagingDate(c, st.Until.In(loc), "status_setter.until")).FontSize(FontSize(c, theme.CaptionSize)).TextColor(k.TextMuted) + } + ui.Box(c).Grow(1) + if Button(c, msg(c, "status_setter.clear"), ButtonOptions{Variant: Ghost, Disabled: *st == CustomStatus{}}).Clicked() { + *st, s.clear = CustomStatus{}, 0 + } + }) + }) + s.until = st.Until + changed := live && *st != old + if changed { + slog.Debug("mujica: status_setter changed", "emoji", st.Emoji, "until", st.Until) + } + return ChoiceResult{Element: col, changed: changed} +} + +func statusUntil(now time.Time, d time.Duration) time.Time { + day := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()) + switch { + case d == 0: + return time.Time{} + case d == -1: + return day.AddDate(0, 0, 1) + case d == -2: + // Weeks end on Sunday night: the next Monday at midnight. + add := (8 - int(day.Weekday())) % 7 + if add == 0 { + add = 7 + } + return day.AddDate(0, 0, add) + } + return now.Add(d) +} diff --git a/status_setter_test.go b/status_setter_test.go new file mode 100644 index 0000000..9620f2b --- /dev/null +++ b/status_setter_test.go @@ -0,0 +1,105 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func TestStatusUntil(t *testing.T) { + wed := time.Date(2026, 10, 7, 14, 30, 0, 0, time.UTC) + for d, want := range map[time.Duration]time.Time{ + 0: {}, + time.Hour: wed.Add(time.Hour), + -1: time.Date(2026, 10, 8, 0, 0, 0, 0, time.UTC), + -2: time.Date(2026, 10, 12, 0, 0, 0, 0, time.UTC), + 30 * time.Minute: wed.Add(30 * time.Minute), + } { + if got := statusUntil(wed, d); !got.Equal(want) { + t.Errorf("%v: %v, want %v", d, got, want) + } + } +} + +func TestStatusSetterEditAndClear(t *testing.T) { + st := CustomStatus{} + n := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Padding(20).Width(420).Children(func() { + if StatusSetter(c, &st, StatusSetterOptions{Location: time.UTC}).Changed() { + n++ + } + }) + }, 520, 600) + if err := tt.Click("Choose an emoji"); err != nil { + t.Fatal(err) + } + if err := tt.Click("Activities"); err != nil { + t.Fatal(err) + } + if err := tt.Click("violin"); err != nil { + t.Fatal(err) + } + if err := tt.Click("Status text"); err != nil { + t.Fatal(err) + } + tt.Type("Rehearsing") + if err := tt.Click("Don't clear"); err != nil { + t.Fatal(err) + } + if err := tt.Click("1 hour"); err != nil { + t.Fatal(err) + } + if st.Emoji != "🎻" || st.Text != "Rehearsing" || st.Until.IsZero() || n < 3 { + t.Fatalf("status %+v changes %d", st, n) + } + if err := tt.Click("Clear status"); err != nil { + t.Fatal(err) + } + if st != (CustomStatus{}) { + t.Fatalf("not cleared: %+v", st) + } +} + +func TestStatusSetterSnapshot(t *testing.T) { + st := CustomStatus{Emoji: "🎻", Text: "Rehearsing the second act"} + snapshot(t, "status_setter", 460, 140, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(420).Children(func() { StatusSetter(c, &st, StatusSetterOptions{Location: time.UTC}) }) + }) +} + +func TestStatusSetterLoadedExpiryAndDisabledPopup(t *testing.T) { + st := CustomStatus{Until: time.Date(2026, 10, 6, 15, 0, 0, 0, time.UTC)} + disabled := false + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Disabled(disabled).Children(func() { StatusSetter(c, &st, StatusSetterOptions{Location: time.UTC}) }) + }, 600, 400) + if tt.HasText("Don't clear") { + t.Fatal("loaded expiry appears as never") + } + if err := tt.Click("Tue 15:00"); err != nil { + t.Fatal(err) + } + if err := tt.Click("Don't clear"); err != nil { + t.Fatal(err) + } + if !st.Until.IsZero() { + t.Fatal("loaded expiry was not cleared") + } + if err := tt.Click("Don't clear"); err != nil { + t.Fatal(err) + } + disabled = true + tt.Frame() + if tt.HasText("30 minutes") { + t.Fatal("disabled expiry popup remains visible") + } + disabled = false + tt.Frame() + if tt.HasText("30 minutes") { + t.Fatal("expiry popup reopened after enabling") + } +} diff --git a/tags_input.go b/tags_input.go index 3f9afc6..b1b2944 100644 --- a/tags_input.go +++ b/tags_input.go @@ -27,6 +27,8 @@ type TagsInputOptions struct { Disabled bool // Invalid draws the border in the danger color. Invalid bool + // Query optionally holds the current editor text. + Query *string } // TagsInputParts are the parts of a TagsInput. @@ -42,6 +44,7 @@ func (p TagsInputParts) Changed() bool { return p.changed } type tagsInputState struct { query string + q *string err string backspace bool } @@ -61,6 +64,10 @@ func TagsInput(c *ui.Context, tags *[]string, opts TagsInputOptions) TagsInputPa outer := ui.Column(c).Gap(d.Unit()) parts.Element = outer st := ui.Local(outer, "tags", func() tagsInputState { return tagsInputState{} }) + st.q = &st.query + if opts.Query != nil { + st.q = opts.Query + } add := func(s string) bool { s = strings.TrimSpace(s) switch { @@ -92,7 +99,7 @@ func TagsInput(c *ui.Context, tags *[]string, opts TagsInputOptions) TagsInputPa disabled := opts.Disabled || outer.IsDisabled() if st.backspace { st.backspace = false - if !disabled && len(*tags) > 0 && st.query == "" { + if !disabled && len(*tags) > 0 && *st.q == "" { remove(len(*tags) - 1) } } @@ -120,13 +127,13 @@ func TagsInput(c *ui.Context, tags *[]string, opts TagsInputOptions) TagsInputPa // The input keeps its identity whatever chips come before it. holder := ui.Box(c).Key("input").Grow(1).MinWidth(d.Unit() * 24) holder.Children(func() { - in := inputGroupEditor(c, holder, &st.query, disabled).FocusRing(false).FillWidth().Placeholder(opts.Placeholder) + in := inputGroupEditor(c, holder, st.q, disabled).FocusRing(false).FillWidth().Placeholder(opts.Placeholder) parts.Input = in if opts.Label != "" { in.Label(opts.Label) } in.HandleInput(func(ev ui.InputEvent) bool { - if !disabled && ev.Kind == ui.InputKeyDown && ev.Mods == 0 && ev.Key == ui.KeyBackspace && st.query == "" { + if !disabled && ev.Kind == ui.InputKeyDown && ev.Mods == 0 && ev.Key == ui.KeyBackspace && *st.q == "" { st.backspace = true return true } @@ -168,8 +175,8 @@ func tagsInputCommit(st *tagsInputState, in *ui.Element, seps string, add func(s if in.Changed() { st.err = "" } - if strings.ContainsAny(st.query, seps) { - pieces := strings.FieldsFunc(st.query+"\x00", func(r rune) bool { return strings.ContainsRune(seps, r) }) + if strings.ContainsAny(*st.q, seps) { + pieces := strings.FieldsFunc(*st.q+"\x00", func(r rune) bool { return strings.ContainsRune(seps, r) }) last := strings.TrimSuffix(pieces[len(pieces)-1], "\x00") var kept []string for _, p := range pieces[:len(pieces)-1] { @@ -177,9 +184,9 @@ func tagsInputCommit(st *tagsInputState, in *ui.Element, seps string, add func(s kept = append(kept, strings.TrimSpace(p)) } } - st.query = strings.Join(append(kept, last), string([]rune(seps)[0])) + *st.q = strings.Join(append(kept, last), string([]rune(seps)[0])) } - if in.Submitted() && add(st.query) { - st.query = "" + if in.Submitted() && add(*st.q) { + *st.q = "" } } diff --git a/testdata/snapshots/darwin/call_controls-dark.png b/testdata/snapshots/darwin/call_controls-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..f6722557fd22e3b0592e7f9431842d83b2f376bc GIT binary patch literal 3916 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/call_controls-light.png b/testdata/snapshots/darwin/call_controls-light.png new file mode 100644 index 0000000000000000000000000000000000000000..bb25ed9a37223edfb99de49a70a6ac854a59b103 GIT binary patch literal 3893 zcmdT{c{CLK8b)7ZB)hDQ8j2WeWn@caNj^)mWhwibEn~!BWXVpE2-C<~UonQsFt)N} z3*V$M7)x0i%os5kOSroC{(sN?@7{CX^Pb;!&ig*kd7k&2U#gXb3C{_M6Krg3Jf=4c zt=ZVv%a7I%fgDHqVue6F8yoL0Q$u~5hsE?Mgp~~$#Q8I9+y(BIpKK<2i@icoP*tAq z%*hi1Cym)bk+@M2^${zI;|Ny{?mg;F_7$Ok_iF;Vva$sN?*k1@t0%5?-Ae1d$T8Y` zJ@FKKcODNU+XbE<6Rtb}4vc@CN*G|owzJTP;nuwZZAQx= z9tWyD2LHf2#;)zk`MSyT@0+h8p?P@*VF*d-$jyH-yHG#3giA= z0+8^sbB?I=N9g9y$({RD_1dtj^px)SSgnnbCU3o|0yiYD2zPCm0bO+~4Qp>NiRjMm z2t^9N9?%gouSmx~{FA~$yQy^{Nf+!VAMys?q=^;f(b zwrAE}DfL)tfRrU{E({uLM`O7f8$&faG+F^w?|)o()adrk_j?$Wg1UGn&MhOP zaq{&kGm&2#JvjE?YS;K!TQ6Y(#72qcVK2izItQqW3hUC+8+fChr5h6`9V6E1pOe;J zasT+zpeBuJv5r{3?>pNP7a||{PrsO}(%WWHn^DjCJ6M9_6%>o6a;Qg3=s@csP(W>pVZrI`NR6=tyf1T$D1oud6^E$F`n+xo@uXlBJeJYuf za#@Yx9eD~->)}on6^E9Oo`k`OfRk3PaUDy53�J%xpz%eIp8C0?Pv7y~pzW4~JaT zFNz0lUsS(1et>G0dTpa#w+t%6JL}lP_v|F6{K}4s_%tx2?w&u&(BAqk(6PP9dwWbjK*IOUO-bI?y}LdLgn_kncM>-&dqoN%lrmiDPPW=-r@ir+AO zOlk%TwUE4lVy5JU!cQIUZ>?seFSVngEPT7w)Dt{P^GtD00nUfn{@^a@0ztHu2~cwi zLS0?el~FyXG+rY0juO!uwjN>dMf47qI~M#A;+yu@8xq8~zZ5@nHW8QSypjIIIM^Wo zDz?lAszS3JIdl*^$F;3?$B)#LHfQHUQ%|r>P6vWB(RqA+;ofEPLE%u#4^=&chhq~gigKWs3%^T)~HBzK#k9Y z;^!-(%k0S3&UN(dX0Tu1=5ZuuYG2>dBYoKz;#Tmv{)}m<^kcx+h<>j}!^3k?zzoN! z4N)Q7O_J_7X?0&Gd3DZq-8z;<0%U2ctON%qdsQ9T(#Mhx1c${wBaXzHz~>XK=x=Xr z^5UP4run~&L$^iB==L8pIUlSRXx0bXO{P9}f$YycI&9tSqTF-W)xjxGip}q ztqziJC>V@=>el6+>e&8CiwFII+;d&}N2(6bvi{NNq(26As+u8LZ=W<4NK#eqV2cDb zM>0E`oRFPbclG(A32tJav_#Z?upI}VQ@yhNfq@sy$?;{5m|ttW4AtJBc=M%b!4?To9%3gApqLsuh7|?Ui-Yc^W9~^Zv-Zh7B z?o;pZGi;U7w;*Vt@r;}2@occxut&29Qi3?thAfDV*@E zO;S2r!Y>tfU6>=oP@ua+Sr(w?>mGep4XhT=mjd4P1l%%6DbPG8Q|fACHGl8)vkY_3 zx|5TmHQ_Kk@-so|gRx!6JK6+`s?$Wh?3A0kl{Yf7stbBCwu$d!D##7LeK%9*0>t`; zW%AF?x9z6vHiH9?Cqcnom7)Qae-L#swSFDwO3{4}N!=hFVV8v4@%`T9Wi8&jQ(ytIThQEJje zi56-P-xD@~U4|~?nQQNTuc|StHUPeD?R|!NgNT~XjRTGGoPkF;1na<*DE`&sxV3xf zX=Vch0}4J~PSq6)UWY33ny_ziE6Akvj}BeqqX!- z_r7LL9CUc>Eh{h!h)L;EP^v??<@TkeZWReSB!B+T)>Udm#AEJMiLB=~_JcEPTTL$L zDo+O~hvt^O2b6<~;XXNb?OI7$dd;upG1i1gdrflG?7q=kTXUz~p&ydd3lnnPB@;ET z8ygRysq8sVUtnR~5606Yh0j0mOq5$>`J6H@-uiO;!L<#-q+COcCoZE-srXW?MdSx+ zShQV)H#Nw}R_?R5wQ9R`dnxYi5@vpv0C;_NC(1$AYP9PYEo zD!v%j^SaPZH72d_3qEFa^dZ#-E@MQ9g3r6>8J!rdk1 zo}Pr8IMpA&&JzaZJZ zi1gs`&#*fIupR6lMl}&`@^&E#(2uCePY^i{#Zd+~))Q}A&Tf4b+MG z-M~>0Yi|oO%AE}W;?u&RdzE5}@Q<$7wt%Kve7wFiP| o+ri(_9mfAB4?3Ic_7H40(_>|L-%Sb~eTUghjVugn3|!;?0pv-M2mk;8 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/channel_list-dark.png b/testdata/snapshots/darwin/channel_list-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..cabdb238622008eeb41042278b7f9d89ea9f679b GIT binary patch literal 11482 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/channel_list-light.png b/testdata/snapshots/darwin/channel_list-light.png new file mode 100644 index 0000000000000000000000000000000000000000..173404d08155942d291f9b65454c21d9363e7dff GIT binary patch literal 11163 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 b8OF~I3DOO{bvSy{Erz0;nru1H{M-KkEv_6P literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/chat_message-dark.png b/testdata/snapshots/darwin/chat_message-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..f76407142c823d90eb127c3f82ac9a055a268405 GIT binary patch literal 21420 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/emoji_picker-light.png b/testdata/snapshots/darwin/emoji_picker-light.png new file mode 100644 index 0000000000000000000000000000000000000000..a4867f6892587c2e59427593f822e4ff685d8666 GIT binary patch literal 20646 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/incoming_call_dialog-dark.png b/testdata/snapshots/darwin/incoming_call_dialog-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..310ecbaf07a324fc4f54448f5f324c7c57a132da GIT binary patch literal 18098 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 MlM}5HHVFK`0A0VaWdHyG literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/incoming_call_dialog-light.png b/testdata/snapshots/darwin/incoming_call_dialog-light.png new file mode 100644 index 0000000000000000000000000000000000000000..15a5017318bc8a12a94e89db9e72972a736888c9 GIT binary patch literal 19482 zcmeFZWpG?Q6D~N39pe~c98(N2Gses@Gsn!#%*@P8F*7r>9osQ8$IQ%pCm+0fcWd|8 z-XD9bwr1+gAxW)At=7{mX+mYCMG)Yy;Q#;tf|%%cc>v%e3;^&U2IeF9&UZniU;sd3 zQ|vpxqD#if9N}jGJrJ@-y66htKlj^#k^xetzo+KAXk3C76i^2M0qO=o(ffS(|4;wd z;6UxKyU5;`*{Dknw?Yk%KtUrLgDi>W^6soBxl)f0p)6$r6h2R&bwXL7D5xHU-C(Dz z(Gfr$mP62Qcsf|M&lC?nh4TSxF2@Arv@>q>7(k1`}su~35S@>Rcd1cO(q z;qIxu@sZ(~z(glTa2%rC!%sfr&~cPZ5)KK=GitG0+8e*4>;gfUP2^AR!H=O$VSl{|rNEYdDaD@)@s-dQV8) z+c>xLUOW8zrZz*D!jT0m6X$W%%9@+d?;D}opj9?_C<;j9vlm!--wXvxp4|QT=2xDy z&M|FbThkGC6=lUUqobc!Amn`&3D89Y5%YW7MS{s*PkSC8n#sKfY%7(YFgQ?vL=6&p zUj?psO;L*aVwZxE1vC{na0|pv3dJ6sIbLZ-l^Nr{PU>v17 zi08~Wl3|U^FyY#+=b`>4B^prOGZE%;j1+rYq4$z#z+}TBqaDF5k51EgkAm{sWWZ8} zDAjnt^9Pq(zau{NQz-x_0`0$w_v3`d{L`n24HZ6QNES7C;$n+t;(j;m1WqI~I4G$% zV+%*}Mj$M(&qlvP)Y**Gl%&3~>F9LI%~$tWs(eAL`(rhL8USw`8Yl#%xMWT8Zb>}M zVjVpX4}2$mG(jqhtEPngdpJB%CZU-I2H73f=ijW{egt%pVfr0DGUv6z(w;Xw#xEp=!w zbyOWS&DC@6uhCla(Z@djOBSgG$3A)le`EpJ2CQw#5al)rkQQ?|=Gd2ep*s1Qo3W1T zPY^Z$+zbG;+K#*JpS2;~tPPx2eo3RW1l2W+uR;94H4m4}`93n)QTg%F+LYvh_FwVT zFx(;|)47c_t+~!ioz058C@BC^Y2VOmNC-$gIn}rTXK7rw0qUj@OH~1f^)ynYeb$2G zpc0%yT~*3l(`ApWeIYmAOz95Tn&Ja3r;T>wiX;vseks&$06jA*@Q@iux=noLm`T5U zW}^$5c(G=c8j%`Nt)dRMz!2$Vy(O)<6FOf*KX;f@0ziP%0Du5NrJk6g5_cv^qK(;- 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 Gp$Pz}Jz_Kf literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/mail_composer-dark.png b/testdata/snapshots/darwin/mail_composer-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..55e628d31c0937fa398c02550852f4930a95ed33 GIT binary patch literal 22432 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/mail_list-dark.png b/testdata/snapshots/darwin/mail_list-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..ade1f580967560c64537832cb553650c3873b1e2 GIT binary patch literal 19374 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 CBrPQX literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/mail_reader-light.png b/testdata/snapshots/darwin/mail_reader-light.png new file mode 100644 index 0000000000000000000000000000000000000000..2d8994651fc666dd312cc95a6fc3b11ce8580992 GIT binary patch literal 30452 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/online_status-dark.png b/testdata/snapshots/darwin/online_status-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..c3ba64eaed8866996143aec63c31480cef1cb66b GIT binary patch literal 4014 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 I4VRez0pYydjsO4v literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/online_status-light.png b/testdata/snapshots/darwin/online_status-light.png new file mode 100644 index 0000000000000000000000000000000000000000..8e8555a1f3fd0e69ef1872f4b9cf2ab34f4ebbcd GIT binary patch literal 3889 zcmdT{i8mD7`&SVuV=B=ryAmQxc7xa0-x#VfvZWB&*G7z`WtezFHCYBjQpOgq1|wq( zA$wlNZYJ9p4b#MwH8Xzm{U3hke9!lud+xpGo^#K=&vQS|=kq-2E)Y90QE5>D0Rb@w zd+X~00*Bu6*C3I@{INXLeMdk5u;XBD34Kt+q8)=$CX0pF3!kTALxJeCl4ylyppCUx zq+lYb8Y+uL6_4(<7&THV2U{^FI5}rel;K2ETUp&6$gbSg6RIKc{waI}W^FSN{O7dL z3Gkt&-C`FGUgah6$4&+_uS>J@Rq2wDmsj93tlJ9|;8~1rI;ke~-%05-@EC z{Bwl$zc~HQsV`gjoBXpGT>}+XQc^N68M@k8o(sX@+se&Bx-us# z7_cFYT@7(@aq2E|$3vPuo5G2cAPG_^Qsf~2T5cEBtsONT|-&w={ zELOXyDUxBaQ*2m*I%gZLyXL<+6g)Xx3|`e zMTcBn8~RY_IZD{y;bu1yLI}K-x~(IR^@-$EeIlp4MfhC|m*->T_7#c>3E$=IZ!f=F zt_-S7q5kYKJm5N&jpT2-=XNf%bC>KCB>WR!Z5(%4Nsz2)7#USWf|aFwH+gREJ{g5Q zpYQ24={5f1x7f}3CLET775;3G0_s*12jb+~^$9@1`g_bbadD*ITUi9<0NcbIZcevv z2bTO`Og1GY@wbz^X7}t<4driNdWnY=7@wpLO z`K|xmrCM_&yNR0VDMLu01tVP$o~DJJ5QMSjbNQ!a=?h!~=KF&O$0rq1$Qx5UpM$hI zdE?(-5-Uf8BZo8-{8FNS9rij0umrlJ@DmX?E&L`OduOg!#$+wiOZp>7 z6loc0&8im! zjgSuCNuT|(JRDo^D@M*3tMHU0&lW=?F_{cMyDY3(66{*-e57&fpI?2pc-=icDC>QX zk;cVK-E`6vy^J`1GtNkSlIqJG<@lAg?s!qPi#%NkiAhPyfwl?ph^Tn#;+w_YsGm+M zln#=x)Ip~&@;NR1Ky^uZ*UOlKj$fL|WDVoBk`dQvrGRXaAJ90tnG{v{9gUC0>&y=4 zN;&AG^^+4bSu!TREJHs2JATC?KB-CcKejnuD|su7I4emo0vHnivP!bL>%M%B8S&3e z4fP!9Uh!XBTbEm)5+%SAt_?gXEUAZ-H9JlS((~wG9`+;G|FUK3F&mPtQgBsQ0xTWl z9d;WBCIf7S)JeAz-mPc6@!Gi0p5z0;UW3Eg0*mBup}8@jmC@9zq?WJiy^$HeXXOT2 zw*yuRreCbZqJNCWhJ?ZjWA}Pj(^DR%C|J0Rmqwdl`7{(3H)}v@axijzzz!iCQ=T?$ zxUc<1yKo%NTGs(&<9B@w5DD>e7SS>(H2w?H)P&^Z#0As z6jTIAx?QU3ONHB{DxKF5v{?72%s!A3TTZPy?#Fw^mOV{^%u&a@++p!1E3ps!jq-Z# z8_DqBygi5BOZY7Vu&Zm^W>w;=C+m`xxnfR)a(Y7gy{g^-yuLwmF_3?FhN_-pHsf*j zqjFRV#IWUgCjH^awYUnK8#ZNg?Qa*ZTa|S9>%O;lKPhuc=Cl-kpKpZ%^<7PK+iEoeC}M|e&kzzfZu%EzXt zX$C`}-`~$*@PQLwtN1~eIWU3NOu!a*2V}+%H8+f};*L7s)y435Ji1^>x3A8(XKIht z9?VaPARq7C-4H3=JmJVAUh{er?K5tBwUXzQCu&MI5<#h%TCiLZQZkH!YX^3PXM(dUEU(YUwILRsBq?32A=qFcOG`xItCB6n%r5q0?{lq@Rs4 zM-L7B8RLiN)V`#O)@W2~wBDSe(5!HjzQVove{VZ$4d(9bmpI`F4be)G@ft{%kUR5phui45p(3D)236i!G3|_Y*eSe zRa>-IogVz*c<_CvSz=3JVS)F$SR+3I7waF&-Zm5^ie1ffM$*#W4bWDtQahKm^PlY% z?BxsTY`gL!JehH*S^zHa_fWzLH!iYs>AVWl=B{^N{^#G`JENKzqBisz`?iPKKws^% zu7=gH_ud!8@{0RR%O;sirx%5f9<5TZhJLTwLGE;PbhM)5)k1FgN_L$%aUyY@Crk(D zfIMy?s$tdR{bkELkK`4LrWdFc%$e1rRP9sYW3gXY8<;kE1C%CE)MOlc3e&}m1polL z7{|5OXSU1eIemQT)^ySgbS~kt_v6;CPYR)qUcn5u%-#>{Z)$KGU2pGG(bwEWo0YH< zA}0AdXIGbXQqVHIx4it_V$*_1>ZbuIt?aFOHe9x_bBn`~zQWNt)h_zf`Kiyxgyqho z9R;#A)7`yFK2DI1#uxmYMVEceR5bNN=)lRbJb?VLZG1>@K*+p(K(_x=9*#6cpL zj}6x$zM9+%3lEk=J>B$3LUM%#6eo+vGd{~HPv-=8&>mmOy^GgVfKOhi{A5R-kk}~nPJA> zGD_hmPM6t_FtURz+aVSZT=)|9MFdc|U%J>ecizJ>mwNi6B)+?|(@F^)N^OXumUW}4 z5@jx`=56LdTDawvWvQaeudjT&bRFi{FtxqjWwu?Q5DMST?&*_FSBToN0-SN9)rg{z zG_pM3C_cyXk>*diTS@_AAs53``RPL_|2CC84Np#YppT2{t8cp_J9nN(R{cw%+>p^o zX2oY1mgGg!pV*l|y}bU@9ZOxNWZ;S5{nn{?sJcFr;IJ}Wq-Ep{)HlpX^tJi~PE1TP z-~S=*opLgHp3BVUdu$gq&{zF(#QNX~N+rqDBz`QbsGmD-)vad|MqxPl$o=NDmjH~g z5P6@HE_&CL&C-FF${+nMmLfL8*|6#{%}2-*bUZ;M(8Wr6-F21$5gn;}_5}4|4Q#FWU>d(wGGV?o$UY`Xq_HE7 z@*N3Qif|&08L6AEJQw5Vz0_BOo{bBar|n3XUk<=e?}>3`F0Z7gcs*-PO<`@H^f2>MnHvfckAN{8CuJ!3JVo3%>pM{{VIjyaE6K literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/pinned_messages-dark.png b/testdata/snapshots/darwin/pinned_messages-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..0db5534fe383f3b6b35558236354ab948684a3b2 GIT binary patch literal 10904 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/quoted_text-dark.png b/testdata/snapshots/darwin/quoted_text-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a6212e6707402761c05457dff9a69b7a22796476 GIT binary patch literal 11912 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/quoted_text-light.png b/testdata/snapshots/darwin/quoted_text-light.png new file mode 100644 index 0000000000000000000000000000000000000000..c50af2fee54be92ac1f22fcb8e4e97c3017e9b76 GIT binary patch literal 11530 zcmeI2Wl&sSx8@-s!2<*h8iIQgoJN8}aCdk2#vy?~fJTA^_u$$<;}YB-~yA}ZY^b6$J<=A)+UWg4w4;xc(n5_;Sxbup z*PMr&Ta7SK#?RiOQrttbm3;ls+S|)FRN!rQBrBb4ilppE3EYK0_luQyhq)= z%gLL9nfbk+HwuZ-A;rK5&Mz8Qgqwd&?2xqz7728}g8BwSYuu{rVr#qg!;!zN_|%(h zT-I`ZE#03Q=b;%IVi}V(G;A8?{6PI#4bN42drldR5Ca4=IOu%btKC9(A61bv{l z_qnDoYtE}D@md(4R$kZi^mK7VJM|@aW+qQ6UC7hsv4vksDs-9rE0Ez%1YnBZiy079 zyK|?oWtDOOb7hEh zPk9A;1=4n}apL(HH-DakR6dik9bOh>;|{Ty-rj;^HIb_MRAP30Y!Q4|ubEBZQK0qQ zd_x1-7@Tw^OE`SMoW5{rp=Pl@FtDpfZYHvpw9PjO2gzJ;aHZPg=x&msQXh(o^sO_F zD(0K8S8|8x#{)#!Y`H;2Uf#hD6$x1q3exvy(NYrnk$i3hNTwT(`c33#o3fetTR-?6 zISZ9MRSfYJL#4WV=%%Ofi8UAr)b$J{*pr$^4AoV1u#swZ*fWJ4;_ga%92^`vzAG)Y zo#~m0$Cqco?go1b3W8hOmSfY>j@sb+HfkAiazk2`C*u>_tjSM%Z4cj({|3N=b*RQx z8@tjFG@i8Vnbtd~RPrysY+I^``){1v#PfJnJo{quQ+#=w^|KtlavwNapZ!Yvz(LUZ z_uAX`%}u?p9eu(#UQ#|%nznFp2ZwU*(j>)F;-2E z2d-pxEY%LWiRDp%5YE5fL-wSkPv=uMmxTH|FFzVMFRu>sgP1UD-PsOsuPuIe(k;qH*+&! zb#HGA<3CU!;wQr|lajO^Z}$z57}=Tde_0WsLvC;;kpCXGa^+NYFWqM-iuZi^o%bR{ z36`iL9g~9lyH0O)N$T9Sk;xlwEf@ACXA5jvuG+65G6n zJFl|4(btb9@iR6yb}bBs^!t<1*f|A0l8j>GL9@4#%GxAQwSi7%}P^8nC*$*TQTzjzszS=)3Msp`ilvO5O=K4S|8d9l@w7R&;|m zXX8lD&QGI2NlIjbI*eOxqaq+m6-8yKAS=!O@ZVva(yL@bRZ<+55+x;S{90-;Gc()T=BdfewLP0@4G(8J zih_E2WZ2q)Y+I|%>@2tuf4&-se?Jx|e+CQ;o7{TJgZVuRXh-=s9uWk#x$mvMTxw>+ zziB!(P^zUEL*l5Srk0j?@vCs=bykL}rE~n40M!vpI);3%dS31Jo*xN|=L3C!Oy;zT zRgdv4$?ZPnb<)s5TD@6C_waT5o1uSlx| z&H^f&bdkVx!z97#HGIk@EN!{Ge({kc5>ZB;A}@6wTnkH2??w6&9uAEfk%7w!(cgV= zd9?DlI4o_|Dm!g**+`0pROr=2mKLV{_%Un>?WYPBQS$evL9(`i7Do`{VaO#IOzk`d z=nX`#+4YW(|5PlTw5}b`3nx}p(RpAf_i(2b4$`UFu5`b8jrI{p2c^`}wJIAfT>}Fl z56yoZtp-Yy@0PK(u=oPQ^xW#VLCY@0Od5y2JFC71_ESbz)p14h5Sd;LHW@0*&3i-OfBM{m&o&P+M})BR6~_mM?(smys0}y+?ysxB|ekwUs!e>BYmv zbvW1N5_iT|atoU{c?q_^m$hr<@w#@rwcIRP^9$(h5Ep3zjKWZHn6Q8A^zsr+nE3Q( z^CP?R-)B8Wy4inMcditg5Pgkyvks&}K2yT&YJ%K+~PPX=RwdLt!tWuM- zwDt9EO-)&eOTz~sDIA|*^4WgkD4-s==7Oc+G8&}bmF9;v_ zlv72^z_8lc+0v+Ue!NDrMfrB8@$?jf5aUIL;?b_zYqjex);KlC!UADhs~I)5@DHcQ zCgQ~pZ;9l>;%l@8GxsJ7>Bwf9-S{MUnKx8;f)%Zx+5i?rK;+I&F}`Dcu(P!dxUsCS zh?Sw0FCg*`5P$xV0ct`1MEiPYn}~!I{`~hIrwTv+4ULqxrG?PRlh*qi$~Nn82{DI9 zLw64kr0g7Mc*$E!>Lj+SvWkl3w(0%6lq0oiep z?zh)2(NomR=Arww;>glVTE2nT9SO~zYWr}wfk^si@WTqMURJTOJU7=A07$t*2#f6F~eiv|VWAu>HT#Yz-jX$awc|5tz!wVz1b8|iqmxIZ+scWa2~2b+GI>BDf!WKFee zMIUWb10RJzl^r}GoSI>*%zbtDqm3V_(WlWRPd0J3VY$yk{(hc;0#{D}j)Gh_s}?;2 z7F#Ti!tj13<(av3eN$ZJ&v58@B(x zIol>7!^s}SASH#9ziO_n)n`sDDJ~w^I?W%NO-lGlMhY)1KvzvXO9L{!uH0~n(}w~d zf5TA^Wc=wVimX2Arv~ed59NuRvVOt+$y@Vbwa0Xl3*PL}uU*>Yy=@&`+GLR;t+bYFniPch`yGu#UB_(@+Nf}H5_u|dyAr1Cy49sHiS@#s{Lq(6 z6$VuzvJMBF1_l|z_bH;%HVzK)pYzFI`7TELkB>vC8J-;+geCsCyu3_JwQ6cwSRSS0 z=7o@8g@#J;PMUB2P4YqE=7y28DHb+1&dk)!%xEf%1gJ}1sW1|7SqKmn?C+B`>Mzgw zwYoN@cNn|-wDQIU7_^)0TV(|xHd=p{+(}QU+4Y!)tKaG?9bJi*E~ZNY;O2+m_xERi zrR(zN_BME?B4h<(_T)Q0h2S-9kgWVgvwhv*Q+YFTRQx`rWV2Sc@Q*du^XHCAHQV-e zmh}^{{?m$quckc+g9g<7^W8U#4G%vR1FJm}XQQVJaAGuhxLyn?06QmHh7X8hSa(Ju zhpgw7p>9CHxYpTDt~=whQNk-E5@E90M}~?s5kqx#5=+bAgM;$<)Kv9lJrdF=O9!+3 z9+Q1*yI4=wC(n2Q^K4AooI7?l{ipaMdrT0EB9T4D?~~g}e2!j8BXB{0af$yg4;4pq z4CR1b=XBVznZni`?ol-lHw%5kIn*^!K0 z$Jizf*^yZj&R&G_?HO}FsEF0RKlgX!@RwaA&S0LdVT79%A5DjZCS2|2fikNPv@?3M z%pW-X-EBn9ss;F7id8Vup#+ zTB>I0@=ZtP8%|=yR6(hh+0bwGW5!CU%`-fIixvcB}8am|K{b)y`*3sWw zM*Ev;@jJ6^DON~wdwOJXd16bW@JHvt;lDO+D=Vb=%C)%TzA7K2qbV73afI*t(i`Ol zk}K7e*bS>~(*uv!=}IRiIp?_>7mta%h!rsIH&*jRsvEB1IwR})adB$mo$r9VSddGw zXgOe@Lm1guaIn)j;(77LhmW;{S186xOf9}AQfPubeJyr4XLc;_MiMp&-jVW}q{}uX zY$jy?$j%&UHJq53uw7|XD|TF+7$i#rMx`6oYy7@!^;j`LG(5O9qu=FEs6yb@%IfS- zU;Od9{@o3R2_b2r?aS_sloTsqeuWwW$G#xHD#J2pW!8iFKvaue$>6FSjiika4|?^E z+`MjjU$L>P7j(l@wwnaP6A9}jY#rMk;nmz9y*Eg*#t#m7RX> z87~k%nl*e$J6Tx-#GY@N_&sjVi!mhaG{J}0Cu3eQm+o$!iM%`>?(PlP9z+ld9gTm= zb$PjW)INOxG%2bq^8>vNr1YnjAMwW(zMp^dg3c7Wu~xZGfjD@LLlLzAg+$ue+VaTO zKb(W8e&;ZU2h(_4Wuo!*A8EQm0@Zjj#3|ycI9nepB}Rt@8KTuf_wI{6>X?b*gqJ*d zhJ^LriEJ1q7N$Z=@0|$o4BB(FPZoUM+1feK9O z-HO3sG6*i~xvCtR&}L|k{-ib6lC$WJbB=QVs5{SDXsV&pd%`vk2n&m`78gabKy&Z; zZlugqpSuUmQoOfdCLj{~7uz^X7x30!SB-oik??TWTt*sH9w3b8H-u?TpNRd{8T0U@*ErnB`b#st3s3v zGHAIErut*M7!T#c-LCgP^M5k*x#@CS&O#SU{3UjjPdln8(CWF3<`P;;95_TtP04KkgZ&;5QU4^h=YY?Y;ZL3GZ{EA z?rpqF4F30!wm%22YVBZOkVGJEZ+Pr?;oMHLzp%&0V`BvG{{TKjz)OJ7;JWytC!e@N zzqnc5V6xK42pIWFJ?8N)I;BuY9)rl)c)ZbymtdxgT4d{EfLC`09p%`eM28pOx>(hExw}Sla~PQ@i@62Mn76$z+_~Ff^zNPZ^wpLuKoDg`HvfO zB7CSaE}b0p1IYB*xIlu_ILBd%uh;s7?bMb=Gvy24P8EQnDt|e zvy)S0Ztj`Y*mg}E+UeWSS#WtM#S>+&YH^6z*QlrvBTATVx!5>-m+wzY#%#@ULk`LN z-_#tHUh@&Knoe7F&m!?X!`)P=hqp;`Or|K&%`eda;H5XYCA{XY8$Ag~#(+S!UMO^J5YfDds;^b|+-)skOfTadV7?$UB;JKmZrz zW@P6IOa^(2X8J+%n)z?(m&#{X8viQl{}c4KEYx-QgvdZwSDS6>yOQlpK(WC3@m>l2 z%$NXbY=g;Y3?uqpXPZ=hxx7%1IB0J5Y`wcZ)N}HHm9E?oz^2=L9Goa1l0F?QDxW%Z z2qbaEOi@x$I?2V7KW5dh4}_DvW@jD~@Oz4Zr6SG_;xo>VHx}=@A5iCz5lCPp&=-o| zuZ#gi`%f>MjgZ0RaZQ@C6gOD^@uN(&IZ+GLL<)7V@_Z|9;(zh)F&2b7{zfmz!lAjTxe0w$8xC@9z>CdrhM@P02e2-es?(V)H*h;$3pFd}a$%+h*fx>F&7Bks3j4Ht{9w#{G3}lol zo}`EA{QmUs1cElYs2Be=zU92mSJVWA_=yQ|-!{CGYWH<}V6Dwp0k`voB%!f=qBw;$ zg=44hykc;g8_#w^oyF4)(g$AtD=b%DRcYM5KaIXniS>*8S@&>4hMjmj*fqU+z9Dwfkd7Ns;K(>xo>x?MUAU*G6?4VB1Oh4LeK zwc7XA;X$~A^Ko5SeZ=UJ%M*tp{wEA6^5FZUzGi`D68V=RU!P9xILt^a%PS?f><46J z&zhr-r)Pd;h8?a{plBCgk zGdY5?+H+wln)5d=@UFk3BS%8{9iFVafB_mW?S2%io}M_{{PMJrchObo7iaR-+pQVu zn?DyUvyvXU*l9csO^uhA=b6IZP5F&Ifc6oO%8h;Iy%TpWTvHS^6xFp{XsmXNpqBh( z{ONLW9_wWuET8+S@P74itsZ;{=GSxGZs#&$C6ELCs>!hA7%?OzA(v^Pfdqf!25Hv> zbA!&fL7dAD&2l-)K(PDzdU5;$jkBGM$KxbdgjYhOF+*UTzDz|mtu^KOY-}`98zW2{ zY{Zy7Xw-H$K-4u7H8A6de_8y(9()SQ>hNn*&9$bzD~Td(UV(joy=}Z6)2#IA225(B+$@QKgGZ1VDppJ zW*HtEVQ{u|DeA@vHGw3tTE2gSEQ)GjfsW-?lRwq+|7=C8`w(_pR$|8-@{GpXSZf$RG zk1KYM@_3p!geOMRMFUJVd|lmAxh2ArQD5NboW;*p(6L! zUGs`Hcw*|L7xH^4k@;^3B5qcP0Ifj%{*va~t|+g}O9%MkT+aiRXw>CTn@xo}z*l+PFa-B}## z4O(N(Qbu~luY-yH-G1!=`|0VDG7B9*IBj790>Y^>M3_Bn3T$Z9`KsZ#a5w_v6?Pq; zx*hewk7_|}ls#NA>ZKoQ42l=-S6FcjC^zvBHw-2>Uh;Cn_hiph}$R4cA8f z(rH~X+IjSUsky=z15?%YeW$jH$-O$Kd0{~=dEoXi9z8w1my_BwC~ikjkGSZ)H-gjJ zIod;GV+$Tp%kZ)Ch-=4*sXbb1?(;1$%<^sG2D5A<=Z9%wAu6v(HqDZUz z{P)}iU{XR>E93#s0^QBe_sflp+I=z(Mluyw_aGxC_>edi#n6H4x!t)>Pe_Z4e|Fd5 z>-$G6CHTP959g;8y!#-?oK8F{j<$DkYtr+6GSuED-~cd^0J*jyXvC7bey#!JmO;YntLp zo?{%+0rP{~A2VkWUB_@zUA zu`p4f6b$&AnK`uL!jI1dMZM&M~KZtF9x?TX5bbFKco z&?y)^LnFR9IkTy$QE{~IJt8X6iC~iuaeelRKK@N#OtaVFyUt;y^}VeW7;9-+EyC}{ zI~AKvfJfj1lS@RKeNUAYl%RJ?Y%NCLbjW_0%8aira>Nhx>*MZ@hcMly_V+1e zgpDBXy~jDLQeFP@YtUjR%dR9_YR z<%?Hr@G~uZeFaW1_x}d7{nteI&$owrA*?QteItW8DotH}J@I zQM52Cp-iPN3J?giinNNDo>v@I+;qw7?du!*JUC^0v60p;f1Y%$8G zaEy!=n=cv_`G&H%xa7?)m39KGe{$%|{bY~&23Ksi7e*Fj_Kc&hL);3`Li>50Mt#RR z%=i?lk*1=MHR z7PYDCYbz?3Ew;C27g2H}sw+S%gie)JP#6w76WqJR8(jSE%BKG?I?w0GB2qM1ftWs&$1YkqoSou5nYguWz>(@#SQQCY@ z5X+%$O_#9x6C4yQumI{mqt=hv+1d82^L(^Cb3*IV1b(tHLaj;o@cf~#w>O|iL-OCy ztz88Pi%8DmqFR$-Ptr21xOd#~ObcvJIS%{ay`CIGya;j5t*WVavueZ{e2Fa=kYQkx z(ksgdY%0OPwryFKxvVPrUVZcdQ;9>#be2b8xhgTOG_4dpNVj|@)j|o4x4XC3a#3rs zlLnhC^}A$fias}cM*A-kRr`DEyn$?1J&EGVJpr<)&Laa87EtRU8F_O(0B^JcuGJpJo#F>)xKuR6YWUK?3k8_5M#_B(b$ z)l1V8_s&7f*-Y33)(}Fg2qtDm-L}E^fm9R}7nsMG80ZuG7wzOX`Rl4Zxpa_ztuO!P z&&=XMM;YNMzrw~F#j`EUq(I?o&QOz_r9Y@23km@w1E6uSZK3X{@~&V{uz@%q-04dXGXzNAu0T zPD-9Je#-1r3C+#TG~XN{PDl4cqirj~r}^2{!N9{b7q(S*y)SF4XltvWq&9bQI_f!D zsIqxJ6mMY?CnMa2Yq@SI2~}oI8X{)Z|1&Y=TKY(oVlf}HodY}*!BAJS z7jqZd2lJ6?27bE6`sS;@IHhmke+2pIrb}-U!d~mKsmQH))Ui)?M5M2YzNixbl8gdiT znI`rVwX{56p>mc1C@V^?S$7$$>u5;u^P6M55R>Gdd~xPP0sk{UU_Z)fj>;#2x66=E z0{>blpydFN3RM>5;@aFk1d2Mf;5#lZ?wIu_3#*)J8qHhcwx%C`FQ0wQ^j7)n^L_u} zMbnB2Ddyx{p&KdYv#*~x>535l5o+Sx>i@h^@IRZ*6AI8A_#a(@|CdjMCKH#Ru#xta XIrpp3ol$^2&PcM7iV_uK#zFrL2tv*h literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/read_receipt-dark.png b/testdata/snapshots/darwin/read_receipt-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..1f778210295ccc1ec0534b9044205f4b4b1fd2f5 GIT binary patch literal 5167 zcmd5=XEYpKx0a9)qDx+75K$&!5PhO0M2YBK)Ci(X)X~TAMvXFvHhKxsM;VMxkPt>2 zy>~G>(ZVQK-uK7-eb-(0uJ5d~&N}DMUVERtpJ(s&gllOiQ<5{26A=+ns=QRtAtJhA zcYO~eyLo-C2!0b-psatCCYUbRsq_|+z6%mXFhp|pwKC_ZY>En`rX88=Yok04uWd#qe1Cnx{>R<|6Q zb5F}tE`;A`>cYQ6Eqdm%NCI06Chn=Bu_&kCrM8QCk7LdE)W6!CUzmB`g-F( z5n$`PU&l5#X{VKG)L`sUjs=8)C_*N&(gV^zl9o$$HKrPQnZzm9hoImMoMV;tNa`8rUn4)y6|luBITMK z5uAga8@8)vcbqUi*<#{veIidEzwlL2rFJ*O|9r9_4fEvg!A{`Q!?$6=gWWi<&k`5G z^rU|boKI;008~J(M}t#COU{iaiAgfqtH|$4@B5Zrmz`$xibi>Be7g)ux2-Y3u@ZAM z=lk0}0{uZH5H^cC_tjrD-ts@DDyVsR^@&*tk-_bo;VNC4namVFTl@d&j19w;IeOMbhU(!I@DBM6cpInloXHnx9Iw>Ezm&E-oN(w9#tfJ z0!{Qe4av`cNFh?ytgRfW+T-pk(=7C-Fml7%DxHpc>Tmda=?)b`*oK++f9ZjeWez-F zZM0bd?Y2jS81Ft_PZ2J%K4&Zsw^D}r+~pJC*Ebv|Ar**v>apWw>>DjSKYFSj)Rz1y zQDzc0gUDMMzB*g<_uP3IV;LG6nkRLVC;pZoi|zov&AvVIH}fp2b6~?&p(~RkI5;d6 zd{_ek#rngy?+d0{99NvP6R24bN(~h+9zTXvc&uf9;p_0)j#+Z4=Su=%(ACzjk28F# zI61|Yl-?&yzT$qn*;$jP^Tqd)U7nXsA1$3U7nI%gfsND`Ak*CC3KVmk&F5dt;ke$k z7CVJ{B`=V-*FDZ08;>y;Cs^$A$b6e);ekX!{}@DcKfKmkdJeV=8nmmq9mL@_aG7wZ zHk5oj=);bk;N5?qgkN`|k^dDL!PzoH%f^fre}AjviJxrawVN6jQB#Kn!}b?`Kqxpp z(r`JLhi6$C;b&y7ZKj*sD|k0~hwxILd*J{{(gJ@faJhAYH1@3VmqDSb&`;PGMl4bc z_sA^cgFPf3EG{lTL*^`hNl`vqI!!r z9M;;1ZPoU>fAo}<>I}1Rk`3`&=Dk%}^Q=B$#;@S5LF74#(2Z@ zE3(BZkR>C^K$Sx9E)wf#XP2Gz54p&&P?5-8mbb5W!ifJrNT$^uJk=llUG%kD{CCmG z`LCjr+@t2( z8QGdZs>RQm?X_Hu&>hRAEs3CjPwrVG7EKanpK|6wW7AFb~8RDetJhK zM+-0Q{pNdaPX;0PHz;5g{Q#j<1>ATPgQbK8+==O8m1!TI_i{5m@5{x_QyJFbcH6>< zfmG?>2K=|mvmhH!;c1UF%*tQ)YRhQkoeJ{&VL$z_qLcQr^u~sgale!k<#WP|UKYAQ zRa&z=p6*C;C_Ka*19+Y>!{f>vG@6y5QrzksUiC?_g|UtI6BCk>WcJcFhIcxZ6N_g_ zV`$`O%)%lRK63)!ZiuDwdK}q840`f(PPNux_Ds0>431#@(OGQv^E2*0jWoLKZ%)Z$ zHKQMK`KK}Jo~F&26)ycIw}TeXsr!fxF4yeQIxPF~1vQ$GO>3R-X0xmx9})a;glE7Y zLbItx`cdovx?@G)S?4@gaFd;tD#U;%(dB76Ka1>_6Yrf!1&~IcT_*Uop3bZCe|mNU zSv01~3J&xcABRLKS>e&ySt9Dklpo%VxWoi1Md|5p43ScwuwFKtUR^0k;oGy~;xday z*MXXhz#3X07q^#nZt*J=&hEunsTgzWreyORq^`YZ=<_~(B?g@b!TrlP0voQ?z0usk zrIaR>j?2Cj&?;5}mDAk)$p-Z1b3M|6?pNI6(NxECxy@sx-WKm|?m^E$99*1yUBhNO zKZU=|^n!lRDzb+O6kxA7DJdz#Yj;W1PWpQKbc;q=CzDaV%Wh8(Zl3q`^>!kdnV2eZ zO7Alga}QmRFr?$SP-JaUtL|3 zf5&kuU;S5$4|U^EEGUkFDb(zK>&XG>Vt+i)v79e!vp@c%8xgU*R1AK&?d>;7C;wy9 zdAIoYIT;6+B=nfal@!{TUke&f0fB2ST3@9^%%VFx2;NDPfU zgBVR4%d0~3M*{rp5@%PDs@OXmGBR5F4BUEN=??br#qazgPS`Y;4m)jz`I(yOxvhzd zwidN%?vwtE?@!#<7s*W;#H88zAK-4%@jqCexhdS>_1?6hJCyXrurW&f>}G78v{v~V zTvjd|?>c}6bqogXZO=N~_%q$DQIp>M@LTQ{Yna&o(XYVu=`y;4_^j3y%!dX^uPU| zwC25vGbqVrR7y(R5;ZZ+Pobl0B#C)+`r_HmV{k>+2bpNLWAINzYmxOR^g?%7KAbUy zg4XaZWAdlBvYbpzOz-%VasFON-foFKc?ua|Lp-LQ1a=(#prgPbLnwx2$mdy3~65PE!P@NBf8h zo-cThrV*Tq@1;hEXHMieen|{bSiG{ofw(i4mvH6K+L2(_1Uv4vd;w)MJ7w?{%Qoyd zDK_l5RRpFx3LS;6!4wy5A(w;e2c5kNN?w~rXWg}zLTi)y0lqS=F>QN?Gp9LH%YbgB zc;1gfB|&@mLkidQ``Itz^tIK*Q?Db=8Ma5<2_3w8na>Yj&804QtwS8Ze0KAGXdzh3 z)lZO@DmCA*KiyV+gOJA0qA41{Dnbt($#Me_iWesgDFN8BWO1pd9JsZ=kh9{;4XR-n z_iAUUy+sr55B^T|n9?u0`L-rQsne#L6cprqH!UFkvkN&VnwRzgRbPHb=1OYN8w)Gp z-J6znda8}slHI1~z3%1l0B!S)qkNlj*#Qp&uru8fCt@i-ueQr2SqBJ-AysQ*64M9s z^Ud$a(#uUuNN`!1L(a3&tdRxt^`2eNG9rL=%p5CcmL0(82H#nha!qCr1Q(X`Hl<%d z;m2_Y`-mxBHoRQPNB<0*%TG;uAs$UeWJY4W@9deDYVpVmo3N8D0vFnbftN}T(A={0 zQs_u1tpz6~p8VPcIwuws`u=jE8J>7=)}Aiosj3!3A_VJj;$GuXkDQl1=(!POusdUZ zt~ko6Ya8{WhbOo+Sscqpj;(DrvT`;Sa>Rt%5SZx==Z+|9#}68}%k5qZOuJ!bNkXme zsmR*b0+|p;eSKHOMNfUv$3_<_@og@rU*#^;;C_MlM1@eR*^CV3O^0$OVfSy@ZRldr zTFlO4!M>L@cPotP5B)Th@^feJnIdS0@a`_4&G!%~9j~R1j@2v!!tI&zfuqRIOYgbbm5!%5bksX)w&-Elqr}C3G`l|#!gOH@CdpXTyirV0$#fh(74})Wu zIF;XNq#v5A?8o+&?o~&Zl?gJlbjCClV;&Fwm|JuctHr3*Iq0>u1;s0wHP;tDX-X|E z1Yl|8!J&yZUl!irEbfDR3-Hf-3!(uaEY$!j-GpCdUMd~J&|Ef(#;xht8m6plM}AFw zf6)R2xBLm~S@X3!J0a9grYzOV8R#JDS>LeFyr)@Pl*d9nDz*Hr@OP+=%L#}e9AcX* zX?rkUmUQ_}wHv7~2tRB=IY)%9CatKO#7UqC{&arJBJe|mh*FHix+e01LDA+=M54BS zX0}gP`tzPXwrDU;NIr=x)#hI7)pA5ck(ILxOd5v8b|C<--Bw=OY~O**GeEPrGDm;J zB_!K5@dDSXmc@!+xmBGJ6h1x7t1jlnz4={zHZdY(CB{H+j>4_GU~1HvL=3bO&{q25 z&;_fEk(Cw6#tV1*F0@m8|Ydu|sZf#M6iIfF{tO7>Ys>Wq2 zuS1uU+A14kvg(A9$Z02zLVuEqX!g|`CgfSPHnnU5e7kl){JbSam_}oyMoMP9Q;EmK zJ;m3ltwnWb?th z{@c$ygNLXK(;Q+PO@ICY!Z+4*AFmEuI2bP1XYDxkGnW@C!Tcn(C}~us^0-nxPDrGS z&|$FYKG^g&pf^|79|hJrQVLEixXjf4EE~n+3+KiJqu6aqkhy^KL@yBg|7JngblB zmQ0)_e))OV;BgyH1)_k_3(UhpC3h~DsUP;AaI@~hF5yTnENIQA{mtB#t6>DEt* z4}2Z{fZ%pde2t`e?xdEHOLnoaBz@|%RbesR&I7*gU!m=0<5X#D(zP5VNZLQ z#B6I_zhywKb-;_r1617STk!{TMrW{y&w()x?_JAgDjm0Mkj@t8_`TjO--2Zj9GGUR z5wl=*B%MIN;UmQYTVL+&237HbOWZ0m^y@!g zeKj>18@pf+wy4CV98mFhX$Sv0y&CS;$GYBCgefdWMNU#mW)J{pSY{tMhC3+Nu6r5L zLK5_r$zY(?d!}H@j2MLcW|L~6uQ9QCO%VXM4h{)`+h$+bj5k~7zx_vG!q2)qp!s+}At{UfPtu(J2NGB`JK6t2F~g-T{5~PF XQ|?tXUHkBk=z6IrYABS+zX|*=nAy5T literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/read_receipt-light.png b/testdata/snapshots/darwin/read_receipt-light.png new file mode 100644 index 0000000000000000000000000000000000000000..75c0c3f4f6b4fd82c4ab71624a4d48eb357b27f0 GIT binary patch literal 4883 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/recipient_input-light.png b/testdata/snapshots/darwin/recipient_input-light.png new file mode 100644 index 0000000000000000000000000000000000000000..27f3076e325a7cf207e3c0078f67e682997301fb GIT binary patch literal 8766 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�ne?;snUesXv$%I%ZEbDz)2A0s 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/snooze_picker-light.png b/testdata/snapshots/darwin/snooze_picker-light.png new file mode 100644 index 0000000000000000000000000000000000000000..5ef2b08f678ebeefff8cb16f4a7460dc94b1f3ce GIT binary patch literal 13738 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 QK76Dkr~bYI@bT+^0JPJ1u>b%7 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/status_setter-light.png b/testdata/snapshots/darwin/status_setter-light.png new file mode 100644 index 0000000000000000000000000000000000000000..99e6fc304d5bec6cd2ac7f087abbcbcc75aeb6f1 GIT binary patch literal 10179 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/thread_panel-dark.png b/testdata/snapshots/darwin/thread_panel-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..fa5a42989dd86ed89c1d34341df7524286848370 GIT binary patch literal 23400 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%0Dg*N%h~2?agFx>{ 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 gLBF9)P#};AansO}UDss(~o6Oh{F&%PW zu^f#i#pDb#%(aic-_Kw0`RVid<@I>IUXRxguk-nO##umbhzLmw@$m47fX%L3@$eid z+}BM74(`jtLqRS)JVFrgbwitA{KB}P#dD-I|MG^gLNw)>FSuSIQoQJNhV4C-HQxkD zzrxpU3G2RJ(TkXcOZ3VBUH2dl;`(QlpHJfv_4pBi%6mmW9vKPonpif(844(f{e24D z!Cw4ptL#t(Iwmk?kNf*6Yc*nWGAD)8%VH*0A>Y=E|7DmmD<`RW0Q3IH=m8L%e<4z~ z>d^m+u|0uk_fYEi($~eCFzEJkT=t=lu&{?nmc<&Mv3U>-3SMa*6z-A!Q_vDO(aFJQ z{DpCYJ4B@CpvFLzG5~NbGj-=+RgT=Ks|*NISG|;^XQmT3C~kC9OC4P*1zgSK{nLe+zirtIQ`2=-v--1{BB!y z!tp!8tJ=D`vKcw4_@feMt>$BsV76$`9tmjKQC!qHmMpLD#~FO#uIl#K1iOiWS>yCT z;ZbqLG&1I*V&|UD<#liEkOEiN?-g@7gH9$fzt7tf<@xH+#TtPY3FbFj9s<$w*F z2kx$ZU*VE{OzKHks^f6QuP19#&1tp9!!-T=_6=gIxe+yNj_%$Fm6CL#YM>#^wt=s& zD8@(~cM!-O%Z**Q-{;u)7O3UZO+J3`hVzG_f0+3XebukX=|%kW1#vXS&EmBa=k`sX zswZOPz@daV*2n%KM{m1;rk(2_x6b8xrM(GV-W1<6GBPtVE9Fm?mlgX3M@cNrlPtC?+lHC=3qU#@?UF00MGGI#?nx~8Q?)Y^Mqvwk#OuB6 z2|*sx+zk|5S)&uOO$8dtYzXyXsrJpehz!8Qw+z{(8Lrb-j&QVLYwZXk3JC)%a@DS) zKDh0tA*k@m-Xw-hShBcqUmhui=jbAR@-7m~j7lyq z)N!7mgcjE8Onl95IeBL%hhm}!0!?4TTH|&S6I{l8fs5sg%$N4jV(AV}RxbWEWPFPU zO>4JA-^H7)8`Wt;8_v!m13vdsjRwyi4R&rCXu^y@<5PBJF2@E3iyP&~Jks>>d8f-Z zc4be8Jlt+qwQJ++M_Xc&h@Iow&RiOcZD6^ev>KJlk00EkpVQQoW3O|9TgyqqmC4=X zZdzHH3Cw}Q6bYkjkZx?KzPW)EOwwe33ZYZPjZD7J&%{onOU;Fn;{~&ehUOo%Nw&t@pw0HOv)ONKIM!kNvaTL^;nF>SOTbs*C=Ktq2oE7y}G4JoFLl-&4gkGJ#3 zUR7MdJF{P!mdMy@lJXs|eC{8Y)zCk*P;7u96A1f@ox1n&8#1D1<^dwg^H8Q z?3>Ltygrh_Ed?uZ*FIIhsI0swZ;)=9`}QJ+#p-4Oy0G;Rz(sar_I~UZkuu`(k^ZmR zftD2wrxbP_dOPRJku!auT8^=>WH-SZ<*Yb0!!)H1Y&z`FYB(&Nh)(eVY_Gvhfs?k@ z1tXW<@cnsiIpk3l{;i3fr7_Xx)(pta)6q2;Rh>mH1Foep(z)E1{B*$!(!xr`x=c{E zDcbXw^;me`1Y1?_ZeSY7ifG7?1JbA!)z0^|?6h>$g|ZdVC#bk0Pr6wS`nZlrKcsk! zRox1*DZeGO>VoxJF&K0nl1aP)=!&nj^B-L(jeM`@ItiXk1=Q;P^hL8Fv#IgqB3JP& zmDi>Ww*#pkw9Amo|-=#3(7qm zefXs51nt%8;L|B7GOhPw87}rJuzmx2K6EH*qaqHaR#!dR27QF8V8G#)X>rBp9PV`` z?O(`qSb0+}K2hm;p|xL0z=o`($*c%pSm_CQKpQSzK40|sn}8q_UV-+8_FpM_V|S^N9;*?Zr2g4jq)sYn3;0BPH6 zmM#Fmo>Jl2T4JxT?q^5(0RWObTg$6%QTdz+ppz@?r}!F%>mZ?VX`du_?W9CvuPS-R ze>WKEZR4$eu8O{lz#R^7yMaCAR=s*eBP?- zTCzs+mAwg?Mkda+$UPstsMJp5aDxFAO|E3FeFlQ25ug7H{UU}MjgI%BCjehd8=4|4oZEvfPSj&$IA>CD=|LfRwR?s(O0WrX#Bxollxyrh zBfzgo;Kk}+b7-A`bx}9TEFh3`cT&GgMqEZMR{h1QQGzd=^gcLv(exEcC&Ir$l{7iF zr%iR7kLD*Wzj>0Eq5{_F(zeTNi7v8SG5(F7aunKSs|f<2t#vmuXcNS$cA6w2OP zVhv;HlJFu0;NLg$%bJ>S**i&EKV%)hsb^l1aE1r8?qHMNN4esI))$NPDa(2aEz_vS z9l3gBqxglhEfD*q^2rTF;2qSfdf1SEpyOE(3{*3oSszuqyO!`Zbn8pF-p+I;)SPM@ z<|)=a_8dLaYv&L zf0E5uKRXqF)L`0g(6?;}i8k+j;@E;Um~!y?UXDlHSlMH8Hx-lQI z(tjaa51LDjqC%-7U5vBcz6u^RB*Efl`z&TOglbl|KgJY#cXkbfuXHGI z&lpH{O`+n_i;xN*-W6PWixF*8!3#Ze}Gg5n@+3} z78$!_5M4`<^oXL?a5QkHZ_+`Y{f15G*uL5`)(OYbuYfoNuA{g}O9Upb_T|XUT9XXF z$P?r|nMgVFZ5NP{%)FA@lfCK#y?y$^RWAwh9~1|5cD?i|tCiS^S>-H3_3d>C|B;QYi+o&(3rg+6WNjG8F1Fo1`o7bQ1uuJTw5O*(@BMj8*95ts zO7jl>zgHfeOV@1IggS3#bxtzeIAGPjLy~m8EoEj2F{#tg5WCG2gF-hVnU#FU~6$(gz2=Ck1Z!viKx9Q ze;gH;+P6_*M$pW(!R=fZA=~h>QRnv!4=XADIePA8E_j4fA82%Cl;g7#6P#A4>qCd) zA$NE`?yR)$h52zAWta)&7)F>mr~goUE6`55l9=!LmN;@@^VswcrQCtxd8+0qsexp< zxHO8M<8cS*x9jt0qPN3})``w4pLWla@+A3qwOx6-)T-ihT(ip7~k_d)`HNY%f>m z=hz3Cnh9NG$Uqd?5S%f4IwHoKp=AnL~+RDBvn;-hu-)|O=C`WJDo)Ww5&2D%KyWJ{h_IM}3SwHP&tbezGD zSmv9&VAc%7y(?3UIVz#VN3 zkd=Hf4l-emgZ$%P-7!2VC$eN>z$k=lY>509`D9uBe=W@X1V-#01`KgBFQ!*TCJIv^ Oz}5<4S!;gd-hTiTg8MuG literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/user_profile_card-dark.png b/testdata/snapshots/darwin/user_profile_card-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..123e131f4ec3675975dfb988695275b2325bed0f GIT binary patch literal 17577 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 literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/user_profile_card-light.png b/testdata/snapshots/darwin/user_profile_card-light.png new file mode 100644 index 0000000000000000000000000000000000000000..1d9aa0341601d13a9f327ebd893ce9e7146931c3 GIT binary patch literal 17152 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%0AE-q@Q1*wJ zGal)#zZeF=hZgmzVD$5R_Us{@&70S2xrHKrE8}`~K1NL}i`_nL)k4e6M~drO2+W^Q zMdgXr_Eo#|ch2L#;YMFOJIt?dVzMmVqKNwkKYq4x+?CQGmOc=8Wh5jZcj{kOllk!a zaGMN8u&GtPuifmCm3$D&x1S&|P5B-~-k3Fc&HXKf)fz5O0zJV6*i?6aMQzpeGJo$R zK3Xk(uEyu75VJTgDRk8RL2$O*-`XV^*L4TL>DFn`2q6qH7vHuj|LP9Tc10N+;0UN3WC?7->A>-?l|1kIcOvD zZ4_rOf+-6B(@;TP-#hWdl}8@?b#c*I$W*qhOIOk7#PW;6D9`09UbOfro6+=K?{LiO z(#$8l@AU9`u?fKqzls%RWdrZf>xE8@@5Om1$q;Z-ArIDH(FLcrJUdEjvp zxb8pyRe}n~3WEeuO3}9AdwX2#>z#f!zah{whvh@vpI^O|AN=52jf&-aefl~A`;%Rh z(}>JJ;Ap>KrX)QrO`RHD9U-+%4B|``R4k5}Usxyabl7+DPTYSC9DB>#1^!~< z>V(zDMEd-u`kO93D-4hBWhc4C+qC-}Pl!jpywt7JbY9f<_RL z#Q8%NRiyv(t8z(|=A6e%T*SuUPLOsgw$~8f&1~Z$VvL#7d!aP|YF4<49X$ym0yt9V zqWf9}E^9;EZ)Do!BYJAcB|z6XA1qt!`>@besl}#bGW_-RRrl8D42U8l;CYqG=KU-M z!2g80z0UnTmDQC6Fne6+BnTjK73AQO~}XqQ@k6W`^W#BxDE=ghj#H&EEW7hU~^e@^8GQ* zD4)aXdwQk^P1W2kBzk4|^8IH`3YOFNy_x>kpI5eJG!$}gyPjEM(YcPrfs?*U8`IC( zQ{A2EYRbNHs~s`DT{=#$f?GHJA7T(&bd?F4)cFjGVZo@;7~XX-mmZ1_hLpu-;WiyQ5bD;I;8>VQ<@0atLn<~+%FL3X;M+{4&+e~z1~9tlB2g9Royxd7j(J(c<0&c-F{^Dt zz6k|hkK24b#A7+yd~@HLvu}R&sQn-lJ=eAv3Bvwq(zI_7ms-$fE{6BewrAWE?fF_QrlENq3$PpD4Se4m0C7D|&SFCvxq;8z}a z2mxkF6{7&{jc4)l1wsf=i)kXbSEeEX$VTFM!te1DCySlwKcgp{a~|JwO>v?8Yg)Bg zlcoOM9ABWhU3qWi_vY2RmWBVF9{=wWuYRciF^_8y1N_{~-!|vIU5Q Mh^%mxpuYeA0wl>A^#A|> literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/video_call_grid-dark.png b/testdata/snapshots/darwin/video_call_grid-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..e4c418f03a6e7e7927936dd7f3c36f146f8be2de GIT binary patch literal 12871 zcmeHubx>SQurCgQB@hB(aY%3iEbb88g1fs17Iz7@1a}B-!7V^=cZVzl_u%esm*h*n z`~G=#t6tTUTlK1@=Iq(&bEc<%zwWcAdp1~JRvaA_9~A}$23=A@L=grC4h04VRv88E z>6;O5B?=fA=I4?kg37L`d-HN~F9m_U$7asXQ}p!GS$8xP6CV@v7Ri~2!;jHj&vqJ* zM6aHEK5Kzr@(ot=e+CU*(Jvr{ZLef8N?@kM{2EwE@6*!C^_7Q!Vfa1&?GXSScXL+= zg)HC-;Qja?6EZL!rHtWIPkt|nnnrZg<| ze@F8e5S5KZo$Dl@R5w+kmiTIHxU_kA-|O*6B#ddHvy7=H_|zdF?6qua_4TdG-rd)!2Yb?MYm z5m5u7IH>uCrNi%?Uxq@m^wljU-D!CxG%5JD^PkbsO2sL1E3A_dl$V$w@Q!xvxkvYg>;(S=o(+orr) zk;n0$yv_)tHDFsR`8j#Pe_)*U(AuL9U{l5)`8FUIS0JUnPcJ0Yhhth0lI4O#qbk{= zA({n8i(M}CfK?gmwg`8HYjA|1Vn|03dwtKlc!s!^oJz?Iw*B5z(=I z>qI2#?FS%qxMN8xB+-L~2f=hYeKfegZ}`OP;qWto=}H23Grh$tZPM%>0gv^Tq@_=R zSipzkWJC`Bmu#H@$Y;pMMsjJo484;xBv$G43-|#i-_t$u>THYYyHRHEyGUPRcs?X| zz!{L?yU~BC<&yv>E~IsDK?Y1PLEL-HvRbivY}`|}KOLWMk-C)^qPfsmmr{&og^AKd zpx+L`g+!^pX8&~ZEmH!!aHmWZPNgW5RWy*@dT+>ej|-zu=DDS`^h*xs)U8_qf>EE; zq&~&le(=T>AlSF-ogpbx6i@;{j)VpOfAZAU6U*NPr8kp$=d+spMGCaApi=$#Ua?}$ zEq(PB;nWKupmmt4;(!9b6tcf=gG2cxX+M(Z_gK&GZ7_hR=I~s24LQxd_?61wdZkgo zNN)7NmriYrfJrd|vaZj_Q%>40S@P7#3RS9l;iIM+7hh|=%yusqNh^@y|Dg$F6(HO= z`6*=|ghFI=Mx8jvBgTIVZ89SM#w_$KI*RjEbXQ9 z)r0yQq@!EkVoGf)ZdS_caxSQ&(zS;V>k(7(HO6iiy;n17pdD99D&tNZS6Ox6?bvab z*NkcwG3m5O6*Cc@k@g$w2%I>tTdcJH<0790fDNT1noU1xVlT0Beh4(5uR|1Q4=K`_ zt&XK?Co2AxqxvOh&*N-Q6N~3{`i>HwDsgZhNDxtu{%c9Lh6bN@OLcIRlV=v+O6AU! zp=&E~=S{`^itj7N9r9?|HfA$ktmQv0Ox0HVOB9`W2CGRc`Ti)usR*20jnB3S zxU_pSARt6=x{U2%2jwG@{u4KjcUNC858 zgfl%&al{cFq+xe$?0+6=29zMjozjI(y6InI>k&+8?x7PZ8anZRIgu$3@1LAo9k$+&JdR}4@*S^i;<{9I99*r< zNoVLj94t)f`kXI4&fG_1FnF7WRoq^(g(*k87~aAL4G93|jh2bwFM+ase2{`l&ST>* z1hqcZjJ>NP_Z}DPy6cMGp4%znjNOT9WrWIs&EKO23o6ZP{~Bumr0n^aX}410e(ZC0 z&pNygOxI1GUThzbP&vLgJNyf!a8Q==TNw}ZFz;kkvX~DY6raNsa}E1#{sIzbaKt-m zZe5$FxC1?=YK&lg5G>^z{d+ZD`*Iy(*7@EDhoA-D1H~U7Hc$m|ilroScf}2wuhvB@ z!2JmfG@Whwgps4Ihxr*Vk#srXd7Y_7WqD`j;)a##|cp{Rvfs=e%sxGDuly> z$_XO<1h-R=`@FbQ5i_n@rI+S(nRyie=ZE$>`=_!Xedb5BPZBTM6Jox9k*PZ0Sfq4G z+EkRSsKz0XnqzG}yr#OGALrdZCBI&q_ZU5d1HizyVUB^0c;ygK{c{^o1>#Z^%6l;w zDcEU4UiY6md$hG)KZ{wrmQ}_e)Q17WAbrdV?OZ;+MWJo8@*Yu932yz2Y<#gTj3pC^ zZ?eP-By*fJ?ItRHE~voY${5v(@aqcLrwidewhvY!5Rn4B(;4|aQNURu{&oWe&>hfv zAiYSm@yK@r|8b97w}%{mpiCOZK_MrVf-=+zm8=F@Wi{*kogy1>sUS&st!CPO zhR@_1{*{KcH8d@Ab+L>G3yaMUDt^@Dct&qn@t8+58bd{@*XRy#Vdg)(!`L=@&P7ohM);mYZr9hX~O3zIpIFDu?DF5 z%{x*Vh_d{h{brok0IH0YwbMg^>$gkdSv{055b*Nah|(yGKMTD^kq$?9dAiv@OWKF? zPch*Q3sQD&7@PdUJk;qr|JFft6zZh+Xa3k+9mA2T0VytDma_RgPf0P;v8&!{;rAB z=`KB**8ZT)qjOEV2{#2%0Rqmv}nw{ZEOYj%DL{lLXZ0JZc%_Ap+`f zsV{}h(t)vdtNj0}EBvIcPHBaT`f!Y&joB|5#qT((Rd}l35c@-(!tE0mg%FXhQ7KY# z7a`6(c_LO5=d^J%Z|g9yjD0mF<>{VTQaGh)N)G1@nI4~dN(oiIRvctWB}Y*^bEFT- zq}D7xc~dx~{oEmtG>z`Ji7~N2KS-1ecj|t09n4CU_Dw$1CR!Xf%~F<9EHzd?q;cR% zRYU1HMg5INz$?J{W;Vv7>)y>5t1u{22uM?ZSHx#--aAS8dz_|jx2i?CADxo_!GQ8V zy5d40=jiN-eBE)t7sP@me(IYqy}X;MCdfLm?c4d2?OD>9i}6$|5T|JWSsV-!9^}Re z%0`?hNfK)g5;cFbwkzf34c&aazw~-zE=9Q_L}87w%9K(nk4*Dvhx89Ztbtislj#!{ zk;+ytvyIN9x#Jm9qoTGpDRiR{1hGWPLt?0xzJ-%M6Ny2P#KNYC&CH~Lvm@O6rlw)} zL0*zaoz?>WAE>pFAdp**x?zDgEMrAKAbkZAGIe65&y{F#SY@K(-opvSP)laFoqDD% zZJGdUYinlrKk_&tbrW&J{u3xP(S?PLIA68wHeR^!y|wj6wE5bG{;Ez#dl?B`69)aC z81xH8{B~QF=M?b{=`1BFIBqm37!)s1EF>C&xGNiJ;VuOmlo14%5p`p@SLb3$QIfN1 zLUu&TpP2$cM&_}2op_V`=(0GNLRdm!eHjJ@+oraR3wPm;nmB8<8RW-sO9`VWPY#lX zfTRkzadF1I!p*Gy!Ci_fczp8Y5@hdy4Q;ph{K-eqz2!*CCm(ZU0%i)Ll{s5$-?gO| zx}xP$kS}C7X=w^!9sCnBb@YLtv&SQ0lrR1{QxLF+VS8VgH%eBD;`libEvOd+O_Qx-k)6Bx09GPOe6nW-HTx`&(2>EgVT=(mB37Cy5Wl zlsbT-W5NY^6J(XkX1K4dpA(q!voq&p=wbG};*Cub@LApTpak@H32R2{a_9D-J@-C{6iRIjxj zdVa#(;rlvD*U0`VG2z4F?c|o7%g+`2H#GJJD`Vl^bJ>R32X&WaGox?YJl0I5!frQ_ zQ_{6-5y)8AD=bnjnyw#QGD_TY+c3?VIN>zSYw6uiKXXT%UvI335hOtm+xlOEz3LD1 zete^MD^0PJy&13TU>o%2T754ob+s4k5}K|Tjyd3QmzATp&*!qy7j$UdTw`_`tN(;1 z3Jy>iKVB-w#<^B1N7W*EWX9)aMLaJ-<7{4O{KWKZXX$pW;w29USR94^tu}3l;mXg6 zO}e+Is*E2vtKY?R&Byx?@zWODLM?+9USvhGCNp@g_IBZ?FDR2Ac|t=rt9m1o_&1}= zFG;*DhHrMq%Jr_txOq{r#<;Ys8=K`GFI%}B_dd)(k|Ld0fG#B08;>3)%G_zLeTPzU zx+Emv4y`_8W*eW?rKSwMxK`$z%W&yeBa2nF#?Ubp$>3wU1ooSKI0~jraxpcAVCV-< z#$LA+#-%|Ad+lE|Na&@3 zm%j=I)AT!)+|^<*y7GFx>xmsVBjG!v_l^jKnzIF#H!qi-k0ixt?Op(gqTSAxYe(rd zLNV>Rv5N7aQ+v&u4Uu~5X)?+ZxX>#QqehS7|NMv#Q&?(|e%J7_+^MkyT z$;2pCO8xqW_a$VMlk!bQwY}?tC{DXc_H}E^fqYwM!Aka{Y&1{L7u)5v;8w3A8=DIq z)x_~Hv5Wy){3|UStKcu~1{?mg@`Id})Tt?5SPdx3oad)3%#f z%k^~}S5iVLKVeBSH)=^tgvmio`uJM`hITLW$6g9mX^LGF#H?*=#9MUYsM-(DMHLu= zPMfD(KFk~?ixqG4ks5Uj^*?bdgYzz(ijps+cVIu>4}G@p=nhvk%6QyoVBOZ{?zUBI zk&oM~(o?bGWd8bU4Z#gr$PSlSIeB!oA}VU6s?qtqr}uvPVdU$8#T)yjhO{~HOCtH! zmMqCsS=>Q;FP1SooaPCvq#c$AYdQbZ0ZeE5zxF z5kpf)6p=Ja#!R6_$R;%ie(M)ZdFLCFJRJf>l9ZZ>gF}SNMU&49eVZUOr*U9-00;^& z=yB#w+kU@!do45OFHzu+)>`1}?!0+utsI-N|jj!y~CR!~t~x@T%l-80f;WQsZFPE)saS9jhF>%l4b>*%&*)(Wx1^*k$*A`^iaGyMEsG zey3xe%c^C5YST8gezvk|ZFt?o`OfnoS~`v)QQ70{s;E|qo4a9WG(F??N9;A@kjGtP zOXKYUB(g>}CAqq#@@}slEnTF2+wsBWqNKwQkdQE6*f$spB*e zh8A%oT0ViZ&9v^Fv!w2dr;tQqX_fu@?2}f)OUljKm9Ef}>~W`j6ta*K*GhCz)#qvx z#+yUh+6`-65dotdt!Jlux%D#OI^+$Pl)ED^U)6sYRf*=&`T!0QOU- z;%e7^_$e)!=PJ}U`O{>iP{<*i> zd3%FQ`b*pyzO`=|2krGIX(xK#ckYK}^k}FFLp}#H@V5fHhqW24t~3-g9goZ~uTjX} zu%&^KhjuBgWo9ZvkO$G6RZ3hQ$yI90kA?jLnUhUrT2^xgu)>Iq^xa?;>6Q&B)WKmb8eg{H|klaP(~(4k8h6g=S@Z!?=K zVwkoRgFYbkW!h{}(Q8C8RKh%LbuSPaxjcXiQ2!Oc^~vDKP=0=N=x`sZ`ldL$QT|y0 z#}?{doSTyq>f$OKmW*KpJqk~~cOXQ_;&Nfyv7abdScvtq)hklMFeSYVp zOo}ZHsW9g3l7>)7+Dpc$?%li>c5;%jUXWZ|MK>CH2Z(t~Q<+^LK@`Ou!040-m;1g- zC~gr*r0k@E0O$KItR)ku57f^h)PDl_56=JVhpq;opH4j0AoD9s16YMF2GUAY$lF(m z5X8^Injg8iIH>ZMlltqqnqUE8Yk3RJFjYkj8|DlBg7+0DXr>Wz%X6@A1}n$c<4iOt zid;xwvP39~RQH5b3YKfx6IDQWqfxB7U@V#(&0ukLG8j5cp|>xYnJe?vDUFYiKp;&# zK-!3*xP8)*bpJ7;S*4ZqQW%S|)vO^m++F-}rMpODwo20thPq=oSbXp+n$Cd1?Mt z$s7hjQq0|QC>Zvm1QJF-4}6yRo$q( z`qQVU(O+NuZ$2y;UWGP$Y=@`J!-H%_7gnc}hS>0_hRH3*&epz(Tjo}A?o(|&e8Q3N zgrD?;b(Zi%z(iB72;xIiCzTfr9J9Aj&|;HGk)=$+^SINEifwBCk~{3gEI7K9a=iQ9 zIG!YOe;OOU`yG=!;Qy&ZXG#c}5kE+r$ELmT=B2k?$rfk*2Zq@G>B4VmmGpySQdSg! znEtNccQ1LG!^P967QTWXl>TItuaMi9d2Fh*8Lw9Zh1w?*LIPhYUS_MG)8~F0OE96} z{i5hh8!wlSR;EWEZ|1LL0IcD$x>O@^zR@|2{F_RYgk&icAxuCv-D@T-F+;1->A!GY zb&&H?7t&j39B=rUn2ptIJ69@NDevwsoO?tjB+f++C;ln~{mKkW`e*Hh*W&wbx+g>x z&8hic1$H(9>AzqrUUVok?5>A~vgG?)u3nrpPn@%zQvA(j3+bz;CKt!kS>&#Z$#r+U zJ#_d%s_M@fKYS%?XW?vMa(*1%*qY-1M;tT@iqrPt|7@3*y(4Z1Oj;KP;-KM#I+6)! z6uOCCPB!!G+w>ByIjh*Ht^dv%;n4oRc#(DRuMSe6Z#%==V*0&8 zjzMRM$k}tXMobGRUttNJT13ZF0Sgl#Sl^QCw-;z?4SeIVl7OD7^fMJ}GmbOgaceW~ zqrv0TB3dU>Wvv(0EGHox{lg_fHOb=?Qyf-*tx^ISLT1qzB%a0llE?wwH>3C9|ICE; zchnQ~R(7~vR>85;=xT8^d<#;hq@9|~^6xkyD6aWfvp)L<8olWMEk#DU@J69jo5o|+ z6#Y*o9r9eb_yxJo9HE%_Lz;6%KS+vh!4kprZ*3ZaCY+;utSxsTE)-}@a1*`h9V{nkf=Q?o4 zqq9Iz8%W}S_WUq(!wcHPn0zTpvgQSC`-%)KdI%^jZS@e|j0pZIm_NreXPK+SQ}yBa z$Iz&YO-i$I%28A9j7C*0AKm`Npm&q$x2T$$qKBuq>wlK;45^i~<~Ai-b#_0Jzjd}m zdCBKC&6B|_A$EVP-hoHI?yGH&=X^R32C?VSHkBex)z@N$ila~?(?~0Tw$U;^{1mXR z$F^$<7!px6sO{RY;B&Wivo8>1rp9~8F^2nUgtNYBM!IHjbCjxeGQ()OeP>5kWjX|s zz1nmG{G$XRH=zE54asPmIhcHk-1}-@txDg7B`GvC)O6HRMpkxW$3=~pUqg?>s-MyA z)BqzVcgVz{obz`j?ukU=u)VH+TuxbSbK$mZ|YKPLD+%1b#X{}WyE?UhVanO#3<)(() z;lmXBF`oUY`gQuXPg)9?xz^N_mp_{GQ_elI=dAqfz@y4|JlGi4bw!aonv|NOncHIm zICN|mZOLQ(VLvn1*Qx0}c|an2*EE8-0~Sy4@QkcyOUlSd z>xx`zZ(bD+37wA@n69 zY#u^QijU;7u9>4!!4x`3V^WfcPZ!OG_Mj1KViQ@Mv0h@(&6KF#97?n-$YQWy(jBc7 z7+fO*I#C9cndZ0(?^z;ymjNI%*pW2TvZDBH7RS3TjwdC3t`EpO2t12$ zT{(CbSZ3^aM7u5)X?A~MeYR(LzY{*SO~$3{b0U8)>CWz0L77E2Ej#)@Xmw-;a3|Q8 zPw4@1B(biIl}LUE=CS<{ga4NivTc|V{V%vWlErnbtR_E%^hMjg&x8HP{7;!!Dt!r@ zLPV5NlLlT3_1q=E=rs?Vn%?i6>o0`tVIc3+K(EC)L$C3t#3WL?38UZmmXV_WTRh=H zfG6uBIHJ;kyc9L5rHu&&= z>mT;dk%ao{rHQ#-ty4rJiHS9l4^(W`OQ*vs{Hx}rK4}2!wb!%k;~0~7tU*61r2Wig zyfdQpo*oSUq|E_%03G}3x!LR!LNg-YCf}+M+EF(xt%fyF_`fxjH>gNn+m;2T6w6Zx z{JkHROR_1C=wVw)aI6c=g+&QyXDiFh;elZY{w+dP7z!CguohjoASMDH zCGn%R@HLpg9IRy}q(GS%kM>+LdR5cDj(y6QGa|7I0ovqEVvo3n+J_TG2TXseZa{p= z`0~gvyXY2hVuTfq`1)Njnhig5LWeYm?BC9=T^i`Zo}zwMYishWc&cysAL~nuijv%} zDNl6GX(I;u1jKG^+g4qWDSm}A^ zlr)tXOS$sdluTTfS5{bO5HDWbgg1*HNmM=*7z*PM6itT}8NvhYks*#cj?`m1Ki@jy z#!pi;wv>J2$hx4kFO1nYUtNC`zXVKY-^Z-hDcwxE zt*;U$h~2W{>7UJvShFdyWh5>8zvLB(sIaMw*RC1kbyNZdnF)Kp+|*bCf_qnW+Ak*M z3AinCV%dLn&KGIlU?B>ykcWGMjt8_ZIdZ7tTAz!$wQ6X$F*_RX=vTr{<^W8Y30Ag3 zYALyF4%)$$t@Q|7D(9`P=V{YfFL@kI>xHS>KvM1B!Cb_hjl_rUO}ocsB!w<~sPp!k z%SfFd&rrPotaKoKG*E}c#PolOQD&7PcquFi=sY4EwVS7IpmOEh4;AOFuzjy$fBlg; zKwZN-q+5Y()&hVB&kQ+^V+tdq-EwG6&LhWp)B1vV;i9VpII0Yb)mt1D zoKz_I{4-0)XRM`F>8qqv@wdi*>GJv9DTmaREq?BL$OW9D|4>< zstlVv-(ohOgT3>}(kwG13Cye6#9HwD5fJ@d6oZ-X>AUgh^4SiRm|?BsJ{RIhbDKj8Dp^!*SoL5+5x@q;MhI}F0M;Tf{BkC??r+q>}eA#Wn@ z%kK?=k=h?Fpzktt-3+D<^%jNy#4Ov=Ff!{{(h~10!TV2`3fLsN^{KjKK@Zm#Ats?p zL2DDu)k}|yH(;hkV>ukD%EbndTv1bRAm)wxgMo3~HxsdCrJi7bo{pxPxM(WweCI7`SLOk{{D znPf2&kklc2xsc1=C?oLNSV+=Nu;ug~<9VygvcK)x35!;Sz>=rID#Yn@bJ*>qkiPuz z_B2+Gm%rRJVZzcWG5(~m^<;=Lwz1@gVa2EHEe5*MvLa8@-BXcq=cyLgiuJK^t@Jea zxwY`f@;3o-@iMj>Tw6qf-$@4sM^ozcYYv+(U0OYJH_F`P_%6>{_{#TvP8szyuG=;( zO_PTxrveOP`;A`>cjr>5uoSr*7Vs&!{5Wu|lhQupAvOQ_(7V{&Bc^a}N0>1;&JcKl zVyLBTZjQo=FCo>0Sp)@^V}J6?gnfh0BpCeZ3XUxK3NB1Uw}3htPD)y^hEi2g^J^ZG z5u3bV5k-wQ9DQOU!!lYX-&5ECn`}bxlcMvNpG2hW(Ia)?aB9Gl&vx^)J zZAEDGuGwl{HX1HZ%iD)NW21eZ;siP=uogk}w;DvXBzIm0HMQFF<@LeD1;ePQzU}K= zp;70?RnLO`b5|ao)X7AZcC1ykRnDnblkmTOtxoxpU1b@hH0$5wfZytPo+vvE%OQ)@ zVn@Mg{LH!h^nxSUMiK|+Nt00@+n#U8sO&Zjx<`Ad^;Kq&i;BLXA(Yz}Av@su)Wjy@ z!!F7CY~f@O&826tFyV_BZ9H?JbNr!GBcDThvVyYVVZE?|(s&Y;8K2#wmr^2wo7>*! zIUycwCr%y~7I4zTRVNJ%&BcC7%YyY|M&5ooA2tetr?-#NsfA>Wu7?veuBpFR_3g`Y z5sB8EUH63t;Zs}zy`!O$W0&{pM*|%}ro8rF^Hjrry_X9E^g%M?vk`M=*PcAmgLmGK zvK|@*y&%8HJ|CZjo05{S%CS<$X3o~!>S2(7n#YCe6v_4KX-8z9O!IE%d0#!x-=nu3O=BHMi=tB%ikpGEWRoWzpaXG{Vhe&|*`V!W~0SY>Na zJdNyyLv3eqZ`tOlO`KtGk%aX}47tOmHPpFX<#A;l4k3@UynKvPH?IfcL>DC`B{rGx z2Ra0;A{kamKNIuW?_bm9>7_zF8wI-qO=*69B%c|Bgbe`K%`J8>T%;cz6&-2nxU^W2 zJ?u|TPd4}yVl!~vKJRGBG_mNhzNFN26~Cj!MB(Ilv#0u4iyA{-udS2qM$w|*1xp6) z-n~e*=6(}F&Ol*D6D%#s)D$OzLPoCew7)UR5!5GnUHr7Q>L)!6e*g%J{~Gh{M=5IUD^5A)dmbpeVemf(UJ{;>?LB zfs>LF{HX}XPNZ*Hs)n9#E`cEeg=|H^@M<>TsnQR6qAJH*0Ojc7=FIJ}_eD$Du9pDb zueW+b40wiRp;VoyhFDA_(HO-Vwv9AjI?(kLEY9Gt6_Ml@Y!xR; zPMdzEOlLcOgeG74Xa()=h_XauP4G14S%zRu(8(*a=2A;B*5YTd^5OzoIbR!RI-E@h z4-8n^#j(~F7ZoMH&fS98;OF7#GfG~>5Y{!5<8WPFdCN?=*E2OxEDJ2VY!nDrD$jvL zm5e0~wwa_OjhfEXr_OD3z}8NLWyR$sC1uz3?Ay+26akp_tD*+anUPm{k^gK^`Zs61Z3f_@!fEV6`5%hfW1^)l`f5!r343JQRy@`q^IAA`4e0E33 r#h5@JVFCIu@W3`0r2olBfG|AF-bIl(Z!gP_UspHGZ$O^ZC- literal 0 HcmV?d00001 diff --git a/testdata/snapshots/darwin/video_call_grid-light.png b/testdata/snapshots/darwin/video_call_grid-light.png new file mode 100644 index 0000000000000000000000000000000000000000..bfa23da71ef37553696f6090bda6b6f2dd16bf3b GIT binary patch literal 13164 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 By%hie literal 0 HcmV?d00001 diff --git a/thread_panel.go b/thread_panel.go new file mode 100644 index 0000000..2752af3 --- /dev/null +++ b/thread_panel.go @@ -0,0 +1,101 @@ +package mujica + +import ( + "fmt" + "log/slog" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// ThreadPanelOptions configure a ThreadPanel. +type ThreadPanelOptions struct { + // Width is the panel's width; zero means 360. + Width float32 + Disabled bool +} + +// ThreadPanelResult is the panel's element and this frame's events. +type ThreadPanelResult struct { + Element *ui.Element + // Sent is a reply the user sent; empty is none. + Sent string +} + +type threadState struct { + list MessageListState + draft string +} + +type threadKey struct{} + +// ThreadPanel displays a root message, replies and an editor. +func ThreadPanel(c *ui.Context, open *bool, root ChatEntry, replies []ChatEntry, opts ThreadPanelOptions) ThreadPanelResult { + var r ThreadPanelResult + if opts.Width < 0 { + panic("mujica: ThreadPanel Width must not be negative") + } + w := opts.Width + if w == 0 { + w = 360 + } + ww, _ := c.Size() + w = min(w, ww) + k := Tokens(c) + u := Density(c).Unit() + panel := ui.Column(c).Width(w).FillHeight().Shrink(0).Background(k.Surface).BorderWidth(0, 0, 0, 1). + BorderColor(k.Border).Role(ui.RoleGroup).Label(msg(c, "thread_panel.title")).Disabled(opts.Disabled) + if panel.IsDisabled() { + *open = false + } + if !*open { + panel.Invisible() + return r + } + overlayStyle(c, panel, overlayEnter(c, panel)) + panel.BorderWidth(0, 0, 0, 1).BorderColor(k.Border) + r.Element = panel + st := ui.Local(panel, threadKey{}, func() *threadState { return &threadState{} }) + s := *st + panel.Children(func() { + ui.Row(c).Padding(u*3, u*3, u*2, u*4).AlignItems(ui.Center).Children(func() { + ui.Text(c, msg(c, "thread_panel.title")).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).FontWeight(600).Grow(1) + if iconAction(c, msgClose, msg(c, "thread_panel.close")).Clicked() { + *open = false + } + }) + ui.Scroll(c).MaxHeight(160).Shrink(1).Padding(0, u*2).Children(func() { ChatMessage(c, root, ChatMessageOptions{}) }) + ui.Row(c).Gap(u*2).Padding(u*2, u*4).AlignItems(ui.Center).Children(func() { + ui.Text(c, fmt.Sprintf(msg(c, "thread_panel.replies"), len(replies))).FontSize(FontSize(c, theme.CaptionSize)). + TextColor(k.TextMuted).SingleLine() + ui.Box(c).Height(1).Grow(1).Background(k.Border) + }) + MessageList(c, &s.list, len(replies), MessageListOptions{ + ID: func(i int) string { return replies[i].ID }, + Label: func(i int) string { return replies[i].Author + ": " + replies[i].Text }, + }, func(i int) { + ChatMessage(c, replies[i], ChatMessageOptions{Continued: i > 0 && ChatContinues(replies[i-1], replies[i])}) + }) + ui.Row(c).Gap(u*2).Padding(u*3).AlignItems(ui.Center).BorderWidth(1, 0, 0, 0).BorderColor(k.Border).Children(func() { + in := TextInput(c, &s.draft, TextInputOptions{Placeholder: msg(c, "thread_panel.reply"), Label: msg(c, "thread_panel.reply"), Disabled: opts.Disabled}) + in.Element.Grow(1) + send := IconButton(c, msgSend, msg(c, "thread_panel.send"), IconButtonOptions{Disabled: strings.TrimSpace(s.draft) == ""}) + if (in.Submitted() || send.Clicked()) && strings.TrimSpace(s.draft) != "" && !panel.IsDisabled() { + r.Sent, s.draft = strings.TrimSpace(s.draft), "" + s.list.ScrollToEnd() + } + }) + }) + if !panel.IsDisabled() && panel.Shortcut(0, ui.KeyEscape) { + *open = false + } + switch { + case r.Sent != "": + slog.Debug("mujica: thread_panel send", "len", len(r.Sent)) + case !*open: + slog.Debug("mujica: thread_panel close") + } + return r +} diff --git a/thread_panel_test.go b/thread_panel_test.go new file mode 100644 index 0000000..9a2174e --- /dev/null +++ b/thread_panel_test.go @@ -0,0 +1,77 @@ +package mujica + +import ( + "testing" + "time" + + "github.com/egoist/mygo/ui" +) + +func TestThreadPanelReplyAndClose(t *testing.T) { + at := time.Date(2026, 10, 5, 20, 0, 0, 0, time.UTC) + root := ChatEntry{ID: "r", Author: "Sakiko", Time: at, Text: "Set list for Friday?"} + replies := []ChatEntry{{ID: "1", Author: "Uika", Time: at.Add(time.Minute), Text: "Overture first."}} + open := true + var sent []string + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Row(c).Fill().Children(func() { + ui.Box(c).Grow(1) + if r := ThreadPanel(c, &open, root, replies, ThreadPanelOptions{}); r.Sent != "" { + sent = append(sent, r.Sent) + } + }) + }, 600, 600) + if !tt.HasText("Set list for Friday?") || !tt.HasText("1 replies") || !tt.HasText("Overture first.") { + t.Fatalf("texts %v", tt.Texts()) + } + if err := tt.Click("Reply in thread"); err != nil { + t.Fatal(err) + } + tt.Type("Then the masquerade.") + tt.Key(0, ui.KeyEnter) + if len(sent) != 1 || sent[0] != "Then the masquerade." { + t.Fatalf("sent %q", sent) + } + tt.Key(0, ui.KeyEscape) + if open { + t.Fatal("Escape did not close") + } +} + +func TestThreadPanelSnapshot(t *testing.T) { + at := time.Date(2026, 10, 5, 20, 0, 0, 0, time.UTC) + open := true + root := ChatEntry{ID: "r", Author: "Sakiko", Time: at, Text: "Set list for Friday?"} + replies := []ChatEntry{{ID: "1", Author: "Uika", Time: at.Add(time.Minute), Text: "Overture first."}, + {ID: "2", Author: "Uika", Time: at.Add(2 * time.Minute), Text: "Then the masquerade."}} + snapshot(t, "thread_panel", 400, 560, func(c *ui.Context) { + ui.Row(c).Fill().Children(func() { ThreadPanel(c, &open, root, replies, ThreadPanelOptions{}) }) + }) +} + +func TestThreadPanelFitsWindowAndDisabled(t *testing.T) { + open, disabled := true, false + root := ChatEntry{ID: "root", Author: "Author", Text: "Question"} + sent := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Row(c).Fill().Children(func() { + if ThreadPanel(c, &open, root, nil, ThreadPanelOptions{Disabled: disabled}).Sent != "" { + sent++ + } + }) + }, 280, 400) + r, ok := tt.Find("Thread") + if !ok || r.X < 0 || r.X+r.W > 280 { + t.Fatalf("thread bounds %+v", r) + } + disabled = true + tt.Frame() + _ = tt.Click("Reply in thread") + tt.Type("Blocked") + tt.Key(0, ui.KeyEnter) + if open || sent != 0 { + t.Fatal("disabled thread stayed open or sent") + } +} diff --git a/unread_divider.go b/unread_divider.go new file mode 100644 index 0000000..6bca759 --- /dev/null +++ b/unread_divider.go @@ -0,0 +1,31 @@ +package mujica + +import ( + "fmt" + + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// UnreadDivider marks where unread messages begin; count zero shows "New". +func UnreadDivider(c *ui.Context, count int) *ui.Element { + if count < 0 { + panic("mujica: UnreadDivider count must not be negative") + } + k := Tokens(c) + u := Density(c).Unit() + text := msg(c, "unread_divider.new") + if count > 0 { + text = fmt.Sprintf(msg(c, "unread_divider.count"), count) + } + row := ui.Row(c).FillWidth().Gap(u * 2).AlignItems(ui.Center).MinHeight(theme.MinHitSize).Role(ui.RoleStatus).Label(text) + row.Children(func() { + line := func() { ui.Box(c).Height(1).Grow(1).Background(k.Danger) } + line() + ui.Text(c, text).FontSize(FontSize(c, theme.CaptionSize)).FontWeight(600).TextColor(k.Danger).SingleLine(). + Padding(0, u*2).Radius(theme.ControlRadius).Border(theme.BorderWidth, k.Danger) + line() + }) + return row +} diff --git a/unread_divider_test.go b/unread_divider_test.go new file mode 100644 index 0000000..a18ff7f --- /dev/null +++ b/unread_divider_test.go @@ -0,0 +1,27 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestUnreadDivider(t *testing.T) { + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Children(func() { + UnreadDivider(c, 12) + UnreadDivider(c, 0) + }) + }, 400, 120) + if !tt.HasText("12 new messages") || !tt.HasText("New") { + t.Fatalf("texts %v", tt.Texts()) + } + mediaPanics(t, "negative", func(c *ui.Context) { UnreadDivider(c, -1) }) +} + +func TestUnreadDividerSnapshot(t *testing.T) { + snapshot(t, "unread_divider", 420, 70, func(c *ui.Context) { + ui.Column(c).Padding(20).Children(func() { UnreadDivider(c, 3) }) + }) +} diff --git a/user_profile_card.go b/user_profile_card.go new file mode 100644 index 0000000..1457cbe --- /dev/null +++ b/user_profile_card.go @@ -0,0 +1,77 @@ +package mujica + +import ( + "github.com/egoist/mygo/ui" + + "mujicaui/theme" +) + +// UserProfile is the person a UserProfileCard shows. +type UserProfile struct { + // Name is required. + Name string + Image *ui.Bitmap + Presence Presence + // Status is a custom status line, as "In a rehearsal". + Status string + // Role, as "Admin"; empty shows none. + Role string + // About is a short description. + About string +} + +// UserProfileCardOptions configure a UserProfileCard. +type UserProfileCardOptions struct { + // Actions builds buttons at the bottom, as Message or Call. + Actions func() + // Width is the card's width; zero means 300. + Width float32 +} + +// UserProfileCard displays identity, presence, role and action slots. +func UserProfileCard(c *ui.Context, prof UserProfile, opts UserProfileCardOptions) *ui.Element { + if prof.Name == "" { + panic("mujica: UserProfileCard needs a Name") + } + if opts.Width < 0 { + panic("mujica: UserProfileCard Width must not be negative") + } + w := opts.Width + if w == 0 { + w = 300 + } + k := Tokens(c) + u := Density(c).Unit() + card := ui.Column(c).Width(w).Padding(u*4).Gap(u*3).Radius(theme.CardRadius).Background(k.Surface). + Border(theme.BorderWidth, k.Border).Role(ui.RoleGroup).Label(msg(c, "user_profile_card.label") + ": " + prof.Name) + card.Children(func() { + ui.Row(c).Gap(u * 3).AlignItems(ui.Center).Children(func() { + ui.Box(c).Shrink(0).Children(func() { + Avatar(c, prof.Name, AvatarOptions{Image: prof.Image, Size: 56}) + ui.Box(c).Absolute().Right(-1).Bottom(-1).Padding(2).Radius(8).Background(k.Surface).Children(func() { + OnlineStatus(c, prof.Presence, OnlineStatusOptions{HideText: true, Size: 12}) + }) + }) + ui.Column(c).Gap(u).MinWidth(0).Grow(1).Children(func() { + ui.Text(c, prof.Name).Font(theme.SerifFont).FontSize(FontSize(c, theme.H3Size)).FontWeight(600).SingleLine() + ui.Row(c).Gap(u * 2).AlignItems(ui.Center).Wrap().Children(func() { + OnlineStatus(c, prof.Presence, OnlineStatusOptions{}) + if prof.Role != "" { + Badge(c, BadgeOptions{Text: prof.Role, Tone: BadgeNeutral}, nil) + } + }) + }) + }) + if prof.Status != "" { + ui.Text(c, prof.Status).MaxLines(2) + } + if prof.About != "" { + ui.Text(c, prof.About).TextColor(k.TextMuted).FontSize(FontSize(c, theme.CaptionSize)).MaxLines(4) + } + if opts.Actions != nil { + ui.Box(c).Height(1).Background(k.Border) + ui.Row(c).Gap(u * 2).Wrap().Children(opts.Actions) + } + }) + return card +} diff --git a/user_profile_card_test.go b/user_profile_card_test.go new file mode 100644 index 0000000..5741866 --- /dev/null +++ b/user_profile_card_test.go @@ -0,0 +1,43 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestUserProfileCard(t *testing.T) { + clicked := 0 + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + UserProfileCard(c, UserProfile{Name: "Sakiko Togawa", Presence: PresenceBusy, Role: "Keyboard", Status: "In rehearsal"}, + UserProfileCardOptions{Actions: func() { + if Button(c, "Message", ButtonOptions{}).Clicked() { + clicked++ + } + }}) + }, 400, 300) + for _, s := range []string{"Sakiko Togawa", "Busy", "Keyboard", "In rehearsal"} { + if !tt.HasText(s) { + t.Fatalf("no %q in %v", s, tt.Texts()) + } + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyEnter) + if clicked != 1 { + t.Fatal("action slot not reachable by keyboard") + } + mediaPanics(t, "no name", func(c *ui.Context) { UserProfileCard(c, UserProfile{}, UserProfileCardOptions{}) }) +} + +func TestUserProfileCardSnapshot(t *testing.T) { + snapshot(t, "user_profile_card", 360, 260, func(c *ui.Context) { + ui.Column(c).Padding(20).Children(func() { + UserProfileCard(c, UserProfile{Name: "Sakiko Togawa", Presence: PresenceOnline, Role: "Keyboard", Status: "Composing the second act", + About: "Founder of the masquerade."}, UserProfileCardOptions{Actions: func() { + Button(c, "Message", ButtonOptions{}) + Button(c, "Call", ButtonOptions{Variant: Secondary}) + }}) + }) + }) +} diff --git a/video_call_grid.go b/video_call_grid.go new file mode 100644 index 0000000..4acd2c9 --- /dev/null +++ b/video_call_grid.go @@ -0,0 +1,107 @@ +package mujica + +import ( + "math" + "strings" + + "github.com/egoist/mygo/ui" + + "mujicaui/internal" + "mujicaui/theme" +) + +// CallParticipant supplies identity, frames and call state. +type CallParticipant struct { + ID, Name string + // Frame is their video; nil shows their avatar. + Frame ui.ImageSource + Image *ui.Bitmap + Muted bool + CameraOff bool + Speaking bool +} + +// VideoCallGridOptions configure a VideoCallGrid. +type VideoCallGridOptions struct { + // Columns fixes the column count; zero fits a near-square grid. + Columns int +} + +// VideoCallGrid displays participant frames and speaker marks. +func VideoCallGrid(c *ui.Context, people []CallParticipant, opts VideoCallGridOptions) *ui.Element { + if opts.Columns < 0 { + panic("mujica: VideoCallGrid Columns must not be negative") + } + seen := map[string]bool{} + for _, p := range people { + if p.ID == "" || p.Name == "" || seen[p.ID] { + panic("mujica: VideoCallGrid participants need unique IDs and names: " + p.ID) + } + seen[p.ID] = true + } + cols := opts.Columns + if cols == 0 { + cols = max(1, int(math.Ceil(math.Sqrt(float64(len(people)))))) + } + k := Tokens(c) + u := Density(c).Unit() + tracks := make([]ui.Track, cols) + for i := range tracks { + tracks[i] = ui.Fr(1) + } + grid := ui.Box(c).Grid().ColumnTracks(tracks...).Gap(u * 2).FocusGroup(ui.Horizontal | ui.Vertical). + Role(ui.RoleGroup).Label(msg(c, "video_call_grid.label")) + grid.Children(func() { + for _, p := range people { + callTile(c, k, p) + } + }) + return grid +} + +func callTile(c *ui.Context, k theme.Tokens, p CallParticipant) { + u := Density(c).Unit() + var notes []string + if p.Speaking { + notes = append(notes, msg(c, "video_call_grid.speaking")) + } + if p.Muted { + notes = append(notes, msg(c, "video_call_grid.muted")) + } + if p.CameraOff { + notes = append(notes, msg(c, "video_call_grid.cameraOff")) + } + label := p.Name + if len(notes) > 0 { + label += ", " + strings.Join(notes, ", ") + } + tile := ui.Box(c).Key(p.ID).AspectRatio(16.0 / 9).Radius(theme.CardRadius).Clip().Background(videoBlack).Center(). + Focusable().Role(ui.RoleImage).Label(label) + internal.Ring(tile, k.Focus, theme.CardRadius) + light := ui.Hex("#F2EBDD") + tile.Children(func() { + if p.Frame != nil && !p.CameraOff { + ui.Image(c, p.Frame).Fit(ui.Cover).Absolute().Left(0).Top(0).Right(0).Bottom(0) + } else { + Avatar(c, p.Name, AvatarOptions{Image: p.Image, Size: 56}) + } + ui.Row(c).Absolute().Left(u*2).Bottom(u*2).Gap(u).AlignItems(ui.Center).Padding(2, u*1.5). + Radius(theme.ControlRadius).Background(ui.RGBA(0, 0, 0, 0.6)).TextColor(light).Children(func() { + if p.Muted { + ui.Icon(c, msgMicOff).Size(13, 13).TextColor(ui.Hex("#F0A1AA")) + } + if p.Speaking { + ui.Icon(c, msgSpeaking).Size(13, 13) + } + ui.Text(c, p.Name).FontSize(FontSize(c, theme.CaptionSize)).SingleLine() + }) + }) + if p.Speaking { + tile.DrawOver(func(pt *ui.Painter, r ui.Rect) { + pt.Stroke(ui.Rect{X: r.X + 1.5, Y: r.Y + 1.5, W: r.W - 3, H: r.H - 3}, k.AccentText, theme.CardRadius, 3) + if tile.FocusVisible() { + internal.FocusRing(pt, r, theme.CardRadius, k.Focus) + } + }) + } +} diff --git a/video_call_grid_test.go b/video_call_grid_test.go new file mode 100644 index 0000000..0bb961e --- /dev/null +++ b/video_call_grid_test.go @@ -0,0 +1,43 @@ +package mujica + +import ( + "testing" + + "github.com/egoist/mygo/ui" +) + +func TestVideoCallGridTilesAndSpeaker(t *testing.T) { + people := []CallParticipant{{ID: "1", Name: "Sakiko", Speaking: true}, {ID: "2", Name: "Uika", Muted: true, Frame: mediaTestBitmap(32, 18)}, + {ID: "3", Name: "Mutsumi", CameraOff: true}, {ID: "4", Name: "Umiri"}, {ID: "5", Name: "Nyamu"}} + var rects []ui.Rect + tt := ui.NewTester(func(c *ui.Context) { + Use(c, Settings{}) + ui.Column(c).Width(600).Children(func() { VideoCallGrid(c, people, VideoCallGridOptions{}) }) + }, 700, 600) + for _, name := range []string{"Sakiko, speaking", "Uika, muted", "Mutsumi, camera off", "Umiri", "Nyamu"} { + r, ok := tt.Find(name) + if !ok { + t.Fatalf("no tile %q in %v", name, tt.Texts()) + } + rects = append(rects, r) + } + if rects[3].Y <= rects[0].Y || rects[1].Y != rects[0].Y || rects[2].Y != rects[0].Y { + t.Fatalf("tiles %v", rects) + } + tt.Key(0, ui.KeyTab) + tt.Key(0, ui.KeyRight) + if !tt.Focused("Uika, muted") { + t.Fatal("arrows do not move between tiles") + } + mediaPanics(t, "duplicate", func(c *ui.Context) { + VideoCallGrid(c, []CallParticipant{{ID: "a", Name: "A"}, {ID: "a", Name: "B"}}, VideoCallGridOptions{}) + }) +} + +func TestVideoCallGridSnapshot(t *testing.T) { + people := []CallParticipant{{ID: "1", Name: "Sakiko", Speaking: true, Frame: mediaTestBitmap(160, 90)}, {ID: "2", Name: "Uika", Muted: true}, + {ID: "3", Name: "Mutsumi", CameraOff: true}, {ID: "4", Name: "Umiri", Frame: mediaTestBitmap(90, 160)}} + snapshot(t, "video_call_grid", 520, 340, func(c *ui.Context) { + ui.Column(c).Padding(20).Width(480).Children(func() { VideoCallGrid(c, people, VideoCallGridOptions{}) }) + }) +}