196 lines
6.5 KiB
Go
196 lines
6.5 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/egoist/mygo/ui"
|
|
mujica "mujicaui"
|
|
"mujicaui/theme"
|
|
)
|
|
|
|
var filesPeople = []mujica.Collaborator{
|
|
{ID: "a", Name: "Ada Lovelace"}, {ID: "b", Name: "Blaise Pascal", Away: true},
|
|
{ID: "c", Name: "Carl Gauss"}, {ID: "d", Name: "Dora Maar"}, {ID: "e", Name: "Emmy Noether"},
|
|
}
|
|
|
|
func presenceAvatarsDemo(c *ui.Context, log func(string)) {
|
|
type state struct {
|
|
following string
|
|
disabled, empty bool
|
|
max float64
|
|
}
|
|
s := ui.Local(c.Root(), "392", func() state { return state{max: 3} })
|
|
mediaCheck(c, log, &s.disabled, "Disabled")
|
|
mediaCheck(c, log, &s.empty, "Empty")
|
|
if mujica.NumberInput(c, &s.max, mujica.NumberInputOptions{Min: 1, Max: 5, Step: 1, Label: "Visible avatars"}).Changed() {
|
|
log(fmt.Sprintf("Visible: %.0f", s.max))
|
|
}
|
|
people := filesPeople
|
|
if s.empty {
|
|
people = nil
|
|
}
|
|
r := mujica.PresenceAvatars(c, people, mujica.PresenceAvatarsOptions{Following: s.following, Max: int(s.max), Disabled: s.disabled})
|
|
if r.Follow != "" {
|
|
s.following = r.Follow
|
|
log("Follow: " + r.Follow)
|
|
}
|
|
if r.Unfollow {
|
|
s.following = ""
|
|
log("Following stopped")
|
|
}
|
|
}
|
|
|
|
var filesReactionChoices = []string{"\U0001f44d", "\u2764\ufe0f", "\U0001f389", "\U0001f440", "\U0001f64f"}
|
|
|
|
func reactionsDemo(c *ui.Context, log func(string)) {
|
|
type state struct {
|
|
items []mujica.Reaction
|
|
disabled bool
|
|
}
|
|
s := ui.Local(c.Root(), "394", func() state {
|
|
return state{items: []mujica.Reaction{{Emoji: filesReactionChoices[0], Count: 3, Mine: true}, {Emoji: filesReactionChoices[2], Count: 1}}}
|
|
})
|
|
mediaCheck(c, log, &s.disabled, "Disabled")
|
|
if mujica.Button(c, "Clear reactions", mujica.ButtonOptions{}).Clicked() {
|
|
s.items = nil
|
|
log("Reactions cleared")
|
|
}
|
|
r := mujica.Reactions(c, s.items, mujica.ReactionsOptions{Choices: filesReactionChoices, Disabled: s.disabled})
|
|
emoji := r.Toggled
|
|
if emoji == "" {
|
|
emoji = r.Added
|
|
}
|
|
if emoji == "" {
|
|
return
|
|
}
|
|
for i := range s.items {
|
|
if s.items[i].Emoji == emoji {
|
|
if s.items[i].Mine {
|
|
s.items[i].Mine = false
|
|
s.items[i].Count--
|
|
} else {
|
|
s.items[i].Mine = true
|
|
s.items[i].Count++
|
|
}
|
|
if s.items[i].Count == 0 {
|
|
s.items = append(s.items[:i:i], s.items[i+1:]...)
|
|
}
|
|
log("Reaction toggled")
|
|
return
|
|
}
|
|
}
|
|
s.items = append(s.items, mujica.Reaction{Emoji: emoji, Count: 1, Mine: true})
|
|
log("Reaction added")
|
|
}
|
|
|
|
func shareDialogDemo(c *ui.Context, log func(string)) {
|
|
type state struct {
|
|
members []mujica.ShareMember
|
|
open, disabled bool
|
|
next int
|
|
}
|
|
s := ui.Local(c.Root(), "395", func() state {
|
|
return state{members: []mujica.ShareMember{
|
|
{ID: "owner", Name: "Ada Lovelace", Email: "ada@court.org", Owner: true, Permission: mujica.PermissionEdit},
|
|
{ID: "b", Name: "Blaise Pascal", Email: "blaise@court.org", Permission: mujica.PermissionView},
|
|
}}
|
|
})
|
|
mediaCheck(c, log, &s.disabled, "Disabled")
|
|
if mujica.Button(c, "Share Ledger", mujica.ButtonOptions{Disabled: s.disabled}).Clicked() {
|
|
s.open = true
|
|
log("Share dialog opened")
|
|
}
|
|
was := s.open
|
|
r := mujica.ShareDialog(c, &s.open, &s.members, mujica.ShareDialogOptions{Title: "Ledger", Link: "https://court.org/ledger", Disabled: s.disabled, OnCopy: func(link string) { c.WriteClipboard(link); log("Copy callback") }})
|
|
if r.Invited != nil {
|
|
s.next++
|
|
s.members = append(s.members, mujica.ShareMember{ID: fmt.Sprintf("invite-%d", s.next), Name: r.Invited.Email, Email: r.Invited.Email, Permission: r.Invited.Permission})
|
|
log("Member invited")
|
|
}
|
|
if r.Changed != "" {
|
|
log("Permission changed: " + r.Changed)
|
|
}
|
|
if r.Removed != "" {
|
|
log("Member removed: " + r.Removed)
|
|
}
|
|
if r.Copied {
|
|
log("Link copied")
|
|
}
|
|
if was && !s.open {
|
|
log("Share dialog closed")
|
|
}
|
|
}
|
|
|
|
func permissionSelectDemo(c *ui.Context, log func(string)) {
|
|
type state struct {
|
|
value mujica.Permission
|
|
disabled bool
|
|
}
|
|
s := ui.Local(c.Root(), "396", func() state { return state{} })
|
|
mediaCheck(c, log, &s.disabled, "Disabled")
|
|
if mujica.PermissionSelect(c, &s.value, mujica.PermissionSelectOptions{Disabled: s.disabled}).Changed() {
|
|
log(fmt.Sprintf("Permission: %d", s.value))
|
|
}
|
|
}
|
|
|
|
func liveIndicatorDemo(c *ui.Context, log func(string)) {
|
|
type state struct {
|
|
status mujica.LiveStatus
|
|
showTime bool
|
|
}
|
|
s := ui.Local(c.Root(), "399", func() state { return state{showTime: true} })
|
|
if mujica.Select(c, &s.status, []mujica.SelectOption[mujica.LiveStatus]{{Value: mujica.LiveSynced, Label: "Synced"}, {Value: mujica.LiveSyncing, Label: "Syncing"}, {Value: mujica.LiveReconnecting, Label: "Reconnecting"}, {Value: mujica.LiveOffline, Label: "Offline"}, {Value: mujica.LiveError, Label: "Error"}}, mujica.SelectOptions{Label: "Sync status"}).Changed() {
|
|
log(fmt.Sprintf("Sync status: %d", s.status))
|
|
}
|
|
mediaCheck(c, log, &s.showTime, "Last sync time")
|
|
now := time.Date(2026, 10, 5, 12, 0, 0, 0, time.UTC)
|
|
opts := mujica.LiveIndicatorOptions{Error: "Server unavailable", Now: now}
|
|
if s.showTime {
|
|
opts.LastSynced = now.Add(-3 * time.Minute)
|
|
}
|
|
if mujica.LiveIndicator(c, s.status, opts).Changed() {
|
|
s.status = mujica.LiveReconnecting
|
|
log("Sync retried")
|
|
}
|
|
}
|
|
|
|
func remoteCursorDemo(c *ui.Context, log func(string)) {
|
|
type state struct {
|
|
offset float64
|
|
selection, second bool
|
|
}
|
|
s := ui.Local(c.Root(), "400", func() state { return state{offset: 48, selection: true, second: true} })
|
|
if mujica.NumberInput(c, &s.offset, mujica.NumberInputOptions{Min: 0, Max: 79, Step: 1, Label: "Remote text offset"}).Changed() {
|
|
log(fmt.Sprintf("Offset: %.0f", s.offset))
|
|
}
|
|
mediaCheck(c, log, &s.selection, "Selection")
|
|
mediaCheck(c, log, &s.second, "Second collaborator")
|
|
carets := []mujica.RemoteCaret{{ID: "ada", Name: "Ada", Offset: int(s.offset), Anchor: int(s.offset)}}
|
|
if s.selection {
|
|
carets[0].Anchor = max(0, carets[0].Offset-5)
|
|
}
|
|
if s.second {
|
|
carets = append(carets, mujica.RemoteCaret{ID: "blaise", Name: "Blaise", Offset: 8, Anchor: 8})
|
|
}
|
|
ui.Box(c).Height(140).FillWidth().Background(mujica.Tokens(c).Surface).Children(func() {
|
|
ui.Column(c).Children(func() {
|
|
for _, line := range []string{"The seal of the court is kept", "by the chancellor, who answers"} {
|
|
ui.Text(c, line).Font(theme.MonoFont).FontSize(mujica.FontSize(c, 13)).Height(20)
|
|
}
|
|
})
|
|
at := func(o int) (float32, float32) { return float32(o%40) * 8, float32(o/40) * 20 }
|
|
mujica.RemoteCursor(c, carets, mujica.RemoteCursorOptions{
|
|
Caret: func(o int) ui.Rect { x, y := at(o); return ui.Rect{X: x, Y: y, H: 20} },
|
|
Selection: func(from, to int) []ui.Rect {
|
|
var out []ui.Rect
|
|
for o := from; o < to; o++ {
|
|
x, y := at(o)
|
|
out = append(out, ui.Rect{X: x, Y: y, W: 8, H: 20})
|
|
}
|
|
return out
|
|
},
|
|
})
|
|
})
|
|
}
|