Commit 980212f8 authored by Yusuke Iwaki's avatar Yusuke Iwaki

implement message view stub.

parent 54872cab
package chat.rocket.android.activity; package chat.rocket.android.activity;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle;
import chat.rocket.android.LaunchUtil; import chat.rocket.android.LaunchUtil;
import chat.rocket.android.RocketChatCache; import chat.rocket.android.RocketChatCache;
import chat.rocket.android.model.ServerConfig; import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.realm_helper.RealmListObserver; import chat.rocket.android.realm_helper.RealmListObserver;
import chat.rocket.android.realm_helper.RealmStore; import chat.rocket.android.realm_helper.RealmStore;
import chat.rocket.android.service.RocketChatService; import chat.rocket.android.service.RocketChatService;
import icepick.State;
abstract class AbstractAuthedActivity extends AbstractFragmentActivity { abstract class AbstractAuthedActivity extends AbstractFragmentActivity {
private RealmListObserver<ServerConfig> unconfiguredServersObserver = private RealmListObserver<ServerConfig> unconfiguredServersObserver =
...@@ -19,8 +21,8 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity { ...@@ -19,8 +21,8 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity {
} }
}); });
protected String serverConfigId; @State protected String serverConfigId;
protected String roomId; @State protected String roomId;
SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener =
(sharedPreferences, key) -> { (sharedPreferences, key) -> {
...@@ -67,11 +69,7 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity { ...@@ -67,11 +69,7 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity {
onRoomIdUpdated(); onRoomIdUpdated();
} }
protected void onServerConfigIdUpdated() { protected void onServerConfigIdUpdated() {}
RocketChatCache.get(this).edit()
.remove(RocketChatCache.KEY_SELECTED_ROOM_ID)
.apply();
}
protected void onRoomIdUpdated() {} protected void onRoomIdUpdated() {}
...@@ -93,4 +91,8 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity { ...@@ -93,4 +91,8 @@ abstract class AbstractAuthedActivity extends AbstractFragmentActivity {
unconfiguredServersObserver.unsub(); unconfiguredServersObserver.unsub();
super.onPause(); super.onPause();
} }
@Override protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
} }
...@@ -29,7 +29,9 @@ public class MainActivity extends AbstractAuthedActivity { ...@@ -29,7 +29,9 @@ public class MainActivity extends AbstractAuthedActivity {
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
setupSidebar(); setupSidebar();
showFragment(new HomeFragment()); if (roomId == null) {
showFragment(new HomeFragment());
}
} }
private void setupSidebar() { private void setupSidebar() {
......
...@@ -2,14 +2,22 @@ package chat.rocket.android.fragment.chatroom; ...@@ -2,14 +2,22 @@ package chat.rocket.android.fragment.chatroom;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import chat.rocket.android.R; import chat.rocket.android.R;
import chat.rocket.android.helper.LogcatIfError; import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.layouthelper.chatroom.MessageListAdapter;
import chat.rocket.android.model.SyncState; import chat.rocket.android.model.SyncState;
import chat.rocket.android.model.ddp.Message;
import chat.rocket.android.model.ddp.RoomSubscription; import chat.rocket.android.model.ddp.RoomSubscription;
import chat.rocket.android.model.internal.LoadMessageProcedure; import chat.rocket.android.model.internal.LoadMessageProcedure;
import chat.rocket.android.realm_helper.RealmHelper; import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.realm_helper.RealmModelListView;
import chat.rocket.android.realm_helper.RealmObjectObserver; import chat.rocket.android.realm_helper.RealmObjectObserver;
import chat.rocket.android.realm_helper.RealmStore; import chat.rocket.android.realm_helper.RealmStore;
import io.realm.Realm;
import io.realm.RealmResults;
import io.realm.Sort;
import org.json.JSONObject; import org.json.JSONObject;
/** /**
...@@ -45,6 +53,8 @@ public class RoomFragment extends AbstractChatRoomFragment { ...@@ -45,6 +53,8 @@ public class RoomFragment extends AbstractChatRoomFragment {
roomObserver = realmHelper roomObserver = realmHelper
.createObjectObserver(realm -> realm.where(RoomSubscription.class).equalTo("rid", roomId)) .createObjectObserver(realm -> realm.where(RoomSubscription.class).equalTo("rid", roomId))
.setOnUpdateListener(this::onRenderRoom); .setOnUpdateListener(this::onRenderRoom);
initialRequest();
} }
@Override protected int getLayout() { @Override protected int getLayout() {
...@@ -52,8 +62,24 @@ public class RoomFragment extends AbstractChatRoomFragment { ...@@ -52,8 +62,24 @@ public class RoomFragment extends AbstractChatRoomFragment {
} }
@Override protected void onSetupView() { @Override protected void onSetupView() {
RealmModelListView listView = (RealmModelListView) rootView.findViewById(R.id.listview);
realmHelper.bindListView(listView,
realm -> realm.where(Message.class)
.equalTo("rid", roomId)
.findAllSorted("ts", Sort.DESCENDING),
MessageListAdapter::new);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext(),
LinearLayoutManager.VERTICAL, true);
listView.setLayoutManager(layoutManager);
}
private void onRenderRoom(RoomSubscription roomSubscription) {
activityToolbar.setTitle(roomSubscription.getName());
}
// TODO: just a sample!! private void initialRequest() {
realmHelper.executeTransaction(realm -> { realmHelper.executeTransaction(realm -> {
realm.createOrUpdateObjectFromJson(LoadMessageProcedure.class, new JSONObject() realm.createOrUpdateObjectFromJson(LoadMessageProcedure.class, new JSONObject()
.put("roomId", roomId) .put("roomId", roomId)
...@@ -64,8 +90,8 @@ public class RoomFragment extends AbstractChatRoomFragment { ...@@ -64,8 +90,8 @@ public class RoomFragment extends AbstractChatRoomFragment {
}).continueWith(new LogcatIfError()); }).continueWith(new LogcatIfError());
} }
private void onRenderRoom(RoomSubscription roomSubscription) { private RealmResults<Message> queryItems(Realm realm) {
activityToolbar.setTitle(roomSubscription.getName()); return realm.where(Message.class).equalTo("rid", roomId).findAllSorted("ts");
} }
@Override public void onResume() { @Override public void onResume() {
......
package chat.rocket.android.layouthelper.chatroom;
import android.content.Context;
import android.view.View;
import chat.rocket.android.model.ddp.Message;
import chat.rocket.android.realm_adapter.RealmModelListAdapter;
/**
* message list adapter for chat room.
*/
public class MessageListAdapter extends RealmModelListAdapter<Message, MessageViewHolder> {
public MessageListAdapter(Context context) {
super(context);
}
@Override protected int getItemViewType(Message model) {
return 0;
}
@Override protected int getLayout(int viewType) {
return android.R.layout.simple_list_item_1;
}
@Override protected MessageViewHolder onCreateRealmModelViewHolder(int viewType, View itemView) {
return new MessageViewHolder(itemView);
}
}
package chat.rocket.android.layouthelper.chatroom;
import android.graphics.Color;
import android.view.View;
import android.widget.TextView;
import chat.rocket.android.model.ddp.Message;
import chat.rocket.android.realm_adapter.RealmModelViewHolder;
/**
*/
public class MessageViewHolder extends RealmModelViewHolder<Message> {
private TextView text;
public MessageViewHolder(View itemView) {
super(itemView);
text = (TextView) itemView.findViewById(android.R.id.text1);
}
public void bind(Message message) {
text.setText(message.getMsg());
text.setTextColor(Color.BLACK);
}
}
...@@ -64,8 +64,7 @@ public class LoadMessageProcedureObserver extends AbstractModelObserver<LoadMess ...@@ -64,8 +64,7 @@ public class LoadMessageProcedureObserver extends AbstractModelObserver<LoadMess
.put("roomId", roomId) .put("roomId", roomId)
.put("syncstate", SyncState.SYNCED) .put("syncstate", SyncState.SYNCED)
.put("timestamp", lastTs) .put("timestamp", lastTs)
.put("hasNext", lastTs > 0)) .put("hasNext", lastTs > 0)));
);
}) })
).continueWithTask(task -> { ).continueWithTask(task -> {
if (task.isFaulted()) { if (task.isFaulted()) {
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView <chat.rocket.android.realm_helper.RealmModelListView
android:id="@+id/recyclerview" android:id="@+id/listview"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
/> />
......
...@@ -36,4 +36,5 @@ dependencies { ...@@ -36,4 +36,5 @@ dependencies {
compile rootProject.ext.supportAnnotations compile rootProject.ext.supportAnnotations
compile rootProject.ext.supportAppCompat compile rootProject.ext.supportAppCompat
compile rootProject.ext.supportDesign compile rootProject.ext.supportDesign
compile 'io.realm:android-adapters:1.4.0'
} }
package chat.rocket.android.realm_adapter;
import android.content.Context;
import android.support.annotation.LayoutRes;
import android.view.View;
import android.view.ViewGroup;
import io.realm.Realm;
import io.realm.RealmObject;
import io.realm.RealmRecyclerViewAdapter;
import io.realm.RealmResults;
public abstract class RealmModelListAdapter<T extends RealmObject,
VH extends RealmModelViewHolder<T>> extends RealmRecyclerViewAdapter<T, VH> {
public interface Query<T extends RealmObject> {
RealmResults<T> queryItems(Realm realm);
}
public interface Constructor<T extends RealmObject, VH extends RealmModelViewHolder<T>> {
RealmModelListAdapter<T, VH> getNewInstance(Context context);
}
public RealmModelListAdapter(Context context) {
super(context, null, true);
}
protected abstract int getItemViewType(T model);
protected abstract @LayoutRes int getLayout(int viewType);
protected abstract VH onCreateRealmModelViewHolder(int viewType, View itemView);
@Override public final int getItemViewType(int position) {
return getItemViewType(getItem(position));
}
@Override public VH onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = inflater.inflate(getLayout(viewType), parent, false);
return onCreateRealmModelViewHolder(viewType, itemView);
}
@Override public void onBindViewHolder(VH holder, int position) {
holder.bind(getItem(position));
}
}
package chat.rocket.android.realm_adapter;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import io.realm.RealmObject;
public abstract class RealmModelViewHolder<T extends RealmObject> extends RecyclerView.ViewHolder {
public RealmModelViewHolder(View itemView) {
super(itemView);
}
public abstract void bind(T model);
}
...@@ -32,7 +32,7 @@ abstract class AbstractRealmResultsObserver<T extends RealmObject> { ...@@ -32,7 +32,7 @@ abstract class AbstractRealmResultsObserver<T extends RealmObject> {
} }
public void keepalive() { public void keepalive() {
if (realm == null || realm.isClosed()) { if (realm == null || realm.isClosed() || !results.isValid()) {
unsub(); unsub();
sub(); sub();
} }
...@@ -41,7 +41,9 @@ abstract class AbstractRealmResultsObserver<T extends RealmObject> { ...@@ -41,7 +41,9 @@ abstract class AbstractRealmResultsObserver<T extends RealmObject> {
public void unsub() { public void unsub() {
try { try {
if (results != null) { if (results != null) {
results.removeChangeListener(listener); if (results.isValid()) {
results.removeChangeListener(listener);
}
results = null; results = null;
} }
if (realm != null && !realm.isClosed()) { if (realm != null && !realm.isClosed()) {
......
...@@ -3,6 +3,8 @@ package chat.rocket.android.realm_helper; ...@@ -3,6 +3,8 @@ package chat.rocket.android.realm_helper;
import android.os.Looper; import android.os.Looper;
import bolts.Task; import bolts.Task;
import bolts.TaskCompletionSource; import bolts.TaskCompletionSource;
import chat.rocket.android.realm_adapter.RealmModelListAdapter;
import chat.rocket.android.realm_adapter.RealmModelViewHolder;
import io.realm.Realm; import io.realm.Realm;
import io.realm.RealmConfiguration; import io.realm.RealmConfiguration;
import io.realm.RealmObject; import io.realm.RealmObject;
...@@ -168,4 +170,13 @@ public class RealmHelper { ...@@ -168,4 +170,13 @@ public class RealmHelper {
RealmObjectObserver.Query<T> query) { RealmObjectObserver.Query<T> query) {
return new RealmObjectObserver<T>(this, query); return new RealmObjectObserver<T>(this, query);
} }
public <T extends RealmObject, VH extends RealmModelViewHolder<T>> void bindListView(
RealmModelListView listView,
RealmModelListAdapter.Query<T> query,
RealmModelListAdapter.Constructor<T, VH> constructor) {
if (listView != null) {
listView.setup(this, query, constructor);
}
}
} }
package chat.rocket.android.realm_helper;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.View;
import chat.rocket.android.realm_adapter.RealmModelListAdapter;
import chat.rocket.android.realm_adapter.RealmModelViewHolder;
import io.realm.Realm;
import io.realm.RealmObject;
import io.realm.RealmResults;
public class RealmModelListView extends RecyclerView {
private Realm realm;
public RealmModelListView(Context context) {
super(context);
}
public RealmModelListView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RealmModelListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/*package*/ <T extends RealmObject, VH extends RealmModelViewHolder<T>> void setup(
final RealmHelper realmHelper,
final RealmModelListAdapter.Query<T> query,
final RealmModelListAdapter.Constructor<T, VH> constructor) {
addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
@Override public void onViewAttachedToWindow(View view) {
realm = realmHelper.instance();
RealmResults<T> results = query.queryItems(realm);
RealmModelListAdapter<T, VH> adapter = constructor.getNewInstance(view.getContext());
adapter.updateData(results);
setAdapter(adapter);
}
@Override public void onViewDetachedFromWindow(View view) {
setAdapter(null);
if (realm != null && !realm.isClosed()) {
realm.close();
}
}
});
}
// just for preventing from unexpected overriding.
@Override public final void setAdapter(Adapter adapter) {
super.setAdapter(adapter);
}
}
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