Implement paging for search
This commit is contained in:
parent
6bccdd62ce
commit
80da410c3b
3 changed files with 30 additions and 16 deletions
|
@ -227,26 +227,33 @@ func listMessages(conn *imapclient.Client, mboxName string, page int) ([]IMAPMes
|
||||||
return msgs, nil
|
return msgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func searchMessages(conn *imapclient.Client, mboxName, query string) ([]IMAPMessage, error) {
|
func searchMessages(conn *imapclient.Client, mboxName, query string, page int) (msgs []IMAPMessage, total int, err error) {
|
||||||
if err := ensureMailboxSelected(conn, mboxName); err != nil {
|
if err := ensureMailboxSelected(conn, mboxName); err != nil {
|
||||||
return nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
criteria := imap.SearchCriteria{Text: []string{query}}
|
criteria := imap.SearchCriteria{Text: []string{query}}
|
||||||
nums, err := conn.Search(&criteria)
|
nums, err := conn.Search(&criteria)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("UID SEARCH failed: %v", err)
|
return nil, 0, fmt.Errorf("UID SEARCH failed: %v", err)
|
||||||
}
|
}
|
||||||
if len(nums) == 0 {
|
total = len(nums)
|
||||||
return nil, nil
|
|
||||||
|
from := page*messagesPerPage
|
||||||
|
to := from + messagesPerPage
|
||||||
|
if from >= len(nums) {
|
||||||
|
return nil, total, nil
|
||||||
}
|
}
|
||||||
|
if to > len(nums) {
|
||||||
|
to = len(nums)
|
||||||
|
}
|
||||||
|
nums = nums[from:to]
|
||||||
|
|
||||||
indexes := make(map[uint32]int)
|
indexes := make(map[uint32]int)
|
||||||
for i, num := range nums {
|
for i, num := range nums {
|
||||||
indexes[num] = i
|
indexes[num] = i
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: paging
|
|
||||||
var seqSet imap.SeqSet
|
var seqSet imap.SeqSet
|
||||||
seqSet.AddNum(nums...)
|
seqSet.AddNum(nums...)
|
||||||
|
|
||||||
|
@ -258,7 +265,7 @@ func searchMessages(conn *imapclient.Client, mboxName, query string) ([]IMAPMess
|
||||||
done <- conn.Fetch(&seqSet, fetch, ch)
|
done <- conn.Fetch(&seqSet, fetch, ch)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
msgs := make([]IMAPMessage, len(nums))
|
msgs = make([]IMAPMessage, len(nums))
|
||||||
for msg := range ch {
|
for msg := range ch {
|
||||||
i, ok := indexes[msg.SeqNum]
|
i, ok := indexes[msg.SeqNum]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -268,10 +275,10 @@ func searchMessages(conn *imapclient.Client, mboxName, query string) ([]IMAPMess
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := <-done; err != nil {
|
if err := <-done; err != nil {
|
||||||
return nil, fmt.Errorf("failed to fetch message list: %v", err)
|
return nil, 0, fmt.Errorf("failed to fetch message list: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return msgs, nil
|
return msgs, total, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMessagePart(conn *imapclient.Client, mboxName string, uid uint32, partPath []int) (*IMAPMessage, *message.Entity, error) {
|
func getMessagePart(conn *imapclient.Client, mboxName string, uid uint32, partPath []int) (*IMAPMessage, *message.Entity, error) {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
<h2>{{.Mailbox.Name}}</h2>
|
<h2>{{.Mailbox.Name}}</h2>
|
||||||
|
|
||||||
<form method="post" action="">
|
<form method="get" action="">
|
||||||
<input type="search" name="query" value="{{.Query}}">
|
<input type="search" name="query" value="{{.Query}}">
|
||||||
<input type="submit" value="Search">
|
<input type="submit" value="Search">
|
||||||
</form>
|
</form>
|
||||||
|
@ -36,11 +36,11 @@
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
{{if ge .PrevPage 0}}
|
{{if ge .PrevPage 0}}
|
||||||
<a href="?page={{.PrevPage}}">Prev</a>
|
<a href="?page={{.PrevPage}}&query={{.Query}}">Prev</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if and (ge .PrevPage 0) (ge .NextPage 0)}}·{{end}}
|
{{if and (ge .PrevPage 0) (ge .NextPage 0)}}·{{end}}
|
||||||
{{if ge .NextPage 0}}
|
{{if ge .NextPage 0}}
|
||||||
<a href="?page={{.NextPage}}">Next</a>
|
<a href="?page={{.NextPage}}&query={{.Query}}">Next</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
</p>
|
</p>
|
||||||
{{else}}
|
{{else}}
|
||||||
|
|
|
@ -74,18 +74,19 @@ func handleGetMailbox(ctx *koushin.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query := ctx.FormValue("query")
|
query := ctx.QueryParam("query")
|
||||||
|
|
||||||
var mailboxes []*imap.MailboxInfo
|
var mailboxes []*imap.MailboxInfo
|
||||||
var msgs []IMAPMessage
|
var msgs []IMAPMessage
|
||||||
var mbox *imap.MailboxStatus
|
var mbox *imap.MailboxStatus
|
||||||
|
var total int
|
||||||
err = ctx.Session.DoIMAP(func(c *imapclient.Client) error {
|
err = ctx.Session.DoIMAP(func(c *imapclient.Client) error {
|
||||||
var err error
|
var err error
|
||||||
if mailboxes, err = listMailboxes(c); err != nil {
|
if mailboxes, err = listMailboxes(c); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if query != "" {
|
if query != "" {
|
||||||
msgs, err = searchMessages(c, mboxName, query)
|
msgs, total, err = searchMessages(c, mboxName, query, page)
|
||||||
} else {
|
} else {
|
||||||
msgs, err = listMessages(c, mboxName, page)
|
msgs, err = listMessages(c, mboxName, page)
|
||||||
}
|
}
|
||||||
|
@ -100,8 +101,14 @@ func handleGetMailbox(ctx *koushin.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
prevPage, nextPage := -1, -1
|
prevPage, nextPage := -1, -1
|
||||||
if query == "" {
|
if query != "" {
|
||||||
// TODO: paging for search
|
if page > 0 {
|
||||||
|
prevPage = page - 1
|
||||||
|
}
|
||||||
|
if (page+1)*messagesPerPage <= total {
|
||||||
|
nextPage = page + 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if page > 0 {
|
if page > 0 {
|
||||||
prevPage = page - 1
|
prevPage = page - 1
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue