diff --git a/app/src/main/java/com/denizd/substitutionplan/adapters/ColourAdapter.kt b/app/src/main/java/com/denizd/substitutionplan/adapters/ColourAdapter.kt index 1206311..aba2cf3 100644 --- a/app/src/main/java/com/denizd/substitutionplan/adapters/ColourAdapter.kt +++ b/app/src/main/java/com/denizd/substitutionplan/adapters/ColourAdapter.kt @@ -11,29 +11,33 @@ import com.denizd.substitutionplan.models.Colour import com.denizd.substitutionplan.R import com.google.android.material.card.MaterialCardView -internal class ColourAdapter(private var mColours: List, onClickListener: OnClickListener) : RecyclerView.Adapter() { +/** + * Adapter class used for displaying the courses as well as their associated colours in the + * customisation dialog. Used in SettingsFragment.kt + * + * @param colours a list of all courses and their associated colour + * @param onClickListener a reference to an OnClickListener + */ +internal class ColourAdapter(private var colours: List, private val onClickListener: OnClickListener) : RecyclerView.Adapter() { - private val mOnClickListener = onClickListener - - class ColourViewHolder(view: View, clickListener: OnClickListener) : RecyclerView.ViewHolder(view), View.OnClickListener { + internal class ColourViewHolder(view: View, private val clickListener: OnClickListener) : RecyclerView.ViewHolder(view), View.OnClickListener { val title: TextView = view.findViewById(R.id.item_text) var image: ImageView = view.findViewById(R.id.item_image) val titleNoLang: TextView = view.findViewById(R.id.item_text_no_lang) val cardView: MaterialCardView = view.findViewById(R.id.cardView) - private val mClickListener = clickListener init { view.setOnClickListener(this) } - override fun onClick(v: View?) { mClickListener.onClick(adapterPosition, title.text.toString(), titleNoLang.text.toString()) } + override fun onClick(v: View?) { clickListener.onClick(adapterPosition, title.text.toString(), titleNoLang.text.toString()) } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ColourViewHolder { val v = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false) - return ColourViewHolder(v, mOnClickListener) + return ColourViewHolder(v, onClickListener) } override fun onBindViewHolder(holder: ColourViewHolder, position: Int) { - val currentItem = mColours[position] + val currentItem = colours[position] holder.title.text = currentItem.title holder.titleNoLang.text = currentItem.titleNoLang @@ -54,7 +58,7 @@ internal class ColourAdapter(private var mColours: List, onClickListener holder.title.setTextColor(ContextCompat.getColor(holder.title.context, textColor)) } - override fun getItemCount(): Int = mColours.size + override fun getItemCount(): Int = colours.size internal interface OnClickListener { fun onClick(position: Int, title: String, titleNoLang: String) diff --git a/app/src/main/java/com/denizd/substitutionplan/adapters/FoodAdapter.kt b/app/src/main/java/com/denizd/substitutionplan/adapters/FoodAdapter.kt index facbea5..d8f021f 100644 --- a/app/src/main/java/com/denizd/substitutionplan/adapters/FoodAdapter.kt +++ b/app/src/main/java/com/denizd/substitutionplan/adapters/FoodAdapter.kt @@ -5,39 +5,38 @@ import android.view.View import android.view.ViewGroup import android.widget.TextView -import java.util.ArrayList import androidx.recyclerview.widget.RecyclerView import com.denizd.substitutionplan.models.Food import com.denizd.substitutionplan.R -internal class FoodAdapter(food: ArrayList) : RecyclerView.Adapter() { - private var mFood: List? = null +/** + * Adapter class used in FoodFragment.kt to display the food menu to the user + * + * @param foods a list of all food entries on the menu + */ +internal class FoodAdapter(private var foods: List) : RecyclerView.Adapter() { - class CardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - var mFood: TextView = itemView.findViewById(R.id.cardInfoText) + internal class FoodViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + var text: TextView = itemView.findViewById(R.id.cardInfoText) } - init { - mFood = food - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CardViewHolder { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FoodViewHolder { val v = LayoutInflater.from(parent.context).inflate(R.layout.just_a_card, parent, false) - return CardViewHolder(v) + return FoodViewHolder(v) } - override fun onBindViewHolder(holder: CardViewHolder, position: Int) { - val currentItem = mFood!![position] + override fun onBindViewHolder(holder: FoodViewHolder, position: Int) { + val currentItem = foods[position] - holder.mFood.text = currentItem.food + holder.text.text = currentItem.food } override fun getItemCount(): Int { - return mFood!!.size + return foods.size } - fun setFood(food: List) { - mFood = food + fun setFood(foods: List) { + this.foods = foods notifyDataSetChanged() } } diff --git a/app/src/main/java/com/denizd/substitutionplan/adapters/RingtoneAdapter.kt b/app/src/main/java/com/denizd/substitutionplan/adapters/RingtoneAdapter.kt index 74f4b59..bb8b2a8 100644 --- a/app/src/main/java/com/denizd/substitutionplan/adapters/RingtoneAdapter.kt +++ b/app/src/main/java/com/denizd/substitutionplan/adapters/RingtoneAdapter.kt @@ -10,40 +10,39 @@ import com.denizd.substitutionplan.R import com.denizd.substitutionplan.models.Ringtone import com.google.android.material.card.MaterialCardView -internal class RingtoneAdapter(private var _ringtones: List, onClickListener: OnClickListener) : RecyclerView.Adapter() { +/** + * Adapter class used for displaying all available notification ringtones to the user up to + * Android version 7 (Nougat). Used in SettingsFragment.kt + * + * @param ringtones a list of all ringtones including their URI + * @param onClickListener a reference to an OnClickListener to set the ringtone + */ +internal class RingtoneAdapter(private val ringtones: List, private val onClickListener: OnClickListener) : RecyclerView.Adapter() { - private val _onClickListener = onClickListener - - class RingtoneViewHolder(view: View, clickListener: OnClickListener) : RecyclerView.ViewHolder(view), View.OnClickListener { + internal class RingtoneViewHolder(view: View, private val clickListener: OnClickListener) : RecyclerView.ViewHolder(view), View.OnClickListener { val name: TextView = view.findViewById(R.id.item_text) val uri: TextView = view.findViewById(R.id.item_text_no_lang) val cardView: MaterialCardView = view.findViewById(R.id.cardView) - private val _clickListener = clickListener init { view.setOnClickListener(this) } - override fun onClick(v: View?) { _clickListener.onRingtoneClick(adapterPosition, name.text.toString(), uri.text.toString()) } + override fun onClick(v: View?) { clickListener.onRingtoneClick(adapterPosition, name.text.toString(), uri.text.toString()) } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RingtoneViewHolder { val v = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false) - return RingtoneViewHolder( - v, - _onClickListener - ) + return RingtoneViewHolder(v, onClickListener) } override fun onBindViewHolder(holder: RingtoneViewHolder, position: Int) { - val currentItem = _ringtones[position] + val currentItem = ringtones[position] holder.name.text = currentItem.name holder.uri.text = currentItem.uri - holder.cardView.setCardBackgroundColor(ContextCompat.getColor(holder.cardView.context, - R.color.colorBackground - )) + holder.cardView.setCardBackgroundColor(ContextCompat.getColor(holder.cardView.context, R.color.colorBackground)) } - override fun getItemCount(): Int = _ringtones.size + override fun getItemCount(): Int = ringtones.size internal interface OnClickListener { fun onRingtoneClick(position: Int, name: String, uri: String) diff --git a/app/src/main/java/com/denizd/substitutionplan/adapters/CardAdapter.kt b/app/src/main/java/com/denizd/substitutionplan/adapters/SubstitutionAdapter.kt similarity index 66% rename from app/src/main/java/com/denizd/substitutionplan/adapters/CardAdapter.kt rename to app/src/main/java/com/denizd/substitutionplan/adapters/SubstitutionAdapter.kt index 3312d04..1dba6a5 100644 --- a/app/src/main/java/com/denizd/substitutionplan/adapters/CardAdapter.kt +++ b/app/src/main/java/com/denizd/substitutionplan/adapters/SubstitutionAdapter.kt @@ -1,6 +1,7 @@ package com.denizd.substitutionplan.adapters import android.content.ActivityNotFoundException +import android.content.Context import android.content.SharedPreferences import android.net.Uri import android.text.SpannableString @@ -16,18 +17,20 @@ import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import com.denizd.substitutionplan.data.HelperFunctions import com.denizd.substitutionplan.R -import com.denizd.substitutionplan.models.Subst +import com.denizd.substitutionplan.models.Substitution import com.google.android.material.card.MaterialCardView import java.util.* -internal class CardAdapter(private var mSubst: List, private val prefs: SharedPreferences) : RecyclerView.Adapter() { +/** + * Adapter class for the Recycler View used to display the substitution plan in + * PlanFragment.kt and its subclasses + * + * @param substitutions a list of all substitutions of data type Substitution + * @param prefs a reference to the app's Shared Preferences used to get user-set colours + */ +internal class SubstitutionAdapter(private var substitutions: List, private val prefs: SharedPreferences) : RecyclerView.Adapter() { - private var colour = 0 - private var colourString = "" - private var colorCheck = "" - private val cancellations = arrayOf("eigenverantwortliches arbeiten", "entfall", "entfällt", "fällt aus", "freisetzung", "vtr. ohne lehrer") - - class CardViewHolder(view: View) : RecyclerView.ViewHolder(view), View.OnClickListener { + internal class CardViewHolder(view: View) : RecyclerView.ViewHolder(view), View.OnClickListener { var iconView: ImageView = view.findViewById(R.id.iconView) var group: TextView = view.findViewById(R.id.group) @@ -38,16 +41,16 @@ internal class CardAdapter(private var mSubst: List, private val prefs: S var additional: TextView = view.findViewById(R.id.additional) var teacher: TextView = view.findViewById(R.id.teacher) var spacer: TextView = view.findViewById(R.id.spacer) - var card: MaterialCardView = view.findViewById(R.id.planCard) + val context: Context = card.context init { view.setOnClickListener(this) } override fun onClick(v: View?) { if (date.text.toString().length > 7 && date.text.toString().substring(3, 7) == "http") { try { - CustomTabsIntent.Builder().build().launchUrl(card.context, - Uri.parse(date.text.toString().substring(3))) + CustomTabsIntent.Builder().build().launchUrl(context, + Uri.parse(date.text.substring(3))) } catch (e: ActivityNotFoundException) { - Toast.makeText(card.context, card.context.getString(R.string.chrome_not_found), Toast.LENGTH_LONG).show() + Toast.makeText(context, context.getString(R.string.chrome_not_found), Toast.LENGTH_LONG).show() } } } @@ -59,12 +62,13 @@ internal class CardAdapter(private var mSubst: List, private val prefs: S } override fun onBindViewHolder(holder: CardViewHolder, position: Int) { - val currentItem = mSubst[position] + val currentItem = substitutions[position] var psa = false val strings = arrayOf(SpannableString(currentItem.group), SpannableString(currentItem.time), SpannableString(currentItem.course), SpannableString(currentItem.room), SpannableString(currentItem.teacher)) - var cardBackgroundColour = 0 + val cardBackgroundColour: Int + var colour = 0 for (string in strings) { val questionMarkIndex = string.indexOf("?") @@ -76,11 +80,11 @@ internal class CardAdapter(private var mSubst: List, private val prefs: S val add = currentItem.additional.toLowerCase(Locale.ROOT) val type = currentItem.type.toLowerCase(Locale.ROOT) if (add.isNotEmpty()) { - if (HelperFunctions.checkStringForArray(add, cancellations)) { + if (HelperFunctions.checkStringForArray(add, HelperFunctions.cancellations)) { strikeThrough(strings) } } else { - if (HelperFunctions.checkStringForArray(type, cancellations)) { + if (HelperFunctions.checkStringForArray(type, HelperFunctions.cancellations)) { strikeThrough(strings) } } @@ -100,7 +104,7 @@ internal class CardAdapter(private var mSubst: List, private val prefs: S cardBackgroundColour = R.color.colorAccent View.GONE } else { - colourString = getColourString(holder.course.text.toString()) + val colourString = HelperFunctions.getColourString(holder.course.text.toString()) val colourPrefsInt = if (colourString.isNotEmpty()) { prefs.getString("card$colourString", "") ?: "" } else { @@ -150,58 +154,13 @@ internal class CardAdapter(private var mSubst: List, private val prefs: S holder.teacher.setTextColor(textColor) } - override fun getItemCount(): Int = mSubst.size + override fun getItemCount(): Int = substitutions.size - fun setSubst(subst: List) { - mSubst = subst + fun setSubst(substitutions: List) { + this.substitutions = substitutions notifyDataSetChanged() } - private fun getColourString(course: String): String { - return try { - colorCheck = course.toLowerCase(Locale.ROOT).substring(0, 3) - when (colorCheck) { - "deu", "dep", "daz", "fda" -> "German" - "mat", "map" -> "Maths" - "eng", "enp", "ena" -> "English" - "spo", "spp", "spth" -> "PhysEd" - "pol", "pop" -> "Politics" - "dar", "dap" -> "Theatre" - "phy", "php" -> "Physics" - "bio", "bip", "nw1", "nw2", "nw3", "nw4" -> "Biology" - "che", "chp" -> "Chemistry" - "phi", "psp" -> "Philosophy" - "laa", "laf", "lat" -> "Latin" - "spa", "spf" -> "Spanish" - "fra", "frf", "frz" -> "French" - "inf" -> "CompSci" - "ges" -> "History" - "rel" -> "Religion" - "geg" -> "Geography" - "kun" -> "Arts" - "mus" -> "Music" - "tue" -> "Turkish" - "chi" -> "Chinese" - "gll" -> "GLL" - "wat" -> "WAT" - "för" -> "Forder" - "met", "wpb" -> "WP" - else -> "" - } - } catch (e: StringIndexOutOfBoundsException) { - try { - colorCheck = course.toLowerCase(Locale.ROOT).substring(0, 2) - when (colorCheck) { - "nw" -> "Biology" - "wp" -> "WP" - else -> "" - } - } catch (e2: StringIndexOutOfBoundsException) { - "" - } - } - } - private fun strikeThrough(strings: Array) { for (i in 2..4) { strings[i].setSpan(StrikethroughSpan(), 0, strings[i].length, 0) } } diff --git a/app/src/main/java/com/denizd/substitutionplan/data/DataFetcher.kt b/app/src/main/java/com/denizd/substitutionplan/data/DataFetcher.kt index 5138295..a323338 100644 --- a/app/src/main/java/com/denizd/substitutionplan/data/DataFetcher.kt +++ b/app/src/main/java/com/denizd/substitutionplan/data/DataFetcher.kt @@ -18,7 +18,7 @@ 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.denizd.substitutionplan.models.Substitution import com.google.android.material.snackbar.Snackbar import org.jsoup.Jsoup import java.lang.ref.WeakReference @@ -57,7 +57,7 @@ internal class DataFetcher(isPlan: Boolean, isMenu: Boolean, isJobService: Boole private val edit = prefs.edit() private var currentTime = "" private var currentFoodTime = "" - private var substUrl = "https://djd4rkn355.github.io/subst.html" + private var substUrl = "https://djd4rkn355.github.io/avh_substitutions.html" private var foodUrl = "https://djd4rkn355.github.io/food.html" override fun doInBackground(vararg params: Void?): Void? { @@ -149,7 +149,7 @@ internal class DataFetcher(isPlan: Boolean, isMenu: Boolean, isJobService: Boole if (currentTime != prefs.getString("timeNew", "")) { val rows = doc.select("tr") val paragraphs = doc.select("p") - val substArray = ArrayList() + val substArray = ArrayList() val coursePreference = prefs.getString("courses", "") ?: "" val classPreference = prefs.getString("classes", "") ?: "" @@ -169,7 +169,7 @@ internal class DataFetcher(isPlan: Boolean, isMenu: Boolean, isJobService: Boole val row = rows[i] val cols = row.select("th") - val subst = Subst( + val subst = Substitution( group = cols[0].text(), date = cols[1].text(), time = cols[2].text(), @@ -237,11 +237,12 @@ internal class DataFetcher(isPlan: Boolean, isMenu: Boolean, isJobService: Boole val notification = NotificationCompat.Builder(context, HelperFunctions.notificationChannelId) .setStyle(NotificationCompat.DecoratedCustomViewStyle()) .setCustomContentView(notificationLayout) - .setSmallIcon(R.drawable.ic_avhlogo) .setContentIntent(openAppPending) .setAutoCancel(true) .setColor(ContextCompat.getColor(context, R.color.colorAccent)) + notification.setSmallIcon(if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) R.drawable.ic_avh else R.drawable.ic_avhlogo) + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { val sound = if ((prefs.getString("ringtoneUri", "") ?: "").isNotEmpty()) { Uri.parse(prefs.getString("ringtoneUri", "") ?: "") diff --git a/app/src/main/java/com/denizd/substitutionplan/data/HelperFunctions.kt b/app/src/main/java/com/denizd/substitutionplan/data/HelperFunctions.kt index 731d292..f626ae4 100644 --- a/app/src/main/java/com/denizd/substitutionplan/data/HelperFunctions.kt +++ b/app/src/main/java/com/denizd/substitutionplan/data/HelperFunctions.kt @@ -20,7 +20,7 @@ import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat.checkSelfPermission import androidx.fragment.app.FragmentActivity import com.denizd.substitutionplan.R -import com.denizd.substitutionplan.models.Subst +import com.denizd.substitutionplan.models.Substitution import java.util.* import java.io.File import java.io.FileOutputStream @@ -45,6 +45,12 @@ internal object HelperFunctions { "brown", "grey", "pureWhite", "salmon", "tangerine", "banana", "flora", "spindrift", "sky", "orchid", "lavender", "carnation", "brown2", "pureBlack") + /** + * A list of all phrases used to describe that a course has been cancelled. Expand this + * if necessary. No further code changes required if this is expanded + */ + val cancellations = arrayOf("eigenverantwortliches arbeiten", "entfall", "entfällt", "fällt aus", "freisetzung", "vtr. ohne lehrer") + private val colourIntegers = intArrayOf( 0, R.color.bgRed, @@ -135,6 +141,60 @@ internal object HelperFunctions { } } + /** + * This function returns a string that is used to get the colour set for a specific course + * from Shared Preferences + * + * @param course the course abbreviation as a string + * + * @return the string used to store the course's colour in Shared Preferences + */ + fun getColourString(course: String): String { + var colorCheck: String + return try { + colorCheck = course.toLowerCase(Locale.ROOT).substring(0, 3) + when (colorCheck) { + "deu", "dep", "daz", "fda" -> "German" + "mat", "map" -> "Maths" + "eng", "enp", "ena" -> "English" + "spo", "spp", "spth" -> "PhysEd" + "pol", "pop" -> "Politics" + "dar", "dap" -> "Theatre" + "phy", "php" -> "Physics" + "bio", "bip", "nw1", "nw2", "nw3", "nw4" -> "Biology" + "che", "chp" -> "Chemistry" + "phi", "psp" -> "Philosophy" + "laa", "laf", "lat" -> "Latin" + "spa", "spf" -> "Spanish" + "fra", "frf", "frz" -> "French" + "inf" -> "CompSci" + "ges" -> "History" + "rel" -> "Religion" + "geg" -> "Geography" + "kun" -> "Arts" + "mus" -> "Music" + "tue" -> "Turkish" + "chi" -> "Chinese" + "gll" -> "GLL" + "wat" -> "WAT" + "för" -> "Forder" + "met", "wpb" -> "WP" + else -> "" + } + } catch (e: StringIndexOutOfBoundsException) { + try { + colorCheck = course.toLowerCase(Locale.ROOT).substring(0, 2) + when (colorCheck) { + "nw" -> "Biology" + "wp" -> "WP" + else -> "" + } + } catch (e2: StringIndexOutOfBoundsException) { + "" + } + } + } + /** * This function served as a way to transfer a deprecated method of storing user-defined * course colours to a new method. It is not required otherwise, but still remains in @@ -163,17 +223,17 @@ internal object HelperFunctions { * This function serves for checking whether a course on the substitution plan is relevant to * the user and should be shown on their personal plan as well as in their notifications * - * @param subst the substitution item + * @param substitution the substitution item * @param coursePreference a string that represents the courses the user is enrolled in * @param classPreference a string that represents the group the user is in * @param psa decide whether or not any PSA items should be included in the filter * * @return true if the substitution is relevant to the user, false otherwise */ - 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") { + fun checkPersonalSubstitutions(substitution: Substitution, coursePreference: String, classPreference: String, psa: Boolean): Boolean { + val group = substitution.group + val course = substitution.course + if (psa && substitution.date.isNotEmpty() && substitution.date.substring(0, 3) == "psa") { return true } if (coursePreference.isEmpty() && classPreference.isNotEmpty()) { diff --git a/app/src/main/java/com/denizd/substitutionplan/data/LoginWebViewClient.kt b/app/src/main/java/com/denizd/substitutionplan/data/LoginWebViewClient.kt index 0227618..98d9de6 100644 --- a/app/src/main/java/com/denizd/substitutionplan/data/LoginWebViewClient.kt +++ b/app/src/main/java/com/denizd/substitutionplan/data/LoginWebViewClient.kt @@ -1,8 +1,11 @@ package com.denizd.substitutionplan.data +import android.graphics.Bitmap +import android.util.Log import android.webkit.CookieManager import android.webkit.WebView import android.webkit.WebViewClient +import java.lang.IllegalStateException /** * Class that extends WebViewClient to provide a function that checks the webpage's cookies to @@ -10,27 +13,40 @@ import android.webkit.WebViewClient * * @param successListener a reference to the OnLoginSuccessListener implemented in an activity */ -internal class LoginWebViewClient(successListener: OnLoginSuccessListener) : WebViewClient() { +internal class LoginWebViewClient(private val successListener: OnLoginSuccessListener) : WebViewClient() { - private val mSuccessListener = successListener + /** + * onPageStarted has been overridden to prevent users from reaching a domain different from + * the school's login page + */ + override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { + super.onPageStarted(view, url, favicon) + + if (url != "https://307.joomla.schule.bremen.de/index.php/component/users/profile?Itemid=171" + && url != "https://307.joomla.schule.bremen.de/index.php/component/users/#top") { + reloadLoginPage(webView = view) + } + } /** * OnPageFinished has been overridden to check if the cookie "joomla_user_state=logged_in" * exists, and returns true to the OnLoginSuccessListener - * - * @param view a reference to the WebView - * @param url a reference to the url of the WebView */ override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) - view?.scrollY = -4000 + view?.scrollY = -10_000 + val cookies = CookieManager.getInstance().getCookie(url) if (cookies.contains("joomla_user_state=logged_in")) { - mSuccessListener.onLoginSucceeded(true) + successListener.onLoginSucceeded(true) } } + private fun reloadLoginPage(webView: WebView?) { + webView?.loadUrl("https://307.joomla.schule.bremen.de/index.php/component/users/#top") + } + /** * The interface that provides onLoginSucceeded to the activity or fragment that implements it */ diff --git a/app/src/main/java/com/denizd/substitutionplan/database/SubstDao.kt b/app/src/main/java/com/denizd/substitutionplan/database/SubstDao.kt index 7f28284..d651461 100644 --- a/app/src/main/java/com/denizd/substitutionplan/database/SubstDao.kt +++ b/app/src/main/java/com/denizd/substitutionplan/database/SubstDao.kt @@ -3,23 +3,23 @@ package com.denizd.substitutionplan.database import androidx.lifecycle.LiveData import androidx.room.* import com.denizd.substitutionplan.models.Food -import com.denizd.substitutionplan.models.Subst +import com.denizd.substitutionplan.models.Substitution @Dao internal interface SubstDao { // @get:Query("SELECT * FROM subst_table ORDER BY date ASC, `group` ASC, time ASC, priority DESC") @get:Query("SELECT * FROM subst_table ORDER BY priority DESC") - val allSubst: LiveData> + val allSubstitutions: LiveData> @Insert - fun insertSubst(subst: Subst) + fun insertSubst(substitution: Substitution) @Update - fun updateSubst(subst: Subst) + fun updateSubst(substitution: Substitution) @Delete - fun deleteSubst(subst: Subst) + fun deleteSubst(substitution: Substitution) @Query("DELETE FROM subst_table") fun deleteAllSubst() diff --git a/app/src/main/java/com/denizd/substitutionplan/database/SubstDatabase.kt b/app/src/main/java/com/denizd/substitutionplan/database/SubstDatabase.kt index 390f140..f67e359 100644 --- a/app/src/main/java/com/denizd/substitutionplan/database/SubstDatabase.kt +++ b/app/src/main/java/com/denizd/substitutionplan/database/SubstDatabase.kt @@ -7,9 +7,9 @@ import androidx.room.RoomDatabase import androidx.room.migration.Migration import androidx.sqlite.db.SupportSQLiteDatabase import com.denizd.substitutionplan.models.Food -import com.denizd.substitutionplan.models.Subst +import com.denizd.substitutionplan.models.Substitution -@Database(entities = [Subst::class, Food::class], version = 7, exportSchema = false) +@Database(entities = [Substitution::class, Food::class], version = 7, exportSchema = false) internal abstract class SubstDatabase : RoomDatabase() { abstract fun substDao(): SubstDao diff --git a/app/src/main/java/com/denizd/substitutionplan/database/SubstRepository.kt b/app/src/main/java/com/denizd/substitutionplan/database/SubstRepository.kt index 0589342..4c43a80 100644 --- a/app/src/main/java/com/denizd/substitutionplan/database/SubstRepository.kt +++ b/app/src/main/java/com/denizd/substitutionplan/database/SubstRepository.kt @@ -4,32 +4,32 @@ import android.app.Application import android.os.AsyncTask import androidx.lifecycle.LiveData -import com.denizd.substitutionplan.models.Subst +import com.denizd.substitutionplan.models.Substitution internal class SubstRepository(application: Application) { private val substDao: SubstDao? - val allSubst: LiveData>? + val allSubstitutions: LiveData>? init { val database = SubstDatabase.getInstance(application) substDao = database?.substDao() - allSubst = substDao?.allSubst + allSubstitutions = substDao?.allSubstitutions } - fun insert(subst: Subst) { - InsertSubstAsync(substDao).execute(subst) + fun insert(substitution: Substitution) { + InsertSubstAsync(substDao).execute(substitution) } fun deleteAllSubst() { DeleteAllSubstAsync(substDao).execute() } - class InsertSubstAsync(substDao: SubstDao?) : AsyncTask() { + class InsertSubstAsync(substDao: SubstDao?) : AsyncTask() { private val mSubstDao = substDao - override fun doInBackground(vararg substs: Subst): Void? { - mSubstDao?.insertSubst(substs[0]) + override fun doInBackground(vararg substitutions: Substitution): Void? { + mSubstDao?.insertSubst(substitutions[0]) return null } } diff --git a/app/src/main/java/com/denizd/substitutionplan/database/SubstViewModel.kt b/app/src/main/java/com/denizd/substitutionplan/database/SubstViewModel.kt index 9d85f93..78078ef 100644 --- a/app/src/main/java/com/denizd/substitutionplan/database/SubstViewModel.kt +++ b/app/src/main/java/com/denizd/substitutionplan/database/SubstViewModel.kt @@ -6,16 +6,16 @@ import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.denizd.substitutionplan.data.DataFetcher -import com.denizd.substitutionplan.models.Subst +import com.denizd.substitutionplan.models.Substitution internal class SubstViewModel(application: Application) : AndroidViewModel(application) { private val repository: SubstRepository = SubstRepository(application) - val allSubst: LiveData>? + val allSubstitutions: LiveData>? private val app = application init { - allSubst = repository.allSubst + allSubstitutions = repository.allSubstitutions } fun refresh(swipeRefreshLayout: SwipeRefreshLayout, rootView: View, refreshMenu: Boolean) { diff --git a/app/src/main/java/com/denizd/substitutionplan/fragments/FoodFragment.kt b/app/src/main/java/com/denizd/substitutionplan/fragments/FoodFragment.kt index 9a376fc..5ea0255 100644 --- a/app/src/main/java/com/denizd/substitutionplan/fragments/FoodFragment.kt +++ b/app/src/main/java/com/denizd/substitutionplan/fragments/FoodFragment.kt @@ -35,17 +35,10 @@ internal class FoodFragment : Fragment(R.layout.food_layout) { super.onViewCreated(view, savedInstanceState) val pullToRefresh = view.findViewById(R.id.pullToRefresh) - try { - recyclerView = view.findViewById(R.id.linear_food) - recyclerView.hasFixedSize() - recyclerView.layoutManager = GridLayoutManager(mContext, 1) - recyclerView.adapter = mAdapter - - try { - recyclerView.removeAllViews() - } catch (ignored: NullPointerException) {} - - } catch (ignored: NullPointerException) {} + recyclerView = view.findViewById(R.id.linear_food) + recyclerView.hasFixedSize() + recyclerView.layoutManager = GridLayoutManager(mContext, 1) + recyclerView.adapter = mAdapter foodViewModel = ViewModelProviders.of(this).get(FoodViewModel::class.java) foodViewModel.allFoods?.observe(this, Observer> { foodList -> diff --git a/app/src/main/java/com/denizd/substitutionplan/fragments/GeneralPlanFragment.kt b/app/src/main/java/com/denizd/substitutionplan/fragments/GeneralPlanFragment.kt index 8937e01..9222410 100644 --- a/app/src/main/java/com/denizd/substitutionplan/fragments/GeneralPlanFragment.kt +++ b/app/src/main/java/com/denizd/substitutionplan/fragments/GeneralPlanFragment.kt @@ -3,14 +3,14 @@ package com.denizd.substitutionplan.fragments import android.os.Bundle import android.view.View import androidx.lifecycle.Observer -import com.denizd.substitutionplan.models.Subst +import com.denizd.substitutionplan.models.Substitution internal class GeneralPlanFragment : PlanFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - substViewModel.allSubst?.observe(this, Observer> { substitutions -> + substViewModel.allSubstitutions?.observe(this, Observer> { substitutions -> mAdapter.setSubst(substitutions) recyclerView.scheduleLayoutAnimation() }) diff --git a/app/src/main/java/com/denizd/substitutionplan/fragments/PersonalPlanFragment.kt b/app/src/main/java/com/denizd/substitutionplan/fragments/PersonalPlanFragment.kt index ec8ac71..60e3fd8 100644 --- a/app/src/main/java/com/denizd/substitutionplan/fragments/PersonalPlanFragment.kt +++ b/app/src/main/java/com/denizd/substitutionplan/fragments/PersonalPlanFragment.kt @@ -5,7 +5,7 @@ import android.view.View import androidx.lifecycle.Observer import com.denizd.substitutionplan.data.HelperFunctions import com.denizd.substitutionplan.R -import com.denizd.substitutionplan.models.Subst +import com.denizd.substitutionplan.models.Substitution internal class PersonalPlanFragment : PlanFragment() { @@ -19,7 +19,7 @@ internal class PersonalPlanFragment : PlanFragment() { val coursePreference = prefs.getString("courses", "") ?: "" val classPreference = prefs.getString("classes", "") ?: "" - substViewModel.allSubst?.observe(this, Observer> { substitutions -> + substViewModel.allSubstitutions?.observe(this, Observer> { substitutions -> planCardList.clear() personalPlanEmptyEmoticon.visibility = View.GONE personalPlanEmptyText.visibility = View.GONE diff --git a/app/src/main/java/com/denizd/substitutionplan/fragments/PlanFragment.kt b/app/src/main/java/com/denizd/substitutionplan/fragments/PlanFragment.kt index 0bd410d..9c4f8d0 100644 --- a/app/src/main/java/com/denizd/substitutionplan/fragments/PlanFragment.kt +++ b/app/src/main/java/com/denizd/substitutionplan/fragments/PlanFragment.kt @@ -15,15 +15,15 @@ import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.denizd.substitutionplan.* -import com.denizd.substitutionplan.adapters.CardAdapter +import com.denizd.substitutionplan.adapters.SubstitutionAdapter import com.denizd.substitutionplan.database.SubstViewModel -import com.denizd.substitutionplan.models.Subst +import com.denizd.substitutionplan.models.Substitution import kotlin.collections.ArrayList internal open class PlanFragment : Fragment(R.layout.plan) { lateinit var recyclerView: RecyclerView - lateinit var mAdapter: CardAdapter - var planCardList = ArrayList() + lateinit var mAdapter: SubstitutionAdapter + var planCardList = ArrayList() lateinit var substViewModel: SubstViewModel private lateinit var mContext: Context lateinit var prefs: SharedPreferences @@ -53,7 +53,7 @@ internal open class PlanFragment : Fragment(R.layout.plan) { recyclerView = view.findViewById(R.id.linearRecycler) recyclerView.hasFixedSize() recyclerView.layoutManager = GridLayoutManager(mContext, getGridColumnCount(resources.configuration)) - mAdapter = CardAdapter(planCardList, prefs) + mAdapter = SubstitutionAdapter(planCardList, prefs) recyclerView.adapter = mAdapter if (prefs.getInt("firstTimeOpening", 0) == 1) { diff --git a/app/src/main/java/com/denizd/substitutionplan/fragments/SettingsFragment.kt b/app/src/main/java/com/denizd/substitutionplan/fragments/SettingsFragment.kt index 779b2e0..3d6912f 100644 --- a/app/src/main/java/com/denizd/substitutionplan/fragments/SettingsFragment.kt +++ b/app/src/main/java/com/denizd/substitutionplan/fragments/SettingsFragment.kt @@ -188,69 +188,6 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl } } - override fun onClick(v: View?) { - when (v?.id) { - R.id.chipHelpCourses -> createDialog(getString(R.string.courses_help_dialog_title), getString(R.string.courses_help_dialog_text)) - R.id.chipHelpClasses -> createDialog(getString(R.string.grade_help_dialog_title), getString( - R.string.grade_help_dialog_text - )) - R.id.btnCustomiseColours -> createColourDialog() - R.id.btnNoNotif -> createDialog(mContext.getString(R.string.no_notifications_title), mContext.getString(R.string.no_notifications_dialog_text)) - R.id.btnCustomiseRingtone -> createRingtoneDialog() - R.id.btnWebsite -> { - try { - customTabsIntent.launchUrl(mContext, Uri.parse("http://307.joomla.schule.bremen.de")) - } catch (e: ActivityNotFoundException) { - makeToast(getString(R.string.chrome_not_found)) - } - } - R.id.btnLicences -> { - createDialog(mContext.getString(R.string.licences_title), licences) - } - R.id.btnTerms -> { - createDialog("Terms & Conditions", termsAndConditions) - } - R.id.btnPrivacyP -> { - createDialog("Privacy Policy", privacyPolicy) - } - R.id.btnForceRefresh -> { - DataFetcher( - isPlan = true, - isMenu = true, - isJobService = false, - context = mContext, - application = activity!!.application, - parentView = view!!.rootView, - forced = true - ).execute() - } - } - } - - override fun onCheckedChanged(v: CompoundButton?, isChecked: Boolean) { - if (v?.isPressed == true) { - when (v.id) { - R.id.switchDisableGreeting -> { - prefs.edit().putBoolean("greeting", isChecked).apply() - } - R.id.switchNotifications -> { - prefs.edit().putBoolean("notif", isChecked).apply() - if (isChecked) { - subscribeToTopic(Topic.ANDROID) - } else { - unsubscribeFromTopic(Topic.ANDROID) - } - } - R.id.switchDefaultPlan -> { - prefs.edit().putBoolean("defaultPersonalised", isChecked).apply() - } - R.id.switchAutoRefresh -> { - prefs.edit().putBoolean("autoRefresh", isChecked).apply() - } - } - } - } - private fun createDialog(title: String, text: String) { val alertDialog = AlertDialog.Builder(mContext, R.style.AlertDialog @@ -262,7 +199,7 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl } private fun createColourDialog() { - val colourCustomiserBuilder = AlertDialog.Builder(mContext, R.style.AlertDialog) + val colourCustomisationDialogBuilder = AlertDialog.Builder(mContext, R.style.AlertDialog) val dialogView = View.inflate(mContext, R.layout.recycler_dialog, null) val titleText = dialogView.findViewById(R.id.empty_textviewtitle) @@ -273,9 +210,9 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl layoutManager = GridLayoutManager(mContext, 1) adapter = ColourAdapter(getColourList(), this@SettingsFragment) } - colourCustomiserBuilder.setView(dialogView) - val colourCustomiserDialog = colourCustomiserBuilder.create() - colourCustomiserDialog.show() + colourCustomisationDialogBuilder.setView(dialogView) + val colourCustomisationDialog = colourCustomisationDialogBuilder.create() + colourCustomisationDialog.show() } private fun getColourList(): ArrayList { @@ -371,15 +308,6 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl return alarms } - override fun onRingtoneClick(position: Int, name: String, uri: String) { - prefs.edit().apply { - putString("ringtoneName", name) - putString("ringtoneUri", uri) - }.apply() - setRingtoneText() - ringtoneCustomiserDialog.dismiss() - } - private fun setRingtoneText() { currentRingtone.text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { mContext.getString(R.string.pick_ringtone_desc_o) @@ -393,36 +321,6 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl } } - override fun onClick(position: Int, title: String, titleNoLang: String) { - val colourPickerBuilder = AlertDialog.Builder(mContext, R.style.AlertDialog) - val pickerDialogView = View.inflate(mContext, R.layout.empty_dialog, null) - val pickerTitleText = pickerDialogView.findViewById(R.id.empty_textviewtitle) - val pickerLayout = pickerDialogView.findViewById(R.id.empty_linearlayout) - pickerTitleText.text = title - - val picker = View.inflate(mContext, R.layout.bg_colour_picker, null) - pickerLayout.addView(picker) - colourPickerBuilder.setView(pickerDialogView) - val colourPickerDialog: AlertDialog = colourPickerBuilder.create() - - val buttons = intArrayOf(R.id.def, R.id.red, R.id.orange, R.id.yellow, R.id.green, - R.id.teal, R.id.cyan, R.id.blue, R.id.purple, R.id.pink, R.id.brown, R.id.grey, - R.id.pureWhite, R.id.salmon, R.id.tangerine, R.id.banana, R.id.flora, R.id.spindrift, - R.id.sky, R.id.orchid, R.id.lavender, R.id.carnation, R.id.brown2, R.id.pureBlack) - val colours = HelperFunctions.colourNames - - for (i2 in buttons.indices) { - picker.findViewById(buttons[i2]).setOnClickListener { - prefs.edit().putString("card$titleNoLang", colours[i2]).apply() - val recyclerViewState = colourRecycler.layoutManager?.onSaveInstanceState() - colourRecycler.adapter = ColourAdapter(getColourList(), this) - colourRecycler.layoutManager?.onRestoreInstanceState(recyclerViewState) - colourPickerDialog.dismiss() - } - } - colourPickerDialog.show() - } - private fun debugMenu(): Boolean { val alertDialog = AlertDialog.Builder(mContext, R.style.AlertDialog) val dialogView = View.inflate(mContext, R.layout.edittext_dialog, null) @@ -437,16 +335,14 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl ) dialogButton.setOnClickListener { when (dialogEditText.text.toString()) { - "_DIAGNOSTICS" -> { + "_STATISTICS" -> { val alertDialogDev = AlertDialog.Builder(mContext, R.style.AlertDialog) val devDialogView = View.inflate(mContext, R.layout.diagnostics_dialog, null) val devDialogText = devDialogView.findViewById(R.id.dialogtext) val resetLaunchBtn = devDialogView.findViewById