@@ -1,13 +1,14 @@
1package editor
1package editor
6 "math/rand"
5 "math/rand"
9 "path/filepath"
8 "path/filepath"
@@ -146,7 +147,7 @@ func (m *editorCmp) send() tea.Cmd {
147 attachments := m.attachments
148 attachments := m.attachments
149− if value == "" {
150+ if value == "" && !message.ContainsTextAttachment(attachments) {
150 return nil
151 return nil
@@ -233,13 +234,31 @@ func (m *editorCmp) Update(msg tea.Msg) (util.Model, tea.Cmd) {
233 m.textarea.SetValue(msg.Text)
234 m.textarea.SetValue(msg.Text)
234 m.textarea.MoveToEnd()
235 m.textarea.MoveToEnd()
235 case tea.PasteMsg:
236 case tea.PasteMsg:
236− content, path, err := pasteToFile(msg)
237+ // If pasted text has more than 2 newlines, treat it as a file attachment.
237− if errors.Is(err, errNotAFile) {
238+ if strings.Count(msg.Content, "\n") > 2 {
238− m.textarea, cmd = m.textarea.Update(msg)
239+ content := []byte(msg.Content)
239− return m, cmd
240+ if len(content) > maxAttachmentSize {
241+ return m, util.ReportWarn("Paste is too big (>5mb)")
243+ name := fmt.Sprintf("paste_%d.txt", m.pasteIdx())
244+ mimeType := mimeOf(content)
245+ attachment := message.Attachment{
251+ return m, util.CmdHandler(filepicker.FilePickedMsg{
252+ Attachment: attachment,
256+ // Try to parse as a file path.
257+ content, path, err := filepathToFile(msg.Content)
241 if err != nil {
258 if err != nil {
242− return m, util.ReportError(err)
259+ // Not a file path, just update the textarea normally.
260+ m.textarea, cmd = m.textarea.Update(msg)
245 if len(content) > maxAttachmentSize {
264 if len(content) > maxAttachmentSize {
@@ -256,7 +275,6 @@ func (m *editorCmp) Update(msg tea.Msg) (util.Model, tea.Cmd) {
256 if !attachment.IsText() && !attachment.IsImage() {
275 if !attachment.IsText() && !attachment.IsImage() {
257 return m, util.ReportWarn("Invalid file content type: " + mimeType)
276 return m, util.ReportWarn("Invalid file content type: " + mimeType)
259− m.textarea.InsertString(attachment.FileName)
260 return m, util.CmdHandler(filepicker.FilePickedMsg{
278 return m, util.CmdHandler(filepicker.FilePickedMsg{
261 Attachment: attachment,
279 Attachment: attachment,
@@ -627,33 +645,21 @@ func New(app *app.App) Editor {
628var maxAttachmentSize = 5 * 1024 * 1024 // 5MB
646var maxAttachmentSize = 5 * 1024 * 1024 // 5MB
630−var errNotAFile = errors.New("not a file")
648+var pasteRE = regexp.MustCompile(`paste_(\d+).txt`)
632−func pasteToFile(msg tea.PasteMsg) ([]byte, string, error) {
633− content, path, err := filepathToFile(msg.Content)
635− return content, path, err
638− if strings.Count(msg.Content, "\n") > 2 {
639− return contentToFile([]byte(msg.Content))
642− return nil, "", errNotAFile
645−func contentToFile(content []byte) ([]byte, string, error) {
650+func (m *editorCmp) pasteIdx() int {
646− f, err := os.CreateTemp("", "paste_*.txt")
651+ result := 0
647− if err != nil {
652+ for _, at := range m.attachments {
648− return nil, "", err
653+ found := pasteRE.FindStringSubmatch(at.FileName)
649− }
654+ if len(found) == 0 {
650− if _, err := f.Write(content); err != nil {
655+ continue
657+ idx, err := strconv.Atoi(found[1])
653− if err := f.Close(); err != nil {
658+ if err == nil {
654− return nil, "", err
659+ result = max(result, idx)
656− return content, f.Name(), nil
662+ return result + 1
659func filepathToFile(name string) ([]byte, string, error) {
665func filepathToFile(name string) ([]byte, string, error) {