package net.osmand.plus.osmedit; import android.app.Activity; import android.app.Dialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.os.Bundle; import android.support.annotation.MainThread; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v7.app.AlertDialog; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import net.osmand.plus.IconsCache; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.dialogs.ProgressDialogFragment; import net.osmand.plus.osmedit.dialogs.SendPoiDialogFragment; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Map; public class OsmEditsUploadListenerHelper implements OsmEditsUploadListener { public static final String TAG = "OsmEditUploadListenerHe"; private final FragmentActivity activity; private final String numberFormat; public OsmEditsUploadListenerHelper(FragmentActivity activity, String numberFormat) { this.activity = activity; this.numberFormat = numberFormat; } @Override public void uploadUpdated(OsmPoint point) { } @MainThread @Override public void uploadEnded(Map<OsmPoint, String> loadErrorsMap) { int uploaded = 0; int pointsNum = loadErrorsMap.keySet().size(); for (OsmPoint point : loadErrorsMap.keySet()) { if (loadErrorsMap.get(point) == null) { uploaded++; } } if (uploaded == pointsNum) { Toast.makeText(activity, MessageFormat.format(numberFormat, uploaded), Toast.LENGTH_LONG) .show(); } else if (pointsNum == 1) { Log.v(TAG, "in if1"); OsmPoint point = loadErrorsMap.keySet().iterator().next(); String message = loadErrorsMap.get(point); if (message.equals(activity.getString(R.string.auth_failed))) { SendPoiDialogFragment dialogFragment = SendPoiDialogFragment.createInstance(new OsmPoint[]{point}); if (activity instanceof MapActivity) { dialogFragment.setPoiUploader(new SendPoiDialogFragment.SimpleProgressDialogPoiUploader() { @NonNull @Override protected MapActivity getMapActivity() { return (MapActivity) activity; } }); } dialogFragment.show(activity.getSupportFragmentManager(), "error_loading"); } else { DialogFragment dialogFragment = UploadingErrorDialogFragment.getInstance(message, point); dialogFragment.show(activity.getSupportFragmentManager(), "error_loading"); } } else { UploadingMultipleErrorDialogFragment dialogFragment = UploadingMultipleErrorDialogFragment.createInstance(loadErrorsMap); dialogFragment.show(activity.getSupportFragmentManager(), "multiple_error_loading"); } } private static void showUploadItemsProgressDialog(Fragment fragment, OsmPoint[] toUpload) { FragmentActivity activity = fragment.getActivity(); OsmEditingPlugin plugin = OsmandPlugin.getEnabledPlugin(OsmEditingPlugin.class); OsmEditsUploadListenerHelper helper = new OsmEditsUploadListenerHelper(activity, activity.getResources().getString(R.string.local_openstreetmap_were_uploaded)); ProgressDialogFragment dialog = ProgressDialogFragment.createInstance( R.string.uploading, R.string.local_openstreetmap_uploading, ProgressDialog.STYLE_HORIZONTAL); dialog.show(activity.getSupportFragmentManager(), ProgressDialogFragment.TAG); UploadOpenstreetmapPointAsyncTask uploadTask = new UploadOpenstreetmapPointAsyncTask( dialog, helper, plugin, toUpload.length, false, false); uploadTask.execute(toUpload); } public static final class UploadingErrorDialogFragment extends DialogFragment { private static final String ERROR_MESSAGE = "error_message"; private static final String POINT = "point"; @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { Bundle argument = getArguments(); String errorMessage = argument.getString(ERROR_MESSAGE); final OsmPoint point = (OsmPoint) argument.getSerializable(POINT); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(getResources().getString(R.string.failed_to_upload)) .setMessage(MessageFormat.format( getResources().getString(R.string.error_message_pattern), errorMessage)) .setPositiveButton(R.string.shared_string_ok, null); builder.setNeutralButton(getResources().getString(R.string.delete_change), new DialogInterface.OnClickListener() { public void onClick(@Nullable DialogInterface dialog, int id) { OsmEditingPlugin plugin = OsmandPlugin.getEnabledPlugin(OsmEditingPlugin.class); assert point != null; assert plugin != null; if (point.getGroup() == OsmPoint.Group.BUG) { plugin.getDBBug().deleteAllBugModifications( (OsmNotesPoint) point); } else if (point.getGroup() == OsmPoint.Group.POI) { plugin.getDBPOI().deletePOI((OpenstreetmapPoint) point); } } }); return builder.create(); } public static UploadingErrorDialogFragment getInstance(String errorMessage, OsmPoint point) { UploadingErrorDialogFragment fragment = new UploadingErrorDialogFragment(); Bundle bundle = new Bundle(); bundle.putString(ERROR_MESSAGE, errorMessage); bundle.putSerializable(POINT, point); fragment.setArguments(bundle); return fragment; } } public static final class UploadingMultipleErrorDialogFragment extends DialogFragment { private static final String HAS_ERROR = "has_error"; private static final String POINT_NAMES = "point_names"; private static final String POINTS_WITH_ERRORS = "points_with_errors"; @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { Bundle arguments = getArguments(); String[] pointNames = arguments.getStringArray(POINT_NAMES); boolean[] hasErrors = arguments.getBooleanArray(HAS_ERROR); final OsmPoint[] points = (OsmPoint[]) arguments.getSerializable(POINTS_WITH_ERRORS); int successfulUploads = 0; assert hasErrors != null; for (boolean hasError : hasErrors) { if (!hasError) { successfulUploads++; } } PointsWithErrorsAdapter adapter = PointsWithErrorsAdapter.createInstance(getActivity(), pointNames, hasErrors); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(MessageFormat.format(getResources() .getString(R.string.successfully_uploaded_pattern), successfulUploads, hasErrors.length)) .setAdapter(adapter, null) .setPositiveButton(R.string.shared_string_ok, null) .setNeutralButton(getResources().getString(R.string.try_again), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { OsmEditsUploadListenerHelper .showUploadItemsProgressDialog( UploadingMultipleErrorDialogFragment.this, points); } }); return builder.create(); } public static UploadingMultipleErrorDialogFragment createInstance( Map<OsmPoint, String> loadErrorsMap) { String[] pointNames = new String[loadErrorsMap.keySet().size()]; boolean[] hasErrors = new boolean[loadErrorsMap.keySet().size()]; ArrayList<OsmPoint> pointsWithErrors = new ArrayList<>(); int i = 0; for (OsmPoint point : loadErrorsMap.keySet()) { pointNames[i] = point.getGroup() == OsmPoint.Group.BUG ? ((OsmNotesPoint) point).getText() : ((OpenstreetmapPoint) point).getName(); pointNames[i] = TextUtils.isEmpty(pointNames[i]) ? "id:" + point.getId() : pointNames[i]; hasErrors[i] = loadErrorsMap.get(point) != null; if (hasErrors[i]) { pointsWithErrors.add(point); } i++; } if (pointNames.length != hasErrors.length) { throw new IllegalArgumentException("pointNames and hasError arrays " + "must me of equal length"); } UploadingMultipleErrorDialogFragment fragment = new UploadingMultipleErrorDialogFragment(); Bundle bundle = new Bundle(); bundle.putSerializable(POINTS_WITH_ERRORS, pointsWithErrors.toArray(new OsmPoint[pointsWithErrors.size()])); bundle.putStringArray(POINT_NAMES, pointNames); bundle.putBooleanArray(HAS_ERROR, hasErrors); fragment.setArguments(bundle); return fragment; } } private static final class PointWithPotentialError { String point; boolean hasError; public PointWithPotentialError(String point, boolean hasError) { this.point = point; this.hasError = hasError; } } private static final class PointsWithErrorsAdapter extends ArrayAdapter<PointWithPotentialError> { private final int layoutResourceId; PointWithPotentialError[] data; Activity context; private PointsWithErrorsAdapter(Activity context, int layoutResourceId, PointWithPotentialError[] objects) { super(context, layoutResourceId, objects); data = objects; this.context = context; this.layoutResourceId = layoutResourceId; } @Override public View getView(int position, View convertView, @NonNull ViewGroup parent) { View row = convertView; PointHolder holder; if (row == null) { LayoutInflater inflater = context.getLayoutInflater(); row = inflater.inflate(layoutResourceId, parent, false); holder = new PointHolder(); holder.checkedUncheckedImageView = (ImageView) row.findViewById(R.id.iconImageView); holder.pointNameTextView = (TextView) row.findViewById(R.id.nameTextView); row.setTag(holder); } else { holder = (PointHolder) row.getTag(); } PointWithPotentialError pointWrapper = data[position]; holder.pointNameTextView.setText(pointWrapper.point); IconsCache cache = ((OsmandApplication) context.getApplication()).getIconsCache(); holder.checkedUncheckedImageView.setImageDrawable(pointWrapper.hasError ? cache.getThemedIcon(R.drawable.ic_action_remove_dark) : cache.getThemedIcon(R.drawable.ic_action_done)); return row; } public static PointsWithErrorsAdapter createInstance(Activity activity, String[] pointNames, boolean[] hasError) { PointWithPotentialError[] array = new PointWithPotentialError[pointNames.length]; for (int i = 0; i < pointNames.length; i++) { array[i] = new PointWithPotentialError(pointNames[i], hasError[i]); } return new PointsWithErrorsAdapter(activity, R.layout.osm_edit_list_item, array); } private static class PointHolder { TextView pointNameTextView; ImageView checkedUncheckedImageView; } } }