mirror of
https://github.com/fiatjaf/nak.git
synced 2024-10-30 09:09:08 -04:00
basically the same functionality as the old nak.
This commit is contained in:
parent
570ee55359
commit
88dd984095
13
build.sbt
13
build.sbt
|
@ -3,7 +3,12 @@ enablePlugins(ScalaJSPlugin, EsbuildPlugin)
|
||||||
name := "nostr-army-knife"
|
name := "nostr-army-knife"
|
||||||
scalaVersion := "3.2.2"
|
scalaVersion := "3.2.2"
|
||||||
|
|
||||||
scalaJSUseMainModuleInitializer := true
|
lazy val root = (project in file("."))
|
||||||
|
.settings(
|
||||||
libraryDependencies += "com.armanbilge" %%% "calico" % "0.2.0-RC2"
|
libraryDependencies ++= Seq(
|
||||||
libraryDependencies += "com.fiatjaf" %%% "snow" % "0.0.1-SNAPSHOT"
|
"com.armanbilge" %%% "calico" % "0.2.0-RC2",
|
||||||
|
"com.fiatjaf" %%% "snow" % "0.0.1-SNAPSHOT"
|
||||||
|
),
|
||||||
|
scalaJSUseMainModuleInitializer := true,
|
||||||
|
scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) }
|
||||||
|
)
|
||||||
|
|
|
@ -5,10 +5,12 @@ import cats.syntax.all.*
|
||||||
import fs2.concurrent.*
|
import fs2.concurrent.*
|
||||||
import fs2.dom.{Event => _, *}
|
import fs2.dom.{Event => _, *}
|
||||||
import io.circe.parser.*
|
import io.circe.parser.*
|
||||||
|
import io.circe.syntax.*
|
||||||
import calico.*
|
import calico.*
|
||||||
import calico.html.io.{*, given}
|
import calico.html.io.{*, given}
|
||||||
import calico.syntax.*
|
import calico.syntax.*
|
||||||
import snow.*
|
import snow.*
|
||||||
|
import scoin.*
|
||||||
|
|
||||||
object Store {
|
object Store {
|
||||||
def apply(window: Window[IO]): Resource[IO, Store] = {
|
def apply(window: Window[IO]): Resource[IO, Store] = {
|
||||||
|
@ -49,25 +51,42 @@ object Main extends IOWebApp {
|
||||||
store =>
|
store =>
|
||||||
div(
|
div(
|
||||||
cls := "flex w-full h-full flex-col items-center justify-center",
|
cls := "flex w-full h-full flex-col items-center justify-center",
|
||||||
h1(cls := "px-1 py-2 text-lg", "nostr army knife"),
|
|
||||||
div(
|
div(
|
||||||
cls := "flex justify-center my-3"
|
cls := "w-4/5",
|
||||||
// button(cls := buttonCls, "generate event", onClick --> (_.foreach(_ => ))),
|
h1(cls := "px-1 py-2 text-center text-xl", "nostr army knife"),
|
||||||
),
|
div(
|
||||||
input(store),
|
cls := "flex justify-center my-3",
|
||||||
result(store)
|
input(store),
|
||||||
|
button(
|
||||||
|
cls :=
|
||||||
|
"shrink bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 mx-2 px-4 rounded ",
|
||||||
|
"generate event",
|
||||||
|
onClick --> (_.foreach(_ =>
|
||||||
|
store.input.set(
|
||||||
|
Event(
|
||||||
|
kind = 1,
|
||||||
|
content = "hello world"
|
||||||
|
).sign(PrivateKey(randomBytes32()))
|
||||||
|
.asJson
|
||||||
|
.printWith(Utils.jsonPrinter)
|
||||||
|
)
|
||||||
|
))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
result(store)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
def input(store: Store): Resource[IO, HtmlDivElement[IO]] =
|
def input(store: Store): Resource[IO, HtmlDivElement[IO]] =
|
||||||
div(
|
div(
|
||||||
cls := "w-full",
|
cls := "w-full grow",
|
||||||
div(
|
div(
|
||||||
cls := "w-full flex justify-center",
|
cls := "w-full flex justify-center",
|
||||||
textArea.withSelf { self =>
|
textArea.withSelf { self =>
|
||||||
(
|
(
|
||||||
cls := "w-2/3 max-h-96 p-3",
|
cls := "w-full max-h-96 p-3 rounded",
|
||||||
styleAttr := "min-height: 200px",
|
styleAttr := "min-height: 400px",
|
||||||
placeholder := "paste something nostric",
|
placeholder := "paste something nostric",
|
||||||
onInput --> (_.foreach(_ =>
|
onInput --> (_.foreach(_ =>
|
||||||
self.value.get.flatMap(store.input.set)
|
self.value.get.flatMap(store.input.set)
|
||||||
|
@ -80,23 +99,46 @@ object Main extends IOWebApp {
|
||||||
|
|
||||||
def result(store: Store): Resource[IO, HtmlDivElement[IO]] =
|
def result(store: Store): Resource[IO, HtmlDivElement[IO]] =
|
||||||
div(
|
div(
|
||||||
cls := "w-full flex justify-center",
|
cls := "w-full flex my-5",
|
||||||
store.input.map { input =>
|
store.input.map { input =>
|
||||||
if input.trim() == "" then ""
|
if input.trim() == "" then div("")
|
||||||
else
|
else
|
||||||
decode[Event](input) match {
|
decode[Event](input) match {
|
||||||
case Right(event) => event.toString
|
case Left(err: io.circe.ParsingFailure) =>
|
||||||
|
div("not valid JSON")
|
||||||
case Left(err: io.circe.DecodingFailure) =>
|
case Left(err: io.circe.DecodingFailure) =>
|
||||||
err.pathToRootString match {
|
err.pathToRootString match {
|
||||||
case Some(path) => s"field $path is missing or wrong"
|
case None => div(s"decoding ${err.pathToRootString}")
|
||||||
case None => s"decoding ${err.pathToRootString}"
|
case Some(path) => div(s"field $path is missing or wrong")
|
||||||
}
|
}
|
||||||
case Left(err: io.circe.ParsingFailure) =>
|
case Right(event) =>
|
||||||
"not valid JSON"
|
div(
|
||||||
|
cls := "text-md",
|
||||||
|
styleAttr := "font-family: monospace",
|
||||||
|
div(
|
||||||
|
span(cls := "font-bold", "serialized event "),
|
||||||
|
event.serialized
|
||||||
|
),
|
||||||
|
div(
|
||||||
|
span(cls := "font-bold", "implied event id "),
|
||||||
|
event.hash.toHex
|
||||||
|
),
|
||||||
|
div(
|
||||||
|
span(
|
||||||
|
cls := "font-bold",
|
||||||
|
"does the implied event id match the given event id? "
|
||||||
|
),
|
||||||
|
event.id == event.hash.toHex match {
|
||||||
|
case true => "yes"; case false => "no"
|
||||||
|
}
|
||||||
|
),
|
||||||
|
div(
|
||||||
|
span(cls := "font-bold", "is signature valid? "),
|
||||||
|
event.isValid match { case true => "yes"; case false => "no" }
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
val buttonCls =
|
|
||||||
"bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 mx-2 px-4 rounded"
|
|
||||||
}
|
}
|
||||||
|
|
18
src/main/scala/Utils.scala
Normal file
18
src/main/scala/Utils.scala
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import io.circe.Printer
|
||||||
|
|
||||||
|
object Utils {
|
||||||
|
val jsonPrinter = Printer(
|
||||||
|
dropNullValues = false,
|
||||||
|
indent = " ",
|
||||||
|
lbraceRight = "\n",
|
||||||
|
rbraceLeft = "\n",
|
||||||
|
lbracketRight = "\n",
|
||||||
|
rbracketLeft = "\n",
|
||||||
|
lrbracketsEmpty = "",
|
||||||
|
arrayCommaRight = "\n",
|
||||||
|
objectCommaRight = "\n",
|
||||||
|
colonLeft = "",
|
||||||
|
colonRight = " ",
|
||||||
|
sortKeys = true
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user