Skip to content

Commit

Permalink
Add rank badges to MarketEtf module
Browse files Browse the repository at this point in the history
- fix display of 24h period in UI
  • Loading branch information
ealymbaev committed Jun 12, 2024
1 parent 51b0f39 commit 325ec61
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 31 deletions.
32 changes: 19 additions & 13 deletions UnstoppableWallet/UnstoppableWallet/Extensions/Etf.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,6 @@ import Foundation
import MarketKit
import UIKit

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

public func hash(into hasher: inout Hasher) {
hasher.combine(ticker)
}
}

extension Etf {
var imageUrl: String {
let scale = Int(UIScreen.main.scale)
Expand All @@ -26,9 +16,25 @@ extension Etf {
}
}

extension [Etf] {
func sorted(sortBy: MarketEtfViewModel.SortBy, timePeriod: MarketEtfViewModel.TimePeriod) -> [Etf] {
sorted { lhsEtf, rhsEtf in
struct RankedEtf: Hashable {
let etf: Etf
let rank: Int

public static func == (lhs: RankedEtf, rhs: RankedEtf) -> Bool {
lhs.etf.ticker == rhs.etf.ticker
}

public func hash(into hasher: inout Hasher) {
hasher.combine(etf.ticker)
}
}

extension [RankedEtf] {
func sorted(sortBy: MarketEtfViewModel.SortBy, timePeriod: MarketEtfViewModel.TimePeriod) -> [RankedEtf] {
sorted { lhsRankedEtf, rhsRankedEtf in
let lhsEtf = lhsRankedEtf.etf
let rhsEtf = rhsRankedEtf.etf

switch sortBy {
case .highestAssets, .lowestAssets:
guard let lhsAssets = lhsEtf.totalAssets else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ struct MarketEtfView: View {
ProgressView()
Spacer()
}
case let .loaded(etfs):
case let .loaded(rankedEtfs):
ScrollViewReader { proxy in
ThemeList(bottomSpacing: .margin16, invisibleTopView: true) {
header()
Expand All @@ -40,7 +40,7 @@ struct MarketEtfView: View {
.listRowInsets(EdgeInsets())
.listRowSeparator(.hidden)

list(etfs: etfs)
list(rankedEtfs: rankedEtfs)
}
.onChange(of: viewModel.sortBy) { _ in withAnimation { proxy.scrollTo(themeListTopViewId) } }
.onChange(of: viewModel.timePeriod) { _ in withAnimation { proxy.scrollTo(themeListTopViewId) } }
Expand Down Expand Up @@ -137,14 +137,17 @@ struct MarketEtfView: View {
)
}

@ViewBuilder private func list(etfs: [Etf]) -> some View {
@ViewBuilder private func list(rankedEtfs: [RankedEtf]) -> some View {
Section {
ListForEach(etfs) { etf in
ListForEach(rankedEtfs) { rankedEtf in
let etf = rankedEtf.etf

ListRow {
itemContent(
imageUrl: URL(string: etf.imageUrl),
ticker: etf.ticker,
name: etf.name,
rank: rankedEtf.rank,
totalAssets: etf.totalAssets,
change: etf.inflow(timePeriod: viewModel.timePeriod)
)
Expand All @@ -165,6 +168,7 @@ struct MarketEtfView: View {
imageUrl: nil,
ticker: "ABCD",
name: "Ticker Name",
rank: 12,
totalAssets: 123_345_678,
change: index % 2 == 0 ? 123_456 : -123_456
)
Expand All @@ -178,7 +182,7 @@ struct MarketEtfView: View {
}
}

@ViewBuilder private func itemContent(imageUrl: URL?, ticker: String, name: String, totalAssets: Decimal?, change: Decimal?) -> some View {
@ViewBuilder private func itemContent(imageUrl: URL?, ticker: String, name: String, rank: Int, totalAssets: Decimal?, change: Decimal?) -> some View {
KFImage.url(imageUrl)
.resizable()
.placeholder { RoundedRectangle(cornerRadius: .cornerRadius8).fill(Color.themeSteel20) }
Expand All @@ -193,7 +197,10 @@ struct MarketEtfView: View {
}

HStack(spacing: .margin8) {
Text(name).textSubhead2()
HStack(spacing: .margin4) {
BadgeViewNew(text: "\(rank)")
Text(name).textSubhead2()
}
Spacer()
DiffText(change, currency: viewModel.currency)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ class MarketEtfViewModel: ObservableObject {
switch internalState {
case .loading:
state = .loading
case let .loaded(etfs):
state = .loaded(etfs: etfs.sorted(sortBy: sortBy, timePeriod: timePeriod))
case let .loaded(rankedEtfs):
state = .loaded(rankedEtfs: rankedEtfs.sorted(sortBy: sortBy, timePeriod: timePeriod))
case let .failed(error):
state = .failed(error: error)
}
Expand All @@ -73,9 +73,11 @@ extension MarketEtfViewModel {
Task { [weak self, marketKit, currency] in
do {
let etfs = try await marketKit.etfs(currencyCode: currency.code)
let sortedEtfs = etfs.sorted { $0.totalAssets ?? 0 > $1.totalAssets ?? 0 }
let rankedEtfs = sortedEtfs.enumerated().map { RankedEtf(etf: $1, rank: $0 + 1) }

await MainActor.run { [weak self] in
self?.internalState = .loaded(etfs: etfs)
self?.internalState = .loaded(rankedEtfs: rankedEtfs)
}
} catch {
await MainActor.run { [weak self] in
Expand All @@ -90,7 +92,7 @@ extension MarketEtfViewModel {
extension MarketEtfViewModel {
enum State {
case loading
case loaded(etfs: [Etf])
case loaded(rankedEtfs: [RankedEtf])
case failed(error: Error)
}

Expand All @@ -111,14 +113,14 @@ extension MarketEtfViewModel {

var title: String {
switch self {
case let .period(timePeriod): return "market.time_period.\(timePeriod.rawValue)".localized
case let .period(timePeriod): return timePeriod.title
case .all: return "market.etf.period.all".localized
}
}

var shortTitle: String {
switch self {
case let .period(timePeriod): return "market.time_period.\(timePeriod.rawValue).short".localized
case let .period(timePeriod): return timePeriod.shortTitle
case .all: return "market.etf.period.all".localized
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,17 @@ extension [MarketKit.TopPlatform] {

extension HsTimePeriod {
var title: String {
"market.time_period.\(rawValue)".localized
switch self {
case .hour24: return "market.time_period.1d".localized
default: return "market.time_period.\(rawValue)".localized
}
}

var shortTitle: String {
"market.time_period.\(rawValue).short".localized
switch self {
case .hour24: return "market.time_period.1d.short".localized
default: return "market.time_period.\(rawValue).short".localized
}
}

init?(_ periodType: HsPeriodType) {
Expand All @@ -208,11 +214,17 @@ extension HsTimePeriod {

extension WatchlistTimePeriod {
var title: String {
"market.time_period.\(rawValue)".localized
switch self {
case .hour24: return "market.time_period.1d".localized
default: return "market.time_period.\(rawValue)".localized
}
}

var shortTitle: String {
"market.time_period.\(rawValue).short".localized
switch self {
case .hour24: return "market.time_period.1d.short".localized
default: return "market.time_period.\(rawValue).short".localized
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,6 @@
"market.top_coins" = "Top %@";

"market.time_period.title" = "Period";
"market.time_period.24h" = "24 Hours";
"market.time_period.1d" = "1 Day";
"market.time_period.1w" = "1 Week";
"market.time_period.2w" = "2 Weeks";
Expand All @@ -734,7 +733,6 @@
"market.time_period.1y" = "1 Year";
"market.time_period.2y" = "2 Years";
"market.time_period.5y" = "5 Years";
"market.time_period.24h.short" = "24H";
"market.time_period.1d.short" = "1D";
"market.time_period.1w.short" = "1W";
"market.time_period.2w.short" = "2W";
Expand Down

0 comments on commit 325ec61

Please sign in to comment.