298 lines
12 KiB
Swift
298 lines
12 KiB
Swift
import Alamofire
|
|
import Eureka
|
|
import HAKit
|
|
import MBProgressHUD
|
|
import PromiseKit
|
|
import Shared
|
|
import UIKit
|
|
import Version
|
|
|
|
class ConnectionSettingsViewController: HAFormViewController, RowControllerType {
|
|
public var onDismissCallback: ((UIViewController) -> Void)?
|
|
|
|
let server: Server
|
|
|
|
init(server: Server) {
|
|
self.server = server
|
|
|
|
super.init()
|
|
}
|
|
|
|
private var tokens: [HACancellable] = []
|
|
|
|
deinit {
|
|
tokens.forEach { $0.cancel() }
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
title = server.info.name
|
|
|
|
tokens.append(server.observe { [weak self] info in
|
|
self?.form.allRows.forEach { $0.updateCell() }
|
|
self?.title = info.name
|
|
})
|
|
|
|
let connection = Current.api(for: server)?.connection
|
|
|
|
if Current.servers.all.count > 1 {
|
|
form +++ Section(footer: L10n.Settings.ConnectionSection.activateSwipeHint) {
|
|
_ in
|
|
} <<< ButtonRow {
|
|
$0.title = L10n.Settings.ConnectionSection.activateServer
|
|
$0.onCellSelection { [server] _, _ in
|
|
Current.sceneManager.webViewWindowControllerPromise.done {
|
|
$0.open(server: server)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
form
|
|
+++ Section(header: L10n.Settings.StatusSection.header, footer: "") {
|
|
$0.tag = "status"
|
|
}
|
|
|
|
<<< LabelRow("connectionPath") {
|
|
$0.title = L10n.Settings.ConnectionSection.connectingVia
|
|
$0.displayValueFor = { [server] _ in server.info.connection.activeURLType.description }
|
|
}
|
|
|
|
<<< LabelRow("version") {
|
|
$0.title = L10n.Settings.StatusSection.VersionRow.title
|
|
$0.displayValueFor = { [server] _ in server.info.version.description }
|
|
}
|
|
|
|
<<< with(WebSocketStatusRow()) {
|
|
$0.connection = connection
|
|
}
|
|
|
|
<<< LabelRow { row in
|
|
row.title = L10n.SettingsDetails.Notifications.LocalPush.title
|
|
let manager = Current.notificationManager.localPushManager
|
|
|
|
let updateValue = { [weak row, server] in
|
|
guard let row else { return }
|
|
switch manager.status(for: server) {
|
|
case .disabled:
|
|
row.value = L10n.SettingsDetails.Notifications.LocalPush.Status.disabled
|
|
case .unsupported:
|
|
row.value = L10n.SettingsDetails.Notifications.LocalPush.Status.unsupported
|
|
case let .allowed(state):
|
|
switch state {
|
|
case .unavailable:
|
|
row.value = L10n.SettingsDetails.Notifications.LocalPush.Status.unavailable
|
|
case .establishing:
|
|
row.value = L10n.SettingsDetails.Notifications.LocalPush.Status.establishing
|
|
case let .available(received: received):
|
|
let formatted = NumberFormatter.localizedString(
|
|
from: NSNumber(value: received),
|
|
number: .decimal
|
|
)
|
|
row.value = L10n.SettingsDetails.Notifications.LocalPush.Status.available(formatted)
|
|
}
|
|
}
|
|
|
|
row.updateCell()
|
|
}
|
|
|
|
let cancel = manager.addObserver(for: server) { _ in
|
|
updateValue()
|
|
}
|
|
after(life: self).done(cancel.cancel)
|
|
updateValue()
|
|
}
|
|
|
|
<<< LabelRow { row in
|
|
row.title = L10n.Settings.ConnectionSection.loggedInAs
|
|
|
|
if let connection {
|
|
tokens.append(connection.caches.user.subscribe { _, user in
|
|
row.value = user.name
|
|
row.updateCell()
|
|
})
|
|
}
|
|
}
|
|
|
|
+++ Section(L10n.Settings.ConnectionSection.details)
|
|
|
|
<<< TextRow("locationName") {
|
|
$0.title = L10n.Settings.StatusSection.LocationNameRow.title
|
|
$0.placeholder = server.info.remoteName
|
|
$0.value = server.info.setting(for: .localName)
|
|
|
|
var timer: Timer?
|
|
|
|
$0.onChange { [server] row in
|
|
if let timer, timer.isValid {
|
|
timer.fireDate = Current.date().addingTimeInterval(1.0)
|
|
} else {
|
|
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: false, block: { _ in
|
|
server.info.setSetting(value: row.value, for: .localName)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
<<< TextRow {
|
|
$0.title = L10n.SettingsDetails.General.DeviceName.title
|
|
$0.placeholder = Current.device.deviceName()
|
|
$0.value = server.info.setting(for: .overrideDeviceName)
|
|
$0.onChange { [server] row in
|
|
server.info.setSetting(value: row.value, for: .overrideDeviceName)
|
|
}
|
|
}
|
|
|
|
<<< ButtonRowWithPresent<ConnectionURLViewController> { row in
|
|
row.cellStyle = .value1
|
|
row.title = L10n.Settings.ConnectionSection.InternalBaseUrl.title
|
|
row.displayValueFor = { [server] _ in
|
|
if server.info.connection.internalSSIDs?.isEmpty ?? true,
|
|
server.info.connection.internalHardwareAddresses?.isEmpty ?? true {
|
|
return "‼️ \(L10n.Settings.ConnectionSection.InternalBaseUrl.RequiresSetup.title)"
|
|
} else {
|
|
return server.info.connection.address(for: .internal)?.absoluteString ?? "—"
|
|
}
|
|
}
|
|
row.presentationMode = .show(controllerProvider: .callback(builder: { [server] in
|
|
ConnectionURLViewController(server: server, urlType: .internal, row: row)
|
|
}), onDismiss: { [navigationController] _ in
|
|
navigationController?.popViewController(animated: true)
|
|
})
|
|
|
|
row.evaluateHidden()
|
|
}
|
|
|
|
<<< ButtonRowWithPresent<ConnectionURLViewController> { row in
|
|
row.cellStyle = .value1
|
|
row.title = L10n.Settings.ConnectionSection.ExternalBaseUrl.title
|
|
row.displayValueFor = { [server] _ in
|
|
if server.info.connection.useCloud, server.info.connection.canUseCloud {
|
|
return L10n.Settings.ConnectionSection.HomeAssistantCloud.title
|
|
} else {
|
|
return server.info.connection.address(for: .external)?.absoluteString ?? "—"
|
|
}
|
|
}
|
|
row.presentationMode = .show(controllerProvider: .callback(builder: { [server] in
|
|
ConnectionURLViewController(server: server, urlType: .external, row: row)
|
|
}), onDismiss: { [navigationController] _ in
|
|
navigationController?.popViewController(animated: true)
|
|
})
|
|
}
|
|
|
|
+++ Section(L10n.SettingsDetails.Privacy.title)
|
|
|
|
<<< PushRow<ServerLocationPrivacy> {
|
|
$0.title = L10n.Settings.ConnectionSection.LocationSendType.title
|
|
$0.selectorTitle = $0.title
|
|
$0.value = server.info.setting(for: .locationPrivacy)
|
|
$0.options = ServerLocationPrivacy.allCases
|
|
$0.displayValueFor = { $0?.localizedDescription }
|
|
$0.onPresent { [server] _, to in
|
|
to.enableDeselection = false
|
|
if server.info.version <= .updateLocationGPSOptional {
|
|
to.sectionKeyForValue = { _ in
|
|
// so we get asked for section titles
|
|
"section"
|
|
}
|
|
to.selectableRowSetup = { row in
|
|
row.disabled = true
|
|
}
|
|
to.sectionHeaderTitleForKey = { _ in
|
|
nil
|
|
}
|
|
to.sectionFooterTitleForKey = { _ in
|
|
Version.updateLocationGPSOptional.coreRequiredString
|
|
}
|
|
}
|
|
}
|
|
$0.onChange { [server] row in
|
|
server.info.setSetting(value: row.value, for: .locationPrivacy)
|
|
HomeAssistantAPI.manuallyUpdate(
|
|
applicationState: UIApplication.shared.applicationState,
|
|
type: .programmatic
|
|
).cauterize()
|
|
}
|
|
}
|
|
|
|
<<< PushRow<ServerSensorPrivacy> {
|
|
$0.title = L10n.Settings.ConnectionSection.SensorSendType.title
|
|
$0.selectorTitle = $0.title
|
|
$0.value = server.info.setting(for: .sensorPrivacy)
|
|
$0.options = ServerSensorPrivacy.allCases
|
|
$0.displayValueFor = { $0?.localizedDescription }
|
|
$0.onPresent { _, to in
|
|
to.enableDeselection = false
|
|
}
|
|
$0.onChange { [server] row in
|
|
server.info.setSetting(value: row.value, for: .sensorPrivacy)
|
|
Current.api(for: server)?.registerSensors().cauterize()
|
|
}
|
|
}
|
|
|
|
+++ Section()
|
|
|
|
<<< ButtonRow {
|
|
$0.title = L10n.Settings.ConnectionSection.DeleteServer.title
|
|
$0.onCellSelection { [navigationController, server, view] cell, _ in
|
|
let alert = UIAlertController(
|
|
title: L10n.Settings.ConnectionSection.DeleteServer.title,
|
|
message: L10n.Settings.ConnectionSection.DeleteServer.message,
|
|
preferredStyle: .actionSheet
|
|
)
|
|
|
|
with(alert.popoverPresentationController) {
|
|
$0?.sourceView = cell
|
|
$0?.sourceRect = cell.bounds
|
|
}
|
|
|
|
alert
|
|
.addAction(UIAlertAction(
|
|
title: L10n.Settings.ConnectionSection.DeleteServer.title,
|
|
style: .destructive,
|
|
handler: { _ in
|
|
let hud = MBProgressHUD.showAdded(to: view!, animated: true)
|
|
hud.label.text = L10n.Settings.ConnectionSection.DeleteServer.progress
|
|
hud.show(animated: true)
|
|
|
|
let waitAtLeast = after(seconds: 3.0)
|
|
|
|
firstly {
|
|
race(
|
|
when(resolved: Current.apis.map { $0.tokenManager.revokeToken() }).asVoid(),
|
|
after(seconds: 10.0)
|
|
)
|
|
}.then {
|
|
waitAtLeast
|
|
}.get {
|
|
Current.api(for: server)?.connection?.disconnect()
|
|
Current.servers.remove(identifier: server.identifier)
|
|
}.ensure {
|
|
hud.hide(animated: true)
|
|
}.done {
|
|
Current.onboardingObservation.needed(.logout)
|
|
navigationController?.popViewController(animated: true)
|
|
}.cauterize()
|
|
}
|
|
))
|
|
|
|
alert.addAction(UIAlertAction(title: L10n.cancelLabel, style: .cancel, handler: nil))
|
|
cell.formViewController()?.present(alert, animated: true, completion: nil)
|
|
}
|
|
$0.cellUpdate { cell, _ in
|
|
cell.textLabel?.textColor = .systemRed
|
|
}
|
|
}
|
|
}
|
|
|
|
override func viewWillDisappear(_ animated: Bool) {
|
|
super.viewWillDisappear(animated)
|
|
|
|
// Detect when your view controller is popped and invoke the callback
|
|
if !isMovingToParent {
|
|
onDismissCallback?(self)
|
|
}
|
|
}
|
|
}
|