Checkpoint commit adding missing motor download workflow.
This commit is contained in:
		
							parent
							
								
									ae34a951a6
								
							
						
					
					
						commit
						125162bcbe
					
				@ -0,0 +1,52 @@
 | 
			
		||||
package net.sf.openrocket.android.rocket;
 | 
			
		||||
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
import net.sf.openrocket.motor.ThrustCurveMotorPlaceholder;
 | 
			
		||||
import android.app.AlertDialog;
 | 
			
		||||
import android.app.Dialog;
 | 
			
		||||
import android.content.DialogInterface;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.support.v4.app.DialogFragment;
 | 
			
		||||
 | 
			
		||||
public class MissingMotorDialogFragment extends DialogFragment {
 | 
			
		||||
 | 
			
		||||
	Set<ThrustCurveMotorPlaceholder> missingMotors;
 | 
			
		||||
 | 
			
		||||
	public static MissingMotorDialogFragment newInstance( Set<ThrustCurveMotorPlaceholder> missingMotors ) {
 | 
			
		||||
		MissingMotorDialogFragment frag = new MissingMotorDialogFragment();
 | 
			
		||||
		frag.missingMotors = missingMotors;
 | 
			
		||||
		return frag;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public Dialog onCreateDialog(Bundle savedInstanceState) {
 | 
			
		||||
 | 
			
		||||
		AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
 | 
			
		||||
		//	                .setIcon(android.R.drawable.alert_dialog_icon)
 | 
			
		||||
		builder.setTitle("Missing Motors");
 | 
			
		||||
		StringBuilder sb = new StringBuilder();
 | 
			
		||||
		sb.append("The following motors are missing:");
 | 
			
		||||
		for( ThrustCurveMotorPlaceholder m : missingMotors ) {
 | 
			
		||||
			sb.append("\n").append(m.getManufacturer()).append(" ").append(m.getDesignation());
 | 
			
		||||
		}
 | 
			
		||||
		sb.append("\nWould you like to download them from Thrustcurve?");
 | 
			
		||||
		builder.setMessage(sb.toString());
 | 
			
		||||
		builder.setPositiveButton("OK",
 | 
			
		||||
				new DialogInterface.OnClickListener() {
 | 
			
		||||
			public void onClick(DialogInterface dialog, int whichButton) {
 | 
			
		||||
				((OpenRocketLoaderActivity)getActivity()).doFixMissingMotors();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
				);
 | 
			
		||||
		builder.setNegativeButton("Cancel",
 | 
			
		||||
				new DialogInterface.OnClickListener() {
 | 
			
		||||
			public void onClick(DialogInterface dialog, int whichButton) {
 | 
			
		||||
				((OpenRocketLoaderActivity)getActivity()).doNotFixMissingMotors();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
				);
 | 
			
		||||
		return builder.create();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,76 @@
 | 
			
		||||
package net.sf.openrocket.android.rocket;
 | 
			
		||||
 | 
			
		||||
import java.util.HashSet;
 | 
			
		||||
import java.util.Iterator;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
import net.sf.openrocket.aerodynamics.WarningSet;
 | 
			
		||||
import net.sf.openrocket.android.util.AndroidLogWrapper;
 | 
			
		||||
import net.sf.openrocket.file.DatabaseMotorFinder;
 | 
			
		||||
import net.sf.openrocket.motor.Motor;
 | 
			
		||||
import net.sf.openrocket.motor.ThrustCurveMotorPlaceholder;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.Configuration;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.MotorMount;
 | 
			
		||||
import net.sf.openrocket.rocketcomponent.Rocket;
 | 
			
		||||
 | 
			
		||||
public abstract class MissingMotorHelpers {
 | 
			
		||||
 | 
			
		||||
	public static Set<ThrustCurveMotorPlaceholder> findMissingMotors( Rocket rocket ) {
 | 
			
		||||
 | 
			
		||||
		Set<ThrustCurveMotorPlaceholder> missingMotors = new HashSet<ThrustCurveMotorPlaceholder>();
 | 
			
		||||
		Configuration config = rocket.getDefaultConfiguration();
 | 
			
		||||
		for( String configID : rocket.getMotorConfigurationIDs() ) {
 | 
			
		||||
			config.setMotorConfigurationID(configID);
 | 
			
		||||
			Iterator<MotorMount> mmts = config.motorIterator();
 | 
			
		||||
			while ( mmts.hasNext() ) {
 | 
			
		||||
				MotorMount mmt = mmts.next();
 | 
			
		||||
				Motor m = mmt.getMotor(configID);
 | 
			
		||||
				if ( m instanceof ThrustCurveMotorPlaceholder ) {
 | 
			
		||||
					missingMotors.add( (ThrustCurveMotorPlaceholder) m );
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for ( ThrustCurveMotorPlaceholder m : missingMotors ) {
 | 
			
		||||
			AndroidLogWrapper.d(MissingMotorHelpers.class, "Missing Motor: {}", m);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return missingMotors;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public static void updateMissingMotors( Rocket rocket, WarningSet warnings ) {
 | 
			
		||||
	
 | 
			
		||||
		DatabaseMotorFinder finder = new DatabaseMotorFinder();
 | 
			
		||||
		
 | 
			
		||||
		Configuration config = rocket.getDefaultConfiguration();
 | 
			
		||||
		for( String configID : rocket.getMotorConfigurationIDs() ) {
 | 
			
		||||
			config.setMotorConfigurationID(configID);
 | 
			
		||||
			Iterator<MotorMount> mmts = config.motorIterator();
 | 
			
		||||
			while ( mmts.hasNext() ) {
 | 
			
		||||
				MotorMount mmt = mmts.next();
 | 
			
		||||
				Motor m = mmt.getMotor(configID);
 | 
			
		||||
				if ( m instanceof ThrustCurveMotorPlaceholder ) {
 | 
			
		||||
					
 | 
			
		||||
					ThrustCurveMotorPlaceholder placeholder = (ThrustCurveMotorPlaceholder)m;
 | 
			
		||||
					Motor newMotor = finder.findMotor(placeholder.getMotorType(),
 | 
			
		||||
							placeholder.getManufacturer(),
 | 
			
		||||
							placeholder.getDesignation(),
 | 
			
		||||
							placeholder.getDiameter(),
 | 
			
		||||
							placeholder.getLength(),
 | 
			
		||||
							placeholder.getDigest(),
 | 
			
		||||
							warnings);
 | 
			
		||||
 | 
			
		||||
					if ( newMotor != null ) {
 | 
			
		||||
						// one is now here so replace it
 | 
			
		||||
						mmt.setMotor(configID, newMotor);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
@ -1,32 +1,52 @@
 | 
			
		||||
package net.sf.openrocket.android.rocket;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
import net.sf.openrocket.R;
 | 
			
		||||
import net.sf.openrocket.aerodynamics.WarningSet;
 | 
			
		||||
import net.sf.openrocket.android.Application;
 | 
			
		||||
import net.sf.openrocket.android.thrustcurve.TCMissingMotorDownloadAction;
 | 
			
		||||
import net.sf.openrocket.android.thrustcurve.TCQueryAction;
 | 
			
		||||
import net.sf.openrocket.android.util.AndroidLogWrapper;
 | 
			
		||||
import android.app.AlertDialog;
 | 
			
		||||
import android.app.Dialog;
 | 
			
		||||
import net.sf.openrocket.motor.ThrustCurveMotorPlaceholder;
 | 
			
		||||
import android.app.ProgressDialog;
 | 
			
		||||
import android.content.DialogInterface;
 | 
			
		||||
import android.content.Intent;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.support.v4.app.DialogFragment;
 | 
			
		||||
import android.support.v4.app.FragmentActivity;
 | 
			
		||||
 | 
			
		||||
public class OpenRocketLoaderActivity extends FragmentActivity {
 | 
			
		||||
public class OpenRocketLoaderActivity extends FragmentActivity
 | 
			
		||||
implements TCQueryAction.OnComplete
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	private OpenRocketLoaderResult result;
 | 
			
		||||
	
 | 
			
		||||
	private Set<ThrustCurveMotorPlaceholder> missingMotors;
 | 
			
		||||
	private OpenRocketLoaderTask task;
 | 
			
		||||
	private ProgressDialog progress;
 | 
			
		||||
	private DialogFragment missingMotorDialog;
 | 
			
		||||
	private TCMissingMotorDownloadAction missingMotorDownloadAction;
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected void onCreate(Bundle savedInstanceState) {
 | 
			
		||||
		super.onCreate(savedInstanceState);
 | 
			
		||||
		setContentView(R.layout.main);
 | 
			
		||||
		Intent i = getIntent();
 | 
			
		||||
		Uri file = i.getData();
 | 
			
		||||
		loadOrkFile(file);
 | 
			
		||||
		missingMotorDownloadAction = new TCMissingMotorDownloadAction(this);
 | 
			
		||||
		if ( savedInstanceState == null || savedInstanceState.getBoolean("isLoading", false) == false ) {
 | 
			
		||||
			Intent i = getIntent();
 | 
			
		||||
			Uri file = i.getData();
 | 
			
		||||
			loadOrkFile(file);
 | 
			
		||||
		} else {
 | 
			
		||||
			progress = ProgressDialog.show(this, "Loading file", "");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected void onSaveInstanceState(Bundle outState) {
 | 
			
		||||
		super.onSaveInstanceState(outState);
 | 
			
		||||
		outState.putBoolean("isLoading", true);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
@ -37,6 +57,10 @@ public class OpenRocketLoaderActivity extends FragmentActivity {
 | 
			
		||||
			}
 | 
			
		||||
			progress = null;
 | 
			
		||||
		}
 | 
			
		||||
		if ( missingMotorDownloadAction != null ) {
 | 
			
		||||
			missingMotorDownloadAction.dismiss();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		super.onDestroy();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -46,84 +70,83 @@ public class OpenRocketLoaderActivity extends FragmentActivity {
 | 
			
		||||
		File orkFile = new File(path);
 | 
			
		||||
		progress = ProgressDialog.show(this, "Loading file", "");
 | 
			
		||||
 | 
			
		||||
		final OpenRocketLoaderTask task = new OpenRocketLoaderTask() {
 | 
			
		||||
 | 
			
		||||
			/* (non-Javadoc)
 | 
			
		||||
			 * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
 | 
			
		||||
			 */
 | 
			
		||||
			@Override
 | 
			
		||||
			protected void onPostExecute(OpenRocketLoaderResult result) {
 | 
			
		||||
				super.onPostExecute(result);
 | 
			
		||||
				AndroidLogWrapper.d(OpenRocketLoaderActivity.class,"Finished loading " + OpenRocketLoaderActivity.this);
 | 
			
		||||
				finishedLoading(result);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		};
 | 
			
		||||
		task = new OpenRocketLoaderTask(this);
 | 
			
		||||
 | 
			
		||||
		task.execute(orkFile);
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void finishedLoading(OpenRocketLoaderResult result) {
 | 
			
		||||
		if ( progress.isShowing() ) {
 | 
			
		||||
	/**
 | 
			
		||||
	 * Called by the OpenRocketLoaderTask when it completes.
 | 
			
		||||
	 * is default visibility so it can be called from this package.
 | 
			
		||||
	 * 
 | 
			
		||||
	 * @param result
 | 
			
		||||
	 */
 | 
			
		||||
	void finishedLoading(OpenRocketLoaderResult result) {
 | 
			
		||||
		if ( progress != null && progress.isShowing() ) {
 | 
			
		||||
			progress.dismiss();
 | 
			
		||||
		}
 | 
			
		||||
		this.result = result;
 | 
			
		||||
		((Application)OpenRocketLoaderActivity.this.getApplication()).setRocketDocument( result.rocket );
 | 
			
		||||
 | 
			
		||||
		updateMissingMotors();
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void updateMissingMotors() {
 | 
			
		||||
		missingMotors = MissingMotorHelpers.findMissingMotors(result.rocket.getRocket());
 | 
			
		||||
 | 
			
		||||
		if ( missingMotors.size() > 0 ) {
 | 
			
		||||
			missingMotorDialog = MissingMotorDialogFragment.newInstance( missingMotors );
 | 
			
		||||
			missingMotorDialog.show(getSupportFragmentManager(), "missing motors");
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		displayWarningDialog();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Called when the TCMissingMotorDownload process finishes.
 | 
			
		||||
	 */
 | 
			
		||||
	@Override
 | 
			
		||||
	public void onComplete() {
 | 
			
		||||
 | 
			
		||||
		// Need to update the motor references.
 | 
			
		||||
		MissingMotorHelpers.updateMissingMotors(result.rocket.getRocket(), result.warnings);
 | 
			
		||||
 | 
			
		||||
		displayWarningDialog();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void displayWarningDialog() {
 | 
			
		||||
		WarningSet warnings = result.warnings;
 | 
			
		||||
		if (warnings == null || warnings.isEmpty()) {
 | 
			
		||||
			((Application)OpenRocketLoaderActivity.this.getApplication()).setRocketDocument( result.rocket );
 | 
			
		||||
			Intent i = new Intent(this,OpenRocketViewer.class);
 | 
			
		||||
			startActivity(i);
 | 
			
		||||
			finish();
 | 
			
		||||
		} else {
 | 
			
		||||
			// TODO - Build a warning listing dialog
 | 
			
		||||
			DialogFragment newFragment = WarningDialogFragment.newInstance();
 | 
			
		||||
			newFragment.show(getSupportFragmentManager(), "dialog");
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		moveOnToViewer();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    public void doPositiveClick() {
 | 
			
		||||
        // Do stuff here.
 | 
			
		||||
        AndroidLogWrapper.i(OpenRocketLoaderActivity.class, "Positive click!");
 | 
			
		||||
        finish();
 | 
			
		||||
    }
 | 
			
		||||
	public void doFixMissingMotors() {
 | 
			
		||||
 | 
			
		||||
    public void doNegativeClick() {
 | 
			
		||||
        // Do stuff here.
 | 
			
		||||
    	AndroidLogWrapper.i(OpenRocketLoaderActivity.class, "Negative click!");
 | 
			
		||||
        finish();
 | 
			
		||||
    }
 | 
			
		||||
		missingMotorDialog.dismiss();
 | 
			
		||||
 | 
			
		||||
    public static class WarningDialogFragment extends DialogFragment {
 | 
			
		||||
		missingMotorDownloadAction.setMissingMotors(missingMotors);
 | 
			
		||||
		missingMotorDownloadAction.start();
 | 
			
		||||
 | 
			
		||||
	    public static WarningDialogFragment newInstance() {
 | 
			
		||||
	    	WarningDialogFragment frag = new WarningDialogFragment();
 | 
			
		||||
	        Bundle args = new Bundle();
 | 
			
		||||
	        frag.setArguments(args);
 | 
			
		||||
	        return frag;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	    @Override
 | 
			
		||||
	    public Dialog onCreateDialog(Bundle savedInstanceState) {
 | 
			
		||||
	public void doNotFixMissingMotors() {
 | 
			
		||||
		missingMotorDialog.dismiss();
 | 
			
		||||
		displayWarningDialog();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	        return new AlertDialog.Builder(getActivity())
 | 
			
		||||
//	                .setIcon(android.R.drawable.alert_dialog_icon)
 | 
			
		||||
	                .setTitle("Warnings")
 | 
			
		||||
	                .setPositiveButton("OK",
 | 
			
		||||
	                    new DialogInterface.OnClickListener() {
 | 
			
		||||
	                        public void onClick(DialogInterface dialog, int whichButton) {
 | 
			
		||||
	                            ((OpenRocketLoaderActivity)getActivity()).doPositiveClick();
 | 
			
		||||
	                        }
 | 
			
		||||
	                    }
 | 
			
		||||
	                )
 | 
			
		||||
	                .setNegativeButton("Cancel",
 | 
			
		||||
	                    new DialogInterface.OnClickListener() {
 | 
			
		||||
	                        public void onClick(DialogInterface dialog, int whichButton) {
 | 
			
		||||
	                            ((OpenRocketLoaderActivity)getActivity()).doNegativeClick();
 | 
			
		||||
	                        }
 | 
			
		||||
	                    }
 | 
			
		||||
	                )
 | 
			
		||||
	                .create();
 | 
			
		||||
	    }
 | 
			
		||||
	private void moveOnToViewer() {
 | 
			
		||||
		Intent i = new Intent(this,OpenRocketViewer.class);
 | 
			
		||||
		startActivity(i);
 | 
			
		||||
		finish();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,13 +4,20 @@ import java.io.File;
 | 
			
		||||
 | 
			
		||||
import net.sf.openrocket.android.util.AndroidLogWrapper;
 | 
			
		||||
import net.sf.openrocket.document.OpenRocketDocument;
 | 
			
		||||
import net.sf.openrocket.file.DatabaseMotorFinder;
 | 
			
		||||
import net.sf.openrocket.file.DatabaseMotorFinderWithMissingMotors;
 | 
			
		||||
import net.sf.openrocket.file.RocketLoadException;
 | 
			
		||||
import net.sf.openrocket.file.openrocket.importt.OpenRocketLoader;
 | 
			
		||||
import android.app.Activity;
 | 
			
		||||
import android.os.AsyncTask;
 | 
			
		||||
 | 
			
		||||
public class OpenRocketLoaderTask extends AsyncTask<File, Void, OpenRocketLoaderResult> {
 | 
			
		||||
	
 | 
			
		||||
	private OpenRocketLoaderActivity parent;
 | 
			
		||||
	
 | 
			
		||||
	public OpenRocketLoaderTask( OpenRocketLoaderActivity parent ) {
 | 
			
		||||
		this.parent = parent;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* (non-Javadoc)
 | 
			
		||||
	 * @see android.os.AsyncTask#doInBackground(Params[])
 | 
			
		||||
	 */
 | 
			
		||||
@ -21,7 +28,7 @@ public class OpenRocketLoaderTask extends AsyncTask<File, Void, OpenRocketLoader
 | 
			
		||||
		OpenRocketLoader rocketLoader = new OpenRocketLoader();
 | 
			
		||||
		try {
 | 
			
		||||
			OpenRocketLoaderResult result = new OpenRocketLoaderResult();
 | 
			
		||||
			OpenRocketDocument rocket = rocketLoader.load(arg0[0], new DatabaseMotorFinder());
 | 
			
		||||
			OpenRocketDocument rocket = rocketLoader.load(arg0[0], new DatabaseMotorFinderWithMissingMotors());
 | 
			
		||||
			result.rocket = rocket;
 | 
			
		||||
			result.warnings = result.warnings;
 | 
			
		||||
			return result;
 | 
			
		||||
@ -32,4 +39,11 @@ public class OpenRocketLoaderTask extends AsyncTask<File, Void, OpenRocketLoader
 | 
			
		||||
		
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	protected void onPostExecute(OpenRocketLoaderResult result) {
 | 
			
		||||
		super.onPostExecute(result);
 | 
			
		||||
		AndroidLogWrapper.d(OpenRocketLoaderActivity.class,"Finished loading " + OpenRocketLoaderTask.this);
 | 
			
		||||
		parent.finishedLoading(result);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,36 @@
 | 
			
		||||
package net.sf.openrocket.android.rocket;
 | 
			
		||||
 | 
			
		||||
import android.app.AlertDialog;
 | 
			
		||||
import android.app.Dialog;
 | 
			
		||||
import android.content.DialogInterface;
 | 
			
		||||
import android.os.Bundle;
 | 
			
		||||
import android.support.v4.app.DialogFragment;
 | 
			
		||||
 | 
			
		||||
public class WarningDialogFragment extends DialogFragment {
 | 
			
		||||
 | 
			
		||||
	public static WarningDialogFragment newInstance() {
 | 
			
		||||
		WarningDialogFragment frag = new WarningDialogFragment();
 | 
			
		||||
		Bundle args = new Bundle();
 | 
			
		||||
		frag.setArguments(args);
 | 
			
		||||
		return frag;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public Dialog onCreateDialog(Bundle savedInstanceState) {
 | 
			
		||||
 | 
			
		||||
		AlertDialog.Builder builder =  new AlertDialog.Builder(getActivity());
 | 
			
		||||
		//	                .setIcon(android.R.drawable.alert_dialog_icon)
 | 
			
		||||
		builder.setTitle("Warnings");
 | 
			
		||||
		builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
 | 
			
		||||
			public void onClick(DialogInterface dialog, int whichButton) {
 | 
			
		||||
				getActivity().finish();
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
		builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
 | 
			
		||||
			public void onCancel(DialogInterface dialog) {
 | 
			
		||||
				getActivity().finish();
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
		return builder.create();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user