Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MOB-601 : Position Card Updates #206

Merged
merged 6 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class dydxMarketPositionViewPresenter: HostedViewPresenter<dydxMarketPositionVie
viewModel?.logoUrl = sharedOrderViewModel.logoUrl
viewModel?.gradientType = sharedOrderViewModel.gradientType

viewModel?.amount = dydxFormatter.shared.dollar(number: position.valueTotal.current?.doubleValue, digits: 2)
viewModel?.amount = dydxFormatter.shared.dollar(number: position.notionalTotal.current?.doubleValue, digits: 2)

viewModel?.openPrice = dydxFormatter.shared.dollar(number: position.entryPrice.current?.doubleValue, digits: configs.displayTickSizeDecimals?.intValue ?? 0)
viewModel?.closePrice = dydxFormatter.shared.dollar(number: position.exitPrice?.doubleValue, digits: configs.displayTickSizeDecimals?.intValue ?? 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ class dydxPortfolioPositionsViewPresenter: HostedViewPresenter<dydxPortfolioPosi
let item = positionsCache?[position.assetId] ?? dydxPortfolioPositionItemViewModel()

let positionSize = abs(position.size.current?.doubleValue ?? 0)
let notionalValue = abs(position.notionalTotal.current?.doubleValue ?? 0)
item.size = dydxFormatter.shared.localFormatted(number: positionSize, digits: configs.displayStepSizeDecimals?.intValue ?? 1)
item.notionalValue = dydxFormatter.shared.dollar(number: notionalValue, digits: 2) ?? "--"
item.token?.symbol = asset.id

if position.resources.indicator.current == "long" {
Expand All @@ -136,7 +138,11 @@ class dydxPortfolioPositionsViewPresenter: HostedViewPresenter<dydxPortfolioPosi
}

item.indexPrice = dydxFormatter.shared.dollar(number: market.oraclePrice, digits: configs.displayTickSizeDecimals?.intValue ?? 0)
item.entryPrice = dydxFormatter.shared.dollar(number: position.entryPrice.current, digits: configs.displayTickSizeDecimals?.intValue ?? 0)
if let liquidationPrice = position.liquidationPrice.current {
item.liquidationPrice = dydxFormatter.shared.dollar(number: liquidationPrice, digits: configs.displayTickSizeDecimals?.intValue ?? 0)
} else {
item.liquidationPrice = DataLocalizer.localize(path: "APP.GENERAL.NONE")
}

item.unrealizedPnl = SignedAmountViewModel(amount: position.unrealizedPnl.current?.doubleValue ?? 0, displayType: .dollar, coloringOption: .allText)
item.unrealizedPnlPercent = dydxFormatter.shared.percent(number: position.unrealizedPnlPercent.current?.doubleValue, digits: 2) ?? ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,16 @@ final class dydxTradeReceiptPresenter: dydxReceiptPresenter {
AbacusStateManager.shared.state.selectedSubaccountPositions,
AbacusStateManager.shared.state.marketMap)
.sink { [weak self] input, positions, marketMap in
if let tradeSummary = input.summary,
let marketId = input.marketId,
let market = marketMap[marketId],
let position = positions.first(where: { $0.id == marketId }) {
self?.updateExpectedPrice(tradeSummary: tradeSummary, market: market)
self?.updateLiquidationPrice(position: position, market: market)
self?.updatePositionMargin(position: position)
self?.updatePositionLeverage(position: position)
self?.updateTradingFee(tradeSummary: tradeSummary)
self?.updateTradingRewards(tradeSummary: tradeSummary)
}
let tradeSummary = input.summary
let marketId = input.marketId
let market = marketMap[marketId ?? ""]
let position = positions.first(where: { $0.id == marketId })
self?.updateExpectedPrice(tradeSummary: tradeSummary, market: market)
self?.updateLiquidationPrice(position: position, market: market)
self?.updatePositionMargin(position: position)
self?.updatePositionLeverage(position: position)
self?.updateTradingFee(tradeSummary: tradeSummary)
self?.updateTradingRewards(tradeSummary: tradeSummary)
Comment on lines +46 to +55
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this change ensures the initial (empty) state loads

despite null values, we still want to display the receipt line titles

}
.store(in: &subscriptions)

Expand Down Expand Up @@ -85,16 +84,16 @@ final class dydxTradeReceiptPresenter: dydxReceiptPresenter {
}
}

