PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/moul/x/social/threads/v0

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v0
Namespace
moul / x / social / threads
Files
5 (README)(gnomod.toml)
Exported functions
18
Module
gno.land/r/moul/x/social/threads/v0
gno
0.9
This realm implements a recognized token.THREAD →

Files (5)

  • README.mdmarkdown
  • gnomod.tomltoml
  • render.gnogno
  • threads.gnogno
  • threads_test.gnogno
render.gnogno
1package threads23import (4	"strconv"5	"strings"67	"chain/runtime"89	"gno.land/p/moul/kit/store/v0"10	"gno.land/p/moul/kit/ui/v0"11	"gno.land/p/moul/md/v0"12	"gno.land/p/moul/realmpath/v0"13	th "gno.land/p/moul/x/social/threads/v0"14)1516// Render routes three views: the realm's own index, one page's threads, and17// one thread.18//19// A page key contains slashes, so "page/<key>" is split on the prefix rather20// than by path element: realmpath gives the parts, and rejoining them would21// only be a way to get it wrong.22func Render(path string) string {23	req := realmpath.Parse(path)2425	switch {26	case strings.HasPrefix(req.Path, "page/"):27		return renderPage(strings.TrimPrefix(req.Path, "page/"))28	case strings.HasPrefix(req.Path, "thread/"):29		return renderThread(strings.TrimPrefix(req.Path, "thread/"))30	case req.Path == "":31		return renderIndex()32	default:33		return md.H1("Not found") + "No such view: " + ui.Inline(req.Path)34	}35}3637func renderIndex() string {38	out := md.H1("Threads")39	out += "A discussion block any realm can embed, keyed on the page it appears on.\n\n"4041	t := ui.NewTable("threads", "pages", "THREAD supply")42	t.Row(strconv.Itoa(board.Len()), strconv.Itoa(board.Pages()), strconv.FormatInt(points.Supply(), 10))43	out += t.String()4445	out += md.H2("Recent, across every page")46	out += listing(board.Recent(20), true)4748	out += md.H2("The token")49	out += points.Render()5051	out += md.H2("Embedding it")52	out += "Two lines in the host realm, and it stores nothing:\n\n"53	out += md.LanguageCodeBlock("go", `import "`+realmPath+`"5455func Render(path string) string {56	return body + threads.RenderBlock()57}`)58	out += "The page key is the host realm's own path, read off the call. " +59		md.InlineCode("RenderBlockFor(page)") + " names one explicitly.\n"6061	return out62}6364func renderPage(page string) string {65	if !th.ValidPage(page) {66		return md.H1("Threads") + "Not a page key: " + ui.Inline(page)67	}68	out := md.H1("Threads on " + ui.Inline(page))69	out += md.Link("the page itself", th.RealmURL(page)) + "\n\n"70	out += listing(board.List(page, runtime.ChainHeight(), 0), false)71	out += "\n" + ui.Action("💬 Post here", "Post", "page", page, "body", "") + "\n"72	return out73}7475func renderThread(raw string) string {76	id, ok := store.ParseID(raw)77	if !ok {78		return md.H1("Threads") + "Not a thread id: " + ui.Inline(raw)79	}80	t, found := board.Get(id)81	if !found {82		return md.H1("Threads") + "No thread #" + id.String()83	}8485	out := md.H1("Thread #" + id.String())86	out += md.Blockquote(ui.Inline(t.Body)) + "\n"87	out += md.Italic("by "+ui.Addr(t.Author)+" · on "+88		md.Link(t.Page, th.PageURL(realmPath, t.Page))+89		" · "+strconv.Itoa(t.Repliers())+" earned") + "\n\n"9091	if t.PinnedUntil > runtime.ChainHeight() {92		out += "📌 pinned until block " + strconv.FormatInt(t.PinnedUntil, 10) + "\n\n"93	}9495	out += md.H2("Replies")96	if len(t.Replies) == 0 {97		out += ui.Empty("Nobody has replied yet.")98	} else {99		r := ui.NewTable("by", "said", "block")100		for _, rep := range t.Replies {101			r.Row(ui.Addr(rep.Author), ui.Cell(rep.Body), strconv.FormatInt(rep.At, 10))102		}103		out += r.String()104	}105106	out += "\n" + ui.Action("💬 Reply", "Reply", "threadID", id.String(), "body", "") +107		" · " + ui.Action("📌 Boost", "Boost", "threadID", id.String()) + "\n"108	return out109}110111// listing renders a set of threads. withPage adds the page column, which the112// index needs and a page view would only repeat.113func listing(items []th.Listing, withPage bool) string {114	if len(items) == 0 {115		return ui.Empty("No threads yet.")116	}117	headers := []string{"", "#", "thread", "by", "replies"}118	if withPage {119		headers = append(headers, "page")120	}121	t := ui.NewTable(headers...)122	now := runtime.ChainHeight()123	for _, it := range items {124		mark := ""125		if it.Thread.Pinned(now) {126			mark = "📌"127		}128		cells := []string{129			mark,130			// The link title is the id, never the body: md.Link escapes131			// markdown but not a pipe, and a pipe in a table cell opens a132			// column. ui.Cell is the only thing that rewrites it.133			md.Link("#"+it.ID.String(), th.ThreadURL(realmPath, it.ID)),134			ui.Cell(ui.ShortN(it.Thread.Body, th.ExcerptLen, 0)),135			ui.Addr(it.Thread.Author),136			strconv.Itoa(len(it.Thread.Replies)),137		}138		if withPage {139			cells = append(cells, ui.Cell(it.Thread.Page))140		}141		t.Row(cells...)142	}143	return t.String()144}145

Functions

  • Allowance(owner string, spender string) int64

  • Approve(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, spender string, amount int64)

  • BalanceOf(owner string) int64

  • Boost(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, threadID int64)

  • Count(page string) int

  • Pages() int

  • PinnedUntil(threadID int64) int64

  • Post(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, page string, body string) int64

  • Render(path string) string

  • RenderBlock() string

  • RenderBlockFor(page string) string

  • Repliers(threadID int64) int

  • Reply(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, threadID int64, body string)

  • TokenKey() string

  • Total() int

  • TotalSupply() int64

  • Transfer(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, to string, amount int64)

  • TransferFrom(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, from string, to string, amount int64)

Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

Rendered

RenderedRawgnoweb ↗

vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.