plugins/base: add settings page

Add a settings page where the user can change the number of messages
displayed per page.
This commit is contained in:
Simon Ser 2020-01-28 20:04:33 +01:00
parent bdf1a8b02b
commit 4d68400036
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
5 changed files with 100 additions and 7 deletions

View file

@ -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
}

View file

@ -4,8 +4,6 @@ import (
"git.sr.ht/~emersion/koushin"
)
const messagesPerPage = 50
func init() {
p := koushin.GoPlugin{Name: "base"}

View file

@ -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>

View file

@ -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"}}

View file

@ -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,
})
}