package org.azavea.otm.ui; import android.app.Fragment; 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.LinearLayout; import android.widget.TextView; import android.widget.Toast; import org.azavea.helpers.Logger; import org.azavea.otm.App; import org.azavea.otm.R; import org.azavea.otm.data.EditEntry; import org.azavea.otm.data.EditEntryContainer; import org.azavea.otm.data.User; import org.azavea.otm.rest.RequestGenerator; import org.azavea.otm.rest.handlers.ContainerRestHandler; import org.json.JSONException; import java.text.SimpleDateFormat; import java.util.LinkedHashMap; public class ProfileDisplay extends Fragment { private static final int SHOW_LOGIN = 0; private static final int EDITS_TO_REQUEST = 5; private static LinkedHashMap<Integer, EditEntry> loadedEdits = new LinkedHashMap<>(); // The fields on User which are displayed on Profile Page public static final String[][] userFields = {{"Username", "username"}, {"First Name", "first_name"}, {"Last Name", "last_name"}, {"Organization", "organization"}}; private final RequestGenerator client = new RequestGenerator(); private int editRequestCount = 0; private boolean loadingRecentEdits = false; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); View view = inflater.inflate(R.layout.profile, container, false); int switcherVisibility = App.hasSkinCode() ? View.GONE : View.VISIBLE; view.findViewById(R.id.change_instance_anonymous).setVisibility(switcherVisibility); view.findViewById(R.id.change_instance_loggedin).setVisibility(switcherVisibility); registerHandlers(view); return view; } @Override public void onResume() { super.onResume(); editRequestCount = 0; loadProfile(getView(), getActivity().getLayoutInflater()); } public void addMoreEdits() { if (!loadingRecentEdits) { Toast.makeText(App.getAppInstance(), "Loading more edits...", Toast.LENGTH_SHORT).show(); renderRecentEdits(getActivity().getLayoutInflater()); } } private void loadProfile(View view, LayoutInflater inflater) { if (App.getLoginManager().isLoggedIn()) { User user = App.getLoginManager().loggedInUser; renderUserFields(view, inflater, user, userFields); view.findViewById(R.id.profile_activity_loggedin).setVisibility(View.VISIBLE); view.findViewById(R.id.profile_activity_anonymous).setVisibility(View.GONE); /* * Presently, OTM2 is not loading User Edits. * * NotifyingScrollView scroll = * (NotifyingScrollView)findViewById(R.id.userFieldsScroll); * scroll.setOnScrollToBottomListener(new * NotifyingScrollView.OnScrollToBottomListener() { * * @Override public void OnScrollToBottom() { addMoreEdits(); } }); */ } else { view.findViewById(R.id.profile_activity_loggedin).setVisibility(View.GONE); view.findViewById(R.id.profile_activity_anonymous).setVisibility(View.VISIBLE); } } private void renderUserFields(View view, LayoutInflater inflater, User user, String[][] fieldNames) { LinearLayout fieldContainer = (LinearLayout) view.findViewById(R.id.profile_field_container); renderRecentEdits(inflater); fieldContainer.removeAllViews(); for (String[] fieldPair : fieldNames) { String label = fieldPair[0]; String value = user.getField(fieldPair[1]).toString(); View row = inflater.inflate(R.layout.plot_field_row, null); ((TextView) row.findViewById(R.id.field_label)).setText(label); row.setTag(fieldPair[1]); ((TextView) row.findViewById(R.id.field_value)).setText(value); fieldContainer.addView(row); } } private void registerHandlers(final View view) { View.OnClickListener switchInstanceListener = v -> startActivity(new Intent(getActivity(), InstanceSwitcherActivity.class)); view.findViewById(R.id.change_instance_anonymous).setOnClickListener(switchInstanceListener); view.findViewById(R.id.change_instance_loggedin).setOnClickListener(switchInstanceListener); view.findViewById(R.id.logout).setOnClickListener(v -> { App.getLoginManager().logOut(getActivity()); loadProfile(view, getActivity().getLayoutInflater()); }); view.findViewById(R.id.change_password).setOnClickListener(v -> startActivity(new Intent(getActivity(), ChangePassword.class))); view.findViewById(R.id.change_profile_picture).setOnClickListener(v -> { // TODO: Refactor photo handling code in TreeEditDisplay for use here }); view.findViewById(R.id.login).setOnClickListener(v -> { Intent login = new Intent(getActivity(), LoginActivity.class); startActivityForResult(login, SHOW_LOGIN); }); } public void renderRecentEdits(final LayoutInflater layout) { // Presently, OTM2 edits are instance based and we are not loading // user recent edits for the profile page. I want to leave the // edits display code uncommented, so just return early for now boolean showEdits = false; if (!showEdits) { return; } // Don't load additional edits if there are edits currently loading if (loadingRecentEdits) { return; } loadingRecentEdits = true; try { client.getUserEdits(getActivity(), App.getLoginManager().loggedInUser, this.editRequestCount, this.EDITS_TO_REQUEST, new ContainerRestHandler<EditEntryContainer>(new EditEntryContainer()) { @Override public void dataReceived(EditEntryContainer container) { try { addEditEntriesToView(layout, container); } catch (JSONException e) { Logger.error("Could not parse user edits response", e); Toast.makeText(App.getAppInstance(), "Could not retrieve user edits", Toast.LENGTH_SHORT).show(); } finally { loadingRecentEdits = false; } } private void addEditEntriesToView(final LayoutInflater layout, EditEntryContainer container) throws JSONException { LinkedHashMap<Integer, EditEntry> edits = (LinkedHashMap<Integer, EditEntry>) container .getAll(); loadedEdits.putAll(edits); LinearLayout scroll = (LinearLayout) getActivity().findViewById(R.id.user_edits); for (EditEntry edit : edits.values()) { // Create a view for this edit entry, and add a // click handler to it View row = layout.inflate(R.layout.recent_edit_row, null); ((TextView) row.findViewById(R.id.edit_type)).setText(capitalize(edit.getName())); String editTime = new SimpleDateFormat("MMMMM dd, yyyy 'at' h:mm a").format(edit .getEditTime()); ((TextView) row.findViewById(R.id.edit_time)).setText(editTime); ((TextView) row.findViewById(R.id.edit_value)).setText("+" + Integer.toString(edit.getValue())); row.setTag(edit.getId()); setPlotClickHandler(row); scroll.addView(row); } // Increment the paging editRequestCount += EDITS_TO_REQUEST; } private void setPlotClickHandler(View row) { row.findViewById(R.id.edit_row).setOnClickListener(v -> { try { // TODO: Login user check/prompt EditEntry edit = loadedEdits.get(v.getTag()); if (edit.getPlot() != null) { final Intent viewPlot = new Intent(v.getContext(), TreeInfoDisplay.class); viewPlot.putExtra("plot", edit.getPlot().getData().toString()); viewPlot.putExtra("user", App.getLoginManager().loggedInUser .getData().toString()); startActivity(viewPlot); } } catch (Exception e) { String msg = "Unable to display tree/plot info"; Toast.makeText(v.getContext(), msg, Toast.LENGTH_SHORT).show(); Logger.error(msg, e); } }); } @Override public void failure(Throwable e, String message) { loadingRecentEdits = false; Log.e(App.LOG_TAG, message); Toast.makeText(App.getAppInstance(), "Could not retrieve user edits", Toast.LENGTH_SHORT) .show(); } } ); } catch (JSONException e) { Logger.error("Failed to fetch user edits", e); Toast.makeText(getActivity(), "Could not retrieve user edits", Toast.LENGTH_SHORT).show(); } } private String capitalize(String phrase) { String[] tokens = phrase.split("\\s"); String capitalized = ""; for (String token : tokens) { char capLetter = Character.toUpperCase(token.charAt(0)); capitalized += " " + capLetter + token.substring(1, token.length()); } return capitalized; } }