Skip to content

Commit

Permalink
Refactor Treasuries module to use SwiftUI
Browse files Browse the repository at this point in the history
  • Loading branch information
esen committed Jun 4, 2024
1 parent 9ea81b0 commit 5a00bb9
Show file tree
Hide file tree
Showing 11 changed files with 284 additions and 471 deletions.
24 changes: 6 additions & 18 deletions UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions UnstoppableWallet/UnstoppableWallet/Extensions/CoinTreasury.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,13 @@ extension CoinTreasury {
return "https://cdn.blocksdecoded.com/treasury-icons/\(fundUid)@\(scale)x.png"
}
}

extension CoinTreasury: Hashable {
public static func == (lhs: CoinTreasury, rhs: CoinTreasury) -> Bool {
lhs.fundUid == rhs.fundUid
}

public func hash(into hasher: inout Hasher) {
hasher.combine(fundUid)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ class CoinAnalyticsViewController: ThemeViewController {
}

private func openTreasuries() {
let viewController = CoinTreasuriesModule.viewController(coin: viewModel.coin)
let viewController = CoinTreasuriesView(coin: viewModel.coin).toViewController(title: "coin_analytics.treasuries".localized)
parentNavigationController?.pushViewController(viewController, animated: true)
}

Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import Kingfisher
import MarketKit
import SwiftUI

struct CoinTreasuriesView: View {
@StateObject var viewModel: CoinTreasuriesViewModel

@State private var filterSelectorPresented = false

init(coin: Coin) {
_viewModel = StateObject(wrappedValue: CoinTreasuriesViewModel(coin: coin))
}

var body: some View {
ThemeView {
switch viewModel.state {
case .loading:
VStack(spacing: 0) {
header()
loadingList()
}
case let .loaded(treasuries):
VStack(spacing: 0) {
header()

ThemeList(bottomSpacing: .margin32) {
list(treasuries: treasuries)
footer()
.listRowBackground(Color.clear)
.listRowInsets(EdgeInsets())
.listRowSeparator(.hidden)
}
}
case .failed:
SyncErrorView {
Task {
await viewModel.refresh()
}
}
}
}
}

@ViewBuilder private func header() -> some View {
HorizontalDivider(color: .themeSteel10)
HStack {
HStack {
Button(action: {
filterSelectorPresented = true
}) {
Text(viewModel.filter.title)
}
.buttonStyle(SecondaryButtonStyle(style: .transparent, rightAccessory: .dropDown))
}
.alert(
isPresented: $filterSelectorPresented,
title: "coin_analytics.treasuries.filters".localized,
viewItems: viewModel.filters.map { .init(text: $0.title, selected: viewModel.filter == $0) },
onTap: { index in
guard let index else {
return
}

viewModel.filter = viewModel.filters[index]
}
)

Spacer()

Button(action: {
viewModel.toggleSortBy()
}) {
Image(viewModel.orderedAscending ? "sort_l2h_20" : "sort_h2l_20").renderingMode(.template)
}
.buttonStyle(SecondaryCircleButtonStyle(style: .default))
.padding(.trailing, .margin16)
}
.padding(.vertical, .margin8)
}

@ViewBuilder private func list(treasuries: [CoinTreasury]) -> some View {
ListForEach(treasuries) { treasury in
itemContent(
logoUrl: treasury.fundLogoUrl,
fund: treasury.fund,
amount: ValueFormatter.instance.formatShort(value: treasury.amount, decimalCount: 8, symbol: viewModel.coinCode) ?? "---",
country: treasury.country,
amountInCurrency: ValueFormatter.instance.formatShort(currency: viewModel.currency, value: treasury.amountInCurrency) ?? "---"
)
}
}

@ViewBuilder private func footer() -> some View {
Text("Powered by Bitcointreasuries.net")
.textCaption(color: .themeGray)
.padding(.top, .margin12)
.padding(.horizontal, .margin24)
.frame(maxWidth: .infinity)
}

@ViewBuilder private func loadingList() -> some View {
ThemeList(Array(0 ... 10)) { _ in
ListRow {
itemContent(
logoUrl: nil,
fund: "",
amount: "",
country: "",
amountInCurrency: ""
)
.redacted()
}
}
.simultaneousGesture(DragGesture(minimumDistance: 0), including: .all)
}

@ViewBuilder private func itemContent(logoUrl: String?, fund: String, amount: String, country: String, amountInCurrency: String) -> some View {
ListRow {
if let url = logoUrl.flatMap({ URL(string: $0) }) {
KFImage.url(url)
.resizable()
.frame(width: .iconSize32, height: .iconSize32)
}

VStack(spacing: 1) {
HStack(spacing: .margin8) {
Text(fund).textBody()
Spacer()
Text(amount).textBody()
}

HStack(spacing: .margin8) {
Text(country).textSubhead2()
Spacer()
Text(amountInCurrency).textSubhead2(color: .themeJacob)
}
}
}
}
}
Loading

0 comments on commit 5a00bb9

Please sign in to comment.