Skip to content

Commit

Permalink
chore: moving SettingsMenu to SwiftUI
Browse files Browse the repository at this point in the history
  • Loading branch information
Syn-McJ committed Sep 1, 2024
1 parent 2aae770 commit be7bc3b
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 145 deletions.
6 changes: 6 additions & 0 deletions DashWallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,8 @@
754BEA132C0B6BD700E8C93C /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 754BEA112C0B6BD700E8C93C /* HomeViewModel.swift */; };
755049A92C846299008FA7EB /* DWAboutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 755049A72C846299008FA7EB /* DWAboutViewController.m */; };
755049AA2C846299008FA7EB /* DWAboutViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 755049A72C846299008FA7EB /* DWAboutViewController.m */; };
755049AC2C846576008FA7EB /* MenuItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755049AB2C846576008FA7EB /* MenuItemModel.swift */; };
755049AD2C846576008FA7EB /* MenuItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755049AB2C846576008FA7EB /* MenuItemModel.swift */; };
755A22BD2B1385FD001F170D /* IconAttributedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755A22BC2B1385FD001F170D /* IconAttributedText.swift */; };
755B4B222B0C903500B844F0 /* DWDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755B4B212B0C903500B844F0 /* DWDateFormatter.swift */; };
755B4B232B0C903500B844F0 /* DWDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755B4B212B0C903500B844F0 /* DWDateFormatter.swift */; };
Expand Down Expand Up @@ -2432,6 +2434,7 @@
754BEA112C0B6BD700E8C93C /* HomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = "<group>"; };
755049A72C846299008FA7EB /* DWAboutViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DWAboutViewController.m; sourceTree = "<group>"; };
755049A82C846299008FA7EB /* DWAboutViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWAboutViewController.h; sourceTree = "<group>"; };
755049AB2C846576008FA7EB /* MenuItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuItemModel.swift; sourceTree = "<group>"; };
755A22BC2B1385FD001F170D /* IconAttributedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconAttributedText.swift; sourceTree = "<group>"; };
755B4B212B0C903500B844F0 /* DWDateFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DWDateFormatter.swift; sourceTree = "<group>"; };
755C32372C358FBD007DA721 /* BackupSeedPhraseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackupSeedPhraseViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4122,6 +4125,7 @@
2A7A7BCA2347EF7A00451078 /* Security */,
2A7A7BD32348CB4F00451078 /* Settings */,
2A7A7BDA2348DBE700451078 /* Tools */,
755049AB2C846576008FA7EB /* MenuItemModel.swift */,
);
path = Menu;
sourceTree = "<group>";
Expand Down Expand Up @@ -8943,6 +8947,7 @@
C9F42FB829DFC507001BC549 /* SpendableTransaction.swift in Sources */,
11ED906B29681773003784F9 /* StakingInfoDialogController.swift in Sources */,
0F36937E2919A5DB007F4E91 /* TwoFactorAuthViewController.swift in Sources */,
755049AC2C846576008FA7EB /* MenuItemModel.swift in Sources */,
75EBAA292BBBE385004488E3 /* ZenLedgerViewModel.swift in Sources */,
471A260A289ACDF70056B7B2 /* Taxes.swift in Sources */,
2AD1CE9722DD0E8E00C99324 /* DWSeedWordModel+DWLayoutSupport.m in Sources */,
Expand Down Expand Up @@ -9176,6 +9181,7 @@
C9D2C7022A320AA000D15901 /* CrowdNodeWebViewController.swift in Sources */,
C9D2C7032A320AA000D15901 /* UIViewController+DWDisplayError.m in Sources */,
C9D2C7042A320AA000D15901 /* BRAppleWatchData.m in Sources */,
755049AD2C846576008FA7EB /* MenuItemModel.swift in Sources */,
C9D2C7052A320AA000D15901 /* DWRequestAmountContentView.m in Sources */,
C943B3312A408CED00AF23C5 /* DWProfileAboutCellModel.m in Sources */,
C943B4C42A40A54600AF23C5 /* DWSearchViewController.m in Sources */,
Expand Down
36 changes: 36 additions & 0 deletions DashWallet/Sources/UI/Menu/MenuItemModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// Created by Andrei Ashikhmin
// Copyright © 2024 Dash Core Group. All rights reserved.
//
// Licensed under the MIT License (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import SwiftUI

