From 564dae4862cc9d0787161a8179051829a5961028 Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Fri, 16 Feb 2018 18:32:14 +0100 Subject: [PATCH] Improve code formatting --- app/build.gradle.kts | 2 - .../kuschku/quasseldroid_ng/QuasseldroidNG.kt | 10 - .../persistence/AccountDatabase.kt | 8 +- .../persistence/QuasselBacklogStorage.kt | 22 +- .../persistence/QuasselDatabase.kt | 27 +- .../quasseldroid_ng/service/QuasselService.kt | 22 +- .../ui/chat/BufferListAdapter.kt | 23 +- .../ui/chat/BufferViewConfigAdapter.kt | 6 +- .../ui/chat/BufferViewConfigFragment.kt | 16 +- .../quasseldroid_ng/ui/chat/ChatActivity.kt | 59 ++- .../ui/chat/FormattedMessage.kt | 7 + .../quasseldroid_ng/ui/chat/MessageAdapter.kt | 26 +- .../ui/chat/MessageListFragment.kt | 19 +- .../ui/chat/MessageRenderer.kt | 10 +- .../ui/chat/QuasselMessageRenderer.kt | 30 +- .../quasseldroid_ng/ui/setup/SetupActivity.kt | 6 +- .../ui/setup/accounts/AccountAdapter.kt | 3 +- .../ui/setup/accounts/AccountEditActivity.kt | 2 +- .../setup/accounts/AccountSelectionSlide.kt | 9 +- .../ui/setup/accounts/AccountViewModel.kt | 3 +- .../util/AndroidHandlerThread.kt | 6 +- .../AndroidCompatibilityUtils.kt | 6 +- .../compatibility/AndroidLoggingHandler.kt | 3 +- .../util/helper/ActivityHelper.kt | 3 +- .../util/helper/LiveDataHelper.kt | 12 +- .../util/quassel/IrcUserUtils.kt | 8 +- .../util/service/ServiceBoundActivity.kt | 4 +- .../util/ui/ContextThemeWrapper.kt | 5 +- .../util/ui/DrawerRecyclerView.kt | 31 +- .../ui/MaterialContentLoadingProgressBar.kt | 4 +- .../util/ui/NavigationDrawerLayout.kt | 31 +- .../util/ui/SpanFormatter.java | 158 ++++---- app/src/main/res/layout/activity_main.xml | 284 +++++++------- app/src/main/res/layout/fragment_messages.xml | 48 +-- .../res/layout/widget_chatmessage_action.xml | 58 +-- .../res/layout/widget_chatmessage_error.xml | 60 +-- .../res/layout/widget_chatmessage_plain.xml | 62 +-- .../res/layout/widget_chatmessage_server.xml | 60 +-- .../res/mipmap-hdpi/ic_launcher_recents.png | Bin 0 -> 4120 bytes .../res/mipmap-mdpi/ic_launcher_recents.png | Bin 0 -> 2793 bytes .../res/mipmap-xhdpi/ic_launcher_recents.png | Bin 0 -> 6175 bytes .../res/mipmap-xxhdpi/ic_launcher_recents.png | Bin 0 -> 11789 bytes .../mipmap-xxxhdpi/ic_launcher_recents.png | Bin 0 -> 18337 bytes app/src/main/res/values/dimens.xml | 6 +- app/src/main/res/values/strings.xml | 4 +- app/src/main/res/values/themes_quassel.xml | 136 +++---- .../kuschku/libquassel/annotations/Slot.java | 2 +- .../libquassel/annotations/Syncable.java | 2 +- .../annotations/InvokerProcessor.java | 370 +++++++++--------- .../kuschku/libquassel/protocol/MetaType.kt | 6 +- .../message/CoreSetupDataSerializer.kt | 18 +- .../protocol/message/RequestType.kt | 3 +- .../protocol/message/SessionInitSerializer.kt | 12 +- .../primitive/serializer/BoolSerializer.kt | 12 +- .../serializer/DateTimeSerializer.kt | 3 +- .../serializer/HostAddressSerializer.kt | 6 +- .../primitive/serializer/MessageSerializer.kt | 3 +- .../serializer/VariantMapSerializer.kt | 14 +- .../quassel/syncables/AliasManager.kt | 15 +- .../quassel/syncables/BacklogManager.kt | 7 +- .../quassel/syncables/BufferViewConfig.kt | 3 +- .../libquassel/quassel/syncables/Identity.kt | 6 +- .../quassel/syncables/IrcChannel.kt | 32 +- .../libquassel/quassel/syncables/IrcUser.kt | 5 +- .../libquassel/quassel/syncables/Network.kt | 55 ++- .../quassel/syncables/RpcHandler.kt | 6 +- .../syncables/interfaces/IBacklogManager.kt | 12 +- .../syncables/interfaces/IBufferSyncer.kt | 6 +- .../interfaces/IIgnoreListManager.kt | 10 +- .../syncables/interfaces/IIrcListHelper.kt | 6 +- .../quassel/syncables/interfaces/INetwork.kt | 12 +- .../syncables/interfaces/IRpcHandler.kt | 2 - .../syncables/interfaces/invokers/Invokers.kt | 12 +- .../libquassel/session/CoreConnection.kt | 31 +- .../libquassel/session/ObjectStorage.kt | 9 +- .../libquassel/session/ProtocolHandler.kt | 4 +- .../de/kuschku/libquassel/session/Session.kt | 10 +- .../libquassel/session/SessionManager.kt | 11 +- .../java/de/kuschku/libquassel/util/Flag.kt | 6 +- .../de/kuschku/libquassel/util/LongFlag.kt | 12 +- .../de/kuschku/libquassel/util/ShortFlag.kt | 12 +- .../reference/JavaLoggingHandler.kt | 6 +- .../libquassel/util/helpers/ArrayHelper.kt | 9 +- .../libquassel/util/nio/WrappedChannel.kt | 11 +- .../kuschku/libquassel/ConnectionUnitTest.kt | 18 +- .../kuschku/libquassel/SerializerUnitTest.kt | 15 +- malheur/build.gradle.kts | 2 +- .../java/de/kuschku/malheur/CrashHandler.kt | 24 +- .../malheur/collectors/DisplayCollector.kt | 3 +- .../malheur/collectors/EnvCollector.kt | 3 +- 90 files changed, 1172 insertions(+), 953 deletions(-) create mode 100644 app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/FormattedMessage.kt create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_recents.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_recents.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_recents.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_recents.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_recents.png diff --git a/app/build.gradle.kts b/app/build.gradle.kts index be54154de..753d81c0c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -127,8 +127,6 @@ dependencies { } implementation(project(":malheur")) - debugImplementation("com.squareup.leakcanary", "leakcanary-android", "1.5.1") - testImplementation(appArch("persistence.room", "testing")) testImplementation("junit", "junit", "4.12") diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/QuasseldroidNG.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/QuasseldroidNG.kt index bb0a3058a..16c3177cf 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/QuasseldroidNG.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/QuasseldroidNG.kt @@ -14,16 +14,6 @@ import de.kuschku.quasseldroid_ng.util.helper.systemService class QuasseldroidNG : Application() { override fun onCreate() { - /* - // We do not need LeakCanary in RELEASE builds - if (LeakCanary.isInAnalyzerProcess(this)) { - // This process is dedicated to LeakCanary for heap analysis. - // You should not init your app in this process. - return - } - LeakCanary.install(this) - */ - CrashHandler.init( application = this, buildConfig = BuildConfig::class.java diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/AccountDatabase.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/AccountDatabase.kt index d17a86787..d5429e045 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/AccountDatabase.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/AccountDatabase.kt @@ -4,7 +4,7 @@ import android.arch.paging.LivePagedListProvider import android.arch.persistence.room.* import android.content.Context -@Database(entities = arrayOf(AccountDatabase.Account::class), version = 1) +@Database(entities = [(AccountDatabase.Account::class)], version = 1) abstract class AccountDatabase : RoomDatabase() { abstract fun accounts(): AccountDao @@ -52,8 +52,10 @@ abstract class AccountDatabase : RoomDatabase() { if (database == null) { synchronized(LOCK) { if (database == null) { - database = Room.databaseBuilder(context.applicationContext, - AccountDatabase::class.java, DATABASE_NAME) + database = Room.databaseBuilder( + context.applicationContext, + AccountDatabase::class.java, DATABASE_NAME + ) .build() } } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselBacklogStorage.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselBacklogStorage.kt index b05e47731..dd8b2b764 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselBacklogStorage.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselBacklogStorage.kt @@ -21,16 +21,18 @@ class QuasselBacklogStorage(private val db: QuasselDatabase) : BacklogStorage { } for (message in messages) { - db.message().save(QuasselDatabase.DatabaseMessage( - messageId = message.messageId, - time = message.time, - type = message.type.value, - flag = message.flag.value, - bufferId = message.bufferInfo.bufferId, - sender = message.sender, - senderPrefixes = message.senderPrefixes, - content = message.content - )) + db.message().save( + QuasselDatabase.DatabaseMessage( + messageId = message.messageId, + time = message.time, + type = message.type.value, + flag = message.flag.value, + bufferId = message.bufferInfo.bufferId, + sender = message.sender, + senderPrefixes = message.senderPrefixes, + content = message.content + ) + ) } } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselDatabase.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselDatabase.kt index 723a937a9..714246e92 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselDatabase.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/persistence/QuasselDatabase.kt @@ -9,7 +9,7 @@ import de.kuschku.libquassel.protocol.Message_Flag import de.kuschku.libquassel.protocol.Message_Type import org.threeten.bp.Instant -@Database(entities = arrayOf(QuasselDatabase.DatabaseMessage::class), version = 2) +@Database(entities = [(QuasselDatabase.DatabaseMessage::class)], version = 2) @TypeConverters(QuasselDatabase.DatabaseMessage.MessageTypeConverters::class) abstract class QuasselDatabase : RoomDatabase() { abstract fun message(): MessageDao @@ -35,15 +35,19 @@ abstract class QuasselDatabase : RoomDatabase() { override fun toString(): String { return "Message(messageId=$messageId, time=$time, type=${Message_Type.of( - type)}, flag=${Message_Flag.of( - flag)}, bufferId=$bufferId, sender='$sender', senderPrefixes='$senderPrefixes', content='$content')" + type + )}, flag=${Message_Flag.of( + flag + )}, bufferId=$bufferId, sender='$sender', senderPrefixes='$senderPrefixes', content='$content')" } object MessageDiffCallback : DiffCallback<DatabaseMessage>() { - override fun areContentsTheSame(oldItem: QuasselDatabase.DatabaseMessage, newItem: QuasselDatabase.DatabaseMessage) + override fun areContentsTheSame(oldItem: QuasselDatabase.DatabaseMessage, + newItem: QuasselDatabase.DatabaseMessage) = oldItem == newItem - override fun areItemsTheSame(oldItem: QuasselDatabase.DatabaseMessage, newItem: QuasselDatabase.DatabaseMessage) + override fun areItemsTheSame(oldItem: QuasselDatabase.DatabaseMessage, + newItem: QuasselDatabase.DatabaseMessage) = oldItem.messageId == newItem.messageId } } @@ -80,7 +84,9 @@ abstract class QuasselDatabase : RoomDatabase() { @Query("DELETE FROM message WHERE bufferId = :bufferId") fun clearMessages(@IntRange(from = 0) bufferId: Int) - @Query("DELETE FROM message WHERE bufferId = :bufferId AND messageId >= :first AND messageId <= :last") + @Query( + "DELETE FROM message WHERE bufferId = :bufferId AND messageId >= :first AND messageId <= :last" + ) fun clearMessages(@IntRange(from = 0) bufferId: Int, first: Int, last: Int) } @@ -94,8 +100,10 @@ abstract class QuasselDatabase : RoomDatabase() { if (database == null) { synchronized(LOCK) { if (database == null) { - database = Room.databaseBuilder(context.applicationContext, - QuasselDatabase::class.java, DATABASE_NAME) + database = Room.databaseBuilder( + context.applicationContext, + QuasselDatabase::class.java, DATABASE_NAME + ) .build() } } @@ -109,6 +117,7 @@ abstract class QuasselDatabase : RoomDatabase() { } } -fun QuasselDatabase.MessageDao.clearMessages(@IntRange(from = 0) bufferId: Int, idRange: kotlin.ranges.IntRange) { +fun QuasselDatabase.MessageDao.clearMessages(@IntRange(from = 0) + bufferId: Int, idRange: kotlin.ranges.IntRange) { this.clearMessages(bufferId, idRange.first, idRange.last) } \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt index 7ef65d2cc..a3c6e5fca 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt @@ -1,5 +1,6 @@ package de.kuschku.quasseldroid_ng.service +import android.annotation.SuppressLint import android.arch.lifecycle.LifecycleService import android.arch.lifecycle.Observer import android.content.Intent @@ -24,12 +25,11 @@ class QuasselService : LifecycleService() { private lateinit var clientData: ClientData private val trustManager = object : X509TrustManager { - override fun checkClientTrusted(p0: Array<out X509Certificate>?, p1: String?) { - } - - override fun checkServerTrusted(p0: Array<out X509Certificate>?, p1: String?) { - } + @SuppressLint("TrustAllX509TrustManager") + override fun checkClientTrusted(p0: Array<out X509Certificate>?, p1: String?) = Unit + @SuppressLint("TrustAllX509TrustManager") + override fun checkServerTrusted(p0: Array<out X509Certificate>?, p1: String?) = Unit override fun getAcceptedIssuers(): Array<X509Certificate> = emptyArray() } @@ -45,8 +45,10 @@ class QuasselService : LifecycleService() { override fun connect(address: SocketAddress, user: String, pass: String, reconnect: Boolean) { disconnect() - sessionManager.connect(clientData, trustManager, address, ::AndroidHandlerService, - user to pass, reconnect) + sessionManager.connect( + clientData, trustManager, address, ::AndroidHandlerService, + user to pass, reconnect + ) } override fun reconnect() { @@ -118,9 +120,11 @@ class QuasselService : LifecycleService() { .delay(200, TimeUnit.MILLISECONDS) .throttleFirst(1, TimeUnit.SECONDS) .toLiveData() - .observe(this, Observer { + .observe( + this, Observer { sessionManager.reconnect() - }) + } + ) } override fun onBind(intent: Intent?): QuasselBinder { diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferListAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferListAdapter.kt index 4eec89285..499ff06f5 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferListAdapter.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferListAdapter.kt @@ -25,7 +25,8 @@ class BufferListAdapter( var data = mutableListOf<BufferInfo>() init { - liveData.observe(lifecycleOwner, Observer { list: List<BufferInfo>? -> + liveData.observe( + lifecycleOwner, Observer { list: List<BufferInfo>? -> runInBackground { val old = data val new = list?.sortedBy(BufferInfo::networkId) ?: emptyList() @@ -39,14 +40,18 @@ class BufferListAdapter( override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = old[oldItemPosition] == new[newItemPosition] - }, true) - runOnUiThread(Runnable { - data.clear() - data.addAll(new) - result.dispatchUpdatesTo(this@BufferListAdapter) - }) + }, true + ) + runOnUiThread( + Runnable { + data.clear() + data.addAll(new) + result.dispatchUpdatesTo(this@BufferListAdapter) + } + ) } - }) + } + ) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = BufferViewHolder( @@ -80,7 +85,7 @@ class BufferListAdapter( fun bind(info: BufferInfo) { text.text = when { info.type.hasFlag(BufferInfo.Type.StatusBuffer) -> "Network ${info.networkId}" - else -> "${info.networkId}/${info.bufferName}" + else -> "${info.networkId}/${info.bufferName}" } bufferId = info.bufferId } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigAdapter.kt index 007573f62..afadc9b6d 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigAdapter.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigAdapter.kt @@ -24,13 +24,15 @@ class BufferViewConfigAdapter( val data = mutableListOf<BufferViewConfig>() init { - liveData.observe(lifecycleOwner, Observer { list: List<BufferViewConfig>? -> + liveData.observe( + lifecycleOwner, Observer { list: List<BufferViewConfig>? -> data.clear() if (list != null) { data.addAll(list) } notifyDataSetChanged() - }) + } + ) } override fun isEmpty() = data.isEmpty() diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigFragment.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigFragment.kt index 2babd2c93..af325bf39 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigFragment.kt @@ -50,9 +50,11 @@ class BufferViewConfigFragment : ServiceBoundFragment() { manager.live_bufferViewConfigs.map { ids -> ids.mapNotNull { id -> manager.bufferViewConfig(id) - }.sortedWith(Comparator { a, b -> - (a?.bufferViewName() ?: "").compareTo((b?.bufferViewName() ?: ""), true) - }) + }.sortedWith( + Comparator { a, b -> + (a?.bufferViewName() ?: "").compareTo((b?.bufferViewName() ?: ""), true) + } + ) } }.or(emptyList()) @@ -92,7 +94,13 @@ class BufferViewConfigFragment : ServiceBoundFragment() { chatListSpinner.adapter = adapter chatListSpinner.onItemSelectedListener = itemSelectedListener - chatList.adapter = BufferListAdapter(this, bufferList, handlerThread::post, activity!!::runOnUiThread, clickListener) + chatList.adapter = BufferListAdapter( + this, + bufferList, + handlerThread::post, + activity!!::runOnUiThread, + clickListener + ) chatList.layoutManager = LinearLayoutManager(context) chatList.itemAnimator = DefaultItemAnimator() return view diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt index 589ec88eb..679b94aa2 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt @@ -32,8 +32,8 @@ import de.kuschku.quasseldroid_ng.util.service.ServiceBoundActivity import de.kuschku.quasseldroid_ng.util.ui.MaterialContentLoadingProgressBar class ChatActivity : ServiceBoundActivity() { - var contentMessages: MessageListFragment? = null - var chatListFragment: BufferViewConfigFragment? = null + private var contentMessages: MessageListFragment? = null + private var chatListFragment: BufferViewConfigFragment? = null @BindView(R.id.drawerLayout) lateinit var drawerLayout: DrawerLayout @@ -72,8 +72,12 @@ class ChatActivity : ServiceBoundActivity() { database = QuasselDatabase.Creator.init(application) - contentMessages = supportFragmentManager.findFragmentById(R.id.contentMessages) as? MessageListFragment - chatListFragment = supportFragmentManager.findFragmentById(R.id.chatListFragment) as? BufferViewConfigFragment + contentMessages = supportFragmentManager.findFragmentById( + R.id.contentMessages + ) as? MessageListFragment + chatListFragment = supportFragmentManager.findFragmentById( + R.id.chatListFragment + ) as? BufferViewConfigFragment setSupportActionBar(toolbar) @@ -85,21 +89,29 @@ class ChatActivity : ServiceBoundActivity() { println("Changed buffer to $it") } - currentBuffer.observe(this, Observer { + currentBuffer.observe( + this, Observer { if (it != null) { drawerLayout.closeDrawer(Gravity.START, true) } - }) - - drawerToggle = ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close) + } + ) + + drawerToggle = ActionBarDrawerToggle( + this, + drawerLayout, + R.string.drawer_open, + R.string.drawer_close + ) drawerToggle.syncState() - backend.observeSticky(this, Observer { backendValue -> + backend.observeSticky( + this, Observer { backendValue -> if (backendValue != null) { val database = AccountDatabase.Creator.init(this) handler.post { val accountId = getSharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE) - ?.getLong(Keys.Status.selectedAccount, -1) ?: -1 + ?.getLong(Keys.Status.selectedAccount, -1) ?: -1 if (accountId == -1L) { setResult(Activity.RESULT_OK) finish() @@ -118,7 +130,8 @@ class ChatActivity : ServiceBoundActivity() { } } } - }) + } + ) buttonSend.setOnClickListener { sessionManager { sessionManager -> @@ -131,7 +144,8 @@ class ChatActivity : ServiceBoundActivity() { input.text.clear() } - state.observe(this, Observer { + state.observe( + this, Observer { val status = it ?: ConnectionState.DISCONNECTED if (status == ConnectionState.CONNECTED) { @@ -141,19 +155,28 @@ class ChatActivity : ServiceBoundActivity() { progressBar.isIndeterminate = status != ConnectionState.INIT } - progressBar.toggle(status != ConnectionState.CONNECTED && status != ConnectionState.DISCONNECTED) + progressBar.toggle( + status != ConnectionState.CONNECTED && status != ConnectionState.DISCONNECTED + ) snackbar?.dismiss() - snackbar = Snackbar.make(findViewById(R.id.contentMessages), status.name, Snackbar.LENGTH_SHORT) + snackbar = Snackbar.make( + findViewById(R.id.contentMessages), + status.name, + Snackbar.LENGTH_SHORT + ) snackbar?.show() - }) + } + ) - initStatus.observe(this, Observer { + initStatus.observe( + this, Observer { val (progress, max) = it ?: 0 to 0 progressBar.max = max progressBar.progress = progress - }) + } + ) } override fun onCreateOptionsMenu(menu: Menu?): Boolean { @@ -173,7 +196,7 @@ class ChatActivity : ServiceBoundActivity() { } true } - else -> super.onOptionsItemSelected(item) + else -> super.onOptionsItemSelected(item) } override fun onDestroy() { diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/FormattedMessage.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/FormattedMessage.kt new file mode 100644 index 000000000..d245270de --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/FormattedMessage.kt @@ -0,0 +1,7 @@ +package de.kuschku.quasseldroid_ng.ui.chat + +class FormattedMessage( + val id: Int, + val time: CharSequence, + val content: CharSequence +) \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageAdapter.kt index 3cdfd1a86..28720cc90 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageAdapter.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageAdapter.kt @@ -13,7 +13,10 @@ import de.kuschku.libquassel.util.hasFlag import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase import de.kuschku.quasseldroid_ng.util.helper.getOrPut -class MessageAdapter(context: Context) : PagedListAdapter<QuasselDatabase.DatabaseMessage, QuasselMessageViewHolder>(QuasselDatabase.DatabaseMessage.MessageDiffCallback) { +class MessageAdapter(context: Context) : + PagedListAdapter<QuasselDatabase.DatabaseMessage, QuasselMessageViewHolder>( + QuasselDatabase.DatabaseMessage.MessageDiffCallback + ) { private val messageRenderer: MessageRenderer = QuasselMessageRenderer(context) private val messageCache = LruCache<Int, FormattedMessage>(512) @@ -23,7 +26,14 @@ class MessageAdapter(context: Context) : PagedListAdapter<QuasselDatabase.Databa } override fun onBindViewHolder(holder: QuasselMessageViewHolder, position: Int) { - getItem(position)?.let { messageRenderer.bind(holder, messageCache.getOrPut(it.messageId) { messageRenderer.render(it) }) } + getItem(position)?.let { + messageRenderer.bind( + holder, + messageCache.getOrPut(it.messageId) { + messageRenderer.render(it) + } + ) + } } override fun getItemViewType(position: Int): Int { @@ -52,11 +62,13 @@ class MessageAdapter(context: Context) : PagedListAdapter<QuasselDatabase.Databa override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuasselMessageViewHolder { val messageType = messageType(viewType) val hasHighlight = hasHiglight(viewType) - val viewHolder = QuasselMessageViewHolder(LayoutInflater.from(parent.context).inflate( - messageRenderer.layout(messageType, hasHighlight), - parent, - false - )) + val viewHolder = QuasselMessageViewHolder( + LayoutInflater.from(parent.context).inflate( + messageRenderer.layout(messageType, hasHighlight), + parent, + false + ) + ) messageRenderer.init(viewHolder, messageType, hasHighlight) return viewHolder } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageListFragment.kt index cccda2cf3..1e67bdae3 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageListFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageListFragment.kt @@ -47,13 +47,16 @@ class MessageListFragment : ServiceBoundFragment() { setHasOptionsMenu(true) } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView(inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?): View? { val view = inflater.inflate(R.layout.fragment_messages, container, false) ButterKnife.bind(this, view) database = QuasselDatabase.Creator.init(context!!.applicationContext) val data = buffer.switchMap { - database.message().findByBufferIdPaged(it).create(Int.MAX_VALUE, + database.message().findByBufferIdPaged(it).create( + Int.MAX_VALUE, PagedList.Config.Builder() .setPageSize(50) .setEnablePlaceholders(false) @@ -64,18 +67,22 @@ class MessageListFragment : ServiceBoundFragment() { val adapter = MessageAdapter(context!!) - data.observe(this, Observer { list -> + data.observe( + this, Observer { list -> adapter.setList(list) - }) + } + ) - buffer.observe(this, Observer { + buffer.observe( + this, Observer { handler.post { // Try loading messages when switching to empty buffer if (it != null && database.message().bufferSize(it) == 0) { loadMore() } } - }) + } + ) var recyclerViewMeasuredHeight = 0 val scrollDownListener = object : RecyclerView.OnScrollListener() { diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageRenderer.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageRenderer.kt index c351e2273..99403809e 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageRenderer.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MessageRenderer.kt @@ -10,11 +10,9 @@ interface MessageRenderer { fun bind(holder: QuasselMessageViewHolder, message: FormattedMessage) fun render(message: QuasselDatabase.DatabaseMessage): FormattedMessage - fun init(viewHolder: QuasselMessageViewHolder, messageType: Message_Type?, hasHighlight: Boolean) {} + fun init(viewHolder: QuasselMessageViewHolder, + messageType: Message_Type?, + hasHighlight: Boolean) { + } } -class FormattedMessage( - val id: Int, - val time: CharSequence, - val content: CharSequence -) \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/QuasselMessageRenderer.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/QuasselMessageRenderer.kt index fe5ed6e93..2591661c6 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/QuasselMessageRenderer.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/QuasselMessageRenderer.kt @@ -17,18 +17,22 @@ import org.threeten.bp.format.DateTimeFormatter import java.text.SimpleDateFormat class QuasselMessageRenderer(context: Context) : MessageRenderer { - private val timeFormatter = DateTimeFormatter.ofPattern((DateFormat.getTimeFormat(context) as SimpleDateFormat).toLocalizedPattern()) + private val timeFormatter = DateTimeFormatter.ofPattern( + (DateFormat.getTimeFormat(context) as SimpleDateFormat).toLocalizedPattern() + ) private val senderColors: IntArray private val zoneId = ZoneId.systemDefault() init { - val typedArray = context.obtainStyledAttributes(intArrayOf( - R.attr.senderColor0, R.attr.senderColor1, R.attr.senderColor2, R.attr.senderColor3, - R.attr.senderColor4, R.attr.senderColor5, R.attr.senderColor6, R.attr.senderColor7, - R.attr.senderColor8, R.attr.senderColor9, R.attr.senderColorA, R.attr.senderColorB, - R.attr.senderColorC, R.attr.senderColorD, R.attr.senderColorE, R.attr.senderColorF - )) + val typedArray = context.obtainStyledAttributes( + intArrayOf( + R.attr.senderColor0, R.attr.senderColor1, R.attr.senderColor2, R.attr.senderColor3, + R.attr.senderColor4, R.attr.senderColor5, R.attr.senderColor6, R.attr.senderColor7, + R.attr.senderColor8, R.attr.senderColor9, R.attr.senderColorA, R.attr.senderColorB, + R.attr.senderColorC, R.attr.senderColorD, R.attr.senderColorE, R.attr.senderColorF + ) + ) senderColors = IntArray(16) { typedArray.getColor(it, 0) } @@ -39,13 +43,15 @@ class QuasselMessageRenderer(context: Context) : MessageRenderer { = when (type) { Nick, Notice, Mode, Join, Part, Quit, Kick, Kill, Server, Info, DayChange, Topic, NetsplitJoin, NetsplitQuit, Invite -> R.layout.widget_chatmessage_server - Error -> R.layout.widget_chatmessage_error - Action -> R.layout.widget_chatmessage_action - Plain -> R.layout.widget_chatmessage_plain - else -> R.layout.widget_chatmessage_plain + Error -> R.layout.widget_chatmessage_error + Action -> R.layout.widget_chatmessage_action + Plain -> R.layout.widget_chatmessage_plain + else -> R.layout.widget_chatmessage_plain } - override fun init(viewHolder: QuasselMessageViewHolder, messageType: Message_Type?, hasHighlight: Boolean) { + override fun init(viewHolder: QuasselMessageViewHolder, + messageType: Message_Type?, + hasHighlight: Boolean) { if (hasHighlight) { val attrs = intArrayOf(R.attr.colorBackgroundHighlight) val colors = viewHolder.itemView.context.obtainStyledAttributes(attrs) diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/SetupActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/SetupActivity.kt index 9a943d1eb..d93c2da7d 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/SetupActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/SetupActivity.kt @@ -86,7 +86,8 @@ abstract class SetupActivity : AppCompatActivity() { else viewPager.setCurrentItem(viewPager.currentItem + 1, true) } - isValid.observeSticky(this, Observer { + isValid.observeSticky( + this, Observer { if (it == true) { button.show() adapter.lastValidItem = viewPager.currentItem @@ -94,7 +95,8 @@ abstract class SetupActivity : AppCompatActivity() { button.hide() adapter.lastValidItem = viewPager.currentItem - 1 } - }) + } + ) viewPager.addOnPageChangeListener(pageChangeListener) pageChanged() updateRecentsHeader() diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountAdapter.kt index 8e48236f1..542ce9a8a 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountAdapter.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountAdapter.kt @@ -108,7 +108,8 @@ class AccountAdapter : when (viewType) { TYPE_ADD -> R.layout.widget_core_account_add else -> R.layout.widget_core_account - }, parent, false) + }, parent, false + ) return when (viewType) { TYPE_ADD -> AccountViewHolder.Add(view, addListener) else -> AccountViewHolder.Item(view, actionListener, clickListener) diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountEditActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountEditActivity.kt index 43cfa75c7..43880debd 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountEditActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountEditActivity.kt @@ -124,7 +124,7 @@ class AccountEditActivity : AppCompatActivity() { private val isValid get() = nameValidator.isValid && hostValidator.isValid && portValidator.isValid - && userValidator.isValid + && userValidator.isValid override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.setup_edit_account, menu) diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountSelectionSlide.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountSelectionSlide.kt index 86b305133..78b14161a 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountSelectionSlide.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountSelectionSlide.kt @@ -44,12 +44,15 @@ class AccountSelectionSlide : SlideFragment() { val view = inflater.inflate(R.layout.setup_select_account, container, false) ButterKnife.bind(this, view) val accountViewModel = ViewModelProviders.of(this).get( - AccountViewModel::class.java) + AccountViewModel::class.java + ) val firstObserver = object : Observer<PagedList<AccountDatabase.Account>?> { override fun onChanged(t: PagedList<AccountDatabase.Account>?) { if (t?.isEmpty() != false) - startActivityForResult(Intent(context, AccountSetupActivity::class.java), - REQUEST_CREATE_FIRST) + startActivityForResult( + Intent(context, AccountSetupActivity::class.java), + REQUEST_CREATE_FIRST + ) accountViewModel.accounts.removeObserver(this) } } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountViewModel.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountViewModel.kt index 8804e9805..cf2aca05e 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountViewModel.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/accounts/AccountViewModel.kt @@ -8,7 +8,8 @@ import de.kuschku.quasseldroid_ng.persistence.AccountDatabase class AccountViewModel(application: Application) : AndroidViewModel(application) { private val database: AccountDatabase = AccountDatabase.Creator.init( - getApplication()) + getApplication() + ) val accounts: LiveData<PagedList<AccountDatabase.Account>> = database.accounts().all().create( 0, PagedList.Config.Builder() diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/AndroidHandlerThread.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/AndroidHandlerThread.kt index 447111622..3af062e48 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/AndroidHandlerThread.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/AndroidHandlerThread.kt @@ -94,11 +94,13 @@ class AndroidHandlerThread(name: String) : HandlerThread(name) { fun sendEmptyMessageDelayed(what: Int, delayMillis: Long): Boolean = handler?.sendEmptyMessageDelayed(what, delayMillis) ?: throw RuntimeException( - "Thread not started") + "Thread not started" + ) fun sendEmptyMessageAtTime(what: Int, uptimeMillis: Long): Boolean = handler?.sendEmptyMessageAtTime(what, uptimeMillis) ?: throw RuntimeException( - "Thread not started") + "Thread not started" + ) fun sendMessageDelayed(msg: Message, delayMillis: Long): Boolean = handler?.sendMessageDelayed(msg, delayMillis) ?: throw RuntimeException("Thread not started") diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidCompatibilityUtils.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidCompatibilityUtils.kt index 15ab06a45..dcd0ac3f3 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidCompatibilityUtils.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidCompatibilityUtils.kt @@ -23,8 +23,8 @@ object AndroidCompatibilityUtils { private fun isChromeBook(): Boolean { return Build.MANUFACTURER.toLowerCase(Locale.ENGLISH).contains("chromium") || - Build.MANUFACTURER.toLowerCase(Locale.ENGLISH).contains("chrome") || - Build.BRAND.toLowerCase(Locale.ENGLISH).contains("chromium") || - Build.BRAND.toLowerCase(Locale.ENGLISH).contains("chrome") + Build.MANUFACTURER.toLowerCase(Locale.ENGLISH).contains("chrome") || + Build.BRAND.toLowerCase(Locale.ENGLISH).contains("chromium") || + Build.BRAND.toLowerCase(Locale.ENGLISH).contains("chrome") } } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidLoggingHandler.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidLoggingHandler.kt index 9208d91dd..7071e9bd2 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidLoggingHandler.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/compatibility/AndroidLoggingHandler.kt @@ -10,7 +10,8 @@ object AndroidLoggingHandler : LoggingHandler() { override fun log(logLevel: LogLevel, tag: String, message: String?, throwable: Throwable?) { val priority = priority( - logLevel) + logLevel + ) if (message != null) Log.println(priority, tag, message) if (throwable != null) diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/ActivityHelper.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/ActivityHelper.kt index 4662c5653..2e1d4dc88 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/ActivityHelper.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/ActivityHelper.kt @@ -35,7 +35,8 @@ fun Activity.updateRecentsHeaderIfExisting( * @param colorPrimary The color used as background for the header of the recents card - passed as Android * Color Resource */ -fun Activity.updateRecentsHeaderIfExisting(@StringRes label: Int, @DrawableRes icon: Int, @ColorRes colorPrimary: Int) { +fun Activity.updateRecentsHeaderIfExisting(@StringRes label: Int, @DrawableRes icon: Int, @ColorRes +colorPrimary: Int) { val labelRaw = resources.getString(label) val iconRaw = BitmapFactory.decodeResource(resources, icon) val colorPrimaryRaw = resources.getColorBackport(colorPrimary, theme) diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/LiveDataHelper.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/LiveDataHelper.kt index ea273739e..17c04403f 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/LiveDataHelper.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/helper/LiveDataHelper.kt @@ -10,7 +10,8 @@ inline fun <X, Y> LiveData<X?>.switchMap( noinline func: (X) -> LiveData<Y>? ): LiveData<Y> { val result = MediatorLiveData<Y>() - result.addSource(this, object : Observer<X?> { + result.addSource( + this, object : Observer<X?> { internal var mSource: LiveData<Y>? = null override fun onChanged(x: X?) { @@ -26,7 +27,8 @@ inline fun <X, Y> LiveData<X?>.switchMap( result.value = null } } - }) + } + ) return result } @@ -36,7 +38,8 @@ inline fun <X, Y> LiveData<X?>.switchMapRx( noinline func: (X) -> Observable<Y>? ): LiveData<Y?> { val result = MediatorLiveData<Y>() - result.addSource(this, object : Observer<X?> { + result.addSource( + this, object : Observer<X?> { internal var mSource: LiveData<Y>? = null override fun onChanged(x: X?) { @@ -52,7 +55,8 @@ inline fun <X, Y> LiveData<X?>.switchMapRx( result.value = null } } - }) + } + ) return result } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/quassel/IrcUserUtils.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/quassel/IrcUserUtils.kt index f9a348d9b..738f86ef3 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/quassel/IrcUserUtils.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/quassel/IrcUserUtils.kt @@ -35,7 +35,9 @@ object IrcUserUtils { ) } - private fun String.firstIndex(char: Char, startIndex: Int? = null, ignoreCase: Boolean = false): Int? { + private fun String.firstIndex(char: Char, + startIndex: Int? = null, + ignoreCase: Boolean = false): Int? { val lastIndex = indexOf(char, startIndex ?: 0, ignoreCase) if (lastIndex < 0) return null @@ -43,7 +45,9 @@ object IrcUserUtils { return lastIndex } - private fun String.lastIndex(char: Char, startIndex: Int? = null, ignoreCase: Boolean = false): Int? { + private fun String.lastIndex(char: Char, + startIndex: Int? = null, + ignoreCase: Boolean = false): Int? { val lastIndex = lastIndexOf(char, startIndex ?: lastIndex, ignoreCase) if (lastIndex < 0) return null diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt index ef9518e58..411cf406d 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt @@ -11,9 +11,9 @@ import de.kuschku.quasseldroid_ng.util.helper.updateRecentsHeaderIfExisting abstract class ServiceBoundActivity : AppCompatActivity() { @DrawableRes - protected val icon: Int = R.mipmap.ic_launcher + protected val icon: Int = R.mipmap.ic_launcher_recents @ColorRes - protected val recentsHeaderColor: Int = R.color.colorPrimaryDark + protected val recentsHeaderColor: Int = R.color.colorPrimary private val connection = BackendServiceConnection() diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/ContextThemeWrapper.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/ContextThemeWrapper.kt index 39996a3ca..1d253a110 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/ContextThemeWrapper.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/ContextThemeWrapper.kt @@ -7,8 +7,8 @@ import android.content.res.Configuration import android.content.res.Resources import android.os.Build import android.support.annotation.StyleRes -import android.support.v7.appcompat.R import android.view.LayoutInflater +import de.kuschku.quasseldroid_ng.R /** * A ContextWrapper that allows you to modify the theme from what is in the @@ -88,7 +88,8 @@ class ContextThemeWrapper : ContextWrapper { fun applyOverrideConfiguration(overrideConfiguration: Configuration) { if (mResources != null) { throw IllegalStateException( - "getResources() or getAssets() has already been called") + "getResources() or getAssets() has already been called" + ) } if (this.overrideConfiguration != null) { throw IllegalStateException("Override configuration has already been set") diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/DrawerRecyclerView.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/DrawerRecyclerView.kt index 451cb8197..2d0f6f948 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/DrawerRecyclerView.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/DrawerRecyclerView.kt @@ -20,25 +20,32 @@ class DrawerRecyclerView @JvmOverloads constructor( private val maxWidth: Int init { - val a = context.obtainStyledAttributes(attrs, - R.styleable.ScrimInsetsFrameLayout, defStyleAttr, - R.style.Widget_Design_ScrimInsetsFrameLayout) + val a = context.obtainStyledAttributes( + attrs, + R.styleable.ScrimInsetsFrameLayout, defStyleAttr, + R.style.Widget_Design_ScrimInsetsFrameLayout + ) mInsetForeground = a.getDrawable(R.styleable.ScrimInsetsFrameLayout_insetForeground) a.recycle() setWillNotDraw(true) // No need to draw until the insets are adjusted - ViewCompat.setOnApplyWindowInsetsListener(this + ViewCompat.setOnApplyWindowInsetsListener( + this ) { _, insets -> if (null == mInsets) { mInsets = Rect() } - mInsets!!.set(insets.systemWindowInsetLeft, - insets.systemWindowInsetTop, - insets.systemWindowInsetRight, - insets.systemWindowInsetBottom) - setPadding(insets.systemWindowInsetLeft, - insets.systemWindowInsetTop, - insets.systemWindowInsetRight, - insets.systemWindowInsetBottom) + mInsets!!.set( + insets.systemWindowInsetLeft, + insets.systemWindowInsetTop, + insets.systemWindowInsetRight, + insets.systemWindowInsetBottom + ) + setPadding( + insets.systemWindowInsetLeft, + insets.systemWindowInsetTop, + insets.systemWindowInsetRight, + insets.systemWindowInsetBottom + ) setWillNotDraw(!insets.hasSystemWindowInsets() || mInsetForeground == null) ViewCompat.postInvalidateOnAnimation(this@DrawerRecyclerView) insets.consumeSystemWindowInsets() diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/MaterialContentLoadingProgressBar.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/MaterialContentLoadingProgressBar.kt index bceebb5e0..ed521dc57 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/MaterialContentLoadingProgressBar.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/MaterialContentLoadingProgressBar.kt @@ -27,7 +27,9 @@ import me.zhanghai.android.materialprogressbar.MaterialProgressBar * a minimum amount of time to avoid "flashes" in the UI when an event could take * a largely variable time to complete (from none, to a user perceivable amount) */ -class MaterialContentLoadingProgressBar @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : MaterialProgressBar(context, attrs, 0) { +class MaterialContentLoadingProgressBar @JvmOverloads constructor(context: Context, + attrs: AttributeSet? = null) : + MaterialProgressBar(context, attrs, 0) { private var mStartTime: Long = -1 private var mPostedHide = false private var mPostedShow = false diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/NavigationDrawerLayout.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/NavigationDrawerLayout.kt index 1090d6fa2..b42f6d9c7 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/NavigationDrawerLayout.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/NavigationDrawerLayout.kt @@ -35,25 +35,32 @@ class NavigationDrawerLayout @JvmOverloads constructor( private val maxWidth: Int init { - val a = context.obtainStyledAttributes(attrs, - R.styleable.ScrimInsetsFrameLayout, defStyleAttr, - R.style.Widget_Design_ScrimInsetsFrameLayout) + val a = context.obtainStyledAttributes( + attrs, + R.styleable.ScrimInsetsFrameLayout, defStyleAttr, + R.style.Widget_Design_ScrimInsetsFrameLayout + ) mInsetForeground = a.getDrawable(R.styleable.ScrimInsetsFrameLayout_insetForeground) a.recycle() setWillNotDraw(true) // No need to draw until the insets are adjusted - ViewCompat.setOnApplyWindowInsetsListener(this + ViewCompat.setOnApplyWindowInsetsListener( + this ) { _, insets -> if (null == mInsets) { mInsets = Rect() } - mInsets!!.set(insets.systemWindowInsetLeft, - insets.systemWindowInsetTop, - insets.systemWindowInsetRight, - insets.systemWindowInsetBottom) - setPadding(insets.systemWindowInsetLeft, - insets.systemWindowInsetTop, - insets.systemWindowInsetRight, - insets.systemWindowInsetBottom) + mInsets!!.set( + insets.systemWindowInsetLeft, + insets.systemWindowInsetTop, + insets.systemWindowInsetRight, + insets.systemWindowInsetBottom + ) + setPadding( + insets.systemWindowInsetLeft, + insets.systemWindowInsetTop, + insets.systemWindowInsetRight, + insets.systemWindowInsetBottom + ) setWillNotDraw(!insets.hasSystemWindowInsets() || mInsetForeground == null) ViewCompat.postInvalidateOnAnimation(this@NavigationDrawerLayout) insets.consumeSystemWindowInsets() diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/SpanFormatter.java b/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/SpanFormatter.java index 31f342ec7..fe0e46f91 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/SpanFormatter.java +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/ui/SpanFormatter.java @@ -53,88 +53,88 @@ import java.util.regex.Pattern; * @author George T. Steel */ public class SpanFormatter { - private static final Pattern FORMAT_SEQUENCE = Pattern.compile("%([0-9]+\\$|<?)([^a-zA-z%]*)([[a-zA-Z%]&&[^tT]]|[tT][a-zA-Z])"); + private static final Pattern FORMAT_SEQUENCE = Pattern.compile("%([0-9]+\\$|<?)([^a-zA-z%]*)([[a-zA-Z%]&&[^tT]]|[tT][a-zA-Z])"); + + private SpanFormatter() { + } + + /** + * Version of {@link String#format(String, Object...)} that works on {@link Spanned} strings to preserve rich text formatting. + * Both the {@code format} as well as any {@code %s args} can be Spanned and will have their formatting preserved. + * Due to the way {@link Spannable}s work, any argument's spans will can only be included <b>once</b> in the result. + * Any duplicates will appear as text only. + * + * @param format the format string (see {@link java.util.Formatter#format}) + * @param args the list of arguments passed to the formatter. If there are + * more arguments than required by {@code format}, + * additional arguments are ignored. + * @return the formatted string (with spans). + */ + @NonNull + public static SpannedString format(@NonNull CharSequence format, Object... args) { + return format(Locale.getDefault(), format, args); + } + + /** + * Version of {@link String#format(Locale, String, Object...)} that works on {@link Spanned} strings to preserve rich text formatting. + * Both the {@code format} as well as any {@code %s args} can be Spanned and will have their formatting preserved. + * Due to the way {@link Spannable}s work, any argument's spans will can only be included <b>once</b> in the result. + * Any duplicates will appear as text only. + * + * @param locale the locale to apply; {@code null} value means no localization. + * @param format the format string (see {@link java.util.Formatter#format}) + * @param args the list of arguments passed to the formatter. + * @return the formatted string (with spans). + * @see String#format(Locale, String, Object...) + */ + @NonNull + public static SpannedString format(@NonNull Locale locale, @NonNull CharSequence format, Object... args) { + SpannableStringBuilder out = new SpannableStringBuilder(format); + + int i = 0; + int argAt = -1; + + while (i < out.length()) { + Matcher m = FORMAT_SEQUENCE.matcher(out); + if (!m.find(i)) break; + i = m.start(); + int exprEnd = m.end(); + + String argTerm = m.group(1); + String modTerm = m.group(2); + String typeTerm = m.group(3); + + CharSequence cookedArg; + + if (typeTerm.equals("%")) { + cookedArg = "%"; + } else { + int argIdx; + switch (argTerm) { + case "": + argIdx = ++argAt; + break; + case "<": + argIdx = argAt; + break; + default: + argIdx = Integer.parseInt(argTerm.substring(0, argTerm.length() - 1)) - 1; + break; + } - private SpanFormatter() { - } + Object argItem = args[argIdx]; - /** - * Version of {@link String#format(String, Object...)} that works on {@link Spanned} strings to preserve rich text formatting. - * Both the {@code format} as well as any {@code %s args} can be Spanned and will have their formatting preserved. - * Due to the way {@link Spannable}s work, any argument's spans will can only be included <b>once</b> in the result. - * Any duplicates will appear as text only. - * - * @param format the format string (see {@link java.util.Formatter#format}) - * @param args the list of arguments passed to the formatter. If there are - * more arguments than required by {@code format}, - * additional arguments are ignored. - * @return the formatted string (with spans). - */ - @NonNull - public static SpannedString format(@NonNull CharSequence format, Object... args) { - return format(Locale.getDefault(), format, args); - } - - /** - * Version of {@link String#format(Locale, String, Object...)} that works on {@link Spanned} strings to preserve rich text formatting. - * Both the {@code format} as well as any {@code %s args} can be Spanned and will have their formatting preserved. - * Due to the way {@link Spannable}s work, any argument's spans will can only be included <b>once</b> in the result. - * Any duplicates will appear as text only. - * - * @param locale the locale to apply; {@code null} value means no localization. - * @param format the format string (see {@link java.util.Formatter#format}) - * @param args the list of arguments passed to the formatter. - * @return the formatted string (with spans). - * @see String#format(Locale, String, Object...) - */ - @NonNull - public static SpannedString format(@NonNull Locale locale, @NonNull CharSequence format, Object... args) { - SpannableStringBuilder out = new SpannableStringBuilder(format); - - int i = 0; - int argAt = -1; - - while (i < out.length()) { - Matcher m = FORMAT_SEQUENCE.matcher(out); - if (!m.find(i)) break; - i = m.start(); - int exprEnd = m.end(); - - String argTerm = m.group(1); - String modTerm = m.group(2); - String typeTerm = m.group(3); - - CharSequence cookedArg; - - if (typeTerm.equals("%")) { - cookedArg = "%"; - } else { - int argIdx; - switch (argTerm) { - case "": - argIdx = ++argAt; - break; - case "<": - argIdx = argAt; - break; - default: - argIdx = Integer.parseInt(argTerm.substring(0, argTerm.length() - 1)) - 1; - break; - } - - Object argItem = args[argIdx]; - - if (typeTerm.equals("s") && argItem instanceof Spanned) { - cookedArg = (Spanned) argItem; - } else { - cookedArg = String.format(locale, "%" + modTerm + typeTerm, argItem); - } - } - - out.replace(i, exprEnd, cookedArg); - i += cookedArg.length(); + if (typeTerm.equals("s") && argItem instanceof Spanned) { + cookedArg = (Spanned) argItem; + } else { + cookedArg = String.format(locale, "%" + modTerm + typeTerm, argItem); } + } - return new SpannedString(out); + out.replace(i, exprEnd, cookedArg); + i += cookedArg.length(); } + + return new SpannedString(out); + } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index aece9930f..1094421ed 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,156 +1,156 @@ <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/drawerLayout" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:fitsSystemWindows="true"> + + <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/drawerLayout" android:layout_width="match_parent" android:layout_height="match_parent" - android:fitsSystemWindows="true"> + android:fitsSystemWindows="true" + android:orientation="vertical"> - <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" + <android.support.design.widget.AppBarLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:theme="?attr/actionBarTheme"> + + <FrameLayout android:layout_width="match_parent" - android:layout_height="match_parent" - android:fitsSystemWindows="true" - android:orientation="vertical"> - - <android.support.design.widget.AppBarLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:theme="?attr/actionBarTheme"> - - <FrameLayout - android:layout_width="match_parent" - android:layout_height="?attr/actionBarSize"> - - <android.support.v7.widget.Toolbar - android:id="@+id/toolbar" - android:layout_width="match_parent" - android:layout_height="match_parent" - app:contentInsetStartWithNavigation="0dp" - app:popupTheme="@style/Widget.PopupOverlay"> - - <LinearLayout - android:id="@+id/toolbar_action_area" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:background="?attr/selectableItemBackgroundBorderless" - android:clickable="true" - android:focusable="true" - android:focusableInTouchMode="false" - android:gravity="center_vertical|start" - android:minHeight="?attr/actionBarSize" - android:orientation="vertical"> - - <LinearLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:layout_marginTop="-2dp" - android:baselineAligned="false" - android:gravity="center_vertical"> - - <TextView - android:id="@+id/key" - style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title" - android:layout_width="16dp" - android:layout_height="16dp" - android:layout_marginEnd="2dp" - android:layout_marginRight="2dp" - android:layout_marginTop="2dp" - android:gravity="center" - android:textSize="16sp" - android:visibility="gone" /> - - <TextView - android:id="@+id/toolbar_title" - style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:ellipsize="end" - android:gravity="center_vertical" - android:singleLine="true" - android:text="@string/app_name" /> - - </LinearLayout> - - <TextView - android:id="@+id/toolbar_subtitle" - style="@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="-3dp" - android:ellipsize="end" - android:singleLine="true" - android:visibility="gone" /> - </LinearLayout> - - </android.support.v7.widget.Toolbar> - - <de.kuschku.quasseldroid_ng.util.ui.MaterialContentLoadingProgressBar - android:id="@+id/progressBar" - style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="bottom" - app:mpb_progressStyle="horizontal" - app:mpb_setBothDrawables="true" - app:mpb_useIntrinsicPadding="false" - tools:indeterminate="true" /> - </FrameLayout> - - </android.support.design.widget.AppBarLayout> - - <fragment - android:id="@+id/contentMessages" - android:name="de.kuschku.quasseldroid_ng.ui.chat.MessageListFragment" - android:layout_width="match_parent" - android:layout_height="0dip" - android:layout_weight="1" - tools:layout="@layout/fragment_messages" /> - - <android.support.v7.widget.CardView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="?colorBackgroundCard" - app:cardElevation="4dp"> + android:layout_height="?attr/actionBarSize"> + + <android.support.v7.widget.Toolbar + android:id="@+id/toolbar" + android:layout_width="match_parent" + android:layout_height="match_parent" + app:contentInsetStartWithNavigation="0dp" + app:popupTheme="@style/Widget.PopupOverlay"> + + <LinearLayout + android:id="@+id/toolbar_action_area" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:background="?attr/selectableItemBackgroundBorderless" + android:clickable="true" + android:focusable="true" + android:focusableInTouchMode="false" + android:gravity="center_vertical|start" + android:minHeight="?attr/actionBarSize" + android:orientation="vertical"> <LinearLayout - android:layout_width="match_parent" - android:layout_height="?actionBarSize"> - - <EditText - android:id="@+id/input" - android:layout_width="0dip" - android:layout_height="match_parent" - android:layout_weight="1" /> - - <Button - android:id="@+id/buttonSend" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:text="Send" /> + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:layout_marginTop="-2dp" + android:baselineAligned="false" + android:gravity="center_vertical"> + + <TextView + android:id="@+id/key" + style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title" + android:layout_width="16dp" + android:layout_height="16dp" + android:layout_marginEnd="2dp" + android:layout_marginRight="2dp" + android:layout_marginTop="2dp" + android:gravity="center" + android:textSize="16sp" + android:visibility="gone" /> + + <TextView + android:id="@+id/toolbar_title" + style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" + android:gravity="center_vertical" + android:singleLine="true" + android:text="@string/app_name" /> + </LinearLayout> - </android.support.v7.widget.CardView> + <TextView + android:id="@+id/toolbar_subtitle" + style="@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="-3dp" + android:ellipsize="end" + android:singleLine="true" + android:visibility="gone" /> + </LinearLayout> + + </android.support.v7.widget.Toolbar> + + <de.kuschku.quasseldroid_ng.util.ui.MaterialContentLoadingProgressBar + android:id="@+id/progressBar" + style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom" + app:mpb_progressStyle="horizontal" + app:mpb_setBothDrawables="true" + app:mpb_useIntrinsicPadding="false" + tools:indeterminate="true" /> + </FrameLayout> + + </android.support.design.widget.AppBarLayout> + + <fragment + android:id="@+id/contentMessages" + android:name="de.kuschku.quasseldroid_ng.ui.chat.MessageListFragment" + android:layout_width="match_parent" + android:layout_height="0dip" + android:layout_weight="1" + tools:layout="@layout/fragment_messages" /> + + <android.support.v7.widget.CardView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?colorBackgroundCard" + app:cardElevation="4dp"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="?actionBarSize"> - </LinearLayout> + <EditText + android:id="@+id/input" + android:layout_width="0dip" + android:layout_height="match_parent" + android:layout_weight="1" /> - <include layout="@layout/fragment_nick_list" /> + <Button + android:id="@+id/buttonSend" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_vertical" + android:text="Send" /> + </LinearLayout> - <de.kuschku.quasseldroid_ng.util.ui.NavigationDrawerLayout - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_gravity="start" - android:background="?attr/colorBackground" - android:fitsSystemWindows="true" - app:insetForeground="?attr/colorPrimaryDark"> - - <fragment - android:id="@+id/chatListFragment" - android:name="de.kuschku.quasseldroid_ng.ui.chat.BufferViewConfigFragment" - android:layout_width="match_parent" - android:layout_height="match_parent" - tools:layout="@layout/fragment_chat_list" /> - </de.kuschku.quasseldroid_ng.util.ui.NavigationDrawerLayout> + </android.support.v7.widget.CardView> + + </LinearLayout> + + <include layout="@layout/fragment_nick_list" /> + + <de.kuschku.quasseldroid_ng.util.ui.NavigationDrawerLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="start" + android:background="?attr/colorBackground" + android:fitsSystemWindows="true" + app:insetForeground="?attr/colorPrimaryDark"> + + <fragment + android:id="@+id/chatListFragment" + android:name="de.kuschku.quasseldroid_ng.ui.chat.BufferViewConfigFragment" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:layout="@layout/fragment_chat_list" /> + </de.kuschku.quasseldroid_ng.util.ui.NavigationDrawerLayout> </android.support.v4.widget.DrawerLayout> diff --git a/app/src/main/res/layout/fragment_messages.xml b/app/src/main/res/layout/fragment_messages.xml index 57e8d5acd..ac1b5a37a 100644 --- a/app/src/main/res/layout/fragment_messages.xml +++ b/app/src/main/res/layout/fragment_messages.xml @@ -1,31 +1,31 @@ <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:tools="http://schemas.android.com/tools" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="?attr/colorBackground"> + + <android.support.v7.widget.RecyclerView + android:id="@+id/messages" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="?attr/colorBackground"> - - <android.support.v7.widget.RecyclerView - android:id="@+id/messages" - android:layout_width="match_parent" - android:layout_height="match_parent" - app:stackFromEnd="true" - tools:listitem="@layout/widget_chatmessage_plain" /> + app:stackFromEnd="true" + tools:listitem="@layout/widget_chatmessage_plain" /> - <android.support.design.widget.FloatingActionButton - android:id="@+id/scrollDown" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="end|bottom" - android:layout_marginBottom="12dp" - android:layout_marginEnd="12dp" - android:layout_marginRight="12dp" - android:tint="@color/colorFillDark" - app:backgroundTint="#8A808080" - app:elevation="0dip" - app:fabSize="mini" - app:pressedTranslationZ="0dip" - app:srcCompat="@drawable/ic_scroll_down" /> + <android.support.design.widget.FloatingActionButton + android:id="@+id/scrollDown" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end|bottom" + android:layout_marginBottom="12dp" + android:layout_marginEnd="12dp" + android:layout_marginRight="12dp" + android:tint="@color/colorFillDark" + app:backgroundTint="#8A808080" + app:elevation="0dip" + app:fabSize="mini" + app:pressedTranslationZ="0dip" + app:srcCompat="@drawable/ic_scroll_down" /> </FrameLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/widget_chatmessage_action.xml b/app/src/main/res/layout/widget_chatmessage_action.xml index b4271dd33..754adfd98 100644 --- a/app/src/main/res/layout/widget_chatmessage_action.xml +++ b/app/src/main/res/layout/widget_chatmessage_action.xml @@ -20,35 +20,35 @@ --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:clickable="true" - android:focusable="true" - android:gravity="top" - android:orientation="horizontal" - android:paddingBottom="@dimen/message_vertical" - android:paddingEnd="@dimen/message_horizontal" - android:paddingLeft="@dimen/message_horizontal" - android:paddingRight="@dimen/message_horizontal" - android:paddingStart="@dimen/message_horizontal" - android:paddingTop="@dimen/message_vertical" - android:textAppearance="?android:attr/textAppearanceListItemSmall"> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:clickable="true" + android:focusable="true" + android:gravity="top" + android:orientation="horizontal" + android:paddingBottom="@dimen/message_vertical" + android:paddingEnd="@dimen/message_horizontal" + android:paddingLeft="@dimen/message_horizontal" + android:paddingRight="@dimen/message_horizontal" + android:paddingStart="@dimen/message_horizontal" + android:paddingTop="@dimen/message_vertical" + android:textAppearance="?android:attr/textAppearanceListItemSmall"> - <TextView - android:id="@+id/time" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/message_horizontal" - android:layout_marginRight="@dimen/message_horizontal" - android:textColor="?attr/colorForegroundSecondary" - android:typeface="monospace" /> + <TextView + android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/message_horizontal" + android:layout_marginRight="@dimen/message_horizontal" + android:textColor="?attr/colorForegroundSecondary" + android:typeface="monospace" /> - <TextView - android:id="@+id/content" - android:layout_width="0dip" - android:layout_height="wrap_content" - android:layout_weight="1" - android:textColor="?attr/colorForegroundAction" - android:textIsSelectable="true" - android:textStyle="italic" /> + <TextView + android:id="@+id/content" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="?attr/colorForegroundAction" + android:textIsSelectable="true" + android:textStyle="italic" /> </LinearLayout> diff --git a/app/src/main/res/layout/widget_chatmessage_error.xml b/app/src/main/res/layout/widget_chatmessage_error.xml index 44e42f1cd..a19b7e87f 100644 --- a/app/src/main/res/layout/widget_chatmessage_error.xml +++ b/app/src/main/res/layout/widget_chatmessage_error.xml @@ -1,35 +1,35 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="?attr/colorBackgroundSecondary" - android:clickable="true" - android:focusable="true" - android:gravity="top" - android:orientation="horizontal" - android:paddingBottom="@dimen/message_vertical" - android:paddingEnd="@dimen/message_horizontal" - android:paddingLeft="@dimen/message_horizontal" - android:paddingRight="@dimen/message_horizontal" - android:paddingStart="@dimen/message_horizontal" - android:paddingTop="@dimen/message_vertical" - android:textAppearance="?android:attr/textAppearanceListItemSmall"> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?attr/colorBackgroundSecondary" + android:clickable="true" + android:focusable="true" + android:gravity="top" + android:orientation="horizontal" + android:paddingBottom="@dimen/message_vertical" + android:paddingEnd="@dimen/message_horizontal" + android:paddingLeft="@dimen/message_horizontal" + android:paddingRight="@dimen/message_horizontal" + android:paddingStart="@dimen/message_horizontal" + android:paddingTop="@dimen/message_vertical" + android:textAppearance="?android:attr/textAppearanceListItemSmall"> - <TextView - android:id="@+id/time" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/message_horizontal" - android:layout_marginRight="@dimen/message_horizontal" - android:textColor="?attr/colorForegroundSecondary" - android:typeface="monospace" /> + <TextView + android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/message_horizontal" + android:layout_marginRight="@dimen/message_horizontal" + android:textColor="?attr/colorForegroundSecondary" + android:typeface="monospace" /> - <TextView - android:id="@+id/content" - android:layout_width="0dip" - android:layout_height="wrap_content" - android:layout_weight="1" - android:textColor="?attr/colorForegroundError" - android:textIsSelectable="true" - android:textStyle="italic" /> + <TextView + android:id="@+id/content" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="?attr/colorForegroundError" + android:textIsSelectable="true" + android:textStyle="italic" /> </LinearLayout> diff --git a/app/src/main/res/layout/widget_chatmessage_plain.xml b/app/src/main/res/layout/widget_chatmessage_plain.xml index 75105c7d9..705534482 100644 --- a/app/src/main/res/layout/widget_chatmessage_plain.xml +++ b/app/src/main/res/layout/widget_chatmessage_plain.xml @@ -1,36 +1,36 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:clickable="true" - android:focusable="true" - android:gravity="top" - android:orientation="horizontal" - android:paddingBottom="@dimen/message_vertical" - android:paddingEnd="@dimen/message_horizontal" - android:paddingLeft="@dimen/message_horizontal" - android:paddingRight="@dimen/message_horizontal" - android:paddingStart="@dimen/message_horizontal" - android:paddingTop="@dimen/message_vertical" - android:textAppearance="?android:attr/textAppearanceListItemSmall"> + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:clickable="true" + android:focusable="true" + android:gravity="top" + android:orientation="horizontal" + android:paddingBottom="@dimen/message_vertical" + android:paddingEnd="@dimen/message_horizontal" + android:paddingLeft="@dimen/message_horizontal" + android:paddingRight="@dimen/message_horizontal" + android:paddingStart="@dimen/message_horizontal" + android:paddingTop="@dimen/message_vertical" + android:textAppearance="?android:attr/textAppearanceListItemSmall"> - <TextView - android:id="@+id/time" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/message_horizontal" - android:layout_marginRight="@dimen/message_horizontal" - android:textColor="?attr/colorForegroundSecondary" - android:typeface="monospace" - tools:text="[15:55]" /> + <TextView + android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/message_horizontal" + android:layout_marginRight="@dimen/message_horizontal" + android:textColor="?attr/colorForegroundSecondary" + android:typeface="monospace" + tools:text="[15:55]" /> - <TextView - android:id="@+id/content" - android:layout_width="0dip" - android:layout_height="wrap_content" - android:layout_weight="1" - android:textColor="?attr/colorForeground" - android:textIsSelectable="true" - tools:text="justJanne: hiii" /> + <TextView + android:id="@+id/content" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="?attr/colorForeground" + android:textIsSelectable="true" + tools:text="justJanne: hiii" /> </LinearLayout> diff --git a/app/src/main/res/layout/widget_chatmessage_server.xml b/app/src/main/res/layout/widget_chatmessage_server.xml index 40613e00c..a9ac1112f 100644 --- a/app/src/main/res/layout/widget_chatmessage_server.xml +++ b/app/src/main/res/layout/widget_chatmessage_server.xml @@ -1,35 +1,35 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="?attr/colorBackgroundSecondary" - android:clickable="true" - android:focusable="true" - android:gravity="top" - android:orientation="horizontal" - android:paddingBottom="@dimen/message_vertical" - android:paddingEnd="@dimen/message_horizontal" - android:paddingLeft="@dimen/message_horizontal" - android:paddingRight="@dimen/message_horizontal" - android:paddingStart="@dimen/message_horizontal" - android:paddingTop="@dimen/message_vertical" - android:textAppearance="?android:attr/textAppearanceListItemSmall"> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?attr/colorBackgroundSecondary" + android:clickable="true" + android:focusable="true" + android:gravity="top" + android:orientation="horizontal" + android:paddingBottom="@dimen/message_vertical" + android:paddingEnd="@dimen/message_horizontal" + android:paddingLeft="@dimen/message_horizontal" + android:paddingRight="@dimen/message_horizontal" + android:paddingStart="@dimen/message_horizontal" + android:paddingTop="@dimen/message_vertical" + android:textAppearance="?android:attr/textAppearanceListItemSmall"> - <TextView - android:id="@+id/time" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/message_horizontal" - android:layout_marginRight="@dimen/message_horizontal" - android:textColor="?attr/colorForegroundSecondary" - android:typeface="monospace" /> + <TextView + android:id="@+id/time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/message_horizontal" + android:layout_marginRight="@dimen/message_horizontal" + android:textColor="?attr/colorForegroundSecondary" + android:typeface="monospace" /> - <TextView - android:id="@+id/content" - android:layout_width="0dip" - android:layout_height="wrap_content" - android:layout_weight="1" - android:textColor="?attr/colorForegroundSecondary" - android:textIsSelectable="true" - android:textStyle="italic" /> + <TextView + android:id="@+id/content" + android:layout_width="0dip" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textColor="?attr/colorForegroundSecondary" + android:textIsSelectable="true" + android:textStyle="italic" /> </LinearLayout> diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_recents.png b/app/src/main/res/mipmap-hdpi/ic_launcher_recents.png new file mode 100644 index 0000000000000000000000000000000000000000..704b703466300312afef5183f4815c87b853a6a8 GIT binary patch literal 4120 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 WNIVYPfL&q$0000<MNUMnLSTX+@9(St literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_recents.png b/app/src/main/res/mipmap-mdpi/ic_launcher_recents.png new file mode 100644 index 0000000000000000000000000000000000000000..aa6768589fdc17dc9615ccd9d9a72202a63ed2f6 GIT binary patch literal 2793 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_recents.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_recents.png new file mode 100644 index 0000000000000000000000000000000000000000..b602349062aab9c0f7b44b347d9400177b0da5f3 GIT binary patch literal 6175 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_recents.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_recents.png new file mode 100644 index 0000000000000000000000000000000000000000..d4b4622fcf9b571ce307740c5f9335daed3f99c6 GIT binary patch literal 11789 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 E2lxr>F#rGn literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_recents.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_recents.png new file mode 100644 index 0000000000000000000000000000000000000000..aada01932a343ad3cf2e5afe2767c22f21dddbb1 GIT binary patch literal 18337 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	A-Z^Db`$I0jGcViE`iYID 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index dd9f8a6b1..03012d411 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -1,6 +1,6 @@ <resources> - <dimen name="navigation_drawer_max_width">320dp</dimen> + <dimen name="navigation_drawer_max_width">320dp</dimen> - <dimen name="message_horizontal">8dp</dimen> - <dimen name="message_vertical">2dp</dimen> + <dimen name="message_horizontal">8dp</dimen> + <dimen name="message_vertical">2dp</dimen> </resources> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8e98b5f95..7771d68ff 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -5,6 +5,6 @@ <string name="connection_service_description">Keeps a connection to your core to allow for notifications, and to transmit messages.</string> <string name="crash_text">QD-NG has crashed</string> - <string name="drawer_open">Open</string> - <string name="drawer_close">Close</string> + <string name="drawer_open">Open</string> + <string name="drawer_close">Close</string> </resources> diff --git a/app/src/main/res/values/themes_quassel.xml b/app/src/main/res/values/themes_quassel.xml index 1b8cee6ec..d9cbff96d 100644 --- a/app/src/main/res/values/themes_quassel.xml +++ b/app/src/main/res/values/themes_quassel.xml @@ -1,83 +1,83 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <string name="themeQuasselLightName">Quasselâ„¢ (Light)</string> - <string name="themeQuasselLightId">QUASSEL_LIGHT</string> + <string name="themeQuasselLightName">Quasselâ„¢ (Light)</string> + <string name="themeQuasselLightId">QUASSEL_LIGHT</string> - <style name="Theme.ChatTheme.Quassel_Light" parent="Theme.ChatTheme.Light"> - <item name="senderColor0">#cc0000</item> - <item name="senderColor1">#006cad</item> - <item name="senderColor2">#4d9900</item> - <item name="senderColor3">#6600cc</item> - <item name="senderColor4">#a67d00</item> - <item name="senderColor5">#009927</item> - <item name="senderColor6">#0030c0</item> - <item name="senderColor7">#cc009a</item> - <item name="senderColor8">#b94600</item> - <item name="senderColor9">#869900</item> - <item name="senderColorA">#149900</item> - <item name="senderColorB">#009960</item> - <item name="senderColorC">#006cad</item> - <item name="senderColorD">#0099cc</item> - <item name="senderColorE">#b300cc</item> - <item name="senderColorF">#cc004d</item> + <style name="Theme.ChatTheme.Quassel_Light" parent="Theme.ChatTheme.Light"> + <item name="senderColor0">#cc0000</item> + <item name="senderColor1">#006cad</item> + <item name="senderColor2">#4d9900</item> + <item name="senderColor3">#6600cc</item> + <item name="senderColor4">#a67d00</item> + <item name="senderColor5">#009927</item> + <item name="senderColor6">#0030c0</item> + <item name="senderColor7">#cc009a</item> + <item name="senderColor8">#b94600</item> + <item name="senderColor9">#869900</item> + <item name="senderColorA">#149900</item> + <item name="senderColorB">#009960</item> + <item name="senderColorC">#006cad</item> + <item name="senderColorD">#0099cc</item> + <item name="senderColorE">#b300cc</item> + <item name="senderColorF">#cc004d</item> - <item name="colorForeground">#DE000000</item> - <item name="colorForegroundHighlight">#DE000000</item> - <item name="colorForegroundSecondary">#8A000000</item> - <item name="colorForegroundAction">#1a237e</item> - <item name="colorForegroundError">#800000</item> + <item name="colorForeground">#DE000000</item> + <item name="colorForegroundHighlight">#DE000000</item> + <item name="colorForegroundSecondary">#8A000000</item> + <item name="colorForegroundAction">#1a237e</item> + <item name="colorForegroundError">#800000</item> - <item name="colorForegroundMirc">0x1</item> + <item name="colorForegroundMirc">0x1</item> - <item name="colorBackground">#FAFAFA</item> - <item name="colorBackgroundHighlight">#ff8811</item> - <item name="colorBackgroundSecondary">@null</item> - <item name="colorBackgroundCard">#FFFFFF</item> - <item name="colorBackgroundDialog">#FAFAFA</item> + <item name="colorBackground">#FAFAFA</item> + <item name="colorBackgroundHighlight">#ff8811</item> + <item name="colorBackgroundSecondary">@null</item> + <item name="colorBackgroundCard">#FFFFFF</item> + <item name="colorBackgroundDialog">#FAFAFA</item> - <item name="colorTintActivity">#88cc33</item> - <item name="colorTintMessage">#2277dd</item> - <item name="colorTintHighlight">#ff8811</item> - </style> + <item name="colorTintActivity">#88cc33</item> + <item name="colorTintMessage">#2277dd</item> + <item name="colorTintHighlight">#ff8811</item> + </style> - <string name="themeQuasselDarkName">Quasselâ„¢ (Dark)</string> - <string name="themeQuasselDarkId">QUASSEL_DARK</string> + <string name="themeQuasselDarkName">Quasselâ„¢ (Dark)</string> + <string name="themeQuasselDarkId">QUASSEL_DARK</string> - <style name="Theme.ChatTheme.Quassel_Dark" parent="Theme.ChatTheme"> - <item name="senderColor0">#cc0000</item> - <item name="senderColor1">#006cad</item> - <item name="senderColor2">#4d9900</item> - <item name="senderColor3">#6600cc</item> - <item name="senderColor4">#a67d00</item> - <item name="senderColor5">#009927</item> - <item name="senderColor6">#0030c0</item> - <item name="senderColor7">#cc009a</item> - <item name="senderColor8">#b94600</item> - <item name="senderColor9">#869900</item> - <item name="senderColorA">#149900</item> - <item name="senderColorB">#009960</item> - <item name="senderColorC">#006cad</item> - <item name="senderColorD">#0099cc</item> - <item name="senderColorE">#b300cc</item> - <item name="senderColorF">#cc004d</item> + <style name="Theme.ChatTheme.Quassel_Dark" parent="Theme.ChatTheme"> + <item name="senderColor0">#cc0000</item> + <item name="senderColor1">#006cad</item> + <item name="senderColor2">#4d9900</item> + <item name="senderColor3">#6600cc</item> + <item name="senderColor4">#a67d00</item> + <item name="senderColor5">#009927</item> + <item name="senderColor6">#0030c0</item> + <item name="senderColor7">#cc009a</item> + <item name="senderColor8">#b94600</item> + <item name="senderColor9">#869900</item> + <item name="senderColorA">#149900</item> + <item name="senderColorB">#009960</item> + <item name="senderColorC">#006cad</item> + <item name="senderColorD">#0099cc</item> + <item name="senderColorE">#b300cc</item> + <item name="senderColorF">#cc004d</item> - <item name="colorForeground">#FFFFFF</item> - <item name="colorForegroundHighlight">#FFFFFF</item> - <item name="colorForegroundSecondary">#B3FFFFFF</item> - <item name="colorForegroundAction">#7986cb</item> - <item name="colorForegroundError">#800000</item> + <item name="colorForeground">#FFFFFF</item> + <item name="colorForegroundHighlight">#FFFFFF</item> + <item name="colorForegroundSecondary">#B3FFFFFF</item> + <item name="colorForegroundAction">#7986cb</item> + <item name="colorForegroundError">#800000</item> - <item name="colorForegroundMirc">0x0</item> + <item name="colorForegroundMirc">0x0</item> - <item name="colorBackground">#303030</item> - <item name="colorBackgroundHighlight">#ff8811</item> - <item name="colorBackgroundSecondary">@null</item> - <item name="colorBackgroundCard">#424242</item> - <item name="colorBackgroundDialog">#303030</item> + <item name="colorBackground">#303030</item> + <item name="colorBackgroundHighlight">#ff8811</item> + <item name="colorBackgroundSecondary">@null</item> + <item name="colorBackgroundCard">#424242</item> + <item name="colorBackgroundDialog">#303030</item> - <item name="colorTintActivity">#88cc33</item> - <item name="colorTintMessage">#2277dd</item> - <item name="colorTintHighlight">#ff8811</item> - </style> + <item name="colorTintActivity">#88cc33</item> + <item name="colorTintMessage">#2277dd</item> + <item name="colorTintHighlight">#ff8811</item> + </style> </resources> diff --git a/invokerannotations/src/main/java/de/kuschku/libquassel/annotations/Slot.java b/invokerannotations/src/main/java/de/kuschku/libquassel/annotations/Slot.java index e09a0bc39..4630dc726 100644 --- a/invokerannotations/src/main/java/de/kuschku/libquassel/annotations/Slot.java +++ b/invokerannotations/src/main/java/de/kuschku/libquassel/annotations/Slot.java @@ -9,5 +9,5 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.SOURCE) @Target(value = ElementType.METHOD) public @interface Slot { - String value() default ""; + String value() default ""; } diff --git a/invokerannotations/src/main/java/de/kuschku/libquassel/annotations/Syncable.java b/invokerannotations/src/main/java/de/kuschku/libquassel/annotations/Syncable.java index 77367a296..163e0c1e5 100644 --- a/invokerannotations/src/main/java/de/kuschku/libquassel/annotations/Syncable.java +++ b/invokerannotations/src/main/java/de/kuschku/libquassel/annotations/Syncable.java @@ -9,5 +9,5 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(value = ElementType.TYPE) public @interface Syncable { - String name(); + String name(); } diff --git a/invokergenerator/src/main/java/de/kuschku/libquassel/annotations/InvokerProcessor.java b/invokergenerator/src/main/java/de/kuschku/libquassel/annotations/InvokerProcessor.java index 133a67143..0a3a15456 100644 --- a/invokergenerator/src/main/java/de/kuschku/libquassel/annotations/InvokerProcessor.java +++ b/invokergenerator/src/main/java/de/kuschku/libquassel/annotations/InvokerProcessor.java @@ -38,202 +38,202 @@ import javax.lang.model.type.TypeMirror; @SupportedSourceVersion(SourceVersion.RELEASE_8) public class InvokerProcessor extends AbstractProcessor { - private Filer filer; - - @Override - public synchronized void init(ProcessingEnvironment processingEnv) { - filer = processingEnv.getFiler(); - } - - @Override - public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { - List<SyncableElement> syncableElements = new ArrayList<>(); - for (Element element : roundEnv.getElementsAnnotatedWith(Syncable.class)) { - if (element.getKind() == ElementKind.INTERFACE) { - List<SlotElement> slotElements = new ArrayList<>(); - for (Element element1 : element.getEnclosedElements()) { - if (element1.getKind() == ElementKind.METHOD) { - ExecutableElement it = (ExecutableElement) element1; - ExecutableType methodType = (ExecutableType) it.asType(); - - Slot slotAnnotation = element1.getAnnotation(Slot.class); - if (slotAnnotation != null) { - String slotName = slotAnnotation.value().isEmpty() ? it.getSimpleName().toString() : slotAnnotation.value(); - slotElements.add(new SlotElement(it, methodType, slotName, slotAnnotation)); - } - } - } - - PackageElement packageElement = (PackageElement) element.getEnclosingElement(); - TypeElement typeElement = (TypeElement) element; - Syncable annotation = typeElement.getAnnotation(Syncable.class); - - syncableElements.add(new SyncableElement(packageElement, typeElement, annotation, slotElements)); + private Filer filer; + + @Override + public synchronized void init(ProcessingEnvironment processingEnv) { + filer = processingEnv.getFiler(); + } + + @Override + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + List<SyncableElement> syncableElements = new ArrayList<>(); + for (Element element : roundEnv.getElementsAnnotatedWith(Syncable.class)) { + if (element.getKind() == ElementKind.INTERFACE) { + List<SlotElement> slotElements = new ArrayList<>(); + for (Element element1 : element.getEnclosedElements()) { + if (element1.getKind() == ElementKind.METHOD) { + ExecutableElement it = (ExecutableElement) element1; + ExecutableType methodType = (ExecutableType) it.asType(); + + Slot slotAnnotation = element1.getAnnotation(Slot.class); + if (slotAnnotation != null) { + String slotName = slotAnnotation.value().isEmpty() ? it.getSimpleName().toString() : slotAnnotation.value(); + slotElements.add(new SlotElement(it, methodType, slotName, slotAnnotation)); } + } } - try { - for (SyncableElement syncableElement : syncableElements) { - generateInvoker(syncableElement); - } - } catch (IOException e) { - e.printStackTrace(); - } - return true; - } + PackageElement packageElement = (PackageElement) element.getEnclosingElement(); + TypeElement typeElement = (TypeElement) element; + Syncable annotation = typeElement.getAnnotation(Syncable.class); - private void generateInvoker(SyncableElement element) throws IOException { - String packageName = element.packageElement.getQualifiedName().toString() + ".invokers"; - String invokerName = element.annotation.name() + "Invoker"; - - ClassName type = ClassName.get(packageName, invokerName); - ClassName wrongObjectTypeException = ClassName.get("de.kuschku.libquassel.quassel.exceptions", "WrongObjectTypeException"); - ClassName unknownMethodException = ClassName.get("de.kuschku.libquassel.quassel.exceptions", "UnknownMethodException"); - ClassName nonNullAnnotation = ClassName.get("android.support.annotation", "NonNull"); - - MethodSpec methodSpecConstructor = MethodSpec - .constructorBuilder() - .addModifiers(Modifier.PRIVATE) - .build(); - - FieldSpec fieldSpecInstance = FieldSpec - .builder(type, "INSTANCE", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) - .initializer("new $T()", type) - .build(); - - MethodSpec methodSpecClassName = MethodSpec - .methodBuilder("getClassName") - .addModifiers(Modifier.PUBLIC) - .addAnnotation(nonNullAnnotation) - .addAnnotation(Override.class) - .returns(String.class) - .addStatement("return $S", element.annotation.name()) - .build(); - - ParameterSpec parameterSpecOn = ParameterSpec - .builder( - Object.class, - "on" - ) - .addAnnotation(nonNullAnnotation) - .build(); - - ParameterSpec parameterSpecMethod = ParameterSpec - .builder( - String.class, - "method" - ) - .addAnnotation(nonNullAnnotation).build(); - - ParameterSpec parameterSpecParams = ParameterSpec - .builder( - ParameterizedTypeName.get( - ClassName.get(List.class), - ParameterizedTypeName.get( - ClassName.get("de.kuschku.libquassel.protocol", "QVariant"), - TypeName.get(Object.class) - ) - ), - "params" - ) - .addAnnotation(nonNullAnnotation) - .build(); - - MethodSpec.Builder invokeSpec = MethodSpec - .methodBuilder("invoke") - .addModifiers(Modifier.PUBLIC) - .addAnnotation(Override.class) - .addException(wrongObjectTypeException) - .addException(unknownMethodException) - .addParameter(parameterSpecOn) - .addParameter(parameterSpecMethod) - .addParameter(parameterSpecParams) - .beginControlFlow("if (on instanceof $T)", element.typeElement) - .addStatement("$T it = ($T) $N", element.typeElement, element.typeElement, parameterSpecOn) - .beginControlFlow("switch ($N)", parameterSpecMethod); - - for (SlotElement slot : element.slots) { - invokeSpec = invokeSpec.beginControlFlow("case $S:", slot.slotName); - invokeSpec = invokeSpec.addCode("it.$N(\n$>", slot.element.getSimpleName()); - for (int i = 0; i < slot.type.getParameterTypes().size(); i++) { - TypeMirror parameterType = slot.type.getParameterTypes().get(i); - boolean isLast = i + 1 == slot.type.getParameterTypes().size(); - - invokeSpec = invokeSpec.addCode("($T) $N.get($L).getData()", parameterType, parameterSpecParams, i); - if (!isLast) - invokeSpec = invokeSpec.addCode(","); - invokeSpec = invokeSpec.addCode("\n"); - } - invokeSpec = invokeSpec.addCode("$<);\n"); - invokeSpec = invokeSpec.endControlFlow("return"); - } - - invokeSpec = invokeSpec - .beginControlFlow("default:") - .addStatement("throw new $T($N(), $N)", - unknownMethodException, - methodSpecClassName, - parameterSpecMethod - ) - .endControlFlow() - .endControlFlow() - .addCode("$<} else{\n$>") - .addStatement("throw new $T($N, $N())", - wrongObjectTypeException, - parameterSpecOn, - methodSpecClassName - ) - .endControlFlow(); - - TypeSpec typeSpec = TypeSpec - .classBuilder(type) - .addSuperinterface(ParameterizedTypeName.get( - ClassName.get(packageName, "Invoker"), - TypeName.get(element.typeElement.asType()) - )) - .addModifiers(Modifier.PUBLIC) - .addField(fieldSpecInstance) - .addMethod(methodSpecConstructor) - .addMethod(methodSpecClassName) - .addMethod(invokeSpec.build()) - .build(); - - JavaFile javaFile = JavaFile - .builder(packageName, typeSpec) - .build(); - - javaFile.writeTo(filer); + syncableElements.add(new SyncableElement(packageElement, typeElement, annotation, slotElements)); + } } - private class SlotElement { - final ExecutableElement element; - final ExecutableType type; - - final String slotName; - - final Slot slot; + try { + for (SyncableElement syncableElement : syncableElements) { + generateInvoker(syncableElement); + } + } catch (IOException e) { + e.printStackTrace(); + } + return true; + } + + private void generateInvoker(SyncableElement element) throws IOException { + String packageName = element.packageElement.getQualifiedName().toString() + ".invokers"; + String invokerName = element.annotation.name() + "Invoker"; + + ClassName type = ClassName.get(packageName, invokerName); + ClassName wrongObjectTypeException = ClassName.get("de.kuschku.libquassel.quassel.exceptions", "WrongObjectTypeException"); + ClassName unknownMethodException = ClassName.get("de.kuschku.libquassel.quassel.exceptions", "UnknownMethodException"); + ClassName nonNullAnnotation = ClassName.get("android.support.annotation", "NonNull"); + + MethodSpec methodSpecConstructor = MethodSpec + .constructorBuilder() + .addModifiers(Modifier.PRIVATE) + .build(); + + FieldSpec fieldSpecInstance = FieldSpec + .builder(type, "INSTANCE", Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) + .initializer("new $T()", type) + .build(); + + MethodSpec methodSpecClassName = MethodSpec + .methodBuilder("getClassName") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(nonNullAnnotation) + .addAnnotation(Override.class) + .returns(String.class) + .addStatement("return $S", element.annotation.name()) + .build(); + + ParameterSpec parameterSpecOn = ParameterSpec + .builder( + Object.class, + "on" + ) + .addAnnotation(nonNullAnnotation) + .build(); + + ParameterSpec parameterSpecMethod = ParameterSpec + .builder( + String.class, + "method" + ) + .addAnnotation(nonNullAnnotation).build(); + + ParameterSpec parameterSpecParams = ParameterSpec + .builder( + ParameterizedTypeName.get( + ClassName.get(List.class), + ParameterizedTypeName.get( + ClassName.get("de.kuschku.libquassel.protocol", "QVariant"), + TypeName.get(Object.class) + ) + ), + "params" + ) + .addAnnotation(nonNullAnnotation) + .build(); + + MethodSpec.Builder invokeSpec = MethodSpec + .methodBuilder("invoke") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .addException(wrongObjectTypeException) + .addException(unknownMethodException) + .addParameter(parameterSpecOn) + .addParameter(parameterSpecMethod) + .addParameter(parameterSpecParams) + .beginControlFlow("if (on instanceof $T)", element.typeElement) + .addStatement("$T it = ($T) $N", element.typeElement, element.typeElement, parameterSpecOn) + .beginControlFlow("switch ($N)", parameterSpecMethod); + + for (SlotElement slot : element.slots) { + invokeSpec = invokeSpec.beginControlFlow("case $S:", slot.slotName); + invokeSpec = invokeSpec.addCode("it.$N(\n$>", slot.element.getSimpleName()); + for (int i = 0; i < slot.type.getParameterTypes().size(); i++) { + TypeMirror parameterType = slot.type.getParameterTypes().get(i); + boolean isLast = i + 1 == slot.type.getParameterTypes().size(); + + invokeSpec = invokeSpec.addCode("($T) $N.get($L).getData()", parameterType, parameterSpecParams, i); + if (!isLast) + invokeSpec = invokeSpec.addCode(","); + invokeSpec = invokeSpec.addCode("\n"); + } + invokeSpec = invokeSpec.addCode("$<);\n"); + invokeSpec = invokeSpec.endControlFlow("return"); + } - public SlotElement(ExecutableElement element, ExecutableType type, String slotName, Slot slot) { - this.element = element; - this.type = type; - this.slotName = slotName; - this.slot = slot; - } + invokeSpec = invokeSpec + .beginControlFlow("default:") + .addStatement("throw new $T($N(), $N)", + unknownMethodException, + methodSpecClassName, + parameterSpecMethod + ) + .endControlFlow() + .endControlFlow() + .addCode("$<} else{\n$>") + .addStatement("throw new $T($N, $N())", + wrongObjectTypeException, + parameterSpecOn, + methodSpecClassName + ) + .endControlFlow(); + + TypeSpec typeSpec = TypeSpec + .classBuilder(type) + .addSuperinterface(ParameterizedTypeName.get( + ClassName.get(packageName, "Invoker"), + TypeName.get(element.typeElement.asType()) + )) + .addModifiers(Modifier.PUBLIC) + .addField(fieldSpecInstance) + .addMethod(methodSpecConstructor) + .addMethod(methodSpecClassName) + .addMethod(invokeSpec.build()) + .build(); + + JavaFile javaFile = JavaFile + .builder(packageName, typeSpec) + .build(); + + javaFile.writeTo(filer); + } + + private class SlotElement { + final ExecutableElement element; + final ExecutableType type; + + final String slotName; + + final Slot slot; + + public SlotElement(ExecutableElement element, ExecutableType type, String slotName, Slot slot) { + this.element = element; + this.type = type; + this.slotName = slotName; + this.slot = slot; } + } - private class SyncableElement { - final PackageElement packageElement; - final TypeElement typeElement; + private class SyncableElement { + final PackageElement packageElement; + final TypeElement typeElement; - final Syncable annotation; + final Syncable annotation; - final List<SlotElement> slots; + final List<SlotElement> slots; - public SyncableElement(PackageElement packageElement, TypeElement typeElement, Syncable annotation, List<SlotElement> slots) { - this.packageElement = packageElement; - this.typeElement = typeElement; - this.annotation = annotation; - this.slots = slots; - } + public SyncableElement(PackageElement packageElement, TypeElement typeElement, Syncable annotation, List<SlotElement> slots) { + this.packageElement = packageElement; + this.typeElement = typeElement; + this.annotation = annotation; + this.slots = slots; } + } } diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/MetaType.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/MetaType.kt index 79cd1d31c..fee50680b 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/MetaType.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/MetaType.kt @@ -53,8 +53,10 @@ data class MetaType<T>(val klass: Class<T>, val type: Type, val serializer: Seri addType(Type.UserType, QType.BufferId, IntSerializer) addType(Type.UserType, QType.BufferInfo, BufferInfoSerializer) addType(Type.UserType, QType.DccConfig_IpDetectionMode, DccConfig_IpDetectionModeSerializer) - addType(Type.UserType, QType.DccConfig_PortSelectionMode, - DccConfig_PortSelectionModeSerializer) + addType( + Type.UserType, QType.DccConfig_PortSelectionMode, + DccConfig_PortSelectionModeSerializer + ) addType(Type.UserType, QType.IrcUser, VariantMapSerializer) addType(Type.UserType, QType.IrcChannel, VariantMapSerializer) addType(Type.UserType, QType.Identity, VariantMapSerializer) diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/message/CoreSetupDataSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/message/CoreSetupDataSerializer.kt index 33fbc4cd8..47462bb78 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/message/CoreSetupDataSerializer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/message/CoreSetupDataSerializer.kt @@ -8,14 +8,16 @@ import de.kuschku.libquassel.protocol.value object CoreSetupDataSerializer : HandshakeMessageSerializer<HandshakeMessage.CoreSetupData> { override fun serialize(data: HandshakeMessage.CoreSetupData) = mapOf( "MsgType" to QVariant_("CoreSetupData", Type.QString), - "SetupData" to QVariant_(mapOf( - "AdminUser" to QVariant_(data.adminUser, Type.QString), - "AdminPasswd" to QVariant_(data.adminPassword, Type.QString), - "Backend" to QVariant_(data.backend, Type.QString), - "ConnectionProperties" to QVariant_(data.setupData, Type.QVariantMap), - "Authenticator" to QVariant_(data.authenticator, Type.QString), - "AuthProperties" to QVariant_(data.authSetupData, Type.QVariantMap) - ), Type.QVariantMap) + "SetupData" to QVariant_( + mapOf( + "AdminUser" to QVariant_(data.adminUser, Type.QString), + "AdminPasswd" to QVariant_(data.adminPassword, Type.QString), + "Backend" to QVariant_(data.backend, Type.QString), + "ConnectionProperties" to QVariant_(data.setupData, Type.QVariantMap), + "Authenticator" to QVariant_(data.authenticator, Type.QString), + "AuthProperties" to QVariant_(data.authSetupData, Type.QVariantMap) + ), Type.QVariantMap + ) ) override fun deserialize(data: QVariantMap): HandshakeMessage.CoreSetupData { diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/message/RequestType.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/message/RequestType.kt index 3fcc834c2..957b99ab3 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/message/RequestType.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/message/RequestType.kt @@ -11,7 +11,8 @@ enum class RequestType(val value: Int) { companion object { private val byId = enumValues<RequestType>().associateBy( - RequestType::value) + RequestType::value + ) fun of(value: Int) = byId[value] ?: Invalid } diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/message/SessionInitSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/message/SessionInitSerializer.kt index fd2981f5d..fb18d6748 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/message/SessionInitSerializer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/message/SessionInitSerializer.kt @@ -8,11 +8,13 @@ import de.kuschku.libquassel.protocol.value object SessionInitSerializer : HandshakeMessageSerializer<HandshakeMessage.SessionInit> { override fun serialize(data: HandshakeMessage.SessionInit) = mapOf( "MsgType" to QVariant_("SessionInit", Type.QString), - "SessionState" to QVariant_(mapOf( - "BufferInfos" to QVariant_(data.bufferInfos, Type.QVariantList), - "NetworkIds" to QVariant_(data.networkIds, Type.QVariantList), - "Identities" to QVariant_(data.identities, Type.QVariantList) - ), Type.QVariantMap) + "SessionState" to QVariant_( + mapOf( + "BufferInfos" to QVariant_(data.bufferInfos, Type.QVariantList), + "NetworkIds" to QVariant_(data.networkIds, Type.QVariantList), + "Identities" to QVariant_(data.identities, Type.QVariantList) + ), Type.QVariantMap + ) ) override fun deserialize(data: QVariantMap): HandshakeMessage.SessionInit { diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/BoolSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/BoolSerializer.kt index 582234af7..85785e8db 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/BoolSerializer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/BoolSerializer.kt @@ -6,11 +6,13 @@ import java.nio.ByteBuffer object BoolSerializer : Serializer<Boolean> { override fun serialize(buffer: ChainedByteBuffer, data: Boolean, - features: Quassel_Features) = buffer.put(if (data) { - 0x01 - } else { - 0x00 - }.toByte()) + features: Quassel_Features) = buffer.put( + if (data) { + 0x01 + } else { + 0x00 + }.toByte() + ) override fun deserialize(buffer: ByteBuffer, features: Quassel_Features) = buffer.get() != 0x00.toByte() diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/DateTimeSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/DateTimeSerializer.kt index 41fd63f5b..1c7c30095 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/DateTimeSerializer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/DateTimeSerializer.kt @@ -48,7 +48,8 @@ object DateTimeSerializer : Serializer<Temporal> { } else -> throw IllegalArgumentException( - "Unsupported Format: ${data::class.java.canonicalName}") + "Unsupported Format: ${data::class.java.canonicalName}" + ) } } diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/HostAddressSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/HostAddressSerializer.kt index d2a8cce1d..ab1bc9a1f 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/HostAddressSerializer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/HostAddressSerializer.kt @@ -20,8 +20,10 @@ object HostAddressSerializer : Serializer<InetAddress> { buffer.put(data.address) } else -> { - ByteSerializer.serialize(buffer, NetworkLayerProtocol.UnknownNetworkLayerProtocol.value, - features) + ByteSerializer.serialize( + buffer, NetworkLayerProtocol.UnknownNetworkLayerProtocol.value, + features + ) throw IllegalArgumentException("Invalid network protocol ${data.javaClass.canonicalName}") } } diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/MessageSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/MessageSerializer.kt index a8fc39d9b..2dd02f8cb 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/MessageSerializer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/MessageSerializer.kt @@ -29,7 +29,8 @@ object MessageSerializer : Serializer<Message> { time = Instant.ofEpochSecond(IntSerializer.deserialize(buffer, features).toLong()), type = Message.MessageType.of(IntSerializer.deserialize(buffer, features)), flag = Message.MessageFlag.of( - ByteSerializer.deserialize(buffer, features).toInt()), + ByteSerializer.deserialize(buffer, features).toInt() + ), bufferInfo = BufferInfoSerializer.deserialize(buffer, features), sender = StringSerializer.UTF8.deserialize(buffer, features) ?: "", senderPrefixes = if (features.hasFlag(QuasselFeature.SenderPrefixes)) diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/VariantMapSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/VariantMapSerializer.kt index 21e9f5b96..916448afe 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/VariantMapSerializer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/VariantMapSerializer.kt @@ -15,12 +15,14 @@ object VariantMapSerializer : Serializer<QVariantMap> { } override fun deserialize(buffer: ByteBuffer, features: Quassel_Features): QVariantMap { - return mutableMapOf(*(0 until IntSerializer.deserialize(buffer, features)).map { - Pair( - StringSerializer.UTF16.deserialize(buffer, features) ?: "", - VariantSerializer.deserialize(buffer, features) - ) - }.toTypedArray()) + return mutableMapOf( + *(0 until IntSerializer.deserialize(buffer, features)).map { + Pair( + StringSerializer.UTF16.deserialize(buffer, features) ?: "", + VariantSerializer.deserialize(buffer, features) + ) + }.toTypedArray() + ) } } diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/AliasManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/AliasManager.kt index 1ee3e1616..33ac5d95e 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/AliasManager.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/AliasManager.kt @@ -34,7 +34,8 @@ class AliasManager constructor( if (names.size != expansions.size) throw IllegalArgumentException( - "Sizes do not match: names=${names.size}, expansions=${expansions.size}") + "Sizes do not match: names=${names.size}, expansions=${expansions.size}" + ) _aliases.clear() _aliases.addAll(names.zip(expansions, ::Alias)) @@ -79,7 +80,7 @@ class AliasManager constructor( val secondSlashPos = msg.indexOf('/', 1) val firstSpacePos = msg.indexOf(' ') if (!msg.startsWith('/') || firstSpacePos == 1 || - (secondSlashPos != -1 && (secondSlashPos < firstSpacePos || firstSpacePos == -1))) { + (secondSlashPos != -1 && (secondSlashPos < firstSpacePos || firstSpacePos == -1))) { if (msg.startsWith("//")) msg = msg.substring(1) // "//asdf" is transformed to "/asdf" else if (msg.startsWith("/ ")) @@ -89,9 +90,9 @@ class AliasManager constructor( // check for aliases val split = msg.split(' ', ignoreCase = true, limit = 2) val search: String = split.firstOrNull() - ?: return + ?: return val found = _aliases.firstOrNull { it.name.equals(search, true) } - ?: return + ?: return expand(found.expansion, info, split.getOrNull(1) ?: "", previousCommands) } @@ -104,9 +105,11 @@ class AliasManager constructor( val paramRange = Pattern.compile("""\$(\d+)\.\.(\d*)""") val commands = Arrays.asList( - *expansion.split("; ?").dropLastWhile { it.isEmpty() }.toTypedArray()) + *expansion.split("; ?").dropLastWhile { it.isEmpty() }.toTypedArray() + ) val params = Arrays.asList<String>( - *msg.split(' ').dropLastWhile({ it.isEmpty() }).toTypedArray()) + *msg.split(' ').dropLastWhile({ it.isEmpty() }).toTypedArray() + ) val expandedCommands = LinkedList<String>() for (i in commands.indices) { diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt index dd9150141..d24621833 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BacklogManager.kt @@ -16,16 +16,13 @@ class BacklogManager( private var loading = AtomicInteger(-1) - override fun requestBacklog(bufferId: BufferId, first: MsgId, last: MsgId, limit: Int, additional: Int) { + override fun requestBacklog(bufferId: BufferId, first: MsgId, last: MsgId, limit: Int, + additional: Int) { if (loading.getAndSet(bufferId) != bufferId) { super.requestBacklog(bufferId, first, last, limit, additional) } } - override fun requestBacklogAll(first: MsgId, last: MsgId, limit: Int, additional: Int) { - super.requestBacklogAll(first, last, limit, additional) - } - override fun receiveBacklog(bufferId: BufferId, first: MsgId, last: MsgId, limit: Int, additional: Int, messages: QVariantList) { loading.compareAndSet(bufferId, -1) diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt index 2ed66474c..949af19cf 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt @@ -72,7 +72,8 @@ class BufferViewConfig constructor( setBufferViewName(properties["bufferViewName"].valueOr(this::bufferViewName)) setNetworkId(properties["networkId"].valueOr(this::networkId)) setAddNewBuffersAutomatically( - properties["addNewBuffersAutomatically"].valueOr(this::addNewBuffersAutomatically)) + properties["addNewBuffersAutomatically"].valueOr(this::addNewBuffersAutomatically) + ) setSortAlphabetically(properties["sortAlphabetically"].valueOr(this::sortAlphabetically)) setHideInactiveBuffers(properties["hideInactiveBuffers"].valueOr(this::hideInactiveBuffers)) setHideInactiveNetworks(properties["hideInactiveNetworks"].valueOr(this::hideInactiveNetworks)) diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Identity.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Identity.kt index 0acd3e335..a45e24501 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Identity.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/Identity.kt @@ -51,11 +51,13 @@ class Identity constructor( setAutoAwayTime(properties["autoAwayTime"].valueOr(this::autoAwayTime)) setAutoAwayReason(properties["autoAwayReason"].valueOr(this::autoAwayReason)) setAutoAwayReasonEnabled( - properties["autoAwayReasonEnabled"].valueOr(this::autoAwayReasonEnabled)) + properties["autoAwayReasonEnabled"].valueOr(this::autoAwayReasonEnabled) + ) setDetachAwayEnabled(properties["detachAwayEnabled"].valueOr(this::detachAwayEnabled)) setDetachAwayReason(properties["detachAwayReason"].valueOr(this::detachAwayReason)) setDetachAwayReasonEnabled( - properties["detachAwayReasonEnabled"].valueOr(this::detachAwayReasonEnabled)) + properties["detachAwayReasonEnabled"].valueOr(this::detachAwayReasonEnabled) + ) setIdent(properties["ident"].valueOr(this::ident)) setKickReason(properties["kickReason"].valueOr(this::kickReason)) setPartReason(properties["partReason"].valueOr(this::partReason)) 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 6db909a98..9d4a65d46 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 @@ -29,15 +29,21 @@ class IrcChannel( } override fun initChanModes(): QVariantMap = mapOf( - "A" to QVariant_(_A_channelModes.entries.map { (key, value) -> - key to QVariant_(value.toList(), Type.QStringList) - }, Type.QVariantMap), - "B" to QVariant_(_B_channelModes.entries.map { (key, value) -> - key to QVariant_(value, Type.QString) - }, Type.QVariantMap), - "C" to QVariant_(_C_channelModes.entries.map { (key, value) -> - key to QVariant_(value, Type.QString) - }, Type.QVariantMap), + "A" to QVariant_( + _A_channelModes.entries.map { (key, value) -> + key to QVariant_(value.toList(), Type.QStringList) + }, Type.QVariantMap + ), + "B" to QVariant_( + _B_channelModes.entries.map { (key, value) -> + key to QVariant_(value, Type.QString) + }, Type.QVariantMap + ), + "C" to QVariant_( + _C_channelModes.entries.map { (key, value) -> + key to QVariant_(value, Type.QString) + }, Type.QVariantMap + ), "D" to QVariant_(_D_channelModes.joinToString(), Type.QString) ) @@ -67,9 +73,11 @@ class IrcChannel( } override fun initSetUserModes(usermodes: QVariantMap) { - _userModes.putAll(usermodes.entries.map { (key, value) -> - network().newIrcUser(key) to value.value("") - }.toMap()) + _userModes.putAll( + usermodes.entries.map { (key, value) -> + network().newIrcUser(key) to value.value("") + }.toMap() + ) } override fun initSetProperties(properties: QVariantMap) { 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 f9a51c952..cc0d9d2c8 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 @@ -240,8 +240,9 @@ class IrcUser( } override fun partChannel(channelname: String) { - val channel = network().ircChannel(channelname) - ?: throw IllegalArgumentException("Received part for unknown channel : $channelname") + val channel = network().ircChannel(channelname) ?: throw IllegalArgumentException( + "Received part for unknown channel : $channelname" + ) partChannel(channel) } 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 ae5584314..146d07605 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 @@ -80,9 +80,9 @@ class Network constructor( if (_channelModes == null) determineChannelModeTypes() return _channelModes?.entries - ?.filter { (_, chars) -> chars.contains(mode) } - ?.map(Map.Entry<ChannelModeType, Set<Char>>::key) - ?.firstOrNull() ?: ChannelModeType.NOT_A_CHANMODE + ?.filter { (_, chars) -> chars.contains(mode) } + ?.map(Map.Entry<ChannelModeType, Set<Char>>::key) + ?.firstOrNull() ?: ChannelModeType.NOT_A_CHANMODE } private fun determineChannelModeTypes() { @@ -675,12 +675,16 @@ class Network constructor( override fun initIrcUsersAndChannels(): QVariantMap { return mapOf( - "Users" to QVariant_(_ircUsers.values.map { it.toVariantMap() }.transpose().map { - QVariant_(it, Type.QVariantList) - }, Type.QVariantMap), - "Channels" to QVariant_(_ircChannels.values.map { it.toVariantMap() }.transpose().map { - QVariant_(it, Type.QVariantList) - }, Type.QVariantMap) + "Users" to QVariant_( + _ircUsers.values.map { it.toVariantMap() }.transpose().map { + QVariant_(it, Type.QVariantList) + }, Type.QVariantMap + ), + "Channels" to QVariant_( + _ircChannels.values.map { it.toVariantMap() }.transpose().map { + QVariant_(it, Type.QVariantList) + }, Type.QVariantMap + ) ) } @@ -689,12 +693,18 @@ class Network constructor( "currentServer" to QVariant_(currentServer(), Type.QString), "myNick" to QVariant_(myNick(), Type.QString), "latency" to QVariant_(latency(), Type.Int), - "codecForServer" to QVariant_(codecForServer().serializeString(StringSerializer.UTF8), - Type.QByteArray), - "codecForEncoding" to QVariant_(codecForEncoding().serializeString(StringSerializer.UTF8), - Type.QByteArray), - "codecForDecoding" to QVariant_(codecForDecoding().serializeString(StringSerializer.UTF8), - Type.QByteArray), + "codecForServer" to QVariant_( + codecForServer().serializeString(StringSerializer.UTF8), + Type.QByteArray + ), + "codecForEncoding" to QVariant_( + codecForEncoding().serializeString(StringSerializer.UTF8), + Type.QByteArray + ), + "codecForDecoding" to QVariant_( + codecForDecoding().serializeString(StringSerializer.UTF8), + Type.QByteArray + ), "identityId" to QVariant_(identity(), QType.IdentityId), "isConnected" to QVariant_(isConnected(), Type.Bool), "connectionState" to QVariant_(connectionState(), Type.Int), @@ -731,7 +741,8 @@ class Network constructor( override fun initSetServerList(serverList: QVariantList) { _serverList = serverList.mapNotNull { it.value<QVariantMap?>() }.map( - Server.Companion::fromVariantMap).toMutableList() + Server.Companion::fromVariantMap + ).toMutableList() } override fun initSetIrcUsersAndChannels(usersAndChannels: QVariantMap) { @@ -770,11 +781,15 @@ class Network constructor( setCodecForServer( properties["codecForServer"].value(codecForServer().serializeString(StringSerializer.UTF8)) ) - setCodecForEncoding(properties["codecForEncoding"].value( - codecForEncoding().serializeString(StringSerializer.UTF8)) + setCodecForEncoding( + properties["codecForEncoding"].value( + codecForEncoding().serializeString(StringSerializer.UTF8) + ) ) - setCodecForDecoding(properties["codecForDecoding"].value( - codecForDecoding().serializeString(StringSerializer.UTF8)) + setCodecForDecoding( + properties["codecForDecoding"].value( + codecForDecoding().serializeString(StringSerializer.UTF8) + ) ) setIdentity(properties["identityId"].valueOr(this::identity)) setConnected(properties["isConnected"].valueOr(this::isConnected)) 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 2cf9c2190..e7ad6859a 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 @@ -68,8 +68,10 @@ class RpcHandler( } override fun sendInput(bufferInfo: BufferInfo, message: String) { - RPC("2sendInput(BufferInfo,QString)", ARG(bufferInfo, QType.BufferInfo), - ARG(message, Type.QString)) + RPC( + "2sendInput(BufferInfo,QString)", ARG(bufferInfo, QType.BufferInfo), + ARG(message, Type.QString) + ) } inline fun RPC(function: String, vararg arg: QVariant_) { diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IBacklogManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IBacklogManager.kt index f142ef481..86d8c0682 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IBacklogManager.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IBacklogManager.kt @@ -10,15 +10,19 @@ interface IBacklogManager : ISyncableObject { @Slot fun requestBacklog(bufferId: BufferId, first: MsgId = -1, last: MsgId = -1, limit: Int = -1, additional: Int = 0) { - REQUEST("requestBacklog", ARG(bufferId, QType.BufferId), ARG(first, QType.MsgId), - ARG(last, QType.MsgId), ARG(limit, Type.Int), ARG(additional, Type.Int)) + REQUEST( + "requestBacklog", ARG(bufferId, QType.BufferId), ARG(first, QType.MsgId), + ARG(last, QType.MsgId), ARG(limit, Type.Int), ARG(additional, Type.Int) + ) } @Slot fun requestBacklogAll(first: MsgId = -1, last: MsgId = -1, limit: Int = -1, additional: Int = 0) { - REQUEST("requestBacklogAll", ARG(first, QType.MsgId), ARG(last, QType.MsgId), - ARG(limit, Type.Int), ARG(additional, Type.Int)) + REQUEST( + "requestBacklogAll", ARG(first, QType.MsgId), ARG(last, QType.MsgId), + ARG(limit, Type.Int), ARG(additional, Type.Int) + ) } @Slot diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IBufferSyncer.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IBufferSyncer.kt index b0adef439..26d510445 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IBufferSyncer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IBufferSyncer.kt @@ -35,8 +35,10 @@ interface IBufferSyncer : ISyncableObject { @Slot fun requestMergeBuffersPermanently(buffer1: BufferId, buffer2: BufferId) { - REQUEST("requestMergeBuffersPermanently", ARG(buffer1, QType.BufferId), - ARG(buffer2, QType.BufferId)) + REQUEST( + "requestMergeBuffersPermanently", ARG(buffer1, QType.BufferId), + ARG(buffer2, QType.BufferId) + ) } @Slot diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IIgnoreListManager.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IIgnoreListManager.kt index f28a4dc26..26dec34a6 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IIgnoreListManager.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IIgnoreListManager.kt @@ -20,10 +20,12 @@ interface IIgnoreListManager : ISyncableObject { @Slot fun requestAddIgnoreListItem(type: Int, ignoreRule: String, isRegEx: Boolean, strictness: Int, scope: Int, scopeRule: String, isActive: Boolean) { - REQUEST("requestAddIgnoreListItem", ARG(type, Type.Int), ARG(ignoreRule, Type.QString), - ARG(isRegEx, Type.Bool), - ARG(strictness, Type.Int), ARG(scope, Type.Int), ARG(scopeRule, Type.QString), - ARG(isActive, Type.Bool)) + REQUEST( + "requestAddIgnoreListItem", ARG(type, Type.Int), ARG(ignoreRule, Type.QString), + ARG(isRegEx, Type.Bool), + ARG(strictness, Type.Int), ARG(scope, Type.Int), ARG(scopeRule, Type.QString), + ARG(isActive, Type.Bool) + ) } @Slot diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IIrcListHelper.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IIrcListHelper.kt index 8b8788e9e..fe2faef1a 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IIrcListHelper.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/IIrcListHelper.kt @@ -9,8 +9,10 @@ import de.kuschku.libquassel.protocol.Type interface IIrcListHelper : ISyncableObject { @Slot fun requestChannelList(netId: NetworkId, channelFilters: QStringList): QVariantList { - REQUEST("requestChannelList", ARG(netId, QType.NetworkId), - ARG(channelFilters, Type.QStringList)) + REQUEST( + "requestChannelList", ARG(netId, QType.NetworkId), + ARG(channelFilters, Type.QStringList) + ) return emptyList() } 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 6953f88cf..02c7d6de8 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 @@ -45,8 +45,10 @@ interface INetwork : ISyncableObject { @Slot fun addSupport(param: String, value: String = String()) { - SYNC("addSupport(param: String, value: String = String", ARG(param, Type.QString), - ARG(value, Type.QString)) + SYNC( + "addSupport(param: String, value: String = String", ARG(param, Type.QString), + ARG(value, Type.QString) + ) } @Slot @@ -242,7 +244,8 @@ interface INetwork : ISyncableObject { companion object { private val byId = enumValues<ConnectionState>().associateBy( - ConnectionState::value) + ConnectionState::value + ) fun of(value: Int) = byId[value] ?: Disconnected } @@ -336,7 +339,8 @@ interface INetwork : ISyncableObject { companion object { private val byId = enumValues<ProxyType>().associateBy( - ProxyType::value) + ProxyType::value + ) fun of(value: Int) = byId[value] ?: DefaultProxy } 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 595386657..4d2949eef 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 @@ -7,9 +7,7 @@ import de.kuschku.libquassel.protocol.Message import de.kuschku.libquassel.protocol.NetworkId import de.kuschku.libquassel.protocol.QVariantMap import de.kuschku.libquassel.quassel.BufferInfo -import de.kuschku.libquassel.session.ISession import de.kuschku.libquassel.session.Session -import de.kuschku.libquassel.session.SignalProxy import java.nio.ByteBuffer @Syncable(name = "RpcHandler") 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 203884d8e..f9aad6605 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 @@ -44,8 +44,10 @@ object Invokers { private fun <T> getInvoker(type: Class<T>): Invoker<T>? { val syncable: Syncable? = type.getAnnotation(Syncable::class.java) if (syncable == null) { - log(WARN, "Invokers", - "Invoker not annotated: ${type.canonicalName}") + log( + WARN, "Invokers", + "Invoker not annotated: ${type.canonicalName}" + ) return null } @@ -54,8 +56,10 @@ object Invokers { val klass = Class.forName("$packageName.$className") val invoker = klass.getDeclaredField("INSTANCE").get(null) if (invoker !is Invoker<*>) { - log(WARN, "Invokers", - "Invoker not of proper type: ${type.canonicalName} != ${invoker.javaClass.canonicalName}") + log( + WARN, "Invokers", + "Invoker not of proper type: ${type.canonicalName} != ${invoker.javaClass.canonicalName}" + ) return null } diff --git a/lib/src/main/java/de/kuschku/libquassel/session/CoreConnection.kt b/lib/src/main/java/de/kuschku/libquassel/session/CoreConnection.kt index f5776b8c9..2c17144a3 100644 --- a/lib/src/main/java/de/kuschku/libquassel/session/CoreConnection.kt +++ b/lib/src/main/java/de/kuschku/libquassel/session/CoreConnection.kt @@ -44,7 +44,8 @@ class CoreConnection( private val chainedBuffer = ChainedByteBuffer(direct = true) val state: BehaviorSubject<ConnectionState> = BehaviorSubject.createDefault( - ConnectionState.DISCONNECTED) + ConnectionState.DISCONNECTED + ) private var channel: WrappedChannel? = null @@ -66,9 +67,11 @@ class CoreConnection( private fun sendHandshake() { setState(ConnectionState.HANDSHAKE) - IntSerializer.serialize(chainedBuffer, - 0x42b33f00 or session.clientData.protocolFeatures.toInt(), - session.coreFeatures) + IntSerializer.serialize( + chainedBuffer, + 0x42b33f00 or session.clientData.protocolFeatures.toInt(), + session.coreFeatures + ) for (supportedProtocol in session.clientData.supportedProtocols) { IntSerializer.serialize(chainedBuffer, supportedProtocol.toInt(), session.coreFeatures) } @@ -99,12 +102,14 @@ class CoreConnection( when (protocol.version.toInt()) { 0x02 -> { // Send client clientData to core - dispatch(HandshakeMessage.ClientInit( - clientVersion = session.clientData.identifier, - buildDate = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm:ss") - .format(session.clientData.buildDate.atOffset(ZoneOffset.UTC)), - clientFeatures = Quassel_Features.of(*Quassel_Feature.values()) - )) + dispatch( + HandshakeMessage.ClientInit( + clientVersion = session.clientData.identifier, + buildDate = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm:ss") + .format(session.clientData.buildDate.atOffset(ZoneOffset.UTC)), + clientFeatures = Quassel_Features.of(*Quassel_Feature.values()) + ) + ) } else -> { throw IllegalArgumentException("Invalid Protocol Version: $protocol") @@ -127,8 +132,10 @@ class CoreConnection( try { val data = HandshakeMessage.serialize(message) handlerService.write( - MessageRunnable(data, HandshakeVariantMapSerializer, chainedBuffer, channel, - session.coreFeatures) + MessageRunnable( + data, HandshakeVariantMapSerializer, chainedBuffer, channel, + session.coreFeatures + ) ) } catch (e: Throwable) { log(WARN, TAG, "Error encountered while serializing handshake message", e) diff --git a/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt b/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt index 0a1bd7715..c1ad35b68 100644 --- a/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt +++ b/lib/src/main/java/de/kuschku/libquassel/session/ObjectStorage.kt @@ -23,10 +23,13 @@ class ObjectStorage(private val proxy: SignalProxy) { objectTree.put("${obj.className}:$new", obj) objectTree.remove("${obj.className}:$old") proxy.dispatch( - SignalProxyMessage.RpcCall("__objectRenamed__", listOf( + SignalProxyMessage.RpcCall( + "__objectRenamed__", listOf( QVariant_(obj.className, Type.QString), QVariant_(new, Type.QString), - QVariant_(old, Type.QString)) - )) + QVariant_(old, Type.QString) + ) + ) + ) } fun get(className: QType, objectName: String) = get(className.typeName, objectName) 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 07a591686..89165784d 100644 --- a/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt +++ b/lib/src/main/java/de/kuschku/libquassel/session/ProtocolHandler.kt @@ -57,7 +57,7 @@ abstract class ProtocolHandler : SignalProxy, AuthHandler, Closeable { override fun handle(f: SignalProxyMessage.InitData): Boolean { log(DEBUG, "ProtocolHandler", "< $f") val obj: ISyncableObject = objectStorage.get(f.className, f.objectName) - ?: throw ObjectNotFoundException(f.className, f.objectName) + ?: throw ObjectNotFoundException(f.className, f.objectName) obj.fromVariantMap(f.initData) obj.initialized = true @@ -103,7 +103,7 @@ abstract class ProtocolHandler : SignalProxy, AuthHandler, Closeable { log(DEBUG, "ProtocolHandler", f.toString()) val invoker = Invokers.get(f.className) - ?: throw IllegalArgumentException("Invalid classname: ${f.className}") + ?: throw IllegalArgumentException("Invalid classname: ${f.className}") currentCallClass = f.className currentCallInstance = f.objectName currentCallSlot = f.slotName 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 1faddcd31..6039586c8 100644 --- a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt +++ b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt @@ -50,10 +50,12 @@ class Session( override fun handle(f: HandshakeMessage.ClientInitAck): Boolean { coreFeatures = f.coreFeatures ?: Quassel_Feature.NONE - dispatch(HandshakeMessage.ClientLogin( - user = userData.first, - password = userData.second - )) + dispatch( + HandshakeMessage.ClientLogin( + user = userData.first, + password = userData.second + ) + ) return true } diff --git a/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt b/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt index 4de216bde..98f166bbd 100644 --- a/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt +++ b/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt @@ -71,7 +71,16 @@ class SessionManager(offlineSession: ISession, val backlogStorage: BacklogStorag lastHandlerService = handlerService lastUserData = userData lastShouldReconnect = shouldReconnect - inProgressSession.onNext(Session(clientData, trustManager, address, handlerService(), backlogStorage, userData)) + inProgressSession.onNext( + Session( + clientData, + trustManager, + address, + handlerService(), + backlogStorage, + userData + ) + ) } private var lastClientData: ClientData? = null diff --git a/lib/src/main/java/de/kuschku/libquassel/util/Flag.kt b/lib/src/main/java/de/kuschku/libquassel/util/Flag.kt index b0863fb29..aff3f65f3 100644 --- a/lib/src/main/java/de/kuschku/libquassel/util/Flag.kt +++ b/lib/src/main/java/de/kuschku/libquassel/util/Flag.kt @@ -58,7 +58,8 @@ infix fun <T> Flags<T>.hasFlag(which: T): Boolean where T : Enum<T>, T : Flag<T> } infix fun <T> Flags<T>.or(other: Flag<T>): Flags<T> where T : kotlin.Enum<T>, T : Flag<T> = Flags( - value or other.bit) + value or other.bit +) operator infix fun <T> Flags<T>.plus( other: Flags<T>): Flags<T> where T : Enum<T>, T : Flag<T> = Flags(value or other.value) @@ -67,4 +68,5 @@ operator infix fun <T> Flags<T>.plus( other: Flag<T>): Flags<T> where T : Enum<T>, T : Flag<T> = Flags(value or other.bit) infix fun <T> Flags<T>.unset(which: T): Flags<T> where T : Enum<T>, T : Flag<T> = Flags( - value xor which.bit) + value xor which.bit +) diff --git a/lib/src/main/java/de/kuschku/libquassel/util/LongFlag.kt b/lib/src/main/java/de/kuschku/libquassel/util/LongFlag.kt index 48ca720b8..6617ff225 100644 --- a/lib/src/main/java/de/kuschku/libquassel/util/LongFlag.kt +++ b/lib/src/main/java/de/kuschku/libquassel/util/LongFlag.kt @@ -59,16 +59,20 @@ infix fun <T> LongFlags<T>.hasFlag(which: T): Boolean where T : Enum<T>, T : Lon infix fun <T> LongFlags<T>.or( other: LongFlag<T>): LongFlags<T> where T : kotlin.Enum<T>, T : LongFlag<T> = LongFlags( - value or other.bit) + value or other.bit +) operator infix fun <T> LongFlags<T>.plus( other: LongFlags<T>): LongFlags<T> where T : Enum<T>, T : LongFlag<T> = LongFlags( - value or other.value) + value or other.value +) operator infix fun <T> LongFlags<T>.plus( other: LongFlag<T>): LongFlags<T> where T : Enum<T>, T : LongFlag<T> = LongFlags( - value or other.bit) + value or other.bit +) infix fun <T> LongFlags<T>.unset( which: T): LongFlags<T> where T : Enum<T>, T : LongFlag<T> = LongFlags( - value xor which.bit) + value xor which.bit +) diff --git a/lib/src/main/java/de/kuschku/libquassel/util/ShortFlag.kt b/lib/src/main/java/de/kuschku/libquassel/util/ShortFlag.kt index 5107f60ea..ec88fd70e 100644 --- a/lib/src/main/java/de/kuschku/libquassel/util/ShortFlag.kt +++ b/lib/src/main/java/de/kuschku/libquassel/util/ShortFlag.kt @@ -63,16 +63,20 @@ infix fun <T> ShortFlags<T>.hasFlag(which: T): Boolean where T : Enum<T>, T : Sh infix fun <T> ShortFlags<T>.or( other: ShortFlag<T>): ShortFlags<T> where T : kotlin.Enum<T>, T : ShortFlag<T> = ShortFlags( - value or other.bit) + value or other.bit +) operator infix fun <T> ShortFlags<T>.plus( other: ShortFlags<T>): ShortFlags<T> where T : Enum<T>, T : ShortFlag<T> = ShortFlags( - value or other.value) + value or other.value +) operator infix fun <T> ShortFlags<T>.plus( other: ShortFlag<T>): ShortFlags<T> where T : Enum<T>, T : ShortFlag<T> = ShortFlags( - value or other.bit) + value or other.bit +) infix fun <T> ShortFlags<T>.unset( which: T): ShortFlags<T> where T : Enum<T>, T : ShortFlag<T> = ShortFlags( - value xor which.bit) + value xor which.bit +) diff --git a/lib/src/main/java/de/kuschku/libquassel/util/compatibility/reference/JavaLoggingHandler.kt b/lib/src/main/java/de/kuschku/libquassel/util/compatibility/reference/JavaLoggingHandler.kt index 668d86959..0a83d806b 100644 --- a/lib/src/main/java/de/kuschku/libquassel/util/compatibility/reference/JavaLoggingHandler.kt +++ b/lib/src/main/java/de/kuschku/libquassel/util/compatibility/reference/JavaLoggingHandler.kt @@ -7,12 +7,14 @@ import java.util.logging.Logger object JavaLoggingHandler : LoggingHandler() { override fun isLoggable(logLevel: LogLevel, tag: String): Boolean { return Logger.getLogger(tag).isLoggable( - priority(logLevel)) + priority(logLevel) + ) } override fun log(logLevel: LogLevel, tag: String, message: String?, throwable: Throwable?) { val priority = priority( - logLevel) + logLevel + ) val logger = Logger.getLogger(tag) if (message != null) logger.log(priority, message) diff --git a/lib/src/main/java/de/kuschku/libquassel/util/helpers/ArrayHelper.kt b/lib/src/main/java/de/kuschku/libquassel/util/helpers/ArrayHelper.kt index 0acd30bec..279bb3f85 100644 --- a/lib/src/main/java/de/kuschku/libquassel/util/helpers/ArrayHelper.kt +++ b/lib/src/main/java/de/kuschku/libquassel/util/helpers/ArrayHelper.kt @@ -5,10 +5,11 @@ import de.kuschku.libquassel.util.compatibility.log fun ByteArray.hexDump() { for (i in 0 until this.size step 33) { - log(WARN, "HexDump", - (0 until 33).map { it + i }.filter { it < this.size }.joinToString(" ") { - String.format("%02x", this[it]) - } + log( + WARN, "HexDump", + (0 until 33).map { it + i }.filter { it < this.size }.joinToString(" ") { + String.format("%02x", this[it]) + } ) } } diff --git a/lib/src/main/java/de/kuschku/libquassel/util/nio/WrappedChannel.kt b/lib/src/main/java/de/kuschku/libquassel/util/nio/WrappedChannel.kt index 1170202b2..e6465fa89 100644 --- a/lib/src/main/java/de/kuschku/libquassel/util/nio/WrappedChannel.kt +++ b/lib/src/main/java/de/kuschku/libquassel/util/nio/WrappedChannel.kt @@ -42,15 +42,18 @@ class WrappedChannel( companion object { fun ofSocket(s: Socket): WrappedChannel { - return WrappedChannel(s, s.getInputStream(), - s.getOutputStream()) + return WrappedChannel( + s, s.getInputStream(), + s.getOutputStream() + ) } } fun withCompression(): WrappedChannel { val deflaterOutputStream = CompatibilityUtils.createDeflaterOutputStream(rawOutStream) - return WrappedChannel(socket, InflaterInputStream(rawInStream), deflaterOutputStream, - deflaterOutputStream::flush + return WrappedChannel( + socket, InflaterInputStream(rawInStream), deflaterOutputStream, + deflaterOutputStream::flush ) } diff --git a/lib/src/test/java/de/kuschku/libquassel/ConnectionUnitTest.kt b/lib/src/test/java/de/kuschku/libquassel/ConnectionUnitTest.kt index abe501dcc..1bdc88b92 100644 --- a/lib/src/test/java/de/kuschku/libquassel/ConnectionUnitTest.kt +++ b/lib/src/test/java/de/kuschku/libquassel/ConnectionUnitTest.kt @@ -30,13 +30,14 @@ class ConnectionUnitTest { } private fun runTest(host: String, port: Int, user: String, pass: String) { - val session = Session(ClientData( - identifier = "libquassel test", - buildDate = Instant.EPOCH, - clientFeatures = Quassel_Feature.of(*QuasselFeature.validValues), - protocolFeatures = Protocol_Feature.of(ProtocolFeature.TLS, ProtocolFeature.Compression), - supportedProtocols = listOf(Protocol.Datastream) - ), object : X509TrustManager { + val session = Session( + ClientData( + identifier = "libquassel test", + buildDate = Instant.EPOCH, + clientFeatures = Quassel_Feature.of(*QuasselFeature.validValues), + protocolFeatures = Protocol_Feature.of(ProtocolFeature.TLS, ProtocolFeature.Compression), + supportedProtocols = listOf(Protocol.Datastream) + ), object : X509TrustManager { override fun checkClientTrusted(p0: Array<out X509Certificate>?, p1: String?) { } @@ -50,7 +51,8 @@ class ConnectionUnitTest { override fun clearMessages(bufferId: BufferId, idRange: IntRange) = Unit override fun clearMessages(bufferId: BufferId) = Unit override fun clearMessages() = Unit - }, user to pass) + }, user to pass + ) session.join() } } diff --git a/lib/src/test/java/de/kuschku/libquassel/SerializerUnitTest.kt b/lib/src/test/java/de/kuschku/libquassel/SerializerUnitTest.kt index 40ec0c047..d097fa660 100644 --- a/lib/src/test/java/de/kuschku/libquassel/SerializerUnitTest.kt +++ b/lib/src/test/java/de/kuschku/libquassel/SerializerUnitTest.kt @@ -48,11 +48,15 @@ class SerializerUnitTest { assertEquals(now, roundTrip(DateTimeSerializer, now)) val value1 = Instant.EPOCH.atOffset(ZoneOffset.ofTotalSeconds(1234)) - assertEquals(value1.atZoneSimilarLocal(ZoneOffset.UTC).toInstant(), - roundTrip(DateTimeSerializer, value1)) + assertEquals( + value1.atZoneSimilarLocal(ZoneOffset.UTC).toInstant(), + roundTrip(DateTimeSerializer, value1) + ) val value2 = Instant.now().atOffset(ZoneOffset.ofTotalSeconds(1234)) - assertEquals(value2.atZoneSimilarLocal(ZoneOffset.UTC).toInstant(), - roundTrip(DateTimeSerializer, value2)) + assertEquals( + value2.atZoneSimilarLocal(ZoneOffset.UTC).toInstant(), + roundTrip(DateTimeSerializer, value2) + ) val value3 = LocalDateTime.of(1970, 1, 1, 0, 0) .atZone(ZoneOffset.systemDefault()).toInstant() @@ -97,7 +101,8 @@ class SerializerUnitTest { fun <T> roundTrip(serializer: Serializer<T>, value: T, features: Quassel_Features = Quassel_Feature.NONE): T { val chainedBuffer = ChainedByteBuffer( - direct = false) + direct = false + ) serializer.serialize(chainedBuffer, value, features) val buffer = chainedBuffer.toBuffer() return serializer.deserialize(buffer, features) diff --git a/malheur/build.gradle.kts b/malheur/build.gradle.kts index 81022a438..95578183e 100644 --- a/malheur/build.gradle.kts +++ b/malheur/build.gradle.kts @@ -19,5 +19,5 @@ android { dependencies { implementation(kotlin("stdlib", "1.2.0")) - implementation("com.google.code.gson", "gson", "2.2.4") + implementation("com.google.code.gson", "gson", "2.8.0") } diff --git a/malheur/src/main/java/de/kuschku/malheur/CrashHandler.kt b/malheur/src/main/java/de/kuschku/malheur/CrashHandler.kt index a371e6648..3e67a36a3 100644 --- a/malheur/src/main/java/de/kuschku/malheur/CrashHandler.kt +++ b/malheur/src/main/java/de/kuschku/malheur/CrashHandler.kt @@ -24,16 +24,20 @@ object CrashHandler { val stackTraces = Thread.getAllStackTraces() Thread { try { - val json = gson.toJson(reportCollector.collect(CrashContext( - application = application, - config = config, - crashingThread = activeThread, - throwable = throwable, - startTime = startTime, - crashTime = crashTime, - buildConfig = buildConfig, - stackTraces = stackTraces - ), config)) + val json = gson.toJson( + reportCollector.collect( + CrashContext( + application = application, + config = config, + crashingThread = activeThread, + throwable = throwable, + startTime = startTime, + crashTime = crashTime, + buildConfig = buildConfig, + stackTraces = stackTraces + ), config + ) + ) // FIXME STOPSHIP Implement crash handling } catch (e: Throwable) { e.printStackTrace() diff --git a/malheur/src/main/java/de/kuschku/malheur/collectors/DisplayCollector.kt b/malheur/src/main/java/de/kuschku/malheur/collectors/DisplayCollector.kt index c00c07610..eda35c684 100644 --- a/malheur/src/main/java/de/kuschku/malheur/collectors/DisplayCollector.kt +++ b/malheur/src/main/java/de/kuschku/malheur/collectors/DisplayCollector.kt @@ -15,7 +15,8 @@ import java.lang.reflect.Modifier class DisplayCollector(application: Application) : Collector<DisplayInfo, Boolean> { private val windowManager = application.getSystemService( - Context.WINDOW_SERVICE) as WindowManager + Context.WINDOW_SERVICE + ) as WindowManager @Suppress("DEPRECATION") override fun collect(context: CrashContext, config: Boolean): DisplayInfo? { diff --git a/malheur/src/main/java/de/kuschku/malheur/collectors/EnvCollector.kt b/malheur/src/main/java/de/kuschku/malheur/collectors/EnvCollector.kt index 5cb6e7d95..3adcb27f5 100644 --- a/malheur/src/main/java/de/kuschku/malheur/collectors/EnvCollector.kt +++ b/malheur/src/main/java/de/kuschku/malheur/collectors/EnvCollector.kt @@ -16,7 +16,8 @@ class EnvCollector(application: Application) : Collector<EnvInfo, EnvConfig> { override fun collect(context: CrashContext, config: EnvConfig) = EnvInfo( paths = collectIf(config.paths) { reflectionCollectGetters( - Environment::class.java)?.map { (key, value) -> + Environment::class.java + )?.map { (key, value) -> key to if (value is File) { value.canonicalPath } else { -- GitLab