diff --git a/app/build.gradle b/app/build.gradle index 0331620..f2dad60 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,10 +28,11 @@ android { compileSdkVersion 21 buildToolsVersion '21.1.2' defaultConfig { + applicationId "com.pluscubed.plustimer" minSdkVersion 14 targetSdkVersion 21 - versionCode 19 - versionName '0.2.1' + versionCode 20 + versionName '0.2.2' } if (project.hasProperty("RELEASE_STORE_FILE")) { @@ -75,10 +76,6 @@ android { ext.enableCrashlytics = false } } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 - } } dependencies { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 93a25a0..adea6f3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,10 +1,9 @@ - + - + - diff --git a/app/src/main/java/com/pluscubed/plustimer/model/PuzzleType.java b/app/src/main/java/com/pluscubed/plustimer/model/PuzzleType.java index 3ef6b17..4e7449b 100644 --- a/app/src/main/java/com/pluscubed/plustimer/model/PuzzleType.java +++ b/app/src/main/java/com/pluscubed/plustimer/model/PuzzleType.java @@ -128,6 +128,14 @@ public synchronized static void initialize(Context context) { PrefUtils.saveVersionCode(context); } + public String getHistoryFileName() { + return historyFileName; + } + + public String getCurrentSessionFileName() { + return currentSessionFileName; + } + public HistorySessions getHistorySessions() { return mHistorySessions; } @@ -265,7 +273,7 @@ public void resetCurrentSession() { mCurrentSession.reset(); } - public boolean isEnabled() { + boolean isEnabled() { return mEnabled; } diff --git a/app/src/main/java/com/pluscubed/plustimer/model/Session.java b/app/src/main/java/com/pluscubed/plustimer/model/Session.java index 4b16157..cb8174e 100644 --- a/app/src/main/java/com/pluscubed/plustimer/model/Session.java +++ b/app/src/main/java/com/pluscubed/plustimer/model/Session.java @@ -52,13 +52,13 @@ public void reset() { notifyReset(); } - public void notifySolveAdded() { + void notifySolveAdded() { for (Observer s : mObservers) { s.onSolveAdded(); } } - public void notifySolveDeleted(int index) { + void notifySolveDeleted(int index) { for (Observer s : mObservers) { s.onSolveRemoved(index); } @@ -70,7 +70,7 @@ public void notifySolveChanged(int index) { } } - public void notifyReset() { + void notifyReset() { for (Observer s : mObservers) { s.onReset(); } @@ -146,8 +146,8 @@ public String getStringCurrentAverageOf(int number, * @param millisecondsEnabled whether to display milliseconds * @return the best average of some number of solves */ - public String getStringBestAverageOf(int number, - boolean millisecondsEnabled) { + String getStringBestAverageOf(int number, + boolean millisecondsEnabled) { long bestAverage = getBestAverageOf(number); if (bestAverage == GET_AVERAGE_INVALID_NOT_ENOUGH) { return ""; diff --git a/app/src/main/java/com/pluscubed/plustimer/ui/AboutActivity.java b/app/src/main/java/com/pluscubed/plustimer/ui/AboutActivity.java index 7969468..aa07d15 100644 --- a/app/src/main/java/com/pluscubed/plustimer/ui/AboutActivity.java +++ b/app/src/main/java/com/pluscubed/plustimer/ui/AboutActivity.java @@ -17,7 +17,7 @@ import com.pluscubed.plustimer.BuildConfig; import com.pluscubed.plustimer.R; -import com.pluscubed.plustimer.utils.Utils; +import com.pluscubed.plustimer.utils.ErrorUtils; /** * About Page @@ -126,7 +126,7 @@ public void onClick(View v) { send.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Utils.sendHistoryDataEmail(getActivity()); + ErrorUtils.sendFileDataEmail(getActivity()); } }); diff --git a/app/src/main/java/com/pluscubed/plustimer/ui/CreateDialogCallback.java b/app/src/main/java/com/pluscubed/plustimer/ui/CreateDialogCallback.java deleted file mode 100644 index 5bd4ca6..0000000 --- a/app/src/main/java/com/pluscubed/plustimer/ui/CreateDialogCallback.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.pluscubed.plustimer.ui; - -/** - * On Solve Item - */ -public interface CreateDialogCallback { - - void createSolveDisplayDialog(String displayName, int sessionIndex, - int solveIndex); - - void createSolveAddDialog(String displayName, int sessionIndex); -} diff --git a/app/src/main/java/com/pluscubed/plustimer/ui/CurrentSessionActivity.java b/app/src/main/java/com/pluscubed/plustimer/ui/CurrentSessionActivity.java index 3c5f897..146b376 100644 --- a/app/src/main/java/com/pluscubed/plustimer/ui/CurrentSessionActivity.java +++ b/app/src/main/java/com/pluscubed/plustimer/ui/CurrentSessionActivity.java @@ -1,6 +1,8 @@ package com.pluscubed.plustimer.ui; -import android.app.DialogFragment; +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; import android.app.Fragment; import android.app.FragmentManager; import android.graphics.Color; @@ -13,16 +15,19 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.DecelerateInterpolator; import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.LinearLayout; import android.widget.Spinner; import com.crashlytics.android.Crashlytics; import com.pluscubed.plustimer.BuildConfig; import com.pluscubed.plustimer.R; import com.pluscubed.plustimer.model.PuzzleType; +import com.pluscubed.plustimer.ui.widget.LockingViewPager; import com.pluscubed.plustimer.ui.widget.SlidingTabLayout; -import com.pluscubed.plustimer.utils.Utils; import io.fabric.sdk.android.Fabric; @@ -30,11 +35,8 @@ * Current Session Activity */ public class CurrentSessionActivity extends DrawerActivity implements - CreateDialogCallback, CurrentSessionTimerFragment.ActivityCallback { - public static final String DIALOG_SOLVE_TAG = "SOLVE_DIALOG"; - private static final String STATE_MENU_ITEMS_ENABLE_BOOLEAN = "menu_items_enable_boolean"; @@ -46,16 +48,93 @@ public class CurrentSessionActivity extends DrawerActivity implements private int mSelectedPage; private boolean mInvalidateActionBarOnDrawerClosed; + private SlidingTabLayout mSlidingTabLayout; + private LockingViewPager mViewPager; - public static String makeFragmentName(int viewId, int index) { + private static String makeFragmentName(int viewId, int index) { return "android:switcher:" + viewId + ":" + index; } - @Override public Toolbar getActionBarToolbar() { return super.getActionBarToolbar(); } + @Override + public void playToolbarExitAnimation() { + final LinearLayout toolbar = (LinearLayout) findViewById(R.id.activity_current_session_headerbar); + findViewById(R.id.activity_current_session_toolbarshadow).setVisibility(View.GONE); + ObjectAnimator exit = ObjectAnimator.ofFloat(toolbar, View.Y, + -toolbar.getHeight()); + exit.setDuration(300); + exit.setInterpolator(new AccelerateInterpolator()); + AnimatorSet scrambleAnimatorSet = new AnimatorSet(); + scrambleAnimatorSet.play(exit); + scrambleAnimatorSet.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + if (toolbar.getY() == -toolbar.getHeight()) { + toolbar.setVisibility(View.GONE); + } + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + scrambleAnimatorSet.start(); + } + + @Override + public void playToolbarEnterAnimation() { + final LinearLayout toolbar = (LinearLayout) findViewById(R.id.activity_current_session_headerbar); + ObjectAnimator exit = ObjectAnimator.ofFloat(toolbar, View.Y, 0f); + exit.setDuration(300); + exit.setInterpolator(new DecelerateInterpolator()); + AnimatorSet scrambleAnimatorSet = new AnimatorSet(); + scrambleAnimatorSet.play(exit); + toolbar.setVisibility(View.VISIBLE); + scrambleAnimatorSet.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + findViewById(R.id.activity_current_session_toolbarshadow).setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + scrambleAnimatorSet.start(); + } + + @Override + public void lockDrawerAndViewPager(boolean lock) { + mSlidingTabLayout.setClickEnabled(!lock); + mViewPager.setPagingEnabled(!lock); + lockDrawer(lock); + } + @Override public CurrentSessionTimerRetainedFragment getTimerRetainedFragment() { return (CurrentSessionTimerRetainedFragment) @@ -73,12 +152,12 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_current_session); - PuzzleType.initialize(this); - if (BuildConfig.USE_CRASHLYTICS) { Fabric.with(this, new Crashlytics()); } + PuzzleType.initialize(this); + if (savedInstanceState != null) { mScrambleImageActionEnable = savedInstanceState.getBoolean (STATE_MENU_ITEMS_ENABLE_BOOLEAN); @@ -94,24 +173,24 @@ protected void onCreate(Bundle savedInstanceState) { } //Set up ViewPager with CurrentSessionAdapter - ViewPager viewPager = (ViewPager) findViewById(R.id + mViewPager = (LockingViewPager) findViewById(R.id .activity_current_session_viewpager); - viewPager.setAdapter(new CurrentSessionPagerAdapter + mViewPager.setAdapter(new CurrentSessionPagerAdapter (getFragmentManager(), getResources().getStringArray(R.array .current_session_page_titles))); //Set up SlidingTabLayout - SlidingTabLayout slidingTabLayout = (SlidingTabLayout) findViewById(R + mSlidingTabLayout = (SlidingTabLayout) findViewById(R .id.activity_current_session_slidingtablayout); int[] attrs = {R.attr.colorAccent}; - slidingTabLayout.setSelectedIndicatorColors(obtainStyledAttributes + mSlidingTabLayout.setSelectedIndicatorColors(obtainStyledAttributes (attrs).getColor(0, Color.BLACK)); - slidingTabLayout.setDistributeEvenly(true); - slidingTabLayout.setCustomTabView(R.layout.sliding_tab_textview, + mSlidingTabLayout.setDistributeEvenly(true); + mSlidingTabLayout.setCustomTabView(R.layout.sliding_tab_textview, android.R.id.text1); - slidingTabLayout.setViewPager(viewPager); - slidingTabLayout.setOnPageChangeListener(new ViewPager + mSlidingTabLayout.setViewPager(mViewPager); + mSlidingTabLayout.setOnPageChangeListener(new ViewPager .OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, @@ -128,11 +207,12 @@ public void onPageScrollStateChanged(int state) { if (state == ViewPager.SCROLL_STATE_DRAGGING || state == ViewPager.SCROLL_STATE_SETTLING) { getCurrentSessionTimerFragment().stopHoldTimer(); + getCurrentSessionTimerFragment().playEnterAnimations(); getSolveListFragment().finishActionMode(); } } }); - viewPager.setCurrentItem(0); + mViewPager.setCurrentItem(0); getSupportActionBar().setElevation(0); @@ -159,7 +239,7 @@ private SolveListFragment getSolveListFragment() { .activity_current_session_viewpager, 1)); } - public void queueInvalidateOptionsMenu() { + void queueInvalidateOptionsMenu() { if (!isNavDrawerOpen()) { invalidateOptionsMenu(); } else { @@ -187,6 +267,7 @@ protected void onNavDrawerClosed() { protected void onNavDrawerSlide(float offset) { getSolveListFragment().finishActionMode(); getCurrentSessionTimerFragment().stopHoldTimer(); + getCurrentSessionTimerFragment().playEnterAnimations(); } @Override @@ -255,33 +336,6 @@ public void onNothingSelected(AdapterView parent) { return super.onCreateOptionsMenu(menu); } - @Override - public void createSolveDisplayDialog(String displayName, int sessionIndex, - int solveIndex) { - DialogFragment dialog = (DialogFragment) getFragmentManager() - .findFragmentByTag(DIALOG_SOLVE_TAG); - if (!Utils.assertSolveExists(this, solveIndex, PuzzleType.CURRENT_SESSION)) { - return; - } - if (dialog == null) { - SolveDialogFragment d = SolveDialogFragment.newInstanceDisplay - (PuzzleType.getCurrent().name(), - PuzzleType.CURRENT_SESSION, solveIndex); - d.show(getFragmentManager(), DIALOG_SOLVE_TAG); - } - } - - @Override - public void createSolveAddDialog(String displayName, int sessionIndex) { - DialogFragment dialog = (DialogFragment) getFragmentManager() - .findFragmentByTag(DIALOG_SOLVE_TAG); - if (dialog == null) { - SolveDialogFragment d = SolveDialogFragment.newInstanceAdd - (PuzzleType.getCurrent().name(), PuzzleType.CURRENT_SESSION); - d.show(getFragmentManager(), DIALOG_SOLVE_TAG); - } - } - public class CurrentSessionPagerAdapter extends FragmentPagerAdapter { private final String[] mPageTitles; diff --git a/app/src/main/java/com/pluscubed/plustimer/ui/CurrentSessionTimerFragment.java b/app/src/main/java/com/pluscubed/plustimer/ui/CurrentSessionTimerFragment.java index 7a545fb..e65d44b 100644 --- a/app/src/main/java/com/pluscubed/plustimer/ui/CurrentSessionTimerFragment.java +++ b/app/src/main/java/com/pluscubed/plustimer/ui/CurrentSessionTimerFragment.java @@ -1,5 +1,6 @@ package com.pluscubed.plustimer.ui; +import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.app.Fragment; @@ -16,7 +17,6 @@ import android.preference.PreferenceManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.Toolbar; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.MenuItem; @@ -37,9 +37,12 @@ import com.pluscubed.plustimer.R; import com.pluscubed.plustimer.model.BldSolve; import com.pluscubed.plustimer.model.PuzzleType; +import com.pluscubed.plustimer.model.ScrambleAndSvg; import com.pluscubed.plustimer.model.Session; import com.pluscubed.plustimer.model.Solve; +import com.pluscubed.plustimer.utils.ErrorUtils; import com.pluscubed.plustimer.utils.PrefUtils; +import com.pluscubed.plustimer.utils.SolveDialogUtils; import com.pluscubed.plustimer.utils.Utils; import java.util.Arrays; @@ -53,8 +56,8 @@ public class CurrentSessionTimerFragment extends Fragment { public static final String TAG = "CURRENT_SESSION_TIMER_FRAGMENT"; - public static final long HOLD_TIME = 550000000L; - public static final int REFRESH_RATE = 15; + private static final long HOLD_TIME = 550000000L; + private static final int REFRESH_RATE = 15; private static final String STATE_IMAGE_DISPLAYED = "scramble_image_displayed_boolean"; private static final String STATE_START_TIME = "start_time_long"; @@ -62,6 +65,32 @@ public class CurrentSessionTimerFragment extends Fragment { private static final String STATE_INSPECTING = "inspecting_boolean"; private static final String STATE_INSPECTION_START_TIME = "inspection_start_time_long"; + + private final PuzzleType.Observer puzzleTypeObserver = + new PuzzleType.Observer() { + @Override + public void onPuzzleTypeChanged() { + //Update quick stats and hlistview + onSessionSolvesChanged(); + + //Set timer text to ready, scramble text to scrambling + mScrambleText.setText(R.string.scrambling); + + //Update options menu (disable) + enableMenuItems(false); + showScrambleImage(false); + + mBldMode = PuzzleType.getCurrent().name().contains("BLD"); + + resetGenerateScramble(); + + resetTimer(); + + PuzzleType.getCurrent().getSession(PuzzleType.CURRENT_SESSION) + .registerObserver(sessionObserver); + } + }; + private final Session.Observer sessionObserver = new Session.Observer() { @Override public void onSolveAdded() { @@ -91,56 +120,8 @@ public void onReset() { adapter.updateSolvesList(-1, ObservedMode.RESET); } }; - private final Runnable mHoldTimerRunnable = new Runnable() { - @Override - public void run() { - setTextColor(Color.GREEN); - setTimerTextToPrefSize(); - } - }; - private boolean mHoldToStartEnabled; - private boolean mInspectionEnabled; - private boolean mTwoRowTimeEnabled; - private PrefUtils.TimerUpdate mUpdateTimePref; - private boolean mMillisecondsEnabled; - private boolean mMonospaceScrambleFontEnabled; - private int mPrefSize; - private boolean mKeepScreenOn; - private boolean mSignEnabled; - - - private CurrentSessionTimerRetainedFragment mRetainedFragment; - - - private TextView mTimerText; - private TextView mTimerText2; - private TextView mScrambleText; - private RecyclerView mTimeBarRecycler; - private ImageView mScrambleImage; - private TextView mStatsSolvesText; - private TextView mStatsText; - private LinearLayout mLastBarLinearLayout; - private Button mLastDnfButton; - private Button mLastPlusTwoButton; - private Button mLastDeleteButton; - private FrameLayout mDynamicStatusBarFrame; - private TextView mDynamicStatusBarText; - - private Handler mUiHandler; - - - private boolean mHoldTiming; - private long mHoldTimerStartTimestamp; - private boolean mInspecting; - private long mInspectionStartTimestamp; - private long mInspectionStopTimestamp; - private long mTimingStartTimestamp; - private boolean mFromSavedInstanceState; - private boolean mTiming; - private boolean mScrambleImageDisplay; - private boolean mLateStartPenalty; - private final Runnable mInspectionRunnable = new Runnable() { + private final Runnable inspectionRunnable = new Runnable() { @Override public void run() { String[] array = Utils.timeStringsFromNsSplitByDecimal @@ -163,6 +144,8 @@ public void run() { stopHoldTimer(); stopInspection(); + playEnterAnimations(); + Solve s = new Solve(mRetainedFragment .getCurrentScrambleAndSvg(), 0); s.setPenalty(Solve.Penalty.DNF); @@ -191,32 +174,18 @@ public void run() { mUiHandler.postDelayed(this, REFRESH_RATE); } }; - private boolean mBldMode; - private final PuzzleType.Observer puzzleTypeObserver = new PuzzleType - .Observer() { + private final Runnable holdTimerRunnable = new Runnable() { @Override - public void onPuzzleTypeChanged() { - //Update quick stats and hlistview - onSessionSolvesChanged(); - - //Set timer text to ready, scramble text to scrambling - mScrambleText.setText(R.string.scrambling); - - //Update options menu (disable) - enableMenuItems(false); - showScrambleImage(false); - - mBldMode = PuzzleType.getCurrent().name().contains("BLD"); - - resetGenerateScramble(); - - resetTimer(); - - PuzzleType.getCurrent().getSession(PuzzleType.CURRENT_SESSION) - .registerObserver(sessionObserver); + public void run() { + setTextColor(Color.GREEN); + setTimerTextToPrefSize(); + if (!mInspecting) { + playExitAnimations(); + getActivityCallback().lockDrawerAndViewPager(true); + } } }; - private final Runnable mTimerRunnable = new Runnable() { + private final Runnable timerRunnable = new Runnable() { @Override public void run() { if (mUpdateTimePref != PrefUtils.TimerUpdate.OFF) { @@ -238,6 +207,52 @@ public void run() { } }; + //Preferences + private boolean mHoldToStartEnabled; + private boolean mInspectionEnabled; + private boolean mTwoRowTimeEnabled; + private PrefUtils.TimerUpdate mUpdateTimePref; + private boolean mMillisecondsEnabled; + private boolean mMonospaceScrambleFontEnabled; + private int mPrefSize; + private boolean mKeepScreenOn; + private boolean mSignEnabled; + + //Retained Fragment + private CurrentSessionTimerRetainedFragment mRetainedFragment; + + //Views + private TextView mTimerText; + private TextView mTimerText2; + private TextView mScrambleText; + private RecyclerView mTimeBarRecycler; + private ImageView mScrambleImage; + private TextView mStatsSolvesText; + private TextView mStatsText; + private LinearLayout mLastBarLinearLayout; + private Button mLastDnfButton; + private Button mLastPlusTwoButton; + private Button mLastDeleteButton; + private FrameLayout mDynamicStatusBarFrame; + private TextView mDynamicStatusBarText; + + //Handler + private Handler mUiHandler; + + //Dynamic status variables + private boolean mHoldTiming; + private long mHoldTimerStartTimestamp; + private boolean mInspecting; + private long mInspectionStartTimestamp; + private long mInspectionStopTimestamp; + private long mTimingStartTimestamp; + private boolean mFromSavedInstanceState; + private boolean mTiming; + private boolean mScrambleImageDisplay; + private boolean mLateStartPenalty; + private boolean mBldMode; + private AnimatorSet mLastBarAnimationSet; + //Generate string with specified current averages and mean of current // session private String buildStatsWithAveragesOf(Context context, @@ -270,7 +285,7 @@ private String buildStatsWithAveragesOf(Context context, * * @param array An array of 2 strings */ - public void setTimerText(String[] array) { + void setTimerText(String[] array) { if (mTwoRowTimeEnabled) { mTimerText.setText(array[0]); mTimerText2.setText(array[1]); @@ -288,42 +303,63 @@ public void setTimerText(String[] array) { } } - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putBoolean(STATE_IMAGE_DISPLAYED, mScrambleImageDisplay); - outState.putLong(STATE_START_TIME, mTimingStartTimestamp); - outState.putBoolean(STATE_RUNNING, mTiming); - outState.putBoolean(STATE_INSPECTING, mInspecting); - outState.putLong(STATE_INSPECTION_START_TIME, - mInspectionStartTimestamp); - } - //Set scramble text and scramble image to current ones public void setScrambleTextAndImageToCurrent() { - if (mRetainedFragment.getCurrentScrambleAndSvg() != null) { + ScrambleAndSvg currentScrambleAndSvg = mRetainedFragment.getCurrentScrambleAndSvg(); + if (currentScrambleAndSvg != null) { SVG svg = null; try { - svg = SVG.getFromString(mRetainedFragment - .getCurrentScrambleAndSvg().getSvg()); + svg = SVG.getFromString(currentScrambleAndSvg.getSvg()); } catch (SVGParseException e) { e.printStackTrace(); } - Drawable drawable = new PictureDrawable(svg.renderToPicture()); + Drawable drawable = null; + if (svg != null) { + drawable = new PictureDrawable(svg.renderToPicture()); + } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { mScrambleImage.setLayerType(View.LAYER_TYPE_SOFTWARE, null); } mScrambleImage.setImageDrawable(drawable); - mScrambleText.setText(mRetainedFragment.getCurrentScrambleAndSvg - ().getUiScramble(mSignEnabled, PuzzleType.getCurrent() - .name())); + mScrambleText.setText(ErrorUtils.getUiScramble(getActivity(), -1, currentScrambleAndSvg, mSignEnabled, + PuzzleType.getCurrent().name())); } else { mRetainedFragment.generateNextScramble(); mRetainedFragment.postSetScrambleViewsToCurrent(); } } + void onSessionSolvesChanged() { + updateStatsAndTimer(); + + //Update RecyclerView + SolveRecyclerAdapter adapter = (SolveRecyclerAdapter) mTimeBarRecycler.getAdapter(); + adapter.updateSolvesList(-1, ObservedMode.UPDATE_ALL); + } + + private void updateStatsAndTimer() { + //Update stats + mStatsSolvesText.setText(getString(R.string.solves) + PuzzleType + .getCurrent().getSession(PuzzleType.CURRENT_SESSION) + .getNumberOfSolves()); + mStatsText.setText(buildStatsWithAveragesOf(getActivity(), 5, 12, 100)); + + if (!mTiming && !mInspecting) setTimerTextToLastSolveTime(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + //Toggle image button + case R.id.menu_activity_current_session_scramble_image_menuitem: + toggleScrambleImage(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -356,45 +392,155 @@ public void onCreate(Bundle savedInstanceState) { } @Override - public void onDestroy() { - super.onDestroy(); - //When destroyed, stop timer runnable - mUiHandler.removeCallbacksAndMessages(null); - mRetainedFragment.setTargetFragment(null, 0); + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_current_session_timer, + container, false); - PuzzleType.getCurrent().getSession(PuzzleType.CURRENT_SESSION) - .unregisterObserver(sessionObserver); - PuzzleType.unregisterObserver(puzzleTypeObserver); - } + mTimerText = (TextView) v.findViewById(R.id + .fragment_current_session_timer_time_textview); + mTimerText2 = (TextView) v.findViewById(R.id + .fragment_current_session_timer_timeSecondary_textview); + mScrambleText = (TextView) v.findViewById(R.id + .fragment_current_session_timer_scramble_textview); + mScrambleImage = (ImageView) v.findViewById(R.id + .fragment_current_session_timer_scramble_imageview); + mTimeBarRecycler = (RecyclerView) v.findViewById(R.id + .fragment_current_session_timer_timebar_recycler); - public void onSessionSolvesChanged() { - updateStatsAndTimer(); + mStatsText = (TextView) v.findViewById(R.id + .fragment_current_session_timer_stats_textview); + mStatsSolvesText = (TextView) v.findViewById(R.id + .fragment_current_session_timer_stats_solves_number_textview); - //Update RecyclerView - SolveRecyclerAdapter adapter = (SolveRecyclerAdapter) mTimeBarRecycler.getAdapter(); - adapter.updateSolvesList(-1, ObservedMode.UPDATE_ALL); - } + mLastBarLinearLayout = (LinearLayout) v.findViewById(R.id + .fragment_current_session_timer_last_linearlayout); + mLastDnfButton = (Button) v.findViewById(R.id + .fragment_current_session_timer_last_dnf_button); + mLastPlusTwoButton = (Button) v.findViewById(R.id + .fragment_current_session_timer_last_plustwo_button); + mLastDeleteButton = (Button) v.findViewById(R.id + .fragment_current_session_timer_last_delete_button); - private void updateStatsAndTimer() { - //Update stats - mStatsSolvesText.setText(getString(R.string.solves) + PuzzleType - .getCurrent().getSession(PuzzleType.CURRENT_SESSION) - .getNumberOfSolves()); - mStatsText.setText(buildStatsWithAveragesOf(getActivity(), 5, 12, 100)); + mLastDnfButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Session currentSession = PuzzleType.getCurrent().getSession(PuzzleType.CURRENT_SESSION); + if (ErrorUtils.isSolveNonexistent(getActivity(), PuzzleType.getCurrent().name(), + currentSession.getNumberOfSolves() - 1, PuzzleType.CURRENT_SESSION)) { + return; + } + currentSession.getLastSolve().setPenalty(Solve + .Penalty.DNF); + playLastBarExitAnimation(); + } + }); - if (!mTiming && !mInspecting) setTimerTextToLastSolveTime(); - } + mLastPlusTwoButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Session currentSession = PuzzleType.getCurrent().getSession(PuzzleType.CURRENT_SESSION); + if (ErrorUtils.isSolveNonexistent(getActivity(), PuzzleType.getCurrent().name(), + currentSession.getNumberOfSolves() - 1, PuzzleType.CURRENT_SESSION)) { + return; + } + currentSession.getLastSolve().setPenalty(Solve + .Penalty.PLUSTWO); + playLastBarExitAnimation(); + } + }); - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - //Toggle image button - case R.id.menu_activity_current_session_scramble_image_menuitem: - toggleScrambleImage(); - return true; - default: - return super.onOptionsItemSelected(item); + mLastDeleteButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Session currentSession = PuzzleType.getCurrent().getSession(PuzzleType.CURRENT_SESSION); + if (ErrorUtils.isSolveNonexistent(getActivity(), PuzzleType.getCurrent().name(), + currentSession.getNumberOfSolves() - 1, PuzzleType.CURRENT_SESSION)) { + return; + } + currentSession.deleteSolve(currentSession.getLastSolve()); + playLastBarExitAnimation(); + } + }); + + LinearLayoutManager timeBarLayoutManager = new LinearLayoutManager(getActivity(), + LinearLayoutManager.HORIZONTAL, false); + mTimeBarRecycler.setLayoutManager(timeBarLayoutManager); + mTimeBarRecycler.setHasFixedSize(true); + mTimeBarRecycler.setAdapter(new SolveRecyclerAdapter()); + + mDynamicStatusBarFrame = (FrameLayout) v.findViewById(R.id.fragment_current_session_timer_dynamic_status_frame); + mDynamicStatusBarText = (TextView) v.findViewById(R.id.fragment_current_session_timer_dynamic_status_text); + + mRetainedFragment = getActivityCallback().getTimerRetainedFragment(); + mRetainedFragment.setTargetFragment(this, 0); + + //When the root view is touched... + v.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: { + return onTimerTouchDown(); + } + case MotionEvent.ACTION_UP: { + onTimerTouchUp(); + return false; + } + default: + return false; + } + } + }); + + if (!mFromSavedInstanceState) { + //When the fragment is initializing, disable action bar and + // generate a scramble. + mRetainedFragment.resetScramblerThread(); + enableMenuItems(false); + mScrambleText.setText(R.string.scrambling); + mRetainedFragment.generateNextScramble(); + mRetainedFragment.postSetScrambleViewsToCurrent(); + } else { + if (mInspecting) { + mUiHandler.post(inspectionRunnable); + } + if (mTiming) { + mUiHandler.post(timerRunnable); + } + if (mTiming || mInspecting) { + enableMenuItems(false); + } else if (!mRetainedFragment.isScrambling()) { + enableMenuItems(true); + } + if (mInspecting || mTiming || !mRetainedFragment.isScrambling()) { + // If timer is timing/inspecting, then update text/image to + // current. If timer is + // not timing/inspecting and not scrambling, + // then update scramble views to current. + setScrambleTextAndImageToCurrent(); + } else { + mScrambleText.setText(R.string.scrambling); + } } + + //If the scramble image is currently displayed and it is not scrambling, + // then make sure it is set to visible; otherwise, set to gone. + showScrambleImage(mScrambleImageDisplay && !mRetainedFragment + .isScrambling()); + + mScrambleImage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + toggleScrambleImage(); + } + }); + + mBldMode = PuzzleType.getCurrent().name().contains("BLD"); + + onSessionSolvesChanged(); + + return v; } @Override @@ -419,7 +565,38 @@ public void onResume() { onSessionSolvesChanged(); } - public void initSharedPrefs() { + @Override + public void onPause() { + super.onPause(); + getActivity().getWindow().clearFlags(WindowManager.LayoutParams + .FLAG_KEEP_SCREEN_ON); + PuzzleType.getCurrent().saveCurrentSession(getActivity()); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(STATE_IMAGE_DISPLAYED, mScrambleImageDisplay); + outState.putLong(STATE_START_TIME, mTimingStartTimestamp); + outState.putBoolean(STATE_RUNNING, mTiming); + outState.putBoolean(STATE_INSPECTING, mInspecting); + outState.putLong(STATE_INSPECTION_START_TIME, + mInspectionStartTimestamp); + } + + @Override + public void onDestroy() { + super.onDestroy(); + //When destroyed, stop timer runnable + mUiHandler.removeCallbacksAndMessages(null); + mRetainedFragment.setTargetFragment(null, 0); + + PuzzleType.getCurrent().getSession(PuzzleType.CURRENT_SESSION) + .unregisterObserver(sessionObserver); + PuzzleType.unregisterObserver(puzzleTypeObserver); + } + + void initSharedPrefs() { mInspectionEnabled = PrefUtils.isInspectionEnabled(getActivity()); mHoldToStartEnabled = PrefUtils.isHoldToStartEnabled(getActivity()); mTwoRowTimeEnabled = @@ -433,7 +610,7 @@ public void initSharedPrefs() { mMonospaceScrambleFontEnabled = PrefUtils.isMonospaceScrambleFontEnabled(getActivity()); } - public void setTimerTextToPrefSize() { + void setTimerTextToPrefSize() { if (mTimerText.getText() != getString(R.string.ready)) { if (mTimerText != null && mTimerText2 != null) { if (mTwoRowTimeEnabled) { @@ -449,7 +626,7 @@ public void setTimerTextToPrefSize() { } } - public void showScrambleImage(boolean enable) { + void showScrambleImage(boolean enable) { if (enable) { mScrambleImage.setVisibility(View.VISIBLE); } else { @@ -458,25 +635,6 @@ public void showScrambleImage(boolean enable) { mScrambleImageDisplay = enable; } - public void resetGenerateScramble() { - mRetainedFragment.resetScramblerThread(); - mRetainedFragment.generateNextScramble(); - mRetainedFragment.postSetScrambleViewsToCurrent(); - } - - public void resetTimer() { - mUiHandler.removeCallbacksAndMessages(null); - mHoldTiming = false; - mTiming = false; - mLateStartPenalty = false; - mHoldTimerStartTimestamp = 0; - mInspectionStartTimestamp = 0; - mTimingStartTimestamp = 0; - mInspecting = false; - setTextColorPrimary(); - playDynamicStatusBarExitAnimation(); - } - private void setTextColorPrimary() { int[] textColorAttr = new int[]{android.R.attr.textColor}; TypedArray a = getActivity().obtainStyledAttributes(new TypedValue().data, textColorAttr); @@ -485,11 +643,28 @@ private void setTextColorPrimary() { setTextColor(color); } - public void setTextColor(int color) { + void setTextColor(int color) { mTimerText.setTextColor(color); mTimerText2.setTextColor(color); } + /** + * Sets the timer text to last solve's time; if there are no solves, + * set to ready. Updates the timer text's size. + */ + void setTimerTextToLastSolveTime() { + if (PuzzleType.getCurrent().getSession(PuzzleType.CURRENT_SESSION) + .getNumberOfSolves() != 0) { + setTimerText(PuzzleType.getCurrent().getSession(PuzzleType + .CURRENT_SESSION) + .getLastSolve().getTimeStringArray(mMillisecondsEnabled)); + } else { + setTimerText(new String[]{getString(R.string.ready), ""}); + mTimerText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 100); + } + setTimerTextToPrefSize(); + } + public void enableMenuItems(boolean enable) { ActivityCallback callback = getActivityCallback(); callback.enableMenuItems(enable); @@ -507,7 +682,7 @@ private ActivityCallback getActivityCallback() { return callback; } - public void toggleScrambleImage() { + void toggleScrambleImage() { if (mScrambleImageDisplay) { mScrambleImageDisplay = false; mScrambleImage.setVisibility(View.GONE); @@ -526,256 +701,210 @@ public void onClick(View v) { } } - @Override - public void onPause() { - super.onPause(); - getActivity().getWindow().clearFlags(WindowManager.LayoutParams - .FLAG_KEEP_SCREEN_ON); - PuzzleType.getCurrent().saveCurrentSession(getActivity()); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.fragment_current_session_timer, - container, false); + /** + * @return whether {@link com.pluscubed.plustimer.ui.CurrentSessionTimerFragment#onTimerTouchUp()} + * will be triggered when touch is released + */ + private boolean onTimerTouchDown() { + boolean scrambling = mRetainedFragment.isScrambling(); + + //Currently Timing: User stopping timer + if (mTiming) { + Solve s; + if (!mBldMode) { + s = new Solve(mRetainedFragment + .getCurrentScrambleAndSvg(), + System.nanoTime() - mTimingStartTimestamp); + } else { + s = new BldSolve(mRetainedFragment.getCurrentScrambleAndSvg(), + System.nanoTime() - mTimingStartTimestamp, + mInspectionStopTimestamp - mInspectionStartTimestamp); + } - mTimerText = (TextView) v.findViewById(R.id - .fragment_current_session_timer_time_textview); - mTimerText2 = (TextView) v.findViewById(R.id - .fragment_current_session_timer_timeSecondary_textview); - mScrambleText = (TextView) v.findViewById(R.id - .fragment_current_session_timer_scramble_textview); - mScrambleImage = (ImageView) v.findViewById(R.id - .fragment_current_session_timer_scramble_imageview); - mTimeBarRecycler = (RecyclerView) v.findViewById(R.id - .fragment_current_session_timer_timebar_recycler); + if (mInspectionEnabled && mLateStartPenalty) { + s.setPenalty(Solve.Penalty.PLUSTWO); + } + //Add the solve to the current session with the + // current scramble/scramble image and time + PuzzleType.getCurrent().getSession(PuzzleType + .CURRENT_SESSION).addSolve(s); + playLastBarEnterAnimation(); + playDynamicStatusBarExitAnimation(); + playEnterAnimations(); + getActivityCallback().lockDrawerAndViewPager(false); - mStatsText = (TextView) v.findViewById(R.id - .fragment_current_session_timer_stats_textview); - mStatsSolvesText = (TextView) v.findViewById(R.id - .fragment_current_session_timer_stats_solves_number_textview); + resetTimer(); - mLastBarLinearLayout = (LinearLayout) v.findViewById(R.id - .fragment_current_session_timer_last_linearlayout); - mLastDnfButton = (Button) v.findViewById(R.id - .fragment_current_session_timer_last_dnf_button); - mLastPlusTwoButton = (Button) v.findViewById(R.id - .fragment_current_session_timer_last_plustwo_button); - mLastDeleteButton = (Button) v.findViewById(R.id - .fragment_current_session_timer_last_delete_button); + setTimerTextToLastSolveTime(); - mLastDnfButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - PuzzleType.getCurrent().getSession(PuzzleType - .CURRENT_SESSION).getLastSolve().setPenalty(Solve - .Penalty.DNF); - playLastBarExitAnimation(); - } - }); - mLastPlusTwoButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - PuzzleType.getCurrent().getSession(PuzzleType - .CURRENT_SESSION).getLastSolve().setPenalty(Solve - .Penalty.PLUSTWO); - playLastBarExitAnimation(); + if (scrambling) { + mScrambleText.setText(R.string.scrambling); } - }); - mLastDeleteButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Session session = PuzzleType.getCurrent().getSession(PuzzleType.CURRENT_SESSION); - session.deleteSolve(session.getLastSolve()); - playLastBarExitAnimation(); - } - }); + mRetainedFragment.postSetScrambleViewsToCurrent(); + return false; + } - LinearLayoutManager timeBarLayoutManager = new LinearLayoutManager(getActivity(), - LinearLayoutManager.HORIZONTAL, false); - mTimeBarRecycler.setLayoutManager(timeBarLayoutManager); - mTimeBarRecycler.setHasFixedSize(true); - mTimeBarRecycler.setAdapter(new SolveRecyclerAdapter()); + if (mBldMode) { + return onTimerBldTouchDown(scrambling); + } - mDynamicStatusBarFrame = (FrameLayout) v.findViewById(R.id.fragment_current_session_timer_dynamic_status_frame); - mDynamicStatusBarText = (TextView) v.findViewById(R.id.fragment_current_session_timer_dynamic_status_text); + if (mHoldToStartEnabled && + ((!mInspectionEnabled && !scrambling) || mInspecting)) { + //If hold to start is on, start the hold timer + //If inspection is enabled, only start hold timer when inspecting + //Go to section 2 + startHoldTimer(); + return true; + } else if (mInspecting) { + //If inspecting and hold to start is off, start regular timer + //Go to section 3 + setTextColor(Color.GREEN); + return true; + } - mRetainedFragment = getActivityCallback().getTimerRetainedFragment(); - mRetainedFragment.setTargetFragment(this, 0); + //If inspection is on and haven't started yet: section 1 + //If hold to start and inspection are both off: section 3 + if (!scrambling) { + setTextColor(Color.GREEN); + return true; + } + return false; + } - //When the root view is touched... - v.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: { - boolean scrambling = mRetainedFragment.isScrambling(); - if (mTiming) { - //If we're timing and user stopped - - Solve s; - if (!mBldMode) { - s = new Solve(mRetainedFragment - .getCurrentScrambleAndSvg(), - System.nanoTime() - mTimingStartTimestamp); - } else { - s = new BldSolve(mRetainedFragment.getCurrentScrambleAndSvg(), - System.nanoTime() - mTimingStartTimestamp, - mInspectionStopTimestamp - mInspectionStartTimestamp); - } - - if (mInspectionEnabled && mLateStartPenalty) { - s.setPenalty(Solve.Penalty.PLUSTWO); - } - //Add the solve to the current session with the - // current scramble/scramble image and time - PuzzleType.getCurrent().getSession(PuzzleType - .CURRENT_SESSION).addSolve(s); - playLastBarEnterAnimation(); - playDynamicStatusBarExitAnimation(); - - resetTimer(); - - setTimerTextToLastSolveTime(); - - //Update stats and HListView - - if (scrambling) { - mScrambleText.setText(R.string.scrambling); - } - - mRetainedFragment.postSetScrambleViewsToCurrent(); - return false; - } - if (!mBldMode && mHoldToStartEnabled && - ((!mInspectionEnabled && !scrambling) || mInspecting)) { - //If hold to start is on and/or inspecting, start the hold timer - startHoldTimer(); - return true; - } else if (mInspecting) { - //If inspecting and hold to start is off, start regular timer - //BLD inspecting as well - return true; - } - return !scrambling; - } + private boolean onTimerBldTouchDown(boolean scrambling) { + //If inspecting: section 3 + //If not inspecting yet and not scrambling: section 1 + setTextColor(Color.GREEN); + return mInspecting || !scrambling; + } - case MotionEvent.ACTION_UP: { - if ((mInspectionEnabled || mBldMode) && !mInspecting) { - //If inspection is on (or BLD) and not inspecting - startInspection(); - } else if (!mBldMode && mHoldToStartEnabled) { - //Hold to start is on (may be inspecting) - if (mHoldTiming && - (System.nanoTime() - mHoldTimerStartTimestamp >= - HOLD_TIME)) { - stopInspection(); - stopHoldTimer(); - //User held long enough for timer to turn - // green and lifted: start timing - startTiming(); - if (!mBldMode && !mInspectionEnabled) { - //If hold timer was started but not in - // inspection, generate next scramble - mRetainedFragment.generateNextScramble(); - } - } else { - //User started hold timer but lifted before - // the timer is green - stopHoldTimer(); - } - } else { - //Hold to start is off, start timing - if (mInspecting) { - stopInspection(); - } - startTiming(); - if (!mBldMode) { - mRetainedFragment.generateNextScramble(); - } - } - return false; - } - default: - return false; + private void onTimerTouchUp() { + if ((mInspectionEnabled || mBldMode) && !mInspecting) { + //Section 1 + //If inspection is on (or BLD) and not inspecting + startInspection(); + playExitAnimations(); + } else if (!mBldMode && mHoldToStartEnabled) { + //Section 2 + //Hold to start is on (may be inspecting) + if (mHoldTiming && + (System.nanoTime() - mHoldTimerStartTimestamp >= + HOLD_TIME)) { + //User held long enough for timer to turn + // green and lifted: start timing + stopInspection(); + stopHoldTimer(); + startTiming(); + if (!mBldMode && !mInspectionEnabled) { + //If hold timer was started but not in + // inspection, generate next scramble + mRetainedFragment.generateNextScramble(); } + } else { + //User started hold timer but lifted before + // the timer is green: stop hold timer + stopHoldTimer(); } - }); - - if (!mFromSavedInstanceState) { - //When the fragment is initializing, disable action bar and - // generate a scramble. - mRetainedFragment.resetScramblerThread(); - enableMenuItems(false); - mScrambleText.setText(R.string.scrambling); - mRetainedFragment.generateNextScramble(); - mRetainedFragment.postSetScrambleViewsToCurrent(); } else { + //Section 3 + //Hold to start is off, start timing if (mInspecting) { - mUiHandler.post(mInspectionRunnable); - } - if (mTiming) { - mUiHandler.post(mTimerRunnable); - } - if (mTiming || mInspecting) { - enableMenuItems(false); - } else if (!mRetainedFragment.isScrambling()) { - enableMenuItems(true); - } - if (mInspecting || mTiming || !mRetainedFragment.isScrambling()) { - // If timer is timing/inspecting, then update text/image to - // current. If timer is - // not timing/inspecting and not scrambling, - // then update scramble views to current. - setScrambleTextAndImageToCurrent(); + stopInspection(); } else { - mScrambleText.setText(R.string.scrambling); + playExitAnimations(); + } + startTiming(); + if (!mBldMode) { + mRetainedFragment.generateNextScramble(); } } + } - //If the scramble image is currently displayed and it is not scrambling, - // then make sure it is set to visible; otherwise, set to gone. - showScrambleImage(mScrambleImageDisplay && !mRetainedFragment - .isScrambling()); + void playDynamicStatusBarEnterAnimation() { + ObjectAnimator enter = ObjectAnimator.ofFloat(mDynamicStatusBarFrame, View.TRANSLATION_Y, 0f); + enter.setDuration(125); + enter.setInterpolator(new DecelerateInterpolator()); + AnimatorSet dynamicStatusBarAnimatorSet = new AnimatorSet(); + dynamicStatusBarAnimatorSet.play(enter); + dynamicStatusBarAnimatorSet.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } - mScrambleImage.setOnClickListener(new View.OnClickListener() { @Override - public void onClick(View v) { - toggleScrambleImage(); + public void onAnimationEnd(Animator animation) { + for (int i = 0; i < mTimeBarRecycler.getChildCount(); i++) { + mTimeBarRecycler.getChildAt(i).setEnabled(false); + } } - }); - mBldMode = PuzzleType.getCurrent().name().contains("BLD"); + @Override + public void onAnimationCancel(Animator animation) { - onSessionSolvesChanged(); + } - return v; - } + @Override + public void onAnimationRepeat(Animator animation) { - public void playDynamicStatusBarEnterAnimation() { - ObjectAnimator enter = ObjectAnimator.ofFloat(mDynamicStatusBarFrame, View.TRANSLATION_Y, 0f); - enter.setDuration(125); - enter.setInterpolator(new DecelerateInterpolator()); - AnimatorSet dynamicStatusBarAnimatorSet = new AnimatorSet(); - dynamicStatusBarAnimatorSet.play(enter); + } + }); dynamicStatusBarAnimatorSet.start(); } - public void playDynamicStatusBarExitAnimation() { + void playDynamicStatusBarExitAnimation() { ObjectAnimator exit = ObjectAnimator.ofFloat(mDynamicStatusBarFrame, View.TRANSLATION_Y, mDynamicStatusBarFrame.getHeight()); exit.setDuration(125); exit.setInterpolator(new AccelerateInterpolator()); AnimatorSet dynamicStatusBarAnimatorSet = new AnimatorSet(); dynamicStatusBarAnimatorSet.play(exit); + dynamicStatusBarAnimatorSet.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + for (int i = 0; i < mTimeBarRecycler.getChildCount(); i++) { + mTimeBarRecycler.getChildAt(i).setEnabled(true); + } + } + + @Override + public void onAnimationEnd(Animator animation) { + + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); dynamicStatusBarAnimatorSet.start(); + } + + private void playExitAnimations() { + Utils.lockOrientation(getActivity()); + playScrambleExitAnimation(); + playStatsExitAnimation(); + getActivityCallback().playToolbarExitAnimation(); + } + public void playEnterAnimations() { + Utils.unlockOrientation(getActivity()); + playScrambleEnterAnimation(); + playStatsEnterAnimation(); + getActivityCallback().playToolbarEnterAnimation(); } private void playLastBarEnterAnimation() { + if (mLastBarAnimationSet != null) { + mLastBarAnimationSet.cancel(); + } mLastDeleteButton.setEnabled(true); mLastDnfButton.setEnabled(true); mLastPlusTwoButton.setEnabled(true); @@ -786,12 +915,12 @@ private void playLastBarEnterAnimation() { exit.setStartDelay(1500); enter.setInterpolator(new DecelerateInterpolator()); exit.setInterpolator(new AccelerateInterpolator()); - AnimatorSet lastBarAnimationSet = new AnimatorSet(); - lastBarAnimationSet.playSequentially(enter, exit); - lastBarAnimationSet.start(); + mLastBarAnimationSet = new AnimatorSet(); + mLastBarAnimationSet.playSequentially(enter, exit); + mLastBarAnimationSet.start(); } - public void playLastBarExitAnimation() { + void playLastBarExitAnimation() { mLastDeleteButton.setEnabled(false); mLastDnfButton.setEnabled(false); mLastPlusTwoButton.setEnabled(false); @@ -803,76 +932,124 @@ public void playLastBarExitAnimation() { lastBarAnimationSet.start(); } - public void startHoldTimer() { + void playScrambleExitAnimation() { + ObjectAnimator exit = ObjectAnimator.ofFloat(mScrambleText, View.ALPHA, 0f); + exit.setDuration(300); + ObjectAnimator exit2 = ObjectAnimator.ofFloat(mScrambleText, View.TRANSLATION_Y, -Utils.convertDpToPx(getActivity(), 24)); + exit2.setDuration(300); + exit2.setInterpolator(new AccelerateInterpolator()); + AnimatorSet scrambleAnimatorSet = new AnimatorSet(); + scrambleAnimatorSet.play(exit).with(exit2); + scrambleAnimatorSet.start(); + } + + void playScrambleEnterAnimation() { + ObjectAnimator enter = ObjectAnimator.ofFloat(mScrambleText, View.ALPHA, 1f); + enter.setDuration(300); + ObjectAnimator enter2 = ObjectAnimator.ofFloat(mScrambleText, View.TRANSLATION_Y, 0f); + enter2.setDuration(300); + enter2.setInterpolator(new DecelerateInterpolator()); + AnimatorSet scrambleAnimatorSet = new AnimatorSet(); + scrambleAnimatorSet.play(enter).with(enter2); + scrambleAnimatorSet.start(); + } + + void playStatsExitAnimation() { + ObjectAnimator exit = ObjectAnimator.ofFloat(mStatsText, View.ALPHA, 0f); + exit.setDuration(300); + ObjectAnimator exit3 = ObjectAnimator.ofFloat(mStatsSolvesText, View.ALPHA, 0f); + exit3.setDuration(300); + AnimatorSet scrambleAnimatorSet = new AnimatorSet(); + scrambleAnimatorSet.play(exit).with(exit3); + scrambleAnimatorSet.start(); + } + + void playStatsEnterAnimation() { + ObjectAnimator enter = ObjectAnimator.ofFloat(mStatsText, View.ALPHA, 1f); + enter.setDuration(300); + ObjectAnimator enter3 = ObjectAnimator.ofFloat(mStatsSolvesText, View.ALPHA, 1f); + enter3.setDuration(300); + AnimatorSet scrambleAnimatorSet = new AnimatorSet(); + scrambleAnimatorSet.play(enter).with(enter3); + scrambleAnimatorSet.start(); + } + + void startHoldTimer() { playLastBarExitAnimation(); mHoldTiming = true; mHoldTimerStartTimestamp = System.nanoTime(); setTextColor(Color.RED); - mUiHandler.postDelayed(mHoldTimerRunnable, 550); + mUiHandler.postDelayed(holdTimerRunnable, 550); } public void stopHoldTimer() { mHoldTiming = false; mHoldTimerStartTimestamp = 0; - mUiHandler.removeCallbacks(mHoldTimerRunnable); + mUiHandler.removeCallbacks(holdTimerRunnable); setTextColorPrimary(); } /** * Start inspection; Start Generating Next Scramble */ - public void startInspection() { + void startInspection() { playLastBarExitAnimation(); - mDynamicStatusBarText.setText(R.string.inspecting); playDynamicStatusBarEnterAnimation(); + mDynamicStatusBarText.setText(R.string.inspecting); mInspectionStartTimestamp = System.nanoTime(); mInspecting = true; if (mBldMode) { - mUiHandler.post(mTimerRunnable); + mUiHandler.post(timerRunnable); } else { - mUiHandler.post(mInspectionRunnable); + mUiHandler.post(inspectionRunnable); } mRetainedFragment.generateNextScramble(); enableMenuItems(false); showScrambleImage(false); + getActivityCallback().lockDrawerAndViewPager(true); + setTextColorPrimary(); } - public void stopInspection() { + void stopInspection() { mInspectionStopTimestamp = System.nanoTime(); mInspecting = false; - mUiHandler.removeCallbacks(mInspectionRunnable); + mUiHandler.removeCallbacks(inspectionRunnable); } /** * Start timing; does not start generating next scramble */ - public void startTiming() { + void startTiming() { playLastBarExitAnimation(); playDynamicStatusBarEnterAnimation(); mTimingStartTimestamp = System.nanoTime(); mInspecting = false; mTiming = true; - if (!mBldMode) mUiHandler.post(mTimerRunnable); + if (!mBldMode) mUiHandler.post(timerRunnable); enableMenuItems(false); showScrambleImage(false); mDynamicStatusBarText.setText(R.string.timing); + getActivityCallback().lockDrawerAndViewPager(true); + setTextColorPrimary(); } - /** - * Sets the timer text to last solve's time; if there are no solves, - * set to ready. Updates the timer text's size. - */ - public void setTimerTextToLastSolveTime() { - if (PuzzleType.getCurrent().getSession(PuzzleType.CURRENT_SESSION) - .getNumberOfSolves() != 0) { - setTimerText(PuzzleType.getCurrent().getSession(PuzzleType - .CURRENT_SESSION) - .getLastSolve().getTimeStringArray(mMillisecondsEnabled)); - } else { - setTimerText(new String[]{getString(R.string.ready), ""}); - mTimerText.setTextSize(TypedValue.COMPLEX_UNIT_SP, 100); - } - setTimerTextToPrefSize(); + void resetGenerateScramble() { + mRetainedFragment.resetScramblerThread(); + mRetainedFragment.generateNextScramble(); + mRetainedFragment.postSetScrambleViewsToCurrent(); + } + + void resetTimer() { + mUiHandler.removeCallbacksAndMessages(null); + mHoldTiming = false; + mTiming = false; + mLateStartPenalty = false; + mHoldTimerStartTimestamp = 0; + mInspectionStartTimestamp = 0; + mTimingStartTimestamp = 0; + mInspecting = false; + setTextColorPrimary(); + playDynamicStatusBarExitAnimation(); } public Handler getUiHandler() { @@ -884,7 +1061,11 @@ public enum ObservedMode { } public interface ActivityCallback { - Toolbar getActionBarToolbar(); + void lockDrawerAndViewPager(boolean lock); + + void playToolbarEnterAnimation(); + + void playToolbarExitAnimation(); CurrentSessionTimerRetainedFragment getTimerRetainedFragment(); @@ -974,15 +1155,8 @@ public ViewHolder(TextView v) { textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - try { - CreateDialogCallback callback = - (CreateDialogCallback) getActivity(); - callback.createSolveDisplayDialog(null, 0, getPosition()); - } catch (ClassCastException e) { - throw new ClassCastException(getActivity() - .toString() + " must implement " + - "CreateDialogCallback"); - } + SolveDialogUtils.createSolveDialog(getActivity(), false, PuzzleType.getCurrent().name(), + PuzzleType.CURRENT_SESSION, getPosition()); } }); } diff --git a/app/src/main/java/com/pluscubed/plustimer/ui/DrawerActivity.java b/app/src/main/java/com/pluscubed/plustimer/ui/DrawerActivity.java index e884c0e..a2e1e2c 100644 --- a/app/src/main/java/com/pluscubed/plustimer/ui/DrawerActivity.java +++ b/app/src/main/java/com/pluscubed/plustimer/ui/DrawerActivity.java @@ -25,13 +25,13 @@ */ public abstract class DrawerActivity extends ThemableActivity { - protected static final int NAVDRAWER_ITEM_CURRENT_SESSION = 0; - protected static final int NAVDRAWER_ITEM_HISTORY = 1; - protected static final int NAVDRAWER_ITEM_SETTINGS = -3; - protected static final int NAVDRAWER_ITEM_HELP = -4; - protected static final int NAVDRAWER_ITEM_ABOUT = -5; - protected static final int NAVDRAWER_ITEM_INVALID = -1; - protected static final int NAVDRAWER_ITEM_SEPARATOR = -2; + static final int NAVDRAWER_ITEM_CURRENT_SESSION = 0; + static final int NAVDRAWER_ITEM_HISTORY = 1; + private static final int NAVDRAWER_ITEM_SETTINGS = -3; + private static final int NAVDRAWER_ITEM_HELP = -4; + private static final int NAVDRAWER_ITEM_ABOUT = -5; + private static final int NAVDRAWER_ITEM_INVALID = -1; + private static final int NAVDRAWER_ITEM_SEPARATOR = -2; private static final int[] NAVDRAWER_ITEMS = new int[]{ NAVDRAWER_ITEM_CURRENT_SESSION, NAVDRAWER_ITEM_HISTORY, @@ -56,8 +56,6 @@ public abstract class DrawerActivity extends ThemableActivity { R.string.history }; private DrawerLayout mDrawerLayout; - private ScrollView mDrawerScrollView; - private LinearLayout mDrawerListLinearLayout; private Handler mHandler; private Toolbar mActionBarToolbar; @@ -67,14 +65,14 @@ public abstract class DrawerActivity extends ThemableActivity { * Subclasses of BaseActivity override this to indicate what nav drawer item * corresponds to them. */ - protected int getSelfNavDrawerItem() { + int getSelfNavDrawerItem() { return NAVDRAWER_ITEM_INVALID; } - protected void onNavDrawerSlide(float offset) { + void onNavDrawerSlide(float offset) { } - protected void onNavDrawerClosed() { + void onNavDrawerClosed() { } @Override @@ -82,7 +80,7 @@ protected boolean hasNavDrawer() { return true; } - protected Toolbar getActionBarToolbar() { + Toolbar getActionBarToolbar() { if (mActionBarToolbar == null) { mActionBarToolbar = (Toolbar) findViewById(R.id.toolbar_actionbar); if (mActionBarToolbar != null) { @@ -135,7 +133,7 @@ public void onDrawerStateChanged(int newState) { } }); - mDrawerScrollView = (ScrollView) findViewById(R.id + ScrollView mDrawerScrollView = (ScrollView) findViewById(R.id .activity_drawer_drawer_scrollview); int actionBarSize = resources.getDimensionPixelSize(R.dimen .navigation_drawer_margin); @@ -149,18 +147,9 @@ public void onDrawerStateChanged(int newState) { params.width = navDrawerWidth; mDrawerScrollView.setLayoutParams(params); - mDrawerListLinearLayout = (LinearLayout) findViewById(R.id + LinearLayout mDrawerListLinearLayout = (LinearLayout) findViewById(R.id .activity_drawer_drawer_linearlayout); - mActionBarToolbar.setNavigationIcon(R.drawable.ic_drawer); - mActionBarToolbar.setNavigationOnClickListener(new View - .OnClickListener() { - @Override - public void onClick(View view) { - mDrawerLayout.openDrawer(Gravity.START); - } - }); - resetTitle(); if (!PrefUtils.isWelcomeDone(this)) { @@ -191,7 +180,7 @@ public void onClick(View v) { } } - protected void resetTitle() { + void resetTitle() { setTitle(NAVDRAWER_ACTIONBAR_TITLE_RES_ID[getSelfNavDrawerItem()]); ViewTreeObserver vto = findViewById(android.R.id.content).getViewTreeObserver(); vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @@ -210,6 +199,14 @@ public void onGlobalLayout() { }); } + void lockDrawer(boolean lock) { + if (lock) { + mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); + } else { + mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED); + } + } + @Override public void setContentView(int layoutResID) { super.setContentView(layoutResID); @@ -260,7 +257,7 @@ public void run() { goToNavDrawerItem(itemId); } }, NAVDRAWER_LAUNCH_DELAY); - if (!isSpecialItem(itemId)) { + if (isNormalItem(itemId)) { View mainContent = findViewById(R.id .activity_drawer_content_linearlayout); if (mainContent != null) { @@ -272,17 +269,17 @@ public void run() { mDrawerLayout.closeDrawer(Gravity.START); } - private boolean isSpecialItem(int itemId) { - return itemId == NAVDRAWER_ITEM_SETTINGS || itemId == - NAVDRAWER_ITEM_HELP || itemId == NAVDRAWER_ITEM_ABOUT; + private boolean isNormalItem(int itemId) { + return itemId != NAVDRAWER_ITEM_SETTINGS && itemId != + NAVDRAWER_ITEM_HELP && itemId != NAVDRAWER_ITEM_ABOUT; } - protected boolean isNavDrawerOpen() { + boolean isNavDrawerOpen() { return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(Gravity .START); } - protected void closeNavDrawer() { + void closeNavDrawer() { if (mDrawerLayout != null) { mDrawerLayout.closeDrawer(Gravity.START); } @@ -311,6 +308,6 @@ private void goToNavDrawerItem(int itemId) { startActivity(i); //If it is not a special item, finish this activity - if (!isSpecialItem(itemId)) finish(); + if (isNormalItem(itemId)) finish(); } } diff --git a/app/src/main/java/com/pluscubed/plustimer/ui/HistorySessionListFragment.java b/app/src/main/java/com/pluscubed/plustimer/ui/HistorySessionListFragment.java index e3f6260..2a84fba 100644 --- a/app/src/main/java/com/pluscubed/plustimer/ui/HistorySessionListFragment.java +++ b/app/src/main/java/com/pluscubed/plustimer/ui/HistorySessionListFragment.java @@ -36,7 +36,6 @@ import com.pluscubed.plustimer.utils.PrefUtils; import com.pluscubed.plustimer.utils.Utils; -import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -175,19 +174,15 @@ public String formatLabel(double value, boolean isValueX) { mGraph.setDataPointsRadius(Utils.convertDpToPx(getActivity(), 3)); headerView.addView(mGraph, 1); getListView().addHeaderView(headerView, null, false); - try { - setListAdapter(new SessionListAdapter()); - } catch (IOException e) { - e.printStackTrace(); - } + setListAdapter(new SessionListAdapter()); } - public void onSessionListChanged() { + void onSessionListChanged() { updateStats(); ((SessionListAdapter) getListAdapter()).onSessionListChanged(); } - public void updateStats() { + void updateStats() { PuzzleType.valueOf(mPuzzleTypeName).getHistorySessions().sort(); List historySessions = PuzzleType.valueOf(mPuzzleTypeName) .getHistorySessions().getList(); @@ -397,8 +392,8 @@ public void updateStats() { * @param sessions list of sessions * @return String with the best averages of [numbers] */ - public String getBestAverageOfNumberOfSessions(int[] numbers, - List sessions) { + String getBestAverageOfNumberOfSessions(int[] numbers, + List sessions) { StringBuilder builder = new StringBuilder(); for (int number : numbers) { ArrayList bestAverages = new ArrayList<>(); @@ -504,7 +499,7 @@ public void onListItemClick(ListView l, View v, int position, long id) { public class SessionListAdapter extends ArrayAdapter { - SessionListAdapter() throws IOException { + SessionListAdapter() { super(getActivity(), 0, new ArrayList()); onSessionListChanged(); } diff --git a/app/src/main/java/com/pluscubed/plustimer/ui/HistorySolveListActivity.java b/app/src/main/java/com/pluscubed/plustimer/ui/HistorySolveListActivity.java index 1153716..d2610ba 100644 --- a/app/src/main/java/com/pluscubed/plustimer/ui/HistorySolveListActivity.java +++ b/app/src/main/java/com/pluscubed/plustimer/ui/HistorySolveListActivity.java @@ -1,6 +1,5 @@ package com.pluscubed.plustimer.ui; -import android.app.DialogFragment; import android.app.Fragment; import android.app.FragmentManager; import android.os.Bundle; @@ -10,56 +9,21 @@ import com.pluscubed.plustimer.R; import com.pluscubed.plustimer.model.PuzzleType; -import com.pluscubed.plustimer.utils.Utils; /** * History SolveList (started onListItemClick HistorySessionListFragment) * activity */ -public class HistorySolveListActivity extends ThemableActivity - implements CreateDialogCallback { +public class HistorySolveListActivity extends ThemableActivity { public static final String EXTRA_HISTORY_SESSION_POSITION = "com" + ".pluscubed.plustimer.history_session_position"; public static final String EXTRA_HISTORY_PUZZLETYPE_DISPLAYNAME = "com" + ".pluscubed.plustimer.history_puzzletype_displayname"; - public static final String HISTORY_DIALOG_SOLVE_TAG = + private static final String HISTORY_DIALOG_SOLVE_TAG = "HISTORY_MODIFY_DIALOG"; - @Override - public void createSolveDisplayDialog(String puzzleTypeName, int sessionIndex, - int solveIndex) { - DialogFragment dialog = (DialogFragment) getFragmentManager() - .findFragmentByTag(HISTORY_DIALOG_SOLVE_TAG); - if (!Utils.assertSolveExists(this, solveIndex, sessionIndex)) { - return; - } - if (dialog == null) { - SolveDialogFragment d = SolveDialogFragment.newInstanceDisplay - (PuzzleType.valueOf(puzzleTypeName).toString(), - sessionIndex, solveIndex); - d.show(getFragmentManager(), HISTORY_DIALOG_SOLVE_TAG); - } - } - - @Override - public void createSolveAddDialog(String displayName, int sessionIndex) { - DialogFragment dialog = (DialogFragment) getFragmentManager() - .findFragmentByTag(HISTORY_DIALOG_SOLVE_TAG); - if (dialog == null) { - SolveDialogFragment d = SolveDialogFragment.newInstanceAdd - (PuzzleType.valueOf(displayName).toString(), - sessionIndex); - d.show(getFragmentManager(), HISTORY_DIALOG_SOLVE_TAG); - } - } - - private SolveListFragment getSolveListFragment() { - return (SolveListFragment) getFragmentManager().findFragmentById - (android.R.id.content); - } - @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_history_solvelist, menu); @@ -69,6 +33,7 @@ public boolean onCreateOptionsMenu(Menu menu) { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setContentView(R.layout.activity_with_toolbar); PuzzleType.initialize(this); int position = getIntent().getIntExtra @@ -76,7 +41,6 @@ protected void onCreate(Bundle savedInstanceState) { String puzzleType = getIntent().getStringExtra (EXTRA_HISTORY_PUZZLETYPE_DISPLAYNAME); - setContentView(R.layout.activity_with_toolbar); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_actionbar); setSupportActionBar(toolbar); diff --git a/app/src/main/java/com/pluscubed/plustimer/ui/SolveDialogFragment.java b/app/src/main/java/com/pluscubed/plustimer/ui/SolveDialogFragment.java index cffb272..ab59791 100644 --- a/app/src/main/java/com/pluscubed/plustimer/ui/SolveDialogFragment.java +++ b/app/src/main/java/com/pluscubed/plustimer/ui/SolveDialogFragment.java @@ -25,6 +25,7 @@ import com.pluscubed.plustimer.model.PuzzleType; import com.pluscubed.plustimer.model.ScrambleAndSvg; import com.pluscubed.plustimer.model.Solve; +import com.pluscubed.plustimer.utils.ErrorUtils; import com.pluscubed.plustimer.utils.PrefUtils; import com.pluscubed.plustimer.utils.ThemeUtils; import com.pluscubed.plustimer.utils.Utils; @@ -39,21 +40,21 @@ */ public class SolveDialogFragment extends DialogFragment { - public static final String ARG_DIALOG_INIT_PUZZLETYPE_DISPLAY_NAME + private static final String ARG_DIALOG_INIT_PUZZLETYPE_DISPLAY_NAME = "com.pluscubed.plustimer.dialog.puzzleType"; - public static final String ARG_DIALOG_INIT_SESSION_INDEX + private static final String ARG_DIALOG_INIT_SESSION_INDEX = "com.pluscubed.plustimer.dialog.sessionIndex"; - public static final String ARG_DIALOG_INIT_SOLVE_INDEX + private static final String ARG_DIALOG_INIT_SOLVE_INDEX = "com.pluscubed.plustimer.dialog.solveIndex"; - public static final String ARG_DIALOG_INIT_ADD_MODE + private static final String ARG_DIALOG_INIT_ADD_MODE = "com.pluscubed.plustimer.dialog.addMode"; - public static final int DIALOG_PENALTY_NONE = 0; - public static final int DIALOG_PENALTY_PLUSTWO = 1; - public static final int DIALOG_PENALTY_DNF = 2; + private static final int DIALOG_PENALTY_NONE = 0; + private static final int DIALOG_PENALTY_PLUSTWO = 1; + private static final int DIALOG_PENALTY_DNF = 2; private String mPuzzleTypeName; private int mSessionIndex; @@ -68,26 +69,14 @@ public class SolveDialogFragment extends DialogFragment { private boolean mMillisecondsEnabled; private EditText mTimeEdit; - static SolveDialogFragment newInstanceAdd(String puzzleTypeName, - int sessionIndex) { - SolveDialogFragment d = new SolveDialogFragment(); - Bundle args = new Bundle(); - args.putInt(ARG_DIALOG_INIT_SESSION_INDEX, sessionIndex); - args.putInt(ARG_DIALOG_INIT_SOLVE_INDEX, -1); - args.putString(ARG_DIALOG_INIT_PUZZLETYPE_DISPLAY_NAME, puzzleTypeName); - args.putBoolean(ARG_DIALOG_INIT_ADD_MODE, true); - d.setArguments(args); - return d; - } - - static SolveDialogFragment newInstanceDisplay(String puzzleTypeName, + public static SolveDialogFragment newInstance(boolean addMode, String puzzleTypeName, int sessionIndex, int solveIndex) { SolveDialogFragment d = new SolveDialogFragment(); Bundle args = new Bundle(); args.putInt(ARG_DIALOG_INIT_SESSION_INDEX, sessionIndex); args.putInt(ARG_DIALOG_INIT_SOLVE_INDEX, solveIndex); args.putString(ARG_DIALOG_INIT_PUZZLETYPE_DISPLAY_NAME, puzzleTypeName); - args.putBoolean(ARG_DIALOG_INIT_ADD_MODE, false); + args.putBoolean(ARG_DIALOG_INIT_ADD_MODE, addMode); d.setArguments(args); return d; } @@ -340,6 +329,9 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa } private void onNeutral() { + if (ErrorUtils.isSolveNonexistent(getActivity(), mPuzzleTypeName, 100, mSessionIndex)) { + return; + } PuzzleType.valueOf(mPuzzleTypeName).getSession (mSessionIndex).deleteSolve (mSolveIndex); @@ -377,7 +369,7 @@ private void onPositive() { } dismiss(); } catch (InvalidScrambleException e) { - mScrambleEdit.setError("Invalid scramble."); + mScrambleEdit.setError(getString(R.string.invalid_scramble)); } } @@ -385,7 +377,7 @@ public void addListener(OnDialogDismissedListener listener) { mListener = listener; } - public void updateTitle() { + void updateTitle() { getDialog().setTitle(mSolveCopy.getDescriptiveTimeString (mMillisecondsEnabled)); } diff --git a/app/src/main/java/com/pluscubed/plustimer/ui/SolveListFragment.java b/app/src/main/java/com/pluscubed/plustimer/ui/SolveListFragment.java index 1cd1ac4..0c14b3a 100644 --- a/app/src/main/java/com/pluscubed/plustimer/ui/SolveListFragment.java +++ b/app/src/main/java/com/pluscubed/plustimer/ui/SolveListFragment.java @@ -22,9 +22,12 @@ import com.pluscubed.plustimer.R; import com.pluscubed.plustimer.model.PuzzleType; +import com.pluscubed.plustimer.model.ScrambleAndSvg; import com.pluscubed.plustimer.model.Session; import com.pluscubed.plustimer.model.Solve; +import com.pluscubed.plustimer.utils.ErrorUtils; import com.pluscubed.plustimer.utils.PrefUtils; +import com.pluscubed.plustimer.utils.SolveDialogUtils; import com.pluscubed.plustimer.utils.Utils; import java.util.ArrayList; @@ -118,12 +121,6 @@ private void initSharedPrefs() { mSignEnabled = PrefUtils.isSignEnabled(getActivity()); } - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - } - - private void share() { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); @@ -169,21 +166,15 @@ public boolean onOptionsItemSelected(MenuItem item) { getActivity().finish(); return true; case R.id.menu_solvelist_add_menuitem: - try { - CreateDialogCallback callback = (CreateDialogCallback) getActivity(); - callback.createSolveAddDialog(mPuzzleTypeName, - mSessionIndex); - } catch (ClassCastException e) { - throw new ClassCastException(getActivity().toString() - + " must implement CreateDialogCallback"); - } + SolveDialogUtils.createSolveDialog(getActivity(), true, mPuzzleTypeName, + mSessionIndex, 0); default: return super.onOptionsItemSelected(item); } } - public void updateStats() { + void updateStats() { mQuickStats.setText( mSession.toString(getActivity(), getPuzzleType().toString(), mCurrentToggle, false, mMillisecondsEnabled, @@ -283,16 +274,8 @@ public void onClick(View v) { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { - try { - CreateDialogCallback callback = (CreateDialogCallback) - getActivity(); - callback.createSolveDisplayDialog(mPuzzleTypeName, - mSessionIndex, mSession.getPosition((Solve) - mListView.getItemAtPosition(position))); - } catch (ClassCastException e) { - throw new ClassCastException(getActivity().toString() - + " must implement CreateDialogCallback"); - } + SolveDialogUtils.createSolveDialog(getActivity(), false, mPuzzleTypeName, mSessionIndex, + mSession.getPosition((Solve) mListView.getItemAtPosition(position))); } }); @@ -354,7 +337,7 @@ public void onDestroy() { PuzzleType.unregisterObserver(puzzleTypeObserver); } - public void enableResetSubmitButtons(boolean enable) { + void enableResetSubmitButtons(boolean enable) { mResetSubmitLinearLayout.setVisibility(enable ? View.VISIBLE : View .GONE); } @@ -366,7 +349,7 @@ public void onPause() { if (mCurrentToggle) getPuzzleType().saveCurrentSession(getActivity()); } - public void onSessionSolvesChanged() { + void onSessionSolvesChanged() { mSession = getPuzzleType().getSession(mSessionIndex); if (!mCurrentToggle && mSession.getNumberOfSolves() <= 0) { getPuzzleType().getHistorySessions().deleteSession(mSessionIndex, @@ -429,8 +412,11 @@ public View getView(int position, View convertView, ViewGroup parent) { time.setText(s.getDescriptiveTimeString(mMillisecondsEnabled)); } - desc.setText(s.getScrambleAndSvg().getUiScramble(mSignEnabled, - mPuzzleTypeName)); + ScrambleAndSvg scrambleAndSvg = s.getScrambleAndSvg(); + String uiScramble = ErrorUtils.getUiScramble(getActivity(), position, scrambleAndSvg, + mSignEnabled, mPuzzleTypeName); + + desc.setText(uiScramble); return convertView; } diff --git a/app/src/main/java/com/pluscubed/plustimer/ui/SpinnerPuzzleTypeAdapter.java b/app/src/main/java/com/pluscubed/plustimer/ui/SpinnerPuzzleTypeAdapter.java index c3c3ed8..a76cf40 100644 --- a/app/src/main/java/com/pluscubed/plustimer/ui/SpinnerPuzzleTypeAdapter.java +++ b/app/src/main/java/com/pluscubed/plustimer/ui/SpinnerPuzzleTypeAdapter.java @@ -14,11 +14,11 @@ /** * An Adapter for a Spinner with values of the PuzzleTypes */ -public class SpinnerPuzzleTypeAdapter extends ArrayAdapter { +class SpinnerPuzzleTypeAdapter extends ArrayAdapter { - LayoutInflater mLayoutInflater; + private LayoutInflater mLayoutInflater; - Context mContext; + private Context mContext; public SpinnerPuzzleTypeAdapter(LayoutInflater inflater, Context context) { super(context, 0, PuzzleType.valuesExcludeDisabled()); diff --git a/app/src/main/java/com/pluscubed/plustimer/ui/ThemableActivity.java b/app/src/main/java/com/pluscubed/plustimer/ui/ThemableActivity.java index 38b8d4d..c114f7d 100644 --- a/app/src/main/java/com/pluscubed/plustimer/ui/ThemableActivity.java +++ b/app/src/main/java/com/pluscubed/plustimer/ui/ThemableActivity.java @@ -10,11 +10,11 @@ import com.pluscubed.plustimer.utils.ThemeUtils; -public class ThemableActivity extends ActionBarActivity { +public abstract class ThemableActivity extends ActionBarActivity { private ThemeUtils mThemeUtils; - protected boolean hasNavDrawer() { + boolean hasNavDrawer() { return false; } diff --git a/app/src/main/java/com/pluscubed/plustimer/ui/widget/LockingViewPager.java b/app/src/main/java/com/pluscubed/plustimer/ui/widget/LockingViewPager.java new file mode 100644 index 0000000..761422f --- /dev/null +++ b/app/src/main/java/com/pluscubed/plustimer/ui/widget/LockingViewPager.java @@ -0,0 +1,37 @@ +package com.pluscubed.plustimer.ui.widget; + +import android.content.Context; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.MotionEvent; + +/** + * http://stackoverflow.com/questions/7814017/is-it-possible-to-disable-scrolling-on-a-viewpager + */ +public class LockingViewPager extends ViewPager { + + private boolean mPagingEnabled = true; + + public LockingViewPager(Context context) { + super(context); + } + + public LockingViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + return this.mPagingEnabled && super.onTouchEvent(event); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + return this.mPagingEnabled && super.onInterceptTouchEvent(event); + } + + public void setPagingEnabled(boolean b) { + this.mPagingEnabled = b; + } + +} diff --git a/app/src/main/java/com/pluscubed/plustimer/ui/widget/SlidingTabLayout.java b/app/src/main/java/com/pluscubed/plustimer/ui/widget/SlidingTabLayout.java index 1f85c2e..91e137e 100644 --- a/app/src/main/java/com/pluscubed/plustimer/ui/widget/SlidingTabLayout.java +++ b/app/src/main/java/com/pluscubed/plustimer/ui/widget/SlidingTabLayout.java @@ -146,7 +146,7 @@ public void setViewPager(ViewPager viewPager) { * tab view is not set via * {@link #setCustomTabView(int, int)}. */ - protected TextView createDefaultTabView(Context context) { + TextView createDefaultTabView(Context context) { TextView textView = new TextView(context); textView.setGravity(Gravity.CENTER); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP); @@ -220,6 +220,14 @@ public void setContentDescription(int i, String desc) { mContentDescriptions.put(i, desc); } + public void setClickEnabled(boolean enabled) { + int childCount = mTabStrip.getChildCount(); + for (int i = 0; i < childCount; i++) { + View v = mTabStrip.getChildAt(i); + v.setEnabled(enabled); + } + } + @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); diff --git a/app/src/main/java/com/pluscubed/plustimer/ui/widget/SlidingTabStrip.java b/app/src/main/java/com/pluscubed/plustimer/ui/widget/SlidingTabStrip.java index de55e05..7598fc8 100644 --- a/app/src/main/java/com/pluscubed/plustimer/ui/widget/SlidingTabStrip.java +++ b/app/src/main/java/com/pluscubed/plustimer/ui/widget/SlidingTabStrip.java @@ -1,6 +1,5 @@ package com.pluscubed.plustimer.ui.widget; -import android.R; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; @@ -33,14 +32,14 @@ class SlidingTabStrip extends LinearLayout { this(context, null); } - SlidingTabStrip(Context context, AttributeSet attrs) { + private SlidingTabStrip(Context context, AttributeSet attrs) { super(context, attrs); setWillNotDraw(false); final float density = getResources().getDisplayMetrics().density; TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute(R.attr.colorForeground, outValue, + context.getTheme().resolveAttribute(android.R.attr.colorForeground, outValue, true); final int themeForegroundColor = outValue.data; diff --git a/app/src/main/java/com/pluscubed/plustimer/utils/ErrorUtils.java b/app/src/main/java/com/pluscubed/plustimer/utils/ErrorUtils.java new file mode 100644 index 0000000..a5fb9e8 --- /dev/null +++ b/app/src/main/java/com/pluscubed/plustimer/utils/ErrorUtils.java @@ -0,0 +1,140 @@ +package com.pluscubed.plustimer.utils; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.util.Log; +import android.view.WindowManager; + +import com.afollestad.materialdialogs.MaterialDialog; +import com.crashlytics.android.Crashlytics; +import com.pluscubed.plustimer.BuildConfig; +import com.pluscubed.plustimer.R; +import com.pluscubed.plustimer.model.PuzzleType; +import com.pluscubed.plustimer.model.ScrambleAndSvg; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** + * Error Utility Methods + */ +public class ErrorUtils { + + public static void logCrashlytics(Exception e) { + if (BuildConfig.USE_CRASHLYTICS) { + logCrashlytics(e); + } + } + + public static void showErrorDialog(final Context context, String userReadableMessage, Exception e, + boolean sendFileData) { + try { + MaterialDialog.Builder builder = new MaterialDialog.Builder(context) + .title("Error") + .positiveText("Dismiss"); + if (sendFileData) { + builder.negativeText(R.string.email_developer_history_data) + .callback(new MaterialDialog.ButtonCallback() { + @Override + public void onNegative(MaterialDialog dialog) { + super.onNegative(dialog); + sendFileDataEmail(context); + } + }); + } + if (!userReadableMessage.equals("")) { + builder.content(userReadableMessage + "\n" + e.getMessage()); + } + builder.show(); + } catch (WindowManager.BadTokenException e2) { + e.printStackTrace(); + e2.printStackTrace(); + } + } + + public static void showJsonSyntaxError(Context c, Exception e) { + logCrashlytics(e); + showErrorDialog(c, "History/current data can't be read from storage.", e, true); + } + + public static String getUiScramble(Context c, int position, ScrambleAndSvg scrambleAndSvg, boolean signEnabled, + String puzzleTypeName) { + String uiScramble = ""; + try { + uiScramble = scrambleAndSvg.getUiScramble(signEnabled, + puzzleTypeName); + } catch (NullPointerException e) { + String positionString = String.valueOf(position); + if (position == -1) { + positionString = "CurrentScrambleAndSvg"; + } + logCrashlytics(e); + showErrorDialog(c, "Solve #" + positionString + " UI scramble doesn't exist", e, false); + } + return uiScramble; + } + + public static boolean isSolveNonexistent(Context c, String puzzleTypeName, int solveIndex, int sessionIndex) { + try { + PuzzleType.valueOf(puzzleTypeName).getSession(sessionIndex).getSolveByPosition(solveIndex); + return false; + } catch (IndexOutOfBoundsException e) { + if (BuildConfig.USE_CRASHLYTICS) { + Crashlytics.log(Log.ERROR, + "Solve #" + solveIndex + " nonexistent", + PuzzleType.getCurrent() + .getSession(sessionIndex) + .toString(c, PuzzleType.getCurrent().name(), true, true, true, false) + ); + } + showErrorDialog(c, "Solve #" + solveIndex + " doesn't exist", e, false); + logCrashlytics(e); + return true; + } + } + + public static void sendFileDataEmail(Context context) { + BufferedReader r = null; + StringBuilder total = new StringBuilder(); + for (PuzzleType p : PuzzleType.values()) { + for (int i = 0; i < 2; i++) { + try { + String fileName; + if (i == 0) { + fileName = p.getHistoryFileName(); + } else { + fileName = p.getCurrentSessionFileName(); + } + total.append("\n\n\n").append(fileName).append("\n"); + InputStream in = context.openFileInput(fileName); + r = new BufferedReader(new InputStreamReader(in)); + String line; + while ((line = r.readLine()) != null) { + total.append(line); + } + } catch (FileNotFoundException e) { + // File not found: ignore + } catch (IOException e) { + showErrorDialog(context, "", e, false); + } finally { + if (r != null) { + try { + r.close(); + } catch (IOException e) { + logCrashlytics(e); + showErrorDialog(context, "", e, false); + } + } + } + } + } + Intent intent = new Intent(Intent.ACTION_SENDTO, + Uri.fromParts("mailto", "plusCubed@gmail.com", null)); + intent.putExtra(Intent.EXTRA_TEXT, total.toString()); + context.startActivity(Intent.createChooser(intent, context.getString(R.string.send_email))); + } +} diff --git a/app/src/main/java/com/pluscubed/plustimer/utils/PrefUtils.java b/app/src/main/java/com/pluscubed/plustimer/utils/PrefUtils.java index b795dd5..1cf32d4 100644 --- a/app/src/main/java/com/pluscubed/plustimer/utils/PrefUtils.java +++ b/app/src/main/java/com/pluscubed/plustimer/utils/PrefUtils.java @@ -11,31 +11,31 @@ import java.util.Set; public class PrefUtils { - public static final String PREF_INSPECTION_CHECKBOX = - "pref_inspection_checkbox"; - public static final String PREF_HOLDTOSTART_CHECKBOX = - "pref_holdtostart_checkbox"; - public static final String PREF_KEEPSCREENON_CHECKBOX = - "pref_keepscreenon_checkbox"; - public static final String PREF_TWO_ROW_TIME_CHECKBOX = - "pref_two_row_time_checkbox"; public static final String PREF_TIME_TEXT_SIZE_EDITTEXT = "pref_time_display_size_edittext"; public static final String PREF_UPDATE_TIME_LIST = "pref_update_time_list"; - public static final String PREF_MILLISECONDS_CHECKBOX = - "pref_milliseconds_checkbox"; - public static final String PREF_SIGN_CHECKBOX = - "pref_sign_checkbox"; public static final String PREF_PUZZLETYPES_MULTISELECTLIST = "pref_puzzletypes_multiselectlist"; public static final String PREF_THEME_LIST = "pref_theme_list"; - public static final String PREF_MONOSPACE_SCRAMBLES_CHECKBOX = + private static final String PREF_INSPECTION_CHECKBOX = + "pref_inspection_checkbox"; + private static final String PREF_HOLDTOSTART_CHECKBOX = + "pref_holdtostart_checkbox"; + private static final String PREF_KEEPSCREENON_CHECKBOX = + "pref_keepscreenon_checkbox"; + private static final String PREF_TWO_ROW_TIME_CHECKBOX = + "pref_two_row_time_checkbox"; + private static final String PREF_MILLISECONDS_CHECKBOX = + "pref_milliseconds_checkbox"; + private static final String PREF_SIGN_CHECKBOX = + "pref_sign_checkbox"; + private static final String PREF_MONOSPACE_SCRAMBLES_CHECKBOX = "pref_monospace_scrambles_checkbox"; - public static final String PREF_VERSION_CODE = + private static final String PREF_VERSION_CODE = "pref_version_code"; - public static final String PREF_CURRENT_PUZZLETYPE = + private static final String PREF_CURRENT_PUZZLETYPE = "current_puzzletype"; private static final String PREF_WELCOME_DONE = "welcome_done"; diff --git a/app/src/main/java/com/pluscubed/plustimer/utils/SolveDialogUtils.java b/app/src/main/java/com/pluscubed/plustimer/utils/SolveDialogUtils.java new file mode 100644 index 0000000..0d117b0 --- /dev/null +++ b/app/src/main/java/com/pluscubed/plustimer/utils/SolveDialogUtils.java @@ -0,0 +1,30 @@ +package com.pluscubed.plustimer.utils; + +import android.app.Activity; +import android.app.DialogFragment; +import android.app.FragmentManager; + +import com.pluscubed.plustimer.model.PuzzleType; +import com.pluscubed.plustimer.ui.SolveDialogFragment; + +/** + * Creating solve dialogs + */ +public class SolveDialogUtils { + public static final String DIALOG_SOLVE_TAG = "SOLVE_DIALOG"; + + public static void createSolveDialog(Activity activity, boolean addMode, String puzzleTypeName, + int sessionIndex, int solveIndex) { + FragmentManager fragmentManager = activity.getFragmentManager(); + DialogFragment dialog = (DialogFragment) fragmentManager.findFragmentByTag(DIALOG_SOLVE_TAG); + if (ErrorUtils.isSolveNonexistent(activity, puzzleTypeName, solveIndex, sessionIndex)) { + return; + } + if (dialog == null) { + SolveDialogFragment d = SolveDialogFragment + .newInstance(addMode, PuzzleType.getCurrent().name(), + PuzzleType.CURRENT_SESSION, solveIndex); + d.show(fragmentManager, DIALOG_SOLVE_TAG); + } + } +} diff --git a/app/src/main/java/com/pluscubed/plustimer/utils/Utils.java b/app/src/main/java/com/pluscubed/plustimer/utils/Utils.java index ac59cc8..5cbcc9f 100644 --- a/app/src/main/java/com/pluscubed/plustimer/utils/Utils.java +++ b/app/src/main/java/com/pluscubed/plustimer/utils/Utils.java @@ -1,16 +1,18 @@ package com.pluscubed.plustimer.utils; +import android.app.Activity; import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.util.Log; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; +import android.os.Build; +import android.view.Display; +import android.view.Surface; +import android.view.WindowManager; -import com.afollestad.materialdialogs.MaterialDialog; -import com.crashlytics.android.Crashlytics; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonSyntaxException; import com.google.gson.reflect.TypeToken; -import com.pluscubed.plustimer.R; import com.pluscubed.plustimer.model.PuzzleType; import com.pluscubed.plustimer.model.Session; import com.pluscubed.plustimer.model.Solve; @@ -53,34 +55,32 @@ public static int convertDpToPx(Context context, float dp) { + 0.5f); } - public static void sendHistoryDataEmail(Context context) { - BufferedReader r = null; - StringBuilder total = new StringBuilder(); - for (PuzzleType p : PuzzleType.values()) { - try { - total.append("\n\n\n").append(p.name()).append("\n"); - InputStream in = context.openFileInput(p.name() + ".json"); - r = new BufferedReader(new InputStreamReader(in)); - String line; - while ((line = r.readLine()) != null) { - total.append(line); - } - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (r != null) { - try { - r.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } + public static void lockOrientation(Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); + } + Display display = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); + int rotation = display.getRotation(); + int tempOrientation = activity.getResources().getConfiguration().orientation; + int orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; + switch (tempOrientation) { + case Configuration.ORIENTATION_LANDSCAPE: + if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) + orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; + else + orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; + break; + case Configuration.ORIENTATION_PORTRAIT: + if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270) + orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; + else + orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; } - Intent intent = new Intent(Intent.ACTION_SENDTO, - Uri.fromParts("mailto", "plusCubed@gmail.com", null)); - intent.putExtra(Intent.EXTRA_TEXT, total.toString()); - context.startActivity(Intent.createChooser(intent, context.getString(R.string.send_email))); + activity.setRequestedOrientation(orientation); + } + + public static void unlockOrientation(Activity activity) { + activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); } /** @@ -110,30 +110,10 @@ public static void saveSessionListToFile(Context context, } } - public static boolean assertSolveExists(Context c, int solveIndex, int sessionIndex) { - try { - PuzzleType.getCurrent().getSession(sessionIndex).getSolveByPosition(solveIndex); - return true; - } catch (IndexOutOfBoundsException e) { - new MaterialDialog.Builder(c) - .content("Error: Solve #" + solveIndex + " doesn't exist") - .positiveText("Dismiss") - .show(); - Crashlytics.log(Log.ERROR, - "Solve #" + solveIndex + " nonexistent", - PuzzleType.getCurrent() - .getSession(sessionIndex) - .toString(c, PuzzleType.getCurrent().name(), true, true, true, false) - ); - Crashlytics.logException(e); - return false; - } - } - /** * Get list and save new list */ - public static void updateData(Context context, String fileName) { + private static void updateData(Context context, String fileName) { List historySessions = getSessionListFromFile(context, fileName); saveSessionListToFile(context, fileName, historySessions); } @@ -164,6 +144,8 @@ public static List getSessionListFromFile(Context context, } } catch (FileNotFoundException e) { //File not found: create empty list + } catch (JsonSyntaxException e) { + ErrorUtils.showJsonSyntaxError(context, e); } finally { if (reader != null) { try { @@ -293,7 +275,7 @@ public static String[] timeStringsFromNsSplitByDecimal(long nanoseconds, * @param list the list of solves to extract times from * @return the list of nanoseconds of times */ - public static List getListTimeTwoNoDnf(List list) { + private static List getListTimeTwoNoDnf(List list) { ArrayList timeTwo = new ArrayList<>(); for (Solve i : list) { if (!(i.getPenalty() == Solve.Penalty.DNF)) { diff --git a/app/src/main/res/layout/activity_current_session.xml b/app/src/main/res/layout/activity_current_session.xml index 28ef8df..582913c 100644 --- a/app/src/main/res/layout/activity_current_session.xml +++ b/app/src/main/res/layout/activity_current_session.xml @@ -16,6 +16,7 @@ android:orientation="vertical"> - + android:background="?toolbarShadow" /> diff --git a/app/src/main/res/layout/activity_history_sessionlist.xml b/app/src/main/res/layout/activity_history_sessionlist.xml index 6a7c63d..745e47d 100644 --- a/app/src/main/res/layout/activity_history_sessionlist.xml +++ b/app/src/main/res/layout/activity_history_sessionlist.xml @@ -25,8 +25,7 @@ + android:background="?toolbarShadow" /> diff --git a/app/src/main/res/layout/activity_with_toolbar.xml b/app/src/main/res/layout/activity_with_toolbar.xml index 439d6c7..1a50106 100644 --- a/app/src/main/res/layout/activity_with_toolbar.xml +++ b/app/src/main/res/layout/activity_with_toolbar.xml @@ -14,8 +14,7 @@ + android:background="?toolbarShadow" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_current_session_timer.xml b/app/src/main/res/layout/fragment_current_session_timer.xml index 8ac7165..9020b5c 100644 --- a/app/src/main/res/layout/fragment_current_session_timer.xml +++ b/app/src/main/res/layout/fragment_current_session_timer.xml @@ -46,10 +46,8 @@ android:layout_alignParentStart="true" android:background="?android:windowBackground" android:paddingBottom="5dp" - android:paddingEnd="7dp" android:paddingLeft="7dp" android:paddingRight="7dp" - android:paddingStart="7dp" android:paddingTop="5dp" android:textSize="16sp" /> @@ -63,12 +61,11 @@ android:layout_alignParentRight="true" android:background="?android:windowBackground" android:paddingBottom="5dp" - android:paddingEnd="7dp" android:paddingLeft="5dp" android:paddingRight="7dp" - android:paddingStart="5dp" android:text="@string/solves" - android:textSize="16sp" /> + android:textSize="16sp" + tools:ignore="RtlHardcoded" /> \ No newline at end of file diff --git a/app/src/main/res/layout/list_item_single_line.xml b/app/src/main/res/layout/list_item_single_line.xml index f21dc85..5b60cd9 100644 --- a/app/src/main/res/layout/list_item_single_line.xml +++ b/app/src/main/res/layout/list_item_single_line.xml @@ -6,8 +6,6 @@ android:layout_height="48dp" android:background="?activatedBackground" android:gravity="center_vertical" - android:paddingEnd="16dp" android:paddingLeft="16dp" android:paddingRight="16dp" - android:paddingStart="16dp" android:textSize="16sp" /> diff --git a/app/src/main/res/layout/recycler_item_solve.xml b/app/src/main/res/layout/recycler_item_solve.xml index f63d387..5968871 100644 --- a/app/src/main/res/layout/recycler_item_solve.xml +++ b/app/src/main/res/layout/recycler_item_solve.xml @@ -7,10 +7,8 @@ android:background="@drawable/item_background_dark" android:fontFamily="@string/font_fontFamily_medium" android:gravity="center" - android:paddingEnd="8dp" android:paddingLeft="8dp" android:paddingRight="8dp" - android:paddingStart="8dp" android:textColor="?colorAccent" android:textSize="16sp" android:textStyle="@integer/font_textStyle_medium"> diff --git a/app/src/main/res/layout/sliding_tab_textview.xml b/app/src/main/res/layout/sliding_tab_textview.xml index 467076a..b789c47 100644 --- a/app/src/main/res/layout/sliding_tab_textview.xml +++ b/app/src/main/res/layout/sliding_tab_textview.xml @@ -8,10 +8,8 @@ android:background="@drawable/item_background_dark" android:fontFamily="@string/font_fontFamily_medium" android:gravity="center" - android:paddingEnd="16dp" android:paddingLeft="16dp" android:paddingRight="16dp" - android:paddingStart="16dp" android:textAllCaps="true" android:textColor="@color/sliding_tab_text_color" android:textSize="12sp" diff --git a/app/src/main/res/layout/spinner_item.xml b/app/src/main/res/layout/spinner_item.xml index 79eee69..2ed148f 100644 --- a/app/src/main/res/layout/spinner_item.xml +++ b/app/src/main/res/layout/spinner_item.xml @@ -13,9 +13,9 @@ android:gravity="center_vertical|start" android:paddingBottom="8dp" android:paddingLeft="16dp" - android:paddingStart="16dp" android:paddingTop="8dp" - android:textSize="16sp" /> + android:textSize="16sp" + tools:ignore="RtlHardcoded,RtlSymmetry" /> + android:textSize="16sp" + tools:ignore="RtlHardcoded,RtlSymmetry" /> + android:textSize="12sp" + tools:ignore="RtlHardcoded,RtlSymmetry" /> diff --git a/app/src/main/res/layout/spinner_item_dropdown2.xml b/app/src/main/res/layout/spinner_item_dropdown2.xml index 9a6e866..929745c 100644 --- a/app/src/main/res/layout/spinner_item_dropdown2.xml +++ b/app/src/main/res/layout/spinner_item_dropdown2.xml @@ -11,10 +11,8 @@ android:layout_height="wrap_content" android:ellipsize="end" android:gravity="center_vertical|start" - android:paddingEnd="16dp" android:paddingLeft="16dp" android:paddingRight="16dp" - android:paddingStart="16dp" android:paddingTop="8dp" android:singleLine="true" android:textSize="16sp" /> @@ -26,10 +24,8 @@ android:ellipsize="end" android:gravity="center_vertical|start" android:paddingBottom="8dp" - android:paddingEnd="16dp" android:paddingLeft="16dp" android:paddingRight="16dp" - android:paddingStart="16dp" android:singleLine="true" android:textSize="12sp" /> diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 00a2bda..f17ec37 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -2,7 +2,6 @@ #151515 #212121 - #4c000000 #4d73ff #20ffffff diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml index db9a3e6..5709fe7 100644 --- a/app/src/main/res/values/ids.xml +++ b/app/src/main/res/values/ids.xml @@ -74,6 +74,9 @@ + + + \ No newline at end of file diff --git a/app/src/noPermissions/AndroidManifest.xml b/app/src/noPermissions/AndroidManifest.xml index b6e060b..ccfda0f 100644 --- a/app/src/noPermissions/AndroidManifest.xml +++ b/app/src/noPermissions/AndroidManifest.xml @@ -1,8 +1,8 @@ + xmlns:tools="http://schemas.android.com/tools"> + tools:node="remove" />