initial commit
This commit is contained in:
15
src/jvmMain/kotlin/online/maestoso/cofront/Cofront.kt
Normal file
15
src/jvmMain/kotlin/online/maestoso/cofront/Cofront.kt
Normal file
@@ -0,0 +1,15 @@
|
||||
package online.maestoso.cofront
|
||||
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.engine.*
|
||||
import io.ktor.server.netty.*
|
||||
import online.maestoso.cofront.frontend.configureFrontend
|
||||
|
||||
fun main() {
|
||||
embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = Application::module)
|
||||
.start(wait = true)
|
||||
}
|
||||
fun Application.module() {
|
||||
configureSecurity()
|
||||
configureFrontend()
|
||||
}
|
||||
25
src/jvmMain/kotlin/online/maestoso/cofront/Security.kt
Normal file
25
src/jvmMain/kotlin/online/maestoso/cofront/Security.kt
Normal file
@@ -0,0 +1,25 @@
|
||||
package online.maestoso.cofront
|
||||
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import io.ktor.server.sessions.*
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
fun Application.configureSecurity() {
|
||||
install(Sessions) {
|
||||
cookie<MySession>("MY_SESSION") {
|
||||
cookie.extensions["SameSite"] = "lax"
|
||||
}
|
||||
}
|
||||
routing {
|
||||
get("/session/increment") {
|
||||
val session = call.sessions.get<MySession>() ?: MySession()
|
||||
call.sessions.set(session.copy(count = session.count + 1))
|
||||
call.respondText("Counter is ${session.count}. Refresh to increment.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class MySession(val count: Int = 0)
|
||||
11
src/jvmMain/kotlin/online/maestoso/cofront/api/API.kt
Normal file
11
src/jvmMain/kotlin/online/maestoso/cofront/api/API.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
@file:OptIn(ExperimentalUuidApi::class)
|
||||
|
||||
package online.maestoso.cofront.api
|
||||
|
||||
import online.maestoso.cofront.Identifier
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
fun test() {
|
||||
val i = Identifier(Uuid.generateV7(), "localhost")
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package online.maestoso.cofront.frontend
|
||||
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.response.respondResource
|
||||
import io.ktor.server.routing.get
|
||||
import io.ktor.server.routing.routing
|
||||
import kotlinx.html.FlowOrMetaDataOrPhrasingContent
|
||||
import kotlinx.html.link
|
||||
import kotlinx.html.meta
|
||||
|
||||
const val FAVICON_ROOT: String = "/static/favicon"
|
||||
fun FlowOrMetaDataOrPhrasingContent.favicon() {
|
||||
link(rel = "icon", type = "image/png", href= "$FAVICON_ROOT/favicon-96x96.png") {
|
||||
attributes["sizes"] = "96x96"
|
||||
}
|
||||
link(rel = "icon", type = "image/svg+xml", href="$FAVICON_ROOT/favicon.svg")
|
||||
link(rel = "shortcut icon", href="$FAVICON_ROOT/favicon.ico")
|
||||
link(rel = "apple-touch-icon", href="$FAVICON_ROOT/apple-touch-icon.png") {
|
||||
attributes["sizes"] = "180x180"
|
||||
}
|
||||
meta(name = "apple-mobile-web-app-tile", content="Cofront")
|
||||
link(rel = "manifest", href="$FAVICON_ROOT/site.webmanifest")
|
||||
}
|
||||
fun Application.configureFavicon() {
|
||||
routing {
|
||||
get("/favicon.ico") {
|
||||
call.respondResource("static/favicon/favicon.ico")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package online.maestoso.cofront.frontend
|
||||
|
||||
import io.ktor.server.application.Application
|
||||
|
||||
fun Application.configureFrontend() {
|
||||
configureResources()
|
||||
addAllPages()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package online.maestoso.cofront.frontend
|
||||
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.http.content.staticResources
|
||||
import io.ktor.server.routing.get
|
||||
import io.ktor.server.routing.routing
|
||||
import kotlinx.html.FlowOrMetaDataOrPhrasingContent
|
||||
import kotlinx.html.script
|
||||
|
||||
fun Application.configureJavascript() {
|
||||
routing {
|
||||
staticResources("/js", "js")
|
||||
}
|
||||
}
|
||||
|
||||
fun FlowOrMetaDataOrPhrasingContent.js() {
|
||||
script(type = ContentType.Text.JavaScript.toString(), src = "js/Cofront.js") {}
|
||||
}
|
||||
50
src/jvmMain/kotlin/online/maestoso/cofront/frontend/Page.kt
Normal file
50
src/jvmMain/kotlin/online/maestoso/cofront/frontend/Page.kt
Normal file
@@ -0,0 +1,50 @@
|
||||
package online.maestoso.cofront.frontend
|
||||
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.html.*
|
||||
import io.ktor.server.routing.*
|
||||
import kotlinx.css.CssBuilder
|
||||
import kotlinx.html.BODY
|
||||
import kotlinx.html.HEAD
|
||||
import kotlinx.html.body
|
||||
import kotlinx.html.head
|
||||
import kotlinx.html.meta
|
||||
import kotlinx.html.style
|
||||
import kotlinx.html.unsafe
|
||||
import online.maestoso.cofront.frontend.pages.Index
|
||||
import kotlin.String
|
||||
import kotlin.Unit
|
||||
|
||||
abstract class Page(val path: String) {
|
||||
open val style: CssBuilder.() -> Unit = {}
|
||||
open val head: HEAD.() -> Unit = {}
|
||||
open val body: BODY.() -> Unit = {}
|
||||
|
||||
fun addPage(app: Application) {
|
||||
app.routing {
|
||||
get(this@Page.path) {
|
||||
call.respondHtml {
|
||||
head {
|
||||
meta(charset = Charsets.UTF_8.toString())
|
||||
stylesheet()
|
||||
favicon()
|
||||
js()
|
||||
apply(this@Page.head)
|
||||
val css = CssBuilder().apply(this@Page.style)
|
||||
unsafe {
|
||||
this@head.style(type = ContentType.Text.CSS.toString(), content = css.toString())
|
||||
}
|
||||
}
|
||||
body {
|
||||
apply(this@Page.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Application.addAllPages() {
|
||||
Index.addPage(this)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package online.maestoso.cofront.frontend
|
||||
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.http.content.*
|
||||
import io.ktor.server.response.respondRedirect
|
||||
import io.ktor.server.routing.*
|
||||
|
||||
fun Application.configureResources() {
|
||||
configureFavicon()
|
||||
configureJavascript()
|
||||
routing {
|
||||
get("/res/{path}") {
|
||||
when(call.parameters["path"]) {
|
||||
"index.css" -> call.configureStylesheet()
|
||||
else -> call.respondRedirect("/static/${call.parameters["path"]}", true)
|
||||
}
|
||||
}
|
||||
staticResources("/static", "static")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package online.maestoso.cofront.frontend
|
||||
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import kotlinx.css.*
|
||||
import kotlinx.html.FlowOrMetaDataOrPhrasingContent
|
||||
import kotlinx.html.link
|
||||
|
||||
suspend fun RoutingCall.configureStylesheet() {
|
||||
css {
|
||||
media("(prefers-color-scheme: dark)") {
|
||||
html {
|
||||
backgroundColor = Color("#222")
|
||||
color = Color.white
|
||||
}
|
||||
}
|
||||
media("not (prefers-color-scheme: dark)") {
|
||||
html {
|
||||
backgroundColor = Color.ghostWhite
|
||||
color = Color.black
|
||||
}
|
||||
}
|
||||
html {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
suspend inline fun ApplicationCall.css(builder: CssBuilder.() -> Unit) {
|
||||
this.respondText(CssBuilder().apply(builder).toString(), ContentType.Text.CSS)
|
||||
}
|
||||
fun FlowOrMetaDataOrPhrasingContent.stylesheet() {
|
||||
link(rel = "stylesheet", href = "/res/index.css")
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package online.maestoso.cofront.frontend.pages
|
||||
|
||||
import kotlinx.html.BODY
|
||||
import kotlinx.html.h1
|
||||
import online.maestoso.cofront.frontend.Page
|
||||
|
||||
object Index : Page("/") {
|
||||
override val body: BODY.() -> Unit = {
|
||||
h1 {
|
||||
+"Cofront"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user