Browse Source

Merge branch '4_multiLanguage_Biometric'

Conflicts:
	GMERemittance/Module/SendMoney/SendMoneyVerification/User Interface/View/SendMoneyVerificationViewController.swift
pull/1/head
james 5 years ago
parent
commit
c45c41713a
  1. 308
      GMERemittance/AppDelegate 2.swift
  2. 2
      GMERemittance/AppDelegate.swift
  3. 207
      GMERemittance/Module/BiometricAuthModules/BiometricAuthentication/User Interface/View/BiometricAuthenticationViewController.swift
  4. 2
      GMERemittance/Module/BiometricAuthModules/BiometricAuthentication/User Interface/Wireframe/BiometricAuthenticationWireframe.swift
  5. 7
      GMERemittance/Module/BiometricAuthModules/BiometricAuthenticationNotification/User Interface/View/BiometricAuthenticationNotification.storyboard
  6. 92
      GMERemittance/Module/BiometricAuthModules/BiometricAuthenticationNotification/User Interface/View/BiometricAuthenticationNotificationViewController.swift
  7. 4
      GMERemittance/SideMenu/SettingViewController.swift
  8. 14
      en.lproj/Localizable.strings

308
GMERemittance/AppDelegate 2.swift

@ -0,0 +1,308 @@
//
// AppDelegate.swift
// GMERemittance
//
// Created by Fm-user on 11/30/17.
// Copyright © 2017 Gobal Money Express Co. Ltd. All rights reserved.
//
import UIKit
import Firebase
import FirebaseAuth
import UserNotifications
import FirebaseInstanceID
import FirebaseMessaging
import BRYXBanner
import Fabric
import Crashlytics
import AlamofireNetworkActivityLogger
import IQKeyboardManagerSwift
import LGSideMenuController
import Localize_Swift
let server: Server = .uat2
var overlayView: UIView?
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {
var window: UIWindow?
let gcmMessageIDKey = "gcm_message_id"
var firstTranscationStatusForHome:Bool?
var firstTranscationStatusForProfileForm:Bool?
var cmRegistrationId: String?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
UIApplication.shared.applicationIconBadgeNumber = 0
firstTranscationStatusForHome = true
firstTranscationStatusForProfileForm = true
NetworkActivityLogger.shared.startLogging()
NetworkActivityLogger.shared.level = .debug
IQKeyboardManager.shared.enable = true
IQKeyboardManager.shared.shouldResignOnTouchOutside = true
FirebaseApp.configure()
Fabric.with([Crashlytics.self])
Fabric.sharedSDK().debug = true
Messaging.messaging().delegate = self
registerForNotification(application: application)
setUUID()
setupNavBar()
setupStatusBar()
setEntryPoint()
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self
} else {
// Fallback on earlier versions
}
return true
}
private func setUUID() {
if UserDefaults.standard.string(forKey: AppConstants.uuid) == nil {
let uuid = UUID().uuidString
UserDefaults.standard.set(uuid, forKey: AppConstants.uuid)
}
}
private func setupStatusBar() {
// let statusBar: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
// if statusBar.responds(to:#selector(setter: UIView.backgroundColor)) {
// statusBar.backgroundColor = UIColor.blue
// }
}
private func setupNavBar() {
let appearance = UINavigationBar.appearance()
appearance.backIndicatorImage = #imageLiteral(resourceName: "backIconBlack")
appearance.backIndicatorTransitionMaskImage = #imageLiteral(resourceName: "backIconBlack")
appearance.tintColor = UIColor.black
}
private func setEntryPoint() {
// check user status
guard let _ = KeyChain.shared.get(key: .email),
(KeyChain.shared.get(key: .login) ?? "1") == "1" ? true : false else {
self.goSplashScreen()
return
}
let biometricAuthenticationWireframe = BiometricAuthenticationWireframe()
biometricAuthenticationWireframe.openWithDelegate(
on: self.window!,
delegate: self
)
}
private func registerForNotification(application: UIApplication) {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerForRemoteNotifications()
application.registerUserNotificationSettings(settings)
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
if userInfo[gcmMessageIDKey] != nil {
}
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
cmRegistrationId = fcmToken
print(fcmToken)
}
func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
print(remoteMessage.appData)
}
public func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
}
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// var userInfo = notification.request.content.userInfo
// if let aps = userInfo["aps"] as? NSDictionary,
// let alert = aps["alert"] as? NSDictionary,
// let body = alert["body"] as? String,
// let title = alert["title"] as? String {
// let image = UIImage.init(named: "ic_gme")
// let banner = Banner(title: title, subtitle: body, image: image, backgroundColor: UIColor(red:0.93, green:0.11, blue:0.14, alpha:1.0))
// banner.show(duration: 5.0)
// }
completionHandler(
[UNNotificationPresentationOptions.alert,
UNNotificationPresentationOptions.sound,
UNNotificationPresentationOptions.badge])
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
// print("Unable to register for remote notifications: \(error.localizedDescription)")
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
}
/**
method for redirection of page when push notification tap
*/
func applicationDidEnterBackground(_ application: UIApplication) {
let store = UserDefaults.standard
let language = Localize.currentLanguage()
store.set(language, forKey: AppConstants.currentLanguage)
let viewcontroller = UIViewController()
viewcontroller.view.backgroundColor = AppConstants.themeRedColor
viewcontroller.view.frame = UIScreen.main.bounds
overlayView = viewcontroller.view
guard let view = overlayView else {return}
let topView = UIApplication.shared.keyWindow?.subviews.last
topView?.addSubview(view)
topView?.bringSubview(toFront: view)
}
func applicationWillEnterForeground(_ application: UIApplication) {
if let language = UserDefaults.standard.string(forKey: AppConstants.currentLanguage) {
Localize.setCurrentLanguage(language)
}
overlayView?.removeFromSuperview()
}
private func doLogin(){
self.window?.rootViewController?.showProgressHud()
let loginService = LoginService()
guard let userID = KeyChain.shared.get(key: .email),
let password = KeyChain.shared.get(key: .password) else {
self.goSplashScreen()
return
}
loginService._login(
userId: userID,
password: password,
success: { (user) in
let accessCode = user?.accessCode ?? ""
let accessCodeBase64 = accessCode
Utility.save(user: user, accessCodeBase64: accessCodeBase64, password: password, login: true)
let mainWireFrame = MainWireframe.shared
let tabBarViewController = mainWireFrame?.getMainView()
let sidemenuVc = UIStoryboard(name: "SideMenu", bundle: nil).instantiateViewController(withIdentifier: "SideMenuViewController") as! SideMenuViewController
let sideMenuController = LGSideMenuController(rootViewController: tabBarViewController, leftViewController: sidemenuVc, rightViewController: nil)
sideMenuController.rootViewLayerShadowColor = UIColor(white: 0.9, alpha: 0.6)
sideMenuController.rootViewLayerShadowRadius = 8.0
sideMenuController.leftViewPresentationStyle = .scaleFromBig
sideMenuController.leftViewWidth = UIScreen.main.bounds.width - 70.0
if #available(iOS 10.0, *) {
sideMenuController.leftViewBackgroundBlurEffect = UIBlurEffect(style: .regular)
} else {
// Fallback on earlier versions
}
self.window?.rootViewController?.hideProgressHud()
self.window?.backgroundColor = sidemenuVc.view.backgroundColor
self.window?.rootViewController = sideMenuController
}) { (error) in
self.window?.rootViewController?.hideProgressHud()
self.window?.rootViewController?.alert(message: error.localizedDescription, title: "Warning"){
// if failed login, remove all in keychain, change logout status and then go splash screen
KeyChain.shared.removeAll()
self.goSplashScreen()
}
}
}
private func goSplashScreen() {
let splashWireframe = SplashScreenWireframe()
let nav = UINavigationController.init(rootViewController: splashWireframe.getMainView())
self.window?.rootViewController = nav
}
}
// MARK: - BiometricAuthenticationViewControllerDelegate
extension AppDelegate: BiometricAuthenticationViewControllerDelegate{
func viewController(_ viewController: BiometricAuthenticationViewController, informationTitleLabel titleLabel: UILabel) {
titleLabel.text = "bio_login_intro".localized()
}
func didComplete(_ viewController: BiometricAuthenticationViewController) {
self.doLogin()
}
func viewController(_ viewController: BiometricAuthenticationViewController, didFailWithError error: Error, errorMessage: String?) {
print("BiometricAuthenticationWireframe Error: \(errorMessage ?? "")")
// if don't use biometric authentication or user press password
DispatchQueue.main.async {
if let error = error as? BiometricAuthenticationError {
switch error {
case .biometryNotAvailable, .userFallback:
let secureKeypad = SecureKeypad(target: viewController)
secureKeypad.title = "Password of your account"
secureKeypad.placeholder = "Enter your password for login"
secureKeypad.placeholderFont = UIFont(name: "Arial", size: 15)
secureKeypad.delegate = self
secureKeypad.present(animated: true)
default:
break
}
}
}
}
func doSelectLocalAuthenticationPolicy(_ viewController: BiometricAuthenticationViewController) -> BiometricAuthenticationPolicy{
return .deviceOwnerAuthenticationWithBiometrics
}
}
// MARK: - SecureKeypadDelegate
extension AppDelegate: SecureKeypadDelegate {
func didComplete(_ encryptedString: String) {
if encryptedString != "" {
KeyChain.shared.save(data: encryptedString, key: .password)
self.doLogin()
}
}
}

