From c2a6574436b5fc2199d678fea31eeb10f89e62af Mon Sep 17 00:00:00 2001 From: Rui <102453770+ruixhuang@users.noreply.github.com> Date: Wed, 6 Nov 2024 12:59:49 -0800 Subject: [PATCH 1/2] Update token name from asset.id to asset.displayableAssetId (#289) --- dydx/Podfile.lock | 16 +- .../Sources/Amplitude/Constants.swift | 2 +- dydx/Pods/Local Podspecs/abacus.podspec.json | 6 +- dydx/Pods/Manifest.lock | 16 +- dydx/Pods/Pods.xcodeproj/project.pbxproj | 130 +++++++------- .../SDWebImage/Core/SDAnimatedImage.m | 6 +- .../SDWebImage/Core/SDAnimatedImageView.h | 14 ++ .../SDWebImage/Core/SDAnimatedImageView.m | 73 +++++++- .../SDWebImage/SDWebImage/Core/SDDiskCache.m | 12 +- .../SDWebImage/Core/SDImageCacheConfig.h | 2 +- .../SDWebImage/Core/SDImageCacheConfig.m | 2 +- .../SDWebImage/Core/SDImageTransformer.h | 5 + .../SDWebImage/Core/SDImageTransformer.m | 8 +- .../SDWebImage/Core/UIImage+Transform.h | 13 +- .../SDWebImage/Core/UIImage+Transform.m | 164 +++++++++++++++++- .../SDWebImage/Private/SDImageFramePool.m | 3 +- .../AmplitudeSwift/AmplitudeSwift-Info.plist | 2 +- ...Bundle-Amplitude-AmplitudeSwift-Info.plist | 2 +- ...rceBundle-SDWebImage-SDWebImage-Info.plist | 2 +- .../SDWebImage/SDWebImage-Info.plist | 2 +- ...ncelPendingIsolatedOrdersViewBuilder.swift | 2 +- .../dydxMarketConfigsViewPresenter.swift | 18 +- .../dydxMarketDepthChartViewPresenter.swift | 2 +- .../dydxMarketStatsViewPresenter.swift | 2 +- .../Search/dydxMarketsSearchViewBuilder.swift | 2 +- .../Shared/SharedMarketPresenter.swift | 2 +- .../_v4/Markets/dydxMarketsViewBuilder.swift | 2 +- .../dydxPortfolioFillsViewPresenter.swift | 2 +- .../dydxPortfolioFundingViewPresenter.swift | 2 +- .../dydxPortfolioOrdersViewPresenter.swift | 2 +- .../dydxPortfolioPositionsViewPresenter.swift | 2 +- .../dydxProfileHistoryViewPresenter.swift | 4 +- .../dydxTradeSheetTipDraftViewPresenter.swift | 2 +- .../dydxTradeStatusViewBuilder.swift | 2 +- podspecs/Abacus.podspec | 2 +- 35 files changed, 394 insertions(+), 134 deletions(-) diff --git a/dydx/Podfile.lock b/dydx/Podfile.lock index 9726166a1..6eaea6614 100644 --- a/dydx/Podfile.lock +++ b/dydx/Podfile.lock @@ -1,6 +1,6 @@ PODS: - - Abacus (1.13.17) - - AmplitudeSwift (1.10.0): + - Abacus (1.13.18) + - AmplitudeSwift (1.10.1): - AnalyticsConnector (~> 1.0.1) - AnalyticsConnector (1.0.3) - AppsFlyerFramework (6.15.3): @@ -251,9 +251,9 @@ PODS: - PromisesObjC (= 2.4.0) - RDHCollectionViewGridLayout (1.2.5) - ReachabilitySwift (5.2.4) - - SDWebImage (5.19.7): - - SDWebImage/Core (= 5.19.7) - - SDWebImage/Core (5.19.7) + - SDWebImage (5.20.0): + - SDWebImage/Core (= 5.20.0) + - SDWebImage/Core (5.20.0) - SDWebImageSVGCoder (1.7.0): - SDWebImage/Core (~> 5.6) - SDWebImageSwiftUI (3.1.1): @@ -382,8 +382,8 @@ CHECKOUT OPTIONS: :git: https://github.com/dydxprotocol/Charts.git SPEC CHECKSUMS: - Abacus: c49081ef835542a3721b308a956db52888c3c585 - AmplitudeSwift: 4093845011c73eaf65cd198b115a678ba7c9ecda + Abacus: ad923b7bd4d7a7dc4824a5b88130f0d7c56af1d0 + AmplitudeSwift: 9a4b3e0cb70ad8f89176925e7a6f979c5d48f362 AnalyticsConnector: a53214d38ae22734c6266106c0492b37832633a9 AppsFlyerFramework: ad7ff0d22aa36c7f8cc4f71a5424e19b89ccb8ae Atributika: ecedf5259e4aa3c6278d840b6c18d60c1a8b6ca0 @@ -431,7 +431,7 @@ SPEC CHECKSUMS: PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851 RDHCollectionViewGridLayout: 4b4229212ed8c136aa70101d92ecd43742ca62b6 ReachabilitySwift: 32793e867593cfc1177f5d16491e3a197d2fccda - SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3 + SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8 SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c SDWebImageSwiftUI: dcff3d05fd0579ff280221ae8856c34ac3b67f25 SimpleKeychain: 8193a9e40967eccac933c1fde82de46c07a5ae26 diff --git a/dydx/Pods/AmplitudeSwift/Sources/Amplitude/Constants.swift b/dydx/Pods/AmplitudeSwift/Sources/Amplitude/Constants.swift index c61f8342a..9edb42f93 100644 --- a/dydx/Pods/AmplitudeSwift/Sources/Amplitude/Constants.swift +++ b/dydx/Pods/AmplitudeSwift/Sources/Amplitude/Constants.swift @@ -46,7 +46,7 @@ public enum ServerZone: Int { public struct Constants { static let SDK_LIBRARY = "amplitude-swift" - static let SDK_VERSION = "1.10.0" + static let SDK_VERSION = "1.10.1" public static let DEFAULT_API_HOST = "https://api2.amplitude.com/2/httpapi" public static let EU_DEFAULT_API_HOST = "https://api.eu.amplitude.com/2/httpapi" static let BATCH_API_HOST = "https://api2.amplitude.com/batch" diff --git a/dydx/Pods/Local Podspecs/abacus.podspec.json b/dydx/Pods/Local Podspecs/abacus.podspec.json index f07e8e8c9..51d88d177 100644 --- a/dydx/Pods/Local Podspecs/abacus.podspec.json +++ b/dydx/Pods/Local Podspecs/abacus.podspec.json @@ -1,10 +1,10 @@ { "name": "Abacus", - "version": "1.13.17", + "version": "1.13.18", "homepage": "https://github.com/dydxprotocol/v4-abacus", "source": { "git": "git@github.com:dydxprotocol/v4-abacus.git", - "tag": "v1.13.17" + "tag": "v1.13.18" }, "authors": "", "license": "", @@ -20,7 +20,7 @@ "name": "Build abacus", "execution_position": "before_compile", "shell_path": "/bin/sh", - "script": " if [ \"YES\" = \"$COCOAPODS_SKIP_KOTLIN_BUILD\" ]; then\n echo \"Skipping Gradle build task invocation due to COCOAPODS_SKIP_KOTLIN_BUILD environment variable set to \"YES\"\"\n exit 0\n fi\n set -evx\n \n REPO_ROOT=\"$PODS_TARGET_SRCROOT\"\n \n if [ ! -f $REPO_ROOT/gradlew ]; then\n rm -rf $PRODUCT_MODULE_NAME\n git clone git@github.com:dydxprotocol/v4-abacus.git --branch v1.13.17 $PRODUCT_MODULE_NAME\n \n \"$REPO_ROOT/gradlew\" -p \"$REPO_ROOT\" $KOTLIN_PROJECT_PATH:syncFramework -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME -Pkotlin.native.cocoapods.archs=\"$ARCHS\" -Pkotlin.native.cocoapods.configuration=\"$CONFIGURATION\"\n \n # We will need to overwrite the dummy framework generated by cocoapods with the actual one from Kotlin\n \n TARGET_FRAMEWORK=\"${TARGET_BUILD_DIR}/${TARGET_NAME}.framework\"\n ABACUS_FRAMEWORK=\"$REPO_ROOT/build/cocoapods/framework/$PRODUCT_MODULE_NAME.framework\"\n rm -rf $TARGET_FRAMEWORK\n mkdir $TARGET_FRAMEWORK\n cp -rf $ABACUS_FRAMEWORK/* $TARGET_FRAMEWORK\n else\n \"$REPO_ROOT/gradlew\" -p \"$REPO_ROOT\" $KOTLIN_PROJECT_PATH:syncFramework -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME -Pkotlin.native.cocoapods.archs=\"$ARCHS\" -Pkotlin.native.cocoapods.configuration=\"$CONFIGURATION\"\n fi\n" + "script": " if [ \"YES\" = \"$COCOAPODS_SKIP_KOTLIN_BUILD\" ]; then\n echo \"Skipping Gradle build task invocation due to COCOAPODS_SKIP_KOTLIN_BUILD environment variable set to \"YES\"\"\n exit 0\n fi\n set -evx\n \n REPO_ROOT=\"$PODS_TARGET_SRCROOT\"\n \n if [ ! -f $REPO_ROOT/gradlew ]; then\n rm -rf $PRODUCT_MODULE_NAME\n git clone git@github.com:dydxprotocol/v4-abacus.git --branch v1.13.18 $PRODUCT_MODULE_NAME\n \n \"$REPO_ROOT/gradlew\" -p \"$REPO_ROOT\" $KOTLIN_PROJECT_PATH:syncFramework -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME -Pkotlin.native.cocoapods.archs=\"$ARCHS\" -Pkotlin.native.cocoapods.configuration=\"$CONFIGURATION\"\n \n # We will need to overwrite the dummy framework generated by cocoapods with the actual one from Kotlin\n \n TARGET_FRAMEWORK=\"${TARGET_BUILD_DIR}/${TARGET_NAME}.framework\"\n ABACUS_FRAMEWORK=\"$REPO_ROOT/build/cocoapods/framework/$PRODUCT_MODULE_NAME.framework\"\n rm -rf $TARGET_FRAMEWORK\n mkdir $TARGET_FRAMEWORK\n cp -rf $ABACUS_FRAMEWORK/* $TARGET_FRAMEWORK\n else\n \"$REPO_ROOT/gradlew\" -p \"$REPO_ROOT\" $KOTLIN_PROJECT_PATH:syncFramework -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME -Pkotlin.native.cocoapods.archs=\"$ARCHS\" -Pkotlin.native.cocoapods.configuration=\"$CONFIGURATION\"\n fi\n" } ], "platforms": { diff --git a/dydx/Pods/Manifest.lock b/dydx/Pods/Manifest.lock index 9726166a1..6eaea6614 100644 --- a/dydx/Pods/Manifest.lock +++ b/dydx/Pods/Manifest.lock @@ -1,6 +1,6 @@ PODS: - - Abacus (1.13.17) - - AmplitudeSwift (1.10.0): + - Abacus (1.13.18) + - AmplitudeSwift (1.10.1): - AnalyticsConnector (~> 1.0.1) - AnalyticsConnector (1.0.3) - AppsFlyerFramework (6.15.3): @@ -251,9 +251,9 @@ PODS: - PromisesObjC (= 2.4.0) - RDHCollectionViewGridLayout (1.2.5) - ReachabilitySwift (5.2.4) - - SDWebImage (5.19.7): - - SDWebImage/Core (= 5.19.7) - - SDWebImage/Core (5.19.7) + - SDWebImage (5.20.0): + - SDWebImage/Core (= 5.20.0) + - SDWebImage/Core (5.20.0) - SDWebImageSVGCoder (1.7.0): - SDWebImage/Core (~> 5.6) - SDWebImageSwiftUI (3.1.1): @@ -382,8 +382,8 @@ CHECKOUT OPTIONS: :git: https://github.com/dydxprotocol/Charts.git SPEC CHECKSUMS: - Abacus: c49081ef835542a3721b308a956db52888c3c585 - AmplitudeSwift: 4093845011c73eaf65cd198b115a678ba7c9ecda + Abacus: ad923b7bd4d7a7dc4824a5b88130f0d7c56af1d0 + AmplitudeSwift: 9a4b3e0cb70ad8f89176925e7a6f979c5d48f362 AnalyticsConnector: a53214d38ae22734c6266106c0492b37832633a9 AppsFlyerFramework: ad7ff0d22aa36c7f8cc4f71a5424e19b89ccb8ae Atributika: ecedf5259e4aa3c6278d840b6c18d60c1a8b6ca0 @@ -431,7 +431,7 @@ SPEC CHECKSUMS: PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851 RDHCollectionViewGridLayout: 4b4229212ed8c136aa70101d92ecd43742ca62b6 ReachabilitySwift: 32793e867593cfc1177f5d16491e3a197d2fccda - SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3 + SDWebImage: 73c6079366fea25fa4bb9640d5fb58f0893facd8 SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c SDWebImageSwiftUI: dcff3d05fd0579ff280221ae8856c34ac3b67f25 SimpleKeychain: 8193a9e40967eccac933c1fde82de46c07a5ae26 diff --git a/dydx/Pods/Pods.xcodeproj/project.pbxproj b/dydx/Pods/Pods.xcodeproj/project.pbxproj index 53c331170..5cb91551d 100644 --- a/dydx/Pods/Pods.xcodeproj/project.pbxproj +++ b/dydx/Pods/Pods.xcodeproj/project.pbxproj @@ -22,10 +22,10 @@ }; 2B2AD932AF1A90828B4DFC5AC6955ADA /* Abacus */ = { isa = PBXAggregateTarget; - buildConfigurationList = 98C816ACF8DC829734CE5843CDAFC177 /* Build configuration list for PBXAggregateTarget "Abacus" */; + buildConfigurationList = 2EC7EDBB2B8194A99148858952FBE995 /* Build configuration list for PBXAggregateTarget "Abacus" */; buildPhases = ( - 63C3EF02B441C9A17EEB0E0CAB3E6F80 /* [CP-User] Build abacus */, - D3B86C7F128FDE416BED701CA30F0727 /* [CP] Copy dSYMs */, + FEF71DA61C0F407F64C44F708B8FE79A /* [CP-User] Build abacus */, + 7D584380B808F2F0AB3BC8DD9B1DA594 /* [CP] Copy dSYMs */, ); dependencies = ( ); @@ -24933,15 +24933,22 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/FirebaseAnalytics/FirebaseAnalytics-xcframeworks.sh\"\n"; showEnvVarsInLog = 0; }; - 63C3EF02B441C9A17EEB0E0CAB3E6F80 /* [CP-User] Build abacus */ = { + 7D584380B808F2F0AB3BC8DD9B1DA594 /* [CP] Copy dSYMs */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - name = "[CP-User] Build abacus"; + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Abacus/Abacus-copy-dsyms-input-files.xcfilelist", + ); + name = "[CP] Copy dSYMs"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Abacus/Abacus-copy-dsyms-output-files.xcfilelist", + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = " if [ \"YES\" = \"$COCOAPODS_SKIP_KOTLIN_BUILD\" ]; then\n echo \"Skipping Gradle build task invocation due to COCOAPODS_SKIP_KOTLIN_BUILD environment variable set to \"YES\"\"\n exit 0\n fi\n set -evx\n \n REPO_ROOT=\"$PODS_TARGET_SRCROOT\"\n \n if [ ! -f $REPO_ROOT/gradlew ]; then\n rm -rf $PRODUCT_MODULE_NAME\n git clone git@github.com:dydxprotocol/v4-abacus.git --branch v1.13.17 $PRODUCT_MODULE_NAME\n \n \"$REPO_ROOT/gradlew\" -p \"$REPO_ROOT\" $KOTLIN_PROJECT_PATH:syncFramework -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME -Pkotlin.native.cocoapods.archs=\"$ARCHS\" -Pkotlin.native.cocoapods.configuration=\"$CONFIGURATION\"\n \n # We will need to overwrite the dummy framework generated by cocoapods with the actual one from Kotlin\n \n TARGET_FRAMEWORK=\"${TARGET_BUILD_DIR}/${TARGET_NAME}.framework\"\n ABACUS_FRAMEWORK=\"$REPO_ROOT/build/cocoapods/framework/$PRODUCT_MODULE_NAME.framework\"\n rm -rf $TARGET_FRAMEWORK\n mkdir $TARGET_FRAMEWORK\n cp -rf $ABACUS_FRAMEWORK/* $TARGET_FRAMEWORK\n else\n \"$REPO_ROOT/gradlew\" -p \"$REPO_ROOT\" $KOTLIN_PROJECT_PATH:syncFramework -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME -Pkotlin.native.cocoapods.archs=\"$ARCHS\" -Pkotlin.native.cocoapods.configuration=\"$CONFIGURATION\"\n fi\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Abacus/Abacus-copy-dsyms.sh\"\n"; + showEnvVarsInLog = 0; }; AA25B77F33C1BF0ACDDA59D430A4FF57 /* [CP] Copy XCFrameworks */ = { isa = PBXShellScriptBuildPhase; @@ -24960,39 +24967,32 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/GoogleAppMeasurement/GoogleAppMeasurement-xcframeworks.sh\"\n"; showEnvVarsInLog = 0; }; - D3B86C7F128FDE416BED701CA30F0727 /* [CP] Copy dSYMs */ = { + DB7C100E6D7A5CF954757DB8962D9B72 /* [CP] Copy XCFrameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Abacus/Abacus-copy-dsyms-input-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/AppsFlyerFramework/AppsFlyerFramework-xcframeworks-input-files.xcfilelist", ); - name = "[CP] Copy dSYMs"; + name = "[CP] Copy XCFrameworks"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Abacus/Abacus-copy-dsyms-output-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/AppsFlyerFramework/AppsFlyerFramework-xcframeworks-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Abacus/Abacus-copy-dsyms.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/AppsFlyerFramework/AppsFlyerFramework-xcframeworks.sh\"\n"; showEnvVarsInLog = 0; }; - DB7C100E6D7A5CF954757DB8962D9B72 /* [CP] Copy XCFrameworks */ = { + FEF71DA61C0F407F64C44F708B8FE79A /* [CP-User] Build abacus */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/AppsFlyerFramework/AppsFlyerFramework-xcframeworks-input-files.xcfilelist", - ); - name = "[CP] Copy XCFrameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/AppsFlyerFramework/AppsFlyerFramework-xcframeworks-output-files.xcfilelist", - ); + name = "[CP-User] Build abacus"; runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/AppsFlyerFramework/AppsFlyerFramework-xcframeworks.sh\"\n"; - showEnvVarsInLog = 0; + shellScript = " if [ \"YES\" = \"$COCOAPODS_SKIP_KOTLIN_BUILD\" ]; then\n echo \"Skipping Gradle build task invocation due to COCOAPODS_SKIP_KOTLIN_BUILD environment variable set to \"YES\"\"\n exit 0\n fi\n set -evx\n \n REPO_ROOT=\"$PODS_TARGET_SRCROOT\"\n \n if [ ! -f $REPO_ROOT/gradlew ]; then\n rm -rf $PRODUCT_MODULE_NAME\n git clone git@github.com:dydxprotocol/v4-abacus.git --branch v1.13.18 $PRODUCT_MODULE_NAME\n \n \"$REPO_ROOT/gradlew\" -p \"$REPO_ROOT\" $KOTLIN_PROJECT_PATH:syncFramework -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME -Pkotlin.native.cocoapods.archs=\"$ARCHS\" -Pkotlin.native.cocoapods.configuration=\"$CONFIGURATION\"\n \n # We will need to overwrite the dummy framework generated by cocoapods with the actual one from Kotlin\n \n TARGET_FRAMEWORK=\"${TARGET_BUILD_DIR}/${TARGET_NAME}.framework\"\n ABACUS_FRAMEWORK=\"$REPO_ROOT/build/cocoapods/framework/$PRODUCT_MODULE_NAME.framework\"\n rm -rf $TARGET_FRAMEWORK\n mkdir $TARGET_FRAMEWORK\n cp -rf $ABACUS_FRAMEWORK/* $TARGET_FRAMEWORK\n else\n \"$REPO_ROOT/gradlew\" -p \"$REPO_ROOT\" $KOTLIN_PROJECT_PATH:syncFramework -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME -Pkotlin.native.cocoapods.archs=\"$ARCHS\" -Pkotlin.native.cocoapods.configuration=\"$CONFIGURATION\"\n fi\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -35420,23 +35420,6 @@ }; name = Release; }; - 40E9BA07D877263596F3A92D8ACA5446 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = D10DBF2FFCAE2CFAFDB147B38E7246C5 /* Abacus.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - SDKROOT = iphoneos; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; 41D99213EDF82FE35283F6CAE66E042D /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = A240064D0247866EEC30A89A9736E113 /* MaterialActivityIndicator.debug.xcconfig */; @@ -39038,24 +39021,6 @@ }; name = Debug; }; - A89A254C86208F5F0212E3D1452AEBD6 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 3F58A67E444353CF2F3A3D37E5BBE252 /* Abacus.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - SDKROOT = iphoneos; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; AAA884D13FC537CC71FDBC78E166E178 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 1E8843F57B6EA95A419244D7CA9AA1E1 /* DGCharts.debug.xcconfig */; @@ -39090,6 +39055,23 @@ }; name = Debug; }; + AD342EF8B8F86A929C50CD3BEF75E736 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D10DBF2FFCAE2CFAFDB147B38E7246C5 /* Abacus.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; AD3ACC11AAC57CA8B83E2DCEEEE21678 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = C5F736672CB99E19C0B5A13B8D3A457F /* JTCalendar.release.xcconfig */; @@ -39381,6 +39363,24 @@ }; name = Release; }; + B7815826282ADD408405813DDB4B4029 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3F58A67E444353CF2F3A3D37E5BBE252 /* Abacus.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SDKROOT = iphoneos; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; B7B9D58AA5C1EA8309A27538ACAEE4CA /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 4AA0D180BF223229CDCF7372C22F8583 /* PanModal.debug.xcconfig */; @@ -42325,6 +42325,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 2EC7EDBB2B8194A99148858952FBE995 /* Build configuration list for PBXAggregateTarget "Abacus" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AD342EF8B8F86A929C50CD3BEF75E736 /* Debug */, + B7815826282ADD408405813DDB4B4029 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 32D9A7EDFCDCDDBB39F3175168F6918F /* Build configuration list for PBXNativeTarget "Pods-iOS-UIToolkitsTests" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -42766,15 +42775,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 98C816ACF8DC829734CE5843CDAFC177 /* Build configuration list for PBXAggregateTarget "Abacus" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 40E9BA07D877263596F3A92D8ACA5446 /* Debug */, - A89A254C86208F5F0212E3D1452AEBD6 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 9991DADC9BCE9575FA37871EBBEBD215 /* Build configuration list for PBXNativeTarget "FirebaseCoreInternal" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/dydx/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImage.m b/dydx/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImage.m index 56c63e1c4..14384e722 100644 --- a/dydx/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImage.m +++ b/dydx/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImage.m @@ -182,6 +182,8 @@ - (instancetype)initWithData:(NSData *)data scale:(CGFloat)scale options:(SDImag #else self = [super initWithCGImage:image.CGImage scale:MAX(scale, 1) orientation:image.imageOrientation]; #endif + // Defines the associated object that holds the format for static images + super.sd_imageFormat = format; return self; } } @@ -374,10 +376,6 @@ - (SDImageFormat)sd_imageFormat { } } -- (void)setSd_imageFormat:(SDImageFormat)sd_imageFormat { - return; -} - - (BOOL)sd_isVector { return NO; } diff --git a/dydx/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImageView.h b/dydx/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImageView.h index 431be9214..aa315066e 100644 --- a/dydx/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImageView.h +++ b/dydx/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImageView.h @@ -12,6 +12,7 @@ #import "SDAnimatedImage.h" #import "SDAnimatedImagePlayer.h" +#import "SDImageTransformer.h" /** A drop-in replacement for UIImageView/NSImageView, you can use this for animated image rendering. @@ -28,6 +29,19 @@ NS_SWIFT_UI_ACTOR */ @property (nonatomic, strong, readonly, nullable) SDAnimatedImagePlayer *player; +/** + The transformer for each decoded animated image frame. + We supports post-transform on animated image frame from version 5.20. + When you configure the transformer on `SDAnimatedImageView` and animation is playing, the `transformedImageWithImage:forKey:` will be called just after the frame is decoded. (note: The `key` arg is always empty for backward-compatible and may be removed in the future) + + Example to tint the alpha animated image frame with a black color: + * @code + imageView.animationTransformer = [SDImageTintTransformer transformerWithColor:UIColor.blackColor]; + * @endcode + @note The `transformerKey` property is used to ensure the buffer cache available. So make sure it's correct value match the actual logic on transformer. Which means, for the `same frame index + same transformer key`, the transformed image should always be the same. + */ +@property (nonatomic, strong, nullable) id animationTransformer; + /** Current display frame image. This value is KVO Compliance. */ diff --git a/dydx/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImageView.m b/dydx/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImageView.m index 7e7336723..193652df0 100644 --- a/dydx/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImageView.m +++ b/dydx/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImageView.m @@ -15,6 +15,70 @@ #import "SDInternalMacros.h" #import "objc/runtime.h" +// A wrapper to implements the transformer on animated image, like tint color +@interface SDAnimatedImageFrameProvider : NSObject +@property (nonatomic, strong) id provider; +@property (nonatomic, strong) id transformer; +@end + +@implementation SDAnimatedImageFrameProvider + +- (instancetype)initWithProvider:(id)provider transformer:(id)transformer { + self = [super init]; + if (self) { + _provider = provider; + _transformer = transformer; + } + return self; +} + +- (NSUInteger)hash { + NSUInteger prime = 31; + NSUInteger result = 1; + NSUInteger providerHash = self.provider.hash; + NSUInteger transformerHash = self.transformer.transformerKey.hash; + result = prime * result + providerHash; + result = prime * result + transformerHash; + return result; +} + +- (BOOL)isEqual:(id)object { + if (nil == object) { + return NO; + } + if (self == object) { + return YES; + } + if (![object isKindOfClass:[self class]]) { + return NO; + } + return self.provider == [object provider] + && [self.transformer.transformerKey isEqualToString:[object transformer].transformerKey]; +} + +- (NSData *)animatedImageData { + return self.provider.animatedImageData; +} + +- (NSUInteger)animatedImageFrameCount { + return self.provider.animatedImageFrameCount; +} + +- (NSUInteger)animatedImageLoopCount { + return self.provider.animatedImageLoopCount; +} + +- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index { + return [self.provider animatedImageDurationAtIndex:index]; +} + +- (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index { + UIImage *frame = [self.provider animatedImageFrameAtIndex:index]; + return [self.transformer transformedImageWithImage:frame forKey:@""]; +} + +@end + @interface UIImageView () @end @@ -139,7 +203,14 @@ - (void)setImage:(UIImage *)image provider = (id)image; } // Create animated player - self.player = [SDAnimatedImagePlayer playerWithProvider:provider]; + if (self.animationTransformer) { + // Check if post-transform animation available + provider = [[SDAnimatedImageFrameProvider alloc] initWithProvider:provider transformer:self.animationTransformer]; + self.player = [SDAnimatedImagePlayer playerWithProvider:provider]; + } else { + // Normal animation without post-transform + self.player = [SDAnimatedImagePlayer playerWithProvider:provider]; + } } else { // Update Frame Count self.player.totalFrameCount = [(id)image animatedImageFrameCount]; diff --git a/dydx/Pods/SDWebImage/SDWebImage/Core/SDDiskCache.m b/dydx/Pods/SDWebImage/SDWebImage/Core/SDDiskCache.m index f1ee26803..938b844af 100644 --- a/dydx/Pods/SDWebImage/SDWebImage/Core/SDDiskCache.m +++ b/dydx/Pods/SDWebImage/SDWebImage/Core/SDDiskCache.m @@ -71,13 +71,16 @@ - (NSData *)dataForKey:(NSString *)key { } NSData *data = [NSData dataWithContentsOfFile:filePath options:self.config.diskCacheReadingOptions error:nil]; if (data) { + [[NSURL fileURLWithPath:filePath] setResourceValue:[NSDate date] forKey:NSURLContentAccessDateKey error:nil]; return data; } // fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name // checking the key with and without the extension - data = [NSData dataWithContentsOfFile:filePath.stringByDeletingPathExtension options:self.config.diskCacheReadingOptions error:nil]; + filePath = filePath.stringByDeletingPathExtension; + data = [NSData dataWithContentsOfFile:filePath options:self.config.diskCacheReadingOptions error:nil]; if (data) { + [[NSURL fileURLWithPath:filePath] setResourceValue:[NSDate date] forKey:NSURLContentAccessDateKey error:nil]; return data; } @@ -149,11 +152,8 @@ - (void)removeExpiredData { NSURL *diskCacheURL = [NSURL fileURLWithPath:self.diskCachePath isDirectory:YES]; // Compute content date key to be used for tests - NSURLResourceKey cacheContentDateKey = NSURLContentModificationDateKey; + NSURLResourceKey cacheContentDateKey; switch (self.config.diskCacheExpireType) { - case SDImageCacheConfigExpireTypeAccessDate: - cacheContentDateKey = NSURLContentAccessDateKey; - break; case SDImageCacheConfigExpireTypeModificationDate: cacheContentDateKey = NSURLContentModificationDateKey; break; @@ -163,7 +163,9 @@ - (void)removeExpiredData { case SDImageCacheConfigExpireTypeChangeDate: cacheContentDateKey = NSURLAttributeModificationDateKey; break; + case SDImageCacheConfigExpireTypeAccessDate: default: + cacheContentDateKey = NSURLContentAccessDateKey; break; } diff --git a/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageCacheConfig.h b/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageCacheConfig.h index 91889158d..dace4beba 100644 --- a/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageCacheConfig.h +++ b/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageCacheConfig.h @@ -115,7 +115,7 @@ typedef NS_ENUM(NSUInteger, SDImageCacheConfigExpireType) { /* * The attribute which the clear cache will be checked against when clearing the disk cache - * Default is Modified Date + * Default is Access Date */ @property (assign, nonatomic) SDImageCacheConfigExpireType diskCacheExpireType; diff --git a/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageCacheConfig.m b/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageCacheConfig.m index 6e594edab..70402dbb2 100644 --- a/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageCacheConfig.m +++ b/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageCacheConfig.m @@ -34,7 +34,7 @@ - (instancetype)init { _diskCacheWritingOptions = NSDataWritingAtomic; _maxDiskAge = kDefaultCacheMaxDiskAge; _maxDiskSize = 0; - _diskCacheExpireType = SDImageCacheConfigExpireTypeModificationDate; + _diskCacheExpireType = SDImageCacheConfigExpireTypeAccessDate; _fileManager = nil; if (@available(iOS 10.0, tvOS 10.0, macOS 10.12, watchOS 3.0, *)) { _ioQueueAttributes = DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL; // DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM diff --git a/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageTransformer.h b/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageTransformer.h index 31b4370e0..ed8175d04 100644 --- a/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageTransformer.h +++ b/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageTransformer.h @@ -31,6 +31,7 @@ FOUNDATION_EXPORT NSString * _Nullable SDThumbnailedKeyForKey(NSString * _Nullab /** A transformer protocol to transform the image load from cache or from download. You can provide transformer to cache and manager (Through the `transformer` property or context option `SDWebImageContextImageTransformer`). + From v5.20, the transformer class also can be used on animated image frame post-transform logic, see `SDAnimatedImageView`. @note The transform process is called from a global queue in order to not to block the main queue. */ @@ -50,6 +51,7 @@ FOUNDATION_EXPORT NSString * _Nullable SDThumbnailedKeyForKey(NSString * _Nullab @required /** For each transformer, it must contains its cache key to used to store the image cache or query from the cache. This key will be appened after the original cache key generated by URL or from user. + Which means, the cache should match what your transformer logic do. The same `input image` + `transformer key`, should always generate the same `output image`. @return The cache key to appended after the original cache key. Should not be nil. */ @@ -223,11 +225,14 @@ FOUNDATION_EXPORT NSString * _Nullable SDThumbnailedKeyForKey(NSString * _Nullab The tint color. */ @property (nonatomic, strong, readonly, nonnull) UIColor *tintColor; +/// The blend mode, defaults to `sourceIn` if you use the initializer without blend mode +@property (nonatomic, assign, readonly) CGBlendMode blendMode; - (nonnull instancetype)init NS_UNAVAILABLE; + (nonnull instancetype)new NS_UNAVAILABLE; + (nonnull instancetype)transformerWithColor:(nonnull UIColor *)tintColor; ++ (nonnull instancetype)transformerWithColor:(nonnull UIColor *)tintColor blendMode:(CGBlendMode)blendMode; @end diff --git a/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageTransformer.m b/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageTransformer.m index 8e7a3e2a8..813be2e89 100644 --- a/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageTransformer.m +++ b/dydx/Pods/SDWebImage/SDWebImage/Core/SDImageTransformer.m @@ -245,20 +245,26 @@ - (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key { @interface SDImageTintTransformer () @property (nonatomic, strong, nonnull) UIColor *tintColor; +@property (nonatomic, assign) CGBlendMode blendMode; @end @implementation SDImageTintTransformer + (instancetype)transformerWithColor:(UIColor *)tintColor { + return [self transformerWithColor:tintColor blendMode:kCGBlendModeSourceIn]; +} + ++ (instancetype)transformerWithColor:(UIColor *)tintColor blendMode:(CGBlendMode)blendMode { SDImageTintTransformer *transformer = [SDImageTintTransformer new]; transformer.tintColor = tintColor; + transformer.blendMode = blendMode; return transformer; } - (NSString *)transformerKey { - return [NSString stringWithFormat:@"SDImageTintTransformer(%@)", self.tintColor.sd_hexString]; + return [NSString stringWithFormat:@"SDImageTintTransformer(%@,%d)", self.tintColor.sd_hexString, self.blendMode]; } - (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key { diff --git a/dydx/Pods/SDWebImage/SDWebImage/Core/UIImage+Transform.h b/dydx/Pods/SDWebImage/SDWebImage/Core/UIImage+Transform.h index 60b488ae9..f4c50d3a8 100644 --- a/dydx/Pods/SDWebImage/SDWebImage/Core/UIImage+Transform.h +++ b/dydx/Pods/SDWebImage/SDWebImage/Core/UIImage+Transform.h @@ -98,13 +98,24 @@ typedef NS_OPTIONS(NSUInteger, SDRectCorner) { #pragma mark - Image Blending /** - Return a tinted image with the given color. This actually use alpha blending of current image and the tint color. + Return a tinted image with the given color. This actually use `sourceIn` blend mode. + @note Before 5.20, this API actually use `sourceAtop` and cause naming confusing. After 5.20, we match UIKit's behavior using `sourceIn`. @param tintColor The tint color. @return The new image with the tint color. */ - (nullable UIImage *)sd_tintedImageWithColor:(nonnull UIColor *)tintColor; +/** + Return a tinted image with the given color and blend mode. + @note The blend mode treat `self` as background image (destination), treat `tintColor` as input image (source). So mostly you need `source` variant blend mode (use `sourceIn` not `destinationIn`), which is different from UIKit's `+[UIImage imageWithTintColor:]`. + + @param tintColor The tint color. + @param blendMode The blend mode. + @return The new image with the tint color. + */ +- (nullable UIImage *)sd_tintedImageWithColor:(nonnull UIColor *)tintColor blendMode:(CGBlendMode)blendMode; + /** Return the pixel color at specify position. The point is from the top-left to the bottom-right and 0-based. The returned the color is always be RGBA format. The image must be CG-based. @note The point's x/y will be converted into integer. diff --git a/dydx/Pods/SDWebImage/SDWebImage/Core/UIImage+Transform.m b/dydx/Pods/SDWebImage/SDWebImage/Core/UIImage+Transform.m index 65c7d638a..bed7279d5 100644 --- a/dydx/Pods/SDWebImage/SDWebImage/Core/UIImage+Transform.m +++ b/dydx/Pods/SDWebImage/SDWebImage/Core/UIImage+Transform.m @@ -536,28 +536,177 @@ - (nullable UIImage *)sd_flippedImageWithHorizontal:(BOOL)horizontal vertical:(B #pragma mark - Image Blending +static NSString * _Nullable SDGetCIFilterNameFromBlendMode(CGBlendMode blendMode) { + // CGBlendMode: https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_images/dq_images.html#//apple_ref/doc/uid/TP30001066-CH212-CJBIJEFG + // CIFilter: https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/uid/TP30000136-SW71 + NSString *filterName; + switch (blendMode) { + case kCGBlendModeMultiply: + filterName = @"CIMultiplyBlendMode"; + break; + case kCGBlendModeScreen: + filterName = @"CIScreenBlendMode"; + break; + case kCGBlendModeOverlay: + filterName = @"CIOverlayBlendMode"; + break; + case kCGBlendModeDarken: + filterName = @"CIDarkenBlendMode"; + break; + case kCGBlendModeLighten: + filterName = @"CILightenBlendMode"; + break; + case kCGBlendModeColorDodge: + filterName = @"CIColorDodgeBlendMode"; + break; + case kCGBlendModeColorBurn: + filterName = @"CIColorBurnBlendMode"; + break; + case kCGBlendModeSoftLight: + filterName = @"CISoftLightBlendMode"; + break; + case kCGBlendModeHardLight: + filterName = @"CIHardLightBlendMode"; + break; + case kCGBlendModeDifference: + filterName = @"CIDifferenceBlendMode"; + break; + case kCGBlendModeExclusion: + filterName = @"CIExclusionBlendMode"; + break; + case kCGBlendModeHue: + filterName = @"CIHueBlendMode"; + break; + case kCGBlendModeSaturation: + filterName = @"CISaturationBlendMode"; + break; + case kCGBlendModeColor: + // Color blend mode uses the luminance values of the background with the hue and saturation values of the source image. + filterName = @"CIColorBlendMode"; + break; + case kCGBlendModeLuminosity: + filterName = @"CILuminosityBlendMode"; + break; + + // macOS 10.5+ + case kCGBlendModeSourceAtop: + case kCGBlendModeDestinationAtop: + filterName = @"CISourceAtopCompositing"; + break; + case kCGBlendModeSourceIn: + case kCGBlendModeDestinationIn: + filterName = @"CISourceInCompositing"; + break; + case kCGBlendModeSourceOut: + case kCGBlendModeDestinationOut: + filterName = @"CISourceOutCompositing"; + break; + case kCGBlendModeNormal: // SourceOver + case kCGBlendModeDestinationOver: + filterName = @"CISourceOverCompositing"; + break; + + // need special handling + case kCGBlendModeClear: + // use clear color instead + break; + case kCGBlendModeCopy: + // use input color instead + break; + case kCGBlendModeXOR: + // unsupported + break; + case kCGBlendModePlusDarker: + // chain filters + break; + case kCGBlendModePlusLighter: + // chain filters + break; + } + return filterName; +} + - (nullable UIImage *)sd_tintedImageWithColor:(nonnull UIColor *)tintColor { + return [self sd_tintedImageWithColor:tintColor blendMode:kCGBlendModeSourceIn]; +} + +- (nullable UIImage *)sd_tintedImageWithColor:(nonnull UIColor *)tintColor blendMode:(CGBlendMode)blendMode { BOOL hasTint = CGColorGetAlpha(tintColor.CGColor) > __FLT_EPSILON__; if (!hasTint) { return self; } + // blend mode, see https://en.wikipedia.org/wiki/Alpha_compositing #if SD_UIKIT || SD_MAC // CIImage shortcut - if (self.CIImage) { - CIImage *ciImage = self.CIImage; + CIImage *ciImage = self.CIImage; + if (ciImage) { CIImage *colorImage = [CIImage imageWithColor:[[CIColor alloc] initWithColor:tintColor]]; colorImage = [colorImage imageByCroppingToRect:ciImage.extent]; - CIFilter *filter = [CIFilter filterWithName:@"CISourceAtopCompositing"]; - [filter setValue:colorImage forKey:kCIInputImageKey]; - [filter setValue:ciImage forKey:kCIInputBackgroundImageKey]; - ciImage = filter.outputImage; + NSString *filterName = SDGetCIFilterNameFromBlendMode(blendMode); + // Some blend mode is not nativelly supported + if (filterName) { + CIFilter *filter = [CIFilter filterWithName:filterName]; + [filter setValue:colorImage forKey:kCIInputImageKey]; + [filter setValue:ciImage forKey:kCIInputBackgroundImageKey]; + ciImage = filter.outputImage; + } else { + if (blendMode == kCGBlendModeClear) { + // R = 0 + CIColor *clearColor; + if (@available(iOS 10.0, macOS 10.12, tvOS 10.0, *)) { + clearColor = CIColor.clearColor; + } else { + clearColor = [[CIColor alloc] initWithColor:UIColor.clearColor]; + } + colorImage = [CIImage imageWithColor:clearColor]; + colorImage = [colorImage imageByCroppingToRect:ciImage.extent]; + ciImage = colorImage; + } else if (blendMode == kCGBlendModeCopy) { + // R = S + ciImage = colorImage; + } else if (blendMode == kCGBlendModePlusLighter) { + // R = MIN(1, S + D) + // S + D + CIFilter *filter = [CIFilter filterWithName:@"CIAdditionCompositing"]; + [filter setValue:colorImage forKey:kCIInputImageKey]; + [filter setValue:ciImage forKey:kCIInputBackgroundImageKey]; + ciImage = filter.outputImage; + // MIN + ciImage = [ciImage imageByApplyingFilter:@"CIColorClamp" withInputParameters:nil]; + } else if (blendMode == kCGBlendModePlusDarker) { + // R = MAX(0, (1 - D) + (1 - S)) + // (1 - D) + CIFilter *filter1 = [CIFilter filterWithName:@"CIColorControls"]; + [filter1 setValue:ciImage forKey:kCIInputImageKey]; + [filter1 setValue:@(-0.5) forKey:kCIInputBrightnessKey]; + ciImage = filter1.outputImage; + // (1 - S) + CIFilter *filter2 = [CIFilter filterWithName:@"CIColorControls"]; + [filter2 setValue:colorImage forKey:kCIInputImageKey]; + [filter2 setValue:@(-0.5) forKey:kCIInputBrightnessKey]; + colorImage = filter2.outputImage; + // + + CIFilter *filter = [CIFilter filterWithName:@"CIAdditionCompositing"]; + [filter setValue:colorImage forKey:kCIInputImageKey]; + [filter setValue:ciImage forKey:kCIInputBackgroundImageKey]; + ciImage = filter.outputImage; + // MAX + ciImage = [ciImage imageByApplyingFilter:@"CIColorClamp" withInputParameters:nil]; + } else { + SD_LOG("UIImage+Transform error: Unsupported blend mode: %d", blendMode); + ciImage = nil; + } + } + + if (ciImage) { #if SD_UIKIT UIImage *image = [UIImage imageWithCIImage:ciImage scale:self.scale orientation:self.imageOrientation]; #else UIImage *image = [[UIImage alloc] initWithCIImage:ciImage scale:self.scale orientation:kCGImagePropertyOrientationUp]; #endif return image; + } } #endif @@ -565,9 +714,6 @@ - (nullable UIImage *)sd_tintedImageWithColor:(nonnull UIColor *)tintColor { CGRect rect = { CGPointZero, size }; CGFloat scale = self.scale; - // blend mode, see https://en.wikipedia.org/wiki/Alpha_compositing - CGBlendMode blendMode = kCGBlendModeSourceAtop; - SDGraphicsImageRendererFormat *format = [[SDGraphicsImageRendererFormat alloc] init]; format.scale = scale; SDGraphicsImageRenderer *renderer = [[SDGraphicsImageRenderer alloc] initWithSize:size format:format]; diff --git a/dydx/Pods/SDWebImage/SDWebImage/Private/SDImageFramePool.m b/dydx/Pods/SDWebImage/SDWebImage/Private/SDImageFramePool.m index 1eb2cdb32..8e133d22b 100644 --- a/dydx/Pods/SDWebImage/SDWebImage/Private/SDImageFramePool.m +++ b/dydx/Pods/SDWebImage/SDWebImage/Private/SDImageFramePool.m @@ -31,7 +31,8 @@ + (NSMapTable *)providerFramePoolMap { static NSMapTable *providerFramePoolMap; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - providerFramePoolMap = [NSMapTable mapTableWithKeyOptions:NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPointerPersonality valueOptions:NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPointerPersonality]; + // Key use `hash` && `isEqual:` + providerFramePoolMap = [NSMapTable mapTableWithKeyOptions:NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPersonality valueOptions:NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPointerPersonality]; }); return providerFramePoolMap; } diff --git a/dydx/Pods/Target Support Files/AmplitudeSwift/AmplitudeSwift-Info.plist b/dydx/Pods/Target Support Files/AmplitudeSwift/AmplitudeSwift-Info.plist index ca9aab640..345022540 100644 --- a/dydx/Pods/Target Support Files/AmplitudeSwift/AmplitudeSwift-Info.plist +++ b/dydx/Pods/Target Support Files/AmplitudeSwift/AmplitudeSwift-Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.10.0 + 1.10.1 CFBundleSignature ???? CFBundleVersion diff --git a/dydx/Pods/Target Support Files/AmplitudeSwift/ResourceBundle-Amplitude-AmplitudeSwift-Info.plist b/dydx/Pods/Target Support Files/AmplitudeSwift/ResourceBundle-Amplitude-AmplitudeSwift-Info.plist index 683395142..a2a265b1b 100644 --- a/dydx/Pods/Target Support Files/AmplitudeSwift/ResourceBundle-Amplitude-AmplitudeSwift-Info.plist +++ b/dydx/Pods/Target Support Files/AmplitudeSwift/ResourceBundle-Amplitude-AmplitudeSwift-Info.plist @@ -13,7 +13,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.10.0 + 1.10.1 CFBundleSignature ???? CFBundleVersion diff --git a/dydx/Pods/Target Support Files/SDWebImage/ResourceBundle-SDWebImage-SDWebImage-Info.plist b/dydx/Pods/Target Support Files/SDWebImage/ResourceBundle-SDWebImage-SDWebImage-Info.plist index 841da935d..181ceddee 100644 --- a/dydx/Pods/Target Support Files/SDWebImage/ResourceBundle-SDWebImage-SDWebImage-Info.plist +++ b/dydx/Pods/Target Support Files/SDWebImage/ResourceBundle-SDWebImage-SDWebImage-Info.plist @@ -13,7 +13,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 5.19.7 + 5.20.0 CFBundleSignature ???? CFBundleVersion diff --git a/dydx/Pods/Target Support Files/SDWebImage/SDWebImage-Info.plist b/dydx/Pods/Target Support Files/SDWebImage/SDWebImage-Info.plist index 0cc8a0202..2338335ae 100644 --- a/dydx/Pods/Target Support Files/SDWebImage/SDWebImage-Info.plist +++ b/dydx/Pods/Target Support Files/SDWebImage/SDWebImage-Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 5.19.7 + 5.20.0 CFBundleSignature ???? CFBundleVersion diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/CancelOrders/dydxCancelPendingIsolatedOrdersViewBuilder.swift b/dydx/dydxPresenters/dydxPresenters/_v4/CancelOrders/dydxCancelPendingIsolatedOrdersViewBuilder.swift index 2cb732e65..ec42097ad 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/CancelOrders/dydxCancelPendingIsolatedOrdersViewBuilder.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/CancelOrders/dydxCancelPendingIsolatedOrdersViewBuilder.swift @@ -68,7 +68,7 @@ private class dydxCancelPendingIsolatedOrdersViewBuilderPresenter: HostedViewPre else { return } self.viewModel?.marketLogoUrl = URL(string: asset.resources?.imageUrl ?? "") self.viewModel?.assetName = asset.name ?? "--" - self.viewModel?.assetId = asset.id + self.viewModel?.assetId = asset.displayableAssetId self.viewModel?.orderCount = pendingOrders.count self.viewModel?.failureCount = self.viewModel?.failureCount self.viewModel?.cancelAction = { [weak self] in diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/MarketInfo/Components/dydxMarketConfigsViewPresenter.swift b/dydx/dydxPresenters/dydxPresenters/_v4/MarketInfo/Components/dydxMarketConfigsViewPresenter.swift index 3337e28f3..7c624d58f 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/MarketInfo/Components/dydxMarketConfigsViewPresenter.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/MarketInfo/Components/dydxMarketConfigsViewPresenter.swift @@ -15,6 +15,7 @@ import PlatformUI import Abacus import dydxStateManager import dydxFormatter +import Combine protocol dydxMarketConfigsViewPresenterProtocol: HostedViewPresenterProtocol { var viewModel: dydxMarketConfigsViewModel? { get } @@ -32,17 +33,21 @@ class dydxMarketConfigsViewPresenter: HostedViewPresenter, SharedM static func createViewModel(market: PerpetualMarket, asset: Asset?) -> SharedMarketViewModel { let viewModel = SharedMarketViewModel() - viewModel.assetId = asset?.id ?? market.assetId + viewModel.assetId = asset?.displayableAssetId ?? market.assetId viewModel.assetName = asset?.name ?? market.displayId if let imageUrl = asset?.resources?.imageUrl { viewModel.logoUrl = URL(string: imageUrl) diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/Markets/dydxMarketsViewBuilder.swift b/dydx/dydxPresenters/dydxPresenters/_v4/Markets/dydxMarketsViewBuilder.swift index afa21a31a..15ba4bfa5 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/Markets/dydxMarketsViewBuilder.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/Markets/dydxMarketsViewBuilder.swift @@ -126,7 +126,7 @@ private class dydxMarketsViewPresenter: HostedViewPresenter 0 ? .long : .short let position = dydxFormatter.shared.raw(number: NSNumber(value: abs(funding.positionSize)), digits: configs.displayStepSizeDecimals?.intValue ?? 1) item.position = position - item.token?.symbol = asset.id + item.token?.symbol = asset.displayableAssetId if let url = asset.resources?.imageUrl { item.logoUrl = URL(string: url) } diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/Portfolio/Components/dydxPortfolioOrdersViewPresenter.swift b/dydx/dydxPresenters/dydxPresenters/_v4/Portfolio/Components/dydxPortfolioOrdersViewPresenter.swift index f331ee241..9ff235846 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/Portfolio/Components/dydxPortfolioOrdersViewPresenter.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/Portfolio/Components/dydxPortfolioOrdersViewPresenter.swift @@ -110,7 +110,7 @@ class dydxPortfolioOrdersViewPresenter: HostedViewPresenter 0 ? SideTextViewModel(side: .long, coloringOption: .none) : SideTextViewModel(side: .short, coloringOption: .none), - type: .token(TokenTextViewModel(symbol: asset.id)), + type: .token(TokenTextViewModel(symbol: asset.displayableAssetId)), amount: amount) } diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/Trade/TradeInput/Components/SheetTip/dydxTradeSheetTipDraftViewPresenter.swift b/dydx/dydxPresenters/dydxPresenters/_v4/Trade/TradeInput/Components/SheetTip/dydxTradeSheetTipDraftViewPresenter.swift index 22592e401..3c9b5194e 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/Trade/TradeInput/Components/SheetTip/dydxTradeSheetTipDraftViewPresenter.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/Trade/TradeInput/Components/SheetTip/dydxTradeSheetTipDraftViewPresenter.swift @@ -63,7 +63,7 @@ class dydxTradeSheetTipDraftViewPresenter: HostedViewPresenter "git@github.com:dydxprotocol/v4-abacus.git", :tag => "v#{spec.version}" } spec.authors = '' From 295c39ea75900b9c5b248c3122f1e142bc0def60 Mon Sep 17 00:00:00 2001 From: Rui <102453770+ruixhuang@users.noreply.github.com> Date: Fri, 8 Nov 2024 09:59:51 -0800 Subject: [PATCH 2/2] Lots of bug fixes and vault clean-ups (#290) * Clear the close position box after submission * Adjust Isolated Margin editor triggered from Portfolio * Adding alert indicator * Add y axis to Vault chart * Fix inconsistent tabbar icon opacity. * TRA-833: Vault font size increase * Vault: Update text to "Holding" * TRA-837 Holding count * Fix theming change issue * 1D -> 90D * Fixing input formatting issue with non-english locale * TRA-859 None position * Fixing regression of incorrect market oracle price --- .../Theme/ThemeViewModifiers.swift | 12 ++- .../_v4/Markets/dydxMarketsViewBuilder.swift | 2 +- ...ProfileSecondaryButtonsViewPresenter.swift | 15 +++- .../dydxAdjustMarginInputViewBuilder.swift | 2 + .../dydxTradeStatusViewBuilder.swift | 25 ++++++- .../dydxVaultDepositWithdrawViewBuilder.swift | 69 +++++++++++++----- .../Vault/Landing/dydxVaultViewBuilder.swift | 22 +++--- .../icon_earn.imageset/Contents.json | 2 +- .../icon_earn.imageset/Group 1577.svg | 12 +++ .../icon_earn.imageset/icon_earn.pdf | Bin 2588 -> 0 bytes .../icon_market.imageset/Contents.json | 2 +- .../icon_market.imageset/Vector.svg | 3 + .../icon_market.imageset/icon_market.pdf | Bin 1481 -> 0 bytes .../icon_portfolio.imageset/Contents.json | 2 +- .../icon_portfolio.imageset/Subtract.svg | 3 + .../icon_portfolio.pdf | Bin 1453 -> 0 bytes .../icon_profile.imageset/Contents.json | 2 +- .../icon_profile.imageset/Vector.svg | 3 + .../icon_profile.imageset/icon_profile.pdf | Bin 1249 -> 0 bytes .../dydxTitledNumberField.swift | 5 +- .../Components/dydxMarketListView.swift | 10 +-- .../dydxProfileSecondaryButtonsView.swift | 32 +++++++- .../VaultTransferType.swift | 2 +- .../Landing/dydxVaultChartViewModel.swift | 28 ++++--- .../Vault/Landing/dydxVaultPositionView.swift | 23 +++--- .../Vault/Landing/dydxVaultViewModel.swift | 10 +-- 26 files changed, 208 insertions(+), 78 deletions(-) create mode 100644 dydx/dydxViews/dydxViews/Media.xcassets/icon_earn.imageset/Group 1577.svg delete mode 100644 dydx/dydxViews/dydxViews/Media.xcassets/icon_earn.imageset/icon_earn.pdf create mode 100644 dydx/dydxViews/dydxViews/Media.xcassets/icon_market.imageset/Vector.svg delete mode 100644 dydx/dydxViews/dydxViews/Media.xcassets/icon_market.imageset/icon_market.pdf create mode 100644 dydx/dydxViews/dydxViews/Media.xcassets/icon_portfolio.imageset/Subtract.svg delete mode 100644 dydx/dydxViews/dydxViews/Media.xcassets/icon_portfolio.imageset/icon_portfolio.pdf create mode 100644 dydx/dydxViews/dydxViews/Media.xcassets/icon_profile.imageset/Vector.svg delete mode 100644 dydx/dydxViews/dydxViews/Media.xcassets/icon_profile.imageset/icon_profile.pdf diff --git a/PlatformUI/PlatformUI/DesignSystem/Theme/ThemeViewModifiers.swift b/PlatformUI/PlatformUI/DesignSystem/Theme/ThemeViewModifiers.swift index f2d52da3b..b491e7add 100644 --- a/PlatformUI/PlatformUI/DesignSystem/Theme/ThemeViewModifiers.swift +++ b/PlatformUI/PlatformUI/DesignSystem/Theme/ThemeViewModifiers.swift @@ -326,29 +326,35 @@ public enum ClipStyle { } private struct BorderAndClipModifier: ViewModifier { + @EnvironmentObject var themeSettings: ThemeSettings + let style: ClipStyle let borderColor: ThemeColor.SemanticColor let lineWidth: CGFloat func body(content: Content) -> some View { + let color = themeSettings.themeConfig.themeColor.color(of: borderColor) switch style { case .circle: content .clipShape(Circle()) .overlay(Circle() - .strokeBorder(borderColor.color, lineWidth: lineWidth)) + .strokeBorder(color, lineWidth: lineWidth)) + .environmentObject(themeSettings) case .cornerRadius(let cornerRadius): content .clipShape(.rect(cornerRadius: cornerRadius)) .overlay(RoundedRectangle(cornerRadius: cornerRadius) - .strokeBorder(borderColor.color, lineWidth: lineWidth)) + .strokeBorder(color, lineWidth: lineWidth)) + .environmentObject(themeSettings) case .capsule: content .clipShape(Capsule()) .overlay(Capsule() - .strokeBorder(borderColor.color, lineWidth: lineWidth)) + .strokeBorder(color, lineWidth: lineWidth)) + .environmentObject(themeSettings) } } } diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/Markets/dydxMarketsViewBuilder.swift b/dydx/dydxPresenters/dydxPresenters/_v4/Markets/dydxMarketsViewBuilder.swift index 15ba4bfa5..94212f1db 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/Markets/dydxMarketsViewBuilder.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/Markets/dydxMarketsViewBuilder.swift @@ -130,7 +130,7 @@ private class dydxMarketsViewPresenter: HostedViewPresenter, dydxProfileSecondaryButtonsViewPresenterProtocol { + init(viewModel: dydxProfileSecondaryButtonsViewModel) { super.init() @@ -31,16 +33,23 @@ class dydxProfileSecondaryButtonsViewPresenter: HostedViewPresenter 0 } - } .store(in: &self.subscriptions) } diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift b/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift index dbc2a3400..509e8c242 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/Trade/Margin/dydxAdjustMarginInputViewBuilder.swift @@ -110,6 +110,8 @@ private class dydxAdjustMarginInputViewPresenter: HostedViewPresenter Void) = { + private lazy var doneAction: (() -> Void) = { [weak self] in let notificationPermission = NotificationService.shared?.authorization if notificationPermission?.authorization == .notDetermined { - Router.shared?.navigate(to: RoutingRequest(path: "/action/dismiss"), animated: true, completion: { _, _ in + self?.dismissView { Router.shared?.navigate(to: RoutingRequest(path: "/authorization/notification", params: nil), animated: true, completion: nil) - }) + } } else { - Router.shared?.navigate(to: RoutingRequest(path: "/action/dismiss"), animated: true, completion: nil) + self?.dismissView(completion: nil) + } + } + + private func dismissView(completion: (() -> Void)?) { + switch tradeType { + case .trade: + Router.shared?.navigate(to: RoutingRequest(path: "/action/dismiss"), animated: true) { + _, _ in + completion?() + } + case .closePosition: + Router.shared?.navigate(to: RoutingRequest(path: "/action/dismiss"), animated: true) { + _, _ in + Router.shared?.navigate(to: RoutingRequest(path: "/action/dismiss"), animated: true) { _, _ in + completion?() + } + } } } diff --git a/dydx/dydxPresenters/dydxPresenters/_v4/Vault/DepositsAndWithdrawals/dydxVaultDepositWithdrawViewBuilder.swift b/dydx/dydxPresenters/dydxPresenters/_v4/Vault/DepositsAndWithdrawals/dydxVaultDepositWithdrawViewBuilder.swift index ea95d5005..5e0a5cc81 100644 --- a/dydx/dydxPresenters/dydxPresenters/_v4/Vault/DepositsAndWithdrawals/dydxVaultDepositWithdrawViewBuilder.swift +++ b/dydx/dydxPresenters/dydxPresenters/_v4/Vault/DepositsAndWithdrawals/dydxVaultDepositWithdrawViewBuilder.swift @@ -73,24 +73,38 @@ private class dydxVaultDepositWithdrawViewPresenter: HostedViewPresenter rhs.marginUsdc?.doubleValue ?? 0 } - .map { (position) -> dydxVaultPositionViewModel? in + .compactMap { (position) -> dydxVaultPositionViewModel? in guard - let marketId = position.marketId, - // special case for fake USDC market to show unused margin - let assetId = marketId == "UNALLOCATEDUSDC-USD" ? "USDC" : marketMap[marketId]?.assetId + let marketId = position.marketId else { return nil } + // special case for fake USDC market to show unused margin + let assetId = marketId == "UNALLOCATEDUSDC-USD" ? "USDC" : marketMap[marketId]?.assetId let leverage = position.currentLeverageMultiple?.doubleValue - let asset = assetMap[assetId] + let asset: Asset? + if let assetId = assetId { + asset = assetMap[assetId] + } else { + asset = nil + } let equity = position.marginUsdc?.doubleValue ?? 0 let notionalValue = position.currentPosition?.usdc?.doubleValue ?? 0 let positionSize = position.currentPosition?.asset?.doubleValue ?? 0 @@ -129,7 +134,7 @@ private class dydxVaultViewBuilderPresenter: HostedViewPresenter + + + + + + + + + + + diff --git a/dydx/dydxViews/dydxViews/Media.xcassets/icon_earn.imageset/icon_earn.pdf b/dydx/dydxViews/dydxViews/Media.xcassets/icon_earn.imageset/icon_earn.pdf deleted file mode 100644 index 8116bc9f53866eb8285640a15242e17216bef0f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2588 zcmaJ@dpMJQA17K`480vZRBmKBZ?mjqM$try5QQ*ylS5l=Lkf{n$(#xasfQ9pERnKQ z7|kiTmf79tlE)P})NXZj8^MUug5-L7o4LTx?p=&p^4$Z_B zwcNWhZx(u`_Kk~nSE4bhjAj4ai1J6!>J*SpE+iR z-q-%F8D4mIq^f!Juq@d$a;{6>%gJs~R%TdVD|Y)}SoWFVEGT2e7^j@jP_A;qDx|n) zOO24uK{sWpK4qv_Rm|RCPs*@+GR8N1z|$g3g&TZ6djQ3T3hCUu$abxKz;KiA%J$L4 zA!H}vk32e5^HUva|lItQ3Q|9MbMdP)aJiRPty?qL9+l zCgjy)d|O#**W+!~wdZaIc^ZrwRPb>ID%PPmr5Z^>rF7=oJcZImx;7_0Ld7>*VLhh* zwjW%6MU6@+gtG{_#j%(Z!?e*?uef)RFIiNrP~PaOuNo_S;<`3DA-`fuV_)n!X^UDt zi<5_1aBO;f+&kM~U8{kH3|Bq7K>7-KKK)wvYuRZciKRuEKE zMz&)njx*$5^a-onSw}L}*L6HT0`G~8=PKTrl>AzSroQj#@|Q?)6-2C2Jbw@DV5>ph$6Iz-T|!8XgKQG2>V(-IW_ zf)Jmrm(8nwiUjte2ocHaMh8oB)2HoXFEV+`&&Q*>JY~3`{`sx(uxAvDTN*ElSkp3T z1obBhsKz9(%)5ycjiO_^n72(Dhu<{mr{&+n$1S-MWGHaWBAA^F47WZk9Tf;9foL-0jw$up{CfgdU%Y?d`dGT1&cCtDy1I z5Un> z@?b~bj4w<^g_T>T9JOKkCca*CoZ(MXqDMzdK&x~j)Rdk}J-;i3{CswCF#S@4Q@BGw zJtb^oo7De%(v7nl)Y;Bp7ylZl9plDgO5b`Zp@b~_yD+rC%*i>`dDN(FtD3g~oA;o# zIV<9#ivM-D(ye~$qBZ<{OR+^p4%k{@-1kT6K48L-HIrp?Uco66$q?|HDm=M$dL{D4Zs^nU6GHz%vMDB&+2U5)DKi>!$dgQ&0*l~HP;Jjs`gHMp$i`oNS(+!k@tF_qY04NXp_@%zW{TP`+ zyG-d>0vQ~>w_@N5!xCQ)fonS$#Tr-Cbkbj!DXrE?@OcPO{yt5dEBAVRYfO8p*}B;6+)6 zQ0jKv%$6a<0O~=U1JIn;jT>`8z%m{jNAu`*UfzM-j(UEy$^MMGk0^f4h7!mH$|Mqi z-}|y<4uWT84U38V2NN$)x|pNCQ$5NUW&D%rH~xf03IMT{L?Y9ufZKr|{O%NX7z7aZ z1iuBs-vtu=3ERj=0XG0?fc$2^4u+To=+|i>k^@L32UC1NDj?PzVzD6B4;Ew+4J3&& ziUr34XiuPsFu>>s^eFfo~^(^bJ-~g z$PkI%^aq6bUq?ejv}kj`JED=l9BCASe-KE4innKNDH?|sm3#=)2DJQ%+TVwQa3GUu ifVkmr14cOd9|J|zf75CN3hi4vhG+~1s;Rl%4*y>h$ae_< diff --git a/dydx/dydxViews/dydxViews/Media.xcassets/icon_market.imageset/Contents.json b/dydx/dydxViews/dydxViews/Media.xcassets/icon_market.imageset/Contents.json index eb657bfe5..46d18a644 100644 --- a/dydx/dydxViews/dydxViews/Media.xcassets/icon_market.imageset/Contents.json +++ b/dydx/dydxViews/dydxViews/Media.xcassets/icon_market.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "icon_market.pdf", + "filename" : "Vector.svg", "idiom" : "universal" } ], diff --git a/dydx/dydxViews/dydxViews/Media.xcassets/icon_market.imageset/Vector.svg b/dydx/dydxViews/dydxViews/Media.xcassets/icon_market.imageset/Vector.svg new file mode 100644 index 000000000..70c36e02c --- /dev/null +++ b/dydx/dydxViews/dydxViews/Media.xcassets/icon_market.imageset/Vector.svg @@ -0,0 +1,3 @@ + + + diff --git a/dydx/dydxViews/dydxViews/Media.xcassets/icon_market.imageset/icon_market.pdf b/dydx/dydxViews/dydxViews/Media.xcassets/icon_market.imageset/icon_market.pdf deleted file mode 100644 index 8b2a4f00ca54612311f0c5568765732a34e640af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1481 zcmY!laBXcJN0zl9RnWM@Bg^gbB747{JxF9yp|R52I33jDB=*SH3&`;BCad$%n7b-Li@6hKQN`?=8y~*DlNAG&Wr_ zFCvI{mu5xbs&y67oHjnukxHeH1x>#GTP<_dk$qjR=-k-+xl?a{e7!)f#i=1`f=WqA zz3=Ia)(s2fvR123bTM2yY2#i#Z`Cvz!|o0H|Nc95vot1J+se6&cWZf@{qlsE8L!U7 zb*c7*~e!0) zsm~2P8K+d++8#38IHPF6E%tN95uPi}Y&<2MPcgsOGEkdV*vPwX=PB)Gi!Xw&9sD@w z+}3!}?yR?Sk(R`i)K>`>Yj>En<#4G^SMlp@3Ophfa8WclV{d8Gqc~~(D^bG!yJC(h z7*+f`5N3XE&GngUueh}*Z#rn2wE9uEf%Wf0XSVBKyY>0&Z5bZLt88fk9?xH8ZEM)O zD)-dg$jSE(w=K}ydoIL<$#zomrR%egH|^dmsC1pfbIwh{R2JsPjq5p>_IGl7ysl6c z&f0Rp$nJpSkrJ+>CEF%^knUh)@LXMd?X$gKeb#H58DWZsL#u6_WmjrU7?`Xxj*Pw2anJ4$r^uEJ`c+OUPQy>}B z+}s$R-Av%3pzP|HmzQ5stPmXw&14~!1*r=90g36bT<4pbl9}j~U!f2U%)+1y49voC zhLH(O2*HAx6qH(=Us{x$TC4ynAV4`5l!=}5^GZ_lfHs11Jxnklu?Q%pUxv8288ks4YkU-H7%Fi!R0C^Z3!1}?N aRjEMNgA2^Wq7txo42?`Jxl~nM{oMd7bsk0l diff --git a/dydx/dydxViews/dydxViews/Media.xcassets/icon_portfolio.imageset/Contents.json b/dydx/dydxViews/dydxViews/Media.xcassets/icon_portfolio.imageset/Contents.json index 624a796dc..97dc67bf3 100644 --- a/dydx/dydxViews/dydxViews/Media.xcassets/icon_portfolio.imageset/Contents.json +++ b/dydx/dydxViews/dydxViews/Media.xcassets/icon_portfolio.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "icon_portfolio.pdf", + "filename" : "Subtract.svg", "idiom" : "universal" } ], diff --git a/dydx/dydxViews/dydxViews/Media.xcassets/icon_portfolio.imageset/Subtract.svg b/dydx/dydxViews/dydxViews/Media.xcassets/icon_portfolio.imageset/Subtract.svg new file mode 100644 index 000000000..111830d54 --- /dev/null +++ b/dydx/dydxViews/dydxViews/Media.xcassets/icon_portfolio.imageset/Subtract.svg @@ -0,0 +1,3 @@ + + + diff --git a/dydx/dydxViews/dydxViews/Media.xcassets/icon_portfolio.imageset/icon_portfolio.pdf b/dydx/dydxViews/dydxViews/Media.xcassets/icon_portfolio.imageset/icon_portfolio.pdf deleted file mode 100644 index 8c0750783da928ed30b2152e1bb017f4b555eccc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1453 zcmY!laBvK;I`dFTEr~!5FAK2q*+Jp}3?dH8Gc~f-!aK**;ZM9=GpbMYg&rC0lQl z&1dX1{lF34?C?sCv-im7;-J{z(42=Kr7lZ!iD7 z|N8Z}^UHku@~7u_%dfxsz54p2ulqcUFLJT=Nv)dP8t!rK@9Wp6A6Crxk#}vCP4=7j z2P9S+m%rBibtdI%%;}nUW)>Uw?cJVuIavP1R>^z8H!Ch|Kf9$@)ACod(1zWa+?p$7 z#WBBzpH;jncX`8AZif3opLG8nJ@yJ(<%qzQ*_^;r@-qXe#WS=wC@VDmk zSELoGx*tDRvtDV!`_Spvzg@riNp9Qf^@-fCKKygMo1~|;Zec|_+tFiMA2SvPv+e7M zO%m#k?9FQpe|xrS`Ul(TUygjp4L-E$m(Bt&k)I82RVB9(P_DU+~|S$|EZ( zohOuiT*#k)NiE5u%C$Ck^6R9SxqCHCCNZmCta5t0E&7Z}@w&}zik}5JW;$|mUTEL( z_TI8D*pGx9E;jFiRpJ0^qVHV!qX09nT+f&ms zJ4y8LkLHvPSEoCNZ=7md=_&WzjqBp~n~yqX+dL1 zdh+TMY?C6-#GB4+E$eW9rqOY=WY(5*tj*!F&x~BJ?VNKZRx#y5_RBS;uG7wzygMqj zbIGeszxJf%`)x0^KG}2Kc;}QIp^0`A7u(KU*t#iXLVfRv-Z*I`&pGYi+m1e6l-~3I zDKDcBQ^do#xn``z8tv)Hjl`1l=yt%_*-L;7f zsXmkIjJ&E{R$cR*8_&8TY-Mt!ZtU?Vb`Ju>KlVpUU48kr>#VWD+{*!RK1)Ad@GI_Q zUaWpNao;MRdcJS}#gq2R)c@O1d$aELKju2_m;zANg60iaCIjUfNai!QFokD56Syca zOX@r3<>i+YD@4aaGh9ezL8^j&Kw>&92l}R_WF|W0S13d)80Z;*0fJ#<0uw^8U?v5n z7U!21C8riEfC>Rn?geFN=lr~q)I6Y#pb`Kk7?4;56jLyT3L%vfAR&19q3@lU0(7bZ z$Ol0RFngTyOM!X~G2CAaDKB7wVTNK7$b-dj3qcNpc-%R$BrzvH9aU>ZQED2Ofr2>~ z#QPvp!OYau*i->13 + + diff --git a/dydx/dydxViews/dydxViews/Media.xcassets/icon_profile.imageset/icon_profile.pdf b/dydx/dydxViews/dydxViews/Media.xcassets/icon_profile.imageset/icon_profile.pdf deleted file mode 100644 index 209b37afb5c308c580ff51036e8c98d6acbb1bf3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1249 zcmY!laBXc8|>XDYRGfvxyW8OrN{Mebmcd)^<8+RZm7I)qJ{m`nU$W+C!%f2OLL~5 zzFPi%-=BYlbw9s6Jp1um@$TFH&y#;&eRuEk$F~~`moG2Apj)wb(O13+n{G+`zE*jE zg>@k-^A@9LE)PUaK2_MrOPzkJ_gi;Y{+d|l?3lo9a?Tu28+RV@m>rn0<8f{Y_vVhr zIUUV2T=?bgdfb>`Y&Cm{ve%W1OcQ%grrpugD4)7uO61?Ai#Trdmt2Y4>$-dO?ptT# zbdK)g75$d%uUtLL^!u?1zMIuNV=pju1}05!vV1-BbNpQQ>s|r71A6)lZyc!d-L&xZ z3GO?$)?`h1?0V>`XqL`eaqAO>(Wj)CB%~h19J_nt=05YiwmN1Jb>YF=Zb-~=oh7t_ zgU_yLmd9z0KNI2}CN&iqO#7r^E#f38a$v3FxgAUQw)GoMY;q5jNn)!r?*F~Vxv1j& zky*^Hy(bo!>=96uV0Ch4=9nD2#(}XiVynoOnc6{`cRt0Pi!|UV)tjgjVz6VOgKWwH z&M)Vt**ddJeUv%z>F3tYjfWQ8NtSbo-rCxzw}a=r!}M0C(69}Szjh}bU{`8sjg3k^ znsTyb&e4g62NpDC3flNHRY&YniDz%?-E&Iu%_Y{f%^~bZb>*hb`eE>Am7&81Z(fa` zo46drG*38u*rV^@7`LM|QoH8=`)?ObZI&H<*t6VNx6ghK@7(_zulvt<_j>iW3wGP= zcl!SL4oYUwbOK9opcDj2u%;%4@MLHL7X>9_$Gp7!l46DESZLx4sVqoU&<{vVhowf} z)RfFbr~C?qXkgL?C2U~QhBJ(e^^DDp4NS}xj7(vYFq48(i}Op1l2eNnKp6*=l0k{v zIX|x?H4kVbC^x_a0}_jXVhW~EAz+G!c>yGZ$aCJADL|(xfP4_70JFzAzZ9s~5X1e& zkh}vk$qdCLkOzz57J?iG@wjthNn%cZI;z%+qSQ1l0|j#~i1)!kU}kD+Y^nehh5|!i zsDLH%;6mm=ccKcJSz4kCnHvE^2UV4YC5A>zGYhz?lA^@SoYW#NQ0#fS0E0uLI6pU4 wQ$Zs$MH3Pz`a${mB?=%9g9BJUII}7h=z4HLl2}v%_Ku-}kvW&Ds;j>n0FA1&M*si- diff --git a/dydx/dydxViews/dydxViews/Shared/dydxComponents/dydxTitledNumberField.swift b/dydx/dydxViews/dydxViews/Shared/dydxComponents/dydxTitledNumberField.swift index 489f11586..16667dc22 100644 --- a/dydx/dydxViews/dydxViews/Shared/dydxComponents/dydxTitledNumberField.swift +++ b/dydx/dydxViews/dydxViews/Shared/dydxComponents/dydxTitledNumberField.swift @@ -85,6 +85,7 @@ struct dydxTitledNumberField: View { } textFieldView } + if isMaxButtonVisible { Spacer() maxButton @@ -123,7 +124,7 @@ private struct NumberTextField: View { .keyboardType(keyboardType) .focused($isFocused) .onChange(of: isFocused) { _ in - if !isFocused, let value = Double(filteredTextBinding.wrappedValue) { + if !isFocused, let value = Parser.standard.asInputDecimal(filteredTextBinding.wrappedValue)?.doubleValue { actualValue = formatValue(value) } } @@ -149,7 +150,7 @@ private struct NumberTextField: View { } }, set: { newValue in - if let doubleValue = Double(newValue) { + if let doubleValue = Parser.standard.asInputDecimal(newValue)?.doubleValue { actualValue = formatValue(clamp(doubleValue)) } else { actualValue = nil diff --git a/dydx/dydxViews/dydxViews/_v4/Markets/Components/dydxMarketListView.swift b/dydx/dydxViews/dydxViews/_v4/Markets/Components/dydxMarketListView.swift index 1e9937b1c..e6daa4771 100644 --- a/dydx/dydxViews/dydxViews/_v4/Markets/Components/dydxMarketListView.swift +++ b/dydx/dydxViews/dydxViews/_v4/Markets/Components/dydxMarketListView.swift @@ -26,14 +26,14 @@ public class dydxMarketListViewModel: PlatformViewModeling { iconUrl: "https://assets.coingecko.com/coins/images/1/large/bitcoin.png", volume24H: 1_000_000_000, sparkline: [1, 2, 3, 4, 5], - price: 50_000, + price: "50_000", change: 0.05), dydxMarketViewModel(marketId: "ETH-USD", assetId: "ETH", iconUrl: "https://assets.coingecko.com/coins/images/279/large/ethereum.png", volume24H: 500_000_000, sparkline: [5, 4, 3, 2, 1], - price: 3_000, + price: "3_000", change: -0.05) ] return vm @@ -74,7 +74,7 @@ public class dydxMarketViewModel: PlatformViewModeling { public let iconUrl: String? public let volume24H: Double? public let sparkline: [Double]? - public let price: Double? + public let price: String? public let change: Double? @Published public var isFavorite: Bool? @@ -87,7 +87,7 @@ public class dydxMarketViewModel: PlatformViewModeling { iconUrl: String?, volume24H: Double?, sparkline: [Double]?, - price: Double?, + price: String?, change: Double?, isFavorite: Bool? = nil ) { @@ -147,7 +147,7 @@ struct dydxMarketView: View { var priceChangeVStack: some View { VStack(alignment: .trailing, spacing: 2) { - Text(dydxFormatter.shared.dollar(number: viewModel.price) ?? "--") + Text(viewModel.price ?? "--") .themeFont(fontType: .plus, fontSize: .medium) .themeColor(foreground: .textPrimary) SignedAmountViewModel(amount: viewModel.change, displayType: .percent, coloringOption: .allText) diff --git a/dydx/dydxViews/dydxViews/_v4/Profile/Components/dydxProfileSecondaryButtonsView.swift b/dydx/dydxViews/dydxViews/_v4/Profile/Components/dydxProfileSecondaryButtonsView.swift index d8c846748..0e85414b5 100644 --- a/dydx/dydxViews/dydxViews/_v4/Profile/Components/dydxProfileSecondaryButtonsView.swift +++ b/dydx/dydxViews/dydxViews/_v4/Profile/Components/dydxProfileSecondaryButtonsView.swift @@ -13,6 +13,7 @@ public class dydxProfileSecondaryButtonsViewModel: PlatformViewModel { @Published public var settingsAction: (() -> Void)? @Published public var helpAction: (() -> Void)? @Published public var alertsAction: (() -> Void)? + @Published public var hasNewAlerts: Bool = false public init() { } @@ -39,9 +40,34 @@ public class dydxProfileSecondaryButtonsViewModel: PlatformViewModel { @ViewBuilder private var alertsRow: some View { if let alertsAction { - self.createButton(imageName: "icon_alerts", - title: DataLocalizer.localize(path: "APP.GENERAL.ALERTS"), - action: alertsAction) + HStack(spacing: 8) { + PlatformIconViewModel(type: .asset(name: "icon_alerts", bundle: Bundle.dydxView), + clip: .noClip, + size: CGSize(width: 24, height: 24), + templateColor: .textTertiary) + .createView() + + Text(DataLocalizer.localize(path: "APP.GENERAL.ALERTS")) + .themeFont(fontSize: .medium) + .themeColor(foreground: .textPrimary) + .lineLimit(1) + + Spacer() + + if hasNewAlerts { + Circle() + .fill(ThemeColor.SemanticColor.colorPurple.color) + .frame(width: 10, height: 10) + } + } + .padding(.horizontal, 16) + .padding(.vertical, 22) + .themeColor(background: .layer3) + .cornerRadius(12, corners: .allCorners) + .frame(maxWidth: .infinity) + .onTapGesture { + alertsAction() + } } } diff --git a/dydx/dydxViews/dydxViews/_v4/Vault/DepositAndWithdrawal/VaultTransferType.swift b/dydx/dydxViews/dydxViews/_v4/Vault/DepositAndWithdrawal/VaultTransferType.swift index 5870e745f..9d6c508f3 100644 --- a/dydx/dydxViews/dydxViews/_v4/Vault/DepositAndWithdrawal/VaultTransferType.swift +++ b/dydx/dydxViews/dydxViews/_v4/Vault/DepositAndWithdrawal/VaultTransferType.swift @@ -72,7 +72,7 @@ public enum VaultTransferType: CaseIterable, RadioButtonContentDisplayable { var transferDestinationSubtitleText: String { switch self { - case .deposit: return DataLocalizer.localize(path: "APP.VAULTS.PROTOCOL_VAULT") + case .deposit: return DataLocalizer.localize(path: "APP.VAULTS.MEGAVAULT") case .withdraw: return DataLocalizer.localize(path: "APP.VAULTS.CROSS_ACCOUNT") } } diff --git a/dydx/dydxViews/dydxViews/_v4/Vault/Landing/dydxVaultChartViewModel.swift b/dydx/dydxViews/dydxViews/_v4/Vault/Landing/dydxVaultChartViewModel.swift index 00ce0ee65..4f7994991 100644 --- a/dydx/dydxViews/dydxViews/_v4/Vault/Landing/dydxVaultChartViewModel.swift +++ b/dydx/dydxViews/dydxViews/_v4/Vault/Landing/dydxVaultChartViewModel.swift @@ -12,6 +12,7 @@ import Utilities import Charts import Combine import dydxChart +import dydxFormatter public class dydxVaultChartViewModel: PlatformViewModel { public struct Entry { @@ -53,19 +54,19 @@ public class dydxVaultChartViewModel: PlatformViewModel { } public enum ValueTimeOption: CaseIterable, RadioButtonContentDisplayable { - case oneDay case sevenDays case thirtyDays + case ninetyDays var displayText: String { let path: String switch self { - case .oneDay: - path = "APP.GENERAL.TIME_STRINGS.1D" case .sevenDays: path = "APP.GENERAL.TIME_STRINGS.7D" case .thirtyDays: path = "APP.GENERAL.TIME_STRINGS._30D" + case .ninetyDays: + path = "APP.GENERAL.TIME_STRINGS.90D" } return DataLocalizer.shared?.localize(path: path, params: nil) ?? "" } @@ -111,6 +112,7 @@ private struct dydxVaultChartView: View { .frame(minWidth: geometry.size.width, alignment: .center) } } + .frame(height: 38) } private var chart: some View { @@ -119,7 +121,7 @@ private struct dydxVaultChartView: View { y: .value("", entry.value)) .lineStyle(StrokeStyle(lineWidth: 2)) .foregroundStyle(viewModel.lineColor.gradient) - .interpolationMethod(.linear) + .interpolationMethod(.monotone) .symbolSize(0) // adds gradient shading AreaMark( @@ -130,16 +132,24 @@ private struct dydxVaultChartView: View { .foregroundStyle(chartGradient) } .chartXAxis(.hidden) - .chartYAxis(.hidden) + .chartYAxis { + AxisMarks(values: .automatic) { + let value = dydxFormatter.shared.condensedDollar(number: $0.as(Double.self)) + AxisValueLabel { + if let value { + Text(value) + } + } + .font(Font.system(size: 8)) + .foregroundStyle(ThemeColor.SemanticColor.textTertiary.color) + } + } .chartXScale(domain: .automatic(includesZero: false)) .chartYScale(domain: .automatic(includesZero: false)) - - // the lines can extend outside of chart - .padding(.all, 1) } var body: some View { - VStack(spacing: 12) { + VStack(spacing: 8) { radioButtonsRow chart } diff --git a/dydx/dydxViews/dydxViews/_v4/Vault/Landing/dydxVaultPositionView.swift b/dydx/dydxViews/dydxViews/_v4/Vault/Landing/dydxVaultPositionView.swift index 3fc18989e..80af20a38 100644 --- a/dydx/dydxViews/dydxViews/_v4/Vault/Landing/dydxVaultPositionView.swift +++ b/dydx/dydxViews/dydxViews/_v4/Vault/Landing/dydxVaultPositionView.swift @@ -33,11 +33,16 @@ public class dydxVaultPositionViewModel: PlatformViewModel { fileprivate var sideLeverageAttributedText: AttributedString { let attributedSideText = AttributedString(text: side.text, urlString: nil) .themeColor(foreground: side.color) - let leverageText = dydxFormatter.shared.leverage(number: leverage) ?? "--" - let attributedLeverageText = AttributedString(text: "@ " + leverageText, urlString: nil) - .themeColor(foreground: .textTertiary) - return (attributedSideText + attributedLeverageText) + if let leverage = leverage { + let leverageText = dydxFormatter.shared.leverage(number: leverage) ?? "--" + let attributedLeverageText = AttributedString(text: " @ " + leverageText, urlString: nil) + .themeColor(foreground: .textTertiary) + return (attributedSideText + attributedLeverageText) .themeFont(fontType: .base, fontSize: .smaller) + } else { + return attributedSideText + .themeFont(fontType: .base, fontSize: .smaller) + } } fileprivate var notionalValueText: String { @@ -175,10 +180,10 @@ struct VaultPositionView: View { var body: some View { HStack(spacing: Self.interSectionPadding) { - marketSection - .frame(width: Self.marketSectionWidth) - sizeSection - pnlSection - } + marketSection + .frame(width: Self.marketSectionWidth) + sizeSection + pnlSection + } } } diff --git a/dydx/dydxViews/dydxViews/_v4/Vault/Landing/dydxVaultViewModel.swift b/dydx/dydxViews/dydxViews/_v4/Vault/Landing/dydxVaultViewModel.swift index 3bc82f261..18ebf80cf 100644 --- a/dydx/dydxViews/dydxViews/_v4/Vault/Landing/dydxVaultViewModel.swift +++ b/dydx/dydxViews/dydxViews/_v4/Vault/Landing/dydxVaultViewModel.swift @@ -155,7 +155,7 @@ private struct dydxVaultView: View { Spacer(minLength: 4) Text(dydxFormatter.shared.dollar(number: viewModel.vaultBalance) ?? "--") .themeColor(foreground: .textPrimary) - .themeFont(fontType: .base, fontSize: .medium) + .themeFont(fontType: .base, fontSize: .large) } .leftAligned() .padding(.horizontal, 16) @@ -171,7 +171,7 @@ private struct dydxVaultView: View { Spacer(minLength: 4) Text(dydxFormatter.shared.dollar(number: viewModel.allTimeReturnUsdc) ?? "--") .themeColor(foreground: viewModel.allTimeReturnUsdc == nil ? .textPrimary : ThemeSettings.directionalColor(forValue: viewModel.allTimeReturnUsdc)) - .themeFont(fontType: .base, fontSize: .medium) + .themeFont(fontType: .base, fontSize: .large) } .leftAligned() .padding(.horizontal, 16) @@ -196,7 +196,7 @@ private struct dydxVaultView: View { .themeFont(fontType: .base, fontSize: .small) Text(dydxFormatter.shared.percent(number: viewModel.thirtyDayReturnPercent, digits: 0) ?? "") .themeColor(foreground: ThemeSettings.directionalColor(forValue: viewModel.thirtyDayReturnPercent)) - .themeFont(fontType: .base, fontSize: .medium) + .themeFont(fontType: .base, fontSize: .large) } } @@ -207,7 +207,7 @@ private struct dydxVaultView: View { .themeFont(fontType: .base, fontSize: .small) Text(dydxFormatter.shared.dollar(number: viewModel.totalValueLocked, digits: 0) ?? "") .themeColor(foreground: .textPrimary) - .themeFont(fontType: .base, fontSize: .medium) + .themeFont(fontType: .base, fontSize: .large) } } @@ -221,7 +221,7 @@ private struct dydxVaultView: View { // MARK: - Section 4 - positions private var openPositionsHeader: some View { HStack(spacing: 8) { - Text(DataLocalizer.shared?.localize(path: "APP.TRADE.OPEN_POSITIONS", params: nil) ?? "") + Text(DataLocalizer.shared?.localize(path: "APP.VAULTS.HOLDINGS", params: nil) ?? "") .themeColor(foreground: .textSecondary) .themeFont(fontType: .base, fontSize: .larger) Text("\(viewModel.positions?.count ?? 0)")