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 dd8b2b764d6b1423b8f822096f9eae334da51b37..a0134e299cfa660c5ec3fd87a670635fff0868a1 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 @@ -13,10 +13,8 @@ class QuasselBacklogStorage(private val db: QuasselDatabase) : BacklogStorage { for ((bufferId, bufferMessages) in messages.sortedBy { it.messageId }.groupBy { it.bufferInfo.bufferId }) { val lastMessageId = db.message().findLastByBufferId(bufferId)?.messageId val firstMessage = bufferMessages.firstOrNull() - if (lastMessageId != null && firstMessage != null) { - if (lastMessageId < firstMessage.messageId) { - db.message().clearMessages(bufferId) - } + if (lastMessageId == null || firstMessage == null || lastMessageId < firstMessage.messageId) { + db.message().clearMessages(bufferId) } } 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 88942631b463280ec16b7c9559d8e0cb0a591787..4c618ac3304f0bacb62b547f2f825a92bdd12de4 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 @@ -211,6 +211,7 @@ class BufferViewConfigFragment : ServiceBoundFragment() { ) chatList.layoutManager = LinearLayoutManager(context) chatList.itemAnimator = DefaultItemAnimator() + chatList.setItemViewCacheSize(10) return view } 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 85428e267a8e4e7cdf785376afe721a18fdf8d1d..bd40477de6a564e9e8556a35d19a5bd20db96e93 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 @@ -68,5 +68,9 @@ class MessageAdapter(context: Context) : messageRenderer.init(viewHolder, messageType, hasHighlight) return viewHolder } + + operator fun get(position: Int): QuasselDatabase.DatabaseMessage? { + return getItem(position) + } } 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 a71fe90001dc00f04b79a06e908179f19ec862e4..2b54f1f05b32d45948a370236cc9f3cb22273009 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 @@ -15,18 +15,20 @@ import android.view.ViewGroup import butterknife.BindView import butterknife.ButterKnife import de.kuschku.libquassel.protocol.BufferId +import de.kuschku.libquassel.session.Backend +import de.kuschku.libquassel.session.SessionManager import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase import de.kuschku.quasseldroid_ng.util.AndroidHandlerThread -import de.kuschku.quasseldroid_ng.util.helper.invoke -import de.kuschku.quasseldroid_ng.util.helper.switchMap -import de.kuschku.quasseldroid_ng.util.helper.toggle +import de.kuschku.quasseldroid_ng.util.helper.* import de.kuschku.quasseldroid_ng.util.service.ServiceBoundFragment class MessageListFragment : ServiceBoundFragment() { val currentBuffer: MutableLiveData<LiveData<BufferId?>?> = MutableLiveData() private val buffer = currentBuffer.switchMap { it } + private val sessionManager: LiveData<SessionManager?> = backend.map(Backend::sessionManager) + private val handler = AndroidHandlerThread("Chat") private lateinit var database: QuasselDatabase @@ -64,6 +66,7 @@ class MessageListFragment : ServiceBoundFragment() { val linearLayoutManager = LinearLayoutManager(context) linearLayoutManager.reverseLayout = true messageList.layoutManager = linearLayoutManager + messageList.setItemViewCacheSize(20) messageList.addOnScrollListener( object : RecyclerView.OnScrollListener() { @@ -85,6 +88,20 @@ class MessageListFragment : ServiceBoundFragment() { .build() } + sessionManager.zip(buffer).zip(data).observe( + this, Observer { + handler.post { + val session = it?.first?.first + val buffer = it?.first?.second + val bufferSyncer = session?.bufferSyncer + + if (buffer != null && bufferSyncer != null) { + bufferSyncer.requestMarkBufferAsRead(buffer) + } + } + } + ) + data.observe( this, Observer { list -> val findFirstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition() 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 7071e9bd2b50c62c22d7863de2ca70114302171f..97b627e791ffc3e933e37af7d78fc8e236311e76 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 @@ -5,7 +5,7 @@ import de.kuschku.libquassel.util.compatibility.LoggingHandler object AndroidLoggingHandler : LoggingHandler() { override fun isLoggable(logLevel: LogLevel, tag: String): Boolean { - return true || Log.isLoggable(tag, priority(logLevel)) + return Log.isLoggable(tag, priority(logLevel)) } override fun log(logLevel: LogLevel, tag: String, message: String?, throwable: Throwable?) { diff --git a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt index dad9082c4d25f497d1f6241765accca9baf44937..bf240b73564a686eb8746e8b526d5a77ad131e35 100644 --- a/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt +++ b/lib/src/main/java/de/kuschku/libquassel/protocol/primitive/serializer/StringSerializer.kt @@ -1,6 +1,7 @@ package de.kuschku.libquassel.protocol.primitive.serializer import de.kuschku.libquassel.protocol.Quassel_Features +import de.kuschku.libquassel.util.helpers.hexDump import de.kuschku.libquassel.util.nio.ChainedByteBuffer import java.nio.ByteBuffer import java.nio.CharBuffer @@ -46,58 +47,78 @@ abstract class StringSerializer( } override fun serialize(buffer: ChainedByteBuffer, data: String?, features: Quassel_Features) { - if (data == null) { - IntSerializer.serialize(buffer, -1, features) - } else { - val charBuffer = charBuffer(data.length) - charBuffer.put(data) - charBuffer.flip() - val byteBuffer = encoder.encode(charBuffer) - IntSerializer.serialize(buffer, byteBuffer.remaining() + trailingNullBytes, features) - buffer.put(byteBuffer) - for (i in 0 until trailingNullBytes) - buffer.put(0) + try { + if (data == null) { + IntSerializer.serialize(buffer, -1, features) + } else { + val charBuffer = charBuffer(data.length) + charBuffer.put(data) + charBuffer.flip() + val byteBuffer = encoder.encode(charBuffer) + IntSerializer.serialize(buffer, byteBuffer.remaining() + trailingNullBytes, features) + buffer.put(byteBuffer) + for (i in 0 until trailingNullBytes) + buffer.put(0) + } + } catch (e: Throwable) { + throw RuntimeException(data, e) } } - fun serialize(data: String?): ByteBuffer = if (data == null) { - ByteBuffer.allocate(0) - } else { - val charBuffer = charBuffer(data.length) - charBuffer.put(data) - charBuffer.flip() - encoder.encode(charBuffer) + fun serialize(data: String?): ByteBuffer { + try { + if (data == null) { + return ByteBuffer.allocate(0) + } else { + val charBuffer = charBuffer(data.length) + charBuffer.put(data) + charBuffer.flip() + return encoder.encode(charBuffer) + } + } catch (e: Throwable) { + throw RuntimeException(data, e) + } } fun deserializeAll(buffer: ByteBuffer): String? { - val len = buffer.remaining() - return if (len == -1) { - null - } else { - val limit = buffer.limit() - buffer.limit(buffer.position() + len - trailingNullBytes) - val charBuffer = charBuffer(len) - decoder.decode(buffer, charBuffer, true) - buffer.limit(limit) - buffer.position(buffer.position() + trailingNullBytes) - charBuffer.flip() - charBuffer.toString() + try { + val len = buffer.remaining() + return if (len == -1) { + null + } else { + val limit = buffer.limit() + buffer.limit(buffer.position() + len - trailingNullBytes) + val charBuffer = charBuffer(len) + decoder.decode(buffer, charBuffer, true) + buffer.limit(limit) + buffer.position(buffer.position() + trailingNullBytes) + charBuffer.flip() + charBuffer.toString() + } + } catch (e: Throwable) { + buffer.hexDump() + throw RuntimeException(e) } } override fun deserialize(buffer: ByteBuffer, features: Quassel_Features): String? { - val len = IntSerializer.deserialize(buffer, features) - return if (len == -1) { - null - } else { - val limit = buffer.limit() - buffer.limit(buffer.position() + Math.max(0, len - trailingNullBytes)) - val charBuffer = charBuffer(len) - decoder.decode(buffer, charBuffer, true) - buffer.limit(limit) - buffer.position(buffer.position() + trailingNullBytes) - charBuffer.flip() - charBuffer.toString() + try { + val len = IntSerializer.deserialize(buffer, features) + return if (len == -1) { + null + } else { + val limit = buffer.limit() + buffer.limit(buffer.position() + Math.max(0, len - trailingNullBytes)) + val charBuffer = charBuffer(len) + decoder.decode(buffer, charBuffer, true) + buffer.limit(limit) + buffer.position(buffer.position() + trailingNullBytes) + charBuffer.flip() + charBuffer.toString() + } + } catch (e: Throwable) { + buffer.hexDump() + throw RuntimeException(e) } } }