Skip to content

Commit

Permalink
Update empty & error screens to have background behind empty & error …
Browse files Browse the repository at this point in the history
…states logos (#421)

* added background

* fixes

* fix

* added space

* fix spacing

* remove error and empty states

* remove blurred background view

* remove mock data

* fix font
  • Loading branch information
lynx56 authored Sep 29, 2022
1 parent 05a747e commit 383e765
Show file tree
Hide file tree
Showing 12 changed files with 183 additions and 127 deletions.
4 changes: 4 additions & 0 deletions novawallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2172,6 +2172,7 @@
88D997B228ABC90E006135A5 /* AboutCrowdloansView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88D997B128ABC90E006135A5 /* AboutCrowdloansView.swift */; };
88E1E896289C021F00C123A8 /* CurrencyCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88E1E895289C021F00C123A8 /* CurrencyCollectionViewCell.swift */; };
88E1E898289C024400C123A8 /* UIView+Create.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88E1E897289C024400C123A8 /* UIView+Create.swift */; };
88E8CF5E28E3789600C90112 /* CrowdloanEmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88E8CF5D28E3789600C90112 /* CrowdloanEmptyView.swift */; };
88F19DDE28D8D0A100F6E459 /* Either.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F19DDD28D8D0A100F6E459 /* Either.swift */; };
88F19DE028D8D0F600F6E459 /* LoadableViewModelState+Addition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88F19DDF28D8D0F600F6E459 /* LoadableViewModelState+Addition.swift */; };
88F3A9FB9CEA464275F1115E /* ExportMnemonicViewFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47759907380BE9300E54DC78 /* ExportMnemonicViewFactory.swift */; };
Expand Down Expand Up @@ -4934,6 +4935,7 @@
88D997B128ABC90E006135A5 /* AboutCrowdloansView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutCrowdloansView.swift; sourceTree = "<group>"; };
88E1E895289C021F00C123A8 /* CurrencyCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyCollectionViewCell.swift; sourceTree = "<group>"; };
88E1E897289C024400C123A8 /* UIView+Create.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Create.swift"; sourceTree = "<group>"; };
88E8CF5D28E3789600C90112 /* CrowdloanEmptyView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CrowdloanEmptyView.swift; sourceTree = "<group>"; };
88F19DDD28D8D0A100F6E459 /* Either.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Either.swift; sourceTree = "<group>"; };
88F19DDF28D8D0F600F6E459 /* LoadableViewModelState+Addition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LoadableViewModelState+Addition.swift"; sourceTree = "<group>"; };
88F7715F28BEA589008C028A /* YourWalletsIconDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YourWalletsIconDetailsView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -9384,6 +9386,7 @@
849842EA26587AFA006BBB9F /* View */ = {
isa = PBXGroup;
children = (
88E8CF5D28E3789600C90112 /* CrowdloanEmptyView.swift */,
F4F69E272731B0B200214542 /* CrowdloanTableHeaderView.swift */,
84BB3CF7267D276D00676FFE /* CrowdloanTableViewCell.swift */,
8498430226592D29006BBB9F /* CrowdloanStatusSectionView.swift */,
Expand Down Expand Up @@ -14139,6 +14142,7 @@
843E9B2F27C8B17F009C143A /* FileDownloadOperation.swift in Sources */,
8490152124ABC721008F705E /* WalletStaticImageViewModel.swift in Sources */,
F408E9BE26B80FD30043CFE0 /* AnalyticsSectionHeader.swift in Sources */,
88E8CF5E28E3789600C90112 /* CrowdloanEmptyView.swift in Sources */,
84C6801824D7053B00006BF5 /* BorderedSubtitleActionView.swift in Sources */,
84468A0B286663E500BCBE00 /* CrossChainTransferSetupPresenter.swift in Sources */,
84A2C90C24E192F50020D3B7 /* ShakeAnimator.swift in Sources */,
Expand Down
9 changes: 7 additions & 2 deletions novawallet/Common/View/ErrorView/ErrorStateView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class ErrorStateView: UIView {
return button
}()

lazy var stackView = UIStackView(arrangedSubviews: [iconImageView, errorDescriptionLabel, retryButton])

var locale = Locale.current {
didSet {
if locale != oldValue {
Expand All @@ -47,13 +49,16 @@ class ErrorStateView: UIView {
}

private func setupLayout() {
let stackView = UIStackView(arrangedSubviews: [iconImageView, errorDescriptionLabel, retryButton])
stackView.axis = .vertical
stackView.spacing = 16
stackView.alignment = .center

addSubview(stackView)
stackView.snp.makeConstraints { $0.center.equalToSuperview() }
stackView.snp.makeConstraints {
$0.center.equalToSuperview()
$0.leading.top.greaterThanOrEqualToSuperview()
$0.trailing.bottom.lessThanOrEqualToSuperview()
}
}

private func applyLocalization() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,6 @@ final class CrowdloanListPresenter {
self.localizationManager = localizationManager
}

private func provideViewErrorState() {
let message = R.string.localizable
.commonErrorNoDataRetrieved(preferredLanguages: selectedLocale.rLanguages)
view?.didReceive(listState: .error(message: message))
}

private func updateWalletSwitchView() {
guard let wallet = wallet else {
return
Expand All @@ -73,7 +67,7 @@ final class CrowdloanListPresenter {
guard
case let .success(chain) = chainResult,
let asset = chain.utilityAssets().first else {
provideViewErrorState()
provideViewError(chainAsset: nil)
return
}

Expand Down Expand Up @@ -156,7 +150,7 @@ final class CrowdloanListPresenter {
}

guard case let .success(chain) = chainResult, let asset = chain.utilityAssets().first else {
provideViewErrorState()
provideViewError(chainAsset: nil)
return
}

Expand All @@ -166,17 +160,11 @@ final class CrowdloanListPresenter {
return
}

let chainAsset = ChainAssetDisplayInfo(asset: asset.displayInfo, chain: chain.chainFormat)
do {
let crowdloans = try crowdloansResult.get()
let priceData = try? priceDataResult?.get() ?? nil

guard !crowdloans.isEmpty else {
view?.didReceive(listState: .empty)
return
}

let viewInfo = try viewInfoResult.get()
let chainAsset = ChainAssetDisplayInfo(asset: asset.displayInfo, chain: chain.chainFormat)
let externalContributionsCount = externalContributions?.count ?? 0

let amount: Decimal?
Expand All @@ -202,7 +190,7 @@ final class CrowdloanListPresenter {

view?.didReceive(listState: .loaded(viewModel: viewModel))
} catch {
provideViewErrorState()
provideViewError(chainAsset: chainAsset)
}
}

Expand All @@ -221,6 +209,14 @@ final class CrowdloanListPresenter {
displayInfo: displayInfo
)
}

private func provideViewError(chainAsset: ChainAssetDisplayInfo?) {
let viewModel = viewModelFactory.createErrorViewModel(
chainAsset: chainAsset,
locale: selectedLocale
)
view?.didReceive(listState: .loaded(viewModel: viewModel))
}
}

extension CrowdloanListPresenter: CrowdloanListPresenterProtocol {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ final class CrowdloanListViewController: UIViewController, ViewHolder {
rootView.tableView.registerClassForCell(YourContributionsTableViewCell.self)
rootView.tableView.registerClassForCell(AboutCrowdloansTableViewCell.self)
rootView.tableView.registerClassForCell(CrowdloanTableViewCell.self)
rootView.tableView.registerClassForCell(BlurredTableViewCell<CrowdloanEmptyView>.self)
rootView.tableView.registerClassForCell(BlurredTableViewCell<ErrorStateView>.self)
rootView.tableView.registerHeaderFooterView(withClass: CrowdloanStatusSectionView.self)
rootView.tableView.dataSource = self
rootView.tableView.delegate = self
Expand Down Expand Up @@ -107,19 +109,12 @@ final class CrowdloanListViewController: UIViewController, ViewHolder {
switch state {
case .loading:
didStartLoading()
rootView.bringSubviewToFront(rootView.tableView)
case .loaded:
rootView.tableView.refreshControl?.endRefreshing()
didStopLoading()
rootView.bringSubviewToFront(rootView.tableView)
case .empty, .error:
rootView.tableView.refreshControl?.endRefreshing()
didStopLoading()
rootView.bringSubviewToFront(rootView.statusView)
}

rootView.tableView.reloadData()
reloadEmptyState(animated: false)
}

@objc func actionRefresh() {
Expand All @@ -140,7 +135,7 @@ extension CrowdloanListViewController: UITableViewDataSource {
switch state {
case let .loaded(viewModel):
return viewModel.sections.count
case .loading, .empty, .error:
case .loading:
return 0
}
}
Expand All @@ -154,10 +149,10 @@ extension CrowdloanListViewController: UITableViewDataSource {
return cellViewModels.count
case let .completed(_, cellViewModels):
return cellViewModels.count
case .yourContributions, .about:
case .yourContributions, .about, .error, .empty:
return 1
}
case .loading, .empty, .error:
case .loading:
return 0
}
}
Expand All @@ -180,8 +175,25 @@ extension CrowdloanListViewController: UITableViewDataSource {
let cell = tableView.dequeueReusableCellWithType(AboutCrowdloansTableViewCell.self)!
cell.view.bind(model: model)
return cell
case let .error(message):
let cell: BlurredTableViewCell<ErrorStateView> = tableView.dequeueReusableCell(for: indexPath)
cell.view.errorDescriptionLabel.text = message
cell.view.delegate = self
cell.view.locale = selectedLocale
cell.applyStyle()
return cell
case .empty:
let cell: BlurredTableViewCell<CrowdloanEmptyView> = tableView.dequeueReusableCell(for: indexPath)
let text = R.string.localizable
.crowdloanEmptyMessage_v3_9_1(preferredLanguages: selectedLocale.rLanguages)
cell.view.bind(
image: R.image.iconEmptyHistory(),
text: text
)
cell.applyStyle()
return cell
}
case .loading, .empty, .error:
case .loading:
return UITableViewCell()
}
}
Expand Down Expand Up @@ -218,6 +230,10 @@ extension CrowdloanListViewController: UITableViewDelegate {
let headerView: CrowdloanStatusSectionView = tableView.dequeueReusableHeaderFooterView()
headerView.bind(title: title, count: cells.count)
return headerView
case let .empty(title):
let headerView: CrowdloanStatusSectionView = tableView.dequeueReusableHeaderFooterView()
headerView.bind(title: title, count: 0)
return headerView
default:
return nil
}
Expand All @@ -230,7 +246,7 @@ extension CrowdloanListViewController: UITableViewDelegate {

let sectionModel = viewModel.sections[section]
switch sectionModel {
case .active, .completed:
case .active, .completed, .empty:
return UITableView.automaticDimension
default:
return 0.0
Expand Down Expand Up @@ -265,52 +281,11 @@ extension CrowdloanListViewController: Localizable {
}
}

extension CrowdloanListViewController: LoadableViewProtocol {}

extension CrowdloanListViewController: EmptyStateViewOwnerProtocol {
var emptyStateDelegate: EmptyStateDelegate { self }
var emptyStateDataSource: EmptyStateDataSource { self }
var contentViewForEmptyState: UIView { rootView.statusView }
}

extension CrowdloanListViewController: EmptyStateDataSource {
var viewForEmptyState: UIView? {
switch state {
case let .error(message):
let errorView = ErrorStateView()
errorView.errorDescriptionLabel.text = message
errorView.delegate = self
errorView.locale = selectedLocale
return errorView
case .empty:
let emptyView = EmptyStateView()
emptyView.image = R.image.iconEmptyHistory()
emptyView.title = R.string.localizable
.crowdloanEmptyMessage_v2_2_0(preferredLanguages: selectedLocale.rLanguages)
emptyView.titleColor = R.color.colorLightGray()!
emptyView.titleFont = .p2Paragraph
return emptyView
case .loading, .loaded:
return nil
}
}
}

extension CrowdloanListViewController: EmptyStateDelegate {
var shouldDisplayEmptyState: Bool {
switch state {
case .error, .empty:
return true
case .loading, .loaded:
return false
}
}
}

extension CrowdloanListViewController: ErrorStateViewDelegate {
func didRetry(errorView _: ErrorStateView) {
presenter.refresh(shouldReset: true)
}
}

extension CrowdloanListViewController: LoadableViewProtocol {}
extension CrowdloanListViewController: HiddableBarWhenPushed {}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ final class CrowdloanListViewLayout: UIView {
return view
}()

let statusView = UIView()

override init(frame: CGRect) {
super.init(frame: frame)

Expand Down Expand Up @@ -51,13 +49,6 @@ final class CrowdloanListViewLayout: UIView {
addSubview(backgroundView)
backgroundView.snp.makeConstraints { $0.edges.equalToSuperview() }

addSubview(statusView)
statusView.snp.makeConstraints { make in
make.leading.trailing.equalToSuperview()
make.bottom.equalTo(safeAreaLayoutGuide)
make.top.equalTo(safeAreaLayoutGuide).inset(253)
}

addSubview(tableView)
tableView.snp.makeConstraints { make in
make.top.equalToSuperview()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import UIKit

final class CrowdloanEmptyView: UIView {
var verticalSpacing: CGFloat = 8.0 {
didSet {
stackView.spacing = verticalSpacing
}
}

let imageView = UIImageView()

let titleLabel: UILabel = .create {
$0.numberOfLines = 0
$0.textAlignment = .center
$0.backgroundColor = .clear
$0.textColor = R.color.colorWhite64()
$0.font = .p2Paragraph
}

private lazy var stackView = UIStackView(arrangedSubviews: [
imageView,
titleLabel
])

override init(frame: CGRect) {
super.init(frame: frame)

backgroundColor = .clear
setupLayout()
}

@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

private func setupLayout() {
stackView.axis = .vertical
stackView.alignment = .center
stackView.spacing = verticalSpacing

addSubview(stackView)
stackView.snp.makeConstraints {
$0.edges.equalToSuperview()
}
}

func bind(image: UIImage?, text: String?) {
imageView.image = image
titleLabel.text = text
}
}
Loading

0 comments on commit 383e765

Please sign in to comment.