diff --git a/app/src/main/java/org/mercury_im/messenger/ui/chat/ChatActivity.java b/app/src/main/java/org/mercury_im/messenger/ui/chat/ChatActivity.java index 5d091fe..6894da0 100644 --- a/app/src/main/java/org/mercury_im/messenger/ui/chat/ChatActivity.java +++ b/app/src/main/java/org/mercury_im/messenger/ui/chat/ChatActivity.java @@ -3,9 +3,12 @@ package org.mercury_im.messenger.ui.chat; import android.os.Bundle; import android.util.Log; import android.view.Menu; +import android.view.MenuItem; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.SearchView; import androidx.appcompat.widget.Toolbar; import androidx.lifecycle.ViewModelProviders; import androidx.recyclerview.widget.LinearLayoutManager; @@ -25,7 +28,8 @@ import butterknife.BindView; import butterknife.ButterKnife; import io.reactivex.disposables.CompositeDisposable; -public class ChatActivity extends AppCompatActivity implements ChatInputFragment.OnChatInputActionListener { +public class ChatActivity extends AppCompatActivity + implements ChatInputFragment.OnChatInputActionListener, SearchView.OnQueryTextListener { public static final String EXTRA_JID = "JID"; public static final String EXTRA_ACCOUNT = "ACCOUNT"; @@ -98,9 +102,27 @@ public class ChatActivity extends AppCompatActivity implements ChatInputFragment public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_chat, menu); + + final MenuItem searchItem = menu.findItem(R.id.action_search); + final SearchView searchView = (SearchView) searchItem.getActionView(); + searchView.setOnQueryTextListener(this); + return true; } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.action_call: + case R.id.action_clear_history: + case R.id.action_mute: + case R.id.action_delete_chat: + Toast.makeText(this, R.string.not_yet_implemented, Toast.LENGTH_SHORT).show(); + return true; + } + return false; + } + @Override protected void onSaveInstanceState(@NonNull Bundle outState) { outState.putString(EXTRA_JID, jid.toString()); @@ -109,8 +131,13 @@ public class ChatActivity extends AppCompatActivity implements ChatInputFragment } @Override - public void onButtonMediaClicked() { + public void onButtonEmojiClicked() { + Toast.makeText(this, R.string.not_yet_implemented, Toast.LENGTH_SHORT).show(); + } + @Override + public void onButtonMediaClicked() { + Toast.makeText(this, R.string.not_yet_implemented, Toast.LENGTH_SHORT).show(); } @Override @@ -140,4 +167,16 @@ public class ChatActivity extends AppCompatActivity implements ChatInputFragment } }.start(); } + + @Override + public boolean onQueryTextSubmit(String query) { + // Ignore. Logic is in onQueryTextChange. + return false; + } + + @Override + public boolean onQueryTextChange(String query) { + chatViewModel.queryTextChanged(query); + return false; + } } diff --git a/app/src/main/java/org/mercury_im/messenger/ui/chat/ChatInputFragment.java b/app/src/main/java/org/mercury_im/messenger/ui/chat/ChatInputFragment.java index 0fffad7..cc233e4 100644 --- a/app/src/main/java/org/mercury_im/messenger/ui/chat/ChatInputFragment.java +++ b/app/src/main/java/org/mercury_im/messenger/ui/chat/ChatInputFragment.java @@ -97,7 +97,7 @@ public class ChatInputFragment extends Fragment implements View.OnClickListener } @Override - @OnClick({R.id.btn_send, R.id.btn_media}) + @OnClick({R.id.btn_send, R.id.btn_media, R.id.btn_emoji}) public void onClick(View view) { Log.d(TAG, "onClick!"); switch (view.getId()) { @@ -106,7 +106,6 @@ public class ChatInputFragment extends Fragment implements View.OnClickListener if (actionListener != null) { actionListener.onButtonMediaClicked(); } - Toast.makeText(getContext(), R.string.not_yet_implemented, Toast.LENGTH_SHORT).show(); break; // Send message @@ -118,7 +117,9 @@ public class ChatInputFragment extends Fragment implements View.OnClickListener break; case R.id.btn_emoji: - Toast.makeText(getContext(), "Not yet implemented!", Toast.LENGTH_SHORT).show(); + if (actionListener != null) { + actionListener.onButtonEmojiClicked(); + } break; } } @@ -127,6 +128,8 @@ public class ChatInputFragment extends Fragment implements View.OnClickListener void onButtonMediaClicked(); + void onButtonEmojiClicked(); + void onComposingBodyChanged(String body); void onComposingBodySend(String body); diff --git a/app/src/main/java/org/mercury_im/messenger/ui/chat/ChatViewModel.java b/app/src/main/java/org/mercury_im/messenger/ui/chat/ChatViewModel.java index 0162c65..ac6a56f 100644 --- a/app/src/main/java/org/mercury_im/messenger/ui/chat/ChatViewModel.java +++ b/app/src/main/java/org/mercury_im/messenger/ui/chat/ChatViewModel.java @@ -15,6 +15,7 @@ import java.util.List; import javax.inject.Inject; +import io.reactivex.Scheduler; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.functions.Consumer; @@ -30,6 +31,9 @@ public class ChatViewModel extends ViewModel { @Inject RosterRepository rosterRepository; + private long accountId; + private EntityBareJid jid; + private MutableLiveData contact = new MutableLiveData<>(); private MutableLiveData> messages = new MutableLiveData<>(); private MutableLiveData contactDisplayName = new MutableLiveData<>(); @@ -40,6 +44,9 @@ public class ChatViewModel extends ViewModel { } public void init(long accountId, EntityBareJid jid) { + this.accountId = accountId; + this.jid = jid; + disposable.add(rosterRepository.getContact(accountId, jid) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -78,4 +85,20 @@ public class ChatViewModel extends ViewModel { public LiveData getContactDisplayName() { return contactDisplayName; } + + public void queryTextChanged(String query) { + if (query.isEmpty()) { + disposable.add(messageRepository.getAllMessagesOfChat(accountId, jid) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe((Consumer>) + messages -> ChatViewModel.this.messages.setValue(messages))); + } + disposable.add(messageRepository.findMessageByQuery(accountId, jid, query) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe((Consumer>) o -> { + messages.setValue(o); + })); + } } diff --git a/app/src/main/res/layout/view_compose.xml b/app/src/main/res/layout/view_compose.xml index 0314bf4..cda320a 100644 --- a/app/src/main/res/layout/view_compose.xml +++ b/app/src/main/res/layout/view_compose.xml @@ -29,6 +29,7 @@ android:layout_marginBottom="8dp" android:background="@null" android:tint="@color/tint_compose" + android:contentDescription="@string/description_add_emoji" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:srcCompat="@drawable/ic_insert_emoticon_white_24dp" /> @@ -40,7 +41,7 @@ android:layout_marginStart="8dp" android:layout_marginEnd="8dp" android:background="@null" - android:hint="Type your message" + android:hint="@string/hint_type_your_message" android:inputType="textMultiLine|textAutoCorrect|textCapSentences" android:maxLines="6" android:padding="8dp" @@ -57,6 +58,7 @@ android:layout_marginBottom="8dp" android:background="@null" android:tint="@color/tint_compose" + android:contentDescription="@string/description_add_attachment" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:srcCompat="@drawable/ic_attach_file_white_24dp" /> @@ -73,6 +75,7 @@ android:background="@drawable/circle" android:elevation="15dp" android:tint="@color/tint_compose" + android:contentDescription="@string/description_send_message" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:srcCompat="@drawable/ic_send_black_24dp" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8c434a1..8e9aa79 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -105,5 +105,9 @@ Delete History Mute Delete Chat + Type your message + Add emoji + Add attachment + Send Message diff --git a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/MessageDao.java b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/MessageDao.java index 2945bbd..d7d935a 100644 --- a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/MessageDao.java +++ b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/MessageDao.java @@ -25,4 +25,15 @@ public interface MessageDao extends BaseDao { @Query("SELECT * FROM messages WHERE fk_account_id = :accountId AND (`from` = :peer OR `to` = :peer) ORDER BY send_date ASC") Observable> getAllMessagesInConversation(long accountId, EntityBareJid peer); + @Query("SELECT * FROM messages WHERE body LIKE :query COLLATE utf8_general_ci") + Observable> findMessageByQuery(String query); + + @Query("SELECT * FROM messages WHERE fk_account_id = :accountId AND body LIKE :query COLLATE utf8_general_ci") + Observable> findMessageByQuery(long accountId, String query); + + @Query("SELECT * FROM messages " + + "WHERE fk_account_id = :accountId " + + "AND (`from` = :peer OR `to` = :peer) " + + "AND body LIKE :query COLLATE utf8_general_ci") + Observable> findMessageByQuery(long accountId, EntityBareJid peer, String query); } diff --git a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/repository/IMessageRepository.java b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/repository/IMessageRepository.java index 164623c..a9f1d14 100644 --- a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/repository/IMessageRepository.java +++ b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/repository/IMessageRepository.java @@ -54,6 +54,16 @@ public class IMessageRepository implements MessageRepository { @Override public Observable> findMessageByQuery(String query) { - return null; + return messageDao.findMessageByQuery("%" + query + "%"); + } + + @Override + public Observable> findMessageByQuery(long accountId, String query) { + return messageDao.findMessageByQuery(accountId, "%" + query + "%"); + } + + @Override + public Observable> findMessageByQuery(long accountId, EntityBareJid peer, String query) { + return messageDao.findMessageByQuery(accountId, peer, "%" + query + "%"); } } diff --git a/persistence/src/main/java/org/mercury_im/messenger/persistence/repository/MessageRepository.java b/persistence/src/main/java/org/mercury_im/messenger/persistence/repository/MessageRepository.java index aa079d6..4f7b07d 100644 --- a/persistence/src/main/java/org/mercury_im/messenger/persistence/repository/MessageRepository.java +++ b/persistence/src/main/java/org/mercury_im/messenger/persistence/repository/MessageRepository.java @@ -24,4 +24,8 @@ public interface MessageRepository { Observable> getAllMessagesFrom(long accountId, EntityBareJid contact); Observable> findMessageByQuery(String query); + + Observable> findMessageByQuery(long accountId, String query); + + Observable> findMessageByQuery(long accountId, EntityBareJid peer, String query); }