From 90220c51b94e06e08f3b7bfab61fd7621735d239 Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Thu, 4 Feb 2016 14:01:45 +0100
Subject: [PATCH] Fixed bugs with sync objects

---
 .../libquassel/client/QBufferManager.java     | 61 +++++++++++++++----
 .../de/kuschku/libquassel/client/QClient.java |  2 -
 .../libquassel/client/QNetworkManager.java    |  7 ---
 .../localtypes/buffers/ChannelBuffer.java     |  3 +
 .../localtypes/buffers/QueryBuffer.java       |  3 +
 .../syncables/types/impl/IrcChannel.java      | 10 ++-
 .../syncables/types/impl/IrcUser.java         |  7 ++-
 .../syncables/types/impl/Network.java         | 13 ++--
 .../types/interfaces/QIrcChannel.java         |  3 +-
 .../syncables/types/interfaces/QIrcUser.java  |  3 +-
 .../syncables/types/interfaces/QNetwork.java  |  3 +-
 .../quasseldroid_ng/ui/chat/ChatActivity.java | 18 ++++++
 app/src/main/res/menu/formatting.xml          | 15 +++++
 app/src/main/res/values-w820dp/dimens.xml     |  3 -
 app/src/main/res/values/attrs.xml             |  1 +
 app/src/main/res/values/strings.xml           |  1 +
 app/src/main/res/values/styles.xml            |  2 +
 17 files changed, 114 insertions(+), 41 deletions(-)

diff --git a/app/src/main/java/de/kuschku/libquassel/client/QBufferManager.java b/app/src/main/java/de/kuschku/libquassel/client/QBufferManager.java
index dffa62054..9a8c9a9ec 100644
--- a/app/src/main/java/de/kuschku/libquassel/client/QBufferManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/client/QBufferManager.java
@@ -23,15 +23,20 @@ package de.kuschku.libquassel.client;
 
 import android.support.annotation.IntRange;
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import de.kuschku.libquassel.localtypes.buffers.Buffer;
-import de.kuschku.libquassel.localtypes.buffers.Buffers;
+import de.kuschku.libquassel.localtypes.buffers.ChannelBuffer;
+import de.kuschku.libquassel.localtypes.buffers.QueryBuffer;
+import de.kuschku.libquassel.localtypes.buffers.StatusBuffer;
 import de.kuschku.libquassel.primitives.types.BufferInfo;
+import de.kuschku.libquassel.syncables.types.interfaces.QIrcChannel;
+import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser;
 import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
