Skip to content

Commit

Permalink
add start/stop button
Browse files Browse the repository at this point in the history
  • Loading branch information
greenart7c3 committed Feb 12, 2024
1 parent e7c3a94 commit b7c3f6e
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 30 deletions.
15 changes: 10 additions & 5 deletions app/src/main/java/com/greenart7c3/citrine/CustomWebSocketServer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,25 @@ import kotlinx.coroutines.channels.ClosedReceiveChannelException
import java.util.zip.Deflater

class CustomWebSocketServer(private val port: Int, private val appDatabase: AppDatabase) {
private lateinit var server: ApplicationEngine
var server: ApplicationEngine? = null
private val objectMapper = jacksonObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

fun port(): Int {
return server.environment.connectors.first().port
fun port(): Int? {
return server?.environment?.connectors?.first()?.port
}

fun start() {
server = startKtorHttpServer(port)
if (server == null) {
server = startKtorHttpServer(port)
} else {
server!!.start(false)
}
}

fun stop() {
server.stop(1000)
server!!.stop(1000)
server = null
}

private suspend fun subscribe(
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/greenart7c3/citrine/EventFilter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ data class EventFilter(
val authors: Set<String> = emptySet(),
val kinds: Set<Int> = emptySet(),
val tags: Map<String, Set<String>> = emptyMap(),
val since: Int? = null,
var since: Int? = null,
val until: Int? = null,
val limit: Int = 10_000,
private val search: String? = null
Expand All @@ -17,7 +17,7 @@ data class EventFilter(
val searchKeywords: Set<String> = search?.let { tokenizeString(search) } ?: emptySet()

override fun test(event: Event): Boolean {
if (since != null && event.createdAt < since) {
if (since != null && event.createdAt < since!!) {
return false
}

Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/com/greenart7c3/citrine/EventRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ object EventRepository {
)
)
)
if (item.isLast) {
filter.since = event.createdAt.plus(1).toInt()
}
}
}
}
Expand Down
81 changes: 65 additions & 16 deletions app/src/main/java/com/greenart7c3/citrine/EventSubscription.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ import com.fasterxml.jackson.databind.ObjectMapper
import com.greenart7c3.citrine.database.AppDatabase
import io.ktor.server.websocket.DefaultWebSocketServerSession
import io.ktor.websocket.send
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.util.concurrent.ConcurrentHashMap

data class Subscription(
val id: String,
val session: DefaultWebSocketServerSession
val session: DefaultWebSocketServerSession,
val filters: Set<EventFilter>
)

object EventSubscription {
Expand All @@ -21,27 +27,70 @@ object EventSubscription {
subscriptions.remove(subscriptionId)
}

suspend fun subscribe(subscriptionId: String, filters: Set<EventFilter>, session: DefaultWebSocketServerSession, appDatabase: AppDatabase, objectMapper: ObjectMapper) {
subscriptions.plus(
Pair(
@OptIn(DelicateCoroutinesApi::class)
suspend fun subscribe(
subscriptionId: String,
filters: Set<EventFilter>,
session: DefaultWebSocketServerSession,
appDatabase: AppDatabase,
objectMapper: ObjectMapper,
self: Boolean = false
) {
if (self && filters != subscriptions[subscriptionId]?.filters) {
Log.d("filters", "closed")
return
} else {
close(subscriptionId)
subscriptions[subscriptionId] = Subscription(
subscriptionId,
Subscription(
session,
filters
)

for (filter in filters) {
try {
runBlocking {
EventRepository.subscribe(
subscriptionId,
filter,
session,
appDatabase,
objectMapper
)
}
} catch (e: Exception) {
Log.d("error", "Error reading data from database", e)
session.send(
NoticeResult.invalid("Error reading data from database").toJson()
)
}
}
session.send(EOSE(subscriptionId).toJson())

GlobalScope.launch(Dispatchers.IO) {
delay(5000)
subscriptions[subscriptionId] = Subscription(
subscriptionId,
session
session,
filters.map {
val since = it.since?.plus(1) ?: (System.currentTimeMillis() / 1000).toInt()
it.since = since
it
}.toSet()
)
)
)

for (filter in filters) {
try {
runBlocking {
EventRepository.subscribe(subscriptionId, filter, session, appDatabase, objectMapper)
val subscription = subscriptions[subscriptionId]
if (subscription != null) {
subscribe(
subscription.id,
subscription.filters,
subscription.session,
appDatabase,
objectMapper,
true
)
}
} catch (e: Exception) {
Log.d("error", "Error reading data from database", e)
session.send(NoticeResult.invalid("Error reading data from database").toJson())
}
}
session.send(EOSE(subscriptionId).toJson())
}
}
64 changes: 59 additions & 5 deletions app/src/main/java/com/greenart7c3/citrine/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,18 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ElevatedButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.greenart7c3.citrine.ui.theme.CitrineTheme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
private val requestPermissionLauncher =
Expand All @@ -34,15 +38,13 @@ class MainActivity : ComponentActivity() {

private var service: WebSocketServerService? = null
private var bound = false
private var port = mutableIntStateOf(0)
private var isLoading = mutableStateOf(true)

private val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
val binder = service as WebSocketServerService.LocalBinder
this@MainActivity.service = binder.getService()
bound = true
port.intValue = this@MainActivity.service?.webSocketServer?.port() ?: 0
this@MainActivity.isLoading.value = false
}

Expand All @@ -58,6 +60,7 @@ class MainActivity : ComponentActivity() {
requestPermissionLauncher.launch("android.permission.POST_NOTIFICATIONS")

setContent {
val coroutineScope = rememberCoroutineScope()
CitrineTheme {
Surface(
modifier = Modifier.fillMaxSize(),
Expand All @@ -70,8 +73,45 @@ class MainActivity : ComponentActivity() {
if (isLoading.value) {
CircularProgressIndicator()
} else {
Text("Relay started at")
Text("ws://localhost:${port.intValue}")
val isStarted = service?.webSocketServer?.server != null
if (isStarted) {
Text("Relay started at")
Text("ws://localhost:${service?.webSocketServer?.port() ?: 0}")
ElevatedButton(
onClick = {
coroutineScope.launch(Dispatchers.IO) {
isLoading.value = true
stop()
delay(1000)
isLoading.value = false
}
}
) {
if (service?.webSocketServer?.server != null) {
Text("Stop")
} else {
Text("Start")
}
}
} else {
Text("Relay not running")
ElevatedButton(
onClick = {
coroutineScope.launch(Dispatchers.IO) {
isLoading.value = true
start()
delay(1000)
isLoading.value = false
}
}
) {
if (service?.webSocketServer?.server != null) {
Text("Stop")
} else {
Text("Start")
}
}
}
}
}
}
Expand All @@ -86,4 +126,18 @@ class MainActivity : ComponentActivity() {
}
super.onDestroy()
}

private fun stop() {
val intent = Intent(applicationContext, WebSocketServerService::class.java)
stopService(intent)
unbindService(connection)
bound = false
service = null
}

private fun start() {
val intent = Intent(applicationContext, WebSocketServerService::class.java)
startService(intent)
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.greenart7c3.citrine

import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
Expand Down Expand Up @@ -38,6 +39,7 @@ class WebSocketServerService : Service() {
}
}

@SuppressLint("UnspecifiedRegisterReceiverFlag")
override fun onCreate() {
super.onCreate()

Expand All @@ -62,10 +64,9 @@ class WebSocketServerService : Service() {
}

override fun onDestroy() {
super.onDestroy()
unregisterReceiver(brCopy)
// Stop the WebSocket server when the service is destroyed
webSocketServer.stop()
super.onDestroy()
}

override fun onBind(intent: Intent?): IBinder {
Expand Down

0 comments on commit b7c3f6e

Please sign in to comment.