Skip to content
This repository was archived by the owner on May 23, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"-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 { 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