package org.mercury_im.messenger.ui.roster.contacts; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.database.DataSetObserver; import android.opengl.Visibility; import android.os.Bundle; import android.util.Log; 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.SpinnerAdapter; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatDialogFragment; import androidx.lifecycle.LiveData; import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputLayout; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.util.Async; import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.stringprep.XmppStringprepException; import org.mercury_im.messenger.Messenger; import org.mercury_im.messenger.R; import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.exception.ConnectionNotFoundException; import org.mercury_im.messenger.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.setMessage("Add Contact") .setView(dialogView) .setCancelable(false) .setPositiveButton("Add", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // Later overwrite in onResume. } }) .setNegativeButton("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) { Button positiveButton = d.getButton(Dialog.BUTTON_POSITIVE); positiveButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View 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("Account not connected"); } else if (e instanceof ContactAlreadyAddedException) { contactAddressLayout.setError("Contact already added"); } else if (e instanceof XmppStringprepException) { contactAddressLayout.setError("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); } } }