diff options
author | r <r@freesoftwareextremist.com> | 2019-12-27 08:06:43 +0000 |
---|---|---|
committer | r <r@freesoftwareextremist.com> | 2019-12-27 08:09:40 +0000 |
commit | b9d7eb05beb57926181f91685a75b3069d1f8cf8 (patch) | |
tree | 1aa0b5a28fd8cc0c3fc425c227eb747d8528c910 | |
parent | 14bb18fbc7e6cdea57f27a44093d645d97bacb64 (diff) | |
download | bloat-b9d7eb05beb57926181f91685a75b3069d1f8cf8.tar.gz bloat-b9d7eb05beb57926181f91685a75b3069d1f8cf8.zip |
Add settings page
-rw-r--r-- | model/settings.go | 1 | ||||
-rw-r--r-- | renderer/model.go | 15 | ||||
-rw-r--r-- | renderer/renderer.go | 5 | ||||
-rw-r--r-- | service/auth.go | 16 | ||||
-rw-r--r-- | service/logging.go | 16 | ||||
-rw-r--r-- | service/service.go | 56 | ||||
-rw-r--r-- | service/transport.go | 31 | ||||
-rw-r--r-- | static/main.css | 16 | ||||
-rw-r--r-- | templates/navigation.tmpl | 1 | ||||
-rw-r--r-- | templates/postform.tmpl | 2 | ||||
-rw-r--r-- | templates/settings.tmpl | 22 |
11 files changed, 165 insertions, 16 deletions
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 @@ <a class="nav-link" href="/about">about</a> </div> <div> + <a class="nav-link" href="/settings">settings</a> <a class="nav-link" href="/signout">sign out</a> </div> </div> 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 @@ </span> {{end}} <span class="post-form-field"> - <label for="post-visilibity"> Visibility </label> + <label for="post-visilibity"> Scope </label> <select id="post-visilibity" name="visibility"> <option value="public" {{if eq .DefaultVisibility "public"}}selected{{end}}>Public</option> <option value="unlisted" {{if eq .DefaultVisibility "unlisted"}}selected{{end}}>Unlisted</option> diff --git a/templates/settings.tmpl b/templates/settings.tmpl new file mode 100644 index 0000000..e2fd778 --- /dev/null +++ b/templates/settings.tmpl @@ -0,0 +1,22 @@ +{{template "header.tmpl" .HeaderData}} +{{template "navigation.tmpl" .NavbarData}} +<div class="page-title"> Settings </div> + +<form id="settings-form" action="/settings" method="POST"> + <div class="settings-form-field"> + <label for="visibility"> Default scope </label> + <select id="visibility" name="visibility"> + <option value="public" {{if eq .Settings.DefaultVisibility "public"}}selected{{end}}>Public</option> + <option value="unlisted" {{if eq .Settings.DefaultVisibility "unlisted"}}selected{{end}}>Unlisted</option> + <option value="private" {{if eq .Settings.DefaultVisibility "private"}}selected{{end}}>Private</option> + <option value="direct" {{if eq .Settings.DefaultVisibility "direct"}}selected{{end}}>Direct</option> + </select> + </div> + <div class="settings-form-field"> + <input id="copy-scope" name="copy_scope" type="checkbox" value="true" {{if .Settings.CopyScope}}checked{{end}}> + <label for="copy-scope"> Copy scope when replying </label> + </div> + <button type="submit"> Save </button> +</form> + +{{template "footer.tmpl"}} |