package org.mercury_im.messenger.android.ui.chat; import android.content.Intent; import android.os.Bundle; 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.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import org.mercury_im.messenger.android.MercuryImApplication; import org.mercury_im.messenger.R; import org.mercury_im.messenger.android.ui.MercuryActivity; import org.mercury_im.messenger.android.util.ArgumentUtils; import org.mercury_im.messenger.entity.contact.Peer; import org.mercury_im.messenger.android.ui.contacts.detail.ContactDetailActivity; import java.util.UUID; import butterknife.BindView; import butterknife.ButterKnife; import io.reactivex.disposables.CompositeDisposable; import lombok.Value; public class ChatActivity extends AppCompatActivity implements MercuryActivity, ChatInputFragment.OnChatInputActionListener, SearchView.OnQueryTextListener { public static final String EXTRA_CHAT_ID = "CHAT_ID"; private final MessagesRecyclerViewAdapter recyclerViewAdapter = new MessagesRecyclerViewAdapter(); private final CompositeDisposable disposable = new CompositeDisposable(); @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.recyclerView) RecyclerView recyclerView; private AndroidChatViewModel androidChatViewModel; private UUID chatId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MercuryImApplication.getApplication().getAppComponent().inject(this); Arguments arguments = getArguments(savedInstanceState); chatId = arguments.getChatId(); androidChatViewModel = new ViewModelProvider(this).get(AndroidChatViewModel.class); androidChatViewModel.init(chatId); bindUiComponents(); observeViewModel(androidChatViewModel); } private void bindUiComponents() { setContentView(R.layout.activity_chat); ButterKnife.bind(this); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); toolbar.setOnClickListener(v -> { Intent intent = new Intent(ChatActivity.this, ContactDetailActivity.class); intent.putExtra(ContactDetailActivity.EXTRA_PEER_ID, androidChatViewModel.getContactId()); ChatActivity.this.startActivity(intent); }); recyclerView.setAdapter(recyclerViewAdapter); recyclerView.setLayoutManager(new LinearLayoutManager(this)); } public void observeViewModel(AndroidChatViewModel viewModel) { viewModel.getContactDisplayName().observe(this, name -> getSupportActionBar().setTitle(name)); viewModel.getContact().observe(this, contact -> getSupportActionBar().setSubtitle(contact.getJid())); viewModel.getMessages().observe(this, messageModels -> { recyclerViewAdapter.updateMessages(messageModels); recyclerView.scrollToPosition(messageModels.size() - 1); }); } public void onStop() { super.onStop(); disposable.clear(); } @Override 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_debug: Peer peer = androidChatViewModel.getContact().getValue(); Toast.makeText(this, "subscription: " + peer.getSubscriptionDirection().toString() + " isApproved: " + peer.isSubscriptionApproved() + " isPending: " + peer.isSubscriptionPending(), Toast.LENGTH_SHORT).show(); break; // menu_chat case R.id.action_delete_contact: androidChatViewModel.deleteContact(); break; case R.id.action_call: case R.id.action_clear_history: case R.id.action_notification_settings: case R.id.action_delete_chat: // long_click_message case R.id.action_edit_message: case R.id.action_reply_message: case R.id.action_copy_message: case R.id.action_forward_message: case R.id.action_delete_message: case R.id.action_message_details: // short_click_message case R.id.action_react_message: 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_CHAT_ID, chatId.toString()); super.onSaveInstanceState(outState); } @Override 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 public void onComposingBodyChanged(String body) { } @Override public void onComposingBodySend(String body) { String msg = body.trim(); if (msg.isEmpty()) { return; } androidChatViewModel.sendMessage(msg); } @Override public boolean onQueryTextSubmit(String query) { // Ignore. Logic is in onQueryTextChange. return false; } @Override public boolean onQueryTextChange(String query) { androidChatViewModel.queryTextChanged(query); return false; } @Override public boolean onSupportNavigateUp() { // Go back when left arrow is pressed in toolbar onBackPressed(); return true; } private Arguments getArguments(Bundle savedInstanceState) { savedInstanceState = requiredExtras(savedInstanceState, getIntent()); UUID chatId = ArgumentUtils.requireUUID(savedInstanceState, EXTRA_CHAT_ID); return new Arguments(chatId); } @Value private class Arguments { UUID chatId; } }