Merge pull request #6038 from vector-im/feature/bma/detekt

Detekt
This commit is contained in:
Benoit Marty 2022-05-13 23:40:53 +02:00 committed by GitHub
commit 9234c60155
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 265 additions and 121 deletions

View File

@ -67,4 +67,4 @@ jobs:
path: |
vector/build/outputs/apk/*/release/*.apk
# TODO: add exodus checks
# TODO add exodus checks

View File

@ -147,3 +147,23 @@ jobs:
name: release-lint-report-${{ matrix.target }}
path: |
vector/build/reports/*.*
detekt:
name: Detekt Analysis
runs-on: ubuntu-latest
# Allow all jobs on main and develop. Just one per PR.
concurrency:
group: ${{ github.ref == 'refs/heads/main' && format('detekt-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('detekt-develop-{0}', github.sha) || format('detekt-{0}', github.ref) }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v3
- name: Run detekt
run: |
./gradlew detekt
- name: Upload reports
if: always()
uses: actions/upload-artifact@v3
with:
name: detekt-report
path: |
*/build/reports/detekt/detekt.html

View File

@ -35,9 +35,11 @@ buildscript {
}
}
// ktlint Plugin
plugins {
// ktlint Plugin
id "org.jlleitschuh.gradle.ktlint" version "10.3.0"
// Detekt
id "io.gitlab.arturbosch.detekt" version "1.20.0"
}
// https://github.com/jeremylong/DependencyCheck
@ -52,6 +54,7 @@ dependencyCheck {
allprojects {
apply plugin: "org.jlleitschuh.gradle.ktlint"
apply plugin: "io.gitlab.arturbosch.detekt"
repositories {
// Do not use `mavenCentral()`, it prevents Dependabot from working properly
@ -119,7 +122,7 @@ allprojects {
// display the corresponding rule
verbose = true
disabledRules = [
// TODO: Re-enable these 4 rules after reformatting project
// TODO Re-enable these 4 rules after reformatting project
"indent",
"experimental:argument-list-wrapping",
"max-line-length",
@ -140,6 +143,15 @@ allprojects {
"experimental:kdoc-wrapping",
]
}
detekt {
// preconfigure defaults
buildUponDefaultConfig = true
// activate all available (even unstable) rules.
allRules = true
// point to your custom config defining rules to run, overwriting default behavior
config = files("$rootDir/tools/detekt/detekt.yml")
}
}
task clean(type: Delete) {

1
changelog.d/6038.misc Normal file
View File

@ -0,0 +1 @@
Setup detekt

View File

@ -123,6 +123,7 @@ ext.groups = [
'io.github.detekt.sarif4k',
'io.github.microutils',
'io.github.reactivecircus.flowbinding',
'io.gitlab.arturbosch.detekt',
'io.grpc',
'io.jsonwebtoken',
'io.kindedj',
@ -195,6 +196,7 @@ ext.groups = [
'org.testng',
'org.threeten',
'org.webjars',
'org.yaml',
'ru.noties',
'xerces',
'xml-apis',

View File

@ -16,7 +16,7 @@
package im.vector.lib.multipicker
class MultiPicker<T> {
class MultiPicker<T> private constructor() {
companion object Type {
val IMAGE by lazy { MultiPicker<ImagePicker>() }

View File

@ -22,15 +22,15 @@ package org.matrix.android.sdk.api.logger
* val loggerTag = LoggerTag("MyTag", LoggerTag.VOIP)
* Timber.tag(loggerTag.value).v("My log message")
*/
open class LoggerTag(_value: String, parentTag: LoggerTag? = null) {
open class LoggerTag(name: String, parentTag: LoggerTag? = null) {
object SYNC : LoggerTag("SYNC")
object VOIP : LoggerTag("VOIP")
object CRYPTO : LoggerTag("CRYPTO")
val value: String = if (parentTag == null) {
_value
name
} else {
"${parentTag.value}/$_value"
"${parentTag.value}/$name"
}
}

View File

@ -27,13 +27,13 @@ import timber.log.Timber
@JsonClass(generateAdapter = true)
data class RoomGuestAccessContent(
// Required. Whether guests can join the room. One of: ["can_join", "forbidden"]
@Json(name = "guest_access") val _guestAccess: String? = null
@Json(name = "guest_access") val guestAccessStr: String? = null
) {
val guestAccess: GuestAccess? = when (_guestAccess) {
val guestAccess: GuestAccess? = when (guestAccessStr) {
"can_join" -> GuestAccess.CanJoin
"forbidden" -> GuestAccess.Forbidden
else -> {
Timber.w("Invalid value for GuestAccess: `$_guestAccess`")
Timber.w("Invalid value for GuestAccess: `$guestAccessStr`")
null
}
}

View File

@ -22,15 +22,15 @@ import timber.log.Timber
@JsonClass(generateAdapter = true)
data class RoomHistoryVisibilityContent(
@Json(name = "history_visibility") val _historyVisibility: String? = null
@Json(name = "history_visibility") val historyVisibilityStr: String? = null
) {
val historyVisibility: RoomHistoryVisibility? = when (_historyVisibility) {
val historyVisibility: RoomHistoryVisibility? = when (historyVisibilityStr) {
"world_readable" -> RoomHistoryVisibility.WORLD_READABLE
"shared" -> RoomHistoryVisibility.SHARED
"invited" -> RoomHistoryVisibility.INVITED
"joined" -> RoomHistoryVisibility.JOINED
else -> {
Timber.w("Invalid value for RoomHistoryVisibility: `$_historyVisibility`")
Timber.w("Invalid value for RoomHistoryVisibility: `$historyVisibilityStr`")
null
}
}

View File

@ -27,7 +27,7 @@ import timber.log.Timber
*/
@JsonClass(generateAdapter = true)
data class RoomJoinRulesContent(
@Json(name = "join_rule") val _joinRules: String? = null,
@Json(name = "join_rule") val joinRulesStr: String? = null,
/**
* If the allow key is an empty list (or not a list at all),
* then no users are allowed to join without an invite.
@ -35,14 +35,14 @@ data class RoomJoinRulesContent(
*/
@Json(name = "allow") val allowList: List<RoomJoinRulesAllowEntry>? = null
) {
val joinRules: RoomJoinRules? = when (_joinRules) {
val joinRules: RoomJoinRules? = when (joinRulesStr) {
"public" -> RoomJoinRules.PUBLIC
"invite" -> RoomJoinRules.INVITE
"knock" -> RoomJoinRules.KNOCK
"private" -> RoomJoinRules.PRIVATE
"restricted" -> RoomJoinRules.RESTRICTED
else -> {
Timber.w("Invalid value for RoomJoinRules: `$_joinRules`")
Timber.w("Invalid value for RoomJoinRules: `$joinRulesStr`")
null
}
}

View File

@ -47,7 +47,7 @@ class RestrictedRoomPreset(val homeServerCapabilities: HomeServerCapabilities, v
type = EventType.STATE_ROOM_JOIN_RULES,
stateKey = "",
content = RoomJoinRulesContent(
_joinRules = RoomJoinRules.RESTRICTED.value,
joinRulesStr = RoomJoinRules.RESTRICTED.value,
allowList = restrictedList
).toContent()
)

View File

@ -20,6 +20,6 @@ import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = false)
sealed class LazyRoomSyncEphemeral {
data class Parsed(val _roomSyncEphemeral: RoomSyncEphemeral) : LazyRoomSyncEphemeral()
data class Parsed(val roomSyncEphemeral: RoomSyncEphemeral) : LazyRoomSyncEphemeral()
object Stored : LazyRoomSyncEphemeral()
}

View File

@ -74,7 +74,7 @@ internal fun Versions.isLoginAndRegistrationSupportedBySdk(): Boolean {
* Indicate if the homeserver support MSC3440 for threads
*/
internal fun Versions.doesServerSupportThreads(): Boolean {
// TODO: Check for v1.3 or whichever spec version formally specifies MSC3440.
// TODO Check for v1.3 or whichever spec version formally specifies MSC3440.
return unstableFeatures?.get(FEATURE_THREADS_MSC3440_STABLE) ?: false
}

View File

@ -46,7 +46,7 @@ internal class PerSessionBackupQueryRateLimiter @Inject constructor(
) {
companion object {
val MIN_TRY_BACKUP_PERIOD_MILLIS = 60 * 60_000 // 1 hour
const val MIN_TRY_BACKUP_PERIOD_MILLIS = 60 * 60_000 // 1 hour
}
data class Info(

View File

@ -79,7 +79,7 @@ internal class RoomDecryptorProvider @Inject constructor(
newSessionListeners.toList().forEach {
try {
it.onNewSession(roomId, senderKey, sessionId)
} catch (e: Throwable) {
} catch (ignore: Throwable) {
}
}
}

View File

@ -79,7 +79,7 @@ internal class MXMegolmEncryption(
}
// Default rotation periods
// TODO: Make it configurable via parameters
// TODO Make it configurable via parameters
// Session rotation periods
private var sessionRotationPeriodMsgs: Int = 100
private var sessionRotationPeriodMs: Int = 7 * 24 * 3600 * 1000

View File

@ -38,7 +38,7 @@ internal class MXOlmEncryption(
override suspend fun encryptEventContent(eventContent: Content, eventType: String, userIds: List<String>): Content {
// pick the list of recipients based on the membership list.
//
// TODO: there is a race condition here! What if a new user turns up
// TODO there is a race condition here! What if a new user turns up
ensureSession(userIds)
val deviceInfos = ArrayList<CryptoDeviceInfo>()
for (userId in userIds) {

View File

@ -22,7 +22,7 @@ import javax.inject.Inject
@SessionScope
internal class WarnOnUnknownDeviceRepository @Inject constructor() {
// TODO: set it back to true by default. Need UI
// TODO set it back to true by default. Need UI
// Warn the user if some new devices are detected while encrypting a message.
private var warnOnUnknownDevices = false

View File

@ -42,7 +42,7 @@ internal class MigrateCryptoTo007(realm: DynamicRealm) : RealmMigrator(realm, 7)
val jsonSignatures = crossSigningKeysMapper.serializeSignatures(objectSignatures)
it.setString(KeyInfoEntityFields.SIGNATURES, jsonSignatures)
}
} catch (failure: Throwable) {
} catch (ignore: Throwable) {
}
// Migrate frozen classes

View File

@ -69,6 +69,7 @@ internal class DefaultSendEventTask @Inject constructor(
}
} catch (e: Throwable) {
// localEchoRepository.updateSendState(params.event.eventId!!, SendState.UNDELIVERED)
Timber.w(e, "Unable to send the Event")
throw e
}
}

View File

@ -15,7 +15,6 @@
*/
package org.matrix.android.sdk.internal.crypto.tasks
import org.matrix.android.sdk.api.failure.Failure
import org.matrix.android.sdk.internal.crypto.api.CryptoApi
import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
import org.matrix.android.sdk.internal.network.executeRequest
@ -34,20 +33,15 @@ internal class DefaultUploadSignaturesTask @Inject constructor(
) : UploadSignaturesTask {
override suspend fun execute(params: UploadSignaturesTask.Params) {
try {
val response = executeRequest(
globalErrorReceiver,
canRetry = true,
maxRetriesCount = 10
) {
cryptoApi.uploadSignatures(params.signatures)
}
if (response.failures?.isNotEmpty() == true) {
throw Throwable(response.failures.toString())
}
return
} catch (f: Failure) {
throw f
val response = executeRequest(
globalErrorReceiver,
canRetry = true,
maxRetriesCount = 10
) {
cryptoApi.uploadSignatures(params.signatures)
}
if (response.failures?.isNotEmpty() == true) {
throw Throwable(response.failures.toString())
}
}
}

View File

@ -250,7 +250,7 @@ internal object CertUtil {
builder.supportsTlsExtensions(hsConfig.shouldAcceptTlsExtensions)
val list = ArrayList<ConnectionSpec>()
list.add(builder.build())
// TODO: we should display a warning if user enter an http url
// TODO we should display a warning if user enter an http url
if (hsConfig.allowHttpExtension || hsConfig.homeServerUriBase.toString().startsWith("http://")) {
list.add(ConnectionSpec.CLEARTEXT)
}

View File

@ -88,7 +88,7 @@ internal class DefaultFileService @Inject constructor(
Timber.v("## FileService downloadFile $url")
// TODO: Remove use of `synchronized` in suspend function.
// TODO Remove use of `synchronized` in suspend function.
val existingDownload = synchronized(ongoing) {
val existing = ongoing[url]
if (existing != null) {

View File

@ -29,6 +29,6 @@ internal data class GroupSummaryRoomsSection(
@Json(name = "rooms") val rooms: List<String> = emptyList()
// @TODO: Check the meaning and the usage of these categories. This dictionary is empty FTM.
// TODO Check the meaning and the usage of these categories. This dictionary is empty FTM.
// public Map<Object, Object> categories;
)

View File

@ -30,6 +30,6 @@ internal data class GroupSummaryUsersSection(
@Json(name = "users") val users: List<String> = emptyList()
// @TODO: Check the meaning and the usage of these roles. This dictionary is empty FTM.
// TODO Check the meaning and the usage of these roles. This dictionary is empty FTM.
// public Map<Object, Object> roles;
)

View File

@ -16,14 +16,16 @@
package org.matrix.android.sdk.internal.session.identity.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
internal data class SignInvitationBody(
/**The Matrix user ID of the user accepting the invitation.*/
/** The Matrix user ID of the user accepting the invitation.*/
val mxid: String,
/**The token from the call to store- invite..*/
/** The token from the call to store- invite..*/
val token: String,
/** The private key, encoded as Unpadded base64. */
val private_key: String
@Json(name = "private_key")
val privateKey: String
)

View File

@ -136,7 +136,7 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private
if (joinRules != null) {
val body = if (joinRules == RoomJoinRules.RESTRICTED) {
RoomJoinRulesContent(
_joinRules = RoomJoinRules.RESTRICTED.value,
joinRulesStr = RoomJoinRules.RESTRICTED.value,
allowList = allowList
).toContent()
} else {

View File

@ -23,8 +23,11 @@ import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
import org.matrix.android.sdk.api.util.JsonDict
/**
* Serializable object
*/
@JsonClass(generateAdapter = true)
internal data class SerializablePowerLevelsContent(
internal data class SafePowerLevelContent(
@Json(name = "ban") val ban: Int?,
@Json(name = "kick") val kick: Int?,
@Json(name = "invite") val invite: Int?,
@ -41,7 +44,7 @@ internal data class SerializablePowerLevelsContent(
internal fun JsonDict.toSafePowerLevelsContentDict(): JsonDict {
return toModel<PowerLevelsContent>()
?.let { content ->
SerializablePowerLevelsContent(
SafePowerLevelContent(
ban = content.ban,
kick = content.kick,
invite = content.invite,

View File

@ -55,7 +55,7 @@ internal data class SearchRequestRoomEvents(
* Requests the server return the current state for each room returned.
*/
@Json(name = "include_state")
val include_state: Boolean? = null
val includeState: Boolean? = null
/**
* Requests that the server partitions the result set based on the provided list of keys.

View File

@ -213,7 +213,7 @@ internal class RoomSyncHandler @Inject constructor(
val isInitialSync = insertType == EventInsertType.INITIAL_SYNC
val ephemeralResult = (roomSync.ephemeral as? LazyRoomSyncEphemeral.Parsed)
?._roomSyncEphemeral
?.roomSyncEphemeral
?.events
?.takeIf { it.isNotEmpty() }
?.let { handleEphemeral(realm, roomId, it, insertType == EventInsertType.INITIAL_SYNC, aggregator) }

View File

@ -68,7 +68,7 @@ internal class DefaultSessionAccountDataService @Inject constructor(
val params = UpdateUserAccountDataTask.AnyParams(type = type, any = content)
awaitCallback<Unit> { callback ->
updateUserAccountDataTask.configureWith(params) {
this.retryCount = 5 // TODO: Need to refactor retrying out into a helper method.
this.retryCount = 5 // TODO Need to refactor retrying out into a helper method.
this.callback = callback
}
.executeBy(taskExecutor)

View File

@ -151,7 +151,7 @@ internal class DefaultWidgetPostAPIMediator @Inject constructor(private val mosh
override fun sendError(message: String, eventData: JsonDict) {
Timber.e("## sendError() : eventData $eventData failed $message")
// TODO: JS has an additional optional parameter: nestedError
// TODO JS has an additional optional parameter: nestedError
val params = HashMap<String, Map<String, String>>()
val subMap = HashMap<String, String>()
subMap["message"] = message

View File

@ -81,7 +81,7 @@ class DefaultAddPusherTaskTest {
}
@Test
fun `given a persisted push entity and SetPush API fails when adding Pusher then mutates persisted result with Failed registration state and rethrows error`() {
fun `given a persisted push entity and SetPush API fails when adding Pusher then mutates persisted result with Failed registration state and rethrows`() {
val realmResult = PusherEntity()
monarchy.givenWhereReturns(result = realmResult)
pushersAPI.givenSetPusherErrors(SocketException())

View File

@ -60,7 +60,7 @@ private short
final short
### Line length is limited to 160 chars. Please split long lines
[^─]{161}
#[^─]{161}
### "DO NOT COMMIT" has been committed
DO NOT COMMIT

98
tools/detekt/detekt.yml Normal file
View File

@ -0,0 +1,98 @@
# Default rules: https://github.com/detekt/detekt/blob/main/detekt-core/src/main/resources/default-detekt-config.yml
style:
MaxLineLength:
# Default is 120
maxLineLength: 160
MagicNumber:
active: false
ReturnCount:
active: false
UnnecessaryAbstractClass:
active: false
FunctionOnlyReturningConstant:
active: false
UnusedPrivateMember:
# TODO Enable it
active: false
ThrowsCount:
active: false
LoopWithTooManyJumpStatements:
active: false
SerialVersionUIDInSerializableClass:
active: false
ProtectedMemberInFinalClass:
active: false
empty-blocks:
EmptyFunctionBlock:
active: false
EmptySecondaryConstructor:
active: false
potential-bugs:
ImplicitDefaultLocale:
active: false
exceptions:
TooGenericExceptionCaught:
active: false
SwallowedException:
active: false
ThrowingExceptionsWithoutMessageOrCause:
active: false
TooGenericExceptionThrown:
active: false
complexity:
TooManyFunctions:
active: false
LongMethod:
active: false
LongParameterList:
active: false
ComplexMethod:
active: false
NestedBlockDepth:
active: false
ComplexCondition:
active: false
LargeClass:
active: false
naming:
VariableNaming:
# TODO Enable it
active: false
TopLevelPropertyNaming:
# TODO Enable it
active: false
performance:
SpreadOperator:
active: false
# Note: all rules for `comments` are disabled by default, but I put them here to be aware of their existence
comments:
AbsentOrWrongFileLicense:
active: false
licenseTemplateFile: 'license.template'
licenseTemplateIsRegex: false
CommentOverPrivateFunction:
active: false
CommentOverPrivateProperty:
active: false
DeprecatedBlockTag:
active: true
EndOfSentenceFormat:
# TODO Enable it
active: false
OutdatedDocumentation:
# TODO Enable it
active: false
UndocumentedPublicClass:
active: false
UndocumentedPublicFunction:
active: false
UndocumentedPublicProperty:
active: false

View File

@ -8,7 +8,7 @@ import im.vector.app.core.extensions.addFragment
import im.vector.app.core.platform.ToolbarConfigurable
import im.vector.app.core.platform.VectorBaseActivity
//TODO: add this activity to manifest
//TODO add this activity to manifest
class ${activityClass} : VectorBaseActivity(), ToolbarConfigurable {
companion object {

View File

@ -18,7 +18,7 @@ import javax.inject.Inject
data class ${fragmentArgsClass}() : Parcelable
</#if>
//TODO: add this fragment into FragmentModule
//TODO add this fragment into FragmentModule
class ${fragmentClass} @Inject constructor(
private val viewModelFactory: ${viewModelClass}.Factory
) : VectorBaseFragment(), ${viewModelClass}.Factory by viewModelFactory {

View File

@ -87,7 +87,7 @@ class ActiveSessionHolder @Inject constructor(private val activeSessionDataSourc
?: throw IllegalStateException("You should authenticate before using this")
}
// TODO: Stop sync ?
// TODO Stop sync ?
// fun switchToSession(sessionParams: SessionParams) {
// val newActiveSession = authenticationService.getSession(sessionParams)
// activeSession.set(newActiveSession)

View File

@ -134,7 +134,7 @@ object VectorStaticModule {
@Provides
fun providesCurrentSession(activeSessionHolder: ActiveSessionHolder): Session {
// TODO: handle session injection better
// TODO handle session injection better
return activeSessionHolder.getActiveSession()
}

View File

@ -27,23 +27,23 @@ data class UserProperties(
/**
* Whether the user has the favourites space enabled
*/
val WebMetaSpaceFavouritesEnabled: Boolean? = null,
val webMetaSpaceFavouritesEnabled: Boolean? = null,
/**
* Whether the user has the home space set to all rooms
*/
val WebMetaSpaceHomeAllRooms: Boolean? = null,
val webMetaSpaceHomeAllRooms: Boolean? = null,
/**
* Whether the user has the home space enabled
*/
val WebMetaSpaceHomeEnabled: Boolean? = null,
val webMetaSpaceHomeEnabled: Boolean? = null,
/**
* Whether the user has the other rooms space enabled
*/
val WebMetaSpaceOrphansEnabled: Boolean? = null,
val webMetaSpaceOrphansEnabled: Boolean? = null,
/**
* Whether the user has the people space enabled
*/
val WebMetaSpacePeopleEnabled: Boolean? = null,
val webMetaSpacePeopleEnabled: Boolean? = null,
/**
* The selected messaging use case during the onboarding flow.
*/
@ -82,11 +82,11 @@ data class UserProperties(
fun getProperties(): Map<String, Any>? {
return mutableMapOf<String, Any>().apply {
WebMetaSpaceFavouritesEnabled?.let { put("WebMetaSpaceFavouritesEnabled", it) }
WebMetaSpaceHomeAllRooms?.let { put("WebMetaSpaceHomeAllRooms", it) }
WebMetaSpaceHomeEnabled?.let { put("WebMetaSpaceHomeEnabled", it) }
WebMetaSpaceOrphansEnabled?.let { put("WebMetaSpaceOrphansEnabled", it) }
WebMetaSpacePeopleEnabled?.let { put("WebMetaSpacePeopleEnabled", it) }
webMetaSpaceFavouritesEnabled?.let { put("WebMetaSpaceFavouritesEnabled", it) }
webMetaSpaceHomeAllRooms?.let { put("WebMetaSpaceHomeAllRooms", it) }
webMetaSpaceHomeEnabled?.let { put("WebMetaSpaceHomeEnabled", it) }
webMetaSpaceOrphansEnabled?.let { put("WebMetaSpaceOrphansEnabled", it) }
webMetaSpacePeopleEnabled?.let { put("WebMetaSpacePeopleEnabled", it) }
ftueUseCaseSelection?.let { put("ftueUseCaseSelection", it.name) }
numFavouriteRooms?.let { put("numFavouriteRooms", it) }
numSpaces?.let { put("numSpaces", it) }

View File

@ -53,7 +53,7 @@ class AutoCompleter @AssistedInject constructor(
@Assisted val isInThreadTimeline: Boolean,
private val avatarRenderer: AvatarRenderer,
private val commandAutocompletePolicy: CommandAutocompletePolicy,
AutocompleteCommandPresenterFactory: AutocompleteCommandPresenter.Factory,
autocompleteCommandPresenterFactory: AutocompleteCommandPresenter.Factory,
private val autocompleteMemberPresenterFactory: AutocompleteMemberPresenter.Factory,
private val autocompleteRoomPresenter: AutocompleteRoomPresenter,
private val autocompleteGroupPresenter: AutocompleteGroupPresenter,
@ -68,7 +68,7 @@ class AutoCompleter @AssistedInject constructor(
}
private val autocompleteCommandPresenter: AutocompleteCommandPresenter by lazy {
AutocompleteCommandPresenterFactory.create(isInThreadTimeline)
autocompleteCommandPresenterFactory.create(isInThreadTimeline)
}
private var editText: EditText? = null

View File

@ -225,7 +225,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
override fun onUpdate(state: AudioMessagePlaybackTracker.Listener.State) {
when (state) {
is AudioMessagePlaybackTracker.Listener.State.Recording -> {
voiceMessageViews.renderRecordingWaveform(state.amplitudeList.toTypedArray())
voiceMessageViews.renderRecordingWaveform(state.amplitudeList.toList())
}
is AudioMessagePlaybackTracker.Listener.State.Playing -> {
voiceMessageViews.renderPlaying(state)

View File

@ -345,10 +345,10 @@ class VoiceMessageViews(
}
}
fun renderRecordingWaveform(amplitudeList: Array<Int>) {
fun renderRecordingWaveform(amplitudeList: List<Int>) {
views.voicePlaybackWaveform.doOnLayout { waveFormView ->
val waveformColor = ThemeUtils.getColor(waveFormView.context, R.attr.vctr_content_quaternary)
amplitudeList.iterator().forEach {
amplitudeList.forEach {
(waveFormView as AudioWaveformView).add(AudioWaveformView.FFT(it.toFloat(), waveformColor))
}
}

View File

@ -215,7 +215,7 @@ class NotifiableEventResolver @Inject constructor(
keysClaimed = result.claimedEd25519Key?.let { mapOf("ed25519" to it) },
forwardingCurve25519KeyChain = result.forwardingCurve25519KeyChain
)
} catch (e: MXCryptoError) {
} catch (ignore: MXCryptoError) {
}
}
}

View File

@ -309,9 +309,9 @@ class Login2Variant(
activity.finish()
}
private fun updateWithState(LoginViewState2: LoginViewState2) {
private fun updateWithState(loginViewState2: LoginViewState2) {
// Loading
setIsLoading(LoginViewState2.isLoading)
setIsLoading(loginViewState2.isLoading)
}
// Hack for AccountCreatedFragment

View File

@ -288,8 +288,8 @@ class FtueAuthVariant(
.show()
}
private fun onServerSelectionDone(OnboardingViewEvents: OnboardingViewEvents.OnServerSelectionDone) {
when (OnboardingViewEvents.serverType) {
private fun onServerSelectionDone(onboardingViewEvents: OnboardingViewEvents.OnServerSelectionDone) {
when (onboardingViewEvents.serverType) {
ServerType.MatrixOrg -> Unit // In this case, we wait for the login flow
ServerType.EMS,
ServerType.Other -> activity.addFragmentToBackstack(
@ -301,9 +301,9 @@ class FtueAuthVariant(
}
}
private fun onSignModeSelected(OnboardingViewEvents: OnboardingViewEvents.OnSignModeSelected) = withState(onboardingViewModel) { state ->
private fun onSignModeSelected(onboardingViewEvents: OnboardingViewEvents.OnSignModeSelected) = withState(onboardingViewModel) { state ->
// state.signMode could not be ready yet. So use value from the ViewEvent
when (OnboardingViewEvents.signMode) {
when (onboardingViewEvents.signMode) {
SignMode.Unknown -> error("Sign mode has to be set before calling this method")
SignMode.SignUp -> Unit // This case is processed in handleOnboardingViewEvents
SignMode.SignIn -> handleSignInSelected(state)

View File

@ -29,7 +29,7 @@ import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivitySimpleBinding
@AndroidEntryPoint
class QrCodeScannerActivity() : VectorBaseActivity<ActivitySimpleBinding>() {
class QrCodeScannerActivity : VectorBaseActivity<ActivitySimpleBinding>() {
override fun getBinding() = ActivitySimpleBinding.inflate(layoutInflater)

View File

@ -61,6 +61,7 @@ class VectorUncaughtExceptionHandler @Inject constructor(
* @param throwable the throwable
* @return the exception description
*/
@Suppress("PrintStackTrace")
override fun uncaughtException(thread: Thread, throwable: Throwable) {
Timber.v("Uncaught exception: $throwable")
preferences.edit(commit = true) {

View File

@ -44,8 +44,8 @@ import javax.inject.Inject
/**
*
* TODO: Loading indicator while getting emoji data source?
* TODO: Finish Refactor to vector base activity
* TODO Loading indicator while getting emoji data source?
* TODO Finish Refactor to vector base activity
*/
@AndroidEntryPoint
class EmojiReactionPickerActivity : VectorBaseActivity<ActivityEmojiReactionPickerBinding>(),

View File

@ -41,9 +41,9 @@ import kotlin.math.abs
/**
*
* TODO: Configure Span using available width and emoji size
* TODO: Performances
* TODO: Scroll to section - Find a way to snap section to the top
* TODO Configure Span using available width and emoji size
* TODO Performances
* TODO Scroll to section - Find a way to snap section to the top
*/
class EmojiRecyclerAdapter @Inject constructor() :
RecyclerView.Adapter<EmojiRecyclerAdapter.ViewHolder>() {

View File

@ -297,7 +297,7 @@ class CreateRoomViewModel @AssistedInject constructor(
}
}
// TODO: Should this be non-cancellable?
// TODO Should this be non-cancellable?
viewModelScope.launch {
runCatching { session.roomService().createRoom(createRoomParams) }.fold(
{ roomId ->

View File

@ -308,49 +308,55 @@ class OnboardingViewModelTest {
}
@Test
fun `given personalisation enabled and registration has started and has dummy step to do, when handling action, then ignores other steps and executes dummy`() = runTest {
fakeVectorFeatures.givenPersonalisationEnabled()
givenSuccessfulRegistrationForStartAndDummySteps(missingStages = listOf(Stage.Dummy(mandatory = true)))
val test = viewModel.test()
fun `given personalisation enabled and registration has started and has dummy step to do, when handling action, then ignores other steps and does dummy`() {
runTest {
fakeVectorFeatures.givenPersonalisationEnabled()
givenSuccessfulRegistrationForStartAndDummySteps(missingStages = listOf(Stage.Dummy(mandatory = true)))
val test = viewModel.test()
viewModel.handle(OnboardingAction.PostRegisterAction(A_LOADABLE_REGISTER_ACTION))
viewModel.handle(OnboardingAction.PostRegisterAction(A_LOADABLE_REGISTER_ACTION))
test
.assertStatesChanges(
initialState,
{ copy(isLoading = true) },
{ copy(isLoading = false, personalizationState = A_HOMESERVER_CAPABILITIES.toPersonalisationState()) }
)
.assertEvents(OnboardingViewEvents.OnAccountCreated)
.finish()
test
.assertStatesChanges(
initialState,
{ copy(isLoading = true) },
{ copy(isLoading = false, personalizationState = A_HOMESERVER_CAPABILITIES.toPersonalisationState()) }
)
.assertEvents(OnboardingViewEvents.OnAccountCreated)
.finish()
}
}
@Test
fun `given changing profile picture is supported, when updating display name, then updates upstream user display name and moves to choose profile picture`() = runTest {
viewModelWith(initialState.copy(personalizationState = PersonalizationState(supportsChangingProfilePicture = true)))
val test = viewModel.test()
fun `given changing profile avatar is supported, when updating display name, then updates upstream user display name and moves to choose profile avatar`() {
runTest {
viewModelWith(initialState.copy(personalizationState = PersonalizationState(supportsChangingProfilePicture = true)))
val test = viewModel.test()
viewModel.handle(OnboardingAction.UpdateDisplayName(A_DISPLAY_NAME))
viewModel.handle(OnboardingAction.UpdateDisplayName(A_DISPLAY_NAME))
test
.assertStatesChanges(initialState, expectedSuccessfulDisplayNameUpdateStates())
.assertEvents(OnboardingViewEvents.OnChooseProfilePicture)
.finish()
fakeSession.fakeProfileService.verifyUpdatedName(fakeSession.myUserId, A_DISPLAY_NAME)
test
.assertStatesChanges(initialState, expectedSuccessfulDisplayNameUpdateStates())
.assertEvents(OnboardingViewEvents.OnChooseProfilePicture)
.finish()
fakeSession.fakeProfileService.verifyUpdatedName(fakeSession.myUserId, A_DISPLAY_NAME)
}
}
@Test
fun `given changing profile picture is not supported, when updating display name, then updates upstream user display name and completes personalization`() = runTest {
viewModelWith(initialState.copy(personalizationState = PersonalizationState(supportsChangingProfilePicture = false)))
val test = viewModel.test()
fun `given changing profile avatar is not supported, when updating display name, then updates upstream user display name and completes personalization`() {
runTest {
viewModelWith(initialState.copy(personalizationState = PersonalizationState(supportsChangingProfilePicture = false)))
val test = viewModel.test()
viewModel.handle(OnboardingAction.UpdateDisplayName(A_DISPLAY_NAME))
viewModel.handle(OnboardingAction.UpdateDisplayName(A_DISPLAY_NAME))
test
.assertStatesChanges(initialState, expectedSuccessfulDisplayNameUpdateStates())
.assertEvents(OnboardingViewEvents.OnPersonalizationComplete)
.finish()
fakeSession.fakeProfileService.verifyUpdatedName(fakeSession.myUserId, A_DISPLAY_NAME)
test
.assertStatesChanges(initialState, expectedSuccessfulDisplayNameUpdateStates())
.assertEvents(OnboardingViewEvents.OnPersonalizationComplete)
.finish()
fakeSession.fakeProfileService.verifyUpdatedName(fakeSession.myUserId, A_DISPLAY_NAME)
}
}
@Test

View File

@ -34,7 +34,11 @@ class FakeSharedSecretStorageService : SharedSecretStorageService {
TODO("Not yet implemented")
}
override suspend fun generateKeyWithPassphrase(keyId: String, keyName: String, passphrase: String, keySigner: KeySigner, progressListener: ProgressListener?): SsssKeyCreationInfo {
override suspend fun generateKeyWithPassphrase(keyId: String,
keyName: String,
passphrase: String,
keySigner: KeySigner,
progressListener: ProgressListener?): SsssKeyCreationInfo {
TODO("Not yet implemented")
}