Skip to content

Commit

Permalink
Handling of tiles - debugging, streamlining
Browse files Browse the repository at this point in the history
Moved redundant code to StringExtension.swift

Signed-off-by: Tim Müller-Seydlitz <[email protected]>
  • Loading branch information
timbms committed Jun 15, 2022
1 parent 22ce290 commit 4580c65
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 49 deletions.
8 changes: 1 addition & 7 deletions OpenHABCore/Sources/OpenHABCore/Util/Preferences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public struct UserDefaultURL {
get {
guard let localUrl = Preferences.sharedDefaults.string(forKey: key) else { return defaultValue }
let trimmedUri = uriWithoutTrailingSlashes(localUrl).trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
if !validateUrl(trimmedUri) { return defaultValue }
if !trimmedUri.isValidURL { return defaultValue }
return trimmedUri
}
set {
Expand All @@ -61,12 +61,6 @@ public struct UserDefaultURL {
self.defaultValue = defaultValue
}

private func validateUrl(_ stringURL: String) -> Bool {
// return nil if the URL has not a valid format
let url: URL? = URL(string: stringURL)
return url != nil
}

func uriWithoutTrailingSlashes(_ hostUri: String) -> String {
if !hostUri.hasSuffix("/") {
return hostUri
Expand Down
46 changes: 31 additions & 15 deletions OpenHABCore/Sources/OpenHABCore/Util/StringExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
import Foundation
import MapKit
import os.log
import UIKit

extension String {
var doubleValue: Double {
public extension String {
internal var doubleValue: Double {
let formatter = NumberFormatter()
formatter.decimalSeparator = "."
if let asNumber = formatter.number(from: self) {
Expand All @@ -24,7 +25,7 @@ extension String {
}
}

var intValue: Int {
internal var intValue: Int {
if let asNumber = NumberFormatter().number(from: self) {
return asNumber.intValue
} else {
Expand All @@ -37,18 +38,27 @@ extension String {
Independent of locale's decimal separator

*/
var numberValue: NSNumber? {
internal var numberValue: NSNumber? {
let formatter = NumberFormatter()
formatter.numberStyle = .scientific
formatter.decimalSeparator = "."
return formatter.number(from: filter("01234567890E.+-".contains))
}

var asDouble: Double {
internal var asDouble: Double {
numberValue?.doubleValue ?? 0
}

func toItemType() -> OpenHABItem.ItemType? {
var isValidURL: Bool {
// return nil if the URL has not a valid format
URL(string: self) != nil
}

var isAbsoluteURL: Bool {
URL(string: self) == URL(string: self)?.absoluteURL
}

internal func toItemType() -> OpenHABItem.ItemType? {
var typeString: String = self
// Earlier OH2 versions returned e.g. 'Switch' as 'SwitchItem'
if hasSuffix("Item") {
Expand All @@ -67,11 +77,11 @@ extension String {
return OpenHABItem.ItemType(rawValue: typeString)
}

func toWidgetType() -> OpenHABWidget.WidgetType? {
internal func toWidgetType() -> OpenHABWidget.WidgetType? {
OpenHABWidget.WidgetType(rawValue: self)
}

public func parseAsBool() -> Bool {
func parseAsBool() -> Bool {
if self == "ON" { return true }
if let brightness = parseAsBrightness() { return brightness != 0 }
if let decimalValue = Int(self) {
Expand All @@ -81,7 +91,7 @@ extension String {
}
}

public func parseAsNumber(format: String? = nil) -> NumberState {
func parseAsNumber(format: String? = nil) -> NumberState {
switch self {
case "ON": return NumberState(value: 100.0)
case "OFF": return NumberState(value: 0.0)
Expand All @@ -93,7 +103,7 @@ extension String {
}
}

public func parseAsUIColor() -> UIColor? {
func parseAsUIColor() -> UIColor? {
guard self != "Uninitialized" else {
return .black
}
Expand All @@ -106,17 +116,23 @@ extension String {
return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1.0)
}

public func parseAsBrightness() -> Int? {
func parseAsBrightness() -> Int? {
let values = components(separatedBy: ",")
guard values.count == 3 else { return nil }
return Int(values[2].asDouble.rounded())
}

public mutating func prepare() {
self = replacingOccurrences(of: "^\\.\\.", with: "", options: [.regularExpression])
if !starts(with: "/") {
insert("/", at: startIndex)
func prepare() -> String {
var input = replacingOccurrences(of: "^\\.\\.", with: "", options: [.regularExpression])
if !input.starts(with: "/") {
input.insert("/", at: startIndex)
}
return input
}

func deletingPrefix(_ prefix: String) -> String {
guard hasPrefix(prefix) else { return self }
return String(dropFirst(prefix.count))
}
}

Expand Down
50 changes: 35 additions & 15 deletions openHAB/OpenHABDrawerTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ func deriveSitemaps(_ response: Data?, version: Int?) -> [OpenHABSitemap] {
return sitemaps
}

struct UiTile: Decodable {
var name: String
var url: String
var imageUrl: String
}

enum DrawerTableType {
case withStandardMenuEntries
case withoutStandardMenuEntries
Expand Down Expand Up @@ -144,10 +150,6 @@ class OpenHABDrawerTableViewController: UITableViewController {
}
do {
self.uiTiles = try JSONDecoder().decode([OpenHABUiTile].self, from: responseData)
for tile in self.uiTiles {
tile.imageUrl.prepare()
tile.url.prepare()
}
self.tableView.reloadData()
} catch {
os_log("Error: did not receive data %{PUBLIC}@", log: OSLog.remoteAccess, type: .info, error.localizedDescription)
Expand Down Expand Up @@ -219,10 +221,23 @@ class OpenHABDrawerTableViewController: UITableViewController {
let imageView = UIImageView(frame: cell.customImageView.bounds)
let tile = uiTiles[indexPath.row]
cell.customTextLabel?.text = tile.name
if !tile.imageUrl.isEmpty {
if let iconURL = Endpoint.resource(openHABRootUrl: openHABRootUrl, path: tile.imageUrl).url {
os_log("Loading %{PUBLIC}@", log: .default, type: .info, String(describing: iconURL))
imageView.kf.setImage(with: iconURL, placeholder: UIImage(named: "openHABIcon"))
let passedURL = tile.imageUrl
// Dependent on $OPENHAB_CONF/services/runtime.cfg
// Can either be an absolute URL, a path (sometimes malformed) or the content to be displayed (for imageURL)
if !passedURL.isEmpty {
switch passedURL {
case _ where passedURL.hasPrefix("data:image"):
if let imageData = Data(base64Encoded: passedURL.deletingPrefix("data:image/png;base64,"), options: .ignoreUnknownCharacters) {
imageView.image = UIImage(data: imageData)
} // data;image/png;base64,
case _ where passedURL.hasPrefix("http"):
os_log("Loading %{PUBLIC}@", log: .default, type: .info, String(describing: passedURL))
imageView.kf.setImage(with: URL(string: passedURL), placeholder: UIImage(named: "openHABIcon"))
default:
if let builtURL = Endpoint.resource(openHABRootUrl: openHABRootUrl, path: passedURL.prepare()).url {
os_log("Loading %{PUBLIC}@", log: .default, type: .info, String(describing: builtURL))
imageView.kf.setImage(with: builtURL, placeholder: UIImage(named: "openHABIcon"))
}
}
} else {
imageView.image = UIImage(named: "openHABIcon")
Expand Down Expand Up @@ -298,7 +313,18 @@ class OpenHABDrawerTableViewController: UITableViewController {
self.delegate?.modalDismissed(to: .webview)
}
case 1:
openURL(url: Endpoint.resource(openHABRootUrl: openHABRootUrl, path: uiTiles[indexPath.row].url).url)
let passedURL = uiTiles[indexPath.row].url
// Dependent on $OPENHAB_CONF/services/runtime.cfg
// Can either be an absolute URL, a path (sometimes malformed)
if !passedURL.isEmpty {
switch passedURL {
case _ where passedURL.hasPrefix("http"):
openURL(url: URL(string: passedURL))
default:
let builtURL = Endpoint.resource(openHABRootUrl: openHABRootUrl, path: passedURL.prepare())
openURL(url: builtURL.url)
}
}
case 2:
if !sitemaps.isEmpty {
let sitemap = sitemaps[indexPath.row]
Expand Down Expand Up @@ -358,9 +384,3 @@ class OpenHABDrawerTableViewController: UITableViewController {
}
}
}

struct UiTile: Decodable {
var name: String
var url: String
var imageUrl: String
}
6 changes: 0 additions & 6 deletions openHAB/OpenHABTracker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,6 @@ class OpenHABTracker: NSObject {
return url
}

func validateUrl(_ url: String?) -> Bool {
let theURL = "(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+"
let urlTest = NSPredicate(format: "SELF MATCHES %@", theURL)
return urlTest.evaluate(with: url)
}

func isNetworkConnected() -> Bool {
reach?.isReachable ?? false
}
Expand Down
12 changes: 12 additions & 0 deletions openHAB/OpenHABWebViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class OpenHABWebViewController: UIViewController {
true
}

private var observation: NSKeyValueObservation?
private var progressView: UIProgressView!

private lazy var webView: WKWebView = {
let config = WKWebViewConfiguration()
config.allowsInlineMediaPlayback = true
Expand All @@ -58,6 +61,11 @@ class OpenHABWebViewController: UIViewController {
super.viewDidLoad()
navigationController?.interactivePopGestureRecognizer?.isEnabled = true
view.addSubview(webView)
progressView = UIProgressView(progressViewStyle: .default)
progressView.sizeToFit()
observation = webView.observe(\.estimatedProgress, options: [.new]) { _, _ in
self.progressView.progress = Float(self.webView.estimatedProgress)
}
}

override func viewWillAppear(_ animated: Bool) {
Expand Down Expand Up @@ -95,6 +103,10 @@ class OpenHABWebViewController: UIViewController {
}
return orig
}

deinit {
observation = nil
}
}

extension OpenHABWebViewController: WKScriptMessageHandler {
Expand Down
36 changes: 36 additions & 0 deletions openHABTestsSwift/OpenHABEndPoint.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// OpenHABEndPoint.swift
// openHABTestsSwift
//
// Created by Tim Müller-Seydlitz on 10.06.22.
// Copyright © 2022 openHAB e.V. All rights reserved.
//

import XCTest

class OpenHABEndPoint: XCTestCase {

override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
}

override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}

func testExample() throws {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
// Any test you write for XCTest can be annotated as throws and async.
// Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
// Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
}

func testPerformanceExample() throws {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}

}
6 changes: 0 additions & 6 deletions openHABWatch Extension/OpenHABWatchTracker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -269,12 +269,6 @@ class OpenHABWatchTracker: NSObject {
return url
}

func validateUrl(_ url: String?) -> Bool {
let theURL = "(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+"
let urlTest = NSPredicate(format: "SELF MATCHES %@", theURL)
return urlTest.evaluate(with: url)
}

func isNetworkConnected() -> Bool {
pathMonitor.currentPath.status == .satisfied
}
Expand Down

0 comments on commit 4580c65

Please sign in to comment.