Skip to content

Commit

Permalink
TRCL-3319 : Trading Rewards Details Screen History Card (#41)
Browse files Browse the repository at this point in the history
* show help card in trading rewards

* add padding

* set up trading rewards title card

* add list items to the reward history card

* add view more button and header

* add more periods

* fix CD compilation

* address comments
  • Loading branch information
mike-dydx committed Aug 21, 2024
1 parent b9fcb45 commit 937606f
Show file tree
Hide file tree
Showing 12 changed files with 444 additions and 67 deletions.
28 changes: 9 additions & 19 deletions PlatformUI/PlatformUI/Components/TabGroup/TabItemViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,33 +54,23 @@ public class TabItemViewModel: PlatformViewModel, Equatable {
let borderWidth: CGFloat = 1
switch value {
case .text(let value):
let content = Text(value)
.themeFont(fontSize: .medium)
.padding([.bottom, .top], 6)
.padding([.leading, .trailing], 12)
return Text(value)
.themeFont(fontSize: .small)
.padding(.vertical, 6)
.padding(.horizontal, 8)
.themeStyle(styleKey: styleKey, parentStyle: style)
.clipShape(Capsule())
.overlay(
Capsule(style: .circular)
.stroke(ThemeColor.SemanticColor.layer6.color, lineWidth: borderWidth)
)
.padding(borderWidth * 2)
return AnyView(content)
.borderAndClip(style: .capsule, borderColor: .layer6, lineWidth: borderWidth)
.wrappedInAnyView()
case .icon(let image):
let content = PlatformIconViewModel(type: .uiImage(image: image),
return PlatformIconViewModel(type: .uiImage(image: image),
size: CGSize(width: 18, height: 18),
templateColor: templateColor)
.createView(parentStyle: parentStyle)
.padding([.bottom, .top], 6)
.padding([.leading, .trailing], 12)
.themeStyle(styleKey: styleKey, parentStyle: style)
.clipShape(Capsule())
.overlay(
Capsule(style: .circular)
.stroke(ThemeColor.SemanticColor.layer6.color, lineWidth: borderWidth)
)
.padding(borderWidth * 2)
return AnyView(content)
.borderAndClip(style: .capsule, borderColor: .layer6, lineWidth: borderWidth)
.wrappedInAnyView()
case .bar(let value):
let content = VStack {
value.createView(parentStyle: style)
Expand Down
53 changes: 44 additions & 9 deletions PlatformUI/PlatformUI/DesignSystem/Theme/ThemeViewModifiers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -499,16 +499,32 @@ public extension View {
// MARK: AttributedString

public extension AttributedString {
func themeFont(fontType: ThemeFont.FontType = .text, fontSize: ThemeFont.FontSize = .medium) -> Self {
var copy = self
copy.font = ThemeSettings.shared.themeConfig.themeFont.font(of: fontType, fontSize: fontSize)
return copy
/// Applies a font to the attributed string.
/// - Parameters:
/// - foreground: the font to apply
/// - range: the range to modify, `nil` if the entire string should be modified
func themeFont(fontType: ThemeFont.FontType = .text, fontSize: ThemeFont.FontSize = .medium, to range: Range<AttributedString.Index>? = nil) -> Self {
var string = self
if let range = range {
string[range].font = ThemeSettings.shared.themeConfig.themeFont.font(of: fontType, fontSize: fontSize)
} else {
string.font = ThemeSettings.shared.themeConfig.themeFont.font(of: fontType, fontSize: fontSize)
}
return string
}

func themeColor(foreground: ThemeColor.SemanticColor) -> Self {
var copy = self
copy.foregroundColor = ThemeSettings.shared.themeConfig.themeColor.color(of: foreground)
return copy

/// Applies a foreground color to the attributed string.
/// - Parameters:
/// - foreground: the color to apply
/// - range: the range to modify, `nil` if the entire string should be modified
func themeColor(foreground: ThemeColor.SemanticColor, to range: Range<AttributedString.Index>? = nil) -> Self {
var string = self
if let range = range {
string[range].foregroundColor = ThemeSettings.shared.themeConfig.themeColor.color(of: foreground)
} else {
string.foregroundColor = ThemeSettings.shared.themeConfig.themeColor.color(of: foreground)
}
return string
}
}

Expand Down Expand Up @@ -608,3 +624,22 @@ public extension View {
}
}

// MARK: ScrollView

public extension View {
func disableBounces() -> some View {
modifier(DisableBouncesModifier())
}
}

struct DisableBouncesModifier: ViewModifier {
func body(content: Content) -> some View {
content
.onAppear {
UIScrollView.appearance().bounces = false
}
.onDisappear {
UIScrollView.appearance().bounces = true
}
}
}
58 changes: 30 additions & 28 deletions PlatformUI/PlatformUI/PlatformListViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,39 +76,41 @@ open class PlatformListViewModel: PlatformViewModeling {
}

return AnyView(
ForEach(list, id: \.id) { [weak self] item in
Group {
let cell =
VStack(spacing: intraItemSeparator ? 0 : 10) {
ForEach(list, id: \.id) { [weak self] item in
Group {
if item === list.first, let header = self?.header {
header.createView(parentStyle: parentStyle)
} else {
VStack(alignment: .leading, spacing: 0) {
if self?.intraItemSeparator == true {
let shouldDisplayTopSeparator = self?.intraItemSeparator == true && (self?.firstListItemTopSeparator == true && item === list.first)
let shouldDisplayBottomSeparator = self?.intraItemSeparator == true || (item !== list.last || self?.lastListItemBottomSeparator == true)
if shouldDisplayTopSeparator {
DividerModel().createView(parentStyle: parentStyle)
}

Spacer()
item.createView(parentStyle: parentStyle)
Spacer()

if shouldDisplayBottomSeparator {
DividerModel().createView(parentStyle: parentStyle)
let cell =
Group {
if item === list.first, let header = self?.header {
header.createView(parentStyle: parentStyle)
} else {
VStack(alignment: .leading, spacing: 0) {
if self?.intraItemSeparator == true {
let shouldDisplayTopSeparator = self?.intraItemSeparator == true && (self?.firstListItemTopSeparator == true && item === list.first)
let shouldDisplayBottomSeparator = self?.intraItemSeparator == true || (item !== list.last || self?.lastListItemBottomSeparator == true)
if shouldDisplayTopSeparator {
DividerModel().createView(parentStyle: parentStyle)
}

Spacer()
item.createView(parentStyle: parentStyle)
Spacer()

if shouldDisplayBottomSeparator {
DividerModel().createView(parentStyle: parentStyle)
}
} else {
item.createView(parentStyle: parentStyle)
}
} else {
item.createView(parentStyle: parentStyle)
}
}
}
}

if let width = self?.width {
cell.frame(width: width)
} else {
cell
if let width = self?.width {
cell.frame(width: width)
} else {
cell
}
}
}
}
Expand Down
12 changes: 8 additions & 4 deletions dydx/dydxPresenters/dydxPresenters.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@
277E8FC92B1E576B005CCBCB /* dydxProfileRewardsViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277E8FC82B1E576B005CCBCB /* dydxProfileRewardsViewPresenter.swift */; };
277E90152B1EA0E3005CCBCB /* dydxTradingRewardsViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277E90142B1EA0E3005CCBCB /* dydxTradingRewardsViewPresenter.swift */; };
277E90192B1EA3C3005CCBCB /* dydxRewardsSummaryPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277E90182B1EA3C3005CCBCB /* dydxRewardsSummaryPresenter.swift */; };
277E90332B1FAE9A005CCBCB /* dydxRewardsHelpViewBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277E90322B1FAE9A005CCBCB /* dydxRewardsHelpViewBuilder.swift */; };
277E90332B1FAE9A005CCBCB /* dydxRewardsHelpViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277E90322B1FAE9A005CCBCB /* dydxRewardsHelpViewPresenter.swift */; };
277E908B2B2118AE005CCBCB /* dydxRewardsHistoryViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277E908A2B2118AE005CCBCB /* dydxRewardsHistoryViewPresenter.swift */; };
27C027532AFD761300E92CCB /* dydxSettingsHelpRowViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27C027522AFD761300E92CCB /* dydxSettingsHelpRowViewPresenter.swift */; };
27DB2EA32AC1E7B20047BC39 /* dydxTradeRestrictedViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27DB2EA22AC1E7B20047BC39 /* dydxTradeRestrictedViewPresenter.swift */; };
314BBDE9F332ECA910BC414E /* Pods_iOS_dydxPresenters.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F1551C00FFF41C29CFC5BD94 /* Pods_iOS_dydxPresenters.framework */; };
Expand Down Expand Up @@ -475,7 +476,8 @@
277E8FC82B1E576B005CCBCB /* dydxProfileRewardsViewPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = dydxProfileRewardsViewPresenter.swift; sourceTree = "<group>"; };
277E90142B1EA0E3005CCBCB /* dydxTradingRewardsViewPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxTradingRewardsViewPresenter.swift; sourceTree = "<group>"; };
277E90182B1EA3C3005CCBCB /* dydxRewardsSummaryPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxRewardsSummaryPresenter.swift; sourceTree = "<group>"; };
277E90322B1FAE9A005CCBCB /* dydxRewardsHelpViewBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxRewardsHelpViewBuilder.swift; sourceTree = "<group>"; };
277E90322B1FAE9A005CCBCB /* dydxRewardsHelpViewPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxRewardsHelpViewPresenter.swift; sourceTree = "<group>"; };
277E908A2B2118AE005CCBCB /* dydxRewardsHistoryViewPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxRewardsHistoryViewPresenter.swift; sourceTree = "<group>"; };
27C027522AFD761300E92CCB /* dydxSettingsHelpRowViewPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxSettingsHelpRowViewPresenter.swift; sourceTree = "<group>"; };
27DB2EA22AC1E7B20047BC39 /* dydxTradeRestrictedViewPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxTradeRestrictedViewPresenter.swift; sourceTree = "<group>"; };
64487FFE2AA248340068DD87 /* dydxAlertsWorker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = dydxAlertsWorker.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1297,7 +1299,8 @@
isa = PBXGroup;
children = (
277E90182B1EA3C3005CCBCB /* dydxRewardsSummaryPresenter.swift */,
277E90322B1FAE9A005CCBCB /* dydxRewardsHelpViewBuilder.swift */,
277E90322B1FAE9A005CCBCB /* dydxRewardsHelpViewPresenter.swift */,
277E908A2B2118AE005CCBCB /* dydxRewardsHistoryViewPresenter.swift */,
);
path = Components;
sourceTree = "<group>";
Expand Down Expand Up @@ -1772,6 +1775,7 @@
0262F2D529DB4891009889E2 /* WalletAction.swift in Sources */,
023789ED28BD381C00F212E1 /* dydxPresenters.docc in Sources */,
0258B9E72991BC900098E1BE /* dydxNewsAlertsViewBuilder.swift in Sources */,
277E908B2B2118AE005CCBCB /* dydxRewardsHistoryViewPresenter.swift in Sources */,
0230376F28C11BE600412B72 /* dydxMarketsViewBuilder.swift in Sources */,
270BA8F32A6F278F009212EA /* dydxDebugThemeViewerBuilder.swift in Sources */,
02669B952AD87A9D00A756AA /* dydxGlobalWorkers.swift in Sources */,
Expand Down Expand Up @@ -1812,7 +1816,7 @@
02A565AF2A5E310B0035469F /* dydxAlertsProvider.swift in Sources */,
025841F428EE9DE8007338D3 /* dydxAssetItemChartViewPresenter.swift in Sources */,
02860A9F29C15E760079E644 /* dydxOnboardScanViewBuilder.swift in Sources */,
277E90332B1FAE9A005CCBCB /* dydxRewardsHelpViewBuilder.swift in Sources */,
277E90332B1FAE9A005CCBCB /* dydxRewardsHelpViewPresenter.swift in Sources */,
02FAFA5C29D4E08E001A0903 /* dydxDebugViewBuilder.swift in Sources */,
02F700FE29EA0FD9004DEB5E /* dydxReceiptPresenter.swift in Sources */,
027E1EF829CA27CD0098666F /* dydxSettingsLandingViewBuilder.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// dydxRewardsHelpViewBuilder.swift
// dydxRewardsHelpViewPresenter.swift
// dydxPresenters
//
// Created by Michael Maguire on 12/5/23.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//
// dydxRewardsHistoryViewPresenter.swift
// dydxPresenters
//
// Created by Michael Maguire on 12/6/23.
//

import dydxViews
import PlatformParticles
import ParticlesKit
import RoutingKit
import Utilities

public protocol dydxRewardsHistoryViewPresenterProtocol: HostedViewPresenterProtocol {
var viewModel: dydxRewardsHistoryViewModel? { get }
}

public class dydxRewardsHistoryViewPresenter: HostedViewPresenter<dydxRewardsHistoryViewModel>, dydxRewardsHistoryViewPresenterProtocol {

enum Period: CaseIterable {
case monthly
case weekly
case daily

var text: String? {
switch self {
case .monthly: return DataLocalizer.shared?.localize(path: "APP.GENERAL.TIME_STRINGS.MONTHLY", params: nil)
case .weekly: return DataLocalizer.shared?.localize(path: "APP.GENERAL.TIME_STRINGS.WEEKLY", params: nil)
case .daily: return DataLocalizer.shared?.localize(path: "APP.GENERAL.TIME_STRINGS.DAILY", params: nil)
}
}
}

override init() {
super.init()

viewModel = dydxRewardsHistoryViewModel()

viewModel?.filters = Period.allCases.compactMap { period in
guard let text = period.text else { return nil }
return .text(text)
}

viewModel?.onSelectionChanged = { index in
let period = Period.allCases[index]
// TODO filter abacus results by period
// Router.shared?.navigate(to: .init(url: ...), animated: true, completion: nil)
}

// TODO get todos from abacus
viewModel?.items = [
.init(period: "period 1 -> period 2", amount: "1.000"),
.init(period: "period 2 -> period 3", amount: "2.000"),
.init(period: "period 3 -> period 4", amount: "3.000"),
.init(period: "period 4 -> period 5", amount: "4.000"),
.init(period: "period 5 -> period 6", amount: "5.000"),
.init(period: "period 6 -> period 7", amount: "6.000"),
.init(period: "period 7 -> period 8", amount: "7.000"),
.init(period: "period 8 -> period 9", amount: "8.000"),
.init(period: "period 9 -> period 10", amount: "9.000"),
.init(period: "period 10 -> period 11", amount: "10.000"),
.init(period: "period 11 -> period 12", amount: "11.000"),
.init(period: "period 12 -> period 2", amount: "1.000"),
.init(period: "period 13 -> period 3", amount: "2.000"),
.init(period: "period 14 -> period 4", amount: "3.000"),
.init(period: "period 15 -> period 5", amount: "4.000"),
.init(period: "period 16 -> period 6", amount: "5.000"),
.init(period: "period 17 -> period 7", amount: "6.000"),
.init(period: "period 18 -> period 8", amount: "7.000"),
.init(period: "period 19 -> period 9", amount: "8.000"),
.init(period: "period 20 -> period 10", amount: "9.000"),
.init(period: "period 21 -> period 11", amount: "10.000"),
.init(period: "period 22 -> period 3", amount: "2.000"),
.init(period: "period 23 -> period 4", amount: "3.000"),
.init(period: "period 24 -> period 5", amount: "4.000"),
.init(period: "period 25 -> period 6", amount: "5.000"),
.init(period: "period 26 -> period 7", amount: "6.000"),
.init(period: "period 27 -> period 8", amount: "7.000"),
.init(period: "period 28 -> period 9", amount: "8.000"),
.init(period: "period 29 -> period 10", amount: "9.000")
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ private protocol dydxTradingRewardsViewPresenterProtocol: HostedViewPresenterPro
private class dydxTradingRewardsViewPresenter: HostedViewPresenter<dydxTradingRewardsViewModel>, dydxTradingRewardsViewPresenterProtocol {

private let helpPresenter = dydxRewardsHelpViewPresenter()
private let historyPresenter = dydxRewardsHistoryViewPresenter()

override init() {
super.init()
Expand All @@ -46,6 +47,11 @@ private class dydxTradingRewardsViewPresenter: HostedViewPresenter<dydxTradingRe
}

helpPresenter.$viewModel.assign(to: &viewModel.$help)
historyPresenter.$viewModel.assign(to: &viewModel.$history)

historyPresenter.viewModel?.contentChanged = { [weak self] in
self?.viewModel?.objectWillChange.send()
}

self.viewModel = viewModel
}
Expand Down
Loading

0 comments on commit 937606f

Please sign in to comment.