Refactor to organise the project and change visibility modifiers

This commit is contained in:
Deniz Düzgören
2019-09-01 11:54:12 +02:00
parent d4e69462b6
commit 82b5fa1b97
34 changed files with 418 additions and 215 deletions
@@ -0,0 +1,236 @@
package com.denizd.substitutionplan.data
import android.app.*
import android.content.Context
import android.content.Intent
import android.media.RingtoneManager
import android.net.Uri
import android.os.AsyncTask
import android.os.Build
import android.preference.PreferenceManager
import android.view.View
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.denizd.substitutionplan.database.FoodRepository
import com.denizd.substitutionplan.R
import com.denizd.substitutionplan.database.SubstRepository
import com.denizd.substitutionplan.activities.Main
import com.denizd.substitutionplan.models.Food
import com.denizd.substitutionplan.models.Subst
import com.google.android.material.snackbar.Snackbar
import org.jsoup.Jsoup
import kotlin.collections.ArrayList
/**
* This class gets data from the djd4rkn355.github.io domain asynchronously and persists it in the
* database. By using booleans as parameters, network usage and speed can be improved as only
* requested data will be downloaded and processed.
*
* @param isPlan substitution plan will be downloaded and persisted in the database if true
* @param isMenu food menu will be downloaded and persisted in the database if true
* @param isJobService a notification will be prepared and sent if this and isPlan is true
*/
internal class DataFetcher(isPlan: Boolean, isMenu: Boolean, isJobService: Boolean, context: Context, application: Application, parentView: View?) : AsyncTask<Void, Void, Void>() {
private var jobService = isJobService
private var plan = isPlan
private var menu = isMenu
private var mContext = context
private var mApplication = application
private var mView = parentView
private var priority = 200
private var notifText = ""
private var informational = ""
private val prefs = PreferenceManager.getDefaultSharedPreferences(mContext)
private val edit = prefs.edit()
private var currentTime = ""
private var currentFoodTime = ""
private var substUrl = "https://djd4rkn355.github.io/subst.html"
private var foodUrl = "https://djd4rkn355.github.io/food.html"
override fun doInBackground(vararg params: Void?): Void? {
try {
if (prefs.getBoolean("testUrls", false)) {
substUrl = "https://djd4rkn355.github.io/subst_test.html"
foodUrl = "https://djd4rkn355.github.io/food_test.html"
}
when {
menu -> requestFoodMenuData()
plan -> requestSubstPlanAndNotification()
}
if (plan || menu) {
mView?.let { v: View ->
val snackText = "${mContext.getText(R.string.lastUpdated)} ${when {
menu -> currentFoodTime
else -> currentTime
}}"
val snackBarView = v.findViewById<View>(R.id.coordination)
Snackbar.make(snackBarView, snackText, Snackbar.LENGTH_LONG).show()
}
}
} catch (e: Exception) {
mView?.let { v: View ->
val snackBarView = v.findViewById<View>(R.id.coordination)
Snackbar.make(snackBarView, mContext.getString(R.string.noInternet), Snackbar.LENGTH_LONG).setBackgroundTint(ContextCompat.getColor(mContext,
R.color.colorError
)).show()
}
}
return null
}
override fun onPostExecute(result: Void?) {
mView?.let {
try {
it.findViewById<SwipeRefreshLayout>(R.id.pullToRefresh).isRefreshing = false
} catch (ignored: Exception) {}
}
}
private fun requestFoodMenuData() {
val docFood = Jsoup.connect(foodUrl).get()
currentFoodTime = docFood.select("h1")[0].text()
if (currentFoodTime != prefs.getString("timeFoodNew", "")) {
val foodRepository = FoodRepository(mApplication)
val foodElements = docFood.select("th")
foodRepository.deleteAll()
val indices = ArrayList<Int>()
val daysAndVon = arrayOf("Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "von")
for (i in 0 until foodElements.size) {
if (checkStringForArray(foodElements[i].text(), daysAndVon)) indices.add(i)
}
indices.add(foodElements.size)
for ((priority, l) in (0 until indices.size - 1).withIndex()) {
var s = ""
for (i2 in indices[l] until indices[l + 1]) {
if (s.isEmpty()) {
s = foodElements[i2].text()
} else {
s += "\n${foodElements[i2].text()}"
}
}
foodRepository.insert(Food(s, priority))
}
edit.putString("timeFoodNew", currentFoodTime).apply()
}
}
private fun requestSubstPlanAndNotification() {
val doc = Jsoup.connect(substUrl).get()
currentTime = doc.select("h1")[0].text()
if (currentTime != prefs.getString("timeNew", "")) {
val substRepo = SubstRepository(mApplication)
val rows = doc.select("tr")
val paragraphs = doc.select("p")
val substArray = ArrayList<Subst>()
val coursePreference = prefs.getString("courses", "") ?: ""
val classPreference = prefs.getString("classes", "") ?: ""
for (i in 0 until paragraphs.size) {
if (i == 0) {
informational = paragraphs[i].text()
} else {
informational += "\n\n" + paragraphs[i].text()
}
}
edit.putString("informational", informational).apply()
substRepo.deleteAllSubst()
for (i in 0 until rows.size) {
val row = rows[i]
val cols = row.select("th")
val group = cols[0].text()
val course = cols[3].text()
val additional = cols[5].text()
val subst = Subst(
group = group, date = cols[1].text(), time = cols[2].text(), course = course,
room = cols[4].text(), additional = additional, priority = priority
)
substArray.add(subst)
substRepo.insert(subst)
priority--
}
if (jobService && prefs.getBoolean("notif", true)) {
substArray.filter {
MiscData.checkPersonalSubstitutions(
it,
coursePreference,
classPreference,
false
)
}.forEach { substItem ->
notifText += "${if (notifText.isNotEmpty()) ",\n" else ""}$substItem.course: ${if (substItem.additional.isNotEmpty()) substItem.additional else "---"}"
}
}
if (notifText.isNotEmpty()) {
sendNotification()
}
edit.putString("timeNew", currentTime).apply()
}
}
private fun sendNotification() {
val openApp = Intent(mContext, Main::class.java)
openApp.flags = Intent.FLAG_ACTIVITY_NEW_TASK
openApp.flags += Intent.FLAG_ACTIVITY_CLEAR_TASK
val openAppPending = PendingIntent.getActivity(mContext, 0, openApp, 0)
val notificationLayout = RemoteViews(mContext.packageName,
R.layout.notification
)
notificationLayout.setTextViewText(
R.id.notification_title, mContext.getString(
R.string.substitutionPlan
))
notificationLayout.setTextViewText(R.id.notification_textview, notifText)
val manager = mContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
MiscData.getNotificationChannel(mContext, prefs)
val notification = NotificationCompat.Builder(mContext,
MiscData.notificationChannelId
)
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(notificationLayout)
.setSmallIcon(R.drawable.ic_avh)
.setContentIntent(openAppPending)
.setAutoCancel(true)
.setColor(ContextCompat.getColor(mContext,
R.color.colorAccent
))
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
val sound = if ((prefs.getString("ringtoneUri", "") ?: "").isNotEmpty()) {
Uri.parse(prefs.getString("ringtoneUri", "") ?: "")
} else {
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
}
notification.setSound(sound)
}
manager.notify(1, notification.build())
}
private fun checkStringForArray(s: String, checking: Array<String>): Boolean {
for (i in checking.indices) {
if (s.contains(checking[i])) {
return true
}
}
return false
}
}
@@ -0,0 +1,167 @@
package com.denizd.substitutionplan.data
import android.annotation.TargetApi
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.SharedPreferences
import android.graphics.Color
import com.denizd.substitutionplan.R
import com.denizd.substitutionplan.models.Subst
import java.util.*
internal object MiscData {
val languageIndependentCourses = arrayOf("German", "English", "French", "Spanish", "Latin", "Turkish", "Chinese", "Arts", "Music",
"Theatre", "Geography", "History", "Politics", "Philosophy", "Religion", "Maths", "Biology", "Chemistry",
"Physics", "CompSci", "PhysEd", "GLL", "WAT", "Forder", "WP")
val colourNames = arrayOf("default", "red", "orange", "yellow", "green", "teal", "cyan", "blue", "purple", "pink",
"brown", "grey", "pureWhite", "salmon", "tangerine", "banana", "flora", "spindrift", "sky", "orchid",
"lavender", "carnation", "brown2", "pureBlack")
private val colourIntegers = intArrayOf(0,
R.color.bgRed,
R.color.bgOrange,
R.color.bgYellow,
R.color.bgGreen,
R.color.bgTeal,
R.color.bgCyan,
R.color.bgBlue,
R.color.bgPurple,
R.color.bgPink,
R.color.bgBrown,
R.color.bgGrey,
R.color.bgPureWhite,
R.color.bgSalmon,
R.color.bgTangerine,
R.color.bgBanana,
R.color.bgFlora,
R.color.bgSpindrift,
R.color.bgSky,
R.color.bgOrchid,
R.color.bgLavender,
R.color.bgCarnation,
R.color.bgBrown2,
R.color.bgPureBlack
)
const val notificationChannelId = "general"
fun getColourForString(name: String): Int {
return when (name) {
"red" -> R.color.bgRed
"orange" -> R.color.bgOrange
"yellow" -> R.color.bgYellow
"green" -> R.color.bgGreen
"teal" -> R.color.bgTeal
"cyan" -> R.color.bgCyan
"blue" -> R.color.bgBlue
"purple" -> R.color.bgPurple
"pink" -> R.color.bgPink
"brown" -> R.color.bgBrown
"grey" -> R.color.bgGrey
"pureWhite" -> R.color.bgPureWhite
"salmon" -> R.color.bgSalmon
"tangerine" -> R.color.bgTangerine
"banana" -> R.color.bgBanana
"flora" -> R.color.bgFlora
"spindrift" -> R.color.bgSpindrift
"sky" -> R.color.bgSky
"orchid" -> R.color.bgOrchid
"lavender" -> R.color.bgLavender
"carnation" -> R.color.bgCarnation
"brown2" -> R.color.bgBrown2
"pureBlack" -> R.color.bgPureBlack
else -> R.color.colorBackgroundLight
}
}
fun getIconForCourse(course: String): Int {
return with (course.toLowerCase(Locale.ROOT)) {
when {
contains("deu") || contains("dep") || contains("daz") -> R.drawable.ic_german
contains("mat") || contains("map") -> R.drawable.ic_maths
contains("eng") || contains("enp") || contains("ena") -> R.drawable.ic_english
contains("spo") || contains("spp") || contains("spth") -> R.drawable.ic_pe
contains("pol") || contains("pop") -> R.drawable.ic_politics
contains("dar") || contains("dap") -> R.drawable.ic_drama
contains("phy") || contains("php") -> R.drawable.ic_physics
contains("bio") || contains("bip") || contains("nw") -> R.drawable.ic_biology
contains("che") || contains("chp") -> R.drawable.ic_chemistry
contains("phi") || contains("psp") -> R.drawable.ic_philosophy
contains("laa") || contains("laf") || contains("lat") -> R.drawable.ic_latin
contains("spa") || contains("spf") -> R.drawable.ic_spanish
contains("fra") || contains("frf") || contains("frz") -> R.drawable.ic_french
contains("inf") -> R.drawable.ic_compsci
contains("ges") -> R.drawable.ic_history
contains("rel") -> R.drawable.ic_religion
contains("geg") || contains("wuk") -> R.drawable.ic_geography
contains("kun") -> R.drawable.ic_arts
contains("mus") -> R.drawable.ic_music
contains("tue") -> R.drawable.ic_turkish
contains("chi") -> R.drawable.ic_chinese
contains("gll") -> R.drawable.ic_gll
contains("wat") -> R.drawable.ic_wat
contains("för") -> R.drawable.ic_help
contains("wp") || contains("met") -> R.drawable.ic_pencil
else -> R.drawable.ic_empty
}
}
}
fun transferOldColourIntsToString(prefs: SharedPreferences) {
var colour = ""
val edit = prefs.edit()
for (course in languageIndependentCourses) {
for (i in 0 until colourIntegers.size) {
if (prefs.getInt("bg$course", 0) == colourIntegers[i]) {
colour = colourNames[i]
break
}
colour = ""
}
edit.putString("card$course", colour)
}
edit.apply()
}
fun checkPersonalSubstitutions(subst: Subst, coursePreference: String, classPreference: String, psa: Boolean): Boolean {
val group = subst.group
val course = subst.course
if (psa && subst.date.isNotEmpty() && subst.date.substring(0, 3) == "psa") {
return true
}
if (coursePreference.isEmpty() && classPreference.isNotEmpty()) {
if (group.isNotEmpty() && group != "") {
if (classPreference.contains(group) || group.contains(classPreference)) {
return true
}
}
} else if (classPreference.isNotEmpty() && coursePreference.isNotEmpty()) {
if (group != "" && course != "") {
if (coursePreference.contains(course)) {
if (classPreference.contains(group) || group.contains(classPreference)) {
return true
}
}
}
}
return false
}
@TargetApi(26)
fun getNotificationChannel(context: Context, prefs: SharedPreferences): NotificationChannel {
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
return if (!prefs.getBoolean("notifChannelCreated", false)) {
val channel = NotificationChannel(
notificationChannelId, context.getString(
R.string.general
), NotificationManager.IMPORTANCE_DEFAULT)
channel.enableLights(true)
channel.lightColor = Color.BLUE
manager.createNotificationChannel(channel)
prefs.edit().putBoolean("notifChannelCreated", true).apply()
channel
} else {
manager.getNotificationChannel(notificationChannelId)
}
}
}