From c6a70d3d86a3971f28085268f9ac8e9f10646f7c Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Thu, 31 Jan 2019 23:08:06 +0100 Subject: [PATCH] Implement new testing functionality, clean up code --- .../de/kuschku/quasseldroid/Quasseldroid.kt | 6 +- .../quasseldroid/service/BacklogRequester.kt | 2 +- .../service/QuasselNotificationBackend.kt | 6 +- .../quasseldroid/service/QuasselService.kt | 6 +- .../settings/SettingsMigrationManager.kt | 2 - .../quasseldroid/ui/chat/ChatActivity.kt | 9 +- .../chat/buffers/BufferViewConfigFragment.kt | 8 +- .../ui/chat/input/AutoCompleteHelper.kt | 2 +- .../ui/chat/input/ChatlineFragment.kt | 4 +- .../ui/chat/topic/TopicFragment.kt | 2 +- .../chatlist/ChatListCreateFragment.kt | 10 +- .../identity/IdentityCreateFragment.kt | 2 +- .../network/NetworkCreateFragment.kt | 2 +- .../ui/info/channel/ChannelInfoFragment.kt | 8 +- .../ui/info/user/UserInfoFragment.kt | 12 +- .../ui/setup/network/NetworkSetupActivity.kt | 6 +- .../quasseldroid/util/backport/OsConstants.kt | 551 +++++++++--------- .../util/helper/CharSequenceHelper.kt | 2 +- build.gradle.kts | 12 + .../de/kuschku/libquassel/protocol/QTypes.kt | 2 +- .../kuschku/libquassel/protocol/QVariant.kt | 2 + .../kuschku/libquassel/protocol/SignedId.kt | 2 +- .../primitive/serializer/StringSerializer.kt | 2 +- .../primitive/serializer/VariantSerializer.kt | 2 + .../quassel/syncables/BufferSyncer.kt | 6 +- .../quassel/syncables/IgnoreListManager.kt | 13 +- .../quassel/syncables/IrcChannel.kt | 36 +- .../libquassel/quassel/syncables/IrcUser.kt | 38 +- .../libquassel/quassel/syncables/Network.kt | 19 +- .../quassel/syncables/RpcHandler.kt | 22 +- .../syncables/interfaces/IIrcChannel.kt | 16 +- .../quassel/syncables/interfaces/INetwork.kt | 12 +- .../syncables/interfaces/IRpcHandler.kt | 3 - .../syncables/interfaces/ISyncableObject.kt | 2 +- .../syncables/interfaces/invokers/Invokers.kt | 1 + .../de/kuschku/libquassel/session/ISession.kt | 63 +- .../libquassel/session/NotificationManager.kt | 4 +- .../libquassel/session/ProtocolHandler.kt | 2 +- .../de/kuschku/libquassel/session/Session.kt | 17 +- .../util/compatibility/LoggingHandler.kt | 2 +- .../libquassel/util/helpers/MathHelper.kt | 2 +- .../de/kuschku/libquassel/IntegrationTest.kt | 52 ++ .../serializer/StringSerializerTest.kt | 13 +- .../syncables/IgnoreListManagerTest.kt | 5 +- .../de/kuschku/libquassel/util/SetupTests.kt | 138 +++++ .../de/kuschku/libquassel/util/TestSession.kt | 260 +++++++++ lib/src/test/resources/naughty_strings.txt | 1 + .../kuschku/malheur/collectors/Collector.kt | 2 +- .../collectors/ConfigurationCollector.kt | 10 +- persistence/build.gradle.kts | 2 + .../persistence/QuasselBacklogStorage.kt | 6 +- .../persistence/QuasselDatabase.kt | 2 +- .../persistence/QuasselDatabaseHelpers.kt | 2 +- .../util/helper/LiveDataHelper.kt | 2 +- .../util/helper/ObservableHelper.kt | 2 +- .../quasseldroid/viewmodel/EditorViewModel.kt | 3 +- .../viewmodel/QuasselViewModel.kt | 20 +- 57 files changed, 961 insertions(+), 479 deletions(-) create mode 100644 lib/src/test/java/de/kuschku/libquassel/IntegrationTest.kt create mode 100644 lib/src/test/java/de/kuschku/libquassel/util/SetupTests.kt create mode 100644 lib/src/test/java/de/kuschku/libquassel/util/TestSession.kt create mode 100644 lib/src/test/resources/naughty_strings.txt diff --git a/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt b/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt index a054d1368..405b56856 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/Quasseldroid.kt @@ -68,7 +68,6 @@ class Quasseldroid : DaggerApplication() { // Migrate preferences SettingsMigrationManager( - R.xml.preferences, listOf( SettingsMigration.migrationOf(0, 1) { prefs, edit -> // Migrating database @@ -110,7 +109,8 @@ class Quasseldroid : DaggerApplication() { } if (prefs.contains("timestamp")) { - prefs.getString("timestamp", "").let { timestamp -> + prefs.getString("timestamp", "").let { + val timestamp = it ?: "" edit.putBoolean(getString(R.string.preference_show_seconds_key), timestamp.contains("ss")) edit.putBoolean(getString(R.string.preference_show_seconds_key), @@ -120,7 +120,7 @@ class Quasseldroid : DaggerApplication() { } if (prefs.contains("fontsizeChannelList")) { - prefs.getString("fontsizeChannelList", "").toIntOrNull()?.let { fontSize -> + prefs.getString("fontsizeChannelList", "")?.toIntOrNull()?.let { fontSize -> edit.putInt(getString(R.string.preference_textsize_key), fontSize) } edit.remove("fontsizeChannelList") diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/BacklogRequester.kt b/app/src/main/java/de/kuschku/quasseldroid/service/BacklogRequester.kt index b61d63ee2..01e9893cd 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/service/BacklogRequester.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/service/BacklogRequester.kt @@ -43,7 +43,7 @@ class BacklogRequester( "requested(buffer: $buffer, amount: $amount, pageSize: $pageSize, lastMessageId: $lastMessageId, untilAllVisible: $untilAllVisible)") var missing = amount viewModel.session.value?.orNull()?.let { session: ISession -> - session.backlogManager?.let { + session.backlogManager.let { val filtered = database.filtered().get(accountId, buffer, accountDatabase.accounts().findById(accountId)?.defaultFiltered diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt index e4c308a31..c684f5a62 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselNotificationBackend.kt @@ -28,8 +28,8 @@ import de.kuschku.libquassel.protocol.* import de.kuschku.libquassel.quassel.BufferInfo import de.kuschku.libquassel.quassel.ExtendedFeature import de.kuschku.libquassel.quassel.syncables.IgnoreListManager +import de.kuschku.libquassel.session.ISession import de.kuschku.libquassel.session.NotificationManager -import de.kuschku.libquassel.session.Session import de.kuschku.libquassel.util.flag.hasFlag import de.kuschku.libquassel.util.helpers.clampOf import de.kuschku.libquassel.util.irc.HostmaskHelper @@ -102,7 +102,7 @@ class QuasselNotificationBackend @Inject constructor( } } - override fun init(session: Session) { + override fun init(session: ISession) { initTime = Instant.now() if (session.features.negotiated.hasFeature(ExtendedFeature.BacklogFilterType)) { val buffers = session.bufferSyncer.bufferInfos() @@ -192,7 +192,7 @@ class QuasselNotificationBackend @Inject constructor( } @Synchronized - override fun processMessages(session: Session, show: Boolean, vararg messages: Message) { + override fun processMessages(session: ISession, show: Boolean, vararg messages: Message) { val now = Instant.now() val results = messages.filter { val level = it.bufferInfo.type.let { diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt index a2726b36f..a4fd817e3 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt @@ -180,13 +180,13 @@ class QuasselService : DaggerLifecycleService(), } sessionManager.session.value?.let { session -> - session.bufferSyncer?.bufferInfo(bufferId)?.also { bufferInfo -> + session.bufferSyncer.bufferInfo(bufferId)?.also { bufferInfo -> val output = mutableListOf<IAliasManager.Command>() for ((_, formatted) in lines) { - session.aliasManager?.processInput(bufferInfo, formatted, output) + session.aliasManager.processInput(bufferInfo, formatted, output) } for (command in output) { - session.rpcHandler?.sendInput(command.buffer, command.message) + session.rpcHandler.sendInput(command.buffer, command.message) } } handlerService.backend { diff --git a/app/src/main/java/de/kuschku/quasseldroid/settings/SettingsMigrationManager.kt b/app/src/main/java/de/kuschku/quasseldroid/settings/SettingsMigrationManager.kt index cc8835382..3d9c2f558 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/settings/SettingsMigrationManager.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/settings/SettingsMigrationManager.kt @@ -21,13 +21,11 @@ package de.kuschku.quasseldroid.settings import android.annotation.SuppressLint import android.content.Context -import androidx.annotation.XmlRes import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager.KEY_HAS_SET_DEFAULT_VALUES import de.kuschku.quasseldroid.R.xml.preferences class SettingsMigrationManager( - @XmlRes preferences: Int, migrations: List<SettingsMigration> ) { private val migrationMap = migrations.associateBy(SettingsMigration::from) diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt index 5d48d4176..88ffb8c8a 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt @@ -184,7 +184,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc viewModel.session.filter(Optional<ISession>::isPresent).firstElement().subscribe { it.orNull()?.also { session -> - val info = session.bufferSyncer?.find( + val info = session.bufferSyncer.find( bufferName = channel, networkId = networkId, type = Buffer_Type.of(Buffer_Type.ChannelBuffer) @@ -207,11 +207,11 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc } } - session.bufferSyncer?.find( + session.bufferSyncer.find( networkId = networkId, type = Buffer_Type.of(Buffer_Type.StatusBuffer) )?.let { statusInfo -> - session.rpcHandler?.sendInput( + session.rpcHandler.sendInput( statusInfo, "/join $channel" ) } @@ -394,7 +394,6 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc .build() dialog.customView?.run { val userField = findViewById<EditText>(R.id.user) - val passField = findViewById<EditText>(R.id.pass) account?.let { userField.setText(it.user) @@ -778,7 +777,7 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc override fun onSaveInstanceState(outState: Bundle?) { super.onSaveInstanceState(outState) - outState?.putInt(KEY_OPEN_BUFFER, viewModel.buffer.value.id ?: -1) + outState?.putInt(KEY_OPEN_BUFFER, viewModel.buffer.value.id) outState?.putInt(KEY_OPEN_BUFFERVIEWCONFIG, viewModel.bufferViewConfigId.value ?: -1) outState?.putLong(KEY_CONNECTED_ACCOUNT, connectedAccount) outState?.putBoolean(KEY_OPEN_DRAWER_START, drawerLayout.isDrawerOpen(GravityCompat.START)) diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt index ada92099e..122e7c9a7 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/buffers/BufferViewConfigFragment.kt @@ -145,12 +145,12 @@ class BufferViewConfigFragment : ServiceBoundFragment() { true } R.id.action_join -> { - session.rpcHandler?.sendInput(info, "/join ${info.bufferName}") + session.rpcHandler.sendInput(info, "/join ${info.bufferName}") actionMode?.finish() true } R.id.action_part -> { - session.rpcHandler?.sendInput(info, "/part ${info.bufferName}") + session.rpcHandler.sendInput(info, "/part ${info.bufferName}") actionMode?.finish() true } @@ -164,7 +164,7 @@ class BufferViewConfigFragment : ServiceBoundFragment() { .contentColorAttr(R.attr.colorTextPrimary) .onPositive { _, _ -> selected.info?.let { - session.bufferSyncer?.requestRemoveBuffer(info.bufferId) + session.bufferSyncer.requestRemoveBuffer(info.bufferId) } } .onAny { _, _ -> @@ -182,7 +182,7 @@ class BufferViewConfigFragment : ServiceBoundFragment() { false ) { _, input -> selected.info?.let { - session.bufferSyncer?.requestRenameBuffer(info.bufferId, input.toString()) + session.bufferSyncer.requestRenameBuffer(info.bufferId, input.toString()) } } .positiveText(R.string.label_save) diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/AutoCompleteHelper.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/AutoCompleteHelper.kt index 1137b959d..ac177c683 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/AutoCompleteHelper.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/AutoCompleteHelper.kt @@ -177,7 +177,7 @@ class AutoCompleteHelper( return if (bufferSyncer != null) { val networks = session.networks val infos = bufferSyncer.bufferInfos() - val aliases = session.aliasManager?.aliasList().orEmpty() + val aliases = session.aliasManager.aliasList() val network = networks[bufferInfo?.networkId] ?: Network.NULL val ircChannel = if (bufferInfo?.type?.hasFlag(Buffer_Type.ChannelBuffer) == true) { network.ircChannel(bufferInfo.bufferName) ?: IrcChannel.NULL diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/ChatlineFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/ChatlineFragment.kt index 9365bcaa5..e5a2925b9 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/ChatlineFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/input/ChatlineFragment.kt @@ -189,10 +189,10 @@ class ChatlineFragment : ServiceBoundFragment() { session?.bufferSyncer?.bufferInfo(bufferId)?.also { bufferInfo -> val output = mutableListOf<IAliasManager.Command>() for ((_, formatted) in lines) { - session.aliasManager?.processInput(bufferInfo, formatted, output) + session.aliasManager.processInput(bufferInfo, formatted, output) } for (command in output) { - session.rpcHandler?.sendInput(command.buffer, command.message) + session.rpcHandler.sendInput(command.buffer, command.message) } } } diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/topic/TopicFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/topic/TopicFragment.kt index b8ca3f596..e6b056c1d 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/topic/TopicFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/topic/TopicFragment.kt @@ -135,7 +135,7 @@ class TopicFragment : ServiceBoundSettingsFragment(), Savable { viewModel.buffer { bufferId -> session?.bufferSyncer?.bufferInfo(bufferId)?.also { bufferInfo -> val topic = formatSerializer.toEscapeCodes(chatline.safeText) - session.rpcHandler?.sendInput(bufferInfo, "/topic $topic") + session.rpcHandler.sendInput(bufferInfo, "/topic $topic") return true } } diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListCreateFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListCreateFragment.kt index 7ee222962..42204dd07 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListCreateFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListCreateFragment.kt @@ -22,11 +22,9 @@ package de.kuschku.quasseldroid.ui.coresettings.chatlist import de.kuschku.libquassel.util.helpers.value class ChatListCreateFragment : ChatListBaseFragment(true) { - override fun onSave() = viewModel.session.value?.orNull()?.let { session -> - chatlist?.let { (_, data) -> - applyChanges(data, null) - viewModel.bufferViewManager.value?.orNull()?.requestCreateBufferView(data.toVariantMap()) - true - } + override fun onSave() = chatlist?.let { (_, data) -> + applyChanges(data, null) + viewModel.bufferViewManager.value?.orNull()?.requestCreateBufferView(data.toVariantMap()) + true } ?: false } diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityCreateFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityCreateFragment.kt index eab72b7fc..d3797640e 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityCreateFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/identity/IdentityCreateFragment.kt @@ -25,7 +25,7 @@ class IdentityCreateFragment : IdentityBaseFragment(true) { override fun onSave() = viewModel.session.value?.orNull()?.let { session -> identity?.let { (_, data) -> applyChanges(data) - session.rpcHandler?.createIdentity(data, mapOf()) + session.rpcHandler.createIdentity(data, mapOf()) true } ?: false } ?: false diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateFragment.kt index 9f84c09ab..7a5cde498 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateFragment.kt @@ -27,7 +27,7 @@ class NetworkCreateFragment : NetworkBaseFragment(true) { network?.let { (_, data) -> applyChanges(data) viewModel.backend.value?.ifPresent(Backend::requestConnectNewNetwork) - session.rpcHandler?.createNetwork(data.networkInfo(), emptyList()) + session.rpcHandler.createNetwork(data.networkInfo(), emptyList()) true } } ?: false diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/info/channel/ChannelInfoFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/info/channel/ChannelInfoFragment.kt index 4a04aae2e..2cf728b74 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/info/channel/ChannelInfoFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/info/channel/ChannelInfoFragment.kt @@ -121,11 +121,11 @@ class ChannelInfoFragment : ServiceBoundFragment() { actionPart.setOnClickListener { viewModel.session.value?.orNull()?.let { session -> - session.bufferSyncer?.find( + session.bufferSyncer.find( networkId = channel.network().networkId(), type = Buffer_Type.of(Buffer_Type.StatusBuffer) )?.let { statusInfo -> - session.rpcHandler?.sendInput(statusInfo, "/part ${channel.name()}") + session.rpcHandler.sendInput(statusInfo, "/part ${channel.name()}") requireActivity().finish() } } @@ -133,11 +133,11 @@ class ChannelInfoFragment : ServiceBoundFragment() { actionWho.setOnClickListener { viewModel.session.value?.orNull()?.let { session -> - session.bufferSyncer?.find( + session.bufferSyncer.find( networkId = channel.network().networkId(), type = Buffer_Type.of(Buffer_Type.StatusBuffer) )?.let { statusInfo -> - session.rpcHandler?.sendInput(statusInfo, "/who ${channel.name()}") + session.rpcHandler.sendInput(statusInfo, "/who ${channel.name()}") requireActivity().finish() } } diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoFragment.kt index 6da78c876..fea4dba07 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/info/user/UserInfoFragment.kt @@ -252,7 +252,7 @@ class UserInfoFragment : ServiceBoundFragment() { actionQuery.setOnClickListener { viewModel.session.value?.orNull()?.let { session -> - val info = session.bufferSyncer?.find( + val info = session.bufferSyncer.find( bufferName = user.nick, networkId = user.networkId, type = Buffer_Type.of(Buffer_Type.QueryBuffer) @@ -275,12 +275,12 @@ class UserInfoFragment : ServiceBoundFragment() { } }) - session.bufferSyncer?.find( + session.bufferSyncer.find( networkId = user.networkId, type = Buffer_Type.of(Buffer_Type.StatusBuffer) )?.let { statusInfo -> - session.rpcHandler?.sendInput(statusInfo, - "/query ${user.nick}") + session.rpcHandler.sendInput(statusInfo, + "/query ${user.nick}") } } } @@ -297,11 +297,11 @@ class UserInfoFragment : ServiceBoundFragment() { actionWhois.setOnClickListener { viewModel.session { it.orNull()?.let { session -> - session.bufferSyncer?.find( + session.bufferSyncer.find( networkId = user.networkId, type = Buffer_Type.of(Buffer_Type.StatusBuffer) )?.let { statusInfo -> - session.rpcHandler?.sendInput(statusInfo, "/whois ${user.nick} ${user.nick}") + session.rpcHandler.sendInput(statusInfo, "/whois ${user.nick} ${user.nick}") } } } diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/network/NetworkSetupActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/network/NetworkSetupActivity.kt index 48bd8417f..6fd30cd0a 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/network/NetworkSetupActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/network/NetworkSetupActivity.kt @@ -48,11 +48,11 @@ class NetworkSetupActivity : ServiceBoundSetupActivity() { viewModel.backend?.value?.ifPresent { backend -> val session = viewModel.session.value?.orNull() session?.apply { - rpcHandler?.apply { + rpcHandler.apply { when { networkId.isValidId() -> { - val buffer = bufferSyncer?.find(networkId = networkId, - type = Buffer_Type.of(Buffer_Type.StatusBuffer)) + val buffer = bufferSyncer.find(networkId = networkId, + type = Buffer_Type.of(Buffer_Type.StatusBuffer)) if (buffer != null) { data.getStringArray("channels")?.toList().orEmpty().forEach { sendInput(buffer, "/join $it") diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/backport/OsConstants.kt b/app/src/main/java/de/kuschku/quasseldroid/util/backport/OsConstants.kt index af365aaa6..1f92f436e 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/util/backport/OsConstants.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/util/backport/OsConstants.kt @@ -20,7 +20,6 @@ package de.kuschku.quasseldroid.util.backport object OsConstants { - const val EPERM = 1 const val ENOENT = 2 const val ESRCH = 3 @@ -156,283 +155,281 @@ object OsConstants { const val EHWPOISON = 133 const val ENOTSUP = 95 - fun errnoName(errno: Int): String? { - return when (errno) { - EPERM -> "EPERM" - ENOENT -> "ENOENT" - ESRCH -> "ESRCH" - EINTR -> "EINTR" - EIO -> "EIO" - ENXIO -> "ENXIO" - E2BIG -> "E2BIG" - ENOEXEC -> "ENOEXEC" - EBADF -> "EBADF" - ECHILD -> "ECHILD" - EAGAIN -> "EAGAIN" - ENOMEM -> "ENOMEM" - EACCES -> "EACCES" - EFAULT -> "EFAULT" - ENOTBLK -> "ENOTBLK" - EBUSY -> "EBUSY" - EEXIST -> "EEXIST" - EXDEV -> "EXDEV" - ENODEV -> "ENODEV" - ENOTDIR -> "ENOTDIR" - EISDIR -> "EISDIR" - EINVAL -> "EINVAL" - ENFILE -> "ENFILE" - EMFILE -> "EMFILE" - ENOTTY -> "ENOTTY" - ETXTBSY -> "ETXTBSY" - EFBIG -> "EFBIG" - ENOSPC -> "ENOSPC" - ESPIPE -> "ESPIPE" - EROFS -> "EROFS" - EMLINK -> "EMLINK" - EPIPE -> "EPIPE" - EDOM -> "EDOM" - ERANGE -> "ERANGE" - EDEADLK -> "EDEADLK" - ENAMETOOLONG -> "ENAMETOOLONG" - ENOLCK -> "ENOLCK" - ENOSYS -> "ENOSYS" - ENOTEMPTY -> "ENOTEMPTY" - ELOOP -> "ELOOP" - EWOULDBLOCK -> "EWOULDBLOCK" - ENOMSG -> "ENOMSG" - EIDRM -> "EIDRM" - ECHRNG -> "ECHRNG" - EL2NSYNC -> "EL2NSYNC" - EL3HLT -> "EL3HLT" - EL3RST -> "EL3RST" - ELNRNG -> "ELNRNG" - EUNATCH -> "EUNATCH" - ENOCSI -> "ENOCSI" - EL2HLT -> "EL2HLT" - EBADE -> "EBADE" - EBADR -> "EBADR" - EXFULL -> "EXFULL" - ENOANO -> "ENOANO" - EBADRQC -> "EBADRQC" - EBADSLT -> "EBADSLT" - EDEADLOCK -> "EDEADLOCK" - EBFONT -> "EBFONT" - ENOSTR -> "ENOSTR" - ENODATA -> "ENODATA" - ETIME -> "ETIME" - ENOSR -> "ENOSR" - ENONET -> "ENONET" - ENOPKG -> "ENOPKG" - EREMOTE -> "EREMOTE" - ENOLINK -> "ENOLINK" - EADV -> "EADV" - ESRMNT -> "ESRMNT" - ECOMM -> "ECOMM" - EPROTO -> "EPROTO" - EMULTIHOP -> "EMULTIHOP" - EDOTDOT -> "EDOTDOT" - EBADMSG -> "EBADMSG" - EOVERFLOW -> "EOVERFLOW" - ENOTUNIQ -> "ENOTUNIQ" - EBADFD -> "EBADFD" - EREMCHG -> "EREMCHG" - ELIBACC -> "ELIBACC" - ELIBBAD -> "ELIBBAD" - ELIBSCN -> "ELIBSCN" - ELIBMAX -> "ELIBMAX" - ELIBEXEC -> "ELIBEXEC" - EILSEQ -> "EILSEQ" - ERESTART -> "ERESTART" - ESTRPIPE -> "ESTRPIPE" - EUSERS -> "EUSERS" - ENOTSOCK -> "ENOTSOCK" - EDESTADDRREQ -> "EDESTADDRREQ" - EMSGSIZE -> "EMSGSIZE" - EPROTOTYPE -> "EPROTOTYPE" - ENOPROTOOPT -> "ENOPROTOOPT" - EPROTONOSUPPORT -> "EPROTONOSUPPORT" - ESOCKTNOSUPPORT -> "ESOCKTNOSUPPORT" - EOPNOTSUPP -> "EOPNOTSUPP" - EPFNOSUPPORT -> "EPFNOSUPPORT" - EAFNOSUPPORT -> "EAFNOSUPPORT" - EADDRINUSE -> "EADDRINUSE" - EADDRNOTAVAIL -> "EADDRNOTAVAIL" - ENETDOWN -> "ENETDOWN" - ENETUNREACH -> "ENETUNREACH" - ENETRESET -> "ENETRESET" - ECONNABORTED -> "ECONNABORTED" - ECONNRESET -> "ECONNRESET" - ENOBUFS -> "ENOBUFS" - EISCONN -> "EISCONN" - ENOTCONN -> "ENOTCONN" - ESHUTDOWN -> "ESHUTDOWN" - ETOOMANYREFS -> "ETOOMANYREFS" - ETIMEDOUT -> "ETIMEDOUT" - ECONNREFUSED -> "ECONNREFUSED" - EHOSTDOWN -> "EHOSTDOWN" - EHOSTUNREACH -> "EHOSTUNREACH" - EALREADY -> "EALREADY" - EINPROGRESS -> "EINPROGRESS" - ESTALE -> "ESTALE" - EUCLEAN -> "EUCLEAN" - ENOTNAM -> "ENOTNAM" - ENAVAIL -> "ENAVAIL" - EISNAM -> "EISNAM" - EREMOTEIO -> "EREMOTEIO" - EDQUOT -> "EDQUOT" - ENOMEDIUM -> "ENOMEDIUM" - EMEDIUMTYPE -> "EMEDIUMTYPE" - ECANCELED -> "ECANCELED" - ENOKEY -> "ENOKEY" - EKEYEXPIRED -> "EKEYEXPIRED" - EKEYREVOKED -> "EKEYREVOKED" - EKEYREJECTED -> "EKEYREJECTED" - EOWNERDEAD -> "EOWNERDEAD" - ENOTRECOVERABLE -> "ENOTRECOVERABLE" - ERFKILL -> "ERFKILL" - EHWPOISON -> "EHWPOISON" - ENOTSUP -> "ENOTSUP" - else -> null - } + @Suppress("DUPLICATE_LABEL_IN_WHEN") + fun errnoName(errno: Int) = when (errno) { + EPERM -> "EPERM" + ENOENT -> "ENOENT" + ESRCH -> "ESRCH" + EINTR -> "EINTR" + EIO -> "EIO" + ENXIO -> "ENXIO" + E2BIG -> "E2BIG" + ENOEXEC -> "ENOEXEC" + EBADF -> "EBADF" + ECHILD -> "ECHILD" + EAGAIN -> "EAGAIN" + ENOMEM -> "ENOMEM" + EACCES -> "EACCES" + EFAULT -> "EFAULT" + ENOTBLK -> "ENOTBLK" + EBUSY -> "EBUSY" + EEXIST -> "EEXIST" + EXDEV -> "EXDEV" + ENODEV -> "ENODEV" + ENOTDIR -> "ENOTDIR" + EISDIR -> "EISDIR" + EINVAL -> "EINVAL" + ENFILE -> "ENFILE" + EMFILE -> "EMFILE" + ENOTTY -> "ENOTTY" + ETXTBSY -> "ETXTBSY" + EFBIG -> "EFBIG" + ENOSPC -> "ENOSPC" + ESPIPE -> "ESPIPE" + EROFS -> "EROFS" + EMLINK -> "EMLINK" + EPIPE -> "EPIPE" + EDOM -> "EDOM" + ERANGE -> "ERANGE" + EDEADLK -> "EDEADLK" + ENAMETOOLONG -> "ENAMETOOLONG" + ENOLCK -> "ENOLCK" + ENOSYS -> "ENOSYS" + ENOTEMPTY -> "ENOTEMPTY" + ELOOP -> "ELOOP" + EWOULDBLOCK -> "EWOULDBLOCK" + ENOMSG -> "ENOMSG" + EIDRM -> "EIDRM" + ECHRNG -> "ECHRNG" + EL2NSYNC -> "EL2NSYNC" + EL3HLT -> "EL3HLT" + EL3RST -> "EL3RST" + ELNRNG -> "ELNRNG" + EUNATCH -> "EUNATCH" + ENOCSI -> "ENOCSI" + EL2HLT -> "EL2HLT" + EBADE -> "EBADE" + EBADR -> "EBADR" + EXFULL -> "EXFULL" + ENOANO -> "ENOANO" + EBADRQC -> "EBADRQC" + EBADSLT -> "EBADSLT" + EDEADLOCK -> "EDEADLOCK" + EBFONT -> "EBFONT" + ENOSTR -> "ENOSTR" + ENODATA -> "ENODATA" + ETIME -> "ETIME" + ENOSR -> "ENOSR" + ENONET -> "ENONET" + ENOPKG -> "ENOPKG" + EREMOTE -> "EREMOTE" + ENOLINK -> "ENOLINK" + EADV -> "EADV" + ESRMNT -> "ESRMNT" + ECOMM -> "ECOMM" + EPROTO -> "EPROTO" + EMULTIHOP -> "EMULTIHOP" + EDOTDOT -> "EDOTDOT" + EBADMSG -> "EBADMSG" + EOVERFLOW -> "EOVERFLOW" + ENOTUNIQ -> "ENOTUNIQ" + EBADFD -> "EBADFD" + EREMCHG -> "EREMCHG" + ELIBACC -> "ELIBACC" + ELIBBAD -> "ELIBBAD" + ELIBSCN -> "ELIBSCN" + ELIBMAX -> "ELIBMAX" + ELIBEXEC -> "ELIBEXEC" + EILSEQ -> "EILSEQ" + ERESTART -> "ERESTART" + ESTRPIPE -> "ESTRPIPE" + EUSERS -> "EUSERS" + ENOTSOCK -> "ENOTSOCK" + EDESTADDRREQ -> "EDESTADDRREQ" + EMSGSIZE -> "EMSGSIZE" + EPROTOTYPE -> "EPROTOTYPE" + ENOPROTOOPT -> "ENOPROTOOPT" + EPROTONOSUPPORT -> "EPROTONOSUPPORT" + ESOCKTNOSUPPORT -> "ESOCKTNOSUPPORT" + EOPNOTSUPP -> "EOPNOTSUPP" + EPFNOSUPPORT -> "EPFNOSUPPORT" + EAFNOSUPPORT -> "EAFNOSUPPORT" + EADDRINUSE -> "EADDRINUSE" + EADDRNOTAVAIL -> "EADDRNOTAVAIL" + ENETDOWN -> "ENETDOWN" + ENETUNREACH -> "ENETUNREACH" + ENETRESET -> "ENETRESET" + ECONNABORTED -> "ECONNABORTED" + ECONNRESET -> "ECONNRESET" + ENOBUFS -> "ENOBUFS" + EISCONN -> "EISCONN" + ENOTCONN -> "ENOTCONN" + ESHUTDOWN -> "ESHUTDOWN" + ETOOMANYREFS -> "ETOOMANYREFS" + ETIMEDOUT -> "ETIMEDOUT" + ECONNREFUSED -> "ECONNREFUSED" + EHOSTDOWN -> "EHOSTDOWN" + EHOSTUNREACH -> "EHOSTUNREACH" + EALREADY -> "EALREADY" + EINPROGRESS -> "EINPROGRESS" + ESTALE -> "ESTALE" + EUCLEAN -> "EUCLEAN" + ENOTNAM -> "ENOTNAM" + ENAVAIL -> "ENAVAIL" + EISNAM -> "EISNAM" + EREMOTEIO -> "EREMOTEIO" + EDQUOT -> "EDQUOT" + ENOMEDIUM -> "ENOMEDIUM" + EMEDIUMTYPE -> "EMEDIUMTYPE" + ECANCELED -> "ECANCELED" + ENOKEY -> "ENOKEY" + EKEYEXPIRED -> "EKEYEXPIRED" + EKEYREVOKED -> "EKEYREVOKED" + EKEYREJECTED -> "EKEYREJECTED" + EOWNERDEAD -> "EOWNERDEAD" + ENOTRECOVERABLE -> "ENOTRECOVERABLE" + ERFKILL -> "ERFKILL" + EHWPOISON -> "EHWPOISON" + ENOTSUP -> "ENOTSUP" + else -> null } - fun strerror(errno: Int): String? { - return when (errno) { - EPERM -> "Operation not permitted" - ENOENT -> "No such file or directory" - ESRCH -> "No such process" - EINTR -> "Interrupted system call" - EIO -> "Input/output error" - ENXIO -> "No such device or address" - E2BIG -> "Argument list too long" - ENOEXEC -> "Exec format error" - EBADF -> "Bad file descriptor" - ECHILD -> "No child processes" - EAGAIN -> "Resource temporarily unavailable" - ENOMEM -> "Cannot allocate memory" - EACCES -> "Permission denied" - EFAULT -> "Bad address" - ENOTBLK -> "Block device required" - EBUSY -> "Device or resource busy" - EEXIST -> "File exists" - EXDEV -> "Invalid cross-device link" - ENODEV -> "No such device" - ENOTDIR -> "Not a directory" - EISDIR -> "Is a directory" - EINVAL -> "Invalid argument" - ENFILE -> "Too many open files in system" - EMFILE -> "Too many open files" - ENOTTY -> "Inappropriate ioctl for device" - ETXTBSY -> "Text file busy" - EFBIG -> "File too large" - ENOSPC -> "No space left on device" - ESPIPE -> "Illegal seek" - EROFS -> "Read-only file system" - EMLINK -> "Too many links" - EPIPE -> "Broken pipe" - EDOM -> "Numerical argument out of domain" - ERANGE -> "Numerical result out of range" - EDEADLK -> "Resource deadlock avoided" - ENAMETOOLONG -> "File name too long" - ENOLCK -> "No locks available" - ENOSYS -> "Function not implemented" - ENOTEMPTY -> "Directory not empty" - ELOOP -> "Too many levels of symbolic links" - EWOULDBLOCK -> "Resource temporarily unavailable" - ENOMSG -> "No message of desired type" - EIDRM -> "Identifier removed" - ECHRNG -> "Channel number out of range" - EL2NSYNC -> "Level 2 not synchronized" - EL3HLT -> "Level 3 halted" - EL3RST -> "Level 3 reset" - ELNRNG -> "Link number out of range" - EUNATCH -> "Protocol driver not attached" - ENOCSI -> "No CSI structure available" - EL2HLT -> "Level 2 halted" - EBADE -> "Invalid exchange" - EBADR -> "Invalid request descriptor" - EXFULL -> "Exchange full" - ENOANO -> "No anode" - EBADRQC -> "Invalid request code" - EBADSLT -> "Invalid slot" - EDEADLOCK -> "Resource deadlock avoided" - EBFONT -> "Bad font file format" - ENOSTR -> "Device not a stream" - ENODATA -> "No data available" - ETIME -> "Timer expired" - ENOSR -> "Out of streams resources" - ENONET -> "Machine is not on the network" - ENOPKG -> "Package not installed" - EREMOTE -> "Object is remote" - ENOLINK -> "Link has been severed" - EADV -> "Advertise error" - ESRMNT -> "Srmount error" - ECOMM -> "Communication error on send" - EPROTO -> "Protocol error" - EMULTIHOP -> "Multihop attempted" - EDOTDOT -> "RFS specific error" - EBADMSG -> "Bad message" - EOVERFLOW -> "Value too large for defined data type" - ENOTUNIQ -> "Name not unique on network" - EBADFD -> "File descriptor in bad state" - EREMCHG -> "Remote address changed" - ELIBACC -> "Can not access a needed shared library" - ELIBBAD -> "Accessing a corrupted shared library" - ELIBSCN -> ".lib section in a.out corrupted" - ELIBMAX -> "Attempting to link in too many shared libraries" - ELIBEXEC -> "Cannot exec a shared library directly" - EILSEQ -> "Invalid or incomplete multibyte or wide character" - ERESTART -> "Interrupted system call should be restarted" - ESTRPIPE -> "Streams pipe error" - EUSERS -> "Too many users" - ENOTSOCK -> "Socket operation on non-socket" - EDESTADDRREQ -> "Destination address required" - EMSGSIZE -> "Message too long" - EPROTOTYPE -> "Protocol wrong type for socket" - ENOPROTOOPT -> "Protocol not available" - EPROTONOSUPPORT -> "Protocol not supported" - ESOCKTNOSUPPORT -> "Socket type not supported" - EOPNOTSUPP -> "Operation not supported" - EPFNOSUPPORT -> "Protocol family not supported" - EAFNOSUPPORT -> "Address family not supported by protocol" - EADDRINUSE -> "Address already in use" - EADDRNOTAVAIL -> "Cannot assign requested address" - ENETDOWN -> "Network is down" - ENETUNREACH -> "Network is unreachable" - ENETRESET -> "Network dropped connection on reset" - ECONNABORTED -> "Software caused connection abort" - ECONNRESET -> "Connection reset by peer" - ENOBUFS -> "No buffer space available" - EISCONN -> "Transport endpoint is already connected" - ENOTCONN -> "Transport endpoint is not connected" - ESHUTDOWN -> "Cannot send after transport endpoint shutdown" - ETOOMANYREFS -> "Too many references: cannot splice" - ETIMEDOUT -> "Connection timed out" - ECONNREFUSED -> "Connection refused" - EHOSTDOWN -> "Host is down" - EHOSTUNREACH -> "No route to host" - EALREADY -> "Operation already in progress" - EINPROGRESS -> "Operation now in progress" - ESTALE -> "Stale file handle" - EUCLEAN -> "Structure needs cleaning" - ENOTNAM -> "Not a XENIX named type file" - ENAVAIL -> "No XENIX semaphores available" - EISNAM -> "Is a named type file" - EREMOTEIO -> "Remote I/O error" - EDQUOT -> "Disk quota exceeded" - ENOMEDIUM -> "No medium found" - EMEDIUMTYPE -> "Wrong medium type" - ECANCELED -> "Operation canceled" - ENOKEY -> "Required key not available" - EKEYEXPIRED -> "Key has expired" - EKEYREVOKED -> "Key has been revoked" - EKEYREJECTED -> "Key was rejected by service" - EOWNERDEAD -> "Owner died" - ENOTRECOVERABLE -> "State not recoverable" - ERFKILL -> "Operation not possible due to RF-kill" - EHWPOISON -> "Memory page has hardware error" - ENOTSUP -> "Operation not supported" - else -> null - } + @Suppress("DUPLICATE_LABEL_IN_WHEN") + fun strerror(errno: Int) = when (errno) { + EPERM -> "Operation not permitted" + ENOENT -> "No such file or directory" + ESRCH -> "No such process" + EINTR -> "Interrupted system call" + EIO -> "Input/output error" + ENXIO -> "No such device or address" + E2BIG -> "Argument list too long" + ENOEXEC -> "Exec format error" + EBADF -> "Bad file descriptor" + ECHILD -> "No child processes" + EAGAIN -> "Resource temporarily unavailable" + ENOMEM -> "Cannot allocate memory" + EACCES -> "Permission denied" + EFAULT -> "Bad address" + ENOTBLK -> "Block device required" + EBUSY -> "Device or resource busy" + EEXIST -> "File exists" + EXDEV -> "Invalid cross-device link" + ENODEV -> "No such device" + ENOTDIR -> "Not a directory" + EISDIR -> "Is a directory" + EINVAL -> "Invalid argument" + ENFILE -> "Too many open files in system" + EMFILE -> "Too many open files" + ENOTTY -> "Inappropriate ioctl for device" + ETXTBSY -> "Text file busy" + EFBIG -> "File too large" + ENOSPC -> "No space left on device" + ESPIPE -> "Illegal seek" + EROFS -> "Read-only file system" + EMLINK -> "Too many links" + EPIPE -> "Broken pipe" + EDOM -> "Numerical argument out of domain" + ERANGE -> "Numerical result out of range" + EDEADLK -> "Resource deadlock avoided" + ENAMETOOLONG -> "File name too long" + ENOLCK -> "No locks available" + ENOSYS -> "Function not implemented" + ENOTEMPTY -> "Directory not empty" + ELOOP -> "Too many levels of symbolic links" + EWOULDBLOCK -> "Resource temporarily unavailable" + ENOMSG -> "No message of desired type" + EIDRM -> "Identifier removed" + ECHRNG -> "Channel number out of range" + EL2NSYNC -> "Level 2 not synchronized" + EL3HLT -> "Level 3 halted" + EL3RST -> "Level 3 reset" + ELNRNG -> "Link number out of range" + EUNATCH -> "Protocol driver not attached" + ENOCSI -> "No CSI structure available" + EL2HLT -> "Level 2 halted" + EBADE -> "Invalid exchange" + EBADR -> "Invalid request descriptor" + EXFULL -> "Exchange full" + ENOANO -> "No anode" + EBADRQC -> "Invalid request code" + EBADSLT -> "Invalid slot" + EDEADLOCK -> "Resource deadlock avoided" + EBFONT -> "Bad font file format" + ENOSTR -> "Device not a stream" + ENODATA -> "No data available" + ETIME -> "Timer expired" + ENOSR -> "Out of streams resources" + ENONET -> "Machine is not on the network" + ENOPKG -> "Package not installed" + EREMOTE -> "Object is remote" + ENOLINK -> "Link has been severed" + EADV -> "Advertise error" + ESRMNT -> "Srmount error" + ECOMM -> "Communication error on send" + EPROTO -> "Protocol error" + EMULTIHOP -> "Multihop attempted" + EDOTDOT -> "RFS specific error" + EBADMSG -> "Bad message" + EOVERFLOW -> "Value too large for defined data type" + ENOTUNIQ -> "Name not unique on network" + EBADFD -> "File descriptor in bad state" + EREMCHG -> "Remote address changed" + ELIBACC -> "Can not access a needed shared library" + ELIBBAD -> "Accessing a corrupted shared library" + ELIBSCN -> ".lib section in a.out corrupted" + ELIBMAX -> "Attempting to link in too many shared libraries" + ELIBEXEC -> "Cannot exec a shared library directly" + EILSEQ -> "Invalid or incomplete multibyte or wide character" + ERESTART -> "Interrupted system call should be restarted" + ESTRPIPE -> "Streams pipe error" + EUSERS -> "Too many users" + ENOTSOCK -> "Socket operation on non-socket" + EDESTADDRREQ -> "Destination address required" + EMSGSIZE -> "Message too long" + EPROTOTYPE -> "Protocol wrong type for socket" + ENOPROTOOPT -> "Protocol not available" + EPROTONOSUPPORT -> "Protocol not supported" + ESOCKTNOSUPPORT -> "Socket type not supported" + EOPNOTSUPP -> "Operation not supported" + EPFNOSUPPORT -> "Protocol family not supported" + EAFNOSUPPORT -> "Address family not supported by protocol" + EADDRINUSE -> "Address already in use" + EADDRNOTAVAIL -> "Cannot assign requested address" + ENETDOWN -> "Network is down" + ENETUNREACH -> "Network is unreachable" + ENETRESET -> "Network dropped connection on reset" + ECONNABORTED -> "Software caused connection abort" + ECONNRESET -> "Connection reset by peer" + ENOBUFS -> "No buffer space available" + EISCONN -> "Transport endpoint is already connected" + ENOTCONN -> "Transport endpoint is not connected" + ESHUTDOWN -> "Cannot send after transport endpoint shutdown" + ETOOMANYREFS -> "Too many references: cannot splice" + ETIMEDOUT -> "Connection timed out" + ECONNREFUSED -> "Connection refused" + EHOSTDOWN -> "Host is down" + EHOSTUNREACH -> "No route to host" + EALREADY -> "Operation already in progress" + EINPROGRESS -> "Operation now in progress" + ESTALE -> "Stale file handle" + EUCLEAN -> "Structure needs cleaning" + ENOTNAM -> "Not a XENIX named type file" + ENAVAIL -> "No XENIX semaphores available" + EISNAM -> "Is a named type file" + EREMOTEIO -> "Remote I/O error" + EDQUOT -> "Disk quota exceeded" + ENOMEDIUM -> "No medium found" + EMEDIUMTYPE -> "Wrong medium type" + ECANCELED -> "Operation canceled" + ENOKEY -> "Required key not available" + EKEYEXPIRED -> "Key has expired" + EKEYREVOKED -> "Key has been revoked" + EKEYREJECTED -> "Key was rejected by service" + EOWNERDEAD -> "Owner died" + ENOTRECOVERABLE -> "State not recoverable" + ERFKILL -> "Operation not possible due to RF-kill" + EHWPOISON -> "Memory page has hardware error" + ENOTSUP -> "Operation not supported" + else -> null } } diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/helper/CharSequenceHelper.kt b/app/src/main/java/de/kuschku/quasseldroid/util/helper/CharSequenceHelper.kt index 9eb8cd60b..6f41bc665 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/util/helper/CharSequenceHelper.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/util/helper/CharSequenceHelper.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.quasseldroid.util.helper private class DelimitedRangesSequence( diff --git a/build.gradle.kts b/build.gradle.kts index 957774b1e..172e1d2de 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,6 @@ +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + /* * Quasseldroid - Quassel client for Android * @@ -34,4 +37,13 @@ allprojects { jcenter() maven(url = "https://jitpack.io") } + + tasks.withType<KotlinCompile>().configureEach { + kotlinOptions { + freeCompilerArgs += listOf( + "-XXLanguage:+InlineClasses", + "-Xuse-experimental=kotlin.ExperimentalUnsignedTypes" + ) + } + } } diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/QTypes.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/QTypes.kt index eb5ad4338..ed4e1012c 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/QTypes.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/QTypes.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.libquassel.protocol import de.kuschku.libquassel.protocol.primitive.serializer.StringSerializer diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/QVariant.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/QVariant.kt index 471ee1211..3f6c99455 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/QVariant.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/QVariant.kt @@ -67,10 +67,12 @@ sealed class QVariant<T> constructor(val data: T?, val type: Type, val serialize } companion object { + @Suppress("UNCHECKED_CAST") fun <T> of(data: T?, type: Type): QVariant<T> { return QVariant.Typed(data, type, type.serializer as Serializer<T>) } + @Suppress("UNCHECKED_CAST") fun <T> of(data: T?, type: QType) = QVariant.Custom(data, type, type.serializer as Serializer<T>) } diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/SignedId.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/SignedId.kt index 1167b82dd..317cc7cd8 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/SignedId.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/SignedId.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.libquassel.protocol typealias SignedId = Int diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt index 55305124a..86334a1ea 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.libquassel.protocol.primitive.serializer import de.kuschku.libquassel.quassel.QuasselFeatures diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/VariantSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/VariantSerializer.kt index d2d434992..47eea2bb4 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/VariantSerializer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/VariantSerializer.kt @@ -25,6 +25,7 @@ import de.kuschku.libquassel.util.nio.ChainedByteBuffer import java.nio.ByteBuffer object VariantSerializer : Serializer<QVariant_> { + @Suppress("UNCHECKED_CAST") override fun serialize(buffer: ChainedByteBuffer, data: QVariant_, features: QuasselFeatures) { IntSerializer.serialize(buffer, data.type.id, features) BoolSerializer.serialize(buffer, false, features) @@ -37,6 +38,7 @@ object VariantSerializer : Serializer<QVariant_> { override fun deserialize(buffer: ByteBuffer, features: QuasselFeatures): QVariant_ { val rawType = IntSerializer.deserialize(buffer, features) val type = Type.of(rawType) + @Suppress("UNUSED_VARIABLE") val isNull = BoolSerializer.deserialize(buffer, features) return if (type == Type.UserType) { diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt index 6a1c9e48f..0730f5686 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferSyncer.kt @@ -179,7 +179,7 @@ class BufferSyncer constructor( _bufferActivities.remove(buffer);live_bufferActivities.onNext(Unit) _highlightCounts.remove(buffer);live_highlightCounts.onNext(Unit) _bufferInfos.remove(buffer);live_bufferInfos.onNext(Unit) - session.backlogManager?.removeBuffer(buffer) + session.backlogManager.removeBuffer(buffer) notificationManager?.clear(buffer) } @@ -198,7 +198,7 @@ class BufferSyncer constructor( live_bufferInfos.onNext(Unit) if (oldInfo == null) { - session.bufferViewManager?.handleBuffer(info, this) + session.bufferViewManager.handleBuffer(info, this) } } } @@ -232,7 +232,7 @@ class BufferSyncer constructor( flags hasFlag Message_Type.Notice || flags hasFlag Message_Type.Action) { bufferInfo(buffer)?.let { - session.bufferViewManager?.handleBuffer(it, this, true) + session.bufferViewManager.handleBuffer(it, this, true) } } _bufferActivities[buffer] = flags diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt index 66a4c5ec4..b0f464451 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManager.kt @@ -22,19 +22,14 @@ package de.kuschku.libquassel.quassel.syncables import de.kuschku.libquassel.protocol.* import de.kuschku.libquassel.quassel.syncables.interfaces.IIgnoreListManager import de.kuschku.libquassel.session.ISession -import de.kuschku.libquassel.session.Session -import de.kuschku.libquassel.session.SignalProxy import de.kuschku.libquassel.util.ExpressionMatch import de.kuschku.libquassel.util.flag.and import io.reactivex.subjects.BehaviorSubject import java.io.Serializable class IgnoreListManager constructor( - var session: ISession, - proxy: SignalProxy -) : SyncableObject(proxy, "IgnoreListManager"), IIgnoreListManager { - constructor(session: Session) : this(session, session) - + var session: ISession +) : SyncableObject(session.proxy, "IgnoreListManager"), IIgnoreListManager { override fun deinit() { super.deinit() session = ISession.NULL @@ -129,7 +124,7 @@ class IgnoreListManager constructor( fun updates() = live_updates.map { this } - fun copy() = IgnoreListManager(session, proxy).also { + fun copy() = IgnoreListManager(session).also { it.fromVariantMap(toVariantMap()) } @@ -287,7 +282,7 @@ class IgnoreListManager constructor( set(value) { field = value live_updates.onNext(Unit) - if (initialized) session.backlogManager?.updateIgnoreRules() + if (initialized) session.backlogManager.updateIgnoreRules() } fun isEqual(other: IgnoreListManager): Boolean = diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt index 6819fff92..423c811a1 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcChannel.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.libquassel.quassel.syncables import de.kuschku.libquassel.protocol.* @@ -135,7 +135,7 @@ class IrcChannel( fun network() = _network fun ircUsers() = _userModes.keys fun liveIrcUsers(): Observable<MutableSet<IrcUser>> = - live_userModes.map(MutableMap<IrcUser, String>::keys) + live_userModes.map { _userModes }.map(MutableMap<IrcUser, String>::keys) fun userModes(ircUser: IrcUser) = _userModes.getOr(ircUser, "") fun liveUserModes(ircUser: IrcUser) = live_userModes.map { @@ -289,10 +289,10 @@ class IrcChannel( part(network().ircUser(nick)) } - override fun setUserModes(ircuser: IrcUser?, modes: String) { + override fun setUserModes(ircuser: IrcUser?, modes: String?) { if (ircuser == null || !isKnownUser(ircuser)) return - _userModes[ircuser] = modes + _userModes[ircuser] = modes ?: "" updateUsers() } @@ -304,12 +304,13 @@ class IrcChannel( addUserMode(ircuser, String(charArrayOf(mode))) } - override fun addUserMode(ircuser: IrcUser?, mode: String) { - if (ircuser == null || !isKnownUser(ircuser) || !isValidChannelUserMode(mode)) + override fun addUserMode(ircuser: IrcUser?, mode: String?) { + val userMode = mode ?: "" + if (ircuser == null || !isKnownUser(ircuser) || !isValidChannelUserMode(userMode)) return - if (_userModes.getOr(ircuser, "").contains(mode, ignoreCase = true)) + if (_userModes.getOr(ircuser, "").contains(userMode, ignoreCase = true)) return - _userModes[ircuser] = _userModes.getOr(ircuser, "") + mode + _userModes[ircuser] = _userModes.getOr(ircuser, "") + userMode updateUsers() } @@ -317,13 +318,14 @@ class IrcChannel( addUserMode(network().ircUser(nick), mode ?: "") } - override fun removeUserMode(ircuser: IrcUser?, mode: String) { - if (ircuser == null || !isKnownUser(ircuser) || !isValidChannelUserMode(mode)) + override fun removeUserMode(ircuser: IrcUser?, mode: String?) { + val userMode = mode ?: "" + if (ircuser == null || !isKnownUser(ircuser) || !isValidChannelUserMode(userMode)) return - if (!_userModes.getOr(ircuser, "").contains(mode, ignoreCase = true)) + if (!_userModes.getOr(ircuser, "").contains(userMode, ignoreCase = true)) return _userModes[ircuser] = _userModes.getOr(ircuser, "") - .replace(mode, "", ignoreCase = true) + .replace(userMode, "", ignoreCase = true) updateUsers() } @@ -398,15 +400,11 @@ class IrcChannel( private fun updateUsers() { _userCount = _userModes.size - live_userModes.onNext(_userModes) + live_userModes.onNext(Unit) } - private val live_userModes = BehaviorSubject.createDefault(mutableMapOf<IrcUser, String>()) - private var _userModes: MutableMap<IrcUser, String> - get() = live_userModes.value!! - set(value) { - updateUsers() - } + private val live_userModes = BehaviorSubject.createDefault(Unit) + private val _userModes = mutableMapOf<IrcUser, String>() private var _network: Network = network diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcUser.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcUser.kt index cf21fd1fc..cc1eb058a 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcUser.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/IrcUser.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.libquassel.quassel.syncables import de.kuschku.libquassel.protocol.* @@ -76,25 +76,25 @@ class IrcUser( } ?: it } - override fun initSetProperties(properties: QVariantMap, i: Int?) { - setUser(properties["user"].indexed(i).valueOr(this::user)) - setHost(properties["host"].indexed(i).valueOr(this::host)) - setNick(properties["nick"].indexed(i).valueOr(this::nick)) - setRealName(properties["realName"].indexed(i).valueOr(this::realName)) - setAccount(properties["account"].indexed(i).valueOr(this::account)) - setAway(properties["away"].indexed(i).valueOr(this::isAway)) - setAwayMessage(properties["awayMessage"].indexed(i).valueOr(this::awayMessage)) - setIdleTime(properties["idleTime"].indexed(i).valueOr(this::idleTime)) - setLoginTime(properties["loginTime"].indexed(i).valueOr(this::loginTime)) - setServer(properties["server"].indexed(i).valueOr(this::server)) - setIrcOperator(properties["ircOperator"].indexed(i).valueOr(this::ircOperator)) - setLastAwayMessageTime(properties["lastAwayMessageTime"].indexed(i).valueOr { - Instant.ofEpochSecond(properties["lastAwayMessage"].indexed(i).valueOr(this::lastAwayMessage).toLong()) + override fun initSetProperties(properties: QVariantMap, index: Int?) { + setUser(properties["user"].indexed(index).valueOr(this::user)) + setHost(properties["host"].indexed(index).valueOr(this::host)) + setNick(properties["nick"].indexed(index).valueOr(this::nick)) + setRealName(properties["realName"].indexed(index).valueOr(this::realName)) + setAccount(properties["account"].indexed(index).valueOr(this::account)) + setAway(properties["away"].indexed(index).valueOr(this::isAway)) + setAwayMessage(properties["awayMessage"].indexed(index).valueOr(this::awayMessage)) + setIdleTime(properties["idleTime"].indexed(index).valueOr(this::idleTime)) + setLoginTime(properties["loginTime"].indexed(index).valueOr(this::loginTime)) + setServer(properties["server"].indexed(index).valueOr(this::server)) + setIrcOperator(properties["ircOperator"].indexed(index).valueOr(this::ircOperator)) + setLastAwayMessageTime(properties["lastAwayMessageTime"].indexed(index).valueOr { + Instant.ofEpochSecond(properties["lastAwayMessage"].indexed(index).valueOr(this::lastAwayMessage).toLong()) }) - setWhoisServiceReply(properties["whoisServiceReply"].indexed(i).valueOr(this::whoisServiceReply)) - setSuserHost(properties["suserHost"].indexed(i).valueOr(this::suserHost)) - setEncrypted(properties["encrypted"].indexed(i).valueOr(this::encrypted)) - setUserModes(properties["userModes"].indexed(i).valueOr(this::userModes)) + setWhoisServiceReply(properties["whoisServiceReply"].indexed(index).valueOr(this::whoisServiceReply)) + setSuserHost(properties["suserHost"].indexed(index).valueOr(this::suserHost)) + setEncrypted(properties["encrypted"].indexed(index).valueOr(this::encrypted)) + setUserModes(properties["userModes"].indexed(index).valueOr(this::userModes)) } fun updates(): Observable<IrcUser> = hasChangedNotification.map { this } diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt index 77e28b4b0..b309cc1ef 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Network.kt @@ -188,7 +188,7 @@ class Network constructor( override fun setNetworkInfo(info: NetworkInfo) { // we don't set our ID! - if (!info.networkName.isNullOrEmpty() && info.networkName != networkName()) + if (!info.networkName.isEmpty() && info.networkName != networkName()) setNetworkName(info.networkName) if (info.identity.isValidId() && info.identity != identity()) setIdentity(info.identity) @@ -448,11 +448,10 @@ class Network constructor( } } - override fun setConnectionState(state: Int) { - val actualConnectionState = ConnectionState.of(state) - if (_connectionState == actualConnectionState) + override fun setConnectionState(state: ConnectionState) { + if (_connectionState == state) return - _connectionState = actualConnectionState + _connectionState = state live_connectionState.onNext(_connectionState) } @@ -477,13 +476,7 @@ class Network constructor( _identity = identity } - override fun setServerList(serverList: QVariantList) { - setActualServerList(serverList.map { - it.valueOrThrow<QVariantMap>() - }.map(Server.Companion::fromVariantMap)) - } - - fun setActualServerList(serverList: List<INetwork.Server>) { + override fun setActualServerList(serverList: List<INetwork.Server>) { if (_serverList == serverList) return _serverList = serverList @@ -753,13 +746,11 @@ class Network constructor( if (initialized) throw IllegalArgumentException("Received init data for network ${networkId()} after init") val users: Map<String, QVariant_> = usersAndChannels["Users"].valueOr(::emptyMap) - val userKeys = users.keys users["nick"].valueOr<QVariantList>(::emptyList).forEachIndexed { index, nick -> newIrcUser(nick.value(""), users, index) } val channels: Map<String, QVariant_> = usersAndChannels["Channels"].valueOr(::emptyMap) - val channelKeys = channels.keys channels["name"].valueOr<QVariantList>(::emptyList).forEachIndexed { index, nick -> newIrcChannel(nick.value(""), channels, index) } diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt index 779d1f7ee..02baf36bc 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.libquassel.quassel.syncables import de.kuschku.libquassel.protocol.* @@ -25,17 +25,21 @@ import de.kuschku.libquassel.quassel.BufferInfo import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork import de.kuschku.libquassel.quassel.syncables.interfaces.IRpcHandler import de.kuschku.libquassel.session.BacklogStorage +import de.kuschku.libquassel.session.ISession import de.kuschku.libquassel.session.NotificationManager -import de.kuschku.libquassel.session.Session import de.kuschku.libquassel.util.helpers.deserializeString import de.kuschku.libquassel.util.rxjava.ReusableUnicastSubject import java.nio.ByteBuffer class RpcHandler( - override val session: Session, + var session: ISession, private val backlogStorage: BacklogStorage? = null, private val notificationManager: NotificationManager? = null ) : IRpcHandler { + fun deinit() { + session = ISession.NULL + } + override fun displayStatusMsg(net: String?, msg: String?) { } @@ -57,13 +61,13 @@ class RpcHandler( } override fun disconnectFromCore() { - session.disconnectFromCore?.invoke() + session.disconnectFromCore() } override fun objectRenamed(classname: ByteBuffer, newname: String?, oldname: String?) { - session.renameObject(classname.deserializeString(StringSerializer.UTF8) ?: "", - newname ?: "", - oldname ?: "") + session.proxy.renameObject(classname.deserializeString(StringSerializer.UTF8) ?: "", + newname ?: "", + oldname ?: "") } override fun displayMsg(message: Message) { @@ -122,7 +126,7 @@ class RpcHandler( inline fun RPC(function: String, vararg arg: QVariant_) { // Donβt transmit calls back that we just got from the network - if (session.shouldRpc(function)) - session.callRpc(function, arg.toList()) + if (session.proxy.shouldRpc(function)) + session.proxy.callRpc(function, arg.toList()) } } diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IIrcChannel.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IIrcChannel.kt index b2e7510e3..ccaf6dc7a 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IIrcChannel.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IIrcChannel.kt @@ -36,12 +36,12 @@ interface IIrcChannel : ISyncableObject { fun initSetProperties(properties: QVariantMap, i: Int? = null) @Slot - fun addChannelMode(mode: Char, value: String?) + fun addChannelMode(mode: Char, value: String? = null) - fun addUserMode(ircuser: IrcUser?, mode: String) + fun addUserMode(ircuser: IrcUser?, mode: String? = null) @Slot - fun addUserMode(nick: String?, mode: String?) + fun addUserMode(nick: String?, mode: String? = null) @Slot fun joinIrcUser(ircuser: IrcUser) @@ -55,12 +55,12 @@ interface IIrcChannel : ISyncableObject { fun part(nick: String?) @Slot - fun removeChannelMode(mode: Char, value: String?) + fun removeChannelMode(mode: Char, value: String? = null) - fun removeUserMode(ircuser: IrcUser?, mode: String) + fun removeUserMode(ircuser: IrcUser?, mode: String? = null) @Slot - fun removeUserMode(nick: String?, mode: String?) + fun removeUserMode(nick: String?, mode: String? = null) @Slot fun setEncrypted(encrypted: Boolean) @@ -71,10 +71,10 @@ interface IIrcChannel : ISyncableObject { @Slot fun setTopic(topic: String?) - fun setUserModes(ircuser: IrcUser?, modes: String) + fun setUserModes(ircuser: IrcUser?, modes: String? = null) @Slot - fun setUserModes(nick: String?, modes: String?) + fun setUserModes(nick: String?, modes: String? = null) @Slot override fun update(properties: QVariantMap) diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt index 42e8e8af6..dd091bbd1 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/INetwork.kt @@ -49,7 +49,7 @@ interface INetwork : ISyncableObject { fun acknowledgeCap(capability: String?) @Slot - fun addCap(capability: String, value: String?) + fun addCap(capability: String, value: String? = null) @Slot fun addIrcChannel(channel: String?) @@ -115,7 +115,8 @@ interface INetwork : ISyncableObject { fun setConnected(isConnected: Boolean) @Slot - fun setConnectionState(state: Int) + fun setConnectionState(state: Int) = setConnectionState(ConnectionState.of(state)) + fun setConnectionState(state: ConnectionState) @Slot fun setCurrentServer(currentServer: String?) @@ -154,7 +155,12 @@ interface INetwork : ISyncableObject { fun setSaslPassword(password: String?) @Slot - fun setServerList(serverList: QVariantList) + fun setServerList(serverList: QVariantList) { + setActualServerList(serverList.map { + it.valueOrThrow<QVariantMap>() + }.map(Server.Companion::fromVariantMap)) + } + fun setActualServerList(serverList: List<INetwork.Server>) @Slot fun setUnlimitedMessageRate(unlimitedRate: Boolean) diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IRpcHandler.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IRpcHandler.kt index b6f9ea207..06d3f7eba 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IRpcHandler.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IRpcHandler.kt @@ -27,13 +27,10 @@ import de.kuschku.libquassel.protocol.NetworkId import de.kuschku.libquassel.protocol.QVariantMap import de.kuschku.libquassel.quassel.BufferInfo import de.kuschku.libquassel.quassel.syncables.Identity -import de.kuschku.libquassel.session.Session import java.nio.ByteBuffer @Syncable(name = "RpcHandler") interface IRpcHandler { - val session: Session - @Slot(value = "__objectRenamed__") fun objectRenamed(classname: ByteBuffer, newname: String?, oldname: String?) diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt index a37688f67..2520d4634 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.libquassel.quassel.syncables.interfaces import de.kuschku.libquassel.protocol.ARG diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/invokers/Invokers.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/invokers/Invokers.kt index f10966a75..93b022bb9 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/invokers/Invokers.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/invokers/Invokers.kt @@ -83,6 +83,7 @@ object Invokers { return null } + @Suppress("UNCHECKED_CAST") return invoker as Invoker<T>? } diff --git a/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt b/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt index 8e0e595e7..1fda5229c 100644 --- a/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt +++ b/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt @@ -23,6 +23,7 @@ import de.kuschku.libquassel.connection.ConnectionState import de.kuschku.libquassel.connection.Features import de.kuschku.libquassel.protocol.IdentityId import de.kuschku.libquassel.protocol.NetworkId +import de.kuschku.libquassel.protocol.QVariantMap import de.kuschku.libquassel.protocol.message.HandshakeMessage import de.kuschku.libquassel.quassel.QuasselFeatures import de.kuschku.libquassel.quassel.syncables.* @@ -38,23 +39,23 @@ interface ISession : Closeable { val features: Features val sslSession: Observable<Optional<SSLSession>> - val aliasManager: AliasManager? - val backlogManager: BacklogManager? - val bufferSyncer: BufferSyncer? - val bufferViewManager: BufferViewManager? + val aliasManager: AliasManager + val backlogManager: BacklogManager + val bufferSyncer: BufferSyncer + val bufferViewManager: BufferViewManager val certManagers: Map<IdentityId, CertManager> - val coreInfo: CoreInfo? - val dccConfig: DccConfig? + val coreInfo: CoreInfo + val dccConfig: DccConfig val identities: Map<IdentityId, Identity> fun liveIdentities(): Observable<Map<IdentityId, Identity>> - val ignoreListManager: IgnoreListManager? - val highlightRuleManager: HighlightRuleManager? - val ircListHelper: IrcListHelper? + val ignoreListManager: IgnoreListManager + val highlightRuleManager: HighlightRuleManager + val ircListHelper: IrcListHelper val networks: Map<NetworkId, Network> fun liveNetworks(): Observable<Map<NetworkId, Network>> fun liveNetworkAdded(): Observable<NetworkId> - val networkConfig: NetworkConfig? - val rpcHandler: RpcHandler? + val networkConfig: NetworkConfig + val rpcHandler: RpcHandler val initStatus: Observable<Pair<Int, Int>> fun network(id: NetworkId): Network? @@ -63,10 +64,17 @@ interface ISession : Closeable { val proxy: SignalProxy val error: Observable<Error> val connectionError: Observable<Throwable> - val lag: Observable<Long> + val lag: BehaviorSubject<Long> fun login(user: String, pass: String) - fun setupCore(setupData: HandshakeMessage.CoreSetupData) + fun setupCore(setupData: HandshakeMessage.CoreSetupData) { + proxy.dispatch(setupData) + } + fun disconnectFromCore() + fun addNetwork(networkId: NetworkId) + fun removeNetwork(networkId: NetworkId) + fun addIdentity(initData: QVariantMap) + fun removeIdentity(identityId: IdentityId) companion object { val NULL = object : ISession { @@ -79,31 +87,36 @@ interface ISession : Closeable { QuasselFeatures.empty()) override val sslSession: Observable<Optional<SSLSession>> = Observable.empty() - override val rpcHandler: RpcHandler? = null - override val aliasManager: AliasManager? = null - override val backlogManager: BacklogManager? = null - override val bufferSyncer: BufferSyncer? = null - override val bufferViewManager: BufferViewManager? = null + override val rpcHandler = RpcHandler(this) + override val aliasManager = AliasManager(proxy) + override val backlogManager = BacklogManager(this) + override val bufferSyncer = BufferSyncer(this) + override val bufferViewManager = BufferViewManager(proxy) override val certManagers: Map<IdentityId, CertManager> = emptyMap() - override val coreInfo: CoreInfo? = null - override val dccConfig: DccConfig? = null + override val coreInfo = CoreInfo(proxy) + override val dccConfig = DccConfig(proxy) override val identities: Map<IdentityId, Identity> = emptyMap() override fun liveIdentities() = Observable.empty<Map<IdentityId, Identity>>() - override val ignoreListManager: IgnoreListManager? = null - override val highlightRuleManager: HighlightRuleManager? = null - override val ircListHelper: IrcListHelper? = null + override val ignoreListManager = IgnoreListManager(this) + override val highlightRuleManager = HighlightRuleManager(proxy) + override val ircListHelper = IrcListHelper(proxy) override val networks: Map<NetworkId, Network> = emptyMap() override fun liveNetworks() = Observable.empty<Map<NetworkId, Network>>() override fun liveNetworkAdded(): Observable<NetworkId> = PublishSubject.create() - override val networkConfig: NetworkConfig? = null + override val networkConfig = NetworkConfig(proxy) override val initStatus: Observable<Pair<Int, Int>> = Observable.just(0 to 0) - override val lag: Observable<Long> = Observable.just(0L) + override val lag = BehaviorSubject.createDefault(0L) override fun network(id: NetworkId): Network? = null override fun identity(id: IdentityId): Identity? = null override fun login(user: String, pass: String) = Unit override fun setupCore(setupData: HandshakeMessage.CoreSetupData) = Unit + override fun disconnectFromCore() = Unit + override fun addNetwork(networkId: NetworkId) = Unit + override fun removeNetwork(networkId: NetworkId) = Unit + override fun addIdentity(initData: QVariantMap) = Unit + override fun removeIdentity(identityId: IdentityId) = Unit override fun close() = Unit } } diff --git a/lib/src/main/java/de/kuschku/libquassel/session/NotificationManager.kt b/lib/src/main/java/de/kuschku/libquassel/session/NotificationManager.kt index ac07a3663..275112a6f 100644 --- a/lib/src/main/java/de/kuschku/libquassel/session/NotificationManager.kt +++ b/lib/src/main/java/de/kuschku/libquassel/session/NotificationManager.kt @@ -24,7 +24,7 @@ import de.kuschku.libquassel.protocol.Message import de.kuschku.libquassel.protocol.MsgId interface NotificationManager { - fun init(session: Session) - fun processMessages(session: Session, show: Boolean, vararg messages: Message) + fun init(session: ISession) + fun processMessages(session: ISession, show: Boolean, vararg messages: Message) fun clear(buffer: BufferId, lastRead: MsgId = MsgId.MAX_VALUE) } diff --git a/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt b/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt index ac5799918..8263582c1 100644 --- a/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt +++ b/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt @@ -36,7 +36,7 @@ abstract class ProtocolHandler( ) : SignalProxy, AuthHandler, Closeable { protected var closed = false protected abstract val objectStorage: ObjectStorage - protected open var rpcHandler: RpcHandler? = null + protected abstract val rpcHandler: RpcHandler private val toInit = mutableMapOf<ISyncableObject, MutableList<SignalProxyMessage.SyncMessage>>() private val syncQueue = mutableListOf<SignalProxyMessage.SyncMessage>() diff --git a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt index 5fc7fee8a..346f33d4d 100644 --- a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt +++ b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt @@ -103,7 +103,7 @@ class Session( override val networkConfig = NetworkConfig(this) - override var rpcHandler: RpcHandler? = RpcHandler(this, backlogStorage, notificationManager) + override val rpcHandler = RpcHandler(this, backlogStorage, notificationManager) override val initStatus = BehaviorSubject.createDefault(0 to 0) @@ -180,7 +180,7 @@ class Session( _connectionError.onNext(connectionError) } - fun addNetwork(networkId: NetworkId) { + override fun addNetwork(networkId: NetworkId) { val network = Network(networkId, this) networks[networkId] = network synchronize(network) @@ -188,13 +188,13 @@ class Session( network_added.onNext(networkId) } - fun removeNetwork(networkId: NetworkId) { + override fun removeNetwork(networkId: NetworkId) { val network = networks.remove(networkId) stopSynchronize(network) live_networks.onNext(Unit) } - fun addIdentity(initData: QVariantMap) { + override fun addIdentity(initData: QVariantMap) { val identity = Identity(this) identity.fromVariantMap(initData) identities[identity.id()] = identity @@ -202,12 +202,16 @@ class Session( live_identities.onNext(Unit) } - fun removeIdentity(identityId: IdentityId) { + override fun removeIdentity(identityId: IdentityId) { val identity = identities.remove(identityId) stopSynchronize(identity) live_identities.onNext(Unit) } + override fun disconnectFromCore() { + disconnectFromCore?.invoke() + } + override fun handle(f: HandshakeMessage.SessionInit): Boolean { coreConnection.setState(ConnectionState.INIT) @@ -311,8 +315,7 @@ class Session( ircListHelper.deinit() networkConfig.deinit() backlogManager.deinit() - - rpcHandler = null + rpcHandler.deinit() certManagers.clear() identities.clear() diff --git a/lib/src/main/java/de/kuschku/libquassel/util/compatibility/LoggingHandler.kt b/lib/src/main/java/de/kuschku/libquassel/util/compatibility/LoggingHandler.kt index 81af4b791..11a8228d8 100644 --- a/lib/src/main/java/de/kuschku/libquassel/util/compatibility/LoggingHandler.kt +++ b/lib/src/main/java/de/kuschku/libquassel/util/compatibility/LoggingHandler.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.libquassel.util.compatibility import de.kuschku.libquassel.util.compatibility.reference.JavaLoggingHandler diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/MathHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helpers/MathHelper.kt index 0b5620c83..7abbf85c6 100644 --- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/MathHelper.kt +++ b/lib/src/main/java/de/kuschku/libquassel/util/helpers/MathHelper.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.libquassel.util.helpers inline fun clampOf(value: Int, lowerBound: Int, upperBound: Int): Int = diff --git a/lib/src/test/java/de/kuschku/libquassel/IntegrationTest.kt b/lib/src/test/java/de/kuschku/libquassel/IntegrationTest.kt new file mode 100644 index 000000000..e0690bc2e --- /dev/null +++ b/lib/src/test/java/de/kuschku/libquassel/IntegrationTest.kt @@ -0,0 +1,52 @@ +/* + * Quasseldroid - Quassel client for Android + * + * Copyright (c) 2019 Janne Koschinski + * Copyright (c) 2019 The Quassel Project + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.libquassel + +import de.kuschku.libquassel.protocol.NetworkId +import de.kuschku.libquassel.protocol.QType +import de.kuschku.libquassel.protocol.QVariant_ +import de.kuschku.libquassel.protocol.Type +import de.kuschku.libquassel.util.withTestSession +import org.junit.Test + +class IntegrationTest { + @Test + fun test() = withTestSession { + ensure { + rpcHandler.changePassword(0L, "user", "pass", "p@ssword1") + }.does { + callRpc( + "2changePassword(PeerPtr,QString,QString,QString)", + listOf( + QVariant_.of(0L, QType.PeerPtr), + QVariant_.of("user", Type.QString), + QVariant_.of("pass", Type.QString), + QVariant_.of("p@ssword1", Type.QString) + ) + ) + } + + ensure { + val network = network(NetworkId(1))!! + val justJanne = network.ircUser("justJanne")!! + assert(justJanne.channels().contains("#quassel-test")) + } + } +} diff --git a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializerTest.kt b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializerTest.kt index 9981fe8a1..24842a94c 100644 --- a/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializerTest.kt +++ b/lib/src/test/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializerTest.kt @@ -33,8 +33,19 @@ class StringSerializerTest { this::class.java.getResourceAsStream("/blns.txt").bufferedReader(Charsets.UTF_8).forEachLine { // Ignore comments if (!it.startsWith('#')) { - assertThat<String>(roundTrip(StringSerializer.UTF16, it), BomMatcher(it)) assertThat<String>(roundTrip(StringSerializer.UTF8, it), BomMatcher(it)) + assertThat<String>(roundTrip(StringSerializer.UTF16, it), BomMatcher(it)) + } + } + } + + @Test + fun testNaughtyStrings() { + this::class.java.getResourceAsStream("/naughty_strings.txt").bufferedReader(Charsets.UTF_8).forEachLine { + // Ignore comments + if (!it.startsWith('#')) { + assertEquals(it, roundTrip(StringSerializer.UTF8, it)) + assertEquals(it, roundTrip(StringSerializer.UTF16, it)) } } } diff --git a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManagerTest.kt b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManagerTest.kt index 0d53e1c5c..f3a5b9b9e 100644 --- a/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManagerTest.kt +++ b/lib/src/test/java/de/kuschku/libquassel/quassel/syncables/IgnoreListManagerTest.kt @@ -21,7 +21,6 @@ package de.kuschku.libquassel.quassel.syncables import de.kuschku.libquassel.protocol.primitive.serializer.VariantMapSerializer import de.kuschku.libquassel.session.ISession -import de.kuschku.libquassel.session.SignalProxy import de.kuschku.libquassel.util.randomBoolean import de.kuschku.libquassel.util.randomOf import de.kuschku.libquassel.util.randomString @@ -31,7 +30,7 @@ import org.junit.Test class IgnoreListManagerTest { @Test fun testSerialization() { - val original = IgnoreListManager(ISession.NULL, SignalProxy.NULL) + val original = IgnoreListManager(ISession.NULL) original.setIgnoreList(listOf( IgnoreListManager.IgnoreListItem( type = randomOf(*IgnoreListManager.IgnoreType.values()), @@ -65,7 +64,7 @@ class IgnoreListManagerTest { @Test fun testCopy() { - val original = IgnoreListManager(ISession.NULL, SignalProxy.NULL) + val original = IgnoreListManager(ISession.NULL) original.setIgnoreList(listOf( IgnoreListManager.IgnoreListItem( type = randomOf(*IgnoreListManager.IgnoreType.values()), diff --git a/lib/src/test/java/de/kuschku/libquassel/util/SetupTests.kt b/lib/src/test/java/de/kuschku/libquassel/util/SetupTests.kt new file mode 100644 index 000000000..2c46893b2 --- /dev/null +++ b/lib/src/test/java/de/kuschku/libquassel/util/SetupTests.kt @@ -0,0 +1,138 @@ +/* + * Quasseldroid - Quassel client for Android + * + * Copyright (c) 2019 Janne Koschinski + * Copyright (c) 2019 The Quassel Project + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.libquassel.util + +import de.kuschku.libquassel.protocol.IdentityId +import de.kuschku.libquassel.protocol.NetworkId +import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork + +fun withTestSession(f: TestSession.() -> Unit) = f.invoke(setupTestSession()) + +fun setupTestSession() = TestSession().provideTestData { + identities = listOf( + buildIdentity { + setId(IdentityId(1)) + setIdentityName("Default Identity") + setRealName("Janne Mareike Koschinski <janne@kuschku.de>") + setNicks(listOf( + "justJanne", + "ninjanne", + "janne", + "kuschku" + )) + setIdent("justJanne") + } + ) + networks = listOf( + buildNetwork(NetworkId(1)) { + setNetworkName("FreeNode") + setCurrentServer("tepper.freenode.net") + setConnected(true) + setConnectionState(INetwork.ConnectionState.Initialized) + setMyNick("justJanne") + setLatency(48) + setIdentity(IdentityId(1)) + setActualServerList(listOf( + INetwork.Server( + host = "irc.freenode.net", + port = INetwork.PortDefaults.PORT_SSL.port, + useSsl = true + ), + INetwork.Server( + host = "chat.freenode.net", + port = INetwork.PortDefaults.PORT_SSL.port, + useSsl = true + ) + )) + addSupport("CHANTYPES", "#") + addSupport("EXCEPTS") + addSupport("INVEX") + addSupport("CHANMODES", "eIbq,k,flj,CFLMPQScgimnprstz") + addSupport("CHANLIMIT", "#:120") + addSupport("PREFIX", "(ov)@+") + addSupport("MAXLIST", "bqeI:100") + addSupport("MODES", "4") + addSupport("NETWORK", "freenode") + addSupport("STATUSMSG", "@+") + addSupport("CALLERID", "g") + addSupport("CASEMAPPING", "rfc1459") + addSupport("CHARSET", "ascii") + addSupport("NICKLEN", "16") + addSupport("CHANNELLEN", "50") + addSupport("TOPICLEN", "390") + addSupport("DEAF", "D") + addSupport("FNC") + addSupport("TARGMAX", "NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR:") + addSupport("EXTBAN", "$,ajrxz") + addSupport("CLIENTVER", "3.0") + addSupport("ETRACE") + addSupport("KNOCK") + addSupport("WHOX") + addSupport("CPRIVMSG") + addSupport("CNOTICE") + addSupport("SAFELIST") + addSupport("ELIST", "CTU") + + addCap("account-notify") + addCap("sasl") + addCap("identify-msg") + addCap("multi-prefix") + addCap("extended-join") + + acknowledgeCap("sasl") + acknowledgeCap("account-notify") + acknowledgeCap("extended-join") + acknowledgeCap("multi-prefix") + + val justJanne = buildIrcUser("justJanne") { + setUser("kuschku") + setHost("kuschku.de") + setRealName("Janne Mareike Koschinski <janne@kuschku.de>") + setAccount("justJanne") + setServer("tepper.freenode.net") + } + val digitalcircuit = buildIrcUser("digitalcircuit") { + setUser("~quassel") + setHost("2605:6000:1518:830d:ec4:7aff:fe6b:c6b0") + setRealName("Shane <avatar@mg.zorro.casa>") + setAccount("digitalcircuit") + setServer("wolfe.freenode.net") + } + val Sput = buildIrcUser("Sput") { + setUser("~sputnick") + setHost("quassel/developer/sput") + setRealName("Sputnick -- http://quassel-irc.org") + setAccount("Sput") + setServer("niven.freenode.net") + } + + buildIrcChannel("#quassel-test") { + setTopic("Quassel testing channel") + addChannelMode('n') + addChannelMode('t') + addChannelMode('c') + + joinIrcUser(justJanne) + joinIrcUser(digitalcircuit) + joinIrcUser(Sput) + } + } + ) +} diff --git a/lib/src/test/java/de/kuschku/libquassel/util/TestSession.kt b/lib/src/test/java/de/kuschku/libquassel/util/TestSession.kt new file mode 100644 index 000000000..0c35beca8 --- /dev/null +++ b/lib/src/test/java/de/kuschku/libquassel/util/TestSession.kt @@ -0,0 +1,260 @@ +/* + * Quasseldroid - Quassel client for Android + * + * Copyright (c) 2019 Janne Koschinski + * Copyright (c) 2019 The Quassel Project + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.libquassel.util + +import de.kuschku.libquassel.connection.ConnectionState +import de.kuschku.libquassel.connection.Features +import de.kuschku.libquassel.protocol.IdentityId +import de.kuschku.libquassel.protocol.NetworkId +import de.kuschku.libquassel.protocol.QVariantList +import de.kuschku.libquassel.protocol.QVariantMap +import de.kuschku.libquassel.protocol.message.HandshakeMessage +import de.kuschku.libquassel.protocol.message.SignalProxyMessage +import de.kuschku.libquassel.quassel.syncables.* +import de.kuschku.libquassel.quassel.syncables.interfaces.ISyncableObject +import de.kuschku.libquassel.session.Error +import de.kuschku.libquassel.session.ISession +import de.kuschku.libquassel.session.ObjectStorage +import de.kuschku.libquassel.session.ProtocolHandler +import io.reactivex.Observable +import io.reactivex.subjects.BehaviorSubject +import io.reactivex.subjects.PublishSubject +import org.junit.Assert.assertTrue +import javax.net.ssl.SSLSession + +class TestSession : ProtocolHandler({ throw it }), ISession { + private val submissionCallbacks = mutableListOf<SubmissionCallback>() + + interface SubmissionCallback { + fun callSubmitted(message: SignalProxyMessage) + } + + class EnsuranceEnvironment(submittedCalls: List<SignalProxyMessage>) { + private val sync = submittedCalls.mapNotNull { it as? SignalProxyMessage.SyncMessage } + private val rpc = submittedCalls.mapNotNull { it as? SignalProxyMessage.RpcCall } + private val initRequest = submittedCalls.mapNotNull { it as? SignalProxyMessage.InitRequest } + private val initData = submittedCalls.mapNotNull { it as? SignalProxyMessage.InitData } + private val heartbeat = submittedCalls.mapNotNull { it as? SignalProxyMessage.HeartBeat } + private val heartbeatReply = submittedCalls.mapNotNull { it as? SignalProxyMessage.HeartBeatReply } + + fun callSync(target: ISyncableObject, slotName: String, params: QVariantList?) { + val matchingTargetTypes = sync.filter { + it.className == target.className + } + assertTrue( + "SYNC No calls were made on objects of type ${target.className}", + matchingTargetTypes.isNotEmpty() + ) + val matchingTargets = matchingTargetTypes.filter { + it.objectName == target.objectName + } + assertTrue( + "SYNC No calls were made on ${target.className}:${target.objectName}", + matchingTargetTypes.isNotEmpty() + ) + + val matchingNames = matchingTargets.filter { + it.slotName == slotName + } + assertTrue( + "SYNC ${target.className}:${target.objectName}:$slotName() was never called", + matchingNames.isNotEmpty() + ) + if (!params.isNullOrEmpty()) { + val calledParams = matchingNames.map(SignalProxyMessage.SyncMessage::params) + assertTrue( + "SYNC ${target.className}:${target.objectName}:$slotName was called with the wrong parameters:\nExpected:\n $params\nActual:\n ${calledParams.joinToString("\n ")}", + calledParams.contains(params) + ) + } + } + + fun callRpc(slotName: String, params: QVariantList?) { + val matchingNames = rpc.filter { + it.slotName == slotName + } + assertTrue( + "RPC $slotName() was not called", + matchingNames.isNotEmpty() + ) + if (!params.isNullOrEmpty()) { + val calledParams = matchingNames.map(SignalProxyMessage.RpcCall::params) + assertTrue( + "RPC $slotName was called with the wrong parameters:\nExpected:\n $params\nActual:\n ${calledParams.joinToString("\n ")}", + calledParams.contains(params) + ) + } + } + } + + class TestEnvironment(private val session: TestSession) : + SubmissionCallback { + private val submittedCalls = mutableListOf<SignalProxyMessage>() + + fun run(f: ISession.() -> Unit) : TestEnvironment { + session.submissionCallbacks.add(this) + f.invoke(session) + session.submissionCallbacks.remove(this) + return this + } + + fun does(f: EnsuranceEnvironment.() -> Unit) { + f.invoke(EnsuranceEnvironment(submittedCalls)) + } + + override fun callSubmitted(message: SignalProxyMessage) { + submittedCalls.add(message) + } + } + + fun ensure(f: ISession.() -> Unit) = TestEnvironment(this).run(f) + + override val proxy = this + override val objectStorage = ObjectStorage(this) + + override val error: Observable<Error> = Observable.empty() + override val connectionError: Observable<Throwable> = Observable.empty() + + override val state = BehaviorSubject.createDefault(ConnectionState.CONNECTED) + override val features = Features.all() + override val sslSession = BehaviorSubject.createDefault(Optional.empty<SSLSession>()) + + override val aliasManager = AliasManager(proxy) + override val backlogManager = BacklogManager(this) + override val bufferViewManager = BufferViewManager(this) + override val bufferSyncer = BufferSyncer(this) + override val certManagers = mutableMapOf<IdentityId, CertManager>() + override val coreInfo = CoreInfo(this) + override val dccConfig = DccConfig(this) + + override val identities = mutableMapOf<IdentityId, Identity>() + private val live_identities = BehaviorSubject.createDefault(Unit) + override fun liveIdentities(): Observable<Map<IdentityId, Identity>> = live_identities.map { identities.toMap() } + override fun identity(id: IdentityId) = identities[id] + override fun addIdentity(initData: QVariantMap) { + val identity = Identity(this) + identity.fromVariantMap(initData) + identities[identity.id()] = identity + synchronize(identity) + live_identities.onNext(Unit) + } + + override fun removeIdentity(identityId: IdentityId) { + val identity = identities.remove(identityId) + stopSynchronize(identity) + live_identities.onNext(Unit) + } + + override val ignoreListManager = IgnoreListManager(this) + override val highlightRuleManager = HighlightRuleManager(this) + override val ircListHelper = IrcListHelper(this) + + override val networks = mutableMapOf<NetworkId, Network>() + private val live_networks = BehaviorSubject.createDefault(Unit) + override fun liveNetworks(): Observable<Map<NetworkId, Network>> = live_networks.map { networks.toMap() } + override fun network(id: NetworkId) = networks[id] + private val network_added = PublishSubject.create<NetworkId>() + override fun liveNetworkAdded(): Observable<NetworkId> = network_added + override fun addNetwork(networkId: NetworkId) { + val network = Network(networkId, this) + networks[networkId] = network + synchronize(network) + live_networks.onNext(Unit) + network_added.onNext(networkId) + } + + override fun removeNetwork(networkId: NetworkId) { + val network = networks.remove(networkId) + stopSynchronize(network) + live_networks.onNext(Unit) + } + + override val networkConfig = NetworkConfig(this) + + override val rpcHandler = RpcHandler(this) + + override val initStatus = BehaviorSubject.createDefault(0 to 0) + + override val lag = BehaviorSubject.createDefault(0L) + + data class TestData( + val session: TestSession, + var networks: List<Network> = emptyList(), + var identities: List<Identity> = emptyList() + ) { + fun buildNetwork(networkId: NetworkId, f: Network.() -> Unit): Network { + val network = Network(networkId, session.proxy) + f.invoke(network) + return network + } + + fun buildIdentity(f: Identity.() -> Unit): Identity { + val identity = Identity(session.proxy) + f.invoke(identity) + return identity + } + + fun Network.buildIrcChannel(name: String, f: IrcChannel.() -> Unit): IrcChannel { + val ircChannel = IrcChannel(name, this, session.proxy) + ircChannel.initialized = true + f.invoke(ircChannel) + newIrcChannel(name, ircChannel.toVariantMap()) + return ircChannel(name)!! + } + + fun Network.buildIrcUser(name: String, f: IrcUser.() -> Unit): IrcUser { + val ircUser = IrcUser(name, this, session.proxy) + ircUser.initialized = true + f.invoke(ircUser) + newIrcUser(name, ircUser.toVariantMap()) + return ircUser(name)!! + } + } + + fun provideTestData(f: TestData.() -> Unit): TestSession { + val data = TestData(this) + f.invoke(data) + for (network in data.networks) { + network.initialized = true + networks[network.networkId()] = network + } + for (identity in data.identities) { + identity.initialized = true + identities[identity.id()] = identity + } + return this + } + + override fun onInitDone() = Unit + override fun dispatch(message: HandshakeMessage) = Unit + override fun dispatch(message: SignalProxyMessage) { + for (submissionCallback in submissionCallbacks) { + submissionCallback.callSubmitted(message) + } + } + + override fun login(user: String, pass: String) = Unit + + override fun setupCore(setupData: HandshakeMessage.CoreSetupData) { + dispatch(setupData) + } + + override fun disconnectFromCore() {} +} diff --git a/lib/src/test/resources/naughty_strings.txt b/lib/src/test/resources/naughty_strings.txt new file mode 100644 index 000000000..26a67c62e --- /dev/null +++ b/lib/src/test/resources/naughty_strings.txt @@ -0,0 +1 @@ +βThis is very Interesting! πββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ" diff --git a/malheur/src/main/java/de/kuschku/malheur/collectors/Collector.kt b/malheur/src/main/java/de/kuschku/malheur/collectors/Collector.kt index c5725752b..b71347d88 100644 --- a/malheur/src/main/java/de/kuschku/malheur/collectors/Collector.kt +++ b/malheur/src/main/java/de/kuschku/malheur/collectors/Collector.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.malheur.collectors import de.kuschku.malheur.CrashContext diff --git a/malheur/src/main/java/de/kuschku/malheur/collectors/ConfigurationCollector.kt b/malheur/src/main/java/de/kuschku/malheur/collectors/ConfigurationCollector.kt index 0c3c20e17..b0c22147d 100644 --- a/malheur/src/main/java/de/kuschku/malheur/collectors/ConfigurationCollector.kt +++ b/malheur/src/main/java/de/kuschku/malheur/collectors/ConfigurationCollector.kt @@ -23,6 +23,7 @@ import android.app.Application import android.content.res.Configuration import android.util.SparseArray import de.kuschku.malheur.CrashContext +import java.lang.reflect.Field import java.lang.reflect.Modifier class ConfigurationCollector(private val application: Application) : @@ -85,10 +86,13 @@ class ConfigurationCollector(private val application: Application) : } } - override fun collect(context: CrashContext, config: Boolean) = configurationFields.map { - it to Configuration::class.java.getDeclaredField(it.fieldName) + override fun collect(context: CrashContext, config: Boolean) = configurationFields.mapNotNull { info -> + val field : Field? = Configuration::class.java.getDeclaredField(info.fieldName) + field?.let { + Pair(info, it) + } }.filter { (_, field) -> - field != null && !Modifier.isStatic(field.modifiers) + !Modifier.isStatic(field.modifiers) }.map { (info, field) -> val groupInfo = configValueInfo[info.enumPrefix] if (groupInfo != null) { diff --git a/persistence/build.gradle.kts b/persistence/build.gradle.kts index 4c04ee7c8..d2bb7239d 100644 --- a/persistence/build.gradle.kts +++ b/persistence/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + /* * Quasseldroid - Quassel client for Android * diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt index 1e5702931..777774a6e 100644 --- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt +++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselBacklogStorage.kt @@ -75,18 +75,18 @@ class QuasselBacklogStorage(private val db: QuasselDatabase) : BacklogStorage { val networkId = message.bufferInfo.networkId val networkName = session.network(networkId)?.networkName() ?: "" - return session.ignoreListManager?.match( + return session.ignoreListManager.match( message.content, message.sender, message.type, networkName, bufferName ) != IgnoreListManager.StrictnessType.UnmatchedStrictness } fun isIgnored(session: ISession, message: QuasselDatabase.MessageData): Boolean { - val bufferInfo = session.bufferSyncer?.bufferInfo(message.bufferId) + val bufferInfo = session.bufferSyncer.bufferInfo(message.bufferId) val bufferName = bufferInfo?.bufferName ?: "" val networkId = bufferInfo?.networkId ?: NetworkId(-1) val networkName = session.network(networkId)?.networkName() ?: "" - return session.ignoreListManager?.match( + return session.ignoreListManager.match( message.content, message.sender, message.type, networkName, bufferName ) != IgnoreListManager.StrictnessType.UnmatchedStrictness } diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt index 8c56bff6c..fbe433e5e 100644 --- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt +++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabase.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.quasseldroid.persistence import android.content.Context diff --git a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabaseHelpers.kt b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabaseHelpers.kt index 2e3434c0f..952d4e7fd 100644 --- a/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabaseHelpers.kt +++ b/persistence/src/main/java/de/kuschku/quasseldroid/persistence/QuasselDatabaseHelpers.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.quasseldroid.persistence import de.kuschku.libquassel.protocol.BufferId diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/LiveDataHelper.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/LiveDataHelper.kt index da9b90af2..ee55e7c1d 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/LiveDataHelper.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/LiveDataHelper.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.quasseldroid.util.helper import androidx.annotation.MainThread diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt index c0073c307..c28eab4ca 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/util/helper/ObservableHelper.kt @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ - +@file:Suppress("NOTHING_TO_INLINE") package de.kuschku.quasseldroid.util.helper import androidx.lifecycle.LiveData diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/EditorViewModel.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/EditorViewModel.kt index 52df1deb6..80464f9bc 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/EditorViewModel.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/EditorViewModel.kt @@ -65,8 +65,7 @@ class EditorViewModel : ViewModel() { if (bufferSyncer != null) { session.liveNetworks().switchMap { networks -> bufferSyncer.liveBufferInfos().switchMap { infos -> - (session.aliasManager?.updates()?.map(AliasManager::aliasList) - ?: Observable.just(emptyList())).switchMap { aliases -> + session.aliasManager.updates().map(AliasManager::aliasList).switchMap { aliases -> val network = networks[bufferInfo?.networkId] ?: Network.NULL val ircChannel = if (bufferInfo?.type?.hasFlag(Buffer_Type.ChannelBuffer) == true) { network.ircChannel(bufferInfo.bufferName) ?: IrcChannel.NULL diff --git a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt index d185a84da..c72c95560 100644 --- a/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt +++ b/viewmodel/src/main/java/de/kuschku/quasseldroid/viewmodel/QuasselViewModel.kt @@ -85,8 +85,8 @@ class QuasselViewModel : ViewModel() { val backend = backendWrapper.switchMap { it } val sessionManager = backend.mapMapNullable(Backend::sessionManager) val session = sessionManager.mapSwitchMap(SessionManager::session) - val rpcHandler = session.mapMapNullable(ISession::rpcHandler) - val ircListHelper = session.mapMapNullable(ISession::ircListHelper) + val rpcHandler = session.mapMap(ISession::rpcHandler) + val ircListHelper = session.mapMap(ISession::ircListHelper) val features = sessionManager.mapSwitchMap { manager -> manager.state.switchMap { state -> if (state != ConnectionState.CONNECTED) { @@ -111,7 +111,7 @@ class QuasselViewModel : ViewModel() { val connectionProgress = sessionManager.mapSwitchMap(SessionManager::connectionProgress) .mapOrElse(Triple(ConnectionState.DISCONNECTED, 0, 0)) - val bufferViewManager = session.mapMapNullable(ISession::bufferViewManager) + val bufferViewManager = session.mapMap(ISession::bufferViewManager) val bufferViewConfig = bufferViewManager.flatMapSwitchMap { manager -> bufferViewConfigId.map { id -> @@ -135,17 +135,17 @@ class QuasselViewModel : ViewModel() { }.mapOrElse(emptyList()) val leafCertificate = peerCertificateChain.map { Optional.ofNullable(it.firstOrNull()) } - val coreInfo = session.mapMapNullable(ISession::coreInfo).mapSwitchMap(CoreInfo::liveInfo) + val coreInfo = session.mapMap(ISession::coreInfo).mapSwitchMap(CoreInfo::liveInfo) val coreInfoClients = coreInfo.mapMap(CoreInfo.CoreData::sessionConnectedClientData) .mapOrElse(emptyList()) - val networkConfig = session.mapMapNullable(ISession::networkConfig) + val networkConfig = session.mapMap(ISession::networkConfig) - val ignoreListManager = session.mapMapNullable(ISession::ignoreListManager) + val ignoreListManager = session.mapMap(ISession::ignoreListManager) - val highlightRuleManager = session.mapMapNullable(ISession::highlightRuleManager) + val highlightRuleManager = session.mapMap(ISession::highlightRuleManager) - val aliasManager = session.mapMapNullable(ISession::aliasManager) + val aliasManager = session.mapMap(ISession::aliasManager) val networks = session.switchMap { it.map(ISession::liveNetworks).orElse(Observable.just(emptyMap())) @@ -155,7 +155,7 @@ class QuasselViewModel : ViewModel() { it.map(ISession::liveIdentities).orElse(Observable.just(emptyMap())) } - val bufferSyncer = session.mapMapNullable(ISession::bufferSyncer) + val bufferSyncer = session.mapMap(ISession::bufferSyncer) val allBuffers = bufferSyncer.mapSwitchMap { it.liveBufferInfos().map(Map<BufferId, BufferInfo>::values) }.mapOrElse(emptyList()) @@ -170,7 +170,7 @@ class QuasselViewModel : ViewModel() { val markerLine = session.mapSwitchMap { currentSession -> buffer.switchMap { currentBuffer -> // Get a stream of the latest marker line - currentSession.bufferSyncer?.liveMarkerLine(currentBuffer) ?: Observable.empty() + currentSession.bufferSyncer.liveMarkerLine(currentBuffer) } } -- GitLab