Commit e71f1048 authored by jzhang's avatar jzhang

增加本地语言包 首页搭建

parent 854599e0
......@@ -44,6 +44,13 @@
EA14360528E0BF1900FFBE72 /* DemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA14360428E0BF1900FFBE72 /* DemoViewController.swift */; };
EA14360828E0CA3100FFBE72 /* LanguageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA14360628E0CA3100FFBE72 /* LanguageCell.swift */; };
EA14360928E0CA3100FFBE72 /* LanguageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = EA14360728E0CA3100FFBE72 /* LanguageCell.xib */; };
EA8F42C328EE998000983014 /* StringLyingGestureIntroduce.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA8F42BF28EE998000983014 /* StringLyingGestureIntroduce.swift */; };
EA8F42C428EE998000983014 /* StringSittingGestureIntroduce.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA8F42C028EE998000983014 /* StringSittingGestureIntroduce.swift */; };
EA8F42C528EE998000983014 /* StringModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA8F42C128EE998000983014 /* StringModel.swift */; };
EA8F42C628EE998000983014 /* StringLyingGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA8F42C228EE998000983014 /* StringLyingGesture.swift */; };
EA8F42CB28EE99D900983014 /* string_english.json in Resources */ = {isa = PBXBuildFile; fileRef = EA8F42C828EE99D900983014 /* string_english.json */; };
EA8F42CC28EE99D900983014 /* string_french.json in Resources */ = {isa = PBXBuildFile; fileRef = EA8F42C928EE99D900983014 /* string_french.json */; };
EA8F42CD28EE99D900983014 /* string_spanish.json in Resources */ = {isa = PBXBuildFile; fileRef = EA8F42CA28EE99D900983014 /* string_spanish.json */; };
EAD8102728E207A4002A86C9 /* MyTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD8102628E207A4002A86C9 /* MyTools.swift */; };
EAD8102D28E20A54002A86C9 /* PermissionAlertVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD8102C28E20A54002A86C9 /* PermissionAlertVC.swift */; };
/* End PBXBuildFile section */
......@@ -103,6 +110,13 @@
EA14360428E0BF1900FFBE72 /* DemoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoViewController.swift; sourceTree = "<group>"; };
EA14360628E0CA3100FFBE72 /* LanguageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanguageCell.swift; sourceTree = "<group>"; };
EA14360728E0CA3100FFBE72 /* LanguageCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LanguageCell.xib; sourceTree = "<group>"; };
EA8F42BF28EE998000983014 /* StringLyingGestureIntroduce.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringLyingGestureIntroduce.swift; sourceTree = "<group>"; };
EA8F42C028EE998000983014 /* StringSittingGestureIntroduce.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringSittingGestureIntroduce.swift; sourceTree = "<group>"; };
EA8F42C128EE998000983014 /* StringModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringModel.swift; sourceTree = "<group>"; };
EA8F42C228EE998000983014 /* StringLyingGesture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringLyingGesture.swift; sourceTree = "<group>"; };
EA8F42C828EE99D900983014 /* string_english.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = string_english.json; sourceTree = "<group>"; };
EA8F42C928EE99D900983014 /* string_french.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = string_french.json; sourceTree = "<group>"; };
EA8F42CA28EE99D900983014 /* string_spanish.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = string_spanish.json; sourceTree = "<group>"; };
EAD8102628E207A4002A86C9 /* MyTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyTools.swift; sourceTree = "<group>"; };
EAD8102C28E20A54002A86C9 /* PermissionAlertVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionAlertVC.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
......@@ -131,20 +145,20 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
692EC41B284C8D5F0043E3EA /* Lauguage */ = {
692EC41B284C8D5F0043E3EA /* LanguagePackage */ = {
isa = PBXGroup;
children = (
692EC41E284C8D6F0043E3EA /* english.json */,
692EC41D284C8D6F0043E3EA /* french.json */,
692EC41F284C8D6F0043E3EA /* spanish.json */,
);
path = Lauguage;
path = LanguagePackage;
sourceTree = "<group>";
};
694B85AF2848EB4C009BEDE1 = {
isa = PBXGroup;
children = (
692EC41B284C8D5F0043E3EA /* Lauguage */,
EA8F42BD28EE98A000983014 /* Utilities */,
694B85CF2848EB68009BEDE1 /* Flutter */,
694B85BA2848EB4C009BEDE1 /* BreastFeedingDemo */,
694B85B92848EB4C009BEDE1 /* Products */,
......@@ -168,7 +182,6 @@
694B85BB2848EB4C009BEDE1 /* AppDelegate.swift */,
694B85BD2848EB4C009BEDE1 /* SceneDelegate.swift */,
694B85BF2848EB4C009BEDE1 /* ViewController.swift */,
EAD8102628E207A4002A86C9 /* MyTools.swift */,
692EC419284C81700043E3EA /* ViewModel.swift */,
EA14360628E0CA3100FFBE72 /* LanguageCell.swift */,
EA14360728E0CA3100FFBE72 /* LanguageCell.xib */,
......@@ -183,6 +196,7 @@
694B85CF2848EB68009BEDE1 /* Flutter */ = {
isa = PBXGroup;
children = (
692EC41B284C8D5F0043E3EA /* LanguagePackage */,
690F28872852317500EB63F1 /* yuvtransform.xcframework */,
694B85D42848EBB1009BEDE1 /* App.xcframework */,
694B85D52848EBB1009BEDE1 /* camera.xcframework */,
......@@ -216,6 +230,37 @@
path = Pods;
sourceTree = "<group>";
};
EA8F42BD28EE98A000983014 /* Utilities */ = {
isa = PBXGroup;
children = (
EA8F42C728EE99D900983014 /* StringFiles */,
EA8F42BE28EE998000983014 /* StringModel */,
EAD8102628E207A4002A86C9 /* MyTools.swift */,
);
path = Utilities;
sourceTree = "<group>";
};
EA8F42BE28EE998000983014 /* StringModel */ = {
isa = PBXGroup;
children = (
EA8F42BF28EE998000983014 /* StringLyingGestureIntroduce.swift */,
EA8F42C028EE998000983014 /* StringSittingGestureIntroduce.swift */,
EA8F42C128EE998000983014 /* StringModel.swift */,
EA8F42C228EE998000983014 /* StringLyingGesture.swift */,
);
path = StringModel;
sourceTree = "<group>";
};
EA8F42C728EE99D900983014 /* StringFiles */ = {
isa = PBXGroup;
children = (
EA8F42C828EE99D900983014 /* string_english.json */,
EA8F42C928EE99D900983014 /* string_french.json */,
EA8F42CA28EE99D900983014 /* string_spanish.json */,
);
path = StringFiles;
sourceTree = "<group>";
};
EAFC261B28E2144600F802FE /* ViewController */ = {
isa = PBXGroup;
children = (
......@@ -287,9 +332,12 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
EA8F42CC28EE99D900983014 /* string_french.json in Resources */,
694B85C82848EB4E009BEDE1 /* LaunchScreen.storyboard in Resources */,
692EC421284C8D6F0043E3EA /* french.json in Resources */,
EA8F42CB28EE99D900983014 /* string_english.json in Resources */,
694B85C52848EB4E009BEDE1 /* Assets.xcassets in Resources */,
EA8F42CD28EE99D900983014 /* string_spanish.json in Resources */,
EA14360928E0CA3100FFBE72 /* LanguageCell.xib in Resources */,
694B85C32848EB4C009BEDE1 /* Main.storyboard in Resources */,
692EC423284C8D6F0043E3EA /* spanish.json in Resources */,
......@@ -346,12 +394,16 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
EA8F42C528EE998000983014 /* StringModel.swift in Sources */,
694B85C02848EB4C009BEDE1 /* ViewController.swift in Sources */,
694B85BC2848EB4C009BEDE1 /* AppDelegate.swift in Sources */,
EA8F42C328EE998000983014 /* StringLyingGestureIntroduce.swift in Sources */,
697B07ED284F2E5C0051FC23 /* CompleteVC.swift in Sources */,
EA8F42C628EE998000983014 /* StringLyingGesture.swift in Sources */,
EA14360528E0BF1900FFBE72 /* DemoViewController.swift in Sources */,
692EC41A284C81700043E3EA /* ViewModel.swift in Sources */,
EAD8102D28E20A54002A86C9 /* PermissionAlertVC.swift in Sources */,
EA8F42C428EE998000983014 /* StringSittingGestureIntroduce.swift in Sources */,
EA14360828E0CA3100FFBE72 /* LanguageCell.swift in Sources */,
694B85BE2848EB4C009BEDE1 /* SceneDelegate.swift in Sources */,
EAD8102728E207A4002A86C9 /* MyTools.swift in Sources */,
......
......@@ -28,15 +28,15 @@ class ViewController: UIViewController {
var isFirstLoad: Bool = true
fileprivate func updateUI() {
titleL.text = vm.landingPageTitle
stepL1.text = vm.landingPageStep1
stepL2.text = vm.landingPageStep2
stepL3.text = vm.landingPageStep3
permissionText.text = vm.cameraText1
permissionTitle.text = vm.cameraText
permissionOKBtn.setTitle(vm.cameraButtonText, for: .normal)
startBtn.setTitle(vm.landingPageStart, for: .normal)
// titleL.text = vm.landingPageTitle
// stepL1.text = vm.landingPageStep1
// stepL2.text = vm.landingPageStep2
// stepL3.text = vm.landingPageStep3
//
// permissionText.text = vm.cameraText1
// permissionTitle.text = vm.cameraText
// permissionOKBtn.setTitle(vm.cameraButtonText, for: .normal)
// startBtn.setTitle(vm.landingPageStart, for: .normal)
panelV.layer.cornerRadius = 8
permissionPanel.layer.cornerRadius = 8
permissionPanel.clipsToBounds = true
......@@ -107,7 +107,7 @@ class ViewController: UIViewController {
func toCompleteVC() {
let sb = UIStoryboard(name: "Main", bundle: nil)
let vc = sb.instantiateViewController(withIdentifier: "CompleteVC") as! CompleteVC
vc.vm = vm
// vc.vm = vm
navigationController?.pushViewController(vc, animated: true)
}
......@@ -142,35 +142,35 @@ class ViewController: UIViewController {
(panelV.viewWithTag(1001) as! UIButton).isSelected = false
(panelV.viewWithTag(1002) as! UIButton).isSelected = false
switch vm.language {
case .english:
(panelV.viewWithTag(1000) as! UIButton).isSelected = true
case .français:
(panelV.viewWithTag(1001) as! UIButton).isSelected = true
case .español:
(panelV.viewWithTag(1002) as! UIButton).isSelected = true
}
// switch vm.language {
// case .english:
// (panelV.viewWithTag(1000) as! UIButton).isSelected = true
// case .français:
// (panelV.viewWithTag(1001) as! UIButton).isSelected = true
// case .español:
// (panelV.viewWithTag(1002) as! UIButton).isSelected = true
// }
}
@IBAction func dismissPermissimPanel(_: Any) {
permisionPopupV.isHidden = true
}
@IBAction func selectLanguage(_ sender: UIButton) {
switch sender.tag {
case 1000:
vm.language = .english
case 1001:
vm.language = .français
case 1002:
vm.language = .español
default:
break
}
switchBtn.isSelected = false
popupView.isHidden = true
updateUI()
}
// @IBAction func selectLanguage(_ sender: UIButton) {
// switch sender.tag {
// case 1000:
// vm.language = .english
// case 1001:
// vm.language = .français
// case 1002:
// vm.language = .español
// default:
// break
// }
//
// switchBtn.isSelected = false
// popupView.isHidden = true
//
// updateUI()
// }
}
......@@ -8,7 +8,6 @@
import UIKit
class CompleteVC: UIViewController {
var vm: ViewModel?
@IBOutlet var containerV: UIView!
@IBOutlet var titleL: UILabel!
......@@ -17,8 +16,8 @@ class CompleteVC: UIViewController {
super.viewDidLoad()
overrideUserInterfaceStyle = .light
containerV.layer.cornerRadius = 8
titleL.text = vm?.congratulation
btn.setTitle(vm?.completeBtn, for: .normal)
titleL.text = viewModel.string.completeText
btn.setTitle(viewModel.string.cameraButtonText, for: .normal)
}
@IBAction func okAction(_: Any) {
......
......@@ -14,12 +14,18 @@ import ZJTableViewManager
class DemoViewController: UIViewController {
fileprivate var popover: Popover!
fileprivate var manager: ZJTableViewManager!
lazy var vm: ViewModel = .init()
@IBOutlet var titleL: UILabel!
@IBOutlet var stepL1: UILabel!
@IBOutlet var stepL2: UILabel!
@IBOutlet var stepL3: UILabel!
@IBOutlet var scrollView: UIScrollView!
@IBOutlet weak var sittingTitleL: UILabel!
@IBOutlet weak var sittingSubtitleL: UILabel!
@IBOutlet weak var lyingTitleL: UILabel!
@IBOutlet weak var lyingSubtitleL: UILabel!
@IBOutlet weak var topConstraint: NSLayoutConstraint!
var methodChannel: FlutterMethodChannel?
var isFirstLoad: Bool = true
......@@ -28,21 +34,33 @@ class DemoViewController: UIViewController {
overrideUserInterfaceStyle = .light
UIApplication.shared.isIdleTimerDisabled = true
navigationController?.setNavigationBarHidden(true, animated: false)
scrollView.automaticallyAdjustsScrollIndicatorInsets = false
scrollView.contentInsetAdjustmentBehavior = .never
updateUI()
flutterInitialize()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
topConstraint.constant = view.safeAreaInsets.top
}
fileprivate func updateUI() {
titleL.text = vm.landingPageTitle
stepL1.text = vm.landingPageStep1
stepL2.text = vm.landingPageStep2
stepL3.text = vm.landingPageStep3
titleL.text = viewModel.string.homeTitle
stepL1.text = viewModel.string.homeText1
stepL2.text = viewModel.string.homeText2
stepL3.text = viewModel.string.homeText3
sittingTitleL.text = viewModel.string.sittingGesture.title
sittingSubtitleL.text = viewModel.string.sittingGesture.subTitle
lyingTitleL.text = viewModel.string.lyingGesture.title
lyingSubtitleL.text = viewModel.string.lyingGesture.subTitle
}
/// 切换根据选择的语言更新UI
/// - Parameter language: 语言
fileprivate func updateUI(language: ViewModel.Language) {
vm.language = language
viewModel.language = language
updateUI()
}
......@@ -52,7 +70,6 @@ class DemoViewController: UIViewController {
let vc = sb.instantiateViewController(withIdentifier: "PermissionAlertVC") as! PermissionAlertVC
vc.modalPresentationStyle = .overCurrentContext
vc.vm = vm
present(vc, animated: true)
}
......@@ -81,7 +98,7 @@ class DemoViewController: UIViewController {
if let strongSelf = self {
switch call.method {
case "init":
result(strongSelf.vm.flutterArguments)
result(viewModel.flutterArguments)
case "teachingEnd":
strongSelf.methodChannel?.invokeMethod("dispose", arguments: nil)
// ["totalDuration": 3, "reasonText": Concern about my personal privacy, "status": incomplete, "incompleteReasonCode": 2]
......@@ -109,7 +126,6 @@ class DemoViewController: UIViewController {
func toCompleteVC() {
let sb = UIStoryboard(name: "Main", bundle: nil)
let vc = sb.instantiateViewController(withIdentifier: "CompleteVC") as! CompleteVC
vc.vm = vm
navigationController?.pushViewController(vc, animated: true)
}
......@@ -147,7 +163,7 @@ extension DemoViewController {
for i in ViewModel.Language.allCases {
let item = LanguageCellItem(language: i)
section.add(item: item)
if i == vm.language {
if i == viewModel.language {
currentItem = item
}
item.setSelectionHandler { [weak self] (callBackItem: LanguageCellItem) in
......
......@@ -12,14 +12,13 @@ class PermissionAlertVC: UIViewController {
@IBOutlet var permissionTitle: UILabel!
@IBOutlet var permissionText: UILabel!
@IBOutlet var permissionOKBtn: UIButton!
var vm: ViewModel = .init()
override func viewDidLoad() {
super.viewDidLoad()
overrideUserInterfaceStyle = .light
permissionText.text = vm.cameraText1
permissionTitle.text = vm.cameraText
permissionOKBtn.setTitle(vm.cameraButtonText, for: .normal)
permissionText.text = viewModel.string.cameraText1
permissionTitle.text = viewModel.string.cameraText
permissionOKBtn.setTitle(viewModel.string.cameraButtonText, for: .normal)
permissionPanel.layer.cornerRadius = 8
permissionPanel.clipsToBounds = true
......
......@@ -11,8 +11,8 @@ class ViewModel {
/// 语言枚举,enum代表语言包文件名,rawValue代表语言选项
enum Language: String, CaseIterable {
case english = "English"
case français = "Français"
case español = "Español"
case french = "Français"
case spanish = "Español"
}
var env: String = "testing"
......@@ -24,17 +24,19 @@ class ViewModel {
setupText()
}
}
var string: StringModel!
var landingPageTitle: String?
var landingPageStep1: String?
var landingPageStep2: String?
var landingPageStep3: String?
var landingPageStart: String?
var congratulation: String?
var completeBtn: String?
var cameraText: String?
var cameraText1: String?
var cameraButtonText: String?
// var landingPageTitle: String?
// var landingPageStep1: String?
// var landingPageStep2: String?
// var landingPageStep3: String?
// var landingPageStart: String?
// var congratulation: String?
// var completeBtn: String?
// var cameraText: String?
// var cameraText1: String?
// var cameraButtonText: String?
var languagePack: [String: Any] {
let languageFile = "\(language)".appending(".json")
......@@ -64,40 +66,48 @@ class ViewModel {
}
fileprivate func setupText() {
switch language {
case .english:
landingPageTitle = "Breastfeeding posture AI coach"
landingPageStep1 = "Put your device on a stable surface"
landingPageStep2 = "Keep one meter away from the camera, and fit your body into the guide line. Session starts in 5 seconds after you click \"Start Now\" button"
landingPageStep3 = "Camera permission is needed for AI coach. Your clothes will not affect the AI coach"
landingPageStart = "Start Now"
congratulation = "Congratulations!"
completeBtn = "OK"
cameraText = "Camera not detected"
cameraText1 = "Camera disabled. Please grant camera permission first!"
cameraButtonText = "OK"
case .français:
landingPageTitle = "Coach AI en posture d'allaitement"
landingPageStep1 = "Placez votre appareil sur une surface stable"
landingPageStep2 = "Tenez-vous à un mètre de la caméra et placez votre corps dans la ligne de guidage. La session démarre dans 5 secondes après avoir cliqué sur le bouton \"Démarrer maintenant\""
landingPageStep3 = "L'autorisation de la caméra est nécessaire pour l'entraîneur AI. Vos vêtements n'affecteront pas l'entraîneur AI"
landingPageStart = "Commencez maintenant"
congratulation = "Toutes nos félicitations!"
completeBtn = "OK"
cameraText = "Caméra non détectée"
cameraText1 = "Caméra désactivée. Veuillez d'abord accorder l'autorisation de la caméra !"
cameraButtonText = "OK"
case .español:
landingPageTitle = "Asistente de AI de postura de lactancia"
landingPageStep1 = "Coloque su dispositivo en una superficie estable"
landingPageStep2 = "Manténgase a un metro de distancia de la cámara y coloque su cuerpo en la línea. La sesión comienza en 5 segundos después de hacer clic en el botón \"Comenzar ahora\""
landingPageStep3 = "Se necesita permiso para acceder a la cámara para el asistente de IA. Su ropa no afectará al asistente de IA"
landingPageStart = "Empezar ahora"
congratulation = "¡Felicidades!"
completeBtn = "DE ACUERDO"
cameraText = "Cámara no detectada"
cameraText1 = "Cámara desactivada. ¡Por favor, conceda permiso a la cámara primero!"
cameraButtonText = "DE ACUERDO"
}
let languageFile = "string_\(language)".appending(".json")
let path: String = Bundle.main.path(forResource: languageFile, ofType: nil)!
let nsUrl = URL(fileURLWithPath: path)
let nsData = try! Data(contentsOf: nsUrl)
let json = try! JSONSerialization.jsonObject(with: nsData) as! [String: Any]
string = .init(fromDictionary: json)
// switch language {
// case .english:
// landingPageTitle = "Breastfeeding posture AI coach"
// landingPageStep1 = "Put your device on a stable surface"
// landingPageStep2 = "Keep one meter away from the camera, and fit your body into the guide line. Session starts in 5 seconds after you click \"Start Now\" button"
// landingPageStep3 = "Camera permission is needed for AI coach. Your clothes will not affect the AI coach"
// landingPageStart = "Start Now"
// congratulation = "Congratulations!"
// completeBtn = "OK"
// cameraText = "Camera not detected"
// cameraText1 = "Camera disabled. Please grant camera permission first!"
// cameraButtonText = "OK"
// case .français:
// landingPageTitle = "Coach AI en posture d'allaitement"
// landingPageStep1 = "Placez votre appareil sur une surface stable"
// landingPageStep2 = "Tenez-vous à un mètre de la caméra et placez votre corps dans la ligne de guidage. La session démarre dans 5 secondes après avoir cliqué sur le bouton \"Démarrer maintenant\""
// landingPageStep3 = "L'autorisation de la caméra est nécessaire pour l'entraîneur AI. Vos vêtements n'affecteront pas l'entraîneur AI"
// landingPageStart = "Commencez maintenant"
// congratulation = "Toutes nos félicitations!"
// completeBtn = "OK"
// cameraText = "Caméra non détectée"
// cameraText1 = "Caméra désactivée. Veuillez d'abord accorder l'autorisation de la caméra !"
// cameraButtonText = "OK"
// case .español:
// landingPageTitle = "Asistente de AI de postura de lactancia"
// landingPageStep1 = "Coloque su dispositivo en una superficie estable"
// landingPageStep2 = "Manténgase a un metro de distancia de la cámara y coloque su cuerpo en la línea. La sesión comienza en 5 segundos después de hacer clic en el botón \"Comenzar ahora\""
// landingPageStep3 = "Se necesita permiso para acceder a la cámara para el asistente de IA. Su ropa no afectará al asistente de IA"
// landingPageStart = "Empezar ahora"
// congratulation = "¡Felicidades!"
// completeBtn = "DE ACUERDO"
// cameraText = "Cámara no detectada"
// cameraText1 = "Cámara desactivada. ¡Por favor, conceda permiso a la cámara primero!"
// cameraButtonText = "DE ACUERDO"
// }
}
}
......@@ -40,5 +40,16 @@ func hexStringToUIColor(hex: String) -> UIColor {
)
}
extension UIApplication {
var keyWindow: UIWindow? {
self.connectedScenes
.filter { $0.activationState == .foregroundActive }
.compactMap { $0 as? UIWindowScene }.first?.windows
.filter { $0.isKeyWindow }.first
}
}
let viewModel = ViewModel.init()
let mainColor = hexStringToUIColor(hex: "F58685")
let blackColor = hexStringToUIColor(hex: "322D31")
{
"homeTitle": "Breastfeeding posture AI coach",
"homeText1": "Put your device on a stable surface",
"homeText2": "Keep one meter away from the camera, and fit your body into the guide line. Session starts in 5 seconds after you click \"Start Now\" button",
"homeText3": "Camera permission is needed for AI coach. Your clothes will not affect the AI coach",
"homeButtonText": "Start Now",
"completeText": "Congratulations!",
"cameraText": "Camera not detected",
"cameraText1": "Camera disabled. Please grant camera permission first!",
"cameraButtonText": "OK",
"completeText2": "You have recorded",
"completeButtonText": "OK",
"lactationModeText": "Please choose the breastfeeding position",
"sittingGesture": {
"title": "Cradle hold position",
"subTitle": "Suitable for cooperative babies"
},
"lyingGesture": {
"title": "Side-lying position",
"subTitle": "It is suitable for the recovery period of cesarean section or night feeding"
},
"sittingGestureIntroduce": {
"title": "Cradle hold position",
"subTitle": "Baby can search for breast. Suitable for cooperative babies",
"suggestedText1": "Keep baby's head in higher position so you can see baby's face",
"suggestedText2": "Babies and mothers clothes should be unwrapped from the chest and abdomen",
"suggestedText3": "Keep baby's head on your elbow, and do not restrict baby's head with your hand",
"suggestedText4": "Keep baby's ear, shoulder and butt at the same level"
},
"lyingGestureIntroduce": {
"title": "Side-lying position",
"subTitle": "It is suitable for mothers who are in the recovery period of cesarean section or mothers who have experienced episiotomy. It is easy for feeding at night, and it allows mothers to have a better rest and for babies to sleep better. \n Please pay attention to avoid the breast blocking baby's breath.",
"suggestedText1": "Keep baby's head in higher position so you can see baby's face",
"suggestedText2": "Babies and mothers clothes should be unwrapped from the chest and abdomen",
"suggestedText3": "Keep baby's ear, shoulder and butt at the same level",
"suggestedText4": "You may use one hand to support the baby's back, and the other hand to rest under the your head",
"suggestedText5": "Always pay attention to your baby's breath. Do not squeeze the breast. Make the baby's butt closer to the your abdomen, and leave some space between your breast and your baby's nose",
"tipsText": "Please be careful not to touch your nipples during learning session"
}
}
{
"homeTitle": "Coach AI en posture d'allaitement",
"homeText1": "Placez votre appareil sur une surface stable",
"homeText2": "Tenez-vous à un mètre de la caméra et placez votre corps dans la ligne de guidage. La session démarre dans 5 secondes après avoir cliqué sur le bouton \"Démarrer maintenant\"",
"homeText3": "L'autorisation de la caméra est nécessaire pour l'entraîneur AI. Vos vêtements n'affecteront pas l'entraîneur AI",
"homeButtonText": "Commencez maintenant",
"completeText": "Toutes nos félicitations!",
"cameraText": "Caméra non détectée",
"cameraText1": "Caméra désactivée. Veuillez d'abord accorder l'autorisation de la caméra !",
"cameraButtonText": "OK",
"completeText2": "Vous avez enregistré",
"completeButtonText": "OK",
"lactationModeText": "Veuillez choisir la position d'allaitement",
"sittingGesture": {
"title": "Position de maintien du berceau",
"subTitle": "Convient aux bébés coopératifs"
},
"lyingGesture": {
"title": "Position couchée sur le côté",
"subTitle": "Il convient à la période de récupération de la césarienne ou de l'alimentation nocturne"
},
"sittingGestureIntroduce": {
"title": "Position de maintien du berceau",
"subTitle": "Le bébé peut rechercher le sein. Convient aux bébés coopératifs",
"suggestedText1": "Gardez la tête de bébé en position haute pour que vous puissiez voir le visage de bébé",
"suggestedText2": "Les vêtements des bébés et des mères doivent être déballés de la poitrine et de l'abdomen",
"suggestedText3": "Gardez la tête de bébé sur votre coude et ne restreignez pas la tête de bébé avec votre main",
"suggestedText4": "Gardez l'oreille, l'épaule et les fesses de bébé au même niveau"
},
"lyingGestureIntroduce": {
"title": "Position couchée sur le côté",
"subTitle": "Il convient aux mères qui sont en période de convalescence après une césarienne ou aux mères qui ont subi une épisiotomie. Il est facile à nourrir la nuit, permet aux mères de mieux se reposer et aux bébés de mieux dormir. \n Veuillez faire attention à ce que le sein ne bloque pas la respiration du bébé.",
"suggestedText1": "Gardez la tête de bébé en position haute pour que vous puissiez voir le visage de bébé",
"suggestedText2": "Les vêtements des bébés et des mères doivent être déballés de la poitrine et de l'abdomen",
"suggestedText3": "Gardez l'oreille, l'épaule et les fesses de bébé au même niveau",
"suggestedText4": "Vous pouvez utiliser une main pour soutenir le dos du bébé et l'autre main pour vous reposer sous la tête.",
"suggestedText5": "Faites toujours attention à la respiration de votre bébé. Ne serrez pas la poitrine. Rapprochez les fesses du bébé de votre abdomen et laissez un peu d'espace entre votre sein et le nez de votre bébé",
"tipsText": "Veuillez faire attention à ne pas toucher vos mamelons pendant la session d'apprentissage"
}
}
{
"homeTitle": "Asistente de AI de postura de lactancia",
"homeText1": "Coloque su dispositivo en una superficie estable",
"homeText2": "Manténgase a un metro de distancia de la cámara y coloque su cuerpo en la línea. La sesión comienza en 5 segundos después de hacer clic en el botón \"Comenzar ahora\"",
"homeText3": "Se necesita permiso para acceder a la cámara para el asistente de IA. Su ropa no afectará al asistente de IA",
"homeButtonText": "Empezar ahora",
"completeText": "¡Felicidades!",
"cameraText": "Cámara no detectada",
"cameraText1": "Cámara desactivada. ¡Por favor, conceda permiso a la cámara primero!",
"cameraButtonText": "DE ACUERDO",
"completeText2": "Usted ha registrado",
"completeButtonText": "DE ACUERDO",
"lactationModeText": "Por favor, elija la posición de lactancia",
"sittingGesture": {
"title": "Posición de sujeción de cuna",
"subTitle": "Adecuado para bebés cooperativos."
},
"lyingGesture": {
"title": "Posición acostada de lado",
"subTitle": "Es adecuado para el período de recuperación de la cesárea o alimentación nocturna"
},
"sittingGestureIntroduce": {
"title": "Posición de sujeción de cuna",
"subTitle": "El bebé puede buscar el pecho. Adecuado para bebés cooperativos.",
"suggestedText1": "Mantenga la cabeza del bebé en una posición más alta para que pueda ver la cara del bebé",
"suggestedText2": "La ropa de los bebés y las madres debe estar desenvuelta del pecho y el abdomen.",
"suggestedText3": "Mantenga la cabeza del bebé sobre su codo y no restrinja la cabeza del bebé con la mano",
"suggestedText4": "Mantenga la oreja, el hombro y el trasero del bebé al mismo nivel"
},
"lyingGestureIntroduce": {
"title": "Posición acostada de lado",
"subTitle": "Es adecuado para madres que se encuentran en el período de recuperación de una cesárea o madres que han experimentado una episiotomía. Es fácil de alimentar por la noche, y permite que las madres descansen mejor y que los bebés duerman mejor. \n Preste atención para evitar que el pecho bloquee la respiración del bebé.",
"suggestedText1": "Mantenga la cabeza del bebé en una posición más alta para que pueda ver la cara del bebé",
"suggestedText2": "La ropa de los bebés y las madres debe estar desenvuelta del pecho y el abdomen.",
"suggestedText3": "Mantenga la oreja, el hombro y el trasero del bebé al mismo nivel",
"suggestedText4": "Puede usar una mano para sostener la espalda del bebé y la otra mano para descansar debajo de la cabeza.",
"suggestedText5": "Siempre preste atención a la respiración de su bebé. No apriete el pecho. Acerque el trasero del bebé a su abdomen y deje un poco de espacio entre su seno y la nariz de su bebé.",
"tipsText": "Tenga cuidado de no tocarse los pezones durante la sesión de aprendizaje."
}
}
//
// StringLyingGesture.swift
// Model file generated using JSONExport: https://github.com/Ahmed-Ali/JSONExport
import Foundation
class StringLyingGesture : NSObject, NSCoding{
var subTitle : String!
var title : String!
/**
* Instantiate the instance using the passed dictionary values to set the properties values
*/
init(fromDictionary dictionary: [String:Any]){
subTitle = dictionary["subTitle"] as? String
title = dictionary["title"] as? String
}
/**
* Returns all the available property values in the form of [String:Any] object where the key is the approperiate json key and the value is the value of the corresponding property
*/
func toDictionary() -> [String:Any]
{
var dictionary = [String:Any]()
if subTitle != nil{
dictionary["subTitle"] = subTitle
}
if title != nil{
dictionary["title"] = title
}
return dictionary
}
/**
* NSCoding required initializer.
* Fills the data from the passed decoder
*/
@objc required init(coder aDecoder: NSCoder)
{
subTitle = aDecoder.decodeObject(forKey: "subTitle") as? String
title = aDecoder.decodeObject(forKey: "title") as? String
}
/**
* NSCoding required method.
* Encodes mode properties into the decoder
*/
@objc func encode(with aCoder: NSCoder)
{
if subTitle != nil{
aCoder.encode(subTitle, forKey: "subTitle")
}
if title != nil{
aCoder.encode(title, forKey: "title")
}
}
}
\ No newline at end of file
//
// StringLyingGestureIntroduce.swift
// Model file generated using JSONExport: https://github.com/Ahmed-Ali/JSONExport
import Foundation
class StringLyingGestureIntroduce : NSObject, NSCoding{
var subTitle : String!
var suggestedText1 : String!
var suggestedText2 : String!
var suggestedText3 : String!
var suggestedText4 : String!
var suggestedText5 : String!
var tipsText : String!
var title : String!
/**
* Instantiate the instance using the passed dictionary values to set the properties values
*/
init(fromDictionary dictionary: [String:Any]){
subTitle = dictionary["subTitle"] as? String
suggestedText1 = dictionary["suggestedText1"] as? String
suggestedText2 = dictionary["suggestedText2"] as? String
suggestedText3 = dictionary["suggestedText3"] as? String
suggestedText4 = dictionary["suggestedText4"] as? String
suggestedText5 = dictionary["suggestedText5"] as? String
tipsText = dictionary["tipsText"] as? String
title = dictionary["title"] as? String
}
/**
* Returns all the available property values in the form of [String:Any] object where the key is the approperiate json key and the value is the value of the corresponding property
*/
func toDictionary() -> [String:Any]
{
var dictionary = [String:Any]()
if subTitle != nil{
dictionary["subTitle"] = subTitle
}
if suggestedText1 != nil{
dictionary["suggestedText1"] = suggestedText1
}
if suggestedText2 != nil{
dictionary["suggestedText2"] = suggestedText2
}
if suggestedText3 != nil{
dictionary["suggestedText3"] = suggestedText3
}
if suggestedText4 != nil{
dictionary["suggestedText4"] = suggestedText4
}
if suggestedText5 != nil{
dictionary["suggestedText5"] = suggestedText5
}
if tipsText != nil{
dictionary["tipsText"] = tipsText
}
if title != nil{
dictionary["title"] = title
}
return dictionary
}
/**
* NSCoding required initializer.
* Fills the data from the passed decoder
*/
@objc required init(coder aDecoder: NSCoder)
{
subTitle = aDecoder.decodeObject(forKey: "subTitle") as? String
suggestedText1 = aDecoder.decodeObject(forKey: "suggestedText1") as? String
suggestedText2 = aDecoder.decodeObject(forKey: "suggestedText2") as? String
suggestedText3 = aDecoder.decodeObject(forKey: "suggestedText3") as? String
suggestedText4 = aDecoder.decodeObject(forKey: "suggestedText4") as? String
suggestedText5 = aDecoder.decodeObject(forKey: "suggestedText5") as? String
tipsText = aDecoder.decodeObject(forKey: "tipsText") as? String
title = aDecoder.decodeObject(forKey: "title") as? String
}
/**
* NSCoding required method.
* Encodes mode properties into the decoder
*/
@objc func encode(with aCoder: NSCoder)
{
if subTitle != nil{
aCoder.encode(subTitle, forKey: "subTitle")
}
if suggestedText1 != nil{
aCoder.encode(suggestedText1, forKey: "suggestedText1")
}
if suggestedText2 != nil{
aCoder.encode(suggestedText2, forKey: "suggestedText2")
}
if suggestedText3 != nil{
aCoder.encode(suggestedText3, forKey: "suggestedText3")
}
if suggestedText4 != nil{
aCoder.encode(suggestedText4, forKey: "suggestedText4")
}
if suggestedText5 != nil{
aCoder.encode(suggestedText5, forKey: "suggestedText5")
}
if tipsText != nil{
aCoder.encode(tipsText, forKey: "tipsText")
}
if title != nil{
aCoder.encode(title, forKey: "title")
}
}
}
\ No newline at end of file
//
// StringModel.swift
// Model file generated using JSONExport: https://github.com/Ahmed-Ali/JSONExport
import Foundation
class StringModel : NSObject, NSCoding{
var cameraButtonText : String!
var cameraText : String!
var cameraText1 : String!
var completeButtonText : String!
var completeText : String!
var completeText2 : String!
var homeButtonText : String!
var homeText1 : String!
var homeText2 : String!
var homeText3 : String!
var homeTitle : String!
var lactationModeText : String!
var lyingGesture : StringLyingGesture!
var lyingGestureIntroduce : StringLyingGestureIntroduce!
var sittingGesture : StringLyingGesture!
var sittingGestureIntroduce : StringSittingGestureIntroduce!
/**
* Instantiate the instance using the passed dictionary values to set the properties values
*/
init(fromDictionary dictionary: [String:Any]){
cameraButtonText = dictionary["cameraButtonText"] as? String
cameraText = dictionary["cameraText"] as? String
cameraText1 = dictionary["cameraText1"] as? String
completeButtonText = dictionary["completeButtonText"] as? String
completeText = dictionary["completeText"] as? String
completeText2 = dictionary["completeText2"] as? String
homeButtonText = dictionary["homeButtonText"] as? String
homeText1 = dictionary["homeText1"] as? String
homeText2 = dictionary["homeText2"] as? String
homeText3 = dictionary["homeText3"] as? String
homeTitle = dictionary["homeTitle"] as? String
lactationModeText = dictionary["lactationModeText"] as? String
if let lyingGestureData = dictionary["lyingGesture"] as? [String:Any]{
lyingGesture = StringLyingGesture(fromDictionary: lyingGestureData)
}
if let lyingGestureIntroduceData = dictionary["lyingGestureIntroduce"] as? [String:Any]{
lyingGestureIntroduce = StringLyingGestureIntroduce(fromDictionary: lyingGestureIntroduceData)
}
if let sittingGestureData = dictionary["sittingGesture"] as? [String:Any]{
sittingGesture = StringLyingGesture(fromDictionary: sittingGestureData)
}
if let sittingGestureIntroduceData = dictionary["sittingGestureIntroduce"] as? [String:Any]{
sittingGestureIntroduce = StringSittingGestureIntroduce(fromDictionary: sittingGestureIntroduceData)
}
}
/**
* Returns all the available property values in the form of [String:Any] object where the key is the approperiate json key and the value is the value of the corresponding property
*/
func toDictionary() -> [String:Any]
{
var dictionary = [String:Any]()
if cameraButtonText != nil{
dictionary["cameraButtonText"] = cameraButtonText
}
if cameraText != nil{
dictionary["cameraText"] = cameraText
}
if cameraText1 != nil{
dictionary["cameraText1"] = cameraText1
}
if completeButtonText != nil{
dictionary["completeButtonText"] = completeButtonText
}
if completeText != nil{
dictionary["completeText"] = completeText
}
if completeText2 != nil{
dictionary["completeText2"] = completeText2
}
if homeButtonText != nil{
dictionary["homeButtonText"] = homeButtonText
}
if homeText1 != nil{
dictionary["homeText1"] = homeText1
}
if homeText2 != nil{
dictionary["homeText2"] = homeText2
}
if homeText3 != nil{
dictionary["homeText3"] = homeText3
}
if homeTitle != nil{
dictionary["homeTitle"] = homeTitle
}
if lactationModeText != nil{
dictionary["lactationModeText"] = lactationModeText
}
if lyingGesture != nil{
dictionary["lyingGesture"] = lyingGesture.toDictionary()
}
if lyingGestureIntroduce != nil{
dictionary["lyingGestureIntroduce"] = lyingGestureIntroduce.toDictionary()
}
if sittingGesture != nil{
dictionary["sittingGesture"] = sittingGesture.toDictionary()
}
if sittingGestureIntroduce != nil{
dictionary["sittingGestureIntroduce"] = sittingGestureIntroduce.toDictionary()
}
return dictionary
}
/**
* NSCoding required initializer.
* Fills the data from the passed decoder
*/
@objc required init(coder aDecoder: NSCoder)
{
cameraButtonText = aDecoder.decodeObject(forKey: "cameraButtonText") as? String
cameraText = aDecoder.decodeObject(forKey: "cameraText") as? String
cameraText1 = aDecoder.decodeObject(forKey: "cameraText1") as? String
completeButtonText = aDecoder.decodeObject(forKey: "completeButtonText") as? String
completeText = aDecoder.decodeObject(forKey: "completeText") as? String
completeText2 = aDecoder.decodeObject(forKey: "completeText2") as? String
homeButtonText = aDecoder.decodeObject(forKey: "homeButtonText") as? String
homeText1 = aDecoder.decodeObject(forKey: "homeText1") as? String
homeText2 = aDecoder.decodeObject(forKey: "homeText2") as? String
homeText3 = aDecoder.decodeObject(forKey: "homeText3") as? String
homeTitle = aDecoder.decodeObject(forKey: "homeTitle") as? String
lactationModeText = aDecoder.decodeObject(forKey: "lactationModeText") as? String
lyingGesture = aDecoder.decodeObject(forKey: "lyingGesture") as? StringLyingGesture
lyingGestureIntroduce = aDecoder.decodeObject(forKey: "lyingGestureIntroduce") as? StringLyingGestureIntroduce
sittingGesture = aDecoder.decodeObject(forKey: "sittingGesture") as? StringLyingGesture
sittingGestureIntroduce = aDecoder.decodeObject(forKey: "sittingGestureIntroduce") as? StringSittingGestureIntroduce
}
/**
* NSCoding required method.
* Encodes mode properties into the decoder
*/
@objc func encode(with aCoder: NSCoder)
{
if cameraButtonText != nil{
aCoder.encode(cameraButtonText, forKey: "cameraButtonText")
}
if cameraText != nil{
aCoder.encode(cameraText, forKey: "cameraText")
}
if cameraText1 != nil{
aCoder.encode(cameraText1, forKey: "cameraText1")
}
if completeButtonText != nil{
aCoder.encode(completeButtonText, forKey: "completeButtonText")
}
if completeText != nil{
aCoder.encode(completeText, forKey: "completeText")
}
if completeText2 != nil{
aCoder.encode(completeText2, forKey: "completeText2")
}
if homeButtonText != nil{
aCoder.encode(homeButtonText, forKey: "homeButtonText")
}
if homeText1 != nil{
aCoder.encode(homeText1, forKey: "homeText1")
}
if homeText2 != nil{
aCoder.encode(homeText2, forKey: "homeText2")
}
if homeText3 != nil{
aCoder.encode(homeText3, forKey: "homeText3")
}
if homeTitle != nil{
aCoder.encode(homeTitle, forKey: "homeTitle")
}
if lactationModeText != nil{
aCoder.encode(lactationModeText, forKey: "lactationModeText")
}
if lyingGesture != nil{
aCoder.encode(lyingGesture, forKey: "lyingGesture")
}
if lyingGestureIntroduce != nil{
aCoder.encode(lyingGestureIntroduce, forKey: "lyingGestureIntroduce")
}
if sittingGesture != nil{
aCoder.encode(sittingGesture, forKey: "sittingGesture")
}
if sittingGestureIntroduce != nil{
aCoder.encode(sittingGestureIntroduce, forKey: "sittingGestureIntroduce")
}
}
}
\ No newline at end of file
//
// StringSittingGestureIntroduce.swift
// Model file generated using JSONExport: https://github.com/Ahmed-Ali/JSONExport
import Foundation
class StringSittingGestureIntroduce : NSObject, NSCoding{
var subTitle : String!
var suggestedText1 : String!
var suggestedText2 : String!
var suggestedText3 : String!
var suggestedText4 : String!
var title : String!
/**
* Instantiate the instance using the passed dictionary values to set the properties values
*/
init(fromDictionary dictionary: [String:Any]){
subTitle = dictionary["subTitle"] as? String
suggestedText1 = dictionary["suggestedText1"] as? String
suggestedText2 = dictionary["suggestedText2"] as? String
suggestedText3 = dictionary["suggestedText3"] as? String
suggestedText4 = dictionary["suggestedText4"] as? String
title = dictionary["title"] as? String
}
/**
* Returns all the available property values in the form of [String:Any] object where the key is the approperiate json key and the value is the value of the corresponding property
*/
func toDictionary() -> [String:Any]
{
var dictionary = [String:Any]()
if subTitle != nil{
dictionary["subTitle"] = subTitle
}
if suggestedText1 != nil{
dictionary["suggestedText1"] = suggestedText1
}
if suggestedText2 != nil{
dictionary["suggestedText2"] = suggestedText2
}
if suggestedText3 != nil{
dictionary["suggestedText3"] = suggestedText3
}
if suggestedText4 != nil{
dictionary["suggestedText4"] = suggestedText4
}
if title != nil{
dictionary["title"] = title
}
return dictionary
}
/**
* NSCoding required initializer.
* Fills the data from the passed decoder
*/
@objc required init(coder aDecoder: NSCoder)
{
subTitle = aDecoder.decodeObject(forKey: "subTitle") as? String
suggestedText1 = aDecoder.decodeObject(forKey: "suggestedText1") as? String
suggestedText2 = aDecoder.decodeObject(forKey: "suggestedText2") as? String
suggestedText3 = aDecoder.decodeObject(forKey: "suggestedText3") as? String
suggestedText4 = aDecoder.decodeObject(forKey: "suggestedText4") as? String
title = aDecoder.decodeObject(forKey: "title") as? String
}
/**
* NSCoding required method.
* Encodes mode properties into the decoder
*/
@objc func encode(with aCoder: NSCoder)
{
if subTitle != nil{
aCoder.encode(subTitle, forKey: "subTitle")
}
if suggestedText1 != nil{
aCoder.encode(suggestedText1, forKey: "suggestedText1")
}
if suggestedText2 != nil{
aCoder.encode(suggestedText2, forKey: "suggestedText2")
}
if suggestedText3 != nil{
aCoder.encode(suggestedText3, forKey: "suggestedText3")
}
if suggestedText4 != nil{
aCoder.encode(suggestedText4, forKey: "suggestedText4")
}
if title != nil{
aCoder.encode(title, forKey: "title")
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment