Refactoring, using view binding in all fragments, app now targets API 29, replaced deprecated support library PreferenceManager and Custom Tabs with AndroidX equivalents, version bump to 2.3.3

This commit is contained in:
Deniz Düzgören
2019-10-12 21:03:34 +02:00
parent f5666a20c6
commit 37cf130ba0
27 changed files with 827 additions and 801 deletions
+3
View File
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="delegatedBuild" value="false" />
<option name="testRunner" value="PLATFORM" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
+12 -9
View File
@@ -1,17 +1,17 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'io.fabric'
android {
compileSdkVersion 28
compileSdkVersion 29
defaultConfig {
applicationId "com.denizd.substitutionplan"
minSdkVersion 21
targetSdkVersion 28
targetSdkVersion 29
versionCode 40
versionName "2.3.2"
versionName "2.3.3"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
@@ -21,16 +21,19 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
viewBinding.enabled = true
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta04'
implementation 'com.google.android.material:material:1.1.0-alpha10'
implementation 'com.android.support:customtabs:28.0.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta05'
implementation 'androidx.browser:browser:1.0.0'
implementation 'androidx.preference:preference-ktx:1.1.0'
implementation 'com.google.android.material:material:1.1.0-beta01'
implementation 'com.google.firebase:firebase-core:17.2.0'
implementation 'com.google.firebase:firebase-messaging:20.0.0'
@@ -41,7 +44,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
def lifecycle_version = "2.0.0"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
def room_version = "2.1.0-alpha04"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
@@ -8,7 +8,7 @@ import android.graphics.drawable.AnimatedVectorDrawable
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewAnimationUtils
@@ -50,11 +50,11 @@ internal class FirstTime : AppCompatActivity(R.layout.activity_first_time) {
val edit = prefs.edit()
val fab = findViewById<ExtendedFloatingActionButton>(R.id.efab)
val mainActivity = Intent(this, Main::class.java)
val nameEditText = findViewById<TextInputEditText>(R.id.txtName)
val gradeEditText = findViewById<TextInputEditText>(R.id.txtClasses)
val courseEditText = findViewById<TextInputEditText>(R.id.txtCourses)
val helpGradeButton = findViewById<ImageButton>(R.id.chipHelpClasses)
val helpCoursesButton = findViewById<ImageButton>(R.id.chipHelpCourses)
val nameEditText = findViewById<TextInputEditText>(R.id.edittext_name)
val gradeEditText = findViewById<TextInputEditText>(R.id.edittext_group)
val courseEditText = findViewById<TextInputEditText>(R.id.edittext_courses)
val helpGradeButton = findViewById<ImageButton>(R.id.button_group_help)
val helpCoursesButton = findViewById<ImageButton>(R.id.button_courses_help)
val greetingCheckBox = findViewById<CheckBox>(R.id.cbGreetings)
val notificationCheckBox = findViewById<CheckBox>(R.id.cbNotif)
val darkModeCheckBox = findViewById<CheckBox>(R.id.cbDark)
@@ -7,7 +7,7 @@ import android.graphics.drawable.AnimatedVectorDrawable
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import android.view.View
import android.view.ViewAnimationUtils
import android.view.animation.Animation
@@ -9,7 +9,7 @@ import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
import android.os.Bundle
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import android.view.*
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
@@ -20,7 +20,6 @@ import androidx.core.widget.NestedScrollView
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import androidx.recyclerview.widget.RecyclerView
import com.crashlytics.android.Crashlytics
import com.denizd.substitutionplan.data.HelperFunctions
import com.denizd.substitutionplan.R
import com.denizd.substitutionplan.fragments.FoodFragment
@@ -33,6 +32,7 @@ import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.snackbar.Snackbar
import com.google.firebase.FirebaseApp
import java.lang.IllegalArgumentException
import java.lang.NullPointerException
import java.util.*
/**
@@ -49,25 +49,26 @@ internal class Main : AppCompatActivity(R.layout.app_bar_main) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
context = this
// prefs = PreferenceManager.getDefaultSharedPreferences(context)
prefs = PreferenceManager.getDefaultSharedPreferences(context)
val edit = prefs.edit()
val firstTime = Intent(context, FirstTime::class.java)
val login = Intent(context, Login::class.java)
Crashlytics.setUserIdentifier(prefs.getString("username", "") ?: "")
/**
* This cascade of if-else's allows the user to return to any point of the setup if they
* This when-cascade allows the user to return to any point of the setup if they
* decide to postpone it, e.g. logging in but not setting up their preferences. Furthermore,
* it prevents existing users from upgrading from a previous version of the app and skip the
* mandatory login
*/
if (!prefs.getBoolean("successful_login", false)) {
startActivity(login)
when {
!prefs.getBoolean("successful_login", false) -> { // launch the login screen
startActivity(Intent(context, Login::class.java))
finish()
} else if (prefs.getBoolean("firstTime", true)) {
startActivity(firstTime)
}
prefs.getBoolean("firstTime", true) -> { // launch the first time setup screen
startActivity(Intent(context, FirstTime::class.java))
finish()
} else {
}
else -> { // launch the app
if (!prefs.getBoolean("colourTransferred", false)) {
HelperFunctions.transferOldColourIntsToString(prefs)
@@ -109,19 +110,16 @@ internal class Main : AppCompatActivity(R.layout.app_bar_main) {
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
}
}
2 -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}
else -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
2 -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
else -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
}
/// 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) {
try {
Snackbar.make(contextView, "${getString(R.string.last_updated)} ${prefs.getString("timeNew", "")}", Snackbar.LENGTH_LONG).show()
} catch (e: IllegalArgumentException) {}
} catch (e: IllegalArgumentException) {
}
}
/**
@@ -130,7 +128,10 @@ internal class Main : AppCompatActivity(R.layout.app_bar_main) {
* with the constraints
*/
val textViewGreeting = findViewById<TextView>(R.id.text_greeting)
textViewGreeting.text = if (prefs.getBoolean("greeting", true) && (prefs.getString("username", "") ?: "").isNotEmpty()) {
textViewGreeting.text = if (
prefs.getBoolean("greeting", true)
&& (prefs.getString("username", "") ?: "").isNotEmpty()
) {
getGreetingString()
} else {
""
@@ -155,67 +156,59 @@ internal class Main : AppCompatActivity(R.layout.app_bar_main) {
/// Opens the corresponding fragment or the info dialog
bottomNav.setOnNavigationItemSelectedListener { item: MenuItem ->
var fragmentLoading = true
lateinit var fragment: Fragment
when (item.itemId) {
val fragment = when (item.itemId) {
R.id.plan -> {
fragment = GeneralPlanFragment()
toolbarTxt.text = getString(R.string.app_name)
GeneralPlanFragment()
}
R.id.personal -> {
fragment = PersonalPlanFragment()
toolbarTxt.text = personalPlanTitle()
PersonalPlanFragment()
}
R.id.menu -> {
fragment = FoodFragment()
toolbarTxt.text = getString(R.string.food_menu)
FoodFragment()
}
R.id.openinfopanel -> {
openInfoDialog()
fragmentLoading = false
null
}
R.id.settings -> {
fragment = SettingsFragment()
else -> {
toolbarTxt.text = getString(R.string.settings)
SettingsFragment()
}
}
if (fragmentLoading) {
if (fragment == null) {
false
} else {
appBarLayout.setExpanded(true)
loadFragment(fragment)
} else {
false
}
}
/// Scrolls to the top of any currently displayed fragment
bottomNav.setOnNavigationItemReselectedListener { item: MenuItem ->
when (item.itemId) {
R.id.plan, R.id.personal -> {
R.id.plan, R.id.personal, R.id.menu -> {
try {
val recyclerView = findViewById<RecyclerView>(R.id.linearRecycler)
val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
recyclerView.post {
recyclerView.smoothScrollToPosition(0)
}
appBarLayout.setExpanded(true)
} catch (e: NullPointerException) {}
} catch (e: NullPointerException) {
}
R.id.menu -> {
try {
val recyclerView = findViewById<RecyclerView>(R.id.linear_food)
recyclerView.post {
recyclerView.smoothScrollToPosition(0)
}
appBarLayout.setExpanded(true)
} catch (e: NullPointerException) {}
}
R.id.settings -> {
try {
val nsv = findViewById<NestedScrollView>(R.id.nsvsettings)
val nsv = findViewById<NestedScrollView>(R.id.settings_scroll_view)
nsv.post {
nsv.smoothScrollTo(0, 0)
}
appBarLayout.setExpanded(true)
} catch (e: NullPointerException) {}
} catch (e: NullPointerException) {
}
}
}
}
}
@@ -18,16 +18,16 @@ import com.google.android.material.card.MaterialCardView
* @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<Colour>, private val onClickListener: OnClickListener) : RecyclerView.Adapter<ColourAdapter.ColourViewHolder>() {
internal class ColourAdapter(private var colours: List<Colour>, private val onClickListener: OnColourClickListener) : RecyclerView.Adapter<ColourAdapter.ColourViewHolder>() {
internal class ColourViewHolder(view: View, private val clickListener: OnClickListener) : RecyclerView.ViewHolder(view), View.OnClickListener {
internal class ColourViewHolder(view: View, private val clickListener: OnColourClickListener) : 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)
var titleNoLang: String = ""
val cardView: MaterialCardView = view.findViewById(R.id.cardView)
init { view.setOnClickListener(this) }
override fun onClick(v: View?) { clickListener.onClick(adapterPosition, title.text.toString(), titleNoLang.text.toString()) }
override fun onClick(v: View?) { clickListener.onColourClick(adapterPosition, title.text.toString(), titleNoLang) }
}
@@ -40,7 +40,7 @@ internal class ColourAdapter(private var colours: List<Colour>, private val onCl
val currentItem = colours[position]
holder.title.text = currentItem.title
holder.titleNoLang.text = currentItem.titleNoLang
holder.titleNoLang = currentItem.titleNoLang
holder.image.setImageDrawable(ContextCompat.getDrawable(holder.image.context, currentItem.icon))
val colour = if (currentItem.colour != 0) {
currentItem.colour
@@ -60,7 +60,7 @@ internal class ColourAdapter(private var colours: List<Colour>, private val onCl
override fun getItemCount(): Int = colours.size
internal interface OnClickListener {
fun onClick(position: Int, title: String, titleNoLang: String)
internal interface OnColourClickListener {
fun onColourClick(position: Int, title: String, titleNoLang: String)
}
}
@@ -3,6 +3,7 @@ package com.denizd.substitutionplan.adapters
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
@@ -17,15 +18,16 @@ import com.google.android.material.card.MaterialCardView
* @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<Ringtone>, private val onClickListener: OnClickListener) : RecyclerView.Adapter<RingtoneAdapter.RingtoneViewHolder>() {
internal class RingtoneAdapter(private val ringtones: List<Ringtone>, private val onClickListener: OnRingtoneClickListener) : RecyclerView.Adapter<RingtoneAdapter.RingtoneViewHolder>() {
internal class RingtoneViewHolder(view: View, private val clickListener: OnClickListener) : RecyclerView.ViewHolder(view), View.OnClickListener {
internal class RingtoneViewHolder(view: View, private val clickListener: OnRingtoneClickListener) : 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 imageView: ImageView = view.findViewById(R.id.item_image)
var uri: String = ""
val cardView: MaterialCardView = view.findViewById(R.id.cardView)
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) }
}
@@ -38,13 +40,14 @@ internal class RingtoneAdapter(private val ringtones: List<Ringtone>, private va
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.imageView.visibility = View.GONE
holder.uri = currentItem.uri
holder.cardView.setCardBackgroundColor(ContextCompat.getColor(holder.cardView.context, R.color.colorBackgroundLight))
}
override fun getItemCount(): Int = ringtones.size
internal interface OnClickListener {
internal interface OnRingtoneClickListener {
fun onRingtoneClick(position: Int, name: String, uri: String)
}
}
@@ -7,7 +7,7 @@ import android.media.RingtoneManager
import android.net.Uri
import android.os.AsyncTask
import android.os.Build
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import android.view.View
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
@@ -33,14 +33,22 @@ import kotlin.collections.ArrayList
* @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 enables sending of a notification if true
* @param forced if true, times for food menu and substitution table will be overwritten
* with empty values to enable a forced refresh
* @param context the context of the application that will be stored as a WeakReference
* to avoid memory leakage
* @param application a reference to the application that will be stored as a WeakReference
* @param parentView a reference to the parent view that will be stored as a WeakReference
* @param forced if true, times for food menu and substitution table will be overwritten
* with empty values to enable a forced refresh
*/
internal class DataFetcher(isPlan: Boolean, isMenu: Boolean, isJobService: Boolean, context: Context, application: Application, parentView: View?, forced: Boolean) : AsyncTask<Void, Void, Void>() {
internal class DataFetcher(
isPlan: Boolean,
isMenu: Boolean,
isJobService: Boolean = false,
forced: Boolean = false,
context: Context,
application: Application,
parentView: View?
) : AsyncTask<Void, Void, Void>() {
private var jobService = isJobService
private var plan = isPlan
@@ -105,7 +113,7 @@ internal class DataFetcher(isPlan: Boolean, isMenu: Boolean, isJobService: Boole
override fun onPostExecute(result: Void?) {
mView.get()?.let {
try {
it.findViewById<SwipeRefreshLayout>(R.id.pullToRefresh).isRefreshing = false
it.findViewById<SwipeRefreshLayout>(R.id.swipe_refresh_layout).isRefreshing = false
} catch (ignored: Exception) {
}
}
@@ -47,7 +47,7 @@ internal object HelperFunctions {
"lavender", "carnation", "brown2", "pureBlack")
/**
* A lowercased list of all phrases used to describe that a course has been cancelled. Expand
* A lower-cased 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")
@@ -80,6 +80,7 @@ internal object HelperFunctions {
R.color.bgBrown2,
R.color.bgPureBlack
)
const val notificationChannelId = "general"
fun getColourForString(name: String): Int {
@@ -314,8 +315,8 @@ internal object HelperFunctions {
}
/**
* Assigns an integer to a given group used to sort the substitution plan in SQL.
* The ranking is stored as 'priority' in the database
* Assigns an integer to a given group used to sort the substitution plan when retrieving from
* Room database. The ranking is stored as 'priority' in the database
*
* @param group the group string that should be assigned a ranking
* @param isPSA used to determine a PSA, assigns lowest value if true, therefore putting
@@ -377,7 +378,7 @@ internal object HelperFunctions {
private fun getPrefValue(prefs: SharedPreferences, type: String, key: String): Any {
return when (type) {
"string" -> prefs.getString(key, "")
"string" -> prefs.getString(key, "") ?: ""
"int" -> prefs.getInt(key, 0)
"bool" -> prefs.getBoolean(key, false)
else -> ""
@@ -404,6 +405,8 @@ internal object HelperFunctions {
localPrefKeys.add("card${languageIndependentCourses[i]}")
localPrefTypes.add("string")
}
// if bothered, replace this with an API 29-friendly solution
// if not, who cares really, this is not even accessible without special codes
val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
val file = File(dir, "avh_plan_data.xml")
val out = OutputStreamWriter(FileOutputStream(file, false))
@@ -414,9 +417,11 @@ internal object HelperFunctions {
"\n\t<value>${getPrefValue(prefs, localPrefTypes[i], localPrefKeys[i])}</value>"
}
input += "\n</items>"
out.write(input)
out.flush()
out.close()
out.apply {
write(input)
flush()
close()
}
Toast.makeText(context, context.getString(R.string.success), Toast.LENGTH_LONG).show()
} else {
Toast.makeText(context, context.getString(R.string.permission_denied), Toast.LENGTH_LONG).show()
@@ -8,7 +8,7 @@ import android.webkit.WebViewClient
import java.lang.IllegalStateException
/**
* Class that extends WebViewClient to provide a function that checks the webpage's cookies to
* Class that extends WebViewClient to provide a function that checks the website's cookies to
* verify a login
*
* @param successListener a reference to the OnLoginSuccessListener implemented in an activity
@@ -26,8 +26,7 @@ internal class FoodViewModel(application: Application) : AndroidViewModel(applic
isJobService = false,
context = app,
application = app,
parentView = rootView,
forced = false
parentView = rootView
).execute()
}
}
@@ -28,8 +28,7 @@ internal class SubstViewModel(application: Application) : AndroidViewModel(appli
isJobService = false,
context = app,
application = app,
parentView = rootView,
forced = false
parentView = rootView
).execute()
}
}
@@ -3,42 +3,48 @@ package com.denizd.substitutionplan.fragments
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.denizd.substitutionplan.*
import com.denizd.substitutionplan.adapters.FoodAdapter
import com.denizd.substitutionplan.database.FoodViewModel
import com.denizd.substitutionplan.databinding.FoodLayoutBinding
import com.denizd.substitutionplan.models.Food
internal class FoodFragment : Fragment(R.layout.food_layout) {
internal class FoodFragment : Fragment() {
private val foodArrayList = ArrayList<Food>()
private val mAdapter = FoodAdapter(foodArrayList)
private lateinit var mContext: Context
private lateinit var prefs: SharedPreferences
private lateinit var recyclerView: RecyclerView
private lateinit var foodViewModel: FoodViewModel
private lateinit var binding: FoodLayoutBinding
override fun onAttach(context: Context) {
super.onAttach(context)
mContext = context
prefs = PreferenceManager.getDefaultSharedPreferences(mContext)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = FoodLayoutBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val pullToRefresh = view.findViewById<SwipeRefreshLayout>(R.id.pullToRefresh)
recyclerView = view.findViewById(R.id.linear_food)
recyclerView.hasFixedSize()
recyclerView.layoutManager = GridLayoutManager(mContext, 1)
recyclerView.adapter = mAdapter
binding.recyclerView.apply {
hasFixedSize()
layoutManager = GridLayoutManager(mContext, 1)
adapter = mAdapter
}
foodViewModel = ViewModelProviders.of(this).get(FoodViewModel::class.java)
foodViewModel.allFoods?.observe(this, Observer<List<Food>> { foodList ->
@@ -46,16 +52,16 @@ internal class FoodFragment : Fragment(R.layout.food_layout) {
for (item in foodList) {
foodArrayList.add(item)
}
recyclerView.scheduleLayoutAnimation()
binding.recyclerView.scheduleLayoutAnimation()
mAdapter.setFood(foodArrayList)
})
if (prefs.getBoolean("autoRefresh", false)) {
foodViewModel.refresh(swipeRefreshLayout = pullToRefresh, rootView = view.rootView)
foodViewModel.refresh(swipeRefreshLayout = binding.swipeRefreshLayout, rootView = view.rootView)
}
pullToRefresh.setOnRefreshListener {
foodViewModel.refresh(swipeRefreshLayout = pullToRefresh, rootView = view.rootView)
binding.swipeRefreshLayout.setOnRefreshListener {
foodViewModel.refresh(swipeRefreshLayout = binding.swipeRefreshLayout, rootView = view.rootView)
}
}
}
@@ -12,7 +12,7 @@ internal class GeneralPlanFragment : PlanFragment() {
substitutionPlan?.observe(this, Observer<List<Substitution>> { substitutions ->
mAdapter.setSubst(substitutions)
recyclerView.scheduleLayoutAnimation()
binding.recyclerView.scheduleLayoutAnimation()
})
}
}
@@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.View
import androidx.lifecycle.Observer
import com.denizd.substitutionplan.data.HelperFunctions
import com.denizd.substitutionplan.R
import com.denizd.substitutionplan.models.Substitution
internal class PersonalPlanFragment : PlanFragment() {
@@ -12,20 +11,16 @@ internal class PersonalPlanFragment : PlanFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
personalPlanEmptyEmoticon = view.findViewById(R.id.smileydown)
personalPlanEmptyText = view.findViewById(R.id.smileydowntext)
personalPlanEmptyLayout = view.findViewById(R.id.linearsmiley)
val coursePreference = prefs.getString("courses", "") ?: ""
val classPreference = prefs.getString("classes", "") ?: ""
substitutionPlan?.observe(this, Observer<List<Substitution>> { substitutions ->
planCardList.clear()
personalPlanEmptyEmoticon.visibility = View.GONE
personalPlanEmptyText.visibility = View.GONE
personalPlanEmptyLayout.visibility = View.GONE
binding.emptyPlanEmoticon.visibility = View.GONE
binding.emptyPlanText.visibility = View.GONE
binding.emptyPlanLayout.visibility = View.GONE
isPersonalPlanEmpty = true
recyclerView.visibility = View.VISIBLE
binding.recyclerView.visibility = View.VISIBLE
substitutions.filter { substItem ->
HelperFunctions.checkPersonalSubstitutions(
@@ -38,15 +33,15 @@ internal class PersonalPlanFragment : PlanFragment() {
planCardList.add(substItem)
}
isPersonalPlanEmpty = (planCardList.size == 1 && planCardList[0].date.substring(0, 3) == "psa") || planCardList.isEmpty()
recyclerView.scheduleLayoutAnimation()
binding.recyclerView.scheduleLayoutAnimation()
mAdapter.setSubst(planCardList)
handler.postDelayed({
if (isPersonalPlanEmpty) {
personalPlanEmptyEmoticon.visibility = View.VISIBLE
personalPlanEmptyText.visibility = View.VISIBLE
personalPlanEmptyLayout.visibility = View.VISIBLE
personalPlanEmptyLayout.scheduleLayoutAnimation()
binding.emptyPlanEmoticon.visibility = View.VISIBLE
binding.emptyPlanText.visibility = View.VISIBLE
binding.emptyPlanLayout.visibility = View.VISIBLE
binding.emptyPlanLayout.scheduleLayoutAnimation()
}
}, 64)
})
@@ -5,46 +5,48 @@ import android.content.SharedPreferences
import android.content.res.Configuration
import android.os.Bundle
import android.os.Handler
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import android.view.LayoutInflater
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.denizd.substitutionplan.*
import com.denizd.substitutionplan.R
import com.denizd.substitutionplan.adapters.SubstitutionAdapter
import com.denizd.substitutionplan.database.SubstViewModel
import com.denizd.substitutionplan.databinding.PlanBinding
import com.denizd.substitutionplan.models.Substitution
import kotlin.collections.ArrayList
internal open class PlanFragment : Fragment(R.layout.plan) {
internal lateinit var recyclerView: RecyclerView
internal open class PlanFragment : Fragment() {
internal lateinit var mAdapter: SubstitutionAdapter
internal var planCardList = ArrayList<Substitution>()
private lateinit var substViewModel: SubstViewModel
private lateinit var mContext: Context
internal lateinit var prefs: SharedPreferences
internal lateinit var personalPlanEmptyEmoticon: TextView
internal lateinit var personalPlanEmptyText: TextView
internal lateinit var personalPlanEmptyLayout: LinearLayout
internal var isPersonalPlanEmpty: Boolean = true
internal val handler = Handler()
internal var substitutionPlan: LiveData<List<Substitution>>? = null
internal lateinit var binding: PlanBinding
override fun onAttach(context: Context) {
super.onAttach(context)
mContext = context
prefs = PreferenceManager.getDefaultSharedPreferences(mContext)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = PlanBinding.inflate(inflater, container, false)
return binding.root
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
recyclerView.layoutManager = GridLayoutManager(mContext, getGridColumnCount(newConfig))
binding.recyclerView.layoutManager = GridLayoutManager(mContext, getGridColumnCount(newConfig))
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -56,24 +58,24 @@ internal open class PlanFragment : Fragment(R.layout.plan) {
substViewModel.allSubstitutionsOriginal
}
val pullToRefresh = view.findViewById<SwipeRefreshLayout>(R.id.pullToRefresh)
recyclerView = view.findViewById(R.id.linearRecycler)
recyclerView.hasFixedSize()
recyclerView.layoutManager = GridLayoutManager(mContext, getGridColumnCount(resources.configuration))
mAdapter = SubstitutionAdapter(planCardList, prefs)
recyclerView.adapter = mAdapter
binding.recyclerView.apply {
hasFixedSize()
layoutManager = GridLayoutManager(mContext, getGridColumnCount(resources.configuration))
adapter = mAdapter
}
if (prefs.getInt("firstTimeOpening", 0) == 1) {
substViewModel.refresh(swipeRefreshLayout = pullToRefresh, rootView = view.rootView, refreshMenu = true)
substViewModel.refresh(swipeRefreshLayout = binding.swipeRefreshLayout, rootView = view.rootView, refreshMenu = true)
prefs.edit().putInt("firstTimeOpening", 2).apply()
}
if (prefs.getBoolean("autoRefresh", false)) {
substViewModel.refresh(swipeRefreshLayout = pullToRefresh, rootView = view.rootView, refreshMenu = false)
substViewModel.refresh(swipeRefreshLayout = binding.swipeRefreshLayout, rootView = view.rootView, refreshMenu = false)
}
pullToRefresh.setOnRefreshListener {
substViewModel.refresh(swipeRefreshLayout = pullToRefresh, rootView = view.rootView, refreshMenu = false)
binding.swipeRefreshLayout.setOnRefreshListener {
substViewModel.refresh(swipeRefreshLayout = binding.swipeRefreshLayout, rootView = view.rootView, refreshMenu = false)
}
}
@@ -10,11 +10,13 @@ import android.media.RingtoneManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import android.provider.Settings
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.widget.*
import androidx.appcompat.app.AlertDialog
@@ -30,27 +32,33 @@ import com.denizd.substitutionplan.adapters.RingtoneAdapter
import com.denizd.substitutionplan.data.DataFetcher
import com.denizd.substitutionplan.data.HelperFunctions
import com.denizd.substitutionplan.data.Topic
import com.denizd.substitutionplan.databinding.ContentSettingsBinding
import com.denizd.substitutionplan.models.Colour
import com.denizd.substitutionplan.models.Ringtone
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.button.MaterialButton
import com.google.android.material.textfield.TextInputEditText
import com.google.firebase.messaging.FirebaseMessaging
import kotlin.collections.ArrayList
internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnClickListener,
CompoundButton.OnCheckedChangeListener, ColourAdapter.OnClickListener,
RingtoneAdapter.OnClickListener {
internal class SettingsFragment : Fragment(), View.OnClickListener,
CompoundButton.OnCheckedChangeListener, ColourAdapter.OnColourClickListener,
RingtoneAdapter.OnRingtoneClickListener {
private lateinit var mContext: Context
private lateinit var prefs: SharedPreferences
private val builder = CustomTabsIntent.Builder()
private val customTabsIntent = builder.build() as CustomTabsIntent
private val customTabsIntent = CustomTabsIntent.Builder().build() as CustomTabsIntent
private var window: Window? = null
private lateinit var colourRecycler: RecyclerView
private lateinit var ringtoneCustomiserDialog: AlertDialog
private lateinit var currentRingtone: TextView
private var longPressed = false
private var courseHelpClicks = 0
private val ringtones: List<Ringtone> by lazy {
getRingtones()
}
private lateinit var colourRecycler: RecyclerView
private lateinit var ringtoneDialog: AlertDialog
private lateinit var binding: ContentSettingsBinding
override fun onAttach(context: Context) {
super.onAttach(context)
@@ -59,81 +67,115 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl
window = activity?.window
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = ContentSettingsBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val nameEditText = view.findViewById<TextInputEditText>(R.id.txtName)
val gradeEditText = view.findViewById<TextInputEditText>(R.id.txtClasses)
val courseEditText = view.findViewById<TextInputEditText>(R.id.txtCourses)
binding.apply {
val thisFragment = this@SettingsFragment
val greetingSwitch = view.findViewById<Switch>(R.id.switchDisableGreeting)
val notificationSwitch = view.findViewById<Switch>(R.id.switchNotifications)
val defaultPlanSwitch = view.findViewById<Switch>(R.id.switchDefaultPlan)
val autoRefreshSwitch = view.findViewById<Switch>(R.id.switchAutoRefresh)
val versionNumberText = view.findViewById<TextView>(R.id.txtVersionTwo)
val helpGradeButton = view.findViewById<ImageButton>(R.id.chipHelpClasses)
val helpCoursesButton = view.findViewById<ImageButton>(R.id.chipHelpCourses)
val colourCustomisationButton = view.findViewById<LinearLayout>(R.id.btnCustomiseColours)
val versionButton = view.findViewById<LinearLayout>(R.id.btnVersion)
currentRingtone = view.findViewById(R.id.txtCustomiseRingtone2)
// Set text
setRingtoneText()
val forceRefreshButton = view.findViewById<LinearLayout>(R.id.btnForceRefresh)
val colourTextTitle = view.findViewById<TextView>(R.id.txtCustomiseColours1)
val colourTextDesc = view.findViewById<TextView>(R.id.txtCustomiseColours2)
textAppVersionDesc.text = BuildConfig.VERSION_NAME
greetingSwitch.setOnCheckedChangeListener(this)
notificationSwitch.setOnCheckedChangeListener(this)
defaultPlanSwitch.setOnCheckedChangeListener(this)
autoRefreshSwitch.setOnCheckedChangeListener(this)
helpCoursesButton.setOnClickListener(this)
helpGradeButton.setOnClickListener(this)
view.findViewById<ImageButton>(R.id.chip_help_ordering).setOnClickListener(this)
colourCustomisationButton.setOnClickListener(this)
colourCustomisationButton.setOnLongClickListener {
// Set on click listeners
buttonCustomiseColours.setOnClickListener(thisFragment)
buttonNotificationsHelp.setOnClickListener(thisFragment)
buttonCustomiseRingtone.setOnClickListener(thisFragment)
buttonGroupHelp.setOnClickListener(thisFragment)
buttonCoursesHelp.setOnClickListener(thisFragment)
buttonOrderHelp.setOnClickListener(thisFragment)
buttonForcedRefresh.setOnClickListener(thisFragment)
buttonVisitWebsite.setOnClickListener(thisFragment)
buttonLicences.setOnClickListener(thisFragment)
buttonVersion.setOnClickListener(thisFragment)
// Set on long click listeners
buttonCustomiseColours.setOnLongClickListener {
if (!longPressed) {
colourTextTitle.text = getString(R.string.made_by_deniz)
colourTextDesc.text = getString(R.string.thanks_for_using)
textCustomiseColoursTitle.text = getString(R.string.made_by_deniz)
textCustomiseColoursDesc.text = getString(R.string.thanks_for_using)
} else {
colourTextTitle.text = getString(R.string.customise_colours_title)
colourTextDesc.text = getString(R.string.customise_colours_desc)
textCustomiseColoursTitle.text = getString(R.string.customise_colours_title)
textCustomiseColoursDesc.text = getString(R.string.customise_colours_desc)
}
longPressed = !longPressed
true
}
view.findViewById<LinearLayout>(R.id.btnNoNotif).setOnClickListener(this)
view.findViewById<LinearLayout>(R.id.btnCustomiseRingtone).setOnClickListener(this)
view.findViewById<LinearLayout>(R.id.btnWebsite).setOnClickListener(this)
view.findViewById<LinearLayout>(R.id.btnLicences).setOnClickListener(this)
versionButton.setOnClickListener(this)
forceRefreshButton.setOnClickListener(this)
forceRefreshButton.setOnLongClickListener {
buttonForcedRefresh.setOnLongClickListener {
prefs.edit().putString("timeNew", "").putString("newFoodTime", "").apply()
makeToast(mContext.getString(R.string.force_refresh_cleared_times))
true
}
val darkModeDropDown = view.findViewById<AutoCompleteTextView>(R.id.darkModeDropDownText)
buttonVersion.setOnLongClickListener {
debugMenu()
}
// Set on checked change listeners
switchGreeting.setOnCheckedChangeListener(thisFragment)
switchNotifications.setOnCheckedChangeListener(thisFragment)
switchPersonalisedPlan.setOnCheckedChangeListener(thisFragment)
switchAutoRefresh.setOnCheckedChangeListener(thisFragment)
// Set checked
switchGreeting.isChecked = prefs.getBoolean("greeting", true)
switchNotifications.isChecked = prefs.getBoolean("notif", false)
switchPersonalisedPlan.isChecked = prefs.getBoolean("defaultPersonalised", false)
switchAutoRefresh.isChecked = prefs.getBoolean("autoRefresh", false)
// Set edit text (+ listeners)
edittextName.setText(prefs.getString("username", ""))
edittextName.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
prefs.edit().putString("username", edittextName.text.toString().trim()).apply()
}
})
edittextGroup.setText(prefs.getString("classes", ""))
edittextGroup.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
prefs.edit().putString("classes", edittextGroup.text.toString()).apply()
}
})
edittextCourses.setText(prefs.getString("courses", ""))
edittextCourses.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
prefs.edit().putString("courses", edittextCourses.text.toString()).apply()
}
})
// Set spinners (+ listeners)
val darkModeList = if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
R.array.themes_pre_q
} else {
R.array.themes
}
val darkModeAdapter = ArrayAdapter.createFromResource(
mContext,
darkModeList,
R.layout.dropdown_item
)
darkModeAdapter.setDropDownViewResource(R.layout.dropdown_item)
darkModeDropDown.setAdapter(darkModeAdapter)
darkModeDropDown.setText(darkModeDropDown.adapter.getItem(prefs.getInt("themeInt", 0)).toString(), false)
darkModeDropDown.setOnItemClickListener { _, _, position, _ ->
autocompleteDarkMode.setAdapter(darkModeAdapter)
autocompleteDarkMode.setText(autocompleteDarkMode.adapter.getItem(prefs.getInt("themeInt", 0)).toString(), false)
autocompleteDarkMode.setOnItemClickListener { _, _, position, _ ->
prefs.edit().putInt("themeInt", position).apply()
val bottomNav = view.rootView.findViewById<BottomNavigationView>(R.id.bottom_nav)
when (position) {
0 -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
@@ -143,9 +185,7 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl
window?.navigationBarColor = ContextCompat.getColor(mContext, R.color.colorBackground)
}
}
2 -> { // only accessible on Android 10 (and above)
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}
2 -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) // only accessible on API 29+
else -> {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
@@ -153,70 +193,142 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl
}
}
}
if (prefs.getBoolean("defaultPersonalised", false)) {
bottomNav.selectedItemId = R.id.personal
view.rootView.findViewById<BottomNavigationView>(R.id.bottom_nav).selectedItemId = if (prefs.getBoolean("defaultPersonalised", false)) {
R.id.personal
} else {
bottomNav.selectedItemId = R.id.plan
R.id.plan
}
}
val orderingDropDownText = view.findViewById<AutoCompleteTextView>(R.id.order_drop_down_text)
val selectedOrderingOption = if (prefs.getBoolean("app_specific_sorting", true)) 0 else 1
val orderingArrayAdapter = ArrayAdapter.createFromResource(
mContext,
R.array.ordering_systems,
R.layout.dropdown_item
)
orderingArrayAdapter.setDropDownViewResource(R.layout.dropdown_item)
orderingDropDownText.setAdapter(orderingArrayAdapter)
val selectedOrderingOption = if (prefs.getBoolean("app_specific_sorting", true)) 0 else 1
orderingDropDownText.setText(orderingDropDownText.adapter.getItem(selectedOrderingOption).toString(), false)
orderingDropDownText.setOnItemClickListener { _, _, position, _ ->
autocompleteOrder.setAdapter(orderingArrayAdapter)
autocompleteOrder.setText(autocompleteOrder.adapter.getItem(selectedOrderingOption).toString(), false)
autocompleteOrder.setOnItemClickListener { _, _, position, _ ->
prefs.edit().putBoolean("app_specific_sorting", position == 0).apply()
}
greetingSwitch.isChecked = prefs.getBoolean("greeting", true)
notificationSwitch.isChecked = prefs.getBoolean("notif", false)
defaultPlanSwitch.isChecked = prefs.getBoolean("defaultPersonalised", false)
autoRefreshSwitch.isChecked = prefs.getBoolean("autoRefresh", false)
versionNumberText.text = BuildConfig.VERSION_NAME
nameEditText.setText(prefs.getString("username", ""))
nameEditText.addTextChangedListener(object: TextWatcher {
override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
prefs.edit().putString("username", nameEditText.text.toString().trim()).apply()
}
})
gradeEditText.setText(prefs.getString("classes", ""))
gradeEditText.addTextChangedListener(object: TextWatcher {
override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
prefs.edit().putString("classes", gradeEditText.text.toString()).apply()
}
})
courseEditText.setText(prefs.getString("courses", ""))
courseEditText.addTextChangedListener(object: TextWatcher {
override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
prefs.edit().putString("courses", courseEditText.text.toString()).apply()
}
})
versionButton.setOnLongClickListener {
debugMenu()
}
}
// Functions for handling touch events in this fragment
override fun onClick(v: View?) {
when (v?.id) {
R.id.button_customise_colours -> createColourDialog()
R.id.button_notifications_help -> createDialog(mContext.getString(R.string.no_notifications_title), mContext.getString(R.string.no_notifications_dialog_text))
R.id.button_customise_ringtone -> createRingtoneDialog()
R.id.button_group_help -> createDialog(getString(R.string.grade_help_dialog_title), getString(
R.string.grade_help_dialog_text
))
R.id.button_courses_help -> {
if (courseHelpClicks < 11) {
courseHelpClicks += 1
createDialog(getString(R.string.courses_help_dialog_title), getString(R.string.courses_help_dialog_text))
} else {
courseHelpClicks = 0
try {
makeToast(String(Character.toChars(0x2764)))
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://www.youtube.com/watch?v=Jc2xfYuLWgE")) // 'Freak'
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).setPackage("com.google.android.youtube")
startActivity(intent)
} catch (e: ActivityNotFoundException) {
makeToast(getString(R.string.youtube_not_found))
}
}
}
R.id.button_order_help -> createDialog(getString(R.string.ordering_systems_dialog_title), getString(R.string.ordering_systems_dialog_text))
R.id.button_forced_refresh -> {
DataFetcher(
isPlan = true,
isMenu = true,
forced = true,
context = mContext,
application = activity!!.application,
parentView = view!!.rootView
).execute()
}
R.id.button_visit_website -> {
try {
customTabsIntent.launchUrl(mContext, Uri.parse("http://307.joomla.schule.bremen.de"))
} catch (e: ActivityNotFoundException) {
makeToast(getString(R.string.chrome_not_found))
}
}
R.id.button_licences -> {
createDialog(mContext.getString(R.string.licences_title), licences)
}
}
}
override fun onCheckedChanged(v: CompoundButton?, isChecked: Boolean) {
if (v?.isPressed == true) {
when (v.id) {
R.id.switch_greeting -> {
prefs.edit().putBoolean("greeting", isChecked).apply()
}
R.id.switch_notifications -> {
prefs.edit().putBoolean("notif", isChecked).apply()
if (isChecked) {
subscribeToTopic(Topic.ANDROID)
} else {
unsubscribeFromTopic(Topic.ANDROID)
}
}
R.id.switch_personalised_plan -> {
prefs.edit().putBoolean("defaultPersonalised", isChecked).apply()
}
R.id.switch_auto_refresh -> {
prefs.edit().putBoolean("autoRefresh", isChecked).apply()
}
}
}
}
// Functions for handling touch events for recycler view elements
override fun onColourClick(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<TextView>(R.id.empty_textviewtitle)
val pickerLayout = pickerDialogView.findViewById<LinearLayout>(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<MaterialButton>(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()
}
override fun onRingtoneClick(position: Int, name: String, uri: String) {
prefs.edit().apply {
putString("ringtoneName", name)
putString("ringtoneUri", uri)
}.apply()
setRingtoneText()
ringtoneDialog.dismiss()
}
// Functions for handling dialog creation
private fun createDialog(title: String, text: String) {
val alertDialog = AlertDialog.Builder(mContext,
R.style.AlertDialog
@@ -233,7 +345,7 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl
val dialogView = View.inflate(mContext, R.layout.recycler_dialog, null)
val titleText = dialogView.findViewById<TextView>(R.id.empty_textviewtitle)
titleText.text = getString(R.string.customise_colours_title)
colourRecycler = dialogView.findViewById(R.id.recyclerView)
val colourRecycler = dialogView.findViewById<RecyclerView>(R.id.recyclerView)
colourRecycler.apply {
hasFixedSize()
layoutManager = GridLayoutManager(mContext, 1)
@@ -244,48 +356,6 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl
colourCustomisationDialog.show()
}
private fun getColourList(): ArrayList<Colour> {
val colours = ArrayList<Colour>()
val coursesNoLang = HelperFunctions.languageIndependentCourses
val courses = arrayOf(getString(R.string.course_deu), getString(
R.string.course_eng
), getString(R.string.course_fra), getString(R.string.course_spa), getString(
R.string.course_lat
), getString(R.string.course_tue), getString(R.string.course_chi), getString(
R.string.course_kun
), getString(R.string.course_mus), getString(R.string.course_dar), getString(
R.string.course_geg
), getString(R.string.course_ges), getString(R.string.course_pol), getString(
R.string.course_phi
), getString(R.string.course_rel), getString(R.string.course_mat), getString(
R.string.course_bio
), getString(R.string.course_che), getString(R.string.course_phy), getString(
R.string.course_inf
), getString(R.string.course_spo), getString(R.string.course_gll), getString(
R.string.course_wat
), getString(R.string.course_foer), getString(R.string.course_wp))
val coursesIcons = intArrayOf(R.drawable.ic_german, R.drawable.ic_english, R.drawable.ic_french,
R.drawable.ic_spanish, R.drawable.ic_latin, R.drawable.ic_turkish, R.drawable.ic_chinese,
R.drawable.ic_arts, R.drawable.ic_music, R.drawable.ic_drama, R.drawable.ic_geography,
R.drawable.ic_history, R.drawable.ic_politics, R.drawable.ic_philosophy, R.drawable.ic_religion,
R.drawable.ic_maths, R.drawable.ic_biology, R.drawable.ic_chemistry, R.drawable.ic_physics,
R.drawable.ic_compsci, R.drawable.ic_pe, R.drawable.ic_gll, R.drawable.ic_wat,
R.drawable.ic_help, R.drawable.ic_pencil
)
for (i in coursesNoLang.indices) {
colours.add(
Colour(
courses[i],
coursesNoLang[i],
coursesIcons[i],
HelperFunctions.getColourForString(prefs.getString("card${coursesNoLang[i]}", "") ?: "")
)
)
}
return colours
}
private fun createRingtoneDialog() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
HelperFunctions.getNotificationChannel(mContext, prefs)
@@ -305,48 +375,15 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl
recycler.apply {
hasFixedSize()
layoutManager = GridLayoutManager(mContext, 1)
adapter = RingtoneAdapter(ringtones, this@SettingsFragment)
}
ringtoneCustomiserDialog = ringtoneCustomiserBuilder.setView(dialogView).create()
ringtoneCustomiserDialog.show()
ringtoneDialog = ringtoneCustomiserBuilder.setView(dialogView).create()
ringtoneDialog.show()
recycler.postDelayed({
val ringtones = getRingtones().toList()
recycler.adapter = RingtoneAdapter(ringtones, this)
}, 100)
}
}
private fun getRingtones(): ArrayList<Ringtone> {
lateinit var ringtoneCursor: Cursor
val ringtoneManager = RingtoneManager(activity).apply {
setType(RingtoneManager.TYPE_NOTIFICATION)
ringtoneCursor = cursor
}
val alarms = ArrayList<Ringtone>()
while (!ringtoneCursor.isAfterLast && ringtoneCursor.moveToNext()) {
val position = ringtoneCursor.position
alarms.add(
Ringtone(
ringtoneManager.getRingtone(position).getTitle(mContext),
ringtoneManager.getRingtoneUri(position).toString()
)
)
}
return alarms
}
private fun setRingtoneText() {
currentRingtone.text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mContext.getString(R.string.pick_ringtone_desc_o)
} else {
val tone = if ((prefs.getString("ringtoneName", "") ?: "").isNotEmpty()) {
prefs.getString("ringtoneName", "")
} else {
mContext.getString(R.string.default_ringtone)
}
mContext.getString(R.string.pick_ringtone_desc, tone)
// recycler.postDelayed({
// recycler.
// }, 100)
}
}
@@ -387,15 +424,6 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl
alertDialogDev.setView(devDialogView)
alertDialogDev.show()
}
"2019-06-06" -> {
try {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("https://www.youtube.com/watch?v=Jc2xfYuLWgE")) // 'Freak'
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).setPackage("com.google.android.youtube")
startActivity(intent)
} catch (e: ActivityNotFoundException) {
makeToast(getString(R.string.youtube_not_found))
}
}
"_LOGIN" -> {
prefs.edit().putBoolean("successful_login", false).apply()
makeToast("Login flag cleared")
@@ -441,6 +469,112 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl
return true
}
// Functions for retrieving data
private fun getColourList(): ArrayList<Colour> {
val colours = ArrayList<Colour>()
val coursesNoLang = HelperFunctions.languageIndependentCourses
val courses = arrayOf(
getString(R.string.course_deu),
getString(R.string.course_eng),
getString(R.string.course_fra),
getString(R.string.course_spa),
getString(R.string.course_lat),
getString(R.string.course_tue),
getString(R.string.course_chi),
getString(R.string.course_kun),
getString(R.string.course_mus),
getString(R.string.course_dar),
getString(R.string.course_geg),
getString(R.string.course_ges),
getString(R.string.course_pol),
getString(R.string.course_phi),
getString(R.string.course_rel),
getString(R.string.course_mat),
getString(R.string.course_bio),
getString(R.string.course_che),
getString(R.string.course_phy),
getString(R.string.course_inf),
getString(R.string.course_spo),
getString(R.string.course_gll),
getString(R.string.course_wat),
getString(R.string.course_foer),
getString(R.string.course_wp)
)
val coursesIcons = intArrayOf(
R.drawable.ic_german,
R.drawable.ic_english,
R.drawable.ic_french,
R.drawable.ic_spanish,
R.drawable.ic_latin,
R.drawable.ic_turkish,
R.drawable.ic_chinese,
R.drawable.ic_arts,
R.drawable.ic_music,
R.drawable.ic_drama,
R.drawable.ic_geography,
R.drawable.ic_history,
R.drawable.ic_politics,
R.drawable.ic_philosophy,
R.drawable.ic_religion,
R.drawable.ic_maths,
R.drawable.ic_biology,
R.drawable.ic_chemistry,
R.drawable.ic_physics,
R.drawable.ic_compsci,
R.drawable.ic_pe,
R.drawable.ic_gll,
R.drawable.ic_wat,
R.drawable.ic_help,
R.drawable.ic_pencil
)
for (i in coursesNoLang.indices) {
colours.add(
Colour(
courses[i],
coursesNoLang[i],
coursesIcons[i],
HelperFunctions.getColourForString(prefs.getString("card${coursesNoLang[i]}", "") ?: "")
)
)
}
return colours
}
private fun getRingtones(): ArrayList<Ringtone> {
lateinit var ringtoneCursor: Cursor
val ringtoneManager = RingtoneManager(activity).apply {
setType(RingtoneManager.TYPE_NOTIFICATION)
ringtoneCursor = cursor
}
val alarms = ArrayList<Ringtone>()
while (!ringtoneCursor.isAfterLast && ringtoneCursor.moveToNext()) {
val position = ringtoneCursor.position
alarms.add(
Ringtone(
ringtoneManager.getRingtone(position).getTitle(mContext),
ringtoneManager.getRingtoneUri(position).toString()
)
)
}
return alarms
}
// Functions for handling other things
private fun setRingtoneText() {
binding.textCustomiseRingtoneDesc.text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mContext.getString(R.string.pick_ringtone_desc_o)
} else {
val tone = if ((prefs.getString("ringtoneName", "") ?: "").isNotEmpty()) {
prefs.getString("ringtoneName", "")
} else {
mContext.getString(R.string.default_ringtone)
}
mContext.getString(R.string.pick_ringtone_desc, tone)
}
}
private fun makeToast(text: String) {
Toast.makeText(mContext, text, Toast.LENGTH_LONG).show()
}
@@ -460,111 +594,7 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl
private fun subscribeToTopic(topic: Topic) = FirebaseMessaging.getInstance().subscribeToTopic(topic.tag)
private fun unsubscribeFromTopic(topic: Topic) = FirebaseMessaging.getInstance().unsubscribeFromTopic(topic.tag)
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.chip_help_ordering -> createDialog(getString(R.string.ordering_systems_dialog_title), getString(R.string.ordering_systems_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.btnForceRefresh -> {
DataFetcher(
isPlan = true,
isMenu = true,
isJobService = false,
context = mContext,
application = activity!!.application,
parentView = view!!.rootView,
forced = true
).execute()
}
}
}
override fun onRingtoneClick(position: Int, name: String, uri: String) {
prefs.edit().apply {
putString("ringtoneName", name)
putString("ringtoneUri", uri)
}.apply()
setRingtoneText()
ringtoneCustomiserDialog.dismiss()
}
/**
* OnClick method for colour customisation dialog
* @param position the position of the clicked item
* @param title the title of the clicked course
* @param titleNoLang the language-independent string used for storing the course's colour in
* Shared Preferences
*/
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<TextView>(R.id.empty_textviewtitle)
val pickerLayout = pickerDialogView.findViewById<LinearLayout>(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<MaterialButton>(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()
}
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()
}
}
}
}
/// Below this point follow string literals that I didn't bother putting in /res/values
// Below this point follow string literals that I didn't bother putting in /res/values/strings
private val licences = "Libraries:" +
"\n • jsoup HTML parser © 2009-2018 Jonathan Hedley, licensed under the open source MIT Licence" +
@@ -1,5 +1,6 @@
package com.denizd.substitutionplan.services
import android.annotation.SuppressLint
import com.denizd.substitutionplan.data.DataFetcher
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
@@ -8,6 +9,7 @@ import com.google.firebase.messaging.RemoteMessage
* This class handles Firebase data notifications and triggers a refresh of the substitution plan
* as well as the food menu upon arrival
*/
@SuppressLint("MissingFirebaseInstanceTokenRefresh")
internal class FBNotificationService : FirebaseMessagingService() {
override fun onMessageReceived(p0: RemoteMessage) {
@@ -17,8 +19,7 @@ internal class FBNotificationService : FirebaseMessagingService() {
isJobService = true,
context = applicationContext,
application = application,
parentView = null,
forced = false
parentView = null
).execute()
}
}
@@ -2,7 +2,7 @@ package com.denizd.substitutionplan.services
import android.app.job.JobParameters
import android.app.job.JobService
import android.preference.PreferenceManager
import androidx.preference.PreferenceManager
import com.denizd.substitutionplan.data.Topic
import com.google.firebase.FirebaseApp
import com.google.firebase.messaging.FirebaseMessaging
+19 -19
View File
@@ -59,7 +59,7 @@
app:layout_constraintTop_toBottomOf="@+id/txtsetupthings" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/txtLayoutClasses"
android:id="@+id/textinputlayout_group"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
app:boxStrokeColor="@color/colorAccent"
app:boxStrokeWidth="1dp"
@@ -75,7 +75,7 @@
android:importantForAutofill="no">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/txtName"
android:id="@+id/edittext_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
@@ -100,9 +100,9 @@
android:text="@string/grade_text"
android:textColor="@color/colorText"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="@+id/txtLayoutClasses"
app:layout_constraintStart_toStartOf="@+id/txtLayoutClasses"
app:layout_constraintTop_toBottomOf="@+id/txtLayoutClasses" />
app:layout_constraintEnd_toEndOf="@+id/textinputlayout_group"
app:layout_constraintStart_toStartOf="@+id/textinputlayout_group"
app:layout_constraintTop_toBottomOf="@+id/textinputlayout_group" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/txtLayoutClass"
@@ -114,13 +114,13 @@
android:layout_marginTop="8dp"
android:hint="@string/your_grade"
android:textColorHint="@color/colorHint"
app:layout_constraintEnd_toStartOf="@+id/chipHelpClasses"
app:layout_constraintEnd_toStartOf="@+id/button_group_help"
app:layout_constraintStart_toStartOf="@+id/txtNextClass"
app:layout_constraintTop_toBottomOf="@+id/txtNextClass"
android:importantForAutofill="no">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/txtClasses"
android:id="@+id/edittext_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
@@ -137,7 +137,7 @@
</com.google.android.material.textfield.TextInputLayout>
<ImageButton
android:id="@+id/chipHelpClasses"
android:id="@+id/button_group_help"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
@@ -156,12 +156,12 @@
android:gravity="start"
android:layout_marginTop="16dp"
android:textColor="@color/colorText"
app:layout_constraintEnd_toEndOf="@+id/txtLayoutClasses"
app:layout_constraintStart_toStartOf="@+id/txtLayoutClasses"
app:layout_constraintEnd_toEndOf="@+id/textinputlayout_group"
app:layout_constraintStart_toStartOf="@+id/textinputlayout_group"
app:layout_constraintTop_toBottomOf="@+id/txtLayoutClass" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/txtLayoutCourses"
android:id="@+id/textinputlayout_courses"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
app:boxStrokeColor="@color/colorAccent"
app:boxStrokeWidth="1dp"
@@ -170,12 +170,12 @@
android:layout_marginTop="8dp"
android:hint="@string/your_courses"
android:textColorHint="@color/colorHint"
app:layout_constraintEnd_toStartOf="@+id/chipHelpCourses"
app:layout_constraintEnd_toStartOf="@+id/button_courses_help"
app:layout_constraintStart_toStartOf="@+id/txtSenior"
app:layout_constraintTop_toBottomOf="@+id/txtSenior">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/txtCourses"
android:id="@+id/edittext_courses"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
@@ -193,16 +193,16 @@
</com.google.android.material.textfield.TextInputLayout>
<ImageButton
android:id="@+id/chipHelpCourses"
android:id="@+id/button_courses_help"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:backgroundTint="@android:color/transparent"
android:src="@drawable/ic_qmark"
android:tint="@color/colorText"
app:layout_constraintBottom_toBottomOf="@+id/txtLayoutCourses"
app:layout_constraintBottom_toBottomOf="@+id/textinputlayout_courses"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/txtLayoutCourses" />
app:layout_constraintTop_toTopOf="@+id/textinputlayout_courses" />
<TextView
android:id="@+id/txtMore"
@@ -211,9 +211,9 @@
android:layout_marginTop="16dp"
android:text="@string/more_settings_text"
android:textColor="@color/colorText"
app:layout_constraintEnd_toEndOf="@+id/txtLayoutClasses"
app:layout_constraintStart_toStartOf="@+id/txtLayoutClasses"
app:layout_constraintTop_toBottomOf="@+id/txtLayoutCourses" />
app:layout_constraintEnd_toEndOf="@+id/textinputlayout_group"
app:layout_constraintStart_toStartOf="@+id/textinputlayout_group"
app:layout_constraintTop_toBottomOf="@+id/textinputlayout_courses" />
<LinearLayout
android:layout_width="0dp"
+139 -137
View File
@@ -7,7 +7,7 @@
tools:context=".fragments.SettingsFragment">
<androidx.core.widget.NestedScrollView
android:id="@+id/nsvsettings"
android:id="@+id/settings_scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
@@ -36,7 +36,7 @@
android:layout_height="wrap_content">
<TextView
android:id="@+id/txtPersonalise"
android:id="@+id/header_personalise"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
@@ -47,7 +47,7 @@
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/txtLayoutName"
android:id="@+id/textinputlayout_name"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
@@ -61,10 +61,10 @@
app:boxStrokeWidth="1dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtPersonalise">
app:layout_constraintTop_toBottomOf="@+id/header_personalise">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/txtName"
android:id="@+id/edittext_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
@@ -79,38 +79,39 @@
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:id="@+id/txtGreeting"
android:id="@+id/text_greeting_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/greeting_title"
android:textColor="@color/colorText"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@+id/txtPersonalise"
app:layout_constraintTop_toBottomOf="@+id/txtLayoutName" />
app:layout_constraintStart_toStartOf="@+id/header_personalise"
app:layout_constraintTop_toBottomOf="@+id/textinputlayout_name" />
<TextView
android:id="@+id/txtJustnice"
android:id="@+id/text_greeting_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/greeting_desc"
android:textColor="@color/colorHint"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="@+id/txtGreeting"
app:layout_constraintTop_toBottomOf="@+id/txtGreeting" />
app:layout_constraintStart_toStartOf="@+id/text_greeting_title"
app:layout_constraintTop_toBottomOf="@+id/text_greeting_title" />
<Switch
android:id="@+id/switchDisableGreeting"
android:id="@+id/switch_greeting"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="16dp"
android:gravity="end|center"
app:layout_constraintBottom_toBottomOf="@+id/txtJustnice"
app:layout_constraintBottom_toBottomOf="@+id/text_greeting_desc"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/txtGreeting"
app:layout_constraintTop_toTopOf="@+id/txtGreeting" />
app:layout_constraintStart_toStartOf="@+id/text_greeting_title"
app:layout_constraintTop_toTopOf="@+id/text_greeting_title" />
<com.google.android.material.textfield.TextInputLayout android:id="@+id/darkModeDropDown"
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textinputlayout_dark_mode"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
@@ -119,10 +120,10 @@
android:layout_marginEnd="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/switchDisableGreeting">
app:layout_constraintTop_toBottomOf="@+id/switch_greeting">
<AutoCompleteTextView
android:id="@+id/darkModeDropDownText"
android:id="@+id/autocomplete_dark_mode"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"
@@ -133,30 +134,30 @@
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:id="@+id/txtCustomiseColours1"
android:id="@+id/text_customise_colours_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/customise_colours_title"
android:textColor="@color/colorText"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@+id/txtJustnice"
app:layout_constraintTop_toBottomOf="@+id/darkModeDropDown" />
app:layout_constraintStart_toStartOf="@+id/text_greeting_desc"
app:layout_constraintTop_toBottomOf="@+id/textinputlayout_dark_mode" />
<TextView
android:id="@+id/txtCustomiseColours2"
android:id="@+id/text_customise_colours_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/customise_colours_desc"
android:textColor="@color/colorHint"
android:textSize="12sp"
app:layout_constraintBottom_toTopOf="@+id/txtNotifications"
app:layout_constraintStart_toStartOf="@+id/txtCustomiseColours1"
app:layout_constraintTop_toBottomOf="@+id/txtCustomiseColours1" />
app:layout_constraintBottom_toTopOf="@+id/text_notifications_title"
app:layout_constraintStart_toStartOf="@+id/text_customise_colours_title"
app:layout_constraintTop_toBottomOf="@+id/text_customise_colours_title" />
<LinearLayout
android:id="@+id/btnCustomiseColours"
android:id="@+id/button_customise_colours"
style="@style/SelectableItemBackground"
android:layout_width="0dp"
android:layout_height="0dp"
@@ -165,24 +166,24 @@
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@+id/txtNotifications"
app:layout_constraintBottom_toTopOf="@+id/text_notifications_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/darkModeDropDown" />
app:layout_constraintTop_toBottomOf="@+id/textinputlayout_dark_mode" />
<TextView
android:id="@+id/txtNotifications"
android:id="@+id/text_notifications_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/enable_course_notifications_title"
android:textColor="@color/colorText"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@+id/txtCustomiseColours2"
app:layout_constraintTop_toBottomOf="@+id/txtCustomiseColours2" />
app:layout_constraintStart_toStartOf="@+id/text_customise_colours_desc"
app:layout_constraintTop_toBottomOf="@+id/text_customise_colours_desc" />
<TextView
android:id="@+id/txtNotifiedAbout"
android:id="@+id/text_notifications_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
@@ -190,47 +191,47 @@
android:textAlignment="textStart"
android:textColor="@color/colorHint"
android:textSize="12sp"
app:layout_constraintBottom_toTopOf="@+id/txtNoNotif1"
app:layout_constraintStart_toStartOf="@+id/txtNotifications"
app:layout_constraintTop_toBottomOf="@+id/txtNotifications" />
app:layout_constraintBottom_toTopOf="@+id/text_notifications_help_title"
app:layout_constraintStart_toStartOf="@+id/text_notifications_title"
app:layout_constraintTop_toBottomOf="@+id/text_notifications_title" />
<Switch
android:id="@+id/switchNotifications"
android:id="@+id/switch_notifications"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:gravity="end|center"
app:layout_constraintBottom_toTopOf="@+id/txtNoNotif1"
app:layout_constraintBottom_toTopOf="@+id/text_notifications_help_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/txtNotifications"
app:layout_constraintTop_toTopOf="@+id/txtNotifications" />
app:layout_constraintStart_toStartOf="@+id/text_notifications_title"
app:layout_constraintTop_toTopOf="@+id/text_notifications_title" />
<TextView
android:id="@+id/txtNoNotif1"
android:id="@+id/text_notifications_help_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/no_notifications_title"
android:textColor="@color/colorText"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@+id/txtNotifiedAbout"
app:layout_constraintTop_toBottomOf="@+id/txtNotifiedAbout" />
app:layout_constraintStart_toStartOf="@+id/text_notifications_desc"
app:layout_constraintTop_toBottomOf="@+id/text_notifications_desc" />
<TextView
android:id="@+id/txtNoNotif2"
android:id="@+id/text_notifications_help_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="@string/no_notifications_desc"
android:textColor="@color/colorHint"
android:textSize="12sp"
app:layout_constraintBottom_toTopOf="@+id/txtCustomiseRingtone"
app:layout_constraintStart_toStartOf="@+id/txtNoNotif1"
app:layout_constraintTop_toBottomOf="@+id/txtNoNotif1" />
app:layout_constraintBottom_toTopOf="@+id/text_customise_ringtone_title"
app:layout_constraintStart_toStartOf="@+id/text_notifications_help_title"
app:layout_constraintTop_toBottomOf="@+id/text_notifications_help_title" />
<LinearLayout
android:id="@+id/btnNoNotif"
android:id="@+id/button_notifications_help"
style="@style/SelectableItemBackground"
android:layout_width="0dp"
android:layout_height="0dp"
@@ -239,24 +240,24 @@
android:clickable="true"
android:focusable="true"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@+id/txtCustomiseRingtone"
app:layout_constraintBottom_toTopOf="@+id/text_customise_ringtone_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtNotifiedAbout" />
app:layout_constraintTop_toBottomOf="@+id/text_notifications_desc" />
<TextView
android:id="@+id/txtCustomiseRingtone"
android:id="@+id/text_customise_ringtone_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/pick_ringtone_title"
android:textColor="@color/colorText"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@+id/txtNotifiedAbout"
app:layout_constraintTop_toBottomOf="@+id/txtNoNotif2" />
app:layout_constraintStart_toStartOf="@+id/text_notifications_desc"
app:layout_constraintTop_toBottomOf="@+id/text_notifications_help_desc" />
<TextView
android:id="@+id/txtCustomiseRingtone2"
android:id="@+id/text_customise_ringtone_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
@@ -264,11 +265,11 @@
android:textColor="@color/colorHint"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@+id/txtCustomiseRingtone"
app:layout_constraintTop_toBottomOf="@+id/txtCustomiseRingtone" />
app:layout_constraintStart_toStartOf="@+id/text_customise_ringtone_title"
app:layout_constraintTop_toBottomOf="@+id/text_customise_ringtone_title" />
<LinearLayout
android:id="@+id/btnCustomiseRingtone"
android:id="@+id/button_customise_ringtone"
style="@style/SelectableItemBackground"
android:layout_width="0dp"
android:layout_height="0dp"
@@ -280,7 +281,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtNoNotif2" />
app:layout_constraintTop_toBottomOf="@+id/text_notifications_help_desc" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -302,7 +303,7 @@
android:layout_height="wrap_content">
<TextView
android:id="@+id/txtFilter"
android:id="@+id/header_filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
@@ -313,7 +314,7 @@
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/txtLayoutClasses"
android:id="@+id/textinputlayout_group"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
app:boxStrokeColor="@color/colorAccent"
app:boxStrokeWidth="1dp"
@@ -324,13 +325,13 @@
android:layout_marginEnd="8dp"
android:hint="@string/grade"
android:textColorHint="@color/colorHint"
app:layout_constraintEnd_toStartOf="@+id/chipHelpClasses"
app:layout_constraintEnd_toStartOf="@+id/button_group_help"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtFilter"
app:layout_constraintTop_toBottomOf="@+id/header_filter"
android:importantForAutofill="no">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/txtClasses"
android:id="@+id/edittext_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
@@ -345,19 +346,19 @@
</com.google.android.material.textfield.TextInputLayout>
<ImageButton
android:id="@+id/chipHelpClasses"
android:id="@+id/button_group_help"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:src="@drawable/ic_qmark"
android:tint="@color/colorText"
android:backgroundTint="@android:color/transparent"
app:layout_constraintBottom_toBottomOf="@+id/txtLayoutClasses"
app:layout_constraintBottom_toBottomOf="@+id/textinputlayout_group"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/txtLayoutClasses" />
app:layout_constraintTop_toTopOf="@+id/textinputlayout_group" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/txtLayoutCourses"
android:id="@+id/textinputlayout_courses"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
@@ -368,12 +369,12 @@
android:textColorHint="@color/colorHint"
app:boxStrokeColor="@color/colorAccent"
app:boxStrokeWidth="1dp"
app:layout_constraintStart_toStartOf="@+id/txtLayoutClasses"
app:layout_constraintTop_toBottomOf="@+id/txtLayoutClasses"
app:layout_constraintEnd_toStartOf="@+id/chipHelpCourses">
app:layout_constraintStart_toStartOf="@+id/textinputlayout_group"
app:layout_constraintTop_toBottomOf="@+id/textinputlayout_group"
app:layout_constraintEnd_toStartOf="@+id/button_courses_help">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/txtCourses"
android:id="@+id/edittext_courses"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
@@ -388,18 +389,19 @@
</com.google.android.material.textfield.TextInputLayout>
<ImageButton
android:id="@+id/chipHelpCourses"
android:id="@+id/button_courses_help"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:src="@drawable/ic_qmark"
android:tint="@color/colorText"
android:backgroundTint="@android:color/transparent"
app:layout_constraintBottom_toBottomOf="@+id/txtLayoutCourses"
app:layout_constraintBottom_toBottomOf="@+id/textinputlayout_courses"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/txtLayoutCourses" />
app:layout_constraintTop_toTopOf="@+id/textinputlayout_courses" />
<com.google.android.material.textfield.TextInputLayout android:id="@+id/order_drop_down"
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/textinputlayout_order"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
@@ -409,11 +411,11 @@
android:layout_marginBottom="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/chip_help_ordering"
app:layout_constraintTop_toBottomOf="@+id/txtLayoutCourses">
app:layout_constraintEnd_toStartOf="@+id/button_order_help"
app:layout_constraintTop_toBottomOf="@+id/textinputlayout_courses">
<AutoCompleteTextView
android:id="@+id/order_drop_down_text"
android:id="@+id/autocomplete_order"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"
@@ -424,16 +426,16 @@
</com.google.android.material.textfield.TextInputLayout>
<ImageButton
android:id="@+id/chip_help_ordering"
android:id="@+id/button_order_help"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:src="@drawable/ic_qmark"
android:tint="@color/colorText"
android:backgroundTint="@android:color/transparent"
app:layout_constraintBottom_toBottomOf="@+id/order_drop_down"
app:layout_constraintBottom_toBottomOf="@+id/textinputlayout_order"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/order_drop_down" />
app:layout_constraintTop_toTopOf="@+id/textinputlayout_order" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -455,7 +457,7 @@
android:layout_height="wrap_content">
<TextView
android:id="@+id/txtMisc"
android:id="@+id/header_miscellaneous"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
@@ -466,94 +468,94 @@
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/txtPersonalised"
android:id="@+id/text_personalised_plan_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/default_plan_title"
android:textColor="@color/colorText"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@+id/txtMisc"
app:layout_constraintTop_toBottomOf="@+id/txtMisc" />
app:layout_constraintStart_toStartOf="@+id/header_miscellaneous"
app:layout_constraintTop_toBottomOf="@+id/header_miscellaneous" />
<TextView
android:id="@+id/txtDefaultsTo"
android:id="@+id/text_personalised_plan_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/default_plan_desc"
android:textColor="@color/colorHint"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="@+id/txtPersonalised"
app:layout_constraintTop_toBottomOf="@+id/txtPersonalised" />
app:layout_constraintStart_toStartOf="@+id/text_personalised_plan_title"
app:layout_constraintTop_toBottomOf="@+id/text_personalised_plan_title" />
<Switch
android:id="@+id/switchDefaultPlan"
android:id="@+id/switch_personalised_plan"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="16dp"
android:gravity="end|center"
app:layout_constraintBottom_toBottomOf="@+id/txtDefaultsTo"
app:layout_constraintBottom_toBottomOf="@+id/text_personalised_plan_desc"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/txtPersonalised"
app:layout_constraintTop_toTopOf="@+id/txtPersonalised"/>
app:layout_constraintStart_toStartOf="@+id/text_personalised_plan_title"
app:layout_constraintTop_toTopOf="@+id/text_personalised_plan_title"/>
<TextView
android:id="@+id/txtAutoRefresh"
android:id="@+id/text_auto_refresh_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/auto_refresh_title"
android:textColor="@color/colorText"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@+id/txtDefaultsTo"
app:layout_constraintTop_toBottomOf="@+id/txtDefaultsTo" />
app:layout_constraintStart_toStartOf="@+id/text_personalised_plan_desc"
app:layout_constraintTop_toBottomOf="@+id/text_personalised_plan_desc" />
<TextView
android:id="@+id/txtAutoRefreshTwo"
android:id="@+id/text_auto_refresh_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/auto_refresh_desc"
android:textColor="@color/colorHint"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="@+id/txtAutoRefresh"
app:layout_constraintTop_toBottomOf="@+id/txtAutoRefresh" />
app:layout_constraintStart_toStartOf="@+id/text_auto_refresh_title"
app:layout_constraintTop_toBottomOf="@+id/text_auto_refresh_title" />
<Switch
android:id="@+id/switchAutoRefresh"
android:id="@+id/switch_auto_refresh"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="16dp"
android:gravity="end|center"
app:layout_constraintBottom_toBottomOf="@+id/txtAutoRefreshTwo"
app:layout_constraintBottom_toBottomOf="@+id/text_auto_refresh_desc"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/txtAutoRefresh"
app:layout_constraintTop_toTopOf="@+id/txtAutoRefresh"/>
app:layout_constraintStart_toStartOf="@+id/text_auto_refresh_title"
app:layout_constraintTop_toTopOf="@+id/text_auto_refresh_title"/>
<TextView
android:id="@+id/txtForceRefresh"
android:id="@+id/text_forced_refresh_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/force_refresh_title"
android:textColor="@color/colorText"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@+id/txtAutoRefreshTwo"
app:layout_constraintTop_toBottomOf="@+id/txtAutoRefreshTwo" />
app:layout_constraintStart_toStartOf="@+id/text_auto_refresh_desc"
app:layout_constraintTop_toBottomOf="@+id/text_auto_refresh_desc" />
<TextView
android:id="@+id/txtForceRefresh2"
android:id="@+id/text_forced_refresh_desc"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/force_refresh_desc"
android:textColor="@color/colorHint"
android:textSize="12sp"
android:layout_marginEnd="16dp"
app:layout_constraintStart_toStartOf="@+id/txtForceRefresh"
app:layout_constraintStart_toStartOf="@+id/text_forced_refresh_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtForceRefresh" />
app:layout_constraintTop_toBottomOf="@+id/text_forced_refresh_title" />
<LinearLayout
android:id="@+id/btnForceRefresh"
android:id="@+id/button_forced_refresh"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="8dp"
@@ -562,34 +564,34 @@
android:focusable="true"
style="@style/SelectableItemBackground"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@+id/txtVisitWeb"
app:layout_constraintBottom_toTopOf="@+id/text_visit_website_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtAutoRefreshTwo" />
app:layout_constraintTop_toBottomOf="@+id/text_auto_refresh_desc" />
<TextView
android:id="@+id/txtVisitWeb"
android:id="@+id/text_visit_website_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/visit_website_title"
android:textColor="@color/colorText"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@+id/txtForceRefresh2"
app:layout_constraintTop_toBottomOf="@+id/txtForceRefresh2" />
app:layout_constraintStart_toStartOf="@+id/text_forced_refresh_desc"
app:layout_constraintTop_toBottomOf="@+id/text_forced_refresh_desc" />
<TextView
android:id="@+id/txtWeb"
android:id="@+id/text_visit_website_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/visit_website_desc"
android:textColor="@color/colorHint"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="@+id/txtForceRefresh"
app:layout_constraintTop_toBottomOf="@+id/txtVisitWeb" />
app:layout_constraintStart_toStartOf="@+id/text_forced_refresh_title"
app:layout_constraintTop_toBottomOf="@+id/text_visit_website_title" />
<LinearLayout
android:id="@+id/btnWebsite"
android:id="@+id/button_visit_website"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="8dp"
@@ -598,35 +600,35 @@
android:focusable="true"
style="@style/SelectableItemBackground"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="@+id/txtWeb"
app:layout_constraintBottom_toTopOf="@+id/txtLicences"
app:layout_constraintBottom_toBottomOf="@+id/text_visit_website_desc"
app:layout_constraintBottom_toTopOf="@+id/text_licences_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtForceRefresh2" />
app:layout_constraintTop_toBottomOf="@+id/text_forced_refresh_desc" />
<TextView
android:id="@+id/txtLicences"
android:id="@+id/text_licences_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/licences_title"
android:textColor="@color/colorText"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@+id/txtWeb"
app:layout_constraintTop_toBottomOf="@+id/txtWeb" />
app:layout_constraintStart_toStartOf="@+id/text_visit_website_desc"
app:layout_constraintTop_toBottomOf="@+id/text_visit_website_desc" />
<TextView
android:id="@+id/txtWhatittook"
android:id="@+id/text_licences_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/licences_desc"
android:textColor="@color/colorHint"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="@+id/txtLicences"
app:layout_constraintTop_toBottomOf="@+id/txtLicences" />
app:layout_constraintStart_toStartOf="@+id/text_licences_title"
app:layout_constraintTop_toBottomOf="@+id/text_licences_title" />
<LinearLayout
android:id="@+id/btnLicences"
android:id="@+id/button_licences"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="8dp"
@@ -635,36 +637,36 @@
android:focusable="true"
style="@style/SelectableItemBackground"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@+id/txtVersion"
app:layout_constraintBottom_toTopOf="@+id/text_app_version_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtWeb" />
app:layout_constraintTop_toBottomOf="@+id/text_visit_website_desc" />
<TextView
android:id="@+id/txtVersion"
android:id="@+id/text_app_version_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/version"
android:textColor="@color/colorText"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@+id/txtWhatittook"
app:layout_constraintTop_toBottomOf="@+id/txtWhatittook" />
app:layout_constraintStart_toStartOf="@+id/text_licences_desc"
app:layout_constraintTop_toBottomOf="@+id/text_licences_desc" />
<TextView
android:id="@+id/txtVersionTwo"
android:id="@+id/text_app_version_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:textColor="@color/colorHint"
android:textSize="12sp"
android:fontFeatureSettings="tnum"
app:layout_constraintStart_toStartOf="@+id/txtVersion"
app:layout_constraintTop_toBottomOf="@+id/txtVersion"
app:layout_constraintStart_toStartOf="@+id/text_app_version_title"
app:layout_constraintTop_toBottomOf="@+id/text_app_version_title"
app:layout_constraintBottom_toBottomOf="parent"/>
<LinearLayout
android:id="@+id/btnVersion"
android:id="@+id/button_version"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="8dp"
@@ -677,7 +679,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/txtWhatittook" />
app:layout_constraintTop_toBottomOf="@+id/text_licences_desc" />
</androidx.constraintlayout.widget.ConstraintLayout>
+5 -13
View File
@@ -17,14 +17,13 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:layout_margin="16dp">
<TextView
android:id="@+id/group"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toStartOf="@+id/date"
app:layout_constraintStart_toStartOf="parent"
@@ -36,8 +35,8 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:gravity="start|center_vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/group"
@@ -70,8 +69,7 @@
android:id="@+id/teacher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorText"
android:layout_marginEnd="8dp"/>
android:textColor="@color/colorText"/>
</LinearLayout>
@@ -79,10 +77,8 @@
android:id="@+id/additional"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="16dp"
android:textColor="@color/colorText"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/room"
@@ -93,8 +89,6 @@
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:textAlignment="textEnd"
android:textColor="@color/colorText"
app:layout_constraintEnd_toEndOf="parent"
@@ -106,7 +100,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:textAlignment="textEnd"
android:textColor="@color/colorText"
app:layout_constraintEnd_toEndOf="parent"
@@ -118,11 +111,10 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="16dp"
android:textAlignment="textEnd"
android:textColor="@color/colorText"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/time"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/time"
app:layout_constraintWidth_max="200dp" />
+2 -2
View File
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/pullToRefresh"
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/linear_food"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/layout_animation_fall_down"
+9 -24
View File
@@ -15,16 +15,17 @@
android:layout_marginBottom="3dp"
app:cardElevation="2dp">
<androidx.constraintlayout.widget.ConstraintLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_margin="16dp">
<ImageView
android:id="@+id/item_image"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_margin="16dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:tint="@color/colorText"
app:layout_constraintBottom_toBottomOf="@+id/item_text"
app:layout_constraintStart_toStartOf="parent"
@@ -32,27 +33,11 @@
<TextView
android:id="@+id/item_text"
android:layout_width="0dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="16dp"
android:textAlignment="viewStart"
android:textColor="@color/colorText"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/item_image"
app:layout_constraintTop_toTopOf="parent" />
android:layout_gravity="center_vertical"
android:textColor="@color/colorText"/>
<TextView
android:id="@+id/item_text_no_lang"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
+5 -5
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/pullToRefresh"
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
@@ -13,13 +13,13 @@
<LinearLayout
android:orientation="vertical"
android:id="@+id/linearsmiley"
android:id="@+id/empty_plan_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutAnimation="@anim/layout_animation_fall_down">
<TextView
android:id="@+id/smileydown"
android:id="@+id/empty_plan_emoticon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=":("
@@ -30,7 +30,7 @@
tools:ignore="HardcodedText,SpUsage" />
<TextView
android:id="@+id/smileydowntext"
android:id="@+id/empty_plan_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/no_personal_substitutions"
@@ -43,7 +43,7 @@
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/linearRecycler"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/layout_animation_fall_down"
+1 -1
View File
@@ -10,7 +10,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath 'com.android.tools.build:gradle:3.6.0-beta01'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.2'
classpath 'io.fabric.tools:gradle:1.31.0'
+1 -1
View File
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip