183 lines
6.2 KiB
Go
183 lines
6.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/egoist/mygo/ui"
|
|
|
|
"github.com/ZacharyZhang-NY/MujicaUI/data"
|
|
"github.com/ZacharyZhang-NY/MujicaUI/input"
|
|
"github.com/ZacharyZhang-NY/MujicaUI/messaging"
|
|
)
|
|
|
|
func mailListDemo(c *ui.Context, log func(string)) {
|
|
type state struct {
|
|
list data.ListState[string]
|
|
mails []messaging.MailItem
|
|
disabled, empty bool
|
|
opened string
|
|
}
|
|
s := ui.Local(c.Root(), "415", func() state {
|
|
return state{mails: []messaging.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 input.Button(c, "Load 100,000 mails", input.ButtonOptions{Variant: input.Secondary}).Clicked() {
|
|
s.mails = make([]messaging.MailItem, 100000)
|
|
for i := range s.mails {
|
|
s.mails[i] = messaging.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 := messaging.MailList(c, &s.list, mails, messaging.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 := messaging.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 = messaging.MailMarkdown
|
|
m.Body = "**Rehearsal** at nine. [Venue](https://example.com)\n\n<script>alert(1)</script>"
|
|
}
|
|
if s.attachments {
|
|
m.Attachments = []messaging.MailAttachment{{Name: "score.pdf", Size: 2048}}
|
|
}
|
|
ui.Column(c).Disabled(s.disabled).Children(func() {
|
|
r := messaging.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 messaging.MailDraft
|
|
disabled bool
|
|
saved string
|
|
}
|
|
s := ui.Local(c.Root(), "417", func() state { return state{draft: messaging.MailDraft{To: []string{"uika@example.com"}}} })
|
|
mediaCheck(c, log, &s.disabled, "Disabled")
|
|
r := messaging.MailComposer(c, &s.draft, messaging.MailComposerOptions{
|
|
Disabled: s.disabled, Contacts: messagingContacts,
|
|
OnSaveDraft: func(d messaging.MailDraft) { s.saved = d.Subject; log("draft saved") },
|
|
OnAttach: func() {
|
|
s.draft.Attachments = append(s.draft.Attachments, messaging.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 = messaging.MailDraft{}
|
|
}
|
|
if r.Discarded {
|
|
log("draft discarded")
|
|
s.draft = messaging.MailDraft{}
|
|
}
|
|
ui.Text(c, "Saved subject: "+s.saved)
|
|
}
|
|
|
|
var messagingContacts = []messaging.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 messaging.RecipientInput(c, &s.to, messaging.RecipientInputOptions{Contacts: contacts, Label: "Recipients", Disabled: s.disabled}).Changed() {
|
|
log(fmt.Sprintf("recipients %d", len(s.to)))
|
|
}
|
|
if input.Button(c, "Clear recipients", input.ButtonOptions{Variant: input.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 input.TextArea(c, &s.text, input.TextAreaOptions{Label: "Quoted source", MinHeight: 80}).Changed() {
|
|
log("quote source edited")
|
|
}
|
|
ui.Column(c).Disabled(s.disabled).Children(func() {
|
|
if messaging.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 input.NumberInput(c, &s.morning, input.NumberInputOptions{Min: 1, Max: 23, Step: 1, Label: "Morning hour"}).Changed() {
|
|
log(fmt.Sprintf("morning %.0f", s.morning))
|
|
}
|
|
if messaging.SnoozePicker(c, &s.until, messaging.SnoozePickerOptions{Disabled: s.disabled, MorningHour: int(s.morning)}).Changed() {
|
|
log("snooze " + s.until.Format(time.RFC3339))
|
|
}
|
|
if input.Button(c, "Clear snooze", input.ButtonOptions{Variant: input.Secondary, Disabled: s.disabled}).Clicked() {
|
|
s.until = time.Time{}
|
|
log("snooze cleared")
|
|
}
|
|
ui.Text(c, fmt.Sprint("Until: ", s.until))
|
|
}
|