2
GMERemittance/AppDelegate.swift

@ -259,7 +259,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// MARK: - BiometricAuthenticationViewControllerDelegate
extension AppDelegate: BiometricAuthenticationViewControllerDelegate{
func viewController(_ viewController: BiometricAuthenticationViewController, informationTitleLabel titleLabel: UILabel) {
titleLabel.text = "bio_login_intro".localized()
titleLabel.text = "bio_login_intro_text".localized()
}
func didComplete(_ viewController: BiometricAuthenticationViewController) {

207
GMERemittance/Module/BiometricAuthModules/BiometricAuthentication/User Interface/View/BiometricAuthenticationViewController.swift

@ -10,125 +10,126 @@ import UIKit
import LocalAuthentication
enum BiometricAuthenticationPolicy {
case deviceOwnerAuthentication
case deviceOwnerAuthenticationWithBiometrics
case deviceOwnerAuthentication
case deviceOwnerAuthenticationWithBiometrics
}
enum BiometricAuthenticationError: Error {
case authenticationFailed
case userCancel
case userFallback
case biometryNotAvailable
case biometryNotEnrolled
case biometryLockout
case notBeConfigured
var message: String {
let msg: String
switch self {
case .authenticationFailed:
msg = "There was a problem verifying your identity."
case .userCancel:
msg = "You pressed cancel."
case .userFallback:
msg = "You pressed password."
case .biometryNotAvailable:
msg = "Face ID/Touch ID is not available."
case .biometryNotEnrolled:
msg = "Face ID/Touch ID is not set up."
case .biometryLockout:
msg = "Face ID/Touch ID is locked."
default:
msg = "Face ID/Touch ID may not be configured"
}
return msg
case authenticationFailed
case userCancel
case userFallback
case biometryNotAvailable
case biometryNotEnrolled
case biometryLockout
case notBeConfigured
var message: String {
let msg: String
switch self {
case .authenticationFailed:
msg = "There was a problem verifying your identity."
case .userCancel:
msg = "You pressed cancel."
case .userFallback:
msg = "You pressed password."
case .biometryNotAvailable:
msg = "Face ID/Touch ID is not available."
case .biometryNotEnrolled:
msg = "Face ID/Touch ID is not set up."
case .biometryLockout:
msg = "Face ID/Touch ID is locked."
default:
msg = "Face ID/Touch ID may not be configured"
}
return msg
}
}
protocol BiometricAuthenticationViewControllerDelegate: class{
func doSelectLocalAuthenticationPolicy(_ viewController: BiometricAuthenticationViewController) -> BiometricAuthenticationPolicy
func viewController(_ viewController: BiometricAuthenticationViewController, informationTitleLabel titleLabel: UILabel )
func didComplete(_ viewController: BiometricAuthenticationViewController)
func viewController(_ viewController: BiometricAuthenticationViewController, didFailWithError error: Error, errorMessage: String?)
func doSelectLocalAuthenticationPolicy(_ viewController: BiometricAuthenticationViewController) -> BiometricAuthenticationPolicy
func viewController(_ viewController: BiometricAuthenticationViewController, informationTitleLabel titleLabel: UILabel )
func didComplete(_ viewController: BiometricAuthenticationViewController)
func viewController(_ viewController: BiometricAuthenticationViewController, didFailWithError error: Error, errorMessage: String?)
}
extension BiometricAuthenticationViewControllerDelegate {
func doSelectLocalAuthenticationPolicy(_ viewController: BiometricAuthenticationViewController) -> BiometricAuthenticationPolicy{
return .deviceOwnerAuthentication
}
func doSelectLocalAuthenticationPolicy(_ viewController: BiometricAuthenticationViewController) -> BiometricAuthenticationPolicy{
return .deviceOwnerAuthentication
}
}
final class BiometricAuthenticationViewController: UIViewController, BiometricAuthenticationViewInterface {
// MARK: Properties
var presenter: BiometricAuthenticationModuleInterface?
weak var delegate: BiometricAuthenticationViewControllerDelegate?
private var isViewDidLoad = true
// MARK: IBOutlets
@IBOutlet private weak var biometricAuthenticationImageButton: UIButton!
@IBOutlet private weak var informationLabel: UILabel!
// MARK: VC's Life cycle
override func viewDidLoad() {
super.viewDidLoad()
self.setup()
// MARK: Properties
var presenter: BiometricAuthenticationModuleInterface?
weak var delegate: BiometricAuthenticationViewControllerDelegate?
private var isViewDidLoad = true
// MARK: IBOutlets
@IBOutlet private weak var biometricAuthenticationImageButton: UIButton!
@IBOutlet private weak var informationLabel: UILabel!
// MARK: VC's Life cycle
override func viewDidLoad() {
super.viewDidLoad()
self.setup()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if self.isViewDidLoad{
self.showAuthentication()
self.isViewDidLoad = false
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if self.isViewDidLoad{
self.showAuthentication()
self.isViewDidLoad = false
}
}
// MARK: IBActions
@IBAction private func authenticationButtonTouch(_ sender: Any) {
self.showAuthentication()
}
// MARK: Other Functions
private func setup() {
// all setup should be done here
self.setUI()
self.delegate?.viewController(self, informationTitleLabel: self.informationLabel)
}
private func setUI(){
setBackground()
biometricAuthenticationImageButton.rounded()
}
private func setBackground(){
self.view.backgroundColor = AppConstants.themeRedColor
}
private func showAuthentication(){
}
// MARK: IBActions
@IBAction private func authenticationButtonTouch(_ sender: Any) {
self.showAuthentication()
}
// MARK: Other Functions
private func setup() {
// all setup should be done here
self.setUI()
self.delegate?.viewController(self, informationTitleLabel: self.informationLabel)
}
private func setUI(){
setBackground()
biometricAuthenticationImageButton.rounded()
biometricAuthenticationImageButton.setTitle("bio_press_button_title_text".localized(), for: .normal)
}
private func setBackground(){
self.view.backgroundColor = AppConstants.themeRedColor
}
private func showAuthentication(){
guard
let isUseBiometricAuth = KeyChain.shared.get(key: .biometricAuth),
isUseBiometricAuth == "1" else {
let error = BiometricAuthenticationError.biometryNotAvailable
guard
let isUseBiometricAuth = KeyChain.shared.get(key: .biometricAuth),
isUseBiometricAuth == "1" else {
let error = BiometricAuthenticationError.biometryNotAvailable
self.delegate?.viewController(
self,
didFailWithError: error,
errorMessage: error.message
)
return
}
self.presenter?.showBiometricAuthentication()
self.delegate?.viewController(
self,
didFailWithError: error,
errorMessage: error.message
)
return
}
self.presenter?.showBiometricAuthentication()
}
}

2
GMERemittance/Module/BiometricAuthModules/BiometricAuthentication/User Interface/Wireframe/BiometricAuthenticationWireframe.swift

@ -38,7 +38,7 @@ extension BiometricAuthenticationWireframe: BiometricAuthenticationWireframeInpu
let context = LAContext()
var error: NSError?
let msg = "Confirm your fingerprint or face to authenticate."
let msg = "bio_message_title_text".localized()
let vc = self.view as? BiometricAuthenticationViewController ?? BiometricAuthenticationViewController()

7
GMERemittance/Module/BiometricAuthModules/BiometricAuthenticationNotification/User Interface/View/BiometricAuthenticationNotification.storyboard

@ -104,8 +104,8 @@
</view>
</subviews>
</stackView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="(manual: Settings -&gt; Use FaceID &amp; TouchID)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xFc-vx-98G">
<rect key="frame" x="59" y="424.5" width="257.5" height="17"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="(Manual: Settings -&gt; Use FaceID &amp; TouchID)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xFc-vx-98G">
<rect key="frame" x="59.5" y="424.5" width="256.5" height="17"/>
<fontDescription key="fontDescription" name="SanFranciscoDisplay-Regular" family="San Francisco Display" pointSize="14"/>
<color key="textColor" red="0.18823529410000001" green="0.24313725489999999" blue="0.62352941179999999" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
@ -128,6 +128,9 @@
<viewLayoutGuide key="safeArea" id="n22-XI-gDD"/>
</view>
<connections>
<outlet property="contentLabel" destination="sEb-0Y-7MN" id="Ept-ly-T9u"/>
<outlet property="manualLabel" destination="xFc-vx-98G" id="dmg-iB-AHt"/>
<outlet property="titleLabel" destination="FJX-hI-Ewa" id="zwL-G4-yRQ"/>
<outlet property="useBiometricAuthButton" destination="H6Q-aV-Mdd" id="2GS-d3-GuJ"/>
<outlet property="usePasswordButton" destination="X1c-21-gtS" id="FeD-RW-RZN"/>
</connections>

92
GMERemittance/Module/BiometricAuthModules/BiometricAuthenticationNotification/User Interface/View/BiometricAuthenticationNotificationViewController.swift

@ -9,50 +9,64 @@
import UIKit
class BiometricAuthenticationNotificationViewController: UIViewController {
// MARK: Properties
var presenter: BiometricAuthenticationNotificationModuleInterface?
// MARK: IBOutlets
@IBOutlet weak var useBiometricAuthButton: UIButton!
@IBOutlet weak var usePasswordButton: UIButton!
// MARK: VC's Life cycle
override func viewDidLoad() {
super.viewDidLoad()
self.setup()
}
// MARK: IBActions
@IBAction func touchUseBiometricAuth(_ sender: UIButton) {
BiometricAuthenticationWireframe().showBiometricAuthentication() { error in
if error != nil {
KeyChain.shared.save(data: "0", key: .biometricAuth)
} else {
KeyChain.shared.save(data: "1", key: .biometricAuth)
}
self.dismiss(animated: true, completion: nil)
}
}
@IBAction func touchUsePassword(_ sender: UIButton) {
// MARK: Properties
var presenter: BiometricAuthenticationNotificationModuleInterface?
// MARK: IBOutlets
@IBOutlet weak var useBiometricAuthButton: UIButton!
@IBOutlet weak var usePasswordButton: UIButton!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var contentLabel: UILabel!
@IBOutlet weak var manualLabel: UILabel!
// MARK: VC's Life cycle
override func viewDidLoad() {
super.viewDidLoad()
self.setup()
}
// MARK: IBActions
@IBAction func touchUseBiometricAuth(_ sender: UIButton) {
BiometricAuthenticationWireframe().showBiometricAuthentication() { error in
if error != nil {
KeyChain.shared.save(data: "0", key: .biometricAuth)
self.dismiss(animated: true, completion: nil)
} else {
KeyChain.shared.save(data: "1", key: .biometricAuth)
}
self.dismiss(animated: true, completion: nil)
}
// MARK: Other Functions
}
@IBAction func touchUsePassword(_ sender: UIButton) {
KeyChain.shared.save(data: "0", key: .biometricAuth)
self.dismiss(animated: true, completion: nil)
}
// MARK: Other Functions
private func setup() {
// all setup should be done here
useBiometricAuthButton.rounded()
usePasswordButton.rounded()
private func setup() {
// all setup should be done here
useBiometricAuthButton.rounded()
usePasswordButton.rounded()
}
setMultiLanguage()
}
private func setMultiLanguage() {
titleLabel.text = "biometric_noti_title_text".localized()
contentLabel.text = "biometric_noti_content_text".localized()
manualLabel.text = "biometric_noti_manual_text".localized()
usePasswordButton.setTitle("biometric_noti_biometric_use_button_text", for: .normal)
usePasswordButton.setTitle("biometric_noti_password_use_button_text", for: .normal)
}
}
// MARK: BiometricAuthenticationNotificationViewInterface
extension BiometricAuthenticationNotificationViewController: BiometricAuthenticationNotificationViewInterface {
}

4
GMERemittance/SideMenu/SettingViewController.swift

@ -106,13 +106,13 @@ class SettingViewController: UIViewController {
self.changePasswordButton.setTitle("change_password_text".localized(), for: .normal)
self.settingButton.setTitle("language_text".localized(), for: .normal)
self.settingLabel.text = "setting_text".localized()
useBiometricAuthLabel.text = "use_biometric_authentication".localized()
useBiometricAuthLabel.text = "use_biometric_authentication_text".localized()
}
private func configureLanguage() {
self.changePasswordButton.setTitle("change_password_text".localized(), for: .normal)
self.settingButton.setTitle("language_text".localized(), for: .normal)
useBiometricAuthLabel.text = "use_biometric_authentication".localized()
useBiometricAuthLabel.text = "use_biometric_authentication_text".localized()
}
func setupLanguages() {

14
en.lproj/Localizable.strings

@ -415,8 +415,18 @@
"referral_code_text" = "Referral Code (Optional)";
// Biometric authenticaton
"use_biometric_authentication" = "Use TouchID & FaceID";
"bio_login_intro" = "Please enter authentication information for login";
"use_biometric_authentication_text" = "Use FaceID & TouchID";
"bio_login_intro_text" = "Please enter authentication information for login";
"bio_sendmoney_intro_text" = "Please enter authentication information for Remittance";
"bio_message_title_text" = "Confirm your FaceID or TouchID to authenticate.";
"bio_press_button_title_text" = ">> Press to authenticate";
// Biometric authentication notification
"biometric_noti_title_text" = "If use FaceID & TouchID, can quickly and securely use app";
"biometric_noti_content_text" = "Remember, only registered users with FaceID & TouchID can use these app.";
"biometric_noti_manual_text" = "(Manual: Settings -> Use FaceID & TouchID)";
"biometric_noti_biometric_use_button_text" = "Use FaceID & TouchID";
"biometric_noti_password_use_button_text" = "Continue only using password";
// RewardGroup
"reward_group_title_text" = "Reward";

Loading…
Cancel
Save