From 244ede7f0850ced5d77609c3ecd43eff099851ad Mon Sep 17 00:00:00 2001 From: Tim Bert <5411131+timbms@users.noreply.github.com> Date: Wed, 22 Nov 2023 19:35:16 +0100 Subject: [PATCH 01/14] First attempt to get to diffable data source Signed-off-by: Tim Bert <5411131+timbms@users.noreply.github.com> --- openHAB.xcodeproj/project.pbxproj | 6 ++ .../OpenHABSelectionTableViewController.swift | 81 ++++++++++++++++--- openHABUITests/OpenHABUITests.swift | 2 +- .../Views/ContentView.swift | 66 +++++++-------- 4 files changed, 110 insertions(+), 45 deletions(-) diff --git a/openHAB.xcodeproj/project.pbxproj b/openHAB.xcodeproj/project.pbxproj index 02eae31fc..72f682241 100644 --- a/openHAB.xcodeproj/project.pbxproj +++ b/openHAB.xcodeproj/project.pbxproj @@ -1617,6 +1617,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; INFOPLIST_FILE = openHABUITests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1659,6 +1660,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; INFOPLIST_FILE = openHABUITests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1788,6 +1790,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; INFOPLIST_FILE = openHABTestsSwift/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1831,6 +1834,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; INFOPLIST_FILE = openHABTestsSwift/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1988,6 +1992,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "openHAB/openHAB-Prefix.pch"; INFOPLIST_FILE = "openHAB/openHAB-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -2032,6 +2037,7 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "openHAB/openHAB-Prefix.pch"; INFOPLIST_FILE = "openHAB/openHAB-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/openHAB/OpenHABSelectionTableViewController.swift b/openHAB/OpenHABSelectionTableViewController.swift index e3bc64820..37ccbe967 100644 --- a/openHAB/OpenHABSelectionTableViewController.swift +++ b/openHAB/OpenHABSelectionTableViewController.swift @@ -19,9 +19,12 @@ public protocol OpenHABSelectionTableViewControllerDelegate: NSObjectProtocol { } class OpenHABSelectionTableViewController: UITableViewController { - static let tableViewCellIdentifier = "SelectionCell" + private let cellReuseIdentifier = "SelectionCell" - var mappings: [AnyHashable] = [] + private lazy var dataSource = makeDataSource() + private lazy var collectionView = makeCollectionView() + + var mappings: [OpenHABWidgetMapping] = [] weak var delegate: OpenHABSelectionTableViewControllerDelegate? var selectionItem: OpenHABItem? @@ -48,15 +51,14 @@ class OpenHABSelectionTableViewController: UITableViewController { } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: OpenHABSelectionTableViewController.tableViewCellIdentifier, for: indexPath) - if let mapping = mappings[indexPath.row] as? OpenHABWidgetMapping { - cell.textLabel?.text = mapping.label - if selectionItem?.state == mapping.command { - os_log("This item is selected", log: .viewCycle, type: .info) - cell.accessoryType = .checkmark - } else { - cell.accessoryType = .none - } + let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) + let mapping = mappings[indexPath.row] + cell.textLabel?.text = mapping.label + if selectionItem?.state == mapping.command { + os_log("This item is selected", log: .viewCycle, type: .info) + cell.accessoryType = .checkmark + } else { + cell.accessoryType = .none } return cell } @@ -68,3 +70,60 @@ class OpenHABSelectionTableViewController: UITableViewController { navigationController?.popViewController(animated: true) } } + +private extension OpenHABSelectionTableViewController { + enum Section: String, CaseIterable { + case uniq + } +} + +private extension OpenHABSelectionTableViewController { + typealias Cell = UICollectionViewListCell + typealias CellRegistration = UICollectionView.CellRegistration + + func makeCellRegistration() -> CellRegistration { + CellRegistration { cell, indexPath, mapping in + + var content = cell.defaultContentConfiguration() + content.text = mapping.label + + if self.selectionItem?.state == mapping.command { + os_log("This item is selected", log: .viewCycle, type: .info) + content.accessoryType = .checkmark + } else { + cell.accessoryType = .none + } + cell.contentConfiguration = content + } + } +} + +private extension OpenHABSelectionTableViewController { + func makeDataSource() -> UICollectionViewDiffableDataSource { + UICollectionViewDiffableDataSource( + collectionView: collectionView, + cellProvider: makeCellRegistration().cellProvider + ) + } +} + +extension UICollectionView.CellRegistration { + var cellProvider: (UICollectionView, IndexPath, Item) -> Cell { + return { collectionView, indexPath, product in + collectionView.dequeueConfiguredReusableCell( + using: self, + for: indexPath, + item: product + ) + } + } +} + +extension OpenHABSelectionTableViewController { + func update(with list: [OpenHABWidgetMapping], animate: Bool = true) { + var snapshot = NSDiffableDataSourceSnapshot() + snapshot.appendSections(Section.allCases) + snapshot.appendItems(list, toSection: .uniq) + dataSource.apply(snapshot, animatingDifferences: animate) + } +} diff --git a/openHABUITests/OpenHABUITests.swift b/openHABUITests/OpenHABUITests.swift index be90ef4f5..b2f8531ec 100644 --- a/openHABUITests/OpenHABUITests.swift +++ b/openHABUITests/OpenHABUITests.swift @@ -63,7 +63,7 @@ class OpenHABUITests: XCTestCase { menuStaticText?.tap() sleep(1) - + // openHAB logo in left menu webViewsQuery.links.allElementsBoundByIndex[1].tap() sleep(2) diff --git a/openHABWatch Extension/Views/ContentView.swift b/openHABWatch Extension/Views/ContentView.swift index b852d70b6..f5c2e164b 100644 --- a/openHABWatch Extension/Views/ContentView.swift +++ b/openHABWatch Extension/Views/ContentView.swift @@ -19,41 +19,41 @@ struct ContentView: View { @State var title = "openHAB" var body: some View { - ScrollView { - ForEach(viewModel.widgets) { widget in - rowWidget(widget: widget) - .environmentObject(settings) - } - } - .navigationBarTitle(Text(title)) - .alert(isPresented: $viewModel.showAlert) { - Alert( - title: Text(NSLocalizedString("error", comment: "")), - message: Text(viewModel.errorDescription), - dismissButton: .default(Text(NSLocalizedString("retry", comment: ""))) { - DispatchQueue.main.async { - viewModel.refreshUrl() - os_log("reload after alert", log: .default, type: .info) - } + ZStack { + ScrollView { + ForEach(viewModel.widgets) { widget in + rowWidget(widget: widget) + .environmentObject(settings) } - ) - } - .actionSheet(isPresented: $viewModel.showCertificateAlert) { - ActionSheet( - title: Text(NSLocalizedString("warning", comment: "")), - message: Text(viewModel.certificateErrorDescription), - buttons: [ - .default(Text(NSLocalizedString("abort", comment: ""))) { - NetworkConnection.shared.serverCertificateManager.evaluateResult = .deny - }, - .default(Text(NSLocalizedString("once", comment: ""))) { - NetworkConnection.shared.serverCertificateManager.evaluateResult = .permitOnce - }, - .default(Text(NSLocalizedString("always", comment: ""))) { - NetworkConnection.shared.serverCertificateManager.evaluateResult = .permitAlways + } + .navigationBarTitle(Text(title)) + .actionSheet(isPresented: $viewModel.showCertificateAlert) { + ActionSheet( + title: Text(NSLocalizedString("warning", comment: "")), + message: Text(viewModel.certificateErrorDescription), + buttons: [ + .default(Text(NSLocalizedString("abort", comment: ""))) { + NetworkConnection.shared.serverCertificateManager.evaluateResult = .deny + }, + .default(Text(NSLocalizedString("once", comment: ""))) { + NetworkConnection.shared.serverCertificateManager.evaluateResult = .permitOnce + }, + .default(Text(NSLocalizedString("always", comment: ""))) { + NetworkConnection.shared.serverCertificateManager.evaluateResult = .permitAlways + } + ] + ) + } + if viewModel.showAlert { + Text("Refreshing...") + .onAppear { + DispatchQueue.main.async { + viewModel.refreshUrl() + os_log("reload after alert", log: .default, type: .info) + } + viewModel.showAlert = false } - ] - ) + } } } From 8c7f1497cac4f0dfbe4d6a0c205f8ab498b16b52 Mon Sep 17 00:00:00 2001 From: Tim Bert <5411131+timbms@users.noreply.github.com> Date: Wed, 22 Nov 2023 21:38:55 +0100 Subject: [PATCH 02/14] Crashing because of link to to Storyboard searching for a TableView Signed-off-by: Tim Bert <5411131+timbms@users.noreply.github.com> --- .../OpenHABSelectionTableViewController.swift | 41 ++++--------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/openHAB/OpenHABSelectionTableViewController.swift b/openHAB/OpenHABSelectionTableViewController.swift index 37ccbe967..11e58976f 100644 --- a/openHAB/OpenHABSelectionTableViewController.swift +++ b/openHAB/OpenHABSelectionTableViewController.swift @@ -18,11 +18,10 @@ public protocol OpenHABSelectionTableViewControllerDelegate: NSObjectProtocol { func didSelectWidgetMapping(_ selectedMapping: Int) } -class OpenHABSelectionTableViewController: UITableViewController { +class OpenHABSelectionTableViewController: UICollectionViewController { private let cellReuseIdentifier = "SelectionCell" private lazy var dataSource = makeDataSource() - private lazy var collectionView = makeCollectionView() var mappings: [OpenHABWidgetMapping] = [] weak var delegate: OpenHABSelectionTableViewControllerDelegate? @@ -37,33 +36,10 @@ class OpenHABSelectionTableViewController: UITableViewController { os_log("I have %d mappings", log: .viewCycle, type: .info, mappings.count) - // Uncomment the following line to preserve selection between presentations. - // self.clearsSelectionOnViewWillAppear = NO; - - // Uncomment the following line to display an Edit button in the navigation bar for this view controller. - // self.navigationItem.rightBarButtonItem = self.editButtonItem; - } - - // MARK: - Table view data source - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - mappings.count - } - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) - let mapping = mappings[indexPath.row] - cell.textLabel?.text = mapping.label - if selectionItem?.state == mapping.command { - os_log("This item is selected", log: .viewCycle, type: .info) - cell.accessoryType = .checkmark - } else { - cell.accessoryType = .none - } - return cell + collectionView.dataSource = dataSource } - override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { os_log("Selected mapping %d", log: .viewCycle, type: .info, indexPath.row) delegate?.didSelectWidgetMapping(indexPath.row) @@ -82,18 +58,19 @@ private extension OpenHABSelectionTableViewController { typealias CellRegistration = UICollectionView.CellRegistration func makeCellRegistration() -> CellRegistration { - CellRegistration { cell, indexPath, mapping in + CellRegistration { cell, _, mapping in var content = cell.defaultContentConfiguration() content.text = mapping.label + cell.contentConfiguration = content + if self.selectionItem?.state == mapping.command { os_log("This item is selected", log: .viewCycle, type: .info) - content.accessoryType = .checkmark + cell.accessories = [.checkmark()] } else { - cell.accessoryType = .none + cell.accessories = [] } - cell.contentConfiguration = content } } } @@ -109,7 +86,7 @@ private extension OpenHABSelectionTableViewController { extension UICollectionView.CellRegistration { var cellProvider: (UICollectionView, IndexPath, Item) -> Cell { - return { collectionView, indexPath, product in + { collectionView, indexPath, product in collectionView.dequeueConfiguredReusableCell( using: self, for: indexPath, From 8fe48624485a2f3f77431dca88d41aed67fd710b Mon Sep 17 00:00:00 2001 From: Tim Bert <5411131+timbms@users.noreply.github.com> Date: Wed, 22 Nov 2023 22:33:18 +0100 Subject: [PATCH 03/14] Migrated OpenHABSelectionTableViewController to CollectionView - Renamed to OpenHABSelectionCollectionViewController Migrated OpenHABSelectionCollectionViewController away from Storyboard Showing view controllers, rather than pushing them, see https://www.swiftbysundell.com/tips/showing-view-controllers/ Signed-off-by: Tim Bert <5411131+timbms@users.noreply.github.com> --- ... => OpenHABSelectionCollectionViewController.swift} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename openHAB/{OpenHABSelectionTableViewController.swift => OpenHABSelectionCollectionViewController.swift} (90%) diff --git a/openHAB/OpenHABSelectionTableViewController.swift b/openHAB/OpenHABSelectionCollectionViewController.swift similarity index 90% rename from openHAB/OpenHABSelectionTableViewController.swift rename to openHAB/OpenHABSelectionCollectionViewController.swift index 11e58976f..d7b6cdc99 100644 --- a/openHAB/OpenHABSelectionTableViewController.swift +++ b/openHAB/OpenHABSelectionCollectionViewController.swift @@ -18,7 +18,7 @@ public protocol OpenHABSelectionTableViewControllerDelegate: NSObjectProtocol { func didSelectWidgetMapping(_ selectedMapping: Int) } -class OpenHABSelectionTableViewController: UICollectionViewController { +class OpenHABSelectionCollectionViewController: UICollectionViewController { private let cellReuseIdentifier = "SelectionCell" private lazy var dataSource = makeDataSource() @@ -47,13 +47,13 @@ class OpenHABSelectionTableViewController: UICollectionViewController { } } -private extension OpenHABSelectionTableViewController { +private extension OpenHABSelectionCollectionViewController { enum Section: String, CaseIterable { case uniq } } -private extension OpenHABSelectionTableViewController { +private extension OpenHABSelectionCollectionViewController { typealias Cell = UICollectionViewListCell typealias CellRegistration = UICollectionView.CellRegistration @@ -75,7 +75,7 @@ private extension OpenHABSelectionTableViewController { } } -private extension OpenHABSelectionTableViewController { +private extension OpenHABSelectionCollectionViewController { func makeDataSource() -> UICollectionViewDiffableDataSource { UICollectionViewDiffableDataSource( collectionView: collectionView, @@ -96,7 +96,7 @@ extension UICollectionView.CellRegistration { } } -extension OpenHABSelectionTableViewController { +extension OpenHABSelectionCollectionViewController { func update(with list: [OpenHABWidgetMapping], animate: Bool = true) { var snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections(Section.allCases) From 9e2eecefe1fa13700be4f7783eb9dcac41c63562 Mon Sep 17 00:00:00 2001 From: Tim Bert <5411131+timbms@users.noreply.github.com> Date: Wed, 22 Nov 2023 22:33:54 +0100 Subject: [PATCH 04/14] Migrated OpenHABSelectionTableViewController to CollectionView - Renamed to OpenHABSelectionCollectionViewController Migrated OpenHABSelectionCollectionViewController away from Storyboard Showing view controllers, rather than pushing them, see https://www.swiftbysundell.com/tips/showing-view-controllers/ Signed-off-by: Tim Bert <5411131+timbms@users.noreply.github.com> --- openHAB.xcodeproj/project.pbxproj | 8 ++-- openHAB/Main.storyboard | 47 ++++--------------- ...HABSelectionCollectionViewController.swift | 5 +- openHAB/OpenHABSitemapViewController.swift | 7 ++- 4 files changed, 19 insertions(+), 48 deletions(-) diff --git a/openHAB.xcodeproj/project.pbxproj b/openHAB.xcodeproj/project.pbxproj index 72f682241..7d136c87f 100644 --- a/openHAB.xcodeproj/project.pbxproj +++ b/openHAB.xcodeproj/project.pbxproj @@ -137,7 +137,7 @@ DF05EF121D00696200DD646D /* DrawerUITableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF05EF111D00696200DD646D /* DrawerUITableViewCell.swift */; }; DF05FF2018965B5400FF2F9B /* RollershutterUITableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF05FF1F18965B5400FF2F9B /* RollershutterUITableViewCell.swift */; }; DF05FF231896BD2D00FF2F9B /* SelectionUITableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF05FF221896BD2D00FF2F9B /* SelectionUITableViewCell.swift */; }; - DF06F1F618FE7A160011E7B9 /* OpenHABSelectionTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF06F1F518FE7A160011E7B9 /* OpenHABSelectionTableViewController.swift */; }; + DF06F1F618FE7A160011E7B9 /* OpenHABSelectionCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF06F1F518FE7A160011E7B9 /* OpenHABSelectionCollectionViewController.swift */; }; DF06F1F918FEA8420011E7B9 /* ColorPickerUITableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF06F1F818FEA8420011E7B9 /* ColorPickerUITableViewCell.swift */; }; DF06F1FC18FEC2020011E7B9 /* ColorPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF06F1FB18FEC2020011E7B9 /* ColorPickerViewController.swift */; }; DF1B302D1CF5C667009C921C /* OpenHABNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF1B302C1CF5C667009C921C /* OpenHABNotification.swift */; }; @@ -417,7 +417,7 @@ DF05EF111D00696200DD646D /* DrawerUITableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DrawerUITableViewCell.swift; sourceTree = ""; }; DF05FF1F18965B5400FF2F9B /* RollershutterUITableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RollershutterUITableViewCell.swift; sourceTree = ""; }; DF05FF221896BD2D00FF2F9B /* SelectionUITableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectionUITableViewCell.swift; sourceTree = ""; }; - DF06F1F518FE7A160011E7B9 /* OpenHABSelectionTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenHABSelectionTableViewController.swift; sourceTree = ""; }; + DF06F1F518FE7A160011E7B9 /* OpenHABSelectionCollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenHABSelectionCollectionViewController.swift; sourceTree = ""; }; DF06F1F818FEA8420011E7B9 /* ColorPickerUITableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorPickerUITableViewCell.swift; sourceTree = ""; }; DF06F1FB18FEC2020011E7B9 /* ColorPickerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorPickerViewController.swift; sourceTree = ""; }; DF1B302C1CF5C667009C921C /* OpenHABNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenHABNotification.swift; sourceTree = ""; }; @@ -816,7 +816,7 @@ DFDEE3FC18831099008B26AC /* OpenHABSettingsViewController.swift */, DAEAA89A21E2611000267EA3 /* OpenHABNotificationsViewController.swift */, DFDF452E1932032B00A6E581 /* OpenHABLegalViewController.swift */, - DF06F1F518FE7A160011E7B9 /* OpenHABSelectionTableViewController.swift */, + DF06F1F518FE7A160011E7B9 /* OpenHABSelectionCollectionViewController.swift */, A07EF79F2230C0A20040919F /* OpenHABClientCertificatesViewController.swift */, DF4B84101886DA9900F34902 /* Widgets */, DF4A02291CF3157B006C3456 /* Drawer */, @@ -1402,7 +1402,7 @@ DAEAA89B21E2611000267EA3 /* OpenHABNotificationsViewController.swift in Sources */, DF1B302D1CF5C667009C921C /* OpenHABNotification.swift in Sources */, 938BF9D324EFD0B700E6B52F /* UIViewController+Localization.swift in Sources */, - DF06F1F618FE7A160011E7B9 /* OpenHABSelectionTableViewController.swift in Sources */, + DF06F1F618FE7A160011E7B9 /* OpenHABSelectionCollectionViewController.swift in Sources */, DAA42BA821DC97E000244B2A /* NotificationTableViewCell.swift in Sources */, 6595667E28E0BE8E00E8A53B /* MulticastDelegate.swift in Sources */, 286F556F22EA062700AECC5C /* DynamicButtonStyleBell.swift in Sources */, diff --git a/openHAB/Main.storyboard b/openHAB/Main.storyboard index fd3790ea0..1c31bbd51 100644 --- a/openHAB/Main.storyboard +++ b/openHAB/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -1240,7 +1240,7 @@ - +