ProfileActivity.kt 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. package com.sirekanyan.knigopis.feature.profile
  2. import android.content.Context
  3. import android.content.Intent
  4. import android.os.Bundle
  5. import android.support.v7.widget.Toolbar
  6. import android.view.MenuItem
  7. import android.view.animation.AccelerateInterpolator
  8. import android.view.inputmethod.EditorInfo
  9. import com.sirekanyan.knigopis.R
  10. import com.sirekanyan.knigopis.common.BaseActivity
  11. import com.sirekanyan.knigopis.common.extensions.*
  12. import com.sirekanyan.knigopis.common.functions.createTextShareIntent
  13. import com.sirekanyan.knigopis.common.functions.logError
  14. import com.sirekanyan.knigopis.model.BookDataModel
  15. import com.sirekanyan.knigopis.model.dto.Profile
  16. import com.sirekanyan.knigopis.model.dto.User
  17. import io.reactivex.Observable
  18. import io.reactivex.rxkotlin.Observables
  19. import kotlinx.android.synthetic.main.profile_activity.*
  20. import java.util.*
  21. import java.util.concurrent.TimeUnit
  22. fun Context.createProfileIntent() = Intent(this, ProfileActivity::class.java)
  23. class ProfileActivity : BaseActivity() {
  24. private val api by lazy { app.endpoint }
  25. private val bookRepository by lazy { app.bookRepository }
  26. private val auth by lazy { app.authRepository }
  27. private val todoList = Stack<BookDataModel>()
  28. private val doingList = Stack<BookDataModel>()
  29. private val doneList = Stack<BookDataModel>()
  30. private var userId: String? = null
  31. private var profileUrl: String? = null
  32. private lateinit var editOption: MenuItem
  33. override fun onCreate(savedInstanceState: Bundle?) {
  34. super.onCreate(savedInstanceState)
  35. setContentView(R.layout.profile_activity)
  36. initToolbar(profileToolbar)
  37. profileTodoCount.text = getString(R.string.profile_text_todo, 0)
  38. profileDoingCount.text = getString(R.string.profile_text_doing, 0)
  39. profileDoneCount.text = getString(R.string.profile_text_done, 0)
  40. mapOf(
  41. profileTodoCount to todoList,
  42. profileDoingCount to doingList,
  43. profileDoneCount to doneList
  44. ).forEach { view, list ->
  45. view.setOnClickListener {
  46. if (!list.isEmpty()) {
  47. showFooterBook(list.pop())
  48. }
  49. }
  50. }
  51. profileNicknameEditText.setOnEditorActionListener { _, actionId, _ ->
  52. when (actionId) {
  53. EditorInfo.IME_ACTION_DONE -> {
  54. updateNicknameOrExitEditMode()
  55. true
  56. }
  57. else -> false
  58. }
  59. }
  60. }
  61. private fun showFooterBook(book: BookDataModel) {
  62. randomProfileBook.alpha = 1f
  63. randomProfileBook.text = getString(
  64. R.string.profile_text_random,
  65. resources.getTitleString(book.title),
  66. book.priority
  67. )
  68. randomProfileBook.animate()
  69. .setInterpolator(AccelerateInterpolator())
  70. .setDuration(1000)
  71. .alpha(0f)
  72. }
  73. override fun onStart() {
  74. super.onStart()
  75. refreshProfile()
  76. refreshCounters()
  77. }
  78. private fun refreshProfile() {
  79. api.getProfile(auth.getAccessToken()).io2main()
  80. .bind(::onRefreshProfile) {
  81. logError("cannot get profile", it)
  82. }
  83. }
  84. private fun onRefreshProfile(user: User) {
  85. userId = user.id
  86. profileUrl = user.fixedProfile
  87. profileNickname.text = user.nickname.orEmpty()
  88. profileAvatar.setCircleImage(user.photo)
  89. editOption.isVisible = true
  90. }
  91. private fun refreshCounters() {
  92. bookRepository.findCached()
  93. .toSingle(listOf())
  94. .map { it.filterIsInstance<BookDataModel>() }
  95. .map { it.shuffled() }
  96. .flatMapObservable {
  97. Observables.zip(
  98. Observable.fromIterable(it),
  99. Observable.interval(5, TimeUnit.MILLISECONDS)
  100. )
  101. }
  102. .io2main()
  103. .doOnSubscribe {
  104. doneList.clear()
  105. doingList.clear()
  106. todoList.clear()
  107. }
  108. .bind({ (book) ->
  109. addBookToList(book)
  110. }, {
  111. logError("cannot get cached books", it)
  112. })
  113. }
  114. @Suppress("USELESS_CAST")
  115. private fun addBookToList(book: BookDataModel) {
  116. when {
  117. book.isFinished -> {
  118. doneList.push(book)
  119. profileDoneCount.text =
  120. getString(R.string.profile_text_done, doneList.size as Int)
  121. }
  122. book.priority > 0 -> {
  123. doingList.push(book)
  124. profileDoingCount.text =
  125. getString(R.string.profile_text_doing, doingList.size as Int)
  126. }
  127. else -> {
  128. todoList.push(book)
  129. profileTodoCount.text =
  130. getString(R.string.profile_text_todo, todoList.size as Int)
  131. }
  132. }
  133. }
  134. private fun updateNicknameOrExitEditMode() {
  135. if (profileNickname.text.toString() == profileNicknameEditText.text.toString()) {
  136. quitEditMode()
  137. } else {
  138. updateNickname()
  139. }
  140. }
  141. private fun updateNickname() {
  142. val id = userId ?: return
  143. api.updateProfile(
  144. id,
  145. auth.getAccessToken(),
  146. Profile(
  147. profileNicknameEditText.text.toString(),
  148. profileUrl.orEmpty()
  149. )
  150. ).io2main()
  151. .bind({
  152. profileNickname.text = profileNicknameEditText.text
  153. quitEditMode()
  154. refreshProfile()
  155. }, {
  156. toast(R.string.profile_error_save)
  157. logError("cannot update profile", it)
  158. })
  159. }
  160. private fun initToolbar(toolbar: Toolbar) {
  161. toolbar.setNavigationIcon(R.drawable.ic_arrow_back)
  162. toolbar.setNavigationOnClickListener { finish() }
  163. toolbar.inflateMenu(R.menu.profile_menu)
  164. toolbar.setOnMenuItemClickListener {
  165. when (it.itemId) {
  166. R.id.option_edit_profile -> {
  167. if (isEditMode) {
  168. updateNicknameOrExitEditMode()
  169. } else {
  170. enterEditMode()
  171. val nickname = profileNickname.text
  172. profileNicknameEditText.setText(nickname)
  173. profileNicknameEditText.setSelection(nickname.length, nickname.length)
  174. }
  175. true
  176. }
  177. R.id.option_share_profile -> {
  178. profileUrl?.let {
  179. startActivity(
  180. createTextShareIntent(it, getString(R.string.profile_title_share))
  181. )
  182. }
  183. true
  184. }
  185. R.id.option_logout_profile -> {
  186. auth.logout()
  187. finish()
  188. true
  189. }
  190. else -> false
  191. }
  192. }
  193. editOption = toolbar.menu.findItem(R.id.option_edit_profile)
  194. }
  195. override fun onBackPressed() {
  196. if (profileNickname.isVisible) {
  197. super.onBackPressed()
  198. } else {
  199. quitEditMode()
  200. }
  201. }
  202. private fun enterEditMode() {
  203. editOption.setIcon(R.drawable.ic_done)
  204. editOption.setTitle(R.string.profile_option_save)
  205. topProfileSpace.hideNow()
  206. profileNicknameSwitcher.displayedChild = 1
  207. showKeyboard(profileNicknameEditText)
  208. }
  209. private fun quitEditMode() {
  210. editOption.setIcon(R.drawable.ic_edit)
  211. editOption.setTitle(R.string.profile_option_edit)
  212. hideKeyboard()
  213. topProfileSpace.showNow()
  214. profileNicknameSwitcher.displayedChild = 0
  215. }
  216. private val isEditMode
  217. get() = profileNicknameSwitcher.displayedChild == 1
  218. }