From 5c3e26a46a221221a0233a23e784b87c6127c764 Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Tue, 18 Dec 2018 09:42:27 +0100
Subject: [PATCH] Automatically connect to newly created networks

---
 .../quasseldroid/service/AsyncBackend.kt      |  4 +
 .../quasseldroid/service/QuasselService.kt    | 14 ++++
 .../network/NetworkCreateFragment.kt          |  2 +
 .../ui/setup/user/UserSetupActivity.kt        | 74 ++++++++-----------
 .../quassel/syncables/SyncableObject.kt       | 12 ++-
 .../syncables/interfaces/ISyncableObject.kt   |  2 +
 .../de/kuschku/libquassel/session/Backend.kt  |  1 +
 .../de/kuschku/libquassel/session/ISession.kt |  3 +
 .../de/kuschku/libquassel/session/Session.kt  |  4 +
 9 files changed, 73 insertions(+), 43 deletions(-)

diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt b/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt
index 293f9d077..29791d8e7 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/AsyncBackend.kt
@@ -63,4 +63,8 @@ class AsyncBackend(
   }
 
   override fun sessionManager() = backend.sessionManager()
+
+  override fun requestConnectNewNetwork() {
+    backend.requestConnectNewNetwork()
+  }
 }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
index b6dfc8799..06d643d8f 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/service/QuasselService.kt
@@ -273,6 +273,20 @@ class QuasselService : DaggerLifecycleService(),
     override fun disconnect(forever: Boolean) {
       sessionManager.disconnect(forever)
     }
+
+    override fun requestConnectNewNetwork() {
+      sessionManager.session.flatMap(ISession::liveNetworkAdded).firstElement().flatMap { id ->
+        sessionManager.session.flatMap(ISession::liveNetworks)
+          .map { it[id] }
+          .flatMap { network ->
+            network.liveInitialized
+              .filter { it }
+              .map { network }
+          }.firstElement()
+      }.toLiveData().observe(this@QuasselService, Observer {
+        it?.requestConnect()
+      })
+    }
   }
 
   private val handlerService = AndroidHandlerService()
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateFragment.kt
index a611ff3f3..a7a7b42ce 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/network/NetworkCreateFragment.kt
@@ -19,12 +19,14 @@
 
 package de.kuschku.quasseldroid.ui.coresettings.network
 
