diff --git a/app/build.gradle b/app/build.gradle
index 330d85c..fdb72bf 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -30,6 +30,9 @@ android {
kotlinOptions {
jvmTarget = "1.8"
}
+ androidExtensions {
+ experimental = true
+ }
}
dependencies {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e40243f..e23c585 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -26,6 +26,7 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/net/underdesk/circolapp/AlarmBroadcastReceiver.kt b/app/src/main/java/net/underdesk/circolapp/AlarmBroadcastReceiver.kt
new file mode 100644
index 0000000..2c4c5e6
--- /dev/null
+++ b/app/src/main/java/net/underdesk/circolapp/AlarmBroadcastReceiver.kt
@@ -0,0 +1,99 @@
+/*
+ * Circolapp
+ * Copyright (C) 2019 Matteo Schiff
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+
+package net.underdesk.circolapp
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
+import net.underdesk.circolapp.data.AppDatabase
+import net.underdesk.circolapp.data.Circular
+
+class AlarmBroadcastReceiver : BroadcastReceiver() {
+
+ companion object {
+ const val CHANNEL_ID = "net.underdesk.circolapp.REMINDER"
+ const val CIRCULAR_ID = "circular_id"
+ }
+
+ override fun onReceive(context: Context, intent: Intent) {
+ object : Thread() {
+ override fun run() {
+ createNotificationChannel(context)
+ val circular = AppDatabase.getInstance(context).circularDao().getCircular(
+ intent.getLongExtra(
+ CIRCULAR_ID, 0
+ )
+ )
+ createNotification(
+ context,
+ circular
+ )
+ AppDatabase.getInstance(context).circularDao()
+ .update(circular.apply { reminder = false })
+ }
+ }.start()
+ }
+
+ private fun createNotification(context: Context, circular: Circular) {
+ val intent = Intent(context, MainActivity::class.java).apply {
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ }
+ val pendingIntent: PendingIntent =
+ PendingIntent.getActivity(context, 0, intent, 0)
+
+ val builder = NotificationCompat.Builder(context, CHANNEL_ID)
+ .setSmallIcon(R.drawable.ic_notifications_black_24dp)
+ .setContentTitle(context.getString(R.string.notification_title_reminder))
+ .setContentText(circular.name)
+ .setPriority(NotificationCompat.PRIORITY_HIGH)
+ .setCategory(NotificationCompat.CATEGORY_REMINDER)
+ .setContentIntent(pendingIntent)
+ .setAutoCancel(true)
+ .setGroup(CHANNEL_ID)
+ .setStyle(
+ NotificationCompat.BigTextStyle()
+ .bigText(circular.name)
+ )
+
+ with(NotificationManagerCompat.from(context)) {
+ notify(circular.id.toInt(), builder.build())
+ }
+ }
+
+ private fun createNotificationChannel(context: Context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val name = context.getString(R.string.channel_name_reminder)
+ val descriptionText = context.getString(R.string.channel_description_reminder)
+ val importance = NotificationManager.IMPORTANCE_HIGH
+ val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
+ description = descriptionText
+ }
+
+ val notificationManager: NotificationManager =
+ context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ notificationManager.createNotificationChannel(channel)
+ }
+ }
+}
diff --git a/app/src/main/java/net/underdesk/circolapp/adapters/CircularLetterAdapter.kt b/app/src/main/java/net/underdesk/circolapp/adapters/CircularLetterAdapter.kt
index 04eeecc..f06cbb0 100644
--- a/app/src/main/java/net/underdesk/circolapp/adapters/CircularLetterAdapter.kt
+++ b/app/src/main/java/net/underdesk/circolapp/adapters/CircularLetterAdapter.kt
@@ -19,6 +19,7 @@
package net.underdesk.circolapp.adapters
import android.app.DownloadManager
+import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.net.Uri
@@ -28,12 +29,15 @@ import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.TextView
+import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.item_circular.view.*
+import net.underdesk.circolapp.AlarmBroadcastReceiver
import net.underdesk.circolapp.R
import net.underdesk.circolapp.data.AppDatabase
import net.underdesk.circolapp.data.Circular
+import net.underdesk.circolapp.fragments.NewReminderFragment
class CircularLetterAdapter(private val circulars: List) :
@@ -123,6 +127,29 @@ class CircularLetterAdapter(private val circulars: List) :
}.start()
}
+ holder.reminderButton.setOnClickListener {
+ if (circulars[position].reminder) {
+ object : Thread() {
+ override fun run() {
+ val pendingIntent = PendingIntent.getBroadcast(
+ context,
+ circulars[position].id.toInt(),
+ Intent(context, AlarmBroadcastReceiver::class.java),
+ 0
+ )
+
+ pendingIntent.cancel()
+
+ AppDatabase.getInstance(context).circularDao()
+ .update(circulars[position].apply { reminder = false })
+ }
+ }.start()
+ } else {
+ NewReminderFragment.create(circulars[position])
+ .show((context as FragmentActivity).supportFragmentManager, "NewReminderDialog")
+ }
+ }
+
holder.collapseButton.setOnClickListener {
collapsedItems = if (collapsedItems == position) {
-1
diff --git a/app/src/main/java/net/underdesk/circolapp/data/Circular.kt b/app/src/main/java/net/underdesk/circolapp/data/Circular.kt
index afe1696..23c626b 100644
--- a/app/src/main/java/net/underdesk/circolapp/data/Circular.kt
+++ b/app/src/main/java/net/underdesk/circolapp/data/Circular.kt
@@ -18,10 +18,13 @@
package net.underdesk.circolapp.data
+import android.os.Parcelable
import androidx.room.Entity
import androidx.room.PrimaryKey
+import kotlinx.android.parcel.Parcelize
import java.util.regex.Pattern
+@Parcelize
@Entity(tableName = "circulars")
data class Circular(
@PrimaryKey val id: Long,
@@ -29,9 +32,10 @@ data class Circular(
val url: String,
val date: String,
var favourite: Boolean = false,
+ var reminder: Boolean = false,
val attachmentsNames: MutableList = mutableListOf(),
val attachmentsUrls: MutableList = mutableListOf()
-) {
+) : Parcelable {
companion object {
fun generateFromString(string: String, url: String): Circular {
val id = string.split(" ")[1]
diff --git a/app/src/main/java/net/underdesk/circolapp/data/CircularDao.kt b/app/src/main/java/net/underdesk/circolapp/data/CircularDao.kt
index 6be0377..5e1eaad 100644
--- a/app/src/main/java/net/underdesk/circolapp/data/CircularDao.kt
+++ b/app/src/main/java/net/underdesk/circolapp/data/CircularDao.kt
@@ -26,9 +26,15 @@ interface CircularDao {
@Query("SELECT * FROM circulars ORDER BY id DESC")
fun getCirculars(): List
+ @Query("SELECT * FROM circulars WHERE id = :id ORDER BY id DESC")
+ fun getCircular(id: Long): Circular
+
@Query("SELECT * FROM circulars WHERE favourite ORDER BY id DESC")
fun getFavourites(): LiveData>
+ @Query("SELECT * FROM circulars WHERE reminder ORDER BY id DESC")
+ fun getReminders(): LiveData>
+
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll(circulars: List)
diff --git a/app/src/main/java/net/underdesk/circolapp/fragments/NewReminderFragment.kt b/app/src/main/java/net/underdesk/circolapp/fragments/NewReminderFragment.kt
new file mode 100644
index 0000000..f3ea476
--- /dev/null
+++ b/app/src/main/java/net/underdesk/circolapp/fragments/NewReminderFragment.kt
@@ -0,0 +1,131 @@
+/*
+ * Circolapp
+ * Copyright (C) 2019 Matteo Schiff
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+
+package net.underdesk.circolapp.fragments
+
+import android.app.AlarmManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.app.AlarmManagerCompat
+import androidx.fragment.app.DialogFragment
+import kotlinx.android.synthetic.main.dialog_reminder.*
+import net.underdesk.circolapp.AlarmBroadcastReceiver
+import net.underdesk.circolapp.R
+import net.underdesk.circolapp.data.AppDatabase
+import net.underdesk.circolapp.data.Circular
+import java.util.*
+
+
+class NewReminderFragment : DialogFragment() {
+
+ companion object {
+ private const val CIRCULAR = "circular"
+
+ fun create(circular: Circular): NewReminderFragment {
+ val dialog = NewReminderFragment()
+ dialog.arguments = Bundle().apply {
+ putParcelable(CIRCULAR, circular)
+ }
+ return dialog
+ }
+ }
+
+ var dateNotChosen = true
+ var circular: Circular? = null
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ circular = arguments?.getParcelable(CIRCULAR)
+ return inflater.inflate(R.layout.dialog_reminder, container)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ dialog_time_picker.setIs24HourView(true)
+
+ dialog_ok_button.setOnClickListener { next() }
+ dialog_cancel_button.setOnClickListener { dismiss() }
+ }
+
+ fun next() {
+ if (dateNotChosen) {
+ dialog_date_picker.visibility = View.GONE
+ dialog_time_picker.visibility = View.VISIBLE
+ dialog_ok_button.text = getString(R.string.dialog_ok)
+ dateNotChosen = false
+ } else {
+ val calendar = Calendar.getInstance()
+ val hour = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ dialog_time_picker.hour
+ } else {
+ dialog_time_picker.currentHour
+ }
+
+ val minute = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ dialog_time_picker.minute
+ } else {
+ dialog_time_picker.currentMinute
+ }
+
+ calendar.set(
+ dialog_date_picker.year,
+ dialog_date_picker.month,
+ dialog_date_picker.dayOfMonth,
+ hour,
+ minute
+ )
+
+ object : Thread() {
+ override fun run() {
+ context?.let { context ->
+ circular?.let { circular ->
+ AppDatabase.getInstance(context).circularDao()
+ .update(circular.apply { reminder = true })
+
+ val pendingIntent = PendingIntent.getBroadcast(
+ context,
+ circular.id.toInt(),
+ Intent(context, AlarmBroadcastReceiver::class.java)
+ .putExtra(AlarmBroadcastReceiver.CIRCULAR_ID, circular.id),
+ 0
+ )
+
+ AlarmManagerCompat.setExactAndAllowWhileIdle(
+ context.getSystemService(Context.ALARM_SERVICE) as AlarmManager,
+ AlarmManager.RTC_WAKEUP,
+ calendar.timeInMillis,
+ pendingIntent
+ )
+ }
+ }
+ dismiss()
+ }
+ }.start()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/net/underdesk/circolapp/fragments/RemindersFragment.kt b/app/src/main/java/net/underdesk/circolapp/fragments/RemindersFragment.kt
index cbec325..5e618ac 100644
--- a/app/src/main/java/net/underdesk/circolapp/fragments/RemindersFragment.kt
+++ b/app/src/main/java/net/underdesk/circolapp/fragments/RemindersFragment.kt
@@ -25,23 +25,29 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
+import androidx.recyclerview.widget.LinearLayoutManager
+import kotlinx.android.synthetic.main.fragment_circular_letters.view.*
import net.underdesk.circolapp.R
-import net.underdesk.circolapp.viewmodels.CircularLetterViewModel
+import net.underdesk.circolapp.adapters.CircularLetterAdapter
+import net.underdesk.circolapp.viewmodels.RemindersViewModel
class RemindersFragment : Fragment() {
- private lateinit var circularLetterViewModel: CircularLetterViewModel
+ private lateinit var remindersViewModel: RemindersViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
- circularLetterViewModel =
- ViewModelProviders.of(this).get(CircularLetterViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_circular_letters, container, false)
- circularLetterViewModel.circulars.observe(this, Observer {
+ root.circulars_list.layoutManager = LinearLayoutManager(context)
+
+ remindersViewModel =
+ ViewModelProviders.of(this).get(RemindersViewModel::class.java)
+ remindersViewModel.circulars.observe(this, Observer {
+ root.circulars_list.adapter = CircularLetterAdapter(it)
})
return root
}
diff --git a/app/src/main/java/net/underdesk/circolapp/viewmodels/RemindersViewModel.kt b/app/src/main/java/net/underdesk/circolapp/viewmodels/RemindersViewModel.kt
new file mode 100644
index 0000000..827b743
--- /dev/null
+++ b/app/src/main/java/net/underdesk/circolapp/viewmodels/RemindersViewModel.kt
@@ -0,0 +1,30 @@
+/*
+ * Circolapp
+ * Copyright (C) 2019 Matteo Schiff
+ *
+ * This program 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.
+ *
+ * This program 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 .
+ */
+
+package net.underdesk.circolapp.viewmodels
+
+import android.app.Application
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.LiveData
+import net.underdesk.circolapp.data.AppDatabase
+import net.underdesk.circolapp.data.Circular
+
+class RemindersViewModel(application: Application) : AndroidViewModel(application) {
+ val circulars: LiveData> =
+ AppDatabase.getInstance(getApplication()).circularDao().getReminders()
+}
\ No newline at end of file
diff --git a/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt b/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt
index a7d94be..d7e769f 100644
--- a/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt
+++ b/app/src/main/java/net/underdesk/circolapp/works/PollWork.kt
@@ -144,8 +144,8 @@ class PollWork(appContext: Context, workerParams: WorkerParameters) :
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- val name = applicationContext.getString(R.string.channel_name)
- val descriptionText = applicationContext.getString(R.string.channel_description)
+ val name = applicationContext.getString(R.string.channel_name_new)
+ val descriptionText = applicationContext.getString(R.string.channel_description_new)
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
description = descriptionText
diff --git a/app/src/main/res/layout/dialog_reminder.xml b/app/src/main/res/layout/dialog_reminder.xml
new file mode 100644
index 0000000..8bf6262
--- /dev/null
+++ b/app/src/main/res/layout/dialog_reminder.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_reminders.xml b/app/src/main/res/layout/fragment_reminders.xml
deleted file mode 100644
index 77d9ef6..0000000
--- a/app/src/main/res/layout/fragment_reminders.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b3ddee9..a7a5171 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -9,8 +9,16 @@
New circulars%1$d new circulars
- Circular letters
- Notify when your school issue a new circular letter
+ Reminder
+
+ Circular letters
+ Notify when your school issue a new circular letter
+ Reminders
+ Reminder linked with circular letter
+
+ OK
+ Next
+ CancelNetwork not available. Results may be outdated