Commit 8cb36a6f authored by Tiago Cunha's avatar Tiago Cunha Committed by GitHub

Merge pull request #273 from RocketChat/feature/search-channel

TDC emergency search channel
parents 13837af2 43cbdabe
......@@ -109,6 +109,7 @@ dependencies {
compile "com.jakewharton.rxbinding2:rxbinding:$rxbindingVersion"
compile "com.jakewharton.rxbinding2:rxbinding-support-v4:$rxbindingVersion"
compile "com.jakewharton.rxbinding2:rxbinding-appcompat-v7:$rxbindingVersion"
compile "com.trello.rxlifecycle2:rxlifecycle:$rxlifecycleVersion"
compile "com.trello.rxlifecycle2:rxlifecycle-android:$rxlifecycleVersion"
......
......@@ -154,6 +154,11 @@ public class MethodCallHelper {
.onSuccessTask(task -> Task.forResult(null));
}
public Task<Void> joinRoom(String roomId) {
return call("joinRoom", TIMEOUT_MS, () -> new JSONArray().put(roomId))
.onSuccessTask(task -> Task.forResult(null));
}
/**
* Login with username/email and password.
*/
......
......@@ -6,6 +6,7 @@ import java.util.List;
import chat.rocket.android.fragment.chatroom.RocketChatAbsoluteUrl;
import chat.rocket.android.shared.BaseContract;
import chat.rocket.core.models.Room;
import chat.rocket.core.models.SpotlightRoom;
import chat.rocket.core.models.User;
public interface SidebarMainContract {
......@@ -25,6 +26,8 @@ public interface SidebarMainContract {
void onRoomSelected(Room room);
void onSpotlightRoomSelected(SpotlightRoom spotlightRoom);
void onUserOnline();
void onUserAway();
......
......@@ -7,15 +7,22 @@ import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
import com.jakewharton.rxbinding2.support.v7.widget.RxSearchView;
import com.jakewharton.rxbinding2.widget.RxCompoundButton;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import chat.rocket.android.BuildConfig;
import chat.rocket.android.R;
import chat.rocket.android.RocketChatCache;
......@@ -33,14 +40,17 @@ import chat.rocket.android.layouthelper.chatroom.roomlist.FavoriteRoomListHeader
import chat.rocket.android.layouthelper.chatroom.roomlist.RoomListAdapter;
import chat.rocket.android.layouthelper.chatroom.roomlist.RoomListHeader;
import chat.rocket.android.layouthelper.chatroom.roomlist.UnreadRoomListHeader;
import chat.rocket.core.SortDirection;
import chat.rocket.core.interactors.RoomInteractor;
import chat.rocket.core.interactors.SessionInteractor;
import chat.rocket.core.models.Room;
import chat.rocket.core.models.SpotlightRoom;
import chat.rocket.core.models.User;
import chat.rocket.android.renderer.UserRenderer;
import chat.rocket.persistence.realm.repositories.RealmRoomRepository;
import chat.rocket.persistence.realm.repositories.RealmServerInfoRepository;
import chat.rocket.persistence.realm.repositories.RealmSessionRepository;
import chat.rocket.persistence.realm.repositories.RealmSpotlightRoomRepository;
import chat.rocket.persistence.realm.repositories.RealmUserRepository;
import chat.rocket.android.widget.RocketChatAvatar;
......@@ -54,6 +64,10 @@ public class SidebarMainFragment extends AbstractFragment implements SidebarMain
private String hostname;
private MethodCallHelper methodCallHelper;
private RealmSpotlightRoomRepository realmSpotlightRoomRepository;
private SearchView searchView;
public SidebarMainFragment() {
}
......@@ -77,6 +91,9 @@ public class SidebarMainFragment extends AbstractFragment implements SidebarMain
Bundle args = getArguments();
hostname = args == null ? null : args.getString(HOSTNAME);
methodCallHelper = new MethodCallHelper(getContext(), hostname);
realmSpotlightRoomRepository = new RealmSpotlightRoomRepository(hostname);
RealmUserRepository userRepository = new RealmUserRepository(hostname);
AbsoluteUrlHelper absoluteUrlHelper = new AbsoluteUrlHelper(
......@@ -113,6 +130,7 @@ public class SidebarMainFragment extends AbstractFragment implements SidebarMain
return R.layout.fragment_sidebar_main;
}
@SuppressLint("RxLeakedSubscription")
@Override
protected void onSetupView() {
setupUserActionToggle();
......@@ -121,12 +139,55 @@ public class SidebarMainFragment extends AbstractFragment implements SidebarMain
setupVersionInfo();
adapter = new RoomListAdapter();
adapter.setOnItemClickListener(room -> presenter.onRoomSelected(room));
adapter.setOnItemClickListener(new RoomListAdapter.OnItemClickListener() {
@Override
public void onItemClick(Room room) {
searchView.clearFocus();
presenter.onRoomSelected(room);
}
@Override
public void onItemClick(SpotlightRoom spotlightRoom) {
searchView.setQuery(null, false);
searchView.clearFocus();
methodCallHelper.joinRoom(spotlightRoom.getId())
.onSuccessTask(task -> {
presenter.onSpotlightRoomSelected(spotlightRoom);
return null;
});
}
});
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.room_list_container);
recyclerView.setLayoutManager(
new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(adapter);
searchView = (SearchView) rootView.findViewById(R.id.search);
RxSearchView.queryTextChanges(searchView)
.compose(bindToLifecycle())
.debounce(300, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.switchMap(it -> {
if (it.length() == 0) {
adapter.setMode(RoomListAdapter.MODE_ROOM);
return Observable.just(Collections.<SpotlightRoom>emptyList());
}
adapter.setMode(RoomListAdapter.MODE_SPOTLIGHT_ROOM);
final String queryString = it.toString();
methodCallHelper.searchSpotlightRooms(queryString);
return realmSpotlightRoomRepository.getSuggestionsFor(queryString, SortDirection.DESC, 10)
.toObservable();
})
.subscribe(
this::showSearchSuggestions,
Logger::report
);
}
@SuppressLint("RxLeakedSubscription")
......@@ -246,4 +307,8 @@ public class SidebarMainFragment extends AbstractFragment implements SidebarMain
onRenderCurrentUser(user, absoluteUrl);
updateRoomListMode(user);
}
private void showSearchSuggestions(List<SpotlightRoom> spotlightRooms) {
adapter.setSpotlightRoomList(spotlightRooms);
}
}
......@@ -17,6 +17,7 @@ import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.shared.BasePresenter;
import chat.rocket.core.interactors.RoomInteractor;
import chat.rocket.core.models.Room;
import chat.rocket.core.models.SpotlightRoom;
import chat.rocket.core.models.User;
import chat.rocket.core.repositories.UserRepository;
......@@ -76,6 +77,11 @@ public class SidebarMainPresenter extends BasePresenter<SidebarMainContract.View
rocketChatCache.setSelectedRoomId(room.getRoomId());
}
@Override
public void onSpotlightRoomSelected(SpotlightRoom spotlightRoom) {
rocketChatCache.setSelectedRoomId(spotlightRoom.getId());
}
@Override
public void onUserOnline() {
updateCurrentUserStatus(User.STATUS_ONLINE);
......
......@@ -12,21 +12,38 @@ import java.util.Map;
import chat.rocket.android.R;
import chat.rocket.android.widget.internal.RoomListItemView;
import chat.rocket.core.models.Room;
import chat.rocket.core.models.SpotlightRoom;
public class RoomListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static final int MODE_ROOM = 0;
public static final int MODE_SPOTLIGHT_ROOM = 1;
private static final int VIEW_TYPE_HEADER = 0;
private static final int VIEW_TYPE_ROOM = 1;
private List<Room> roomList = Collections.emptyList();
private List<SpotlightRoom> spotlightRoomList = Collections.emptyList();
private List<RoomListHeader> roomListHeaders = Collections.emptyList();
private Map<Integer, RoomListHeader> headersPosition = new HashMap<>();
private int mode = MODE_ROOM;
private OnItemClickListener externalListener;
private OnItemClickListener listener = room -> {
private OnItemClickListener listener = new OnItemClickListener() {
@Override
public void onItemClick(Room room) {
if (externalListener != null) {
externalListener.onItemClick(room);
}
}
@Override
public void onItemClick(SpotlightRoom spotlightRoom) {
if (externalListener != null) {
externalListener.onItemClick(spotlightRoom);
}
}
};
public void setRoomListHeaders(@NonNull List<RoomListHeader> roomListHeaders) {
......@@ -39,6 +56,20 @@ public class RoomListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
updateRoomList();
}
public void setSpotlightRoomList(@NonNull List<SpotlightRoom> spotlightRoomList) {
this.spotlightRoomList = spotlightRoomList;
updateRoomList();
}
public void setMode(int mode) {
this.mode = mode;
if (mode == MODE_ROOM) {
// clean up
spotlightRoomList.clear();
}
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
externalListener = onItemClickListener;
}
......@@ -56,6 +87,7 @@ public class RoomListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (mode == MODE_ROOM) {
if (getItemViewType(position) == VIEW_TYPE_HEADER) {
((RoomListHeaderViewHolder) holder)
.bind(headersPosition.get(position));
......@@ -64,15 +96,26 @@ public class RoomListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
((RoomListItemViewHolder) holder)
.bind(roomList.get(position - getTotalHeadersBeforePosition(position)));
} else if (mode == MODE_SPOTLIGHT_ROOM) {
((RoomListItemViewHolder) holder)
.bind(spotlightRoomList.get(position));
}
}
@Override
public int getItemCount() {
if (mode == MODE_SPOTLIGHT_ROOM) {
return spotlightRoomList.size();
}
return roomList.size() + headersPosition.size();
}
@Override
public int getItemViewType(int position) {
if (mode == MODE_SPOTLIGHT_ROOM) {
return VIEW_TYPE_ROOM;
}
if (headersPosition.containsKey(position)) {
return VIEW_TYPE_HEADER;
}
......@@ -80,8 +123,10 @@ public class RoomListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
}
private void updateRoomList() {
if (mode == MODE_ROOM) {
sortRoomList();
calculateHeadersPosition();
}
notifyDataSetChanged();
}
......@@ -142,5 +187,7 @@ public class RoomListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolde
public interface OnItemClickListener {
void onItemClick(Room room);
void onItemClick(SpotlightRoom spotlightRoom);
}
}
......@@ -4,6 +4,7 @@ import android.support.v7.widget.RecyclerView;
import chat.rocket.android.widget.internal.RoomListItemView;
import chat.rocket.core.models.Room;
import chat.rocket.core.models.SpotlightRoom;
public class RoomListItemViewHolder extends RecyclerView.ViewHolder {
public RoomListItemViewHolder(RoomListItemView itemView,
......@@ -12,7 +13,13 @@ public class RoomListItemViewHolder extends RecyclerView.ViewHolder {
itemView.setOnClickListener(view -> {
if (listener != null) {
Object tag = view.getTag();
if (tag instanceof Room) {
listener.onItemClick((Room) view.getTag());
} else if (tag instanceof SpotlightRoom) {
listener.onItemClick((SpotlightRoom) view.getTag());
}
}
});
}
......@@ -26,4 +33,14 @@ public class RoomListItemViewHolder extends RecyclerView.ViewHolder {
.setUnreadCount(room.getUnread())
.setTag(room);
}
public void bind(SpotlightRoom spotlightRoom) {
((RoomListItemView) itemView)
.setRoomId(spotlightRoom.getId())
.setRoomName(spotlightRoom.getName())
.setRoomType(spotlightRoom.getType())
.setAlert(false)
.setUnreadCount(0)
.setTag(spotlightRoom);
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/AppTheme.Dark"
......@@ -55,11 +56,35 @@
</LinearLayout>
<FrameLayout
android:id="@+id/search_box"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/margin_8"
android:paddingTop="@dimen/margin_8"
android:elevation="2dp"
android:layout_below="@+id/user_info_container"
android:background="?attr/colorPrimaryDark">
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:focusableInTouchMode="true"
android:focusable="true" />
<android.support.v7.widget.SearchView
android:id="@+id/search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:queryHint="@string/navigation_search_rooms"
app:iconifiedByDefault="false" />
</FrameLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/room_list_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/user_info_container"
android:layout_below="@+id/search_box"
android:layout_alignParentBottom="true"
android:background="?attr/colorPrimary" />
......
......@@ -50,4 +50,5 @@
<string name="two_factor_authentication_title">Two-factor authentication</string>
<string name="open_your_authentication_app_and_enter_the_code">Open your authentication app and enter the code</string>
<string name="two_factor_code">Two-factor code</string>
<string name="navigation_search_rooms">Search Rooms</string>
</resources>
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