mirror of
https://github.com/lil-org/tokenary.git
synced 2024-12-24 20:41:35 +03:00
Add accounts empty state
This commit is contained in:
parent
0b97e2800d
commit
d267d2c8dc
@ -63,5 +63,11 @@ struct Strings {
|
|||||||
static let secretWordsGiveFullAccess = "Secret words give full access to your funds."
|
static let secretWordsGiveFullAccess = "Secret words give full access to your funds."
|
||||||
static let privateKeyGivesFullAccess = "Private key gives full access to your funds."
|
static let privateKeyGivesFullAccess = "Private key gives full access to your funds."
|
||||||
static let toShowAccountKey = "To show account key"
|
static let toShowAccountKey = "To show account key"
|
||||||
|
static let loading = "Loading"
|
||||||
|
static let failedToLoad = "Failed to load"
|
||||||
|
static let tryAgain = "Try again"
|
||||||
|
static let noData = "There is no data yet"
|
||||||
|
static let refresh = "Refresh"
|
||||||
|
static let tokenaryIsEmpty = "Tokenary is empty"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
19
Tokenary iOS/Content/Images.swift
Normal file
19
Tokenary iOS/Content/Images.swift
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright © 2021 Tokenary. All rights reserved.
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
struct Images {
|
||||||
|
|
||||||
|
static var noData: UIImage { systemName("wind") }
|
||||||
|
static var failedToLoad: UIImage { systemName("xmark.octagon") }
|
||||||
|
static var preferences: UIImage { systemName("gearshape") }
|
||||||
|
|
||||||
|
private static func named(_ name: String) -> UIImage {
|
||||||
|
return UIImage(named: name)!
|
||||||
|
}
|
||||||
|
|
||||||
|
private static func systemName(_ systemName: String, configuration: UIImage.Configuration? = nil) -> UIImage {
|
||||||
|
return UIImage(systemName: systemName, withConfiguration: configuration)!
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
19
Tokenary iOS/Extensions/UIView.swift
Normal file
19
Tokenary iOS/Extensions/UIView.swift
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright © 2021 Tokenary. All rights reserved.
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
func loadNib<View: UIView>(_ type: View.Type) -> View {
|
||||||
|
return Bundle.main.loadNibNamed(String(describing: type), owner: nil, options: nil)![0] as! View
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UIView {
|
||||||
|
|
||||||
|
func addSubviewConstrainedToFrame(_ subview: UIView) {
|
||||||
|
addSubview(subview)
|
||||||
|
subview.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
let firstConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": subview])
|
||||||
|
let secondConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": subview])
|
||||||
|
addConstraints(firstConstraints + secondConstraints)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
167
Tokenary iOS/Library/DataStateView.swift
Normal file
167
Tokenary iOS/Library/DataStateView.swift
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
// Copyright © 2021 Tokenary. All rights reserved.
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import BlockiesSwift
|
||||||
|
|
||||||
|
enum DataState: CaseIterable {
|
||||||
|
case hasData, loading, failedToLoad, noData, unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol DataStateContainer: AnyObject {
|
||||||
|
|
||||||
|
var dataState: DataState { get set }
|
||||||
|
func configureDataState(_ dataState: DataState, description: String?, image: UIImage?, buttonTitle: String?, actionHandler: (() -> Void)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
class DataStateView: UIView {
|
||||||
|
|
||||||
|
private class Configuration {
|
||||||
|
|
||||||
|
let description: String?
|
||||||
|
let image: UIImage?
|
||||||
|
let buttonTitle: String?
|
||||||
|
let actionHandler: (() -> Void)?
|
||||||
|
|
||||||
|
init(description: String? = nil, image: UIImage? = nil, buttonTitle: String? = nil, actionHandler: (() -> Void)? = nil) {
|
||||||
|
self.description = description
|
||||||
|
self.image = image
|
||||||
|
self.buttonTitle = buttonTitle
|
||||||
|
self.actionHandler = actionHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
static func defaultForDataState(_ dataState: DataState) -> Configuration {
|
||||||
|
let configuration: Configuration
|
||||||
|
switch dataState {
|
||||||
|
case .hasData, .loading, .unknown:
|
||||||
|
configuration = Configuration()
|
||||||
|
case .failedToLoad:
|
||||||
|
configuration = Configuration(description: Strings.failedToLoad, image: Images.failedToLoad, buttonTitle: Strings.tryAgain)
|
||||||
|
case .noData:
|
||||||
|
configuration = Configuration(description: Strings.noData, image: Images.noData, buttonTitle: Strings.refresh)
|
||||||
|
}
|
||||||
|
return configuration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate static let tag = Int.max
|
||||||
|
fileprivate static var new: DataStateView {
|
||||||
|
let view = loadNib(DataStateView.self)
|
||||||
|
view.tag = tag
|
||||||
|
view.isHidden = true
|
||||||
|
view.observeKeyboard()
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate var shouldMoveWithKeyboard = true
|
||||||
|
fileprivate var currentState = DataState.unknown {
|
||||||
|
didSet { updateForCurrentState() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private var configurations = [DataState: Configuration]()
|
||||||
|
|
||||||
|
@IBOutlet private weak var centerYConstraint: NSLayoutConstraint!
|
||||||
|
@IBOutlet private weak var activityIndicator: UIActivityIndicatorView!
|
||||||
|
@IBOutlet private weak var imageView: UIImageView!
|
||||||
|
@IBOutlet private weak var descriptionLabel: UILabel!
|
||||||
|
@IBOutlet private weak var button: UIButton!
|
||||||
|
@IBOutlet private weak var activityIndicatorDescriptionLabel: UILabel! {
|
||||||
|
didSet {
|
||||||
|
activityIndicatorDescriptionLabel.text = Strings.loading.uppercased()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction private func didTapButton(_ sender: Any) {
|
||||||
|
configurations[currentState]?.actionHandler?()
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func configureDataState(_ dataState: DataState, description: String? = nil, image: UIImage? = nil, buttonTitle: String? = nil, actionHandler: (() -> Void)? = nil) {
|
||||||
|
let newConfiguration = Configuration(description: description, image: image, buttonTitle: buttonTitle, actionHandler: actionHandler)
|
||||||
|
configurations[dataState] = newConfiguration
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateForCurrentState() {
|
||||||
|
isHidden = currentState == .unknown || currentState == .hasData
|
||||||
|
|
||||||
|
let configuration = configurations[currentState]
|
||||||
|
let defaultConfiguration = Configuration.defaultForDataState(currentState)
|
||||||
|
|
||||||
|
imageView.image = configuration?.image ?? defaultConfiguration.image
|
||||||
|
descriptionLabel.text = configuration?.description ?? defaultConfiguration.description
|
||||||
|
button.setTitle(configuration?.buttonTitle ?? defaultConfiguration.buttonTitle, for: .normal)
|
||||||
|
|
||||||
|
let isLoading = currentState == .loading
|
||||||
|
|
||||||
|
activityIndicator.isHidden = !isLoading
|
||||||
|
activityIndicatorDescriptionLabel.isHidden = !isLoading
|
||||||
|
imageView.isHidden = isLoading
|
||||||
|
descriptionLabel.isHidden = isLoading
|
||||||
|
button.isHidden = isLoading || configuration?.actionHandler == nil
|
||||||
|
|
||||||
|
if isLoading {
|
||||||
|
activityIndicator.startAnimating()
|
||||||
|
} else if activityIndicator.isAnimating {
|
||||||
|
activityIndicator.stopAnimating()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
|
||||||
|
return button.frame.insetBy(dx: -30, dy: -30).contains(point)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension DataStateView: KeyboardObserver {
|
||||||
|
|
||||||
|
func keyboardWill(show: Bool, height: CGFloat, animtaionOptions: UIView.AnimationOptions, duration: Double) {
|
||||||
|
guard shouldMoveWithKeyboard else { return }
|
||||||
|
let centerOffset: CGFloat = show ? -105 : -50
|
||||||
|
|
||||||
|
UIView.animate(withDuration: duration,
|
||||||
|
delay: 0,
|
||||||
|
options: animtaionOptions,
|
||||||
|
animations: { [weak self] in
|
||||||
|
self?.centerYConstraint.constant = centerOffset
|
||||||
|
self?.layoutIfNeeded()
|
||||||
|
},
|
||||||
|
completion: nil
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension DataStateContainer where Self: UIViewController {
|
||||||
|
|
||||||
|
var dataState: DataState {
|
||||||
|
get {
|
||||||
|
return dataStateView.currentState
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
dataStateView.currentState = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dataStateShouldMoveWithKeyboard(_ shouldMove: Bool) {
|
||||||
|
dataStateView.shouldMoveWithKeyboard = shouldMove
|
||||||
|
}
|
||||||
|
|
||||||
|
func setDataStateViewTransparent(_ isTransparent: Bool) {
|
||||||
|
dataStateView.backgroundColor = isTransparent ? .clear : .systemGroupedBackground
|
||||||
|
}
|
||||||
|
|
||||||
|
func configureDataState(_ dataState: DataState, description: String? = nil, image: UIImage? = nil, buttonTitle: String? = nil, actionHandler: (() -> Void)? = nil) {
|
||||||
|
dataStateView.configureDataState(dataState, description: description, image: image, buttonTitle: buttonTitle, actionHandler: actionHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var dataStateView: DataStateView {
|
||||||
|
if let subview = view.viewWithTag(DataStateView.tag) as? DataStateView { return subview }
|
||||||
|
|
||||||
|
let dataStateView = DataStateView.new
|
||||||
|
view.addSubview(dataStateView)
|
||||||
|
dataStateView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
let firstConstraint = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": dataStateView])
|
||||||
|
let secondConstraint = NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": dataStateView])
|
||||||
|
view.addConstraints(firstConstraint + secondConstraint)
|
||||||
|
view.bringSubviewToFront(dataStateView)
|
||||||
|
return dataStateView
|
||||||
|
}
|
||||||
|
}
|
99
Tokenary iOS/Library/DataStateView.xib
Normal file
99
Tokenary iOS/Library/DataStateView.xib
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19455" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||||
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19454"/>
|
||||||
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
|
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<objects>
|
||||||
|
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||||
|
<view contentMode="scaleToFill" id="lqS-Qo-2hd" customClass="DataStateView" customModule="Tokenary_iOS" customModuleProvider="target">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" animating="YES" style="medium" translatesAutoresizingMaskIntoConstraints="NO" id="0rZ-Sk-fve">
|
||||||
|
<rect key="frame" x="197" y="388" width="20" height="20"/>
|
||||||
|
</activityIndicatorView>
|
||||||
|
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="LOADING" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ImM-Ma-L3J">
|
||||||
|
<rect key="frame" x="180.5" y="416" width="53.5" height="14.5"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||||
|
<color key="textColor" systemColor="secondaryLabelColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="wind" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="OeR-Db-lcJ">
|
||||||
|
<rect key="frame" x="118.5" y="271" width="177" height="174.5"/>
|
||||||
|
<color key="tintColor" systemColor="tertiaryLabelColor"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" secondItem="OeR-Db-lcJ" secondAttribute="height" multiplier="1:1" id="g5A-B4-JDZ"/>
|
||||||
|
<constraint firstAttribute="width" relation="lessThanOrEqual" constant="200" id="qey-Ch-daS"/>
|
||||||
|
</constraints>
|
||||||
|
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="default" weight="thin"/>
|
||||||
|
</imageView>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Failed to load" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Iym-80-uYR">
|
||||||
|
<rect key="frame" x="20" y="454.5" width="374" height="20.5"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<color key="textColor" systemColor="secondaryLabelColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="5ZO-df-Isv">
|
||||||
|
<rect key="frame" x="137" y="527" width="140" height="52"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="52" id="5fo-UF-Qwu"/>
|
||||||
|
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="140" id="JBF-DF-ChM"/>
|
||||||
|
</constraints>
|
||||||
|
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="15"/>
|
||||||
|
<state key="normal" title="Retry"/>
|
||||||
|
<buttonConfiguration key="configuration" style="filled" title="Retry">
|
||||||
|
<fontDescription key="titleFontDescription" type="system" weight="semibold" pointSize="15"/>
|
||||||
|
</buttonConfiguration>
|
||||||
|
<connections>
|
||||||
|
<action selector="didTapButton:" destination="lqS-Qo-2hd" eventType="touchUpInside" id="wYk-pp-YyB"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
</subviews>
|
||||||
|
<viewLayoutGuide key="safeArea" id="lUb-JT-l59"/>
|
||||||
|
<color key="backgroundColor" systemColor="systemGroupedBackgroundColor"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="OeR-Db-lcJ" firstAttribute="top" relation="greaterThanOrEqual" secondItem="lqS-Qo-2hd" secondAttribute="top" constant="150" id="0ao-To-70w"/>
|
||||||
|
<constraint firstItem="OeR-Db-lcJ" firstAttribute="centerX" secondItem="lqS-Qo-2hd" secondAttribute="centerX" id="11T-RK-uzC"/>
|
||||||
|
<constraint firstItem="Iym-80-uYR" firstAttribute="top" secondItem="OeR-Db-lcJ" secondAttribute="bottom" constant="8" id="3dj-vb-QgB"/>
|
||||||
|
<constraint firstItem="0rZ-Sk-fve" firstAttribute="centerX" secondItem="lqS-Qo-2hd" secondAttribute="centerX" id="3yi-dM-5bk"/>
|
||||||
|
<constraint firstItem="0rZ-Sk-fve" firstAttribute="top" secondItem="OeR-Db-lcJ" secondAttribute="bottom" constant="-58.5" id="8Pu-Nt-RW8"/>
|
||||||
|
<constraint firstItem="ImM-Ma-L3J" firstAttribute="centerX" secondItem="0rZ-Sk-fve" secondAttribute="centerX" id="ENE-tI-BjB"/>
|
||||||
|
<constraint firstItem="Iym-80-uYR" firstAttribute="width" secondItem="lqS-Qo-2hd" secondAttribute="width" constant="-40" id="KtH-zG-zmO"/>
|
||||||
|
<constraint firstItem="ImM-Ma-L3J" firstAttribute="top" secondItem="0rZ-Sk-fve" secondAttribute="bottom" constant="8" id="OTT-Nq-oAt"/>
|
||||||
|
<constraint firstItem="5ZO-df-Isv" firstAttribute="centerX" secondItem="lqS-Qo-2hd" secondAttribute="centerX" id="X1o-2s-b8d"/>
|
||||||
|
<constraint firstItem="OeR-Db-lcJ" firstAttribute="width" secondItem="lqS-Qo-2hd" secondAttribute="width" multiplier="3:7" priority="750" id="YTt-wi-2MM"/>
|
||||||
|
<constraint firstItem="Iym-80-uYR" firstAttribute="centerX" secondItem="lqS-Qo-2hd" secondAttribute="centerX" id="e6D-zs-nVx"/>
|
||||||
|
<constraint firstItem="5ZO-df-Isv" firstAttribute="top" secondItem="Iym-80-uYR" secondAttribute="bottom" constant="52" id="i2r-xi-nPw"/>
|
||||||
|
<constraint firstItem="0rZ-Sk-fve" firstAttribute="centerY" secondItem="lqS-Qo-2hd" secondAttribute="centerY" constant="-50" id="yXH-dL-f1g"/>
|
||||||
|
</constraints>
|
||||||
|
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||||
|
<connections>
|
||||||
|
<outlet property="activityIndicator" destination="0rZ-Sk-fve" id="vxk-57-49J"/>
|
||||||
|
<outlet property="activityIndicatorDescriptionLabel" destination="ImM-Ma-L3J" id="JXP-oJ-MHf"/>
|
||||||
|
<outlet property="button" destination="5ZO-df-Isv" id="ktY-5G-IeA"/>
|
||||||
|
<outlet property="centerYConstraint" destination="yXH-dL-f1g" id="CPn-cG-i1P"/>
|
||||||
|
<outlet property="descriptionLabel" destination="Iym-80-uYR" id="pef-lb-qeN"/>
|
||||||
|
<outlet property="imageView" destination="OeR-Db-lcJ" id="hu0-Fa-45B"/>
|
||||||
|
</connections>
|
||||||
|
<point key="canvasLocation" x="139" y="-492"/>
|
||||||
|
</view>
|
||||||
|
</objects>
|
||||||
|
<resources>
|
||||||
|
<image name="wind" catalog="system" width="128" height="103"/>
|
||||||
|
<systemColor name="secondaryLabelColor">
|
||||||
|
<color red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</systemColor>
|
||||||
|
<systemColor name="systemGroupedBackgroundColor">
|
||||||
|
<color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</systemColor>
|
||||||
|
<systemColor name="tertiaryLabelColor">
|
||||||
|
<color red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.29999999999999999" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
</systemColor>
|
||||||
|
</resources>
|
||||||
|
</document>
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
class AccountsListViewController: UIViewController {
|
class AccountsListViewController: UIViewController, DataStateContainer {
|
||||||
|
|
||||||
private let walletsManager = WalletsManager.shared
|
private let walletsManager = WalletsManager.shared
|
||||||
private let keychain = Keychain.shared
|
private let keychain = Keychain.shared
|
||||||
@ -25,8 +25,27 @@ class AccountsListViewController: UIViewController {
|
|||||||
navigationController?.navigationBar.prefersLargeTitles = true
|
navigationController?.navigationBar.prefersLargeTitles = true
|
||||||
navigationItem.largeTitleDisplayMode = .always
|
navigationItem.largeTitleDisplayMode = .always
|
||||||
let addItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addAccount))
|
let addItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addAccount))
|
||||||
let preferencesItem = UIBarButtonItem(image: UIImage(systemName: "gearshape"), style: UIBarButtonItem.Style.plain, target: self, action: #selector(preferencesButtonTapped))
|
let preferencesItem = UIBarButtonItem(image: Images.preferences, style: UIBarButtonItem.Style.plain, target: self, action: #selector(preferencesButtonTapped))
|
||||||
navigationItem.rightBarButtonItems = [addItem, preferencesItem]
|
navigationItem.rightBarButtonItems = [addItem, preferencesItem]
|
||||||
|
configureDataState(.noData, description: Strings.tokenaryIsEmpty, buttonTitle: Strings.addAccount) { [weak self] in
|
||||||
|
self?.addAccount()
|
||||||
|
}
|
||||||
|
dataStateShouldMoveWithKeyboard(false)
|
||||||
|
updateDataState()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateDataState() {
|
||||||
|
let isEmpty = wallets.isEmpty
|
||||||
|
dataState = isEmpty ? .noData : .hasData
|
||||||
|
let canScroll = !isEmpty
|
||||||
|
if tableView.isScrollEnabled != canScroll {
|
||||||
|
tableView.isScrollEnabled = canScroll
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func reloadData() {
|
||||||
|
updateDataState()
|
||||||
|
tableView.reloadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func preferencesButtonTapped() {
|
@objc private func preferencesButtonTapped() {
|
||||||
@ -76,7 +95,7 @@ class AccountsListViewController: UIViewController {
|
|||||||
|
|
||||||
private func createNewAccountAndShowSecretWords() {
|
private func createNewAccountAndShowSecretWords() {
|
||||||
guard let wallet = try? walletsManager.createWallet() else { return }
|
guard let wallet = try? walletsManager.createWallet() else { return }
|
||||||
tableView.reloadData()
|
reloadData()
|
||||||
showKey(wallet: wallet, mnemonic: true)
|
showKey(wallet: wallet, mnemonic: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +123,7 @@ class AccountsListViewController: UIViewController {
|
|||||||
let importAccountViewController = instantiate(ImportViewController.self, from: .main)
|
let importAccountViewController = instantiate(ImportViewController.self, from: .main)
|
||||||
importAccountViewController.completion = { [weak self] success in
|
importAccountViewController.completion = { [weak self] success in
|
||||||
if success {
|
if success {
|
||||||
self?.tableView.reloadData()
|
self?.reloadData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
present(importAccountViewController.inNavigationController, animated: true)
|
present(importAccountViewController.inNavigationController, animated: true)
|
||||||
@ -169,7 +188,7 @@ class AccountsListViewController: UIViewController {
|
|||||||
|
|
||||||
private func removeWallet(_ wallet: TokenaryWallet) {
|
private func removeWallet(_ wallet: TokenaryWallet) {
|
||||||
try? walletsManager.delete(wallet: wallet)
|
try? walletsManager.delete(wallet: wallet)
|
||||||
tableView.reloadData()
|
reloadData()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func didTapExportAccount(_ wallet: TokenaryWallet) {
|
private func didTapExportAccount(_ wallet: TokenaryWallet) {
|
||||||
|
@ -69,6 +69,11 @@
|
|||||||
2C96D39827623EC600687301 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C96D39727623EC600687301 /* URL.swift */; };
|
2C96D39827623EC600687301 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C96D39727623EC600687301 /* URL.swift */; };
|
||||||
2C96D39927623ECE00687301 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C96D39727623EC600687301 /* URL.swift */; };
|
2C96D39927623ECE00687301 /* URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C96D39727623EC600687301 /* URL.swift */; };
|
||||||
2C96D39C2763ADE100687301 /* LocalAuthentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C96D39B2763ADE100687301 /* LocalAuthentication.swift */; };
|
2C96D39C2763ADE100687301 /* LocalAuthentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C96D39B2763ADE100687301 /* LocalAuthentication.swift */; };
|
||||||
|
2C96D3A22763C65B00687301 /* KeyboardObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C96D3A12763C65B00687301 /* KeyboardObserver.swift */; };
|
||||||
|
2C96D3A42763C6A800687301 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C96D3A32763C6A800687301 /* UIView.swift */; };
|
||||||
|
2C96D3A62763CCA000687301 /* Images.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C96D3A52763CCA000687301 /* Images.swift */; };
|
||||||
|
2C96D3A92763D13400687301 /* DataStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C96D3A72763D13400687301 /* DataStateView.swift */; };
|
||||||
|
2C96D3AA2763D13400687301 /* DataStateView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2C96D3A82763D13400687301 /* DataStateView.xib */; };
|
||||||
2C9F0B6526BDC9AF008FA3D6 /* EthereumNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9F0B6426BDC9AF008FA3D6 /* EthereumNetwork.swift */; };
|
2C9F0B6526BDC9AF008FA3D6 /* EthereumNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9F0B6426BDC9AF008FA3D6 /* EthereumNetwork.swift */; };
|
||||||
2C9F0B6826BDCB2E008FA3D6 /* EthereumChain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9F0B6726BDCB2E008FA3D6 /* EthereumChain.swift */; };
|
2C9F0B6826BDCB2E008FA3D6 /* EthereumChain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9F0B6726BDCB2E008FA3D6 /* EthereumChain.swift */; };
|
||||||
2CAA412526C7CD93009F3535 /* ReviewRequester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CAA412426C7CD93009F3535 /* ReviewRequester.swift */; };
|
2CAA412526C7CD93009F3535 /* ReviewRequester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CAA412426C7CD93009F3535 /* ReviewRequester.swift */; };
|
||||||
@ -246,6 +251,11 @@
|
|||||||
2C96D3952762380400687301 /* ButtonWithExtendedArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonWithExtendedArea.swift; sourceTree = "<group>"; };
|
2C96D3952762380400687301 /* ButtonWithExtendedArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonWithExtendedArea.swift; sourceTree = "<group>"; };
|
||||||
2C96D39727623EC600687301 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = "<group>"; };
|
2C96D39727623EC600687301 /* URL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URL.swift; sourceTree = "<group>"; };
|
||||||
2C96D39B2763ADE100687301 /* LocalAuthentication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalAuthentication.swift; sourceTree = "<group>"; };
|
2C96D39B2763ADE100687301 /* LocalAuthentication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalAuthentication.swift; sourceTree = "<group>"; };
|
||||||
|
2C96D3A12763C65B00687301 /* KeyboardObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = KeyboardObserver.swift; path = "../../../Wildberries/wbx-ios/WBX-iOS/Library/Tools/KeyboardObserver.swift"; sourceTree = "<group>"; };
|
||||||
|
2C96D3A32763C6A800687301 /* UIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = "<group>"; };
|
||||||
|
2C96D3A52763CCA000687301 /* Images.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Images.swift; sourceTree = "<group>"; };
|
||||||
|
2C96D3A72763D13400687301 /* DataStateView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataStateView.swift; sourceTree = "<group>"; };
|
||||||
|
2C96D3A82763D13400687301 /* DataStateView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DataStateView.xib; sourceTree = "<group>"; };
|
||||||
2C9F0B6426BDC9AF008FA3D6 /* EthereumNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumNetwork.swift; sourceTree = "<group>"; };
|
2C9F0B6426BDC9AF008FA3D6 /* EthereumNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumNetwork.swift; sourceTree = "<group>"; };
|
||||||
2C9F0B6726BDCB2E008FA3D6 /* EthereumChain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumChain.swift; sourceTree = "<group>"; };
|
2C9F0B6726BDCB2E008FA3D6 /* EthereumChain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumChain.swift; sourceTree = "<group>"; };
|
||||||
2CAA412426C7CD93009F3535 /* ReviewRequester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewRequester.swift; sourceTree = "<group>"; };
|
2CAA412426C7CD93009F3535 /* ReviewRequester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewRequester.swift; sourceTree = "<group>"; };
|
||||||
@ -501,6 +511,7 @@
|
|||||||
2C8E88A0275F99D4003EB8DB /* Content */ = {
|
2C8E88A0275F99D4003EB8DB /* Content */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
2C96D3A52763CCA000687301 /* Images.swift */,
|
||||||
2C8E889E275F9967003EB8DB /* Storyboard.swift */,
|
2C8E889E275F9967003EB8DB /* Storyboard.swift */,
|
||||||
);
|
);
|
||||||
path = Content;
|
path = Content;
|
||||||
@ -519,6 +530,9 @@
|
|||||||
2C96D394276237F600687301 /* Library */ = {
|
2C96D394276237F600687301 /* Library */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
2C96D3A72763D13400687301 /* DataStateView.swift */,
|
||||||
|
2C96D3A82763D13400687301 /* DataStateView.xib */,
|
||||||
|
2C96D3A12763C65B00687301 /* KeyboardObserver.swift */,
|
||||||
2C96D3952762380400687301 /* ButtonWithExtendedArea.swift */,
|
2C96D3952762380400687301 /* ButtonWithExtendedArea.swift */,
|
||||||
2C96D39B2763ADE100687301 /* LocalAuthentication.swift */,
|
2C96D39B2763ADE100687301 /* LocalAuthentication.swift */,
|
||||||
);
|
);
|
||||||
@ -530,6 +544,7 @@
|
|||||||
children = (
|
children = (
|
||||||
2CC6EF0C275E64810040CC62 /* UIViewController.swift */,
|
2CC6EF0C275E64810040CC62 /* UIViewController.swift */,
|
||||||
2C8E88A3275FB7B9003EB8DB /* UIApplication.swift */,
|
2C8E88A3275FB7B9003EB8DB /* UIApplication.swift */,
|
||||||
|
2C96D3A32763C6A800687301 /* UIView.swift */,
|
||||||
2C96D391276232A300687301 /* UITableView.swift */,
|
2C96D391276232A300687301 /* UITableView.swift */,
|
||||||
);
|
);
|
||||||
path = Extensions;
|
path = Extensions;
|
||||||
@ -856,6 +871,7 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
2C96D3AA2763D13400687301 /* DataStateView.xib in Resources */,
|
||||||
2C5FF97E26C84F7C00B32ACC /* LaunchScreen.storyboard in Resources */,
|
2C5FF97E26C84F7C00B32ACC /* LaunchScreen.storyboard in Resources */,
|
||||||
2C96D3902762317300687301 /* AccountTableViewCell.xib in Resources */,
|
2C96D3902762317300687301 /* AccountTableViewCell.xib in Resources */,
|
||||||
2C5FF97B26C84F7C00B32ACC /* Assets.xcassets in Resources */,
|
2C5FF97B26C84F7C00B32ACC /* Assets.xcassets in Resources */,
|
||||||
@ -1080,7 +1096,9 @@
|
|||||||
2CF255A6275A48BB00AE54B9 /* GasService.swift in Sources */,
|
2CF255A6275A48BB00AE54B9 /* GasService.swift in Sources */,
|
||||||
2C96D392276232A300687301 /* UITableView.swift in Sources */,
|
2C96D392276232A300687301 /* UITableView.swift in Sources */,
|
||||||
2CF255A5275A48BB00AE54B9 /* ReviewRequester.swift in Sources */,
|
2CF255A5275A48BB00AE54B9 /* ReviewRequester.swift in Sources */,
|
||||||
|
2C96D3A22763C65B00687301 /* KeyboardObserver.swift in Sources */,
|
||||||
2CF255B6275A746000AE54B9 /* AccountsListViewController.swift in Sources */,
|
2CF255B6275A746000AE54B9 /* AccountsListViewController.swift in Sources */,
|
||||||
|
2C96D3A42763C6A800687301 /* UIView.swift in Sources */,
|
||||||
2CF25597275A46D300AE54B9 /* Defaults.swift in Sources */,
|
2CF25597275A46D300AE54B9 /* Defaults.swift in Sources */,
|
||||||
2CF255A2275A47DD00AE54B9 /* String.swift in Sources */,
|
2CF255A2275A47DD00AE54B9 /* String.swift in Sources */,
|
||||||
2CF2559D275A479800AE54B9 /* TokenaryWallet.swift in Sources */,
|
2CF2559D275A479800AE54B9 /* TokenaryWallet.swift in Sources */,
|
||||||
@ -1097,12 +1115,14 @@
|
|||||||
2CF255B4275A744000AE54B9 /* PasswordViewController.swift in Sources */,
|
2CF255B4275A744000AE54B9 /* PasswordViewController.swift in Sources */,
|
||||||
2C8E889F275F9967003EB8DB /* Storyboard.swift in Sources */,
|
2C8E889F275F9967003EB8DB /* Storyboard.swift in Sources */,
|
||||||
2C96D39C2763ADE100687301 /* LocalAuthentication.swift in Sources */,
|
2C96D39C2763ADE100687301 /* LocalAuthentication.swift in Sources */,
|
||||||
|
2C96D3A62763CCA000687301 /* Images.swift in Sources */,
|
||||||
2CF255AA275A48BB00AE54B9 /* SessionStorage.swift in Sources */,
|
2CF255AA275A48BB00AE54B9 /* SessionStorage.swift in Sources */,
|
||||||
2C96D39827623EC600687301 /* URL.swift in Sources */,
|
2C96D39827623EC600687301 /* URL.swift in Sources */,
|
||||||
2CF255AD275A48CF00AE54B9 /* EthereumChain.swift in Sources */,
|
2CF255AD275A48CF00AE54B9 /* EthereumChain.swift in Sources */,
|
||||||
2CF2559C275A477F00AE54B9 /* ApprovalSubject.swift in Sources */,
|
2CF2559C275A477F00AE54B9 /* ApprovalSubject.swift in Sources */,
|
||||||
2CF255B1275A4A1800AE54B9 /* ResponseToExtension.swift in Sources */,
|
2CF255B1275A4A1800AE54B9 /* ResponseToExtension.swift in Sources */,
|
||||||
2CF2559B275A46E700AE54B9 /* AuthenticationReason.swift in Sources */,
|
2CF2559B275A46E700AE54B9 /* AuthenticationReason.swift in Sources */,
|
||||||
|
2C96D3A92763D13400687301 /* DataStateView.swift in Sources */,
|
||||||
2CF255A3275A47DD00AE54B9 /* UserDefaults.swift in Sources */,
|
2CF255A3275A47DD00AE54B9 /* UserDefaults.swift in Sources */,
|
||||||
2CF255B8275A748300AE54B9 /* ApproveTransactionViewController.swift in Sources */,
|
2CF255B8275A748300AE54B9 /* ApproveTransactionViewController.swift in Sources */,
|
||||||
2C8E88A4275FB7B9003EB8DB /* UIApplication.swift in Sources */,
|
2C8E88A4275FB7B9003EB8DB /* UIApplication.swift in Sources */,
|
||||||
|
Loading…
Reference in New Issue
Block a user