From 7a3211c75c2c9560a046238d6e1db2605a631e30 Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Wed, 5 Jun 2024 16:27:23 -0400 Subject: [PATCH 01/16] hide/show target leverage for margin mode selection --- .../xcshareddata/swiftpm/Package.resolved | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved b/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved index 22de51701..dacd8494d 100644 --- a/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "975d00e29efb8d2ca017c5e61df90418ac01f7d7143e85a3f9ddb4eb982154e4", + "originHash" : "3cd7346cace16cf660f9c22302c5ca6770335c67902f3fd155011356a9d43929", "pins" : [ { "identity" : "bigint", @@ -37,15 +37,6 @@ "version" : "2.0.2" } }, - { - "identity" : "keyboardobserving", - "kind" : "remoteSourceControl", - "location" : "https://github.com/nickffox/KeyboardObserving", - "state" : { - "branch" : "master", - "revision" : "48134b5460435cc9d048223ad7560ee2e40f3d4a" - } - }, { "identity" : "percy-xcui-swift", "kind" : "remoteSourceControl", @@ -199,15 +190,6 @@ "version" : "9.0.9" } }, - { - "identity" : "swiftui-introspect", - "kind" : "remoteSourceControl", - "location" : "https://github.com/siteline/SwiftUI-Introspect.git", - "state" : { - "revision" : "121c146fe591b1320238d054ae35c81ffa45f45a", - "version" : "0.12.0" - } - }, { "identity" : "wallet-mobile-sdk", "kind" : "remoteSourceControl", From 01dc417d57befabef152058809c9364d891545e8 Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Fri, 7 Jun 2024 15:16:12 -0500 Subject: [PATCH 02/16] fix adjust margin % horizontal sizings --- .../xcshareddata/swiftpm/Package.resolved | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved b/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved index dacd8494d..22de51701 100644 --- a/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "3cd7346cace16cf660f9c22302c5ca6770335c67902f3fd155011356a9d43929", + "originHash" : "975d00e29efb8d2ca017c5e61df90418ac01f7d7143e85a3f9ddb4eb982154e4", "pins" : [ { "identity" : "bigint", @@ -37,6 +37,15 @@ "version" : "2.0.2" } }, + { + "identity" : "keyboardobserving", + "kind" : "remoteSourceControl", + "location" : "https://github.com/nickffox/KeyboardObserving", + "state" : { + "branch" : "master", + "revision" : "48134b5460435cc9d048223ad7560ee2e40f3d4a" + } + }, { "identity" : "percy-xcui-swift", "kind" : "remoteSourceControl", @@ -190,6 +199,15 @@ "version" : "9.0.9" } }, + { + "identity" : "swiftui-introspect", + "kind" : "remoteSourceControl", + "location" : "https://github.com/siteline/SwiftUI-Introspect.git", + "state" : { + "revision" : "121c146fe591b1320238d054ae35c81ffa45f45a", + "version" : "0.12.0" + } + }, { "identity" : "wallet-mobile-sdk", "kind" : "remoteSourceControl", From 256fb4123aee71f67088b483ebc3dbcdc0ede9c6 Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Tue, 11 Jun 2024 22:28:53 -0500 Subject: [PATCH 03/16] remove unused files --- .../xcshareddata/swiftpm/Package.resolved | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved b/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved index 22de51701..dacd8494d 100644 --- a/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "975d00e29efb8d2ca017c5e61df90418ac01f7d7143e85a3f9ddb4eb982154e4", + "originHash" : "3cd7346cace16cf660f9c22302c5ca6770335c67902f3fd155011356a9d43929", "pins" : [ { "identity" : "bigint", @@ -37,15 +37,6 @@ "version" : "2.0.2" } }, - { - "identity" : "keyboardobserving", - "kind" : "remoteSourceControl", - "location" : "https://github.com/nickffox/KeyboardObserving", - "state" : { - "branch" : "master", - "revision" : "48134b5460435cc9d048223ad7560ee2e40f3d4a" - } - }, { "identity" : "percy-xcui-swift", "kind" : "remoteSourceControl", @@ -199,15 +190,6 @@ "version" : "9.0.9" } }, - { - "identity" : "swiftui-introspect", - "kind" : "remoteSourceControl", - "location" : "https://github.com/siteline/SwiftUI-Introspect.git", - "state" : { - "revision" : "121c146fe591b1320238d054ae35c81ffa45f45a", - "version" : "0.12.0" - } - }, { "identity" : "wallet-mobile-sdk", "kind" : "remoteSourceControl", From 6b67beede6ea0627e112c44806e8cd5352d33114 Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Wed, 12 Jun 2024 11:13:16 -0500 Subject: [PATCH 04/16] dismiss on success, update button state on submission --- .../xcshareddata/swiftpm/Package.resolved | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved b/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved index dacd8494d..22de51701 100644 --- a/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "3cd7346cace16cf660f9c22302c5ca6770335c67902f3fd155011356a9d43929", + "originHash" : "975d00e29efb8d2ca017c5e61df90418ac01f7d7143e85a3f9ddb4eb982154e4", "pins" : [ { "identity" : "bigint", @@ -37,6 +37,15 @@ "version" : "2.0.2" } }, + { + "identity" : "keyboardobserving", + "kind" : "remoteSourceControl", + "location" : "https://github.com/nickffox/KeyboardObserving", + "state" : { + "branch" : "master", + "revision" : "48134b5460435cc9d048223ad7560ee2e40f3d4a" + } + }, { "identity" : "percy-xcui-swift", "kind" : "remoteSourceControl", @@ -190,6 +199,15 @@ "version" : "9.0.9" } }, + { + "identity" : "swiftui-introspect", + "kind" : "remoteSourceControl", + "location" : "https://github.com/siteline/SwiftUI-Introspect.git", + "state" : { + "revision" : "121c146fe591b1320238d054ae35c81ffa45f45a", + "version" : "0.12.0" + } + }, { "identity" : "wallet-mobile-sdk", "kind" : "remoteSourceControl", From 809983cbdfa6706e3933208b8bdf9bf605a5ef66 Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Wed, 12 Jun 2024 16:50:03 -0500 Subject: [PATCH 05/16] multi-line receipt line item title --- dydx/dydxViews/dydxViews/Shared/BeforeArrowAfter.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dydx/dydxViews/dydxViews/Shared/BeforeArrowAfter.swift b/dydx/dydxViews/dydxViews/Shared/BeforeArrowAfter.swift index 6bc2d458e..c352d8020 100644 --- a/dydx/dydxViews/dydxViews/Shared/BeforeArrowAfter.swift +++ b/dydx/dydxViews/dydxViews/Shared/BeforeArrowAfter.swift @@ -55,7 +55,7 @@ public class BeforeArrowAfterModel: PlatformViewModel, .createView(parentStyle: style.themeColor(foreground: .textPrimary), styleKey: nil) } } - .fixedSize() + ) } } From 9377c165f026038d280b58c268ea958386fc55a0 Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Wed, 12 Jun 2024 16:50:27 -0500 Subject: [PATCH 06/16] use localized error --- .../_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift | 2 +- dydx/dydxStateManager/dydxStateManager/Models+Ext.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift b/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift index 63dc6c234..ecf44660d 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift @@ -89,7 +89,7 @@ private class dydxAdjustMarginInputViewPresenter: HostedViewPresenter Date: Wed, 12 Jun 2024 18:04:32 -0500 Subject: [PATCH 07/16] stubbed unopened isolated positions UI --- .../dydxPortfolioPositionsViewPresenter.swift | 7 +- .../dydxViews.xcodeproj/project.pbxproj | 4 + .../Sections/dydxPortfolioPositionsView.swift | 113 +++++++++++++---- ...openedIsolatedPositionsItemViewModel.swift | 116 ++++++++++++++++++ 4 files changed, 210 insertions(+), 30 deletions(-) create mode 100644 dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/Portfolio/Components/dydxPortfolioPositionsViewPresenter.swift b/dydx/dydxPresenters/dydxPresenters/_v4/Portfolio/Components/dydxPortfolioPositionsViewPresenter.swift index c54fcb50b..29b4e9df7 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/Portfolio/Components/dydxPortfolioPositionsViewPresenter.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/Portfolio/Components/dydxPortfolioPositionsViewPresenter.swift @@ -37,9 +37,9 @@ class dydxPortfolioPositionsViewPresenter: HostedViewPresenter dydxPortfolioPositionItemViewModel? { diff --git a/dydx/dydxViews/dydxViews.xcodeproj/project.pbxproj b/dydx/dydxViews/dydxViews.xcodeproj/project.pbxproj index 17ffee214..ab7b82f7e 100644 --- a/dydx/dydxViews/dydxViews.xcodeproj/project.pbxproj +++ b/dydx/dydxViews/dydxViews.xcodeproj/project.pbxproj @@ -195,6 +195,7 @@ 27C027452AFD734800E92CCB /* dydxSettingsHelpRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27C027442AFD734800E92CCB /* dydxSettingsHelpRowView.swift */; }; 27C6E4C92BC8C30E00ED892A /* dydxCustomLimitPriceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27C6E4BC2BC8C30E00ED892A /* dydxCustomLimitPriceViewModel.swift */; }; 27CDA3D42BBF1AD700FEAFFE /* dydxMultipleOrdersExistViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27CDA3D32BBF1AD700FEAFFE /* dydxMultipleOrdersExistViewModel.swift */; }; + 27E072D22C1A095C0034B963 /* dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27E072D12C1A095C0034B963 /* dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift */; }; 27ED340C2AD47CB100C159F5 /* dydxBannerErrorAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27ED340B2AD47CB100C159F5 /* dydxBannerErrorAlert.swift */; }; 27ED365C2AD735A800C159F5 /* dydxSecurityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27ED365B2AD735A800C159F5 /* dydxSecurityView.swift */; }; 27F624112BBD9FEB00AB6D1A /* dydxPriceInputViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F624042BBD9FEB00AB6D1A /* dydxPriceInputViewModel.swift */; }; @@ -565,6 +566,7 @@ 27C027442AFD734800E92CCB /* dydxSettingsHelpRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxSettingsHelpRowView.swift; sourceTree = ""; }; 27C6E4BC2BC8C30E00ED892A /* dydxCustomLimitPriceViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = dydxCustomLimitPriceViewModel.swift; sourceTree = ""; }; 27CDA3D32BBF1AD700FEAFFE /* dydxMultipleOrdersExistViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxMultipleOrdersExistViewModel.swift; sourceTree = ""; }; + 27E072D12C1A095C0034B963 /* dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift; sourceTree = ""; }; 27ED340B2AD47CB100C159F5 /* dydxBannerErrorAlert.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = dydxBannerErrorAlert.swift; sourceTree = ""; }; 27ED365B2AD735A800C159F5 /* dydxSecurityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxSecurityView.swift; sourceTree = ""; }; 27F624042BBD9FEB00AB6D1A /* dydxPriceInputViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = dydxPriceInputViewModel.swift; sourceTree = ""; }; @@ -1141,6 +1143,7 @@ 02678FA329666BD800EE346B /* dydxPortfolioPositionsView.swift */, 02678FA529666BE600EE346B /* dydxPortfolioOrdersView.swift */, 024F488D2965C91D00E40247 /* dydxPortfolioChartView.swift */, + 27E072D12C1A095C0034B963 /* dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift */, ); path = Sections; sourceTree = ""; @@ -2011,6 +2014,7 @@ 029CBE7728F608F400259C1D /* dydxMarketTradesView.swift in Sources */, 0238FC46296DA53F002E1C1A /* dydxOrderDetailsView.swift in Sources */, 2769090E2AAFD8030075B2D6 /* TransferInstanceViewModel.swift in Sources */, + 27E072D22C1A095C0034B963 /* dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift in Sources */, 024FEB642ACB75E10087A55E /* dydxFeesStuctureView.swift in Sources */, 277E918B2B27762F005CCBCB /* dydxRewardsLaunchIncentivesView.swift in Sources */, 0268BBF92A8BE08C00D0C59B /* dydxTransferOutView.swift in Sources */, diff --git a/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift b/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift index d22bf32b5..b1b3a4655 100644 --- a/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift +++ b/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift @@ -319,41 +319,47 @@ public class dydxPortfolioPositionItemViewModel: PlatformViewModel { } } -public class dydxPortfolioPositionsViewModel: PlatformListViewModel { +public class dydxPortfolioPositionsViewModel: PlatformViewModel { // TODO: remove once isolated markets is supported and force released @Published public var shouldDisplayIsolatedPositionsWarning: Bool = false - @Published public var placeholderText: String? - - public override var placeholder: PlatformViewModel? { - let vm = PlaceholderViewModel() - vm.text = placeholderText - return vm + @Published public var emptyText: String? + @Published public var positionItems: [dydxPortfolioPositionItemViewModel] { + didSet { + contentChanged?() + } + } + @Published public var unopenedIsolatedPositionItems: [dydxPortfolioUnopenedIsolatedPositionsItemViewModel] { + didSet { + contentChanged?() + } } - public override init(items: [PlatformViewModel] = [], - intraItemSeparator: Bool = false, - firstListItemTopSeparator: Bool = false, - lastListItemBottomSeparator: Bool = false, - contentChanged: (() -> Void)? = nil) { - super.init(items: items, - intraItemSeparator: intraItemSeparator, - firstListItemTopSeparator: firstListItemTopSeparator, - lastListItemBottomSeparator: lastListItemBottomSeparator, - contentChanged: contentChanged) - self.width = UIScreen.main.bounds.width - 32 + public var contentChanged: (() -> Void)? + + init( + positionItems: [dydxPortfolioPositionItemViewModel] = [], + unopenedIsolatedPositionItems: [dydxPortfolioUnopenedIsolatedPositionsItemViewModel] = [], + emptyText: String? = nil + ) { + self.positionItems = positionItems + self.unopenedIsolatedPositionItems = unopenedIsolatedPositionItems + self.emptyText = emptyText } public static var previewValue: dydxPortfolioPositionsViewModel { - let vm = dydxPortfolioPositionsViewModel {} - vm.items = [ - dydxPortfolioPositionItemViewModel.previewValue, - dydxPortfolioPositionItemViewModel.previewValue - ] - return vm + dydxPortfolioPositionsViewModel( + positionItems: [ + .previewValue, + .previewValue + ], + unopenedIsolatedPositionItems: [ + .previewValue + ], + emptyText: "empty") } - public override var header: PlatformViewModel? { - guard dydxBoolFeatureFlag.enable_isolated_margins.isEnabled == false, !items.isEmpty else { return nil } + public var positionsHeader: PlatformViewModel? { + guard dydxBoolFeatureFlag.enable_isolated_margins.isEnabled == false, !positionItems.isEmpty else { return nil } return HStack { Text(DataLocalizer.localize(path: "APP.GENERAL.DETAILS")) Spacer() @@ -371,7 +377,7 @@ public class dydxPortfolioPositionsViewModel: PlatformListViewModel { .wrappedViewModel } - public override var footer: PlatformViewModel? { + public var positionsFooter: PlatformViewModel? { guard shouldDisplayIsolatedPositionsWarning && !dydxBoolFeatureFlag.enable_isolated_margins.isEnabled else { return nil } return Text(localizerPathKey: "APP.GENERAL.ISOLATED_POSITIONS_COMING_SOON") .multilineTextAlignment(.center) @@ -382,6 +388,59 @@ public class dydxPortfolioPositionsViewModel: PlatformListViewModel { .padding(.bottom, 16) .wrappedViewModel } + + public var unopenedIsolatedPositionsHeader: PlatformViewModel? { + guard dydxBoolFeatureFlag.enable_isolated_margins.isEnabled == true, !unopenedIsolatedPositionItems.isEmpty else { return nil } + return HStack(spacing: 8) { + Text(localizerPathKey: "APP.TRADE.UNOPENED_ISOLATED_POSITIONS") + .themeFont(fontSize: .larger) + .themeColor(foreground: .textPrimary) + .fixedSize() + Text("\(unopenedIsolatedPositionItems.count)") + .frame(width: 28, height: 28) + .borderAndClip(style: .circle, borderColor: .borderDefault) + Spacer() + } + .padding(.horizontal, 16) + .themeFont(fontSize: .small) + .themeColor(foreground: .textTertiary) + .wrappedViewModel + } + + public override func createView(parentStyle: ThemeStyle = ThemeStyle.defaultStyle, styleKey: String? = nil) -> PlatformView { + PlatformView(viewModel: self, parentStyle: parentStyle, styleKey: styleKey) { [weak self] style in + guard let self = self else { return AnyView(PlatformView.nilView) } + + if let emptyText = self.emptyText, positionItems.isEmpty, unopenedIsolatedPositionItems.isEmpty { + return AnyView( + PlaceholderViewModel(text: emptyText) + .createView(parentStyle: style) + ) + } + + let items = self.positionItems.map { $0.createView(parentStyle: style) } + let unopenedItems = self.unopenedIsolatedPositionItems.map { $0.createView(parentStyle: style) } + + return AnyView( + ScrollView { + LazyVStack { + self.positionsHeader?.createView(parentStyle: style) + + ForEach(items.indices, id: \.self) { index in + items[index] + } + + self.positionsFooter?.createView(parentStyle: style) + self.unopenedIsolatedPositionsHeader?.createView(parentStyle: style) + + ForEach(unopenedItems.indices, id: \.self) { index in + unopenedItems[index] + } + } + } + ) + } + } } #if DEBUG diff --git a/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift b/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift new file mode 100644 index 000000000..483df291b --- /dev/null +++ b/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift @@ -0,0 +1,116 @@ +// +// dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift +// dydxUI +// +// Created by Michael Maguire on 6/12/24. +// Copyright © 2024 dYdX Trading Inc. All rights reserved. +// + +import PlatformUI +import SwiftUI + +public class dydxPortfolioUnopenedIsolatedPositionsItemViewModel: PlatformViewModel { + @Published public var marketLogoUrl: URL? + @Published public var marketName: String + @Published public var margin: String + @Published public var viewOrdersAction: (() -> Void) + @Published public var cancelOrdersAction: (() -> Void) + + public init(marketLogoUrl: URL? = nil, + marketName: String, + margin: String, + viewOrdersAction: @escaping () -> Void, + cancelOrdersAction: @escaping () -> Void) { + self.marketLogoUrl = marketLogoUrl + self.marketName = marketName + self.margin = margin + self.viewOrdersAction = viewOrdersAction + self.cancelOrdersAction = cancelOrdersAction + } + + public static var previewValue: dydxPortfolioUnopenedIsolatedPositionsItemViewModel = { + .init(marketLogoUrl: URL(string: "https://v4.testnet.dydx.exchange/currencies/eth.png"), + marketName: "ETH-USD", + margin: "$1000.00", + viewOrdersAction: {}, + cancelOrdersAction: {} + ) + }() + + private var topContent: some View { + VStack(spacing: 8) { + HStack(spacing: 8) { + PlatformIconViewModel(type: .url(url: marketLogoUrl), + clip: .defaultCircle, + size: CGSize(width: 20, height: 20)) + .createView() + Text(marketName) + .themeFont(fontSize: .small) + .themeColor(foreground: .textSecondary) + Spacer() + } + HStack(spacing: 0) { + Text(localizerPathKey: "APP.GENERAL.MARGIN") + .themeFont(fontSize: .smaller) + .themeColor(foreground: .textTertiary) + Spacer() + Text(margin) + .themeFont(fontSize: .smaller) + .themeColor(foreground: .textSecondary) + } + } + .padding(.vertical, 10) + } + + private var divider: some View { + Divider() + .overlay(ThemeColor.SemanticColor.borderDefault.color) + } + + private var bottomContent: some View { + let viewOrders = Text(localizerPathKey: "APP.CLOSE_POSITIONS_CONFIRMATION_TOAST.VIEW_ORDERS") + .themeFont(fontSize: .smaller) + .themeColor(foreground: .colorPurple) + .padding(.vertical, 8) + let cancel = Text(localizerPathKey: "APP.GENERAL.CANCEL") + .themeFont(fontSize: .smaller) + .themeColor(foreground: .colorRed) + .padding(.vertical, 8) + return HStack(spacing: 0) { + Button(action: viewOrdersAction, label: { viewOrders }) + Spacer() + Button(action: cancelOrdersAction, label: { cancel }) + } + } + + public override func createView(parentStyle: ThemeStyle = ThemeStyle.defaultStyle, styleKey: String? = nil) -> PlatformView { + PlatformView(viewModel: self, parentStyle: parentStyle, styleKey: styleKey) { [weak self] _ in + guard let self = self else { return AnyView(PlatformView.nilView) } + + return VStack(spacing: 0) { + self.topContent + self.divider + self.bottomContent + } + .padding(.horizontal, 12) + .themeColor(background: .layer3) + .clipShape(.rect(cornerRadius: 10)) + .wrappedInAnyView() + } + } +} + +#if DEBUG +struct dydxPortfolioUnopenedIsolatedPositionsItemView_Previews: PreviewProvider { + @StateObject static var themeSettings = ThemeSettings.shared + + static var previews: some View { + Group { + dydxPortfolioUnopenedIsolatedPositionsItemViewModel.previewValue + .createView() + .environmentObject(themeSettings) + .previewLayout(.sizeThatFits) + } + } +} +#endif From 7a3bf311fa5611d6a2463d068bc51d0843138f6f Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Thu, 13 Jun 2024 14:59:12 -0500 Subject: [PATCH 08/16] wire up abacus data for unopened positions --- .../dydxMarketPositionViewPresenter.swift | 2 +- .../dydxPortfolioPositionsViewPresenter.swift | 70 ++++++++++++++++--- .../AbacusState+Combine.swift | 11 +++ .../dydxViews.xcodeproj/project.pbxproj | 8 +-- ...tfolioPendingPositionsItemViewModel.swift} | 31 +++++--- .../Sections/dydxPortfolioPositionsView.swift | 43 +++++++----- 6 files changed, 126 insertions(+), 39 deletions(-) rename dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/{dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift => dydxPortfolioPendingPositionsItemViewModel.swift} (77%) diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/MarketInfo/Components/dydxMarketPositionViewPresenter.swift b/dydx/dydxPresenters/dydxPresenters/_v4/MarketInfo/Components/dydxMarketPositionViewPresenter.swift index 4644bf1c2..a18781b1f 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/MarketInfo/Components/dydxMarketPositionViewPresenter.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/MarketInfo/Components/dydxMarketPositionViewPresenter.swift @@ -50,7 +50,7 @@ class dydxMarketPositionViewPresenter: HostedViewPresenter, dydxPortfolioPositionsViewPresenterProtocol { - private var cache = [String: dydxPortfolioPositionItemViewModel]() + private var positionsCache = [String: dydxPortfolioPositionItemViewModel]() + private var pendingPositionsCache = [String: dydxPortfolioPendingPositionsItemViewModel]() init(viewModel: dydxPortfolioPositionsViewModel?) { super.init() @@ -45,33 +46,86 @@ class dydxPortfolioPositionsViewPresenter: HostedViewPresenter dydxPortfolioPositionItemViewModel? in - let item = Self.createViewModelItem(position: position, marketMap: marketMap, assetMap: assetMap, cache: cache) - cache[position.assetId] = item + let item = Self.createPositionViewModelItem(position: position, + marketMap: marketMap, + assetMap: assetMap, + positionsCache: positionsCache) + positionsCache[position.assetId] = item return item } self.viewModel?.positionItems = items - self.viewModel?.unopenedIsolatedPositionItems = [.previewValue, .previewValue, .previewValue] } - static func createViewModelItem(position: SubaccountPosition, marketMap: [String: PerpetualMarket], assetMap: [String: Asset], cache: [String: dydxPortfolioPositionItemViewModel]? = nil) -> dydxPortfolioPositionItemViewModel? { + private func updatePendingPositions(pendingPositions: [SubaccountPendingPosition], marketMap: [String: PerpetualMarket], assetMap: [String: Asset]) { + let items: [dydxPortfolioPendingPositionsItemViewModel] = pendingPositions.compactMap { pendingPosition -> dydxPortfolioPendingPositionsItemViewModel? in + let item = Self.createPendingPositionsViewModelItem(pendingPosition: pendingPosition, + marketMap: marketMap, + assetMap: assetMap, + pendingPositionsCache: pendingPositionsCache) + pendingPositionsCache[pendingPosition.assetId] = item + return item + } + + self.viewModel?.pendingPositionItems = items + } + + static func createPendingPositionsViewModelItem( + pendingPosition: SubaccountPendingPosition, + marketMap: [String: PerpetualMarket], + assetMap: [String: Asset], + pendingPositionsCache: [String: dydxPortfolioPendingPositionsItemViewModel]? = nil + ) -> dydxPortfolioPendingPositionsItemViewModel? { + + guard let market = marketMap[pendingPosition.marketId], + let configs = market.configs, + let asset = assetMap[pendingPosition.assetId], + let margin = pendingPosition.equity?.current?.doubleValue, + margin != 0, + let marginFormatted = dydxFormatter.shared.dollar(number: margin, digits: 2) + else { + return nil + } + + let viewOrdersAction: () -> Void = { + Router.shared?.navigate(to: RoutingRequest(path: "/market", + params: ["market": market.id, + "currentSection": "positions"]), + animated: true, + completion: nil) + } + let cancelOrdersAction: () -> Void = { + Router.shared?.navigate(to: RoutingRequest(path: "/trade/markets", params: ["market": market.id]), animated: true, completion: nil) + } + + return dydxPortfolioPendingPositionsItemViewModel(marketLogoUrl: URL(string: asset.resources?.imageUrl ?? ""), + marketName: asset.name!, + margin: marginFormatted, + orderCount: pendingPosition.orderCount, + viewOrdersAction: viewOrdersAction, + cancelOrdersAction: cancelOrdersAction) + } + + static func createPositionViewModelItem(position: SubaccountPosition, marketMap: [String: PerpetualMarket], assetMap: [String: Asset], positionsCache: [String: dydxPortfolioPositionItemViewModel]? = nil) -> dydxPortfolioPositionItemViewModel? { guard let market = marketMap[position.id], let configs = market.configs, let asset = assetMap[position.assetId], (position.size.current?.doubleValue ?? 0) != 0 else { return nil } - let item = cache?[position.assetId] ?? dydxPortfolioPositionItemViewModel() + let item = positionsCache?[position.assetId] ?? dydxPortfolioPositionItemViewModel() let positionSize = abs(position.size.current?.doubleValue ?? 0) item.size = dydxFormatter.shared.localFormatted(number: positionSize, digits: configs.displayStepSizeDecimals?.intValue ?? 1) diff --git a/dydx/dydxStateManager/dydxStateManager/AbacusState+Combine.swift b/dydx/dydxStateManager/dydxStateManager/AbacusState+Combine.swift index b5406a923..aadc83895 100644 --- a/dydx/dydxStateManager/dydxStateManager/AbacusState+Combine.swift +++ b/dydx/dydxStateManager/dydxStateManager/AbacusState+Combine.swift @@ -221,6 +221,17 @@ public final class AbacusState { .eraseToAnyPublisher() } + public var selectedSubaccountPendingPositions: AnyPublisher<[SubaccountPendingPosition], Never> { + selectedSubaccount + .compactMap { subaccount in + subaccount?.pendingPositions + } + .prepend([]) + .removeDuplicates() + .share() + .eraseToAnyPublisher() + } + public var selectedSubaccountOrders: AnyPublisher<[SubaccountOrder], Never> { selectedSubaccount .compactMap { subaccount in diff --git a/dydx/dydxViews/dydxViews.xcodeproj/project.pbxproj b/dydx/dydxViews/dydxViews.xcodeproj/project.pbxproj index ab7b82f7e..eb4109129 100644 --- a/dydx/dydxViews/dydxViews.xcodeproj/project.pbxproj +++ b/dydx/dydxViews/dydxViews.xcodeproj/project.pbxproj @@ -195,7 +195,7 @@ 27C027452AFD734800E92CCB /* dydxSettingsHelpRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27C027442AFD734800E92CCB /* dydxSettingsHelpRowView.swift */; }; 27C6E4C92BC8C30E00ED892A /* dydxCustomLimitPriceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27C6E4BC2BC8C30E00ED892A /* dydxCustomLimitPriceViewModel.swift */; }; 27CDA3D42BBF1AD700FEAFFE /* dydxMultipleOrdersExistViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27CDA3D32BBF1AD700FEAFFE /* dydxMultipleOrdersExistViewModel.swift */; }; - 27E072D22C1A095C0034B963 /* dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27E072D12C1A095C0034B963 /* dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift */; }; + 27E072D22C1A095C0034B963 /* dydxPortfolioPendingPositionsItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27E072D12C1A095C0034B963 /* dydxPortfolioPendingPositionsItemViewModel.swift */; }; 27ED340C2AD47CB100C159F5 /* dydxBannerErrorAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27ED340B2AD47CB100C159F5 /* dydxBannerErrorAlert.swift */; }; 27ED365C2AD735A800C159F5 /* dydxSecurityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27ED365B2AD735A800C159F5 /* dydxSecurityView.swift */; }; 27F624112BBD9FEB00AB6D1A /* dydxPriceInputViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27F624042BBD9FEB00AB6D1A /* dydxPriceInputViewModel.swift */; }; @@ -566,7 +566,7 @@ 27C027442AFD734800E92CCB /* dydxSettingsHelpRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxSettingsHelpRowView.swift; sourceTree = ""; }; 27C6E4BC2BC8C30E00ED892A /* dydxCustomLimitPriceViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = dydxCustomLimitPriceViewModel.swift; sourceTree = ""; }; 27CDA3D32BBF1AD700FEAFFE /* dydxMultipleOrdersExistViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxMultipleOrdersExistViewModel.swift; sourceTree = ""; }; - 27E072D12C1A095C0034B963 /* dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift; sourceTree = ""; }; + 27E072D12C1A095C0034B963 /* dydxPortfolioPendingPositionsItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxPortfolioPendingPositionsItemViewModel.swift; sourceTree = ""; }; 27ED340B2AD47CB100C159F5 /* dydxBannerErrorAlert.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = dydxBannerErrorAlert.swift; sourceTree = ""; }; 27ED365B2AD735A800C159F5 /* dydxSecurityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxSecurityView.swift; sourceTree = ""; }; 27F624042BBD9FEB00AB6D1A /* dydxPriceInputViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = dydxPriceInputViewModel.swift; sourceTree = ""; }; @@ -1143,7 +1143,7 @@ 02678FA329666BD800EE346B /* dydxPortfolioPositionsView.swift */, 02678FA529666BE600EE346B /* dydxPortfolioOrdersView.swift */, 024F488D2965C91D00E40247 /* dydxPortfolioChartView.swift */, - 27E072D12C1A095C0034B963 /* dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift */, + 27E072D12C1A095C0034B963 /* dydxPortfolioPendingPositionsItemViewModel.swift */, ); path = Sections; sourceTree = ""; @@ -2014,7 +2014,7 @@ 029CBE7728F608F400259C1D /* dydxMarketTradesView.swift in Sources */, 0238FC46296DA53F002E1C1A /* dydxOrderDetailsView.swift in Sources */, 2769090E2AAFD8030075B2D6 /* TransferInstanceViewModel.swift in Sources */, - 27E072D22C1A095C0034B963 /* dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift in Sources */, + 27E072D22C1A095C0034B963 /* dydxPortfolioPendingPositionsItemViewModel.swift in Sources */, 024FEB642ACB75E10087A55E /* dydxFeesStuctureView.swift in Sources */, 277E918B2B27762F005CCBCB /* dydxRewardsLaunchIncentivesView.swift in Sources */, 0268BBF92A8BE08C00D0C59B /* dydxTransferOutView.swift in Sources */, diff --git a/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift b/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPendingPositionsItemViewModel.swift similarity index 77% rename from dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift rename to dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPendingPositionsItemViewModel.swift index 483df291b..656c44335 100644 --- a/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift +++ b/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPendingPositionsItemViewModel.swift @@ -1,5 +1,5 @@ // -// dydxPortfolioUnopenedIsolatedPositionsItemViewModel.swift +// dydxPortfolioPendingPositionsItemViewModel.swift // dydxUI // // Created by Michael Maguire on 6/12/24. @@ -8,30 +8,35 @@ import PlatformUI import SwiftUI +import Utilities -public class dydxPortfolioUnopenedIsolatedPositionsItemViewModel: PlatformViewModel { +public class dydxPortfolioPendingPositionsItemViewModel: PlatformViewModel { @Published public var marketLogoUrl: URL? @Published public var marketName: String @Published public var margin: String + @Published public var orderCount: Int32 @Published public var viewOrdersAction: (() -> Void) @Published public var cancelOrdersAction: (() -> Void) - public init(marketLogoUrl: URL? = nil, + public init(marketLogoUrl: URL?, marketName: String, margin: String, + orderCount: Int32, viewOrdersAction: @escaping () -> Void, cancelOrdersAction: @escaping () -> Void) { self.marketLogoUrl = marketLogoUrl self.marketName = marketName self.margin = margin + self.orderCount = orderCount self.viewOrdersAction = viewOrdersAction self.cancelOrdersAction = cancelOrdersAction } - public static var previewValue: dydxPortfolioUnopenedIsolatedPositionsItemViewModel = { + public static var previewValue: dydxPortfolioPendingPositionsItemViewModel = { .init(marketLogoUrl: URL(string: "https://v4.testnet.dydx.exchange/currencies/eth.png"), marketName: "ETH-USD", margin: "$1000.00", + orderCount: 2, viewOrdersAction: {}, cancelOrdersAction: {} ) @@ -63,12 +68,22 @@ public class dydxPortfolioUnopenedIsolatedPositionsItemViewModel: PlatformViewMo } private var divider: some View { - Divider() + Spacer(minLength: 1) .overlay(ThemeColor.SemanticColor.borderDefault.color) } private var bottomContent: some View { - let viewOrders = Text(localizerPathKey: "APP.CLOSE_POSITIONS_CONFIRMATION_TOAST.VIEW_ORDERS") + let viewOrdersStringKey: String + let viewOrdersStringParams: [String: String]? + if orderCount > 1 { + viewOrdersStringKey = "APP.GENERAL.VIEW_ORDER" + viewOrdersStringParams = nil + } else { + viewOrdersStringKey = "APP.GENERAL.VIEW_ORDERS_COUNT" + viewOrdersStringParams = ["NUM_ORDERS": "\(orderCount)"] + } + + let viewOrders = Text(localizerPathKey: viewOrdersStringKey, params: viewOrdersStringParams) .themeFont(fontSize: .smaller) .themeColor(foreground: .colorPurple) .padding(.vertical, 8) @@ -101,12 +116,12 @@ public class dydxPortfolioUnopenedIsolatedPositionsItemViewModel: PlatformViewMo } #if DEBUG -struct dydxPortfolioUnopenedIsolatedPositionsItemView_Previews: PreviewProvider { +struct dydxPortfolioPendingPositionsItemView_Previews: PreviewProvider { @StateObject static var themeSettings = ThemeSettings.shared static var previews: some View { Group { - dydxPortfolioUnopenedIsolatedPositionsItemViewModel.previewValue + dydxPortfolioPendingPositionsItemViewModel.previewValue .createView() .environmentObject(themeSettings) .previewLayout(.sizeThatFits) diff --git a/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift b/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift index b1b3a4655..adea59873 100644 --- a/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift +++ b/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift @@ -328,7 +328,7 @@ public class dydxPortfolioPositionsViewModel: PlatformViewModel { contentChanged?() } } - @Published public var unopenedIsolatedPositionItems: [dydxPortfolioUnopenedIsolatedPositionsItemViewModel] { + @Published public var pendingPositionItems: [dydxPortfolioPendingPositionsItemViewModel] { didSet { contentChanged?() } @@ -338,11 +338,11 @@ public class dydxPortfolioPositionsViewModel: PlatformViewModel { init( positionItems: [dydxPortfolioPositionItemViewModel] = [], - unopenedIsolatedPositionItems: [dydxPortfolioUnopenedIsolatedPositionsItemViewModel] = [], + pendingPositionItems: [dydxPortfolioPendingPositionsItemViewModel] = [], emptyText: String? = nil ) { self.positionItems = positionItems - self.unopenedIsolatedPositionItems = unopenedIsolatedPositionItems + self.pendingPositionItems = pendingPositionItems self.emptyText = emptyText } @@ -352,7 +352,7 @@ public class dydxPortfolioPositionsViewModel: PlatformViewModel { .previewValue, .previewValue ], - unopenedIsolatedPositionItems: [ + pendingPositionItems: [ .previewValue ], emptyText: "empty") @@ -389,15 +389,16 @@ public class dydxPortfolioPositionsViewModel: PlatformViewModel { .wrappedViewModel } - public var unopenedIsolatedPositionsHeader: PlatformViewModel? { - guard dydxBoolFeatureFlag.enable_isolated_margins.isEnabled == true, !unopenedIsolatedPositionItems.isEmpty else { return nil } + public var pendingPositionsHeader: PlatformViewModel? { + guard dydxBoolFeatureFlag.enable_isolated_margins.isEnabled == true, !pendingPositionItems.isEmpty else { return nil } return HStack(spacing: 8) { Text(localizerPathKey: "APP.TRADE.UNOPENED_ISOLATED_POSITIONS") .themeFont(fontSize: .larger) .themeColor(foreground: .textPrimary) .fixedSize() - Text("\(unopenedIsolatedPositionItems.count)") + Text("\(pendingPositionItems.count)") .frame(width: 28, height: 28) + .themeColor(background: .layer6) .borderAndClip(style: .circle, borderColor: .borderDefault) Spacer() } @@ -411,7 +412,7 @@ public class dydxPortfolioPositionsViewModel: PlatformViewModel { PlatformView(viewModel: self, parentStyle: parentStyle, styleKey: styleKey) { [weak self] style in guard let self = self else { return AnyView(PlatformView.nilView) } - if let emptyText = self.emptyText, positionItems.isEmpty, unopenedIsolatedPositionItems.isEmpty { + if let emptyText = self.emptyText, positionItems.isEmpty, pendingPositionItems.isEmpty { return AnyView( PlaceholderViewModel(text: emptyText) .createView(parentStyle: style) @@ -419,22 +420,28 @@ public class dydxPortfolioPositionsViewModel: PlatformViewModel { } let items = self.positionItems.map { $0.createView(parentStyle: style) } - let unopenedItems = self.unopenedIsolatedPositionItems.map { $0.createView(parentStyle: style) } + let unopenedItems = self.pendingPositionItems.map { $0.createView(parentStyle: style) } return AnyView( ScrollView { - LazyVStack { - self.positionsHeader?.createView(parentStyle: style) + VStack(spacing: 24) { + LazyVStack { + self.positionsHeader?.createView(parentStyle: style) - ForEach(items.indices, id: \.self) { index in - items[index] - } + ForEach(items.indices, id: \.self) { index in + items[index] + } - self.positionsFooter?.createView(parentStyle: style) - self.unopenedIsolatedPositionsHeader?.createView(parentStyle: style) + self.positionsFooter?.createView(parentStyle: style) + } + if dydxBoolFeatureFlag.enable_isolated_margins.isEnabled { + LazyVStack { + self.pendingPositionsHeader?.createView(parentStyle: style) - ForEach(unopenedItems.indices, id: \.self) { index in - unopenedItems[index] + ForEach(unopenedItems.indices, id: \.self) { index in + unopenedItems[index] + } + } } } } From a7c34cd80cf37b66670f989da1d25d5425758f2d Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Thu, 13 Jun 2024 16:52:45 -0500 Subject: [PATCH 09/16] put back fixed size, clean up --- .../dydxViews/Shared/BeforeArrowAfter.swift | 2 +- .../Sections/dydxPortfolioPositionsView.swift | 49 +++++++++++-------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/dydx/dydxViews/dydxViews/Shared/BeforeArrowAfter.swift b/dydx/dydxViews/dydxViews/Shared/BeforeArrowAfter.swift index c352d8020..95554887e 100644 --- a/dydx/dydxViews/dydxViews/Shared/BeforeArrowAfter.swift +++ b/dydx/dydxViews/dydxViews/Shared/BeforeArrowAfter.swift @@ -55,7 +55,7 @@ public class BeforeArrowAfterModel: PlatformViewModel, .createView(parentStyle: style.themeColor(foreground: .textPrimary), styleKey: nil) } } - + .fixedSize() ) } } diff --git a/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift b/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift index adea59873..4a51d5fab 100644 --- a/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift +++ b/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift @@ -408,6 +408,32 @@ public class dydxPortfolioPositionsViewModel: PlatformViewModel { .wrappedViewModel } + private var openPositionsView: some View { + LazyVStack { + let items = self.positionItems.map { $0.createView() } + self.positionsHeader?.createView() + + ForEach(items.indices, id: \.self) { index in + items[index] + } + + self.positionsFooter?.createView() + } + } + + private var pendingPositionsView: AnyView? { + guard dydxBoolFeatureFlag.enable_isolated_margins.isEnabled else { return nil } + let unopenedItems = self.pendingPositionItems.map { $0.createView() } + return LazyVStack { + self.pendingPositionsHeader?.createView() + + ForEach(unopenedItems.indices, id: \.self) { index in + unopenedItems[index] + } + } + .wrappedInAnyView() + } + public override func createView(parentStyle: ThemeStyle = ThemeStyle.defaultStyle, styleKey: String? = nil) -> PlatformView { PlatformView(viewModel: self, parentStyle: parentStyle, styleKey: styleKey) { [weak self] style in guard let self = self else { return AnyView(PlatformView.nilView) } @@ -419,30 +445,11 @@ public class dydxPortfolioPositionsViewModel: PlatformViewModel { ) } - let items = self.positionItems.map { $0.createView(parentStyle: style) } - let unopenedItems = self.pendingPositionItems.map { $0.createView(parentStyle: style) } - return AnyView( ScrollView { VStack(spacing: 24) { - LazyVStack { - self.positionsHeader?.createView(parentStyle: style) - - ForEach(items.indices, id: \.self) { index in - items[index] - } - - self.positionsFooter?.createView(parentStyle: style) - } - if dydxBoolFeatureFlag.enable_isolated_margins.isEnabled { - LazyVStack { - self.pendingPositionsHeader?.createView(parentStyle: style) - - ForEach(unopenedItems.indices, id: \.self) { index in - unopenedItems[index] - } - } - } + self.openPositionsView + self.pendingPositionsView } } ) From 53f769563a35aa194b6491c75108fc85f3aa8c6b Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Fri, 14 Jun 2024 13:53:13 -0500 Subject: [PATCH 10/16] hide keyboard when margin direction changes --- .../Margin/Components/dydxAdjustMarginDirectionView.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dydx/dydxViews/dydxViews/_v4/Trade/Margin/Components/dydxAdjustMarginDirectionView.swift b/dydx/dydxViews/dydxViews/_v4/Trade/Margin/Components/dydxAdjustMarginDirectionView.swift index 22829dee4..96391a746 100644 --- a/dydx/dydxViews/dydxViews/_v4/Trade/Margin/Components/dydxAdjustMarginDirectionView.swift +++ b/dydx/dydxViews/dydxViews/_v4/Trade/Margin/Components/dydxAdjustMarginDirectionView.swift @@ -65,7 +65,8 @@ public class dydxAdjustMarginDirectionViewModel: PlatformViewModel { selectedItems: selectedItems, currentSelection: self.marginDirection.index, onSelectionChanged: { index in - self.marginDirectionAction?(MarginDirection(index: index)) + PlatformView.hideKeyboard() + self.marginDirectionAction?(MarginDirection(index: index)) }) .createView(parentStyle: style) } From 65bfd3b9a4aa19e85da5e131573957987bc4f0a3 Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Fri, 14 Jun 2024 13:53:57 -0500 Subject: [PATCH 11/16] remove max action --- .../dydxAdjustMarginInputViewBuilder.swift | 3 - .../dydxViews.xcodeproj/project.pbxproj | 4 - .../dydxAdjustMarginAmountView.swift | 82 ------------------- .../Margin/dydxAdjustMarginInputView.swift | 9 +- 4 files changed, 5 insertions(+), 93 deletions(-) delete mode 100644 dydx/dydxViews/dydxViews/_v4/Trade/Margin/Components/dydxAdjustMarginAmountView.swift diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift b/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift index ecf44660d..87dc35abb 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift @@ -80,9 +80,6 @@ private class dydxAdjustMarginInputViewPresenter: HostedViewPresenter Void)? - - public override var inputType: PlatformTextInputViewModel.InputType { .decimalDigits } - - public static var previewValue: dydxAdjustMarginAmountViewModel { - let vm = dydxAdjustMarginAmountViewModel() - vm.label = "Amount" - vm.placeHolder = "0.0" - return vm - } - - public override func createView(parentStyle: ThemeStyle = ThemeStyle.defaultStyle, styleKey: String? = nil) -> PlatformView { - let superView = super.createView(parentStyle: parentStyle, styleKey: styleKey) - return PlatformView { style in - let view = HStack { - superView - - let buttonContent = Text(DataLocalizer.localize(path: "APP.GENERAL.MAX")) - .themeFont(fontSize: .medium) - .wrappedViewModel - - PlatformButtonViewModel(content: buttonContent, type: .pill, state: .secondary, action: { [weak self] in - - PlatformView.hideKeyboard() - self?.maxAction?() - - }) - .createView(parentStyle: style) - .padding(.trailing, 8) - } - .makeInput() - - return AnyView(view) - } - } - -} - -#if DEBUG -struct dydxAdjustMarginAmountView_Previews_Dark: PreviewProvider { - @StateObject static var themeSettings = ThemeSettings.shared - - static var previews: some View { - ThemeSettings.applyDarkTheme() - ThemeSettings.applyStyles() - return dydxAdjustMarginAmountViewModel.previewValue - .createView() - .themeColor(background: .layer0) - .environmentObject(themeSettings) - // .edgesIgnoringSafeArea(.bottom) - .previewLayout(.sizeThatFits) - } -} - -struct dydxAdjustMarginAmountView_Previews_Light: PreviewProvider { - @StateObject static var themeSettings = ThemeSettings.shared - - static var previews: some View { - ThemeSettings.applyLightTheme() - ThemeSettings.applyStyles() - return dydxAdjustMarginAmountViewModel.previewValue - .createView() - .themeColor(background: .layer0) - .environmentObject(themeSettings) - // .edgesIgnoringSafeArea(.bottom) - .previewLayout(.sizeThatFits) - } -} -#endif diff --git a/dydx/dydxViews/dydxViews/_v4/Trade/Margin/dydxAdjustMarginInputView.swift b/dydx/dydxViews/dydxViews/_v4/Trade/Margin/dydxAdjustMarginInputView.swift index 1d272e5c1..76d456a45 100644 --- a/dydx/dydxViews/dydxViews/_v4/Trade/Margin/dydxAdjustMarginInputView.swift +++ b/dydx/dydxViews/dydxViews/_v4/Trade/Margin/dydxAdjustMarginInputView.swift @@ -15,10 +15,10 @@ public class dydxAdjustMarginInputViewModel: PlatformViewModel { @Published public var sharedMarketViewModel: SharedMarketViewModel? = SharedMarketViewModel() @Published public var marginDirection: dydxAdjustMarginDirectionViewModel? = dydxAdjustMarginDirectionViewModel() @Published public var marginPercentage: dydxAdjustMarginPercentageViewModel? = dydxAdjustMarginPercentageViewModel() - @Published public var amount: dydxAdjustMarginAmountViewModel? = dydxAdjustMarginAmountViewModel() + @Published public var amount: PlatformTextInputViewModel? = PlatformTextInputViewModel(inputType: .decimalDigits) @Published public var amountReceipt: dydxAdjustMarginReceiptViewModel? = dydxAdjustMarginReceiptViewModel() @Published public var liquidationPrice: dydxAdjustMarginLiquidationPriceViewModel? = dydxAdjustMarginLiquidationPriceViewModel() - @Published public var submissionError: InlineAlertViewModel? + @Published public var inlineAlert: InlineAlertViewModel? @Published public var buttonReceipt: dydxAdjustMarginReceiptViewModel? = dydxAdjustMarginReceiptViewModel() @Published public var ctaButton: dydxAdjustMarginCtaButtonViewModel? = dydxAdjustMarginCtaButtonViewModel() @Published public var shouldDisplayCrossFirst: Bool = true @@ -33,7 +33,7 @@ public class dydxAdjustMarginInputViewModel: PlatformViewModel { let vm = dydxAdjustMarginInputViewModel() vm.marginPercentage = .previewValue vm.marginDirection = .previewValue - vm.amount = .previewValue + vm.amount = .init() vm.amountReceipt = .previewValue vm.liquidationPrice = .previewValue vm.buttonReceipt = .previewValue @@ -57,11 +57,12 @@ public class dydxAdjustMarginInputViewModel: PlatformViewModel { ZStack(alignment: .top) { self.amountReceipt?.createView(parentStyle: style) self.amount?.createView(parentStyle: style) + .makeInput() .frame(height: 64) } self.liquidationPrice?.createView(parentStyle: style) - self.submissionError?.createView(parentStyle: style) + self.inlineAlert?.createView(parentStyle: style) Spacer() } From 2f1ec61302095d913e5d766ebf2fff3a0e2c5fac Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Fri, 14 Jun 2024 13:54:29 -0500 Subject: [PATCH 12/16] add local validation --- .../xcshareddata/swiftpm/Package.resolved | 20 +---- .../dydxAdjustMarginInputViewBuilder.swift | 78 +++++++++++++++---- .../dydxReceiptChangeItemView.swift | 2 +- 3 files changed, 67 insertions(+), 33 deletions(-) diff --git a/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved b/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved index 22de51701..dacd8494d 100644 --- a/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "975d00e29efb8d2ca017c5e61df90418ac01f7d7143e85a3f9ddb4eb982154e4", + "originHash" : "3cd7346cace16cf660f9c22302c5ca6770335c67902f3fd155011356a9d43929", "pins" : [ { "identity" : "bigint", @@ -37,15 +37,6 @@ "version" : "2.0.2" } }, - { - "identity" : "keyboardobserving", - "kind" : "remoteSourceControl", - "location" : "https://github.com/nickffox/KeyboardObserving", - "state" : { - "branch" : "master", - "revision" : "48134b5460435cc9d048223ad7560ee2e40f3d4a" - } - }, { "identity" : "percy-xcui-swift", "kind" : "remoteSourceControl", @@ -199,15 +190,6 @@ "version" : "9.0.9" } }, - { - "identity" : "swiftui-introspect", - "kind" : "remoteSourceControl", - "location" : "https://github.com/siteline/SwiftUI-Introspect.git", - "state" : { - "revision" : "121c146fe591b1320238d054ae35c81ffa45f45a", - "version" : "0.12.0" - } - }, { "identity" : "wallet-mobile-sdk", "kind" : "remoteSourceControl", diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift b/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift index 87dc35abb..78f3d5094 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift @@ -86,7 +86,7 @@ private class dydxAdjustMarginInputViewPresenter: HostedViewPresenter String? { + guard let amount = parser.asNumber(input.amount)?.doubleValue else { return nil } + switch input.type { + case IsolatedMarginAdjustmentType.add: + if let crossFreeCollateral = input.summary?.crossFreeCollateral?.doubleValue, amount >= crossFreeCollateral { + return "ERRORS.TRANSFER_MODAL.TRANSFER_MORE_THAN_FREE" + } + if let crossMarginUsageUpdated = input.summary?.crossMarginUsageUpdated?.doubleValue, crossMarginUsageUpdated > 1 { + return "ERRORS.TRADE_BOX.INVALID_NEW_ACCOUNT_MARGIN_USAGE" + } + case IsolatedMarginAdjustmentType.remove: + if let freeCollateral = input.summary?.crossFreeCollateral?.doubleValue, amount >= freeCollateral { + return "ERRORS.TRANSFER_MODAL.TRANSFER_MORE_THAN_FREE" + } + if let positionMarginUpdated = input.summary?.positionMarginUpdated?.doubleValue, positionMarginUpdated < 0 { + return "ERRORS.TRADE_BOX.INVALID_NEW_ACCOUNT_MARGIN_USAGE" + } + if let effectiveInitialMarginFraction = market.configs?.effectiveInitialMarginFraction?.doubleValue, effectiveInitialMarginFraction > 0 { + let marketMaxLeverage = 1 / effectiveInitialMarginFraction + if let positionLeverageUpdated = input.summary?.positionLeverageUpdated?.doubleValue, positionLeverageUpdated > marketMaxLeverage { + return "ERRORS.TRADE_BOX_TITLE.INVALID_NEW_POSITION_LEVERAGE" + } + } + default: + break + } + + return nil + } + + private func clearPostValues() { + for receipt in [viewModel?.amountReceipt, viewModel?.buttonReceipt] { + for item in receipt?.receiptChangeItems ?? [] { + item.value.after = nil + } + } + } + + private func updatePrePostValues(input: AdjustIsolatedMarginInput, market: PerpetualMarket) { var crossReceiptItems = [dydxReceiptChangeItemView]() var positionReceiptItems = [dydxReceiptChangeItemView]() + if let errorStringKey = validate(input: input, market: market) { + clearPostValues() + viewModel?.inlineAlert = InlineAlertViewModel(InlineAlertViewModel.Config( + title: nil, + body: DataLocalizer.localize(path: errorStringKey), + level: .error)) + return + } + + viewModel?.inlineAlert = nil + let crossFreeCollateral: AmountTextModel = .init(amount: input.summary?.crossFreeCollateral, unit: .dollar) let crossFreeCollateralUpdated: AmountTextModel = .init(amount: input.summary?.crossFreeCollateralUpdated, unit: .dollar) let crossFreeCollateralChange: AmountChangeModel = .init( before: crossFreeCollateral.amount != nil ? crossFreeCollateral : nil, - after: crossFreeCollateralUpdated.amount != nil ? crossFreeCollateralUpdated : nil) + // client-side validation, cross free collateral should never be negative + after: crossFreeCollateralUpdated.amount?.doubleValue ?? 0 > 0 ? crossFreeCollateralUpdated : nil) crossReceiptItems.append( dydxReceiptChangeItemView( title: DataLocalizer.localize(path: "APP.GENERAL.CROSS_FREE_COLLATERAL"), @@ -164,7 +212,8 @@ private class dydxAdjustMarginInputViewPresenter: HostedViewPresenter 0 ? crossMarginUsageUpdated : nil) crossReceiptItems.append( dydxReceiptChangeItemView( title: DataLocalizer.localize(path: "APP.GENERAL.CROSS_MARGIN_USAGE"), @@ -174,7 +223,8 @@ private class dydxAdjustMarginInputViewPresenter: HostedViewPresenter 0 ? positionMarginUpdated : nil) positionReceiptItems.append( dydxReceiptChangeItemView( title: DataLocalizer.localize(path: "APP.TRADE.POSITION_MARGIN"), @@ -182,9 +232,11 @@ private class dydxAdjustMarginInputViewPresenter: HostedViewPresenter 0 && positionLeverageUpdatedDouble < 1000 ? positionLeverageUpdated : nil) positionReceiptItems.append( dydxReceiptChangeItemView( title: DataLocalizer.localize(path: "APP.TRADE.POSITION_LEVERAGE"), diff --git a/dydx/dydxViews/dydxViews/_v4/Receipt/Components/dydxReceiptChangeItemView.swift b/dydx/dydxViews/dydxViews/_v4/Receipt/Components/dydxReceiptChangeItemView.swift index 573007338..d5cd75581 100644 --- a/dydx/dydxViews/dydxViews/_v4/Receipt/Components/dydxReceiptChangeItemView.swift +++ b/dydx/dydxViews/dydxViews/_v4/Receipt/Components/dydxReceiptChangeItemView.swift @@ -33,9 +33,9 @@ public class dydxReceiptChangeItemView: PlatformViewModel { Text(self.title) .themeFont(fontSize: .small) .themeColor(foreground: .textTertiary) + .lineLimit(2) Spacer() self.value.createView(parentStyle: parentStyle) - .fixedSize(horizontal: true, vertical: false) } ) } From d512b0c70db6feae3d2d4ecab933193f81be761b Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Fri, 14 Jun 2024 14:47:42 -0500 Subject: [PATCH 13/16] update button state after validation --- .../xcshareddata/swiftpm/Package.resolved | 20 ++++++++++++++++++- .../dydxAdjustMarginInputViewBuilder.swift | 15 ++++---------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved b/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved index dacd8494d..22de51701 100644 --- a/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/dydx/dydx.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "3cd7346cace16cf660f9c22302c5ca6770335c67902f3fd155011356a9d43929", + "originHash" : "975d00e29efb8d2ca017c5e61df90418ac01f7d7143e85a3f9ddb4eb982154e4", "pins" : [ { "identity" : "bigint", @@ -37,6 +37,15 @@ "version" : "2.0.2" } }, + { + "identity" : "keyboardobserving", + "kind" : "remoteSourceControl", + "location" : "https://github.com/nickffox/KeyboardObserving", + "state" : { + "branch" : "master", + "revision" : "48134b5460435cc9d048223ad7560ee2e40f3d4a" + } + }, { "identity" : "percy-xcui-swift", "kind" : "remoteSourceControl", @@ -190,6 +199,15 @@ "version" : "9.0.9" } }, + { + "identity" : "swiftui-introspect", + "kind" : "remoteSourceControl", + "location" : "https://github.com/siteline/SwiftUI-Introspect.git", + "state" : { + "revision" : "121c146fe591b1320238d054ae35c81ffa45f45a", + "version" : "0.12.0" + } + }, { "identity" : "wallet-mobile-sdk", "kind" : "remoteSourceControl", diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift b/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift index 78f3d5094..b7d4336ee 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift @@ -119,7 +119,6 @@ private class dydxAdjustMarginInputViewPresenter: HostedViewPresenter 0 { - self.ctaButtonPresenter.viewModel?.ctaButtonState = .enabled() - } else { - self.ctaButtonPresenter.viewModel?.ctaButtonState = .disabled() - } - } - private func updateFields(input: AdjustIsolatedMarginInput) { viewModel?.amount?.value = dydxFormatter.shared.raw(number: parser.asNumber(input.amount), digits: 2) } From 7f1587f877e0584fd547961da38afbfed1c64b24 Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Fri, 14 Jun 2024 14:52:48 -0500 Subject: [PATCH 14/16] remove alternate validation --- .../Margin/dydxAdjustMarginInputViewBuilder.swift | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift b/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift index b7d4336ee..a953810e5 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift @@ -202,8 +202,7 @@ private class dydxAdjustMarginInputViewPresenter: HostedViewPresenter 0 ? crossFreeCollateralUpdated : nil) + after: crossFreeCollateralUpdated.amount != nil ? crossFreeCollateralUpdated : nil) crossReceiptItems.append( dydxReceiptChangeItemView( title: DataLocalizer.localize(path: "APP.GENERAL.CROSS_FREE_COLLATERAL"), @@ -213,8 +212,7 @@ private class dydxAdjustMarginInputViewPresenter: HostedViewPresenter 0 ? crossMarginUsageUpdated : nil) + after: crossMarginUsageUpdated.amount != nil ? crossMarginUsageUpdated : nil) crossReceiptItems.append( dydxReceiptChangeItemView( title: DataLocalizer.localize(path: "APP.GENERAL.CROSS_MARGIN_USAGE"), @@ -224,8 +222,7 @@ private class dydxAdjustMarginInputViewPresenter: HostedViewPresenter 0 ? positionMarginUpdated : nil) + after: positionMarginUpdated.amount != nil ? positionMarginUpdated : nil) positionReceiptItems.append( dydxReceiptChangeItemView( title: DataLocalizer.localize(path: "APP.TRADE.POSITION_MARGIN"), @@ -233,11 +230,9 @@ private class dydxAdjustMarginInputViewPresenter: HostedViewPresenter 0 && positionLeverageUpdatedDouble < 1000 ? positionLeverageUpdated : nil) + after: positionLeverageUpdated.amount != nil ? positionLeverageUpdated : nil) positionReceiptItems.append( dydxReceiptChangeItemView( title: DataLocalizer.localize(path: "APP.TRADE.POSITION_LEVERAGE"), From b9bd0809782b573d1f4a8ea99a0df1add4506dec Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Fri, 14 Jun 2024 14:54:03 -0500 Subject: [PATCH 15/16] clean up --- dydx/dydxViews/dydxViews/Shared/BeforeArrowAfter.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dydx/dydxViews/dydxViews/Shared/BeforeArrowAfter.swift b/dydx/dydxViews/dydxViews/Shared/BeforeArrowAfter.swift index 95554887e..6bc2d458e 100644 --- a/dydx/dydxViews/dydxViews/Shared/BeforeArrowAfter.swift +++ b/dydx/dydxViews/dydxViews/Shared/BeforeArrowAfter.swift @@ -55,7 +55,7 @@ public class BeforeArrowAfterModel: PlatformViewModel, .createView(parentStyle: style.themeColor(foreground: .textPrimary), styleKey: nil) } } - .fixedSize() + .fixedSize() ) } } From de39f47380e9b165ff43b1afa2156f96029a9dd4 Mon Sep 17 00:00:00 2001 From: mike-dydx Date: Mon, 17 Jun 2024 13:57:14 -0400 Subject: [PATCH 16/16] ui tweaks --- .../dydxPortfolioPendingPositionsItemViewModel.swift | 9 ++++++--- .../Components/Sections/dydxPortfolioPositionsView.swift | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPendingPositionsItemViewModel.swift b/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPendingPositionsItemViewModel.swift index 656c44335..97422b084 100644 --- a/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPendingPositionsItemViewModel.swift +++ b/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPendingPositionsItemViewModel.swift @@ -68,14 +68,15 @@ public class dydxPortfolioPendingPositionsItemViewModel: PlatformViewModel { } private var divider: some View { - Spacer(minLength: 1) + Rectangle() + .frame(height: 1) .overlay(ThemeColor.SemanticColor.borderDefault.color) } private var bottomContent: some View { let viewOrdersStringKey: String let viewOrdersStringParams: [String: String]? - if orderCount > 1 { + if orderCount == 1 { viewOrdersStringKey = "APP.GENERAL.VIEW_ORDER" viewOrdersStringParams = nil } else { @@ -102,12 +103,14 @@ public class dydxPortfolioPendingPositionsItemViewModel: PlatformViewModel { PlatformView(viewModel: self, parentStyle: parentStyle, styleKey: styleKey) { [weak self] _ in guard let self = self else { return AnyView(PlatformView.nilView) } + let horizontalPadding: CGFloat = 12 return VStack(spacing: 0) { self.topContent self.divider + .padding(.horizontal, -horizontalPadding) self.bottomContent } - .padding(.horizontal, 12) + .padding(.horizontal, horizontalPadding) .themeColor(background: .layer3) .clipShape(.rect(cornerRadius: 10)) .wrappedInAnyView() diff --git a/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift b/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift index 4a51d5fab..fb0ff5359 100644 --- a/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift +++ b/dydx/dydxViews/dydxViews/_v4/Portfolio/Components/Sections/dydxPortfolioPositionsView.swift @@ -398,7 +398,8 @@ public class dydxPortfolioPositionsViewModel: PlatformViewModel { .fixedSize() Text("\(pendingPositionItems.count)") .frame(width: 28, height: 28) - .themeColor(background: .layer6) + .themeColor(background: .layer3) + .themeColor(foreground: .textSecondary) .borderAndClip(style: .circle, borderColor: .borderDefault) Spacer() }