Info table now recognises line breaks from the website and shows them in the dialog; implemented debug dialog that presents the most recent exception caused in DataFetcher.kt

This commit is contained in:
Deniz Düzgören
2019-10-18 21:25:54 +02:00
parent b332381342
commit 0c5f075fd0
5 changed files with 98 additions and 71 deletions
+2 -2
View File
@@ -10,8 +10,8 @@ android {
applicationId "com.denizd.substitutionplan" applicationId "com.denizd.substitutionplan"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 29
versionCode 41 versionCode 42
versionName "2.3.3" versionName "2.3.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {
@@ -86,10 +86,10 @@ internal class Main : AppCompatActivity(R.layout.app_bar_main) {
val contextView = findViewById<View>(R.id.coordination) val contextView = findViewById<View>(R.id.coordination)
val window = this.window val window = this.window
/// Sets the theme explicitly to dismiss the splash screen // Sets the theme explicitly to dismiss the splash screen
setTheme(R.style.AppTheme0) setTheme(R.style.AppTheme0)
/// Sets the system bar's colours according to the current Android version // Sets the system bar's colours according to the current Android version
val barColour = when { val barColour = when {
Build.VERSION.SDK_INT < Build.VERSION_CODES.M -> ContextCompat.getColor(context, R.color.legacyBlack) Build.VERSION.SDK_INT < Build.VERSION_CODES.M -> ContextCompat.getColor(context, R.color.legacyBlack)
Build.VERSION.SDK_INT <= Build.VERSION_CODES.P -> ContextCompat.getColor(context, R.color.colorBackground) Build.VERSION.SDK_INT <= Build.VERSION_CODES.P -> ContextCompat.getColor(context, R.color.colorBackground)
@@ -100,7 +100,7 @@ internal class Main : AppCompatActivity(R.layout.app_bar_main) {
window.statusBarColor = barColour window.statusBarColor = barColour
} }
/// Applies theming with additional workarounds for API levels 23-28 (M-P) // Applies theming with additional workarounds for API levels 23-28 (M-P)
when (prefs.getInt("themeInt", 0)) { when (prefs.getInt("themeInt", 0)) {
0 -> { 0 -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
@@ -113,7 +113,7 @@ internal class Main : AppCompatActivity(R.layout.app_bar_main) {
else -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) else -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
} }
/// Displays the date and time of the last refresh of the substitution plan in a snack bar // Displays the date and time of the last refresh of the substitution plan in a snack bar
if (!prefs.getBoolean("autoRefresh", false) && prefs.getInt("firstTimeOpening", 0) != 0) { if (!prefs.getBoolean("autoRefresh", false) && prefs.getInt("firstTimeOpening", 0) != 0) {
try { try {
Snackbar.make(contextView, "${getString(R.string.last_updated)} ${prefs.getString("timeNew", "")}", Snackbar.LENGTH_LONG).show() Snackbar.make(contextView, "${getString(R.string.last_updated)} ${prefs.getString("timeNew", "")}", Snackbar.LENGTH_LONG).show()
@@ -136,12 +136,12 @@ internal class Main : AppCompatActivity(R.layout.app_bar_main) {
"" ""
} }
/// Legacy function // Legacy function
if (prefs.getInt("firstTimeOpening", 0) == 0) { if (prefs.getInt("firstTimeOpening", 0) == 0) {
edit.putInt("firstTimeOpening", prefs.getInt("firstTimeOpening", 0) + 1).apply() edit.putInt("firstTimeOpening", prefs.getInt("firstTimeOpening", 0) + 1).apply()
} }
/// Launch the user-specified fragment (general or personal plan) // Launch the user-specified fragment (general or personal plan)
val defaultFragment = if (prefs.getBoolean("defaultPersonalised", false)) { val defaultFragment = if (prefs.getBoolean("defaultPersonalised", false)) {
bottomNav.selectedItemId = R.id.personal bottomNav.selectedItemId = R.id.personal
toolbarTxt.text = personalPlanTitle() toolbarTxt.text = personalPlanTitle()
@@ -153,7 +153,7 @@ internal class Main : AppCompatActivity(R.layout.app_bar_main) {
} }
loadFragment(defaultFragment) loadFragment(defaultFragment)
/// Opens the corresponding fragment or the info dialog // Opens the corresponding fragment or the info dialog
bottomNav.setOnNavigationItemSelectedListener { item: MenuItem -> bottomNav.setOnNavigationItemSelectedListener { item: MenuItem ->
val fragment = when (item.itemId) { val fragment = when (item.itemId) {
R.id.plan -> { R.id.plan -> {
@@ -185,7 +185,7 @@ internal class Main : AppCompatActivity(R.layout.app_bar_main) {
} }
} }
/// Scrolls to the top of any currently displayed fragment // Scrolls to the top of any currently displayed fragment
bottomNav.setOnNavigationItemReselectedListener { item: MenuItem -> bottomNav.setOnNavigationItemReselectedListener { item: MenuItem ->
when (item.itemId) { when (item.itemId) {
R.id.plan, R.id.personal, R.id.menu -> { R.id.plan, R.id.personal, R.id.menu -> {
@@ -255,7 +255,7 @@ internal class Main : AppCompatActivity(R.layout.app_bar_main) {
return true return true
} }
/// Triggers FBPingService.kt to re-subscribe to the selected Firebase topics every 15 minutes // Triggers FBPingService.kt to re-subscribe to the selected Firebase topics every 15 minutes
private fun pingFirebaseTopics() { private fun pingFirebaseTopics() {
val componentName = ComponentName(this, FBPingService::class.java) val componentName = ComponentName(this, FBPingService::class.java)
val info = JobInfo.Builder(42, componentName) val info = JobInfo.Builder(42, componentName)
@@ -7,9 +7,12 @@ import android.media.RingtoneManager
import android.net.Uri import android.net.Uri
import android.os.AsyncTask import android.os.AsyncTask
import android.os.Build import android.os.Build
import android.util.Log
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import android.view.View import android.view.View
import android.widget.RemoteViews import android.widget.RemoteViews
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
@@ -73,6 +76,8 @@ internal class DataFetcher(
if (prefs.getBoolean("testUrls", false)) { if (prefs.getBoolean("testUrls", false)) {
substUrl = "https://djd4rkn355.github.io/subst_test.html" substUrl = "https://djd4rkn355.github.io/subst_test.html"
foodUrl = "https://djd4rkn355.github.io/food_test.html" foodUrl = "https://djd4rkn355.github.io/food_test.html"
} else if ((prefs.getString("custom_test_url", "") ?: "").isNotEmpty()) {
substUrl = "https://djd4rkn355.github.io/${prefs.getString("custom_test_url", "")}"
} }
if (forceRefresh) { if (forceRefresh) {
@@ -99,13 +104,13 @@ internal class DataFetcher(
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace()
mView.get()?.let { v: View -> mView.get()?.let { v: View ->
val snackBarView = v.findViewById<View>(R.id.coordination) val snackBarView = v.findViewById<View>(R.id.coordination)
Snackbar.make(snackBarView, mContext.get()?.getString(R.string.no_internet_connection) ?: "", Snackbar.LENGTH_LONG).setBackgroundTint(ContextCompat.getColor(mContext.get()!!, Snackbar.make(snackBarView, mContext.get()?.getString(R.string.no_internet_connection) ?: "", Snackbar.LENGTH_LONG).setBackgroundTint(ContextCompat.getColor(mContext.get()!!,
R.color.colorError R.color.colorError
)).show() )).show()
} }
prefs.edit().putString("debug_recent_exception", Log.getStackTraceString(e)).apply()
} }
return null return null
} }
@@ -157,7 +162,7 @@ internal class DataFetcher(
val substRepo = SubstRepository(mApplication) val substRepo = SubstRepository(mApplication)
if (currentTime != prefs.getString("timeNew", "")) { if (currentTime != prefs.getString("timeNew", "")) {
val rows = doc.select("tr") val rows = doc.select("tr")
val paragraphs = doc.select("p") val paragraphs = doc.select("h6")
val substArray = ArrayList<Substitution>() val substArray = ArrayList<Substitution>()
val coursePreference = prefs.getString("courses", "") ?: "" val coursePreference = prefs.getString("courses", "") ?: ""
@@ -165,9 +170,9 @@ internal class DataFetcher(
for (i in 0 until paragraphs.size) { for (i in 0 until paragraphs.size) {
if (i == 0) { if (i == 0) {
informational = paragraphs[i].text() informational = formatElement(paragraphs[i].html())
} else { } else {
informational += "\n\n" + paragraphs[i].text() informational += "\n\n" + formatElement(paragraphs[i].html())
} }
} }
edit.putString("informational", informational).apply() edit.putString("informational", informational).apply()
@@ -189,7 +194,7 @@ internal class DataFetcher(
additional = cols[5].text(), additional = cols[5].text(),
teacher = cols[6].text(), teacher = cols[6].text(),
type = cols[7].text(), type = cols[7].text(),
priority = HelperFunctions.assignRanking(group, date.substring(0, 3) == "psa"), priority = HelperFunctions.assignRanking(group, (date.length > 2 && date.substring(0, 3) == "psa")),
date_priority = HelperFunctions.assignDatePriority(date), date_priority = HelperFunctions.assignDatePriority(date),
website_priority = websitePriority website_priority = websitePriority
) )
@@ -268,4 +273,9 @@ internal class DataFetcher(
manager.notify(1, notification.build()) manager.notify(1, notification.build())
} }
} }
private fun formatElement(element: String): String {
return element
.replace("<br>", "\n")
}
} }
@@ -414,8 +414,9 @@ internal class SettingsFragment : Fragment(), View.OnClickListener, View.OnLongC
R.string.experimental_menu_dialog_text R.string.experimental_menu_dialog_text
) )
dialogButton.setOnClickListener { dialogButton.setOnClickListener {
when (dialogEditText.text.toString()) { with (dialogEditText.text.toString()) {
"_statistics" -> { when {
this == "_statistics" -> {
val alertDialogDev = AlertDialog.Builder(mContext) val alertDialogDev = AlertDialog.Builder(mContext)
val devDialogView = View.inflate(mContext, R.layout.diagnostics_dialog, null) val devDialogView = View.inflate(mContext, R.layout.diagnostics_dialog, null)
val devDialogText = devDialogView.findViewById<TextView>(R.id.dialogtext) val devDialogText = devDialogView.findViewById<TextView>(R.id.dialogtext)
@@ -438,20 +439,30 @@ internal class SettingsFragment : Fragment(), View.OnClickListener, View.OnLongC
alertDialogDev.setView(devDialogView) alertDialogDev.setView(devDialogView)
alertDialogDev.show() alertDialogDev.show()
} }
"_login" -> { this == "_login" -> {
prefs.edit().putBoolean("successful_login", false).apply() prefs.edit().putBoolean("successful_login", false).apply()
makeToast("Login flag cleared") makeToast("Login flag cleared")
} }
"_firsttime" -> { this == "_firsttime" -> {
prefs.edit().putBoolean("firstTime", true).apply() prefs.edit().putBoolean("firstTime", true).apply()
makeToast("First time flag cleared") makeToast("First time flag cleared")
} }
"_testurls" -> { this == "_testurls" -> {
val currentTest = !prefs.getBoolean("testUrls", false) val currentTest = !prefs.getBoolean("testUrls", false)
prefs.edit().putBoolean("testUrls", currentTest).apply() prefs.edit().putBoolean("testUrls", currentTest)
.putString("custom_test_url", "").apply()
makeToast("Cleared custom URL")
makeToast("Test URLs set to $currentTest") makeToast("Test URLs set to $currentTest")
} }
"_devchannel" -> { length > 4 && substring(0, 4) == "_url" -> {
prefs.edit().putString("custom_test_url", substring(4, length)).apply()
makeToast("Successfully entered custom URL")
}
length == 4 && substring(0, 4) == "_url" -> {
prefs.edit().putString("custom_test_url", "").apply()
makeToast("Cleared custom URL")
}
this == "_devchannel" -> {
val subbed = if (prefs.getBoolean("subscribedToFBDebugChannel", false)) { val subbed = if (prefs.getBoolean("subscribedToFBDebugChannel", false)) {
unsubscribeFromTopic(Topic.DEVELOPMENT) unsubscribeFromTopic(Topic.DEVELOPMENT)
"Unsubscribed from" "Unsubscribed from"
@@ -462,7 +473,7 @@ internal class SettingsFragment : Fragment(), View.OnClickListener, View.OnLongC
prefs.edit().putBoolean("subscribedToFBDebugChannel", !prefs.getBoolean("subscribedToFBDebugChannel", false)).apply() prefs.edit().putBoolean("subscribedToFBDebugChannel", !prefs.getBoolean("subscribedToFBDebugChannel", false)).apply()
makeToast("$subbed Firebase development channel") makeToast("$subbed Firebase development channel")
} }
"_ioschannel" -> { this == "_ioschannel" -> {
val subbed = if (prefs.getBoolean("subscribedToiOSChannel", false)) { val subbed = if (prefs.getBoolean("subscribedToiOSChannel", false)) {
unsubscribeFromTopic(Topic.IOS) unsubscribeFromTopic(Topic.IOS)
"Unsubscribed from" "Unsubscribed from"
@@ -473,11 +484,15 @@ internal class SettingsFragment : Fragment(), View.OnClickListener, View.OnLongC
prefs.edit().putBoolean("subscribedToiOSChannel", !prefs.getBoolean("subscribedToiOSChannel", false)).apply() prefs.edit().putBoolean("subscribedToiOSChannel", !prefs.getBoolean("subscribedToiOSChannel", false)).apply()
makeToast("$subbed iOS channel") makeToast("$subbed iOS channel")
} }
"_write" -> HelperFunctions.writePrefsToXml(prefs, mContext, activity!!) this == "_viewstacktrace" -> {
"_read" -> HelperFunctions.readPrefsFromXml(prefs, mContext, activity!!) createDialog("Debug Stack Trace", prefs.getString("debug_recent_exception", "") ?: "")
}
this == "_write" -> HelperFunctions.writePrefsToXml(prefs, mContext, activity!!)
this == "_read" -> HelperFunctions.readPrefsFromXml(prefs, mContext, activity!!)
else -> makeToast(getString(R.string.invalid_code)) else -> makeToast(getString(R.string.invalid_code))
} }
} }
}
alertDialog.setView(dialogView) alertDialog.setView(dialogView)
alertDialog.show() alertDialog.show()
return true return true
+2
View File
@@ -33,4 +33,6 @@
<item name="dialogCornerRadius">12dp</item> <item name="dialogCornerRadius">12dp</item>
</style> </style>
<style name="AppTheme0.LegacyAlert" parent="Theme.AppCompat.Dialog.Alert"/>
</resources> </resources>