diff --git a/app/build.gradle b/app/build.gradle index 6ee06b2..92c4ade 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,5 +28,7 @@ dependencies { compile 'com.android.support:support-annotations:25.3.1' compile 'com.android.support:cardview-v7:25.3.1' compile 'com.android.support.constraint:constraint-layout:1.0.2' + compile 'com.nex3z:flow-layout:1.0.0' + compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:+' testCompile 'junit:junit:4.12' } diff --git a/app/src/main/assets/exercises.sqlite b/app/src/main/assets/databases/exercises.sqlite similarity index 100% rename from app/src/main/assets/exercises.sqlite rename to app/src/main/assets/databases/exercises.sqlite diff --git a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/ChooseExerciseActivity.java b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/ChooseExerciseActivity.java index f2a19d5..d7cb4dc 100644 --- a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/ChooseExerciseActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/ChooseExerciseActivity.java @@ -1,10 +1,13 @@ package org.secuso.privacyfriendlybreakreminder.activities; import android.content.Intent; +import android.support.v4.content.ContextCompat; +import android.support.v4.util.Pair; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.util.SortedList; +import android.support.v7.widget.CardView; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; @@ -12,18 +15,21 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; +import android.widget.TextView; +import android.widget.ToggleButton; import org.secuso.privacyfriendlybreakreminder.R; import org.secuso.privacyfriendlybreakreminder.activities.adapter.ExerciseAdapter; -import org.secuso.privacyfriendlybreakreminder.activities.layout.FlowLayout; import org.secuso.privacyfriendlybreakreminder.database.SQLiteHelper; import org.secuso.privacyfriendlybreakreminder.database.data.Exercise; +import com.nex3z.flowlayout.FlowLayout; import org.secuso.privacyfriendlybreakreminder.exercises.ExerciseLocale; import org.secuso.privacyfriendlybreakreminder.exercises.ExerciseSections; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; +import java.util.LinkedList; import java.util.List; import static org.secuso.privacyfriendlybreakreminder.activities.adapter.ExerciseAdapter.ID_COMPARATOR; @@ -40,6 +46,9 @@ public class ChooseExerciseActivity extends AppCompatActivity { ExerciseAdapter exerciseAdapter; SQLiteHelper databaseHelper; + List buttons; + boolean[] buttonStates; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -75,21 +84,58 @@ public class ChooseExerciseActivity extends AppCompatActivity { filterButtonLayout.removeAllViews(); - for(ExerciseSections section : ExerciseSections.getSectionList()) { - // TODO: Add Buttons for every section we have - //View view = LayoutInflater.from(this).inflate(R.layout.layout_section_filter_button, null, false); - //TextView image = (TextView) view.findViewById(R.id.button_text); - //filterButtonLayout.addView(view); + final List sections = ExerciseSections.getSectionList(); + buttonStates = new boolean[sections.size()]; + buttons = new ArrayList<>(sections.size()); + + for(int i = 0; i < sections.size(); ++i) { + ExerciseSections section = sections.get(i); + + View view = LayoutInflater.from(this).inflate(R.layout.layout_section_filter_button, null, false); + ToggleButton button = (ToggleButton) view.findViewById(R.id.button); + + String sectionText = section.getLocalName(this); + + button.setClickable(true); + button.setChecked(false); + button.setTextOff(sectionText); + button.setTextOn(sectionText); + button.setText(sectionText); + button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + List filterSections = new ArrayList(sections.size()); + + for(int i = 0; i < buttons.size(); ++i) { + if(buttons.get(i).isChecked()) { + filterSections.add(sections.get(i).name()); + } + } + + exerciseAdapter.replaceAll(databaseHelper.getExerciseListBySections(ExerciseLocale.getLocale(), filterSections)); + exerciseList.scrollToPosition(0); + } + }); + + buttons.add(button); + filterButtonLayout.addView(view); } } - public void onClick(View v) { - // TODO get onclicklistener to call this method so we can filter the list - //exerciseAdapter.replaceAll(databaseHelper.getExerciseListBySections()); - exerciseList.scrollToPosition(0); + private void switchButton(View v) { + for(int i = 0; i < buttons.size(); ++i) { + if(v.equals(buttons.get(i))) { + buttonStates[i] = !buttonStates[i]; + CardView b = (CardView) v; + b.setBackgroundColor(buttonStates[i] ? + ContextCompat.getColor(this, R.color.colorAccent) : + ContextCompat.getColor(this, R.color.middlegrey)); + } + } } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch(item.getItemId()) { diff --git a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/ExerciseActivity.java b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/ExerciseActivity.java index 7ba5964..6b99f74 100644 --- a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/ExerciseActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/ExerciseActivity.java @@ -1,11 +1,16 @@ package org.secuso.privacyfriendlybreakreminder.activities; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; import android.graphics.Color; import android.os.Build; import android.os.CountDownTimer; import android.preference.PreferenceManager; +import android.support.constraint.ConstraintLayout; +import android.support.v4.app.ActivityCompat; import android.support.v4.content.AsyncTaskLoader; import android.support.v4.content.Loader; import android.support.v4.view.MenuItemCompat; @@ -17,11 +22,13 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.WindowManager; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import org.secuso.privacyfriendlybreakreminder.R; +import org.secuso.privacyfriendlybreakreminder.activities.tutorial.PrefManager; import org.secuso.privacyfriendlybreakreminder.database.SQLiteHelper; import org.secuso.privacyfriendlybreakreminder.database.data.Exercise; import org.secuso.privacyfriendlybreakreminder.database.data.ExerciseSet; @@ -29,7 +36,7 @@ import org.secuso.privacyfriendlybreakreminder.exercises.ExerciseLocale; import java.util.Locale; -import static android.support.design.R.id.center_horizontal; +import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.support.design.R.id.center_vertical; public class ExerciseActivity extends AppCompatActivity implements android.support.v4.app.LoaderManager.LoaderCallbacks{ @@ -38,13 +45,26 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo // UI private TextView breakTimerText; - private ImageView playButton; private ProgressBar progressBar; private TextView timerText; private TextView executionText; private TextView descriptionText; - private ImageView exerciseImage; private TextView sectionText; + private ImageView exerciseImage; + private ConstraintLayout exerciseContent; + private ImageButton playButton; + private ImageButton repeatButton; + private ImageButton continuousButton; + private ImageButton prevButton; + private ImageButton nextButton; + private ProgressBar progressBarBig; + private TextView breakTimerTextBig; + private ConstraintLayout bigProgressBarLayout; + + private boolean repeatStatus; + private boolean continuousStatus; + private boolean showBigTimer = false; + private boolean showControlButtons = true; // exerciseSet info private long exerciseSetId; @@ -53,8 +73,8 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo private int currentExercisePart = 0; // timer - private long exerciseTime = 20 * 1000; // TODO - get from exercise? - private long pauseDuration = 5 * 60 * 1000; // TODO 5 minutes - get from settings + private final long exerciseTime = 20 * 1000; + private long pauseDuration; private CountDownTimer exerciseTimer; private CountDownTimer breakTimer; private boolean isBreakTimerRunning; @@ -62,14 +82,21 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo private long remainingBreakDuration; private long remainingExerciseDuration; - // database + // database and utility private SQLiteHelper dbHelper; + private SharedPreferences pref; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_exercise); + pref = PreferenceManager.getDefaultSharedPreferences(this); + exerciseSetId = pref.getLong(PrefManager.DEFAULT_EXERCISE_SET, 0L); + pauseDuration = pref.getLong(PrefManager.PAUSE_TIME, 5 * 60 * 1000); + repeatStatus = pref.getBoolean(PrefManager.REPEAT_STATUS, false); + continuousStatus = pref.getBoolean(PrefManager.CONTINUOUS_STATUS, false); + initResources(); ActionBar ab = getSupportActionBar(); @@ -78,9 +105,6 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo ab.setHomeAsUpIndicator(R.drawable.ic_close_white); } - exerciseSetId = PreferenceManager.getDefaultSharedPreferences(this).getLong("DEFAULT_EXERCISE_SET", 0L); - pauseDuration = PreferenceManager.getDefaultSharedPreferences(this).getLong("DEFAULT_PAUSE_DURATION", 0L); - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); getSupportLoaderManager().initLoader(0, null, this); @@ -88,13 +112,25 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo private void initResources() { dbHelper = new SQLiteHelper(this); - playButton = (ImageView) findViewById(R.id.button_playPause); + playButton = (ImageButton) findViewById(R.id.button_playPause); progressBar = (ProgressBar) findViewById(R.id.progressBar); timerText = (TextView) findViewById(R.id.timerText); executionText = (TextView) findViewById(R.id.execution); descriptionText = (TextView) findViewById(R.id.description); exerciseImage = (ImageView) findViewById(R.id.exercise_image); sectionText = (TextView) findViewById(R.id.section); + repeatButton = (ImageButton) findViewById(R.id.button_repeat); + exerciseContent = (ConstraintLayout) findViewById(R.id.exercise_layout); + continuousButton = (ImageButton) findViewById(R.id.button_continuous); + prevButton = (ImageButton) findViewById(R.id.button_prev); + nextButton = (ImageButton) findViewById(R.id.button_next); + + progressBarBig = (ProgressBar) findViewById(R.id.progressBarBig); + breakTimerTextBig = (TextView) findViewById(R.id.breakTimerTextBig); + bigProgressBarLayout = (ConstraintLayout) findViewById(R.id.bigProgressBarLayout); + + setRepeatButtonStatus(repeatStatus); + setContinuousButtonStatus(continuousStatus); } @Override @@ -133,8 +169,11 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { + Intent intent = new Intent(ExerciseActivity.this, TimerActivity.class); + intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP); + ExerciseActivity.this.finish(); - ExerciseActivity.this.startActivity(new Intent(ExerciseActivity.this, TimerActivity.class)); + ExerciseActivity.this.startActivity(intent); ExerciseActivity.this.overridePendingTransition(0, 0); } }) @@ -148,6 +187,30 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo .create().show(); } + private void showEndDialog() { + new AlertDialog.Builder(this) + .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + Intent intent = new Intent(ExerciseActivity.this, TimerActivity.class); + intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP); + + ExerciseActivity.this.finish(); + ExerciseActivity.this.startActivity(intent); + ExerciseActivity.this.overridePendingTransition(0, 0); + } + }) + .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dialogInterface.dismiss(); + } + }) + .setTitle(R.string.dialog_end_break_confirmation_title) + .setMessage(R.string.dialog_end_break_confirmation) + .create().show(); + } + @Override public Loader onCreateLoader(int id, final Bundle args) { return new AsyncTaskLoader(this) { @@ -177,12 +240,12 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo if(this.set.size() > 0) { setExercise(0); } else { - // TODO IF THERE ARE NO EXERCISES ONLY SHOW TIMER : showTimer(); + showBigTimer(true); + showControlButtons(false); } // load data only once getSupportLoaderManager().destroyLoader(0); - pauseDuration = PreferenceManager.getDefaultSharedPreferences(ExerciseActivity.this).getLong("PAUSE TIME", 5 * 60 * 1000); startBreakTimer(); } @@ -211,6 +274,83 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo timerText.setText(time); } + private void updateBigProgress(long remainingDuration) { + progressBarBig.setMax((int)pauseDuration); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + progressBarBig.setProgress(progressBarBig.getMax() - (int) remainingDuration, true); + } else { + progressBarBig.setProgress(progressBarBig.getMax() - (int) remainingDuration); + } + + int secondsUntilFinished = (int) Math.ceil(remainingDuration / 1000.0); + int minutesUntilFinished = secondsUntilFinished / 60; + int seconds = secondsUntilFinished % 60; + int minutes = minutesUntilFinished % 60; + + String time = String.format(Locale.US, "%02d:%02d", minutes, seconds); + breakTimerTextBig.setText(time); + } + + private void showBigTimer(boolean show) { + if(showBigTimer != show) { + + showBigTimer = show; + + if (show) { + + bigProgressBarLayout.setVisibility(View.VISIBLE); + bigProgressBarLayout.animate().alpha(1.0f).setDuration(125).setListener(null); + + exerciseContent.animate().alpha(0.0f).setDuration(125).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + if (!showBigTimer) + exerciseContent.setVisibility(View.GONE); + } + }); + + + } else { + + bigProgressBarLayout.animate().alpha(0.0f).setDuration(125).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + if (!showBigTimer) + bigProgressBarLayout.setVisibility(View.GONE); + } + }); + + exerciseContent.setVisibility(View.VISIBLE); + exerciseContent.animate().alpha(1.0f).setDuration(125).setListener(null); + + + } + } + } + + private void showControlButtons(boolean show) { + if(show != showControlButtons) { + showControlButtons = show; + + if(show) { + playButton.setVisibility(View.VISIBLE); + repeatButton.setVisibility(View.VISIBLE); + continuousButton.setVisibility(View.VISIBLE); + prevButton.setVisibility(View.VISIBLE); + nextButton.setVisibility(View.VISIBLE); + } else { + playButton.setVisibility(View.GONE); + repeatButton.setVisibility(View.GONE); + continuousButton.setVisibility(View.GONE); + prevButton.setVisibility(View.GONE); + nextButton.setVisibility(View.GONE); + } + } + } + public void onClick(View view) { switch(view.getId()) { case R.id.progressBarLayout: @@ -223,6 +363,12 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo case R.id.button_prev: handlePrevClicked(); break; + case R.id.button_repeat: + handleRepeatClicked(); + break; + case R.id.button_continuous: + handleContinuousClicked(); + break; default: } } @@ -233,35 +379,43 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo private boolean nextExercise() { if(set != null) { - setExercise((currentExercise + 1)); - return true; - } - return false; - } - private boolean previousExercise() { - if(set != null) { - setExercise(currentExercise - 1); - return true; + if(showBigTimer && repeatStatus && currentExercise == set.size()) { + // repeat status is was turned back on.. and somebody presses next + showBigTimer(false); + currentExercise = set.size() - 1; + } + + if(setExercise((currentExercise + 1))) { + return true; + } else { + showBigTimer(true); + } } return false; } - private void setExercise(int number) { + private boolean previousExercise() { + if(showBigTimer) { + showBigTimer(false); + } + return set != null && setExercise(currentExercise - 1); + } + + private boolean setExercise(int number) { if(set != null) { if(set.size() != 0) { - // TODO: stop if we reach the end or loop around - boolean loopAround = true; - if(number < 0) { - currentExercise = loopAround ? + currentExercise = repeatStatus ? (number + set.size()) : 0; } else if(number >= set.size()) { - currentExercise = loopAround ? + currentExercise = repeatStatus ? (number % set.size()) : - (set.size() -1); + (set.size()); + + if(!repeatStatus) return false; } else { currentExercise = number; @@ -269,8 +423,10 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo currentExercisePart = 0; showExercise(set.get(currentExercise), currentExercisePart); + return true; } } + return false; } private boolean nextExercisePart() { @@ -304,11 +460,40 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo sectionText.setText(e.getSection()); exerciseImage.setImageResource(e.getImageResIds(this)[image]); - // TODO: continuous play? - // if() - startExerciseTimer(); - // else - //resetExerciseTimer(); + if(continuousStatus) + startExerciseTimer(); + else + resetExerciseTimer(); + } + + private void handleRepeatClicked() { + repeatStatus = !repeatStatus; + + pref.edit().putBoolean(PrefManager.REPEAT_STATUS, repeatStatus).apply(); + + setRepeatButtonStatus(repeatStatus); + } + + private void setRepeatButtonStatus(boolean repeatStatus) { + repeatButton.setColorFilter( + repeatStatus ? + ActivityCompat.getColor(this, R.color.colorPrimary) : + ActivityCompat.getColor(this, R.color.middlegrey)); + } + + private void handleContinuousClicked() { + continuousStatus = !continuousStatus; + + pref.edit().putBoolean(PrefManager.CONTINUOUS_STATUS, continuousStatus).apply(); + + setContinuousButtonStatus(continuousStatus); + } + + private void setContinuousButtonStatus(boolean continuousStatus) { + continuousButton.setColorFilter( + continuousStatus ? + ActivityCompat.getColor(this, R.color.colorPrimary) : + ActivityCompat.getColor(this, R.color.middlegrey)); } private void handlePrevClicked() { @@ -340,6 +525,7 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo public void onTick(long millisUntilFinished) { remainingBreakDuration = millisUntilFinished; updateBreakTimer(remainingBreakDuration); + updateBigProgress(remainingBreakDuration); } @Override @@ -347,7 +533,10 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo remainingBreakDuration = 0; isBreakTimerRunning = false; updateBreakTimer(remainingBreakDuration); - // TODO: show dialog to end the exercises? + updateBigProgress(remainingBreakDuration); + + showEndDialog(); + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } }; @@ -438,11 +627,13 @@ public class ExerciseActivity extends AppCompatActivity implements android.suppo } private void resetExerciseTimer() { - exerciseTimer.cancel(); + if(exerciseTimer != null) { + exerciseTimer.cancel(); + } isExerciseTimerRunning = false; remainingExerciseDuration = 0; updatePlayButton(false); - updateProgress(0L); + updateProgress(exerciseTime); } } diff --git a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/ManageExerciseSetsActivity.java b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/ManageExerciseSetsActivity.java index 7b0a15e..576cc8c 100644 --- a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/ManageExerciseSetsActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/ManageExerciseSetsActivity.java @@ -227,7 +227,7 @@ public class ManageExerciseSetsActivity extends BaseActivity implements android. List deleteIds = exerciseSetAdapter.getDeleteIdList(); if(deleteIds.size() == 0) { - Toast.makeText(this, "Please select an item to delete.", Toast.LENGTH_SHORT).show(); + Toast.makeText(this, R.string.toast_please_select_an_item_to_delete, Toast.LENGTH_SHORT).show(); } else { for (Long l : deleteIds) { helper.deleteExerciseSet(l); @@ -316,7 +316,7 @@ public class ManageExerciseSetsActivity extends BaseActivity implements android. String text = exerciseSetName.getText().toString(); if(TextUtils.isEmpty(text)) { - Toast.makeText(getActivity(), "Please specify a name.", Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), R.string.toast_please_specify_a_name, Toast.LENGTH_SHORT).show(); return; } diff --git a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/TimerActivity.java b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/TimerActivity.java index b3ad752..b717efe 100644 --- a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/TimerActivity.java +++ b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/TimerActivity.java @@ -28,6 +28,7 @@ import android.widget.ProgressBar; import android.widget.Spinner; import android.widget.TextView; +import org.secuso.privacyfriendlybreakreminder.activities.tutorial.PrefManager; import org.secuso.privacyfriendlybreakreminder.exercises.ExerciseLocale; import org.secuso.privacyfriendlybreakreminder.R; import org.secuso.privacyfriendlybreakreminder.activities.adapter.ExerciseSetSpinnerAdapter; @@ -40,14 +41,11 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; +import static org.secuso.privacyfriendlybreakreminder.activities.tutorial.PrefManager.DEFAULT_EXERCISE_SET; +import static org.secuso.privacyfriendlybreakreminder.activities.tutorial.PrefManager.PAUSE_TIME; + public class TimerActivity extends BaseActivity implements android.support.v4.app.LoaderManager.LoaderCallbacks> { private static final String TAG = TimerActivity.class.getSimpleName(); - private static final String PREF_PICKER_SECONDS = TAG + ".PREF_PICKER_SECONDS"; - private static final String PREF_PICKER_MINUTES = TAG + ".PREF_PICKER_MINUTES"; - private static final String PREF_PICKER_HOURS = TAG + ".PREF_PICKER_HOURS"; - - private static final String PREF_BREAK_PICKER_SECONDS = TAG + "PREF_BREAK_PICKER_SECONDS"; - private static final String PREF_BREAK_PICKER_MINUTES = TAG + "PREF_BREAK_PICKER_MINUTES"; // UI private ProgressBar progressBar; @@ -191,7 +189,7 @@ public class TimerActivity extends BaseActivity implements android.support.v4.ap exerciseSetSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { - pref.edit().putLong("DEFAULT_EXERCISE_SET", id).apply(); + pref.edit().putLong(DEFAULT_EXERCISE_SET, id).apply(); } @Override public void onNothingSelected(AdapterView parent) {} @@ -207,25 +205,25 @@ public class TimerActivity extends BaseActivity implements android.support.v4.ap secondsPicker.setDisplayedValues(SECONDS_MINUTES); secondsPicker.setMinValue(0); secondsPicker.setMaxValue(SECONDS_MINUTES.length - 1); - secondsPicker.setValue(pref.getInt(PREF_PICKER_SECONDS, 0)); + secondsPicker.setValue(pref.getInt(PrefManager.PREF_PICKER_SECONDS, 0)); secondsBreakPicker.setDisplayedValues(SECONDS_MINUTES); secondsBreakPicker.setMinValue(0); secondsBreakPicker.setMaxValue(SECONDS_MINUTES.length - 1); - secondsBreakPicker.setValue(pref.getInt(PREF_BREAK_PICKER_SECONDS, 0)); + secondsBreakPicker.setValue(pref.getInt(PrefManager.PREF_BREAK_PICKER_SECONDS, 0)); minutesPicker.setDisplayedValues(SECONDS_MINUTES); minutesPicker.setMinValue(0); minutesPicker.setMaxValue(SECONDS_MINUTES.length - 1); - minutesPicker.setValue(pref.getInt(PREF_PICKER_MINUTES, 30)); + minutesPicker.setValue(pref.getInt(PrefManager.PREF_PICKER_MINUTES, 30)); minutesBreakPicker.setDisplayedValues(SECONDS_MINUTES); minutesBreakPicker.setMinValue(0); minutesBreakPicker.setMaxValue(SECONDS_MINUTES.length - 1); - minutesBreakPicker.setValue(pref.getInt(PREF_BREAK_PICKER_MINUTES, 0)); + minutesBreakPicker.setValue(pref.getInt(PrefManager.PREF_BREAK_PICKER_MINUTES, 0)); hoursPicker.setDisplayedValues(HOURS); hoursPicker.setMinValue(0); hoursPicker.setMaxValue(HOURS.length - 1); - hoursPicker.setValue(pref.getInt(PREF_PICKER_HOURS, 1)); + hoursPicker.setValue(pref.getInt(PrefManager.PREF_PICKER_HOURS, 1)); setDividerColor(secondsPicker, R.color.transparent); @@ -293,18 +291,18 @@ public class TimerActivity extends BaseActivity implements android.support.v4.ap SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); pref.edit() - .putInt(PREF_BREAK_PICKER_SECONDS, secondsBreakPicker.getValue()) - .putInt(PREF_BREAK_PICKER_MINUTES, minutesBreakPicker.getValue()) - .putLong("PAUSE TIME", getCurrentSetBreakTime()).apply(); + .putInt(PrefManager.PREF_BREAK_PICKER_SECONDS, secondsBreakPicker.getValue()) + .putInt(PrefManager.PREF_BREAK_PICKER_MINUTES, minutesBreakPicker.getValue()) + .putLong(PAUSE_TIME, getCurrentSetBreakTime()).apply(); } } } private void saveCurrentSetDuration() { SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); - pref.edit().putInt(PREF_PICKER_SECONDS, secondsPicker.getValue()) - .putInt(PREF_PICKER_MINUTES, minutesPicker.getValue()) - .putInt(PREF_PICKER_HOURS, hoursPicker.getValue()).apply(); + pref.edit().putInt(PrefManager.PREF_PICKER_SECONDS, secondsPicker.getValue()) + .putInt(PrefManager.PREF_PICKER_MINUTES, minutesPicker.getValue()) + .putInt(PrefManager.PREF_PICKER_HOURS, hoursPicker.getValue()).apply(); } private long getCurrentSetDuration() { diff --git a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/adapter/ExerciseSetListAdapter.java b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/adapter/ExerciseSetListAdapter.java index 5f6e4a0..8b3c0cc 100644 --- a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/adapter/ExerciseSetListAdapter.java +++ b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/adapter/ExerciseSetListAdapter.java @@ -122,19 +122,7 @@ public class ExerciseSetListAdapter extends RecyclerView.Adapter 1) { - imageID = imageIDSplit[0]; // only take the first image as a display image - } - - int imageResID = mContext.getResources().getIdentifier( - "exercise_" + imageID, - "drawable", - mContext.getPackageName()); - - image.setImageResource(imageResID); + image.setImageResource(set.get(i).getImageResIds(mContext)[0]); vh.exerciseList.addView(view); } diff --git a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/adapter/ExerciseSetSpinnerAdapter.java b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/adapter/ExerciseSetSpinnerAdapter.java index 83a2f8d..a83fba0 100644 --- a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/adapter/ExerciseSetSpinnerAdapter.java +++ b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/adapter/ExerciseSetSpinnerAdapter.java @@ -83,7 +83,6 @@ public class ExerciseSetSpinnerAdapter extends ArrayAdapter { } else { noExercisesText.setVisibility(View.GONE); } - noExercisesText.setTextColor(ContextCompat.getColor(getContext(), R.color.black)); //LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); //View row = inflater.inflate(resource, parent, false); diff --git a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/layout/FlowLayout.java b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/layout/FlowLayout.java deleted file mode 100644 index c44a89d..0000000 --- a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/layout/FlowLayout.java +++ /dev/null @@ -1,166 +0,0 @@ -package org.secuso.privacyfriendlybreakreminder.activities.layout; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; - -import org.secuso.privacyfriendlybreakreminder.R; - -public class FlowLayout extends ViewGroup { - private int mHorizontalSpacing; - private int mVerticalSpacing; - private Paint mPaint; - - public FlowLayout(Context context, AttributeSet attrs) { - super(context, attrs); - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout); - try { - mHorizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_horizontalSpacing, 0); - mVerticalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_verticalSpacing, 0); - } finally { - a.recycle(); - } - - mPaint = new Paint(); - mPaint.setAntiAlias(true); - mPaint.setColor(0xffff0000); - mPaint.setStrokeWidth(2.0f); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthSize = MeasureSpec.getSize(widthMeasureSpec) - getPaddingRight(); - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - - boolean growHeight = widthMode != MeasureSpec.UNSPECIFIED; - - int width = 0; - int height = getPaddingTop(); - - int currentWidth = getPaddingLeft(); - int currentHeight = 0; - - boolean breakLine = false; - boolean newLine = false; - int spacing = 0; - - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - View child = getChildAt(i); - measureChild(child, widthMeasureSpec, heightMeasureSpec); - - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - spacing = mHorizontalSpacing; - if (lp.horizontalSpacing >= 0) { - spacing = lp.horizontalSpacing; - } - - if (growHeight && (breakLine || currentWidth + child.getMeasuredWidth() > widthSize)) { - height += currentHeight + mVerticalSpacing; - currentHeight = 0; - width = Math.max(width, currentWidth - spacing); - currentWidth = getPaddingLeft(); - newLine = true; - } else { - newLine = false; - } - - lp.x = currentWidth; - lp.y = height; - - currentWidth += child.getMeasuredWidth() + spacing; - currentHeight = Math.max(currentHeight, child.getMeasuredHeight()); - - breakLine = lp.breakLine; - } - - if (!newLine) { - height += currentHeight; - width = Math.max(width, currentWidth - spacing); - } - - width += getPaddingRight(); - height += getPaddingBottom(); - - setMeasuredDimension(resolveSize(width, widthMeasureSpec), - resolveSize(height, heightMeasureSpec)); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - View child = getChildAt(i); - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - child.layout(lp.x, lp.y, lp.x + child.getMeasuredWidth(), lp.y + child.getMeasuredHeight()); - } - } - - @Override - protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - boolean more = super.drawChild(canvas, child, drawingTime); - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - if (lp.horizontalSpacing > 0) { - float x = child.getRight(); - float y = child.getTop() + child.getHeight() / 2.0f; - canvas.drawLine(x, y - 4.0f, x, y + 4.0f, mPaint); - canvas.drawLine(x, y, x + lp.horizontalSpacing, y, mPaint); - canvas.drawLine(x + lp.horizontalSpacing, y - 4.0f, x + lp.horizontalSpacing, y + 4.0f, mPaint); - } - if (lp.breakLine) { - float x = child.getRight(); - float y = child.getTop() + child.getHeight() / 2.0f; - canvas.drawLine(x, y, x, y + 6.0f, mPaint); - canvas.drawLine(x, y + 6.0f, x + 6.0f, y + 6.0f, mPaint); - } - return more; - } - - @Override - protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { - return p instanceof LayoutParams; - } - - @Override - protected LayoutParams generateDefaultLayoutParams() { - return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); - } - - @Override - public LayoutParams generateLayoutParams(AttributeSet attrs) { - return new LayoutParams(getContext(), attrs); - } - - @Override - protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { - return new LayoutParams(p.width, p.height); - } - - public static class LayoutParams extends ViewGroup.LayoutParams { - int x; - int y; - - public int horizontalSpacing; - public boolean breakLine; - - public LayoutParams(Context context, AttributeSet attrs) { - super(context, attrs); - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout_LayoutParams); - try { - horizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_LayoutParams_layout_horizontalSpacing, -1); - breakLine = a.getBoolean(R.styleable.FlowLayout_LayoutParams_layout_breakLine, false); - } finally { - a.recycle(); - } - } - - public LayoutParams(int w, int h) { - super(w, h); - } - } -} diff --git a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/tutorial/PrefManager.java b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/tutorial/PrefManager.java index 7c5612e..e318b4d 100644 --- a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/tutorial/PrefManager.java +++ b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/activities/tutorial/PrefManager.java @@ -2,12 +2,28 @@ package org.secuso.privacyfriendlybreakreminder.activities.tutorial; import android.content.Context; import android.content.SharedPreferences; +import android.preference.PreferenceManager; /** * Class structure taken from tutorial at http://www.androidhive.info/2016/05/android-build-intro-slider-app/ */ public class PrefManager { + private static final String TAG = PrefManager.class.getSimpleName(); + + public static final String PREF_PICKER_SECONDS = TAG + ".PREF_PICKER_SECONDS"; + public static final String PREF_PICKER_MINUTES = TAG + ".PREF_PICKER_MINUTES"; + public static final String PREF_PICKER_HOURS = TAG + ".PREF_PICKER_HOURS"; + public static final String PREF_BREAK_PICKER_SECONDS = TAG + ".PREF_BREAK_PICKER_SECONDS"; + public static final String PREF_BREAK_PICKER_MINUTES = TAG + ".PREF_BREAK_PICKER_MINUTES"; + + public static final String DEFAULT_EXERCISE_SET = "DEFAULT_EXERCISE_SET"; + public static final String PAUSE_TIME = "PAUSE TIME"; + public static final String REPEAT_STATUS = "REPEAT_STATUS"; + public static final String CONTINUOUS_STATUS = "CONTINUOUS_STATUS"; + + private SharedPreferences pref; + private SharedPreferences defaultPref; // Shared preferences file name private static final String PREF_NAME = "welcome"; @@ -16,6 +32,7 @@ public class PrefManager { public PrefManager(Context context) { pref = context.getSharedPreferences(PREF_NAME, 0); + defaultPref = PreferenceManager.getDefaultSharedPreferences(context); } public void setFirstTimeLaunch(boolean isFirstTime) { @@ -23,7 +40,22 @@ public class PrefManager { } public boolean isFirstTimeLaunch() { - return pref.getBoolean(IS_FIRST_TIME_LAUNCH, true); + boolean isFirstTimeLaunch = pref.getBoolean(IS_FIRST_TIME_LAUNCH, true); + + if(isFirstTimeLaunch) + defaultPref.edit() + .putLong(DEFAULT_EXERCISE_SET, 0L) + .putLong(PAUSE_TIME, 5 * 60 * 1000) + .putBoolean(REPEAT_STATUS, false) + .putBoolean(CONTINUOUS_STATUS, false) + .putInt(PREF_BREAK_PICKER_SECONDS, 0) + .putInt(PREF_BREAK_PICKER_MINUTES, 5) + .putInt(PREF_PICKER_SECONDS, 0) + .putInt(PREF_PICKER_MINUTES, 0) + .putInt(PREF_PICKER_HOURS, 1) + .apply(); + + return isFirstTimeLaunch; } } diff --git a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/database/SQLiteHelper.java b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/database/SQLiteHelper.java index e34493e..eb68564 100644 --- a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/database/SQLiteHelper.java +++ b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/database/SQLiteHelper.java @@ -9,6 +9,8 @@ import android.database.sqlite.SQLiteOpenHelper; import android.support.annotation.NonNull; import android.util.Log; +import com.readystatesoftware.sqliteasset.SQLiteAssetHelper; + import org.secuso.privacyfriendlybreakreminder.database.columns.ExerciseSetColumns; import org.secuso.privacyfriendlybreakreminder.database.data.Exercise; import org.secuso.privacyfriendlybreakreminder.database.columns.ExerciseColumns; @@ -23,48 +25,48 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; -public class SQLiteHelper extends SQLiteOpenHelper { +public class SQLiteHelper extends SQLiteAssetHelper { private static final String TAG = SQLiteHelper.class.getSimpleName(); private Context mContext; private static final String DATABASE_NAME = "exercises.sqlite"; private static final String DATABASE_PATH = "/data/data/org.secuso.privacyfriendlybreakreminder/databases/"; - private static final int DATABASE_VERSION = 2; + private static final int DATABASE_VERSION = 1; private static final String[] deleteQueryList = { ExerciseColumns.SQL_DELETE_ENTRIES, ExerciseLocalColumns.SQL_DELETE_ENTRIES, ExerciseSetColumns.SQL_DELETE_ENTRIES}; - private boolean onCreate; - private boolean onUpgrade; +// private boolean onCreate; +// private boolean onUpgrade; public SQLiteHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); mContext = context; } - @Override - public void onOpen(SQLiteDatabase db) { - if (onCreate || onUpgrade) { - onCreate = onUpgrade = false; - copyDatabaseFromAssets(db); - } - } - - @Override - public void onCreate(SQLiteDatabase db) { - onCreate = true; - } - - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - onUpgrade = true; - } - - public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { - onUpgrade(db, oldVersion, newVersion); - } +// @Override +// public void onOpen(SQLiteDatabase db) { +// if (onCreate || onUpgrade) { +// onCreate = onUpgrade = false; +// copyDatabaseFromAssets(db); +// } +// } +// +// @Override +// public void onCreate(SQLiteDatabase db) { +// onCreate = true; +// } +// +// public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { +// onUpgrade = true; +// } +// +// public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { +// onUpgrade(db, oldVersion, newVersion); +// } public synchronized void deleteExerciseSet(long id) { diff --git a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/exercises/ExerciseSections.java b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/exercises/ExerciseSections.java index c8a58c4..aae2c47 100644 --- a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/exercises/ExerciseSections.java +++ b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/exercises/ExerciseSections.java @@ -2,12 +2,10 @@ package org.secuso.privacyfriendlybreakreminder.exercises; import android.content.Context; import android.support.annotation.StringRes; -import android.support.v4.content.ContextCompat; import org.secuso.privacyfriendlybreakreminder.R; import java.util.Arrays; -import java.util.LinkedList; import java.util.List; /** diff --git a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/service/TimerService.java b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/service/TimerService.java index 451147e..ee445dc 100644 --- a/app/src/main/java/org/secuso/privacyfriendlybreakreminder/service/TimerService.java +++ b/app/src/main/java/org/secuso/privacyfriendlybreakreminder/service/TimerService.java @@ -251,12 +251,12 @@ public class TimerService extends Service { } private void updateNotification() { - if(isRunning() || isPaused()) + if(isRunning() || isPaused()) { startForeground(NOTIFICATION_ID, buildNotification()); - else - stopForeground(false); - - notificationManager.notify(NOTIFICATION_ID, buildNotification()); + notificationManager.notify(NOTIFICATION_ID, buildNotification()); + } else { + stopForeground(true); + } } @Override diff --git a/app/src/main/res/drawable/button_section.xml b/app/src/main/res/drawable/button_section.xml new file mode 100644 index 0000000..ab7da09 --- /dev/null +++ b/app/src/main/res/drawable/button_section.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/button_section_textcolor.xml b/app/src/main/res/drawable/button_section_textcolor.xml new file mode 100644 index 0000000..937719f --- /dev/null +++ b/app/src/main/res/drawable/button_section_textcolor.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_repeat_black_48dp.xml b/app/src/main/res/drawable/ic_repeat_black_48dp.xml new file mode 100644 index 0000000..9092e30 --- /dev/null +++ b/app/src/main/res/drawable/ic_repeat_black_48dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_update_black_40dp.xml b/app/src/main/res/drawable/ic_update_black_40dp.xml new file mode 100644 index 0000000..52577d1 --- /dev/null +++ b/app/src/main/res/drawable/ic_update_black_40dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_choose_exercise.xml b/app/src/main/res/layout/activity_choose_exercise.xml index d19930c..3bbe37c 100644 --- a/app/src/main/res/layout/activity_choose_exercise.xml +++ b/app/src/main/res/layout/activity_choose_exercise.xml @@ -6,30 +6,37 @@ android:layout_height="match_parent" tools:context="org.secuso.privacyfriendlybreakreminder.activities.ChooseExerciseActivity"> - + app:layout_constraintTop_toTopOf="parent" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" /> + android:layout_marginBottom="4dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="4dp" /> diff --git a/app/src/main/res/layout/activity_exercise.xml b/app/src/main/res/layout/activity_exercise.xml index b302f42..693a871 100644 --- a/app/src/main/res/layout/activity_exercise.xml +++ b/app/src/main/res/layout/activity_exercise.xml @@ -44,7 +44,7 @@ app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:srcCompat="@drawable/ic_skip_next_black_48dp" - app:layout_constraintHorizontal_bias="0.75" /> + app:layout_constraintHorizontal_bias="0.6666" /> + app:layout_constraintHorizontal_bias="0.3333" /> - - - - - - - - - - + app:srcCompat="@drawable/ic_repeat_black_48dp" /> - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + android:text="00:00" + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.AppCompat.Large" + android:textColor="@color/colorPrimaryDark" + android:textSize="36sp" + android:textStyle="bold" + android:visibility="visible" + app:layout_constraintBottom_toBottomOf="@+id/progressBarBig" + app:layout_constraintLeft_toLeftOf="@+id/progressBarBig" + app:layout_constraintRight_toRightOf="@+id/progressBarBig" + app:layout_constraintTop_toTopOf="@+id/progressBarBig" /> + diff --git a/app/src/main/res/layout/activity_timer.xml b/app/src/main/res/layout/activity_timer.xml index bb9b526..d91fd11 100644 --- a/app/src/main/res/layout/activity_timer.xml +++ b/app/src/main/res/layout/activity_timer.xml @@ -99,7 +99,9 @@ + android:text="@string/activity_timer_choose_time" + android:textSize="18sp" + android:textStyle="bold" /> + android:text="@string/activity_timer_choose_break" + android:layout_marginTop="8dp" + android:textSize="18sp" + android:textStyle="bold" /> + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e68fceb..b74f7d0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -297,7 +297,7 @@ Neck Arms Torso - Spinal Column + Spine Pelvis Legs Choose Exercises @@ -311,6 +311,10 @@ Time remaining: Select a work duration: Select a break duration: + Please specify a name. + Please select an item to delete. + Do you want to go back to the main menu? + Break time is up!