package org.mercury_im.messenger.android.ui.contacts.detail; import android.app.AlertDialog; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelStoreOwner; import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.card.MaterialCardView; import com.google.android.material.chip.Chip; import com.google.android.material.chip.ChipGroup; import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton; import org.mercury_im.messenger.android.ui.openpgp.OpenPgpV4FingerprintFormatter; import org.mercury_im.messenger.android.ui.openpgp.ToggleableFingerprintsAdapter; import org.mercury_im.messenger.core.Messenger; import org.mercury_im.messenger.R; import org.mercury_im.messenger.android.ui.chat.ChatActivity; import org.mercury_im.messenger.android.util.ColorUtil; import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem; import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import butterknife.BindView; import butterknife.ButterKnife; import io.reactivex.Completable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; public class ContactDetailFragment extends Fragment { private static final Logger LOGGER = Logger.getLogger(ContactDetailFragment.class.getName()); @BindView(R.id.contact_avatar) ImageView contactAvatar; @BindView(R.id.contact_status_badge) ImageView contactStatusBadge; @BindView(R.id.contact_name) TextView contactName; @BindView(R.id.contact_address) TextView contactAddress; @BindView(R.id.contact_presence) TextView contactPresence; @BindView(R.id.contact_account) TextView contactAccount; @BindView(R.id.contact_groups) ChipGroup contactGroups; @BindView(R.id.fab) ExtendedFloatingActionButton fab; @BindView(R.id.button_add_to_group) Button button; @BindView(R.id.fingerprint_list) RecyclerView fingerprintRecyclerView; @BindView(R.id.card_contact_fingerprints) MaterialCardView fingerprintsLayout; private ContactDetailViewModel viewModel; @BindView(R.id.card_ikey_fingerprint) MaterialCardView ikeyLayout; @BindView(R.id.fingerprint) TextView ikeyFingerprint; private ToggleableFingerprintsAdapter fingerprintsAdapter; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_contact_details, container, false); ButterKnife.bind(this, view); if (fab != null) { fab.setOnClickListener(v -> { Intent intent = new Intent(getContext(), ChatActivity.class); intent.putExtra(ChatActivity.EXTRA_CHAT_ID, viewModel.getOrCreateChat().blockingGet().toString()); startActivity(intent); }); } contactName.setOnClickListener(v -> displayChangeContactNameDialog()); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { viewModel.addContactToRosterGroup().subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(); } }); fingerprintsAdapter = new ToggleableFingerprintsAdapter( (fingerprint, checked) -> viewModel.markFingerprintTrusted(fingerprint, checked)); fingerprintRecyclerView.setAdapter(fingerprintsAdapter); return view; } private void displayChangeContactNameDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setTitle("Edit Contact Name"); final EditText editText = new EditText(getContext()); editText.setText(contactName.getText()); builder.setView(editText) .setPositiveButton("Save", (dialog, which) -> { Completable.fromAction(() -> viewModel.changeContactName(editText.getText().toString())).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(() -> {}, e -> Log.e(Messenger.TAG, "Error changing contact name", e)); }) .setNegativeButton("Cancel", (dialog, which) -> dialog.cancel()); builder.show(); } @Override public void onAttach(Context context) { super.onAttach(context); viewModel = new ViewModelProvider((ViewModelStoreOwner) context).get(ContactDetailViewModel.class); observeViewModel(); } private void observeViewModel() { viewModel.getContactAvatar().observe(this, drawable -> contactAvatar.setImageDrawable(drawable)); viewModel.getContactPresenceMode().observe(this, mode -> { int color = 0; switch (mode) { case chat: case available: color = ColorUtil.rgb(0, 255, 0); break; case away: case xa: color = ColorUtil.rgb(255, 128, 0); break; case dnd: color = ColorUtil.rgb(255, 0, 0); break; } contactStatusBadge.setColorFilter(color); }); viewModel.getContactName().observe(this, name -> contactName.setText(name)); viewModel.getContactAddress().observe(this, address -> contactAddress.setText(address)); viewModel.getContactPresenceStatus().observe(this, presenceText -> contactPresence.setText(presenceText)); viewModel.getContactAccountAddress().observe(this, address -> contactAccount.setText(address)); viewModel.getContactGroups().observe(this, this::setRosterGroups); viewModel.getContactFingerprints().observe(this, this::setFingerprints); } private void setRosterGroups(List groups) { contactGroups.removeAllViews(); for (String group : groups) { Chip chip = new Chip(contactGroups.getContext()); chip.setText(group); chip.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { viewModel.removeContactFromRosterGroup(group) .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) .subscribe(); return true; } }); contactGroups.addView(chip); } } private void setIkeyFingerprint(Optional fingerprintViewItemOptional) { if (fingerprintViewItemOptional.isPresent()) { ikeyLayout.setVisibility(View.VISIBLE); ikeyFingerprint.setText(OpenPgpV4FingerprintFormatter.formatOpenPgpV4Fingerprint(fingerprintViewItemOptional.getItem().getFingerprint())); } else { ikeyLayout.setVisibility(View.GONE); } } private void setFingerprints(List fingerprints) { LOGGER.log(Level.INFO, "Display fingerprints: " + Arrays.asList(fingerprints.toArray())); fingerprintsLayout.setVisibility(fingerprints.isEmpty() ? View.GONE : View.VISIBLE); fingerprintsAdapter.setItems(fingerprints); } }