mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Refactor and write documentation for Habit
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.unit.models;
|
package org.isoron.uhabits.unit.models;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
import android.support.test.runner.AndroidJUnit4;
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
|
|
||||||
@@ -31,6 +32,8 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
|
import static org.hamcrest.core.IsNot.not;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@@ -43,6 +46,49 @@ public class HabitTest
|
|||||||
HabitFixtures.purgeHabits();
|
HabitFixtures.purgeHabits();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructor_default()
|
||||||
|
{
|
||||||
|
Habit habit = new Habit();
|
||||||
|
assertThat(habit.archived, is(0));
|
||||||
|
assertThat(habit.highlight, is(0));
|
||||||
|
|
||||||
|
assertThat(habit.reminderDays, is(nullValue()));
|
||||||
|
assertThat(habit.reminderHour, is(nullValue()));
|
||||||
|
assertThat(habit.reminderMin, is(nullValue()));
|
||||||
|
|
||||||
|
assertThat(habit.streaks, is(not(nullValue())));
|
||||||
|
assertThat(habit.scores, is(not(nullValue())));
|
||||||
|
assertThat(habit.repetitions, is(not(nullValue())));
|
||||||
|
assertThat(habit.checkmarks, is(not(nullValue())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructor_habit()
|
||||||
|
{
|
||||||
|
Habit model = new Habit();
|
||||||
|
model.archived = 1;
|
||||||
|
model.highlight = 1;
|
||||||
|
model.color = Color.BLACK;
|
||||||
|
model.freqNum = 10;
|
||||||
|
model.freqDen = 20;
|
||||||
|
model.reminderDays = 1;
|
||||||
|
model.reminderHour = 8;
|
||||||
|
model.reminderMin = 30;
|
||||||
|
model.position = 0;
|
||||||
|
|
||||||
|
Habit habit = new Habit(model);
|
||||||
|
assertThat(habit.archived, is(model.archived));
|
||||||
|
assertThat(habit.highlight, is(model.highlight));
|
||||||
|
assertThat(habit.color, is(model.color));
|
||||||
|
assertThat(habit.freqNum, is(model.freqNum));
|
||||||
|
assertThat(habit.freqDen, is(model.freqDen));
|
||||||
|
assertThat(habit.reminderDays, is(model.reminderDays));
|
||||||
|
assertThat(habit.reminderHour, is(model.reminderHour));
|
||||||
|
assertThat(habit.reminderMin, is(model.reminderMin));
|
||||||
|
assertThat(habit.position, is(model.position));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void reorderTest()
|
public void reorderTest()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ import java.util.TimeZone;
|
|||||||
public class DateHelper
|
public class DateHelper
|
||||||
{
|
{
|
||||||
public static long millisecondsInOneDay = 24 * 60 * 60 * 1000;
|
public static long millisecondsInOneDay = 24 * 60 * 60 * 1000;
|
||||||
|
public static int ALL_WEEK_DAYS = 127;
|
||||||
|
|
||||||
private static Long fixedLocalTime = null;
|
private static Long fixedLocalTime = null;
|
||||||
|
|
||||||
public static long getLocalTime()
|
public static long getLocalTime()
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import android.view.View;
|
|||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
|
||||||
import org.isoron.uhabits.BuildConfig;
|
import org.isoron.uhabits.BuildConfig;
|
||||||
|
import org.isoron.uhabits.commands.Command;
|
||||||
|
|
||||||
public abstract class DialogHelper
|
public abstract class DialogHelper
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import android.os.Bundle;
|
|||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
|
import org.isoron.uhabits.commands.Command;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.commands;
|
package org.isoron.uhabits.commands;
|
||||||
|
|
||||||
import org.isoron.helpers.Command;
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
@@ -45,15 +44,13 @@ public class ArchiveHabitsCommand extends Command
|
|||||||
@Override
|
@Override
|
||||||
public void execute()
|
public void execute()
|
||||||
{
|
{
|
||||||
for(Habit h : habits)
|
Habit.archive(habits);
|
||||||
h.archive();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void undo()
|
public void undo()
|
||||||
{
|
{
|
||||||
for(Habit h : habits)
|
Habit.unarchive(habits);
|
||||||
h.unarchive();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getExecuteStringId()
|
public Integer getExecuteStringId()
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ package org.isoron.uhabits.commands;
|
|||||||
|
|
||||||
import com.activeandroid.ActiveAndroid;
|
import com.activeandroid.ActiveAndroid;
|
||||||
|
|
||||||
import org.isoron.helpers.Command;
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
@@ -47,22 +46,7 @@ public class ChangeHabitColorCommand extends Command
|
|||||||
@Override
|
@Override
|
||||||
public void execute()
|
public void execute()
|
||||||
{
|
{
|
||||||
ActiveAndroid.beginTransaction();
|
Habit.setColor(habits, newColor);
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for(Habit h : habits)
|
|
||||||
{
|
|
||||||
h.color = newColor;
|
|
||||||
h.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
ActiveAndroid.setTransactionSuccessful();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
ActiveAndroid.endTransaction();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.isoron.helpers;
|
package org.isoron.uhabits.commands;
|
||||||
|
|
||||||
public abstract class Command
|
public abstract class Command
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of Loop Habit Tracker.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.commands;
|
||||||
|
|
||||||
|
public class CommandFailedException extends RuntimeException
|
||||||
|
{
|
||||||
|
public CommandFailedException()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommandFailedException(String message)
|
||||||
|
{
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.commands;
|
package org.isoron.uhabits.commands;
|
||||||
|
|
||||||
import org.isoron.helpers.Command;
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
@@ -51,7 +50,10 @@ public class CreateHabitCommand extends Command
|
|||||||
@Override
|
@Override
|
||||||
public void undo()
|
public void undo()
|
||||||
{
|
{
|
||||||
Habit.get(savedId).delete();
|
Habit habit = Habit.get(savedId);
|
||||||
|
if(habit == null) throw new CommandFailedException("Habit not found");
|
||||||
|
|
||||||
|
habit.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.commands;
|
package org.isoron.uhabits.commands;
|
||||||
|
|
||||||
import org.isoron.helpers.Command;
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.commands;
|
package org.isoron.uhabits.commands;
|
||||||
|
|
||||||
import org.isoron.helpers.Command;
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
@@ -43,6 +42,8 @@ public class EditHabitCommand extends Command
|
|||||||
public void execute()
|
public void execute()
|
||||||
{
|
{
|
||||||
Habit habit = Habit.get(savedId);
|
Habit habit = Habit.get(savedId);
|
||||||
|
if(habit == null) throw new CommandFailedException("Habit not found");
|
||||||
|
|
||||||
habit.copyAttributes(modified);
|
habit.copyAttributes(modified);
|
||||||
habit.save();
|
habit.save();
|
||||||
if (hasIntervalChanged)
|
if (hasIntervalChanged)
|
||||||
@@ -56,6 +57,8 @@ public class EditHabitCommand extends Command
|
|||||||
public void undo()
|
public void undo()
|
||||||
{
|
{
|
||||||
Habit habit = Habit.get(savedId);
|
Habit habit = Habit.get(savedId);
|
||||||
|
if(habit == null) throw new CommandFailedException("Habit not found");
|
||||||
|
|
||||||
habit.copyAttributes(original);
|
habit.copyAttributes(original);
|
||||||
habit.save();
|
habit.save();
|
||||||
if (hasIntervalChanged)
|
if (hasIntervalChanged)
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.commands;
|
package org.isoron.uhabits.commands;
|
||||||
|
|
||||||
import org.isoron.helpers.Command;
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
public class ToggleRepetitionCommand extends Command
|
public class ToggleRepetitionCommand extends Command
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.commands;
|
package org.isoron.uhabits.commands;
|
||||||
|
|
||||||
import org.isoron.helpers.Command;
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
@@ -45,15 +44,13 @@ public class UnarchiveHabitsCommand extends Command
|
|||||||
@Override
|
@Override
|
||||||
public void execute()
|
public void execute()
|
||||||
{
|
{
|
||||||
for(Habit h : habits)
|
Habit.unarchive(habits);
|
||||||
h.unarchive();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void undo()
|
public void undo()
|
||||||
{
|
{
|
||||||
for(Habit h : habits)
|
Habit.archive(habits);
|
||||||
h.archive();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getExecuteStringId()
|
public Integer getExecuteStringId()
|
||||||
|
|||||||
@@ -39,16 +39,17 @@ import com.android.datetimepicker.time.RadialPickerLayout;
|
|||||||
import com.android.datetimepicker.time.TimePickerDialog;
|
import com.android.datetimepicker.time.TimePickerDialog;
|
||||||
|
|
||||||
import org.isoron.helpers.ColorHelper;
|
import org.isoron.helpers.ColorHelper;
|
||||||
import org.isoron.helpers.Command;
|
|
||||||
import org.isoron.helpers.DateHelper;
|
import org.isoron.helpers.DateHelper;
|
||||||
import org.isoron.helpers.DialogHelper.OnSavedListener;
|
import org.isoron.helpers.DialogHelper.OnSavedListener;
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
|
import org.isoron.uhabits.commands.Command;
|
||||||
import org.isoron.uhabits.commands.CreateHabitCommand;
|
import org.isoron.uhabits.commands.CreateHabitCommand;
|
||||||
import org.isoron.uhabits.commands.EditHabitCommand;
|
import org.isoron.uhabits.commands.EditHabitCommand;
|
||||||
import org.isoron.uhabits.dialogs.WeekdayPickerDialog;
|
import org.isoron.uhabits.dialogs.WeekdayPickerDialog;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
public class EditHabitFragment extends DialogFragment
|
public class EditHabitFragment extends DialogFragment
|
||||||
implements OnClickListener, WeekdayPickerDialog.OnWeekdaysPickedListener,
|
implements OnClickListener, WeekdayPickerDialog.OnWeekdaysPickedListener,
|
||||||
@@ -136,7 +137,10 @@ public class EditHabitFragment extends DialogFragment
|
|||||||
}
|
}
|
||||||
else if (mode == EDIT_MODE)
|
else if (mode == EDIT_MODE)
|
||||||
{
|
{
|
||||||
originalHabit = Habit.get((Long) args.get("habitId"));
|
Long habitId = (Long) args.get("habitId");
|
||||||
|
if(habitId == null) throw new IllegalArgumentException("habitId must be specified");
|
||||||
|
|
||||||
|
originalHabit = Habit.get(habitId);
|
||||||
modifiedHabit = new Habit(originalHabit);
|
modifiedHabit = new Habit(originalHabit);
|
||||||
|
|
||||||
getDialog().setTitle(R.string.edit_habit);
|
getDialog().setTitle(R.string.edit_habit);
|
||||||
@@ -178,14 +182,18 @@ public class EditHabitFragment extends DialogFragment
|
|||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
private void updateReminder()
|
private void updateReminder()
|
||||||
{
|
{
|
||||||
if (modifiedHabit.reminderHour != null)
|
if (modifiedHabit.hasReminder())
|
||||||
{
|
{
|
||||||
tvReminderTime.setTextColor(Color.BLACK);
|
tvReminderTime.setTextColor(Color.BLACK);
|
||||||
tvReminderTime.setText(DateHelper.formatTime(getActivity(), modifiedHabit.reminderHour,
|
tvReminderTime.setText(DateHelper.formatTime(getActivity(), modifiedHabit.reminderHour,
|
||||||
modifiedHabit.reminderMin));
|
modifiedHabit.reminderMin));
|
||||||
tvReminderDays.setVisibility(View.VISIBLE);
|
tvReminderDays.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
boolean weekdays[] = DateHelper.unpackWeekdayList(modifiedHabit.reminderDays);
|
||||||
|
tvReminderDays.setText(DateHelper.formatWeekdayList(getActivity(), weekdays));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -193,9 +201,6 @@ public class EditHabitFragment extends DialogFragment
|
|||||||
tvReminderTime.setText(R.string.reminder_off);
|
tvReminderTime.setText(R.string.reminder_off);
|
||||||
tvReminderDays.setVisibility(View.GONE);
|
tvReminderDays.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean weekdays[] = DateHelper.unpackWeekdayList(modifiedHabit.reminderDays);
|
|
||||||
tvReminderDays.setText(DateHelper.formatWeekdayList(getActivity(), weekdays));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnSavedListener(OnSavedListener onSavedListener)
|
public void setOnSavedListener(OnSavedListener onSavedListener)
|
||||||
@@ -303,12 +308,13 @@ public class EditHabitFragment extends DialogFragment
|
|||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
private void onDateSpinnerClick()
|
private void onDateSpinnerClick()
|
||||||
{
|
{
|
||||||
int defaultHour = 8;
|
int defaultHour = 8;
|
||||||
int defaultMin = 0;
|
int defaultMin = 0;
|
||||||
|
|
||||||
if (modifiedHabit.reminderHour != null)
|
if (modifiedHabit.hasReminder())
|
||||||
{
|
{
|
||||||
defaultHour = modifiedHabit.reminderHour;
|
defaultHour = modifiedHabit.reminderHour;
|
||||||
defaultMin = modifiedHabit.reminderMin;
|
defaultMin = modifiedHabit.reminderMin;
|
||||||
@@ -319,8 +325,11 @@ public class EditHabitFragment extends DialogFragment
|
|||||||
timePicker.show(getFragmentManager(), "timePicker");
|
timePicker.show(getFragmentManager(), "timePicker");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
private void onWeekdayClick()
|
private void onWeekdayClick()
|
||||||
{
|
{
|
||||||
|
if(!modifiedHabit.hasReminder()) return;
|
||||||
|
|
||||||
WeekdayPickerDialog dialog = new WeekdayPickerDialog();
|
WeekdayPickerDialog dialog = new WeekdayPickerDialog();
|
||||||
dialog.setListener(this);
|
dialog.setListener(this);
|
||||||
dialog.setSelectedDays(DateHelper.unpackWeekdayList(modifiedHabit.reminderDays));
|
dialog.setSelectedDays(DateHelper.unpackWeekdayList(modifiedHabit.reminderDays));
|
||||||
@@ -332,14 +341,14 @@ public class EditHabitFragment extends DialogFragment
|
|||||||
{
|
{
|
||||||
modifiedHabit.reminderHour = hour;
|
modifiedHabit.reminderHour = hour;
|
||||||
modifiedHabit.reminderMin = minute;
|
modifiedHabit.reminderMin = minute;
|
||||||
|
modifiedHabit.reminderDays = DateHelper.ALL_WEEK_DAYS;
|
||||||
updateReminder();
|
updateReminder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTimeCleared(RadialPickerLayout view)
|
public void onTimeCleared(RadialPickerLayout view)
|
||||||
{
|
{
|
||||||
modifiedHabit.reminderHour = null;
|
modifiedHabit.clearReminder();
|
||||||
modifiedHabit.reminderMin = null;
|
|
||||||
updateReminder();
|
updateReminder();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,12 +366,14 @@ public class EditHabitFragment extends DialogFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
public void onSaveInstanceState(Bundle outState)
|
public void onSaveInstanceState(Bundle outState)
|
||||||
{
|
{
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
|
|
||||||
outState.putInt("color", modifiedHabit.color);
|
outState.putInt("color", modifiedHabit.color);
|
||||||
if(modifiedHabit.reminderHour != null)
|
|
||||||
|
if(modifiedHabit.hasReminder())
|
||||||
{
|
{
|
||||||
outState.putInt("reminderMin", modifiedHabit.reminderMin);
|
outState.putInt("reminderMin", modifiedHabit.reminderMin);
|
||||||
outState.putInt("reminderHour", modifiedHabit.reminderHour);
|
outState.putInt("reminderHour", modifiedHabit.reminderHour);
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ import com.mobeta.android.dslv.DragSortController;
|
|||||||
import com.mobeta.android.dslv.DragSortListView;
|
import com.mobeta.android.dslv.DragSortListView;
|
||||||
import com.mobeta.android.dslv.DragSortListView.DropListener;
|
import com.mobeta.android.dslv.DragSortListView.DropListener;
|
||||||
|
|
||||||
import org.isoron.helpers.Command;
|
import org.isoron.uhabits.commands.Command;
|
||||||
import org.isoron.helpers.DateHelper;
|
import org.isoron.helpers.DateHelper;
|
||||||
import org.isoron.helpers.DialogHelper;
|
import org.isoron.helpers.DialogHelper;
|
||||||
import org.isoron.helpers.DialogHelper.OnSavedListener;
|
import org.isoron.helpers.DialogHelper.OnSavedListener;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import android.widget.LinearLayout;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.isoron.helpers.ColorHelper;
|
import org.isoron.helpers.ColorHelper;
|
||||||
import org.isoron.helpers.Command;
|
import org.isoron.uhabits.commands.Command;
|
||||||
import org.isoron.helpers.DialogHelper;
|
import org.isoron.helpers.DialogHelper;
|
||||||
import org.isoron.uhabits.HabitBroadcastReceiver;
|
import org.isoron.uhabits.HabitBroadcastReceiver;
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.isoron.helpers.DateHelper;
|
import org.isoron.helpers.DateHelper;
|
||||||
@@ -43,13 +44,17 @@ public class ReminderHelper
|
|||||||
createReminderAlarm(context, habit, null);
|
createReminderAlarm(context, habit, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void createReminderAlarm(Context context, Habit habit, Long reminderTime)
|
public static void createReminderAlarm(Context context, Habit habit, @Nullable Long reminderTime)
|
||||||
{
|
{
|
||||||
|
if(!habit.hasReminder()) return;
|
||||||
|
|
||||||
if (reminderTime == null)
|
if (reminderTime == null)
|
||||||
{
|
{
|
||||||
Calendar calendar = Calendar.getInstance();
|
Calendar calendar = Calendar.getInstance();
|
||||||
calendar.setTimeInMillis(System.currentTimeMillis());
|
calendar.setTimeInMillis(System.currentTimeMillis());
|
||||||
|
//noinspection ConstantConditions
|
||||||
calendar.set(Calendar.HOUR_OF_DAY, habit.reminderHour);
|
calendar.set(Calendar.HOUR_OF_DAY, habit.reminderHour);
|
||||||
|
//noinspection ConstantConditions
|
||||||
calendar.set(Calendar.MINUTE, habit.reminderMin);
|
calendar.set(Calendar.MINUTE, habit.reminderMin);
|
||||||
calendar.set(Calendar.SECOND, 0);
|
calendar.set(Calendar.SECOND, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ package org.isoron.uhabits.models;
|
|||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.activeandroid.ActiveAndroid;
|
import com.activeandroid.ActiveAndroid;
|
||||||
import com.activeandroid.Model;
|
import com.activeandroid.Model;
|
||||||
@@ -39,50 +41,113 @@ import java.util.List;
|
|||||||
@Table(name = "Habits")
|
@Table(name = "Habits")
|
||||||
public class Habit extends Model
|
public class Habit extends Model
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Name of the habit
|
||||||
|
*/
|
||||||
@Column(name = "name")
|
@Column(name = "name")
|
||||||
public String name;
|
public String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description of the habit
|
||||||
|
*/
|
||||||
@Column(name = "description")
|
@Column(name = "description")
|
||||||
public String description;
|
public String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frequency numerator. If a habit is performed 3 times in 7 days, this field equals 3.
|
||||||
|
*/
|
||||||
@Column(name = "freq_num")
|
@Column(name = "freq_num")
|
||||||
public Integer freqNum;
|
public Integer freqNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frequency denominator. If a habit is performed 3 times in 7 days, this field equals 7.
|
||||||
|
*/
|
||||||
@Column(name = "freq_den")
|
@Column(name = "freq_den")
|
||||||
public Integer freqDen;
|
public Integer freqDen;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Color of the habit. The format is the same as android.graphics.Color.
|
||||||
|
*/
|
||||||
@Column(name = "color")
|
@Column(name = "color")
|
||||||
public Integer color;
|
public Integer color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Position of the habit. Habits are usually sorted by this field.
|
||||||
|
*/
|
||||||
@Column(name = "position")
|
@Column(name = "position")
|
||||||
public Integer position;
|
public Integer position;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hour of the day the reminder should be shown. If there is no reminder, this equals to null.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
@Column(name = "reminder_hour")
|
@Column(name = "reminder_hour")
|
||||||
public Integer reminderHour;
|
public Integer reminderHour;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minute the reminder should be shown. If there is no reminder, this equals to null.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
@Column(name = "reminder_min")
|
@Column(name = "reminder_min")
|
||||||
public Integer reminderMin;
|
public Integer reminderMin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Days of the week the reminder should be shown. This field can be converted to a list of
|
||||||
|
* booleans using the method DateHelper.unpackWeekdayList and converted back to an integer by
|
||||||
|
* using the method DateHelper.packWeekdayList. If there is no reminder, it equals null.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
@Column(name = "reminder_days")
|
@Column(name = "reminder_days")
|
||||||
public Integer reminderDays;
|
public Integer reminderDays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not currently used.
|
||||||
|
*/
|
||||||
@Column(name = "highlight")
|
@Column(name = "highlight")
|
||||||
public Integer highlight;
|
public Integer highlight;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag that indicates whether the habit is archived. Archived habits are usually omitted from
|
||||||
|
* listings, unless explicitly included.
|
||||||
|
*/
|
||||||
@Column(name = "archived")
|
@Column(name = "archived")
|
||||||
public Integer archived;
|
public Integer archived;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of streaks belonging to this habit.
|
||||||
|
*/
|
||||||
public StreakList streaks;
|
public StreakList streaks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of scores belonging to this habit.
|
||||||
|
*/
|
||||||
public ScoreList scores;
|
public ScoreList scores;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of repetitions belonging to this habit.
|
||||||
|
*/
|
||||||
public RepetitionList repetitions;
|
public RepetitionList repetitions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of checkmarks belonging to this habit.
|
||||||
|
*/
|
||||||
public CheckmarkList checkmarks;
|
public CheckmarkList checkmarks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a habit with the same attributes as the specified habit.
|
||||||
|
*
|
||||||
|
* @param model the model whose attributes should be copied from
|
||||||
|
*/
|
||||||
public Habit(Habit model)
|
public Habit(Habit model)
|
||||||
{
|
{
|
||||||
copyAttributes(model);
|
copyAttributes(model);
|
||||||
initializeLists();
|
initializeLists();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a habit with default attributes. The habit is not archived, not highlighted, has
|
||||||
|
* no reminders and is placed in the last position of the list of habits.
|
||||||
|
*/
|
||||||
public Habit()
|
public Habit()
|
||||||
{
|
{
|
||||||
this.color = ColorHelper.palette[5];
|
this.color = ColorHelper.palette[5];
|
||||||
@@ -91,7 +156,6 @@ public class Habit extends Model
|
|||||||
this.archived = 0;
|
this.archived = 0;
|
||||||
this.freqDen = 7;
|
this.freqDen = 7;
|
||||||
this.freqNum = 3;
|
this.freqNum = 3;
|
||||||
this.reminderDays = 127;
|
|
||||||
initializeLists();
|
initializeLists();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,17 +167,36 @@ public class Habit extends Model
|
|||||||
checkmarks = new CheckmarkList(this);
|
checkmarks = new CheckmarkList(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Habit get(Long id)
|
/**
|
||||||
|
* Returns the habit with specified id.
|
||||||
|
*
|
||||||
|
* @param id the id of the habit
|
||||||
|
* @return the habit, or null if none exist
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static Habit get(@NonNull Long id)
|
||||||
{
|
{
|
||||||
return Habit.load(Habit.class, id);
|
return Habit.load(Habit.class, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all habits, optionally including archived habits.
|
||||||
|
*
|
||||||
|
* @param includeArchive whether archived habits should be included the list
|
||||||
|
* @return list of all habits
|
||||||
|
*/
|
||||||
public static List<Habit> getAll(boolean includeArchive)
|
public static List<Habit> getAll(boolean includeArchive)
|
||||||
{
|
{
|
||||||
if(includeArchive) return selectWithArchived().execute();
|
if(includeArchive) return selectWithArchived().execute();
|
||||||
else return select().execute();
|
else return select().execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the id of a habit on the database.
|
||||||
|
*
|
||||||
|
* @param oldId the original id
|
||||||
|
* @param newId the new id
|
||||||
|
*/
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
public static void updateId(long oldId, long newId)
|
public static void updateId(long oldId, long newId)
|
||||||
{
|
{
|
||||||
@@ -125,21 +208,32 @@ public class Habit extends Model
|
|||||||
return new Select().from(Habit.class).where("archived = 0").orderBy("position");
|
return new Select().from(Habit.class).where("archived = 0").orderBy("position");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static From selectWithArchived()
|
protected static From selectWithArchived()
|
||||||
{
|
{
|
||||||
return new Select().from(Habit.class).orderBy("position");
|
return new Select().from(Habit.class).orderBy("position");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total number of unarchived habits.
|
||||||
|
*
|
||||||
|
* @return number of unarchived habits
|
||||||
|
*/
|
||||||
public static int count()
|
public static int count()
|
||||||
{
|
{
|
||||||
return select().count();
|
return select().count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the total number of habits, including archived habits.
|
||||||
|
*
|
||||||
|
* @return number of habits, including archived
|
||||||
|
*/
|
||||||
public static int countWithArchived()
|
public static int countWithArchived()
|
||||||
{
|
{
|
||||||
return selectWithArchived().count();
|
return selectWithArchived().count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static java.util.List<Habit> getHighlightedHabits()
|
public static java.util.List<Habit> getHighlightedHabits()
|
||||||
{
|
{
|
||||||
return select().where("highlight = 1")
|
return select().where("highlight = 1")
|
||||||
@@ -147,11 +241,22 @@ public class Habit extends Model
|
|||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static java.util.List<Habit> getHabitsWithReminder()
|
/**
|
||||||
|
* Returns a list the habits that have a reminder. Does not include archived habits.
|
||||||
|
*
|
||||||
|
* @return list of habits with reminder
|
||||||
|
*/
|
||||||
|
public static List<Habit> getHabitsWithReminder()
|
||||||
{
|
{
|
||||||
return select().where("reminder_hour is not null").execute();
|
return select().where("reminder_hour is not null").execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the position of a habit in the list.
|
||||||
|
*
|
||||||
|
* @param from the habit that should be moved
|
||||||
|
* @param to the habit that currently occupies the desired position
|
||||||
|
*/
|
||||||
public static void reorder(Habit from, Habit to)
|
public static void reorder(Habit from, Habit to)
|
||||||
{
|
{
|
||||||
if(from == to) return;
|
if(from == to) return;
|
||||||
@@ -173,6 +278,10 @@ public class Habit extends Model
|
|||||||
from.save();
|
from.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recompute the field position for every habit in the database. It should never be necessary
|
||||||
|
* to call this method.
|
||||||
|
*/
|
||||||
public static void rebuildOrder()
|
public static void rebuildOrder()
|
||||||
{
|
{
|
||||||
List<Habit> habits = selectWithArchived().execute();
|
List<Habit> habits = selectWithArchived().execute();
|
||||||
@@ -196,6 +305,11 @@ public class Habit extends Model
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies all the attributes of the specified habit into this habit
|
||||||
|
*
|
||||||
|
* @param model the model whose attributes should be copied from
|
||||||
|
*/
|
||||||
public void copyAttributes(Habit model)
|
public void copyAttributes(Habit model)
|
||||||
{
|
{
|
||||||
this.name = model.name;
|
this.name = model.name;
|
||||||
@@ -211,12 +325,21 @@ public class Habit extends Model
|
|||||||
this.archived = model.archived;
|
this.archived = model.archived;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the habit on the database, and assigns the specified id to it.
|
||||||
|
*
|
||||||
|
* @param id the id that the habit should receive
|
||||||
|
*/
|
||||||
public void save(Long id)
|
public void save(Long id)
|
||||||
{
|
{
|
||||||
save();
|
save();
|
||||||
Habit.updateId(getId(), id);
|
Habit.updateId(getId(), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the habit and all data associated to it, including checkmarks, repetitions and
|
||||||
|
* scores.
|
||||||
|
*/
|
||||||
public void cascadeDelete()
|
public void cascadeDelete()
|
||||||
{
|
{
|
||||||
Long id = getId();
|
Long id = getId();
|
||||||
@@ -238,25 +361,93 @@ public class Habit extends Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the public URI that identifies this habit
|
||||||
|
* @return the uri
|
||||||
|
*/
|
||||||
public Uri getUri()
|
public Uri getUri()
|
||||||
{
|
{
|
||||||
return Uri.parse(String.format("content://org.isoron.uhabits/habit/%d", getId()));
|
return Uri.parse(String.format("content://org.isoron.uhabits/habit/%d", getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void archive()
|
/**
|
||||||
{
|
* Returns whether the habit is archived or not.
|
||||||
archived = 1;
|
* @return true if archived
|
||||||
save();
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
public void unarchive()
|
|
||||||
{
|
|
||||||
archived = 0;
|
|
||||||
save();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isArchived()
|
public boolean isArchived()
|
||||||
{
|
{
|
||||||
return archived != 0;
|
return archived != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void updateAttributes(List<Habit> habits, Integer color, Integer archived)
|
||||||
|
{
|
||||||
|
ActiveAndroid.beginTransaction();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (Habit h : habits)
|
||||||
|
{
|
||||||
|
if(color != null) h.color = color;
|
||||||
|
if(archived != null) h.archived = archived;
|
||||||
|
h.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
ActiveAndroid.setTransactionSuccessful();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
ActiveAndroid.endTransaction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Archives an entire list of habits
|
||||||
|
*
|
||||||
|
* @param habits the habits to be archived
|
||||||
|
*/
|
||||||
|
public static void archive(List<Habit> habits)
|
||||||
|
{
|
||||||
|
updateAttributes(habits, null, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unarchives an entire list of habits
|
||||||
|
*
|
||||||
|
* @param habits the habits to be unarchived
|
||||||
|
*/
|
||||||
|
public static void unarchive(List<Habit> habits)
|
||||||
|
{
|
||||||
|
updateAttributes(habits, null, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the color for an entire list of habits.
|
||||||
|
*
|
||||||
|
* @param habits the habits to be modified
|
||||||
|
* @param color the new color to be set
|
||||||
|
*/
|
||||||
|
public static void setColor(List<Habit> habits, int color)
|
||||||
|
{
|
||||||
|
updateAttributes(habits, color, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the habit has a reminder set.
|
||||||
|
*
|
||||||
|
* @return true if habit has reminder
|
||||||
|
*/
|
||||||
|
public boolean hasReminder()
|
||||||
|
{
|
||||||
|
return (reminderHour != null && reminderMin != null && reminderDays != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the reminder for a habit. This sets all the related fields to null.
|
||||||
|
*/
|
||||||
|
public void clearReminder()
|
||||||
|
{
|
||||||
|
reminderHour = null;
|
||||||
|
reminderMin = null;
|
||||||
|
reminderDays = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user