Add reply links on thread page
authorr <r@freesoftwareextremist.com>
Wed, 18 Dec 2019 22:14:02 +0000 (22:14 +0000)
committerr <r@freesoftwareextremist.com>
Wed, 18 Dec 2019 22:14:02 +0000 (22:14 +0000)
mastodon/status.go
model/status.go [new file with mode: 0644]
renderer/model.go
service/service.go
static/main.css
templates/status.tmpl
templates/thread.tmpl

index b6110d577ff2b3186660eeec1e83a13d488d1ff3..9f029d131fd19793985a91bfbd644e433b7db2a7 100644 (file)
@@ -10,6 +10,15 @@ import (
        "time"
 )
 
+type StatusPleroma struct {
+       InReplyToAccountAcct string `json:"in_reply_to_account_acct"`
+}
+
+type ReplyInfo struct {
+       ID     string `json:"id"`
+       Number int    `json:"number"`
+}
+
 // Status is struct to hold status.
 type Status struct {
        ID                 string       `json:"id"`
@@ -38,6 +47,13 @@ type Status struct {
        Application        Application  `json:"application"`
        Language           string       `json:"language"`
        Pinned             interface{}  `json:"pinned"`
+
+       // Custom fields
+       Pleroma         StatusPleroma          `json:"pleroma"`
+       HideAccountInfo bool                   `json:"hide_account_info"`
+       ShowReplies     bool                   `json:"show_replies"`
+       ReplyMap        map[string][]ReplyInfo `json:"reply_map"`
+       ReplyNumber     int                    `json:"reply_number"`
 }
 
 // Context hold information for mastodon context.
diff --git a/model/status.go b/model/status.go
new file mode 100644 (file)
index 0000000..8b53790
--- /dev/null
@@ -0,0 +1 @@
+package model
index 45293867e2babd9d3c8fbfa4a89d2c068db15ddd..2a320cc533956f7a9d6bca640637f2e1fbd8acc7 100644 (file)
@@ -36,21 +36,21 @@ func NewTimelinePageTemplateData(statuses []*mastodon.Status, hasNext bool, next
 }
 
 type ThreadPageTemplateData struct {
-       Status       *mastodon.Status
-       Context      *mastodon.Context
+       Statuses     []*mastodon.Status
        PostReply    bool
        ReplyToID    string
        ReplyContent string
+       ReplyMap     map[string][]mastodon.ReplyInfo
        NavbarData   *NavbarTemplateData
 }
 
-func NewThreadPageTemplateData(status *mastodon.Status, context *mastodon.Context, postReply bool, replyToID string, replyContent string, navbarData *NavbarTemplateData) *ThreadPageTemplateData {
+func NewThreadPageTemplateData(statuses []*mastodon.Status, postReply bool, replyToID string, replyContent string, replyMap map[string][]mastodon.ReplyInfo, navbarData *NavbarTemplateData) *ThreadPageTemplateData {
        return &ThreadPageTemplateData{
-               Status:       status,
-               Context:      context,
+               Statuses:     statuses,
                PostReply:    postReply,
                ReplyToID:    replyToID,
                ReplyContent: replyContent,
+               ReplyMap:     replyMap,
                NavbarData:   navbarData,
        }
 }
index bb03c263401347ed6e37b78c49229d62017e15d0..6c7a37d7746b9a43715aa6a46f79f7154f93cf92 100644 (file)
@@ -267,34 +267,46 @@ func (svc *service) ServeThreadPage(ctx context.Context, client io.Writer, c *ma
                return
        }
 
-       context, err := c.GetStatusContext(ctx, id)
-       if err != nil {
-               return
-       }
-
        u, err := c.GetAccountCurrentUser(ctx)
        if err != nil {
                return
        }
 
        var content string
+       var replyToID string
        if reply {
+               replyToID = id
                if u.ID != status.Account.ID {
                        content += "@" + status.Account.Acct + " "
                }
-               for _, m := range status.Mentions {
-                       if u.ID != m.ID {
-                               content += "@" + m.Acct + " "
+               for i := range status.Mentions {
+                       if status.Mentions[i].ID != u.ID && status.Mentions[i].ID != status.Account.ID {
+                               content += "@" + status.Mentions[i].Acct + " "
                        }
                }
        }
 
+       context, err := c.GetStatusContext(ctx, id)
+       if err != nil {
+               return
+       }
+
+       statuses := append(append(context.Ancestors, status), context.Descendants...)
+
+       replyMap := make(map[string][]mastodon.ReplyInfo)
+
+       for i := range statuses {
+               statuses[i].ShowReplies = true
+               statuses[i].ReplyMap = replyMap
+               addToReplyMap(replyMap, statuses[i].InReplyToID, statuses[i].ID, i+1)
+       }
+
        navbarData, err := svc.getNavbarTemplateData(ctx, client, c)
        if err != nil {
                return
        }
 
-       data := renderer.NewThreadPageTemplateData(status, context, reply, id, content, navbarData)
+       data := renderer.NewThreadPageTemplateData(statuses, reply, replyToID, content, replyMap, navbarData)
        err = svc.renderer.RenderThreadPage(ctx, client, data)
        if err != nil {
                return
@@ -323,7 +335,7 @@ func (svc *service) ServeNotificationPage(ctx context.Context, client io.Writer,
                switch notifications[i].Type {
                case "reblog", "favourite":
                        if notifications[i].Status != nil {
-                               notifications[i].Status.Account.ID = ""
+                               notifications[i].Status.HideAccountInfo = true
                        }
                }
                if notifications[i].Pleroma != nil && notifications[i].Pleroma.IsSeen {
@@ -418,3 +430,19 @@ func (svc *service) PostTweet(ctx context.Context, client io.Writer, c *mastodon
 
        return s.ID, nil
 }
+
+func addToReplyMap(m map[string][]mastodon.ReplyInfo, key interface{}, val string, number int) {
+       if key == nil {
+               return
+       }
+       keyStr, ok := key.(string)
+       if !ok {
+               return
+       }
+       _, ok = m[keyStr]
+       if !ok {
+               m[keyStr] = []mastodon.ReplyInfo{}
+       }
+
+       m[keyStr] = append(m[keyStr], mastodon.ReplyInfo{val, number})
+}
index 8865820c58b14a71ee62b5378a9dc5bcffb6e511..7f8cd90caf4a0a3f2d729c7384cdd37b6fc67cb0 100644 (file)
@@ -7,7 +7,7 @@
 }
 
 .status-content {
-       margin: 8px 0;
+       margin: 4px 0 8px 0;
 }
 
 .status-content p {
@@ -18,6 +18,7 @@
        height: 48px;
        width: 48px;
        margin-right: 8px;
+       object-fit: contain;
 }
 
 .status {
        height: 24px;
        width: 24px;
        margin-bottom: -8px;
+       margin-right: 0px;
 }
 
 .retweet-info .status-dname{
 .notification-follow-uname {
        margin-top: 8px;
 }
+
+.status-reply-to {
+       vertical-align: center;
+       font-size: 10pt
+}
+
+.status-reply-container .icon {
+       font-size: 10pt;
+       vertical-align: sub;
+       margin-right: -2px;
+}
+
+.status-reply-text {
+       font-size: 10pt;
+}
+
+.status-reply {
+       font-size: 10pt;
+}
+
+.status-reply-info-divider {
+       margin: 0 4px;
+}
index 7020be073025b2ab19d17dadbf88535474092b24..4dbbe3c255c5ae420a9707fa640e61ceb8ac9502 100644 (file)
        {{block "status" .}}
        <div class="status-container">
                <div>
-                       {{if ne .Account.ID ""}}
+                       {{if not .HideAccountInfo}}
                        <img class="status-profile-img" src="{{.Account.AvatarStatic}}" alt="profile-avatar" />
                        {{end}}
                </div>
                <div class="status"> 
-                       {{if ne .Account.ID ""}}
+                       {{if not .HideAccountInfo}}
                        <div class="status-name">
                                <span class="status-dname"> {{WithEmojis .Account.DisplayName .Account.Emojis}} </span> 
                                <span class="status-uname"> {{.Account.Acct}} </span>
                        </div>
                        {{end}}
+                       <div class="status-reply-container">
+                               {{if .InReplyToID}}
+                               <span class="icon dripicons-forward"></span> 
+                               <a class="status-reply-to" href="{{if not .ShowReplies}}/thread/{{.InReplyToID}}{{end}}#status-{{.InReplyToID}}"> reply to {{.Pleroma.InReplyToAccountAcct}} </a>
+                               {{if index .ReplyMap .ID}} <span class="status-reply-info-divider"> - </span> {{end}}
+                               {{end}}
+                               {{if .ShowReplies}}
+                               {{if index .ReplyMap .ID}} <span class="status-reply-text"> replies: </span> {{end}}
+                               {{range index .ReplyMap .ID}}
+                               <a class="status-reply" href="#status-{{.ID}}">#{{.Number}}</a>
+                               {{end}}
+                               {{end}}
+                       </div>
                        <div class="status-content"> {{WithEmojis .Content .Emojis}} </div>
                        <div class="status-media-container">
                        {{range .MediaAttachments}}
index 29d702b8b76e2fd8dafa4eef3d3d0cced174565c..e36c5ea618508fa14a62ba624f2caf9dde9f6711 100644 (file)
@@ -2,12 +2,10 @@
 {{template "navigation.tmpl" .NavbarData}}
 <div class="page-title"> Thread </div>
 
-{{range .Context.Ancestors}}
+{{range .Statuses}}
 {{template "status.tmpl" .}}
-{{end}}
 
-{{template "status.tmpl" .Status}}
-{{if .PostReply}}
+{{if eq .ID $.ReplyToID}}
 <form class="timeline-post-form" action="/post" method="POST" enctype="multipart/form-data">
        <input type="hidden" name="reply_to_id" value="{{.ReplyToID}}" />
        <label for="post-content"> Reply to {{.Status.Account.DisplayName}} </label>
@@ -20,8 +18,6 @@
 </form>
 {{end}}
 
-{{range .Context.Descendants}}
-{{template "status.tmpl" .}}
 {{end}}
 
 {{template "footer.tmpl"}}