interactive event filling of missing properties.

This commit is contained in:
fiatjaf 2023-03-24 23:20:24 -03:00
parent 4d23a4c6af
commit 58517711b6
No known key found for this signature in database
GPG Key ID: BAD43C4BE5C1A3A1
5 changed files with 88 additions and 9 deletions

View File

@ -1,4 +1,4 @@
import cats.data.* import cats.data.{Store => *, *}
import cats.effect.* import cats.effect.*
import cats.effect.syntax.all.* import cats.effect.syntax.all.*
import cats.syntax.all.* import cats.syntax.all.*
@ -12,6 +12,8 @@ import calico.syntax.*
import scoin.* import scoin.*
import snow.* import snow.*
import Utils.*
object Components { object Components {
def renderEventPointer( def renderEventPointer(
evp: snow.EventPointer evp: snow.EventPointer
@ -53,12 +55,83 @@ object Components {
else None else None
) )
def renderEvent(event: Event): Resource[IO, HtmlDivElement[IO]] = def renderEvent(
event: Event,
store: Store
): Resource[IO, HtmlDivElement[IO]] =
div( div(
cls := "text-md", cls := "text-md",
List(("pubkey", event.pubkey), ("id", event.id), ("sig", event.sig)) if event.pubkey.isEmpty then
.filter((_, v) => v.isEmpty) Some(
.map { (label, _) => entry("property missing", label) }, div(
cls := "flex items-center",
entry("missing", "pubkey"),
button(
Styles.buttonSmall,
"fill with a debugging key",
onClick --> (_.foreach { _ =>
store.input.set(
event
.copy(pubkey = Some(keyOne.publicKey.xonly))
.asJson
.printWith(jsonPrinter)
)
})
)
)
)
else None,
if event.id.isEmpty then
Some(
div(
cls := "flex items-center",
entry("missing", "id"),
if event.pubkey.isDefined then
Some(
button(
Styles.buttonSmall,
"fill id",
onClick --> (_.foreach(_ =>
store.input.set(
event
.copy(id = Some(event.hash.toHex))
.asJson
.printWith(jsonPrinter)
)
))
)
)
else None
)
)
else None,
if event.sig.isEmpty then
Some(
div(
cls := "flex items-center",
entry("missing", "sig"),
if event.id.isDefined && event.pubkey == Some(
keyOne.publicKey.xonly
)
then
Some(
button(
Styles.buttonSmall,
"sign",
onClick --> (_.foreach(_ =>
store.input.set(
event
.sign(keyOne)
.asJson
.printWith(jsonPrinter)
)
))
)
)
else None
)
)
else None,
entry("serialized event", event.serialized), entry("serialized event", event.serialized),
entry("implied event id", event.hash.toHex), entry("implied event id", event.hash.toHex),
entry( entry(

View File

@ -58,7 +58,7 @@ object Main extends IOWebApp {
Event( Event(
kind = 1, kind = 1,
content = "hello world" content = "hello world"
).sign(PrivateKey(randomBytes32())) ).sign(keyOne)
.asJson .asJson
.printWith(jsonPrinter) .printWith(jsonPrinter)
) )
@ -91,8 +91,7 @@ object Main extends IOWebApp {
cls := "w-full flex my-5", cls := "w-full flex my-5",
store.result.map { store.result.map {
case Left(msg) => div(msg) case Left(msg) => div(msg)
case Right(event: Event) => case Right(event: Event) => renderEvent(event, store)
renderEvent(event)
case Right(pp: ProfilePointer) => renderProfilePointer(pp) case Right(pp: ProfilePointer) => renderProfilePointer(pp)
case Right(evp: EventPointer) => renderEventPointer(evp) case Right(evp: EventPointer) => renderEventPointer(evp)
case Right(sk: PrivateKey) => case Right(sk: PrivateKey) =>

View File

@ -4,6 +4,7 @@ import cats.effect.syntax.all.*
import cats.syntax.all.* import cats.syntax.all.*
import fs2.concurrent.* import fs2.concurrent.*
import fs2.dom.{Event => _, *} import fs2.dom.{Event => _, *}
import scoin.PrivateKey
case class Store( case class Store(
input: SignallingRef[IO, String], input: SignallingRef[IO, String],

View File

@ -3,5 +3,7 @@ import calico.html.io.*
object Styles { object Styles {
val button = cls := val button = cls :=
"shrink bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 mx-2 px-4 rounded " "shrink bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 mx-2 px-4 rounded "
val buttonSmall = cls :=
"shrink text-sm bg-blue-500 hover:bg-blue-700 text-white font-bold mx-2 px-2 rounded "
val mono = styleAttr := "font-family: monospace" val mono = styleAttr := "font-family: monospace"
} }

View File

@ -1,6 +1,10 @@
import io.circe.Printer import io.circe.Printer
import scodec.bits.ByteVector
import scoin.*
object Utils { object Utils {
val keyOne = PrivateKey(ByteVector32(ByteVector(0x01).padLeft(32)))
val jsonPrinter = Printer( val jsonPrinter = Printer(
dropNullValues = false, dropNullValues = false,
indent = " ", indent = " ",