mirror of
https://github.com/Matte23/circolapp.git
synced 2025-12-06 07:29:10 +00:00
Add shared module
This commit is contained in:
@@ -46,8 +46,13 @@ android {
|
||||
dependencies {
|
||||
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
|
||||
|
||||
// Shared module
|
||||
implementation(project(":shared"))
|
||||
|
||||
// Kotlin
|
||||
implementation(Dependencies.Kotlin.core)
|
||||
implementation(Dependencies.Kotlin.coroutinesCore)
|
||||
implementation(Dependencies.Kotlin.coroutinesAndroid)
|
||||
|
||||
// AndroidX
|
||||
implementation(Dependencies.AndroidX.appcompat)
|
||||
@@ -55,13 +60,11 @@ dependencies {
|
||||
implementation(Dependencies.AndroidX.constraintLayout)
|
||||
implementation(Dependencies.AndroidX.swipeRefreshLayout)
|
||||
implementation(Dependencies.AndroidX.lifecycleExtensions)
|
||||
implementation(Dependencies.AndroidX.lifecycleLiveData)
|
||||
implementation(Dependencies.AndroidX.preference)
|
||||
implementation(Dependencies.AndroidX.navigationFragment)
|
||||
implementation(Dependencies.AndroidX.navigationUi)
|
||||
implementation(Dependencies.AndroidX.workManager)
|
||||
implementation(Dependencies.AndroidX.Room.roomRuntime)
|
||||
implementation(Dependencies.AndroidX.Room.roomKtx)
|
||||
kapt(Dependencies.AndroidX.Room.roomCompiler)
|
||||
|
||||
// Google
|
||||
implementation(Dependencies.Google.material)
|
||||
@@ -70,17 +73,11 @@ dependencies {
|
||||
implementation(platform(Dependencies.Firebase.bom))
|
||||
implementation(Dependencies.Firebase.messaging)
|
||||
|
||||
// Square
|
||||
implementation(Dependencies.Square.okhttp)
|
||||
implementation(Dependencies.Square.moshi)
|
||||
kapt(Dependencies.Square.moshiCodegen)
|
||||
|
||||
// AboutLibraries
|
||||
implementation(Dependencies.AboutLibraries.aboutLibrariesCore)
|
||||
implementation(Dependencies.AboutLibraries.aboutLibraries)
|
||||
|
||||
// Misc
|
||||
implementation(Dependencies.Misc.jsoup)
|
||||
implementation(Dependencies.Misc.appIntro)
|
||||
implementation(Dependencies.Misc.materialSpinner)
|
||||
|
||||
|
||||
@@ -29,8 +29,10 @@ import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.app.TaskStackBuilder
|
||||
import net.underdesk.circolapp.data.AppDatabase
|
||||
import net.underdesk.circolapp.data.Circular
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import net.underdesk.circolapp.data.AndroidDatabase
|
||||
import net.underdesk.circolapp.shared.data.Circular
|
||||
|
||||
class AlarmBroadcastReceiver : BroadcastReceiver() {
|
||||
|
||||
@@ -41,27 +43,25 @@ class AlarmBroadcastReceiver : BroadcastReceiver() {
|
||||
}
|
||||
|
||||
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
|
||||
),
|
||||
intent.getIntExtra(
|
||||
SCHOOL_ID,
|
||||
0
|
||||
)
|
||||
GlobalScope.launch {
|
||||
createNotificationChannel(context)
|
||||
val circular = AndroidDatabase.getDaoInstance(context).getCircular(
|
||||
intent.getLongExtra(
|
||||
CIRCULAR_ID,
|
||||
0
|
||||
),
|
||||
intent.getIntExtra(
|
||||
SCHOOL_ID,
|
||||
0
|
||||
)
|
||||
createNotification(
|
||||
context,
|
||||
circular
|
||||
)
|
||||
AppDatabase.getInstance(context).circularDao()
|
||||
.update(circular.apply { reminder = false })
|
||||
}
|
||||
}.start()
|
||||
)
|
||||
createNotification(
|
||||
context,
|
||||
circular
|
||||
)
|
||||
AndroidDatabase.getDaoInstance(context)
|
||||
.update(circular.id, circular.school, circular.favourite, false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createNotification(context: Context, circular: Circular) {
|
||||
|
||||
@@ -26,7 +26,8 @@ import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.preference.*
|
||||
import kotlinx.android.synthetic.main.settings_activity.*
|
||||
import net.underdesk.circolapp.push.FirebaseTopicUtils
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
import net.underdesk.circolapp.server.AndroidServerApi
|
||||
import net.underdesk.circolapp.shared.server.ServerAPI
|
||||
import net.underdesk.circolapp.works.PollWork
|
||||
|
||||
class SettingsActivity : AppCompatActivity() {
|
||||
@@ -55,7 +56,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||
schoolPreference?.let { setSchoolListPreference(it) }
|
||||
val schoolPreferenceListener =
|
||||
Preference.OnPreferenceChangeListener { _, value ->
|
||||
ServerAPI.changeServer(value.toString().toInt(), requireContext())
|
||||
AndroidServerApi.changeServer(value.toString().toInt(), requireContext())
|
||||
true
|
||||
}
|
||||
schoolPreference?.onPreferenceChangeListener = schoolPreferenceListener
|
||||
@@ -109,7 +110,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||
val enablePolling = sharedPreferences.getBoolean("enable_polling", false)
|
||||
|
||||
if (notifyNewCirculars && !enablePolling) {
|
||||
val serverID = ServerAPI.getInstance(requireContext()).serverID()
|
||||
val serverID = AndroidServerApi.getInstance(requireContext()).serverID()
|
||||
val serverToken = ServerAPI.Companion.Servers.values()[serverID].toString()
|
||||
|
||||
FirebaseTopicUtils.selectTopic(serverToken, requireContext())
|
||||
|
||||
@@ -32,17 +32,20 @@ import androidx.fragment.app.FragmentActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlinx.android.synthetic.main.item_circular.view.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
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.data.AndroidDatabase
|
||||
import net.underdesk.circolapp.fragments.NewReminderFragment
|
||||
import net.underdesk.circolapp.shared.data.Circular
|
||||
import net.underdesk.circolapp.utils.DownloadableFile
|
||||
import net.underdesk.circolapp.utils.FileUtils
|
||||
|
||||
class CircularLetterAdapter(
|
||||
private var circulars: List<Circular>,
|
||||
private val adapterCallback: AdapterCallback
|
||||
private val adapterCallback: AdapterCallback,
|
||||
private val adapterScope: CoroutineScope
|
||||
) :
|
||||
RecyclerView.Adapter<CircularLetterAdapter.CircularLetterViewHolder>() {
|
||||
private lateinit var context: Context
|
||||
@@ -158,31 +161,37 @@ class CircularLetterAdapter(
|
||||
}
|
||||
|
||||
holder.favouriteButton.setOnClickListener {
|
||||
object : Thread() {
|
||||
override fun run() {
|
||||
AppDatabase.getInstance(context).circularDao()
|
||||
.update(circulars[position].apply { favourite = !favourite })
|
||||
}
|
||||
}.start()
|
||||
adapterScope.launch {
|
||||
AndroidDatabase.getDaoInstance(context).update(
|
||||
circulars[position].id,
|
||||
circulars[position].school,
|
||||
!circulars[position].favourite,
|
||||
circulars[position].reminder
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
adapterScope.launch {
|
||||
val pendingIntent = PendingIntent.getBroadcast(
|
||||
context,
|
||||
circulars[position].id.toInt(),
|
||||
Intent(context, AlarmBroadcastReceiver::class.java),
|
||||
0
|
||||
)
|
||||
|
||||
pendingIntent.cancel()
|
||||
|
||||
AndroidDatabase.getDaoInstance(context)
|
||||
.update(
|
||||
circulars[position].id,
|
||||
circulars[position].school,
|
||||
circulars[position].favourite,
|
||||
false
|
||||
)
|
||||
|
||||
pendingIntent.cancel()
|
||||
|
||||
AppDatabase.getInstance(context).circularDao()
|
||||
.update(circulars[position].apply { reminder = false })
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
} else {
|
||||
NewReminderFragment.create(circulars[position])
|
||||
.show((context as FragmentActivity).supportFragmentManager, "NewReminderDialog")
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package net.underdesk.circolapp.data
|
||||
|
||||
import android.content.Context
|
||||
import net.underdesk.circolapp.server.AndroidServerApi
|
||||
import net.underdesk.circolapp.shared.data.CircularDao
|
||||
import net.underdesk.circolapp.shared.data.CircularRepository
|
||||
import net.underdesk.circolapp.shared.server.ServerAPI
|
||||
|
||||
object AndroidCircularRepository {
|
||||
@Volatile
|
||||
private var instance: CircularRepository? = null
|
||||
|
||||
fun getInstance(circularDao: CircularDao, serverAPI: ServerAPI) =
|
||||
instance ?: synchronized(this) {
|
||||
instance ?: CircularRepository(circularDao, serverAPI).also { instance = it }
|
||||
}
|
||||
|
||||
fun getInstance(context: Context) =
|
||||
getInstance(AndroidDatabase.getDaoInstance(context), AndroidServerApi.getInstance(context))
|
||||
}
|
||||
@@ -18,31 +18,27 @@
|
||||
|
||||
package net.underdesk.circolapp.data
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import android.content.Context
|
||||
import net.underdesk.circolapp.shared.data.AppDatabase
|
||||
import net.underdesk.circolapp.shared.data.CircularDao
|
||||
import net.underdesk.circolapp.shared.data.DatabaseDriverFactory
|
||||
|
||||
class Converters {
|
||||
object AndroidDatabase {
|
||||
|
||||
@TypeConverter
|
||||
fun stringToList(data: String?): List<String> {
|
||||
val list: MutableList<String> = mutableListOf()
|
||||
@Volatile
|
||||
private var instance: AppDatabase? = null
|
||||
|
||||
if (data != null) {
|
||||
for (attachment in data.split("˜")) {
|
||||
list.add(attachment)
|
||||
}
|
||||
fun getInstance(context: Context): AppDatabase {
|
||||
return instance ?: synchronized(this) {
|
||||
instance ?: AppDatabase(
|
||||
DatabaseDriverFactory(
|
||||
context
|
||||
).createDriver()
|
||||
).also { instance = it }
|
||||
}
|
||||
|
||||
return list.dropLast(1)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun listToString(list: List<String>): String {
|
||||
var string = ""
|
||||
|
||||
for (attachment in list) {
|
||||
string += "$attachment˜"
|
||||
}
|
||||
|
||||
return string
|
||||
fun getDaoInstance(context: Context): CircularDao {
|
||||
return CircularDao(getInstance(context))
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Circolapp
|
||||
* Copyright (C) 2019-2020 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.underdesk.circolapp.data
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
|
||||
@Database(entities = [Circular::class], version = 2, exportSchema = false)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun circularDao(): CircularDao
|
||||
|
||||
companion object {
|
||||
|
||||
@Volatile
|
||||
private var instance: AppDatabase? = null
|
||||
|
||||
private const val DATABASE_NAME = "database"
|
||||
|
||||
fun getInstance(context: Context): AppDatabase {
|
||||
return instance ?: synchronized(this) {
|
||||
instance ?: Room.databaseBuilder(
|
||||
context,
|
||||
AppDatabase::class.java,
|
||||
DATABASE_NAME
|
||||
).fallbackToDestructiveMigration().build().also { instance = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Circolapp
|
||||
* Copyright (C) 2019-2020 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.underdesk.circolapp.data
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.room.Entity
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
|
||||
@Parcelize
|
||||
@Entity(tableName = "circulars", primaryKeys = ["id", "school"])
|
||||
data class Circular(
|
||||
val id: Long,
|
||||
val school: Int,
|
||||
val name: String,
|
||||
val url: String,
|
||||
val date: String,
|
||||
var favourite: Boolean = false,
|
||||
var reminder: Boolean = false,
|
||||
val attachmentsNames: MutableList<String> = mutableListOf(),
|
||||
val attachmentsUrls: MutableList<String> = mutableListOf()
|
||||
) : Parcelable
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Circolapp
|
||||
* Copyright (C) 2019-2020 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.underdesk.circolapp.data
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.room.*
|
||||
|
||||
@Dao
|
||||
interface CircularDao {
|
||||
@Query("SELECT * FROM circulars WHERE school is :school ORDER BY id DESC")
|
||||
fun getCirculars(school: Int): List<Circular>
|
||||
|
||||
@Query("SELECT * FROM circulars WHERE school is :school ORDER BY id DESC")
|
||||
fun getLiveCirculars(school: Int): LiveData<List<Circular>>
|
||||
|
||||
@Query("SELECT * FROM circulars WHERE school is :school AND name LIKE :query ORDER BY id DESC")
|
||||
fun searchCirculars(query: String, school: Int): LiveData<List<Circular>>
|
||||
|
||||
@Query("SELECT * FROM circulars WHERE school is :school AND id = :id ORDER BY id DESC")
|
||||
fun getCircular(id: Long, school: Int): Circular
|
||||
|
||||
@Query("SELECT * FROM circulars WHERE school is :school AND favourite ORDER BY id DESC")
|
||||
fun getFavourites(school: Int): LiveData<List<Circular>>
|
||||
|
||||
@Query("SELECT * FROM circulars WHERE school is :school AND favourite AND name LIKE :query ORDER BY id DESC")
|
||||
fun searchFavourites(query: String, school: Int): LiveData<List<Circular>>
|
||||
|
||||
@Query("SELECT * FROM circulars WHERE school is :school AND reminder ORDER BY id DESC")
|
||||
fun getReminders(school: Int): LiveData<List<Circular>>
|
||||
|
||||
@Query("SELECT * FROM circulars WHERE school is :school AND reminder AND name LIKE :query ORDER BY id DESC")
|
||||
fun searchReminders(query: String, school: Int): LiveData<List<Circular>>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
fun insertAll(circulars: List<Circular>)
|
||||
|
||||
@Update
|
||||
fun update(circular: Circular)
|
||||
|
||||
@Query("DELETE FROM circulars")
|
||||
fun deleteAll()
|
||||
}
|
||||
@@ -1,50 +1 @@
|
||||
package net.underdesk.circolapp.data
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
|
||||
class CircularRepository(
|
||||
val circularDao: CircularDao,
|
||||
private val serverAPI: ServerAPI
|
||||
) {
|
||||
suspend fun updateCirculars(returnNewCirculars: Boolean = true): Pair<List<Circular>, Boolean> {
|
||||
var onlyNewCirculars = listOf<Circular>()
|
||||
|
||||
return withContext(Dispatchers.IO) {
|
||||
val result = serverAPI.getCircularsFromServer()
|
||||
if (result.second == ServerAPI.Companion.Result.ERROR)
|
||||
return@withContext Pair(emptyList(), false)
|
||||
|
||||
val oldCirculars = circularDao.getCirculars(serverAPI.serverID())
|
||||
val newCirculars = result.first
|
||||
|
||||
if (newCirculars.size != oldCirculars.size) {
|
||||
if (newCirculars.size < oldCirculars.size) {
|
||||
circularDao.deleteAll()
|
||||
}
|
||||
|
||||
if (returnNewCirculars) {
|
||||
val oldCircularsSize =
|
||||
if (newCirculars.size < oldCirculars.size) 0 else oldCirculars.size
|
||||
|
||||
val circularCount = newCirculars.size - oldCircularsSize
|
||||
onlyNewCirculars = newCirculars.subList(0, circularCount)
|
||||
}
|
||||
|
||||
circularDao.insertAll(newCirculars)
|
||||
}
|
||||
Pair(onlyNewCirculars, true)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var instance: CircularRepository? = null
|
||||
|
||||
fun getInstance(circularDao: CircularDao, serverAPI: ServerAPI) =
|
||||
instance ?: synchronized(this) {
|
||||
instance ?: CircularRepository(circularDao, serverAPI).also { instance = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.android.synthetic.main.fragment_circular_letters.*
|
||||
@@ -32,9 +33,7 @@ import kotlinx.android.synthetic.main.fragment_circular_letters.view.*
|
||||
import net.underdesk.circolapp.MainActivity
|
||||
import net.underdesk.circolapp.R
|
||||
import net.underdesk.circolapp.adapters.CircularLetterAdapter
|
||||
import net.underdesk.circolapp.data.AppDatabase
|
||||
import net.underdesk.circolapp.data.CircularRepository
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
import net.underdesk.circolapp.data.AndroidCircularRepository
|
||||
import net.underdesk.circolapp.viewmodels.CircularLetterViewModel
|
||||
import net.underdesk.circolapp.viewmodels.CircularLetterViewModelFactory
|
||||
|
||||
@@ -45,10 +44,7 @@ class CircularLetterFragment :
|
||||
|
||||
private val circularLetterViewModel: CircularLetterViewModel by viewModels {
|
||||
CircularLetterViewModelFactory(
|
||||
CircularRepository.getInstance(
|
||||
AppDatabase.getInstance(requireContext()).circularDao(),
|
||||
ServerAPI.getInstance(requireContext())
|
||||
),
|
||||
AndroidCircularRepository.getInstance(requireContext()),
|
||||
requireActivity().application
|
||||
)
|
||||
}
|
||||
@@ -67,7 +63,7 @@ class CircularLetterFragment :
|
||||
{
|
||||
if (root.circulars_list.adapter == null) {
|
||||
root.circulars_list.adapter =
|
||||
CircularLetterAdapter(it, activity as MainActivity)
|
||||
CircularLetterAdapter(it, activity as MainActivity, lifecycleScope)
|
||||
} else {
|
||||
(root.circulars_list.adapter as CircularLetterAdapter).changeDataSet(it)
|
||||
}
|
||||
|
||||
@@ -24,14 +24,13 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import kotlinx.android.synthetic.main.fragment_circular_letters.view.*
|
||||
import net.underdesk.circolapp.MainActivity
|
||||
import net.underdesk.circolapp.R
|
||||
import net.underdesk.circolapp.adapters.CircularLetterAdapter
|
||||
import net.underdesk.circolapp.data.AppDatabase
|
||||
import net.underdesk.circolapp.data.CircularRepository
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
import net.underdesk.circolapp.data.AndroidCircularRepository
|
||||
import net.underdesk.circolapp.viewmodels.FavouritesViewModel
|
||||
import net.underdesk.circolapp.viewmodels.FavouritesViewModelFactory
|
||||
|
||||
@@ -39,10 +38,7 @@ class FavouritesFragment : Fragment(), MainActivity.SearchCallback {
|
||||
|
||||
private val favouritesViewModel: FavouritesViewModel by viewModels {
|
||||
FavouritesViewModelFactory(
|
||||
CircularRepository.getInstance(
|
||||
AppDatabase.getInstance(requireContext()).circularDao(),
|
||||
ServerAPI.getInstance(requireContext())
|
||||
),
|
||||
AndroidCircularRepository.getInstance(requireContext()),
|
||||
requireActivity().application
|
||||
)
|
||||
}
|
||||
@@ -62,7 +58,7 @@ class FavouritesFragment : Fragment(), MainActivity.SearchCallback {
|
||||
{
|
||||
if (root.circulars_list.adapter == null) {
|
||||
root.circulars_list.adapter =
|
||||
CircularLetterAdapter(it, activity as MainActivity)
|
||||
CircularLetterAdapter(it, activity as MainActivity, lifecycleScope)
|
||||
} else {
|
||||
(root.circulars_list.adapter as CircularLetterAdapter).changeDataSet(it)
|
||||
}
|
||||
|
||||
@@ -29,36 +29,33 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.app.AlarmManagerCompat
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import kotlinx.android.synthetic.main.dialog_reminder.*
|
||||
import kotlinx.coroutines.launch
|
||||
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.data.AndroidDatabase
|
||||
import net.underdesk.circolapp.shared.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)
|
||||
}
|
||||
dialog.circular = circular
|
||||
return dialog
|
||||
}
|
||||
}
|
||||
|
||||
private var dateNotChosen = true
|
||||
var circular: Circular? = null
|
||||
lateinit var circular: Circular
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
circular = arguments?.getParcelable(CIRCULAR)
|
||||
return inflater.inflate(R.layout.dialog_reminder, container)
|
||||
}
|
||||
|
||||
@@ -101,33 +98,31 @@ class NewReminderFragment : DialogFragment() {
|
||||
minute
|
||||
)
|
||||
|
||||
object : Thread() {
|
||||
override fun run() {
|
||||
context?.let { context ->
|
||||
circular?.let { circular ->
|
||||
AppDatabase.getInstance(context).circularDao()
|
||||
.update(circular.apply { reminder = true })
|
||||
lifecycleScope.launch {
|
||||
context?.let { context ->
|
||||
circular.let { circular ->
|
||||
AndroidDatabase.getDaoInstance(context)
|
||||
.update(circular.id, circular.school, circular.favourite, true)
|
||||
|
||||
val pendingIntent = PendingIntent.getBroadcast(
|
||||
context,
|
||||
circular.id.toInt(),
|
||||
Intent(context, AlarmBroadcastReceiver::class.java)
|
||||
.putExtra(AlarmBroadcastReceiver.CIRCULAR_ID, circular.id)
|
||||
.putExtra(AlarmBroadcastReceiver.SCHOOL_ID, circular.school),
|
||||
0
|
||||
)
|
||||
val pendingIntent = PendingIntent.getBroadcast(
|
||||
context,
|
||||
circular.id.toInt(),
|
||||
Intent(context, AlarmBroadcastReceiver::class.java)
|
||||
.putExtra(AlarmBroadcastReceiver.CIRCULAR_ID, circular.id)
|
||||
.putExtra(AlarmBroadcastReceiver.SCHOOL_ID, circular.school),
|
||||
0
|
||||
)
|
||||
|
||||
AlarmManagerCompat.setExactAndAllowWhileIdle(
|
||||
context.getSystemService(Context.ALARM_SERVICE) as AlarmManager,
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
calendar.timeInMillis,
|
||||
pendingIntent
|
||||
)
|
||||
}
|
||||
AlarmManagerCompat.setExactAndAllowWhileIdle(
|
||||
context.getSystemService(Context.ALARM_SERVICE) as AlarmManager,
|
||||
AlarmManager.RTC_WAKEUP,
|
||||
calendar.timeInMillis,
|
||||
pendingIntent
|
||||
)
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
}.start()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,14 +24,13 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import kotlinx.android.synthetic.main.fragment_circular_letters.view.*
|
||||
import net.underdesk.circolapp.MainActivity
|
||||
import net.underdesk.circolapp.R
|
||||
import net.underdesk.circolapp.adapters.CircularLetterAdapter
|
||||
import net.underdesk.circolapp.data.AppDatabase
|
||||
import net.underdesk.circolapp.data.CircularRepository
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
import net.underdesk.circolapp.data.AndroidCircularRepository
|
||||
import net.underdesk.circolapp.viewmodels.RemindersViewModel
|
||||
import net.underdesk.circolapp.viewmodels.RemindersViewModelFactory
|
||||
|
||||
@@ -39,10 +38,7 @@ class RemindersFragment : Fragment(), MainActivity.SearchCallback {
|
||||
|
||||
private val remindersViewModel: RemindersViewModel by viewModels {
|
||||
RemindersViewModelFactory(
|
||||
CircularRepository.getInstance(
|
||||
AppDatabase.getInstance(requireContext()).circularDao(),
|
||||
ServerAPI.getInstance(requireContext())
|
||||
),
|
||||
AndroidCircularRepository.getInstance(requireContext()),
|
||||
requireActivity().application
|
||||
)
|
||||
}
|
||||
@@ -62,7 +58,7 @@ class RemindersFragment : Fragment(), MainActivity.SearchCallback {
|
||||
{
|
||||
if (root.circulars_list.adapter == null) {
|
||||
root.circulars_list.adapter =
|
||||
CircularLetterAdapter(it, activity as MainActivity)
|
||||
CircularLetterAdapter(it, activity as MainActivity, lifecycleScope)
|
||||
} else {
|
||||
(root.circulars_list.adapter as CircularLetterAdapter).changeDataSet(it)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ import com.github.appintro.SlidePolicy
|
||||
import com.tiper.MaterialSpinner
|
||||
import kotlinx.android.synthetic.main.fragment_school_selection.view.*
|
||||
import net.underdesk.circolapp.R
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
import net.underdesk.circolapp.server.AndroidServerApi
|
||||
import net.underdesk.circolapp.shared.server.ServerAPI
|
||||
|
||||
class SchoolSelectionFragment : Fragment(), SlidePolicy, MaterialSpinner.OnItemSelectedListener {
|
||||
private lateinit var preferenceManager: SharedPreferences
|
||||
@@ -53,7 +54,7 @@ class SchoolSelectionFragment : Fragment(), SlidePolicy, MaterialSpinner.OnItemS
|
||||
editor.putString("school", position.toString())
|
||||
editor.apply()
|
||||
|
||||
ServerAPI.changeServer(position, requireContext())
|
||||
AndroidServerApi.changeServer(position, requireContext())
|
||||
schoolSelected = true
|
||||
|
||||
parent.error = null
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package net.underdesk.circolapp.server
|
||||
|
||||
import android.content.Context
|
||||
import androidx.preference.PreferenceManager
|
||||
import net.underdesk.circolapp.push.FirebaseTopicUtils
|
||||
import net.underdesk.circolapp.shared.server.ServerAPI
|
||||
|
||||
object AndroidServerApi {
|
||||
@Volatile
|
||||
private var instance: ServerAPI? = null
|
||||
|
||||
fun getInstance(server: ServerAPI.Companion.Servers): ServerAPI {
|
||||
return instance ?: synchronized(this) {
|
||||
instance ?: ServerAPI(ServerAPI.createServer(server)).also { instance = it }
|
||||
}
|
||||
}
|
||||
|
||||
fun getInstance(context: Context): ServerAPI {
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val serverID = sharedPreferences.getString("school", "0")?.toInt() ?: 0
|
||||
|
||||
val server = ServerAPI.Companion.Servers.values()[serverID]
|
||||
|
||||
return instance ?: synchronized(this) {
|
||||
instance ?: ServerAPI(ServerAPI.createServer(server)).also { instance = it }
|
||||
}
|
||||
}
|
||||
|
||||
fun changeServer(index: Int, context: Context) {
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val newServer = ServerAPI.Companion.Servers.values()[index]
|
||||
|
||||
val notifyNewCirculars = sharedPreferences.getBoolean("notify_new_circulars", true)
|
||||
val enablePolling = sharedPreferences.getBoolean("enable_polling", false)
|
||||
|
||||
if (notifyNewCirculars && !enablePolling)
|
||||
FirebaseTopicUtils.selectTopic(newServer.toString(), context)
|
||||
|
||||
instance?.changeServer(ServerAPI.createServer(newServer))
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Circolapp
|
||||
* Copyright (C) 2019-2020 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.underdesk.circolapp.server
|
||||
|
||||
import net.underdesk.circolapp.data.Circular
|
||||
|
||||
abstract class Server {
|
||||
abstract val serverID: Int
|
||||
abstract suspend fun getCircularsFromServer(): Pair<List<Circular>, ServerAPI.Companion.Result>
|
||||
abstract suspend fun newCircularsAvailable(): Pair<Boolean, ServerAPI.Companion.Result>
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Circolapp
|
||||
* Copyright (C) 2019-2020 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.underdesk.circolapp.server
|
||||
|
||||
import android.content.Context
|
||||
import androidx.preference.PreferenceManager
|
||||
import net.underdesk.circolapp.data.Circular
|
||||
import net.underdesk.circolapp.push.FirebaseTopicUtils
|
||||
import net.underdesk.circolapp.server.curie.CurieServer
|
||||
import net.underdesk.circolapp.server.porporato.PorporatoServer
|
||||
|
||||
class ServerAPI(
|
||||
private var server: Server
|
||||
) {
|
||||
fun serverID(): Int = server.serverID
|
||||
|
||||
suspend fun getCircularsFromServer(): Pair<List<Circular>, Result> {
|
||||
val newCircularsAvailable = server.newCircularsAvailable()
|
||||
|
||||
if (newCircularsAvailable.second == Result.ERROR)
|
||||
return Pair(emptyList(), Result.ERROR)
|
||||
|
||||
if (!newCircularsAvailable.first)
|
||||
return Pair(emptyList(), Result.SUCCESS)
|
||||
|
||||
return server.getCircularsFromServer()
|
||||
}
|
||||
|
||||
fun changeServer(server: Server) {
|
||||
this.server = server
|
||||
}
|
||||
|
||||
companion object {
|
||||
enum class Servers {
|
||||
CURIE, PORPORATO
|
||||
}
|
||||
|
||||
enum class Result {
|
||||
SUCCESS, ERROR
|
||||
}
|
||||
|
||||
fun getServerId(server: Servers): Int {
|
||||
return Servers.values().indexOf(server)
|
||||
}
|
||||
|
||||
fun getServerName(server: Servers) = when (server) {
|
||||
Servers.CURIE -> "Liceo scientifico Maria Curie"
|
||||
Servers.PORPORATO -> "Liceo G.F. Porporato"
|
||||
}
|
||||
|
||||
@Volatile
|
||||
private var instance: ServerAPI? = null
|
||||
|
||||
fun getInstance(server: Servers): ServerAPI {
|
||||
return instance ?: synchronized(this) {
|
||||
instance ?: ServerAPI(createServer(server)).also { instance = it }
|
||||
}
|
||||
}
|
||||
|
||||
fun getInstance(context: Context): ServerAPI {
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val serverID = sharedPreferences.getString("school", "0")?.toInt() ?: 0
|
||||
|
||||
val server = Servers.values()[serverID]
|
||||
|
||||
return instance ?: synchronized(this) {
|
||||
instance ?: ServerAPI(createServer(server)).also { instance = it }
|
||||
}
|
||||
}
|
||||
|
||||
fun changeServer(index: Int, context: Context) {
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val newServer = Servers.values()[index]
|
||||
|
||||
val notifyNewCirculars = sharedPreferences.getBoolean("notify_new_circulars", true)
|
||||
val enablePolling = sharedPreferences.getBoolean("enable_polling", false)
|
||||
|
||||
if (notifyNewCirculars && !enablePolling)
|
||||
FirebaseTopicUtils.selectTopic(newServer.toString(), context)
|
||||
|
||||
instance?.changeServer(createServer(newServer))
|
||||
}
|
||||
|
||||
private fun createServer(server: Servers) = when (server) {
|
||||
Servers.CURIE -> CurieServer()
|
||||
Servers.PORPORATO -> PorporatoServer()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package net.underdesk.circolapp.server.curie
|
||||
|
||||
import com.squareup.moshi.Moshi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import net.underdesk.circolapp.data.Circular
|
||||
import net.underdesk.circolapp.server.Server
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
import net.underdesk.circolapp.server.curie.pojo.Response
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.Jsoup
|
||||
import java.io.IOException
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class CurieServer : Server() {
|
||||
private val moshi = Moshi.Builder().build()
|
||||
private val responseAdapter = moshi.adapter(Response::class.java)
|
||||
private val client = OkHttpClient()
|
||||
|
||||
override val serverID = ServerAPI.getServerId(ServerAPI.Companion.Servers.CURIE)
|
||||
|
||||
override suspend fun getCircularsFromServer(): Pair<List<Circular>, ServerAPI.Companion.Result> {
|
||||
return try {
|
||||
withContext(Dispatchers.Default) {
|
||||
val json = retrieveDataFromServer()
|
||||
|
||||
val document = Jsoup.parseBodyFragment(json.content.rendered)
|
||||
val htmlList = document.getElementsByTag("ul")[0].getElementsByTag("a")
|
||||
|
||||
val list = ArrayList<Circular>()
|
||||
|
||||
htmlList.forEach { element ->
|
||||
if (element.parents().size == 6) {
|
||||
list.last().attachmentsNames.add(element.text())
|
||||
list.last().attachmentsUrls.add(element.attr("href"))
|
||||
} else if (element.parents().size == 4) {
|
||||
list.add(generateFromString(element.text(), element.attr("href")))
|
||||
}
|
||||
}
|
||||
Pair(list, ServerAPI.Companion.Result.SUCCESS)
|
||||
}
|
||||
} catch (exception: IOException) {
|
||||
Pair(emptyList(), ServerAPI.Companion.Result.ERROR)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun newCircularsAvailable(): Pair<Boolean, ServerAPI.Companion.Result> {
|
||||
return Pair(true, ServerAPI.Companion.Result.SUCCESS)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private suspend fun retrieveDataFromServer(): Response {
|
||||
val request = Request.Builder()
|
||||
.url(ENDPOINT_URL)
|
||||
.build()
|
||||
|
||||
return withContext(Dispatchers.IO) {
|
||||
val response = client.newCall(request).execute()
|
||||
|
||||
if (!response.isSuccessful) {
|
||||
throw IOException("HTTP error code: ${response.code})")
|
||||
}
|
||||
|
||||
responseAdapter.fromJson(
|
||||
response.body!!.string()
|
||||
)!!
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateFromString(string: String, url: String): Circular {
|
||||
val idRegex =
|
||||
"""(\d+)"""
|
||||
val matcherId = Pattern.compile(idRegex).matcher(string)
|
||||
matcherId.find()
|
||||
val id = matcherId.group(1)
|
||||
|
||||
val dateRegex =
|
||||
"""(\d{2}/\d{2}/\d{4})"""
|
||||
val matcherDate = Pattern.compile(dateRegex).matcher(string)
|
||||
|
||||
var title = string.removeSuffix("-signed")
|
||||
|
||||
return if (matcherDate.find()) {
|
||||
title = title.removeRange(0, matcherDate.end())
|
||||
.removePrefix(" ")
|
||||
.removePrefix("_")
|
||||
.removePrefix(" ")
|
||||
|
||||
Circular(id.toLong(), serverID, title, url, matcherDate.group(1) ?: "")
|
||||
} else {
|
||||
Circular(id.toLong(), serverID, title, url, "")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ENDPOINT_URL = "https://www.curiepinerolo.edu.it/wp-json/wp/v2/pages/5958"
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package net.underdesk.circolapp.server.curie.pojo
|
||||
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Content(
|
||||
val rendered: String
|
||||
)
|
||||
@@ -1,8 +0,0 @@
|
||||
package net.underdesk.circolapp.server.curie.pojo
|
||||
|
||||
import com.squareup.moshi.JsonClass
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class Response(
|
||||
val content: Content
|
||||
)
|
||||
@@ -1,160 +0,0 @@
|
||||
package net.underdesk.circolapp.server.porporato
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import net.underdesk.circolapp.data.Circular
|
||||
import net.underdesk.circolapp.server.Server
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.Jsoup
|
||||
import java.io.IOException
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class PorporatoServer : Server() {
|
||||
private val client = OkHttpClient()
|
||||
|
||||
private val baseUrl = "https://www.liceoporporato.edu.it/ARCHIVIO/PR/VP/"
|
||||
private val endpointUrls = listOf(
|
||||
"https://www.liceoporporato.edu.it/ARCHIVIO/PR/VP/circolari.php?dirname=CIRCOLARIP/- CIRCOLARI 2020-21/-01-Settembre/",
|
||||
"https://www.liceoporporato.edu.it/ARCHIVIO/PR/VP/circolari.php?dirname=CIRCOLARIP/- CIRCOLARI 2020-21/-02-Ottobre/",
|
||||
"https://www.liceoporporato.edu.it/ARCHIVIO/PR/VP/circolari.php?dirname=CIRCOLARIP/- CIRCOLARI 2020-21/-03-Novembre/",
|
||||
"https://www.liceoporporato.edu.it/ARCHIVIO/PR/VP/circolari.php?dirname=CIRCOLARIP/- CIRCOLARI 2020-21/-04-Dicembre/",
|
||||
"https://www.liceoporporato.edu.it/ARCHIVIO/PR/VP/circolari.php?dirname=CIRCOLARIP/- CIRCOLARI 2020-21/-05-Gennaio/",
|
||||
"https://www.liceoporporato.edu.it/ARCHIVIO/PR/VP/circolari.php?dirname=CIRCOLARIP/- CIRCOLARI 2020-21/-06-Febbraio/",
|
||||
"https://www.liceoporporato.edu.it/ARCHIVIO/PR/VP/circolari.php?dirname=CIRCOLARIP/- CIRCOLARI 2020-21/-07-Marzo/",
|
||||
"https://www.liceoporporato.edu.it/ARCHIVIO/PR/VP/circolari.php?dirname=CIRCOLARIP/- CIRCOLARI 2020-21/-08-Aprile/",
|
||||
"https://www.liceoporporato.edu.it/ARCHIVIO/PR/VP/circolari.php?dirname=CIRCOLARIP/- CIRCOLARI 2020-21/-09-Maggio/",
|
||||
"https://www.liceoporporato.edu.it/ARCHIVIO/PR/VP/circolari.php?dirname=CIRCOLARIP/- CIRCOLARI 2020-21/-10-Giugno/",
|
||||
"https://www.liceoporporato.edu.it/ARCHIVIO/PR/VP/circolari.php?dirname=CIRCOLARIP/- CIRCOLARI 2020-21/-11-Luglio/",
|
||||
"https://www.liceoporporato.edu.it/ARCHIVIO/PR/VP/circolari.php?dirname=CIRCOLARIP/- CIRCOLARI 2020-21/-12-Agosto/"
|
||||
)
|
||||
|
||||
override val serverID = ServerAPI.getServerId(ServerAPI.Companion.Servers.PORPORATO)
|
||||
|
||||
override suspend fun getCircularsFromServer(): Pair<List<Circular>, ServerAPI.Companion.Result> {
|
||||
return try {
|
||||
val list = arrayListOf<Circular>()
|
||||
|
||||
for (url in endpointUrls) {
|
||||
list.addAll(parsePage(url))
|
||||
}
|
||||
|
||||
list.sortByDescending { it.id }
|
||||
|
||||
Pair(list, ServerAPI.Companion.Result.SUCCESS)
|
||||
} catch (exception: IOException) {
|
||||
Pair(emptyList(), ServerAPI.Companion.Result.ERROR)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun newCircularsAvailable(): Pair<Boolean, ServerAPI.Companion.Result> {
|
||||
return Pair(true, ServerAPI.Companion.Result.SUCCESS)
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private suspend fun parsePage(url: String): List<Circular> {
|
||||
val response = retrieveDataFromServer(url)
|
||||
|
||||
return withContext(Dispatchers.Default) {
|
||||
val document = Jsoup.parseBodyFragment(response)
|
||||
val htmlList = document.getElementsByTag("table")[2]
|
||||
.getElementsByTag("td")[2]
|
||||
.getElementsByTag("a")
|
||||
|
||||
val list = ArrayList<Circular>()
|
||||
|
||||
for (i in 0 until htmlList.size) {
|
||||
list.add(
|
||||
generateFromString(
|
||||
htmlList[i].text(),
|
||||
htmlList[i].attr("href"),
|
||||
i.toLong()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// Identify and group all attachments
|
||||
list.removeAll { attachment ->
|
||||
if (attachment.name.startsWith("All", true)) {
|
||||
val parent = list.find { it.id == attachment.id && !it.name.startsWith("All") }
|
||||
parent?.attachmentsNames?.add(attachment.name)
|
||||
parent?.attachmentsUrls?.add(attachment.url)
|
||||
|
||||
return@removeAll true
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
// Identify and group attachments not marked with "All"
|
||||
var lastIndex = -1
|
||||
var lastId = -1L
|
||||
|
||||
list.removeAll { attachment ->
|
||||
if (lastId == attachment.id) {
|
||||
val parent = list[lastIndex]
|
||||
parent.attachmentsNames.add(attachment.name)
|
||||
parent.attachmentsUrls.add(attachment.url)
|
||||
|
||||
return@removeAll true
|
||||
}
|
||||
lastId = attachment.id
|
||||
lastIndex = list.indexOf(attachment)
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
list
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private suspend fun retrieveDataFromServer(url: String): String {
|
||||
val request = Request.Builder()
|
||||
.url(url)
|
||||
.build()
|
||||
|
||||
return withContext(Dispatchers.IO) {
|
||||
val response = client.newCall(request).execute()
|
||||
|
||||
if (!response.isSuccessful) {
|
||||
throw IOException("HTTP error code: ${response.code})")
|
||||
}
|
||||
|
||||
response.body!!.string()
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateFromString(string: String, path: String, index: Long): Circular {
|
||||
val fullUrl = baseUrl + path
|
||||
var title = string
|
||||
|
||||
val idRegex =
|
||||
"""(\d+)"""
|
||||
val matcherId = Pattern.compile(idRegex).matcher(string)
|
||||
val id = if (!string.startsWith("Avviso") && matcherId.find()) {
|
||||
title = title.removeRange(matcherId.start(), matcherId.end())
|
||||
.removePrefix(" ")
|
||||
.removePrefix("-")
|
||||
.removePrefix(" ")
|
||||
|
||||
matcherId.group(1)?.toLong() ?: -index
|
||||
} else {
|
||||
-index
|
||||
}
|
||||
|
||||
val dateRegex =
|
||||
"""(\d{2}-\d{2}-\d{4})"""
|
||||
val matcherDate = Pattern.compile(dateRegex).matcher(title)
|
||||
|
||||
return if (matcherDate.find()) {
|
||||
title = title.removeRange(matcherDate.start(), matcherDate.end())
|
||||
.removeSuffix(" (pubb.: )")
|
||||
|
||||
Circular(id, serverID, title, fullUrl, matcherDate.group(1)?.replace("-", "/") ?: "")
|
||||
} else {
|
||||
Circular(id, serverID, title, fullUrl, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,8 @@ import android.content.SharedPreferences
|
||||
import androidx.lifecycle.*
|
||||
import androidx.preference.PreferenceManager
|
||||
import kotlinx.coroutines.launch
|
||||
import net.underdesk.circolapp.data.Circular
|
||||
import net.underdesk.circolapp.data.CircularRepository
|
||||
import net.underdesk.circolapp.shared.data.Circular
|
||||
import net.underdesk.circolapp.shared.data.CircularRepository
|
||||
import net.underdesk.circolapp.utils.DoubleTrigger
|
||||
|
||||
class CircularLetterViewModel internal constructor(
|
||||
@@ -40,12 +40,12 @@ class CircularLetterViewModel internal constructor(
|
||||
val circulars: LiveData<List<Circular>> =
|
||||
Transformations.switchMap(DoubleTrigger(query, schoolID)) { input ->
|
||||
if (input.first == null || input.first == "") {
|
||||
circularRepository.circularDao.getLiveCirculars(input.second ?: 0)
|
||||
circularRepository.circularDao.getFlowCirculars(input.second ?: 0).asLiveData()
|
||||
} else {
|
||||
circularRepository.circularDao.searchCirculars(
|
||||
"%${input.first}%",
|
||||
input.second ?: 0
|
||||
)
|
||||
).asLiveData()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package net.underdesk.circolapp.viewmodels
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import net.underdesk.circolapp.data.CircularRepository
|
||||
import net.underdesk.circolapp.shared.data.CircularRepository
|
||||
|
||||
class CircularLetterViewModelFactory(
|
||||
private val circularRepository: CircularRepository,
|
||||
|
||||
@@ -20,13 +20,10 @@ package net.underdesk.circolapp.viewmodels
|
||||
|
||||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.Transformations
|
||||
import androidx.lifecycle.*
|
||||
import androidx.preference.PreferenceManager
|
||||
import net.underdesk.circolapp.data.Circular
|
||||
import net.underdesk.circolapp.data.CircularRepository
|
||||
import net.underdesk.circolapp.shared.data.Circular
|
||||
import net.underdesk.circolapp.shared.data.CircularRepository
|
||||
import net.underdesk.circolapp.utils.DoubleTrigger
|
||||
|
||||
class FavouritesViewModel internal constructor(
|
||||
@@ -46,12 +43,12 @@ class FavouritesViewModel internal constructor(
|
||||
val circulars: LiveData<List<Circular>> =
|
||||
Transformations.switchMap(DoubleTrigger(query, schoolID)) { input ->
|
||||
if (input.first == null || input.first == "") {
|
||||
circularRepository.circularDao.getFavourites(input.second ?: 0)
|
||||
circularRepository.circularDao.getFavourites(input.second ?: 0).asLiveData()
|
||||
} else {
|
||||
circularRepository.circularDao.searchFavourites(
|
||||
"%${input.first}%",
|
||||
input.second ?: 0
|
||||
)
|
||||
).asLiveData()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package net.underdesk.circolapp.viewmodels
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import net.underdesk.circolapp.data.CircularRepository
|
||||
import net.underdesk.circolapp.shared.data.CircularRepository
|
||||
|
||||
class FavouritesViewModelFactory(
|
||||
private val circularRepository: CircularRepository,
|
||||
|
||||
@@ -20,13 +20,10 @@ package net.underdesk.circolapp.viewmodels
|
||||
|
||||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.Transformations
|
||||
import androidx.lifecycle.*
|
||||
import androidx.preference.PreferenceManager
|
||||
import net.underdesk.circolapp.data.Circular
|
||||
import net.underdesk.circolapp.data.CircularRepository
|
||||
import net.underdesk.circolapp.shared.data.Circular
|
||||
import net.underdesk.circolapp.shared.data.CircularRepository
|
||||
import net.underdesk.circolapp.utils.DoubleTrigger
|
||||
|
||||
class RemindersViewModel internal constructor(
|
||||
@@ -46,12 +43,12 @@ class RemindersViewModel internal constructor(
|
||||
val circulars: LiveData<List<Circular>> =
|
||||
Transformations.switchMap(DoubleTrigger(query, schoolID)) { input ->
|
||||
if (input.first == null || input.first == "") {
|
||||
circularRepository.circularDao.getReminders(input.second ?: 0)
|
||||
circularRepository.circularDao.getReminders(input.second ?: 0).asLiveData()
|
||||
} else {
|
||||
circularRepository.circularDao.searchReminders(
|
||||
"%${input.first}%",
|
||||
input.second ?: 0
|
||||
)
|
||||
).asLiveData()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package net.underdesk.circolapp.viewmodels
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import net.underdesk.circolapp.data.CircularRepository
|
||||
import net.underdesk.circolapp.shared.data.CircularRepository
|
||||
|
||||
class RemindersViewModelFactory(
|
||||
private val circularRepository: CircularRepository,
|
||||
|
||||
@@ -33,10 +33,8 @@ import androidx.work.*
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import net.underdesk.circolapp.MainActivity
|
||||
import net.underdesk.circolapp.R
|
||||
import net.underdesk.circolapp.data.AppDatabase
|
||||
import net.underdesk.circolapp.data.Circular
|
||||
import net.underdesk.circolapp.data.CircularRepository
|
||||
import net.underdesk.circolapp.server.ServerAPI
|
||||
import net.underdesk.circolapp.data.AndroidCircularRepository
|
||||
import net.underdesk.circolapp.shared.data.Circular
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class PollWork(appContext: Context, workerParams: WorkerParameters) :
|
||||
@@ -93,10 +91,7 @@ class PollWork(appContext: Context, workerParams: WorkerParameters) :
|
||||
}
|
||||
|
||||
override suspend fun doWork(): Result = coroutineScope {
|
||||
val circularRepository = CircularRepository.getInstance(
|
||||
AppDatabase.getInstance(applicationContext).circularDao(),
|
||||
ServerAPI.getInstance(applicationContext)
|
||||
)
|
||||
val circularRepository = AndroidCircularRepository.getInstance(applicationContext)
|
||||
|
||||
val result = circularRepository.updateCirculars()
|
||||
if (!result.second)
|
||||
|
||||
Reference in New Issue
Block a user