From 65ee7a5366cfea06deee2172a2abce797104ba98 Mon Sep 17 00:00:00 2001 From: Leon Hudak <33522493+leohhhn@users.noreply.github.com> Date: Tue, 3 Sep 2024 18:17:37 +0200 Subject: [PATCH] feat(examples): add `r/leon` (#2740) ## Description This PR adds v1 of `r/leon` to the examples folder. It contains `r/leon/home` & `r/leon/config`. For context - this is meant to be a personal realm (or set of realms) that every gno.land user should have at some point. Later, the idea is to have a [special user page](https://github.com/gnolang/gno/issues/2189) which will fetch the `Render()` of `r/username/home`. This will serve like the profile of the user; and the home realm will most likely be upgradeable down the line. The reason I am making this a PR and not simply publishing it to the Portal Loop is that it allows for further code changes down the line. `examples/` get loaded into genesis first, and all other replayed addpkg transactions after that, making it possible to have "upgradeable" realms on Portal Loop.
Contributors' checklist... - [x] Added new tests, or not needed, or not feasible - [x] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [x] Updated the official documentation or not needed - [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [x] Added references to related issues and PRs - [x] Provided any useful hints for running manual tests - [x] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).
--- examples/gno.land/r/leon/config/config.gno | 65 +++++++++++ examples/gno.land/r/leon/config/gno.mod | 1 + examples/gno.land/r/leon/home/gno.mod | 8 ++ examples/gno.land/r/leon/home/home.gno | 121 +++++++++++++++++++++ 4 files changed, 195 insertions(+) create mode 100644 examples/gno.land/r/leon/config/config.gno create mode 100644 examples/gno.land/r/leon/config/gno.mod create mode 100644 examples/gno.land/r/leon/home/gno.mod create mode 100644 examples/gno.land/r/leon/home/home.gno diff --git a/examples/gno.land/r/leon/config/config.gno b/examples/gno.land/r/leon/config/config.gno new file mode 100644 index 00000000000..cbc1e537e3f --- /dev/null +++ b/examples/gno.land/r/leon/config/config.gno @@ -0,0 +1,65 @@ +package config + +import ( + "errors" + "std" +) + +var ( + main std.Address // leon's main address + backup std.Address // backup address +) + +func init() { + main = "g125em6arxsnj49vx35f0n0z34putv5ty3376fg5" +} + +func Address() std.Address { + return main +} + +func Backup() std.Address { + return backup +} + +func SetAddress(a std.Address) error { + if !a.IsValid() { + return errors.New("config: invalid address") + } + + if err := checkAuthorized(); err != nil { + return err + } + + main = a + return nil +} + +func SetBackup(a std.Address) error { + if !a.IsValid() { + return errors.New("config: invalid address") + } + + if err := checkAuthorized(); err != nil { + return err + } + + backup = a + return nil +} + +func checkAuthorized() error { + caller := std.PrevRealm().Addr() + if caller != main || caller != backup { + return errors.New("config: unauthorized") + } + + return nil +} + +func AssertAuthorized() { + caller := std.PrevRealm().Addr() + if caller != main || caller != backup { + panic("config: unauthorized") + } +} diff --git a/examples/gno.land/r/leon/config/gno.mod b/examples/gno.land/r/leon/config/gno.mod new file mode 100644 index 00000000000..e8cd5cd85b7 --- /dev/null +++ b/examples/gno.land/r/leon/config/gno.mod @@ -0,0 +1 @@ +module gno.land/r/leon/config diff --git a/examples/gno.land/r/leon/home/gno.mod b/examples/gno.land/r/leon/home/gno.mod new file mode 100644 index 00000000000..48cf64a9d0a --- /dev/null +++ b/examples/gno.land/r/leon/home/gno.mod @@ -0,0 +1,8 @@ +module gno.land/r/leon/home + +require ( + gno.land/p/demo/ufmt v0.0.0-latest + gno.land/r/demo/art/gnoface v0.0.0-latest + gno.land/r/demo/art/millipede v0.0.0-latest + gno.land/r/leon/config v0.0.0-latest +) diff --git a/examples/gno.land/r/leon/home/home.gno b/examples/gno.land/r/leon/home/home.gno new file mode 100644 index 00000000000..1f6a07e8959 --- /dev/null +++ b/examples/gno.land/r/leon/home/home.gno @@ -0,0 +1,121 @@ +package home + +import ( + "std" + "strconv" + + "gno.land/p/demo/ufmt" + + "gno.land/r/demo/art/gnoface" + "gno.land/r/demo/art/millipede" + "gno.land/r/leon/config" +) + +var ( + pfp string // link to profile picture + pfpCaption string // profile picture caption + abtMe [2]string +) + +func init() { + pfp = "https://i.imgflip.com/91vskx.jpg" + pfpCaption = "[My favourite painting & pfp](https://en.wikipedia.org/wiki/Wanderer_above_the_Sea_of_Fog)" + abtMe = [2]string{ + `### About me +Hi, I'm Leon, a DevRel Engineer at gno.land. I am a tech enthusiast, +life-long learner, and sharer of knowledge.`, + `### Contributions +My contributions to gno.land can mainly be found +[here](https://github.com/gnolang/gno/issues?q=sort:updated-desc+author:leohhhn). + +TODO import r/gh +`, + } +} + +func UpdatePFP(url, caption string) { + config.AssertAuthorized() + pfp = url + pfpCaption = caption +} + +func UpdateAboutMe(col1, col2 string) { + config.AssertAuthorized() + abtMe[0] = col1 + abtMe[1] = col2 +} + +func Render(path string) string { + out := "# Leon's Homepage\n\n" + + out += renderAboutMe() + out += renderBlogPosts() + out += "\n\n" + out += renderArt() + + return out +} + +func renderBlogPosts() string { + out := "" + //out += "## Leon's Blog Posts" + + // todo fetch blog posts authored by @leohhhn + // and render them + return out +} + +func renderAboutMe() string { + out := "
" + + out += "
\n\n" + out += ufmt.Sprintf("![my profile pic](%s)\n\n%s\n\n", pfp, pfpCaption) + out += "
\n\n" + + out += "
\n\n" + out += abtMe[0] + "\n\n" + out += "
\n\n" + + out += "
\n\n" + out += abtMe[1] + "\n\n" + out += "
\n\n" + + out += "
\n\n" + + return out +} + +func renderArt() string { + out := `
` + "\n\n" + out += "# Gno Art\n\n" + + out += "
" + + out += renderGnoFace() + out += renderMillipede() + out += "Empty spot :/" + + out += "
\n\n" + + out += "This art is dynamic; it will change with every new block.\n\n" + out += `
` + "\n" + + return out +} + +func renderGnoFace() string { + out := "
\n\n" + out += gnoface.Render(strconv.Itoa(int(std.GetHeight()))) + out += "
\n\n" + + return out +} + +func renderMillipede() string { + out := "
\n\n" + out += "Millipede\n\n" + out += "```\n" + millipede.Draw(int(std.GetHeight())%10+1) + "```\n" + out += "
\n\n" + + return out +}