render_reply.gno

package boards2

import (
	"strconv"
	"strings"

	"gno.land/p/gnoland/boards"
	"gno.land/p/jeronimoalbi/mdform"
	"gno.land/p/jeronimoalbi/pager"
	"gno.land/p/leon/svgbtn"
	"gno.land/p/moul/md"
	"gno.land/p/nt/mux/v0"
	"gno.land/p/nt/ufmt/v0"
)

func renderReply(res *mux.ResponseWriter, req *mux.Request) {
	name := req.GetVar("board")
	board, found := gBoards.GetByName(name)
	if !found {
		res.Write("Board not found")
		return
	}

	rawID := req.GetVar("thread")
	threadID, err := strconv.Atoi(rawID)
	if err != nil {
		res.Write("Invalid thread ID: " + rawID)
		return
	}

	rawID = req.GetVar("reply")
	replyID, err := strconv.Atoi(rawID)
	if err != nil {
		res.Write("Invalid reply ID: " + rawID)
		return
	}

	thread, found := getThread(board, boards.ID(threadID))
	if !found {
		res.Write("Thread not found")
		return
	}

	reply, found := getReply(thread, boards.ID(replyID))
	if !found {
		res.Write("Reply not found")
		return
	}

	// Call render even for hidden replies to display children.
	// Original comment content will be hidden under the hood.
	// See: #3480
	res.Write(renderPostInner(reply))
}

func renderTopLevelReplies(post *boards.Post, path, indent string, levels int) string {
	p, err := pager.New(path, post.Replies.Size(), pager.WithPageSize(pageSizeReplies))
	if err != nil {
		panic(err)
	}

	var (
		b              strings.Builder
		commentsIndent = indent + "> "
	)

	render := func(reply *boards.Post) bool {
		b.WriteString(indent + "\n" + renderPost(reply, "", commentsIndent, levels-1))
		return false
	}

	b.WriteString("\n" + md.HorizontalRule() + "Sort by: ")

	r := parseRealmPath(path)
	sortOrder := r.Query.Get("order")
	if sortOrder == "desc" {
		r.Query.Set("order", "asc")
		b.WriteString(md.Link("newest first", r.String()) + "\n")

	} else {
		r.Query.Set("order", "desc")
		b.WriteString(md.Link("oldest first", r.String()) + "\n")
	}

	count := p.PageSize()
	if sortOrder == "desc" {
		count = -count // Reverse iterate
	}

	post.Replies.Iterate(p.Offset(), count, render)

	if p.HasPages() {
		b.WriteString(md.HorizontalRule())
		b.WriteString(pager.Picker(p))
	}
	return b.String()
}

func renderSubReplies(post *boards.Post, indent string, levels int) string {
	var (
		b              strings.Builder
		commentsIndent = indent + "> "
	)

	post.Replies.Iterate(0, post.Replies.Size(), func(reply *boards.Post) bool {
		b.WriteString(indent + "\n" + renderPost(reply, "", commentsIndent, levels-1))
		return false
	})
	return b.String()
}

func renderEditReply(res *mux.ResponseWriter, req *mux.Request) {
	name := req.GetVar("board")
	board, found := gBoards.GetByName(name)
	if !found {
		res.Write("Board not found")
		return
	}

	rawID := req.GetVar("thread")
	threadID, err := strconv.Atoi(rawID)
	if err != nil {
		res.Write("Invalid thread ID: " + rawID)
		return
	}

	rawID = req.GetVar("reply")
	replyID, err := strconv.Atoi(rawID)
	if err != nil {
		res.Write("Invalid reply ID: " + rawID)
		return
	}

	thread, found := getThread(board, boards.ID(threadID))
	if !found {
		res.Write("Thread not found")
		return
	}

	reply, found := getReply(thread, boards.ID(replyID))
	if !found {
		res.Write("Reply not found")
		return
	}

	form := mdform.New("exec", "EditReply")
	form.Input(
		"boardID",
		"placeholder", "Board ID",
		"value", board.ID.String(),
		"readonly", "true",
	)
	form.Input(
		"threadID",
		"placeholder", "Thread ID",
		"value", thread.ID.String(),
		"readonly", "true",
	)
	form.Input(
		"replyID",
		"placeholder", "Reply ID",
		"value", reply.ID.String(),
		"readonly", "true",
	)
	form.Textarea(
		"body",
		"placeholder", "Comment",
		"value", reply.Body,
		"required", "true",
	)

	res.Write(md.H1(board.Name + ": Edit Comment"))
	res.Write(md.Link("← Back to thread", makeThreadURI(thread)) + "\n\n")
	res.Write(
		md.Paragraph(
			ufmt.Sprintf("Editing a comment from the thread: %s", md.Link(thread.Title, makeThreadURI(thread))),
		),
	)
	res.Write(form.String())
	res.Write("\n\n**Done?** " + svgbtn.ButtonWithRadius(136, 32, 4, "#E2E2E2", "#54595D", "Return to thread", makeThreadURI(thread)) + "\n")
}