Skip to content

Commit 3dbc816

Browse files
committed
Merge branch 'develop' into 'master'
Develop See merge request papers/airgap/airgap-vault!403
2 parents e6ae6f2 + 2d105ee commit 3dbc816

File tree

10 files changed

+140
-94
lines changed

10 files changed

+140
-94
lines changed

android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ android {
3737
kotlinOptions {
3838
jvmTarget = '11'
3939
}
40-
lintOptions {
40+
lint {
4141
abortOnError false
4242
}
4343
}
@@ -72,7 +72,7 @@ dependencies {
7272
def fragmentVersion = "1.4.0"
7373
implementation("androidx.fragment:fragment-ktx:$fragmentVersion")
7474

75-
def biometricVersion = "1.2.0-alpha04"
75+
def biometricVersion = "1.2.0-alpha05"
7676
implementation("androidx.biometric:biometric:$biometricVersion")
7777

7878
def coroutinesVersion = "1.6.0"

android/app/src/main/java/it/airgap/vault/plugin/securityutils/authprompt/AuthPromptFragment.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@ import androidx.fragment.app.Fragment
1010
import it.airgap.vault.R
1111
import kotlinx.coroutines.CompletableDeferred
1212
import kotlinx.coroutines.Deferred
13+
import java.util.concurrent.atomic.AtomicInteger
1314

1415
class AuthPromptFragment : Fragment(R.layout.fragment_authenticator) {
1516

1617
private val _resultDeferred: CompletableDeferred<Boolean> = CompletableDeferred()
1718
val resultDeferred: Deferred<Boolean>
1819
get() = _resultDeferred
1920

21+
private val attempts: AtomicInteger = AtomicInteger(0)
22+
2023
private var _biometricPromptInfo: BiometricPrompt.PromptInfo? = null
2124
private val biometricPromptInfo: BiometricPrompt.PromptInfo
2225
get() = _biometricPromptInfo ?: BiometricPrompt.PromptInfo.Builder().apply {
@@ -37,17 +40,21 @@ class AuthPromptFragment : Fragment(R.layout.fragment_authenticator) {
3740
BiometricPrompt(this, executor, object : BiometricPrompt.AuthenticationCallback() {
3841
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
3942
super.onAuthenticationError(errorCode, errString)
43+
attempts.set(0)
4044
_resultDeferred.complete(false)
4145
}
4246

4347
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
4448
super.onAuthenticationSucceeded(result)
49+
attempts.set(0)
4550
_resultDeferred.complete(true)
4651
}
4752

4853
override fun onAuthenticationFailed() {
4954
super.onAuthenticationFailed()
50-
_resultDeferred.complete(false)
55+
if (attempts.incrementAndGet() >= MAX_AUTH_TRIES) {
56+
_resultDeferred.complete(false)
57+
}
5158
}
5259
})
5360
}.also { _biometricPrompt = it }
@@ -64,4 +71,8 @@ class AuthPromptFragment : Fragment(R.layout.fragment_authenticator) {
6471

6572
super.onDestroyView()
6673
}
74+
75+
companion object {
76+
private const val MAX_AUTH_TRIES = 3
77+
}
6778
}

android/build.gradle

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ allprojects {
2525
mavenCentral()
2626
maven { url 'https://jitpack.io' }
2727
}
28+
afterEvaluate {
29+
if (getPlugins().hasPlugin('android') ||
30+
getPlugins().hasPlugin('android-library')) {
31+
configure(android.lint) {
32+
abortOnError false
33+
}
34+
}
35+
}
2836
}
2937

