diff --git a/plugins/base/imap.go b/plugins/base/imap.go
index 0c36baa..e7b526e 100755
--- a/plugins/base/imap.go
+++ b/plugins/base/imap.go
@@ -237,7 +237,7 @@ func (msg *IMAPMessage) HasFlag(flag string) bool {
return false
}
-func listMessages(conn *imapclient.Client, mboxName string, page int) ([]IMAPMessage, error) {
+func listMessages(conn *imapclient.Client, mboxName string, page, messagesPerPage int) ([]IMAPMessage, error) {
if err := ensureMailboxSelected(conn, mboxName); err != nil {
return nil, err
}
@@ -281,7 +281,7 @@ func listMessages(conn *imapclient.Client, mboxName string, page int) ([]IMAPMes
return msgs, nil
}
-func searchMessages(conn *imapclient.Client, mboxName, query string, page int) (msgs []IMAPMessage, total int, err error) {
+func searchMessages(conn *imapclient.Client, mboxName, query string, page, messagesPerPage int) (msgs []IMAPMessage, total int, err error) {
if err := ensureMailboxSelected(conn, mboxName); err != nil {
return nil, 0, err
}
diff --git a/plugins/base/plugin.go b/plugins/base/plugin.go
index 16eaf1d..5743977 100644
--- a/plugins/base/plugin.go
+++ b/plugins/base/plugin.go
@@ -4,8 +4,6 @@ import (
"git.sr.ht/~emersion/koushin"
)
-const messagesPerPage = 50
-
func init() {
p := koushin.GoPlugin{Name: "base"}
diff --git a/plugins/base/public/mailbox.html b/plugins/base/public/mailbox.html
index d19c73d..9e2a0a2 100644
--- a/plugins/base/public/mailbox.html
+++ b/plugins/base/public/mailbox.html
@@ -3,7 +3,9 @@
koushin
- Logout · Compose
+ Logout
+ · Compose
+ · Settings
{{.Mailbox.Name}}
diff --git a/plugins/base/public/settings.html b/plugins/base/public/settings.html
new file mode 100644
index 0000000..c0d715c
--- /dev/null
+++ b/plugins/base/public/settings.html
@@ -0,0 +1,18 @@
+{{template "head.html"}}
+
+koushin
+
+
+ Back
+
+
+Settings
+
+
+
+{{template "foot.html"}}
diff --git a/plugins/base/routes.go b/plugins/base/routes.go
index f7b85e6..ec22d1b 100644
--- a/plugins/base/routes.go
+++ b/plugins/base/routes.go
@@ -55,6 +55,9 @@ func registerRoutes(p *koushin.GoPlugin) {
p.POST("/message/:mbox/:uid/delete", handleDelete)
p.POST("/message/:mbox/:uid/flag", handleSetFlags)
+
+ p.GET("/settings", handleSettings)
+ p.POST("/settings", handleSettings)
}
type MailboxRenderData struct {
@@ -80,6 +83,12 @@ func handleGetMailbox(ctx *koushin.Context) error {
}
}
+ settings, err := loadSettings(ctx.Session.Store())
+ if err != nil {
+ return err
+ }
+ messagesPerPage := settings.MessagesPerPage
+
query := ctx.QueryParam("query")
var mailboxes []*imap.MailboxInfo
@@ -92,9 +101,9 @@ func handleGetMailbox(ctx *koushin.Context) error {
return err
}
if query != "" {
- msgs, total, err = searchMessages(c, mboxName, query, page)
+ msgs, total, err = searchMessages(c, mboxName, query, page, messagesPerPage)
} else {
- msgs, err = listMessages(c, mboxName, page)
+ msgs, err = listMessages(c, mboxName, page, messagesPerPage)
}
if err != nil {
return err
@@ -185,6 +194,12 @@ func handleGetPart(ctx *koushin.Context, raw bool) error {
return echo.NewHTTPError(http.StatusBadRequest, err)
}
+ settings, err := loadSettings(ctx.Session.Store())
+ if err != nil {
+ return err
+ }
+ messagesPerPage := settings.MessagesPerPage
+
var mailboxes []*imap.MailboxInfo
var msg *IMAPMessage
var part *message.Entity
@@ -685,3 +700,63 @@ func handleSetFlags(ctx *koushin.Context) error {
return ctx.Redirect(http.StatusFound, fmt.Sprintf("/message/%v/%v", url.PathEscape(mboxName), uid))
}
+
+const settingsKey = "base.settings"
+const maxMessagesPerPage = 100
+
+type Settings struct {
+ MessagesPerPage int
+}
+
+func loadSettings(s koushin.Store) (*Settings, error) {
+ settings := &Settings{
+ MessagesPerPage: 50,
+ }
+ if err := s.Get(settingsKey, settings); err != nil && err != koushin.ErrNoStoreEntry {
+ return nil, err
+ }
+ if err := settings.check(); err != nil {
+ return nil, err
+ }
+ return settings, nil
+}
+
+func (s *Settings) check() error {
+ if s.MessagesPerPage <= 0 || s.MessagesPerPage > maxMessagesPerPage {
+ return fmt.Errorf("messages per page out of bounds: %v", s.MessagesPerPage)
+ }
+ return nil
+}
+
+type SettingsRenderData struct {
+ koushin.BaseRenderData
+ Settings *Settings
+}
+
+func handleSettings(ctx *koushin.Context) error {
+ settings, err := loadSettings(ctx.Session.Store())
+ if err != nil {
+ return fmt.Errorf("failed to load settings: %v", err)
+ }
+
+ if ctx.Request().Method == http.MethodPost {
+ settings.MessagesPerPage, err = strconv.Atoi(ctx.FormValue("messages_per_page"))
+ if err != nil {
+ return echo.NewHTTPError(http.StatusBadRequest, "invalid messages per page: %v", err)
+ }
+
+ if err := settings.check(); err != nil {
+ return echo.NewHTTPError(http.StatusBadRequest, err)
+ }
+ if err := ctx.Session.Store().Put(settingsKey, settings); err != nil {
+ return fmt.Errorf("failed to save settings: %v", err)
+ }
+
+ return ctx.Redirect(http.StatusFound, "/mailbox/INBOX")
+ }
+
+ return ctx.Render(http.StatusOK, "settings.html", &SettingsRenderData{
+ BaseRenderData: *koushin.NewBaseRenderData(ctx),
+ Settings: settings,
+ })
+}