Added drop down menu in the settings to switch between app-specific and website original sorting procedures

This commit is contained in:
Deniz Düzgören
2019-09-24 09:32:25 +02:00
parent 1882034ec5
commit 87d4f11cba
13 changed files with 114 additions and 24 deletions
@@ -58,6 +58,7 @@ internal class DataFetcher(isPlan: Boolean, isMenu: Boolean, isJobService: Boole
private var currentFoodTime = "" private var currentFoodTime = ""
private var substUrl = "https://djd4rkn355.github.io/avh_substitutions.html" private var substUrl = "https://djd4rkn355.github.io/avh_substitutions.html"
private var foodUrl = "https://djd4rkn355.github.io/food.html" private var foodUrl = "https://djd4rkn355.github.io/food.html"
private var websitePriority = 0
override fun doInBackground(vararg params: Void?): Void? { override fun doInBackground(vararg params: Void?): Void? {
try { try {
@@ -181,10 +182,12 @@ internal class DataFetcher(isPlan: Boolean, isMenu: Boolean, isJobService: Boole
teacher = cols[6].text(), teacher = cols[6].text(),
type = cols[7].text(), type = cols[7].text(),
priority = HelperFunctions.assignRanking(group, date.substring(0, 3) == "psa"), priority = HelperFunctions.assignRanking(group, date.substring(0, 3) == "psa"),
date_priority = HelperFunctions.assignDatePriority(date) date_priority = HelperFunctions.assignDatePriority(date),
website_priority = websitePriority
) )
substArray.add(subst) substArray.add(subst)
substRepo.insert(subst) substRepo.insert(subst)
websitePriority += 1
} }
var countOfNotificationItems = 0 var countOfNotificationItems = 0
var countOfMoreNotificationItems = 0 var countOfMoreNotificationItems = 0
@@ -8,8 +8,11 @@ import com.denizd.substitutionplan.models.Substitution
@Dao @Dao
internal interface SubstDao { internal interface SubstDao {
@get:Query("SELECT * FROM subst_table ORDER BY date_priority ASC, priority ASC, `group` ASC, time ASC") @get:Query("SELECT * FROM subst_table ORDER BY date_priority ASC, date ASC, priority ASC, `group` ASC, time ASC")
val allSubstitutions: LiveData<List<Substitution>> val allSubstitutionsSorted: LiveData<List<Substitution>>
@get:Query("SELECT * FROM subst_table ORDER BY website_priority ASC")
val allSubstitutionsOriginal: LiveData<List<Substitution>>
@Insert @Insert
fun insertSubst(substitution: Substitution) fun insertSubst(substitution: Substitution)
@@ -9,7 +9,7 @@ import androidx.sqlite.db.SupportSQLiteDatabase
import com.denizd.substitutionplan.models.Food import com.denizd.substitutionplan.models.Food
import com.denizd.substitutionplan.models.Substitution import com.denizd.substitutionplan.models.Substitution
@Database(entities = [Substitution::class, Food::class], version = 8, exportSchema = false) @Database(entities = [Substitution::class, Food::class], version = 9, exportSchema = false)
internal abstract class SubstDatabase : RoomDatabase() { internal abstract class SubstDatabase : RoomDatabase() {
abstract fun substDao(): SubstDao abstract fun substDao(): SubstDao
@@ -32,6 +32,11 @@ internal abstract class SubstDatabase : RoomDatabase() {
database.execSQL("ALTER TABLE subst_table ADD COLUMN date_priority INTEGER NOT NULL DEFAULT 0") database.execSQL("ALTER TABLE subst_table ADD COLUMN date_priority INTEGER NOT NULL DEFAULT 0")
} }
} }
private val addWebsitePriorityColumn = object : Migration(8, 9) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE subst_table ADD COLUMN website_priority INTEGER NOT NULL DEFAULT 0")
}
}
fun getInstance(context: Context): SubstDatabase? { fun getInstance(context: Context): SubstDatabase? {
if (instance == null) { if (instance == null) {
@@ -39,7 +44,7 @@ internal abstract class SubstDatabase : RoomDatabase() {
instance = Room.databaseBuilder(context.applicationContext, instance = Room.databaseBuilder(context.applicationContext,
SubstDatabase::class.java, SubstDatabase::class.java,
"subst_database") "subst_database")
.addMigrations(addTeacherColumn, addTypeColumn, addDatePriorityColumn) .addMigrations(addTeacherColumn, addTypeColumn, addDatePriorityColumn, addWebsitePriorityColumn)
.fallbackToDestructiveMigration() .fallbackToDestructiveMigration()
.build() .build()
} }
@@ -9,13 +9,15 @@ import com.denizd.substitutionplan.models.Substitution
internal class SubstRepository(application: Application) { internal class SubstRepository(application: Application) {
private val substDao: SubstDao? private val substDao: SubstDao?
val allSubstitutions: LiveData<List<Substitution>>? val allSubstitutionsSorted: LiveData<List<Substitution>>?
val allSubstitutionsOriginal: LiveData<List<Substitution>>?
init { init {
val database = val database =
SubstDatabase.getInstance(application) SubstDatabase.getInstance(application)
substDao = database?.substDao() substDao = database?.substDao()
allSubstitutions = substDao?.allSubstitutions allSubstitutionsSorted = substDao?.allSubstitutionsSorted
allSubstitutionsOriginal = substDao?.allSubstitutionsOriginal
} }
fun insert(substitution: Substitution) { fun insert(substitution: Substitution) {
@@ -11,11 +11,13 @@ import com.denizd.substitutionplan.models.Substitution
internal class SubstViewModel(application: Application) : AndroidViewModel(application) { internal class SubstViewModel(application: Application) : AndroidViewModel(application) {
private val repository: SubstRepository = SubstRepository(application) private val repository: SubstRepository = SubstRepository(application)
val allSubstitutions: LiveData<List<Substitution>>? val allSubstitutionsSorted: LiveData<List<Substitution>>?
val allSubstitutionsOriginal: LiveData<List<Substitution>>?
private val app = application private val app = application
init { init {
allSubstitutions = repository.allSubstitutions allSubstitutionsSorted = repository.allSubstitutionsSorted
allSubstitutionsOriginal = repository.allSubstitutionsOriginal
} }
fun refresh(swipeRefreshLayout: SwipeRefreshLayout, rootView: View, refreshMenu: Boolean) { fun refresh(swipeRefreshLayout: SwipeRefreshLayout, rootView: View, refreshMenu: Boolean) {
@@ -10,7 +10,7 @@ internal class GeneralPlanFragment : PlanFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
substViewModel.allSubstitutions?.observe(this, Observer<List<Substitution>> { substitutions -> substitutionPlan?.observe(this, Observer<List<Substitution>> { substitutions ->
mAdapter.setSubst(substitutions) mAdapter.setSubst(substitutions)
recyclerView.scheduleLayoutAnimation() recyclerView.scheduleLayoutAnimation()
}) })
@@ -19,7 +19,7 @@ internal class PersonalPlanFragment : PlanFragment() {
val coursePreference = prefs.getString("courses", "") ?: "" val coursePreference = prefs.getString("courses", "") ?: ""
val classPreference = prefs.getString("classes", "") ?: "" val classPreference = prefs.getString("classes", "") ?: ""
substViewModel.allSubstitutions?.observe(this, Observer<List<Substitution>> { substitutions -> substitutionPlan?.observe(this, Observer<List<Substitution>> { substitutions ->
planCardList.clear() planCardList.clear()
personalPlanEmptyEmoticon.visibility = View.GONE personalPlanEmptyEmoticon.visibility = View.GONE
personalPlanEmptyText.visibility = View.GONE personalPlanEmptyText.visibility = View.GONE
@@ -10,6 +10,7 @@ import android.view.View
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModelProviders import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@@ -21,18 +22,19 @@ import com.denizd.substitutionplan.models.Substitution
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
internal open class PlanFragment : Fragment(R.layout.plan) { internal open class PlanFragment : Fragment(R.layout.plan) {
lateinit var recyclerView: RecyclerView internal lateinit var recyclerView: RecyclerView
lateinit var mAdapter: SubstitutionAdapter internal lateinit var mAdapter: SubstitutionAdapter
var planCardList = ArrayList<Substitution>() internal var planCardList = ArrayList<Substitution>()
lateinit var substViewModel: SubstViewModel private lateinit var substViewModel: SubstViewModel
private lateinit var mContext: Context private lateinit var mContext: Context
lateinit var prefs: SharedPreferences internal lateinit var prefs: SharedPreferences
lateinit var personalPlanEmptyEmoticon: TextView internal lateinit var personalPlanEmptyEmoticon: TextView
lateinit var personalPlanEmptyText: TextView internal lateinit var personalPlanEmptyText: TextView
lateinit var personalPlanEmptyLayout: LinearLayout internal lateinit var personalPlanEmptyLayout: LinearLayout
var isPersonalPlanEmpty: Boolean = true internal var isPersonalPlanEmpty: Boolean = true
val handler = Handler() internal val handler = Handler()
internal var substitutionPlan: LiveData<List<Substitution>>? = null
override fun onAttach(context: Context) { override fun onAttach(context: Context) {
super.onAttach(context) super.onAttach(context)
@@ -48,6 +50,11 @@ internal open class PlanFragment : Fragment(R.layout.plan) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
substViewModel = ViewModelProviders.of(this).get(SubstViewModel::class.java) substViewModel = ViewModelProviders.of(this).get(SubstViewModel::class.java)
substitutionPlan = if (prefs.getBoolean("app_specific_sorting", true)) {
substViewModel.allSubstitutionsSorted
} else {
substViewModel.allSubstitutionsOriginal
}
val pullToRefresh = view.findViewById<SwipeRefreshLayout>(R.id.pullToRefresh) val pullToRefresh = view.findViewById<SwipeRefreshLayout>(R.id.pullToRefresh)
recyclerView = view.findViewById(R.id.linearRecycler) recyclerView = view.findViewById(R.id.linearRecycler)
@@ -86,6 +86,7 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl
autoRefreshSwitch.setOnCheckedChangeListener(this) autoRefreshSwitch.setOnCheckedChangeListener(this)
helpCoursesButton.setOnClickListener(this) helpCoursesButton.setOnClickListener(this)
helpGradeButton.setOnClickListener(this) helpGradeButton.setOnClickListener(this)
view.findViewById<ImageButton>(R.id.chip_help_ordering).setOnClickListener(this)
colourCustomisationButton.setOnClickListener(this) colourCustomisationButton.setOnClickListener(this)
view.findViewById<LinearLayout>(R.id.btnNoNotif).setOnClickListener(this) view.findViewById<LinearLayout>(R.id.btnNoNotif).setOnClickListener(this)
view.findViewById<LinearLayout>(R.id.btnCustomiseRingtone).setOnClickListener(this) view.findViewById<LinearLayout>(R.id.btnCustomiseRingtone).setOnClickListener(this)
@@ -148,6 +149,23 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl
} }
} }
val orderingDropDownText = view.findViewById<AutoCompleteTextView>(R.id.order_drop_down_text)
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, _ ->
prefs.edit().putBoolean("app_specific_sorting", position == 0).apply()
}
greetingSwitch.isChecked = prefs.getBoolean("greeting", true) greetingSwitch.isChecked = prefs.getBoolean("greeting", true)
notificationSwitch.isChecked = prefs.getBoolean("notif", false) notificationSwitch.isChecked = prefs.getBoolean("notif", false)
@@ -437,6 +455,7 @@ internal class SettingsFragment : Fragment(R.layout.content_settings), View.OnCl
R.id.chipHelpClasses -> createDialog(getString(R.string.grade_help_dialog_title), getString( R.id.chipHelpClasses -> createDialog(getString(R.string.grade_help_dialog_title), getString(
R.string.grade_help_dialog_text 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.btnCustomiseColours -> createColourDialog()
R.id.btnNoNotif -> createDialog(mContext.getString(R.string.no_notifications_title), mContext.getString(R.string.no_notifications_dialog_text)) 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.btnCustomiseRingtone -> createRingtoneDialog()
@@ -14,7 +14,8 @@ internal data class Substitution(
val teacher: String, val teacher: String,
val type: String, val type: String,
val priority: Int, val priority: Int,
val date_priority: Int val date_priority: Int,
val website_priority: Int
) { ) {
@PrimaryKey(autoGenerate = true) @PrimaryKey(autoGenerate = true)
+36 -2
View File
@@ -363,7 +363,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:hint="@string/courses" android:hint="@string/courses"
android:importantForAutofill="no" android:importantForAutofill="no"
android:textColorHint="@color/colorHint" android:textColorHint="@color/colorHint"
@@ -371,7 +370,6 @@
app:boxStrokeWidth="1dp" app:boxStrokeWidth="1dp"
app:layout_constraintStart_toStartOf="@+id/txtLayoutClasses" app:layout_constraintStart_toStartOf="@+id/txtLayoutClasses"
app:layout_constraintTop_toBottomOf="@+id/txtLayoutClasses" app:layout_constraintTop_toBottomOf="@+id/txtLayoutClasses"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/chipHelpCourses"> app:layout_constraintEnd_toStartOf="@+id/chipHelpCourses">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
@@ -401,6 +399,42 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/txtLayoutCourses" /> app:layout_constraintTop_toTopOf="@+id/txtLayoutCourses" />
<com.google.android.material.textfield.TextInputLayout android:id="@+id/order_drop_down"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
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">
<AutoCompleteTextView
android:id="@+id/order_drop_down_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:editable="false"
android:hint="@string/ordering_system_hint"
android:textColor="@color/colorText"
android:textSize="14sp"/>
</com.google.android.material.textfield.TextInputLayout>
<ImageButton
android:id="@+id/chip_help_ordering"
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_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/order_drop_down" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView> </androidx.cardview.widget.CardView>
+7
View File
@@ -157,4 +157,11 @@
<string name="logging_in">Einloggen…</string> <string name="logging_in">Einloggen…</string>
<string name="load_page_again">Lade Login-Seite erneut</string> <string name="load_page_again">Lade Login-Seite erneut</string>
<string name="logged_in">Du bist eingeloggt!</string> <string name="logged_in">Du bist eingeloggt!</string>
<string-array name="ordering_systems">
<item>App-spezifisch</item>
<item>Website-Original</item>
</string-array>
<string name="ordering_system_hint">Sortierweise</string>
<string name="ordering_systems_dialog_title">Informationen über Sortierweisen</string>
<string name="ordering_systems_dialog_text">Du kannst zwischen zwei Sortierweisen auswählen, welche die Reihenfolge der Einträge auf dem Vertretungsplan bestimmen.\n\nStandardmäßig ist \'App-spezifisch\' ausgewählt; dies bietet einen konsistenten Plan sortiert nach Klassen, dann nach Stunden.\n\n\'Website-Original\' bietet die Original-Reihenfolge der Website. Diese ist jedoch nicht konsistent, weswegen \'App-spezifisch\' standardmäßig ausgewählt ist.</string>
</resources> </resources>
+7
View File
@@ -169,4 +169,11 @@
<string name="logging_in">Logging in…</string> <string name="logging_in">Logging in…</string>
<string name="load_page_again">Load login page again</string> <string name="load_page_again">Load login page again</string>
<string name="logged_in">Login successful!</string> <string name="logged_in">Login successful!</string>
<string-array name="ordering_systems">
<item>App-specific</item>
<item>Website original</item>
</string-array>
<string name="ordering_system_hint">Ordering system</string>
<string name="ordering_systems_dialog_title">Information on ordering systems</string>
<string name="ordering_systems_dialog_text">You may pick between two ordering systems that dictate the order in which the items on the substitution plan will appear in.\n\nThe default \'app-specific\' is an algorithm implemented in this app that provides a consistently-sorted substitution plan ordered just like the substitution plan on the website used to; sorted by classes, then by time.\n\n\'Website original\' offers the items on the substitution plan just like they\'re presented on the school website, but since these are not guaranteed to be consistent, \'app-specific\' is picked by default.</string>
</resources> </resources>