struct MenuItemModel: Identifiable, Equatable {
let id = UUID()

var title: String
var subtitle: String? = nil
var details: String? = nil
var icon: IconName? = nil
var showInfo: Bool = false
var showChevron: Bool = false
var showToggle: Bool = false
@State var isToggled: Bool = false
var action: (() -> Void)? = nil

static func == (lhs: MenuItemModel, rhs: MenuItemModel) -> Bool {
lhs.id == rhs.id
}
}
225 changes: 126 additions & 99 deletions DashWallet/Sources/UI/Menu/Settings/SettingsMenuViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
//

import UIKit
import SwiftUI

@objc(DWSettingsMenuViewControllerDelegate)
protocol SettingsMenuViewControllerDelegate: AnyObject {
Expand All @@ -28,9 +29,6 @@ class SettingsMenuViewController: UIViewController, DWLocalCurrencyViewControlle
@objc weak var delegate: SettingsMenuViewControllerDelegate?

private lazy var model: DWSettingsMenuModel = DWSettingsMenuModel()
private var formController: DWFormTableViewController!
private var localCurrencyCellModel: DWSelectorFormCellModel!
private var switchNetworkCellModel: DWSelectorFormCellModel!

init() {
super.init(nibName: nil, bundle: nil)
Expand All @@ -47,10 +45,21 @@ class SettingsMenuViewController: UIViewController, DWLocalCurrencyViewControlle

view.backgroundColor = .dw_secondaryBackground()

formController = DWFormTableViewController(style: .plain)
formController.setSections(sections, placeholderText: nil)

dw_embedChild(formController)
let content = SettingsMenuContent(
items: menuItems(),
onLocalCurrencyChange: { [weak self] in
self?.showCurrencySelector()
},
onNetworkChange: { [weak self] in
self?.showChangeNetwork()
},
onRescanBlockchain: { [weak self] in
self?.showWarningAboutReclassifiedTransactions()
}
)
let swiftUIController = UIHostingController(rootView: content)
swiftUIController.view.backgroundColor = .dw_secondaryBackground()
dw_embedChild(swiftUIController)
}

override var preferredStatusBarStyle: UIStatusBarStyle {
Expand All @@ -60,7 +69,6 @@ class SettingsMenuViewController: UIViewController, DWLocalCurrencyViewControlle
// MARK: - LocalCurrencyViewControllerDelegate

func localCurrencyViewController(_ controller: DWLocalCurrencyViewController, didSelectCurrency currencyCode: String) {
updateLocalCurrencyCellModel()
navigationController?.popViewController(animated: true)
}

Expand All @@ -70,95 +78,71 @@ class SettingsMenuViewController: UIViewController, DWLocalCurrencyViewControlle

// MARK: - Private

private var items: [DWBaseFormCellModel] {
var items: [DWBaseFormCellModel] = []

let localCurrencyCell = DWSelectorFormCellModel(title: NSLocalizedString("Local Currency", comment: ""))
localCurrencyCellModel = localCurrencyCell
updateLocalCurrencyCellModel()
localCurrencyCell.accessoryType = .disclosureIndicator
localCurrencyCell.didSelectBlock = { [weak self] _, _ in
self?.showCurrencySelector()
}
items.append(localCurrencyCell)

let notificationsCell = DWSwitcherFormCellModel(title: NSLocalizedString("Enable Receive Notifications", comment: ""))
notificationsCell.isOn = model.notificationsEnabled
notificationsCell.didChangeValueBlock = { [weak self] cellModel in
self?.model.notificationsEnabled = cellModel.isOn
}
items.append(notificationsCell)

let networkCell = DWSelectorFormCellModel(title: NSLocalizedString("Network", comment: ""))
switchNetworkCellModel = networkCell
updateSwitchNetworkCellModel()
networkCell.accessoryType = .disclosureIndicator
networkCell.didSelectBlock = { [weak self] _, indexPath in
guard let self = self else { return }
let tableView = self.formController.tableView!
guard let cell = tableView.cellForRow(at: indexPath) else { return }
self.showChangeNetwork(from: tableView, sourceRect: cell.frame)
}
items.append(networkCell)

let rescanCell = DWSelectorFormCellModel(title: NSLocalizedString("Rescan Blockchain", comment: ""))
rescanCell.didSelectBlock = { [weak self] _, indexPath in
guard let self = self else { return }
let tableView = self.formController.tableView!
guard let cell = tableView.cellForRow(at: indexPath) else { return }
self.showWarningAboutReclassifiedTransactions(tableView, sourceRect: cell.frame)
}
items.append(rescanCell)

let aboutCell = DWSelectorFormCellModel(title: NSLocalizedString("About", comment: ""))
aboutCell.accessoryType = .disclosureIndicator
aboutCell.didSelectBlock = { [weak self] _, _ in
self?.showAboutController()
}
items.append(aboutCell)
private func menuItems() -> [MenuItemModel] {
var items: [MenuItemModel] = [
MenuItemModel(
title: NSLocalizedString("Local Currency", comment: ""),
subtitle: model.localCurrencyCode,
showChevron: true,
action: { [weak self] in
self?.showCurrencySelector()
}
),
MenuItemModel(
title: NSLocalizedString("Enable Receive Notifications", comment: ""),
showToggle: true,
isToggled: self.model.notificationsEnabled,
action: { [weak self] in
self?.model.notificationsEnabled.toggle()
}
),
MenuItemModel(
title: NSLocalizedString("Network", comment: ""),
subtitle: model.networkName,
showChevron: true,
action: { [weak self] in
self?.showChangeNetwork()
}
),
MenuItemModel(
title: NSLocalizedString("Rescan Blockchain", comment: ""),
showChevron: true,
action: { [weak self] in
self?.showWarningAboutReclassifiedTransactions()
}
),
MenuItemModel(
title: NSLocalizedString("About", comment: ""),
showChevron: true,
action: { [weak self] in
self?.showAboutController()
}
)
]

#if DASHPAY
let coinJoinCell = DWSelectorFormCellModel(title: NSLocalizedString("CoinJoin", comment: ""))
coinJoinCell.didSelectBlock = { [weak self] _, _ in
self?.showCoinJoinController()
}
items.append(coinJoinCell)

let votingCell = DWSwitcherFormCellModel(title: "Enable Voting")
votingCell.isOn = VotingPrefsWrapper.getIsEnabled()
votingCell.didChangeValueBlock = { cellModel in
VotingPrefsWrapper.setIsEnabled(value: cellModel.isOn)
}
items.append(votingCell)
items.append(contentsOf: [
MenuItemModel(
title: NSLocalizedString("CoinJoin", comment: ""),
showChevron: true,
action: { [weak self] in
self?.showCoinJoinController()
}
),
MenuItemModel(
title: "Enable Voting",
showToggle: true,
isToggled: VotingPrefs.shared.votingEnabled,
action: {
VotingPrefs.shared.votingEnabled.toggle()
}
)
])
#endif

return items
}

private var sections: [DWFormSectionModel] {
return items.map { item in
let section = DWFormSectionModel()
section.items = [item]
return section
}
}

private func updateLocalCurrencyCellModel() {
localCurrencyCellModel.subTitle = model.localCurrencyCode
}

private func updateSwitchNetworkCellModel() {
switchNetworkCellModel.subTitle = model.networkName
}

private func rescanBlockchainAction(from sourceView: UIView, sourceRect: CGRect) {
DWSettingsMenuModel.rescanBlockchainAction(from: self, sourceView: sourceView, sourceRect: sourceRect) { [weak self] confirmed in
if confirmed {
self?.delegate?.settingsMenuViewControllerDidRescanBlockchain(self!)
}
}
}

private func showCurrencySelector() {
let controller = DWLocalCurrencyViewController(navigationAppearance: .default, presentationMode: .screen, currencyCode: nil)
controller.delegate = self
Expand All @@ -182,21 +166,21 @@ class SettingsMenuViewController: UIViewController, DWLocalCurrencyViewControlle
navigationController?.pushViewController(vc, animated: true)
}

private func showChangeNetwork(from sourceView: UIView, sourceRect: CGRect) {
private func showChangeNetwork() {
let actionSheet = UIAlertController(title: NSLocalizedString("Network", comment: ""), message: nil, preferredStyle: .actionSheet)

let mainnetAction = UIAlertAction(title: NSLocalizedString("Mainnet", comment: ""), style: .default) { [weak self] _ in
DWSettingsMenuModel.switchToMainnet { success in
if success {
self?.updateSwitchNetworkCellModel()
self?.updateView()
}
}
}

let testnetAction = UIAlertAction(title: NSLocalizedString("Testnet", comment: ""), style: .default) { [weak self] _ in
DWSettingsMenuModel.switchToTestnet { success in
if success {
self?.updateSwitchNetworkCellModel()
self?.updateView()
}
}
}
Expand All @@ -208,21 +192,21 @@ class SettingsMenuViewController: UIViewController, DWLocalCurrencyViewControlle
actionSheet.addAction(cancelAction)

if UIDevice.current.userInterfaceIdiom == .pad {
actionSheet.popoverPresentationController?.sourceView = sourceView
actionSheet.popoverPresentationController?.sourceRect = sourceRect
actionSheet.popoverPresentationController?.sourceView = view
actionSheet.popoverPresentationController?.sourceRect = view.bounds
}

present(actionSheet, animated: true, completion: nil)
}

private func showWarningAboutReclassifiedTransactions(_ sourceView: UIView, sourceRect: CGRect) {
private func showWarningAboutReclassifiedTransactions() {
let actionSheet = UIAlertController(
title: NSLocalizedString("You will lose all your manually reclassified transactions types", comment: ""),
message: NSLocalizedString("If you would like to save manually reclassified types for transactions you should export a CSV transaction file.", comment: ""),
preferredStyle: .actionSheet)

let continueAction = UIAlertAction(title: NSLocalizedString("Continue", comment: ""), style: .default) { [weak self] _ in
self?.rescanBlockchainAction(from: sourceView, sourceRect: sourceRect)
self?.rescanBlockchainAction()
}

let exportAction = UIAlertAction(title: NSLocalizedString("Export CSV", comment: ""), style: .default) { [weak self] _ in
Expand All @@ -236,13 +220,21 @@ class SettingsMenuViewController: UIViewController, DWLocalCurrencyViewControlle
actionSheet.addAction(cancelAction)

if UIDevice.current.userInterfaceIdiom == .pad {
actionSheet.popoverPresentationController?.sourceView = sourceView
actionSheet.popoverPresentationController?.sourceRect = sourceRect
actionSheet.popoverPresentationController?.sourceView = view
actionSheet.popoverPresentationController?.sourceRect = view.bounds
}

present(actionSheet, animated: true, completion: nil)
}

private func rescanBlockchainAction() {
DWSettingsMenuModel.rescanBlockchainAction(from: self, sourceView: view, sourceRect: view.bounds) { [weak self] confirmed in
if confirmed {
self?.delegate?.settingsMenuViewControllerDidRescanBlockchain(self!)
}
}
}

private func exportTransactionsInCSV() {
view.dw_showProgressHUD(withMessage: NSLocalizedString("Generating CSV Report", comment: ""))

Expand All @@ -263,4 +255,39 @@ class SettingsMenuViewController: UIViewController, DWLocalCurrencyViewControlle
self?.dw_displayErrorModally(error)
}
}

private func updateView() {
// Trigger a view update
viewDidLoad()
}
}

struct SettingsMenuContent: View {
var items: [MenuItemModel]
var onLocalCurrencyChange: () -> Void
var onNetworkChange: () -> Void
var onRescanBlockchain: () -> Void

var body: some View {
List(items) { item in
MenuItem(
title: item.title,
subtitle: item.subtitle,
details: item.details,
icon: item.icon,
showInfo: item.showInfo,
showChevron: item.showChevron,
showToggle: item.showToggle,
isToggled: item.isToggled,
action: item.action
)
.background(Color.secondaryBackground)
.cornerRadius(8)
.shadow(color: .shadow, radius: 10, x: 0, y: 5)
.listRowSeparator(.hidden)
.listRowBackground(Color.clear)
}
.listStyle(.plain)
.background(Color.clear)
}
}
Loading

0 comments on commit be7bc3b

Please sign in to comment.