private func updateExpectedPrice(tradeSummary: TradeInputSummary?, market: PerpetualMarket) {
let value = dydxFormatter.shared.dollar(number: tradeSummary?.price?.doubleValue, digits: market.configs?.displayTickSizeDecimals?.intValue ?? 0)
private func updateExpectedPrice(tradeSummary: TradeInputSummary?, market: PerpetualMarket?) {
let value = dydxFormatter.shared.dollar(number: tradeSummary?.price?.doubleValue, digits: market?.configs?.displayTickSizeDecimals?.intValue ?? 2)
expectedPriceViewModel.title = DataLocalizer.localize(path: "APP.TRADE.EXPECTED_PRICE")
expectedPriceViewModel.value = value
}

private func updateLiquidationPrice(position: SubaccountPosition?, market: PerpetualMarket) {
private func updateLiquidationPrice(position: SubaccountPosition?, market: PerpetualMarket?) {
let title = DataLocalizer.localize(path: "APP.TRADE.LIQUIDATION_PRICE_SHORT")
let unit = AmountTextModel.Unit.dollar
let tickSize = market.configs?.displayTickSizeDecimals?.intValue.asNsNumber
let tickSize = market?.configs?.displayTickSizeDecimals?.intValue.asNsNumber ?? 2
liquidationPriceViewModel.title = title
liquidationPriceViewModel.value = createAmountChangeViewModel(title: title, tradeState: position?.liquidationPrice, tickSize: tickSize, unit: unit)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ public class dydxPortfolioPositionItemViewModel: PlatformViewModel {
}

public init(size: String? = nil,
notionalValue: String? = nil,
token: TokenTextViewModel? = TokenTextViewModel(),
sideText: SideTextViewModel = SideTextViewModel(),
leverage: String? = nil,
leverageIcon: LeverageRiskModel? = nil,
liquidationPrice: String? = nil,
indexPrice: String? = nil,
entryPrice: String? = nil,
unrealizedPnl: SignedAmountViewModel? = nil,
Expand All @@ -38,25 +40,27 @@ public class dydxPortfolioPositionItemViewModel: PlatformViewModel {
onTapAction: (() -> Void)? = nil,
onMarginEditAction: (() -> Void)? = nil) {
self.size = size
self.notionalValue = notionalValue
self.token = token
self.sideText = sideText
self.leverage = leverage
self.leverageIcon = leverageIcon
self.liquidationPrice = liquidationPrice
self.indexPrice = indexPrice
self.entryPrice = entryPrice
self.unrealizedPnlPercent = "10%"
self.gradientType = gradientType
self.logoUrl = logoUrl
self.handler = Handler(onTapAction: onTapAction, onMarginEditAction: onMarginEditAction)
}

@Published public var size: String?
@Published public var notionalValue: String?
@Published public var token: TokenTextViewModel?
@Published public var sideText = SideTextViewModel()
@Published public var leverage: String?
@Published public var leverageIcon: LeverageRiskModel?
@Published public var liquidationPrice: String?
@Published public var indexPrice: String?
@Published public var entryPrice: String?
@Published public var unrealizedPnl: SignedAmountViewModel?
@Published public var unrealizedPnlPercent: String = ""
@Published public var marginValue: String = "--"
Expand All @@ -69,6 +73,7 @@ public class dydxPortfolioPositionItemViewModel: PlatformViewModel {
public static var previewValue: dydxPortfolioPositionItemViewModel {
let item = dydxPortfolioPositionItemViewModel(
size: "299",
notionalValue: "$420.69",
token: .previewValue,
sideText: .previewValue,
leverage: "0.01x",
Expand All @@ -94,13 +99,12 @@ public class dydxPortfolioPositionItemViewModel: PlatformViewModel {
}

return AnyView(
VStack {
VStack(spacing: 20) {
self.createTopView(parentStyle: style)
self.createBottomView(parentStyle: style)
}
.frame(height: 120)
.padding(.vertical, 12)
.padding(.horizontal, 8)
.padding(.vertical, 16)
.padding(.horizontal, 20)
.themeGradient(background: .layer3, gradientType: self.gradientType)
.cornerRadius(16)
.onTapGesture { [weak self] in
Expand All @@ -112,89 +116,90 @@ public class dydxPortfolioPositionItemViewModel: PlatformViewModel {
}

private func createTopView(parentStyle: ThemeStyle) -> some View {
let icon = self.createLogo(parentStyle: parentStyle)
let main = self.createMain(parentStyle: parentStyle)

return PlatformTableViewCellViewModel(logo: icon.wrappedViewModel,
main: main.wrappedViewModel)
.createView(parentStyle: parentStyle)
HStack(spacing: 0) {
createLogo(parentStyle: parentStyle)
Spacer(minLength: 8)
createTopRowStats(parentStyle: parentStyle)
}
}

private func createBottomView(parentStyle: ThemeStyle) -> some View {
GeometryReader { geo in
HStack(alignment: .top) {
SingleAxisGeometryReader(axis: .horizontal, alignment: .center) { width in
let numElements: CGFloat = 3.0
let spacing: CGFloat = 8
let elementWidth = max(0, (width - (numElements - 1) * spacing) / numElements)
return HStack(alignment: .top, spacing: 8) {
VStack(alignment: .leading, spacing: 4) {
Text(DataLocalizer.localize(path: "APP.GENERAL.INDEX_ENTRY"))
.themeFont(fontSize: .smaller)
.themeColor(foreground: .textTertiary)

Text(self.indexPrice ?? "")
.themeFont(fontSize: .small)
.themeColor(foreground: .textPrimary)
.minimumScaleFactor(0.5)

Text(self.entryPrice ?? "")
.themeFont(fontSize: .smaller)
.themeColor(foreground: .textTertiary)
.minimumScaleFactor(0.5)
Group {
Text(DataLocalizer.localize(path: "APP.GENERAL.LIQ_ORACLE"))
.themeFont(fontSize: .smaller)
.themeColor(foreground: .textTertiary)

Text(self.liquidationPrice ?? "")
.themeFont(fontSize: .small)
.themeColor(foreground: .textPrimary)

Text(self.indexPrice ?? "")
.themeFont(fontSize: .smaller)
.themeColor(foreground: .textTertiary)
}
.lineLimit(1)
.minimumScaleFactor(0.5)
.frame(width: elementWidth, alignment: .leading)
}
.leftAligned()
.frame(width: geo.size.width / 3)

VStack(alignment: .leading, spacing: 4) {
Text(DataLocalizer.localize(path: "APP.GENERAL.PROFIT_AND_LOSS"))
.themeFont(fontSize: .smaller)
.themeColor(foreground: .textTertiary)

self.unrealizedPnl?.createView(parentStyle: parentStyle.themeFont(fontType: .number, fontSize: .small))
Text(self.unrealizedPnlPercent)
.themeFont(fontSize: .smaller)
.themeColor(foreground: .textTertiary)
Group {
Text(DataLocalizer.localize(path: "APP.GENERAL.PROFIT_AND_LOSS"))
.themeFont(fontSize: .smaller)
.themeColor(foreground: .textTertiary)

self.unrealizedPnl?.createView(parentStyle: parentStyle.themeFont(fontType: .number, fontSize: .small))
Text(self.unrealizedPnlPercent)
.themeFont(fontSize: .smaller)
.themeColor(foreground: .textTertiary)
}
.frame(width: elementWidth, alignment: .leading)
}
.leftAligned()
.frame(width: geo.size.width / 3)

VStack(alignment: .leading, spacing: 4) {
Text(DataLocalizer.localize(path: "APP.GENERAL.MARGIN"))
.themeFont(fontSize: .smaller)
.themeColor(foreground: .textTertiary)

HStack {
VStack(alignment: .leading, spacing: 4) {
Text(self.marginValue)
.themeFont(fontSize: .small)
.themeColor(foreground: .textPrimary)
.minimumScaleFactor(0.5)

Text(self.marginMode)
.themeFont(fontSize: .smaller)
.themeColor(foreground: .textTertiary)
.minimumScaleFactor(0.5)
}

Spacer()

if self.isMarginAdjustable {
Group {
Text(DataLocalizer.localize(path: "APP.GENERAL.MARGIN"))
.themeFont(fontSize: .smaller)
.themeColor(foreground: .textTertiary)

HStack(spacing: 8) {
VStack(alignment: .leading, spacing: 4) {
Text(self.marginValue)
.themeFont(fontSize: .small)
.themeColor(foreground: .textPrimary)

Text(self.marginMode)
.themeFont(fontSize: .smaller)
.themeColor(foreground: .textTertiary)
}

let buttonContent = PlatformIconViewModel(type: .asset(name: "icon_edit", bundle: Bundle.dydxView),
size: CGSize(width: 20, height: 20),
templateColor: .textSecondary)
PlatformButtonViewModel(content: buttonContent,
type: PlatformButtonType.iconType) { [weak self] in
self?.handler?.onMarginEditAction?()
if self.isMarginAdjustable {

let buttonContent = PlatformIconViewModel(type: .asset(name: "icon_edit", bundle: Bundle.dydxView),
size: CGSize(width: 20, height: 20),
templateColor: .textSecondary)
PlatformButtonViewModel(content: buttonContent,
type: PlatformButtonType.iconType) { [weak self] in
self?.handler?.onMarginEditAction?()
}
.createView(parentStyle: parentStyle)
.frame(width: 32, height: 32)
.themeColor(background: .layer6)
.border(borderWidth: 1, cornerRadius: 7, borderColor: ThemeColor.SemanticColor.layer7.color)
}
.createView(parentStyle: parentStyle)
.frame(width: 32, height: 32)
.themeColor(background: .layer6)
.border(borderWidth: 1, cornerRadius: 7, borderColor: ThemeColor.SemanticColor.layer7.color)
}
}
.frame(width: elementWidth, alignment: .leading)
}
.leftAligned()
.frame(width: geo.size.width / 3)
}

}
.padding(.horizontal, 16)
}

private func createLogo( parentStyle: ThemeStyle) -> some View {
Expand All @@ -206,28 +211,33 @@ public class dydxPortfolioPositionItemViewModel: PlatformViewModel {
}
}

private func createMain(parentStyle: ThemeStyle) -> some View {
VStack(alignment: .leading, spacing: 0) {
HStack(spacing: 2) {
Text(size ?? "")
.themeFont(fontType: .number, fontSize: .small)

token?.createView(parentStyle: parentStyle.themeFont(fontSize: .smallest))
private func createTopRowStats(parentStyle: ThemeStyle) -> some View {
HStack(alignment: .top, spacing: 0) {
VStack(alignment: .leading, spacing: 2) {
HStack(spacing: 4) {
Text(size ?? "")
.themeFont(fontType: .base, fontSize: .small)
.themeColor(foreground: .textPrimary)
token?.createView(parentStyle: parentStyle.themeFont(fontSize: .smallest))
}
Text(notionalValue ?? "")
.themeFont(fontSize: .smaller)
.themeColor(foreground: .textTertiary)
}

HStack(spacing: 2) {
Spacer(minLength: 8)
HStack(alignment: .top, spacing: 2) {
sideText
.createView(parentStyle: parentStyle.themeFont(fontSize: .smaller))
Text("@")
.themeFont(fontSize: .smaller)
.themeColor(foreground: .textTertiary)

Text(leverage ?? "")
.themeFont(fontType: .number, fontSize: .smaller)
.themeFont(fontType: .base, fontSize: .smaller)
.themeColor(foreground: .textPrimary)
}
}
.leftAligned()
.minimumScaleFactor(0.5)
}
}

Expand Down Expand Up @@ -282,7 +292,6 @@ public class dydxPortfolioPositionsViewModel: PlatformViewModel {
.borderAndClip(style: .circle, borderColor: .borderDefault)
Spacer()
}
.padding(.horizontal, 16)
.frame(width: UIScreen.main.bounds.width - 32)
.themeFont(fontSize: .small)
.themeColor(foreground: .textTertiary)
Expand Down
Loading