package com.door43.translationstudio.newui.publish; import android.content.Intent; import android.os.Bundle; import android.support.design.widget.Snackbar; import android.support.v7.widget.Toolbar; import android.view.MenuItem; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.door43.translationstudio.R; import com.door43.translationstudio.core.Library; import com.door43.translationstudio.core.SourceLanguage; import com.door43.translationstudio.core.SourceTranslation; import com.door43.translationstudio.core.TargetTranslation; import com.door43.translationstudio.core.Translator; import com.door43.translationstudio.newui.BaseActivity; import com.door43.translationstudio.newui.translate.TargetTranslationActivity; import com.door43.translationstudio.AppContext; import com.door43.widget.ViewUtil; import java.security.InvalidParameterException; import java.util.Locale; public class PublishActivity extends BaseActivity implements PublishStepFragment.OnEventListener { public static final int STEP_VALIDATE = 0; public static final int STEP_PROFILE = 1; public static final int STEP_REVIEW = 2; public static final int STEP_PUBLISH = 3; public static final String EXTRA_TARGET_TRANSLATION_ID = "extra_target_translation_id"; private static final String STATE_STEP = "state_step"; private static final String STATE_PUBLISH_FINISHED = "state_publish_finished"; public static final String EXTRA_CALLING_ACTIVITY = "extra_calling_activity"; private PublishStepFragment mFragment; private Translator mTranslator; private TargetTranslation mTargetTranslation; private int mCurrentStep = 0; private ViewHolder mValidationIndicator; private ViewHolder mProfileIndicator; private ViewHolder mReviewIndicator; private ViewHolder mPublishIndicator; public static final int ACTIVITY_HOME = 1001; public static final int ACTIVITY_TRANSLATION = 1002; private boolean mPublishFinished = false; private int mCallingActivity; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_publish); final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); mTranslator = AppContext.getTranslator(); // validate parameters Bundle args = getIntent().getExtras(); final String targetTranslationId = args.getString(EXTRA_TARGET_TRANSLATION_ID, null); mTargetTranslation = mTranslator.getTargetTranslation(targetTranslationId); if(mTargetTranslation == null) { throw new InvalidParameterException("a valid target translation id is required"); } // identify calling activity mCallingActivity = args.getInt(EXTRA_CALLING_ACTIVITY, 0); if(mCallingActivity == 0) { throw new InvalidParameterException("you must specify the calling activity"); } // stage indicators mValidationIndicator = new ViewHolder((LinearLayout)findViewById(R.id.validation_button), (ImageView)findViewById(R.id.validation_active), (ImageView)findViewById(R.id.validation_done), (TextView)findViewById(R.id.validation_step), (TextView)findViewById(R.id.validation_title), (ImageView)findViewById(R.id.validation_circle)); mProfileIndicator = new ViewHolder((LinearLayout)findViewById(R.id.profile_button), (ImageView)findViewById(R.id.profile_active), (ImageView)findViewById(R.id.profile_done), (TextView)findViewById(R.id.profile_step), (TextView)findViewById(R.id.profile_title), (ImageView)findViewById(R.id.profile_circle)); mReviewIndicator = new ViewHolder((LinearLayout)findViewById(R.id.review_button), (ImageView)findViewById(R.id.review_active), (ImageView)findViewById(R.id.review_done), (TextView)findViewById(R.id.review_step), (TextView)findViewById(R.id.review_title), (ImageView)findViewById(R.id.review_circle)); mPublishIndicator = new ViewHolder((LinearLayout)findViewById(R.id.publish_button), (ImageView)findViewById(R.id.publish_active), (ImageView)findViewById(R.id.publish_done), (TextView)findViewById(R.id.publish_step), (TextView)findViewById(R.id.publish_title), (ImageView)findViewById(R.id.publish_circle)); if(savedInstanceState != null) { mCurrentStep = savedInstanceState.getInt(STATE_STEP, 0); mPublishFinished = savedInstanceState.getBoolean(STATE_PUBLISH_FINISHED, false); } updateIndicatorsForStep(mCurrentStep); // inject fragments if(findViewById(R.id.fragment_container) != null) { if(savedInstanceState != null) { mFragment = (PublishStepFragment)getFragmentManager().findFragmentById(R.id.fragment_container); } else { mFragment = new ValidationFragment(); String sourceTranslationId = AppContext.getSelectedSourceTranslationId(targetTranslationId); if(sourceTranslationId == null) { // use the default target translation if they have not chosen one. Library library = AppContext.getLibrary(); SourceLanguage sourceLanguage = library.getPreferredSourceLanguage(mTargetTranslation.getProjectId(), Locale.getDefault().getLanguage()); if(sourceLanguage != null) { SourceTranslation sourceTranslation = library.getDefaultSourceTranslation(mTargetTranslation.getProjectId(), sourceLanguage.getId()); if (sourceTranslation != null) { sourceTranslationId = sourceTranslation.getId(); } } } if(sourceTranslationId != null) { args.putSerializable(PublishStepFragment.ARG_SOURCE_TRANSLATION_ID, sourceTranslationId); mFragment.setArguments(args); getFragmentManager().beginTransaction().add(R.id.fragment_container, mFragment).commit(); // TODO: animate } else { // the user must choose a source translation before they can publish Snackbar snack = Snackbar.make(findViewById(android.R.id.content), R.string.choose_source_translations, Snackbar.LENGTH_LONG); ViewUtil.setSnackBarTextColor(snack, getResources().getColor(R.color.light_primary_text)); snack.show(); finish(); } } } // step click listeners mValidationIndicator.mButtonLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { goToStep(STEP_VALIDATE, false); } }); mProfileIndicator.mButtonLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { goToStep(STEP_PROFILE, false); } }); mReviewIndicator.mButtonLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { goToStep(STEP_REVIEW, false); } }); mPublishIndicator.mButtonLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { goToStep(STEP_PUBLISH, false); } }); } @Override public boolean onOptionsItemSelected(MenuItem item) { if(item.getItemId() == android.R.id.home) { if(mCallingActivity == ACTIVITY_TRANSLATION) { // TRICKY: the translation activity is finished after opening the publish activity // because we may have to go back and forth and don't want to fill up the stack Intent intent = new Intent(this, TargetTranslationActivity.class); Bundle args = new Bundle(); args.putString(AppContext.EXTRA_TARGET_TRANSLATION_ID, mTargetTranslation.getId()); intent.putExtras(args); startActivity(intent); } finish(); } return true; } @Override public void onBackPressed() { // TRICKY: the translation activity is finished after opening the publish activity // because we may have to go back and forth and don't want to fill up the stack if(mCallingActivity == ACTIVITY_TRANSLATION) { Intent intent = new Intent(this, TargetTranslationActivity.class); Bundle args = new Bundle(); args.putString(AppContext.EXTRA_TARGET_TRANSLATION_ID, mTargetTranslation.getId()); intent.putExtras(args); startActivity(intent); } finish(); } @Override public void nextStep() { goToStep(mCurrentStep + 1, true); } @Override public void finishPublishing() { mPublishIndicator.setDone(true); mPublishIndicator.setActive(true); mPublishFinished = true; } /** * checks if the user can go to this step yet * @param step * @return */ private boolean validateStep(int step, boolean force) { if(step > STEP_PUBLISH) { step = STEP_PUBLISH; } if(force) { // allow users to open this step if all of the previous steps have been visited while (step > 0) { step--; switch (step) { case STEP_VALIDATE: if (!mValidationIndicator.isVisited()) { return false; } break; case STEP_PROFILE: if (!mProfileIndicator.isVisited()) { return false; } break; case STEP_REVIEW: if (!mReviewIndicator.isVisited()) { return false; } break; case STEP_PUBLISH: // never gets called break; } } } else { // allow the user to open a previously opened step switch (step) { case STEP_VALIDATE: if (!mValidationIndicator.isVisited()) { return false; } break; case STEP_PROFILE: if (!mProfileIndicator.isVisited()) { return false; } break; case STEP_REVIEW: if (!mReviewIndicator.isVisited()) { return false; } break; case STEP_PUBLISH: if (!mPublishIndicator.isVisited()) { return false; } break; } } return true; } /** * Moves to the a stage in the publish process * @param step * @param force forces the step to be opened even if it has never been opened before */ private void goToStep(int step, boolean force) { if(!validateStep(step, force) || step == mCurrentStep) { return; } if(step > STEP_PUBLISH) { mCurrentStep = STEP_PUBLISH; // mark the publish step as done mPublishIndicator.setDone(true); } else { mCurrentStep = step; } updateIndicatorsForStep(mCurrentStep); switch(mCurrentStep) { case STEP_PROFILE: mFragment = new TranslatorsFragment(); break; case STEP_REVIEW: mFragment = new ReviewFragment(); break; case STEP_PUBLISH: mFragment = new PublishFragment(); break; case STEP_VALIDATE: default: mFragment = new ValidationFragment(); break; } Bundle args = getIntent().getExtras(); String sourceTranslationId = AppContext.getSelectedSourceTranslationId(mTargetTranslation.getId()); // TRICKY: if the user has not chosen a source translation (this is an empty translation) the id will be null if(sourceTranslationId == null) { SourceTranslation sourceTranslation = AppContext.getLibrary().getDefaultSourceTranslation(mTargetTranslation.getProjectId(), Locale.getDefault().getLanguage()); if(sourceTranslation != null) { sourceTranslationId = sourceTranslation.getId(); } } args.putSerializable(PublishStepFragment.ARG_SOURCE_TRANSLATION_ID, sourceTranslationId); args.putBoolean(PublishStepFragment.ARG_PUBLISH_FINISHED, mPublishFinished); mFragment.setArguments(args); getFragmentManager().beginTransaction().replace(R.id.fragment_container, mFragment).commit(); // TODO: animate } /** * Correctly renders the state indicators * @param step */ private void updateIndicatorsForStep(int step) { // reset if(mPublishFinished) { mValidationIndicator.setDone(true); mProfileIndicator.setDone(true); mReviewIndicator.setDone(true); mPublishIndicator.setDone(true); } else { mValidationIndicator.setVisited(false); mProfileIndicator.setVisited(false); mReviewIndicator.setVisited(false); mPublishIndicator.setVisited(false); } switch (step) { case STEP_VALIDATE: mValidationIndicator.setActive(true); mProfileIndicator.setActive(false); mReviewIndicator.setActive(false); mPublishIndicator.setActive(false); break; case STEP_PROFILE: mValidationIndicator.setDone(true); mProfileIndicator.setActive(true); mReviewIndicator.setActive(false); mPublishIndicator.setActive(false); break; case STEP_REVIEW: mValidationIndicator.setDone(true); mProfileIndicator.setDone(true); mReviewIndicator.setActive(true); mPublishIndicator.setActive(false); break; case STEP_PUBLISH: mValidationIndicator.setDone(true); mProfileIndicator.setDone(true); mReviewIndicator.setDone(true); mPublishIndicator.setActive(true); break; } } private class ViewHolder { private final LinearLayout mButtonLayout; private final ImageView mActiveView; private final ImageView mDoneView; private final TextView mStepView; private final TextView mTitleView; private final ImageView mCircleView; private boolean mVisited = false; private boolean mDone; public ViewHolder(LinearLayout buttonLayout, ImageView activeView, ImageView doneView, TextView stepView, TextView titleView, ImageView circleView) { mButtonLayout = buttonLayout; mActiveView = activeView; mDoneView = doneView; mStepView = stepView; mTitleView = titleView; mCircleView = circleView; } /** * Checks if the step has been finished at least once durring this session. * @return */ public boolean isDone() { return mDone; } /** * Checks if the step has been visited at least once durring this session. * @return */ public boolean isVisited() { return mVisited; } /** * Marks the step has active or not * @param active */ public void setActive(boolean active) { if(active) { setVisited(true); mActiveView.setVisibility(View.VISIBLE); if(!mDone) { mStepView.setVisibility(View.VISIBLE); mDoneView.setVisibility(View.GONE); } else { mDoneView.setVisibility(View.VISIBLE); } } else { mActiveView.setVisibility(View.GONE); } } /** * Marks the step has done or not * @param done */ public void setDone(boolean done) { if(done) { mDone = true; setVisited(true); mActiveView.setVisibility(View.GONE); mStepView.setVisibility(View.GONE); mDoneView.setVisibility(View.VISIBLE); } else if(!mDone) { // finished steps cannot be un-finished mStepView.setVisibility(View.VISIBLE); mDoneView.setVisibility(View.GONE); } } /** * Sets the step as visisted or not * @param visited */ public void setVisited(boolean visited) { // TODO: tint the drawables as well if(visited) { mVisited = true; mStepView.setTextColor(getResources().getColor(R.color.light_primary_text)); mTitleView.setTextColor(getResources().getColor(R.color.light_primary_text)); ViewUtil.tintViewDrawable(mCircleView, getResources().getColor(R.color.light_primary_text)); } else if(!mVisited) { // visited steps cannot be un-visited setDone(false); setActive(false); mStepView.setTextColor(getResources().getColor(R.color.light_secondary_text)); mTitleView.setTextColor(getResources().getColor(R.color.light_secondary_text)); ViewUtil.tintViewDrawable(mCircleView, getResources().getColor(R.color.light_secondary_text)); } } } public void onSaveInstanceState(Bundle out) { out.putInt(STATE_STEP, mCurrentStep); out.putBoolean(STATE_PUBLISH_FINISHED, mPublishFinished); super.onSaveInstanceState(out); } }