From 8aa612ea692469ef7a35e4a53e137100d3276ff5 Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Wed, 7 Sep 2016 23:04:09 +0200
Subject: [PATCH] Finished identity editing

---
 app/src/main/AndroidManifest.xml              |  2 +-
 .../de/kuschku/libquassel/client/AClient.java | 21 +++--
 .../de/kuschku/libquassel/client/Client.java  |  1 +
 .../de/kuschku/libquassel/client/QClient.java |  2 +-
 .../primitives/QMetaTypeRegistry.java         |  3 +-
 .../libquassel/primitives/types/QVariant.java | 17 ++--
 .../syncables/types/SyncableObject.java       | 13 +++-
 .../types/impl/BufferViewConfig.java          |  3 +-
 .../syncables/types/impl/Identity.java        |  2 +-
 .../quasseldroid_ng/ui/chat/MainActivity.java | 45 +++++++----
 .../ui/chat/drawer/NetworkItem.java           |  4 +
 .../identity/IdentityCreateActivity.java      | 17 ++--
 .../identity/IdentityEditActivity.java        | 45 ++++++-----
 .../identity/IdentityListActivity.java        |  3 +-
 .../identity/IdentitySpinnerAdapter.java      | 78 ++++++++++---------
 .../nick/IdentityNickListActivity.java        |  3 +
 .../network/NetworkCreateActivity.java        |  4 +-
 .../network/NetworkEditActivity.java          | 74 +++++++++---------
 .../util/niohelpers/WrappedChannel.java       |  4 +-
 .../observables/lists/ObservableList.java     |  8 +-
 20 files changed, 200 insertions(+), 149 deletions(-)

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 999982773..30f732755 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -111,7 +111,7 @@
 
         <activity
             android:name=".ui.coresettings.identity.IdentityListActivity"
-            android:label="Edit Networks"
+            android:label="Edit Identities"
             android:launchMode="singleTask"
             android:parentActivityName=".ui.chat.MainActivity"
             android:theme="@style/AppTheme.Light"/>
diff --git a/app/src/main/java/de/kuschku/libquassel/client/AClient.java b/app/src/main/java/de/kuschku/libquassel/client/AClient.java
index 74d546fd3..d83fef0f2 100644
--- a/app/src/main/java/de/kuschku/libquassel/client/AClient.java
+++ b/app/src/main/java/de/kuschku/libquassel/client/AClient.java
@@ -23,8 +23,7 @@ package de.kuschku.libquassel.client;
 
 import android.support.annotation.NonNull;
 
-import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -53,43 +52,43 @@ public abstract class AClient<T extends AClient<T>> extends SyncableObject<T> im
     }
 
     @Override
