Commit 92a70c60 authored by laggedHero's avatar laggedHero Committed by GitHub

Merge pull request #88 from RocketChat/feature/unread-mode

Feature/unread mode
parents f91a845d 1880ace4
......@@ -36,6 +36,6 @@ public class RocketChatApplication extends MultiDexApplication {
InstabugWrapper.build(this, getString(R.string.instabug_api_key));
//TODO: add periodic trigger for RocketChatService.keepalive(this) here!
//TODO: add periodic trigger for RocketChatService.keepAlive(this) here!
}
}
package chat.rocket.android.api;
import android.support.annotation.Nullable;
import org.json.JSONArray;
import org.json.JSONException;
import java.util.UUID;
import bolts.Task;
import chat.rocket.android.helper.OkHttpHelper;
import chat.rocket.android.helper.TextUtils;
......@@ -12,6 +9,11 @@ import chat.rocket.android.log.RCLog;
import chat.rocket.android_ddp.DDPClient;
import chat.rocket.android_ddp.DDPClientCallback;
import chat.rocket.android_ddp.DDPSubscription;
import java.util.UUID;
import org.json.JSONArray;
import org.json.JSONException;
import rx.Observable;
/**
......
......@@ -7,16 +7,14 @@ import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.jakewharton.rxbinding.view.RxView;
import com.jakewharton.rxbinding.widget.RxCompoundButton;
import chat.rocket.android.R;
import chat.rocket.android.RocketChatCache;
import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.fragment.AbstractFragment;
import chat.rocket.android.fragment.sidebar.dialog.AbstractAddRoomDialogFragment;
import chat.rocket.android.fragment.sidebar.dialog.AddChannelDialogFragment;
import chat.rocket.android.fragment.sidebar.dialog.AddDirectMessageDialogFragment;
import chat.rocket.android.fragment.sidebar.dialog.AddChannelDialogFragment;
import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.layouthelper.chatroom.RoomListManager;
......@@ -29,6 +27,9 @@ import chat.rocket.android.realm_helper.RealmObjectObserver;
import chat.rocket.android.realm_helper.RealmStore;
import chat.rocket.android.renderer.UserRenderer;
import com.jakewharton.rxbinding.view.RxView;
import com.jakewharton.rxbinding.widget.RxCompoundButton;
public class SidebarMainFragment extends AbstractFragment {
private String serverConfigId;
......@@ -75,7 +76,7 @@ public class SidebarMainFragment extends AbstractFragment {
currentUserObserver = realmHelper
.createObjectObserver(User::queryCurrentUser)
.setOnUpdateListener(this::onRenderCurrentUser);
.setOnUpdateListener(this::onCurrentUser);
methodCallHelper = new MethodCallHelper(getContext(), serverConfigId);
}
......@@ -103,6 +104,8 @@ public class SidebarMainFragment extends AbstractFragment {
setupAddChannelButton();
roomListManager = new RoomListManager(
rootView.findViewById(R.id.unread_title),
(LinearLayout) rootView.findViewById(R.id.unread_container),
(LinearLayout) rootView.findViewById(R.id.channels_container),
(LinearLayout) rootView.findViewById(R.id.direct_messages_container));
roomListManager.setOnItemClickListener(view -> {
......@@ -142,6 +145,11 @@ public class SidebarMainFragment extends AbstractFragment {
}
}
private void onCurrentUser(User user) {
onRenderCurrentUser(user);
updateRoomListMode(user);
}
private void onRenderCurrentUser(User user) {
if (user != null && !TextUtils.isEmpty(hostname)) {
new UserRenderer(getContext(), user)
......@@ -151,6 +159,13 @@ public class SidebarMainFragment extends AbstractFragment {
}
}
private void updateRoomListMode(User user) {
if (user == null || user.getSettings() == null || user.getSettings().getPreferences() == null) {
return;
}
roomListManager.setUnreadRoomMode(user.getSettings().getPreferences().isUnreadRoomsMode());
}
private void setupLogoutButton() {
rootView.findViewById(R.id.btn_logout).setOnClickListener(view -> {
if (methodCallHelper != null) {
......
......@@ -3,61 +3,60 @@ package chat.rocket.android.layouthelper.chatroom;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.model.ddp.RoomSubscription;
import chat.rocket.android.widget.internal.RoomListItemView;
import java.util.List;
/**
* Utility class for mapping Room list into channel list ViewGroup.
*/
public class RoomListManager {
private View unreadTitle;
private ViewGroup unreadRoomsContainer;
private ViewGroup channelsContainer;
private ViewGroup dmContainer;
private boolean unreadRoomMode = false;
private List<RoomSubscription> roomSubscriptionList;
/**
* Callback interface for List item clicked.
*/
public interface OnItemClickListener {
void onItemClick(RoomListItemView roomListItemView);
}
private OnItemClickListener listener;
/**
* constructor with three ViewGroups.
*/
public RoomListManager(View unreadTitle, ViewGroup unreadRoomsContainer,
ViewGroup channelsContainer, ViewGroup dmContainer) {
this(unreadTitle, unreadRoomsContainer, channelsContainer, dmContainer, false);
}
/**
* constructor with two ViewGroups.
*/
public RoomListManager(ViewGroup channelsContainer, ViewGroup dmContainer) {
public RoomListManager(View unreadTitle, ViewGroup unreadRoomsContainer,
ViewGroup channelsContainer, ViewGroup dmContainer,
boolean unreadRoomMode) {
this.unreadTitle = unreadTitle;
this.unreadRoomsContainer = unreadRoomsContainer;
this.channelsContainer = channelsContainer;
this.dmContainer = dmContainer;
}
private static void removeItemIfExists(ViewGroup parent, String roomName) {
for (int i = 0; i < parent.getChildCount(); i++) {
RoomListItemView roomListItemView = (RoomListItemView) parent.getChildAt(i);
if (roomName.equals(roomListItemView.getRoomName())) {
parent.removeViewAt(i);
break;
}
}
this.unreadRoomMode = unreadRoomMode;
}
/**
* update ViewGroups with room list.
*/
public void setRooms(List<RoomSubscription> roomSubscriptionList) {
removeDeletedItem(channelsContainer, roomSubscriptionList);
removeDeletedItem(dmContainer, roomSubscriptionList);
for (RoomSubscription roomSubscription : roomSubscriptionList) {
String name = roomSubscription.getName();
if (TextUtils.isEmpty(name)) {
continue;
}
String type = roomSubscription.getType();
if (RoomSubscription.TYPE_CHANNEL.equals(type)
|| RoomSubscription.TYPE_PRIVATE.equals(type)) {
insertOrUpdateItem(channelsContainer, roomSubscription);
removeItemIfExists(dmContainer, name);
} else if (RoomSubscription.TYPE_DIRECT_MESSAGE.equals(type)) {
removeItemIfExists(channelsContainer, name);
insertOrUpdateItem(dmContainer, roomSubscription);
}
}
this.roomSubscriptionList = roomSubscriptionList;
updateRoomsList();
}
/**
......@@ -86,6 +85,11 @@ public class RoomListManager {
}
}
public void setUnreadRoomMode(boolean unreadRoomMode) {
this.unreadRoomMode = unreadRoomMode;
updateRoomsList();
}
private void insertOrUpdateItem(ViewGroup parent, RoomSubscription roomSubscription) {
final String roomName = roomSubscription.getName();
......@@ -129,10 +133,47 @@ public class RoomListManager {
}
}
/**
* Callback interface for List item clicked.
*/
public interface OnItemClickListener {
void onItemClick(RoomListItemView roomListItemView);
private void updateRoomsList() {
removeDeletedItem(unreadRoomsContainer, roomSubscriptionList);
removeDeletedItem(channelsContainer, roomSubscriptionList);
removeDeletedItem(dmContainer, roomSubscriptionList);
for (RoomSubscription roomSubscription : roomSubscriptionList) {
String name = roomSubscription.getName();
if (TextUtils.isEmpty(name)) {
continue;
}
String type = roomSubscription.getType();
if (unreadRoomMode && roomSubscription.isAlert()) {
insertOrUpdateItem(unreadRoomsContainer, roomSubscription);
removeItemIfExists(channelsContainer, name);
removeItemIfExists(dmContainer, name);
} else if (RoomSubscription.TYPE_CHANNEL.equals(type)
|| RoomSubscription.TYPE_PRIVATE.equals(type)) {
removeItemIfExists(unreadRoomsContainer, name);
insertOrUpdateItem(channelsContainer, roomSubscription);
removeItemIfExists(dmContainer, name);
} else if (RoomSubscription.TYPE_DIRECT_MESSAGE.equals(type)) {
removeItemIfExists(unreadRoomsContainer, name);
removeItemIfExists(channelsContainer, name);
insertOrUpdateItem(dmContainer, roomSubscription);
}
}
boolean showUnread = unreadRoomMode && unreadRoomsContainer.getChildCount() != 0;
unreadTitle.setVisibility(showUnread ? View.VISIBLE : View.GONE);
unreadRoomsContainer.setVisibility(showUnread ? View.VISIBLE : View.GONE);
}
private static void removeItemIfExists(ViewGroup parent, String roomName) {
for (int i = 0; i < parent.getChildCount(); i++) {
RoomListItemView roomListItemView = (RoomListItemView) parent.getChildAt(i);
if (roomName.equals(roomListItemView.getRoomName())) {
parent.removeViewAt(i);
break;
}
}
}
}
package chat.rocket.android.model.ddp;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
@SuppressWarnings({"PMD.ShortVariable"})
public class Preferences extends RealmObject {
@PrimaryKey private String id;
private boolean newRoomNotification;
private boolean newMessageNotification;
private boolean useEmojis;
private boolean convertAsciiEmoji;
private boolean saveMobileBandwidth;
private boolean collapseMediaByDefault;
private boolean unreadRoomsMode;
private boolean autoImageLoad;
private String emailNotificationMode;
private boolean unreadAlert;
private int desktopNotificationDuration;
private int viewMode;
private boolean hideUsernames;
private boolean hideAvatars;
private boolean hideFlexTab;
// private List<String> highlights; // Realm does not support this yet
public boolean isNewRoomNotification() {
return newRoomNotification;
}
public boolean isNewMessageNotification() {
return newMessageNotification;
}
public boolean isUseEmojis() {
return useEmojis;
}
public boolean isConvertAsciiEmoji() {
return convertAsciiEmoji;
}
public boolean isSaveMobileBandwidth() {
return saveMobileBandwidth;
}
public boolean isCollapseMediaByDefault() {
return collapseMediaByDefault;
}
public boolean isUnreadRoomsMode() {
return unreadRoomsMode;
}
public boolean isAutoImageLoad() {
return autoImageLoad;
}
public String getEmailNotificationMode() {
return emailNotificationMode;
}
public boolean isUnreadAlert() {
return unreadAlert;
}
public int getDesktopNotificationDuration() {
return desktopNotificationDuration;
}
public int getViewMode() {
return viewMode;
}
public boolean isHideUsernames() {
return hideUsernames;
}
public boolean isHideAvatars() {
return hideAvatars;
}
public boolean isHideFlexTab() {
return hideFlexTab;
}
}
package chat.rocket.android.model.ddp;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
@SuppressWarnings({"PMD.ShortVariable"})
public class Settings extends RealmObject {
@PrimaryKey private String id;
private Preferences preferences;
public Preferences getPreferences() {
return preferences;
}
}
......@@ -22,6 +22,7 @@ public class User extends RealmObject {
private String status;
private double utcOffset;
private RealmList<Email> emails;
private Settings settings;
public static RealmQuery<User> queryCurrentUser(Realm realm) {
return realm.where(User.class).isNotEmpty("emails");
......@@ -66,4 +67,8 @@ public class User extends RealmObject {
public void setEmails(RealmList<Email> emails) {
this.emails = emails;
}
public Settings getSettings() {
return settings;
}
}
......@@ -14,6 +14,7 @@ public class LoadMessageProcedure extends RealmObject {
private long timestamp;
private int count;
@SuppressWarnings({"PMD.AvoidFieldNameMatchingMethodName"})
private boolean hasNext;
public String getRoomId() {
......
......@@ -71,7 +71,7 @@ public class RocketChatService extends Service {
if (webSocketThreads.containsKey(serverConfigId)) {
RocketChatWebSocketThread thread = webSocketThreads.get(serverConfigId);
if (thread != null) {
thread.keepalive();
thread.keepAlive();
}
}
}
......@@ -110,7 +110,7 @@ public class RocketChatService extends Service {
.onSuccessTask(task -> {
RocketChatWebSocketThread thread = task.getResult();
if (thread != null) {
thread.keepalive();
thread.keepAlive();
}
return ServerConfig.updateState(serverConfigId, ServerConfig.STATE_CONNECTED);
}).continueWith(new LogcatIfError());
......
......@@ -140,7 +140,7 @@ public class RocketChatWebSocketThread extends HandlerThread {
* synchronize the state of the thread with ServerConfig.
*/
@DebugLog
public void keepalive() {
public void keepAlive() {
if (ddpClient == null || !ddpClient.isConnected()) {
defaultRealm.executeTransaction(realm -> {
ServerConfig config = realm.where(ServerConfig.class)
......@@ -242,9 +242,9 @@ public class RocketChatWebSocketThread extends HandlerThread {
Object obj = ctor.newInstance(appContext, hostname, serverConfigRealm, ddpClient);
if (obj instanceof Registrable) {
Registrable registerable = (Registrable) obj;
registerable.register();
listeners.add(registerable);
Registrable registrable = (Registrable) obj;
registrable.register();
listeners.add(registrable);
}
} catch (Exception exception) {
RCLog.w(exception, "Failed to register listeners!!");
......@@ -260,8 +260,8 @@ public class RocketChatWebSocketThread extends HandlerThread {
Iterator<Registrable> iterator = listeners.iterator();
while (iterator.hasNext()) {
Registrable registerable = iterator.next();
registerable.unregister();
Registrable registrable = iterator.next();
registrable.unregister();
iterator.remove();
}
if (ddpClient != null) {
......
......@@ -3,6 +3,9 @@ package chat.rocket.android.service.ddp.base;
import android.content.Context;
import io.realm.RealmObject;
import org.json.JSONException;
import org.json.JSONObject;
import chat.rocket.android.api.DDPClientWrapper;
import chat.rocket.android.model.ddp.User;
import chat.rocket.android.realm_helper.RealmHelper;
......@@ -30,4 +33,23 @@ public class UserDataSubscriber extends AbstractBaseSubscriber {
protected Class<? extends RealmObject> getModelClass() {
return User.class;
}
@Override
protected JSONObject customizeFieldJson(JSONObject json) throws JSONException {
json = super.customizeFieldJson(json);
// The user object may have some children without a proper primary key (ex.: settings)
// Here we identify this and add a local key
if (json.has("settings")) {
final JSONObject settingsJson = json.getJSONObject("settings");
settingsJson.put("id", json.getString("_id"));
if (settingsJson.has("preferences")) {
final JSONObject preferencesJson = settingsJson.getJSONObject("preferences");
preferencesJson.put("id", json.getString("_id"));
}
}
return json;
}
}
......@@ -33,4 +33,5 @@
<string name="add_server_activity_waiting_server">Connecting to server…</string>
<string name="server_config_activity_authenticating">Authenticating…</string>
<string name="home_fragment_title">Rocket.Chat - Home</string>
<string name="fragment_sidebar_main_unread_rooms_title">UNREAD ROOMS</string>
</resources>
......@@ -5,7 +5,7 @@ ext {
retroLambdaPatch = 'me.tatarka.retrolambda.projectlombok:lombok.ast:0.2.3.a2'
compileSdkVersion = 25
buildToolsVersion = '25.0.1'
minSdkVersion = 21 //for accelerating multi-dex build. OVERRIDEN BY Circle CI to 17
minSdkVersion = 16
supportVersion = '25.0.1'
supportAnnotations = "com.android.support:support-annotations:$supportVersion"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment