From 47af28546b0845f1f097bff7976155838ca62cec Mon Sep 17 00:00:00 2001 From: Keith Holliday Date: Mon, 10 Apr 2017 14:23:42 -0600 Subject: [PATCH] Added initial repeatabls UI --- Habitica/res/layout/activity_task_form.xml | 75 ++++-- Habitica/res/layout/tasks_startdate.xml | 23 ++ Habitica/res/values/strings.xml | 10 + Habitica/res/values/values.xml | 12 + .../ui/activities/TaskFormActivity.java | 231 ++++++++++++++++++ gradle.properties | 3 + 6 files changed, 334 insertions(+), 20 deletions(-) create mode 100644 Habitica/res/layout/tasks_startdate.xml create mode 100644 gradle.properties diff --git a/Habitica/res/layout/activity_task_form.xml b/Habitica/res/layout/activity_task_form.xml index a68c12a43..6ab5c2fcc 100644 --- a/Habitica/res/layout/activity_task_form.xml +++ b/Habitica/res/layout/activity_task_form.xml @@ -231,6 +231,7 @@ @@ -257,21 +258,7 @@ android:layout_marginTop="20dp" android:orientation="vertical"> - - - + @@ -294,7 +281,34 @@ android:layout_marginTop="20dp" android:orientation="vertical"> - + + + + + + + + android:text="@string/repeatables_on_title" + android:id="@+id/repeatables_on_title" + android:textAppearance="?android:attr/textAppearanceMedium" /> + + + + @@ -325,8 +352,16 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:is="@id+/summary" - android:textAppearance="?android:attr/textAppearanceLarge" /> + android:id="@+id/summaryTitle" + android:text="@string/repeatables_summary_title" + android:textAppearance="?android:attr/textAppearanceMedium" /> + + diff --git a/Habitica/res/layout/tasks_startdate.xml b/Habitica/res/layout/tasks_startdate.xml new file mode 100644 index 000000000..7423d86e6 --- /dev/null +++ b/Habitica/res/layout/tasks_startdate.xml @@ -0,0 +1,23 @@ + + + + + + + + \ No newline at end of file diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml index 31943442f..86d49d168 100644 --- a/Habitica/res/values/strings.xml +++ b/Habitica/res/values/strings.xml @@ -118,6 +118,16 @@ On Certain Days of the Week Every X Days + Summary + Repeats + Repeats On + Daily + Weekly + Monthly + Yearly + Day of Month + Day of Week + Monday Tuesday Wednesday diff --git a/Habitica/res/values/values.xml b/Habitica/res/values/values.xml index 5b9a18efe..8619ffcc2 100644 --- a/Habitica/res/values/values.xml +++ b/Habitica/res/values/values.xml @@ -19,6 +19,18 @@ @string/frequency_daily + + @string/repeatables_frequency_daily + @string/repeatables_frequency_weekly + @string/repeatables_frequency_monthly + @string/repeatables_frequency_yearly + + + + @string/repeatables_frequency_day_of_month + @string/repeatables_frequency_day_of_week + + @string/monday @string/tuesday diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java index 3fa63ec30..6afdaec17 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/TaskFormActivity.java @@ -1,10 +1,35 @@ package com.habitrpg.android.habitica.ui.activities; + +import com.habitrpg.android.habitica.R; +import com.habitrpg.android.habitica.components.AppComponent; +import com.habitrpg.android.habitica.events.TaskSaveEvent; +import com.habitrpg.android.habitica.events.commands.DeleteTaskCommand; +import com.habitrpg.android.habitica.helpers.FirstDayOfTheWeekHelper; +import com.habitrpg.android.habitica.helpers.RemindersManager; +import com.habitrpg.android.habitica.helpers.RemoteConfigManager; +import com.habitrpg.android.habitica.helpers.TaskFilterHelper; +import com.habitrpg.android.habitica.helpers.TaskAlarmManager; +import com.habitrpg.android.habitica.ui.WrapContentRecyclerViewLayoutManager; +import com.habitrpg.android.habitica.ui.adapter.tasks.CheckListAdapter; +import com.habitrpg.android.habitica.ui.adapter.tasks.RemindersAdapter; +import com.habitrpg.android.habitica.ui.helpers.MarkdownParser; +import com.habitrpg.android.habitica.ui.helpers.SimpleItemTouchHelperCallback; +import com.habitrpg.android.habitica.ui.helpers.ViewHelper; +import com.raizlabs.android.dbflow.sql.builder.Condition; +import com.raizlabs.android.dbflow.sql.language.Select; + +import net.pherth.android.emoji_library.EmojiEditText; +import net.pherth.android.emoji_library.EmojiPopup; + +import org.greenrobot.eventbus.EventBus; + import android.app.DatePickerDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; +import android.content.res.Resources; import android.os.Build; import android.os.Bundle; import android.support.annotation.Nullable; @@ -17,10 +42,12 @@ import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.text.TextUtils; +import android.util.TypedValue; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.ArrayAdapter; @@ -28,9 +55,11 @@ import android.widget.Button; import android.widget.CheckBox; import android.widget.DatePicker; import android.widget.EditText; +import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.NumberPicker; +import android.widget.RelativeLayout; import android.widget.Spinner; import android.widget.TableRow; import android.widget.TextView; @@ -138,6 +167,9 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem @BindView(R.id.task_weekdays_wrapper) LinearLayout weekdayWrapper; + @BindView(R.id.frequency_title) + TextView frequencyTitleTextView; + @BindView(R.id.task_frequency_spinner) Spinner dailyFrequencySpinner; @@ -178,10 +210,31 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem @BindView(R.id.duedate_checkbox) CheckBox dueDateCheckBox; + @BindView(R.id.startdate_text_title) + TextView startDateTitleTextView; @BindView(R.id.startdate_text_edittext) EditText startDatePickerText; + @BindView (R.id.repeatables_startdate_text_edittext) + EditText repeatablesStartDatePickerText; DateEditTextListener startDateListener; + @BindView(R.id.repeatables) + LinearLayout repeatablesLayout; + + @BindView(R.id.repeatables_on_title) + TextView reapeatablesOnTextView; + @BindView(R.id.task_repeatables_on_spinner) + Spinner repeatablesOnSpinner; + + @BindView(R.id.task_repeatables_every_x_spinner) + NumberPicker repeatablesEveryXSpinner; + + @BindView(R.id.task_repeatables_frequency_container) + LinearLayout repeatablesFrequencyContainer; + + @BindView(R.id.summary) + TextView summaryTextView; + @BindView(R.id.duedate_text_edittext) EditText dueDatePickerText; DateEditTextListener dueDateListener; @@ -192,6 +245,9 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem @BindView(R.id.task_tags_checklist) LinearLayout tagsContainerLinearLayout; + @BindView(R.id.task_repeatables_frequency_spinner) + Spinner repeatablesFrequencySpinner; + @Inject TaskFilterHelper taskFilterHelper; @@ -404,6 +460,8 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem emojiToggle2.setOnClickListener(new emojiClickListener(newCheckListEditText)); } + enableRepeatables(); + Observable.defer(() -> Observable.just(new Select().from(Tag.class) .where(Condition.column("user_id").eq(this.userId)) .queryList()) @@ -420,7 +478,170 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem ); } + // @TODO: abstract business logic to Presenter and only modify view? + private void enableRepeatables() + { + if (!RemoteConfigManager.repeatablesAreEnabled()){ + return; + } + if (!taskType.equals("daily")) { + repeatablesLayout.setVisibility(View.INVISIBLE); + ViewGroup.LayoutParams repeatablesLayoutParams = repeatablesLayout.getLayoutParams(); + repeatablesLayoutParams.height = 0; + repeatablesLayout.setLayoutParams(repeatablesLayoutParams); + return; + }; + + startDateLayout.setVisibility(View.INVISIBLE); + + ViewGroup.LayoutParams startDateLayoutParams = startDateLayout.getLayoutParams(); + startDateLayoutParams.height = 0; + startDateLayout.setLayoutParams(startDateLayoutParams); + + ViewGroup.LayoutParams startDatePickerTextParams = startDatePickerText.getLayoutParams(); + startDatePickerTextParams.height = 0; + startDatePickerText.setLayoutParams(startDatePickerTextParams); + + ViewGroup.LayoutParams startDateTitleTextViewParams = startDateTitleTextView.getLayoutParams(); + startDateTitleTextViewParams.height = 0; + startDateTitleTextView.setLayoutParams(startDateTitleTextViewParams); + + weekdayWrapper.setVisibility(View.INVISIBLE); + ViewGroup.LayoutParams weekdayWrapperParams = weekdayWrapper.getLayoutParams(); + weekdayWrapperParams.height = 0; + weekdayWrapper.setLayoutParams(weekdayWrapperParams); + + ViewGroup.LayoutParams frequencyTitleTextViewParams = frequencyTitleTextView.getLayoutParams(); + frequencyTitleTextViewParams.height = 0; + frequencyTitleTextView.setLayoutParams(frequencyTitleTextViewParams); + + ViewGroup.LayoutParams dailyFrequencySpinnerParams = dailyFrequencySpinner.getLayoutParams(); + dailyFrequencySpinnerParams.height = 0; + dailyFrequencySpinner.setLayoutParams(dailyFrequencySpinnerParams); + + startDateListener = new DateEditTextListener(repeatablesStartDatePickerText); + + ArrayAdapter frequencyAdapter = ArrayAdapter.createFromResource(this, + R.array.repeatables_frequencies, android.R.layout.simple_spinner_item); + frequencyAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + this.repeatablesFrequencySpinner.setAdapter(frequencyAdapter); + this.repeatablesFrequencySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + generateSummary(); + Resources r = getResources(); + + // @TODO: remove magic numbers + + if (position == 2) { + ViewGroup.LayoutParams repeatablesOnSpinnerParams = repeatablesOnSpinner.getLayoutParams(); + repeatablesOnSpinnerParams.height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 72, r.getDisplayMetrics()); + repeatablesOnSpinner.setLayoutParams(repeatablesOnSpinnerParams); + + ViewGroup.LayoutParams repeatablesOnTitleParams = reapeatablesOnTextView.getLayoutParams(); + repeatablesOnTitleParams.height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, r.getDisplayMetrics()); + reapeatablesOnTextView.setLayoutParams(repeatablesOnTitleParams); + + return; + } + + if (position == 1) { + ViewGroup.LayoutParams repeatablesFrequencyContainerParams = repeatablesFrequencyContainer.getLayoutParams(); + repeatablesFrequencyContainerParams.height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 172, r.getDisplayMetrics()); + repeatablesFrequencyContainer.setLayoutParams(repeatablesFrequencyContainerParams); + return; + } + + ViewGroup.LayoutParams repeatablesOnSpinnerParams = repeatablesOnSpinner.getLayoutParams(); + repeatablesOnSpinnerParams.height = 0; + repeatablesOnSpinner.setLayoutParams(repeatablesOnSpinnerParams); + + ViewGroup.LayoutParams repeatablesOnTitleParams = reapeatablesOnTextView.getLayoutParams(); + repeatablesOnTitleParams.height = 0; + reapeatablesOnTextView.setLayoutParams(repeatablesOnTitleParams); + + ViewGroup.LayoutParams repeatablesFrequencyContainerParams = repeatablesFrequencyContainer.getLayoutParams(); + repeatablesFrequencyContainerParams.height = 0; + repeatablesFrequencyContainer.setLayoutParams(repeatablesFrequencyContainerParams); + } + + @Override + public void onNothingSelected(AdapterView parent) { + + } + }); + + ArrayAdapter repeatablesOnAdapter = ArrayAdapter.createFromResource(this, + R.array.repeatables_on, android.R.layout.simple_spinner_item); + repeatablesOnAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + this.repeatablesOnSpinner.setAdapter(repeatablesOnAdapter); + this.repeatablesOnSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + generateSummary(); + } + + @Override + public void onNothingSelected(AdapterView parent) { + + } + }); + + setEveryXSpinner(repeatablesEveryXSpinner); + repeatablesEveryXSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() { + @Override + public void onValueChange(NumberPicker picker, int oldVal, int newVal) { + generateSummary(); + } + }); + + String[] weekdays = getResources().getStringArray(R.array.weekdays); + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + String dayOfTheWeek = sharedPreferences.getString("FirstDayOfTheWeek", + Integer.toString(Calendar.getInstance().getFirstDayOfWeek())); + firstDayOfTheWeekHelper = + FirstDayOfTheWeekHelper.newInstance(Integer.parseInt(dayOfTheWeek)); + ArrayList weekdaysTemp = new ArrayList<>(Arrays.asList(weekdays)); + Collections.rotate(weekdaysTemp, firstDayOfTheWeekHelper.getDailyTaskFormOffset()); + weekdays = weekdaysTemp.toArray(new String[1]); + + for (int i = 0; i < 7; i++) { + View weekdayRow = getLayoutInflater().inflate(R.layout.row_checklist, repeatablesFrequencyContainer, false); + CheckBox checkbox = (CheckBox) weekdayRow.findViewById(R.id.checkbox); + checkbox.setText(weekdays[i]); + checkbox.setChecked(true); + frequencyContainer.addView(weekdayRow); + } + + generateSummary(); + } + + private void generateSummary () { + String frequency = repeatablesFrequencySpinner.getSelectedItem().toString(); + String everyX = String.valueOf(repeatablesEveryXSpinner.getValue()); + String frequencyQualifier = ""; + + switch (frequency) { + case "Daily": + frequencyQualifier = "day(s)"; + break; + case "Weekly": + frequencyQualifier = "week(s)"; + break; + case "Monthly": + frequencyQualifier = "month(s)"; + break; + case "Yearly": + frequencyQualifier = "year(s)"; + break; + } + + String weekdays = ""; + + String summary = "Repeats " + frequency + " every " + everyX + " " + frequencyQualifier + " on " + weekdays; + summaryTextView.setText(summary); + } @Override protected void injectActivity(AppComponent component) { @@ -564,6 +785,16 @@ public class TaskFormActivity extends BaseActivity implements AdapterView.OnItem } } + private void setEveryXSpinner(NumberPicker frequencyPicker) { +// View dayRow = getLayoutInflater().inflate(R.layout.row_number_picker, this.frequencyContainer, false); +// frequencyPicker = (NumberPicker) dayRow.findViewById(R.id.numberPicker); + frequencyPicker.setMinValue(1); + frequencyPicker.setMaxValue(366); +// TextView tv = (TextView) dayRow.findViewById(R.id.label); +// tv.setText(getResources().getString(R.string.frequency_daily)); +// this.frequencyContainer.addView(dayRow); + } + private void setDailyFrequencyViews() { this.frequencyContainer.removeAllViews(); if (this.dailyFrequencySpinner.getSelectedItemPosition() == 0) { diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 000000000..3fcfe5803 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.configureondemand=true +org.gradle.daemon=true +org.gradle.jvmargs=-Xmx2048m \ No newline at end of file