Skip to content

Instantly share code, notes, and snippets.

@TonioGela
Created May 6, 2024 09:51
Show Gist options
  • Save TonioGela/dc8170c288a543ae17b5a1c0560b5824 to your computer and use it in GitHub Desktop.
Save TonioGela/dc8170c288a543ae17b5a1c0560b5824 to your computer and use it in GitHub Desktop.
Calico web app to convert file in page
//> using scala 3.4.1
//> using platform js
//> using packaging.output main.js
//> using jsMode dev
//> using dep com.armanbilge::calico::0.2.2
import calico.IOWebApp
import calico.html.io.{*, given}
import cats.effect.*
import cats.syntax.all.*
import cats.effect.std.Console
import fs2.{Stream, Pipe}
import fs2.dom.*
import org.scalajs.dom.*
import org.scalajs.dom.ConvertToBlobOptions
import scala.scalajs.js.JSConverters.*
import fs2.concurrent.SignallingRef
import cats.data.Nested
import fs2.concurrent.Signal
object MyCalicoApp extends IOWebApp:
def extractFiles(input: HTMLInputElement): Stream[IO, File] =
Option(input.files).fold(Stream.empty)(files =>
org.scalajs.dom.console.log(files)
Stream.range(0, files.length).map(files.item)
).covary[IO]
def transformContent(f: Pipe[IO, Byte, Byte]): Pipe[IO, File, File] =
_.evalMap(file =>
readReadableStream(IO(file.stream()))
.through(f)
.chunks
.map(_.toJSArrayBuffer)
.compile
.toList
.map(_.toJSIterable)
.map(
new File(
_,
s"TRANSFORMED_${file.name}",
new FilePropertyBag { `type` = "text/plain" }
)
)
)
def render: Resource[IO, HtmlElement[IO]] =
SignallingRef.of[IO, List[File]](List.empty[File]).toResource.flatMap { files =>
div(
input.withSelf { self =>
(
onChange --> (
_.foreach(_ =>
extractFiles(self.asInstanceOf[HTMLInputElement])
.through(transformContent(bs =>
fs2.text.utf8Decode(bs)
.map(_.toUpperCase)
.through(fs2.text.utf8.encode)
))
.compile
.toList
.flatMap(files.set)
)),
typ := "file",
multiple := true
)
},
p(
children <-- files.nested.map(f =>
a(
f.name,
href := URL.createObjectURL(f),
download := f.name,
)
).value
)
)
}
<!DOCTYPE html>
<html>
<body>
<div id="app"></div>
<script src="./main.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment