TimetableFragment.kt 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. package com.ethosa.ktc.ui.fragments
  2. import android.annotation.SuppressLint
  3. import android.content.Context
  4. import android.content.SharedPreferences
  5. import android.os.Bundle
  6. import android.view.LayoutInflater
  7. import android.view.View
  8. import android.view.ViewGroup
  9. import androidx.recyclerview.widget.LinearLayoutManager
  10. import androidx.recyclerview.widget.RecyclerView
  11. import com.ethosa.ktc.college.CollegeApi
  12. import com.ethosa.ktc.college.CollegeCallback
  13. import com.ethosa.ktc.college.timetable.*
  14. import com.ethosa.ktc.databinding.FragmentTimetableBinding
  15. import com.ethosa.ktc.ui.adapters.BranchAdapter
  16. import com.ethosa.ktc.ui.adapters.CourseAdapter
  17. import com.ethosa.ktc.ui.adapters.TimetableAdapter
  18. import com.ethosa.ktc.utils.IOFragmentBackPressed
  19. import com.ethosa.ktc.utils.SpacingItemDecoration
  20. import com.google.gson.Gson
  21. import okhttp3.Call
  22. import okhttp3.Response
  23. /**
  24. * Provides working with KTC timetable.
  25. * Includes branches, courses with groups and timetable for any week.
  26. */
  27. class TimetableFragment : IOFragmentBackPressed() {
  28. private var _binding: FragmentTimetableBinding? = null
  29. private lateinit var itemDecoration: RecyclerView.ItemDecoration
  30. private lateinit var preferences: SharedPreferences
  31. private val college = CollegeApi()
  32. private val binding get() = _binding!!
  33. // 0 - branches, 1 - courses, 2 - timetable.
  34. private var state = 0
  35. var branch: Branch? = null
  36. var group: Group? = null
  37. var week: Int = 0
  38. companion object {
  39. const val STATE = "state"
  40. const val BRANCH = "branch"
  41. const val GROUP = "group"
  42. const val GROUP_TITLE = "group_title"
  43. const val WEEK = "week"
  44. }
  45. override fun onCreateView(
  46. inflater: LayoutInflater,
  47. container: ViewGroup?,
  48. savedInstanceState: Bundle?
  49. ): View {
  50. _binding = FragmentTimetableBinding.inflate(inflater, container, false)
  51. binding.timetable.layoutManager = LinearLayoutManager(context)
  52. itemDecoration = SpacingItemDecoration(0, 32)
  53. binding.timetable.addItemDecoration(itemDecoration)
  54. // Load state
  55. preferences = requireActivity().getSharedPreferences("com.ethosa.ktc", Context.MODE_PRIVATE)
  56. state = preferences.getInt(STATE, 0)
  57. branch = Branch(preferences.getInt(BRANCH, 0), "")
  58. group = Group(
  59. preferences.getInt(GROUP, 0),
  60. preferences.getString(GROUP_TITLE, "")!!
  61. )
  62. week = preferences.getInt(WEEK, 0)
  63. loadState()
  64. // Analog for back button
  65. binding.back.setOnClickListener {
  66. // back button disabled when state isn't 0
  67. binding.back.isEnabled = !onBackPressed()
  68. }
  69. // Next week
  70. binding.next.setOnClickListener {
  71. if (week < 57)
  72. changeWeek(1)
  73. }
  74. // previous week
  75. binding.previous.setOnClickListener {
  76. if (week > 1)
  77. changeWeek(-1)
  78. }
  79. return binding.root
  80. }
  81. /**
  82. * destroy bindings.
  83. */
  84. override fun onDestroyView() {
  85. super.onDestroyView()
  86. _binding = null
  87. }
  88. private fun changeWeek(i: Int) {
  89. // Provides week changing behavior.
  90. week += i
  91. binding.next.isEnabled = false
  92. binding.previous.isEnabled = false
  93. fetchTimetable(group!!.id, week)
  94. }
  95. private fun loadState() {
  96. // Fetches timetable from loaded state.
  97. when (state) {
  98. 0 -> fetchBranches()
  99. 1 -> fetchCourses(branch!!.id)
  100. 2 -> fetchTimetable(group!!.id)
  101. }
  102. }
  103. override fun onBackPressed(): Boolean {
  104. // Provides behavior on Back pressed.
  105. when (state) {
  106. 1 -> fetchBranches()
  107. 2 -> fetchCourses(branch!!.id)
  108. else -> return false
  109. }
  110. return true
  111. }
  112. private fun updateState(current: Int = 0) {
  113. // Updates fragment's state and saves it into SharedPreferences
  114. state = current
  115. preferences.edit().putInt(STATE, state).apply()
  116. }
  117. private fun updateTimetable(timetable: Week) {
  118. // Updates fragment's group and saves it into SharedPreferences
  119. preferences.edit().putInt(GROUP, group!!.id).apply()
  120. preferences.edit().putInt(WEEK, timetable.week_number).apply()
  121. preferences.edit().putString(GROUP_TITLE, group!!.title).apply()
  122. }
  123. /**
  124. * Fetches branches and shows it.
  125. */
  126. @Suppress("MemberVisibilityCanBePrivate")
  127. fun fetchBranches() {
  128. updateState()
  129. college.fetchBranches(object : CollegeCallback {
  130. override fun onResponse(call: Call, response: Response) {
  131. if (_binding == null) return
  132. // Parse JSON
  133. val json = response.body?.string()
  134. val branches = Gson().fromJson(json, Branches::class.java)
  135. requireActivity().runOnUiThread {
  136. binding.back.isEnabled = true
  137. binding.timetableToolbar.visibility = View.GONE
  138. binding.timetable.adapter = BranchAdapter(this@TimetableFragment, branches)
  139. }
  140. }
  141. })
  142. }
  143. /**
  144. * Fetches courses for specified branch.
  145. * @param branchId unique branch ID.
  146. */
  147. fun fetchCourses(branchId: Int) {
  148. updateState(1)
  149. college.fetchCourses(branchId, object : CollegeCallback {
  150. @SuppressLint("SetTextI18n")
  151. override fun onResponse(call: Call, response: Response) {
  152. if (_binding == null) return
  153. // Parse JSON
  154. val json = response.body?.string()
  155. val courses = Gson().fromJson(json, Courses::class.java)
  156. requireActivity().runOnUiThread {
  157. binding.back.isEnabled = true
  158. binding.timetableToolbar.visibility = View.VISIBLE
  159. binding.next.visibility = View.GONE
  160. binding.previous.visibility = View.GONE
  161. binding.timetableTitle.text = "Курсы"
  162. binding.timetable.adapter = CourseAdapter(this@TimetableFragment, courses)
  163. preferences.edit().putInt(BRANCH, branch!!.id).apply()
  164. }
  165. }
  166. })
  167. }
  168. /**
  169. * Fetches timetable for specified groupId.
  170. * @param groupId unique group ID.
  171. * @param week by default is current week.
  172. */
  173. fun fetchTimetable(groupId: Int, week: Int? = null) {
  174. updateState(2)
  175. college.fetchTimetable(groupId, object : CollegeCallback {
  176. @SuppressLint("SetTextI18n")
  177. override fun onResponse(call: Call, response: Response) {
  178. if (_binding == null) return
  179. // Parse JSON
  180. val json = response.body?.string()
  181. val timetable = Gson().fromJson(json, Week::class.java)
  182. this@TimetableFragment.week = timetable.week_number
  183. requireActivity().runOnUiThread {
  184. binding.back.isEnabled = true
  185. binding.next.isEnabled = true
  186. binding.previous.isEnabled = true
  187. binding.timetableTitle.text = "${group!!.title}\n${timetable.week_number} неделя"
  188. binding.timetableToolbar.visibility = View.VISIBLE
  189. binding.next.visibility = View.VISIBLE
  190. binding.previous.visibility = View.VISIBLE
  191. binding.timetable.adapter = TimetableAdapter(this@TimetableFragment, timetable)
  192. updateTimetable(timetable)
  193. }
  194. }
  195. }, week)
  196. }
  197. }