cchat-gtk/internal/ui/messages/message/sending.go

162 lines
3.9 KiB
Go
Raw Normal View History

2020-06-06 07:44:36 +00:00
package message
import (
2020-07-10 23:26:07 +00:00
"fmt"
2020-06-06 07:44:36 +00:00
"html"
"github.com/diamondburned/cchat"
2020-07-10 23:26:07 +00:00
"github.com/diamondburned/cchat-gtk/internal/humanize"
"github.com/diamondburned/cchat-gtk/internal/ui/messages/input/attachment"
"github.com/diamondburned/cchat-gtk/internal/ui/primitives"
2020-07-10 23:26:07 +00:00
"github.com/gotk3/gotk3/gtk"
"github.com/gotk3/gotk3/pango"
)
var EmptyContentPlaceholder = fmt.Sprintf(
`<span alpha="25%%">%s</span>`, html.EscapeString("<empty>"),
2020-06-06 07:44:36 +00:00
)
// Presender describes actions doable on a presend message container.
type Presender interface {
SendingMessage() PresendMessage
SetDone(id cchat.ID)
SetLoading()
2020-06-06 07:44:36 +00:00
SetSentError(err error)
}
// PresendMessage is an interface for any message about to be sent.
type PresendMessage interface {
cchat.MessageHeader
cchat.SendableMessage
cchat.Noncer
// These methods are reserved for internal use.
Files() []attachment.File
}
// PresendState is the generic state with extra methods implemented for stateful
// mutability of the generic message state.
type PresendState struct {
*State
2020-07-10 23:26:07 +00:00
// states; to be cleared on SetDone()
presend PresendMessage
2020-07-10 23:26:07 +00:00
uploads *attachment.MessageUploader
2020-06-06 07:44:36 +00:00
}
var (
_ Presender = (*PresendState)(nil)
)
2020-06-06 07:44:36 +00:00
type SendMessageData struct {
}
2020-06-06 07:44:36 +00:00
// NewPresendState creates a new presend state.
func NewPresendState(self *Author, msg PresendMessage) *PresendState {
c := NewEmptyState()
c.Author = self
c.Nonce = msg.Nonce()
c.Time = msg.Time()
2020-07-10 23:26:07 +00:00
p := &PresendState{
State: c,
2020-07-10 23:26:07 +00:00
presend: msg,
uploads: attachment.NewMessageUploader(msg.Files()),
2020-06-06 07:44:36 +00:00
}
p.SetLoading()
2020-06-06 07:44:36 +00:00
return p
}
func (m *PresendState) SendingMessage() PresendMessage { return m.presend }
// SetSensitive sets the sensitivity of the content.
func (m *PresendState) SetSensitive(sensitive bool) {
2021-01-05 02:05:33 +00:00
m.Content.SetSensitive(sensitive)
2020-06-06 07:44:36 +00:00
}
// SetDone sets the status of the state.
func (m *PresendState) SetDone(id cchat.ID) {
2020-07-10 23:26:07 +00:00
// Apply the received ID.
m.ID = id
m.Nonce = ""
2020-07-10 23:26:07 +00:00
// Reset the state to be normal. Especially setting presend to nil should
// free it from memory.
m.presend = nil
m.uploads = nil
2021-01-05 02:05:33 +00:00
m.Content.SetTooltipText("")
2020-07-10 23:26:07 +00:00
// Remove everything in the content box.
m.clearBox()
// Re-add the content label.
2021-01-05 02:05:33 +00:00
m.Content.Add(m.ContentBody)
// Set the sensitivity from false in SetLoading back to true.
m.SetSensitive(true)
2020-06-06 07:44:36 +00:00
}
// SetLoading greys the message to indicate that it's loading.
func (m *PresendState) SetLoading() {
m.SetSensitive(false)
2021-01-05 02:05:33 +00:00
m.Content.SetTooltipText("")
2020-07-10 23:26:07 +00:00
// Clear everything inside the content container.
m.clearBox()
// Add the content label.
2021-01-05 02:05:33 +00:00
m.Content.Add(m.ContentBody)
2020-07-10 23:26:07 +00:00
// Add the attachment progress box back in, if any.
if m.uploads != nil {
m.uploads.Show() // show the bars
2021-01-05 02:05:33 +00:00
m.Content.Add(m.uploads)
2020-07-10 23:26:07 +00:00
}
2020-07-10 23:26:07 +00:00
if content := m.presend.Content(); content != "" {
m.ContentBody.SetText(content)
} else {
// Use a placeholder content if the actual content is empty.
m.ContentBody.SetMarkup(EmptyContentPlaceholder)
}
}
2020-06-07 04:27:28 +00:00
// SetSentError sets the error into the message to notify the user.
func (m *PresendState) SetSentError(err error) {
m.SetSensitive(true) // allow events incl right clicks
2021-01-05 02:05:33 +00:00
m.Content.SetTooltipText(err.Error())
2020-07-10 23:26:07 +00:00
// Remove everything again.
m.clearBox()
// Re-add the label.
2021-01-05 02:05:33 +00:00
m.Content.Add(m.ContentBody)
2020-07-10 23:26:07 +00:00
// Style the label appropriately by making it red.
var content = EmptyContentPlaceholder
if m.presend != nil && m.presend.Content() != "" {
content = m.presend.Content()
2020-07-10 23:26:07 +00:00
}
m.ContentBody.SetMarkup(fmt.Sprintf(`<span color="red">%s</span>`, content))
// Add a smaller label indicating an error.
errl, _ := gtk.LabelNew("")
errl.SetXAlign(0)
errl.SetLineWrap(true)
errl.SetLineWrapMode(pango.WRAP_WORD_CHAR)
errl.SetMarkup(fmt.Sprintf(
`<span size="small" color="red"><b>Error:</b> %s</span>`,
html.EscapeString(humanize.Error(err)),
))
errl.Show()
2021-01-05 02:05:33 +00:00
m.Content.Add(errl)
2020-07-10 23:26:07 +00:00
}
// clearBox clears everything inside the content container.
func (m *PresendState) clearBox() {
2021-01-05 02:05:33 +00:00
primitives.RemoveChildren(m.Content)
2020-06-06 07:44:36 +00:00
}