From 22fd71a3eb05b353628c68129cac99f3267e6cf9 Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Wed, 6 Dec 2017 04:51:42 +0100 Subject: [PATCH] Implemented rudimentary chatting --- app/build.gradle.kts | 2 +- .../kuschku/quasseldroid_ng/QuasseldroidNG.kt | 7 +- .../persistence/QuasselDatabase.kt | 11 +- .../quasseldroid_ng/service/QuasselService.kt | 8 +- .../ui/chat/BufferListAdapter.kt | 21 ++- .../ui/chat/BufferViewConfigFragment.kt | 13 +- .../quasseldroid_ng/ui/chat/ChatActivity.kt | 123 ++++++++++-------- .../ui/chat/MessageListFragment.kt | 80 +++++++----- app/src/main/res/layout/activity_main.xml | 40 +++++- app/src/main/res/layout/content_main.xml | 36 ----- app/src/main/res/layout/content_messages.xml | 8 ++ app/src/main/res/menu/main.xml | 10 +- app/src/main/res/values/strings.xml | 2 + .../quassel/syncables/BacklogManager.kt | 4 + .../de/kuschku/libquassel/session/Backend.kt | 2 +- .../de/kuschku/libquassel/session/ISession.kt | 2 + .../de/kuschku/libquassel/session/Session.kt | 2 + .../libquassel/session/SessionManager.kt | 9 +- .../util/compatibility/LoggingHandler.kt | 2 +- 19 files changed, 230 insertions(+), 152 deletions(-) delete mode 100644 app/src/main/res/layout/content_main.xml create mode 100644 app/src/main/res/layout/content_messages.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 44ca3080c..bce3a7a92 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -34,7 +34,7 @@ android { minSdkVersion(16) targetSdkVersion(26) - applicationId = "de.kuschku.quasseldroid_ng.test" + applicationId = "de.kuschku.quasseldroid_ng" versionCode = 1 versionName = cmd("git", "describe", "--tags", "HEAD") ?: "1.0.0" 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 8eac65731..f03aecc1f 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/QuasseldroidNG.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/QuasseldroidNG.kt @@ -1,7 +1,6 @@ package de.kuschku.quasseldroid_ng import android.app.Application -import android.content.Context import android.content.pm.ShortcutInfo import android.content.pm.ShortcutManager import android.graphics.drawable.Icon @@ -13,11 +12,9 @@ import de.kuschku.quasseldroid_ng.util.compatibility.AndroidStreamChannelFactory import de.kuschku.quasseldroid_ng.util.helper.systemService class QuasseldroidNG : Application() { - override fun attachBaseContext(base: Context?) { - super.attachBaseContext(base) - } - override fun onCreate() { + println("QuasseldroidNG::onCreate") + CrashHandler.init( application = this, buildConfig = BuildConfig::class.java 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 bcf7feb38..89d9c7a8e 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 @@ -42,16 +42,19 @@ abstract class QuasselDatabase : RoomDatabase() { @Dao interface MessageDao { @Query("SELECT * FROM message WHERE messageId = :messageId") - fun find(messageId: Int): DatabaseMessage + fun find(messageId: Int): DatabaseMessage? - @Query("SELECT * FROM message WHERE bufferId = :bufferId") + @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC") fun findByBufferId(bufferId: Int): List<DatabaseMessage> - @Query("SELECT * FROM message WHERE bufferId = :bufferId AND messageId < :messageId") + @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC") fun findByBufferIdPaged(bufferId: Int): LivePagedListProvider<Int, DatabaseMessage> @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId DESC LIMIT 1") - fun findLastByBufferId(bufferId: Int): DatabaseMessage + fun findLastByBufferId(bufferId: Int): DatabaseMessage? + + @Query("SELECT * FROM message WHERE bufferId = :bufferId ORDER BY messageId ASC LIMIT 1") + fun findFirstByBufferId(bufferId: Int): DatabaseMessage? @Insert(onConflict = OnConflictStrategy.REPLACE) fun save(vararg entities: DatabaseMessage) 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 76a57ee88..b1394e95c 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 @@ -53,8 +53,8 @@ class QuasselService : LifecycleService() { sessionManager.reconnect() } - override fun disconnect() { - sessionManager.disconnect() + override fun disconnect(forever: Boolean) { + sessionManager.disconnect(forever) } } @@ -80,9 +80,9 @@ class QuasselService : LifecycleService() { } } - override fun disconnect() { + override fun disconnect(forever: Boolean) { handler.post { - backendImplementation.disconnect() + backendImplementation.disconnect(forever) } } 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 f11f3f84c..4eec89285 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 @@ -11,6 +11,7 @@ import android.view.ViewGroup import android.widget.TextView import butterknife.BindView import butterknife.ButterKnife +import de.kuschku.libquassel.protocol.BufferId import de.kuschku.libquassel.quassel.BufferInfo import de.kuschku.libquassel.util.hasFlag @@ -18,7 +19,8 @@ class BufferListAdapter( lifecycleOwner: LifecycleOwner, liveData: LiveData<List<BufferInfo>?>, runInBackground: (() -> Unit) -> Any, - runOnUiThread: (Runnable) -> Any + runOnUiThread: (Runnable) -> Any, + private val clickListener: ((BufferId) -> Unit)? = null ) : RecyclerView.Adapter<BufferListAdapter.BufferViewHolder>() { var data = mutableListOf<BufferInfo>() @@ -48,8 +50,8 @@ class BufferListAdapter( } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = BufferViewHolder( - LayoutInflater.from(parent.context) - .inflate(android.R.layout.simple_list_item_1, parent, false) + LayoutInflater.from(parent.context).inflate(android.R.layout.simple_list_item_1, parent, false), + clickListener = clickListener ) override fun onBindViewHolder(holder: BufferViewHolder, position: Int) @@ -57,12 +59,22 @@ class BufferListAdapter( override fun getItemCount() = data.size - class BufferViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + class BufferViewHolder( + itemView: View, + private val clickListener: ((BufferId) -> Unit)? = null + ) : RecyclerView.ViewHolder(itemView) { @BindView(android.R.id.text1) lateinit var text: TextView + var bufferId: BufferId? = null + init { ButterKnife.bind(this, itemView) + itemView.setOnClickListener { + val buffer = bufferId + if (buffer != null) + clickListener?.invoke(buffer) + } } fun bind(info: BufferInfo) { @@ -70,6 +82,7 @@ class BufferListAdapter( info.type.hasFlag(BufferInfo.Type.StatusBuffer) -> "Network ${info.networkId}" else -> "${info.networkId}/${info.bufferName}" } + bufferId = info.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 d689fa5a8..bcb8e99ed 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 @@ -38,7 +38,7 @@ class BufferViewConfigFragment : ServiceBoundFragment() { @BindView(R.id.chatList) lateinit var chatList: RecyclerView - var currentBuffer: MutableLiveData<BufferId>? = null + val currentBuffer: MutableLiveData<LiveData<BufferId?>?> = MutableLiveData() private val sessionManager: LiveData<SessionManager?> = backend.map(Backend::sessionManager) @@ -92,8 +92,7 @@ class BufferViewConfigFragment : ServiceBoundFragment() { chatListSpinner.adapter = adapter chatListSpinner.onItemSelectedListener = itemSelectedListener - chatList.adapter = BufferListAdapter(this, bufferList, handlerThread::post, - activity::runOnUiThread) + chatList.adapter = BufferListAdapter(this, bufferList, handlerThread::post, activity::runOnUiThread, clickListener) chatList.layoutManager = LinearLayoutManager(context) chatList.itemAnimator = DefaultItemAnimator() return view @@ -103,4 +102,12 @@ class BufferViewConfigFragment : ServiceBoundFragment() { handlerThread.onDestroy() super.onDestroy() } + + val clickListeners = mutableListOf<(BufferId) -> Unit>() + + private val clickListener: ((BufferId) -> Unit)? = { + for (clickListener in clickListeners) { + clickListener.invoke(it) + } + } } 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 8767ac897..e51792e05 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 @@ -2,47 +2,54 @@ package de.kuschku.quasseldroid_ng.ui.chat import android.app.Activity import android.arch.lifecycle.LiveData +import android.arch.lifecycle.MutableLiveData import android.arch.lifecycle.Observer import android.content.Context import android.os.Bundle import android.support.design.widget.Snackbar +import android.support.v4.widget.DrawerLayout +import android.support.v7.app.ActionBarDrawerToggle import android.support.v7.widget.Toolbar -import android.util.Log import android.view.Menu import android.view.MenuItem import android.widget.Button -import android.widget.TextView +import android.widget.EditText import butterknife.BindView import butterknife.ButterKnife +import de.kuschku.libquassel.protocol.BufferId import de.kuschku.libquassel.session.Backend import de.kuschku.libquassel.session.ConnectionState import de.kuschku.libquassel.session.SessionManager import de.kuschku.libquassel.session.SocketAddress -import de.kuschku.libquassel.util.compatibility.LoggingHandler -import de.kuschku.libquassel.util.compatibility.LoggingHandler.LogLevel.INFO import de.kuschku.quasseldroid_ng.Keys import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.persistence.AccountDatabase +import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase import de.kuschku.quasseldroid_ng.util.AndroidHandlerThread import de.kuschku.quasseldroid_ng.util.helper.editApply import de.kuschku.quasseldroid_ng.util.helper.map import de.kuschku.quasseldroid_ng.util.helper.observeSticky import de.kuschku.quasseldroid_ng.util.helper.switchMapRx import de.kuschku.quasseldroid_ng.util.service.ServiceBoundActivity -import org.threeten.bp.ZoneOffset -import org.threeten.bp.ZonedDateTime -import org.threeten.bp.format.DateTimeFormatter class ChatActivity : ServiceBoundActivity() { - @BindView(R.id.clear) - lateinit var clear: Button + var contentMessages: MessageListFragment? = null + var chatListFragment: BufferViewConfigFragment? = null - @BindView(R.id.errorList) - lateinit var errorList: TextView + @BindView(R.id.drawerLayout) + lateinit var drawerLayout: DrawerLayout @BindView(R.id.toolbar) lateinit var toolbar: Toolbar + @BindView(R.id.buttonSend) + lateinit var buttonSend: Button + + @BindView(R.id.input) + lateinit var input: EditText + + private lateinit var drawerToggle: ActionBarDrawerToggle + private val handler = AndroidHandlerThread("Chat") private val sessionManager: LiveData<SessionManager?> = backend.map(Backend::sessionManager) @@ -50,45 +57,36 @@ class ChatActivity : ServiceBoundActivity() { private var snackbar: Snackbar? = null - private val dateTimeFormatter: DateTimeFormatter = DateTimeFormatter.ISO_TIME - private val logHandler = object : LoggingHandler() { - override fun log(logLevel: LogLevel, tag: String, message: String?, - throwable: Throwable?) { - val time = dateTimeFormatter.format(ZonedDateTime.now(ZoneOffset.UTC)) - runOnUiThread { - errorList.append("$time $tag: ") - if (message != null) { - errorList.append(message) - } - if (throwable != null) { - errorList.append("\n") - errorList.append(Log.getStackTraceString(throwable)) - } - errorList.append("\n") - } - } - - override fun isLoggable(logLevel: LogLevel, tag: String) - = (logLevel.ordinal >= INFO.ordinal) - } - - override fun onRestoreInstanceState(savedInstanceState: Bundle?) { - super.onRestoreInstanceState(savedInstanceState) - errorList.text = savedInstanceState?.getString("log", "") ?: "" - } + private val currentBuffer = MutableLiveData<BufferId>() - override fun onSaveInstanceState(outState: Bundle?) { - outState?.putString("log", errorList.text.toString()) - super.onSaveInstanceState(outState) - } + private lateinit var database: QuasselDatabase override fun onCreate(savedInstanceState: Bundle?) { + println("ChatActivity::onCreate") handler.onCreate() super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) ButterKnife.bind(this) + + database = QuasselDatabase.Creator.init(application) + + contentMessages = supportFragmentManager.findFragmentById(R.id.contentMessages) as? MessageListFragment + chatListFragment = supportFragmentManager.findFragmentById(R.id.chatListFragment) as? BufferViewConfigFragment + setSupportActionBar(toolbar) + chatListFragment?.currentBuffer?.value = currentBuffer + contentMessages?.currentBuffer?.value = currentBuffer + + chatListFragment?.clickListeners?.add { + currentBuffer.value = it + println("Changed buffer to $it") + } + + //drawerToggle = ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close) + //actionBar.setDisplayHomeAsUpEnabled(true) + //actionBar.setHomeButtonEnabled(true) + backend.observeSticky(this, Observer { backendValue -> if (backendValue != null) { val database = AccountDatabase.Creator.init(this) @@ -115,15 +113,22 @@ class ChatActivity : ServiceBoundActivity() { } }) - clear.setOnClickListener { - errorList.text = "" + buttonSend.setOnClickListener { + sessionManager.value?.also { sessionManager -> + currentBuffer.value?.also { bufferId -> + sessionManager.bufferSyncer?.bufferInfo(bufferId)?.also { bufferInfo -> + sessionManager.rpcHandler?.sendInput(bufferInfo, input.text.toString()) + } + } + } + input.text.clear() } state.observe(this, Observer { val status = it ?: ConnectionState.DISCONNECTED snackbar?.dismiss() - snackbar = Snackbar.make(errorList, status.name, Snackbar.LENGTH_SHORT) + snackbar = Snackbar.make(window.decorView.rootView, status.name, Snackbar.LENGTH_SHORT) snackbar?.show() }) } @@ -139,27 +144,35 @@ class ChatActivity : ServiceBoundActivity() { getSharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE).editApply { putBoolean(Keys.Status.reconnect, false) } - backend.value?.disconnect() + backend.value?.disconnect(true) setResult(Activity.RESULT_OK) finish() } true } + R.id.loadMore -> handler.post { + currentBuffer.value?.also { bufferId -> + sessionManager.value?.apply { + backlogManager?.requestBacklog( + bufferId = bufferId, + last = database.message().findFirstByBufferId(bufferId)?.messageId ?: -1, + limit = 20 + ) + } + } + } + R.id.clear -> handler.post { + currentBuffer.value?.also { bufferId -> + sessionManager.value?.apply { + backlogStorage.clearMessages(bufferId) + } + } + } else -> super.onOptionsItemSelected(item) } - override fun onStart() { - super.onStart() - LoggingHandler.loggingHandlers.add(logHandler) - } - override fun onDestroy() { handler.onDestroy() super.onDestroy() } - - override fun onStop() { - LoggingHandler.loggingHandlers.remove(logHandler) - super.onStop() - } } 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 9a1d83d1e..3e98bb186 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 @@ -7,67 +7,85 @@ import android.arch.paging.PagedList import android.arch.paging.PagedListAdapter import android.os.Bundle import android.support.v7.recyclerview.extensions.DiffCallback +import android.support.v7.widget.DefaultItemAnimator +import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView +import butterknife.BindView +import butterknife.ButterKnife import de.kuschku.libquassel.protocol.BufferId +import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase import de.kuschku.quasseldroid_ng.util.helper.switchMap import de.kuschku.quasseldroid_ng.util.service.ServiceBoundFragment class MessageListFragment : ServiceBoundFragment() { - var currentBuffer: LiveData<BufferId?> = MutableLiveData() + val currentBuffer: MutableLiveData<LiveData<BufferId?>?> = MutableLiveData() private lateinit var database: QuasselDatabase private val adapter = MessageAdapter() - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) + @BindView(R.id.messageList) + lateinit var messageList: RecyclerView + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + val view = inflater.inflate(R.layout.content_messages, container, false) + ButterKnife.bind(this, view) database = QuasselDatabase.Creator.init(context.applicationContext) val data = currentBuffer.switchMap { - database.message().findByBufferIdPaged(it).create(Int.MAX_VALUE, - PagedList.Config.Builder() - .setPageSize(20) - .setEnablePlaceholders(true) - .setPrefetchDistance(20) - .build() - ) + it.switchMap { + database.message().findByBufferIdPaged(it).create(Int.MAX_VALUE, + PagedList.Config.Builder() + .setPageSize(20) + .setEnablePlaceholders(true) + .setPrefetchDistance(20) + .build() + ) + } } + data.observe(this, Observer { list -> adapter.setList(list) }) - } - class MessageAdapter : PagedListAdapter<QuasselDatabase.DatabaseMessage, MessageViewHolder>(MessageDiffCallback) { - override fun onBindViewHolder(holder: MessageViewHolder?, position: Int) { - holder?.bind(getItem(position)) - } + messageList.adapter = adapter + messageList.layoutManager = LinearLayoutManager(context) + messageList.itemAnimator = DefaultItemAnimator() - override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): MessageViewHolder { - return MessageViewHolder(LayoutInflater.from(parent?.context).inflate(android.R.layout.simple_list_item_1, parent, false)) - } + return view } +} - object MessageDiffCallback : DiffCallback<QuasselDatabase.DatabaseMessage>() { - override fun areContentsTheSame(oldItem: QuasselDatabase.DatabaseMessage, newItem: QuasselDatabase.DatabaseMessage) - = oldItem == newItem +class MessageAdapter : PagedListAdapter<QuasselDatabase.DatabaseMessage, MessageViewHolder>(MessageDiffCallback) { + override fun onBindViewHolder(holder: MessageViewHolder?, position: Int) { + holder?.bind(getItem(position)) + } - override fun areItemsTheSame(oldItem: QuasselDatabase.DatabaseMessage, newItem: QuasselDatabase.DatabaseMessage) - = oldItem.messageId == newItem.messageId + override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): MessageViewHolder { + return MessageViewHolder(LayoutInflater.from(parent?.context).inflate(android.R.layout.simple_list_item_1, parent, false)) } +} - class MessageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - fun bind(message: QuasselDatabase.DatabaseMessage?) { - val text = (itemView as TextView) - if (message == null) { - text.text = "null" - } else { - text.text = "[${message.time}] <${message.senderPrefixes}${message.sender}> ${message.content}" - } +object MessageDiffCallback : DiffCallback<QuasselDatabase.DatabaseMessage>() { + override fun areContentsTheSame(oldItem: QuasselDatabase.DatabaseMessage, newItem: QuasselDatabase.DatabaseMessage) + = oldItem == newItem + + override fun areItemsTheSame(oldItem: QuasselDatabase.DatabaseMessage, newItem: QuasselDatabase.DatabaseMessage) + = oldItem.messageId == newItem.messageId +} + +class MessageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + fun bind(message: QuasselDatabase.DatabaseMessage?) { + val text = (itemView as TextView) + if (message == null) { + text.text = "null" + } else { + text.text = "[${message.time}] <${message.senderPrefixes}${message.sender}> ${message.content}" } } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index b5f90adae..2f9777bab 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,6 +1,7 @@ <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" - android:id="@+id/drawer_layout" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/drawerLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> @@ -83,7 +84,39 @@ </android.support.design.widget.AppBarLayout> - <include layout="@layout/content_main" /> + <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/content_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"> + + <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" /> + </LinearLayout> + + </android.support.v7.widget.CardView> </LinearLayout> @@ -101,6 +134,7 @@ android:id="@+id/chatListFragment" android:name="de.kuschku.quasseldroid_ng.ui.chat.BufferViewConfigFragment" android:layout_width="match_parent" - android:layout_height="match_parent" /> + android:layout_height="match_parent" + tools:layout="@layout/content_chat_list" /> </de.kuschku.quasseldroid_ng.util.ui.NavigationDrawerLayout> </android.support.v4.widget.DrawerLayout> diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml deleted file mode 100644 index 4c0a9bf4f..000000000 --- a/app/src/main/res/layout/content_main.xml +++ /dev/null @@ -1,36 +0,0 @@ -<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="?attr/colorBackground" - tools:showIn="@layout/activity_main"> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginBottom="8dp" - android:layout_marginTop="8dp" - android:orientation="vertical" - android:paddingLeft="24dp" - android:paddingRight="24dp"> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content"> - - <Button - android:id="@+id/clear" - style="@style/Widget.Button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:minWidth="88dp" - android:text="Clear" /> - </LinearLayout> - - <TextView - android:id="@+id/errorList" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:textIsSelectable="true" /> - </LinearLayout> -</ScrollView> diff --git a/app/src/main/res/layout/content_messages.xml b/app/src/main/res/layout/content_messages.xml new file mode 100644 index 000000000..cce02ed3b --- /dev/null +++ b/app/src/main/res/layout/content_messages.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/messageList" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="?attr/colorBackground" + tools:listitem="@android:layout/simple_list_item_1" /> \ No newline at end of file diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml index 2079987d4..1f23bf3b4 100644 --- a/app/src/main/res/menu/main.xml +++ b/app/src/main/res/menu/main.xml @@ -1,5 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> -<menu xmlns:android="http://schemas.android.com/apk/res/android"> +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + <item + android:id="@+id/loadMore" + android:title="Load More" + app:showAsAction="always" /> + <item + android:id="@+id/clear" + android:title="Delete History" /> <item android:id="@+id/settings" android:title="Settings" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5748b2baf..8e98b5f95 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -5,4 +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> </resources> 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 598f70e39..7d8b5c902 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 @@ -11,6 +11,10 @@ class BacklogManager( proxy: SignalProxy, private val backlogStorage: BacklogStorage ) : SyncableObject(proxy, "BacklogManager"), IBacklogManager { + init { + initialized = true + } + override fun receiveBacklog(bufferId: BufferId, first: MsgId, last: MsgId, limit: Int, additional: Int, messages: QVariantList) { for (message: Message in messages.mapNotNull<QVariant_, Message>(QVariant_::value)) { diff --git a/lib/src/main/java/de/kuschku/libquassel/session/Backend.kt b/lib/src/main/java/de/kuschku/libquassel/session/Backend.kt index ff51c4acb..529c0210a 100644 --- a/lib/src/main/java/de/kuschku/libquassel/session/Backend.kt +++ b/lib/src/main/java/de/kuschku/libquassel/session/Backend.kt @@ -4,6 +4,6 @@ interface Backend { fun connectUnlessConnected(address: SocketAddress, user: String, pass: String, reconnect: Boolean) fun connect(address: SocketAddress, user: String, pass: String, reconnect: Boolean) fun reconnect() - fun disconnect() + fun disconnect(forever: Boolean = false) fun sessionManager(): SessionManager } diff --git a/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt b/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt index b5f4c0990..991c3f309 100644 --- a/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt +++ b/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt @@ -22,9 +22,11 @@ interface ISession : Closeable { val ircListHelper: IrcListHelper? val networks: Map<NetworkId, Network> val networkConfig: NetworkConfig? + val rpcHandler: RpcHandler? companion object { val NULL = object : ISession { + override val rpcHandler: RpcHandler? = null override val aliasManager: AliasManager? = null override val backlogManager: BacklogManager? = null override val bufferSyncer: BufferSyncer? = null 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 14edd30e5..fbfbc2061 100644 --- a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt +++ b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt @@ -88,6 +88,8 @@ class Session( synchronize(ircListHelper, true) synchronize(networkConfig, true) + synchronize(backlogManager) + 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 0385cf9c6..545a2da00 100644 --- a/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt +++ b/lib/src/main/java/de/kuschku/libquassel/session/SessionManager.kt @@ -13,7 +13,7 @@ import io.reactivex.Observable import io.reactivex.subjects.BehaviorSubject import javax.net.ssl.X509TrustManager -class SessionManager(offlineSession: ISession, private val backlogStorage: BacklogStorage) : ISession { +class SessionManager(offlineSession: ISession, val backlogStorage: BacklogStorage) : ISession { override val aliasManager: AliasManager? get() = session.or(lastSession).aliasManager override val backlogManager: BacklogManager? @@ -38,6 +38,8 @@ class SessionManager(offlineSession: ISession, private val backlogStorage: Backl get() = session.or(lastSession).networks override val networkConfig: NetworkConfig? get() = session.or(lastSession).networkConfig + override val rpcHandler: RpcHandler? + get() = session.or(lastSession).rpcHandler override fun close() = session.or(lastSession).close() @@ -95,8 +97,9 @@ class SessionManager(offlineSession: ISession, private val backlogStorage: Backl } } - fun disconnect() { - inProgressSession.value + fun disconnect(forever: Boolean) { + if (forever) + backlogStorage.clearMessages() inProgressSession.value.close() inProgressSession.onNext(ISession.NULL) } diff --git a/lib/src/main/java/de/kuschku/libquassel/util/compatibility/LoggingHandler.kt b/lib/src/main/java/de/kuschku/libquassel/util/compatibility/LoggingHandler.kt index 261b46ea0..73aa925a3 100644 --- a/lib/src/main/java/de/kuschku/libquassel/util/compatibility/LoggingHandler.kt +++ b/lib/src/main/java/de/kuschku/libquassel/util/compatibility/LoggingHandler.kt @@ -11,7 +11,7 @@ abstract class LoggingHandler { if (isLoggable(logLevel, tag)) { object : LogContext { override fun log(message: String?, throwable: Throwable?) { - log(logLevel, tag, message, throwable) + this@LoggingHandler.log(logLevel, tag, message, throwable) } }.f() } -- GitLab