mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Add notification actions (check, snooze)
This commit is contained in:
BIN
res/drawable-hdpi/ic_action_snooze.png
Normal file
BIN
res/drawable-hdpi/ic_action_snooze.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
BIN
res/drawable-mdpi/ic_action_snooze.png
Normal file
BIN
res/drawable-mdpi/ic_action_snooze.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 694 B |
22
res/drawable-v21/habits_item_check_normal.xml
Normal file
22
res/drawable-v21/habits_item_check_normal.xml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
<item>
|
||||||
|
<shape android:shape="oval" >
|
||||||
|
<gradient
|
||||||
|
android:endColor="#00000000"
|
||||||
|
android:gradientRadius="50%p"
|
||||||
|
android:startColor="#50000000"
|
||||||
|
android:type="radial" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item
|
||||||
|
android:bottom="6dp"
|
||||||
|
android:left="4dp"
|
||||||
|
android:right="4dp"
|
||||||
|
android:top="2dp">
|
||||||
|
<shape android:shape="oval" >
|
||||||
|
<solid android:color="#ffffff" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
</layer-list>
|
||||||
22
res/drawable-v21/habits_item_check_pressed.xml
Normal file
22
res/drawable-v21/habits_item_check_pressed.xml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||||
|
<item>
|
||||||
|
<shape android:shape="oval" >
|
||||||
|
<gradient
|
||||||
|
android:endColor="#00000000"
|
||||||
|
android:gradientRadius="50%p"
|
||||||
|
android:startColor="#50000000"
|
||||||
|
android:type="radial" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item
|
||||||
|
android:bottom="6dp"
|
||||||
|
android:left="4dp"
|
||||||
|
android:right="4dp"
|
||||||
|
android:top="2dp">
|
||||||
|
<shape android:shape="oval" >
|
||||||
|
<solid android:color="#20000000" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
</layer-list>
|
||||||
BIN
res/drawable-xhdpi/ic_action_snooze.png
Normal file
BIN
res/drawable-xhdpi/ic_action_snooze.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
res/drawable-xxhdpi/ic_action_snooze.png
Normal file
BIN
res/drawable-xxhdpi/ic_action_snooze.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
@@ -4,7 +4,7 @@
|
|||||||
<shape android:shape="oval" >
|
<shape android:shape="oval" >
|
||||||
<gradient
|
<gradient
|
||||||
android:endColor="#00000000"
|
android:endColor="#00000000"
|
||||||
android:gradientRadius="50%p"
|
android:gradientRadius="@dimen/radius"
|
||||||
android:startColor="#50000000"
|
android:startColor="#50000000"
|
||||||
android:type="radial" />
|
android:type="radial" />
|
||||||
</shape>
|
</shape>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<shape android:shape="oval" >
|
<shape android:shape="oval" >
|
||||||
<gradient
|
<gradient
|
||||||
android:endColor="#00000000"
|
android:endColor="#00000000"
|
||||||
android:gradientRadius="50%p"
|
android:gradientRadius="@dimen/radius"
|
||||||
android:startColor="#50000000"
|
android:startColor="#50000000"
|
||||||
android:type="radial" />
|
android:type="radial" />
|
||||||
</shape>
|
</shape>
|
||||||
|
|||||||
@@ -42,4 +42,6 @@
|
|||||||
<string name="habit_key"></string>
|
<string name="habit_key"></string>
|
||||||
<string name="offset_key"></string>
|
<string name="offset_key"></string>
|
||||||
|
|
||||||
|
<item type="id" name="KEY_TIMESTAMP"/>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -21,6 +21,11 @@ public class DateHelper
|
|||||||
return (timestamp / millisecondsInOneDay) * millisecondsInOneDay;
|
return (timestamp / millisecondsInOneDay) * millisecondsInOneDay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long getStartOfToday()
|
||||||
|
{
|
||||||
|
return getStartOfDay(DateHelper.getLocalTime());
|
||||||
|
}
|
||||||
|
|
||||||
// public static Date getStartOfDay(Date date)
|
// public static Date getStartOfDay(Date date)
|
||||||
// {
|
// {
|
||||||
// Calendar calendar = Calendar.getInstance();
|
// Calendar calendar = Calendar.getInstance();
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ import android.app.PendingIntent;
|
|||||||
import android.content.Context;
|
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.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@@ -44,43 +46,64 @@ public class MainActivity extends Activity
|
|||||||
showHabitsFragment = (ShowHabitsFragment) getFragmentManager().findFragmentById(
|
showHabitsFragment = (ShowHabitsFragment) getFragmentManager().findFragmentById(
|
||||||
R.id.fragment1);
|
R.id.fragment1);
|
||||||
|
|
||||||
|
Log.d("MainActivity", "Creating activity");
|
||||||
|
|
||||||
undoList = new LinkedList<Command>();
|
undoList = new LinkedList<Command>();
|
||||||
redoList = new LinkedList<Command>();
|
redoList = new LinkedList<Command>();
|
||||||
|
|
||||||
createReminderAlarms();
|
createReminderAlarms(MainActivity.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createReminderAlarms()
|
@Override
|
||||||
|
protected void onStart()
|
||||||
|
{
|
||||||
|
super.onStart();
|
||||||
|
showHabitsFragment.notifyDataSetChanged();
|
||||||
|
Log.d("MainActivity", "Starting activity");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void createReminderAlarms(Context context)
|
||||||
{
|
{
|
||||||
for(Habit habit : Habit.getHabitsWithReminder())
|
for(Habit habit : Habit.getHabitsWithReminder())
|
||||||
{
|
createReminderAlarm(context, habit, null);
|
||||||
Uri uri = Uri.parse("content://org.isoron.uhabits/habit/" + habit.getId());
|
}
|
||||||
|
|
||||||
|
public static void createReminderAlarm(Context context, Habit habit, Long reminderTime)
|
||||||
|
{
|
||||||
|
Uri uri = Uri.parse("content://org.isoron.uhabits/habit/" + habit.getId());
|
||||||
|
|
||||||
|
if(reminderTime == null)
|
||||||
|
{
|
||||||
Calendar calendar = Calendar.getInstance();
|
Calendar calendar = Calendar.getInstance();
|
||||||
calendar.setTimeInMillis(System.currentTimeMillis());
|
calendar.setTimeInMillis(System.currentTimeMillis());
|
||||||
calendar.set(Calendar.HOUR_OF_DAY, habit.reminder_hour);
|
calendar.set(Calendar.HOUR_OF_DAY, habit.reminder_hour);
|
||||||
calendar.set(Calendar.MINUTE, habit.reminder_min);
|
calendar.set(Calendar.MINUTE, habit.reminder_min);
|
||||||
calendar.set(Calendar.SECOND, 0);
|
calendar.set(Calendar.SECOND, 0);
|
||||||
|
|
||||||
long reminderTime = calendar.getTimeInMillis();
|
reminderTime = calendar.getTimeInMillis();
|
||||||
|
|
||||||
if(System.currentTimeMillis() > reminderTime) {
|
if(System.currentTimeMillis() > reminderTime) {
|
||||||
reminderTime += AlarmManager.INTERVAL_DAY;
|
reminderTime += AlarmManager.INTERVAL_DAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent alarmIntent = new Intent(MainActivity.this, ReminderAlarmReceiver.class);
|
|
||||||
alarmIntent.setData(uri);
|
|
||||||
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this,
|
|
||||||
((int)(habit.getId() % Integer.MAX_VALUE)) + 1,
|
|
||||||
alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
|
|
||||||
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
|
||||||
manager.setExact(AlarmManager.RTC_WAKEUP, reminderTime, pendingIntent);
|
|
||||||
|
|
||||||
Log.d("Alarm", String.format("Setting alarm (%s): %s", DateFormat.getDateTimeInstance()
|
|
||||||
.format(new Date(reminderTime)), habit.name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Intent alarmIntent = new Intent(context, ReminderAlarmReceiver.class);
|
||||||
|
alarmIntent.setAction(ReminderAlarmReceiver.ACTION_REMIND);
|
||||||
|
alarmIntent.setData(uri);
|
||||||
|
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
|
||||||
|
((int)(habit.getId() % Integer.MAX_VALUE)) + 1,
|
||||||
|
alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
|
||||||
|
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
||||||
|
if (Build.VERSION.SDK_INT >= 19) {
|
||||||
|
manager.setExact(AlarmManager.RTC_WAKEUP, reminderTime, pendingIntent);
|
||||||
|
} else {
|
||||||
|
manager.set(AlarmManager.RTC_WAKEUP, reminderTime, pendingIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d("Alarm", String.format("Setting alarm (%s): %s", DateFormat.getDateTimeInstance()
|
||||||
|
.format(new Date(reminderTime)), habit.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package org.isoron.uhabits;
|
package org.isoron.uhabits;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.isoron.helpers.DateHelper;
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.AlarmManager;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
@@ -20,22 +21,77 @@ import android.util.Log;
|
|||||||
|
|
||||||
public class ReminderAlarmReceiver extends BroadcastReceiver
|
public class ReminderAlarmReceiver extends BroadcastReceiver
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public static String ACTION_CHECK = "org.isoron.uhabits.ACTION_CHECK";
|
||||||
|
public static String ACTION_DISMISS = "org.isoron.uhabits.ACTION_DISMISS";
|
||||||
|
public static String ACTION_REMIND = "org.isoron.uhabits.ACTION_REMIND";
|
||||||
|
public static String ACTION_REMOVE_REMINDER = "org.isoron.uhabits.ACTION_REMOVE_REMINDER";
|
||||||
|
public static String ACTION_SNOOZE = "org.isoron.uhabits.ACTION_SNOOZE";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent)
|
public void onReceive(Context context, Intent intent)
|
||||||
{
|
{
|
||||||
createNotification(context, intent.getData(), intent.getDataString());
|
String action = intent.getAction();
|
||||||
|
|
||||||
|
if(action.equals(ACTION_REMIND))
|
||||||
|
createNotification(context, intent.getData());
|
||||||
|
|
||||||
|
else if(action.equals(ACTION_DISMISS))
|
||||||
|
dismissAllHabits();
|
||||||
|
|
||||||
|
else if(action.equals(ACTION_CHECK))
|
||||||
|
checkHabit(context, intent.getData());
|
||||||
|
|
||||||
|
else if(action.equals(ACTION_SNOOZE))
|
||||||
|
snoozeHabit(context, intent.getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void snoozeHabit(Context context, Uri data)
|
||||||
|
{
|
||||||
|
int delayMinutes = 15;
|
||||||
|
Habit habit = Habit.get(ContentUris.parseId(data));
|
||||||
|
MainActivity.createReminderAlarm(context, habit, new Date().getTime() + delayMinutes * 1000);
|
||||||
|
dismissNotification(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkHabit(Context context, Uri data)
|
||||||
|
{
|
||||||
|
Habit habit = Habit.get(ContentUris.parseId(data));
|
||||||
|
habit.toggleRepetitionToday();
|
||||||
|
habit.save();
|
||||||
|
dismissNotification(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dismissAllHabits()
|
||||||
|
{
|
||||||
|
for(Habit h : Habit.getHighlightedHabits())
|
||||||
|
{
|
||||||
|
Log.d("Alarm", String.format("Removing highlight from: %s", h.name));
|
||||||
|
h.highlight = 0;
|
||||||
|
h.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dismissNotification(Context context)
|
||||||
|
{
|
||||||
|
NotificationManager notificationManager = (NotificationManager) context
|
||||||
|
.getSystemService(Activity.NOTIFICATION_SERVICE);
|
||||||
|
|
||||||
|
notificationManager.cancel(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void createNotification(Context context, Uri data, String text)
|
private void createNotification(Context context, Uri data)
|
||||||
{
|
{
|
||||||
Log.d("Alarm", "Alarm received!");
|
Log.d("Alarm", "Alarm received!");
|
||||||
|
|
||||||
Habit habit = Habit.get(ContentUris.parseId(data));
|
Habit habit = Habit.get(ContentUris.parseId(data));
|
||||||
|
|
||||||
// Check if user already did the habit repetition
|
if(habit.hasImplicitRepToday())
|
||||||
if(habit.hasRep(DateHelper.getStartOfDay(DateHelper.getLocalTime())))
|
{
|
||||||
|
Log.d("Alarm", String.format("(%s) has implicit rep today", habit.name));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Log.d("Alarm", String.format("Applying highlight: %s", habit.name));
|
Log.d("Alarm", String.format("Applying highlight: %s", habit.name));
|
||||||
habit.highlight = 1;
|
habit.highlight = 1;
|
||||||
@@ -49,25 +105,36 @@ public class ReminderAlarmReceiver extends BroadcastReceiver
|
|||||||
contentIntent.setData(data);
|
contentIntent.setData(data);
|
||||||
PendingIntent contentPendingIntent = PendingIntent.getActivity(context, 0, contentIntent, 0);
|
PendingIntent contentPendingIntent = PendingIntent.getActivity(context, 0, contentIntent, 0);
|
||||||
|
|
||||||
Intent deleteIntent = new Intent(context, ReminderAlarmDismissReceiver.class);
|
Intent deleteIntent = new Intent(context, ReminderAlarmReceiver.class);
|
||||||
|
deleteIntent.setAction(ACTION_DISMISS);
|
||||||
PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, 0);
|
PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, 0);
|
||||||
|
|
||||||
|
Intent checkIntent = new Intent(context, ReminderAlarmReceiver.class);
|
||||||
|
checkIntent.setData(data);
|
||||||
|
checkIntent.setAction(ACTION_CHECK);
|
||||||
|
PendingIntent checkIntentPending = PendingIntent.getBroadcast(context, 0, checkIntent, 0);
|
||||||
|
|
||||||
|
Intent snoozeIntent = new Intent(context, ReminderAlarmReceiver.class);
|
||||||
|
snoozeIntent.setData(data);
|
||||||
|
snoozeIntent.setAction(ACTION_SNOOZE);
|
||||||
|
PendingIntent snoozeIntentPending = PendingIntent.getBroadcast(context, 0, snoozeIntent, 0);
|
||||||
|
|
||||||
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
||||||
|
|
||||||
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
|
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
|
||||||
inboxStyle.setBigContentTitle("Habit Reminder:");
|
inboxStyle.setBigContentTitle("Habit Reminder:");
|
||||||
List<Habit> pendingHabits = Habit.getHighlightedHabits();
|
List<Habit> pendingHabits = Habit.getHighlightedHabits();
|
||||||
|
StringBuffer contentText = new StringBuffer();
|
||||||
for(Habit h : pendingHabits)
|
for(Habit h : pendingHabits)
|
||||||
{
|
{
|
||||||
if(h.hasRep(DateHelper.getStartOfDay(DateHelper.getLocalTime())))
|
if(h.hasImplicitRepToday())
|
||||||
continue;
|
continue;
|
||||||
inboxStyle.addLine(h.name);
|
|
||||||
Log.d("Alarm", String.format("Found highlighted: %s", h.name));
|
|
||||||
}
|
|
||||||
|
|
||||||
String contentText = habit.name;
|
inboxStyle.addLine(h.name);
|
||||||
if(pendingHabits.size() > 1) {
|
if(contentText.length() > 0)
|
||||||
contentText = String.format("%d pending habits.", pendingHabits.size());
|
contentText.append(", ");
|
||||||
|
contentText.append(h.name);
|
||||||
|
Log.d("Alarm", String.format("Found highlighted: %s", h.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
Notification notification =
|
Notification notification =
|
||||||
@@ -77,6 +144,8 @@ public class ReminderAlarmReceiver extends BroadcastReceiver
|
|||||||
.setContentText(contentText)
|
.setContentText(contentText)
|
||||||
.setContentIntent(contentPendingIntent)
|
.setContentIntent(contentPendingIntent)
|
||||||
.setDeleteIntent(deletePendingIntent)
|
.setDeleteIntent(deletePendingIntent)
|
||||||
|
.addAction(R.drawable.ic_action_check, "Check", checkIntentPending)
|
||||||
|
.addAction(R.drawable.ic_action_snooze, "Later", snoozeIntentPending)
|
||||||
.setSound(soundUri)
|
.setSound(soundUri)
|
||||||
.setStyle(inboxStyle)
|
.setStyle(inboxStyle)
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ public class ShowHabitsFragment extends Fragment implements OnSavedListener, OnI
|
|||||||
{
|
{
|
||||||
final Habit habit = (Habit) getItem(position);
|
final Habit habit = (Habit) getItem(position);
|
||||||
|
|
||||||
if(view == null)
|
if(view == null || (Long) view.getTag(R.id.KEY_TIMESTAMP) != DateHelper.getStartOfToday())
|
||||||
{
|
{
|
||||||
view = inflater.inflate(R.layout.show_habits_item, null);
|
view = inflater.inflate(R.layout.show_habits_item, null);
|
||||||
((TextView) view.findViewById(R.id.tvStar)).setTypeface(fontawesome);
|
((TextView) view.findViewById(R.id.tvStar)).setTypeface(fontawesome);
|
||||||
@@ -125,6 +125,8 @@ public class ShowHabitsFragment extends Fragment implements OnSavedListener, OnI
|
|||||||
btCheck.setOnLongClickListener(ShowHabitsFragment.this);
|
btCheck.setOnLongClickListener(ShowHabitsFragment.this);
|
||||||
((LinearLayout) view.findViewById(R.id.llButtons)).addView(check);
|
((LinearLayout) view.findViewById(R.id.llButtons)).addView(check);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
view.setTag(R.id.KEY_TIMESTAMP, DateHelper.getStartOfToday());
|
||||||
}
|
}
|
||||||
|
|
||||||
TextView tvStar = (TextView) view.findViewById(R.id.tvStar);
|
TextView tvStar = (TextView) view.findViewById(R.id.tvStar);
|
||||||
@@ -312,7 +314,7 @@ public class ShowHabitsFragment extends Fragment implements OnSavedListener, OnI
|
|||||||
public void onSaved(Command command)
|
public void onSaved(Command command)
|
||||||
{
|
{
|
||||||
executeCommand(command);
|
executeCommand(command);
|
||||||
mainActivity.createReminderAlarms();
|
MainActivity.createReminderAlarms(mainActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyDataSetChanged()
|
public void notifyDataSetChanged()
|
||||||
|
|||||||
@@ -277,6 +277,11 @@ public class Habit extends Model
|
|||||||
return (count > 0);
|
return (count > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasRepToday()
|
||||||
|
{
|
||||||
|
return hasRep(DateHelper.getStartOfToday());
|
||||||
|
}
|
||||||
|
|
||||||
public void deleteReps(long timestamp)
|
public void deleteReps(long timestamp)
|
||||||
{
|
{
|
||||||
new Delete().from(Repetition.class).where("habit = ?", getId())
|
new Delete().from(Repetition.class).where("habit = ?", getId())
|
||||||
@@ -319,6 +324,13 @@ public class Habit extends Model
|
|||||||
return check;
|
return check;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasImplicitRepToday()
|
||||||
|
{
|
||||||
|
long today = DateHelper.getStartOfToday();
|
||||||
|
int reps[] = getReps(today - DateHelper.millisecondsInOneDay, today);
|
||||||
|
return (reps[0] > 0);
|
||||||
|
}
|
||||||
|
|
||||||
public Repetition getOldestRep()
|
public Repetition getOldestRep()
|
||||||
{
|
{
|
||||||
return (Repetition) selectReps().limit(1).executeSingle();
|
return (Repetition) selectReps().limit(1).executeSingle();
|
||||||
@@ -341,6 +353,11 @@ public class Habit extends Model
|
|||||||
deleteScoresNewerThan(timestamp);
|
deleteScoresNewerThan(timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void toggleRepetitionToday()
|
||||||
|
{
|
||||||
|
toggleRepetition(DateHelper.getStartOfToday());
|
||||||
|
}
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
* Scoring *
|
* Scoring *
|
||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|||||||
Reference in New Issue
Block a user