| @@ -0,0 +1,130 @@ | ||
| // | ||
| // Copyright (c) 2020 Gobierno de España | ||
| // | ||
| // This Source Code Form is subject to the terms of the Mozilla Public | ||
| // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
| // | ||
| // SPDX-License-Identifier: MPL-2.0 | ||
| // | ||
| import Logging | ||
| import Foundation | ||
|
|
||
| // Adapted from https://nshipster.com/textoutputstream/ | ||
| struct FileHandlerOutputStream: TextOutputStream { | ||
| enum FileHandlerOutputStream: Error { | ||
| case couldNotCreateFile | ||
| } | ||
|
|
||
| private let fileHandle: FileHandle | ||
| let encoding: String.Encoding | ||
|
|
||
| init(localFile url: URL, encoding: String.Encoding = .utf8) throws { | ||
| if !FileManager.default.fileExists(atPath: url.path) { | ||
| guard FileManager.default.createFile(atPath: url.path, contents: nil, attributes: nil) else { | ||
| throw FileHandlerOutputStream.couldNotCreateFile | ||
| } | ||
| } | ||
|
|
||
| let fileHandle = try FileHandle(forWritingTo: url) | ||
| fileHandle.seekToEndOfFile() | ||
| self.fileHandle = fileHandle | ||
| self.encoding = encoding | ||
| } | ||
|
|
||
| mutating func write(_ string: String) { | ||
| if let data = string.data(using: encoding) { | ||
| fileHandle.write(data) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| public struct FileLogging { | ||
| let stream: TextOutputStream | ||
| private var localFile: URL | ||
|
|
||
| public init(to localFile: URL) throws { | ||
| self.stream = try FileHandlerOutputStream(localFile: localFile) | ||
| self.localFile = localFile | ||
| } | ||
|
|
||
| public func handler(label: String) -> FileLogHandler { | ||
| return FileLogHandler(label: label, fileLogger: self) | ||
| } | ||
|
|
||
| public static func logger(label: String, localFile url: URL) throws -> Logger { | ||
| let logging = try FileLogging(to: url) | ||
| return Logger(label: label, factory: logging.handler) | ||
| } | ||
| } | ||
|
|
||
| // Adapted from https://github.com/apple/swift-log.git | ||
| /// `FileLogHandler` is a simple implementation of `LogHandler` for directing | ||
| /// `Logger` output to a local file. Appends log output to this file, even across constructor calls. | ||
| public struct FileLogHandler: LogHandler { | ||
| private let stream: TextOutputStream | ||
| private var label: String | ||
|
|
||
| public var logLevel: Logger.Level = .info | ||
|
|
||
| private var prettyMetadata: String? | ||
| public var metadata = Logger.Metadata() { | ||
| didSet { | ||
| self.prettyMetadata = self.prettify(self.metadata) | ||
| } | ||
| } | ||
|
|
||
| public subscript(metadataKey metadataKey: String) -> Logger.Metadata.Value? { | ||
| get { | ||
| return self.metadata[metadataKey] | ||
| } | ||
| set { | ||
| self.metadata[metadataKey] = newValue | ||
| } | ||
| } | ||
|
|
||
| public init(label: String, fileLogger: FileLogging) { | ||
| self.label = label | ||
| self.stream = fileLogger.stream | ||
| } | ||
|
|
||
| public init(label: String, localFile url: URL) throws { | ||
| self.label = label | ||
| self.stream = try FileHandlerOutputStream(localFile: url) | ||
| } | ||
|
|
||
| public func log(level: Logger.Level, | ||
| message: Logger.Message, | ||
| metadata: Logger.Metadata?, | ||
| source: String, | ||
| file: String, | ||
| function: String, | ||
| line: UInt) { | ||
| let prettyMetadata = metadata?.isEmpty ?? true | ||
| ? self.prettyMetadata | ||
| : self.prettify(self.metadata.merging(metadata!, uniquingKeysWith: { _, new in new })) | ||
|
|
||
| var stream = self.stream | ||
| stream.write("\(self.timestamp()) \(level) \(self.label) :\(prettyMetadata.map { " \($0)" } ?? "") \(message)\n") | ||
| } | ||
|
|
||
| private func prettify(_ metadata: Logger.Metadata) -> String? { | ||
| return !metadata.isEmpty ? metadata.map { "\($0)=\($1)" }.joined(separator: " ") : nil | ||
| } | ||
|
|
||
| private func timestamp() -> String { | ||
| var buffer = [Int8](repeating: 0, count: 255) | ||
| var timestamp = time(nil) | ||
| let localTime = localtime(×tamp) | ||
| strftime(&buffer, buffer.count, "%Y-%m-%dT%H:%M:%S%z", localTime) | ||
| return buffer.withUnsafeBufferPointer { | ||
| $0.withMemoryRebound(to: CChar.self) { | ||
| String(cString: $0.baseAddress!) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -5,9 +5,9 @@ | ||
| "color-space" : "srgb", | ||
| "components" : { | ||
| "alpha" : "1.000", | ||
| "blue" : "0.416", | ||
| "green" : "0.690", | ||
| "red" : "0.345" | ||
| } | ||
| }, | ||
| "idiom" : "universal" | ||
| @@ -1,20 +1,20 @@ | ||
| { | ||
| "colors" : [ | ||
| { | ||
| "color" : { | ||
| "color-space" : "srgb", | ||
| "components" : { | ||
| "alpha" : "1.000", | ||
| "blue" : "0.969", | ||
| "green" : "0.976", | ||
| "red" : "0.980" | ||
| } | ||
| }, | ||
| "idiom" : "universal" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -1,20 +1,20 @@ | ||
| { | ||
| "colors" : [ | ||
| { | ||
| "color" : { | ||
| "color-space" : "srgb", | ||
| "components" : { | ||
| "alpha" : "1.000", | ||
| "blue" : "0.929", | ||
| "green" : "0.580", | ||
| "red" : "0.455" | ||
| } | ||
| }, | ||
| "idiom" : "universal" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -1,20 +1,20 @@ | ||
| { | ||
| "colors" : [ | ||
| { | ||
| "color" : { | ||
| "color-space" : "srgb", | ||
| "components" : { | ||
| "alpha" : "1.000", | ||
| "blue" : "0.341", | ||
| "green" : "0.424", | ||
| "red" : "0.878" | ||
| } | ||
| }, | ||
| "idiom" : "universal" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -1,20 +1,20 @@ | ||
| { | ||
| "colors" : [ | ||
| { | ||
| "color" : { | ||
| "color-space" : "srgb", | ||
| "components" : { | ||
| "alpha" : "1.000", | ||
| "blue" : "0.718", | ||
| "green" : "0.486", | ||
| "red" : "0.541" | ||
| } | ||
| }, | ||
| "idiom" : "universal" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -0,0 +1,20 @@ | ||
| { | ||
| "colors" : [ | ||
| { | ||
| "color" : { | ||
| "color-space" : "srgb", | ||
| "components" : { | ||
| "alpha" : "1.000", | ||
| "blue" : "0.655", | ||
| "green" : "0.231", | ||
| "red" : "0.286" | ||
| } | ||
| }, | ||
| "idiom" : "universal" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -1,20 +1,20 @@ | ||
| { | ||
| "colors" : [ | ||
| { | ||
| "color" : { | ||
| "color-space" : "srgb", | ||
| "components" : { | ||
| "alpha" : "1.000", | ||
| "blue" : "0.878", | ||
| "green" : "0.851", | ||
| "red" : "0.827" | ||
| } | ||
| }, | ||
| "idiom" : "universal" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -1,20 +1,20 @@ | ||
| { | ||
| "colors" : [ | ||
| { | ||
| "color" : { | ||
| "color-space" : "srgb", | ||
| "components" : { | ||
| "alpha" : "1.000", | ||
| "blue" : "0.612", | ||
| "green" : "0.314", | ||
| "red" : "0.439" | ||
| } | ||
| }, | ||
| "idiom" : "universal" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -1,20 +1,20 @@ | ||
| { | ||
| "colors" : [ | ||
| { | ||
| "color" : { | ||
| "color-space" : "srgb", | ||
| "components" : { | ||
| "alpha" : "1.000", | ||
| "blue" : "0.941", | ||
| "green" : "0.941", | ||
| "red" : "0.941" | ||
| } | ||
| }, | ||
| "idiom" : "universal" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -0,0 +1,20 @@ | ||
| { | ||
| "colors" : [ | ||
| { | ||
| "color" : { | ||
| "color-space" : "srgb", | ||
| "components" : { | ||
| "alpha" : "1.000", | ||
| "blue" : "0.969", | ||
| "green" : "0.976", | ||
| "red" : "0.980" | ||
| } | ||
| }, | ||
| "idiom" : "universal" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -1,23 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "filename" : "Boton 2.png", | ||
| "idiom" : "universal", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "filename" : "Boton 2@2x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "filename" : "Boton 2@3x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "3x" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "filename" : "selected.png", | ||
| "idiom" : "universal", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "filename" : "selected@2x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "filename" : "selected@3x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "3x" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "filename" : "Frame.png", | ||
| "idiom" : "universal", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "filename" : "Frame@2x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "filename" : "Frame@3x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "3x" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "filename" : "settings_home.png", | ||
| "idiom" : "universal", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "filename" : "settings_home@2x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "filename" : "settings_home@3x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "3x" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "filename" : "Group 82.png", | ||
| "idiom" : "universal", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "filename" : "Group 82@2x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "filename" : "Group 82@3x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "3x" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "filename" : "Group 82.png", | ||
| "idiom" : "universal", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "filename" : "Group 82@2x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "filename" : "Group 82@3x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "3x" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "filename" : "settings.png", | ||
| "idiom" : "universal", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "filename" : "settings@2x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "filename" : "settings@3x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "3x" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -0,0 +1,23 @@ | ||
| { | ||
| "images" : [ | ||
| { | ||
| "filename" : "settings.png", | ||
| "idiom" : "universal", | ||
| "scale" : "1x" | ||
| }, | ||
| { | ||
| "filename" : "settings@2x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "2x" | ||
| }, | ||
| { | ||
| "filename" : "settings@3x.png", | ||
| "idiom" : "universal", | ||
| "scale" : "3x" | ||
| } | ||
| ], | ||
| "info" : { | ||
| "author" : "xcode", | ||
| "version" : 1 | ||
| } | ||
| } |
| @@ -0,0 +1,36 @@ | ||
| // | ||
| // Copyright (c) 2020 Gobierno de España | ||
| // | ||
| // This Source Code Form is subject to the terms of the Mozilla Public | ||
| // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
| // | ||
| // SPDX-License-Identifier: MPL-2.0 | ||
| // | ||
| import UIKit | ||
|
|
||
| class BaseViewController: UIViewController { | ||
|
|
||
| @IBOutlet weak var backButton: UIButton? | ||
|
|
||
| override func viewDidLoad() { | ||
| super.viewDidLoad() | ||
|
|
||
| setAccesibilityBackButton() | ||
| } | ||
|
|
||
| private func setAccesibilityBackButton() { | ||
|
|
||
| //Set Accesibility logic | ||
| backButton?.isAccessibilityElement = true | ||
| let previous = navigationController?.previousViewController | ||
| if let strTitle = (previous as? AccTitleView)?.accTitle ?? previous?.title { | ||
| backButton?.accessibilityLabel = "\(strTitle)," + "ACC_BUTTON_BACK_TO".localized | ||
| } else { | ||
| backButton?.accessibilityLabel = "ACC_BUTTON_BACK".localized | ||
| } | ||
| backButton?.accessibilityHint = "ACC_HINT".localized | ||
| } | ||
| } |
| @@ -0,0 +1,33 @@ | ||
| // | ||
| // Copyright (c) 2020 Gobierno de España | ||
| // | ||
| // This Source Code Form is subject to the terms of the Mozilla Public | ||
| // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
| // | ||
| // SPDX-License-Identifier: MPL-2.0 | ||
| // | ||
| import UIKit | ||
|
|
||
| class CustomSlider: UISlider { | ||
|
|
||
| //To set line height value from IB, here ten is default value | ||
| @IBInspectable var trackLineHeight: CGFloat = 18 | ||
|
|
||
| //To set custom size of track so here override trackRect function of slider control | ||
| override func trackRect(forBounds bound: CGRect) -> CGRect { | ||
| //Here, set track frame | ||
| return CGRect(origin: bound.origin, size: CGSize(width: bound.width, height: trackLineHeight)) | ||
| } | ||
|
|
||
| override func draw(_ rect: CGRect) { | ||
|
|
||
| if self.value == self.maximumValue { | ||
| self.value = (self.value - 0.1) | ||
| self.maximumTrackTintColor = UIColor.degradado | ||
| self.minimumTrackTintColor = UIColor.degradado | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,46 @@ | ||
| // | ||
| // Copyright (c) 2020 Gobierno de España | ||
| // | ||
| // This Source Code Form is subject to the terms of the Mozilla Public | ||
| // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
| // | ||
| // SPDX-License-Identifier: MPL-2.0 | ||
| // | ||
| import UIKit | ||
|
|
||
| class CustomSliderView: UIView, XibInstantiatable { | ||
|
|
||
| @IBOutlet weak var slider: CustomSlider! | ||
| @IBOutlet weak var stepLabel: UILabel! | ||
| @IBOutlet weak var viewContainer: UIView! | ||
|
|
||
| override init(frame: CGRect) { | ||
| super.init(frame: frame) | ||
| instantiate() | ||
| self.translatesAutoresizingMaskIntoConstraints = false | ||
| } | ||
|
|
||
| required init?(coder aDecoder: NSCoder) { | ||
| super.init(coder: aDecoder) | ||
| instantiate() | ||
| } | ||
|
|
||
| func configure(indexStep: Int, totalStep: Int, accesibilityHelper: String? = nil) { | ||
|
|
||
| stepLabel.text = "MY_HEALTH_RANGER".localized | ||
| stepLabel.text = stepLabel.text?.replacingOccurrences(of: "$1", with: "\(indexStep)") | ||
| stepLabel.text = stepLabel.text?.replacingOccurrences(of: "$2", with: "\(totalStep)") | ||
|
|
||
| if let strAccesibility = accesibilityHelper { | ||
| viewContainer.accessibilityLabel = strAccesibility | ||
| } | ||
|
|
||
| //Config slider | ||
| slider.maximumValue = 1 | ||
| slider.maximumValue = Float(totalStep) | ||
| slider.value = Float(indexStep) | ||
| } | ||
| } |
| @@ -0,0 +1,83 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> | ||
| <device id="retina6_1" orientation="portrait" appearance="light"/> | ||
| <dependencies> | ||
| <deployment identifier="iOS"/> | ||
| <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17126"/> | ||
| <capability name="Named colors" minToolsVersion="9.0"/> | ||
| <capability name="Safe area layout guides" minToolsVersion="9.0"/> | ||
| <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> | ||
| </dependencies> | ||
| <objects> | ||
| <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CustomSliderView" customModule="Radar_COVID" customModuleProvider="target"> | ||
| <connections> | ||
| <outlet property="slider" destination="cLw-D7-Kjk" id="gfM-eP-8LX"/> | ||
| <outlet property="stepLabel" destination="o6R-S9-XpD" id="RjR-iM-bOP"/> | ||
| <outlet property="viewContainer" destination="k7M-g6-tVc" id="0fq-IJ-GkA"/> | ||
| </connections> | ||
| </placeholder> | ||
| <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> | ||
| <view contentMode="scaleToFill" id="iN0-l3-epB"> | ||
| <rect key="frame" x="0.0" y="0.0" width="258" height="54"/> | ||
| <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> | ||
| <subviews> | ||
| <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="k7M-g6-tVc"> | ||
| <rect key="frame" x="0.0" y="0.0" width="258" height="54"/> | ||
| <subviews> | ||
| <slider opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="0.0" maxValue="2" continuous="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cLw-D7-Kjk" customClass="CustomSlider" customModule="Radar_COVID" customModuleProvider="target"> | ||
| <rect key="frame" x="-2" y="0.0" width="262" height="55"/> | ||
| <color key="tintColor" name="degradado"/> | ||
| <accessibility key="accessibilityConfiguration"> | ||
| <bool key="isElement" value="NO"/> | ||
| </accessibility> | ||
| <color key="thumbTintColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> | ||
| <userDefinedRuntimeAttributes> | ||
| <userDefinedRuntimeAttribute type="number" keyPath="trackLineHeight"> | ||
| <real key="value" value="18"/> | ||
| </userDefinedRuntimeAttribute> | ||
| </userDefinedRuntimeAttributes> | ||
| </slider> | ||
| <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="o6R-S9-XpD"> | ||
| <rect key="frame" x="0.0" y="54" width="258" height="0.0"/> | ||
| <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> | ||
| <accessibility key="accessibilityConfiguration"> | ||
| <bool key="isElement" value="NO"/> | ||
| </accessibility> | ||
| <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/> | ||
| <nil key="textColor"/> | ||
| <nil key="highlightedColor"/> | ||
| </label> | ||
| </subviews> | ||
| <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> | ||
| <accessibility key="accessibilityConfiguration"> | ||
| <bool key="isElement" value="YES"/> | ||
| </accessibility> | ||
| <constraints> | ||
| <constraint firstAttribute="trailing" secondItem="o6R-S9-XpD" secondAttribute="trailing" id="12C-gf-tqx"/> | ||
| <constraint firstItem="o6R-S9-XpD" firstAttribute="top" secondItem="cLw-D7-Kjk" secondAttribute="bottom" id="1uv-Zn-gsf"/> | ||
| <constraint firstItem="cLw-D7-Kjk" firstAttribute="leading" secondItem="k7M-g6-tVc" secondAttribute="leading" id="INv-DW-0Rf"/> | ||
| <constraint firstAttribute="trailing" secondItem="cLw-D7-Kjk" secondAttribute="trailing" id="RXe-U5-WPE"/> | ||
| <constraint firstAttribute="bottom" secondItem="o6R-S9-XpD" secondAttribute="bottom" id="T5a-F1-0JX"/> | ||
| <constraint firstItem="o6R-S9-XpD" firstAttribute="leading" secondItem="k7M-g6-tVc" secondAttribute="leading" id="haI-Zn-PBM"/> | ||
| <constraint firstItem="cLw-D7-Kjk" firstAttribute="top" secondItem="k7M-g6-tVc" secondAttribute="top" id="uzk-kQ-u6Y"/> | ||
| </constraints> | ||
| </view> | ||
| </subviews> | ||
| <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/> | ||
| <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> | ||
| <constraints> | ||
| <constraint firstItem="k7M-g6-tVc" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="5GO-DQ-9kA"/> | ||
| <constraint firstAttribute="bottom" secondItem="k7M-g6-tVc" secondAttribute="bottom" id="VKj-I1-HQv"/> | ||
| <constraint firstItem="k7M-g6-tVc" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="gLp-8q-5nI"/> | ||
| <constraint firstAttribute="trailing" secondItem="k7M-g6-tVc" secondAttribute="trailing" id="moa-Mr-I6S"/> | ||
| </constraints> | ||
| <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> | ||
| <point key="canvasLocation" x="-423" y="-74"/> | ||
| </view> | ||
| </objects> | ||
| <resources> | ||
| <namedColor name="degradado"> | ||
| <color red="0.28627450980392155" green="0.23137254901960785" blue="0.65490196078431373" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> | ||
| </namedColor> | ||
| </resources> | ||
| </document> |
| @@ -0,0 +1,94 @@ | ||
| // | ||
| // Copyright (c) 2020 Gobierno de España | ||
| // | ||
| // This Source Code Form is subject to the terms of the Mozilla Public | ||
| // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
| // | ||
| // SPDX-License-Identifier: MPL-2.0 | ||
| // | ||
| import Foundation | ||
| import UIKit | ||
| protocol SwitchStateListener { | ||
| func stateChanged(active: Bool, switcher: CustomSwitch) | ||
| } | ||
| class CustomSwitch: UIView, XibInstantiatable { | ||
|
|
||
| @IBOutlet weak var stateImage: UIImageView! | ||
| @IBOutlet weak var regularSwitch: UISwitch! | ||
| @IBOutlet weak var container: UIView! | ||
|
|
||
| @IBInspectable var swicherType: String? | ||
|
|
||
| var isTermSwitcher: Bool { | ||
| return swicherType == "terms" | ||
| } | ||
| var isPolicySwitcher: Bool { | ||
| return swicherType == "policy" | ||
| } | ||
|
|
||
| var delegate: SwitchStateListener? | ||
| var active = false | ||
| var switchStateImage: UIImage? { | ||
| return self.active ? | ||
| UIImage(named: "CheckboxSelected") | ||
| : UIImage(named: "CheckboxUnselected") | ||
| } | ||
|
|
||
| override init(frame: CGRect) { | ||
| super.init(frame: frame) | ||
| instantiate() | ||
| self.setupAccessibility() | ||
| self.translatesAutoresizingMaskIntoConstraints = false | ||
| } | ||
|
|
||
| required init?(coder aDecoder: NSCoder) { | ||
| super.init(coder: aDecoder) | ||
| instantiate() | ||
| self.setupAccessibility() | ||
| } | ||
|
|
||
|
|
||
| func updateViews() { | ||
| if !UIAccessibility.isVoiceOverRunning { | ||
| self.stateImage.image = self.switchStateImage | ||
| } | ||
| } | ||
|
|
||
| func setupAccessibility() { | ||
| container.isUserInteractionEnabled = true | ||
|
|
||
| if UIAccessibility.isVoiceOverRunning { | ||
| self.stateImage.isHidden = true | ||
| self.regularSwitch.isHidden = false | ||
| } else { | ||
| container.addGestureRecognizer( | ||
| UITapGestureRecognizer(target: self, action: #selector(toggleState)) | ||
| ) | ||
| self.stateImage.isHidden = false | ||
| self.regularSwitch.isHidden = true | ||
|
|
||
| } | ||
|
|
||
| regularSwitch.accessibilityTraits = UISwitch().accessibilityTraits | ||
| regularSwitch.accessibilityHint = "ACC_HINT".localized | ||
| } | ||
|
|
||
| func setAccesibilityLabel(accessibilityLabel: String) { | ||
| regularSwitch.accessibilityLabel = accessibilityLabel | ||
| } | ||
|
|
||
| @objc func toggleState(){ | ||
| self.active = !active | ||
| delegate?.stateChanged(active: self.active, switcher: self) | ||
| updateViews() | ||
| } | ||
|
|
||
|
|
||
| @IBAction func onSwithChange(_ sender: Any) { | ||
| toggleState() | ||
| } | ||
|
|
||
| } |
| @@ -0,0 +1,78 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17156" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES"> | ||
| <device id="retina6_1" orientation="portrait" appearance="light"/> | ||
| <dependencies> | ||
| <deployment identifier="iOS"/> | ||
| <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/> | ||
| <capability name="Safe area layout guides" minToolsVersion="9.0"/> | ||
| <capability name="System colors in document resources" minToolsVersion="11.0"/> | ||
| <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> | ||
| </dependencies> | ||
| <objects> | ||
| <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="CustomSwitch" customModule="Radar_COVID" customModuleProvider="target"> | ||
| <connections> | ||
| <outlet property="container" destination="sdI-Gq-5J5" id="hyD-eY-cza"/> | ||
| <outlet property="regularSwitch" destination="35V-uJ-mhN" id="6zv-UX-1oG"/> | ||
| <outlet property="stateImage" destination="nkg-yX-hqd" id="25D-8a-4Zt"/> | ||
| </connections> | ||
| </placeholder> | ||
| <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> | ||
| <view contentMode="scaleToFill" id="iN0-l3-epB"> | ||
| <rect key="frame" x="0.0" y="0.0" width="49" height="40"/> | ||
| <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> | ||
| <subviews> | ||
| <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sdI-Gq-5J5"> | ||
| <rect key="frame" x="0.0" y="0.0" width="49" height="40"/> | ||
| <subviews> | ||
| <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="CheckboxUnselected" translatesAutoresizingMaskIntoConstraints="NO" id="nkg-yX-hqd"> | ||
| <rect key="frame" x="15.5" y="3" width="18" height="18"/> | ||
| <accessibility key="accessibilityConfiguration"> | ||
| <accessibilityTraits key="traits" none="YES"/> | ||
| <bool key="isElement" value="NO"/> | ||
| </accessibility> | ||
| <constraints> | ||
| <constraint firstAttribute="width" constant="18" id="C3v-iO-uEM"/> | ||
| <constraint firstAttribute="height" constant="18" id="t8z-u5-HS3"/> | ||
| </constraints> | ||
| </imageView> | ||
| <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="35V-uJ-mhN"> | ||
| <rect key="frame" x="0.0" y="0.0" width="51" height="31"/> | ||
| <accessibility key="accessibilityConfiguration"> | ||
| <accessibilityTraits key="traits" none="YES"/> | ||
| </accessibility> | ||
| <constraints> | ||
| <constraint firstAttribute="width" constant="49" id="dWk-OB-Z7g"/> | ||
| </constraints> | ||
| <connections> | ||
| <action selector="onSwithChange:" destination="-1" eventType="valueChanged" id="4Zb-6e-Adn"/> | ||
| </connections> | ||
| </switch> | ||
| </subviews> | ||
| <constraints> | ||
| <constraint firstItem="35V-uJ-mhN" firstAttribute="top" secondItem="sdI-Gq-5J5" secondAttribute="top" id="3ug-OJ-vJl"/> | ||
| <constraint firstItem="35V-uJ-mhN" firstAttribute="leading" secondItem="sdI-Gq-5J5" secondAttribute="leading" id="7RH-db-FfA"/> | ||
| <constraint firstAttribute="height" constant="40" id="Lwg-TB-dcq"/> | ||
| <constraint firstItem="nkg-yX-hqd" firstAttribute="top" secondItem="sdI-Gq-5J5" secondAttribute="top" constant="3" id="Szv-Fb-ter"/> | ||
| <constraint firstAttribute="trailing" secondItem="35V-uJ-mhN" secondAttribute="trailing" id="lFg-Qg-zcU"/> | ||
| <constraint firstItem="nkg-yX-hqd" firstAttribute="centerX" secondItem="sdI-Gq-5J5" secondAttribute="centerX" id="v82-cp-H6q"/> | ||
| <constraint firstItem="35V-uJ-mhN" firstAttribute="centerX" secondItem="sdI-Gq-5J5" secondAttribute="centerX" id="zUq-dV-D4G"/> | ||
| </constraints> | ||
| </view> | ||
| </subviews> | ||
| <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/> | ||
| <color key="backgroundColor" systemColor="systemBackgroundColor"/> | ||
| <constraints> | ||
| <constraint firstItem="sdI-Gq-5J5" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="oYT-8M-NjE"/> | ||
| <constraint firstItem="sdI-Gq-5J5" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="zXf-iH-sQ0"/> | ||
| </constraints> | ||
| <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/> | ||
| <point key="canvasLocation" x="-371.73913043478262" y="-220.98214285714286"/> | ||
| </view> | ||
| </objects> | ||
| <resources> | ||
| <image name="CheckboxUnselected" width="16" height="16"/> | ||
| <systemColor name="systemBackgroundColor"> | ||
| <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> | ||
| </systemColor> | ||
| </resources> | ||
| </document> |
| @@ -0,0 +1,29 @@ | ||
| // | ||
| // Copyright (c) 2020 Gobierno de España | ||
| // | ||
| // This Source Code Form is subject to the terms of the Mozilla Public | ||
| // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
| // | ||
| // SPDX-License-Identifier: MPL-2.0 | ||
| // | ||
| import UIKit | ||
|
|
||
| protocol XibInstantiatable { | ||
| func instantiate() | ||
| } | ||
|
|
||
| extension XibInstantiatable where Self: UIView { | ||
| func instantiate() { | ||
| let bundle = Bundle(for: type(of: self)) | ||
| let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle) | ||
| guard let view = nib.instantiate(withOwner: self, options: nil).first as? UIView else { | ||
| return | ||
| } | ||
| view.frame = self.bounds | ||
| insertSubview(view, at: 0) | ||
|
|
||
| view.autoresizingMask = [UIView.AutoresizingMask.flexibleWidth, UIView.AutoresizingMask.flexibleHeight] | ||
| } | ||
| } |
| @@ -0,0 +1,34 @@ | ||
| // | ||
| // Copyright (c) 2020 Gobierno de España | ||
| // | ||
| // This Source Code Form is subject to the terms of the Mozilla Public | ||
| // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
| // | ||
| // SPDX-License-Identifier: MPL-2.0 | ||
| // | ||
|
|
||
| import Foundation | ||
| class TermsAcceptedRepository { | ||
|
|
||
| private var userDefaults: UserDefaults | ||
| private let termsAcceptedKey = "UserDefaultsTermsAccepted.accepted" | ||
|
|
||
| init() { | ||
| self.userDefaults = UserDefaults.standard | ||
| } | ||
|
|
||
| var termsAccepted: Bool { | ||
| get { | ||
| return userDefaults.bool(forKey: termsAcceptedKey) | ||
| } | ||
| set(newVal) { | ||
| userDefaults.setValue(newVal, forKey: termsAcceptedKey) | ||
| } | ||
| } | ||
|
|
||
| } | ||
|
|
||
|
|
| @@ -27,5 +27,9 @@ struct ExpositionInfo: Codable, Equatable { | ||
| case exposed | ||
| case infected | ||
| } | ||
|
|
||
| func isOk() -> Bool { | ||
| error == nil | ||
| } | ||
|
|
||
| } | ||
| @@ -0,0 +1,36 @@ | ||
| // | ||
| // Copyright (c) 2020 Gobierno de España | ||
| // | ||
| // This Source Code Form is subject to the terms of the Mozilla Public | ||
| // License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| // file, You can obtain one at https://mozilla.org/MPL/2.0/. | ||
| // | ||
| // SPDX-License-Identifier: MPL-2.0 | ||
| // | ||
| import Foundation | ||
|
|
||
| struct ItemLocale: Codable { | ||
|
|
||
| let id: String | ||
| let description: String | ||
|
|
||
| static func mappertToKeyValueDto(keyValueDto: KeyValueDto) -> ItemLocale { | ||
| ItemLocale.init(id: keyValueDto.id ?? "", description: keyValueDto.description ?? "") | ||
| } | ||
|
|
||
| static func mappertToDic(dic: [String: String?]) -> [ItemLocale] { | ||
| var locales: [ItemLocale] = [] | ||
|
|
||
| dic.forEach { loc in | ||
| locales.append(ItemLocale.init(id: loc.key, description: loc.value ?? "")) | ||
| } | ||
| return locales | ||
| } | ||
| } | ||
|
|
||
| struct Locales: Codable { | ||
|
|
||
| let itemLocales: [ItemLocale] | ||
| } |