From 47583974dd867a3def7abafe4ce4ce0ac03c6425 Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski <janne@kuschku.de> Date: Mon, 28 Feb 2022 02:38:57 +0100 Subject: [PATCH] feat: implement a simple version of the message renderer --- .../quasseldroid/ui/routes/HomeRoute.kt | 68 ------ .../justjanne/quasseldroid/ui/theme/Color.kt | 11 - .../de/justjanne/quasseldroid/MainActivity.kt | 0 .../quasseldroid/QuasseldroidRouter.kt | 0 .../quasseldroid/messages/MessageBuffer.kt | 0 .../quasseldroid/messages/MessageStore.kt | 0 .../sample/SampleConnectedClientProvider.kt | 0 .../sample/SampleCoreInfoProvider.kt | 0 .../service/ClientSessionWrapper.kt | 0 .../quasseldroid/service/ConnectionData.kt | 0 .../quasseldroid/service/QuasselBackend.kt | 0 .../quasseldroid/service/QuasselBinder.kt | 0 .../quasseldroid/service/QuasselRunner.kt | 0 .../quasseldroid/service/QuasselService.kt | 0 .../ui/components/ConnectedClientCard.kt | 0 .../ui/components/CoreInfoView.kt | 0 .../quasseldroid/ui/components/LoginView.kt | 2 +- .../ui/components/PasswordTextField.kt | 0 .../quasseldroid/ui/routes/CoreInfoRoute.kt | 0 .../quasseldroid/ui/routes/HomeRoute.kt | 220 ++++++++++++++++++ .../quasseldroid/ui/routes/LoginRoute.kt | 0 .../justjanne/quasseldroid/ui/theme/Color.kt | 30 +++ .../justjanne/quasseldroid/ui/theme/Shape.kt | 0 .../justjanne/quasseldroid/ui/theme/Theme.kt | 0 .../justjanne/quasseldroid/ui/theme/Type.kt | 0 .../quasseldroid/util/FlowExtensions.kt | 6 + .../lifecycle/ContextualLifecycleObserver.kt | 0 .../DefaultContextualLifecycleObserver.kt | 0 .../util/lifecycle/LifecycleStatus.kt | 0 .../quasseldroid/util/saver/BufferIdSaver.kt | 10 + .../util/saver/IdentityIdSaver.kt | 10 + .../quasseldroid/util/saver/MsgIdSaver.kt | 10 + .../quasseldroid/util/saver/NetworkIdSaver.kt | 10 + .../util/saver}/TextFieldValueSaver.kt | 2 +- app/src/main/kotlin/irc/CRCUtils.kt | 44 ++++ app/src/main/kotlin/irc/SenderColorUtil.kt | 13 ++ .../util/irc/SenderColorUtilTest.kt | 14 ++ .../src/main/kotlin/justjanne.java.gradle.kts | 13 ++ .../justjanne.kotlin.android.gradle.kts | 18 ++ .../main/kotlin/justjanne.kotlin.gradle.kts | 4 +- 40 files changed, 403 insertions(+), 82 deletions(-) delete mode 100644 app/src/main/java/de/justjanne/quasseldroid/ui/routes/HomeRoute.kt delete mode 100644 app/src/main/java/de/justjanne/quasseldroid/ui/theme/Color.kt rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/MainActivity.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/QuasseldroidRouter.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/messages/MessageBuffer.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/messages/MessageStore.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/sample/SampleConnectedClientProvider.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/sample/SampleCoreInfoProvider.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/service/ClientSessionWrapper.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/service/ConnectionData.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/service/QuasselBackend.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/service/QuasselBinder.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/service/QuasselRunner.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/service/QuasselService.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/ui/components/ConnectedClientCard.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/ui/components/CoreInfoView.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/ui/components/LoginView.kt (98%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/ui/components/PasswordTextField.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/ui/routes/CoreInfoRoute.kt (100%) create mode 100644 app/src/main/kotlin/de/justjanne/quasseldroid/ui/routes/HomeRoute.kt rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/ui/routes/LoginRoute.kt (100%) create mode 100644 app/src/main/kotlin/de/justjanne/quasseldroid/ui/theme/Color.kt rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/ui/theme/Shape.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/ui/theme/Theme.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/ui/theme/Type.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/util/FlowExtensions.kt (81%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/util/lifecycle/ContextualLifecycleObserver.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/util/lifecycle/DefaultContextualLifecycleObserver.kt (100%) rename app/src/main/{java => kotlin}/de/justjanne/quasseldroid/util/lifecycle/LifecycleStatus.kt (100%) create mode 100644 app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/BufferIdSaver.kt create mode 100644 app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/IdentityIdSaver.kt create mode 100644 app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/MsgIdSaver.kt create mode 100644 app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/NetworkIdSaver.kt rename app/src/main/{java/de/justjanne/quasseldroid/util => kotlin/de/justjanne/quasseldroid/util/saver}/TextFieldValueSaver.kt (88%) create mode 100644 app/src/main/kotlin/irc/CRCUtils.kt create mode 100644 app/src/main/kotlin/irc/SenderColorUtil.kt create mode 100644 app/src/test/kotlin/de/kuschku/justjanne/quasseldroid/util/irc/SenderColorUtilTest.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/ui/routes/HomeRoute.kt b/app/src/main/java/de/justjanne/quasseldroid/ui/routes/HomeRoute.kt deleted file mode 100644 index 165d193ba..000000000 --- a/app/src/main/java/de/justjanne/quasseldroid/ui/routes/HomeRoute.kt +++ /dev/null @@ -1,68 +0,0 @@ -package de.justjanne.quasseldroid.ui.routes - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.Button -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.platform.LocalContext -import androidx.navigation.NavController -import de.justjanne.libquassel.protocol.syncables.state.BufferViewConfigState -import de.justjanne.libquassel.protocol.util.combineLatest -import de.justjanne.libquassel.protocol.util.flatMap -import de.justjanne.quasseldroid.service.QuasselBackend -import de.justjanne.quasseldroid.util.mapNullable -import de.justjanne.quasseldroid.util.rememberFlow - -@Composable -fun HomeRoute(backend: QuasselBackend, navController: NavController) { - val session = rememberFlow(null) { - backend.flow() - .mapNullable { it.session } - } - - val bufferViewConfigs: List<BufferViewConfigState> = rememberFlow(emptyList()) { - backend.flow() - .mapNullable { it.session } - .flatMap() - .mapNullable { it.bufferViewManager } - .flatMap() - .mapNullable { it.bufferViewConfigs() } - .combineLatest() - } - - val initStatus = rememberFlow(null) { - backend.flow() - .mapNullable { it.session } - .mapNullable { it.baseInitHandler } - .flatMap() - } - - val context = LocalContext.current - Column { - Text("Side: ${session?.side}") - if (initStatus != null) { - val done = initStatus.total - initStatus.waiting.size - Text("Init: ${initStatus.started} $done/ ${initStatus.total}") - } - Button(onClick = { navController.navigate("coreInfo") }) { - Text("Core Info") - } - Button(onClick = { - backend.disconnect(context) - navController.navigate("login") - }) { - Text("Disconnect") - } - Text("BufferViewConfigs: ${bufferViewConfigs.size}") - LazyColumn { - items(bufferViewConfigs, key = BufferViewConfigState::bufferViewId) { - Row { - Text("${it.bufferViewId}: ${it.bufferViewName}") - } - } - } - } -} diff --git a/app/src/main/java/de/justjanne/quasseldroid/ui/theme/Color.kt b/app/src/main/java/de/justjanne/quasseldroid/ui/theme/Color.kt deleted file mode 100644 index 269987abf..000000000 --- a/app/src/main/java/de/justjanne/quasseldroid/ui/theme/Color.kt +++ /dev/null @@ -1,11 +0,0 @@ -package de.justjanne.quasseldroid.ui.theme - -import androidx.compose.ui.graphics.Color - -val Primary = Color(0xFF0a70c0) -val PrimaryDark = Color(0xFF105a94) -val Accent = Color(0xFFffaf3b) - -val Secure = Color(0xFF4CAF50) -val PartiallySecure = Color(0xFFFFC107) -val Insecure = Color(0xFFD32F2F) diff --git a/app/src/main/java/de/justjanne/quasseldroid/MainActivity.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/MainActivity.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/MainActivity.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/MainActivity.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/QuasseldroidRouter.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/QuasseldroidRouter.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/QuasseldroidRouter.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/QuasseldroidRouter.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/messages/MessageBuffer.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/messages/MessageBuffer.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/messages/MessageBuffer.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/messages/MessageBuffer.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/messages/MessageStore.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/messages/MessageStore.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/messages/MessageStore.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/messages/MessageStore.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/sample/SampleConnectedClientProvider.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/sample/SampleConnectedClientProvider.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/sample/SampleConnectedClientProvider.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/sample/SampleConnectedClientProvider.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/sample/SampleCoreInfoProvider.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/sample/SampleCoreInfoProvider.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/sample/SampleCoreInfoProvider.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/sample/SampleCoreInfoProvider.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/service/ClientSessionWrapper.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/service/ClientSessionWrapper.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/service/ClientSessionWrapper.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/service/ClientSessionWrapper.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/service/ConnectionData.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/service/ConnectionData.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/service/ConnectionData.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/service/ConnectionData.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/service/QuasselBackend.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/service/QuasselBackend.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/service/QuasselBackend.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/service/QuasselBackend.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/service/QuasselBinder.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/service/QuasselBinder.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/service/QuasselBinder.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/service/QuasselBinder.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/service/QuasselRunner.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/service/QuasselRunner.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/service/QuasselRunner.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/service/QuasselRunner.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/service/QuasselService.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/service/QuasselService.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/service/QuasselService.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/service/QuasselService.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/ui/components/ConnectedClientCard.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/ui/components/ConnectedClientCard.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/ui/components/ConnectedClientCard.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/ui/components/ConnectedClientCard.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/ui/components/CoreInfoView.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/ui/components/CoreInfoView.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/ui/components/CoreInfoView.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/ui/components/CoreInfoView.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/ui/components/LoginView.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/ui/components/LoginView.kt similarity index 98% rename from app/src/main/java/de/justjanne/quasseldroid/ui/components/LoginView.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/ui/components/LoginView.kt index 2c1e30c75..d8a5cd6a2 100644 --- a/app/src/main/java/de/justjanne/quasseldroid/ui/components/LoginView.kt +++ b/app/src/main/kotlin/de/justjanne/quasseldroid/ui/components/LoginView.kt @@ -21,7 +21,7 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import de.justjanne.quasseldroid.service.ConnectionData -import de.justjanne.quasseldroid.util.TextFieldValueSaver +import de.justjanne.quasseldroid.util.saver.TextFieldValueSaver import java.net.InetSocketAddress @Preview(name = "Login", showBackground = true) diff --git a/app/src/main/java/de/justjanne/quasseldroid/ui/components/PasswordTextField.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/ui/components/PasswordTextField.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/ui/components/PasswordTextField.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/ui/components/PasswordTextField.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/ui/routes/CoreInfoRoute.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/ui/routes/CoreInfoRoute.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/ui/routes/CoreInfoRoute.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/ui/routes/CoreInfoRoute.kt diff --git a/app/src/main/kotlin/de/justjanne/quasseldroid/ui/routes/HomeRoute.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/ui/routes/HomeRoute.kt new file mode 100644 index 000000000..436ed14ff --- /dev/null +++ b/app/src/main/kotlin/de/justjanne/quasseldroid/ui/routes/HomeRoute.kt @@ -0,0 +1,220 @@ +package de.justjanne.quasseldroid.ui.routes + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.Button +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController +import de.justjanne.bitflags.of +import de.justjanne.libquassel.protocol.models.BufferInfo +import de.justjanne.libquassel.protocol.models.Message +import de.justjanne.libquassel.protocol.models.flags.BufferType +import de.justjanne.libquassel.protocol.models.flags.MessageFlag +import de.justjanne.libquassel.protocol.models.flags.MessageType +import de.justjanne.libquassel.protocol.models.ids.BufferId +import de.justjanne.libquassel.protocol.models.ids.MsgId +import de.justjanne.libquassel.protocol.models.ids.NetworkId +import de.justjanne.libquassel.protocol.util.flatMap +import de.justjanne.libquassel.protocol.util.irc.HostmaskHelper +import de.justjanne.quasseldroid.service.QuasselBackend +import de.justjanne.quasseldroid.ui.theme.SenderColors +import de.justjanne.quasseldroid.ui.theme.Typography +import irc.SenderColorUtil +import de.justjanne.quasseldroid.util.mapNullable +import de.justjanne.quasseldroid.util.rememberFlow +import de.justjanne.quasseldroid.util.saver.BufferIdSaver +import kotlinx.coroutines.flow.map +import org.threeten.bp.Instant +import org.threeten.bp.ZoneId +import org.threeten.bp.format.DateTimeFormatter +import org.threeten.bp.format.FormatStyle + +@Composable +fun HomeRoute(backend: QuasselBackend, navController: NavController) { + val session = rememberFlow(null) { + backend.flow() + .mapNullable { it.session } + } + + val (buffer, setBuffer) = rememberSaveable(stateSaver = BufferIdSaver) { + mutableStateOf(BufferId(-1)) + } + + val messages: List<Message> = rememberFlow(emptyList()) { + backend.flow() + .mapNullable { it.messages } + .flatMap() + .mapNullable { it[buffer] } + .map { it?.messages.orEmpty() } + } + + val initStatus = rememberFlow(null) { + backend.flow() + .mapNullable { it.session } + .mapNullable { it.baseInitHandler } + .flatMap() + } + + val context = LocalContext.current + Column { + Text("Side: ${session?.side}") + if (initStatus != null) { + val done = initStatus.total - initStatus.waiting.size + Text("Init: ${initStatus.started} $done/ ${initStatus.total}") + } + Button(onClick = { navController.navigate("coreInfo") }) { + Text("Core Info") + } + Button(onClick = { + backend.disconnect(context) + navController.navigate("login") + }) { + Text("Disconnect") + } + LazyColumn { + items(messages, key = Message::messageId) { + MessageView(it) + } + } + } +} + + +private val formatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT) + +@Preview(name = "Message", showBackground = true) +@Composable +fun MessageView( + @PreviewParameter(SampleMessageProvider::class) + message: Message +) { + val nick = HostmaskHelper.nick(message.sender) + val senderColor = SenderColors[SenderColorUtil.senderColor(nick)] + + Column { + Row { + Text( + message.senderPrefixes, + style = Typography.body2, + fontWeight = FontWeight.Bold + ) + Text( + nick, + style = Typography.body2, + fontWeight = FontWeight.Bold, + color = senderColor + ) + Spacer(Modifier.width(4.dp)) + Text( + message.realName, + modifier = Modifier.weight(1.0f), + style = Typography.body2, + color = Color(0x8A000000) + ) + } + Row { + Text( + message.content, + modifier = Modifier.weight(1.0f), + style = Typography.body2 + ) + Text( + message.time + .atZone(ZoneId.systemDefault()) + .format(formatter), + style = Typography.body2, + color = Color(0x8A000000), + fontSize = 12.sp + ) + } + } +} + +class SampleMessageProvider : PreviewParameterProvider<Message> { + override val values = sequenceOf( + Message( + messageId = MsgId(108062924), + bufferInfo = BufferInfo( + bufferId = BufferId(3746), + bufferName = "#quasseldroid", + networkId = NetworkId(4), + type = BufferType.of(BufferType.Channel) + ), + time = Instant.parse("2022-02-20T18:24:48.891Z"), + type = MessageType.of(MessageType.Quit), + sender = "CrazyBonz!~CrazyBonz@user/CrazyBonz", + senderPrefixes = "", + avatarUrl = "", + realName = "CrazyBonz", + content = "#quasseldroid", + flag = MessageFlag.of() + ), + Message( + messageId = MsgId(108063975), + bufferInfo = BufferInfo( + bufferId = BufferId(3746), + bufferName = "#quasseldroid", + networkId = NetworkId(4), + type = BufferType.of(BufferType.Channel) + ), + time = Instant.parse("2022-02-20T19:56:01.588Z"), + type = MessageType.of(MessageType.Plain), + sender = "winch!~AdminUser@185.14.29.13", + senderPrefixes = "", + avatarUrl = "", + realName = "Wincher,,,", + content = "Can i script some actions like in mIRC?", + flag = MessageFlag.of() + ), + Message( + messageId = MsgId(108064014), + bufferInfo = BufferInfo( + bufferId = BufferId(3746), + bufferName = "#quasseldroid", + networkId = NetworkId(4), + type = BufferType.of(BufferType.Channel) + ), + time = Instant.parse("2022-02-20T20:06:39.159Z"), + type = MessageType.of(MessageType.Quit), + sender = "mavhq!~quassel@mapp-14-b2-v4wan-161519-cust401.vm15.cable.virginm.net", + senderPrefixes = "", + avatarUrl = "", + realName = "mavhc", + content = "Quit: http://quassel-irc.org - Chat comfortably. Anywhere.", + flag = MessageFlag.of() + ), + Message( + messageId = MsgId(108064022), + bufferInfo = BufferInfo( + bufferId = BufferId(3746), + bufferName = "#quasseldroid", + networkId = NetworkId(4), + type = BufferType.of(BufferType.Channel) + ), + time = Instant.parse("2022-02-20T20:07:13.45Z"), + type = MessageType.of(MessageType.Join), + sender = "mavhq!~quassel@mapp-14-b2-v4wan-161519-cust401.vm15.cable.virginm.net", + senderPrefixes = "", + avatarUrl = "", + realName = "mavhc", + content = "#quasseldroid", + flag = MessageFlag.of() + ) + ) +} diff --git a/app/src/main/java/de/justjanne/quasseldroid/ui/routes/LoginRoute.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/ui/routes/LoginRoute.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/ui/routes/LoginRoute.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/ui/routes/LoginRoute.kt diff --git a/app/src/main/kotlin/de/justjanne/quasseldroid/ui/theme/Color.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/ui/theme/Color.kt new file mode 100644 index 000000000..1460baf88 --- /dev/null +++ b/app/src/main/kotlin/de/justjanne/quasseldroid/ui/theme/Color.kt @@ -0,0 +1,30 @@ +package de.justjanne.quasseldroid.ui.theme + +import androidx.compose.ui.graphics.Color + +val Primary = Color(0xFF0a70c0) +val PrimaryDark = Color(0xFF105a94) +val Accent = Color(0xFFffaf3b) + +val Secure = Color(0xFF4CAF50) +val PartiallySecure = Color(0xFFFFC107) +val Insecure = Color(0xFFD32F2F) + +val SenderColors = listOf( + Color(0xFF_b80a73), + Color(0xFF_814dd5), + Color(0xFF_9f0b0b), + Color(0xFF_139f2f), + Color(0xFF_4e9c9f), + Color(0xFF_8b4a9f), + Color(0xFF_9f8669), + Color(0xFF_2b6b9f), + Color(0xFF_e00d8f), + Color(0xFF_995bfd), + Color(0xFF_c70e0e), + Color(0xFF_18c73e), + Color(0xFF_61c6c7), + Color(0xFF_af5ec7), + Color(0xFF_c7a782), + Color(0xFF_3684c7), +) diff --git a/app/src/main/java/de/justjanne/quasseldroid/ui/theme/Shape.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/ui/theme/Shape.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/ui/theme/Shape.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/ui/theme/Shape.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/ui/theme/Theme.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/ui/theme/Theme.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/ui/theme/Theme.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/ui/theme/Theme.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/ui/theme/Type.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/ui/theme/Type.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/ui/theme/Type.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/ui/theme/Type.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/util/FlowExtensions.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/util/FlowExtensions.kt similarity index 81% rename from app/src/main/java/de/justjanne/quasseldroid/util/FlowExtensions.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/util/FlowExtensions.kt index 2dae17ec6..9463f4a9d 100644 --- a/app/src/main/java/de/justjanne/quasseldroid/util/FlowExtensions.kt +++ b/app/src/main/kotlin/de/justjanne/quasseldroid/util/FlowExtensions.kt @@ -5,6 +5,7 @@ import androidx.compose.runtime.DisallowComposableCalls import androidx.compose.runtime.collectAsState import androidx.compose.runtime.remember import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.emitAll import kotlinx.coroutines.flow.transform @@ -23,3 +24,8 @@ inline fun <T, R> Flow<T?>.flatMapLatestNullable(crossinline transform: suspend inline fun <T> rememberFlow(initial: T, calculation: @DisallowComposableCalls () -> Flow<T>): T { return remember(calculation).collectAsState(initial).value } + +@Composable +inline fun <T> rememberFlow(calculation: @DisallowComposableCalls () -> StateFlow<T>): T { + return remember(calculation).collectAsState().value +} diff --git a/app/src/main/java/de/justjanne/quasseldroid/util/lifecycle/ContextualLifecycleObserver.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/util/lifecycle/ContextualLifecycleObserver.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/util/lifecycle/ContextualLifecycleObserver.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/util/lifecycle/ContextualLifecycleObserver.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/util/lifecycle/DefaultContextualLifecycleObserver.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/util/lifecycle/DefaultContextualLifecycleObserver.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/util/lifecycle/DefaultContextualLifecycleObserver.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/util/lifecycle/DefaultContextualLifecycleObserver.kt diff --git a/app/src/main/java/de/justjanne/quasseldroid/util/lifecycle/LifecycleStatus.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/util/lifecycle/LifecycleStatus.kt similarity index 100% rename from app/src/main/java/de/justjanne/quasseldroid/util/lifecycle/LifecycleStatus.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/util/lifecycle/LifecycleStatus.kt diff --git a/app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/BufferIdSaver.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/BufferIdSaver.kt new file mode 100644 index 000000000..b68d97bb7 --- /dev/null +++ b/app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/BufferIdSaver.kt @@ -0,0 +1,10 @@ +package de.justjanne.quasseldroid.util.saver + +import androidx.compose.runtime.saveable.Saver +import androidx.compose.runtime.saveable.SaverScope +import de.justjanne.libquassel.protocol.models.ids.BufferId + +object BufferIdSaver : Saver<BufferId, Int> { + override fun restore(value: Int) = BufferId(value) + override fun SaverScope.save(value: BufferId) = value.id +} diff --git a/app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/IdentityIdSaver.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/IdentityIdSaver.kt new file mode 100644 index 000000000..ac75e837f --- /dev/null +++ b/app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/IdentityIdSaver.kt @@ -0,0 +1,10 @@ +package de.justjanne.quasseldroid.util.saver + +import androidx.compose.runtime.saveable.Saver +import androidx.compose.runtime.saveable.SaverScope +import de.justjanne.libquassel.protocol.models.ids.IdentityId + +object IdentityIdSaver : Saver<IdentityId, Int> { + override fun restore(value: Int) = IdentityId(value) + override fun SaverScope.save(value: IdentityId) = value.id +} diff --git a/app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/MsgIdSaver.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/MsgIdSaver.kt new file mode 100644 index 000000000..a20623d46 --- /dev/null +++ b/app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/MsgIdSaver.kt @@ -0,0 +1,10 @@ +package de.justjanne.quasseldroid.util.saver + +import androidx.compose.runtime.saveable.Saver +import androidx.compose.runtime.saveable.SaverScope +import de.justjanne.libquassel.protocol.models.ids.MsgId + +object MsgIdSaver : Saver<MsgId, Long> { + override fun restore(value: Long) = MsgId(value) + override fun SaverScope.save(value: MsgId) = value.id +} diff --git a/app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/NetworkIdSaver.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/NetworkIdSaver.kt new file mode 100644 index 000000000..a5eebb462 --- /dev/null +++ b/app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/NetworkIdSaver.kt @@ -0,0 +1,10 @@ +package de.justjanne.quasseldroid.util.saver + +import androidx.compose.runtime.saveable.Saver +import androidx.compose.runtime.saveable.SaverScope +import de.justjanne.libquassel.protocol.models.ids.NetworkId + +object NetworkIdSaver : Saver<NetworkId, Int> { + override fun restore(value: Int) = NetworkId(value) + override fun SaverScope.save(value: NetworkId) = value.id +} diff --git a/app/src/main/java/de/justjanne/quasseldroid/util/TextFieldValueSaver.kt b/app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/TextFieldValueSaver.kt similarity index 88% rename from app/src/main/java/de/justjanne/quasseldroid/util/TextFieldValueSaver.kt rename to app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/TextFieldValueSaver.kt index 31df4795c..e3b061560 100644 --- a/app/src/main/java/de/justjanne/quasseldroid/util/TextFieldValueSaver.kt +++ b/app/src/main/kotlin/de/justjanne/quasseldroid/util/saver/TextFieldValueSaver.kt @@ -1,4 +1,4 @@ -package de.justjanne.quasseldroid.util +package de.justjanne.quasseldroid.util.saver import androidx.compose.runtime.saveable.Saver import androidx.compose.runtime.saveable.SaverScope diff --git a/app/src/main/kotlin/irc/CRCUtils.kt b/app/src/main/kotlin/irc/CRCUtils.kt new file mode 100644 index 000000000..494d9fa0c --- /dev/null +++ b/app/src/main/kotlin/irc/CRCUtils.kt @@ -0,0 +1,44 @@ +package irc + +object CRCUtils { + fun qChecksum(data: ByteArray): Int { + var crc = 0xffff + val crcHighBitMask = 0x8000 + + for (b in data) { + val c = reflect(b.toInt(), 8) + var j = 0x80 + while (j > 0) { + var highBit = crc and crcHighBitMask + crc = crc shl 1 + if (c and j > 0) { + highBit = highBit xor crcHighBitMask + } + if (highBit > 0) { + crc = crc xor 0x1021 + } + j = j shr 1 + } + } + + crc = reflect(crc, 16) + crc = crc xor 0xffff + crc = crc and 0xffff + + return crc + } + + private fun reflect(crc: Int, n: Int): Int { + var j = 1 + var crcout = 0 + var i = 1 shl n - 1 + while (i > 0) { + if (crc and i > 0) { + crcout = crcout or j + } + j = j shl 1 + i = i shr 1 + } + return crcout + } +} diff --git a/app/src/main/kotlin/irc/SenderColorUtil.kt b/app/src/main/kotlin/irc/SenderColorUtil.kt new file mode 100644 index 000000000..6b12a9ced --- /dev/null +++ b/app/src/main/kotlin/irc/SenderColorUtil.kt @@ -0,0 +1,13 @@ +package irc + +import java.util.* + +object SenderColorUtil { + fun senderColor(nick: String): Int { + return 0xf and CRCUtils.qChecksum( + nick.trimEnd('_') + .lowercase(Locale.ENGLISH) + .toByteArray(Charsets.ISO_8859_1) + ) + } +} diff --git a/app/src/test/kotlin/de/kuschku/justjanne/quasseldroid/util/irc/SenderColorUtilTest.kt b/app/src/test/kotlin/de/kuschku/justjanne/quasseldroid/util/irc/SenderColorUtilTest.kt new file mode 100644 index 000000000..79fc84a54 --- /dev/null +++ b/app/src/test/kotlin/de/kuschku/justjanne/quasseldroid/util/irc/SenderColorUtilTest.kt @@ -0,0 +1,14 @@ +package de.kuschku.justjanne.quasseldroid.util.irc + +import irc.SenderColorUtil +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.Test + +class SenderColorUtilTest { + @Test + fun verifyTestData() { + assertEquals(0x5, SenderColorUtil.senderColor("mavhq")) + assertEquals(0xa, SenderColorUtil.senderColor("winch")) + assertEquals(0xc, SenderColorUtil.senderColor("mack")) + } +} diff --git a/gradle/convention/src/main/kotlin/justjanne.java.gradle.kts b/gradle/convention/src/main/kotlin/justjanne.java.gradle.kts index ca33bb8d7..ac5f5d66c 100644 --- a/gradle/convention/src/main/kotlin/justjanne.java.gradle.kts +++ b/gradle/convention/src/main/kotlin/justjanne.java.gradle.kts @@ -1,10 +1,23 @@ +import gradle.kotlin.dsl.accessors._9f9f63157b527b37420ecbe9e569524a.testImplementation +import gradle.kotlin.dsl.accessors._9f9f63157b527b37420ecbe9e569524a.testRuntimeOnly + plugins { java id("justjanne.repositories") } +dependencies { + testImplementation("org.junit.jupiter", "junit-jupiter-api", "5.8.2") + testImplementation("org.junit.jupiter", "junit-jupiter-params", "5.8.2") + testRuntimeOnly("org.junit.jupiter", "junit-jupiter-engine") +} + configure<JavaPluginExtension> { toolchain { languageVersion.set(JavaLanguageVersion.of(8)) } } + +tasks.withType<Test> { + useJUnitPlatform() +} diff --git a/gradle/convention/src/main/kotlin/justjanne.kotlin.android.gradle.kts b/gradle/convention/src/main/kotlin/justjanne.kotlin.android.gradle.kts index bb75c465b..0739cbd60 100644 --- a/gradle/convention/src/main/kotlin/justjanne.kotlin.android.gradle.kts +++ b/gradle/convention/src/main/kotlin/justjanne.kotlin.android.gradle.kts @@ -1,5 +1,6 @@ import gradle.kotlin.dsl.accessors._9f9f63157b527b37420ecbe9e569524a.implementation import gradle.kotlin.dsl.accessors._9f9f63157b527b37420ecbe9e569524a.testImplementation +import gradle.kotlin.dsl.accessors._9f9f63157b527b37420ecbe9e569524a.testRuntimeOnly import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { @@ -11,9 +12,16 @@ plugins { dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib:1.6.10") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0") testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0") + + testImplementation("org.junit.jupiter", "junit-jupiter-api", "5.8.2") + testImplementation("org.junit.jupiter", "junit-jupiter-params", "5.8.2") + testRuntimeOnly("org.junit.jupiter", "junit-jupiter-engine") + + testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.6.10") } tasks.withType<KotlinCompile> { @@ -26,3 +34,13 @@ tasks.withType<KotlinCompile> { jvmTarget = "1.8" } } + +tasks.withType<Test> { + useJUnitPlatform() +} + +configure<JavaPluginExtension> { + toolchain { + languageVersion.set(JavaLanguageVersion.of(8)) + } +} diff --git a/gradle/convention/src/main/kotlin/justjanne.kotlin.gradle.kts b/gradle/convention/src/main/kotlin/justjanne.kotlin.gradle.kts index 04838711e..888ec7207 100644 --- a/gradle/convention/src/main/kotlin/justjanne.kotlin.gradle.kts +++ b/gradle/convention/src/main/kotlin/justjanne.kotlin.gradle.kts @@ -2,7 +2,6 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("justjanne.java") - id("justjanne.repositories") id("com.google.devtools.ksp") kotlin("jvm") kotlin("kapt") @@ -10,8 +9,11 @@ plugins { dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib:1.6.10") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0") + + testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.6.10") } tasks.withType<KotlinCompile> { -- GitLab