From b9d7eb05beb57926181f91685a75b3069d1f8cf8 Mon Sep 17 00:00:00 2001 From: r Date: Fri, 27 Dec 2019 08:06:43 +0000 Subject: [PATCH] Add settings page --- model/settings.go | 1 + renderer/model.go | 15 +++++++---- renderer/renderer.go | 5 ++++ service/auth.go | 16 +++++++++++ service/logging.go | 16 +++++++++++ service/service.go | 56 ++++++++++++++++++++++++++++++++------- service/transport.go | 31 ++++++++++++++++++++++ static/main.css | 16 +++++++++++ templates/navigation.tmpl | 1 + templates/postform.tmpl | 2 +- templates/settings.tmpl | 22 +++++++++++++++ 11 files changed, 165 insertions(+), 16 deletions(-) create mode 100644 templates/settings.tmpl diff --git a/model/settings.go b/model/settings.go index 7afe936..bc8f09f 100644 --- a/model/settings.go +++ b/model/settings.go @@ -2,4 +2,5 @@ package model type Settings struct { DefaultVisibility string `json:"default_visibility"` + CopyScope bool `json:"copy_scope"` } diff --git a/renderer/model.go b/renderer/model.go index ffeb2d1..12fa90f 100644 --- a/renderer/model.go +++ b/renderer/model.go @@ -92,10 +92,15 @@ type RetweetedByData struct { type SearchData struct { *CommonData - Q string - Type string - Users []*mastodon.Account - Statuses []*mastodon.Status - HasNext bool + Q string + Type string + Users []*mastodon.Account + Statuses []*mastodon.Status + HasNext bool NextLink string } + +type SettingsData struct { + *CommonData + Settings *model.Settings +} diff --git a/renderer/renderer.go b/renderer/renderer.go index 5e5f005..a46cfd2 100644 --- a/renderer/renderer.go +++ b/renderer/renderer.go @@ -24,6 +24,7 @@ type Renderer interface { RenderLikedByPage(ctx context.Context, writer io.Writer, data *LikedByData) (err error) RenderRetweetedByPage(ctx context.Context, writer io.Writer, data *RetweetedByData) (err error) RenderSearchPage(ctx context.Context, writer io.Writer, data *SearchData) (err error) + RenderSettingsPage(ctx context.Context, writer io.Writer, data *SettingsData) (err error) } type renderer struct { @@ -96,6 +97,10 @@ func (r *renderer) RenderSearchPage(ctx context.Context, writer io.Writer, data return r.template.ExecuteTemplate(writer, "search.tmpl", data) } +func (r *renderer) RenderSettingsPage(ctx context.Context, writer io.Writer, data *SettingsData) (err error) { + return r.template.ExecuteTemplate(writer, "settings.tmpl", data) +} + func EmojiFilter(content string, emojis []mastodon.Emoji) string { var replacements []string for _, e := range emojis { diff --git a/service/auth.go b/service/auth.go index 431e093..4d1b5af 100644 --- a/service/auth.go +++ b/service/auth.go @@ -157,6 +157,22 @@ func (s *authService) ServeSearchPage(ctx context.Context, client io.Writer, c * return s.Service.ServeSearchPage(ctx, client, c, q, qType, offset) } +func (s *authService) ServeSettingsPage(ctx context.Context, client io.Writer, c *model.Client) (err error) { + c, err = s.getClient(ctx) + if err != nil { + return + } + return s.Service.ServeSettingsPage(ctx, client, c) +} + +func (s *authService) SaveSettings(ctx context.Context, client io.Writer, c *model.Client, settings *model.Settings) (err error) { + c, err = s.getClient(ctx) + if err != nil { + return + } + return s.Service.SaveSettings(ctx, client, c, settings) +} + func (s *authService) Like(ctx context.Context, client io.Writer, c *model.Client, id string) (err error) { c, err = s.getClient(ctx) if err != nil { diff --git a/service/logging.go b/service/logging.go index a5ffd57..cfd3654 100644 --- a/service/logging.go +++ b/service/logging.go @@ -133,6 +133,22 @@ func (s *loggingService) ServeSearchPage(ctx context.Context, client io.Writer, return s.Service.ServeSearchPage(ctx, client, c, q, qType, offset) } +func (s *loggingService) ServeSettingsPage(ctx context.Context, client io.Writer, c *model.Client) (err error) { + defer func(begin time.Time) { + s.logger.Printf("method=%v, took=%v, err=%v\n", + "ServeSettingsPage", time.Since(begin), err) + }(time.Now()) + return s.Service.ServeSettingsPage(ctx, client, c) +} + +func (s *loggingService) SaveSettings(ctx context.Context, client io.Writer, c *model.Client, settings *model.Settings) (err error) { + defer func(begin time.Time) { + s.logger.Printf("method=%v, took=%v, err=%v\n", + "SaveSettings", time.Since(begin), err) + }(time.Now()) + return s.Service.SaveSettings(ctx, client, c, settings) +} + func (s *loggingService) Like(ctx context.Context, client io.Writer, c *model.Client, id string) (err error) { defer func(begin time.Time) { s.logger.Printf("method=%v, id=%v, took=%v, err=%v\n", diff --git a/service/service.go b/service/service.go index 157ddf8..bf7967d 100644 --- a/service/service.go +++ b/service/service.go @@ -40,6 +40,8 @@ type Service interface { ServeLikedByPage(ctx context.Context, client io.Writer, c *model.Client, id string) (err error) ServeRetweetedByPage(ctx context.Context, client io.Writer, c *model.Client, id string) (err error) ServeSearchPage(ctx context.Context, client io.Writer, c *model.Client, q string, qType string, offset int) (err error) + ServeSettingsPage(ctx context.Context, client io.Writer, c *model.Client) (err error) + SaveSettings(ctx context.Context, client io.Writer, c *model.Client, settings *model.Settings) (err error) Like(ctx context.Context, client io.Writer, c *model.Client, id string) (err error) UnLike(ctx context.Context, client io.Writer, c *model.Client, id string) (err error) Retweet(ctx context.Context, client io.Writer, c *model.Client, id string) (err error) @@ -350,13 +352,19 @@ func (svc *service) ServeThreadPage(ctx context.Context, client io.Writer, c *mo } } - s, err := c.GetStatus(ctx, id) - if err != nil { - return err + var visibility string + if c.Session.Settings.CopyScope { + s, err := c.GetStatus(ctx, id) + if err != nil { + return err + } + visibility = s.Visibility + } else { + visibility = c.Session.Settings.DefaultVisibility } postContext = model.PostContext{ - DefaultVisibility: s.Visibility, + DefaultVisibility: visibility, Formats: svc.postFormats, ReplyContext: &model.ReplyContext{ InReplyToID: id, @@ -639,6 +647,40 @@ func (svc *service) ServeSearchPage(ctx context.Context, client io.Writer, c *mo return } +func (svc *service) ServeSettingsPage(ctx context.Context, client io.Writer, c *model.Client) (err error) { + commonData, err := svc.getCommonData(ctx, client, c) + if err != nil { + return + } + + data := &renderer.SettingsData{ + CommonData: commonData, + Settings: &c.Session.Settings, + } + + err = svc.renderer.RenderSettingsPage(ctx, client, data) + if err != nil { + return + } + + return +} + +func (svc *service) SaveSettings(ctx context.Context, client io.Writer, c *model.Client, settings *model.Settings) (err error) { + session, err := svc.sessionRepo.Get(c.Session.ID) + if err != nil { + return + } + + session.Settings = *settings + err = svc.sessionRepo.Add(session) + if err != nil { + return + } + + return +} + func (svc *service) getCommonData(ctx context.Context, client io.Writer, c *model.Client) (data *renderer.CommonData, err error) { data = new(renderer.CommonData) @@ -707,12 +749,6 @@ func (svc *service) PostTweet(ctx context.Context, client io.Writer, c *model.Cl mediaIds = append(mediaIds, a.ID) } - // save visibility if it's a non-reply post - if len(replyToID) < 1 && visibility != c.Session.Settings.DefaultVisibility { - c.Session.Settings.DefaultVisibility = visibility - svc.sessionRepo.Add(c.Session) - } - tweet := &mastodon.Toot{ Status: content, InReplyToID: replyToID, diff --git a/service/transport.go b/service/transport.go index c42462f..3ab2546 100644 --- a/service/transport.go +++ b/service/transport.go @@ -7,6 +7,7 @@ import ( "net/http" "path" "strconv" + "web/model" "github.com/gorilla/mux" ) @@ -305,6 +306,36 @@ func NewHandler(s Service, staticDir string) http.Handler { } }).Methods(http.MethodGet) + r.HandleFunc("/settings", func(w http.ResponseWriter, req *http.Request) { + ctx := getContextWithSession(context.Background(), req) + + err := s.ServeSettingsPage(ctx, w, nil) + if err != nil { + s.ServeErrorPage(ctx, w, err) + return + } + }).Methods(http.MethodGet) + + r.HandleFunc("/settings", func(w http.ResponseWriter, req *http.Request) { + ctx := getContextWithSession(context.Background(), req) + + visibility := req.FormValue("visibility") + copyScope := req.FormValue("copy_scope") == "true" + settings := &model.Settings{ + DefaultVisibility: visibility, + CopyScope: copyScope, + } + + err := s.SaveSettings(ctx, w, nil, settings) + if err != nil { + s.ServeErrorPage(ctx, w, err) + return + } + + w.Header().Add("Location", req.Header.Get("Referer")) + w.WriteHeader(http.StatusFound) + }).Methods(http.MethodPost) + r.HandleFunc("/signout", func(w http.ResponseWriter, req *http.Request) { // TODO remove session from database w.Header().Add("Set-Cookie", fmt.Sprintf("session_id=;max-age=0")) diff --git a/static/main.css b/static/main.css index 87e2cfa..f17a171 100644 --- a/static/main.css +++ b/static/main.css @@ -386,3 +386,19 @@ vertical-align: top; margin: 0 4px 8px 0; } + +#settings-form { + margin: 8px 0; +} + +.settings-form-field { + margin: 4px 0; +} + +.settings-form-field * { + vertical-align: middle; +} + +#settings-form button[type=submit] { + margin-top: 8px; +} diff --git a/templates/navigation.tmpl b/templates/navigation.tmpl index b82c7f5..fe83476 100644 --- a/templates/navigation.tmpl +++ b/templates/navigation.tmpl @@ -20,6 +20,7 @@ about
+ settings sign out
diff --git a/templates/postform.tmpl b/templates/postform.tmpl index 0e104b4..a79f86b 100644 --- a/templates/postform.tmpl +++ b/templates/postform.tmpl @@ -21,7 +21,7 @@ {{end}} - + + + + + + + +
+ + +
+ + + +{{template "footer.tmpl"}}