add ktlint plugin to project and apply default code style (#2209)

* add ktlint plugin to project and apply default code style

* some manual adjustments, fix wildcard imports

* update CONTRIBUTING.md

* fix formatting
This commit is contained in:
Konrad Pozniak 2021-06-28 21:13:24 +02:00 committed by GitHub
commit 16ffcca748
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
227 changed files with 3933 additions and 3371 deletions

View file

@ -2,14 +2,25 @@ package com.keylesspalace.tusky.viewmodel
import android.util.Log
import androidx.lifecycle.MutableLiveData
import com.keylesspalace.tusky.appstore.*
import com.keylesspalace.tusky.appstore.BlockEvent
import com.keylesspalace.tusky.appstore.DomainMuteEvent
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.MuteEvent
import com.keylesspalace.tusky.appstore.ProfileEditedEvent
import com.keylesspalace.tusky.appstore.UnfollowEvent
import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.entity.Account
import com.keylesspalace.tusky.entity.Field
import com.keylesspalace.tusky.entity.IdentityProof
import com.keylesspalace.tusky.entity.Relationship
import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.*
import com.keylesspalace.tusky.util.Either
import com.keylesspalace.tusky.util.Error
import com.keylesspalace.tusky.util.Loading
import com.keylesspalace.tusky.util.Resource
import com.keylesspalace.tusky.util.RxAwareViewModel
import com.keylesspalace.tusky.util.Success
import com.keylesspalace.tusky.util.combineOptionalLiveData
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.disposables.Disposable
import retrofit2.Call
@ -19,9 +30,9 @@ import java.util.concurrent.TimeUnit
import javax.inject.Inject
class AccountViewModel @Inject constructor(
private val mastodonApi: MastodonApi,
private val eventHub: EventHub,
private val accountManager: AccountManager
private val mastodonApi: MastodonApi,
private val eventHub: EventHub,
private val accountManager: AccountManager
) : RxAwareViewModel() {
val accountData = MutableLiveData<Resource<Account>>()
@ -33,7 +44,7 @@ class AccountViewModel @Inject constructor(
val accountFieldData = combineOptionalLiveData(accountData, identityProofData) { accountRes, identityProofs ->
identityProofs.orEmpty().map { Either.Left<IdentityProof, Field>(it) }
.plus(accountRes?.data?.fields.orEmpty().map { Either.Right(it) })
.plus(accountRes?.data?.fields.orEmpty().map { Either.Right(it) })
}
val isRefreshing = MutableLiveData<Boolean>().apply { value = false }
@ -46,11 +57,11 @@ class AccountViewModel @Inject constructor(
init {
eventHub.events
.subscribe { event ->
if (event is ProfileEditedEvent && event.newProfileData.id == accountData.value?.data?.id) {
accountData.postValue(Success(event.newProfileData))
}
}.autoDispose()
.subscribe { event ->
if (event is ProfileEditedEvent && event.newProfileData.id == accountData.value?.data?.id) {
accountData.postValue(Success(event.newProfileData))
}
}.autoDispose()
}
private fun obtainAccount(reload: Boolean = false) {
@ -59,17 +70,20 @@ class AccountViewModel @Inject constructor(
accountData.postValue(Loading())
mastodonApi.account(accountId)
.subscribe({ account ->
.subscribe(
{ account ->
accountData.postValue(Success(account))
isDataLoading = false
isRefreshing.postValue(false)
}, {t ->
},
{ t ->
Log.w(TAG, "failed obtaining account", t)
accountData.postValue(Error())
isDataLoading = false
isRefreshing.postValue(false)
})
.autoDispose()
}
)
.autoDispose()
}
}
@ -79,13 +93,16 @@ class AccountViewModel @Inject constructor(
relationshipData.postValue(Loading())
mastodonApi.relationships(listOf(accountId))
.subscribe({ relationships ->
.subscribe(
{ relationships ->
relationshipData.postValue(Success(relationships[0]))
}, { t ->
},
{ t ->
Log.w(TAG, "failed obtaining relationships", t)
relationshipData.postValue(Error())
})
.autoDispose()
}
)
.autoDispose()
}
}
@ -93,12 +110,15 @@ class AccountViewModel @Inject constructor(
if (identityProofData.value == null || reload) {
mastodonApi.identityProofs(accountId)
.subscribe({ proofs ->
.subscribe(
{ proofs ->
identityProofData.postValue(proofs)
}, { t ->
},
{ t ->
Log.w(TAG, "failed obtaining identity proofs", t)
})
.autoDispose()
}
)
.autoDispose()
}
}
@ -126,11 +146,12 @@ class AccountViewModel @Inject constructor(
fun unmuteAccount() {
changeRelationship(RelationShipAction.UNMUTE)
}
fun changeSubscribingState() {
val relationship = relationshipData.value?.data
if(relationship?.notifying == true /* Mastodon 3.3.0rc1 */
|| relationship?.subscribing == true /* Pleroma */ ) {
if (relationship?.notifying == true || /* Mastodon 3.3.0rc1 */
relationship?.subscribing == true /* Pleroma */
) {
changeRelationship(RelationShipAction.UNSUBSCRIBE)
} else {
changeRelationship(RelationShipAction.SUBSCRIBE)
@ -138,12 +159,12 @@ class AccountViewModel @Inject constructor(
}
fun blockDomain(instance: String) {
mastodonApi.blockDomain(instance).enqueue(object: Callback<Any> {
mastodonApi.blockDomain(instance).enqueue(object : Callback<Any> {
override fun onResponse(call: Call<Any>, response: Response<Any>) {
if (response.isSuccessful) {
eventHub.dispatch(DomainMuteEvent(instance))
val relation = relationshipData.value?.data
if(relation != null) {
if (relation != null) {
relationshipData.postValue(Success(relation.copy(blockingDomain = true)))
}
} else {
@ -158,11 +179,11 @@ class AccountViewModel @Inject constructor(
}
fun unblockDomain(instance: String) {
mastodonApi.unblockDomain(instance).enqueue(object: Callback<Any> {
mastodonApi.unblockDomain(instance).enqueue(object : Callback<Any> {
override fun onResponse(call: Call<Any>, response: Response<Any>) {
if (response.isSuccessful) {
val relation = relationshipData.value?.data
if(relation != null) {
if (relation != null) {
relationshipData.postValue(Success(relation.copy(blockingDomain = false)))
}
} else {
@ -209,12 +230,12 @@ class AccountViewModel @Inject constructor(
RelationShipAction.MUTE -> relation.copy(muting = true)
RelationShipAction.UNMUTE -> relation.copy(muting = false)
RelationShipAction.SUBSCRIBE -> {
if(isMastodon)
if (isMastodon)
relation.copy(notifying = true)
else relation.copy(subscribing = true)
}
RelationShipAction.UNSUBSCRIBE -> {
if(isMastodon)
if (isMastodon)
relation.copy(notifying = false)
else relation.copy(subscribing = false)
}
@ -230,50 +251,53 @@ class AccountViewModel @Inject constructor(
RelationShipAction.MUTE -> mastodonApi.muteAccount(accountId, parameter ?: true, duration)
RelationShipAction.UNMUTE -> mastodonApi.unmuteAccount(accountId)
RelationShipAction.SUBSCRIBE -> {
if(isMastodon)
if (isMastodon)
mastodonApi.followAccount(accountId, notify = true)
else mastodonApi.subscribeAccount(accountId)
}
RelationShipAction.UNSUBSCRIBE -> {
if(isMastodon)
if (isMastodon)
mastodonApi.followAccount(accountId, notify = false)
else mastodonApi.unsubscribeAccount(accountId)
}
}.subscribe(
{ relationship ->
relationshipData.postValue(Success(relationship))
{ relationship ->
relationshipData.postValue(Success(relationship))
when (relationshipAction) {
RelationShipAction.UNFOLLOW -> eventHub.dispatch(UnfollowEvent(accountId))
RelationShipAction.BLOCK -> eventHub.dispatch(BlockEvent(accountId))
RelationShipAction.MUTE -> eventHub.dispatch(MuteEvent(accountId))
else -> {
}
when (relationshipAction) {
RelationShipAction.UNFOLLOW -> eventHub.dispatch(UnfollowEvent(accountId))
RelationShipAction.BLOCK -> eventHub.dispatch(BlockEvent(accountId))
RelationShipAction.MUTE -> eventHub.dispatch(MuteEvent(accountId))
else -> {
}
},
{
relationshipData.postValue(Error(relation))
}
},
{
relationshipData.postValue(Error(relation))
}
)
.autoDispose()
.autoDispose()
}
fun noteChanged(newNote: String) {
noteSaved.postValue(false)
noteDisposable?.dispose()
noteDisposable = Single.timer(1500, TimeUnit.MILLISECONDS)
.flatMap {
mastodonApi.updateAccountNote(accountId, newNote)
}
.doOnSuccess {
noteSaved.postValue(true)
}
.delay(4, TimeUnit.SECONDS)
.subscribe({
.flatMap {
mastodonApi.updateAccountNote(accountId, newNote)
}
.doOnSuccess {
noteSaved.postValue(true)
}
.delay(4, TimeUnit.SECONDS)
.subscribe(
{
noteSaved.postValue(false)
}, {
},
{
Log.e(TAG, "Error updating note", it)
})
}
)
}
override fun onCleared() {

View file

@ -38,39 +38,52 @@ class AccountsInListViewModel @Inject constructor(private val api: MastodonApi)
fun load(listId: String) {
val state = _state.value!!
if (state.accounts.isLeft() || state.accounts.asRight().isEmpty()) {
api.getAccountsInList(listId, 0).subscribe({ accounts ->
updateState { copy(accounts = Right(accounts)) }
}, { e ->
updateState { copy(accounts = Left(e)) }
}).autoDispose()
api.getAccountsInList(listId, 0).subscribe(
{ accounts ->
updateState { copy(accounts = Right(accounts)) }
},
{ e ->
updateState { copy(accounts = Left(e)) }
}
).autoDispose()
}
}
fun addAccountToList(listId: String, account: Account) {
api.addCountToList(listId, listOf(account.id))
.subscribe({
.subscribe(
{
updateState {
copy(accounts = accounts.map { it + account })
}
}, {
Log.i(javaClass.simpleName,
"Failed to add account to the list: ${account.username}")
})
.autoDispose()
},
{
Log.i(
javaClass.simpleName,
"Failed to add account to the list: ${account.username}"
)
}
)
.autoDispose()
}
fun deleteAccountFromList(listId: String, accountId: String) {
api.deleteAccountFromList(listId, listOf(accountId))
.subscribe({
.subscribe(
{
updateState {
copy(accounts = accounts.map { accounts ->
accounts.withoutFirstWhich { it.id == accountId }
})
copy(
accounts = accounts.map { accounts ->
accounts.withoutFirstWhich { it.id == accountId }
}
)
}
}, {
},
{
Log.i(javaClass.simpleName, "Failed to remove account from thelist: $accountId")
})
.autoDispose()
}
)
.autoDispose()
}
fun search(query: String) {
@ -78,15 +91,18 @@ class AccountsInListViewModel @Inject constructor(private val api: MastodonApi)
query.isEmpty() -> updateState { copy(searchResult = null) }
query.isBlank() -> updateState { copy(searchResult = listOf()) }
else -> api.searchAccounts(query, null, 10, true)
.subscribe({ result ->
.subscribe(
{ result ->
updateState { copy(searchResult = result) }
}, {
},
{
updateState { copy(searchResult = listOf()) }
}).autoDispose()
}
).autoDispose()
}
}
private inline fun updateState(crossinline fn: State.() -> State) {
_state.onNext(fn(_state.value!!))
}
}
}

View file

@ -15,12 +15,12 @@
package com.keylesspalace.tusky.viewmodel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import android.content.Context
import android.graphics.Bitmap
import android.net.Uri
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.keylesspalace.tusky.EditProfileActivity.Companion.AVATAR_SIZE
import com.keylesspalace.tusky.EditProfileActivity.Companion.HEADER_HEIGHT
import com.keylesspalace.tusky.EditProfileActivity.Companion.HEADER_WIDTH
@ -30,16 +30,22 @@ import com.keylesspalace.tusky.entity.Account
import com.keylesspalace.tusky.entity.Instance
import com.keylesspalace.tusky.entity.StringField
import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.*
import com.keylesspalace.tusky.util.Error
import com.keylesspalace.tusky.util.IOUtils
import com.keylesspalace.tusky.util.Loading
import com.keylesspalace.tusky.util.Resource
import com.keylesspalace.tusky.util.Success
import com.keylesspalace.tusky.util.getSampledBitmap
import com.keylesspalace.tusky.util.randomAlphanumericString
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.addTo
import io.reactivex.rxjava3.schedulers.Schedulers
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.MultipartBody
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONException
import org.json.JSONObject
import retrofit2.Call
@ -56,10 +62,10 @@ private const val AVATAR_FILE_NAME = "avatar.png"
private const val TAG = "EditProfileViewModel"
class EditProfileViewModel @Inject constructor(
private val mastodonApi: MastodonApi,
private val eventHub: EventHub
): ViewModel() {
class EditProfileViewModel @Inject constructor(
private val mastodonApi: MastodonApi,
private val eventHub: EventHub
) : ViewModel() {
val profileData = MutableLiveData<Resource<Account>>()
val avatarData = MutableLiveData<Resource<Bitmap>>()
@ -72,21 +78,21 @@ class EditProfileViewModel @Inject constructor(
private val disposeables = CompositeDisposable()
fun obtainProfile() {
if(profileData.value == null || profileData.value is Error) {
if (profileData.value == null || profileData.value is Error) {
profileData.postValue(Loading())
mastodonApi.accountVerifyCredentials()
.subscribe(
{profile ->
oldProfileData = profile
profileData.postValue(Success(profile))
},
{
profileData.postValue(Error())
})
.addTo(disposeables)
.subscribe(
{ profile ->
oldProfileData = profile
profileData.postValue(Success(profile))
},
{
profileData.postValue(Error())
}
)
.addTo(disposeables)
}
}
@ -102,12 +108,14 @@ class EditProfileViewModel @Inject constructor(
resizeImage(uri, context, HEADER_WIDTH, HEADER_HEIGHT, cacheFile, headerData)
}
private fun resizeImage(uri: Uri,
context: Context,
resizeWidth: Int,
resizeHeight: Int,
cacheFile: File,
imageLiveData: MutableLiveData<Resource<Bitmap>>) {
private fun resizeImage(
uri: Uri,
context: Context,
resizeWidth: Int,
resizeHeight: Int,
cacheFile: File,
imageLiveData: MutableLiveData<Resource<Bitmap>>
) {
Single.fromCallable {
val contentResolver = context.contentResolver
@ -117,13 +125,13 @@ class EditProfileViewModel @Inject constructor(
throw Exception()
}
//dont upscale image if its smaller than the desired size
// dont upscale image if its smaller than the desired size
val bitmap =
if (sourceBitmap.width <= resizeWidth && sourceBitmap.height <= resizeHeight) {
sourceBitmap
} else {
Bitmap.createScaledBitmap(sourceBitmap, resizeWidth, resizeHeight, true)
}
if (sourceBitmap.width <= resizeWidth && sourceBitmap.height <= resizeHeight) {
sourceBitmap
} else {
Bitmap.createScaledBitmap(sourceBitmap, resizeWidth, resizeHeight, true)
}
if (!saveBitmapToFile(bitmap, cacheFile)) {
throw Exception()
@ -131,17 +139,20 @@ class EditProfileViewModel @Inject constructor(
bitmap
}.subscribeOn(Schedulers.io())
.subscribe({
.subscribe(
{
imageLiveData.postValue(Success(it))
}, {
},
{
imageLiveData.postValue(Error())
})
.addTo(disposeables)
}
)
.addTo(disposeables)
}
fun save(newDisplayName: String, newNote: String, newLocked: Boolean, newFields: List<StringField>, context: Context) {
if(saveData.value is Loading || profileData.value !is Success) {
if (saveData.value is Loading || profileData.value !is Success) {
return
}
@ -184,21 +195,23 @@ class EditProfileViewModel @Inject constructor(
val field3 = calculateFieldToUpdate(newFields.getOrNull(2), fieldsUnchanged)
val field4 = calculateFieldToUpdate(newFields.getOrNull(3), fieldsUnchanged)
if (displayName == null && note == null && locked == null && avatar == null && header == null
&& field1 == null && field2 == null && field3 == null && field4 == null) {
if (displayName == null && note == null && locked == null && avatar == null && header == null &&
field1 == null && field2 == null && field3 == null && field4 == null
) {
/** if nothing has changed, there is no need to make a network request */
saveData.postValue(Success())
return
}
mastodonApi.accountUpdateCredentials(displayName, note, locked, avatar, header,
field1?.first, field1?.second, field2?.first, field2?.second, field3?.first, field3?.second, field4?.first, field4?.second
mastodonApi.accountUpdateCredentials(
displayName, note, locked, avatar, header,
field1?.first, field1?.second, field2?.first, field2?.second, field3?.first, field3?.second, field4?.first, field4?.second
).enqueue(object : Callback<Account> {
override fun onResponse(call: Call<Account>, response: Response<Account>) {
val newProfileData = response.body()
if (!response.isSuccessful || newProfileData == null) {
val errorResponse = response.errorBody()?.string()
val errorMsg = if(!errorResponse.isNullOrBlank()) {
val errorMsg = if (!errorResponse.isNullOrBlank()) {
try {
JSONObject(errorResponse).optString("error", null)
} catch (e: JSONException) {
@ -218,29 +231,28 @@ class EditProfileViewModel @Inject constructor(
saveData.postValue(Error())
}
})
}
// cache activity state for rotation change
fun updateProfile(newDisplayName: String, newNote: String, newLocked: Boolean, newFields: List<StringField>) {
if(profileData.value is Success) {
if (profileData.value is Success) {
val newProfileSource = profileData.value?.data?.source?.copy(note = newNote, fields = newFields)
val newProfile = profileData.value?.data?.copy(displayName = newDisplayName,
locked = newLocked, source = newProfileSource)
val newProfile = profileData.value?.data?.copy(
displayName = newDisplayName,
locked = newLocked, source = newProfileSource
)
profileData.postValue(Success(newProfile))
}
}
private fun calculateFieldToUpdate(newField: StringField?, fieldsUnchanged: Boolean): Pair<RequestBody, RequestBody>? {
if(fieldsUnchanged || newField == null) {
if (fieldsUnchanged || newField == null) {
return null
}
return Pair(
newField.name.toRequestBody(MultipartBody.FORM),
newField.value.toRequestBody(MultipartBody.FORM)
newField.name.toRequestBody(MultipartBody.FORM),
newField.value.toRequestBody(MultipartBody.FORM)
)
}
@ -270,19 +282,18 @@ class EditProfileViewModel @Inject constructor(
}
fun obtainInstance() {
if(instanceData.value == null || instanceData.value is Error) {
if (instanceData.value == null || instanceData.value is Error) {
instanceData.postValue(Loading())
mastodonApi.getInstance().subscribe(
{ instance ->
instanceData.postValue(Success(instance))
},
{
instanceData.postValue(Error())
})
.addTo(disposeables)
{ instance ->
instanceData.postValue(Success(instance))
},
{
instanceData.postValue(Error())
}
)
.addTo(disposeables)
}
}
}
}

View file

@ -55,49 +55,63 @@ internal class ListsViewModel @Inject constructor(private val api: MastodonApi)
copy(loadingState = LoadingState.LOADING)
}
api.getLists().subscribe({ lists ->
updateState {
copy(
api.getLists().subscribe(
{ lists ->
updateState {
copy(
lists = lists,
loadingState = LoadingState.LOADED
)
)
}
},
{ err ->
updateState {
copy(
loadingState = if (err is IOException || err is ConnectException)
LoadingState.ERROR_NETWORK else LoadingState.ERROR_OTHER
)
}
}
}, { err ->
updateState {
copy(loadingState = if (err is IOException || err is ConnectException)
LoadingState.ERROR_NETWORK else LoadingState.ERROR_OTHER)
}
}).autoDispose()
).autoDispose()
}
fun createNewList(listName: String) {
api.createList(listName).subscribe({ list ->
updateState {
copy(lists = lists + list)
api.createList(listName).subscribe(
{ list ->
updateState {
copy(lists = lists + list)
}
},
{
sendEvent(Event.CREATE_ERROR)
}
}, {
sendEvent(Event.CREATE_ERROR)
}).autoDispose()
).autoDispose()
}
fun renameList(listId: String, listName: String) {
api.updateList(listId, listName).subscribe({ list ->
updateState {
copy(lists = lists.replacedFirstWhich(list) { it.id == listId })
api.updateList(listId, listName).subscribe(
{ list ->
updateState {
copy(lists = lists.replacedFirstWhich(list) { it.id == listId })
}
},
{
sendEvent(Event.RENAME_ERROR)
}
}, {
sendEvent(Event.RENAME_ERROR)
}).autoDispose()
).autoDispose()
}
fun deleteList(listId: String) {
api.deleteList(listId).subscribe({
updateState {
copy(lists = lists.withoutFirstWhich { it.id == listId })
api.deleteList(listId).subscribe(
{
updateState {
copy(lists = lists.withoutFirstWhich { it.id == listId })
}
},
{
sendEvent(Event.DELETE_ERROR)
}
}, {
sendEvent(Event.DELETE_ERROR)
}).autoDispose()
).autoDispose()
}
private inline fun updateState(crossinline fn: State.() -> State) {