Skip to content

Commit

Permalink
Add observe extensions for Flow to reduce nesting
Browse files Browse the repository at this point in the history
  • Loading branch information
Goooler committed Mar 27, 2024
1 parent f029b7f commit 30f6b4b
Show file tree
Hide file tree
Showing 36 changed files with 712 additions and 799 deletions.
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ android {

kotlinOptions {
freeCompilerArgs = [
"-Xcontext-receivers",
"-Xno-param-assertions",
"-Xno-call-assertions",
"-Xno-receiver-assertions"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import android.widget.LinearLayout
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
Expand All @@ -40,13 +39,13 @@ import com.keylesspalace.tusky.util.Either
import com.keylesspalace.tusky.util.emojify
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.loadAvatar
import com.keylesspalace.tusky.util.observe
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.unsafeLazy
import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.viewmodel.AccountsInListViewModel
import com.keylesspalace.tusky.viewmodel.State
import javax.inject.Inject
import kotlinx.coroutines.launch

private typealias AccountInfo = Pair<TimelineAccount, Boolean>

Expand Down Expand Up @@ -104,17 +103,15 @@ class AccountsInListFragment : DialogFragment(), Injectable {
binding.accountsSearchRecycler.layoutManager = LinearLayoutManager(view.context)
binding.accountsSearchRecycler.adapter = searchAdapter

viewLifecycleOwner.lifecycleScope.launch {
viewModel.state.collect { state ->
adapter.submitList(state.accounts.asRightOrNull() ?: listOf())
viewModel.state.observe(viewLifecycleOwner) { state ->
adapter.submitList(state.accounts.asRightOrNull() ?: listOf())

when (state.accounts) {
is Either.Right -> binding.messageView.hide()
is Either.Left -> handleError(state.accounts.value)
}

setupSearchView(state)
when (state.accounts) {
is Either.Right -> binding.messageView.hide()
is Either.Left -> handleError(state.accounts.value)
}

setupSearchView(state)
}

binding.searchView.isSubmitButtonEnabled = true
Expand Down
170 changes: 80 additions & 90 deletions app/src/main/java/com/keylesspalace/tusky/EditProfileActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import com.keylesspalace.tusky.util.Error
import com.keylesspalace.tusky.util.Loading
import com.keylesspalace.tusky.util.Success
import com.keylesspalace.tusky.util.await
import com.keylesspalace.tusky.util.observe
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.viewmodel.EditProfileViewModel
Expand Down Expand Up @@ -152,85 +153,79 @@ class EditProfileActivity : BaseActivity(), Injectable {

viewModel.obtainProfile()

lifecycleScope.launch {
viewModel.profileData.collect { profileRes ->
if (profileRes == null) return@collect
when (profileRes) {
is Success -> {
val me = profileRes.data
if (me != null) {
binding.displayNameEditText.setText(me.displayName)
binding.noteEditText.setText(me.source?.note)
binding.lockedCheckBox.isChecked = me.locked

accountFieldEditAdapter.setFields(me.source?.fields.orEmpty())
binding.addFieldButton.isVisible =
(me.source?.fields?.size ?: 0) < maxAccountFields

if (viewModel.avatarData.value == null) {
Glide.with(this@EditProfileActivity)
.load(me.avatar)
.placeholder(R.drawable.avatar_default)
.transform(
FitCenter(),
RoundedCorners(
resources.getDimensionPixelSize(R.dimen.avatar_radius_80dp)
)
viewModel.profileData.observe { profileRes ->
if (profileRes == null) return@observe
when (profileRes) {
is Success -> {
val me = profileRes.data
if (me != null) {
binding.displayNameEditText.setText(me.displayName)
binding.noteEditText.setText(me.source?.note)
binding.lockedCheckBox.isChecked = me.locked

accountFieldEditAdapter.setFields(me.source?.fields.orEmpty())
binding.addFieldButton.isVisible =
(me.source?.fields?.size ?: 0) < maxAccountFields

if (viewModel.avatarData.value == null) {
Glide.with(this@EditProfileActivity)
.load(me.avatar)
.placeholder(R.drawable.avatar_default)
.transform(
FitCenter(),
RoundedCorners(
resources.getDimensionPixelSize(R.dimen.avatar_radius_80dp)
)
.into(binding.avatarPreview)
}

if (viewModel.headerData.value == null) {
Glide.with(this@EditProfileActivity)
.load(me.header)
.into(binding.headerPreview)
}
)
.into(binding.avatarPreview)
}

if (viewModel.headerData.value == null) {
Glide.with(this@EditProfileActivity)
.load(me.header)
.into(binding.headerPreview)
}
}
is Error -> {
Snackbar.make(
binding.avatarButton,
R.string.error_generic,
Snackbar.LENGTH_LONG
)
.setAction(R.string.action_retry) {
viewModel.obtainProfile()
}
.show()
}
is Loading -> { }
}
is Error -> {
Snackbar.make(
binding.avatarButton,
R.string.error_generic,
Snackbar.LENGTH_LONG
)
.setAction(R.string.action_retry) {
viewModel.obtainProfile()
}
.show()
}
is Loading -> { }
}
}

lifecycleScope.launch {
viewModel.instanceData.collect { instanceInfo ->
maxAccountFields = instanceInfo.maxFields
accountFieldEditAdapter.setFieldLimits(
instanceInfo.maxFieldNameLength,
instanceInfo.maxFieldValueLength
)
binding.addFieldButton.isVisible =
accountFieldEditAdapter.itemCount < maxAccountFields
}
viewModel.instanceData.observe { instanceInfo ->
maxAccountFields = instanceInfo.maxFields
accountFieldEditAdapter.setFieldLimits(
instanceInfo.maxFieldNameLength,
instanceInfo.maxFieldValueLength
)
binding.addFieldButton.isVisible =
accountFieldEditAdapter.itemCount < maxAccountFields
}

observeImage(viewModel.avatarData, binding.avatarPreview, true)
observeImage(viewModel.headerData, binding.headerPreview, false)

lifecycleScope.launch {
viewModel.saveData.collect {
if (it == null) return@collect
when (it) {
is Success -> {
finish()
}
is Loading -> {
binding.saveProgressBar.visibility = View.VISIBLE
}
is Error -> {
onSaveFailure(it.errorMessage)
}
viewModel.saveData.observe {
if (it == null) return@observe
when (it) {
is Success -> {
finish()
}
is Loading -> {
binding.saveProgressBar.visibility = View.VISIBLE
}
is Error -> {
onSaveFailure(it.errorMessage)
}
}
}
Expand Down Expand Up @@ -258,10 +253,8 @@ class EditProfileActivity : BaseActivity(), Injectable {
}

onBackPressedDispatcher.addCallback(this, onBackCallback)
lifecycleScope.launch {
viewModel.isChanged.collect { dataWasChanged ->
onBackCallback.isEnabled = dataWasChanged
}
viewModel.isChanged.observe { dataWasChanged ->
onBackCallback.isEnabled = dataWasChanged
}
}

Expand All @@ -277,26 +270,23 @@ class EditProfileActivity : BaseActivity(), Injectable {
imageView: ImageView,
roundedCorners: Boolean
) {
lifecycleScope.launch {
flow.collect { imageUri ->

// skipping all caches so we can always reuse the same uri
val glide = Glide.with(imageView)
.load(imageUri)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)

if (roundedCorners) {
glide.transform(
FitCenter(),
RoundedCorners(resources.getDimensionPixelSize(R.dimen.avatar_radius_80dp))
).into(imageView)
} else {
glide.into(imageView)
}

imageView.show()
flow.observe { imageUri ->
// skipping all caches so we can always reuse the same uri
val glide = Glide.with(imageView)
.load(imageUri)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)

if (roundedCorners) {
glide.transform(
FitCenter(),
RoundedCorners(resources.getDimensionPixelSize(R.dimen.avatar_radius_80dp))
).into(imageView)
} else {
glide.into(imageView)
}

imageView.show()
}
}

Expand Down
19 changes: 7 additions & 12 deletions app/src/main/java/com/keylesspalace/tusky/ListsActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import androidx.activity.viewModels
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.core.widget.doOnTextChanged
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
Expand All @@ -42,6 +41,7 @@ import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.util.BindingHolder
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.observe
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation
import com.keylesspalace.tusky.util.viewBinding
Expand All @@ -56,7 +56,6 @@ import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.LOADING
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector
import javax.inject.Inject
import kotlinx.coroutines.launch

// TODO use the ListSelectionFragment (and/or its adapter or binding) here; but keep the LoadingState from here (?)

Expand Down Expand Up @@ -95,23 +94,19 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
binding.swipeRefreshLayout.setOnRefreshListener { viewModel.retryLoading() }
binding.swipeRefreshLayout.setColorSchemeResources(R.color.tusky_blue)

lifecycleScope.launch {
viewModel.state.collect(this@ListsActivity::update)
}
viewModel.state.observe(this@ListsActivity::update)

viewModel.retryLoading()

binding.addListButton.setOnClickListener {
showlistNameDialog(null)
}

lifecycleScope.launch {
viewModel.events.collect { event ->
when (event) {
Event.CREATE_ERROR -> showMessage(R.string.error_create_list)
Event.UPDATE_ERROR -> showMessage(R.string.error_rename_list)
Event.DELETE_ERROR -> showMessage(R.string.error_delete_list)
}
viewModel.events.observe { event ->
when (event) {
Event.CREATE_ERROR -> showMessage(R.string.error_create_list)
Event.UPDATE_ERROR -> showMessage(R.string.error_rename_list)
Event.DELETE_ERROR -> showMessage(R.string.error_delete_list)
}
}
}
Expand Down
Loading

0 comments on commit 30f6b4b

Please sign in to comment.