Skip to content

Commit

Permalink
Merge pull request #1625 from novasamatech/rc/8.4.0
Browse files Browse the repository at this point in the history
Rc/8.4.0
  • Loading branch information
antonijzelinskij authored Aug 6, 2024
2 parents 92740d2 + cf9b9b1 commit 2d31159
Show file tree
Hide file tree
Showing 109 changed files with 1,837 additions and 325 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
## About
Next gen application for Polkadot & Kusama ecosystem, transparent & community-oriented, focused on convenient UX/UI, fast performance & security.
Nova Wallet aims to provide as many Polkadot ecosystem features as possible in a form of mobile app, unbiased to any network & without any restrictions/limits to the users.
Developed by former Fearless Wallet team & based on open source work under Apache 2.0 license.
Developed by the former Fearless Wallet team & based on open-source work under Apache 2.0 license.

## License
Nova Wallet Android is available under the Apache 2.0 license. See the LICENSE file for more info.
© Novasama Technologies GmbH 2023
© Novasama Technologies GmbH 2023
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import org.junit.Test
import java.math.BigInteger
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers


class GovernanceIntegrationTest : BaseIntegrationTest() {
Expand Down Expand Up @@ -128,7 +130,7 @@ class GovernanceIntegrationTest : BaseIntegrationTest() {
val chain = chain()
val selectedGovernance = supportedGovernanceOption(chain, Chain.Governance.V1)

val referendumDetails = referendumDetailsInteractor.referendumDetailsFlow(referendumId, selectedGovernance, accountId)
val referendumDetails = referendumDetailsInteractor.referendumDetailsFlow(referendumId, selectedGovernance, accountId, CoroutineScope(Dispatchers.Main))
.first()

Log.d(this@GovernanceIntegrationTest.LOG_TAG, referendumDetails.toString())
Expand Down
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
buildscript {
ext {
// App version
versionName = '8.3.1'
versionCode = 150
versionName = '8.4.0'
versionCode = 152

applicationId = "io.novafoundation.nova"
releaseApplicationSuffix = "market"
Expand Down Expand Up @@ -140,7 +140,7 @@ buildscript {
// lifecycle scopes
lifeCycleKtxDep = "androidx.lifecycle:lifecycle-runtime-ktx:$architectureComponentVersion"

permissionsDep = "com.github.florent37:runtime-permission-kotlin:$permissionsVersion"
permissionsDep = "com.github.florent37:RuntimePermission:$permissionsVersion"

roomDep = "androidx.room:room-runtime:$roomVersion"
roomKtxDep = "androidx.room:room-ktx:$roomVersion"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package io.novafoundation.nova.common.domain
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.transform

sealed class ExtendedLoadingState<out T> {

Expand All @@ -19,6 +20,14 @@ inline fun <T, V> Flow<ExtendedLoadingState<T>>.mapLoading(crossinline mapper: s
return map { loadingState -> loadingState.map { mapper(it) } }
}

fun <T> Flow<ExtendedLoadingState<T>>.filterLoaded(): Flow<T> {
return transform { loadingState ->
if (loadingState is ExtendedLoadingState.Loaded) {
emit(loadingState.data)
}
}
}

inline fun <T, R> ExtendedLoadingState<T>.map(mapper: (T) -> R): ExtendedLoadingState<R> {
return when (this) {
is ExtendedLoadingState.Loading -> this
Expand All @@ -33,6 +42,11 @@ val <T> ExtendedLoadingState<T>.dataOrNull: T?
else -> null
}

fun <T> ExtendedLoadingState<T?>.loadedAndEmpty(): Boolean = when (this) {
is ExtendedLoadingState.Loaded -> data == null
else -> false
}

fun <T> loadedNothing(): ExtendedLoadingState<T?> {
return ExtendedLoadingState.Loaded(null)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ sealed class DescriptiveButtonState {
object Loading : DescriptiveButtonState()

object Gone : DescriptiveButtonState()

object Invisible : DescriptiveButtonState()
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,5 @@ fun CoroutineScope.childScope(supervised: Boolean = true): CoroutineScope {
fun Int.asBoolean() = this != 0

fun Boolean?.orFalse() = this ?: false

fun Boolean?.orTrue() = this ?: true
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ fun <T, R> Flow<T>.withLoadingShared(sourceSupplier: suspend (T) -> Flow<R>): Fl

suspend inline fun <reified T> Flow<ExtendedLoadingState<T>>.firstLoaded(): T = first { it.dataOrNull != null }.dataOrNull as T

suspend fun <T> Flow<ExtendedLoadingState<T>>.firstIfLoaded(): T? = first().dataOrNull

/**
* Modifies flow so that it firstly emits [LoadingState.Loading] state.
* Then emits each element from upstream wrapped into [LoadingState.Loaded] state.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import java.io.InputStream
import java.math.BigDecimal
import java.math.BigInteger
import java.math.MathContext
import java.math.RoundingMode
import java.util.Calendar
import java.util.Collections
import java.util.Date
Expand Down Expand Up @@ -179,6 +180,35 @@ fun BigInteger.atLeastZero() = coerceAtLeast(BigInteger.ZERO)

fun BigDecimal.atLeastZero() = coerceAtLeast(BigDecimal.ZERO)

fun BigDecimal.lessEpsilon(): BigDecimal = when {
this.isZero -> this
else -> this.subtract(BigInteger.ONE.toBigDecimal(scale = MathContext.DECIMAL64.precision))
}

fun BigDecimal.divideOrNull(value: BigDecimal): BigDecimal? = try {
this.divide(value)
} catch (e: ArithmeticException) {
null
}

fun BigDecimal.divideOrNull(value: BigDecimal, mathContext: MathContext): BigDecimal? = try {
this.divide(value, mathContext)
} catch (e: ArithmeticException) {
null
}

fun BigDecimal.divideOrNull(value: BigDecimal, roundingMode: RoundingMode): BigDecimal? = try {
this.divide(value, roundingMode)
} catch (e: ArithmeticException) {
null
}

fun BigDecimal.coerceInOrNull(from: BigDecimal, to: BigDecimal): BigDecimal? = if (this >= from && this <= to) {
this
} else {
null
}

fun Long.daysFromMillis() = TimeUnit.MILLISECONDS.toDays(this)

inline fun <T> Collection<T>.sumByBigInteger(extractor: (T) -> BigInteger) = fold(BigInteger.ZERO) { acc, element ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.ContextThemeWrapper
import android.view.View
import androidx.annotation.ColorInt
import androidx.annotation.StyleRes
import androidx.appcompat.widget.AppCompatTextView
Expand All @@ -23,7 +24,6 @@ import io.novafoundation.nova.common.presentation.DescriptiveButtonState
import io.novafoundation.nova.common.utils.dp
import io.novafoundation.nova.common.utils.getColorFromAttr
import io.novafoundation.nova.common.utils.getEnum
import io.novafoundation.nova.common.utils.setVisible
import io.novafoundation.nova.common.utils.useAttributes
import io.novafoundation.nova.common.view.shape.addRipple
import io.novafoundation.nova.common.view.shape.getCornersStateDrawable
Expand All @@ -33,7 +33,8 @@ enum class ButtonState {
NORMAL,
DISABLED,
PROGRESS,
GONE
GONE,
INVISIBLE
}

private const val ICON_SIZE_DP_DEFAULT = 24
Expand Down Expand Up @@ -172,7 +173,12 @@ class PrimaryButton @JvmOverloads constructor(

fun setState(state: ButtonState) {
isEnabled = state == ButtonState.NORMAL
setVisible(state != ButtonState.GONE)

visibility = when (state) {
ButtonState.GONE -> View.GONE
ButtonState.INVISIBLE -> View.INVISIBLE
else -> View.VISIBLE
}

if (state == ButtonState.PROGRESS) {
checkPreparedForProgress()
Expand Down Expand Up @@ -282,5 +288,9 @@ fun PrimaryButton.setState(descriptiveButtonState: DescriptiveButtonState) {
DescriptiveButtonState.Gone -> {
setState(ButtonState.GONE)
}

DescriptiveButtonState.Invisible -> {
setState(ButtonState.INVISIBLE)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package io.novafoundation.nova.common.view

import android.content.Context
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.View
import androidx.lifecycle.LifecycleOwner
import com.github.razir.progressbutton.DrawableButton
import com.github.razir.progressbutton.bindProgressButton
import com.github.razir.progressbutton.hideProgress
import com.github.razir.progressbutton.isProgressActive
import com.github.razir.progressbutton.showProgress
import com.google.android.material.button.MaterialButton
import io.novafoundation.nova.common.presentation.DescriptiveButtonState

class PrimaryButtonV2 @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0,
) : MaterialButton(context, attrs, defStyle) {

private var cachedIcon: Drawable? = null
private var cachedText: String? = null

private var preparedForProgress = false

fun prepareForProgress(lifecycleOwner: LifecycleOwner) {
lifecycleOwner.bindProgressButton(this)

preparedForProgress = true
}

fun checkPreparedForProgress() {
if (!preparedForProgress) {
throw IllegalArgumentException("You must call prepareForProgress() first!")
}
}

fun showProgress(show: Boolean) {
isEnabled = !show

if (show) {
checkPreparedForProgress()

showButtonProgress()
} else {
hideProgress()
}
}

fun hideButtonProgress() {
if (isProgressActive()) {
icon = cachedIcon
hideProgress(cachedText)
}
}

fun showButtonProgress() {
if (isProgressActive()) return

cachedIcon = icon
cachedText = text.toString()

icon = null
showProgress {
progressColor = currentTextColor
gravity = DrawableButton.GRAVITY_CENTER
}
}
}

fun PrimaryButtonV2.setState(state: DescriptiveButtonState) {
isEnabled = state is DescriptiveButtonState.Enabled

visibility = when (state) {
DescriptiveButtonState.Gone -> View.GONE
DescriptiveButtonState.Invisible -> View.INVISIBLE
else -> View.VISIBLE
}

if (state == DescriptiveButtonState.Loading) {
checkPreparedForProgress()

showButtonProgress()
} else {
hideButtonProgress()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/button_background_inactive" android:state_enabled="false" />
<item android:color="@color/button_background_reject" />
</selector>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/button_background_inactive" android:state_enabled="false" />
<item android:color="@color/button_background_approve" />
</selector>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/button_background_inactive" android:state_enabled="false" />
<item android:color="@color/button_background_primary" />
</selector>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/button_background_inactive" android:state_enabled="false" />
<item android:color="@color/button_background_secondary" />
</selector>
9 changes: 9 additions & 0 deletions common/src/main/res/drawable/ic_abstain_vote.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="25dp"
android:height="24dp"
android:viewportWidth="25"
android:viewportHeight="24">
<path
android:pathData="M12.5,1.5C10.423,1.5 8.393,2.116 6.667,3.27C4.94,4.423 3.594,6.063 2.799,7.982C2.005,9.9 1.797,12.012 2.202,14.048C2.607,16.085 3.607,17.956 5.075,19.425C6.544,20.893 8.415,21.893 10.452,22.298C12.488,22.703 14.6,22.496 16.518,21.701C18.437,20.906 20.077,19.56 21.23,17.833C22.384,16.107 23,14.077 23,12C23,9.215 21.894,6.545 19.925,4.575C17.955,2.606 15.285,1.5 12.5,1.5ZM17.127,15.321C17.127,15.495 17.057,15.662 16.934,15.785C16.811,15.908 16.644,15.977 16.47,15.977H8.595C8.421,15.977 8.254,15.908 8.131,15.785C8.008,15.662 7.939,15.495 7.939,15.321C7.939,15.147 8.008,14.98 8.131,14.857C8.254,14.733 8.421,14.664 8.595,14.664H16.47C16.644,14.664 16.811,14.733 16.934,14.857C17.057,14.98 17.127,15.147 17.127,15.321ZM18.406,9.559C18.406,9.792 18.337,10.021 18.207,10.215C18.077,10.409 17.893,10.561 17.677,10.65C17.461,10.74 17.224,10.763 16.994,10.717C16.765,10.672 16.555,10.559 16.39,10.394C16.225,10.229 16.112,10.018 16.066,9.789C16.021,9.56 16.044,9.323 16.134,9.107C16.223,8.891 16.375,8.706 16.569,8.577C16.763,8.447 16.991,8.377 17.225,8.377C17.538,8.377 17.839,8.502 18.06,8.723C18.282,8.945 18.406,9.245 18.406,9.559ZM8.038,10.74C7.804,10.74 7.575,10.671 7.381,10.541C7.187,10.411 7.036,10.227 6.946,10.011C6.857,9.795 6.833,9.557 6.879,9.328C6.925,9.099 7.037,8.889 7.202,8.723C7.367,8.558 7.578,8.446 7.807,8.4C8.036,8.355 8.274,8.378 8.49,8.467C8.705,8.557 8.89,8.708 9.02,8.902C9.149,9.097 9.219,9.325 9.219,9.559C9.219,9.716 9.187,9.872 9.126,10.017C9.065,10.162 8.976,10.293 8.864,10.403C8.751,10.514 8.618,10.6 8.471,10.658C8.325,10.715 8.169,10.743 8.011,10.74H8.038Z"
android:fillColor="#ffffff"/>
</vector>
12 changes: 12 additions & 0 deletions common/src/main/res/drawable/ic_thumbs_down_filled.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="25dp"
android:height="24dp"
android:viewportWidth="25"
android:viewportHeight="24">
<group>
<clip-path android:pathData="M0.5,0h24v24h-24z" />
<path
android:fillColor="#ffffff"
android:pathData="M9.228,21.709C8.085,21.483 7.342,20.382 7.571,19.25L7.672,18.754C7.905,17.592 8.335,16.486 8.938,15.481H2.609C1.445,15.481 0.5,14.545 0.5,13.392C0.5,12.291 1.357,11.39 2.447,11.307C2.108,10.937 1.906,10.445 1.906,9.91C1.906,8.892 2.645,8.043 3.616,7.86C3.422,7.542 3.313,7.172 3.313,6.776C3.313,5.849 3.923,5.062 4.767,4.792C4.736,4.648 4.719,4.496 4.719,4.339C4.719,3.186 5.664,2.25 6.828,2.25H10.058C10.893,2.25 11.706,2.494 12.4,2.951L14.092,4.069C15.266,4.844 15.969,6.15 15.969,7.547V9.214V11.303V12.387C15.969,13.657 15.384,14.854 14.387,15.651L14.061,15.908C12.897,16.83 12.102,18.127 11.811,19.572L11.71,20.068C11.482,21.2 10.37,21.935 9.228,21.709ZM21.594,14.785H18.781C18.003,14.785 17.375,14.162 17.375,13.392V3.643C17.375,2.872 18.003,2.25 18.781,2.25H21.594C22.372,2.25 23,2.872 23,3.643V13.392C23,14.162 22.372,14.785 21.594,14.785Z" />
</group>
</vector>
13 changes: 13 additions & 0 deletions common/src/main/res/drawable/ic_thumbs_up_filled.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="25dp"
android:height="24dp"
android:viewportWidth="25"
android:viewportHeight="24">
<group>
<clip-path
android:pathData="M0.5,0h24v24h-24z"/>
<path
android:pathData="M15.773,2.291C16.915,2.517 17.658,3.618 17.429,4.75L17.328,5.246C17.095,6.408 16.665,7.514 16.063,8.519H22.391C23.555,8.519 24.5,9.455 24.5,10.608C24.5,11.709 23.643,12.61 22.553,12.693C22.892,13.063 23.094,13.555 23.094,14.09C23.094,15.108 22.355,15.957 21.384,16.14C21.578,16.453 21.688,16.828 21.688,17.224C21.688,18.151 21.077,18.938 20.233,19.208C20.264,19.352 20.281,19.504 20.281,19.661C20.281,20.814 19.336,21.75 18.172,21.75H14.942C14.107,21.75 13.294,21.506 12.6,21.049L10.908,19.931C9.734,19.156 9.031,17.85 9.031,16.453V14.786V12.697V11.613C9.031,10.343 9.616,9.146 10.613,8.349L10.939,8.093C12.103,7.17 12.898,5.873 13.189,4.428L13.29,3.932C13.518,2.8 14.63,2.065 15.773,2.291ZM3.406,9.215H6.219C6.997,9.215 7.625,9.838 7.625,10.608V20.357C7.625,21.128 6.997,21.75 6.219,21.75H3.406C2.628,21.75 2,21.128 2,20.357V10.608C2,9.838 2.628,9.215 3.406,9.215Z"
android:fillColor="#ffffff"/>
</group>
</vector>
4 changes: 4 additions & 0 deletions common/src/main/res/values-es/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,9 @@
<string name="referenda_search_toolbar_hint">Buscar por título de referendo o ID</string>
<string name="referenda_title">Referendos</string>
<string name="referendim_details_not_found_title">Referendo no encontrado</string>
<string name="referendum_abstain_vote_invalid_conviction_subtitle">Los votos de Abstención solo se pueden realizar con una convicción de 0.1x. ¿Votar con una convicción de 0.1x?</string>
<string name="referendum_abstain_vote_invalid_conviction_title">Actualización de la convicción</string>
<string name="referendum_abstain_voters_title">Votos de Abstención</string>
<string name="referendum_aye_format">A favor: %s</string>
<string name="referendum_dapp_list_title">Usar el navegador Nova DApp</string>
<string name="referendum_description_fallback">Solo el proponente puede editar esta descripción y el título. Si posees la cuenta del proponente, visita Polkassembly y completa la información sobre tu propuesta</string>
Expand Down Expand Up @@ -1127,6 +1130,7 @@
<string name="settings_twitter">Twitter</string>
<string name="settings_wiki">Wiki</string>
<string name="settings_youtube">Youtube</string>
<string name="setup_referendum_vote_conviction_info">La convicción se establecerá en 0.1x cuando se Abstenga</string>
<string name="setup_staking_conflict_message">No puedes hacer stake con Staking Directo y Pools de Nominación al mismo tiempo</string>
<string name="setup_staking_conflict_title">Ya estás en staking</string>
<string name="setup_staking_type_advanced_options_condition">Gestión avanzada de staking</string>
Expand Down
4 changes: 4 additions & 0 deletions common/src/main/res/values-fr-rFR/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,9 @@
<string name="referenda_search_toolbar_hint">Recherche par titre de référendum ou ID</string>
<string name="referenda_title">Référendums</string>
<string name="referendim_details_not_found_title">Référendum non trouvé</string>
<string name="referendum_abstain_vote_invalid_conviction_subtitle">Les votes d\'abstention ne peuvent se faire qu\'avec une conviction de 0,1x. Voter avec une conviction de 0,1x ?</string>
<string name="referendum_abstain_vote_invalid_conviction_title">Mise à jour de la conviction</string>
<string name="referendum_abstain_voters_title">Votes d\'abstention</string>
<string name="referendum_aye_format">Oui : %s</string>
<string name="referendum_dapp_list_title">Utiliser le navigateur Nova DApp</string>
<string name="referendum_description_fallback">Seul le proposant peut modifier cette description et le titre. Si vous possédez le compte du proposant, visitez Polkassembly et remplissez les informations relatives à votre proposition.</string>
Expand Down Expand Up @@ -1127,6 +1130,7 @@
<string name="settings_twitter">Twitter</string>
<string name="settings_wiki">Wiki</string>
<string name="settings_youtube">YouTube</string>
<string name="setup_referendum_vote_conviction_info">La conviction sera fixée à 0,1x lorsque vous vous abstenez</string>
<string name="setup_staking_conflict_message">Vous ne pouvez pas staker avec le Stake direct et les Pools de Nomination en même temps</string>
<string name="setup_staking_conflict_title">Déjà staké</string>
<string name="setup_staking_type_advanced_options_condition">Gestion avancée du staking</string>
Expand Down
Loading

0 comments on commit 2d31159

Please sign in to comment.