package org.briarproject.android.keyagreement; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.Spinner; import org.briarproject.R; import org.briarproject.android.ActivityComponent; import org.briarproject.android.fragment.BaseFragment; import org.briarproject.android.identity.CreateIdentityActivity; import org.briarproject.android.identity.LocalAuthorItem; import org.briarproject.android.identity.LocalAuthorSpinnerAdapter; import org.briarproject.api.db.DbException; import org.briarproject.api.identity.AuthorId; import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.LocalAuthor; import java.util.Collection; import java.util.logging.Logger; import javax.inject.Inject; import static android.app.Activity.RESULT_OK; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static org.briarproject.android.identity.LocalAuthorItem.NEW; public class ChooseIdentityFragment extends BaseFragment implements OnItemSelectedListener { interface IdentitySelectedListener { void identitySelected(AuthorId localAuthorId); } public static final String TAG = "ChooseIdentityFragment"; private static final Logger LOG = Logger.getLogger(ChooseIdentityFragment.class.getName()); private static final int REQUEST_CREATE_IDENTITY = 1; private IdentitySelectedListener lsnr; private LocalAuthorSpinnerAdapter adapter; private Spinner spinner; private View button; private AuthorId localAuthorId; // Fields that are accessed from background threads must be volatile @Inject protected volatile IdentityManager identityManager; public static ChooseIdentityFragment newInstance() { Bundle args = new Bundle(); ChooseIdentityFragment fragment = new ChooseIdentityFragment(); fragment.setArguments(args); return fragment; } @Override public void injectFragment(ActivityComponent component) { component.inject(this); } @Override public void onAttach(Context context) { super.onAttach(context); try { lsnr = (IdentitySelectedListener) context; } catch (ClassCastException e) { throw new ClassCastException( "Using class must implement IdentitySelectedListener"); } } @Override public String getUniqueTag() { return TAG; } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_keyagreement_id, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); adapter = new LocalAuthorSpinnerAdapter(getActivity(), false); spinner = (Spinner) view.findViewById(R.id.spinner); spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(this); button = view.findViewById(R.id.continueButton); button.setEnabled(false); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { lsnr.identitySelected(localAuthorId); } }); } @Override public void onStart() { super.onStart(); loadLocalAuthors(); } private void loadLocalAuthors() { listener.runOnDbThread(new Runnable() { @Override public void run() { try { long now = System.currentTimeMillis(); Collection authors = identityManager.getLocalAuthors(); long duration = System.currentTimeMillis() - now; if (LOG.isLoggable(INFO)) LOG.info("Loading authors took " + duration + " ms"); displayLocalAuthors(authors); } catch (DbException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); } } }); } private void displayLocalAuthors(final Collection authors) { listener.runOnUiThread(new Runnable() { @Override public void run() { setLocalAuthorId(authors.iterator().next().getId()); // TODO remove comment below when supporting multiple identities /* adapter.clear(); for (LocalAuthor a : authors) adapter.add(new LocalAuthorItem(a)); adapter.sort(LocalAuthorItemComparator.INSTANCE); // If a local author has been selected, select it again if (localAuthorId == null) return; int count = adapter.getCount(); for (int i = 0; i < count; i++) { LocalAuthorItem item = adapter.getItem(i); if (item == NEW) continue; if (item.getLocalAuthor().getId().equals(localAuthorId)) { spinner.setSelection(i); return; } } */ } }); } private void setLocalAuthorId(final AuthorId authorId) { listener.runOnUiThread(new Runnable() { @Override public void run() { localAuthorId = authorId; button.setEnabled(localAuthorId != null); } }); } @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { LocalAuthorItem item = adapter.getItem(position); if (item == NEW) { setLocalAuthorId(null); Intent i = new Intent(getActivity(), CreateIdentityActivity.class); startActivityForResult(i, REQUEST_CREATE_IDENTITY); } else { setLocalAuthorId(item.getLocalAuthor().getId()); } } @Override public void onNothingSelected(AdapterView parent) { setLocalAuthorId(null); } @Override public void onActivityResult(int request, int result, Intent data) { if (request == REQUEST_CREATE_IDENTITY && result == RESULT_OK) { byte[] b = data.getByteArrayExtra("briar.LOCAL_AUTHOR_ID"); if (b == null) throw new IllegalStateException(); setLocalAuthorId(new AuthorId(b)); loadLocalAuthors(); } else super.onActivityResult(request, result, data); } }