From 5a9aae09ccaadd762a09b9d43cacf0b87345c61a Mon Sep 17 00:00:00 2001 From: Janne Koschinski <janne@kuschku.de> Date: Sat, 27 Aug 2016 19:00:17 +0200 Subject: [PATCH] Fixed Sync during join/part/delete of channels --- app/build.gradle | 62 +++++----- .../kuschku/libquassel/ProtocolHandler.java | 5 +- .../de/kuschku/libquassel/client/Client.java | 39 ++++-- .../serializers/IrcUserSerializer.java | 2 +- .../serializers/NetworkSerializer.java | 43 ++++--- .../syncables/types/impl/BufferSyncer.java | 4 + .../types/impl/BufferViewConfig.java | 46 +++++-- .../syncables/types/impl/IrcChannel.java | 17 ++- .../types/interfaces/QBufferViewConfig.java | 5 + .../quasseldroid_ng/ui/chat/MainActivity.java | 22 +++- .../ui/chat/chatview/ChatMessageRenderer.java | 1 - .../chat/drawer/BufferViewConfigAdapter.java | 29 ++++- .../ui/chat/drawer/NetworkItem.java | 112 +++++++++++++++--- .../wrappers/MultiElementCallbackWrapper.java | 4 +- .../util/servicebound/BoundActivity.java | 2 +- app/src/main/res/layout/activity_main.xml | 4 +- app/src/main/res/menu/chatlist.xml | 9 +- app/src/main/res/values/strings.xml | 3 + 18 files changed, 305 insertions(+), 104 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a2fd16b3e..18449596d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -32,40 +32,43 @@ dependencies { } if (project.hasProperty("storeFile")) { - android { - signingConfigs { - release { - storeFile file(project.property("storeFile")) - storePassword project.property("storePassword") - keyAlias project.property("keyAlias") - keyPassword project.property("keyPassword") - } - } - - buildTypes { - release { - signingConfig signingConfigs.release - } + android { + signingConfigs { + release { + storeFile file(project.property("storeFile")) + storePassword project.property("storePassword") + keyAlias project.property("keyAlias") + keyPassword project.property("keyPassword") + } + } + + buildTypes { + release { + signingConfig signingConfigs.release + } + debug { + applicationIdSuffix ".debug" + } + } } - } } def versionPropsFile = file('version.properties') def versionBuild = 0 if (versionPropsFile.exists() && versionPropsFile.canRead()) { - def Properties versionProps = new Properties() - - versionProps.load(new FileInputStream(versionPropsFile)) - def runTasks = gradle.startParameter.taskNames - versionBuild = Integer.valueOf(versionProps['VERSION_BUILD'].toString()) - if ('assemble' in runTasks || 'assembleRelease' in runTasks || 'aR' in runTasks) { - versionBuild = versionBuild + 1 - } - versionProps['VERSION_BUILD'] = versionBuild.toString() - versionProps.store(versionPropsFile.newWriter(), null) + def Properties versionProps = new Properties() + + versionProps.load(new FileInputStream(versionPropsFile)) + def runTasks = gradle.startParameter.taskNames + versionBuild = Integer.valueOf(versionProps['VERSION_BUILD'].toString()) + if ('assemble' in runTasks || 'assembleRelease' in runTasks || 'aR' in runTasks) { + versionBuild = versionBuild + 1 + } + versionProps['VERSION_BUILD'] = versionBuild.toString() + versionProps.store(versionPropsFile.newWriter(), null) } else { - // Get jenkins build number from environment - versionBuild = Integer.valueOf(System.getenv("BUILD_NUMBER")) + // Get jenkins build number from environment + versionBuild = Integer.valueOf(System.getenv("BUILD_NUMBER")) } @@ -74,7 +77,7 @@ def rawVersionName = "0.2.0" android { compileSdkVersion 24 buildToolsVersion "24.0.0" - + defaultConfig { applicationId "com.iskrembilen.quasseldroid" minSdkVersion 16 @@ -148,7 +151,7 @@ dependencies { // UI Libs compile 'com.bignerdranch.android:expandablerecyclerview:2.0.4' - compile(name:'library-release', ext:'aar') + compile(name: 'library-release', ext: 'aar') // This dependency can be removed as soon as the requires ressources are copied over. compile('com.mikepenz:materialdrawer:5.0.3@aar') { transitive = true } compile('com.github.afollestad.material-dialogs:core:0.8.5.3@aar') { transitive = true } @@ -159,7 +162,6 @@ dependencies { compile "com.github.Raizlabs.DBFlow:dbflow-core:3.1.1" compile "com.github.Raizlabs.DBFlow:dbflow:3.1.1" - // Appcompat compile 'com.android.support:appcompat-v7:24.0.0' compile 'com.android.support:design:24.0.0' diff --git a/app/src/main/java/de/kuschku/libquassel/ProtocolHandler.java b/app/src/main/java/de/kuschku/libquassel/ProtocolHandler.java index d626b07bd..3da4609ce 100644 --- a/app/src/main/java/de/kuschku/libquassel/ProtocolHandler.java +++ b/app/src/main/java/de/kuschku/libquassel/ProtocolHandler.java @@ -22,6 +22,7 @@ package de.kuschku.libquassel; import android.support.annotation.NonNull; +import android.util.Log; import org.joda.time.DateTime; import org.joda.time.Interval; @@ -95,7 +96,9 @@ public class ProtocolHandler implements IProtocolHandler { final Object syncable = client.unsafe_getObjectByIdentifier(packedFunc.className, packedFunc.objectName); if (syncable == null) { - client.bufferSync(packedFunc); + Log.d("ProtocolHandler", String.format("Sync Failed: %s::%s(%s, %s)", packedFunc.className, packedFunc.methodName, packedFunc.objectName, packedFunc.params)); + if (client.connectionStatus() == ConnectionChangeEvent.Status.INITIALIZING_DATA) + client.bufferSync(packedFunc); } else { if (syncable instanceof SyncableObject && !((SyncableObject) syncable).initialized()) { client.initObject(packedFunc.className, packedFunc.objectName, (SyncableObject) syncable); 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 fe51a75ae..e11005cd4 100644 --- a/app/src/main/java/de/kuschku/libquassel/client/Client.java +++ b/app/src/main/java/de/kuschku/libquassel/client/Client.java @@ -364,16 +364,21 @@ public class Client extends AClient { } } - // Execute cached sync requests - if (bufferedSyncs.size() > 0) { - String key = hashName(className, objectName); - if (bufferedSyncs.containsKey(key)) { - Log.d("libquassel", "Unqueueing syncs: " + className + ":" + objectName); - List<SyncFunction> functions = bufferedSyncs.get(key); - for (SyncFunction function : functions) - provider.handle(function); - bufferedSyncs.remove(key); + synchronized (bufferedSyncs) { + if (r > 0) r--; + else throw new RuntimeException(); + // Execute cached sync requests + if (bufferedSyncs.size() > 0) { + String key = hashName(className, objectName); + if (bufferedSyncs.containsKey(key)) { + Log.d("libquassel", "Unqueueing syncs: " + className + ":" + objectName); + List<SyncFunction> functions = bufferedSyncs.get(key); + for (SyncFunction function : functions) + provider.handle(function); + bufferedSyncs.remove(key); + } } + r++; } } @@ -445,10 +450,16 @@ public class Client extends AClient { if (connectionStatus() == ConnectionChangeEvent.Status.CONNECTED) { Log.d("libquassel", "Queueing sync: " + packedFunc); } - if (!bufferedSyncs.containsKey(key)) - bufferedSyncs.put(key, new LinkedList<>()); - bufferedSyncs.get(key).add(packedFunc); - Log.d("libquassel", "Queued syncs: " + bufferedSyncs.keySet()); + + synchronized (bufferedSyncs) { + if (r > 0) r--; + else throw new RuntimeException(); + if (!bufferedSyncs.containsKey(key)) + bufferedSyncs.put(key, new LinkedList<>()); + bufferedSyncs.get(key).add(packedFunc); + Log.d("libquassel", "Queued syncs: " + bufferedSyncs.keySet()); + r++; + } } public void bufferBuffer(QBufferViewConfig bufferViewConfig, int bufferId, int pos) { @@ -481,4 +492,6 @@ public class Client extends AClient { public String coreId() { return coreId; } + + private int r = 1; } diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IrcUserSerializer.java b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IrcUserSerializer.java index 498c5701e..7ff0ab262 100644 --- a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IrcUserSerializer.java +++ b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IrcUserSerializer.java @@ -96,7 +96,7 @@ public class IrcUserSerializer implements ObjectSerializer<IrcUser> { (String) map.get("suserHost").data, (String) map.get("nick").data, (String) map.get("realName").data, - (String) map.get("account").data, + (map.get("account") == null) ? "": (String) map.get("account").data, (String) map.get("awayMessage").data, (DateTime) map.get("loginTime").data, (boolean) map.get("encrypted").data, diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkSerializer.java b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkSerializer.java index f68c1ed38..20bf3c4fd 100644 --- a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkSerializer.java +++ b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkSerializer.java @@ -27,6 +27,7 @@ import android.support.annotation.Nullable; import org.joda.time.DateTime; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -48,6 +49,7 @@ import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser; public class NetworkSerializer implements ObjectSerializer<Network> { @NonNull private static final NetworkSerializer serializer = new NetworkSerializer(); + public static final DateTime UNIX_EPOCH = new DateTime(0L); private NetworkSerializer() { } @@ -106,29 +108,36 @@ public class NetworkSerializer implements ObjectSerializer<Network> { ircUsers = new ArrayList<>(max); for (int i = 0; i < max; i++) { ircUsers.add(new IrcUser( - (String) users.get("server").data.get(i), - (String) users.get("ircOperator").data.get(i), - (boolean) users.get("away").data.get(i), - (int) users.get("lastAwayMessage").data.get(i), - (DateTime) users.get("idleTime").data.get(i), - (String) users.get("whoisServiceReply").data.get(i), - (String) users.get("suserHost").data.get(i), - (String) users.get("nick").data.get(i), - (String) users.get("realName").data.get(i), - (String) users.get("account").data.get(i), - (String) users.get("awayMessage").data.get(i), - (DateTime) users.get("loginTime").data.get(i), - (boolean) users.get("encrypted").data.get(i), - (List<String>) users.get("channels").data.get(i), - (String) users.get("host").data.get(i), - (String) users.get("userModes").data.get(i), - (String) users.get("user").data.get(i) + getAtPosition(users, "server", i, ""), + getAtPosition(users, "ircOperator", i, ""), + getAtPosition(users, "away", i, false), + getAtPosition(users, "lastAwayMessage", i, 0), + getAtPosition(users, "idleTime", i, UNIX_EPOCH), + getAtPosition(users, "whoisServiceReply", i, ""), + getAtPosition(users, "suserHost", i, ""), + getAtPosition(users, "nick", i, ""), + getAtPosition(users, "realName", i, ""), + getAtPosition(users, "account", i, ""), + getAtPosition(users, "awayMessage", i, ""), + getAtPosition(users, "loginTime", i, UNIX_EPOCH), + getAtPosition(users, "encrypted", i, false), + getAtPosition(users, "channels", i, Collections.emptyList()), + getAtPosition(users, "host", i, ""), + getAtPosition(users, "userModes", i, ""), + getAtPosition(users, "user", i, "") )); } } return ircUsers; } + private <T> T getAtPosition(@NonNull Map<String, QVariant<List>> users, String field, int index, T or) { + if (users.containsKey(field) && users.get(field) != null && users.get(field).data != null && users.get(field).data.size() > index) + return (T) users.get(field).data.get(index); + else + return or; + } + @NonNull private List<QIrcChannel> extractChannels(@Nullable Map<String, QVariant<List>> channels) { final List<QIrcChannel> ircChannels; diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java index 23176613b..acc57b43b 100644 --- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java +++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferSyncer.java @@ -35,6 +35,7 @@ import de.kuschku.libquassel.primitives.types.QVariant; import de.kuschku.libquassel.syncables.serializers.BufferSyncerSerializer; import de.kuschku.libquassel.syncables.types.abstracts.ABufferSyncer; import de.kuschku.libquassel.syncables.types.interfaces.QBacklogManager; +import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig; import de.kuschku.util.observables.lists.ObservableComparableSortedList; import de.kuschku.util.observables.lists.ObservableSortedList; @@ -123,6 +124,9 @@ public class BufferSyncer extends ABufferSyncer<BufferSyncer> { public void _removeBuffer(int buffer) { assertNotNull(client); + for (QBufferViewConfig config : client.bufferViewManager().bufferViewConfigs()) { + config.deleteBuffer(buffer); + } markerLines.removeAt(markerLines.indexOfKey(buffer)); lastSeenMsgs.removeAt(lastSeenMsgs.indexOfKey(buffer)); client.bufferManager().removeBuffer(buffer); 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 9ec26017d..e21f21901 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 @@ -22,6 +22,7 @@ package de.kuschku.libquassel.syncables.types.impl; import android.support.annotation.NonNull; +import android.util.Log; import java.util.Collections; import java.util.List; @@ -43,7 +44,9 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> { @NonNull private final ObservableList<Integer> buffers; @NonNull - private final ObservableSet<Integer> bufferIds; + private final ObservableSet<Integer> visibleBufferIds; + @NonNull + private final ObservableSet<Integer> allBufferIds; @NonNull private final ObservableSet<Integer> removedBuffers; @NonNull @@ -67,8 +70,12 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> { this.buffers = new ObservableList<>(buffers); buffers.removeAll(removedBuffers); buffers.removeAll(temporarilyRemovedBuffers); - this.bufferIds = new ObservableSet<>(); - bufferIds.addAll(buffers); + this.visibleBufferIds = new ObservableSet<>(); + visibleBufferIds.addAll(buffers); + this.allBufferIds = new ObservableSet<>(); + allBufferIds.addAll(buffers); + allBufferIds.addAll(removedBuffers); + allBufferIds.addAll(temporarilyRemovedBuffers); this.allowedBufferTypes = allowedBufferTypes; this.sortAlphabetically = sortAlphabetically; this.disableDecoration = disableDecoration; @@ -145,7 +152,7 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> { (networkId == 0 || (networkId == buffer.getInfo().networkId)) ) { int bufferid = buffer.getInfo().id; - if (bufferIds.contains(bufferid) && !temporarilyRemovedBuffers.contains(bufferid) && !removedBuffers.contains(bufferid)) + if (visibleBufferIds.contains(bufferid) && !temporarilyRemovedBuffers.contains(bufferid) && !removedBuffers.contains(bufferid)) return DisplayType.ALWAYS; else if (temporarilyRemovedBuffers.contains(bufferid) && !removedBuffers.contains(bufferid)) return DisplayType.TEMP_HIDDEN; @@ -247,7 +254,13 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> { @NonNull @Override public ObservableSet<Integer> bufferIds() { - return bufferIds; + return visibleBufferIds; + } + + @NonNull + @Override + public ObservableSet<Integer> allBufferIds() { + return allBufferIds; } @NonNull @@ -284,6 +297,8 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> { temporarilyRemovedBuffers.remove(bufferId); buffers.add(pos, bufferId); + visibleBufferIds.add(bufferId); + allBufferIds.add(bufferId); } @Override @@ -324,10 +339,9 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> { @Override public void _removeBuffer(int bufferId) { - int index; - if ((index = buffers.indexOf(bufferId)) != -1) { - buffers.remove(index); - } + visibleBufferIds.remove(bufferId); + if (buffers.contains(bufferId)) + buffers.remove((Integer) bufferId); if (removedBuffers.contains(bufferId)) removedBuffers.remove(bufferId); @@ -343,6 +357,7 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> { @Override public void _removeBufferPermanently(int bufferId) { + visibleBufferIds.remove(bufferId); if (buffers.contains(bufferId)) buffers.remove((Integer) bufferId); @@ -377,6 +392,15 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> { return networkList; } + @Override + public void deleteBuffer(int bufferId) { + visibleBufferIds.remove(bufferId); + allBufferIds.remove(bufferId); + buffers.remove(buffers.indexOf(bufferId)); + temporarilyRemovedBuffers.remove(bufferId); + removedBuffers.remove(bufferId); + } + @Override public void _update(@NonNull Map<String, QVariant> from) { _update(BufferViewConfigSerializer.get().fromLegacy(from)); @@ -396,8 +420,8 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> { this.hideInactiveNetworks = from.hideInactiveNetworks; this.buffers.clear(); this.buffers.addAll(from.buffers); - this.bufferIds.retainAll(from.bufferIds); - this.bufferIds.addAll(from.bufferIds); + this.visibleBufferIds.retainAll(from.visibleBufferIds); + this.visibleBufferIds.addAll(from.visibleBufferIds); this.removedBuffers.retainAll(from.removedBuffers); this.removedBuffers.addAll(from.removedBuffers); this.temporarilyRemovedBuffers.retainAll(from.temporarilyRemovedBuffers); 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 5e3fd2cac..201f33605 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 @@ -37,9 +37,12 @@ import java.util.Set; import de.kuschku.libquassel.BusProvider; import de.kuschku.libquassel.client.Client; +import de.kuschku.libquassel.localtypes.buffers.ChannelBuffer; +import de.kuschku.libquassel.primitives.types.BufferInfo; import de.kuschku.libquassel.primitives.types.QVariant; import de.kuschku.libquassel.syncables.serializers.IrcChannelSerializer; import de.kuschku.libquassel.syncables.types.abstracts.AIrcChannel; +import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig; import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser; import de.kuschku.libquassel.syncables.types.interfaces.QNetwork; import de.kuschku.util.irc.ModeUtils; @@ -257,6 +260,7 @@ public class IrcChannel extends AIrcChannel<IrcChannel> { @Override public void _setTopic(String topic) { this.topic = topic; + _update(); } @Override @@ -524,4 +528,15 @@ public class IrcChannel extends AIrcChannel<IrcChannel> { modes.addAll(A_channelModes.keySet()); return modes; } -} + + @Override + public void _update() { + super._update(); + ChannelBuffer buffer = client.bufferManager().channel(this); + if (buffer != null) { + for (QBufferViewConfig qBufferViewConfig : client.bufferViewManager().bufferViewConfigs()) { + qBufferViewConfig.bufferIds().notifyItemChanged(buffer.getInfo().id); + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewConfig.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewConfig.java index 36eec92cf..919a482df 100644 --- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewConfig.java +++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewConfig.java @@ -156,10 +156,15 @@ public interface QBufferViewConfig extends QObservable { ObservableSet<QNetwork> networkList(); + void deleteBuffer(int bufferId); + void updateNetworks(); DisplayType mayDisplay(Buffer buffer); + @NonNull + ObservableSet<Integer> allBufferIds(); + enum DisplayType { NONE, ALWAYS, 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 3ad162032..31134ad77 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 @@ -154,6 +154,18 @@ public class MainActivity extends BoundActivity { chatList.setAdapter(chatListAdapter); chatListToolbar.inflateMenu(R.menu.chatlist); + chatListToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_show_all: { + Log.d("QD-NG", "Toggling Show/Hide All"); + chatListAdapter.toggleShowAll(); + } break; + } + return false; + } + }); DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); if (drawerLayout != null) { @@ -347,6 +359,11 @@ public class MainActivity extends BoundActivity { } } + protected void reconnect() { + binder.stopBackgroundThread(); + connectToServer(manager.account(context.settings().preferenceLastAccount.get())); + } + @Override protected void onConnectToThread(@Nullable ClientBackgroundThread thread) { super.onConnectToThread(thread); @@ -448,7 +465,10 @@ public class MainActivity extends BoundActivity { new MaterialDialog.Builder(this) .content(context.themeUtil().translations.warningCertificate + "\n" + CertificateUtils.certificateToFingerprint(event.certificate, "")) .title("Unknown Certificate") - .onPositive((dialog, which) -> new SQLiteCertificateManager(this).addCertificate(event.certificate, event.address)) + .onPositive((dialog, which) -> { + new SQLiteCertificateManager(this).addCertificate(event.certificate, event.address); + reconnect(); + }) .negativeColor(context.themeUtil().res.colorForeground) .positiveText("Yes") .negativeText("No") diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/chatview/ChatMessageRenderer.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/chatview/ChatMessageRenderer.java index 683444a26..41e97b704 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/chatview/ChatMessageRenderer.java +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/chatview/ChatMessageRenderer.java @@ -254,7 +254,6 @@ public class ChatMessageRenderer { } private void onBindTopic(@NonNull MessageViewHolder holder, @NonNull Message message) { - System.out.println(message); applyStyle(holder, serverStyle, highlightStyle, message.flags.Highlight); holder.content.setText(message.content); } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferViewConfigAdapter.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferViewConfigAdapter.java index 1e1be5585..90f0c3388 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferViewConfigAdapter.java +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferViewConfigAdapter.java @@ -21,6 +21,7 @@ package de.kuschku.quasseldroid_ng.ui.chat.drawer; +import android.databinding.ObservableField; import android.os.Parcelable; import android.support.annotation.Nullable; import android.support.v7.widget.LinearLayoutManager; @@ -35,7 +36,6 @@ import java.lang.ref.WeakReference; import java.util.Map; import java.util.WeakHashMap; -import de.kuschku.libquassel.events.BufferChangeEvent; import de.kuschku.libquassel.localtypes.buffers.Buffer; import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig; import de.kuschku.libquassel.syncables.types.interfaces.QNetwork; @@ -51,15 +51,14 @@ public class BufferViewConfigAdapter extends ExpandableRecyclerAdapter<NetworkVi private final Map<Integer, BufferViewHolder> bufferViewHolderMap = new WeakHashMap<>(); private QBufferViewConfig config; private WeakReference<RecyclerView> recyclerView = new WeakReference<>(null); - private int selectedFrom; - private int selectedTo; private int open; private OnBufferClickListener bufferClickListener; + private ObservableField<Boolean> showAll = new ObservableField<>(false); private ElementCallback<QNetwork> callback = new ElementCallback<QNetwork>() { @Override public void notifyItemInserted(QNetwork network) { - NetworkItem networkItem = new NetworkItem(context, config, network); + NetworkItem networkItem = new NetworkItem(context, config, network, BufferViewConfigAdapter.this); itemMap.put(network, networkItem); items.add(networkItem); } @@ -75,6 +74,18 @@ public class BufferViewConfigAdapter extends ExpandableRecyclerAdapter<NetworkVi } }; + public void notifyChildItemInserted(NetworkItem parentItem, int childPosition) { + super.notifyChildItemInserted(items.indexOf(parentItem), childPosition); + } + + public void notifyChildItemRemoved(NetworkItem parentItem, int childPosition) { + super.notifyChildItemRemoved(items.indexOf(parentItem), childPosition); + } + + public void notifyChildItemChanged(NetworkItem parentItem, int childPosition) { + super.notifyChildItemChanged(items.indexOf(parentItem), childPosition); + } + private BufferViewConfigAdapter(AppContext context, ObservableSortedList<NetworkItem> items) { super(items); this.context = context; @@ -192,7 +203,7 @@ public class BufferViewConfigAdapter extends ExpandableRecyclerAdapter<NetworkVi items.clear(); itemMap.clear(); for (QNetwork network : config.networkList()) { - NetworkItem networkItem = new NetworkItem(context, config, network); + NetworkItem networkItem = new NetworkItem(context, config, network, this); itemMap.put(network, networkItem); items.add(networkItem); } @@ -243,4 +254,12 @@ public class BufferViewConfigAdapter extends ExpandableRecyclerAdapter<NetworkVi } return -1; } + + public ObservableField<Boolean> showAll() { + return showAll; + } + + public void toggleShowAll() { + showAll.set(!showAll.get()); + } } 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 e528083d0..27c981ef8 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 @@ -21,6 +21,9 @@ package de.kuschku.quasseldroid_ng.ui.chat.drawer; +import android.databinding.Observable; +import android.util.Log; + import com.bignerdranch.expandablerecyclerview.Model.ParentListItem; import java.util.List; @@ -32,10 +35,15 @@ import de.kuschku.libquassel.syncables.types.interfaces.QNetwork; import de.kuschku.quasseldroid_ng.ui.theme.AppContext; import de.kuschku.util.irc.IrcCaseMapper; import de.kuschku.util.observables.callbacks.ElementCallback; +import de.kuschku.util.observables.callbacks.UICallback; +import de.kuschku.util.observables.lists.ObservableSet; import de.kuschku.util.observables.lists.ObservableSortedList; public class NetworkItem implements ParentListItem { + private final AppContext context; + private final QBufferViewConfig config; private final QNetwork network; + private final BufferViewConfigAdapter bufferViewConfigAdapter; private final ObservableSortedList<Buffer> buffers = new ObservableSortedList<>(Buffer.class, new ObservableSortedList.ItemComparator<Buffer>() { @Override public int compare(Buffer o1, Buffer o2) { @@ -69,34 +77,108 @@ public class NetworkItem implements ParentListItem { return item1.getInfo().id == item2.getInfo().id; } }); - - public NetworkItem(AppContext context, QBufferViewConfig config, QNetwork network) { - this.network = network; - for (int id : config.bufferList()) { - Buffer buffer = context.client().bufferManager().buffer(id); - if (context.bufferDisplayTypes().contains(config.mayDisplay(buffer)) && buffer.getInfo().networkId == network.networkId()) + private ElementCallback<Integer> callback = new ElementCallback<Integer>() { + @Override + public void notifyItemInserted(Integer element) { + Buffer buffer = context.client().bufferManager().buffer(element); + if (buffer != null && buffer.getInfo().networkId == network.networkId()) { buffers.add(buffer); + } + } + + @Override + public void notifyItemRemoved(Integer element) { + Buffer buffer = context.client().bufferManager().buffer(element); + if (buffer != null && buffer.getInfo().networkId == network.networkId()) { + buffers.remove(buffer); + } } - config.bufferIds().addCallback(new ElementCallback<Integer>() { + + @Override + public void notifyItemChanged(Integer element) { + Buffer buffer = context.client().bufferManager().buffer(element); + if (buffer != null && buffer.getInfo().networkId == network.networkId()) { + buffers.notifyItemChanged(buffers.indexOf(buffer)); + } + } + }; + private ObservableSet<Integer> backingSet; + + public NetworkItem(AppContext context, QBufferViewConfig config, QNetwork network, BufferViewConfigAdapter bufferViewConfigAdapter) { + this.context = context; + this.config = config; + this.network = network; + this.bufferViewConfigAdapter = bufferViewConfigAdapter; + bufferViewConfigAdapter.showAll().addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() { @Override - public void notifyItemInserted(Integer id) { - Buffer buffer = context.client().bufferManager().buffer(id); - if (context.bufferDisplayTypes().contains(config.mayDisplay(buffer)) && buffer.getInfo().networkId == network.networkId()) - buffers.add(buffer); + public void onPropertyChanged(Observable sender, int propertyId) { + setShowAll(bufferViewConfigAdapter.showAll().get()); + } + }); + setShowAll(bufferViewConfigAdapter.showAll().get()); + this.buffers.addCallback(new UICallback() { + @Override + public void notifyItemInserted(int position) { + bufferViewConfigAdapter.notifyChildItemInserted(NetworkItem.this, position); } @Override - public void notifyItemRemoved(Integer id) { - buffers.remove(context.client().bufferManager().buffer(id)); + public void notifyItemChanged(int position) { + bufferViewConfigAdapter.notifyChildItemChanged(NetworkItem.this, position); } @Override - public void notifyItemChanged(Integer id) { - buffers.notifyItemChanged(buffers.indexOf(context.client().bufferManager().buffer(id))); + public void notifyItemRemoved(int position) { + bufferViewConfigAdapter.notifyChildItemRemoved(NetworkItem.this, position); + } + + @Override + public void notifyItemMoved(int from, int to) { + this.notifyItemRemoved(from); + this.notifyItemInserted(to); + } + + @Override + public void notifyItemRangeInserted(int position, int count) { + for (int i = position; i < position + count; i++) { + this.notifyItemInserted(i); + } + } + + @Override + public void notifyItemRangeChanged(int position, int count) { + for (int i = position; i < position + count; i++) { + this.notifyItemChanged(i); + } + } + + @Override + public void notifyItemRangeRemoved(int position, int count) { + for (int i = position; i < position + count; i++) { + this.notifyItemRemoved(position); + } } }); } + public void populateList(ObservableSet<Integer> backingSet) { + if (this.backingSet != null) + this.backingSet.removeCallback(callback); + buffers.clear(); + + backingSet.addCallback(callback); + for (int id : backingSet) { + Buffer buffer = context.client().bufferManager().buffer(id); + if (buffer != null && buffer.getInfo().networkId == network.networkId()) + buffers.add(buffer); + } + this.backingSet = backingSet; + } + + public void setShowAll(boolean showAll) { + populateList(showAll ? config.allBufferIds() : config.bufferIds()); + } + @Override public List<?> getChildItemList() { return buffers; diff --git a/app/src/main/java/de/kuschku/util/observables/callbacks/wrappers/MultiElementCallbackWrapper.java b/app/src/main/java/de/kuschku/util/observables/callbacks/wrappers/MultiElementCallbackWrapper.java index 2d49b099f..706884a1b 100644 --- a/app/src/main/java/de/kuschku/util/observables/callbacks/wrappers/MultiElementCallbackWrapper.java +++ b/app/src/main/java/de/kuschku/util/observables/callbacks/wrappers/MultiElementCallbackWrapper.java @@ -65,14 +65,14 @@ public class MultiElementCallbackWrapper<T> implements ElementCallback<T> { @Override public void notifyItemRemoved(@Nullable T element) { for (ElementCallback<T> callback : callbacks) { - callback.notifyItemInserted(element); + callback.notifyItemRemoved(element); } } @Override public void notifyItemChanged(@Nullable T element) { for (ElementCallback<T> callback : callbacks) { - callback.notifyItemInserted(element); + callback.notifyItemChanged(element); } } } diff --git a/app/src/main/java/de/kuschku/util/servicebound/BoundActivity.java b/app/src/main/java/de/kuschku/util/servicebound/BoundActivity.java index 1ca1e97be..c39787416 100644 --- a/app/src/main/java/de/kuschku/util/servicebound/BoundActivity.java +++ b/app/src/main/java/de/kuschku/util/servicebound/BoundActivity.java @@ -41,7 +41,7 @@ public abstract class BoundActivity extends AppCompatActivity { protected AppContext context = new AppContext(); @StyleRes private int themeId; - private QuasselService.LocalBinder binder; + protected QuasselService.LocalBinder binder; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 64bf92f02..00183c8bf 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -44,13 +44,13 @@ </LinearLayout> <android.support.design.widget.NavigationView - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="start" android:background="?attr/colorBackground"> <LinearLayout - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> diff --git a/app/src/main/res/menu/chatlist.xml b/app/src/main/res/menu/chatlist.xml index fefc30cbf..e2b37c7b7 100644 --- a/app/src/main/res/menu/chatlist.xml +++ b/app/src/main/res/menu/chatlist.xml @@ -22,13 +22,16 @@ <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item + android:id="@+id/action_join_channel" android:icon="?attr/iconAdd" - android:title="Join Channel" + android:title="@string/action_join_channel" app:showAsAction="ifRoom" /> <item - android:title="Show/Hide Hidden" + android:id="@+id/action_show_all" + android:title="@string/action_show_hide_hidden" app:showAsAction="never" /> <item - android:title="Manage Chat Lists" + android:id="@+id/action_manage_chat_lists" + android:title="@string/action_manage_chat_lists" app:showAsAction="never" /> </menu> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ae9968bb3..8ee6c11f0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -84,4 +84,7 @@ <string name="label_settings">Settings</string> <string name="label_search">Find in Buffer</string> <string name="label_disconnect">Disconnect</string> + <string name="action_manage_chat_lists">Manage Chat Lists</string> + <string name="action_show_hide_hidden">Show/Hide Hidden</string> + <string name="action_join_channel">Join Channel</string> </resources> -- GitLab