Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ public struct ErrorDetail: Sendable {
let errors = causes["errors"] as? [NSError],
let firstError = errors.first,
let subCauses = firstError.userInfo["causes"] as? [String: Any],
let ex = subCauses["exceptions"] as? [Any], !ex.isEmpty {
let exceptions = subCauses["exceptions"] as? [Any], !exceptions.isEmpty {

dict["exceptions"] = ex.map { "\($0)" }
dict["exceptions"] = exceptions.map { "\($0)" }
}

return dict
Expand Down
54 changes: 54 additions & 0 deletions RIADigiDoc/Supporting files/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -5088,6 +5088,24 @@
}
}
},
"PIN blocked unblock message" : {
"comment" : "My eID PIN unblock instructions error message",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Unblock to use the PIN again."
}
},
"et" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tühista blokeering, et PIN-i taas kasutada."
}
}
}
},
"PIN change failed" : {
"comment" : "OperationUnblockPin error",
"extractionState" : "manual",
Expand Down Expand Up @@ -5466,6 +5484,42 @@
}
}
},
"PUK blocked Thales" : {
"comment" : "My eID PUK blocked Thales message",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "PUK has been blocked because PUK code has been entered incorrectly 3 times. You can not unblock the PUK code yourself.\n\nAs long as the PUK code is blocked, all eID options can be used, except transactions that need PUK code.\n\nA new document must be requested to receive the new PUK code."
}
},
"et" : {
"stringUnit" : {
"state" : "translated",
"value" : "PUK on blokeeritud, kuna PUK-koodi on sisestatud 3 korda valesti. PUK-koodi ei saa ise lahti blokeerida.\n\nKuigi PUK-kood on blokeeritud, saab kõiki eID võimalusi kasutada, välja arvatud PUK-koodi vajavaid.\n\nUue PUK-koodi saamiseks tuleb taotleda uus dokument."
}
}
}
},
"PUK blocked Thales URL" : {
"comment" : "My eID PUK blocked Thales URL",
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "https://www.id.ee/en/article/changing-id-card-pin-codes-and-puk-code/"
}
},
"et" : {
"stringUnit" : {
"state" : "translated",
"value" : "https://www.id.ee/artikkel/id-kaardi-pin-ja-puk-koodide-muutmine/"
}
}
}
},
"PUK blocked URL" : {
"comment" : "My eID PUK blocked URL",
"extractionState" : "manual",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,9 @@ struct IdCardView: View {
.onDisappear {
pinNumber.removeAll()
Task {
await viewModel.stopDiscoveringReaders()
await MainActor.run {
viewModel.resetErrors()
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ struct PrimaryOutlinedButton: View {
.padding(Dimensions.Padding.XSPadding)
}
.frame(maxWidth: .infinity)
.padding(.vertical, Dimensions.Padding.XSPadding)
.background(
Capsule()
.fill(isButtonEnabled ? theme.surface : Color.gray)
Expand Down
10 changes: 6 additions & 4 deletions RIADigiDoc/UI/Component/My eID/MyEidPinChangeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,15 @@ struct MyEidPinChangeView: View {

let pin = Array(viewModel.input.utf8)

if !pin.isEmpty && viewModel
.isPINLengthValid(pin: pin) && viewModel.step == .new {
viewModel.verifyNewCode()
let currentCodeType = (pinAction == .unblock && viewModel.step == .current) ? .puk : codeType

if !pin.isEmpty && viewModel.isPINLengthValid(for: currentCodeType, pin: pin) &&
viewModel.step == .new {
viewModel.verifyNewCode()
}

return !inputErrorMessage.isEmpty ||
!viewModel.isPINLengthValid(pin: pin)
!viewModel.isPINLengthValid(for: currentCodeType, pin: pin)
}

init(
Expand Down
47 changes: 32 additions & 15 deletions RIADigiDoc/UI/Component/My eID/MyEidPinsAndCertificatesView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,29 @@ struct MyEidPinsAndCertificatesView: View {
var signCertValidTo: String
var isPUKChangeable: Bool

private var pukBlockedMessage: String {
languageSettings.localized(
isPUKChangeable ? "PUK blocked" : "PUK blocked Thales"
)
}

private var pukBlockedUrl: String {
languageSettings.localized("PUK blocked URL")
languageSettings.localized(
isPUKChangeable ? "PUK blocked URL" : "PUK blocked Thales URL"
)
}

private var pinBlockedMessage: String {
let pinBlockedText = languageSettings.localized(
"PIN blocked",
[CodeType.pin1.name]
)

if isPukBlocked {
return pinBlockedText
}

return "\(pinBlockedText) \(languageSettings.localized("PIN blocked unblock message", []))"
}

init(
Expand Down Expand Up @@ -79,12 +100,10 @@ struct MyEidPinsAndCertificatesView: View {
.opacity(opacityForPin1BlockedState)

if isPin1Blocked {
Text(verbatim: languageSettings.localized(
"PIN blocked", [CodeType.pin1.name])
)
.font(typography.bodySmall)
.foregroundStyle(theme.error)
.padding(.vertical, Dimensions.Padding.XSPadding)
Text(verbatim: pinBlockedMessage)
.font(typography.bodySmall)
.foregroundStyle(theme.error)
.padding(.vertical, Dimensions.Padding.XSPadding)
}
}
.padding(.vertical, Dimensions.Padding.SPadding)
Expand All @@ -98,7 +117,7 @@ struct MyEidPinsAndCertificatesView: View {
[signCertValidTo]
)
),
forgotPinText: isPin1Blocked ?
forgotPinText: isPin2Blocked ?
languageSettings.localized("Unblock PIN", [CodeType.pin2.name]) :
languageSettings.localized("Forgot PIN", [CodeType.pin2.name]),
changePinText: languageSettings
Expand All @@ -115,12 +134,10 @@ struct MyEidPinsAndCertificatesView: View {
.opacity(opacityForPin2BlockedState)

if isPin2Blocked {
Text(verbatim: languageSettings.localized(
"PIN blocked", [CodeType.pin2.name])
)
.font(typography.bodySmall)
.foregroundStyle(theme.error)
.padding(.vertical, Dimensions.Padding.XSPadding)
Text(verbatim: pinBlockedMessage)
.font(typography.bodySmall)
.foregroundStyle(theme.error)
.padding(.vertical, Dimensions.Padding.XSPadding)
}
}
.padding(.bottom, Dimensions.Padding.SPadding)
Expand All @@ -139,7 +156,7 @@ struct MyEidPinsAndCertificatesView: View {

if isPukBlocked {
VStack(alignment: .leading) {
Text(verbatim: languageSettings.localized("PUK blocked"))
Text(verbatim: pukBlockedMessage)
.font(typography.bodySmall)
.foregroundStyle(theme.error)
.padding(.vertical, Dimensions.Padding.XSPadding)
Expand Down
8 changes: 4 additions & 4 deletions RIADigiDoc/UI/Component/My eID/MyEidView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ struct MyEidView: View {
_viewModel = State(wrappedValue: Container.shared.myEidViewModel())
self.idCardData = idCardData

self._isPin1Blocked = State(initialValue: idCardData.retryCount.pin1 == 0)
self._isPin2Blocked = State(initialValue: idCardData.retryCount.pin2 == 0)
self._isPukBlocked = State(initialValue: idCardData.retryCount.puk == 0)
viewModel.setIsPinBlocked(.pin1, isBlocked: idCardData.retryCount.pin1 == 0)
viewModel.setIsPinBlocked(.pin2, isBlocked: idCardData.retryCount.pin2 == 0)
viewModel.setIsPinBlocked(.puk, isBlocked: idCardData.retryCount.puk == 0)
}

var body: some View {
Expand Down Expand Up @@ -204,7 +204,7 @@ struct MyEidView: View {
if viewModel.usbReaderStatus != .sCardConnected {
await viewModel.stopDiscoveringReaders()
await MainActor.run {
dismiss()
pathManager.replaceLast(to: .myEidRootView)
}
}
}
Expand Down
31 changes: 31 additions & 0 deletions RIADigiDoc/UI/Component/Shared/Extension/KeyboardExtensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2017 - 2025 Riigi Infosüsteemi Amet
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/

import SwiftUI

extension UIKeyboardType {
var needsDoneButton: Bool {
switch self {
case .numberPad, .decimalPad, .phonePad, .asciiCapableNumberPad:
return true
default:
return false
}
}
}
37 changes: 21 additions & 16 deletions RIADigiDoc/UI/Component/Shared/FloatingLabelTextField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import SwiftUI
import FactoryKit

struct FloatingLabelTextField: View {
@Environment(\.accessibilityVoiceOverEnabled) private var voiceOverEnabled
@Environment(\.sizeCategory) private var sizeCategory
@AppTheme private var theme
@AppTypography private var typography
Expand Down Expand Up @@ -285,14 +286,16 @@ struct FloatingLabelTextField: View {
)
}

Button(
action: {
fieldIsFocused = false
isAccessibilityFocused = true
onDone()
},
label: { Text(verbatim: languageSettings.localized("Done")) }
)
if keyboardType.needsDoneButton {
Button(
action: {
fieldIsFocused = false
isAccessibilityFocused = true
onDone()
},
label: { Text(verbatim: languageSettings.localized("Done")) }
)
}
}
}
}
Expand Down Expand Up @@ -326,14 +329,16 @@ struct FloatingLabelTextField: View {
)
}

Button(
action: {
fieldIsFocused = false
isAccessibilityFocused = true
onDone()
},
label: { Text(verbatim: languageSettings.localized("Done")) }
)
if keyboardType.needsDoneButton {
Button(
action: {
fieldIsFocused = false
isAccessibilityFocused = true
onDone()
},
label: { Text(verbatim: languageSettings.localized("Done")) }
)
}
}
}
}
Expand Down
15 changes: 12 additions & 3 deletions RIADigiDoc/ViewModel/FileOpeningViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,20 @@ class FileOpeningViewModel: FileOpeningViewModelProtocol, Loggable {
case .containerCreationFailed(let errorDetail),
.containerOpeningFailed(let errorDetail),
.containerSavingFailed(let errorDetail):
return ToastMessage(key: "Failed to open container", args: [errorDetail.userInfo["fileName"] as? String ?? ""])
return ToastMessage(
key: "Failed to open container",
args: [errorDetail.userInfo["fileName"] as? String ?? ""]
)
case .addingFilesToContainerFailed(let errorDetail):
return ToastMessage(key: "Failed to open file", args: [errorDetail.userInfo["fileName"] as? String ?? ""])
return ToastMessage(
key: "Failed to open file",
args: [errorDetail.userInfo["fileName"] as? String ?? ""]
)
case .containerDataFileSavingFailed(let errorDetail):
return ToastMessage(key: "Failed to save file", args: [errorDetail.userInfo["fileName"] as? String ?? ""])
return ToastMessage(
key: "Failed to save file",
args: [errorDetail.userInfo["fileName"] as? String ?? ""]
)
case .alreadyInitialized:
return ToastMessage(key: "Libdigidocpp is already initialized")
default:
Expand Down
6 changes: 4 additions & 2 deletions RIADigiDoc/ViewModel/MyEid/MyEidPinChangeViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ final class MyEidPinChangeViewModel: MyEidPinChangeViewModelProtocol, Loggable {
resetInputError()
}

func isPINLengthValid(pin: [UInt8]) -> Bool {
func isPINLengthValid(for codeType: CodeType, pin: [UInt8]) -> Bool {
guard codeType.validLength.contains(pin.count) else {
return false
}
Expand Down Expand Up @@ -268,7 +268,9 @@ final class MyEidPinChangeViewModel: MyEidPinChangeViewModelProtocol, Loggable {
sharedMyEidSession.setIsPinBlocked(codeType, isBlocked: true)
case .wrongPIN(let remaining):
errorMessage = remaining > 1 ? "PIN verification error multiple" : "PIN verification error one"
errorMessageExtraArguments = [codeType.name, String(remaining)]
errorMessageExtraArguments = [
pinAction == .change ? codeType.name : CodeType.puk.name, String(remaining)
]
resetToCurrentPinEntryStep()
default:
resetInputError()
Expand Down
4 changes: 4 additions & 0 deletions RIADigiDoc/ViewModel/MyEid/MyEidViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ class MyEidViewModel: MyEidViewModelProtocol, Loggable {
.date
}

public func setIsPinBlocked(_ codeType: CodeType, isBlocked: Bool) {
sharedMyEidSession.setIsPinBlocked(codeType, isBlocked: isBlocked)
}

public func getIsPinBlocked(for codeType: CodeType) -> Bool {
return sharedMyEidSession.getIsPinBlocked(for: codeType)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

import Foundation
import IdCardLib

@MainActor
protocol MyEidPinChangeViewModelProtocol: Sendable {
Expand All @@ -34,5 +35,5 @@ protocol MyEidPinChangeViewModelProtocol: Sendable {

func verifyNewCode()
func verifyRepeatedCode() -> Bool
func isPINLengthValid(pin: [UInt8]) -> Bool
func isPINLengthValid(for codeType: CodeType, pin: [UInt8]) -> Bool
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public protocol MyEidViewModelProtocol: Sendable {
func parseDateOfBirth(personalCode: String) -> String
func parseExpiryDate(expiryDate: String) -> String
func getDocumentExpirationStatus(expiryDate: String) -> MyEidDocumentStatus
func setIsPinBlocked(_ codeType: CodeType, isBlocked: Bool)
func getIsPinBlocked(for codeType: CodeType) -> Bool
func stopDiscoveringReaders() async
}