Browse Source

Add basic pagination to message list

References: https://todo.sr.ht/~sircmpwn/koushin/22
master
Simon Ser 4 years ago
parent
commit
8de93c50d2
No known key found for this signature in database GPG Key ID: FDE7BE0E88F5E48
7 changed files with 60 additions and 20 deletions
  1. +1
    -1
      conn_pool.go
  2. +10
    -10
      imap.go
  3. +14
    -1
      public/mailbox.html
  4. +7
    -1
      public/message.html
  5. +22
    -1
      server.go
  6. +5
    -5
      smtp.go
  7. +1
    -1
      strconv.go

+ 1
- 1
conn_pool.go View File

@@ -21,7 +21,7 @@ func generateToken() (string, error) {
var ErrSessionExpired = errors.New("session expired")

type Session struct {
locker sync.Mutex
locker sync.Mutex
imapConn *imapclient.Client
username, password string
}


+ 10
- 10
imap.go View File

@@ -206,23 +206,23 @@ func (msg *imapMessage) PartTree() *IMAPPartNode {
return imapPartTree(msg.BodyStructure, nil)
}

func listMessages(conn *imapclient.Client, mboxName string) ([]imapMessage, error) {
func listMessages(conn *imapclient.Client, mboxName string, page int) ([]imapMessage, error) {
if err := ensureMailboxSelected(conn, mboxName); err != nil {
return nil, err
}

n := uint32(50)

mbox := conn.Mailbox()
from := uint32(1)
to := mbox.Messages
if mbox.Messages == 0 {
to := int(mbox.Messages) - page*messagesPerPage
from := to - messagesPerPage
if from <= 0 {
from = 1
}
if to <= 0 {
return nil, nil
} else if mbox.Messages > n {
from = mbox.Messages - n
}

seqSet := new(imap.SeqSet)
seqSet.AddRange(from, to)
seqSet.AddRange(uint32(from), uint32(to))

fetch := []imap.FetchItem{imap.FetchEnvelope, imap.FetchUid, imap.FetchBodyStructure}

@@ -232,7 +232,7 @@ func listMessages(conn *imapclient.Client, mboxName string) ([]imapMessage, erro
done <- conn.Fetch(seqSet, fetch, ch)
}()

msgs := make([]imapMessage, 0, n)
msgs := make([]imapMessage, 0, to-from)
for msg := range ch {
msgs = append(msgs, imapMessage{msg})
}


+ 14
- 1
public/mailbox.html View File

@@ -20,10 +20,23 @@
<ul>
{{range .Messages}}
<li><a href="/message/{{$.Mailbox.Name | pathescape}}/{{.Uid}}?part={{.TextPartName}}">
{{.Envelope.Subject}}
{{if .Envelope.Subject}}
{{.Envelope.Subject}}
{{else}}
(No subject)
{{end}}
</a></li>
{{end}}
</ul>

<p>
{{if ge .PrevPage 0}}
<a href="?page={{.PrevPage}}">Prev</a>
{{end}}
{{if ge .NextPage 0}}
<a href="?page={{.NextPage}}">Next</a>
{{end}}
</p>
{{else}}
<p>Mailbox is empty.</p>
{{end}}


+ 7
- 1
public/message.html View File

@@ -6,7 +6,13 @@
<a href="/mailbox/{{.Mailbox.Name | pathescape}}">Back</a>
</p>

<h2>{{.Message.Envelope.Subject}}</h2>
<h2>
{{if .Message.Envelope.Subject}}
{{.Message.Envelope.Subject}}
{{else}}
(No subject)
{{end}}
</h2>

{{define "message-part-tree"}}
{{/* nested templates can't access the parent's context */}}


+ 22
- 1
server.go View File

@@ -6,6 +6,7 @@ import (
"mime"
"net/http"
"net/url"
"strconv"
"strings"
"time"

@@ -18,6 +19,8 @@ import (

const cookieName = "koushin_session"

const messagesPerPage = 50

type Server struct {
imap struct {
host string
@@ -366,6 +369,14 @@ func New(imapURL, smtpURL string) *echo.Echo {
return echo.NewHTTPError(http.StatusBadRequest, err)
}

page := 0
if pageStr := ctx.QueryParam("page"); pageStr != "" {
var err error
if page, err = strconv.Atoi(pageStr); err != nil || page < 0 {
return echo.NewHTTPError(http.StatusBadRequest, "invalid page index")
}
}

var mailboxes []*imap.MailboxInfo
var msgs []imapMessage
var mbox *imap.MailboxStatus
@@ -374,7 +385,7 @@ func New(imapURL, smtpURL string) *echo.Echo {
if mailboxes, err = listMailboxes(c); err != nil {
return err
}
if msgs, err = listMessages(c, mboxName); err != nil {
if msgs, err = listMessages(c, mboxName, page); err != nil {
return err
}
mbox = c.Mailbox()
@@ -384,10 +395,20 @@ func New(imapURL, smtpURL string) *echo.Echo {
return err
}

prevPage, nextPage := -1, -1
if page > 0 {
prevPage = page - 1
}
if (page+1)*messagesPerPage < int(mbox.Messages) {
nextPage = page + 1
}

return ctx.Render(http.StatusOK, "mailbox.html", map[string]interface{}{
"Mailbox": mbox,
"Mailboxes": mailboxes,
"Messages": msgs,
"PrevPage": prevPage,
"NextPage": nextPage,
})
})



+ 5
- 5
smtp.go View File

@@ -3,9 +3,9 @@ package koushin
import (
"bufio"
"fmt"
"time"
"io"
"strings"
"time"

"github.com/emersion/go-message/mail"
"github.com/emersion/go-smtp"
@@ -50,11 +50,11 @@ func (s *Server) connectSMTP() (*smtp.Client, error) {
}

type OutgoingMessage struct {
From string
To []string
Subject string
From string
To []string
Subject string
InReplyTo string
Text string
Text string
}

func (msg *OutgoingMessage) ToString() string {


+ 1
- 1
strconv.go View File

@@ -2,9 +2,9 @@ package koushin

import (
"fmt"
"net/url"
"strconv"
"strings"
"net/url"
)

func parseUid(s string) (uint32, error) {


Loading…
Cancel
Save