-    public void createIdentity(QIdentity identity) {
-        smartRpc("createIdentity(Identity,QVariantMap)", identity);
+    public void createIdentity(QIdentity identity, Map<String, QVariant> certs) {
+        smartRpcTyped("createIdentity(Identity,QVariantMap)", new QVariant<>(identity), new QVariant<>(certs));
     }
 
     @Override
     public void updateIdentity(int id, Map<String, QVariant> serialized) {
-        smartRpc("updateIdenity(IdentityId,QVariantMap)", id, serialized);
+        smartRpcTyped("updateIdenity(IdentityId,QVariantMap)", new QVariant<>("IdentityId", id), new QVariant<>(serialized));
     }
 
     @Override
     public void removeIdentity(int id) {
-        smartRpc("removeIdentity(IdentityId)", id);
+        smartRpcTyped("removeIdentity(IdentityId)", new QVariant<>("IdentityId", id));
     }
 
     @Override
     public void createNetwork(NetworkInfo info) {
-        createNetwork(info, new ArrayList<>(0));
+        createNetwork(info, Collections.emptyList());
     }
 
     @Override
     public void createNetwork(NetworkInfo info, List<String> persistentChannels) {
-        rpc("2createNetwork(NetworkInfo,QStringList)", Arrays.asList(new QVariant<>(info), new QVariant<>(QMetaType.Type.QStringList, persistentChannels)));
+        smartRpcTyped("createNetwork(NetworkInfo,QStringList)", new QVariant<>(info), new QVariant<>(QMetaType.Type.QStringList, persistentChannels));
     }
 
     @Override
     public void updateNetwork(NetworkInfo info) {
-        smartRpc("updateNetwork(NetworkInfo)", info);
+        smartRpc("updateNetwork(NetworkInfo)", new QVariant<>(info));
     }
 
     @Override
     public void removeNetwork(int id) {
-        smartRpc("removeNetwork(NetworkId)", id);
+        smartRpcTyped("removeNetwork(NetworkId)", new QVariant<>("NetworkId", id));
     }
 
     @Override
     public void changePassword(String username, String oldPassword, String newPassword) {
-        smartRpc("changePassword(PeerPtr,QString,QString,QString)", 0x0000000000000000L, username, oldPassword, newPassword);
+        smartRpc("changePassword(PeerPtr,QString,QString,QString)", new QVariant<>("PeerPtr", 0x0000000000000000L), new QVariant<>(username), new QVariant<>(oldPassword), new QVariant<>(newPassword));
     }
 
     @Override
diff --git a/app/src/main/java/de/kuschku/libquassel/client/Client.java b/app/src/main/java/de/kuschku/libquassel/client/Client.java
index d67818b8d..1bc37157d 100644
--- a/app/src/main/java/de/kuschku/libquassel/client/Client.java
+++ b/app/src/main/java/de/kuschku/libquassel/client/Client.java
@@ -154,6 +154,7 @@ public class Client extends AClient {
     @Override
     public void _identityCreated(@NonNull Identity identity) {
         identityManager.createIdentity(identity);
+        identity.init(String.valueOf(identity.id()), provider, this);
     }
 
     @Override
diff --git a/app/src/main/java/de/kuschku/libquassel/client/QClient.java b/app/src/main/java/de/kuschku/libquassel/client/QClient.java
index 0da325b31..a615d92e6 100644
--- a/app/src/main/java/de/kuschku/libquassel/client/QClient.java
+++ b/app/src/main/java/de/kuschku/libquassel/client/QClient.java
@@ -41,7 +41,7 @@ public interface QClient {
     void sendInput(Command command);
 
     @Synced
-    void createIdentity(QIdentity identity);
+    void createIdentity(QIdentity identity, Map<String, QVariant> certs);
 
     @Synced
     void updateIdentity(int id, final Map<String, QVariant> serialized);
diff --git a/app/src/main/java/de/kuschku/libquassel/primitives/QMetaTypeRegistry.java b/app/src/main/java/de/kuschku/libquassel/primitives/QMetaTypeRegistry.java
index 9b92775c0..953283f6f 100644
--- a/app/src/main/java/de/kuschku/libquassel/primitives/QMetaTypeRegistry.java
+++ b/app/src/main/java/de/kuschku/libquassel/primitives/QMetaTypeRegistry.java
@@ -289,8 +289,9 @@ public class QMetaTypeRegistry {
         else if (type instanceof Message) return stringSerializerMap.get("Message");
         else if (type instanceof BufferInfo) return stringSerializerMap.get("BufferInfo");
         else if (type instanceof NetworkInfo) return stringSerializerMap.get("NetworkInfo");
+        else if (type instanceof QIdentity) return stringSerializerMap.get("Identity");
         else if (type instanceof NetworkServer) return stringSerializerMap.get("Network::Server");
         else
-            throw new AssertionError("Unsupported data type: " + type.getClass().getSimpleName());
+            return null;
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/primitives/types/QVariant.java b/app/src/main/java/de/kuschku/libquassel/primitives/types/QVariant.java
index 40453d6f7..3e3e1df20 100644
--- a/app/src/main/java/de/kuschku/libquassel/primitives/types/QVariant.java
+++ b/app/src/main/java/de/kuschku/libquassel/primitives/types/QVariant.java
@@ -39,16 +39,19 @@ public class QVariant<T> {
     public final QMetaType<T> type;
 
     public QVariant(@NonNull T data) {
-        if (data instanceof QSyncableObject) {
-            this.data = (T) SyncableRegistry.toVariantMap((QSyncableObject) data);
-            this.type = QMetaTypeRegistry.getTypeByObject(this.data);
-        } else if (data instanceof Set) {
+        if (data instanceof Set) {
             this.data = (T) new ArrayList((Set) data);
-            this.type = QMetaTypeRegistry.getTypeByObject(this.data);
         } else {
-            this.data = data;
-            this.type = QMetaTypeRegistry.getTypeByObject(this.data);
+            if (QMetaTypeRegistry.getTypeByObject(data) != null) {
+                this.data = data;
+            } else if (data instanceof QSyncableObject) {
+                this.data = (T) SyncableRegistry.toVariantMap((QSyncableObject) data);
+            } else {
+                throw new IllegalArgumentException();
+            }
         }
+
+        this.type = QMetaTypeRegistry.getTypeByObject(this.data);
     }
 
     public QVariant(@NonNull QMetaType<T> type, @Nullable T data) {
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/SyncableObject.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/SyncableObject.java
index 137114850..ca3142bd7 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/SyncableObject.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/SyncableObject.java
@@ -26,6 +26,7 @@ import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import de.kuschku.libquassel.BusProvider;
@@ -39,6 +40,7 @@ import de.kuschku.util.observables.callbacks.GeneralObservable;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
 
 public abstract class SyncableObject<T> extends GeneralObservable<T> implements QSyncableObject<T> {
     @Nullable
@@ -53,12 +55,14 @@ public abstract class SyncableObject<T> extends GeneralObservable<T> implements
     }
 
     public void sync(@NonNull String methodName, @NonNull Object[] params) {
+        assertTrue(initialized);
         assertNotNull(provider);
 
         provider.dispatch(new SyncFunction<>(getClassName(), getObjectName(), methodName, toVariantList(params)));
     }
 
     public void sync(@NonNull String methodName, @NonNull String[] strings, @NonNull Object[] objects) {
+        assertTrue(initialized);
         assertNotNull(provider);
         assertEquals(strings.length, objects.length);
 
@@ -93,6 +97,10 @@ public abstract class SyncableObject<T> extends GeneralObservable<T> implements
             setObjectName(objectName);
     }
 
+    public void smartRpcTyped(@NonNull String procedureName, @NonNull QVariant... params) {
+        rpcTyped("2" + procedureName, Arrays.asList(params));
+    }
+
     public void smartRpc(@NonNull String procedureName, @NonNull Object... params) {
         rpc("2" + procedureName, params);
     }
@@ -101,7 +109,8 @@ public abstract class SyncableObject<T> extends GeneralObservable<T> implements
         rpc(procedureName, params);
     }
 
-    public void rpc(@NonNull String procedureName, @NonNull List<QVariant> params) {
+    public void rpcTyped(@NonNull String procedureName, @NonNull List<QVariant> params) {
+        assertTrue(initialized);
         assertNotNull(provider);
 
         RpcCallFunction function = new RpcCallFunction(procedureName, params);
@@ -109,7 +118,7 @@ public abstract class SyncableObject<T> extends GeneralObservable<T> implements
     }
 
     public void rpc(@NonNull String procedureName, @NonNull Object[] params) {
-        rpc(procedureName, toVariantList(params));
+        rpcTyped(procedureName, toVariantList(params));
     }
 
     @NonNull
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java
index 31beb3598..ad89470fb 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java
@@ -133,7 +133,8 @@ public class BufferViewConfig extends ABufferViewConfig {
     @Override
     public void _setNetworkId(int networkId) {
         this.networkId = networkId;
-        updateNetworks();
+        if (initialized)
+            updateNetworks();
         _update();
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Identity.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Identity.java
index b8c46c5ab..8928e6e73 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Identity.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Identity.java
@@ -83,7 +83,7 @@ public class Identity extends AIdentity {
     public static Identity createDefault() {
         return new Identity(
                 -1,
-                "",
+                "Standardidentity",
                 "Quassel IRC User",
                 Collections.singletonList("quassel"),
                 "",
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java
index 477e5b33f..bb18a24a7 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java
@@ -138,6 +138,9 @@ public class MainActivity extends BoundActivity {
     private BufferViewConfigAdapter chatListAdapter;
     private Fragment currentFragment;
 
+    private Bundle coreSetupResult;
+    private boolean coreSetupCancelled;
+
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -498,20 +501,9 @@ public class MainActivity extends BoundActivity {
         switch (requestCode) {
             case REQUEST_CODE_CORESETUP: {
                 if (resultCode == RESULT_OK) {
-                    context.provider().event.removeStickyEvent(CoreSetupRequiredEvent.class);
-
-                    Account account = manager.account(context.settings().preferenceLastAccount.get());
-                    Bundle config = data.getParcelableExtra("config");
-                    Map<String, QVariant> configData = new HashMap<>();
-                    for (String key : config.keySet()) {
-                        configData.put(key, new QVariant<>(config.get(key)));
-                    }
-                    context.provider().dispatch(new HandshakeFunction(new CoreSetupData(new SetupData(
-                            account.user,
-                            account.pass,
-                            data.getStringExtra("selectedBackend"),
-                            configData
-                    ))));
+                    coreSetupResult = data.getExtras();
+                } else {
+                    coreSetupCancelled = true;
                 }
             }
             break;
@@ -538,9 +530,28 @@ public class MainActivity extends BoundActivity {
 
     @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
     public void onEventMainThread(CoreSetupRequiredEvent event) {
-        Intent intent = new Intent(getApplicationContext(), CoreSetupActivity.class);
-        intent.putExtra("storageBackends", context.client().core().getStorageBackendsAsBundle());
-        startActivityForResult(intent, REQUEST_CODE_CORESETUP);
+        if (coreSetupCancelled) {
+            finish();
+        } else if (coreSetupResult != null) {
+            context.provider().event.removeStickyEvent(CoreSetupRequiredEvent.class);
+
+            Account account = manager.account(context.settings().preferenceLastAccount.get());
+            Bundle config = coreSetupResult.getBundle("config");
+            Map<String, QVariant> configData = new HashMap<>();
+            for (String key : config.keySet()) {
+                configData.put(key, new QVariant<>(config.get(key)));
+            }
+            context.provider().dispatch(new HandshakeFunction(new CoreSetupData(new SetupData(
+                    account.user,
+                    account.pass,
+                    coreSetupResult.getString("selectedBackend"),
+                    configData
+            ))));
+        } else {
+            Intent intent = new Intent(getApplicationContext(), CoreSetupActivity.class);
+            intent.putExtra("storageBackends", context.client().core().getStorageBackendsAsBundle());
+            startActivityForResult(intent, REQUEST_CODE_CORESETUP);
+        }
     }
 
     @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkItem.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkItem.java
index ec46f7a0a..451d91655 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkItem.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkItem.java
@@ -22,6 +22,7 @@
 package de.kuschku.quasseldroid_ng.ui.chat.drawer;
 
 import android.databinding.Observable;
+import android.util.Log;
 
 import com.bignerdranch.expandablerecyclerview.Model.ParentListItem;
 
@@ -118,6 +119,9 @@ public class NetworkItem implements ParentListItem {
         this.buffers.addCallback(new UICallback() {
             @Override
             public void notifyItemInserted(int position) {
+                Log.d("DEBUG", "Added item at " + position);
+                Log.d("DEBUG", String.valueOf(getChildItemList()));
+
                 bufferViewConfigAdapter.notifyChildItemInserted(NetworkItem.this, position);
             }
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentityCreateActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentityCreateActivity.java
index dc6dcc8e8..8a2f582ca 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentityCreateActivity.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentityCreateActivity.java
@@ -34,13 +34,14 @@ import android.widget.CompoundButton;
 import android.widget.EditText;
 
 import java.util.ArrayList;
+import java.util.Collections;
 
 import butterknife.Bind;
 import butterknife.ButterKnife;
 import de.kuschku.libquassel.syncables.types.impl.Identity;
 import de.kuschku.libquassel.syncables.types.interfaces.QIdentity;
 import de.kuschku.quasseldroid_ng.R;
-import de.kuschku.quasseldroid_ng.ui.coresettings.network.server.NetworkServerListActivity;
+import de.kuschku.quasseldroid_ng.ui.coresettings.identity.nick.IdentityNickListActivity;
 import de.kuschku.util.servicebound.BoundActivity;
 import de.kuschku.util.ui.AnimationHelper;
 
@@ -99,7 +100,7 @@ public class IdentityCreateActivity extends BoundActivity {
         updateAwayOnDetachReasonVisible(null, useAwayOnDetach.isChecked());
 
         nicks.setOnClickListener(v -> {
-            Intent intent1 = new Intent(IdentityCreateActivity.this, NetworkServerListActivity.class);
+            Intent intent1 = new Intent(IdentityCreateActivity.this, IdentityNickListActivity.class);
             intent1.putStringArrayListExtra("nicks", nickList);
             startActivityForResult(intent1, 0, null);
         });
@@ -109,9 +110,11 @@ public class IdentityCreateActivity extends BoundActivity {
 
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        ArrayList<String> nickList = data.getStringArrayListExtra("nicks");
-        if (nickList != null)
-            this.nickList = nickList;
+        if (data != null) {
+            ArrayList<String> nickList = data.getStringArrayListExtra("nicks");
+            if (nickList != null)
+                this.nickList = nickList;
+        }
     }
 
     private void updateAwayOnDetachReasonVisible(CompoundButton button, boolean visible) {
@@ -167,12 +170,12 @@ public class IdentityCreateActivity extends BoundActivity {
                         newIdentity._setAwayReason(awayReason.getText().toString());
 
                     if (!identity.detachAwayEnabled() == useAwayOnDetach.isChecked())
-                        newIdentity.setDetachAwayEnabled(useAwayOnDetach.isChecked());
+                        newIdentity._setDetachAwayEnabled(useAwayOnDetach.isChecked());
 
                     if (!identity.detachAwayReason().equals(awayOnDetachReason.getText().toString()))
                         newIdentity._setDetachAwayReason(awayOnDetachReason.getText().toString());
 
-                    context.client().createIdentity(newIdentity);
+                    context.client().createIdentity(newIdentity, Collections.emptyMap());
 
                     finish();
                 }
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentityEditActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentityEditActivity.java
index 39d1d5fa0..c352ce24b 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentityEditActivity.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentityEditActivity.java
@@ -176,7 +176,7 @@ public class IdentityEditActivity extends BoundActivity {
                         newIdentity._setAwayReason(awayReason.getText().toString());
 
                     if (!identity.detachAwayEnabled() == useAwayOnDetach.isChecked())
-                        newIdentity.setDetachAwayEnabled(useAwayOnDetach.isChecked());
+                        newIdentity._setDetachAwayEnabled(useAwayOnDetach.isChecked());
 
                     if (!identity.detachAwayReason().equals(awayOnDetachReason.getText().toString()))
                         newIdentity._setDetachAwayReason(awayOnDetachReason.getText().toString());
@@ -201,35 +201,38 @@ public class IdentityEditActivity extends BoundActivity {
         QIdentity oldIdentity = this.identity;
         this.identity = identity;
 
-        if (oldIdentity == null || identityName.getText().toString().equals(oldIdentity.identityName()))
-            this.identityName.setText(identity.identityName());
+        if (identity != null) {
 
-        if (oldIdentity == null || realName.getText().toString().equals(oldIdentity.realName()))
-            this.realName.setText(identity.realName());
+            if (oldIdentity == null || identityName.getText().toString().equals(oldIdentity.identityName()))
+                this.identityName.setText(identity.identityName());
 
-        if (oldIdentity == null || ident.getText().toString().equals(oldIdentity.ident()))
-            this.ident.setText(identity.ident());
+            if (oldIdentity == null || realName.getText().toString().equals(oldIdentity.realName()))
+                this.realName.setText(identity.realName());
 
-        if (oldIdentity == null || nickList.equals(new ArrayList<>(oldIdentity.nicks())))
-            this.nickList = new ArrayList<>(identity.nicks());
+            if (oldIdentity == null || ident.getText().toString().equals(oldIdentity.ident()))
+                this.ident.setText(identity.ident());
 
-        if (oldIdentity == null || kickReason.getText().toString().equals(oldIdentity.kickReason()))
-            this.kickReason.setText(identity.kickReason());
+            if (oldIdentity == null || nickList.equals(new ArrayList<>(oldIdentity.nicks())))
+                this.nickList = new ArrayList<>(identity.nicks());
 
-        if (oldIdentity == null || partReason.getText().toString().equals(oldIdentity.partReason()))
-            this.partReason.setText(identity.partReason());
+            if (oldIdentity == null || kickReason.getText().toString().equals(oldIdentity.kickReason()))
+                this.kickReason.setText(identity.kickReason());
 
-        if (oldIdentity == null || quitReason.getText().toString().equals(oldIdentity.quitReason()))
-            this.quitReason.setText(identity.quitReason());
+            if (oldIdentity == null || partReason.getText().toString().equals(oldIdentity.partReason()))
+                this.partReason.setText(identity.partReason());
 
-        if (oldIdentity == null || awayReason.getText().toString().equals(oldIdentity.awayReason()))
-            this.awayReason.setText(identity.awayReason());
+            if (oldIdentity == null || quitReason.getText().toString().equals(oldIdentity.quitReason()))
+                this.quitReason.setText(identity.quitReason());
 
-        if (oldIdentity == null || useAwayOnDetach.isChecked() == oldIdentity.detachAwayEnabled())
-            this.useAwayOnDetach.setChecked(identity.detachAwayEnabled());
+            if (oldIdentity == null || awayReason.getText().toString().equals(oldIdentity.awayReason()))
+                this.awayReason.setText(identity.awayReason());
 
-        if (oldIdentity == null || awayOnDetachReason.getText().toString().equals(oldIdentity.identityName()))
-            this.awayOnDetachReason.setText(identity.detachAwayReason());
+            if (oldIdentity == null || useAwayOnDetach.isChecked() == oldIdentity.detachAwayEnabled())
+                this.useAwayOnDetach.setChecked(identity.detachAwayEnabled());
+
+            if (oldIdentity == null || awayOnDetachReason.getText().toString().equals(oldIdentity.identityName()))
+                this.awayOnDetachReason.setText(identity.detachAwayReason());
+        }
     }
 
     @Override
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentityListActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentityListActivity.java
index a88620961..38635e93c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentityListActivity.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentityListActivity.java
@@ -39,7 +39,6 @@ import butterknife.ButterKnife;
 import de.kuschku.libquassel.client.IdentityManager;
 import de.kuschku.libquassel.syncables.types.interfaces.QIdentity;
 import de.kuschku.quasseldroid_ng.R;
-import de.kuschku.quasseldroid_ng.ui.coresettings.network.NetworkCreateActivity;
 import de.kuschku.util.observables.callbacks.wrappers.AdapterUICallbackWrapper;
 import de.kuschku.util.servicebound.BoundActivity;
 
@@ -77,7 +76,7 @@ public class IdentityListActivity extends BoundActivity {
         list.setAdapter(adapter);
 
         add.setOnClickListener(view -> {
-            startActivity(new Intent(this, NetworkCreateActivity.class));
+            startActivity(new Intent(this, IdentityCreateActivity.class));
         });
 
         setSupportActionBar(toolbar);
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentitySpinnerAdapter.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentitySpinnerAdapter.java
index fd65808ad..b55873b3f 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentitySpinnerAdapter.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/IdentitySpinnerAdapter.java
@@ -49,43 +49,47 @@ public class IdentitySpinnerAdapter implements ThemedSpinnerAdapter, GeneralCall
     private Set<DataSetObserver> observers = new HashSet<>();
 
     public void setIdentityManager(IdentityManager identityManager) {
-        this.identities = identityManager.identities();
-        this.identities.addCallback(new UICallback() {
-            @Override
-            public void notifyItemInserted(int position) {
-                notifyChanged(null);
-            }
-
-            @Override
-            public void notifyItemChanged(int position) {
-                notifyChanged(null);
-            }
-
-            @Override
-            public void notifyItemRemoved(int position) {
-                notifyChanged(null);
-            }
-
-            @Override
-            public void notifyItemMoved(int from, int to) {
-                notifyChanged(null);
-            }
-
-            @Override
-            public void notifyItemRangeInserted(int position, int count) {
-                notifyChanged(null);
-            }
-
-            @Override
-            public void notifyItemRangeChanged(int position, int count) {
-                notifyChanged(null);
-            }
-
-            @Override
-            public void notifyItemRangeRemoved(int position, int count) {
-                notifyChanged(null);
-            }
-        });
+        if (identityManager != null) {
+            this.identities = identityManager.identities();
+            this.identities.addCallback(new UICallback() {
+                @Override
+                public void notifyItemInserted(int position) {
+                    notifyChanged(null);
+                }
+
+                @Override
+                public void notifyItemChanged(int position) {
+                    notifyChanged(null);
+                }
+
+                @Override
+                public void notifyItemRemoved(int position) {
+                    notifyChanged(null);
+                }
+
+                @Override
+                public void notifyItemMoved(int from, int to) {
+                    notifyChanged(null);
+                }
+
+                @Override
+                public void notifyItemRangeInserted(int position, int count) {
+                    notifyChanged(null);
+                }
+
+                @Override
+                public void notifyItemRangeChanged(int position, int count) {
+                    notifyChanged(null);
+                }
+
+                @Override
+                public void notifyItemRangeRemoved(int position, int count) {
+                    notifyChanged(null);
+                }
+            });
+        } else {
+            this.identities = null;
+        }
         notifyChanged(null);
     }
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/nick/IdentityNickListActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/nick/IdentityNickListActivity.java
index 4fefd191c..198ad8257 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/nick/IdentityNickListActivity.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/identity/nick/IdentityNickListActivity.java
@@ -66,12 +66,15 @@ public class IdentityNickListActivity extends BoundActivity implements OnStartDr
                 })
                 .positiveText("Save")
                 .negativeText("Cancel")
+                .neutralText("Delete")
                 .positiveColor(context.themeUtil().res.colorAccent)
                 .negativeColor(context.themeUtil().res.colorForeground)
+                .neutralColor(context.themeUtil().res.colorForeground)
                 .onPositive((dialog1, which) -> {
                     String text = dialog1.getInputEditText().getText().toString().trim();
                     nicks.set(nicks.indexOf(nick), text);
                 })
+                .onNeutral((dialog1, which) -> nicks.remove(nick))
                 .build();
         dialog.show();
     };
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/NetworkCreateActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/NetworkCreateActivity.java
index f6818cd28..202bf3a09 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/NetworkCreateActivity.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/NetworkCreateActivity.java
@@ -246,13 +246,13 @@ public class NetworkCreateActivity extends BoundActivity {
                 NetworkInfo after = new NetworkInfo(
                         0,
                         networkName.getText().toString(),
-                        0,
+                        (int) identity.getSelectedItemId(),
                         useCustomCodecs.isChecked() ? this.codecForServer.getText().toString() : null,
                         useCustomCodecs.isChecked() ? this.codecForEncoding.getText().toString() : null,
                         useCustomCodecs.isChecked() ? this.codecForDecoding.getText().toString() : null,
                         serverList == null ? Collections.emptyList() : serverList,
                         true,
-                        null,
+                        Collections.emptyList(),
                         useAutoIdentify.isChecked(),
                         autoIdentifyService.getText().toString(),
                         autoIdentifyPassword.getText().toString(),
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/NetworkEditActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/NetworkEditActivity.java
index 5f40386a8..2e240b49c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/NetworkEditActivity.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/NetworkEditActivity.java
@@ -283,58 +283,60 @@ public class NetworkEditActivity extends BoundActivity {
         NetworkInfo oldInfo = this.network == null ? null : this.network.networkInfo();
         this.network = network;
 
-        NetworkInfo networkInfo = this.network.networkInfo();
-        if (networkInfo != null) {
-            if (oldInfo == null || oldInfo.networkName().equals(networkName.getText().toString()))
-                networkName.setText(networkInfo.networkName());
+        if (network != null) {
+            NetworkInfo networkInfo = this.network.networkInfo();
+            if (networkInfo != null) {
+                if (oldInfo == null || oldInfo.networkName().equals(networkName.getText().toString()))
+                    networkName.setText(networkInfo.networkName());
 
-            if (oldInfo == null || getIdentityPosition(oldInfo) == identity.getSelectedItemPosition())
-                identity.setSelection(getIdentityPosition(networkInfo));
+                if (oldInfo == null || getIdentityPosition(oldInfo) == identity.getSelectedItemPosition())
+                    identity.setSelection(getIdentityPosition(networkInfo));
 
-            if (oldInfo == null || (oldInfo.codecForServer() != null || oldInfo.codecForEncoding() != null || oldInfo.codecForDecoding() != null) == useCustomCodecs.isChecked())
-                useCustomCodecs.setChecked(networkInfo.codecForServer() != null || networkInfo.codecForEncoding() != null || networkInfo.codecForDecoding() != null);
+                if (oldInfo == null || (oldInfo.codecForServer() != null || oldInfo.codecForEncoding() != null || oldInfo.codecForDecoding() != null) == useCustomCodecs.isChecked())
+                    useCustomCodecs.setChecked(networkInfo.codecForServer() != null || networkInfo.codecForEncoding() != null || networkInfo.codecForDecoding() != null);
 
-            if (oldInfo == null || oldInfo.codecForServer().equals(codecForServer.getText().toString()))
-                codecForServer.setText(networkInfo.codecForServer());
+                if (oldInfo == null || oldInfo.codecForServer().equals(codecForServer.getText().toString()))
+                    codecForServer.setText(networkInfo.codecForServer());
 
-            if (oldInfo == null || oldInfo.codecForEncoding().equals(codecForEncoding.getText().toString()))
-                codecForEncoding.setText(networkInfo.codecForEncoding());
+                if (oldInfo == null || oldInfo.codecForEncoding().equals(codecForEncoding.getText().toString()))
+                    codecForEncoding.setText(networkInfo.codecForEncoding());
 
-            if (oldInfo == null || oldInfo.codecForDecoding().equals(codecForDecoding.getText().toString()))
-                codecForDecoding.setText(networkInfo.codecForDecoding());
+                if (oldInfo == null || oldInfo.codecForDecoding().equals(codecForDecoding.getText().toString()))
+                    codecForDecoding.setText(networkInfo.codecForDecoding());
 
-            if (oldInfo == null || oldInfo.useAutoIdentify() == useAutoIdentify.isChecked())
-                useAutoIdentify.setChecked(networkInfo.useAutoIdentify());
+                if (oldInfo == null || oldInfo.useAutoIdentify() == useAutoIdentify.isChecked())
+                    useAutoIdentify.setChecked(networkInfo.useAutoIdentify());
 
-            if (oldInfo == null || oldInfo.autoIdentifyService().equals(autoIdentifyService.getText().toString()))
-                autoIdentifyService.setText(networkInfo.autoIdentifyService());
+                if (oldInfo == null || oldInfo.autoIdentifyService().equals(autoIdentifyService.getText().toString()))
+                    autoIdentifyService.setText(networkInfo.autoIdentifyService());
 
-            if (oldInfo == null || oldInfo.autoIdentifyPassword().equals(autoIdentifyPassword.getText().toString()))
-                autoIdentifyPassword.setText(networkInfo.autoIdentifyPassword());
+                if (oldInfo == null || oldInfo.autoIdentifyPassword().equals(autoIdentifyPassword.getText().toString()))
+                    autoIdentifyPassword.setText(networkInfo.autoIdentifyPassword());
 
-            if (oldInfo == null || oldInfo.useSasl() == useSasl.isChecked())
-                useSasl.setChecked(networkInfo.useSasl());
+                if (oldInfo == null || oldInfo.useSasl() == useSasl.isChecked())
+                    useSasl.setChecked(networkInfo.useSasl());
 
-            if (oldInfo == null || oldInfo.saslAccount().equals(saslAccount.getText().toString()))
-                saslAccount.setText(networkInfo.saslAccount());
+                if (oldInfo == null || oldInfo.saslAccount().equals(saslAccount.getText().toString()))
+                    saslAccount.setText(networkInfo.saslAccount());
 
-            if (oldInfo == null || oldInfo.saslPassword().equals(saslPassword.getText().toString()))
-                saslPassword.setText(networkInfo.saslPassword());
+                if (oldInfo == null || oldInfo.saslPassword().equals(saslPassword.getText().toString()))
+                    saslPassword.setText(networkInfo.saslPassword());
 
-            if (oldInfo == null || oldInfo.useAutoReconnect() == useAutoReconnect.isChecked())
-                useAutoReconnect.setChecked(networkInfo.useAutoReconnect());
+                if (oldInfo == null || oldInfo.useAutoReconnect() == useAutoReconnect.isChecked())
+                    useAutoReconnect.setChecked(networkInfo.useAutoReconnect());
 
-            if (oldInfo == null || oldInfo.autoReconnectInterval() == NumberHelper.parseInt(autoReconnectInterval.getText().toString(), 0))
-                autoReconnectInterval.setText(String.valueOf(networkInfo.autoReconnectInterval()));
+                if (oldInfo == null || oldInfo.autoReconnectInterval() == NumberHelper.parseInt(autoReconnectInterval.getText().toString(), 0))
+                    autoReconnectInterval.setText(String.valueOf(networkInfo.autoReconnectInterval()));
 
-            if (oldInfo == null || oldInfo.autoReconnectRetries() == NumberHelper.parseInt(autoReconnectRetries.getText().toString(), 0))
-                autoReconnectRetries.setText(String.valueOf(networkInfo.autoReconnectRetries()));
+                if (oldInfo == null || oldInfo.autoReconnectRetries() == NumberHelper.parseInt(autoReconnectRetries.getText().toString(), 0))
+                    autoReconnectRetries.setText(String.valueOf(networkInfo.autoReconnectRetries()));
 
-            if (oldInfo == null || oldInfo.unlimitedReconnectRetries() == unlimitedAutoReconnectRetries.isChecked())
-                unlimitedAutoReconnectRetries.setChecked(networkInfo.unlimitedReconnectRetries());
+                if (oldInfo == null || oldInfo.unlimitedReconnectRetries() == unlimitedAutoReconnectRetries.isChecked())
+                    unlimitedAutoReconnectRetries.setChecked(networkInfo.unlimitedReconnectRetries());
 
-            if (oldInfo == null || oldInfo.rejoinChannels() == rejoinChannels.isChecked())
-                rejoinChannels.setChecked(networkInfo.rejoinChannels());
+                if (oldInfo == null || oldInfo.rejoinChannels() == rejoinChannels.isChecked())
+                    rejoinChannels.setChecked(networkInfo.rejoinChannels());
+            }
         }
     }
 
diff --git a/app/src/main/java/de/kuschku/util/niohelpers/WrappedChannel.java b/app/src/main/java/de/kuschku/util/niohelpers/WrappedChannel.java
index e75664595..829c65f8d 100644
--- a/app/src/main/java/de/kuschku/util/niohelpers/WrappedChannel.java
+++ b/app/src/main/java/de/kuschku/util/niohelpers/WrappedChannel.java
@@ -196,7 +196,7 @@ public class WrappedChannel implements Flushable, ByteChannel, InterruptibleChan
      */
     @Override
     public boolean isOpen() {
-        return true;
+        return in != null || out != null;
     }
 
     /**
@@ -219,7 +219,9 @@ public class WrappedChannel implements Flushable, ByteChannel, InterruptibleChan
     @Override
     public void close() throws IOException {
         if (rawIn != null) rawIn.close();
+        in = null;
         if (rawOut != null) rawOut.close();
+        out = null;
     }
 
     /**
diff --git a/app/src/main/java/de/kuschku/util/observables/lists/ObservableList.java b/app/src/main/java/de/kuschku/util/observables/lists/ObservableList.java
index 099f9c033..1a2935c3b 100644
--- a/app/src/main/java/de/kuschku/util/observables/lists/ObservableList.java
+++ b/app/src/main/java/de/kuschku/util/observables/lists/ObservableList.java
@@ -97,7 +97,6 @@ public class ObservableList<T> extends ArrayList<T> implements IObservableList<U
             return false;
         } else {
             remove(position);
-            callback.notifyItemRemoved(position);
             return true;
         }
     }
@@ -131,6 +130,13 @@ public class ObservableList<T> extends ArrayList<T> implements IObservableList<U
         callback.notifyItemRangeRemoved(0, size);
     }
 
+    @Override
+    public T set(int index, T element) {
+        T set = super.set(index, element);
+        callback.notifyItemChanged(index);
+        return set;
+    }
+
     @NonNull
     @Override
     public Iterator<T> iterator() {
-- 
GitLab