diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 42eee38..67bbef3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -30,14 +30,14 @@ tools:targetApi="31"> diff --git a/app/src/main/java/com/greenart7c3/citrine/MainActivity.kt b/app/src/main/java/com/greenart7c3/citrine/MainActivity.kt index 2d0dd2f..f9615a6 100644 --- a/app/src/main/java/com/greenart7c3/citrine/MainActivity.kt +++ b/app/src/main/java/com/greenart7c3/citrine/MainActivity.kt @@ -30,21 +30,24 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import com.greenart7c3.citrine.service.WebSocketServerService import com.greenart7c3.citrine.ui.dialogs.ContactsDialog import com.greenart7c3.citrine.ui.theme.CitrineTheme +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch class MainActivity : ComponentActivity() { - private val requestPermissionLauncher = - registerForActivityResult( - ActivityResultContracts.RequestPermission() - ) { - val intent = Intent(this, WebSocketServerService::class.java) - startService(intent) - bindService(intent, connection, Context.BIND_AUTO_CREATE) + @OptIn(DelicateCoroutinesApi::class) + private val requestPermissionLauncher = registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { + GlobalScope.launch(Dispatchers.IO) { + start() } + } private var service: WebSocketServerService? = null private var bound = false @@ -64,6 +67,26 @@ class MainActivity : ComponentActivity() { } } + private suspend fun stop() { + isLoading.value = true + val intent = Intent(applicationContext, WebSocketServerService::class.java) + stopService(intent) + unbindService(connection) + bound = false + service = null + delay(1000) + isLoading.value = false + } + + private suspend fun start() { + isLoading.value = true + val intent = Intent(applicationContext, WebSocketServerService::class.java) + startService(intent) + bindService(intent, connection, Context.BIND_AUTO_CREATE) + delay(1000) + isLoading.value = false + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -111,10 +134,10 @@ class MainActivity : ComponentActivity() { if (isLoading.value) { CircularProgressIndicator() } else { - val isStarted = service?.webSocketServer?.server != null + val isStarted = service?.isStarted() ?: false if (isStarted) { Text("Relay started at") - Text("ws://localhost:${service?.webSocketServer?.port() ?: 0}") + Text("ws://localhost:${service?.port() ?: 0}") ElevatedButton( onClick = { coroutineScope.launch(Dispatchers.IO) { @@ -125,11 +148,7 @@ class MainActivity : ComponentActivity() { } } ) { - if (service?.webSocketServer?.server != null) { - Text("Stop") - } else { - Text("Start") - } + Text("Stop") } } else { Text("Relay not running") @@ -143,11 +162,7 @@ class MainActivity : ComponentActivity() { } } ) { - if (service?.webSocketServer?.server != null) { - Text("Stop") - } else { - Text("Start") - } + Text("Start") } } @@ -187,18 +202,4 @@ 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) - } } diff --git a/app/src/main/java/com/greenart7c3/citrine/relays/Client.kt b/app/src/main/java/com/greenart7c3/citrine/relays/Client.kt index d6c179a..b2e811d 100644 --- a/app/src/main/java/com/greenart7c3/citrine/relays/Client.kt +++ b/app/src/main/java/com/greenart7c3/citrine/relays/Client.kt @@ -21,7 +21,7 @@ package com.greenart7c3.citrine.relays import android.util.Log -import com.greenart7c3.citrine.checkNotInMainThread +import com.greenart7c3.citrine.utils.checkNotInMainThread import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.EventInterface import kotlinx.coroutines.DelicateCoroutinesApi diff --git a/app/src/main/java/com/greenart7c3/citrine/relays/Relay.kt b/app/src/main/java/com/greenart7c3/citrine/relays/Relay.kt index 81bd278..b76c745 100644 --- a/app/src/main/java/com/greenart7c3/citrine/relays/Relay.kt +++ b/app/src/main/java/com/greenart7c3/citrine/relays/Relay.kt @@ -22,8 +22,8 @@ package com.greenart7c3.citrine.relays import android.util.Log import com.greenart7c3.citrine.BuildConfig -import com.greenart7c3.citrine.HttpClientManager -import com.greenart7c3.citrine.checkNotInMainThread +import com.greenart7c3.citrine.utils.HttpClientManager +import com.greenart7c3.citrine.utils.checkNotInMainThread import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.EventInterface diff --git a/app/src/main/java/com/greenart7c3/citrine/relays/RelayPool.kt b/app/src/main/java/com/greenart7c3/citrine/relays/RelayPool.kt index 7c353e9..6415365 100644 --- a/app/src/main/java/com/greenart7c3/citrine/relays/RelayPool.kt +++ b/app/src/main/java/com/greenart7c3/citrine/relays/RelayPool.kt @@ -21,7 +21,7 @@ package com.greenart7c3.citrine.relays import androidx.compose.runtime.Immutable -import com.greenart7c3.citrine.checkNotInMainThread +import com.greenart7c3.citrine.utils.checkNotInMainThread import com.vitorpamplona.quartz.events.Event import com.vitorpamplona.quartz.events.EventInterface import kotlinx.coroutines.channels.BufferOverflow diff --git a/app/src/main/java/com/greenart7c3/citrine/CommandResult.kt b/app/src/main/java/com/greenart7c3/citrine/server/CommandResult.kt similarity index 82% rename from app/src/main/java/com/greenart7c3/citrine/CommandResult.kt rename to app/src/main/java/com/greenart7c3/citrine/server/CommandResult.kt index 2adafbe..5c59995 100644 --- a/app/src/main/java/com/greenart7c3/citrine/CommandResult.kt +++ b/app/src/main/java/com/greenart7c3/citrine/server/CommandResult.kt @@ -1,4 +1,4 @@ -package com.greenart7c3.citrine +package com.greenart7c3.citrine.server import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.vitorpamplona.quartz.events.Event @@ -14,6 +14,5 @@ data class CommandResult(val eventId: String, val result: Boolean, val descripti fun ok(event: Event) = CommandResult(event.id, true) fun duplicated(event: Event) = CommandResult(event.id, true, "duplicate:") fun invalid(event: Event, message: String) = CommandResult(event.id, false, "invalid: $message") - fun error(event: Event, message: String) = CommandResult(event.id, false, "error: $message") } } diff --git a/app/src/main/java/com/greenart7c3/citrine/Connection.kt b/app/src/main/java/com/greenart7c3/citrine/server/Connection.kt similarity index 89% rename from app/src/main/java/com/greenart7c3/citrine/Connection.kt rename to app/src/main/java/com/greenart7c3/citrine/server/Connection.kt index 3bbcd37..32c8750 100644 --- a/app/src/main/java/com/greenart7c3/citrine/Connection.kt +++ b/app/src/main/java/com/greenart7c3/citrine/server/Connection.kt @@ -1,4 +1,4 @@ -package com.greenart7c3.citrine +package com.greenart7c3.citrine.server import io.ktor.websocket.DefaultWebSocketSession import java.util.concurrent.atomic.AtomicInteger diff --git a/app/src/main/java/com/greenart7c3/citrine/CustomWebSocketServer.kt b/app/src/main/java/com/greenart7c3/citrine/server/CustomWebSocketServer.kt similarity index 94% rename from app/src/main/java/com/greenart7c3/citrine/CustomWebSocketServer.kt rename to app/src/main/java/com/greenart7c3/citrine/server/CustomWebSocketServer.kt index f6eea4e..aad639b 100644 --- a/app/src/main/java/com/greenart7c3/citrine/CustomWebSocketServer.kt +++ b/app/src/main/java/com/greenart7c3/citrine/server/CustomWebSocketServer.kt @@ -1,11 +1,16 @@ -package com.greenart7c3.citrine +package com.greenart7c3.citrine.server import android.util.Log import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import com.greenart7c3.citrine.BuildConfig import com.greenart7c3.citrine.database.AppDatabase import com.greenart7c3.citrine.database.toEventWithTags +import com.greenart7c3.citrine.utils.isEphemeral +import com.greenart7c3.citrine.utils.isParameterizedReplaceable +import com.greenart7c3.citrine.utils.shouldDelete +import com.greenart7c3.citrine.utils.shouldOverwrite import com.vitorpamplona.quartz.events.Event import io.ktor.http.ContentType import io.ktor.http.HttpMethod @@ -102,7 +107,12 @@ class CustomWebSocketServer(private val port: Int, private val appDatabase: AppD val event = objectMapper.treeToValue(eventNode, Event::class.java) if (!event.hasVerifiedSignature()) { - connection.session.send(CommandResult.invalid(event, "event signature verification failed").toJson()) + connection.session.send( + CommandResult.invalid( + event, + "event signature verification failed" + ).toJson() + ) return } diff --git a/app/src/main/java/com/greenart7c3/citrine/EOSE.kt b/app/src/main/java/com/greenart7c3/citrine/server/EOSE.kt similarity index 76% rename from app/src/main/java/com/greenart7c3/citrine/EOSE.kt rename to app/src/main/java/com/greenart7c3/citrine/server/EOSE.kt index d162217..c7bcf9c 100644 --- a/app/src/main/java/com/greenart7c3/citrine/EOSE.kt +++ b/app/src/main/java/com/greenart7c3/citrine/server/EOSE.kt @@ -1,3 +1,5 @@ +package com.greenart7c3.citrine.server + data class EOSE(val subscriptionId: String) { fun toJson(): String { return """["EOSE","$subscriptionId"]""" diff --git a/app/src/main/java/com/greenart7c3/citrine/EventFilter.kt b/app/src/main/java/com/greenart7c3/citrine/server/EventFilter.kt similarity index 98% rename from app/src/main/java/com/greenart7c3/citrine/EventFilter.kt rename to app/src/main/java/com/greenart7c3/citrine/server/EventFilter.kt index ab13793..45870ac 100644 --- a/app/src/main/java/com/greenart7c3/citrine/EventFilter.kt +++ b/app/src/main/java/com/greenart7c3/citrine/server/EventFilter.kt @@ -1,4 +1,4 @@ -package com.greenart7c3.citrine +package com.greenart7c3.citrine.server import com.vitorpamplona.quartz.events.Event import java.util.function.Predicate diff --git a/app/src/main/java/com/greenart7c3/citrine/EventRepository.kt b/app/src/main/java/com/greenart7c3/citrine/server/EventRepository.kt similarity index 98% rename from app/src/main/java/com/greenart7c3/citrine/EventRepository.kt rename to app/src/main/java/com/greenart7c3/citrine/server/EventRepository.kt index e06d98c..27b5a3c 100644 --- a/app/src/main/java/com/greenart7c3/citrine/EventRepository.kt +++ b/app/src/main/java/com/greenart7c3/citrine/server/EventRepository.kt @@ -1,4 +1,4 @@ -package com.greenart7c3.citrine +package com.greenart7c3.citrine.server import com.greenart7c3.citrine.database.toEvent import com.vitorpamplona.quartz.utils.TimeUtils diff --git a/app/src/main/java/com/greenart7c3/citrine/EventSubscription.kt b/app/src/main/java/com/greenart7c3/citrine/server/EventSubscription.kt similarity index 98% rename from app/src/main/java/com/greenart7c3/citrine/EventSubscription.kt rename to app/src/main/java/com/greenart7c3/citrine/server/EventSubscription.kt index 6f6400a..928da04 100644 --- a/app/src/main/java/com/greenart7c3/citrine/EventSubscription.kt +++ b/app/src/main/java/com/greenart7c3/citrine/server/EventSubscription.kt @@ -1,4 +1,4 @@ -package com.greenart7c3.citrine +package com.greenart7c3.citrine.server import android.util.Log import android.util.LruCache diff --git a/app/src/main/java/com/greenart7c3/citrine/NoticeResult.kt b/app/src/main/java/com/greenart7c3/citrine/server/NoticeResult.kt similarity index 85% rename from app/src/main/java/com/greenart7c3/citrine/NoticeResult.kt rename to app/src/main/java/com/greenart7c3/citrine/server/NoticeResult.kt index fe8e9d2..691937b 100644 --- a/app/src/main/java/com/greenart7c3/citrine/NoticeResult.kt +++ b/app/src/main/java/com/greenart7c3/citrine/server/NoticeResult.kt @@ -1,4 +1,4 @@ -package com.greenart7c3.citrine +package com.greenart7c3.citrine.server data class NoticeResult(val message: String) { fun toJson(): String { diff --git a/app/src/main/java/com/greenart7c3/citrine/SubscriptionManager.kt b/app/src/main/java/com/greenart7c3/citrine/server/SubscriptionManager.kt similarity index 98% rename from app/src/main/java/com/greenart7c3/citrine/SubscriptionManager.kt rename to app/src/main/java/com/greenart7c3/citrine/server/SubscriptionManager.kt index 976e69f..c7c5d7a 100644 --- a/app/src/main/java/com/greenart7c3/citrine/SubscriptionManager.kt +++ b/app/src/main/java/com/greenart7c3/citrine/server/SubscriptionManager.kt @@ -1,6 +1,5 @@ -package com.greenart7c3.citrine +package com.greenart7c3.citrine.server -import EOSE import android.util.Log import io.ktor.websocket.send import kotlinx.coroutines.CancellationException diff --git a/app/src/main/java/com/greenart7c3/citrine/BootBroadcastReceiver.kt b/app/src/main/java/com/greenart7c3/citrine/service/BootBroadcastReceiver.kt similarity index 91% rename from app/src/main/java/com/greenart7c3/citrine/BootBroadcastReceiver.kt rename to app/src/main/java/com/greenart7c3/citrine/service/BootBroadcastReceiver.kt index 3de193f..391b68c 100644 --- a/app/src/main/java/com/greenart7c3/citrine/BootBroadcastReceiver.kt +++ b/app/src/main/java/com/greenart7c3/citrine/service/BootBroadcastReceiver.kt @@ -1,4 +1,4 @@ -package com.greenart7c3.citrine +package com.greenart7c3.citrine.service import android.content.BroadcastReceiver import android.content.Context diff --git a/app/src/main/java/com/greenart7c3/citrine/WebSocketServerService.kt b/app/src/main/java/com/greenart7c3/citrine/service/WebSocketServerService.kt similarity index 89% rename from app/src/main/java/com/greenart7c3/citrine/WebSocketServerService.kt rename to app/src/main/java/com/greenart7c3/citrine/service/WebSocketServerService.kt index b0a969d..a56da9a 100644 --- a/app/src/main/java/com/greenart7c3/citrine/WebSocketServerService.kt +++ b/app/src/main/java/com/greenart7c3/citrine/service/WebSocketServerService.kt @@ -1,4 +1,4 @@ -package com.greenart7c3.citrine +package com.greenart7c3.citrine.service import android.annotation.SuppressLint import android.app.Notification @@ -18,7 +18,11 @@ import android.os.Build import android.os.IBinder import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat.getSystemService +import com.greenart7c3.citrine.MainActivity +import com.greenart7c3.citrine.R import com.greenart7c3.citrine.database.AppDatabase +import com.greenart7c3.citrine.server.CustomWebSocketServer +import com.greenart7c3.citrine.server.EventSubscription class WebSocketServerService : Service() { lateinit var webSocketServer: CustomWebSocketServer @@ -52,9 +56,8 @@ class WebSocketServerService : Service() { } // Start the WebSocket server - val port = if (BuildConfig.DEBUG) defaultPortDebug else defaultPort webSocketServer = CustomWebSocketServer( - port, + DEFAULT_PORT, AppDatabase.getDatabase(this@WebSocketServerService) ) webSocketServer.start() @@ -103,8 +106,15 @@ class WebSocketServerService : Service() { return notificationBuilder.build() } + fun isStarted(): Boolean { + return webSocketServer.server != null + } + + fun port(): Int? { + return webSocketServer.port() + } + companion object { - const val defaultPort = 4869 - const val defaultPortDebug = 4869 + const val DEFAULT_PORT = 4869 } } diff --git a/app/src/main/java/com/greenart7c3/citrine/ui/dialogs/ContactsDialog.kt b/app/src/main/java/com/greenart7c3/citrine/ui/dialogs/ContactsDialog.kt index 61d4d9a..9ea9b82 100644 --- a/app/src/main/java/com/greenart7c3/citrine/ui/dialogs/ContactsDialog.kt +++ b/app/src/main/java/com/greenart7c3/citrine/ui/dialogs/ContactsDialog.kt @@ -35,8 +35,8 @@ import androidx.compose.ui.window.DialogProperties import com.greenart7c3.citrine.database.AppDatabase import com.greenart7c3.citrine.database.toEvent import com.greenart7c3.citrine.relays.Client -import com.greenart7c3.citrine.toDateString import com.greenart7c3.citrine.ui.CloseButton +import com.greenart7c3.citrine.utils.toDateString import com.vitorpamplona.quartz.encoders.bechToBytes import com.vitorpamplona.quartz.encoders.toHexKey import com.vitorpamplona.quartz.events.ContactListEvent diff --git a/app/src/main/java/com/greenart7c3/citrine/DateUtils.kt b/app/src/main/java/com/greenart7c3/citrine/utils/DateUtils.kt similarity index 92% rename from app/src/main/java/com/greenart7c3/citrine/DateUtils.kt rename to app/src/main/java/com/greenart7c3/citrine/utils/DateUtils.kt index 7b88a97..292f285 100644 --- a/app/src/main/java/com/greenart7c3/citrine/DateUtils.kt +++ b/app/src/main/java/com/greenart7c3/citrine/utils/DateUtils.kt @@ -1,4 +1,4 @@ -package com.greenart7c3.citrine +package com.greenart7c3.citrine.utils import java.time.Instant import java.time.LocalDateTime diff --git a/app/src/main/java/com/greenart7c3/citrine/Extensions.kt b/app/src/main/java/com/greenart7c3/citrine/utils/Extensions.kt similarity index 94% rename from app/src/main/java/com/greenart7c3/citrine/Extensions.kt rename to app/src/main/java/com/greenart7c3/citrine/utils/Extensions.kt index 6dfc92f..14fd325 100644 --- a/app/src/main/java/com/greenart7c3/citrine/Extensions.kt +++ b/app/src/main/java/com/greenart7c3/citrine/utils/Extensions.kt @@ -1,4 +1,4 @@ -package com.greenart7c3.citrine +package com.greenart7c3.citrine.utils import com.vitorpamplona.quartz.events.Event diff --git a/app/src/main/java/com/greenart7c3/citrine/HttpClientManager.kt b/app/src/main/java/com/greenart7c3/citrine/utils/HttpClientManager.kt similarity index 88% rename from app/src/main/java/com/greenart7c3/citrine/HttpClientManager.kt rename to app/src/main/java/com/greenart7c3/citrine/utils/HttpClientManager.kt index 8015537..67e29c7 100644 --- a/app/src/main/java/com/greenart7c3/citrine/HttpClientManager.kt +++ b/app/src/main/java/com/greenart7c3/citrine/utils/HttpClientManager.kt @@ -18,9 +18,10 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.greenart7c3.citrine +package com.greenart7c3.citrine.utils import android.util.Log +import com.greenart7c3.citrine.BuildConfig import okhttp3.Interceptor import okhttp3.OkHttpClient import okhttp3.Request @@ -50,20 +51,20 @@ object HttpClientManager { fun setDefaultProxy(proxy: Proxy?) { if (internalProxy != proxy) { Log.d("HttpClient", "Changing proxy to: ${proxy != null}") - this.internalProxy = proxy + internalProxy = proxy // recreates singleton - this.defaultHttpClient = buildHttpClient(internalProxy, defaultTimeout) + defaultHttpClient = buildHttpClient(internalProxy, defaultTimeout) } } fun setDefaultTimeout(timeout: Duration) { Log.d("HttpClient", "Changing timeout to: $timeout") - if (this.defaultTimeout.seconds != timeout.seconds) { - this.defaultTimeout = timeout + if (defaultTimeout.seconds != timeout.seconds) { + defaultTimeout = timeout // recreates singleton - this.defaultHttpClient = buildHttpClient(internalProxy, defaultTimeout) + defaultHttpClient = buildHttpClient(internalProxy, defaultTimeout) } } @@ -98,8 +99,8 @@ object HttpClientManager { } fun getHttpClient(): OkHttpClient { - if (this.defaultHttpClient == null) { - this.defaultHttpClient = buildHttpClient(internalProxy, defaultTimeout) + if (defaultHttpClient == null) { + defaultHttpClient = buildHttpClient(internalProxy, defaultTimeout) } return defaultHttpClient!! } diff --git a/app/src/main/java/com/greenart7c3/citrine/MainThreadChecker.kt b/app/src/main/java/com/greenart7c3/citrine/utils/MainThreadChecker.kt similarity index 94% rename from app/src/main/java/com/greenart7c3/citrine/MainThreadChecker.kt rename to app/src/main/java/com/greenart7c3/citrine/utils/MainThreadChecker.kt index f87251c..a1c848a 100644 --- a/app/src/main/java/com/greenart7c3/citrine/MainThreadChecker.kt +++ b/app/src/main/java/com/greenart7c3/citrine/utils/MainThreadChecker.kt @@ -18,9 +18,10 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.greenart7c3.citrine +package com.greenart7c3.citrine.utils import android.os.Looper +import com.greenart7c3.citrine.BuildConfig fun checkNotInMainThread() { if (BuildConfig.DEBUG && isMainThread()) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index db3184f..feb823e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ okhttp = "5.0.0-alpha.12" room = "2.6.1" workRuntimeKtx = "2.9.0" material3 = "1.2.0" -quartz = "v0.85.0" +quartz = "v0.85.3" [libraries] androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" }