diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9dd8b1dbf..eaa477a7e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -203,6 +203,9 @@ You should have received a copy of the GNU General Public License along with Sim
+
) {
+ for (id in taskIds) {
+ val task = TodoApplication.todoList.getTaskWithId(id)
+ if (task == null) {
+ Log.e(TAG, "Task with id '$id' not found in todo list")
+ continue
+ }
+ val taskIdHash = task.id.hashCode()
+ val editTaskIntent = Intent(this, AddTask::class.java).let {
+ it.putExtra(Constants.EXTRA_TASK_ID, task.id)
+ PendingIntent.getActivity(this, taskIdHash, it, PendingIntent.FLAG_IMMUTABLE)
+ }
+ val markDoneIntent = Intent(this, MarkTaskDone::class.java).let {
+ it.putExtra(Constants.EXTRA_TASK_ID, task.id)
+ PendingIntent.getService(this, taskIdHash, it, PendingIntent.FLAG_IMMUTABLE)
+ }
+ var builder = NotificationCompat.Builder(this, "pin-notifications")
+ .setSmallIcon(R.drawable.ic_done_white_24dp)
+ .setContentTitle(task.text)
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT)
+ .setContentIntent(editTaskIntent)
+ .addAction(R.drawable.ic_done_white_24dp, getString(R.string.done), markDoneIntent)
+ .addExtras(Bundle().apply { putString(Constants.EXTRA_TASK_ID, task.id) })
+ .setGroup("group")
+
+ with(NotificationManagerCompat.from(this)) {
+ notify(taskIdHash, builder.build())
+ }
+ if (!TodoApplication.config.hasKeepSelection) {
+ TodoApplication.todoList.clearSelection()
+ }
+ }
+ }
+
+ public override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+
+ companion object {
+ val TAG = "NotificationService"
+
+ fun removeNotifications(taskIds: List) {
+ taskIds.forEach{
+ TodoApplication.notificationManager.cancel(it.hashCode())
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/nl/mpcjanssen/simpletask/Simpletask.kt b/app/src/main/java/nl/mpcjanssen/simpletask/Simpletask.kt
index 83b0b4338..59e3630b9 100644
--- a/app/src/main/java/nl/mpcjanssen/simpletask/Simpletask.kt
+++ b/app/src/main/java/nl/mpcjanssen/simpletask/Simpletask.kt
@@ -1120,31 +1120,10 @@ class Simpletask : ThemedNoActionBarActivity() {
}
private fun pinNotification(checkedTasks: List) {
- for (task in checkedTasks) {
- val taskIdHash = task.id.hashCode()
- val editTaskIntent = Intent(this, AddTask::class.java).let {
- it.putExtra(Constants.EXTRA_TASK_ID, task.id)
- PendingIntent.getActivity(this, taskIdHash, it, PendingIntent.FLAG_IMMUTABLE)
- }
- val markDoneIntent = Intent(this, MarkTaskDone::class.java).let {
- it.putExtra(Constants.EXTRA_TASK_ID, task.id)
- PendingIntent.getService(this, taskIdHash, it, PendingIntent.FLAG_IMMUTABLE)
- }
- var builder = NotificationCompat.Builder(this, "pin-notifications")
- .setSmallIcon(R.drawable.ic_done_white_24dp)
- .setContentTitle(task.text)
- .setPriority(NotificationCompat.PRIORITY_DEFAULT)
- .setContentIntent(editTaskIntent)
- .addAction(R.drawable.ic_done_white_24dp, getString(R.string.done), markDoneIntent)
- .addExtras(Bundle().apply { putString(Constants.EXTRA_TASK_ID, task.id) })
-
- with(NotificationManagerCompat.from(this)) {
- notify(taskIdHash, builder.build())
- }
- if (!TodoApplication.config.hasKeepSelection) {
- TodoApplication.todoList.clearSelection()
- }
- }
+ val taskIds = checkedTasks.map { it.id }.toTypedArray()
+ val intent = Intent(this, NotificationService::class.java)
+ intent.putExtra(Constants.EXTRA_TASK_ID, taskIds)
+ startForegroundService(intent)
}
private inner class UiHandler () {
diff --git a/app/src/main/java/nl/mpcjanssen/simpletask/TodoApplication.kt b/app/src/main/java/nl/mpcjanssen/simpletask/TodoApplication.kt
index 3a3dc13b1..1cbf18471 100644
--- a/app/src/main/java/nl/mpcjanssen/simpletask/TodoApplication.kt
+++ b/app/src/main/java/nl/mpcjanssen/simpletask/TodoApplication.kt
@@ -74,6 +74,7 @@ class TodoApplication : Application() {
db = Room.databaseBuilder(this,
AppDatabase::class.java, DB_FILE).fallbackToDestructiveMigration()
.build()
+ notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (config.forceEnglish) {
val conf = resources.configuration
conf.locale = Locale.ENGLISH
@@ -220,15 +221,13 @@ class TodoApplication : Application() {
fun updatePinnedNotifications() {
Log.i(TAG, "Updating pinned notifications")
- val notificationManager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
- notificationManager.getActiveNotifications().forEach {
- val taskId = it.notification.extras.getString(Constants.EXTRA_TASK_ID)
- if (taskId != null) {
- val taskText = TodoApplication.todoList.getTaskWithId(taskId)?.text
- val notification = NotificationCompat.Builder(this, it.notification).setContentTitle(taskText).build()
- notificationManager.notify(it.id, notification)
- }
- }
+ val taskIds = notificationManager.getActiveNotifications().map { it.notification.extras.getString(Constants.EXTRA_TASK_ID) }.filterNotNull().toTypedArray()
+ val (completedIds, incompleteIds) = taskIds.partition { todoList.getTaskWithId(it)?.isCompleted() ?: false }
+ NotificationService.removeNotifications(completedIds)
+ Log.i(TAG, "taskIds: $taskIds")
+ val intent = Intent(this, NotificationService::class.java)
+ intent.putExtra(Constants.EXTRA_TASK_ID, incompleteIds.toTypedArray())
+ startForegroundService(intent)
}
fun clearTodoFile() {
@@ -268,8 +267,6 @@ class TodoApplication : Application() {
description = descriptionText
}
// Register the channel with the system
- val notificationManager: NotificationManager =
- getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
@@ -282,6 +279,7 @@ class TodoApplication : Application() {
lateinit var config : Config
lateinit var todoList: TodoList
lateinit var db : AppDatabase
+ lateinit var notificationManager: NotificationManager
}
var today: String = todayAsString
}
diff --git a/app/src/main/java/nl/mpcjanssen/simpletask/dao/TaskIdDao.kt b/app/src/main/java/nl/mpcjanssen/simpletask/dao/TaskIdDao.kt
new file mode 100644
index 000000000..260f3ab90
--- /dev/null
+++ b/app/src/main/java/nl/mpcjanssen/simpletask/dao/TaskIdDao.kt
@@ -0,0 +1,36 @@
+package nl.mpcjanssen.simpletask.dao
+
+import nl.mpcjanssen.simpletask.TodoApplication
+import nl.mpcjanssen.simpletask.task.Task
+import android.content.Context.MODE_PRIVATE
+
+object TaskIdDao {
+ val sharedPrefs = TodoApplication.app.getSharedPreferences("todolist", MODE_PRIVATE)
+ val editor = sharedPrefs.edit()
+
+ fun get(taskText: String): String? {
+ return sharedPrefs.getString(taskText, null)
+ }
+
+ fun add(tasks: List) {
+ tasks.forEach {
+ editor.putString(it.text, it.id)
+ }
+ editor.apply()
+ }
+
+ fun add(task: Task) {
+ add(listOf(task))
+ }
+
+ fun remove(tasks: List) {
+ tasks.forEach {
+ editor.remove(it.text)
+ }
+ editor.apply()
+ }
+
+ fun remove(task: Task) {
+ remove(listOf(task))
+ }
+}
diff --git a/app/src/main/java/nl/mpcjanssen/simpletask/task/Task.kt b/app/src/main/java/nl/mpcjanssen/simpletask/task/Task.kt
index 1b9be27bd..1e8232de5 100644
--- a/app/src/main/java/nl/mpcjanssen/simpletask/task/Task.kt
+++ b/app/src/main/java/nl/mpcjanssen/simpletask/task/Task.kt
@@ -4,7 +4,7 @@ import nl.mpcjanssen.simpletask.util.addInterval
import java.util.*
import java.util.regex.Pattern
-class Task(text: String, defaultPrependedDate: String? = null) {
+class Task(text: String, defaultPrependedDate: String? = null, val id: String = UUID.randomUUID().toString()) {
var tokens: ArrayList
@@ -23,6 +23,10 @@ class Task(text: String, defaultPrependedDate: String? = null) {
tokens = parse(rawText)
}
+ fun withId(id: String): Task {
+ return Task(text, id = id)
+ }
+
private inline fun getFirstToken(): T? {
tokens.filterIsInstance().forEach {
return it
@@ -42,8 +46,6 @@ class Task(text: String, defaultPrependedDate: String? = null) {
}
- var id: String = UUID.randomUUID().toString()
-
val text: String
get() {
return tokens.joinToString(" ") { it.text }
diff --git a/app/src/main/java/nl/mpcjanssen/simpletask/task/TodoList.kt b/app/src/main/java/nl/mpcjanssen/simpletask/task/TodoList.kt
index b9eeac901..f99d838c1 100644
--- a/app/src/main/java/nl/mpcjanssen/simpletask/task/TodoList.kt
+++ b/app/src/main/java/nl/mpcjanssen/simpletask/task/TodoList.kt
@@ -10,6 +10,7 @@ import nl.mpcjanssen.simpletask.remote.FileStore
import nl.mpcjanssen.simpletask.remote.IFileStore
import nl.mpcjanssen.simpletask.util.*
+import nl.mpcjanssen.simpletask.dao.TaskIdDao
import java.io.File
import java.util.*
import java.util.concurrent.CopyOnWriteArrayList
@@ -45,7 +46,7 @@ class TodoList(val config: Config) {
} else {
todoItems.addAll(0, updatedItems)
}
-
+ TaskIdDao.add(items)
}
fun add(t: Task, atEnd: Boolean) {
@@ -57,7 +58,7 @@ class TodoList(val config: Config) {
Log.d(tag, "Remove")
pendingEdits.removeAll(tasks)
todoItems.removeAll(tasks)
-
+ TaskIdDao.remove(tasks)
}
@@ -160,10 +161,13 @@ class TodoList(val config: Config) {
val smallestSize = org.zip(updated) { orgTask, updatedTask ->
val idx = todoItems.indexOf(orgTask)
if (idx != -1) {
- updatedTask.id = orgTask.id
- todoItems[idx] = updatedTask
+ val newTask = updatedTask.withId(orgTask.id)
+ todoItems[idx] = newTask
+ TaskIdDao.remove(orgTask)
+ TaskIdDao.add(newTask)
} else {
todoItems.add(updatedTask)
+ TaskIdDao.add(updatedTask)
}
1
}.size
@@ -263,7 +267,15 @@ class TodoList(val config: Config) {
try {
val items = FileStore.loadTasksFromFile(file)
- val newTodoItems = items.map { Task(it) }.toMutableList()
+ val newTodoItems = items.map {
+ val taskId = TaskIdDao.get(it)
+ if (taskId == null) {
+ val task = Task(it)
+ TaskIdDao.add(task)
+ task
+ }
+ else Task(it, id = taskId)
+ }.toMutableList()
synchronized(todoItems) {
Log.d(tag, "Fill todolist with ${items.size} items")
todoItems = newTodoItems
diff --git a/app/src/main/java/nl/mpcjanssen/simpletask/util/Config.kt b/app/src/main/java/nl/mpcjanssen/simpletask/util/Config.kt
index f99e91f06..27ca651b3 100644
--- a/app/src/main/java/nl/mpcjanssen/simpletask/util/Config.kt
+++ b/app/src/main/java/nl/mpcjanssen/simpletask/util/Config.kt
@@ -1,13 +1,16 @@
package nl.mpcjanssen.simpletask.util
+import android.content.Context.MODE_PRIVATE
import android.os.Build
import android.os.Environment
+import android.preference.PreferenceManager
import android.util.Log
import androidx.annotation.RequiresApi
import me.smichel.android.KPreferences.Preferences
import nl.mpcjanssen.simpletask.*
import nl.mpcjanssen.simpletask.remote.FileStore
import nl.mpcjanssen.simpletask.task.Task
+import nl.mpcjanssen.simpletask.dao.TaskIdDao
import org.json.JSONObject
import java.io.File
import java.util.*
@@ -229,7 +232,16 @@ class Config(app: TodoApplication) : Preferences(app) {
val lines = it.lines()
Log.i(TAG, "Getting ${lines.size} items todoList from cache")
ArrayList().apply {
- addAll(lines.map { line -> Task(line) })
+ addAll(lines.map { line ->
+ val taskId = TaskIdDao.get(line)
+ if (taskId == null) {
+ val task = Task(line)
+ TaskIdDao.add(task)
+ task
+ } else {
+ Task(line, id = taskId)
+ }
+ })
}
}
set(items) {