Skip to content

Commit

Permalink
feat(boardsv2): initialize reposting (#3513)
Browse files Browse the repository at this point in the history
Based on #3469

Closes: #3227
  • Loading branch information
x1unix authored Jan 16, 2025
1 parent 0556dc8 commit 4090aac
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 42 deletions.
5 changes: 5 additions & 0 deletions examples/gno.land/r/demo/boards2/format.gno
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ func newLink(label, uri string) string {
return "[" + label + "](" + uri + ")"
}

// newButtonLink returns a Makdown link with label wrapped in brackets.
func newButtonLink(label, uri string) string {
return `[\[` + label + `\]](` + uri + ")"
}

// newUserLink returns a Markdown link for an account to the users realm.
func newUserLink(addr std.Address) string {
user := users.GetUserByAddress(addr)
Expand Down
119 changes: 81 additions & 38 deletions examples/gno.land/r/demo/boards2/post.gno
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type Post struct {
threadID PostID // original Post.id
parentID PostID // parent Post.id (if reply or repost)
repostBoardID BoardID // original Board.id (if repost)
repostsCount uint64
createdAt time.Time
updatedAt time.Time
}
Expand All @@ -60,7 +61,8 @@ func newPost(board *Board, id PostID, creator std.Address, title, body string, t
}

func (post *Post) IsThread() bool {
return post.parentID == 0
// repost threads also have parent ID
return post.parentID == 0 || post.repostBoardID != 0
}

func (post *Post) GetBoard() *Board {
Expand Down Expand Up @@ -153,18 +155,20 @@ func (thread *Post) GetReply(pid PostID) (_ *Post, found bool) {
return v.(*Post), true
}

func (post *Post) AddRepostTo(creator std.Address, title, body string, dst *Board) *Post {
func (post *Post) AddRepostTo(creator std.Address, repost *Post, dst *Board) {
if !post.IsThread() {
panic("cannot repost non-thread post")
}

pid := dst.incGetPostID()
repost := newPost(dst, pid, creator, title, body, pid, post.id, post.board.id)
dst.threads.Set(pid.Key(), repost)
if post.isHidden {
panic("thread has been flagged as inappropriate")
}

post.repostsCount++
dst.threads.Set(repost.id.Key(), repost)
if !dst.IsPrivate() {
post.reposts.Set(dst.id.Key(), pid)
post.reposts.Set(dst.id.Key(), repost.id)
}
return repost
}

func (post *Post) DeleteReply(replyID PostID) error {
Expand Down Expand Up @@ -216,7 +220,7 @@ func (post *Post) GetReplyFormURL() string {
func (post *Post) GetRepostFormURL() string {
return txlink.Call("CreateRepost",
"bid", post.board.id.String(),
"postID", post.id.String(),
"threadID", post.id.String(),
)
}

Expand All @@ -235,24 +239,6 @@ func (post *Post) GetDeleteFormURL() string {
}

func (post *Post) RenderSummary() string {
if post.repostBoardID != 0 {
dstBoard, found := getBoard(post.repostBoardID)
if !found {
panic("repost board does not exist")
}

thread, found := dstBoard.GetThread(PostID(post.parentID))
if !found {
return "reposted post does not exist"
}

if thread.isHidden {
return "reposted post was hidden"
}

return "Repost: " + post.GetSummary() + "\n" + thread.RenderSummary()
}

var (
s string
postURL = post.GetURL()
Expand All @@ -263,14 +249,43 @@ func (post *Post) RenderSummary() string {
}

s += post.GetSummary() + "\n"

repostBody, _ := post.renderSourcePost("")
s += repostBody

s += "\\- " + newUserLink(post.creator) + ","
s += " " + newLink(post.createdAt.Format(dateFormat), postURL)
s += " \\[" + newLink("x", post.GetDeleteFormURL()) + "]"
s += " " + newButtonLink("x", post.GetDeleteFormURL())
s += " (" + strconv.Itoa(post.replies.Size()) + " replies)"
s += " (" + strconv.Itoa(post.reposts.Size()) + " reposts)" + "\n"
return s
}

func (post *Post) renderSourcePost(indent string) (string, *Post) {
if post.repostBoardID == 0 {
return "", nil
}

indent += "> "

// TODO: figure out a way to decouple posts from a global storage.
board, ok := getBoard(post.repostBoardID)
if !ok {
return indentBody(indent, "*Source board is not available*\n\n"), nil
}

srcPost, ok := board.GetThread(post.parentID)
if !ok {
return indentBody(indent, "*Source post is not available*\n\n"), nil
}

if srcPost.isHidden {
return indentBody(indent, "*Source post has been flagged as inappropriate*\n\n"), nil
}

return indentBody(indent, srcPost.GetSummary()) + "\n\n", srcPost
}

func (post *Post) Render(indent string, levels int) string {
if post == nil {
return "nil post"
Expand All @@ -286,14 +301,34 @@ func (post *Post) Render(indent string, levels int) string {
s += indent + "\n"
}

srcContent, srcPost := post.renderSourcePost(indent)

s += srcContent
s += indentBody(indent, post.body) + "\n" // TODO: indent body lines.

if post.IsThread() {
// Split content and controls for threads.
s += "\n"
}

s += indent + "\\- " + newUserLink(post.creator) + ", "
s += newLink(post.createdAt.Format(dateFormat), postURL)
s += " \\[" + newLink("reply", post.GetReplyFormURL()) + "]"

if post.repostsCount > 0 {
s += ", " + strconv.FormatUint(post.repostsCount, 10) + " reposts"
}

if srcPost != nil {
s += " " + newButtonLink("see source post", srcPost.GetURL())
}

s += " " + newButtonLink("reply", post.GetReplyFormURL())

if post.IsThread() {
s += " \\[" + newLink("repost", post.GetRepostFormURL()) + "]"
s += " " + newButtonLink("repost", post.GetRepostFormURL())
}
s += " \\[" + newLink("x", post.GetDeleteFormURL()) + "]\n"

s += " " + newButtonLink("x", post.GetDeleteFormURL()) + "\n"

if levels > 0 {
if post.replies.Size() > 0 {
Expand Down Expand Up @@ -322,20 +357,28 @@ func (post *Post) RenderInner() string {
}

var (
parent *Post
parentID = post.parentID
threadID = post.threadID
thread, _ = post.board.GetThread(threadID) // TODO: This seems redundant (post == thread)
)

if thread.id == parentID {
parent = thread
} else {
parent, _ = thread.GetReply(parentID)
s := "_" + newLink("see thread", post.board.GetURLFromThreadID(threadID)) + "_\n\n"

// Fully render parent if it's not a repost.
if post.repostBoardID == 0 {
var (
parent *Post
parentID = post.parentID
)

if thread.id == parentID {
parent = thread
} else {
parent, _ = thread.GetReply(parentID)
}

s += parent.Render("", 0) + "\n"
}

s := "_" + newLink("see thread", post.board.GetURLFromThreadID(threadID)) + "_\n\n"
s += parent.Render("", 0) + "\n"
s += post.Render("> ", 5)
return s
}
10 changes: 8 additions & 2 deletions examples/gno.land/r/demo/boards2/post_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,13 @@ func TestPostAddRepostTo(t *testing.T) {
)

createRepost := func() {
repost = thread.AddRepostTo(creator, tc.title, tc.body, tc.dstBoard)
var repostId PostID
if tc.dstBoard != nil {
repostId = tc.dstBoard.incGetPostID()
}

repost = newPost(tc.dstBoard, repostId, creator, tc.title, tc.body, repostId, thread.GetPostID(), thread.GetBoard().GetID())
thread.AddRepostTo(creator, repost, tc.dstBoard)
}

if tc.err != "" {
Expand Down Expand Up @@ -116,7 +122,7 @@ func TestNewThread(t *testing.T) {
uint(threadID),
)
repostURL := ufmt.Sprintf(
"/r/demo/boards2$help&func=CreateRepost&bid=%d&postID=%d",
"/r/demo/boards2$help&func=CreateRepost&bid=%d&threadID=%d",
uint(boardID),
uint(threadID),
)
Expand Down
12 changes: 10 additions & 2 deletions examples/gno.land/r/demo/boards2/public.gno
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,16 @@ func CreateRepost(bid BoardID, threadID PostID, title, body string, dstBoardID B

dst := mustGetBoard(dstBoardID)
thread := mustGetThread(board, threadID)
repost := thread.AddRepostTo(caller, title, body, dst)
return repost.id

repostId := dst.incGetPostID()
repost := newPost(dst, repostId, caller, title, body, repostId, thread.GetPostID(), thread.GetBoard().GetID())

args := Args{board.GetID(), threadID, dst.GetID()}
dst.GetPermissions().WithPermission(caller, PermissionThreadRepost, args, func(_ Args) {
thread.AddRepostTo(caller, repost, dst)
})

return repostId
}

func DeleteThread(bid BoardID, threadID PostID) {
Expand Down

0 comments on commit 4090aac

Please sign in to comment.