Skip to content

Commit

Permalink
CLI-629: vault landing screen floating buttons & CLI-630: deposit/wit…
Browse files Browse the repository at this point in the history
…hdraw screen (#242)

* add withdraw/deposit buttons

* font size adjustment

* stubbed withdraw/deposit screen

* enabled/disabled button states/texts

---------

Co-authored-by: Mike <[email protected]>
  • Loading branch information
mike-dydx and mike-dydx authored Sep 9, 2024
1 parent 8cead70 commit ff58c8a
Show file tree
Hide file tree
Showing 11 changed files with 440 additions and 60 deletions.
12 changes: 12 additions & 0 deletions dydx/dydxPresenters/dydxPresenters.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@
277E90192B1EA3C3005CCBCB /* dydxRewardsSummaryPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277E90182B1EA3C3005CCBCB /* dydxRewardsSummaryPresenter.swift */; };
277E90332B1FAE9A005CCBCB /* dydxRewardsHelpViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277E90322B1FAE9A005CCBCB /* dydxRewardsHelpViewPresenter.swift */; };
277E908B2B2118AE005CCBCB /* dydxRewardsHistoryViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277E908A2B2118AE005CCBCB /* dydxRewardsHistoryViewPresenter.swift */; };
27823CF42C77E21A009BCD51 /* dydxVaultDepositWithdrawViewBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27823CF32C77E21A009BCD51 /* dydxVaultDepositWithdrawViewBuilder.swift */; };
278A4D1E2B8EA95A003898EB /* dydxCollectFeedbackActionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 278A4D1D2B8EA95A003898EB /* dydxCollectFeedbackActionBuilder.swift */; };
278A4D932B8FA5E8003898EB /* dydxRateAppViewBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 278A4D922B8FA5E8003898EB /* dydxRateAppViewBuilder.swift */; };
278A4DA42B8FDD9D003898EB /* dydxRatingsWorker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 278A4DA32B8FDD9D003898EB /* dydxRatingsWorker.swift */; };
Expand Down Expand Up @@ -540,6 +541,7 @@
277E90182B1EA3C3005CCBCB /* dydxRewardsSummaryPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxRewardsSummaryPresenter.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>"; };
27823CF32C77E21A009BCD51 /* dydxVaultDepositWithdrawViewBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxVaultDepositWithdrawViewBuilder.swift; sourceTree = "<group>"; };
278A4D1D2B8EA95A003898EB /* dydxCollectFeedbackActionBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxCollectFeedbackActionBuilder.swift; sourceTree = "<group>"; };
278A4D922B8FA5E8003898EB /* dydxRateAppViewBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxRateAppViewBuilder.swift; sourceTree = "<group>"; };
278A4DA32B8FDD9D003898EB /* dydxRatingsWorker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxRatingsWorker.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1423,6 +1425,7 @@
2751D6442C59642000B36F95 /* Vault */ = {
isa = PBXGroup;
children = (
27823D022C77E30F009BCD51 /* DepositsAndWithdrawals */,
2751D6452C59643800B36F95 /* dydxVaultViewBuilder.swift */,
);
path = Vault;
Expand All @@ -1448,6 +1451,14 @@
path = Components;
sourceTree = "<group>";
};
27823D022C77E30F009BCD51 /* DepositsAndWithdrawals */ = {
isa = PBXGroup;
children = (
27823CF32C77E21A009BCD51 /* dydxVaultDepositWithdrawViewBuilder.swift */,
);
path = DepositsAndWithdrawals;
sourceTree = "<group>";
};
278A4D912B8FA5C1003898EB /* Rating */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -2010,6 +2021,7 @@
0243A76129BE572C00A083FE /* dydxCancelOrderActionBuilder.swift in Sources */,
0279DE482BEBE76900F9ECF8 /* dydxTargetLeverageCtaButtonViewPresenter.swift in Sources */,
023AB3B22BEACE14005230B2 /* dydxTradeInputMarginViewPresenter.swift in Sources */,
27823CF42C77E21A009BCD51 /* dydxVaultDepositWithdrawViewBuilder.swift in Sources */,
64A4DB9929664818008D8E20 /* dydxTradeReceiptPresenter.swift in Sources */,
0236F0CB2968793A00EB995F /* dydxPortfolioFillsViewPresenter.swift in Sources */,
02A565AF2A5E310B0035469F /* dydxAlertsProvider.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,14 @@
"destination":"dydxPresenters.dydxVaultViewBuilder",
"presentation":"root"
},
"/vault/deposit":{
"destination":"dydxPresenters.dydxVaultDepositWithdrawViewBuilder",
"presentation":"prompt"
},
"/vault/withdraw":{
"destination":"dydxPresenters.dydxVaultDepositWithdrawViewBuilder",
"presentation":"prompt"
},
"/wallets":{
"destination":"dydxPresenters.Wallets2ViewBuilder",
"presentation":"half"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//
// dydxVaultDepositWithdrawViewBuilder.swift
// dydxPresenters
//
// Created by Michael Maguire on 8/22/24.
//

import Utilities
import dydxViews
import PlatformParticles
import RoutingKit
import ParticlesKit
import PlatformUI
import dydxStateManager
import FloatingPanel
import PlatformRouting
import dydxFormatter

public class dydxVaultDepositWithdrawViewBuilder: NSObject, ObjectBuilderProtocol {
public func build<T>() -> T? {
let presenter = dydxVaultDepositWithdrawViewPresenter()
let view = presenter.viewModel?.createView() ?? PlatformViewModel().createView()
let viewController = dydxVaultDepositWithdrawViewController(presenter: presenter, view: view, configuration: .default)
return viewController as? T
}
}

private class dydxVaultDepositWithdrawViewController: HostingViewController<PlatformView, dydxVaultDepositWithdrawViewModel> {

override public func arrive(to request: RoutingRequest?, animated: Bool) -> Bool {
let presenter = presenter as? dydxVaultDepositWithdrawViewPresenterProtocol
if request?.path == "/vault/deposit" {
presenter?.transferType = .deposit
return true
} else if request?.path == "/vault/withdraw" {
presenter?.transferType = .withdraw
return true
} else {
return false
}
}
}

private protocol dydxVaultDepositWithdrawViewPresenterProtocol: HostedViewPresenterProtocol {
var viewModel: dydxVaultDepositWithdrawViewModel? { get }
var transferType: VaultTransferType { get set }
}

private class dydxVaultDepositWithdrawViewPresenter: HostedViewPresenter<dydxVaultDepositWithdrawViewModel>, dydxVaultDepositWithdrawViewPresenterProtocol {
var transferType: VaultTransferType = .deposit

override init() {
let viewModel = dydxVaultDepositWithdrawViewModel(selectedTransferType: transferType, submitState: .disabled)

super.init()

self.viewModel = viewModel
}

override func start() {
super.start()

//TODO: replace with real hooks from abacus
update()
}

//TODO: replace with real data from abacus
func update() {
var newInputReceiptChangeItems = [dydxReceiptChangeItemView]()
var newButtonReceiptChangeItems = [dydxReceiptChangeItemView]()

newInputReceiptChangeItems.append(dydxReceiptChangeItemView(title: DataLocalizer.localize(path: "APP.VAULTS.YOUR_VAULT_BALANCE"),
value: AmountChangeModel(before: AmountTextModel(amount: 30.01),
after: AmountTextModel(amount: 30.02))))

newButtonReceiptChangeItems.append(.init(title: DataLocalizer.localize(path: "APP.GENERAL.CROSS_FREE_COLLATERAL"),
value: AmountChangeModel(before: AmountTextModel(amount: 30.01),
after: AmountTextModel(amount: 30.02))))

newButtonReceiptChangeItems.append(.init(title: DataLocalizer.localize(path: "APP.VAULTS.EST_SLIPPAGE"),
value: AmountChangeModel(before: AmountTextModel(amount: 30.01),
after: AmountTextModel(amount: 30.02))))

newButtonReceiptChangeItems.append(.init(title: DataLocalizer.localize(path: "APP.WITHDRAW_MODAL.EXPECTED_AMOUNT_RECEIVED"),
value: AmountChangeModel(before: AmountTextModel(amount: 30.01),
after: AmountTextModel(amount: 30.02))))

viewModel?.inputReceiptChangeItems = newInputReceiptChangeItems
viewModel?.buttonReceiptChangeItems = newButtonReceiptChangeItems

viewModel?.inputInlineAlert = InlineAlertViewModel(InlineAlertViewModel.Config.init(title: "test alert",
body: "test bodytest bodytest bodytest bodytest bodytest bodytest bodytest bodytest bodytest bodytest bodytest bodytest bodytest bodytest bodytest bodytest body",
level: .error))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import RoutingKit
import ParticlesKit
import PlatformUI
import Charts
import dydxStateManager

public class dydxVaultViewBuilder: NSObject, ObjectBuilderProtocol {
public func build<T>() -> T? {
Expand All @@ -40,11 +41,21 @@ private protocol dydxVaultViewBuilderPresenterProtocol: HostedViewPresenterProto
private class dydxVaultViewBuilderPresenter: HostedViewPresenter<dydxVaultViewModel>, dydxVaultViewBuilderPresenterProtocol {
override init() {
super.init()

viewModel = dydxVaultViewModel()
viewModel?.vaultChart = dydxVaultChartViewModel()

let usdcToken = AbacusStateManager.shared.environment?.usdcTokenInfo?.denom
AbacusStateManager.shared.state.accountBalance(of: usdcToken)
.sink {[weak self] usdcBalance in
if usdcBalance ?? 0 > 0 {
self?.viewModel?.depositAction = { Router.shared?.navigate(to: RoutingRequest(path: "/vault/withdraw"), animated: true, completion: nil) }
}
}
.store(in: &subscriptions)
viewModel?.depositAction = { Router.shared?.navigate(to: RoutingRequest(path: "/vault/deposit"), animated: true, completion: nil) }

// TODO: remove & replace, test only
//TODO: remove & replace, test only
Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { [weak self] _ in
guard let self = self else { return }
self.viewModel?.vaultChart?.setEntries(entries: self.generateEntries())
Expand Down
20 changes: 12 additions & 8 deletions dydx/dydxViews/dydxViews.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@
277E91082B2241C1005CCBCB /* dydxRewardsRewardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277E91072B2241C1005CCBCB /* dydxRewardsRewardView.swift */; };
277E914A2B23BB74005CCBCB /* dydxRewardsLearnMoreView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277E91492B23BB74005CCBCB /* dydxRewardsLearnMoreView.swift */; };
277E918B2B27762F005CCBCB /* dydxRewardsLaunchIncentivesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 277E918A2B27762F005CCBCB /* dydxRewardsLaunchIncentivesView.swift */; };
27823D132C77E38C009BCD51 /* dydxVaultDepositWithdrawViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27823D122C77E38C009BCD51 /* dydxVaultDepositWithdrawViewModel.swift */; };
278A4DA22B8FA609003898EB /* dydxRateAppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 278A4DA12B8FA609003898EB /* dydxRateAppView.swift */; };
27A799B92A66EC2D007C3D04 /* ThemeClassicDark.json in Resources */ = {isa = PBXBuildFile; fileRef = 27A799B82A66EC2D007C3D04 /* ThemeClassicDark.json */; };
27AAA9862ACE34C800AF3C56 /* SwiftMessages+Banner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27AAA9852ACE34C800AF3C56 /* SwiftMessages+Banner.swift */; };
Expand Down Expand Up @@ -573,6 +574,7 @@
277E91072B2241C1005CCBCB /* dydxRewardsRewardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxRewardsRewardView.swift; sourceTree = "<group>"; };
277E91492B23BB74005CCBCB /* dydxRewardsLearnMoreView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxRewardsLearnMoreView.swift; sourceTree = "<group>"; };
277E918A2B27762F005CCBCB /* dydxRewardsLaunchIncentivesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxRewardsLaunchIncentivesView.swift; sourceTree = "<group>"; };
27823D122C77E38C009BCD51 /* dydxVaultDepositWithdrawViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxVaultDepositWithdrawViewModel.swift; sourceTree = "<group>"; };
278A4DA12B8FA609003898EB /* dydxRateAppView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxRateAppView.swift; sourceTree = "<group>"; };
27A799B82A66EC2D007C3D04 /* ThemeClassicDark.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ThemeClassicDark.json; sourceTree = "<group>"; };
27AAA9852ACE34C800AF3C56 /* SwiftMessages+Banner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SwiftMessages+Banner.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1493,7 +1495,7 @@
2751D6472C59645000B36F95 /* Vault */ = {
isa = PBXGroup;
children = (
2751D6772C597BFC00B36F95 /* DepositsAndWithdrawals */,
27823D112C77E370009BCD51 /* DepositAndWithdrawal */,
2751D6762C597BEC00B36F95 /* Landing */,
);
path = Vault;
Expand All @@ -1510,13 +1512,6 @@
path = Landing;
sourceTree = "<group>";
};
2751D6772C597BFC00B36F95 /* DepositsAndWithdrawals */ = {
isa = PBXGroup;
children = (
);
path = DepositsAndWithdrawals;
sourceTree = "<group>";
};
277E8FF82B1EA083005CCBCB /* TradingRewards */ = {
isa = PBXGroup;
children = (
Expand All @@ -1541,6 +1536,14 @@
path = Components;
sourceTree = "<group>";
};
27823D112C77E370009BCD51 /* DepositAndWithdrawal */ = {
isa = PBXGroup;
children = (
27823D122C77E38C009BCD51 /* dydxVaultDepositWithdrawViewModel.swift */,
);
path = DepositAndWithdrawal;
sourceTree = "<group>";
};
278A4D942B8FA5F5003898EB /* Rating */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -2059,6 +2062,7 @@
0253155129BFA62700D6CC9B /* dydxOnboardScanInstructionsView.swift in Sources */,
27CDA3D42BBF1AD700FEAFFE /* dydxMultipleOrdersExistViewModel.swift in Sources */,
024B7B5C28B7F90100F7C386 /* dydxViewBundleClass.swift in Sources */,
27823D132C77E38C009BCD51 /* dydxVaultDepositWithdrawViewModel.swift in Sources */,
02A9B60C29005A3F00AE1516 /* AmountChange.swift in Sources */,
64A4DB5329662070008D8E20 /* dydxTradeInputSizeView.swift in Sources */,
02E318A82AB231FA0074DA98 /* PlaceholderView.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ private struct dydxSliderTextInput: View {
numberFormatter: viewModel.numberFormatter,
minValue: viewModel.minValue,
maxValue: viewModel.maxValue,
isMaxButtonVisible: false,
value: $viewModel.value)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import SwiftUI
import dydxFormatter
import PlatformUI
import Utilities

/// Effectively a TextField which forces its input as a number
/// Supports dydx-style title and title accesory view
Expand All @@ -17,6 +18,7 @@ struct dydxTitledNumberField: View {
let numberFormatter: dydxNumberInputFormatter
let minValue: Double
let maxValue: Double
let isMaxButtonVisible: Bool
@Binding var value: Double?
@State private var textWidth: CGFloat = 0

Expand Down Expand Up @@ -60,17 +62,36 @@ struct dydxTitledNumberField: View {
.truncationMode(.middle)
.frame(width: textWidth)
}

private var maxButton: some View {
let buttonContent = Text(DataLocalizer.localize(path: "APP.GENERAL.MAX"))
.themeFont(fontSize: .small)
.wrappedViewModel

return PlatformButtonViewModel(content: buttonContent, type: .pill, state: .secondary, action: {
PlatformView.hideKeyboard()
self.value = maxValue
})
.createView()

}

var body: some View {
VStack(alignment: .leading, spacing: 5) {
HStack(spacing: 5) {
titleView
accessoryTitleView
HStack(spacing: 0) {
VStack(alignment: .leading, spacing: 5) {
HStack(spacing: 5) {
titleView
accessoryTitleView
}
textFieldView
}
if isMaxButtonVisible {
Spacer()
maxButton
}
textFieldView
}
.padding(.vertical, 8)
.padding(.horizontal, 12)
.padding(.vertical, 12)
.padding(.horizontal, 16)
.makeInput()
}
}
Expand Down
Loading

0 comments on commit ff58c8a

Please sign in to comment.