MOB-40 changed nav logic, refactored Home, Pin and Can fragments

This commit is contained in:
Henrik Lepson 2021-10-16 13:20:55 +03:00
parent 2678fd3c42
commit bd686739fc
13 changed files with 382 additions and 104 deletions

View File

@ -1,7 +1,6 @@
package com.tarkvaraprojekt.mobileauthapp
import android.app.AlertDialog
import android.content.DialogInterface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -15,7 +14,9 @@ import com.tarkvaraprojekt.mobileauthapp.databinding.FragmentCanBinding
import com.tarkvaraprojekt.mobileauthapp.model.SmartCardViewModel
/**
* Fragment that deals with asking the user for six digit CAN
* Fragment that deals with asking the user for a six digit CAN. If the CAN is already saved
* then the fragment is skipped immediately and if the CAN is not saved then the user
* is asked whether it should be saved for the future or not before continuing.
*/
class CanFragment : Fragment() {
@ -23,7 +24,10 @@ class CanFragment : Fragment() {
private var binding: FragmentCanBinding? = null
// Navigation arguments. saving = true means that we are navigating here from the settings menu and must return to the settings
// Navigation arguments:
// saving = true means that we are navigating here from the settings menu and must return to the settings menu.
// reading = true means that we are only reading the information from the ID card that does not need PIN 1,
// this information is passed on to the next PinFragment.
private val args: CanFragmentArgs by navArgs()
override fun onCreateView(
@ -37,62 +41,90 @@ class CanFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (viewModel.userCan.length == 6) {
skip()
}
checkIfSkip()
// If the user arrives from the settings menu then the button should say
// save instead of continue.
if (args.saving) {
binding!!.nextButton.text = getString(R.string.save_text)
}
binding!!.nextButton.setOnClickListener { goToNextFragment() }
binding!!.nextButton.setOnClickListener { checkEnteredCan() }
binding!!.cancelButton.setOnClickListener { goToTheStart() }
}
// If CAN is already set
private fun skip() {
findNavController().navigate(R.id.action_canFragment_to_pinFragment)
}
// Might need some rework, must break it up and make logic better.
private fun goToNextFragment() {
val enteredCan = binding!!.canEditText.editText?.text.toString()
if (enteredCan.length != 6) {
Toast.makeText(requireContext(), getString(R.string.length_can), Toast.LENGTH_SHORT)
.show()
} else {
viewModel.setUserCan(
binding!!.canEditText.editText?.text.toString()
)
if (args.saving) {
viewModel.storeCan(requireContext())
findNavController().navigate(R.id.action_canFragment_to_settingsFragment)
} else {
val canStoreQuestion: AlertDialog? = activity?.let { frag ->
val builder = AlertDialog.Builder(frag)
builder.apply {
setPositiveButton(R.string.save_text) { _, _ ->
viewModel.storeCan(
requireContext()
)
findNavController().navigate(R.id.action_canFragment_to_pinFragment)
}
setNegativeButton(R.string.deny_text) { _, _ ->
findNavController().navigate(R.id.action_canFragment_to_pinFragment)
}
}
builder.setMessage(R.string.can_save_request)
builder.setTitle(R.string.save_can_title)
builder.create()
}
canStoreQuestion?.show()
}
/**
* Checks if the current fragment can be skipped or not.
* If the user has CAN saved on the device there is no need to ask it again.
*/
private fun checkIfSkip() {
if (viewModel.userCan.length == 6) {
goToTheNextFragment()
}
}
/**
* Takes user to the next fragment, which is PinFragment.
*/
private fun goToTheNextFragment() {
val action = CanFragmentDirections.actionCanFragmentToPinFragment(reading = args.reading)
findNavController().navigate(action)
}
/**
* Checks whether the user has entered a 6 digit can to the input field.
* If yes then the user is allowed to continue otherwise the user is
* allowed to modify the entered can.
*/
private fun checkEnteredCan() {
val enteredCan = binding!!.canEditText.editText?.text.toString()
if (enteredCan.length == 6) {
viewModel.setUserCan(enteredCan)
if (args.saving) {
viewModel.storeCan(requireContext())
goToTheStart()
} else {
val storeCanQuestion = getDialog()
storeCanQuestion?.show()
}
} else {
Toast.makeText(requireContext(), getString(R.string.length_can), Toast.LENGTH_SHORT)
.show()
}
}
/**
* Builds a dialog that asks the user whether the entered CAN should be saved
* on the device or not.
*/
private fun getDialog(): AlertDialog? {
return activity?.let { frag ->
val builder = AlertDialog.Builder(frag)
builder.apply {
// If response is positive then save the CAN on the device.
setPositiveButton(R.string.save_text) { _, _ ->
viewModel.storeCan(
requireContext()
)
goToTheNextFragment()
}
setNegativeButton(R.string.deny_text) { _, _ ->
goToTheNextFragment()
}
}
builder.setMessage(R.string.can_save_request)
builder.setTitle(R.string.save_can_title)
builder.create()
}
}
/**
* Navigates the user back to the start depending on where the user arrived.
* If the user arrived from the settings menu then the start is the settings menu
* not the HomeFragment.
*/
private fun goToTheStart() {
if (args.saving) {
findNavController().navigate(R.id.action_canFragment_to_settingsFragment)
} else {
viewModel.clearUserInfo()
findNavController().navigate(R.id.action_canFragment_to_homeFragment)
}
}

View File

@ -1,7 +1,6 @@
package com.tarkvaraprojekt.mobileauthapp
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -11,6 +10,13 @@ import androidx.navigation.fragment.findNavController
import com.tarkvaraprojekt.mobileauthapp.databinding.FragmentHomeBinding
import com.tarkvaraprojekt.mobileauthapp.model.SmartCardViewModel
/**
* HomeFragment is only shown to the user when then the user launches the application. When the application
* is launched by another application or a website then this Fragment will be skipped.
* This fragment uses the fields from the MainActivity by casting the activity to MainActivity.
* This might not be the best practice, but the application uses a single activity design so it should
* always work.
*/
class HomeFragment : Fragment() {
private val viewModel: SmartCardViewModel by activityViewModels()
@ -23,18 +29,72 @@ class HomeFragment : Fragment() {
savedInstanceState: Bundle?
): View? {
binding = FragmentHomeBinding.inflate(inflater, container, false)
// Making settings menu active again
(activity as MainActivity).menuAvailable = true
return binding!!.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel.checkCan(requireContext())
viewModel.checkPin(requireContext())
binding!!.beginButton.setOnClickListener { goToNextFragment() }
initialChecks()
binding!!.beginButton.setOnClickListener { goToTheNextFragment() }
}
private fun goToNextFragment() {
findNavController().navigate(R.id.action_homeFragment_to_canFragment)
/**
* Method where all the initial checks that should be done before any user input is accepted should be added.
*/
private fun initialChecks() {
viewModel.checkCan(requireContext())
viewModel.checkPin(requireContext())
displayStates()
}
/**
* Starts the process of interacting with the ID card by sending user to the CAN fragment.
*/
private fun goToTheNextFragment() {
// Making settings menu inactive
(activity as MainActivity).menuAvailable = false
// Currently saving is true because the application is not yet integrated with
// other applications or websites.
val action = HomeFragmentDirections.actionHomeFragmentToCanFragment(reading = true)
findNavController().navigate(action)
}
/**
* Displays texts that inform the user whether the CAN and PIN 1 are saved on the device or not.
* This might help the user to save some time as checking menu is not necessary unless the user
* wishes to make changes to the saved CAN or PIN 1.
*/
private fun displayStates() {
canState()
pinState()
}
/**
* Checks the state of the CAN, saved or not saved. Updates the text and logo.
*/
private fun canState() {
if (viewModel.userCan.length == 6) {
binding!!.canStatusText.text = getString(R.string.can_status_saved)
binding!!.canStatusLogo.setImageResource(R.drawable.ic_check_logo)
} else {
binding!!.canStatusText.text = getString(R.string.can_status_negative)
binding!!.canStatusLogo.setImageResource(R.drawable.ic_info_logo)
}
}
/**
* Checks the state of the PIN 1, saved or not saved. Updates the text and logo.
*/
private fun pinState() {
if (viewModel.userPin.length in 4..12) {
binding!!.pinStatusText.text = getString(R.string.pin_status_saved)
binding!!.pinStatusLogo.setImageResource(R.drawable.ic_check_logo)
} else {
binding!!.pinStatusText.text = getString(R.string.pin_status_negative)
binding!!.pinStatusLogo.setImageResource(R.drawable.ic_info_logo)
}
}
override fun onDestroyView() {

View File

@ -1,22 +1,25 @@
package com.tarkvaraprojekt.mobileauthapp
import android.nfc.NfcAdapter
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
import com.tarkvaraprojekt.mobileauthapp.databinding.ActivityMainBinding
import java.util.*
/**
* The only activity of the application (single activity design).
*/
class MainActivity : AppCompatActivity() {
private lateinit var navigationController: NavController
// If true the settings menu can be accessed from the toolbar in the upper part of the screen.
var menuAvailable: Boolean = true
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater)
@ -35,10 +38,14 @@ class MainActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.menu_settings_option -> {
navigationController.navigate(R.id.action_homeFragment_to_settingsFragment)
true
if (menuAvailable) {
navigationController.navigate(R.id.action_homeFragment_to_settingsFragment)
true
} else {
Toast.makeText(this, getString(R.string.unavailable), Toast.LENGTH_SHORT).show()
false
}
}
else -> super.onOptionsItemSelected(item)
}
}

View File

@ -14,7 +14,9 @@ import com.tarkvaraprojekt.mobileauthapp.databinding.FragmentPinBinding
import com.tarkvaraprojekt.mobileauthapp.model.SmartCardViewModel
/**
* Fragment that deals with asking the user for PIN1
* Fragment that deals with asking the user for PIN 1. If the user has already saved the PIN 1 then it is not asked again
* and the fragment is skipped and if the PIN 1 is not saved then the user is asked whether it should be saved or
* not before continuing.
*/
class PinFragment : Fragment() {
@ -22,7 +24,10 @@ class PinFragment : Fragment() {
private var binding: FragmentPinBinding? = null
// Navigation arguments. saving = true means that we are navigating here from the settings menu and must return to the settings
// Navigation arguments:
// saving = true means that the user must be returned to the settings menu
// reading = true means that we are reading information from the ID card that does
// not require PIN 1 so it is not necessary to ask it.
private val args: CanFragmentArgs by navArgs()
override fun onCreateView(
@ -36,48 +41,51 @@ class PinFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (viewModel.userPin.length in 4..12) {
skip()
}
checkIfSkip()
// If the user arrives from the settings menu then the button says
// save instead of continue.
if (args.saving) {
binding!!.nextButton.text = getString(R.string.save_text)
}
binding!!.nextButton.setOnClickListener { goToNextFragment() }
binding!!.nextButton.setOnClickListener { checkEnteredPin() }
binding!!.cancelButton.setOnClickListener { goToTheStart() }
}
private fun skip() {
/**
* Checks if the current fragment can be skipped or not.
* If the user has PIN 1 saved on the device or PIN 1 is not required
* then the PIN 1 won't be asked.
*/
private fun checkIfSkip() {
if (args.reading) {
goToTheNextFragment()
} else if (viewModel.userPin.length in 4..12) {
goToTheNextFragment()
}
}
/**
* Takes user to the next fragment, which is AuthFragment.
*/
private fun goToTheNextFragment() {
findNavController().navigate(R.id.action_pinFragment_to_authFragment)
}
private fun goToNextFragment() {
val enteredPin1 = binding!!.pinEditText.editText?.text.toString()
if (enteredPin1.length in 4..12) {
viewModel.setUserPin(
binding!!.pinEditText.editText?.text.toString()
)
/**
* Checks whether the user has entered a PIN 1 with length between [4, 12] in the
* input field. If yes then the user is allowed to continue otherwise the user is
* allowed to modify the entered PIN 1.
*/
private fun checkEnteredPin() {
val enteredPin = binding!!.pinEditText.editText?.text.toString()
if (enteredPin.length in 4..12) {
viewModel.setUserPin(enteredPin)
if (args.saving) {
viewModel.storePin(requireContext())
findNavController().navigate(R.id.action_pinFragment_to_settingsFragment)
goToTheStart()
} else {
val canStoreQuestion: AlertDialog? = activity?.let { frag ->
val builder = AlertDialog.Builder(frag)
builder.apply {
setPositiveButton(R.string.save_text) { _, _ ->
viewModel.storePin(
requireContext()
)
findNavController().navigate(R.id.action_pinFragment_to_authFragment)
}
setNegativeButton(R.string.deny_text) { _, _ ->
findNavController().navigate(R.id.action_pinFragment_to_authFragment)
}
}
builder.setMessage(R.string.pin_save_request)
builder.setTitle(R.string.save_pin_title)
builder.create()
}
canStoreQuestion?.show()
val storePinQuestion = getDialog()
storePinQuestion?.show()
}
} else {
Toast.makeText(requireContext(), getString(R.string.length_pin), Toast.LENGTH_SHORT)
@ -85,6 +93,35 @@ class PinFragment : Fragment() {
}
}
/**
* Builds a dialog that asks the user whether the entered PIN 1 should be saved
* on the device or not.
*/
private fun getDialog(): AlertDialog? {
return activity?.let { frag ->
val builder = AlertDialog.Builder(frag)
builder.apply {
// If response is positive save the PIN 1 on the device.
setPositiveButton(R.string.save_text) { _, _ ->
viewModel.storePin(
requireContext()
)
goToTheNextFragment()
}
setNegativeButton(R.string.deny_text) { _, _ ->
goToTheNextFragment()
}
}
builder.setMessage(R.string.pin_save_request)
builder.setTitle(R.string.save_pin_title)
builder.create()
}
}
/**
* Returns user to the start. If the user arrived from the settings menu then the start is
* settings menu not the HomeFragment.
*/
private fun goToTheStart() {
if (args.saving) {
findNavController().navigate(R.id.action_pinFragment_to_settingsFragment)

View File

@ -42,6 +42,7 @@ class SettingsFragment : Fragment() {
binding!!.canMenuAction.setOnClickListener { canAction() }
binding!!.pinMenuAction.setOnClickListener { pinAction() }
binding!!.pinMenuShow.setOnClickListener { togglePin() }
binding!!.returnButton.setOnClickListener { backToHome() }
}
/**
@ -66,7 +67,7 @@ class SettingsFragment : Fragment() {
viewModel.deleteCan(requireContext())
showCanField()
} else {
val action = SettingsFragmentDirections.actionSettingsFragmentToCanFragment(true)
val action = SettingsFragmentDirections.actionSettingsFragmentToCanFragment(saving = true)
findNavController().navigate(action)
}
}
@ -100,7 +101,7 @@ class SettingsFragment : Fragment() {
viewModel.deletePin(requireContext())
showPinField()
} else {
val action = SettingsFragmentDirections.actionSettingsFragmentToPinFragment(true)
val action = SettingsFragmentDirections.actionSettingsFragmentToPinFragment(saving = true)
findNavController().navigate(action)
}
}
@ -125,6 +126,13 @@ class SettingsFragment : Fragment() {
}
}
/**
* Navigates back to home fragment.
*/
private fun backToHome() {
findNavController().navigate(R.id.action_settingsFragment_to_homeFragment)
}
override fun onDestroy() {
super.onDestroy()
binding = null

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z"/>
</vector>

View File

@ -7,23 +7,87 @@
android:padding="24dp"
tools:context=".HomeFragment">
<TextView
android:id="@+id/home_fragment_text"
android:layout_width="wrap_content"
<LinearLayout
android:id="@+id/saved_states"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/home_fragment"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<com.google.android.material.card.MaterialCardView
android:id="@+id/can_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
app:strokeWidth="1dp"
app:strokeColor="@color/stroke_color"
app:cardElevation="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/can_status_logo"
android:layout_marginStart="12dp"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/can_status_text"
android:textSize="20sp"
android:padding="12dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:id="@+id/pin_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
app:strokeWidth="1dp"
app:strokeColor="@color/stroke_color"
app:cardElevation="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/pin_status_logo"
android:layout_marginStart="12dp"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/pin_status_text"
android:textSize="20sp"
android:padding="12dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
<!-- Temporary button for testing purposes -->
<Button
android:id="@+id/begin_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/begin_text"
android:layout_marginTop="24dp"
app:layout_constraintTop_toBottomOf="@id/home_fragment_text"
android:textSize="18sp"
app:layout_constraintTop_toBottomOf="@id/saved_states"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>

View File

@ -33,6 +33,7 @@
<Button
android:id="@+id/can_menu_action"
android:layout_margin="12dp"
android:textSize="18sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
@ -49,11 +50,13 @@
<Button
android:id="@+id/pin_menu_action"
android:layout_margin="12dp"
android:textSize="18sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/pin_menu_show"
android:layout_margin="12dp"
android:textSize="18sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/>
@ -61,4 +64,14 @@
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<Button
android:id="@+id/return_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/return_text"
android:layout_margin="24dp"
android:textSize="18sp"
app:layout_constraintTop_toBottomOf="@id/settings_card"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -42,6 +42,10 @@
android:id="@+id/action_pinFragment_to_authFragment"
app:destination="@id/authFragment"
app:popUpTo="@id/homeFragment" />
<argument
android:name="reading"
app:argType="boolean"
android:defaultValue="false" />
</fragment>
<fragment
android:id="@+id/canFragment"
@ -66,6 +70,10 @@
android:id="@+id/action_canFragment_to_pinFragment"
app:destination="@id/pinFragment"
app:popUpTo="@id/homeFragment" />
<argument
android:name="reading"
app:argType="boolean"
android:defaultValue="false" />
</fragment>
<fragment
android:id="@+id/authFragment"
@ -104,5 +112,10 @@
<action
android:id="@+id/action_settingsFragment_to_pinFragment"
app:destination="@id/pinFragment" />
<action
android:id="@+id/action_settingsFragment_to_homeFragment"
app:destination="@id/homeFragment"
app:popUpTo="@id/homeFragment"
app:popUpToInclusive="true" />
</fragment>
</navigation>

View File

@ -4,11 +4,18 @@
<string name="app_name">NFC authentication</string>
<string name="home_fragment">Work in progress</string>
<string name="begin_text">ALUSTA</string>
<!-- string resources for HomeFragment -->
<string name="pin_status_saved">PIN 1 on salvestatud</string>
<string name="pin_status_negative">PIN 1 ei ole salvestatud</string>
<string name="can_status_saved">CAN on salvestatud</string>
<string name="can_status_negative">CAN ei ole salvestatud</string>
<string name="begin_text">LOE ID KAARTI</string>
<string name="next_text">EDASI</string>
<string name="cancel_text">KATKESTA</string>
<string name="save_text">SALVESTA</string>
<string name="deny_text">EI</string>
<string name="return_text">TAGASI</string>
<!-- string resources for PinFragment -->
<string name="pin_fragment">Palun sisesta PIN 1</string>
@ -54,4 +61,5 @@
<string name="show">NÄITA</string>
<string name="hide">PEIDA</string>
<string name="hidden_pin">****</string>
<string name="unavailable">Seaded pole hetkel saadaval</string>
</resources>

View File

@ -3,11 +3,18 @@
<string name="app_name">NFC authentication</string>
<string name="home_fragment">Work in progress</string>
<string name="begin_text">ALUSTA</string>
<string name="begin_text">LOE ID KAARTI</string>
<string name="next_text">EDASI</string>
<string name="cancel_text">KATKESTA</string>
<string name="save_text">SALVESTA</string>
<string name="deny_text">EI</string>
<string name="return_text">TAGASI</string>
<!-- string resources for HomeFragment -->
<string name="pin_status_saved">PIN 1 on salvestatud</string>
<string name="pin_status_negative">PIN 1 ei ole salvestatud</string>
<string name="can_status_saved">CAN on salvestatud</string>
<string name="can_status_negative">CAN ei ole salvestatud</string>
<!-- string resources for PinFragment -->
<string name="pin_fragment">Palun sisesta PIN 1</string>
@ -52,4 +59,5 @@
<string name="show">NÄITA</string>
<string name="hide">PEIDA</string>
<string name="hidden_pin">****</string>
<string name="unavailable">Seaded pole hetkel saadaval</string>
</resources>

View File

@ -2,11 +2,18 @@
<string name="app_name">NFC authentication</string>
<string name="home_fragment">Work in progress</string>
<string name="begin_text">ALUSTA</string>
<string name="begin_text">LOE ID KAARTI</string>
<string name="next_text">EDASI</string>
<string name="cancel_text">KATKESTA</string>
<string name="save_text">SALVESTA</string>
<string name="deny_text">EI</string>
<string name="return_text">TAGASI</string>
<!-- string resources for HomeFragment -->
<string name="pin_status_saved">PIN 1 on salvestatud</string>
<string name="pin_status_negative">PIN 1 ei ole salvestatud</string>
<string name="can_status_saved">CAN on salvestatud</string>
<string name="can_status_negative">CAN ei ole salvestatud</string>
<!-- string resources for PinFragment -->
<string name="pin_fragment">Palun sisesta PIN 1</string>
@ -52,4 +59,5 @@
<string name="show">NÄITA</string>
<string name="hide">PEIDA</string>
<string name="hidden_pin">****</string>
<string name="unavailable">Seaded pole hetkel saadaval</string>
</resources>