diff --git a/build.gradle b/build.gradle index b21b92ae7..6692adb1e 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.0.0-beta6' + classpath 'com.android.tools.build:gradle:3.0.0' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.6.4' classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' diff --git a/gradle.properties b/gradle.properties index bc47317b6..9e3278641 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ TARGET_SDK_VERSION = 25 COMPILE_SDK_VERSION = 25 DAGGER_VERSION = 2.9 -BUILD_TOOLS_VERSION = 26.0.0 +BUILD_TOOLS_VERSION = 26.0.2 KOTLIN_VERSION = 1.1.2-4 SUPPORT_LIBRARY_VERSION = 25.3.1 diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt b/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt index 2758ba934..b60904840 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt @@ -54,6 +54,15 @@ class PendingIntentFactory }, FLAG_UPDATE_CURRENT) + fun removeRepetition(habit: Habit): PendingIntent = + PendingIntent.getBroadcast( + context, 3, + Intent(context, WidgetReceiver::class.java).apply { + action = WidgetReceiver.ACTION_REMOVE_REPETITION + data = Uri.parse(habit.uriString) + }, + FLAG_UPDATE_CURRENT) + fun showHabit(habit: Habit): PendingIntent = android.support.v4.app.TaskStackBuilder .create(context) diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt index 6a25300d0..15abc403f 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/AndroidNotificationTray.kt @@ -23,6 +23,7 @@ import android.app.* import android.content.* import android.graphics.* import android.graphics.BitmapFactory.* +import android.support.annotation.* import android.support.v4.app.* import android.support.v4.app.NotificationCompat.* import org.isoron.androidbase.* @@ -50,11 +51,24 @@ class AndroidNotificationTray override fun showNotification(habit: Habit, notificationId: Int, timestamp: Timestamp, - reminderTime: Long) { + reminderTime: Long) + { + val notificationManager = NotificationManagerCompat.from(context) + val summary = buildSummary(reminderTime) + notificationManager.notify(Int.MAX_VALUE, summary) + val notification = buildNotification(habit, reminderTime, timestamp) + notificationManager.notify(notificationId, notification) + } + + @NonNull + fun buildNotification(@NonNull habit: Habit, + @NonNull reminderTime: Long, + @NonNull timestamp: Timestamp) : Notification + { - val checkAction = Action( + val addRepetitionAction = Action( R.drawable.ic_action_check, - context.getString(R.string.check), + context.getString(R.string.yes), pendingIntents.addCheckmark(habit, timestamp)) val snoozeAction = Action( @@ -62,6 +76,12 @@ class AndroidNotificationTray context.getString(R.string.snooze), pendingIntents.snoozeNotification(habit)) + val removeRepetitionAction = Action( + R.drawable.ic_action_cancel, + context.getString(R.string.no), + pendingIntents.removeRepetition(habit) + ) + val wearableBg = decodeResource(context.resources, R.drawable.stripe) // Even though the set of actions is the same on the phone and @@ -69,7 +89,8 @@ class AndroidNotificationTray // WearableExtender. val wearableExtender = WearableExtender() .setBackground(wearableBg) - .addAction(checkAction) + .addAction(addRepetitionAction) + .addAction(removeRepetitionAction) .addAction(snoozeAction) val builder = NotificationCompat.Builder(context) @@ -78,20 +99,32 @@ class AndroidNotificationTray .setContentText(habit.description) .setContentIntent(pendingIntents.showHabit(habit)) .setDeleteIntent(pendingIntents.dismissNotification(habit)) - .addAction(checkAction) + .addAction(addRepetitionAction) + .addAction(removeRepetitionAction) .addAction(snoozeAction) .setSound(ringtoneManager.getURI()) .extend(wearableExtender) .setWhen(reminderTime) .setShowWhen(true) .setOngoing(preferences.shouldMakeNotificationsSticky()) + .setGroup("default") if (preferences.shouldMakeNotificationsLed()) builder.setLights(Color.RED, 1000, 1000) - val notificationManager = context.getSystemService( - Activity.NOTIFICATION_SERVICE) as NotificationManager + return builder.build() + } - notificationManager.notify(notificationId, builder.build()) + @NonNull + private fun buildSummary(@NonNull reminderTime: Long) : Notification + { + return NotificationCompat.Builder(context) + .setSmallIcon(R.drawable.ic_notification) + .setContentTitle(context.getString(R.string.app_name)) + .setWhen(reminderTime) + .setShowWhen(true) + .setGroup("default") + .setGroupSummary(true) + .build() } } diff --git a/uhabits-android/src/main/res/drawable-hdpi/ic_action_cancel.png b/uhabits-android/src/main/res/drawable-hdpi/ic_action_cancel.png new file mode 100644 index 000000000..374fc6fc0 Binary files /dev/null and b/uhabits-android/src/main/res/drawable-hdpi/ic_action_cancel.png differ diff --git a/uhabits-android/src/main/res/drawable-mdpi/ic_action_cancel.png b/uhabits-android/src/main/res/drawable-mdpi/ic_action_cancel.png new file mode 100644 index 000000000..e7de03a06 Binary files /dev/null and b/uhabits-android/src/main/res/drawable-mdpi/ic_action_cancel.png differ diff --git a/uhabits-android/src/main/res/drawable-xhdpi/ic_action_cancel.png b/uhabits-android/src/main/res/drawable-xhdpi/ic_action_cancel.png new file mode 100644 index 000000000..dbd10906c Binary files /dev/null and b/uhabits-android/src/main/res/drawable-xhdpi/ic_action_cancel.png differ diff --git a/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_cancel.png b/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_cancel.png new file mode 100644 index 000000000..20591def4 Binary files /dev/null and b/uhabits-android/src/main/res/drawable-xxhdpi/ic_action_cancel.png differ diff --git a/uhabits-android/src/main/res/values/strings.xml b/uhabits-android/src/main/res/values/strings.xml index a78c873cb..5c043b111 100644 --- a/uhabits-android/src/main/res/values/strings.xml +++ b/uhabits-android/src/main/res/values/strings.xml @@ -220,4 +220,6 @@ e.g. Did you exercise today? Question Target + Yes + No \ No newline at end of file diff --git a/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryHabitList.java b/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryHabitList.java index 5e2727114..c1d05f517 100644 --- a/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryHabitList.java +++ b/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryHabitList.java @@ -155,14 +155,14 @@ public class MemoryHabitList extends HabitList } @Override - public int indexOf(@NonNull Habit h) + public synchronized int indexOf(@NonNull Habit h) { return list.indexOf(h); } @NonNull @Override - public Iterator iterator() + public synchronized Iterator iterator() { return Collections.unmodifiableCollection(list).iterator(); } @@ -200,13 +200,13 @@ public class MemoryHabitList extends HabitList } @Override - public int size() + public synchronized int size() { return list.size(); } @Override - public void update(List habits) + public synchronized void update(List habits) { resort(); getObservable().notifyListeners(); diff --git a/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.java b/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.java index bb16e1f49..ab086cff5 100644 --- a/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.java +++ b/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.java @@ -91,7 +91,7 @@ public class SQLiteHabitList extends HabitList @Override @Nullable - public Habit getById(long id) + public synchronized Habit getById(long id) { loadRecords(); return list.getById(id); @@ -99,7 +99,7 @@ public class SQLiteHabitList extends HabitList @Override @NonNull - public Habit getByPosition(int position) + public synchronized Habit getByPosition(int position) { loadRecords(); return list.getByPosition(position); @@ -107,7 +107,7 @@ public class SQLiteHabitList extends HabitList @NonNull @Override - public HabitList getFiltered(HabitMatcher filter) + public synchronized HabitList getFiltered(HabitMatcher filter) { loadRecords(); return list.getFiltered(filter); @@ -121,21 +121,21 @@ public class SQLiteHabitList extends HabitList } @Override - public void setOrder(@NonNull Order order) + public synchronized void setOrder(@NonNull Order order) { list.setOrder(order); getObservable().notifyListeners(); } @Override - public int indexOf(@NonNull Habit h) + public synchronized int indexOf(@NonNull Habit h) { loadRecords(); return list.indexOf(h); } @Override - public Iterator iterator() + public synchronized Iterator iterator() { loadRecords(); return list.iterator(); @@ -214,7 +214,7 @@ public class SQLiteHabitList extends HabitList } @Override - public void repair() + public synchronized void repair() { loadRecords(); rebuildOrder(); @@ -222,7 +222,7 @@ public class SQLiteHabitList extends HabitList } @Override - public int size() + public synchronized int size() { loadRecords(); return list.size(); @@ -245,7 +245,7 @@ public class SQLiteHabitList extends HabitList getObservable().notifyListeners(); } - public void reload() + public synchronized void reload() { loaded = false; } diff --git a/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.java b/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.java index 1f9500123..d3aa800af 100644 --- a/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.java +++ b/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.java @@ -48,14 +48,15 @@ public class WidgetBehavior public void onAddRepetition(@NonNull Habit habit, Timestamp timestamp) { + notificationTray.cancel(habit); Repetition rep = habit.getRepetitions().getByTimestamp(timestamp); if (rep != null) return; performToggle(habit, timestamp); - notificationTray.cancel(habit); } public void onRemoveRepetition(@NonNull Habit habit, Timestamp timestamp) { + notificationTray.cancel(habit); Repetition rep = habit.getRepetitions().getByTimestamp(timestamp); if (rep == null) return; performToggle(habit, timestamp);