Browse Source

Categorize and normalize folder listing

master
Drew DeVault 3 years ago
parent
commit
9e2c420461
4 changed files with 110 additions and 34 deletions
  1. +14
    -2
      plugins/base/imap.go
  2. +61
    -13
      plugins/base/routes.go
  3. +2
    -1
      themes/alps/assets/style.css
  4. +33
    -18
      themes/alps/mailbox.html

+ 14
- 2
plugins/base/imap.go View File

@@ -19,6 +19,9 @@ import (

type MailboxInfo struct {
*imap.MailboxInfo

Active bool
Unseen int
}

func (mbox *MailboxInfo) URL() *url.URL {
@@ -27,6 +30,15 @@ func (mbox *MailboxInfo) URL() *url.URL {
}
}

func (mbox *MailboxInfo) HasAttr(flag string) bool {
for _, attr := range mbox.Attributes {
if attr == flag {
return true
}
}
return false
}

func listMailboxes(conn *imapclient.Client) ([]MailboxInfo, error) {
ch := make(chan *imap.MailboxInfo, 10)
done := make(chan error, 1)
@@ -36,7 +48,7 @@ func listMailboxes(conn *imapclient.Client) ([]MailboxInfo, error) {

var mailboxes []MailboxInfo
for mbox := range ch {
mailboxes = append(mailboxes, MailboxInfo{mbox})
mailboxes = append(mailboxes, MailboxInfo{mbox, false, -1})
}

if err := <-done; err != nil {
@@ -133,7 +145,7 @@ func getMailboxByType(conn *imapclient.Client, mboxType mailboxType) (*MailboxIn
if best == nil {
return nil, nil
}
return &MailboxInfo{best}, nil
return &MailboxInfo{best, false, -1}, nil
}

func ensureMailboxSelected(conn *imapclient.Client, mboxName string) error {


+ 61
- 13
plugins/base/routes.go View File

@@ -65,12 +65,57 @@ func registerRoutes(p *alps.GoPlugin) {

type MailboxRenderData struct {
alps.BaseRenderData
Mailbox *MailboxStatus
Inbox *MailboxStatus
Mailboxes []MailboxInfo
Messages []IMAPMessage
PrevPage, NextPage int
Query string
Mailbox *MailboxStatus
Inbox *MailboxStatus
CategorizedMailboxes CategorizedMailboxes
Mailboxes []MailboxInfo
Messages []IMAPMessage
PrevPage, NextPage int
Query string
}

// Organizes mailboxes into common/uncommon categories
type CategorizedMailboxes struct {
Common struct {
Inbox *MailboxInfo
Drafts *MailboxInfo
Sent *MailboxInfo
Junk *MailboxInfo
Trash *MailboxInfo
Archive *MailboxInfo
}
Additional []*MailboxInfo
}

func categorizeMailboxes(mailboxes []MailboxInfo,
inbox *MailboxStatus, active *MailboxStatus) CategorizedMailboxes {

var out CategorizedMailboxes
mmap := map[string]**MailboxInfo{
"INBOX": &out.Common.Inbox,
"Drafts": &out.Common.Drafts,
"Sent": &out.Common.Sent,
"Junk": &out.Common.Junk,
"Trash": &out.Common.Trash,
"Archive": &out.Common.Archive,
}
for i, _ := range mailboxes {
// Populate unseen & active states
if mailboxes[i].Name == active.Name {
mailboxes[i].Unseen = int(active.Unseen)
mailboxes[i].Active = true
}
if mailboxes[i].Name == inbox.Name {
mailboxes[i].Unseen = int(inbox.Unseen)
}

if ptr, ok := mmap[mailboxes[i].Name]; ok {
*ptr = &mailboxes[i]
} else {
out.Additional = append(out.Additional, &mailboxes[i])
}
}
return out
}

func handleGetMailbox(ctx *alps.Context) error {
@@ -154,15 +199,18 @@ func handleGetMailbox(ctx *alps.Context) error {
title = fmt.Sprintf("(%d) %s", mbox.Unseen, title)
}

categorized := categorizeMailboxes(mailboxes, inbox, mbox)

return ctx.Render(http.StatusOK, "mailbox.html", &MailboxRenderData{
BaseRenderData: *alps.NewBaseRenderData(ctx).WithTitle(title),
Mailbox: mbox,
Inbox: inbox,
Mailboxes: mailboxes,
Messages: msgs,
PrevPage: prevPage,
NextPage: nextPage,
Query: query,
Mailbox: mbox,
Inbox: inbox,
CategorizedMailboxes: categorized,
Mailboxes: mailboxes,
Messages: msgs,
PrevPage: prevPage,
NextPage: nextPage,
Query: query,
})
}



+ 2
- 1
themes/alps/assets/style.css View File

@@ -127,7 +127,8 @@ footer { text-align: right; }


aside { flex: 0 0 180px; }
aside a { width: 100%; display: block; padding: 0.4rem 0 0.4rem 0.5rem; }
aside a,
aside .noselect { width: 100%; display: block; padding: 0.4rem 0 0.4rem 0.5rem; }
aside a.active { font-weight: bold; color: black; text-decoration: none; }
aside img { display: block; }
main {


+ 33
- 18
themes/alps/mailbox.html View File

@@ -1,28 +1,43 @@
{{template "head.html" .}}
{{template "nav.html" .}}

{{ define "mbox-link" }}
{{ if not (.HasAttr "\\Noselect") }}
<a href="{{.URL}}" {{ if .Active }}class="active"{{ end }}>
{{- if eq .Name "INBOX" -}}
Inbox
{{- else -}}
{{ .Name }}
{{- end -}}
{{- if .HasAttr "\\HasChildren" }}/{{ end }}

{{ if and (ne .Unseen -1) (ne .Unseen 0) }}({{ .Unseen }}){{ end }}
</a>
{{ else }}
<span class="noselect">
{{.Name}}{{- if .HasAttr "\\HasChildren" }}/{{ end }}
</span>
{{ end }}
{{ end }}

<div class="page-wrap">
<aside>
<!-- the logo image, dimensions 200x32 may be present or not -->
<a href="/compose" class="new">Compose&nbsp;Mail</a>
{{range .Mailboxes}}
<a href="{{.URL}}" {{ if eq $.Mailbox.Name .Name }}class="active"{{ end }}>
{{ if eq .Name "INBOX" }}
Inbox
{{ else }}
{{ .Name }}
{{ end }}

{{ $unseen := 0 }}
{{ if eq .Name "INBOX" }}
{{ $unseen = $.Inbox.Unseen }}
{{ end }}
{{ if eq .Name $.Mailbox.Name }}
{{ $unseen = $.Mailbox.Unseen }}
{{ end }}
{{ if $unseen }}({{ $unseen }}){{ end }}
</a>
{{end}}
{{ with .CategorizedMailboxes }}
{{ with .Common.Inbox }}{{ template "mbox-link" . }}{{ end}}
{{ with .Common.Drafts }}{{ template "mbox-link" . }}{{ end}}
{{ with .Common.Sent }}{{ template "mbox-link" . }}{{ end}}
{{ with .Common.Junk }}{{ template "mbox-link" . }}{{ end}}
{{ with .Common.Trash }}{{ template "mbox-link" . }}{{ end}}
{{ with .Common.Archive }}{{ template "mbox-link" . }}{{ end}}
{{ if .Additional }}
<hr />
{{ range .Additional }}
{{ template "mbox-link" . }}
{{ end }}
{{ end }}
{{ end }}
</aside>

<div class="container">


Loading…
Cancel
Save