You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
takeshobo/src/jsMain/kotlin/welcome.kt

159 lines
5.0 KiB

import kotlinx.browser.document
import kotlinx.browser.window
import kotlinx.css.*
import kotlinx.html.InputType
import kotlinx.html.js.onChangeFunction
import kotlinx.html.js.onClickFunction
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.MessageEvent
import org.w3c.dom.WebSocket
import org.w3c.dom.events.Event
import org.w3c.fetch.RequestInit
import org.w3c.xhr.FormData
import react.RBuilder
import react.RComponent
import react.RProps
import react.RState
import react.dom.*
import styled.css
import styled.styledDiv
import styled.styledH1
import styled.styledInput
external interface WelcomeProps : RProps {
var webSocket:WebSocket
}
data class WelcomeState(var url:String="",var result:String="",var percentage:kotlin.Float=0F,var allowInput:Boolean=true) : RState
fun Double.format(digits: Int): String = this.asDynamic().toFixed(digits)
fun Float.format(digits: Int): String = this.asDynamic().toFixed(digits)
@OptIn(ExperimentalJsExport::class)
@JsExport
class Welcome(props: WelcomeProps) : RComponent<WelcomeProps, WelcomeState>(props) {
init {
state=WelcomeState()
props.webSocket.onmessage={messageEvent: MessageEvent ->
when(val data=messageEvent.data){
is String-> {
if(data.contains("ptimg-version")){
val urlResult=Json.decodeFromString<UrlResult>(data)
console.info("ptimg_version:${urlResult.t.ptimg_version}")
ImageLoader(urlResult = urlResult).rebuild()
}else{
val task=Json.decodeFromString<ParseTask>(data)
state.result="解析进度:${task.percentage}%"
state.allowInput=(state.percentage==100F)
setState(state)
}
}
else->{
console.info("unknow data:${data}")
}
}
}
}
override fun RBuilder.render() {
styledH1 {
css{
textAlign=TextAlign.center
}
+"朴实无华的"
a {
attrs {
href="https://gammaplus.takeshobo.co.jp"
target="_blank"
}
+"takeshobo"
}
+"漫画解析工具"
}
styledDiv{
css{
textAlign=TextAlign.center
}
styledDiv {
css {
width = LinearDimension.fitContent
margin="0 auto"
}
styledInput {
css {
width = 100.pct
}
attrs{
type=InputType.text
value = state.url
disabled = !state.allowInput
onChangeFunction = { event ->
(event.target as HTMLInputElement).let {
console.info(it.value)
state.url=it.value
setState(
state
)
}
}
}
}
styledDiv {
css{
visibility=Visibility.hidden
height=0.px
paddingLeft=10.px
}
+ state.url
}
}
button {
attrs {
disabled=!state.allowInput
onClickFunction={
state.allowInput=false
state.result="初始化解析任务请稍等"
setState(state)
val formData=FormData()
formData.append("url",state.url)
window.fetch("/api/json", RequestInit(method = "post",body = formData))
.then {
it.text()
}.then {
console.info(it)
state.result=Json.decodeFromString<MessageResponse>(it).message
setState(state)
}
}
}
+"开始解析"
}
div {
+state.result
}
if(state.percentage>0F&&state.percentage<100F){
button {
attrs {
onClickFunction={
props.webSocket.send("cancel")
state=WelcomeState()
setState(state)
}
}
+"取消解析任务"
}
}
}
}
}