+import de.kuschku.libquassel.session.Backend
 import de.kuschku.libquassel.util.helpers.value
 
 class NetworkCreateFragment : NetworkBaseFragment(true) {
   override fun onSave() = viewModel.session.value?.orNull()?.let { session ->
     network?.let { (_, data) ->
       applyChanges(data)
+      viewModel.backend.value?.ifPresent(Backend::requestConnectNewNetwork)
       session.rpcHandler?.createNetwork(data.networkInfo(), emptyList())
       true
     }
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/user/UserSetupActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/user/UserSetupActivity.kt
index 7d8eee924..52d1f539c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/user/UserSetupActivity.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/user/UserSetupActivity.kt
@@ -25,9 +25,7 @@ import android.content.Intent
 import android.os.Bundle
 import androidx.lifecycle.Observer
 import de.kuschku.libquassel.protocol.IdentityId
-import de.kuschku.libquassel.protocol.NetworkId
 import de.kuschku.libquassel.quassel.syncables.Identity
-import de.kuschku.libquassel.quassel.syncables.Network
 import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
 import de.kuschku.libquassel.util.helpers.value
 import de.kuschku.quasseldroid.R
@@ -45,52 +43,44 @@ class UserSetupActivity : ServiceBoundSetupActivity() {
     }
 
   override fun onDone(data: Bundle) {
-    runInBackground {
       val network = data.getSerializable("network") as? DefaultNetwork
       if (network != null) {
-        viewModel.session.value?.orNull()?.rpcHandler?.apply {
-          createIdentity(Defaults.identity(this@UserSetupActivity).apply {
-            setIdentityName(this@UserSetupActivity.getString(R.string.default_identity_identity_name))
-            setNicks(listOf(data.getString("nick")))
-            setRealName(data.getString("realname"))
-          }, emptyMap())
+        viewModel.backend?.value?.ifPresent { backend ->
+          viewModel.session.value?.orNull()?.rpcHandler?.apply {
+            createIdentity(Defaults.identity(this@UserSetupActivity).apply {
+              setIdentityName(this@UserSetupActivity.getString(R.string.default_identity_identity_name))
+              setNicks(listOf(data.getString("nick")))
+              setRealName(data.getString("realname"))
+            }, emptyMap())
 
-          viewModel.identities
-            .map(Map<IdentityId, Identity>::values)
-            .filter(Collection<Identity>::isNotEmpty)
-            .map(Collection<Identity>::first)
-            .firstElement()
-            .toLiveData().observe(this@UserSetupActivity, Observer {
-              if (it != null) {
-                createNetwork(INetwork.NetworkInfo(
-                  networkName = network.name,
-                  identity = it.id(),
-                  serverList = network.servers.map {
-                    INetwork.Server(
-                      host = it.host,
-                      port = it.port,
-                      useSsl = it.secure
-                    )
-                  }
-                ), data.getStringArray("channels")?.toList().orEmpty())
-              }
-            })
+            viewModel.identities
+              .map(Map<IdentityId, Identity>::values)
+              .filter(Collection<Identity>::isNotEmpty)
+              .map(Collection<Identity>::first)
+              .firstElement()
+              .toLiveData().observe(this@UserSetupActivity, Observer {
+                if (it != null) {
+                  createNetwork(INetwork.NetworkInfo(
+                    networkName = network.name,
+                    identity = it.id(),
+                    serverList = network.servers.map {
+                      INetwork.Server(
+                        host = it.host,
+                        port = it.port,
+                        useSsl = it.secure
+                      )
+                    }
+                  ), data.getStringArray("channels")?.toList().orEmpty())
 
-          viewModel.networks
-            .map(Map<NetworkId, Network>::values)
-            .filter(Collection<Network>::isNotEmpty)
-            .map(Collection<Network>::first)
-            .firstElement()
-            .toLiveData().observe(this@UserSetupActivity, Observer {
-              it?.requestConnect()
-              runOnUiThread {
-                setResult(Activity.RESULT_OK)
-                finish()
-              }
-            })
+                  backend.requestConnectNewNetwork()
+
+                  setResult(Activity.RESULT_OK)
+                  finish()
+                }
+              })
+          }
         }
       }
-    }
   }
 
   override val fragments = listOf(
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/SyncableObject.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/SyncableObject.kt
index 7a5ebdf7d..a86753f43 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/SyncableObject.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/SyncableObject.kt
@@ -21,6 +21,8 @@ package de.kuschku.libquassel.quassel.syncables
 
 import de.kuschku.libquassel.quassel.syncables.interfaces.ISyncableObject
 import de.kuschku.libquassel.session.SignalProxy
+import io.reactivex.Observable
+import io.reactivex.subjects.BehaviorSubject
 
 abstract class SyncableObject(
   override val proxy: SignalProxy,
@@ -29,7 +31,15 @@ abstract class SyncableObject(
   final override var objectName: String = ""
     private set
   override var identifier = Pair(className, objectName)
-  override var initialized: Boolean = false
+  override var initialized: Boolean
+    get() = _liveInitialized.value
+    set(value) {
+      _liveInitialized.onNext(value)
+    }
+
+  private val _liveInitialized = BehaviorSubject.createDefault(false)
+  override val liveInitialized: Observable<Boolean>
+    get() = _liveInitialized
 
   protected fun renameObject(newName: String) {
     val oldName = objectName
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt
index ffd22aab8..16308a690 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/interfaces/ISyncableObject.kt
@@ -24,6 +24,7 @@ import de.kuschku.libquassel.protocol.QVariantMap
 import de.kuschku.libquassel.protocol.QVariant_
 import de.kuschku.libquassel.protocol.Type
 import de.kuschku.libquassel.session.SignalProxy
+import io.reactivex.Observable
 
 interface ISyncableObject {
   val objectName: String
@@ -31,6 +32,7 @@ interface ISyncableObject {
   val className: String
   var initialized: Boolean
   val proxy: SignalProxy
+  val liveInitialized: Observable<Boolean>
 
   fun requestUpdate(properties: QVariantMap = toVariantMap()) {
     REQUEST("requestUpdate", ARG(properties, Type.QVariantMap))
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 d661831f4..bc5693714 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/Backend.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/Backend.kt
@@ -28,4 +28,5 @@ interface Backend {
   fun disconnect(forever: Boolean = false)
   fun sessionManager(): SessionManager
   fun updateUserDataAndLogin(user: String, pass: String)
+  fun requestConnectNewNetwork()
 }
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 d9316a931..4f1e51cd7 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/ISession.kt
@@ -30,6 +30,7 @@ import io.reactivex.BackpressureStrategy
 import io.reactivex.Flowable
 import io.reactivex.Observable
 import io.reactivex.subjects.BehaviorSubject
+import io.reactivex.subjects.PublishSubject
 import java.io.Closeable
 import javax.net.ssl.SSLSession
 
@@ -52,6 +53,7 @@ interface ISession : Closeable {
   val ircListHelper: IrcListHelper?
   val networks: Map<NetworkId, Network>
   fun liveNetworks(): Observable<Map<NetworkId, Network>>
+  fun liveNetworkAdded(): Observable<NetworkId>
   val networkConfig: NetworkConfig?
   val rpcHandler: RpcHandler?
   val initStatus: Observable<Pair<Int, Int>>
@@ -93,6 +95,7 @@ interface ISession : Closeable {
       override val ircListHelper: IrcListHelper? = null
       override val networks: Map<NetworkId, Network> = emptyMap()
       override fun liveNetworks() = Observable.empty<Map<NetworkId, Network>>()
+      override fun liveNetworkAdded(): Observable<NetworkId> = PublishSubject.create()
       override val networkConfig: NetworkConfig? = null
       override val initStatus: Observable<Pair<Int, Int>> = Observable.just(0 to 0)
       override val lag: Observable<Long> = Observable.just(0L)
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 b723f7a86..6e4491664 100644
--- a/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/session/Session.kt
@@ -96,6 +96,9 @@ class Session(
   private val live_networks = BehaviorSubject.createDefault(Unit)
   override fun liveNetworks(): Observable<Map<NetworkId, Network>> = live_networks.map { networks.toMap() }
 
+  private val network_added = PublishSubject.create<NetworkId>()
+  override fun liveNetworkAdded(): Observable<NetworkId> = network_added
+
   override val networkConfig = NetworkConfig(this)
 
   override var rpcHandler: RpcHandler? = RpcHandler(this, backlogStorage, notificationManager)
@@ -168,6 +171,7 @@ class Session(
     networks[networkId] = network
     synchronize(network)
     live_networks.onNext(Unit)
+    network_added.onNext(networkId)
   }
 
   fun removeNetwork(networkId: NetworkId) {
-- 
GitLab