basic frontend added
This commit is contained in:
17
app/src/main/assets/webui/assets/index-BR9M1eFw.js
Normal file
17
app/src/main/assets/webui/assets/index-BR9M1eFw.js
Normal file
File diff suppressed because one or more lines are too long
1
app/src/main/assets/webui/assets/index-jwVA1VU4.css
Normal file
1
app/src/main/assets/webui/assets/index-jwVA1VU4.css
Normal file
File diff suppressed because one or more lines are too long
14
app/src/main/assets/webui/index.html
Normal file
14
app/src/main/assets/webui/index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Textpipe SMS Gateway</title>
|
||||
<script type="module" crossorigin src="./assets/index-BR9M1eFw.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-jwVA1VU4.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,5 +1,6 @@
|
||||
package sh.sar.textpipe.server
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import io.ktor.http.*
|
||||
import io.ktor.serialization.kotlinx.json.*
|
||||
@@ -13,18 +14,18 @@ import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import kotlinx.serialization.json.Json
|
||||
import sh.sar.textpipe.data.model.ErrorResponse
|
||||
import sh.sar.textpipe.data.repository.SmsRepository
|
||||
import sh.sar.textpipe.server.auth.configureAuth
|
||||
import sh.sar.textpipe.server.routes.smsRoutes
|
||||
import sh.sar.textpipe.server.routes.statusRoutes
|
||||
import sh.sar.textpipe.server.routes.webUIRoutes
|
||||
import sh.sar.textpipe.sim.SimManager
|
||||
import java.net.BindException
|
||||
import java.net.ServerSocket
|
||||
|
||||
class TextpipeServer(
|
||||
private val context: Context,
|
||||
private val smsRepository: SmsRepository,
|
||||
private val simManager: SimManager
|
||||
) {
|
||||
@@ -143,6 +144,10 @@ class TextpipeServer(
|
||||
|
||||
private fun Application.configureRouting() {
|
||||
routing {
|
||||
// Web UI routes (served from assets)
|
||||
webUIRoutes(context)
|
||||
|
||||
// API routes
|
||||
statusRoutes(simManager, { startTime }, { currentPort })
|
||||
smsRoutes(smsRepository)
|
||||
}
|
||||
|
||||
@@ -6,10 +6,6 @@ import sh.sar.textpipe.data.model.StatusResponse
|
||||
import sh.sar.textpipe.sim.SimManager
|
||||
|
||||
fun Route.statusRoutes(simManager: SimManager, getStartTime: () -> Long, getPort: () -> Int) {
|
||||
get("/") {
|
||||
call.respondText("Textpipe SMS Gateway API")
|
||||
}
|
||||
|
||||
get("/api/status") {
|
||||
val uptime = System.currentTimeMillis() - getStartTime()
|
||||
val response = StatusResponse(
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package sh.sar.textpipe.server.routes
|
||||
|
||||
import android.content.Context
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import java.io.IOException
|
||||
|
||||
fun Route.webUIRoutes(context: Context) {
|
||||
get("/") {
|
||||
serveAsset(context, call, "index.html", ContentType.Text.Html)
|
||||
}
|
||||
|
||||
get("/assets/{file}") {
|
||||
val fileName = call.parameters["file"] ?: return@get
|
||||
val contentType = getContentType(fileName)
|
||||
serveAsset(context, call, "assets/$fileName", contentType)
|
||||
}
|
||||
|
||||
get("/favicon.svg") {
|
||||
serveAsset(context, call, "favicon.svg", ContentType.Image.SVG)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun serveAsset(
|
||||
context: Context,
|
||||
call: io.ktor.server.application.ApplicationCall,
|
||||
path: String,
|
||||
contentType: ContentType
|
||||
) {
|
||||
try {
|
||||
val inputStream = context.assets.open("webui/$path")
|
||||
val bytes = inputStream.readBytes()
|
||||
inputStream.close()
|
||||
call.respondBytes(bytes, contentType)
|
||||
} catch (e: IOException) {
|
||||
call.respond(HttpStatusCode.NotFound, "File not found: $path")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getContentType(fileName: String): ContentType {
|
||||
return when {
|
||||
fileName.endsWith(".js") -> ContentType.Application.JavaScript
|
||||
fileName.endsWith(".css") -> ContentType.Text.CSS
|
||||
fileName.endsWith(".html") -> ContentType.Text.Html
|
||||
fileName.endsWith(".svg") -> ContentType.Image.SVG
|
||||
fileName.endsWith(".png") -> ContentType.Image.PNG
|
||||
fileName.endsWith(".jpg") || fileName.endsWith(".jpeg") -> ContentType.Image.JPEG
|
||||
fileName.endsWith(".json") -> ContentType.Application.Json
|
||||
else -> ContentType.Application.OctetStream
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ class TextpipeService : Service() {
|
||||
smsSender.register()
|
||||
|
||||
smsRepository = SmsRepository(dao, smsSender, simManager)
|
||||
textpipeServer = TextpipeServer(smsRepository, simManager)
|
||||
textpipeServer = TextpipeServer(this, smsRepository, simManager)
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
|
||||
Reference in New Issue
Block a user