diff --git a/res/drawable-hdpi/ic_action_snooze.png b/res/drawable-hdpi/ic_action_snooze.png
new file mode 100644
index 000000000..257274d8a
Binary files /dev/null and b/res/drawable-hdpi/ic_action_snooze.png differ
diff --git a/res/drawable-mdpi/ic_action_snooze.png b/res/drawable-mdpi/ic_action_snooze.png
new file mode 100644
index 000000000..63b4274f8
Binary files /dev/null and b/res/drawable-mdpi/ic_action_snooze.png differ
diff --git a/res/drawable-v21/habits_item_check_normal.xml b/res/drawable-v21/habits_item_check_normal.xml
new file mode 100644
index 000000000..0a83d0180
--- /dev/null
+++ b/res/drawable-v21/habits_item_check_normal.xml
@@ -0,0 +1,22 @@
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable-v21/habits_item_check_pressed.xml b/res/drawable-v21/habits_item_check_pressed.xml
new file mode 100644
index 000000000..8fc26c9e2
--- /dev/null
+++ b/res/drawable-v21/habits_item_check_pressed.xml
@@ -0,0 +1,22 @@
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable-xhdpi/ic_action_snooze.png b/res/drawable-xhdpi/ic_action_snooze.png
new file mode 100644
index 000000000..951ebdab8
Binary files /dev/null and b/res/drawable-xhdpi/ic_action_snooze.png differ
diff --git a/res/drawable-xxhdpi/ic_action_snooze.png b/res/drawable-xxhdpi/ic_action_snooze.png
new file mode 100644
index 000000000..c1b201cea
Binary files /dev/null and b/res/drawable-xxhdpi/ic_action_snooze.png differ
diff --git a/res/drawable/habits_item_check_normal.xml b/res/drawable/habits_item_check_normal.xml
index 0a83d0180..747ab80e6 100644
--- a/res/drawable/habits_item_check_normal.xml
+++ b/res/drawable/habits_item_check_normal.xml
@@ -4,7 +4,7 @@
diff --git a/res/drawable/habits_item_check_pressed.xml b/res/drawable/habits_item_check_pressed.xml
index 8fc26c9e2..887279103 100644
--- a/res/drawable/habits_item_check_pressed.xml
+++ b/res/drawable/habits_item_check_pressed.xml
@@ -4,7 +4,7 @@
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d76b5568b..810e0f446 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -41,5 +41,7 @@
-
+
+
+
\ No newline at end of file
diff --git a/src/org/isoron/helpers/DateHelper.java b/src/org/isoron/helpers/DateHelper.java
index c1bd0624f..8f46a9711 100644
--- a/src/org/isoron/helpers/DateHelper.java
+++ b/src/org/isoron/helpers/DateHelper.java
@@ -20,6 +20,11 @@ public class DateHelper
{
return (timestamp / millisecondsInOneDay) * millisecondsInOneDay;
}
+
+ public static long getStartOfToday()
+ {
+ return getStartOfDay(DateHelper.getLocalTime());
+ }
// public static Date getStartOfDay(Date date)
// {
diff --git a/src/org/isoron/uhabits/MainActivity.java b/src/org/isoron/uhabits/MainActivity.java
index c00a3f266..f10c095ed 100644
--- a/src/org/isoron/uhabits/MainActivity.java
+++ b/src/org/isoron/uhabits/MainActivity.java
@@ -15,7 +15,9 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -43,44 +45,65 @@ public class MainActivity extends Activity
setContentView(R.layout.main_activity);
showHabitsFragment = (ShowHabitsFragment) getFragmentManager().findFragmentById(
R.id.fragment1);
+
+ Log.d("MainActivity", "Creating activity");
undoList = new LinkedList();
redoList = new LinkedList();
- createReminderAlarms();
+ createReminderAlarms(MainActivity.this);
+ }
+
+ @Override
+ protected void onStart()
+ {
+ super.onStart();
+ showHabitsFragment.notifyDataSetChanged();
+ Log.d("MainActivity", "Starting activity");
}
- public void createReminderAlarms()
+ public static void createReminderAlarms(Context context)
{
for(Habit habit : Habit.getHabitsWithReminder())
+ createReminderAlarm(context, habit, null);
+ }
+
+ public static void createReminderAlarm(Context context, Habit habit, Long reminderTime)
+ {
+ Uri uri = Uri.parse("content://org.isoron.uhabits/habit/" + habit.getId());
+
+ if(reminderTime == null)
{
- Uri uri = Uri.parse("content://org.isoron.uhabits/habit/" + habit.getId());
-
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, habit.reminder_hour);
calendar.set(Calendar.MINUTE, habit.reminder_min);
calendar.set(Calendar.SECOND, 0);
- long reminderTime = calendar.getTimeInMillis();
+ reminderTime = calendar.getTimeInMillis();
if(System.currentTimeMillis() > reminderTime) {
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);
+ }
+
+ 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);
-
- Log.d("Alarm", String.format("Setting alarm (%s): %s", DateFormat.getDateTimeInstance()
- .format(new Date(reminderTime)), habit.name));
+ } 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));
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
diff --git a/src/org/isoron/uhabits/ReminderAlarmReceiver.java b/src/org/isoron/uhabits/ReminderAlarmReceiver.java
index acf1578b7..ab0ee593b 100644
--- a/src/org/isoron/uhabits/ReminderAlarmReceiver.java
+++ b/src/org/isoron/uhabits/ReminderAlarmReceiver.java
@@ -1,11 +1,12 @@
package org.isoron.uhabits;
+import java.util.Date;
import java.util.List;
-import org.isoron.helpers.DateHelper;
import org.isoron.uhabits.models.Habit;
import android.app.Activity;
+import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -20,22 +21,77 @@ import android.util.Log;
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
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!");
Habit habit = Habit.get(ContentUris.parseId(data));
- // Check if user already did the habit repetition
- if(habit.hasRep(DateHelper.getStartOfDay(DateHelper.getLocalTime())))
+ if(habit.hasImplicitRepToday())
+ {
+ Log.d("Alarm", String.format("(%s) has implicit rep today", habit.name));
return;
+ }
Log.d("Alarm", String.format("Applying highlight: %s", habit.name));
habit.highlight = 1;
@@ -49,27 +105,38 @@ public class ReminderAlarmReceiver extends BroadcastReceiver
contentIntent.setData(data);
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);
+ 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);
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.setBigContentTitle("Habit Reminder:");
List pendingHabits = Habit.getHighlightedHabits();
+ StringBuffer contentText = new StringBuffer();
for(Habit h : pendingHabits)
{
- if(h.hasRep(DateHelper.getStartOfDay(DateHelper.getLocalTime())))
+ if(h.hasImplicitRepToday())
continue;
+
inboxStyle.addLine(h.name);
+ if(contentText.length() > 0)
+ contentText.append(", ");
+ contentText.append(h.name);
Log.d("Alarm", String.format("Found highlighted: %s", h.name));
}
- String contentText = habit.name;
- if(pendingHabits.size() > 1) {
- contentText = String.format("%d pending habits.", pendingHabits.size());
- }
-
Notification notification =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_notification)
@@ -77,6 +144,8 @@ public class ReminderAlarmReceiver extends BroadcastReceiver
.setContentText(contentText)
.setContentIntent(contentPendingIntent)
.setDeleteIntent(deletePendingIntent)
+ .addAction(R.drawable.ic_action_check, "Check", checkIntentPending)
+ .addAction(R.drawable.ic_action_snooze, "Later", snoozeIntentPending)
.setSound(soundUri)
.setStyle(inboxStyle)
.build();
diff --git a/src/org/isoron/uhabits/dialogs/ShowHabitsFragment.java b/src/org/isoron/uhabits/dialogs/ShowHabitsFragment.java
index ca6eadc6c..36dbed355 100644
--- a/src/org/isoron/uhabits/dialogs/ShowHabitsFragment.java
+++ b/src/org/isoron/uhabits/dialogs/ShowHabitsFragment.java
@@ -46,7 +46,7 @@ import com.mobeta.android.dslv.DragSortListView.DropListener;
public class ShowHabitsFragment extends Fragment implements OnSavedListener, OnItemClickListener,
OnLongClickListener, DropListener
{
-
+
private int tvNameWidth;
private int button_count;
ShowHabitsAdapter adapter;
@@ -102,8 +102,8 @@ public class ShowHabitsFragment extends Fragment implements OnSavedListener, OnI
public View getView(int position, View view, ViewGroup parent)
{
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);
((TextView) view.findViewById(R.id.tvStar)).setTypeface(fontawesome);
@@ -125,6 +125,8 @@ public class ShowHabitsFragment extends Fragment implements OnSavedListener, OnI
btCheck.setOnLongClickListener(ShowHabitsFragment.this);
((LinearLayout) view.findViewById(R.id.llButtons)).addView(check);
}
+
+ view.setTag(R.id.KEY_TIMESTAMP, DateHelper.getStartOfToday());
}
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)
{
executeCommand(command);
- mainActivity.createReminderAlarms();
+ MainActivity.createReminderAlarms(mainActivity);
}
public void notifyDataSetChanged()
diff --git a/src/org/isoron/uhabits/models/Habit.java b/src/org/isoron/uhabits/models/Habit.java
index 8b9d1006f..227ee88a7 100644
--- a/src/org/isoron/uhabits/models/Habit.java
+++ b/src/org/isoron/uhabits/models/Habit.java
@@ -276,6 +276,11 @@ public class Habit extends Model
int count = selectReps().where("timestamp = ?", timestamp).count();
return (count > 0);
}
+
+ public boolean hasRepToday()
+ {
+ return hasRep(DateHelper.getStartOfToday());
+ }
public void deleteReps(long timestamp)
{
@@ -318,6 +323,13 @@ public class Habit extends Model
return check;
}
+
+ public boolean hasImplicitRepToday()
+ {
+ long today = DateHelper.getStartOfToday();
+ int reps[] = getReps(today - DateHelper.millisecondsInOneDay, today);
+ return (reps[0] > 0);
+ }
public Repetition getOldestRep()
{
@@ -340,6 +352,11 @@ public class Habit extends Model
deleteScoresNewerThan(timestamp);
}
+
+ public void toggleRepetitionToday()
+ {
+ toggleRepetition(DateHelper.getStartOfToday());
+ }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Scoring *