package org.mercury_im.messenger.android.ui.chat; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; 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.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.impl.JidCreate; import org.mercury_im.messenger.android.MercuryImApplication; import org.mercury_im.messenger.R; import org.mercury_im.messenger.entity.contact.Peer; import org.mercury_im.messenger.android.ui.roster.contacts.detail.ContactDetailActivity; import java.util.UUID; import butterknife.BindView; import butterknife.ButterKnife; import io.reactivex.disposables.CompositeDisposable; public class ChatActivity extends AppCompatActivity implements ChatInputFragment.OnChatInputActionListener, SearchView.OnQueryTextListener { public static final String EXTRA_JID = "JID"; public static final String EXTRA_ACCOUNT = "ACCOUNT"; @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.recyclerView) RecyclerView recyclerView; private final MessagesRecyclerViewAdapter recyclerViewAdapter = new MessagesRecyclerViewAdapter(); private AndroidChatViewModel androidChatViewModel; private final CompositeDisposable disposable = new CompositeDisposable(); private EntityBareJid jid; private UUID accountId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d("Mercury", "onCreate"); setContentView(R.layout.activity_chat); ButterKnife.bind(this); MercuryImApplication.getApplication().getAppComponent().inject(this); if (savedInstanceState == null) { savedInstanceState = getIntent().getExtras(); if (savedInstanceState == null) return; } setSupportActionBar(toolbar); // Show back arrow getSupportActionBar().setDisplayHomeAsUpEnabled(true); recyclerView.setAdapter(recyclerViewAdapter); recyclerView.setLayoutManager(new LinearLayoutManager(this)); String jidString = savedInstanceState.getString(EXTRA_JID); if (jidString != null) { jid = JidCreate.entityBareFromOrThrowUnchecked(jidString); // JID will never change, so just set it once getSupportActionBar().setSubtitle(jid.asUnescapedString()); accountId = UUID.fromString(savedInstanceState.getString(EXTRA_ACCOUNT)); androidChatViewModel = new ViewModelProvider(this).get(AndroidChatViewModel.class); androidChatViewModel.init(accountId, jid); // Listen for updates to contact information and messages observeViewModel(androidChatViewModel); } toolbar.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(ChatActivity.this, ContactDetailActivity.class); intent.putExtra(ContactDetailActivity.EXTRA_JID, jidString); intent.putExtra(ContactDetailActivity.EXTRA_ACCOUNT, accountId.toString()); ChatActivity.this.startActivity(intent); } }); } public void observeViewModel(AndroidChatViewModel viewModel) { viewModel.getContactDisplayName().observe(this, name -> getSupportActionBar().setTitle(name)); 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_JID, jid.toString()); outState.putString(EXTRA_ACCOUNT, accountId.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; } }