mirror of
https://github.com/diamondburned/cchat-gtk.git
synced 2025-01-08 19:46:44 +00:00
Improvements on popovers and mentions
This commit is contained in:
parent
4c22615301
commit
fdede5fc13
6
go.mod
6
go.mod
|
@ -4,13 +4,11 @@ go 1.14
|
|||
|
||||
replace github.com/gotk3/gotk3 => github.com/diamondburned/gotk3 v0.0.0-20200630065217-97aeb06d705d
|
||||
|
||||
replace github.com/diamondburned/cchat-discord => ../cchat-discord/
|
||||
|
||||
require (
|
||||
github.com/Xuanwo/go-locale v0.2.0
|
||||
github.com/alecthomas/chroma v0.7.3
|
||||
github.com/diamondburned/cchat v0.0.45
|
||||
github.com/diamondburned/cchat-discord v0.0.0-20200718071554-360b34de2a71
|
||||
github.com/diamondburned/cchat v0.0.46
|
||||
github.com/diamondburned/cchat-discord v0.0.0-20200730000036-2c93cdc1974e
|
||||
github.com/diamondburned/cchat-mock v0.0.0-20200709231652-ad222ce5a74b
|
||||
github.com/diamondburned/imgutil v0.0.0-20200710174014-8a3be144a972
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
|
|
6
go.sum
6
go.sum
|
@ -50,6 +50,12 @@ github.com/diamondburned/cchat v0.0.43 h1:HetAujSaUSdnQgAUZgprNLARjf/MSWXpCfWdvX
|
|||
github.com/diamondburned/cchat v0.0.43/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU=
|
||||
github.com/diamondburned/cchat v0.0.45 h1:HMVSKx1h6lh2OenWaBTvMSK531hWaXAW7I0tKZepYug=
|
||||
github.com/diamondburned/cchat v0.0.45/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU=
|
||||
github.com/diamondburned/cchat v0.0.46 h1:fzm2XA9uGasX0uaic1AFfUMGA53PlO+GGmkYbx49A5k=
|
||||
github.com/diamondburned/cchat v0.0.46/go.mod h1:+zXktogE45A0om4fT6B/z6Ii7FXNafjxsNspI0rlhbU=
|
||||
github.com/diamondburned/cchat-discord v0.0.0-20200719175346-af912db55401 h1:llmx/8UiJoTcHUw+GE5/rESVVmmnLh1HEPx3wRj+oQY=
|
||||
github.com/diamondburned/cchat-discord v0.0.0-20200719175346-af912db55401/go.mod h1:+hSrIVYj5tIPLAorDsHj2Tbt2fWlZtOanzfEUHX53HM=
|
||||
github.com/diamondburned/cchat-discord v0.0.0-20200730000036-2c93cdc1974e h1:EA5Vg0x57qLURJP80XhABBW+X0sbQSh2gw5qvPbZTs4=
|
||||
github.com/diamondburned/cchat-discord v0.0.0-20200730000036-2c93cdc1974e/go.mod h1:+hSrIVYj5tIPLAorDsHj2Tbt2fWlZtOanzfEUHX53HM=
|
||||
github.com/diamondburned/cchat-mock v0.0.0-20200709231652-ad222ce5a74b h1:sq0MXjJc3yAOZvuolRxOpKQNvpMLyTmsECxQqdYgF5E=
|
||||
github.com/diamondburned/cchat-mock v0.0.0-20200709231652-ad222ce5a74b/go.mod h1:+bAf0m2o5qH54DmYJ/lR1HeITV53ol0JaoKyFFx3m3E=
|
||||
github.com/diamondburned/gotk3 v0.0.0-20200630065217-97aeb06d705d h1:Ha/I6PMKi+B4hpWclwlXj0tUMehR7Q0TNxPczzBwzPI=
|
||||
|
|
|
@ -67,7 +67,7 @@ func WrapFullMessage(gc *message.GenericContainer) *FullMessage {
|
|||
avatar.SetMarginStart(container.ColumnSpacing * 2)
|
||||
avatar.Connect("clicked", func() {
|
||||
if output := gc.Username.Output(); len(output.Mentions) > 0 {
|
||||
labeluri.PopoverMentioner(avatar, output.Mentions[0])
|
||||
labeluri.PopoverMentioner(avatar, output.Input, output.Mentions[0])
|
||||
}
|
||||
})
|
||||
// We don't call avatar.Show(). That's called in Attach.
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/diamondburned/cchat-gtk/internal/ui/dialog"
|
||||
"github.com/diamondburned/cchat-gtk/internal/ui/primitives"
|
||||
"github.com/diamondburned/cchat-gtk/internal/ui/primitives/roundimage"
|
||||
"github.com/diamondburned/cchat-gtk/internal/ui/primitives/scrollinput"
|
||||
"github.com/diamondburned/cchat-gtk/internal/ui/rich"
|
||||
"github.com/diamondburned/cchat-gtk/internal/ui/rich/parser/markup"
|
||||
"github.com/diamondburned/cchat/text"
|
||||
|
@ -23,8 +24,10 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
MaxWidth = 350
|
||||
MaxHeight = 350
|
||||
AvatarSize = 96
|
||||
PopoverWidth = 250
|
||||
MaxWidth = 350
|
||||
MaxHeight = 350
|
||||
)
|
||||
|
||||
type WidgetConnector interface {
|
||||
|
@ -88,7 +91,7 @@ func BindRichLabel(label Labeler) {
|
|||
var output = label.Output()
|
||||
|
||||
if mention := output.IsMention(uri); mention != nil {
|
||||
if p := popoverMentioner(label, mention); p != nil {
|
||||
if p := popoverMentioner(label, output.Input, mention); p != nil {
|
||||
p.SetPointingTo(ptr)
|
||||
p.Popup()
|
||||
}
|
||||
|
@ -100,32 +103,117 @@ func BindRichLabel(label Labeler) {
|
|||
})
|
||||
}
|
||||
|
||||
func PopoverMentioner(rel gtk.IWidget, mention text.Mentioner) {
|
||||
if p := popoverMentioner(rel, mention); p != nil {
|
||||
func PopoverMentioner(rel gtk.IWidget, input string, mention text.Mentioner) {
|
||||
if p := popoverMentioner(rel, input, mention); p != nil {
|
||||
p.Popup()
|
||||
}
|
||||
}
|
||||
|
||||
func popoverMentioner(rel gtk.IWidget, mention text.Mentioner) *gtk.Popover {
|
||||
func popoverMentioner(rel gtk.IWidget, input string, mention text.Mentioner) *gtk.Popover {
|
||||
var info = mention.MentionInfo()
|
||||
if info.Empty() {
|
||||
return nil
|
||||
}
|
||||
|
||||
start, end := mention.Bounds()
|
||||
h := input[start:end]
|
||||
|
||||
box, _ := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
|
||||
box.Show()
|
||||
|
||||
// Do we have an image or an avatar?
|
||||
var url string
|
||||
var round bool
|
||||
|
||||
switch v := mention.(type) {
|
||||
case text.MentionerImage:
|
||||
url = v.Image()
|
||||
case text.MentionerAvatar:
|
||||
url = v.Avatar()
|
||||
round = true
|
||||
}
|
||||
|
||||
if url != "" {
|
||||
box.PackStart(popoverImg(url, round), false, false, 8)
|
||||
}
|
||||
|
||||
head, _ := gtk.LabelNew(largeText(h))
|
||||
head.SetUseMarkup(true)
|
||||
head.SetLineWrap(true)
|
||||
head.SetLineWrapMode(pango.WRAP_WORD_CHAR)
|
||||
head.SetMarginStart(8)
|
||||
head.SetMarginEnd(8)
|
||||
head.Show()
|
||||
box.PackStart(head, false, false, 0)
|
||||
|
||||
// Left-align the label if we don't have an image.
|
||||
if url == "" {
|
||||
head.SetXAlign(0)
|
||||
}
|
||||
|
||||
l, _ := gtk.LabelNew(markup.Render(info))
|
||||
l.SetUseMarkup(true)
|
||||
l.SetLineWrapMode(pango.WRAP_WORD_CHAR)
|
||||
l.SetLineWrap(true)
|
||||
l.SetXAlign(0)
|
||||
l.SetMarginStart(8)
|
||||
l.SetMarginEnd(8)
|
||||
l.SetMarginTop(8)
|
||||
l.SetMarginBottom(8)
|
||||
l.Show()
|
||||
|
||||
// Enable images???
|
||||
BindActivator(l)
|
||||
|
||||
// Make a scrolling text.
|
||||
scr := scrollinput.NewVScroll(PopoverWidth)
|
||||
scr.Show()
|
||||
scr.Add(l)
|
||||
box.PackStart(scr, false, false, 0)
|
||||
|
||||
p, _ := gtk.PopoverNew(rel)
|
||||
p.Add(l)
|
||||
p.Connect("destroy", l.Destroy)
|
||||
p.Add(box)
|
||||
p.SetSizeRequest(PopoverWidth, -1)
|
||||
p.Connect("destroy", box.Destroy)
|
||||
return p
|
||||
}
|
||||
|
||||
func largeText(text string) string {
|
||||
return fmt.Sprintf(
|
||||
`<span insert-hyphens="false" size="large">%s</span>`, html.EscapeString(text),
|
||||
)
|
||||
}
|
||||
|
||||
// popoverImg creates a new button with an image for it, which is used for the
|
||||
// avatar in the user popover.
|
||||
func popoverImg(url string, round bool) gtk.IWidget {
|
||||
var img *gtk.Image
|
||||
var btn *gtk.Button
|
||||
|
||||
if round {
|
||||
b, _ := roundimage.NewButton()
|
||||
img = b.Image.Image
|
||||
btn = b.Button
|
||||
} else {
|
||||
img, _ = gtk.ImageNew()
|
||||
btn, _ = gtk.ButtonNew()
|
||||
btn.Add(img)
|
||||
}
|
||||
|
||||
img.SetSizeRequest(AvatarSize, AvatarSize)
|
||||
img.SetHAlign(gtk.ALIGN_CENTER)
|
||||
img.Show()
|
||||
|
||||
httputil.AsyncImageSized(img, url, AvatarSize, AvatarSize)
|
||||
|
||||
btn.SetHAlign(gtk.ALIGN_CENTER)
|
||||
btn.SetRelief(gtk.RELIEF_NONE)
|
||||
btn.Connect("clicked", func() { PromptOpen(url) })
|
||||
btn.Show()
|
||||
|
||||
return btn
|
||||
}
|
||||
|
||||
func BindActivator(connector WidgetConnector) {
|
||||
bind(connector, nil)
|
||||
}
|
||||
|
|
|
@ -24,11 +24,12 @@ func hyphenate(text string) string {
|
|||
// RenderOutput is the output of a render.
|
||||
type RenderOutput struct {
|
||||
Markup string
|
||||
Input string // useless to keep parts, as Go will keep all alive anyway
|
||||
Mentions []text.Mentioner
|
||||
}
|
||||
|
||||
// f_Mention is used to print and parse mention URIs.
|
||||
const f_Mention = "cchat://mention:%d" // %d == Mentions[i]
|
||||
const f_Mention = "cchat://mention/%d" // %d == Mentions[i]
|
||||
|
||||
// IsMention returns the mention if the URI is correct, or nil if none.
|
||||
func (r RenderOutput) IsMention(uri string) text.Mentioner {
|
||||
|
@ -65,6 +66,7 @@ func RenderCmplxWithConfig(content text.Rich, cfg RenderConfig) RenderOutput {
|
|||
if len(content.Segments) == 0 {
|
||||
return RenderOutput{
|
||||
Markup: hyphenate(html.EscapeString(content.Content)),
|
||||
Input: content.Content,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +122,7 @@ func RenderCmplxWithConfig(content text.Rich, cfg RenderConfig) RenderOutput {
|
|||
if segment, ok := segment.(text.Mentioner); ok {
|
||||
// Render the mention into "cchat://mention:0" or such. Other
|
||||
// components will take care of showing the information.
|
||||
if cfg.NoMentionLinks {
|
||||
if !cfg.NoMentionLinks {
|
||||
appended.AnchorNU(start, end, fmt.Sprintf(f_Mention, len(mentions)))
|
||||
}
|
||||
|
||||
|
@ -168,6 +170,7 @@ func RenderCmplxWithConfig(content text.Rich, cfg RenderConfig) RenderOutput {
|
|||
|
||||
return RenderOutput{
|
||||
Markup: hyphenate(buf.String()),
|
||||
Input: content.Content,
|
||||
Mentions: mentions,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue