Files
MujicaUI/examples/gallery/pages_messaging_chat.go
T

142 lines
5.1 KiB
Go

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")
}
}