aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xplugins/base/imap.go4
-rw-r--r--plugins/base/plugin.go2
-rw-r--r--plugins/base/public/mailbox.html4
-rw-r--r--plugins/base/public/settings.html18
-rw-r--r--plugins/base/routes.go79
5 files changed, 100 insertions, 7 deletions
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 @@
<h1>koushin</h1>
<p>
- <a href="/logout">Logout</a> · <a href="/compose">Compose</a>
+ <a href="/logout">Logout</a>
+ · <a href="/compose">Compose</a>
+ · <a href="/settings">Settings</a>
</p>
<h2>{{.Mailbox.Name}}</h2>
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"}}
+
+<h1>koushin</h1>
+
+<p>
+ <a href="/mailbox/INBOX">Back</a>
+</p>
+
+<h2>Settings</h2>
+
+<form method="post" action="">
+ <label for="messages_per_page">Messages per page:</label>
+ <input type="number" name="messages_per_page" id="messages_per_page" required value="{{.Settings.MessagesPerPage}}">
+ <br><br>
+ <input type="submit" value="Save">
+</form>
+
+{{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,
+ })
+}