@@ -42,8 +47,8 @@ public class QBufferManager {
     private final QClient client;
 
     // We cache those, because the networks might not be initialized at begin
-    @Nullable
-    private List<BufferInfo> bufferInfos;
+    @NonNull
+    private Map<String, Set<BufferInfo>> bufferInfos = new HashMap<>();
 
     public QBufferManager(QClient client) {
         this.client = client;
@@ -68,19 +73,49 @@ public class QBufferManager {
     }
 
     public void init(List<BufferInfo> bufferInfos) {
-        this.bufferInfos = bufferInfos;
+        for (BufferInfo info : bufferInfos) {
+            if (this.bufferInfos.get(objectName(info)) == null)
+                this.bufferInfos.put(objectName(info), new HashSet<>());
+
+            this.bufferInfos.get(objectName(info)).add(info);
+        }
+    }
+
+    private String objectName(BufferInfo info) {
+        if (info.type() == BufferInfo.Type.STATUS)
+            return String.valueOf(info.networkId());
+        else
+            return info.networkId() + "/" + info.name();
     }
 
-    public void postInit() {
-        if (bufferInfos != null) {
-            for (BufferInfo info : bufferInfos) {
+    public void postInit(String objectName, QIrcUser ircUser) {
+        if (bufferInfos.get(objectName) != null)
+            for (BufferInfo info : bufferInfos.get(objectName)) {
                 QNetwork network = client.networkManager().network(info.networkId());
                 assertNotNull(network);
-                Buffer buffer = Buffers.fromType(info, network);
-                assertNotNull(buffer);
-                createBuffer(buffer);
+                createBuffer(new QueryBuffer(info, ircUser));
+            }
+    }
+
+    public void postInit(String objectName, QNetwork ircUser) {
+        if (bufferInfos.get(objectName) != null)
+            for (BufferInfo info : bufferInfos.get(objectName)) {
+                QNetwork network = client.networkManager().network(info.networkId());
+                assertNotNull(network);
+                createBuffer(new StatusBuffer(info, ircUser));
+            }
+    }
+
+    public Map<Integer, Buffer> buffers() {
+        return buffers;
+    }
+
+    public void postInit(String objectName, QIrcChannel ircChannel) {
+        if (bufferInfos.get(objectName) != null)
+            for (BufferInfo info : bufferInfos.get(objectName)) {
+                QNetwork network = client.networkManager().network(info.networkId());
+                assertNotNull(network);
+                createBuffer(new ChannelBuffer(info, ircChannel));
             }
-        }
-        bufferInfos = null;
     }
 }
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 b4e5ff708..801df36fc 100644
--- a/app/src/main/java/de/kuschku/libquassel/client/QClient.java
+++ b/app/src/main/java/de/kuschku/libquassel/client/QClient.java
@@ -188,8 +188,6 @@ public class QClient extends AClient {
 
         this.connectionStatus = connectionStatus;
         if (connectionStatus == ConnectionChangeEvent.Status.LOADING_BACKLOG) {
-            networkManager.postInit();
-            bufferManager.postInit();
             setConnectionStatus(ConnectionChangeEvent.Status.CONNECTED);
         }
         provider.sendEvent(new ConnectionChangeEvent(connectionStatus));
diff --git a/app/src/main/java/de/kuschku/libquassel/client/QNetworkManager.java b/app/src/main/java/de/kuschku/libquassel/client/QNetworkManager.java
index 7684b6694..a6a879022 100644
--- a/app/src/main/java/de/kuschku/libquassel/client/QNetworkManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/client/QNetworkManager.java
@@ -78,13 +78,6 @@ public class QNetworkManager extends Observable {
 
     }
 
-    public void postInit() {
-        for (QNetwork network : networks.values()) {
-            network.postInit();
-        }
-        _update();
-    }
-
     public List<QNetwork> networks() {
         return new ArrayList<>(networks.values());
     }
diff --git a/app/src/main/java/de/kuschku/libquassel/localtypes/buffers/ChannelBuffer.java b/app/src/main/java/de/kuschku/libquassel/localtypes/buffers/ChannelBuffer.java
index 5f01c7c44..ea3d4db26 100644
--- a/app/src/main/java/de/kuschku/libquassel/localtypes/buffers/ChannelBuffer.java
+++ b/app/src/main/java/de/kuschku/libquassel/localtypes/buffers/ChannelBuffer.java
@@ -27,6 +27,8 @@ import android.support.annotation.Nullable;
 import de.kuschku.libquassel.primitives.types.BufferInfo;
 import de.kuschku.libquassel.syncables.types.interfaces.QIrcChannel;
 
+import static de.kuschku.util.AndroidAssert.assertNotNull;
+
 public class ChannelBuffer implements Buffer {
     @NonNull
     private BufferInfo info;
@@ -34,6 +36,7 @@ public class ChannelBuffer implements Buffer {
     private QIrcChannel channel;
 
     public ChannelBuffer(@NonNull BufferInfo info, @Nullable QIrcChannel channel) {
+        assertNotNull(channel);
         this.info = info;
         this.channel = channel;
     }
diff --git a/app/src/main/java/de/kuschku/libquassel/localtypes/buffers/QueryBuffer.java b/app/src/main/java/de/kuschku/libquassel/localtypes/buffers/QueryBuffer.java
index 45ec2ee3f..48cee5999 100644
--- a/app/src/main/java/de/kuschku/libquassel/localtypes/buffers/QueryBuffer.java
+++ b/app/src/main/java/de/kuschku/libquassel/localtypes/buffers/QueryBuffer.java
@@ -27,6 +27,8 @@ import android.support.annotation.Nullable;
 import de.kuschku.libquassel.primitives.types.BufferInfo;
 import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser;
 
+import static de.kuschku.util.AndroidAssert.assertNotNull;
+
 public class QueryBuffer implements Buffer {
     @Nullable
     private final QIrcUser user;
@@ -34,6 +36,7 @@ public class QueryBuffer implements Buffer {
     private BufferInfo info;
 
     public QueryBuffer(@NonNull BufferInfo info, @Nullable QIrcUser user) {
+        assertNotNull(user);
         this.info = info;
         this.user = user;
     }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcChannel.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcChannel.java
index 4e371f952..c9e53b4f3 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcChannel.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcChannel.java
@@ -416,7 +416,8 @@ public class IrcChannel extends AIrcChannel<IrcChannel> {
 
     @SuppressWarnings("unchecked")
     @Override
-    public void init(QNetwork network) {
+    public void init(QNetwork network, QClient client) {
+        this.client = client;
         this.network = network;
 
 
@@ -441,6 +442,10 @@ public class IrcChannel extends AIrcChannel<IrcChannel> {
 
         cachedUserModes = null;
         cachedChanModes = null;
+
+        this.network._addIrcChannel(this);
+
+        client.bufferManager().postInit(network.networkId() + "/" + name(), this);
         _update();
     }
 
@@ -476,9 +481,8 @@ public class IrcChannel extends AIrcChannel<IrcChannel> {
     @Override
     public void init(@NonNull String objectName, @NonNull BusProvider provider, @NonNull QClient client) {
         super.init(objectName, provider, client);
-
         String[] split = objectName.split("/", 2);
         assertEquals(split.length, 2);
-        init(client.networkManager().network(Integer.parseInt(split[0])));
+        init(client.networkManager().network(Integer.parseInt(split[0])), client);
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcUser.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcUser.java
index 2c00aa28c..66b907e1a 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcUser.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IrcUser.java
@@ -432,13 +432,16 @@ public class IrcUser extends AIrcUser<IrcUser> {
     }
 
     @Override
-    public void init(QNetwork network) {
+    public void init(QNetwork network, QClient client) {
         this.network = network;
+        this.client = client;
+
         channels = new HashSet<>();
         if (cachedChannels != null)
         for (String channelName : cachedChannels) {
             channels.add(network().newIrcChannel(channelName));
         }
+        client.bufferManager().postInit(network.networkId() + "/" + nick(), this);
         _update();
     }
 
@@ -447,7 +450,7 @@ public class IrcUser extends AIrcUser<IrcUser> {
         super.init(objectName, provider, client);
         String[] split = objectName.split("/", 2);
         assertEquals(split.length, 2);
-        init(client.networkManager().network(Integer.parseInt(split[0])));
+        init(client.networkManager().network(Integer.parseInt(split[0])), client);
     }
 
     @Override
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Network.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Network.java
index 8f4102367..4548a6ab2 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Network.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Network.java
@@ -658,7 +658,7 @@ public class Network extends ANetwork<Network> implements Observer {
     @NonNull
     private QIrcUser newIrcUser(@NonNull String mask) {
         IrcUser user = IrcUser.create(mask);
-        user.init(this);
+        user.init(this, client);
         client.requestInitObject("IrcUser", user.getObjectName());
         nicks.put(user.nick(), user);
         _update();
@@ -731,13 +731,9 @@ public class Network extends ANetwork<Network> implements Observer {
         _update();
     }
 
-    public void postInit() {
-        for (QIrcChannel channel : ircChannels()) {
-            channel.init(this);
-        }
-        for (QIrcUser user : ircUsers()) {
-            user.init(this);
-        }
+    @Override
+    public void _addIrcChannel(IrcChannel ircChannel) {
+        channels.put(ircChannel.name(), ircChannel);
     }
 
     @Override
@@ -761,6 +757,7 @@ public class Network extends ANetwork<Network> implements Observer {
         for (QIrcUser name : ircUsers()) {
             client.requestInitObject("IrcUser", networkId() + "/" + name.nick());
         }
+        client.bufferManager().postInit(String.valueOf(networkId()), this);
     }
 
     @Override
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIrcChannel.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIrcChannel.java
index ea24211e0..4427a5c8b 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIrcChannel.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIrcChannel.java
@@ -25,6 +25,7 @@ import android.support.annotation.NonNull;
 
 import java.util.List;
 
+import de.kuschku.libquassel.client.QClient;
 import de.kuschku.libquassel.syncables.Synced;
 
 public interface QIrcChannel {
@@ -144,5 +145,5 @@ public interface QIrcChannel {
 
     void _removeChannelMode(final char mode, final String value);
 
-    void init(QNetwork network);
+    void init(QNetwork network, QClient client);
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIrcUser.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIrcUser.java
index 05d0f780c..e321051b3 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIrcUser.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIrcUser.java
@@ -27,6 +27,7 @@ import org.joda.time.DateTime;
 
 import java.util.List;
 
+import de.kuschku.libquassel.client.QClient;
 import de.kuschku.libquassel.syncables.Synced;
 
 public interface QIrcUser {
@@ -202,5 +203,5 @@ public interface QIrcUser {
 
     void _removeUserModes(final String modes);
 
-    void init(QNetwork network);
+    void init(QNetwork network, QClient client);
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java
index a21fd717d..c4f6ce5eb 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java
@@ -28,6 +28,7 @@ import java.util.List;
 
 import de.kuschku.libquassel.objects.types.NetworkServer;
 import de.kuschku.libquassel.syncables.Synced;
+import de.kuschku.libquassel.syncables.types.impl.IrcChannel;
 import de.kuschku.libquassel.syncables.types.impl.NetworkInfo;
 
 public interface QNetwork {
@@ -340,7 +341,7 @@ public interface QNetwork {
 
     void _removeChansAndUsers();
 
-    void postInit();
+    void _addIrcChannel(IrcChannel ircChannel);
 
     enum ConnectionState {
         Disconnected(0),
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.java
index a100e820d..2444e5132 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.java
@@ -87,6 +87,8 @@ import de.kuschku.libquassel.message.Message;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewManager;
 import de.kuschku.libquassel.syncables.types.interfaces.QIrcChannel;
+import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser;
+import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
 import de.kuschku.quasseldroid_ng.BuildConfig;
 import de.kuschku.quasseldroid_ng.R;
 import de.kuschku.quasseldroid_ng.service.ClientBackgroundThread;
@@ -443,6 +445,22 @@ public class ChatActivity extends AppCompatActivity {
                 case R.id.action_history:
                     slidingLayoutHistory.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
                     return true;
+                case R.id.debug_init_channels: {
+                    for (QNetwork network : context.client().networkManager().networks()) {
+                        for (QIrcChannel name : network.ircChannels()) {
+                            context.client().requestInitObject("IrcChannel", network.networkId() + "/" + name.name());
+                        }
+                    }
+                    return true;
+                }
+                case R.id.debug_init_users: {
+                    for (QNetwork network : context.client().networkManager().networks()) {
+                        for (QIrcUser name : network.ircUsers()) {
+                            context.client().requestInitObject("IrcUser", network.networkId() + "/" + name.nick());
+                        }
+                    }
+                    return true;
+                }
                 default:
                     return false;
             }
diff --git a/app/src/main/res/menu/formatting.xml b/app/src/main/res/menu/formatting.xml
index b807f4c06..57b0ae94f 100644
--- a/app/src/main/res/menu/formatting.xml
+++ b/app/src/main/res/menu/formatting.xml
@@ -52,4 +52,19 @@
         android:icon="?attr/iconHistory"
         android:title="@string/labelHistory"
         app:showAsAction="always" />
+
+    <item
+        android:id="@+id/action_debug"
+        android:icon="?attr/iconDebug"
+        android:title="@string/labelDebug"
+        app:showAsAction="always">
+        <menu>
+            <item
+                android:id="@+id/debug_init_channels"
+                android:title="Request Channels" />
+            <item
+                android:id="@+id/debug_init_users"
+                android:title="Request Users" />
+        </menu>
+    </item>
 </menu>
diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml
index 35ef11afe..64c4e0800 100644
--- a/app/src/main/res/values-w820dp/dimens.xml
+++ b/app/src/main/res/values-w820dp/dimens.xml
@@ -20,8 +20,5 @@
   -->
 
 <resources>
-    <!-- Example customization of dimensions originally defined in res/values/dimens.xml
-         (such as screen margins) for screens with more than 820dp of available width. This
-         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
     <dimen name="activity_horizontal_margin">64dp</dimen>
 </resources>
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index 418fc7e93..986086c9d 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -87,6 +87,7 @@
     <attr name="iconFormatPaint" format="reference" />
     <attr name="iconFormatFill" format="reference" />
     <attr name="iconHistory" format="reference" />
+    <attr name="iconDebug" format="reference" />
 
     <attr name="cardStyle" format="reference" />
 </resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a2be9b54d..e9564f329 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -78,4 +78,5 @@
     <string name="labelHideEvents">Hide events</string>
 
     <string name="warningCertificate">Do you trust this certificate?</string>
+    <string name="labelDebug">Debug</string>
 </resources>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 3ba465708..d23e2803f 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -38,6 +38,7 @@
         <item name="iconFormatPaint">@drawable/ic_format_paint_dark</item>
         <item name="iconFormatFill">@drawable/ic_format_fill_dark</item>
         <item name="iconHistory">@drawable/ic_history_dark</item>
+        <item name="iconDebug">@drawable/ic_bug_dark</item>
 
         <item name="cardStyle">@style/CardView.Dark</item>
     </style>
@@ -58,6 +59,7 @@
         <item name="iconFormatPaint">@drawable/ic_format_paint_light</item>
         <item name="iconFormatFill">@drawable/ic_format_fill_light</item>
         <item name="iconHistory">@drawable/ic_history_light</item>
+        <item name="iconDebug">@drawable/ic_bug_light</item>
 
         <item name="cardStyle">@style/CardView.Light</item>
     </style>
-- 
GitLab