Skip to content

Commit

Permalink
Profile toggle button
Browse files Browse the repository at this point in the history
  • Loading branch information
ruixhuang committed Jan 15, 2025
1 parent 000a34b commit 1415c3d
Show file tree
Hide file tree
Showing 10 changed files with 226 additions and 12 deletions.
4 changes: 4 additions & 0 deletions dydx/dydxPresenters/dydxPresenters.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
02031F1C2AC3A7130069E00D /* dydxTradeSheetTipDraftViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02031F1B2AC3A7130069E00D /* dydxTradeSheetTipDraftViewPresenter.swift */; };
02048AFC2D35837F00394CBE /* dydxSwitchAppModeActionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02048AEE2D35837000394CBE /* dydxSwitchAppModeActionBuilder.swift */; };
02048B122D35E3DF00394CBE /* dydxSimpleUIPositionListViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02048B112D35E3DE00394CBE /* dydxSimpleUIPositionListViewPresenter.swift */; };
02048BBD2D372AAE00394CBE /* dydxProfileTopButtonsViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02048BBC2D372AAD00394CBE /* dydxProfileTopButtonsViewPresenter.swift */; };
0207FC9D2D269C00004C2C9F /* dydxSimpleUITradeInputValidationViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0207FC8F2D269BFF004C2C9F /* dydxSimpleUITradeInputValidationViewPresenter.swift */; };
0207FC9F2D27BA6B004C2C9F /* dydxSimpleUITradeInputCtaButtonViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0207FC9E2D27BA62004C2C9F /* dydxSimpleUITradeInputCtaButtonViewPresenter.swift */; };
0207FCA32D2A181D004C2C9F /* dydxSimpleUIMarketsHeaderViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0207FCA22D2A181C004C2C9F /* dydxSimpleUIMarketsHeaderViewPresenter.swift */; };
Expand Down Expand Up @@ -425,6 +426,7 @@
02031F1B2AC3A7130069E00D /* dydxTradeSheetTipDraftViewPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxTradeSheetTipDraftViewPresenter.swift; sourceTree = "<group>"; };
02048AEE2D35837000394CBE /* dydxSwitchAppModeActionBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxSwitchAppModeActionBuilder.swift; sourceTree = "<group>"; };
02048B112D35E3DE00394CBE /* dydxSimpleUIPositionListViewPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxSimpleUIPositionListViewPresenter.swift; sourceTree = "<group>"; };
02048BBC2D372AAD00394CBE /* dydxProfileTopButtonsViewPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxProfileTopButtonsViewPresenter.swift; sourceTree = "<group>"; };
0207FC8F2D269BFF004C2C9F /* dydxSimpleUITradeInputValidationViewPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxSimpleUITradeInputValidationViewPresenter.swift; sourceTree = "<group>"; };
0207FC9E2D27BA62004C2C9F /* dydxSimpleUITradeInputCtaButtonViewPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxSimpleUITradeInputCtaButtonViewPresenter.swift; sourceTree = "<group>"; };
0207FCA22D2A181C004C2C9F /* dydxSimpleUIMarketsHeaderViewPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxSimpleUIMarketsHeaderViewPresenter.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1030,6 +1032,7 @@
277E8FC82B1E576B005CCBCB /* dydxProfileRewardsViewPresenter.swift */,
027F3F052AB93B3700602E5B /* dydxProfileBalancesViewPresenter.swift */,
0258BA2829929E870098E1BE /* dydxProfileButtonsViewPresenter.swift */,
02048BBC2D372AAD00394CBE /* dydxProfileTopButtonsViewPresenter.swift */,
028DB33F2A05893D0090BE58 /* dydxProfileHeaderViewPresenter.swift */,
02F95A8D2A1D6AAD00828F9A /* dydxProfileHistoryViewPresenter.swift */,
02F6E71E2A8293270018F00C /* dydxProfileFeesViewPresenter.swift */,
Expand Down Expand Up @@ -2281,6 +2284,7 @@
02D1345828ECF30000B46941 /* dydxMarketsSearchViewBuilder.swift in Sources */,
27044F702BBB1CDF004C750D /* dydxTakeProfitStopLossViewPresenter.swift in Sources */,
277DB22F2C669A6800964F9B /* dydxPredictionMarketsNoticeViewBuilder.swift in Sources */,
02048BBD2D372AAE00394CBE /* dydxProfileTopButtonsViewPresenter.swift in Sources */,
64529A4C2AE8705E000810E6 /* dydxUpdateWorker.swift in Sources */,
278A4DA42B8FDD9D003898EB /* dydxRatingsWorker.swift in Sources */,
02DDAD55292587C600CC7531 /* QRCodeDisplayBuilder.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion dydx/dydxPresenters/dydxPresenters/_Features/features.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
"text":"Enable Simple UI"
},
"field":{
"field":"simple_ui",
"field":"ff_simple_ui",
"optional":true,
"type" : "bool",
"options" : [
Expand Down
2 changes: 1 addition & 1 deletion dydx/dydxPresenters/dydxPresenters/_Features/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"link" : {
"text" : "/settings/app_mode"
},
"featureFlag": "simple_ui",
"featureFlag": "ff_simple_ui",
},
{
"title" : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"link" : {
"text" : "/settings/app_mode"
},
"featureFlag": "simple_ui",
"featureFlag": "ff_simple_ui",
},
{
"title" : {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ protocol dydxProfileSecondaryButtonsViewPresenterProtocol: HostedViewPresenterPr

class dydxProfileSecondaryButtonsViewPresenter: HostedViewPresenter<dydxProfileSecondaryButtonsViewModel>, dydxProfileSecondaryButtonsViewPresenterProtocol {

init(viewModel: dydxProfileSecondaryButtonsViewModel) {
override init() {
super.init()

self.viewModel = viewModel
viewModel = dydxProfileSecondaryButtonsViewModel()

viewModel.settingsAction = {
viewModel?.settingsAction = {
Router.shared?.navigate(to: RoutingRequest(path: "/settings"), animated: true, completion: nil)
}

viewModel.helpAction = {
viewModel?.helpAction = {
Router.shared?.navigate(to: RoutingRequest(path: "/help"), animated: true, completion: nil)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// dydxProfileTopButtonsViewPresenter.swift
// dydxPresenters
//
// Created by Rui Huang on 14/01/2025.
//

import Utilities
import dydxViews
import PlatformParticles
import RoutingKit
import ParticlesKit
import PlatformUI
import dydxStateManager
import dydxFormatter
import Combine

protocol dydxProfileTopButtonsViewPresenterProtocol: HostedViewPresenterProtocol {
var viewModel: dydxProfileTopButtonsViewModel? { get }
}

class dydxProfileTopButtonsViewPresenter: HostedViewPresenter<dydxProfileTopButtonsViewModel>, dydxProfileTopButtonsViewPresenterProtocol {
override init() {
super.init()

viewModel = dydxProfileTopButtonsViewModel()

viewModel?.settingsAction = {
Router.shared?.navigate(to: RoutingRequest(path: "/settings"), animated: true, completion: nil)
}

viewModel?.modeAction = {
Router.shared?.navigate(to: RoutingRequest(path: "/settings/app_mode"), animated: true, completion: nil)
}

viewModel?.alertsAction = {
Router.shared?.navigate(to: RoutingRequest(path: "/alerts"), animated: true, completion: nil)
}
}

override func start() {
super.start()

Publishers
.CombineLatest(
AbacusStateManager.shared.state.onboarded,
AbacusStateManager.shared.state.alerts)
.sink { [weak self] onboarded, alerts in
self?.viewModel?.hasNewAlerts = alerts.count > 0 && onboarded
}
.store(in: &self.subscriptions)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import RoutingKit
import ParticlesKit
import PlatformUI
import dydxStateManager
import dydxFormatter

public class dydxProfileViewBuilder: NSObject, ObjectBuilderProtocol {
public func build<T>() -> T? {
Expand Down Expand Up @@ -41,12 +42,13 @@ private protocol dydxProfileViewPresenterProtocol: HostedViewPresenterProtocol {

private class dydxProfileViewPresenter: HostedViewPresenter<dydxProfileViewModel>, dydxProfileViewPresenterProtocol {
private let buttonsPresenter: dydxProfileButtonsViewPresenter
private let secondaryButtonsPresenter: dydxProfileSecondaryButtonsViewPresenter
private let secondaryButtonsPresenter = dydxProfileSecondaryButtonsViewPresenter()
private let headerPresenter: dydxProfileHeaderViewPresenter
private let historyPresenter: dydxProfileHistoryViewPresenter
private let feesPresenter: dydxProfileFeesViewPresenter
private let rewardsPresenter: dydxProfileRewardsViewPresenter
private let balancesPresenter: dydxProfileBalancesViewPresenter
private let topButtonsPresenter = dydxProfileTopButtonsViewPresenter()

private lazy var childPresenters: [HostedViewPresenterProtocol] = [
buttonsPresenter,
Expand All @@ -55,13 +57,13 @@ private class dydxProfileViewPresenter: HostedViewPresenter<dydxProfileViewModel
historyPresenter,
feesPresenter,
rewardsPresenter,
balancesPresenter
balancesPresenter,
topButtonsPresenter
]

override init() {
let viewModel = dydxProfileViewModel()
headerPresenter = .init(viewModel: viewModel.header)
secondaryButtonsPresenter = .init(viewModel: viewModel.secondaryButtons)
buttonsPresenter = .init(viewModel: viewModel.buttons)
historyPresenter = .init()
feesPresenter = .init()
Expand All @@ -77,6 +79,12 @@ private class dydxProfileViewPresenter: HostedViewPresenter<dydxProfileViewModel
rewardsPresenter.$viewModel.assign(to: &viewModel.$rewards)
balancesPresenter.$viewModel.assign(to: &viewModel.$balances)

if dydxBoolFeatureFlag.simple_ui.isEnabled {
topButtonsPresenter.$viewModel.assign(to: &viewModel.$topButtons)
} else {
secondaryButtonsPresenter.$viewModel.assign(to: &viewModel.$secondaryButtons)
}

attachChildren(workers: childPresenters)

viewModel.share?.shareAction = {
Expand Down
4 changes: 4 additions & 0 deletions dydx/dydxViews/dydxViews.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
02031F1A2AC3A6FE0069E00D /* dydxTradeSheetTipDraftView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02031F192AC3A6FE0069E00D /* dydxTradeSheetTipDraftView.swift */; };
02048B0E2D3596F400394CBE /* dydxSimpleUIPortfolioPeriodView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02048B0D2D3596F400394CBE /* dydxSimpleUIPortfolioPeriodView.swift */; };
02048B102D35E3C100394CBE /* dydxSimpleUIPositionListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02048B0F2D35E3C100394CBE /* dydxSimpleUIPositionListView.swift */; };
02048BA02D372A8700394CBE /* dydxProfileTopButtonsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02048B9F2D372A8700394CBE /* dydxProfileTopButtonsView.swift */; };
0207FCA12D2A17DF004C2C9F /* dydxSimpleUIMarketsHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0207FCA02D2A17DF004C2C9F /* dydxSimpleUIMarketsHeaderView.swift */; };
02084B2D297FC2CD00CF9522 /* dydxTransferFaucetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02084B2C297FC2CD00CF9522 /* dydxTransferFaucetView.swift */; };
02084C682981253200CF9522 /* dydxValidationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02084C672981253200CF9522 /* dydxValidationView.swift */; };
Expand Down Expand Up @@ -424,6 +425,7 @@
02031F192AC3A6FE0069E00D /* dydxTradeSheetTipDraftView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxTradeSheetTipDraftView.swift; sourceTree = "<group>"; };
02048B0D2D3596F400394CBE /* dydxSimpleUIPortfolioPeriodView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxSimpleUIPortfolioPeriodView.swift; sourceTree = "<group>"; };
02048B0F2D35E3C100394CBE /* dydxSimpleUIPositionListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxSimpleUIPositionListView.swift; sourceTree = "<group>"; };
02048B9F2D372A8700394CBE /* dydxProfileTopButtonsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxProfileTopButtonsView.swift; sourceTree = "<group>"; };
0207FCA02D2A17DF004C2C9F /* dydxSimpleUIMarketsHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxSimpleUIMarketsHeaderView.swift; sourceTree = "<group>"; };
02084B2C297FC2CD00CF9522 /* dydxTransferFaucetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxTransferFaucetView.swift; sourceTree = "<group>"; };
02084C672981253200CF9522 /* dydxValidationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = dydxValidationView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1208,6 +1210,7 @@
277E8FCA2B1E5798005CCBCB /* dydxProfileRewardsViewModel.swift */,
027F3EF62AB93ADC00602E5B /* dydxProfileBalancesViewModel.swift */,
0258BA2529929D1B0098E1BE /* dydxProfileButtonsView.swift */,
02048B9F2D372A8700394CBE /* dydxProfileTopButtonsView.swift */,
028DB33D2A0589270090BE58 /* dydxProfileHeaderView.swift */,
02F95A8B2A1D6A9200828F9A /* dydxProfileHistoryView.swift */,
02F6E7102A8292FC0018F00C /* dydxProfileFeesView.swift */,
Expand Down Expand Up @@ -2305,6 +2308,7 @@
024FEB642ACB75E10087A55E /* dydxFeesStuctureView.swift in Sources */,
277E918B2B27762F005CCBCB /* dydxRewardsLaunchIncentivesView.swift in Sources */,
0268BBF92A8BE08C00D0C59B /* dydxTransferOutView.swift in Sources */,
02048BA02D372A8700394CBE /* dydxProfileTopButtonsView.swift in Sources */,
0279DE452BEBE75100F9ECF8 /* dydxTargetLeverageCtaButtonView.swift in Sources */,
27EB25852C6D28BF008C187B /* SparklineChart.swift in Sources */,
0208627A28F4D95F00C9D3A0 /* dydxMarketInfoPagingView.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
//
// dydxProfileTopButtonsView.swift
// dydxUI
//
// Created by Rui Huang on 14/01/2025.
// Copyright © 2025 dYdX Trading Inc. All rights reserved.
//

import SwiftUI
import PlatformUI
import Utilities

public class dydxProfileTopButtonsViewModel: PlatformViewModel {
@Published public var settingsAction: (() -> Void)?
@Published public var alertsAction: (() -> Void)?
@Published public var modeAction: (() -> Void)?
@Published public var hasNewAlerts: Bool = false

public lazy var toggleBinding = Binding<Bool> {
return true
} set: { _ in
self.modeAction?()
}

public init() { }

public static var previewValue: dydxProfileTopButtonsViewModel {
let vm = dydxProfileTopButtonsViewModel()
vm.hasNewAlerts = true
return vm
}

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) }

let view = HStack(spacing: 16) {
HStack(spacing: 16) {
self.createButton(style: style,
imageName: "icon_settings",
badge: false,
action: self.settingsAction)
.frame(maxWidth: .infinity)

self.createButton(style: style,
imageName: "icon_alerts",
badge: self.hasNewAlerts,
action: self.alertsAction)
.frame(maxWidth: .infinity)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)

self.createModeButton(style: style)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
.frame(minHeight: 68)

return AnyView(view)
}
}

private func createModeButton(style: ThemeStyle) -> some View {
HStack(alignment: .center) {
VStack(alignment: .leading) {
Text("dYdX " + DataLocalizer.localize(path: "APP.TRADE.MODE.PRO"))
.themeFont(fontSize: .medium)
.themeColor(foreground: .textSecondary)

Text(DataLocalizer.localize(path: "APP.TRADE.MODE.FULLY_FEATURED"))
.themeFont(fontSize: .small)
.themeColor(foreground: .textTertiary)
}
Toggle("", isOn: toggleBinding)
.tint(ThemeColor.SemanticColor.colorPurple.color)
}
.padding(.horizontal, 16)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.themeColor(background: .layer3)
.cornerRadius(12, corners: .allCorners)
}

private func createButton(style: ThemeStyle, imageName: String, badge: Bool, action: (() -> Void)?) -> some View {
let content = ZStack {
PlatformIconViewModel(type: .asset(name: imageName, bundle: Bundle.dydxView),
clip: .noClip,
size: CGSize(width: 24, height: 24),
templateColor: .textTertiary)
.createView(parentStyle: style)
.padding(.horizontal, 16)

if badge {
Circle()
.fill(ThemeColor.SemanticColor.colorPurple.color)
.frame(width: 10, height: 10)
.padding(12)
.rightAligned()
.topAligned()
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.themeColor(background: .layer3)
.cornerRadius(12, corners: .allCorners)

return PlatformButtonViewModel(content: content.wrappedViewModel,
type: .iconType) {
action?()
}
.createView(parentStyle: style)
}
}

#if DEBUG
struct dydxProfileTopButtonsView_Previews_Dark: PreviewProvider {
@StateObject static var themeSettings = ThemeSettings.shared

static var previews: some View {
ThemeSettings.applyDarkTheme()
ThemeSettings.applyStyles()
return dydxProfileTopButtonsViewModel.previewValue
.createView()
.themeColor(background: .layer0)
.environmentObject(themeSettings)
// .edgesIgnoringSafeArea(.bottom)
.previewLayout(.sizeThatFits)
}
}

struct dydxProfileTopButtonsView_Previews_Light: PreviewProvider {
@StateObject static var themeSettings = ThemeSettings.shared

static var previews: some View {
ThemeSettings.applyLightTheme()
ThemeSettings.applyStyles()
return dydxProfileTopButtonsViewModel.previewValue
.createView()
.themeColor(background: .layer0)
.environmentObject(themeSettings)
// .edgesIgnoringSafeArea(.bottom)
.previewLayout(.sizeThatFits)
}
}
#endif
Loading

0 comments on commit 1415c3d

Please sign in to comment.