parent
98fe235f22
commit
97491eb6c0
@ -58,6 +58,7 @@ type UserPreferences struct {
|
|||||||
DisableDownloads bool `yaml:"disable_downloads"`
|
DisableDownloads bool `yaml:"disable_downloads"`
|
||||||
DisableNotifications bool `yaml:"disable_notifications"`
|
DisableNotifications bool `yaml:"disable_notifications"`
|
||||||
DisableShowURLs bool `yaml:"disable_show_urls"`
|
DisableShowURLs bool `yaml:"disable_show_urls"`
|
||||||
|
InlineURLs bool `yaml:"inline_urls"`
|
||||||
AltEnterToSend bool `yaml:"alt_enter_to_send"`
|
AltEnterToSend bool `yaml:"alt_enter_to_send"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
go.mod
4
go.mod
@ -17,8 +17,8 @@ require (
|
|||||||
github.com/zyedidia/clipboard v1.0.3
|
github.com/zyedidia/clipboard v1.0.3
|
||||||
go.etcd.io/bbolt v1.3.6
|
go.etcd.io/bbolt v1.3.6
|
||||||
go.mau.fi/cbind v0.0.0-20220415094356-e1d579b7925e
|
go.mau.fi/cbind v0.0.0-20220415094356-e1d579b7925e
|
||||||
go.mau.fi/mauview v0.1.4-0.20220415181713-aa8cd644bf1d
|
go.mau.fi/mauview v0.1.4-0.20220415185926-d3913ee0f2b4
|
||||||
go.mau.fi/tcell v0.0.0-20220415093808-07c67d224693
|
go.mau.fi/tcell v0.0.0-20220415185117-592f364693a2
|
||||||
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9
|
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9
|
||||||
golang.org/x/net v0.0.0-20220412020605-290c469a71a5
|
golang.org/x/net v0.0.0-20220412020605-290c469a71a5
|
||||||
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2
|
gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2
|
||||||
|
7
go.sum
7
go.sum
@ -56,10 +56,11 @@ go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
|||||||
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||||
go.mau.fi/cbind v0.0.0-20220415094356-e1d579b7925e h1:zY4TZmHAaUhrMFJQfh02dqxDYSfnnXlw/qRoFanxZTw=
|
go.mau.fi/cbind v0.0.0-20220415094356-e1d579b7925e h1:zY4TZmHAaUhrMFJQfh02dqxDYSfnnXlw/qRoFanxZTw=
|
||||||
go.mau.fi/cbind v0.0.0-20220415094356-e1d579b7925e/go.mod h1:9nnzlslhUo/xO+8tsQgkFqG/W+SgD+r0iTYAuglzlmA=
|
go.mau.fi/cbind v0.0.0-20220415094356-e1d579b7925e/go.mod h1:9nnzlslhUo/xO+8tsQgkFqG/W+SgD+r0iTYAuglzlmA=
|
||||||
go.mau.fi/mauview v0.1.4-0.20220415181713-aa8cd644bf1d h1:3HkNVjYG4ht8D80cd0jKCEYXloRULAVwnEjDKFn70U4=
|
go.mau.fi/mauview v0.1.4-0.20220415185926-d3913ee0f2b4 h1:fciW2Q2Gl/E24nXJ1xWeV4x75pFtEBFa8cBkwoIAATs=
|
||||||
go.mau.fi/mauview v0.1.4-0.20220415181713-aa8cd644bf1d/go.mod h1:CPqlQWgiHEJHLNyD8vjMXotnPluMz0eDpKKCimjxFYE=
|
go.mau.fi/mauview v0.1.4-0.20220415185926-d3913ee0f2b4/go.mod h1:1rzvl7kqQ9lv8EVZeAwUlxR4/Q8LM3y2Xogg0yNx0qU=
|
||||||
go.mau.fi/tcell v0.0.0-20220415093808-07c67d224693 h1:pCfn8BS6fiGG1inpebysWQxeRmK/nsgKPMF9TupqYNQ=
|
|
||||||
go.mau.fi/tcell v0.0.0-20220415093808-07c67d224693/go.mod h1:HQLPCz9v8YfYewMetOKrg9pe87XEyNcIfCYYq8VxQbU=
|
go.mau.fi/tcell v0.0.0-20220415093808-07c67d224693/go.mod h1:HQLPCz9v8YfYewMetOKrg9pe87XEyNcIfCYYq8VxQbU=
|
||||||
|
go.mau.fi/tcell v0.0.0-20220415185117-592f364693a2 h1:UocCXayiOk0dzu7GeTyiH6UdpJnp5d645NRDwr6RjLY=
|
||||||
|
go.mau.fi/tcell v0.0.0-20220415185117-592f364693a2/go.mod h1:HQLPCz9v8YfYewMetOKrg9pe87XEyNcIfCYYq8VxQbU=
|
||||||
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 h1:iU7T1X1J6yxDr0rda54sWGkHgOp5XJrqm79gcNlC2VM=
|
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 h1:iU7T1X1J6yxDr0rda54sWGkHgOp5XJrqm79gcNlC2VM=
|
||||||
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
@ -762,6 +762,20 @@ func (stm SimpleToggleMessage) Name() string {
|
|||||||
return string(unicode.ToUpper(rune(stm[0]))) + string(stm[1:])
|
return string(unicode.ToUpper(rune(stm[0]))) + string(stm[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InvertedToggleMessage string
|
||||||
|
|
||||||
|
func (itm InvertedToggleMessage) Format(state bool) string {
|
||||||
|
if state {
|
||||||
|
return "Enabled " + string(itm)
|
||||||
|
} else {
|
||||||
|
return "Disabled " + string(itm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (itm InvertedToggleMessage) Name() string {
|
||||||
|
return string(unicode.ToUpper(rune(itm[0]))) + string(itm[1:])
|
||||||
|
}
|
||||||
|
|
||||||
type NewlineKeybindMessage string
|
type NewlineKeybindMessage string
|
||||||
|
|
||||||
func (nkm NewlineKeybindMessage) Format(state bool) string {
|
func (nkm NewlineKeybindMessage) Format(state bool) string {
|
||||||
@ -790,6 +804,7 @@ var toggleMsg = map[string]ToggleMessage{
|
|||||||
"notifications": SimpleToggleMessage("desktop notifications"),
|
"notifications": SimpleToggleMessage("desktop notifications"),
|
||||||
"unverified": SimpleToggleMessage("sending messages to unverified devices"),
|
"unverified": SimpleToggleMessage("sending messages to unverified devices"),
|
||||||
"showurls": SimpleToggleMessage("show URLs in text format"),
|
"showurls": SimpleToggleMessage("show URLs in text format"),
|
||||||
|
"inlineurls": InvertedToggleMessage("use fancy terminal features to render URLs inside text"),
|
||||||
"newline": NewlineKeybindMessage("should <alt+enter> make a new line or send the message"),
|
"newline": NewlineKeybindMessage("should <alt+enter> make a new line or send the message"),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -837,6 +852,8 @@ func cmdToggle(cmd *Command) {
|
|||||||
val = &cmd.Config.SendToVerifiedOnly
|
val = &cmd.Config.SendToVerifiedOnly
|
||||||
case "showurls":
|
case "showurls":
|
||||||
val = &cmd.Config.Preferences.DisableShowURLs
|
val = &cmd.Config.Preferences.DisableShowURLs
|
||||||
|
case "inlineurls":
|
||||||
|
val = &cmd.Config.Preferences.InlineURLs
|
||||||
case "newline":
|
case "newline":
|
||||||
val = &cmd.Config.Preferences.AltEnterToSend
|
val = &cmd.Config.Preferences.AltEnterToSend
|
||||||
default:
|
default:
|
||||||
|
@ -34,17 +34,18 @@ import (
|
|||||||
"maunium.net/go/mautrix/id"
|
"maunium.net/go/mautrix/id"
|
||||||
|
|
||||||
"maunium.net/go/gomuks/config"
|
"maunium.net/go/gomuks/config"
|
||||||
|
"maunium.net/go/gomuks/matrix/muksevt"
|
||||||
"maunium.net/go/gomuks/matrix/rooms"
|
"maunium.net/go/gomuks/matrix/rooms"
|
||||||
"maunium.net/go/gomuks/ui/widget"
|
"maunium.net/go/gomuks/ui/widget"
|
||||||
)
|
)
|
||||||
|
|
||||||
var matrixToURL = regexp.MustCompile("^(?:https?://)?(?:www\\.)?matrix\\.to/#/([#@!].*)")
|
|
||||||
|
|
||||||
type htmlParser struct {
|
type htmlParser struct {
|
||||||
prefs *config.UserPreferences
|
prefs *config.UserPreferences
|
||||||
room *rooms.Room
|
room *rooms.Room
|
||||||
|
evt *muksevt.Event
|
||||||
|
|
||||||
preserveWhitespace bool
|
preserveWhitespace bool
|
||||||
|
linkIDCounter int
|
||||||
}
|
}
|
||||||
|
|
||||||
func AdjustStyleBold(style tcell.Style) tcell.Style {
|
func AdjustStyleBold(style tcell.Style) tcell.Style {
|
||||||
@ -63,18 +64,24 @@ func AdjustStyleStrikethrough(style tcell.Style) tcell.Style {
|
|||||||
return style.StrikeThrough(true)
|
return style.StrikeThrough(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func AdjustStyleTextColor(color tcell.Color) func(tcell.Style) tcell.Style {
|
func AdjustStyleTextColor(color tcell.Color) AdjustStyleFunc {
|
||||||
return func(style tcell.Style) tcell.Style {
|
return func(style tcell.Style) tcell.Style {
|
||||||
return style.Foreground(color)
|
return style.Foreground(color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AdjustStyleBackgroundColor(color tcell.Color) func(tcell.Style) tcell.Style {
|
func AdjustStyleBackgroundColor(color tcell.Color) AdjustStyleFunc {
|
||||||
return func(style tcell.Style) tcell.Style {
|
return func(style tcell.Style) tcell.Style {
|
||||||
return style.Background(color)
|
return style.Background(color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func AdjustStyleLink(url, id string) AdjustStyleFunc {
|
||||||
|
return func(style tcell.Style) tcell.Style {
|
||||||
|
return style.Hyperlink(url, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (parser *htmlParser) maybeGetAttribute(node *html.Node, attribute string) (string, bool) {
|
func (parser *htmlParser) maybeGetAttribute(node *html.Node, attribute string) (string, bool) {
|
||||||
for _, attr := range node.Attr {
|
for _, attr := range node.Attr {
|
||||||
if attr.Key == attribute {
|
if attr.Key == attribute {
|
||||||
@ -198,7 +205,7 @@ func (parser *htmlParser) linkToEntity(node *html.Node) Entity {
|
|||||||
Children: parser.nodeToEntities(node.FirstChild),
|
Children: parser.nodeToEntities(node.FirstChild),
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(href) == 0 || parser.hasAttribute(node, "data-mautrix-exclude-plaintext") {
|
if len(href) == 0 {
|
||||||
return entity
|
return entity
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,28 +216,25 @@ func (parser *htmlParser) linkToEntity(node *html.Node) Entity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !parser.prefs.DisableShowURLs && !parser.hasAttribute(node, "data-mautrix-no-link") && !sameURL {
|
matrixURI, _ := id.ParseMatrixURIOrMatrixToURL(href)
|
||||||
entity.Children = append(entity.Children, NewTextEntity(fmt.Sprintf(" (%s)", href)))
|
if matrixURI != nil && (matrixURI.Sigil1 == '@' || matrixURI.Sigil1 == '#') && matrixURI.Sigil2 == 0 {
|
||||||
}
|
text := NewTextEntity(matrixURI.PrimaryIdentifier())
|
||||||
|
if matrixURI.Sigil1 == '@' {
|
||||||
match := matrixToURL.FindStringSubmatch(href)
|
if member := parser.room.GetMember(matrixURI.UserID()); member != nil {
|
||||||
if len(match) == 2 {
|
|
||||||
pillTarget := match[1]
|
|
||||||
text := NewTextEntity(pillTarget)
|
|
||||||
if pillTarget[0] == '@' {
|
|
||||||
if member := parser.room.GetMember(id.UserID(pillTarget)); member != nil {
|
|
||||||
text.Text = member.Displayname
|
text.Text = member.Displayname
|
||||||
text.Style = text.Style.Foreground(widget.GetHashColor(pillTarget))
|
text.Style = text.Style.Foreground(widget.GetHashColor(matrixURI.UserID()))
|
||||||
}
|
}
|
||||||
entity.Children = []Entity{text}
|
entity.Children = []Entity{text}
|
||||||
/*} else if slash := strings.IndexRune(pillTarget, '/'); slash != -1 {
|
} else if matrixURI.Sigil1 == '#' {
|
||||||
room := pillTarget[:slash]
|
|
||||||
event := pillTarget[slash+1:]*/
|
|
||||||
} else if pillTarget[0] == '#' {
|
|
||||||
entity.Children = []Entity{text}
|
entity.Children = []Entity{text}
|
||||||
}
|
}
|
||||||
|
} else if parser.prefs.InlineURLs {
|
||||||
|
linkID := fmt.Sprintf("%s-%d", parser.evt.ID, parser.linkIDCounter)
|
||||||
|
parser.linkIDCounter++
|
||||||
|
entity.AdjustStyle(AdjustStyleLink(href, linkID), AdjustStyleReasonNormal)
|
||||||
|
} else if !sameURL && !parser.prefs.DisableShowURLs && !parser.hasAttribute(node, "data-mautrix-exclude-plaintext") {
|
||||||
|
entity.Children = append(entity.Children, NewTextEntity(fmt.Sprintf(" (%s)", href)))
|
||||||
}
|
}
|
||||||
// TODO add click action and underline on hover for links
|
|
||||||
return entity
|
return entity
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,7 +451,7 @@ func (parser *htmlParser) Parse(htmlData string) Entity {
|
|||||||
const TabLength = 4
|
const TabLength = 4
|
||||||
|
|
||||||
// Parse parses a HTML-formatted Matrix event into a UIMessage.
|
// Parse parses a HTML-formatted Matrix event into a UIMessage.
|
||||||
func Parse(prefs *config.UserPreferences, room *rooms.Room, content *event.MessageEventContent, sender id.UserID, senderDisplayname string) Entity {
|
func Parse(prefs *config.UserPreferences, room *rooms.Room, content *event.MessageEventContent, evt *muksevt.Event, senderDisplayname string) Entity {
|
||||||
htmlData := content.FormattedBody
|
htmlData := content.FormattedBody
|
||||||
|
|
||||||
if content.Format != event.FormatHTML {
|
if content.Format != event.FormatHTML {
|
||||||
@ -455,7 +459,7 @@ func Parse(prefs *config.UserPreferences, room *rooms.Room, content *event.Messa
|
|||||||
}
|
}
|
||||||
htmlData = strings.Replace(htmlData, "\t", strings.Repeat(" ", TabLength), -1)
|
htmlData = strings.Replace(htmlData, "\t", strings.Repeat(" ", TabLength), -1)
|
||||||
|
|
||||||
parser := htmlParser{room: room, prefs: prefs}
|
parser := htmlParser{room: room, prefs: prefs, evt: evt}
|
||||||
root := parser.Parse(htmlData)
|
root := parser.Parse(htmlData)
|
||||||
beRoot := root.(*ContainerEntity)
|
beRoot := root.(*ContainerEntity)
|
||||||
beRoot.Block = false
|
beRoot.Block = false
|
||||||
@ -474,7 +478,7 @@ func Parse(prefs *config.UserPreferences, room *rooms.Room, content *event.Messa
|
|||||||
},
|
},
|
||||||
Children: []Entity{
|
Children: []Entity{
|
||||||
NewTextEntity("* "),
|
NewTextEntity("* "),
|
||||||
NewTextEntity(senderDisplayname).AdjustStyle(AdjustStyleTextColor(widget.GetHashColor(sender)), AdjustStyleReasonNormal),
|
NewTextEntity(senderDisplayname).AdjustStyle(AdjustStyleTextColor(widget.GetHashColor(evt.Sender)), AdjustStyleReasonNormal),
|
||||||
NewTextEntity(" "),
|
NewTextEntity(" "),
|
||||||
root,
|
root,
|
||||||
},
|
},
|
||||||
|
@ -205,7 +205,7 @@ func ParseMessage(matrix ifc.MatrixContainer, room *rooms.Room, evt *muksevt.Eve
|
|||||||
switch content.MsgType {
|
switch content.MsgType {
|
||||||
case event.MsgText, event.MsgNotice, event.MsgEmote:
|
case event.MsgText, event.MsgNotice, event.MsgEmote:
|
||||||
if content.Format == event.FormatHTML {
|
if content.Format == event.FormatHTML {
|
||||||
return NewHTMLMessage(evt, displayname, html.Parse(matrix.Preferences(), room, content, evt.Sender, displayname))
|
return NewHTMLMessage(evt, displayname, html.Parse(matrix.Preferences(), room, content, evt, displayname))
|
||||||
}
|
}
|
||||||
content.Body = strings.Replace(content.Body, "\t", " ", -1)
|
content.Body = strings.Replace(content.Body, "\t", " ", -1)
|
||||||
return NewTextMessage(evt, displayname, content.Body)
|
return NewTextMessage(evt, displayname, content.Body)
|
||||||
|
Loading…
Reference in New Issue
Block a user