3038
task clean(type: Delete) {

android/variables.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
ext {
22
minSdkVersion = 22
3-
compileSdkVersion = 32
4-
targetSdkVersion = 32
3+
compileSdkVersion = 33
4+
targetSdkVersion = 33
55
androidxActivityVersion = '1.4.0'
66
androidxAppCompatVersion = '1.4.2'
77
androidxCoordinatorLayoutVersion = '1.2.0'

package.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,23 @@
3838
"apply-diagnostic-modules": "node apply-diagnostic-modules.js"
3939
},
4040
"dependencies": {
41-
"@airgap/aeternity": "0.13.9",
41+
"@airgap/aeternity": "0.13.10",
4242
"@airgap/angular-core": "0.0.34",
4343
"@airgap/angular-ngrx": "0.0.34",
44-
"@airgap/astar": "0.13.9",
45-
"@airgap/bitcoin": "0.13.9",
46-
"@airgap/coinlib-core": "0.13.9",
47-
"@airgap/cosmos": "0.13.9",
48-
"@airgap/ethereum": "0.13.9",
49-
"@airgap/groestlcoin": "0.13.9",
50-
"@airgap/icp": "0.13.9",
51-
"@airgap/module-kit": "0.13.9",
52-
"@airgap/moonbeam": "0.13.9",
53-
"@airgap/polkadot": "0.13.9",
44+
"@airgap/astar": "0.13.10",
45+
"@airgap/bitcoin": "0.13.10",
46+
"@airgap/coinlib-core": "0.13.10",
47+
"@airgap/cosmos": "0.13.10",
48+
"@airgap/ethereum": "0.13.10",
49+
"@airgap/groestlcoin": "0.13.10",
50+
"@airgap/icp": "0.13.10",
51+
"@airgap/module-kit": "0.13.10",
52+
"@airgap/moonbeam": "0.13.10",
53+
"@airgap/polkadot": "0.13.10",
5454
"@airgap/sapling-wasm": "0.0.7",
55-
"@airgap/serializer": "0.13.9",
56-
"@airgap/substrate": "0.13.9",
57-
"@airgap/tezos": "0.13.9",
55+
"@airgap/serializer": "0.13.10",
56+
"@airgap/substrate": "0.13.10",
57+
"@airgap/tezos": "0.13.10",
5858
"@angular/common": "13.2.5",
5959
"@angular/core": "13.2.5",
6060
"@angular/forms": "13.2.5",

src/app/app.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ export class AppComponent implements AfterViewInit {
106106
const protocol: string = data.url.substr(DEEPLINK_VAULT_ADD_ACCOUNT.length)
107107
if (protocol.length > 0) {
108108
this.navigationService
109-
.routeWithState('account-add', { protocol })
109+
.routeWithState('account-add', { protocol, secret: secrets[0] })
110110
.catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION))
111111
} else {
112112
this.navigationService.route('account-add').catch(handleErrorLocal(ErrorCategory.IONIC_NAVIGATION))

src/app/pages/account-add/account-add.page.ts

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Component } from '@angular/core'
22
import { ModalController, AlertController } from '@ionic/angular'
3-
import { ICoinProtocol, MainProtocolSymbols, ProtocolSymbols } from '@airgap/coinlib-core'
3+
import { ICoinProtocol, ProtocolSymbols } from '@airgap/coinlib-core'
44

55
import { ErrorCategory, handleErrorLocal } from '../../services/error-handler/error-handler.service'
66
import { NavigationService } from '../../services/navigation/navigation.service'
@@ -62,9 +62,7 @@ export class AccountAddPage {
6262
const state = this.navigationService.getState()
6363
this.secret = state.secret
6464
this.protocolService.getActiveProtocols().then(async (protocols: ICoinProtocol[]) => {
65-
const navigationIdentifier: ProtocolSymbols | undefined = (this.navigationService.getState().protocol)
66-
? await this.navigationService.getState().protocol.getIdentifier()
67-
: undefined
65+
const navigationIdentifier: ProtocolSymbols | undefined = state.protocol
6866

6967
this.protocolList = await Promise.all(protocols.map(async (protocol) => {
7068
const [symbol, identifier, name, supportsHD] = await Promise.all([
@@ -73,17 +71,13 @@ export class AccountAddPage {
7371
protocol.getName(),
7472
protocol.getSupportsHD()
7573
])
74+
const isChecked = navigationIdentifier === identifier
7675

77-
const isChecked =
78-
identifier === MainProtocolSymbols.BTC_SEGWIT ||
79-
identifier === MainProtocolSymbols.ETH ||
80-
navigationIdentifier === identifier
81-
82-
return {
83-
protocol,
84-
isHDWallet: supportsHD,
85-
customDerivationPath: undefined,
86-
isChecked: isChecked,
76+
return {
77+
protocol,
78+
isHDWallet: supportsHD,
79+
customDerivationPath: undefined,
80+
isChecked: isChecked,
8781
details: { symbol, identifier, name }
8882
}
8983
}))

src/app/pages/secret-add/secret-add.page.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { MnemonicSecret } from '../../models/secret'
88
import { ErrorCategory, handleErrorLocal } from '../../services/error-handler/error-handler.service'
99
import { NavigationService } from '../../services/navigation/navigation.service'
1010
import { SecretsService } from '../../services/secrets/secrets.service'
11+
import { UiEventService } from '@airgap/angular-core'
1112

1213
@Component({
1314
selector: 'airgap-secret-add',
@@ -32,7 +33,8 @@ export class SecretAddPage {
3233
private readonly navigationService: NavigationService,
3334
private readonly platform: Platform,
3435
private readonly lifehashService: LifehashService,
35-
private readonly storageService: VaultStorageService
36+
private readonly storageService: VaultStorageService,
37+
private readonly uiEventService: UiEventService
3638
) {
3739
if (this.navigationService.getState()) {
3840
this.isGenerating = this.navigationService.getState().isGenerating
@@ -51,8 +53,11 @@ export class SecretAddPage {
5153
} catch (error) {
5254
handleErrorLocal(ErrorCategory.SECURE_STORAGE)(error)
5355

54-
// TODO: Show error
55-
this.navigationService.routeToSecretsTab()
56+
if (error.message !== 'Already added secret' /* a workaround to avoid prompting 2 alerts */) {
57+
await this.showErrorAlert()
58+
} else {
59+
this.navigationService.routeToSecretsTab()
60+
}
5661
return
5762
}
5863

@@ -62,4 +67,26 @@ export class SecretAddPage {
6267
public async togglePasscode(): Promise<void> {
6368
this.secret.isParanoia = !this.secret.isParanoia
6469
}
70+
71+
private async showErrorAlert() {
72+
const alert = await this.uiEventService.getTranslatedAlert({
73+
header: 'secret-edit.error_alert.title',
74+
message: 'secret-edit.error_alert.message',
75+
backdropDismiss: true,
76+
buttons: [
77+
{
78+
text: 'secret-edit.error_alert.abort-button_label',
79+
handler: () => {
80+
this.navigationService.routeToSecretsTab()
81+
}
82+
},
83+
{
84+
text: 'secret-edit.error_alert.retry-button_label',
85+
role: 'cancel'
86+
}
87+
]
88+
})
89+
90+
await alert.present().catch(handleErrorLocal(ErrorCategory.IONIC_ALERT))
91+
}
6592
}

src/assets/i18n/en.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,13 @@
155155
"copied": "Recovery key copied",
156156
"reset-error": "Could not set the recovery key"
157157
},
158-
"confirm_label": "Confirm"
158+
"confirm_label": "Confirm",
159+
"error_alert": {
160+
"title": "Error",
161+
"message": "Something went wrong!",
162+
"abort-button_label": "Abort",
163+
"retry-button_label": "Retry"
164+
}
159165
},
160166
"secret-service": {
161167
"alert": {

0 commit comments

Comments
 (0)