Fix #377
This commit is contained in:
parent
1dcf605976
commit
2e399884e9
@ -14,6 +14,7 @@ import android.view.View
|
||||
import android.widget.ImageView
|
||||
import androidx.activity.addCallback
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
@ -36,7 +37,12 @@ import com.mikepenz.materialdrawer.iconics.iconicsIcon
|
||||
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
|
||||
import com.mikepenz.materialdrawer.model.ProfileDrawerItem
|
||||
import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem
|
||||
import com.mikepenz.materialdrawer.model.interfaces.*
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IProfile
|
||||
import com.mikepenz.materialdrawer.model.interfaces.descriptionRes
|
||||
import com.mikepenz.materialdrawer.model.interfaces.descriptionText
|
||||
import com.mikepenz.materialdrawer.model.interfaces.iconUrl
|
||||
import com.mikepenz.materialdrawer.model.interfaces.nameRes
|
||||
import com.mikepenz.materialdrawer.model.interfaces.nameText
|
||||
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader
|
||||
import com.mikepenz.materialdrawer.util.DrawerImageLoader
|
||||
import com.mikepenz.materialdrawer.widget.AccountHeaderView
|
||||
@ -53,10 +59,10 @@ import org.pixeldroid.app.searchDiscover.SearchDiscoverFragment
|
||||
import org.pixeldroid.app.settings.SettingsActivity
|
||||
import org.pixeldroid.app.utils.BaseActivity
|
||||
import org.pixeldroid.app.utils.api.objects.Notification
|
||||
import org.pixeldroid.app.utils.db.addUser
|
||||
import org.pixeldroid.app.utils.db.entities.HomeStatusDatabaseEntity
|
||||
import org.pixeldroid.app.utils.db.entities.PublicFeedStatusDatabaseEntity
|
||||
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
|
||||
import org.pixeldroid.app.utils.db.updateUserInfoDb
|
||||
import org.pixeldroid.app.utils.hasInternet
|
||||
import org.pixeldroid.app.utils.notificationsWorker.NotificationsWorker.Companion.INSTANCE_NOTIFICATION_TAG
|
||||
import org.pixeldroid.app.utils.notificationsWorker.NotificationsWorker.Companion.SHOW_NOTIFICATION_TAG
|
||||
@ -71,6 +77,8 @@ class MainActivity : BaseActivity() {
|
||||
private lateinit var header: AccountHeaderView
|
||||
private var user: UserDatabaseEntity? = null
|
||||
|
||||
private lateinit var model: MainActivityViewModel
|
||||
|
||||
companion object {
|
||||
const val ADD_ACCOUNT_IDENTIFIER: Long = -13
|
||||
}
|
||||
@ -102,6 +110,12 @@ class MainActivity : BaseActivity() {
|
||||
} else {
|
||||
sendTraceDroidStackTracesIfExist("contact@pixeldroid.org", this)
|
||||
|
||||
val _model: MainActivityViewModel by viewModels {
|
||||
MainActivityViewModelFactory(application)
|
||||
}
|
||||
model = _model
|
||||
|
||||
|
||||
setupDrawer()
|
||||
val tabs: List<() -> Fragment> = listOf(
|
||||
{
|
||||
@ -281,16 +295,12 @@ class MainActivity : BaseActivity() {
|
||||
|
||||
lifecycleScope.launchWhenCreated {
|
||||
try {
|
||||
val domain = user?.instance_uri.orEmpty()
|
||||
val accessToken = user?.accessToken.orEmpty()
|
||||
val refreshToken = user?.refreshToken
|
||||
val clientId = user?.clientId.orEmpty()
|
||||
val clientSecret = user?.clientSecret.orEmpty()
|
||||
val api = apiHolder.api ?: apiHolder.setToCurrentUser()
|
||||
|
||||
val account = api.verifyCredentials()
|
||||
addUser(db, account, domain, accessToken = accessToken, refreshToken = refreshToken, clientId = clientId, clientSecret = clientSecret)
|
||||
fillDrawerAccountInfo(account.id!!)
|
||||
updateUserInfoDb(db, account)
|
||||
|
||||
//No need to update drawer account info here, the ViewModel listens to db updates
|
||||
} catch (exception: Exception) {
|
||||
Log.e("ACCOUNT UPDATE:", exception.toString())
|
||||
}
|
||||
@ -337,35 +347,41 @@ class MainActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
private fun fillDrawerAccountInfo(account: String) {
|
||||
val users = db.userDao().getAll().toMutableList()
|
||||
users.sortWith { l, r ->
|
||||
when {
|
||||
l.isActive && !r.isActive -> -1
|
||||
r.isActive && !l.isActive -> 1
|
||||
else -> 0
|
||||
lifecycleScope.launch {
|
||||
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
model.users.collect { list ->
|
||||
val users = list.toMutableList()
|
||||
users.sortWith { l, r ->
|
||||
when {
|
||||
l.isActive && !r.isActive -> -1
|
||||
r.isActive && !l.isActive -> 1
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
val profiles: MutableList<IProfile> = users.map { user ->
|
||||
ProfileDrawerItem().apply {
|
||||
isSelected = user.isActive
|
||||
nameText = user.display_name
|
||||
iconUrl = user.avatar_static
|
||||
isNameShown = true
|
||||
identifier = user.user_id.toLong()
|
||||
descriptionText = user.fullHandle
|
||||
tag = user.instance_uri
|
||||
}
|
||||
}.toMutableList()
|
||||
|
||||
// reuse the already existing "add account" item
|
||||
header.profiles.orEmpty()
|
||||
.filter { it.identifier == ADD_ACCOUNT_IDENTIFIER }
|
||||
.take(1)
|
||||
.forEach { profiles.add(it) }
|
||||
|
||||
header.clear()
|
||||
header.profiles = profiles
|
||||
header.setActiveProfile(account.toLong())
|
||||
}
|
||||
}
|
||||
}
|
||||
val profiles: MutableList<IProfile> = users.map { user ->
|
||||
ProfileDrawerItem().apply {
|
||||
isSelected = user.isActive
|
||||
nameText = user.display_name
|
||||
iconUrl = user.avatar_static
|
||||
isNameShown = true
|
||||
identifier = user.user_id.toLong()
|
||||
descriptionText = user.fullHandle
|
||||
tag = user.instance_uri
|
||||
}
|
||||
}.toMutableList()
|
||||
|
||||
// reuse the already existing "add account" item
|
||||
header.profiles.orEmpty()
|
||||
.filter { it.identifier == ADD_ACCOUNT_IDENTIFIER }
|
||||
.take(1)
|
||||
.forEach { profiles.add(it) }
|
||||
|
||||
header.clear()
|
||||
header.profiles = profiles
|
||||
header.setActiveProfile(account.toLong())
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,52 @@
|
||||
package org.pixeldroid.app
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import org.pixeldroid.app.utils.PixelDroidApplication
|
||||
import org.pixeldroid.app.utils.db.AppDatabase
|
||||
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
|
||||
import javax.inject.Inject
|
||||
|
||||
class MainActivityViewModel(application: Application) : AndroidViewModel(application) {
|
||||
|
||||
@Inject
|
||||
lateinit var db: AppDatabase
|
||||
|
||||
// Mutable state flow that will be used internally in the ViewModel, empty list is given as initial value.
|
||||
private val _users = MutableStateFlow(emptyList<UserDatabaseEntity>())
|
||||
|
||||
// Immutable state flow exposed to UI
|
||||
val users = _users.asStateFlow()
|
||||
|
||||
|
||||
init {
|
||||
(application as PixelDroidApplication).getAppComponent().inject(this)
|
||||
getUsers()
|
||||
}
|
||||
|
||||
private fun getUsers() {
|
||||
viewModelScope.launch {
|
||||
db.userDao().getAllFlow().flowOn(Dispatchers.IO)
|
||||
.collect { users: List<UserDatabaseEntity> ->
|
||||
_users.update { users }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MainActivityViewModelFactory(
|
||||
val application: Application,
|
||||
) : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return modelClass.getConstructor(Application::class.java).newInstance(application)
|
||||
}
|
||||
}
|
@ -73,6 +73,7 @@ internal fun <T: Any> initAdapter(
|
||||
|
||||
swipeRefreshLayout.setOnRefreshListener {
|
||||
adapter.refresh()
|
||||
adapter.notifyDataSetChanged()
|
||||
header?.refreshStories()
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@ class EditProfileActivity : BaseActivity() {
|
||||
}.show()
|
||||
} else {
|
||||
this.isEnabled = false
|
||||
if (model.submittedChanges) setResult(RESULT_OK)
|
||||
super.onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,9 @@ import org.pixeldroid.app.posts.fromHtml
|
||||
import org.pixeldroid.app.utils.PixelDroidApplication
|
||||
import org.pixeldroid.app.utils.api.objects.Account
|
||||
import org.pixeldroid.app.utils.db.AppDatabase
|
||||
import org.pixeldroid.app.utils.db.updateUserInfoDb
|
||||
import org.pixeldroid.app.utils.di.PixelfedAPIHolder
|
||||
import retrofit2.HttpException
|
||||
import javax.inject.Inject
|
||||
|
||||
class EditProfileViewModel(application: Application) : AndroidViewModel(application) {
|
||||
@ -40,6 +42,9 @@ class EditProfileViewModel(application: Application) : AndroidViewModel(applicat
|
||||
|
||||
private var oldProfile: Account? = null
|
||||
|
||||
var submittedChanges = false
|
||||
private set
|
||||
|
||||
init {
|
||||
(application as PixelDroidApplication).getAppComponent().inject(this)
|
||||
loadProfile()
|
||||
@ -50,6 +55,7 @@ class EditProfileViewModel(application: Application) : AndroidViewModel(applicat
|
||||
val api = apiHolder.api ?: apiHolder.setToCurrentUser()
|
||||
try {
|
||||
val profile = api.verifyCredentials()
|
||||
updateUserInfoDb(db, profile)
|
||||
if (oldProfile == null) oldProfile = profile
|
||||
_uiState.update { currentUiState ->
|
||||
currentUiState.copy(
|
||||
@ -96,6 +102,7 @@ class EditProfileViewModel(application: Application) : AndroidViewModel(applicat
|
||||
note = bio,
|
||||
locked = privateAccount,
|
||||
)
|
||||
if (madeChanges()) submittedChanges = true
|
||||
oldProfile = account
|
||||
_uiState.update { currentUiState ->
|
||||
currentUiState.copy(
|
||||
@ -180,7 +187,8 @@ class EditProfileViewModel(application: Application) : AndroidViewModel(applicat
|
||||
_uiState.update { currentUiState ->
|
||||
currentUiState.copy(
|
||||
profilePictureUri = image.toUri(),
|
||||
profilePictureChanged = true
|
||||
profilePictureChanged = true,
|
||||
profileSent = false
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -238,7 +246,7 @@ class EditProfileViewModel(application: Application) : AndroidViewModel(applicat
|
||||
|
||||
val inter =
|
||||
if(pixelfed) api.updateProfilePicture(requestBody.parts[0])
|
||||
else api.updateProfilePictureMastodon((requestBody.parts[0]))
|
||||
else api.updateProfilePictureMastodon(requestBody.parts[0])
|
||||
|
||||
postSub = inter
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -254,6 +262,7 @@ class EditProfileViewModel(application: Application) : AndroidViewModel(applicat
|
||||
}
|
||||
},
|
||||
/* onError = */ { e: Throwable ->
|
||||
Log.e("error", (e as? HttpException)?.message().orEmpty())
|
||||
_uiState.update { currentUiState ->
|
||||
currentUiState.copy(
|
||||
uploadProgress = 0,
|
||||
|
@ -6,6 +6,7 @@ import android.text.method.LinkMovementMethod
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
@ -16,11 +17,14 @@ import com.google.android.material.tabs.TabLayoutMediator
|
||||
import kotlinx.coroutines.launch
|
||||
import org.pixeldroid.app.R
|
||||
import org.pixeldroid.app.databinding.ActivityProfileBinding
|
||||
import org.pixeldroid.app.posts.feeds.uncachedFeeds.UncachedFeedFragment
|
||||
import org.pixeldroid.app.posts.parseHTMLText
|
||||
import org.pixeldroid.app.utils.BaseActivity
|
||||
import org.pixeldroid.app.utils.api.PixelfedAPI
|
||||
import org.pixeldroid.app.utils.api.objects.Account
|
||||
import org.pixeldroid.app.utils.api.objects.FeedContent
|
||||
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
|
||||
import org.pixeldroid.app.utils.db.updateUserInfoDb
|
||||
import org.pixeldroid.app.utils.setProfileImageFromURL
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
@ -56,7 +60,7 @@ class ProfileActivity : BaseActivity() {
|
||||
setContent(account)
|
||||
}
|
||||
|
||||
private fun createProfileTabs(account: Account?): Array<Fragment>{
|
||||
private fun createProfileTabs(account: Account?): Array<UncachedFeedFragment<FeedContent>> {
|
||||
|
||||
val profileFeedFragment = ProfileFeedFragment()
|
||||
profileFeedFragment.arguments = Bundle().apply {
|
||||
@ -80,7 +84,7 @@ class ProfileActivity : BaseActivity() {
|
||||
putSerializable(ProfileFeedFragment.COLLECTIONS, true)
|
||||
}
|
||||
|
||||
val returnArray: Array<Fragment> = arrayOf(
|
||||
val returnArray: Array<UncachedFeedFragment<FeedContent>> = arrayOf(
|
||||
profileGridFragment,
|
||||
profileFeedFragment,
|
||||
profileCollectionsFragment
|
||||
@ -100,7 +104,7 @@ class ProfileActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
private fun setupTabs(
|
||||
tabs: Array<Fragment>
|
||||
tabs: Array<UncachedFeedFragment<FeedContent>>
|
||||
){
|
||||
binding.viewPager.adapter = object : FragmentStateAdapter(this) {
|
||||
override fun createFragment(position: Int): Fragment {
|
||||
@ -134,7 +138,6 @@ class ProfileActivity : BaseActivity() {
|
||||
}.attach()
|
||||
}
|
||||
|
||||
|
||||
private fun setContent(account: Account?) {
|
||||
if(account != null) {
|
||||
setViews(account)
|
||||
@ -152,6 +155,9 @@ class ProfileActivity : BaseActivity() {
|
||||
).show()
|
||||
return@launchWhenResumed
|
||||
}
|
||||
|
||||
updateUserInfoDb(db, myAccount)
|
||||
|
||||
setViews(myAccount)
|
||||
}
|
||||
}
|
||||
@ -217,9 +223,15 @@ class ProfileActivity : BaseActivity() {
|
||||
)
|
||||
}
|
||||
|
||||
private val editResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == RESULT_OK) {
|
||||
// Profile was edited, reload
|
||||
setContent(null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onClickEditButton() {
|
||||
val intent = Intent(this, EditProfileActivity::class.java)
|
||||
ContextCompat.startActivity(this, intent, null)
|
||||
editResult.launch(Intent(this, EditProfileActivity::class.java))
|
||||
}
|
||||
|
||||
private fun onClickFollowers(account: Account?) {
|
||||
|
@ -13,21 +13,34 @@ import org.pixeldroid.app.utils.db.entities.InstanceDatabaseEntity.Companion.DEF
|
||||
import org.pixeldroid.app.utils.normalizeDomain
|
||||
import java.lang.IllegalArgumentException
|
||||
|
||||
fun addUser(db: AppDatabase, account: Account, instance_uri: String, activeUser: Boolean = true,
|
||||
accessToken: String, refreshToken: String?, clientId: String, clientSecret: String) {
|
||||
suspend fun addUser(
|
||||
db: AppDatabase, account: Account, instance_uri: String, activeUser: Boolean = true,
|
||||
accessToken: String, refreshToken: String?, clientId: String, clientSecret: String,
|
||||
) {
|
||||
db.userDao().insertOrUpdate(
|
||||
UserDatabaseEntity(
|
||||
user_id = account.id!!,
|
||||
instance_uri = normalizeDomain(instance_uri),
|
||||
username = account.username!!,
|
||||
display_name = account.getDisplayName(),
|
||||
avatar_static = account.anyAvatar().orEmpty(),
|
||||
isActive = activeUser,
|
||||
accessToken = accessToken,
|
||||
refreshToken = refreshToken,
|
||||
clientId = clientId,
|
||||
clientSecret = clientSecret
|
||||
)
|
||||
UserDatabaseEntity(
|
||||
user_id = account.id!!,
|
||||
instance_uri = normalizeDomain(instance_uri),
|
||||
username = account.username!!,
|
||||
display_name = account.getDisplayName(),
|
||||
avatar_static = account.anyAvatar().orEmpty(),
|
||||
isActive = activeUser,
|
||||
accessToken = accessToken,
|
||||
refreshToken = refreshToken,
|
||||
clientId = clientId,
|
||||
clientSecret = clientSecret
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun updateUserInfoDb(db: AppDatabase, account: Account) {
|
||||
val user = db.userDao().getActiveUser()!!
|
||||
db.userDao().updateUserAccountDetails(
|
||||
account.username.orEmpty(),
|
||||
account.display_name.orEmpty(),
|
||||
account.anyAvatar().orEmpty(),
|
||||
user.user_id,
|
||||
user.instance_uri
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.pixeldroid.app.utils.db.dao
|
||||
|
||||
import androidx.room.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
|
||||
|
||||
@Dao
|
||||
@ -9,17 +10,21 @@ interface UserDao {
|
||||
* Insert a user, if it already exists return -1
|
||||
*/
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
fun insertUser(user: UserDatabaseEntity): Long
|
||||
suspend fun insertUser(user: UserDatabaseEntity): Long
|
||||
|
||||
@Transaction
|
||||
fun insertOrUpdate(user: UserDatabaseEntity) {
|
||||
suspend fun insertOrUpdate(user: UserDatabaseEntity) {
|
||||
if (insertUser(user) == -1L) {
|
||||
updateUser(user)
|
||||
}
|
||||
}
|
||||
|
||||
@Update
|
||||
fun updateUser(user: UserDatabaseEntity)
|
||||
suspend fun updateUser(user: UserDatabaseEntity)
|
||||
|
||||
@Query("UPDATE users SET username = :username, display_name = :displayName, avatar_static = :avatarStatic WHERE user_id = :id and instance_uri = :instanceUri")
|
||||
suspend fun updateUserAccountDetails(username: String, displayName: String, avatarStatic: String, id: String, instanceUri: String)
|
||||
|
||||
|
||||
@Query("UPDATE users SET accessToken = :accessToken, refreshToken = :refreshToken WHERE user_id = :id and instance_uri = :instanceUri")
|
||||
fun updateAccessToken(accessToken: String, refreshToken: String, id: String, instanceUri: String)
|
||||
@ -27,6 +32,9 @@ interface UserDao {
|
||||
@Query("SELECT * FROM users")
|
||||
fun getAll(): List<UserDatabaseEntity>
|
||||
|
||||
@Query("SELECT * FROM users")
|
||||
fun getAllFlow(): Flow<List<UserDatabaseEntity>>
|
||||
|
||||
@Query("SELECT * FROM users WHERE isActive=1")
|
||||
fun getActiveUser(): UserDatabaseEntity?
|
||||
|
||||
|
@ -7,6 +7,7 @@ import org.pixeldroid.app.utils.PixelDroidApplication
|
||||
import org.pixeldroid.app.utils.db.AppDatabase
|
||||
import org.pixeldroid.app.utils.BaseFragment
|
||||
import dagger.Component
|
||||
import org.pixeldroid.app.MainActivityViewModel
|
||||
import org.pixeldroid.app.postCreation.PostCreationViewModel
|
||||
import org.pixeldroid.app.profile.EditProfileViewModel
|
||||
import org.pixeldroid.app.stories.StoriesViewModel
|
||||
@ -25,6 +26,7 @@ interface ApplicationComponent {
|
||||
fun inject(postCreationViewModel: PostCreationViewModel)
|
||||
fun inject(editProfileViewModel: EditProfileViewModel)
|
||||
fun inject(storiesViewModel: StoriesViewModel)
|
||||
fun inject(mainActivityViewModel: MainActivityViewModel)
|
||||
|
||||
val context: Context?
|
||||
val application: Application?
|
||||
|
Loading…
x
Reference in New Issue
Block a user