From 9b345dcdf37869baaab17a22fa01d1ceb45b17a0 Mon Sep 17 00:00:00 2001 From: Michal Polanski Date: Wed, 25 Sep 2024 12:45:24 +0200 Subject: [PATCH] Issue #416: Bug fixes & improvements --- .../SuplaCore+BaseViewController.swift | 5 + .../UI/Buttons/BaseControlButtonView.swift | 12 +- SUPLA/Core/UI/Details/StandardDetailVC.swift | 4 +- .../Core/UI/Views/ThermostatControlView.swift | 30 +-- .../SwitchGeneral/SwitchGeneralVC.swift | 2 + .../SwitchGeneral/SwitchGeneralVM.swift | 2 + .../SlavesDetail/ThermostatSlavesVC.swift | 20 ++ .../SlavesDetail/ThermostatSlavesVM.swift | 56 ++++- .../ThermstatSlavesViewState.swift | 2 + .../ThermostatGeneralVM.swift | 200 ++++++++++-------- SUPLA/Features/Main/MainVC.swift | 2 +- .../Extensions/SAChannelBase+Ext.swift | 9 + SUPLA/Resources/Default.strings | 1 + SUPLA/Resources/Extensions/String+Icons.swift | 1 + .../Resources/Extensions/UIImage+Supla.swift | 1 + .../furnace_off.svg | 4 +- .../furnace_off_nm.svg | 4 +- .../furnace_on.svg | 4 +- .../furnace_on_nm.svg | 4 +- .../gas_off-1.svg | 4 +- .../gas_off.svg | 4 +- .../gas_on-1.svg | 4 +- .../gas_on.svg | 4 +- .../off-1.svg | 2 +- .../off.svg | 2 +- .../on-1.svg | 4 +- .../on.svg | 4 +- .../heat pump_off-1.svg | 6 +- .../heat pump_off.svg | 6 +- .../heat pump_on-1.svg | 12 +- .../heat pump_on.svg | 12 +- .../heat pump2_off-1.svg | 18 +- .../heat pump2_off.svg | 18 +- .../heat pump2_on-1.svg | 18 +- .../heat pump2_on.svg | 18 +- .../heat pump 4_off-1.svg | 14 +- .../heat pump 4_off.svg | 14 +- .../heat pump 4_on-1.svg | 14 +- .../heat pump 4_on.svg | 14 +- .../heating circulation pump on-1.svg | 4 +- .../heating circulation pump on-3.svg | 4 +- .../heating circulation pump on-2.svg | 2 +- .../heating circulation pump on.svg | 2 +- .../icon_list.imageset}/Contents.json | 0 .../icon_list.imageset}/list.pdf | Bin SUPLA/Resources/Strings.swift | 1 + SUPLA/Resources/de.lproj/Localizable.strings | 1 + SUPLA/Resources/pl.lproj/Localizable.strings | 1 + .../ThermostatGeneralVMTests.swift | 18 +- 49 files changed, 360 insertions(+), 228 deletions(-) rename SUPLA/Resources/Resources.xcassets/Images/{list.imageset => Icons/icon_list.imageset}/Contents.json (100%) rename SUPLA/Resources/Resources.xcassets/Images/{list.imageset => Icons/icon_list.imageset}/list.pdf (100%) diff --git a/SUPLA/Core/SwiftUiComponents/Architecture/SuplaCore+BaseViewController.swift b/SUPLA/Core/SwiftUiComponents/Architecture/SuplaCore+BaseViewController.swift index 65330567..53333854 100644 --- a/SUPLA/Core/SwiftUiComponents/Architecture/SuplaCore+BaseViewController.swift +++ b/SUPLA/Core/SwiftUiComponents/Architecture/SuplaCore+BaseViewController.swift @@ -89,6 +89,7 @@ extension SuplaCore { NotificationCenter.default.removeObserver(self, name: UIApplication.willEnterForegroundNotification, object: nil) NotificationCenter.default.removeObserver(self, name: UIApplication.didEnterBackgroundNotification, object: nil) + NotificationCenter.default.removeObserver(self) } override func viewDidDisappear(_ animated: Bool) { @@ -96,6 +97,10 @@ extension SuplaCore { onViewDisappeared() } + func observeNotification(name: NSNotification.Name?, selector: Selector) { + NotificationCenter.default.addObserver(self, selector: selector, name: name, object: nil) + } + private func setupConstraints() { NSLayoutConstraint.activate([ hostingController.view.topAnchor.constraint(equalTo: view.topAnchor), diff --git a/SUPLA/Core/UI/Buttons/BaseControlButtonView.swift b/SUPLA/Core/UI/Buttons/BaseControlButtonView.swift index c31720d7..86e67d35 100644 --- a/SUPLA/Core/UI/Buttons/BaseControlButtonView.swift +++ b/SUPLA/Core/UI/Buttons/BaseControlButtonView.swift @@ -82,10 +82,12 @@ class BaseControlButtonView: UIView { var active: Bool = false { didSet { - layer.shadowColor = active ? type.pressedColor.cgColor : UIColor.black.cgColor - layer.borderColor = active ? type.pressedColor.cgColor : UIColor.disabled.cgColor - textView.textColor = active ? type.textColor : type.inactiveColor - iconView.tintColor = active ? type.textColor : iconColor + traitCollection.performAsCurrent { + layer.shadowColor = active ? type.pressedColor.cgColor : UIColor.black.cgColor + layer.borderColor = active ? type.pressedColor.cgColor : UIColor.disabled.cgColor + textView.textColor = active ? type.textColor : type.inactiveColor + iconView.tintColor = active ? type.textColor : iconColor + } innerShadowView.isHidden = !active setNeedsLayout() @@ -255,7 +257,7 @@ class BaseControlButtonView: UIView { switch (self) { case .positive: return .green case .negative: return .negativeBorder - case .neutral: return .black + case .neutral: return .onBackground } } diff --git a/SUPLA/Core/UI/Details/StandardDetailVC.swift b/SUPLA/Core/UI/Details/StandardDetailVC.swift index 0c165646..5e8cceae 100644 --- a/SUPLA/Core/UI/Details/StandardDetailVC.swift +++ b/SUPLA/Core/UI/Details/StandardDetailVC.swift @@ -164,8 +164,8 @@ class StandardDetailVC private func thermostatList() -> UIViewController { let vc = ThermostatSlavesFeature.ViewController.create(item: item) vc.tabBarItem = UITabBarItem( - title: "List", - image: UIImage(named: "list"), + title: settings.showBottomLabels ? Strings.StandardDetail.tabList : nil, + image: .iconList, tag: DetailTabTag.List.rawValue ) return vc diff --git a/SUPLA/Core/UI/Views/ThermostatControlView.swift b/SUPLA/Core/UI/Views/ThermostatControlView.swift index 2e6f3106..aceef08b 100644 --- a/SUPLA/Core/UI/Views/ThermostatControlView.swift +++ b/SUPLA/Core/UI/Views/ThermostatControlView.swift @@ -107,18 +107,18 @@ final class ThermostatControlView: UIView { traitCollection.performAsCurrent { temperatureCircleShape.operationalMode = operationalMode } - indicatorHeatingShape.isHidden = operationalMode != .heating - indicatorCoolingShape.isHidden = operationalMode != .cooling - currentPowerLabel.isHidden = operationalMode != .heating && operationalMode != .cooling || currentPower <= 1 + indicatorHeatingShape.isHidden = !operationalMode.isHeating + indicatorCoolingShape.isHidden = !operationalMode.isCooling + currentPowerLabel.isHidden = !operationalMode.isHeating && !operationalMode.isCooling || currentPower <= 1 - if (oldValue == .heating && operationalMode != .heating) { + if (oldValue.isHeating && !operationalMode.isHeating) { indicatorHeatingShape.removeAllAnimations() - } else if (operationalMode == .heating && oldValue != .heating) { + } else if (operationalMode.isHeating && !oldValue.isHeating) { indicatorHeatingShape.add(blinkingAnimation, forKey: "heat blinking") } - if (oldValue == .cooling && operationalMode != .cooling) { + if (oldValue.isCooling && !operationalMode.isCooling) { indicatorCoolingShape.removeAllAnimations() - } else if (operationalMode == .cooling && oldValue != .cooling) { + } else if (operationalMode.isCooling && !oldValue.isCooling) { indicatorCoolingShape.add(blinkingAnimation, forKey: "cool blinking") } @@ -129,7 +129,7 @@ final class ThermostatControlView: UIView { var currentPower: Int = 0 { didSet { temperatureCircleShape.currentPower = currentPower - currentPowerLabel.isHidden = operationalMode != .heating && operationalMode != .cooling || currentPower <= 1 + currentPowerLabel.isHidden = !operationalMode.isStrictHeating && !operationalMode.isStrictCooling || currentPower <= 1 currentPowerLabel.text = "\(currentPower - 1)%" setNeedsLayout() @@ -251,11 +251,11 @@ final class ThermostatControlView: UIView { height: maxTemperatureView.intrinsicContentSize.height ) - let correction: CGFloat = currentPower > 1 ? 75 : 55 + let correction: CGFloat = (operationalMode.isStrictCooling || operationalMode.isStrictHeating) && currentPower > 1 ? 75 : 55 indicatorHeatingShape.position = CGPoint(x: frame.width / 2, y: frame.height / 2 - correction) indicatorCoolingShape.position = CGPoint(x: frame.width / 2, y: frame.height / 2 + correction) - let textCorrection: CGFloat = operationalMode == .heating ? -45 : 45 + let textCorrection: CGFloat = operationalMode.isHeating ? -45 : 45 currentPowerLabel.frame = CGRect( x: CGFloat(frame.width / 2 - currentPowerLabel.intrinsicContentSize.width / 2), y: CGFloat(frame.height / 2 - currentPowerLabel.intrinsicContentSize.height / 2) + textCorrection, @@ -416,8 +416,9 @@ private class TemperatureCircleLayer: CAShapeLayer { var operationalMode: ThermostatOperationalMode = .offline { didSet { - powerBackgroundSublayer.isHidden = operationalMode != .cooling && operationalMode != .heating || currentPower <= 1 - powerIndicatorSublayer.isHidden = operationalMode != .cooling && operationalMode != .heating || currentPower <= 1 + let powerHidden = !operationalMode.isStrictCooling && !operationalMode.isStrictHeating || currentPower <= 1 + powerBackgroundSublayer.isHidden = powerHidden + powerIndicatorSublayer.isHidden = powerHidden powerBackgroundSublayer.strokeColor = operationalMode.backgroundColor.cgColor powerIndicatorSublayer.strokeColor = operationalMode.foregroundColor.cgColor @@ -428,8 +429,9 @@ private class TemperatureCircleLayer: CAShapeLayer { var currentPower: Int = 0 { didSet { - powerBackgroundSublayer.isHidden = operationalMode != .cooling && operationalMode != .heating || currentPower <= 1 - powerIndicatorSublayer.isHidden = operationalMode != .cooling && operationalMode != .heating || currentPower <= 1 + let powerHidden = !operationalMode.isStrictCooling && !operationalMode.isStrictHeating || currentPower <= 1 + powerBackgroundSublayer.isHidden = powerHidden + powerIndicatorSublayer.isHidden = powerHidden updatePowerPath() } diff --git a/SUPLA/Features/Details/SwitchDetail/SwitchGeneral/SwitchGeneralVC.swift b/SUPLA/Features/Details/SwitchDetail/SwitchGeneral/SwitchGeneralVC.swift index b57886c2..63b6156d 100644 --- a/SUPLA/Features/Details/SwitchDetail/SwitchGeneral/SwitchGeneralVC.swift +++ b/SUPLA/Features/Details/SwitchDetail/SwitchGeneral/SwitchGeneralVC.swift @@ -83,6 +83,8 @@ class SwitchGeneralVC : BaseViewControllerVM UIViewController { ViewController(viewModel: ViewModel(), item: item) } diff --git a/SUPLA/Features/Details/ThermostatDetail/SlavesDetail/ThermostatSlavesVM.swift b/SUPLA/Features/Details/ThermostatDetail/SlavesDetail/ThermostatSlavesVM.swift index d7312225..1fef2bb5 100644 --- a/SUPLA/Features/Details/ThermostatDetail/SlavesDetail/ThermostatSlavesVM.swift +++ b/SUPLA/Features/Details/ThermostatDetail/SlavesDetail/ThermostatSlavesVM.swift @@ -33,21 +33,54 @@ extension ThermostatSlavesFeature { readChannelWithChildrenTreeUseCase.invoke(remoteId: remoteId) .asDriverWithoutError() .drive( - onNext: { [weak self] in self?.handle(channel: $0) } + onNext: { [weak self] in self?.handle(channel: $0) }, + onCompleted: { SALog.debug("Completed!!") } ) .disposed(by: disposeBag) } + func reloadData(_ remoteId: Int32, _ relatedId: Int32) { + if (state.relatedIds.contains(relatedId)) { + loadData(remoteId) + } + } + private func handle(channel: ChannelWithChildren) { state.master = channel.toThermostatData() state.slaves = channel.allDescendantFlat .filter { $0.relationType == .masterThermostat } .map { $0.toThermostatData() } + + state.relatedIds = channel.relatedIds + state.relatedIds.append( + contentsOf: channel.allDescendantFlat + .filter { $0.relationType == .masterThermostat } + .flatMap { $0.relatedIds } + ) } } } private extension ChannelChild { + var relatedIds: [Int32] { + var ids: [Int32] = [] + ids.append(channel.remote_id) + + if let thermometer = children.first(where: { $0.relationType == .mainThermometer }) { + ids.append(thermometer.channel.remote_id) + } + + if let pumpSwitch = children.first(where: { $0.relationType == .pumpSwitch }) { + ids.append(pumpSwitch.channel.remote_id) + } + + if let heatOrColdSourceSwitch = children.first(where: { $0.relationType == .heatOrColdSourceSwitch }) { + ids.append(heatOrColdSourceSwitch.channel.remote_id) + } + + return ids + } + func toThermostatData() -> ThermostatSlavesFeature.ThermostatData { @Singleton var getChannelCaptionUseCase: GetChannelBaseCaptionUseCase @Singleton var getChannelIconUseCase: GetChannelBaseIconUseCase @@ -78,11 +111,28 @@ private extension ChannelChild { channel: channel ) } - - } private extension ChannelWithChildren { + var relatedIds: [Int32] { + var ids: [Int32] = [] + ids.append(channel.remote_id) + + if let thermometer = children.first(where: { $0.relationType == .mainThermometer }) { + ids.append(thermometer.channel.remote_id) + } + + if let pumpSwitch = children.first(where: { $0.relationType == .pumpSwitch }) { + ids.append(pumpSwitch.channel.remote_id) + } + + if let heatOrColdSourceSwitch = children.first(where: { $0.relationType == .heatOrColdSourceSwitch }) { + ids.append(heatOrColdSourceSwitch.channel.remote_id) + } + + return ids + } + func toThermostatData() -> ThermostatSlavesFeature.ThermostatData { @Singleton var getChannelCaptionUseCase: GetChannelBaseCaptionUseCase @Singleton var getChannelIconUseCase: GetChannelBaseIconUseCase diff --git a/SUPLA/Features/Details/ThermostatDetail/SlavesDetail/ThermstatSlavesViewState.swift b/SUPLA/Features/Details/ThermostatDetail/SlavesDetail/ThermstatSlavesViewState.swift index 092d642e..8ff03aad 100644 --- a/SUPLA/Features/Details/ThermostatDetail/SlavesDetail/ThermstatSlavesViewState.swift +++ b/SUPLA/Features/Details/ThermostatDetail/SlavesDetail/ThermstatSlavesViewState.swift @@ -21,6 +21,8 @@ extension ThermostatSlavesFeature { @Published var master: ThermostatData? = nil @Published var slaves: [ThermostatData] = [] @Published var scale: CGFloat = 1 + + var relatedIds: [Int32] = [] } struct ThermostatData: Equatable, Identifiable { diff --git a/SUPLA/Features/Details/ThermostatDetail/ThermostatGeneral/ThermostatGeneralVM.swift b/SUPLA/Features/Details/ThermostatDetail/ThermostatGeneral/ThermostatGeneralVM.swift index 134488a5..eaee7d22 100644 --- a/SUPLA/Features/Details/ThermostatDetail/ThermostatGeneral/ThermostatGeneralVM.swift +++ b/SUPLA/Features/Details/ThermostatDetail/ThermostatGeneral/ThermostatGeneralVM.swift @@ -16,13 +16,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -import RxSwift import RxRelay +import RxSwift private let REFRESH_DELAY_S: Double = 3 class ThermostatGeneralVM: BaseViewModel { - @Singleton private var readChannelWithChildrenTreeUseCase @Singleton private var createTemperaturesListUseCase @Singleton private var getChannelConfigUseCase @@ -67,7 +66,7 @@ class ThermostatGeneralVM: BaseViewModel dateProvider.currentTimestamp() { + lastInteractionTime + REFRESH_DELAY_S > dateProvider.currentTimestamp() + { SALog.info("Update skipped because of last interaction time") updateRelay.accept(()) return state // Do not change anything during 3 secs after last user interaction @@ -302,7 +303,8 @@ class ThermostatGeneralVM: BaseViewModel ThermostatGeneralViewState { return state .changing( - path: \.heatingIndicatorInactive, - to: !isActive(channelWithChildren, .heating) + path: \.heatingIndicatorActive, + to: isActive(channelWithChildren, .heating) ) .changing( - path: \.coolingIndicatorInactive, - to: !isActive(channelWithChildren, .cooling) + path: \.coolingIndicatorActive, + to: isActive(channelWithChildren, .cooling) ) } @@ -421,7 +423,7 @@ class ThermostatGeneralVM: BaseViewModel var formatter - - if (offline) { - return "offline" - } else if (off) { - return "off" - } else if (mode == .heat) { - return formatter.temperatureToString(setpointHeat, withUnit: false) - } else if (mode == .cool) { - return formatter.temperatureToString(setpointCool, withUnit: false) - } + @Singleton var formatter - return nil + if (offline) { + return "offline" + } else if (off) { + return "off" + } else if (mode == .heat) { + return formatter.temperatureToString(setpointHeat, withUnit: false) + } else if (mode == .cool) { + return formatter.temperatureToString(setpointCool, withUnit: false) } + + return nil } + var setpointHeatPercentage: Float? { - get { - guard let min = configMin, - let max = configMax, - let current = setpointHeat, - !off || weeklyScheduleActive - else { return nil } - return (current - min) / (max - min) - } + guard let min = configMin, + let max = configMax, + let current = setpointHeat, + !off || weeklyScheduleActive + else { return nil } + return (current - min) / (max - min) } + var setpointCoolPercentage: Float? { - get { - guard let min = configMin, - let max = configMax, - let current = setpointCool, - !off || weeklyScheduleActive - else { return nil } - return (current - min) / (max - min) - } + guard let min = configMin, + let max = configMax, + let current = setpointCool, + !off || weeklyScheduleActive + else { return nil } + return (current - min) / (max - min) } + var plusButtonEnabled: Bool { - get { - if (mode == .off && !weeklyScheduleActive) { - return false - } - switch (activeSetpointType) { - case .heat: return (setpointHeat ?? 0) < (configMax ?? 0) - case .cool: return (setpointCool ?? 0) < (configMax ?? 0) - default: return false - } + if (mode == .off && !weeklyScheduleActive) { + return false + } + switch (activeSetpointType) { + case .heat: return (setpointHeat ?? 0) < (configMax ?? 0) + case .cool: return (setpointCool ?? 0) < (configMax ?? 0) + default: return false } } + var minusButtonEnabled: Bool { - get { - if (mode == .off && !weeklyScheduleActive) { - return false - } - switch (activeSetpointType) { - case .heat: return (setpointHeat ?? 0) > (configMin ?? 0) - case .cool: return (setpointCool ?? 0) > (configMin ?? 0) - default: return false - } + if (mode == .off && !weeklyScheduleActive) { + return false + } + switch (activeSetpointType) { + case .heat: return (setpointHeat ?? 0) > (configMin ?? 0) + case .cool: return (setpointCool ?? 0) > (configMin ?? 0) + default: return false } } + var powerIconColor: UIColor { - get { - if ((off && !weeklyScheduleActive) || offline) { - return .red - } else { - return .primary - } + if ((off && !weeklyScheduleActive) || offline) { + return .red + } else { + return .primary } } + var controlButtonsEnabled: Bool { !offline } var configMinMaxHidden: Bool { offline } var grayOutSetpoints: Bool { !offline && off && weeklyScheduleActive } @@ -680,6 +673,7 @@ struct ThermostatGeneralViewState: ViewState { var timerInfoHidden: Bool { sensorIssue != nil || timerEndDate == nil || timerEndDate!.timeIntervalSince1970 < Date().timeIntervalSince1970 } + var endDateText: String { DeviceState.endDateText(timerEndDate) } var currentStateIcon: UIImage? { DeviceState.currentStateIcon(mode)?.uiImage } var currentStateIconColor: UIColor { DeviceState.currentStateIconColor(mode) } @@ -692,12 +686,20 @@ struct ThermostatGeneralViewState: ViewState { } } -enum ThermostatOperationalMode { - case offline, off, heating, cooling, standby +enum ThermostatOperationalMode: Equatable { + case offline, off(heating: Bool, cooling: Bool), heating, cooling, standby var foregroundColor: UIColor { switch (self) { - case .offline, .off: .black + case .offline: .black + case .off(let heating, let cooling): + if (heating) { + .error + } else if (cooling) { + .secondary + } else { + .black + } case .heating: .error case .cooling: .secondary case .standby: .primary @@ -711,9 +713,39 @@ enum ThermostatOperationalMode { default: .transparent } } + + var isHeating: Bool { + switch self { + case .heating: true + case .off(let heating, _): heating + default: false + } + } + + var isCooling: Bool { + switch self { + case .cooling: true + case .off(_, let cooling): cooling + default: false + } + } + + var isStrictHeating: Bool { + switch self { + case .heating: true + default: false + } + } + + var isStrictCooling: Bool { + switch self { + case .cooling: true + default: false + } + } } -fileprivate extension SAChannel { +private extension SAChannel { func isThermostatOff() -> Bool { guard let value = value?.asThermostatValue() else { return false } return !isOnline() || value.mode == .off || value.mode == .notSet @@ -737,7 +769,7 @@ struct SensorIssue: Equatable { let message: String } -fileprivate extension SAChannel { +private extension SAChannel { func isActive(_ flag: SuplaThermostatFlag) -> Bool { guard let value = value?.asThermostatValue() else { return false } return isOnline() && value.state.isOn() && value.flags.contains(flag) diff --git a/SUPLA/Features/Main/MainVC.swift b/SUPLA/Features/Main/MainVC.swift index cb020ccf..e7c41a08 100644 --- a/SUPLA/Features/Main/MainVC.swift +++ b/SUPLA/Features/Main/MainVC.swift @@ -106,7 +106,7 @@ class MainVC: SuplaTabBarController let channelListVC = ChannelListVC() channelListVC.tabBarItem = UITabBarItem( title: settings.showBottomLabels ? Strings.Main.channels : nil, - image: UIImage(named: "list"), + image: .iconList, tag: HomeTabTag.Channels.rawValue ) channelListVC.navigationBarMaintainedByParent = true diff --git a/SUPLA/Model/CoreData/Extensions/SAChannelBase+Ext.swift b/SUPLA/Model/CoreData/Extensions/SAChannelBase+Ext.swift index f421af46..9fec4d98 100644 --- a/SUPLA/Model/CoreData/Extensions/SAChannelBase+Ext.swift +++ b/SUPLA/Model/CoreData/Extensions/SAChannelBase+Ext.swift @@ -58,6 +58,15 @@ extension SAChannelBase { return self.func == SUPLA_CHANNELFNC_HVAC_THERMOSTAT || self.func == SUPLA_CHANNELFNC_HVAC_DOMESTIC_HOT_WATER } + func switchWithButtons() -> Bool { + return switch (self.func) { + case SUPLA_CHANNELFNC_POWERSWITCH, + SUPLA_CHANNELFNC_STAIRCASETIMER, + SUPLA_CHANNELFNC_LIGHTSWITCH: true + default: false + } + } + @objc func isRGBW() -> Bool { return self.func == SUPLA_CHANNELFNC_RGBLIGHTING || self.func == SUPLA_CHANNELFNC_DIMMERANDRGBLIGHTING || self.func == SUPLA_CHANNELFNC_DIMMER diff --git a/SUPLA/Resources/Default.strings b/SUPLA/Resources/Default.strings index 38c641c1..90a2ec72 100644 --- a/SUPLA/Resources/Default.strings +++ b/SUPLA/Resources/Default.strings @@ -106,6 +106,7 @@ "standard_detail_metrics_tab" = "Metrics"; "standard_detail_schedule_tab" = "Week"; "standard_detail_history_tab" = "History"; +"standard_detail_list_tab" = "List"; /* Switch Detail */ "switch_detail_state_label" = "Current state:"; diff --git a/SUPLA/Resources/Extensions/String+Icons.swift b/SUPLA/Resources/Extensions/String+Icons.swift index 0ea1237f..0b6d8d90 100644 --- a/SUPLA/Resources/Extensions/String+Icons.swift +++ b/SUPLA/Resources/Extensions/String+Icons.swift @@ -54,6 +54,7 @@ extension String { static let invisible = "icon_invisible" static let empty = "icon_empty" static let more = "icon_more" + static let list = "icon_list" static let warning = "channel_warning_level1" static let error = "channel_warning_level2" diff --git a/SUPLA/Resources/Extensions/UIImage+Supla.swift b/SUPLA/Resources/Extensions/UIImage+Supla.swift index fd03c675..0f0ef0cc 100644 --- a/SUPLA/Resources/Extensions/UIImage+Supla.swift +++ b/SUPLA/Resources/Extensions/UIImage+Supla.swift @@ -49,6 +49,7 @@ extension UIImage { static let iconInvisible = UIImage(named: .Icons.invisible) static let iconEmpty = UIImage(named: .Icons.empty) static let iconMore = UIImage(named: .Icons.more) + static let iconList = UIImage(named: .Icons.list) static let iconWarning = UIImage(named: .Icons.warning) static let iconError = UIImage(named: .Icons.error) diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-off.imageset/furnace_off.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-off.imageset/furnace_off.svg index e5d23783..ac183d5f 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-off.imageset/furnace_off.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-off.imageset/furnace_off.svg @@ -1,4 +1,4 @@ - - + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-off.imageset/furnace_off_nm.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-off.imageset/furnace_off_nm.svg index 1193a1b8..fbba9a2a 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-off.imageset/furnace_off_nm.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-off.imageset/furnace_off_nm.svg @@ -1,4 +1,4 @@ - - + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-on.imageset/furnace_on.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-on.imageset/furnace_on.svg index 9e38717e..4a329a0c 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-on.imageset/furnace_on.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-on.imageset/furnace_on.svg @@ -1,5 +1,5 @@ - + - + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-on.imageset/furnace_on_nm.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-on.imageset/furnace_on_nm.svg index dc0669da..b64425d2 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-on.imageset/furnace_on_nm.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch-on.imageset/furnace_on_nm.svg @@ -1,5 +1,5 @@ - + - + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-off.imageset/gas_off-1.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-off.imageset/gas_off-1.svg index dee68e28..daf02490 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-off.imageset/gas_off-1.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-off.imageset/gas_off-1.svg @@ -1,4 +1,4 @@ - - + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-off.imageset/gas_off.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-off.imageset/gas_off.svg index 678f9b0b..23feec94 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-off.imageset/gas_off.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-off.imageset/gas_off.svg @@ -1,4 +1,4 @@ - - + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-on.imageset/gas_on-1.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-on.imageset/gas_on-1.svg index 98740efa..b2856dbd 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-on.imageset/gas_on-1.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-on.imageset/gas_on-1.svg @@ -1,5 +1,5 @@ - + - + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-on.imageset/gas_on.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-on.imageset/gas_on.svg index c2dea399..8b869bb5 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-on.imageset/gas_on.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_2-on.imageset/gas_on.svg @@ -1,5 +1,5 @@ - + - + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-off.imageset/off-1.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-off.imageset/off-1.svg index 7b055e97..d6863c7b 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-off.imageset/off-1.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-off.imageset/off-1.svg @@ -1,4 +1,4 @@ - + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-off.imageset/off.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-off.imageset/off.svg index f782ae99..4f01a194 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-off.imageset/off.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-off.imageset/off.svg @@ -1,4 +1,4 @@ - + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-on.imageset/on-1.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-on.imageset/on-1.svg index d0bf7411..21a72b7f 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-on.imageset/on-1.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-on.imageset/on-1.svg @@ -1,5 +1,5 @@ - - + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-on.imageset/on.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-on.imageset/on.svg index ee534d16..c12daceb 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-on.imageset/on.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_3-on.imageset/on.svg @@ -1,5 +1,5 @@ - - + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-off.imageset/heat pump_off-1.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-off.imageset/heat pump_off-1.svg index 3d7f92c7..5228dae0 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-off.imageset/heat pump_off-1.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-off.imageset/heat pump_off-1.svg @@ -1,9 +1,9 @@ - - + + - + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-off.imageset/heat pump_off.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-off.imageset/heat pump_off.svg index fe1d87b9..6c9c461e 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-off.imageset/heat pump_off.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-off.imageset/heat pump_off.svg @@ -1,9 +1,9 @@ - - + + - + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-on.imageset/heat pump_on-1.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-on.imageset/heat pump_on-1.svg index 2af4aa46..29c65f4c 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-on.imageset/heat pump_on-1.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-on.imageset/heat pump_on-1.svg @@ -1,16 +1,16 @@ - - + + - + - - - + + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-on.imageset/heat pump_on.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-on.imageset/heat pump_on.svg index c38e32e1..143976b7 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-on.imageset/heat pump_on.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_4-on.imageset/heat pump_on.svg @@ -1,16 +1,16 @@ - - + + - + - - - + + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-off.imageset/heat pump2_off-1.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-off.imageset/heat pump2_off-1.svg index f8f4fb28..7e6ba4e9 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-off.imageset/heat pump2_off-1.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-off.imageset/heat pump2_off-1.svg @@ -1,15 +1,15 @@ - + - - - - - - - - + + + + + + + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-off.imageset/heat pump2_off.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-off.imageset/heat pump2_off.svg index fa90740a..ae692243 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-off.imageset/heat pump2_off.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-off.imageset/heat pump2_off.svg @@ -1,15 +1,15 @@ - + - - - - - - - - + + + + + + + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-on.imageset/heat pump2_on-1.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-on.imageset/heat pump2_on-1.svg index 9424b6d4..8d66e1ef 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-on.imageset/heat pump2_on-1.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-on.imageset/heat pump2_on-1.svg @@ -1,18 +1,18 @@ - + - + - - - - - - - + + + + + + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-on.imageset/heat pump2_on.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-on.imageset/heat pump2_on.svg index f6695b1f..88d82c67 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-on.imageset/heat pump2_on.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_5-on.imageset/heat pump2_on.svg @@ -1,17 +1,17 @@ - + - - - - - - - - + + + + + + + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-off.imageset/heat pump 4_off-1.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-off.imageset/heat pump 4_off-1.svg index ef37085e..734e8887 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-off.imageset/heat pump 4_off-1.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-off.imageset/heat pump 4_off-1.svg @@ -1,9 +1,9 @@ - - - - - - - + + + + + + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-off.imageset/heat pump 4_off.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-off.imageset/heat pump 4_off.svg index a131ca88..3cb9b1c8 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-off.imageset/heat pump 4_off.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-off.imageset/heat pump 4_off.svg @@ -1,9 +1,9 @@ - - - - - - - + + + + + + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-on.imageset/heat pump 4_on-1.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-on.imageset/heat pump 4_on-1.svg index 1e5db2fc..aa5405d5 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-on.imageset/heat pump 4_on-1.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-on.imageset/heat pump 4_on-1.svg @@ -1,12 +1,12 @@ - - + + - - - - - + + + + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-on.imageset/heat pump 4_on.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-on.imageset/heat pump 4_on.svg index 3d631532..5c5553f0 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-on.imageset/heat pump 4_on.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_heat_or_cold_source_switch_6-on.imageset/heat pump 4_on.svg @@ -1,12 +1,12 @@ - - + + - - - - - + + + + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-off.imageset/heating circulation pump on-1.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-off.imageset/heating circulation pump on-1.svg index 5ccaffdb..d318d139 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-off.imageset/heating circulation pump on-1.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-off.imageset/heating circulation pump on-1.svg @@ -1,4 +1,4 @@ - - + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-off.imageset/heating circulation pump on-3.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-off.imageset/heating circulation pump on-3.svg index 2f6c23e9..8f2c71f5 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-off.imageset/heating circulation pump on-3.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-off.imageset/heating circulation pump on-3.svg @@ -1,4 +1,4 @@ - - + + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-on.imageset/heating circulation pump on-2.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-on.imageset/heating circulation pump on-2.svg index d0d8973f..094d307e 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-on.imageset/heating circulation pump on-2.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-on.imageset/heating circulation pump on-2.svg @@ -1,4 +1,4 @@ - + diff --git a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-on.imageset/heating circulation pump on.svg b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-on.imageset/heating circulation pump on.svg index dcb26497..b37f84da 100644 --- a/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-on.imageset/heating circulation pump on.svg +++ b/SUPLA/Resources/Resources.xcassets/Images/FunctionIcons/fnc_pump_switch-on.imageset/heating circulation pump on.svg @@ -1,4 +1,4 @@ - + diff --git a/SUPLA/Resources/Resources.xcassets/Images/list.imageset/Contents.json b/SUPLA/Resources/Resources.xcassets/Images/Icons/icon_list.imageset/Contents.json similarity index 100% rename from SUPLA/Resources/Resources.xcassets/Images/list.imageset/Contents.json rename to SUPLA/Resources/Resources.xcassets/Images/Icons/icon_list.imageset/Contents.json diff --git a/SUPLA/Resources/Resources.xcassets/Images/list.imageset/list.pdf b/SUPLA/Resources/Resources.xcassets/Images/Icons/icon_list.imageset/list.pdf similarity index 100% rename from SUPLA/Resources/Resources.xcassets/Images/list.imageset/list.pdf rename to SUPLA/Resources/Resources.xcassets/Images/Icons/icon_list.imageset/list.pdf diff --git a/SUPLA/Resources/Strings.swift b/SUPLA/Resources/Strings.swift index 4c20f2de..6f40b61c 100644 --- a/SUPLA/Resources/Strings.swift +++ b/SUPLA/Resources/Strings.swift @@ -174,6 +174,7 @@ struct Strings { static let tabMetrics = "standard_detail_metrics_tab".toLocalized() static let tabSchedule = "standard_detail_schedule_tab".toLocalized() static let tabHistory = "standard_detail_history_tab".toLocalized() + static let tabList = "standard_detail_list_tab".toLocalized() } struct SwitchDetail { diff --git a/SUPLA/Resources/de.lproj/Localizable.strings b/SUPLA/Resources/de.lproj/Localizable.strings index 79357c77..44422222 100644 --- a/SUPLA/Resources/de.lproj/Localizable.strings +++ b/SUPLA/Resources/de.lproj/Localizable.strings @@ -344,6 +344,7 @@ "standard_detail_timer_tab" = "Timer"; "standard_detail_metrics_tab" = "Messungen"; "standard_detail_history_tab" = "Historie"; +"standard_detail_list_tab" = "Liste"; /* Switch Detail */ "switch_detail_state_label" = "Aktuellen Zustand:"; diff --git a/SUPLA/Resources/pl.lproj/Localizable.strings b/SUPLA/Resources/pl.lproj/Localizable.strings index 8ee04b65..ceecdeb0 100644 --- a/SUPLA/Resources/pl.lproj/Localizable.strings +++ b/SUPLA/Resources/pl.lproj/Localizable.strings @@ -374,6 +374,7 @@ "standard_detail_metrics_tab" = "Pomiary"; "standard_detail_schedule_tab" = "Tydzień"; "standard_detail_history_tab" = "Historia"; +"standard_detail_list_tab" = "Lista"; /* Switch Detail */ "switch_detail_state_label" = "Aktualny stan:"; diff --git a/SUPLATests/Tests/Features/Details/ThermostatDetail/ThermostatGeneral/ThermostatGeneralVMTests.swift b/SUPLATests/Tests/Features/Details/ThermostatDetail/ThermostatGeneral/ThermostatGeneralVMTests.swift index 44eecce2..63cd0cab 100644 --- a/SUPLATests/Tests/Features/Details/ThermostatDetail/ThermostatGeneral/ThermostatGeneralVMTests.swift +++ b/SUPLATests/Tests/Features/Details/ThermostatDetail/ThermostatGeneral/ThermostatGeneralVMTests.swift @@ -144,8 +144,8 @@ final class ThermostatGeneralVMTests: ViewModelTest