diff options
author | Drew DeVault <sir@cmpwn.com> | 2020-11-19 13:14:12 -0500 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2020-11-19 13:14:12 -0500 |
commit | 51d762ac5fd21c6cac898b2e5eed2eabdb0fe841 (patch) | |
tree | 9a62e4920c44dd7f3c5afcd49f9ced7573d7f4de | |
parent | 8cc742f45df7544c20f43e781d2c7e4aa6a3f4f5 (diff) | |
download | alps-51d762ac5fd21c6cac898b2e5eed2eabdb0fe841.tar.gz alps-51d762ac5fd21c6cac898b2e5eed2eabdb0fe841.zip |
Implement mailbox subscriptions
-rw-r--r-- | plugins/base/routes.go | 85 | ||||
-rw-r--r-- | themes/alps/assets/style.css | 12 | ||||
-rw-r--r-- | themes/alps/settings.html | 17 | ||||
-rw-r--r-- | themes/alps/util.html | 37 |
4 files changed, 109 insertions, 42 deletions
diff --git a/plugins/base/routes.go b/plugins/base/routes.go index 61d92a6..8c230a4 100644 --- a/plugins/base/routes.go +++ b/plugins/base/routes.go @@ -80,6 +80,7 @@ type IMAPBaseRenderData struct { Mailboxes []MailboxInfo Mailbox *MailboxStatus Inbox *MailboxStatus + Subscriptions map[string]*MailboxStatus } type MailboxRenderData struct { @@ -89,17 +90,22 @@ type MailboxRenderData struct { Query string } +type MailboxDetails struct { + Info *MailboxInfo + Status *MailboxStatus +} + // 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 + Inbox MailboxDetails + Drafts MailboxDetails + Sent MailboxDetails + Junk MailboxDetails + Trash MailboxDetails + Archive MailboxDetails + } + Additional []MailboxDetails } func newIMAPBaseRenderData(ctx *alps.Context, @@ -110,6 +116,12 @@ func newIMAPBaseRenderData(ctx *alps.Context, return nil, echo.NewHTTPError(http.StatusBadRequest, err) } + settings, err := loadSettings(ctx.Session.Store()) + if err != nil { + return nil, fmt.Errorf("failed to load settings: %v", err) + } + + subscriptions := make(map[string]*MailboxStatus) var mailboxes []MailboxInfo var active, inbox *MailboxStatus err = ctx.Session.DoIMAP(func(c *imapclient.Client) error { @@ -117,11 +129,13 @@ func newIMAPBaseRenderData(ctx *alps.Context, if mailboxes, err = listMailboxes(c); err != nil { return err } + if mboxName != "" { if active, err = getMailboxStatus(c, mboxName); err != nil { return echo.NewHTTPError(http.StatusNotFound, err) } } + if mboxName == "INBOX" { inbox = active } else { @@ -129,6 +143,14 @@ func newIMAPBaseRenderData(ctx *alps.Context, return err } } + + for _, sub := range settings.Subscriptions { + if status, err := getMailboxStatus(c, sub); err != nil { + return err + } else { + subscriptions[sub] = status + } + } return nil }) if err != nil { @@ -136,7 +158,7 @@ func newIMAPBaseRenderData(ctx *alps.Context, } var categorized CategorizedMailboxes - mmap := map[string]**MailboxInfo{ + mmap := map[string]*MailboxDetails{ "INBOX": &categorized.Common.Inbox, "Drafts": &categorized.Common.Drafts, "Sent": &categorized.Common.Sent, @@ -157,11 +179,16 @@ func newIMAPBaseRenderData(ctx *alps.Context, mailboxes[i].Total = int(inbox.Messages) } + status, _ := subscriptions[mailboxes[i].Name] if ptr, ok := mmap[mailboxes[i].Name]; ok { - *ptr = &mailboxes[i] + ptr.Info = &mailboxes[i] + ptr.Status = status } else { - categorized.Additional = append( - categorized.Additional, &mailboxes[i]) + categorized.Additional = append(categorized.Additional, + MailboxDetails{ + Info: &mailboxes[i], + Status: status, + }) } } @@ -171,6 +198,7 @@ func newIMAPBaseRenderData(ctx *alps.Context, Mailboxes: mailboxes, Inbox: inbox, Mailbox: active, + Subscriptions: subscriptions, }, nil } @@ -1156,6 +1184,7 @@ type Settings struct { MessagesPerPage int Signature string From string + Subscriptions []string } func loadSettings(s alps.Store) (*Settings, error) { @@ -1186,7 +1215,20 @@ func (s *Settings) check() error { type SettingsRenderData struct { alps.BaseRenderData - Settings *Settings + Mailboxes []MailboxInfo + Settings *Settings + Subscriptions Subscriptions +} + +type Subscriptions []string + +func (s Subscriptions) Has(sub string) bool { + for _, cand := range s { + if cand == sub { + return true + } + } + return false } func handleSettings(ctx *alps.Context) error { @@ -1195,6 +1237,15 @@ func handleSettings(ctx *alps.Context) error { return fmt.Errorf("failed to load settings: %v", err) } + var mailboxes []MailboxInfo + err = ctx.Session.DoIMAP(func(c *imapclient.Client) error { + mailboxes, err = listMailboxes(c) + return err + }) + if err != nil { + return err + } + if ctx.Request().Method == http.MethodPost { settings.MessagesPerPage, err = strconv.Atoi(ctx.FormValue("messages_per_page")) if err != nil { @@ -1203,6 +1254,12 @@ func handleSettings(ctx *alps.Context) error { settings.Signature = ctx.FormValue("signature") settings.From = ctx.FormValue("from") + params, err := ctx.FormParams() + if err != nil { + return err + } + settings.Subscriptions = params["subscriptions"] + if err := settings.check(); err != nil { return echo.NewHTTPError(http.StatusBadRequest, err) } @@ -1216,5 +1273,7 @@ func handleSettings(ctx *alps.Context) error { return ctx.Render(http.StatusOK, "settings.html", &SettingsRenderData{ BaseRenderData: *alps.NewBaseRenderData(ctx), Settings: settings, + Mailboxes: mailboxes, + Subscriptions: Subscriptions(settings.Subscriptions), }) } diff --git a/themes/alps/assets/style.css b/themes/alps/assets/style.css index e64c8a3..d652f66 100644 --- a/themes/alps/assets/style.css +++ b/themes/alps/assets/style.css @@ -88,7 +88,8 @@ input[type="file"], input[type="number"], input[type="date"], input[type="time"], -textarea { +textarea, +select { margin: 0; border: none; border: 1px solid #e0e0e0; @@ -157,7 +158,7 @@ aside ul { aside li { width: 100%; display: flex; - padding: 0.4rem 0 0.4rem 0.5rem; + padding: 0.4rem 0.5rem; } aside li a { @@ -654,7 +655,8 @@ main table tfoot { .action-group label, .action-group input, -.action-group textarea { +.action-group textarea, +.action-group select { display: block; width: 100%; } @@ -665,6 +667,10 @@ main table tfoot { float: left; } +.action-group select { + height: 10rem; +} + .actions-message, .actions-contacts { display: flex; diff --git a/themes/alps/settings.html b/themes/alps/settings.html index 9fc58ca..61e76e6 100644 --- a/themes/alps/settings.html +++ b/themes/alps/settings.html @@ -33,6 +33,23 @@ </div> <div class="action-group"> + <label for="subscriptions">Subscribed folders</label> + <select name="subscriptions" id="subscriptions" multiple> + {{ $subs := .Subscriptions }} + {{ range .Mailboxes }} + {{ if and (ne .Name "INBOX") (not (.HasAttr "\\Noselect")) }} + <option + value="{{.Name}}" + {{ if $subs.Has .Name }} + selected + {{ end }} + >{{.Name}}</option> + {{ end }} + {{ end }} + </select> + </div> + + <div class="action-group"> <label for="messages_per_page">Messages per page</label> <input type="number" diff --git a/themes/alps/util.html b/themes/alps/util.html index 535714f..9cdfd86 100644 --- a/themes/alps/util.html +++ b/themes/alps/util.html @@ -1,43 +1,28 @@ {{ define "mbox-link" }} -{{ if not (.HasAttr "\\Noselect") }} -<li {{ if .Active }}class="active"{{ end }}> - <a href="{{.URL}}"> - {{- if eq .Name "INBOX" -}} +{{ if not (.Info.HasAttr "\\Noselect") }} +<li {{ if .Info.Active }}class="active"{{ end }}> + <a href="{{.Info.URL}}"> + {{- if eq .Info.Name "INBOX" -}} Inbox {{- else -}} - {{ .Name }} + {{ .Info.Name }} {{- end -}} - {{- if .HasAttr "\\HasChildren" }}/{{ end }} + {{- if .Info.HasAttr "\\HasChildren" }}/{{ end }} </a> - <!-- TODO - <button - type="submit" - name="subscribe" - value="{{.Name}}" - form="subscribe-form" - {{ if eq .Name "INBOX" }} - title="Unsubscribe" - {{ else }} - title="Subscribe" - {{ end }} - > - {{ if eq .Name "INBOX" }} - ◉ - {{ else }} - ○ + {{ if .Status }} + {{ if .Status.Unseen }} + <span class="unseen">({{.Status.Unseen}})</span> + {{ end }} {{ end }} - </button> - --> </li> {{ else }} <li class="noselect"> - {{.Name}}{{- if .HasAttr "\\HasChildren" }}/{{ end }} + {{.Info.Name}}{{- if .Info.HasAttr "\\HasChildren" }}/{{ end }} </li> {{ end }} {{ end }} {{ define "aside" }} -<form id="subscribe-form" method="POST"></form> <aside> <ul> <!-- the logo image, dimensions 200x32 may be present or not --> |