package org.mercury_im.messenger.android.ui.roster.contacts; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.LinearLayout; import android.widget.Spinner; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatDialogFragment; import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputLayout; import org.jivesoftware.smack.SmackException; import org.jxmpp.stringprep.XmppStringprepException; import org.mercury_im.messenger.core.Messenger; import org.mercury_im.messenger.R; import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.core.exception.ContactAlreadyAddedException; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.schedulers.Schedulers; public class AddContactDialogFragment extends AppCompatDialogFragment { private final List accounts; private final Messenger messenger; @BindView(R.id.account_select_container) LinearLayout accountSelectorContainer; @BindView(R.id.spinner) Spinner accountSelector; @BindView(R.id.address_layout) TextInputLayout contactAddressLayout; @BindView(R.id.address) TextInputEditText contactAddress; private final CompositeDisposable disposable = new CompositeDisposable(); public AddContactDialogFragment(List accountList, Messenger messenger) { this.accounts = accountList; this.messenger = messenger; } @NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { LayoutInflater inflater = requireActivity().getLayoutInflater(); View dialogView = inflater.inflate(R.layout.dialog_add_contact, null); ButterKnife.bind(this, dialogView); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); // Hide Spinner when only one account. if (accounts == null || accounts.size() <= 1) { accountSelectorContainer.setVisibility(View.GONE); } accountSelector.setAdapter(new AccountAdapter(requireActivity(), accounts)); accountSelector.setSelection(0); builder.setTitle(R.string.dialog_title_add_contact) .setView(dialogView) .setCancelable(false) .setPositiveButton(R.string.button_add, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // Later overwrite in onResume. } }) .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { AddContactDialogFragment.this.onCancel(dialog); } }); return builder.create(); } @Override public void onResume() { super.onResume(); final AlertDialog d = (AlertDialog)getDialog(); if(d == null) { return; } Button positiveButton = d.getButton(Dialog.BUTTON_POSITIVE); positiveButton.setOnClickListener(v -> { Account account = accounts.get(accountSelector.getSelectedItemPosition()); String address = contactAddress.getText() != null ? contactAddress.getText().toString() : ""; disposable.add(messenger.addContact(account.getId(), address) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( AddContactDialogFragment.this::dismiss, e -> { if (e instanceof SmackException.NotLoggedInException || e instanceof SmackException.NotConnectedException) { contactAddressLayout.setError(getString(R.string.error_account_not_connected)); } else if (e instanceof ContactAlreadyAddedException) { contactAddressLayout.setError(getString(R.string.error_contact_already_added)); } else if (e instanceof XmppStringprepException) { contactAddressLayout.setError(getString(R.string.error_invalid_address)); } else { contactAddressLayout.setError(e.getClass().getName()); } } )); }); } @Override public void onDestroy() { super.onDestroy(); disposable.dispose(); } private static class AccountAdapter extends ArrayAdapter { public AccountAdapter(@NonNull Context context, @NonNull List objects) { super(context, R.layout.spinner_item_account, objects); } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.spinner_item_account, parent, false); } TextView textView = convertView.findViewById(R.id.account_address); textView.setText(getItem(position).getAddress()); return convertView; } @Override public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { return getView(position, convertView, parent); } } }