Update user page
authorr <r@freesoftwareextremist.com>
Fri, 31 Jan 2020 03:38:49 +0000 (03:38 +0000)
committerr <r@freesoftwareextremist.com>
Fri, 31 Jan 2020 03:38:49 +0000 (03:38 +0000)
- Use the same page to display status and user list
- Add media only status list

mastodon/accounts.go
renderer/model.go
renderer/renderer.go
service/auth.go
service/logging.go
service/service.go
service/transport.go
templates/followers.tmpl [deleted file]
templates/following.tmpl [deleted file]
templates/user.tmpl

index 8cee6bbef32a4b0b701806c132168325ab4bb3c4..86581ece3a6e2fedddcf58ed8475da44cfea10d7 100644 (file)
@@ -133,9 +133,11 @@ func (c *Client) AccountUpdate(ctx context.Context, profile *Profile) (*Account,
 }
 
 // GetAccountStatuses return statuses by specified accuont.
-func (c *Client) GetAccountStatuses(ctx context.Context, id string, pg *Pagination) ([]*Status, error) {
+func (c *Client) GetAccountStatuses(ctx context.Context, id string, onlyMedia bool, pg *Pagination) ([]*Status, error) {
        var statuses []*Status
-       err := c.doAPI(ctx, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/statuses", url.PathEscape(string(id))), nil, &statuses, pg)
+       params := url.Values{}
+       params.Set("only_media", strconv.FormatBool(onlyMedia))
+       err := c.doAPI(ctx, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/statuses", url.PathEscape(string(id))), params, &statuses, pg)
        if err != nil {
                return nil, err
        }
index 77e67048945faf93441c5ffa95e7ffd50f532924..2aa2f22b8d553cf29598e7a006367ca2db8dd96f 100644 (file)
@@ -69,6 +69,8 @@ type NotificationData struct {
 type UserData struct {
        *CommonData
        User     *mastodon.Account
+       Type     string
+       Users    []*mastodon.Account
        Statuses []*mastodon.Status
        NextLink string
        DarkMode bool
@@ -103,18 +105,6 @@ type RetweetedByData struct {
        NextLink string
 }
 
-type FollowingData struct {
-       *CommonData
-       Users    []*mastodon.Account
-       NextLink string
-}
-
-type FollowersData struct {
-       *CommonData
-       Users    []*mastodon.Account
-       NextLink string
-}
-
 type SearchData struct {
        *CommonData
        Q        string
index cbb6c73928f2950352eaa2c9f721bf01f2ab28ac..5e03158d18cf7bf90bfe4e32e311fb5fcdb518f9 100644 (file)
@@ -28,8 +28,6 @@ type Renderer interface {
        RenderEmojiPage(ctx *Context, writer io.Writer, data *EmojiData) (err error)
        RenderLikedByPage(ctx *Context, writer io.Writer, data *LikedByData) (err error)
        RenderRetweetedByPage(ctx *Context, writer io.Writer, data *RetweetedByData) (err error)
-       RenderFollowingPage(ctx *Context, writer io.Writer, data *FollowingData) (err error)
-       RenderFollowersPage(ctx *Context, writer io.Writer, data *FollowersData) (err error)
        RenderSearchPage(ctx *Context, writer io.Writer, data *SearchData) (err error)
        RenderSettingsPage(ctx *Context, writer io.Writer, data *SettingsData) (err error)
 }
@@ -113,16 +111,6 @@ func (r *renderer) RenderRetweetedByPage(ctx *Context, writer io.Writer,
        return r.template.ExecuteTemplate(writer, "retweetedby.tmpl", WithContext(data, ctx))
 }
 
-func (r *renderer) RenderFollowingPage(ctx *Context, writer io.Writer,
-       data *FollowingData) (err error) {
-       return r.template.ExecuteTemplate(writer, "following.tmpl", WithContext(data, ctx))
-}
-
-func (r *renderer) RenderFollowersPage(ctx *Context, writer io.Writer,
-       data *FollowersData) (err error) {
-       return r.template.ExecuteTemplate(writer, "followers.tmpl", WithContext(data, ctx))
-}
-
 func (r *renderer) RenderSearchPage(ctx *Context, writer io.Writer,
        data *SearchData) (err error) {
        return r.template.ExecuteTemplate(writer, "search.tmpl", WithContext(data, ctx))
index f127f5cbf69c95ef2fa2146bd38e43b706d7ec33..bc4ddbfbf8bf5717c79f26463c4c2cf3170add10 100644 (file)
@@ -101,24 +101,6 @@ func (s *as) ServeRetweetedByPage(ctx context.Context, c *model.Client, id strin
        return s.Service.ServeRetweetedByPage(ctx, c, id)
 }
 
-func (s *as) ServeFollowingPage(ctx context.Context, c *model.Client, id string,
-       maxID string, minID string) (err error) {
-       err = s.authenticateClient(ctx, c)
-       if err != nil {
-               return
-       }
-       return s.Service.ServeFollowingPage(ctx, c, id, maxID, minID)
-}
-
-func (s *as) ServeFollowersPage(ctx context.Context, c *model.Client, id string,
-       maxID string, minID string) (err error) {
-       err = s.authenticateClient(ctx, c)
-       if err != nil {
-               return
-       }
-       return s.Service.ServeFollowersPage(ctx, c, id, maxID, minID)
-}
-
 func (s *as) ServeNotificationPage(ctx context.Context, c *model.Client,
        maxID string, minID string) (err error) {
        err = s.authenticateClient(ctx, c)
@@ -128,13 +110,13 @@ func (s *as) ServeNotificationPage(ctx context.Context, c *model.Client,
        return s.Service.ServeNotificationPage(ctx, c, maxID, minID)
 }
 
-func (s *as) ServeUserPage(ctx context.Context, c *model.Client, id string,
-       maxID string, minID string) (err error) {
+func (s *as) ServeUserPage(ctx context.Context, c *model.Client, id string, 
+       pageType string, maxID string, minID string) (err error) {
        err = s.authenticateClient(ctx, c)
        if err != nil {
                return
        }
-       return s.Service.ServeUserPage(ctx, c, id, maxID, minID)
+       return s.Service.ServeUserPage(ctx, c, id, pageType, maxID, minID)
 }
 
 func (s *as) ServeAboutPage(ctx context.Context, c *model.Client) (err error) {
index edd1035c4a9ead6f4627dfcc85c3558b944720b8..3d2baba4b87fce0ba36d03b192a35a99c7355c3b 100644 (file)
@@ -68,24 +68,6 @@ func (s *ls) ServeRetweetedByPage(ctx context.Context, c *model.Client, id strin
        return s.Service.ServeRetweetedByPage(ctx, c, id)
 }
 
-func (s *ls) ServeFollowingPage(ctx context.Context, c *model.Client, id string,
-       maxID string, minID string) (err error) {
-       defer func(begin time.Time) {
-               s.logger.Printf("method=%v, id=%v, took=%v, err=%v\n",
-                       "ServeFollowingPage", id, time.Since(begin), err)
-       }(time.Now())
-       return s.Service.ServeFollowingPage(ctx, c, id, maxID, minID)
-}
-
-func (s *ls) ServeFollowersPage(ctx context.Context, c *model.Client, id string,
-       maxID string, minID string) (err error) {
-       defer func(begin time.Time) {
-               s.logger.Printf("method=%v, id=%v, took=%v, err=%v\n",
-                       "ServeFollowersPage", id, time.Since(begin), err)
-       }(time.Now())
-       return s.Service.ServeFollowersPage(ctx, c, id, maxID, minID)
-}
-
 func (s *ls) ServeNotificationPage(ctx context.Context, c *model.Client,
        maxID string, minID string) (err error) {
        defer func(begin time.Time) {
@@ -95,13 +77,13 @@ func (s *ls) ServeNotificationPage(ctx context.Context, c *model.Client,
        return s.Service.ServeNotificationPage(ctx, c, maxID, minID)
 }
 
-func (s *ls) ServeUserPage(ctx context.Context, c *model.Client, id string,
-       maxID string, minID string) (err error) {
+func (s *ls) ServeUserPage(ctx context.Context, c *model.Client, id string, 
+       pageType string, maxID string, minID string) (err error) {
        defer func(begin time.Time) {
-               s.logger.Printf("method=%v, id=%v, took=%v, err=%v\n",
-                       "ServeUserPage", id, time.Since(begin), err)
+               s.logger.Printf("method=%v, id=%v, type=%v, took=%v, err=%v\n",
+                       "ServeUserPage", id, pageType, time.Since(begin), err)
        }(time.Now())
-       return s.Service.ServeUserPage(ctx, c, id, maxID, minID)
+       return s.Service.ServeUserPage(ctx, c, id, pageType, maxID, minID)
 }
 
 func (s *ls) ServeAboutPage(ctx context.Context, c *model.Client) (err error) {
index fe025b820dbe46423206bf5613c64b940f59ce4b..ae480d18177698ad6db94eb33a0ab02c6163878c 100644 (file)
@@ -25,10 +25,9 @@ type Service interface {
        ServeThreadPage(ctx context.Context, c *model.Client, id string, reply bool) (err error)
        ServeLikedByPage(ctx context.Context, c *model.Client, id string) (err error)
        ServeRetweetedByPage(ctx context.Context, c *model.Client, id string) (err error)
-       ServeFollowingPage(ctx context.Context, c *model.Client, id string, maxID string, minID string) (err error)
-       ServeFollowersPage(ctx context.Context, c *model.Client, id string, maxID string, minID string) (err error)
        ServeNotificationPage(ctx context.Context, c *model.Client, maxID string, minID string) (err error)
-       ServeUserPage(ctx context.Context, c *model.Client, id string, maxID string, minID string) (err error)
+       ServeUserPage(ctx context.Context, c *model.Client, id string, pageType string,
+               maxID string, minID string) (err error)
        ServeAboutPage(ctx context.Context, c *model.Client) (err error)
        ServeEmojiPage(ctx context.Context, c *model.Client) (err error)
        ServeSearchPage(ctx context.Context, c *model.Client, q string, qType string, offset int) (err error)
@@ -407,73 +406,6 @@ func (svc *service) ServeRetweetedByPage(ctx context.Context, c *model.Client,
        return svc.renderer.RenderRetweetedByPage(rCtx, c.Writer, data)
 }
 
-func (svc *service) ServeFollowingPage(ctx context.Context, c *model.Client,
-       id string, maxID string, minID string) (err error) {
-
-       var nextLink string
-       var pg = mastodon.Pagination{
-               MaxID: maxID,
-               MinID: minID,
-               Limit: 20,
-       }
-
-       followings, err := c.GetAccountFollowing(ctx, id, &pg)
-       if err != nil {
-               return
-       }
-
-       if len(followings) == 20 && len(pg.MaxID) > 0 {
-               nextLink = "/following/" + id + "?max_id=" + pg.MaxID
-       }
-
-       commonData, err := svc.getCommonData(ctx, c, "following")
-       if err != nil {
-               return
-       }
-
-       data := &renderer.FollowingData{
-               CommonData: commonData,
-               Users:      followings,
-               NextLink:   nextLink,
-       }
-
-       rCtx := getRendererContext(c)
-       return svc.renderer.RenderFollowingPage(rCtx, c.Writer, data)
-}
-
-func (svc *service) ServeFollowersPage(ctx context.Context, c *model.Client,
-       id string, maxID string, minID string) (err error) {
-
-       var nextLink string
-       var pg = mastodon.Pagination{
-               MaxID: maxID,
-               MinID: minID,
-               Limit: 20,
-       }
-
-       followers, err := c.GetAccountFollowers(ctx, id, &pg)
-       if err != nil {
-               return
-       }
-
-       if len(followers) == 20 && len(pg.MaxID) > 0 {
-               nextLink = "/followers/" + id + "?max_id=" + pg.MaxID
-       }
-
-       commonData, err := svc.getCommonData(ctx, c, "followers")
-       if err != nil {
-               return
-       }
-
-       data := &renderer.FollowersData{
-               CommonData: commonData,
-               Users:      followers,
-               NextLink:   nextLink,
-       }
-       rCtx := getRendererContext(c)
-       return svc.renderer.RenderFollowersPage(rCtx, c.Writer, data)
-}
-
 func (svc *service) ServeNotificationPage(ctx context.Context, c *model.Client,
        maxID string, minID string) (err error) {
 
@@ -522,10 +454,11 @@ func (svc *service) ServeNotificationPage(ctx context.Context, c *model.Client,
 }
 
 func (svc *service) ServeUserPage(ctx context.Context, c *model.Client,
-       id string, maxID string, minID string) (err error) {
+       id string, pageType string, maxID string, minID string) (err error) {
 
        var nextLink string
-
+       var statuses []*mastodon.Status
+       var users []*mastodon.Account
        var pg = mastodon.Pagination{
                MaxID: maxID,
                MinID: minID,
@@ -537,13 +470,45 @@ func (svc *service) ServeUserPage(ctx context.Context, c *model.Client,
                return
        }
 
-       statuses, err := c.GetAccountStatuses(ctx, id, &pg)
-       if err != nil {
-               return
-       }
-
-       if len(pg.MaxID) > 0 {
-               nextLink = "/user/" + id + "?max_id=" + pg.MaxID
+       switch pageType {
+       case "":
+               statuses, err = c.GetAccountStatuses(ctx, id, false, &pg)
+               if err != nil {
+                       return
+               }
+               if len(statuses) == 20 && len(pg.MaxID) > 0 {
+                       nextLink = fmt.Sprintf("/user/%s?max_id=%s", id,
+                               pg.MaxID)
+               }
+       case "following":
+               users, err = c.GetAccountFollowing(ctx, id, &pg)
+               if err != nil {
+                       return
+               }
+               if len(users) == 20 && len(pg.MaxID) > 0 {
+                       nextLink = fmt.Sprintf("/user/%s/following?max_id=%s",
+                               id, pg.MaxID)
+               }
+       case "followers":
+               users, err = c.GetAccountFollowers(ctx, id, &pg)
+               if err != nil {
+                       return
+               }
+               if len(users) == 20 && len(pg.MaxID) > 0 {
+                       nextLink = fmt.Sprintf("/user/%s/followers?max_id=%s",
+                               id, pg.MaxID)
+               }
+       case "media":
+               statuses, err = c.GetAccountStatuses(ctx, id, true, &pg)
+               if err != nil {
+                       return
+               }
+               if len(statuses) == 20 && len(pg.MaxID) > 0 {
+                       nextLink = fmt.Sprintf("/user/%s/media?max_id=%s",
+                               id, pg.MaxID)
+               }
+       default:
+               return errInvalidArgument
        }
 
        commonData, err := svc.getCommonData(ctx, c, user.DisplayName)
@@ -553,6 +518,8 @@ func (svc *service) ServeUserPage(ctx context.Context, c *model.Client,
 
        data := &renderer.UserData{
                User:       user,
+               Type:       pageType,
+               Users:      users,
                Statuses:   statuses,
                NextLink:   nextLink,
                CommonData: commonData,
index b2fb4a876e03d70ff8892f900c704d69c50ac13d..d945e182f907c5725af457ddb935b4cefe295c01 100644 (file)
@@ -146,36 +146,6 @@ func NewHandler(s Service, staticDir string) http.Handler {
                }
        }
 
-       followingPage := func(w http.ResponseWriter, req *http.Request) {
-               c := newClient(w)
-               ctx := newCtxWithSesion(req)
-               id, _ := mux.Vars(req)["id"]
-               maxID := req.URL.Query().Get("max_id")
-               minID := req.URL.Query().Get("min_id")
-
-               err := s.ServeFollowingPage(ctx, c, id, maxID, minID)
-               if err != nil {
-                       w.WriteHeader(http.StatusInternalServerError)
-                       s.ServeErrorPage(ctx, c, err)
-                       return
-               }
-       }
-
-       followersPage := func(w http.ResponseWriter, req *http.Request) {
-               c := newClient(w)
-               ctx := newCtxWithSesion(req)
-               id, _ := mux.Vars(req)["id"]
-               maxID := req.URL.Query().Get("max_id")
-               minID := req.URL.Query().Get("min_id")
-
-               err := s.ServeFollowersPage(ctx, c, id, maxID, minID)
-               if err != nil {
-                       w.WriteHeader(http.StatusInternalServerError)
-                       s.ServeErrorPage(ctx, c, err)
-                       return
-               }
-       }
-
        notificationsPage := func(w http.ResponseWriter, req *http.Request) {
                c := newClient(w)
                ctx := newCtxWithSesion(req)
@@ -194,10 +164,11 @@ func NewHandler(s Service, staticDir string) http.Handler {
                c := newClient(w)
                ctx := newCtxWithSesion(req)
                id, _ := mux.Vars(req)["id"]
+               pageType, _ := mux.Vars(req)["type"]
                maxID := req.URL.Query().Get("max_id")
                minID := req.URL.Query().Get("min_id")
 
-               err := s.ServeUserPage(ctx, c, id, maxID, minID)
+               err := s.ServeUserPage(ctx, c, id, pageType, maxID, minID)
                if err != nil {
                        w.WriteHeader(http.StatusInternalServerError)
                        s.ServeErrorPage(ctx, c, err)
@@ -600,10 +571,9 @@ func NewHandler(s Service, staticDir string) http.Handler {
        r.HandleFunc("/thread/{id}", threadPage).Methods(http.MethodGet)
        r.HandleFunc("/likedby/{id}", likedByPage).Methods(http.MethodGet)
        r.HandleFunc("/retweetedby/{id}", retweetedByPage).Methods(http.MethodGet)
-       r.HandleFunc("/following/{id}", followingPage).Methods(http.MethodGet)
-       r.HandleFunc("/followers/{id}", followersPage).Methods(http.MethodGet)
        r.HandleFunc("/notifications", notificationsPage).Methods(http.MethodGet)
        r.HandleFunc("/user/{id}", userPage).Methods(http.MethodGet)
+       r.HandleFunc("/user/{id}/{type}", userPage).Methods(http.MethodGet)
        r.HandleFunc("/usersearch/{id}", userSearchPage).Methods(http.MethodGet)
        r.HandleFunc("/about", aboutPage).Methods(http.MethodGet)
        r.HandleFunc("/emojis", emojisPage).Methods(http.MethodGet)
diff --git a/templates/followers.tmpl b/templates/followers.tmpl
deleted file mode 100644 (file)
index 44a303b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{{with .Data}}
-{{template "header.tmpl" (WithContext .HeaderData $.Ctx)}}
-{{template "navigation.tmpl" (WithContext .NavbarData $.Ctx)}}
-<div class="page-title"> Followers </div>
-
-{{template "userlist.tmpl" (WithContext .Users $.Ctx)}}
-<div class="pagination">
-       {{if .NextLink}}
-               <a href="{{.NextLink}}">next</a>
-       {{end}}
-</div>
-
-{{template "footer.tmpl"}}
-{{end}}
diff --git a/templates/following.tmpl b/templates/following.tmpl
deleted file mode 100644 (file)
index 50413d5..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-{{with .Data}}
-{{template "header.tmpl" (WithContext .HeaderData $.Ctx)}}
-{{template "navigation.tmpl" (WithContext .NavbarData $.Ctx)}}
-<div class="page-title"> Following </div>
-
-{{template "userlist.tmpl" (WithContext .Users $.Ctx)}}
-<div class="pagination">
-       {{if .NextLink}}
-               <a href="{{.NextLink}}">next</a>
-       {{end}}
-</div>
-
-{{template "footer.tmpl"}}
-{{end}}
index e3cb7e8e3b177258f3a433a3c05ca2986a635738..30426720914db99da51cbeec605d84d0ca9e548f 100644 (file)
                        {{end}} 
                </div>
                <div>
-                       {{.User.StatusesCount}} statuses - 
-                       <a href="/following/{{.User.ID}}"> {{.User.FollowingCount}} following </a> - 
-                       <a href="/followers/{{.User.ID}}"> {{.User.FollowersCount}} followers </a>
+                       <a href="/user/{{.User.ID}}"> statuses ({{.User.StatusesCount}}) </a> - 
+                       <a href="/user/{{.User.ID}}/following"> following ({{.User.FollowingCount}}) </a> - 
+                       <a href="/user/{{.User.ID}}/followers"> followers ({{.User.FollowersCount}}) </a> - 
+                       <a href="/user/{{.User.ID}}/media"> media </a>
                </div>
                <div>
                        <a href="/usersearch/{{.User.ID}}"> search statuses </a>
 </div>
 </div>
 
+{{if eq .Type ""}}
+<div class="page-title"> Statuses </div>
 {{range .Statuses}}
 {{template "status.tmpl" (WithContext . $.Ctx)}}
 {{end}}
 
+{{else if eq .Type "following"}}
+<div class="page-title"> Following </div>
+{{template "userlist.tmpl" (WithContext .Users $.Ctx)}}
+
+{{else if eq .Type "followers"}}
+<div class="page-title"> Followers </div>
+{{template "userlist.tmpl" (WithContext .Users $.Ctx)}}
+
+{{else if eq .Type "media"}}
+<div class="page-title"> Statuses with media </div>
+{{range .Statuses}}
+{{template "status.tmpl" (WithContext . $.Ctx)}}
+{{end}}
+{{end}}
+
 <div class="pagination">
        {{if .NextLink}}
                <a href="{{.NextLink}}">next</a>