[#1360] Shared state is broken on older ios versions
- Fixes for iOS 16 and older
This commit is contained in:
parent
98ccc6a235
commit
9fe249ee1b
|
@ -6,6 +6,11 @@ directly impact users rather than highlighting other crucial architectural updat
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Splash screen animation is blocked by the main thread on iOS 16 and older.
|
||||||
|
- Inactive hide balances button on iOS 16 and older.
|
||||||
|
- Inactive close button in the exchange rate hint bubble on iOS 16 and older.
|
||||||
|
|
||||||
## 1.2 build 9 (2024-09-17)
|
## 1.2 build 9 (2024-09-17)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
@ -26,7 +26,7 @@ class ExchangeRateProvider {
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
if !_XCTIsTesting {
|
if !_XCTIsTesting {
|
||||||
@Dependency (\.sdkSynchronizer) var sdkSynchronizer
|
@Dependency(\.sdkSynchronizer) var sdkSynchronizer
|
||||||
|
|
||||||
cancellable = sdkSynchronizer.exchangeRateUSDStream().sink { [weak self] result in
|
cancellable = sdkSynchronizer.exchangeRateUSDStream().sink { [weak self] result in
|
||||||
self?.resolveResult(result)
|
self?.resolveResult(result)
|
||||||
|
@ -37,7 +37,7 @@ class ExchangeRateProvider {
|
||||||
func refreshExchangeRateUSD() {
|
func refreshExchangeRateUSD() {
|
||||||
if !_XCTIsTesting {
|
if !_XCTIsTesting {
|
||||||
// guard the feature is opted-in by a user
|
// guard the feature is opted-in by a user
|
||||||
@Dependency (\.userStoredPreferences) var userStoredPreferences
|
@Dependency(\.userStoredPreferences) var userStoredPreferences
|
||||||
|
|
||||||
guard let exchangeRate = userStoredPreferences.exchangeRate(), exchangeRate.automatic else {
|
guard let exchangeRate = userStoredPreferences.exchangeRate(), exchangeRate.automatic else {
|
||||||
return
|
return
|
||||||
|
@ -47,7 +47,7 @@ class ExchangeRateProvider {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@Dependency (\.sdkSynchronizer) var sdkSynchronizer
|
@Dependency(\.sdkSynchronizer) var sdkSynchronizer
|
||||||
|
|
||||||
sdkSynchronizer.refreshExchangeRateUSD()
|
sdkSynchronizer.refreshExchangeRateUSD()
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ class ExchangeRateProvider {
|
||||||
|
|
||||||
latestRate = result
|
latestRate = result
|
||||||
|
|
||||||
@Dependency (\.zcashSDKEnvironment) var zcashSDKEnvironment
|
@Dependency(\.zcashSDKEnvironment) var zcashSDKEnvironment
|
||||||
|
|
||||||
if isStale
|
if isStale
|
||||||
&& result.state != .fetching
|
&& result.state != .fetching
|
||||||
|
@ -88,7 +88,7 @@ class ExchangeRateProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
if latestRate.state == .success {
|
if latestRate.state == .success {
|
||||||
@Dependency (\.zcashSDKEnvironment) var zcashSDKEnvironment
|
@Dependency(\.zcashSDKEnvironment) var zcashSDKEnvironment
|
||||||
|
|
||||||
isStale = false
|
isStale = false
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,7 @@ extension Root {
|
||||||
|
|
||||||
case .splashFinished:
|
case .splashFinished:
|
||||||
state.splashAppeared = true
|
state.splashAppeared = true
|
||||||
|
exchangeRate.refreshExchangeRateUSD()
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .tabs, .initialization, .onboarding, .sandbox, .updateStateAfterConfigUpdate, .alert, .phraseDisplay, .synchronizerStateChanged,
|
case .tabs, .initialization, .onboarding, .sandbox, .updateStateAfterConfigUpdate, .alert, .phraseDisplay, .synchronizerStateChanged,
|
||||||
|
|
|
@ -158,7 +158,6 @@ extension Root {
|
||||||
guard sdkSynchronizer.latestState().syncStatus.isPrepared else {
|
guard sdkSynchronizer.latestState().syncStatus.isPrepared else {
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
exchangeRate.refreshExchangeRateUSD()
|
|
||||||
return .run { [state] send in
|
return .run { [state] send in
|
||||||
do {
|
do {
|
||||||
try await sdkSynchronizer.start(true)
|
try await sdkSynchronizer.start(true)
|
||||||
|
@ -294,7 +293,6 @@ extension Root {
|
||||||
case .initialization(.initializationSuccessfullyDone(let uAddress)):
|
case .initialization(.initializationSuccessfullyDone(let uAddress)):
|
||||||
state.tabsState.addressDetailsState.uAddress = uAddress
|
state.tabsState.addressDetailsState.uAddress = uAddress
|
||||||
state.tabsState.settingsState.advancedSettingsState.uAddress = uAddress
|
state.tabsState.settingsState.advancedSettingsState.uAddress = uAddress
|
||||||
exchangeRate.refreshExchangeRateUSD()
|
|
||||||
return .merge(
|
return .merge(
|
||||||
.send(.initialization(.registerForSynchronizersUpdate)),
|
.send(.initialization(.registerForSynchronizersUpdate)),
|
||||||
.publisher {
|
.publisher {
|
||||||
|
|
|
@ -146,93 +146,97 @@ public struct TabsView: View {
|
||||||
.zashiTitle { navBarView(store.selectedTab) }
|
.zashiTitle { navBarView(store.selectedTab) }
|
||||||
.walletStatusPanel()
|
.walletStatusPanel()
|
||||||
.overlayPreferenceValue(BoundsPreferenceKey.self) { preferences in
|
.overlayPreferenceValue(BoundsPreferenceKey.self) { preferences in
|
||||||
if store.isRateTooltipEnabled {
|
WithPerceptionTracking {
|
||||||
GeometryReader { geometry in
|
if store.isRateTooltipEnabled {
|
||||||
preferences.map {
|
GeometryReader { geometry in
|
||||||
Tooltip(
|
preferences.map {
|
||||||
title: L10n.Tooltip.ExchangeRate.title,
|
Tooltip(
|
||||||
desc: L10n.Tooltip.ExchangeRate.desc
|
title: L10n.Tooltip.ExchangeRate.title,
|
||||||
) {
|
desc: L10n.Tooltip.ExchangeRate.desc
|
||||||
store.send(.rateTooltipTapped)
|
) {
|
||||||
|
store.send(.rateTooltipTapped)
|
||||||
|
}
|
||||||
|
.frame(width: geometry.size.width - 40)
|
||||||
|
.offset(x: 20, y: geometry[$0].minY + geometry[$0].height)
|
||||||
}
|
}
|
||||||
.frame(width: geometry.size.width - 40)
|
|
||||||
.offset(x: 20, y: geometry[$0].minY + geometry[$0].height)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.overlayPreferenceValue(ExchangeRateFeaturePreferenceKey.self) { preferences in
|
.overlayPreferenceValue(ExchangeRateFeaturePreferenceKey.self) { preferences in
|
||||||
if store.isRateEducationEnabled {
|
WithPerceptionTracking {
|
||||||
GeometryReader { geometry in
|
if store.isRateEducationEnabled {
|
||||||
preferences.map {
|
GeometryReader { geometry in
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
preferences.map {
|
||||||
HStack(alignment: .top, spacing: 0) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
Asset.Assets.coinsSwap.image
|
HStack(alignment: .top, spacing: 0) {
|
||||||
.renderingMode(.template)
|
Asset.Assets.coinsSwap.image
|
||||||
.resizable()
|
|
||||||
.frame(width: 20, height: 20)
|
|
||||||
.foregroundColor(Design.Text.primary.color)
|
|
||||||
.padding(10)
|
|
||||||
.background {
|
|
||||||
Circle()
|
|
||||||
.fill(Design.Surfaces.bgTertiary.color)
|
|
||||||
}
|
|
||||||
.padding(.trailing, 16)
|
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 5) {
|
|
||||||
Text(L10n.CurrencyConversion.cardTitle)
|
|
||||||
.font(.custom(FontFamily.Inter.regular.name, size: 14))
|
|
||||||
.foregroundColor(Design.Text.tertiary.color)
|
|
||||||
|
|
||||||
Text(L10n.CurrencyConversion.title)
|
|
||||||
.font(.custom(FontFamily.Inter.semiBold.name, size: 16))
|
|
||||||
.foregroundColor(Design.Text.primary.color)
|
|
||||||
.lineLimit(1)
|
|
||||||
.minimumScaleFactor(0.5)
|
|
||||||
}
|
|
||||||
.padding(.trailing, 16)
|
|
||||||
|
|
||||||
Spacer(minLength: 0)
|
|
||||||
|
|
||||||
Button {
|
|
||||||
store.send(.currencyConversionCloseTapped)
|
|
||||||
} label: {
|
|
||||||
Asset.Assets.buttonCloseX.image
|
|
||||||
.renderingMode(.template)
|
.renderingMode(.template)
|
||||||
.resizable()
|
.resizable()
|
||||||
.frame(width: 20, height: 20)
|
.frame(width: 20, height: 20)
|
||||||
.foregroundColor(Design.HintTooltips.defaultFg.color)
|
.foregroundColor(Design.Text.primary.color)
|
||||||
|
.padding(10)
|
||||||
|
.background {
|
||||||
|
Circle()
|
||||||
|
.fill(Design.Surfaces.bgTertiary.color)
|
||||||
|
}
|
||||||
|
.padding(.trailing, 16)
|
||||||
|
|
||||||
|
VStack(alignment: .leading, spacing: 5) {
|
||||||
|
Text(L10n.CurrencyConversion.cardTitle)
|
||||||
|
.font(.custom(FontFamily.Inter.regular.name, size: 14))
|
||||||
|
.foregroundColor(Design.Text.tertiary.color)
|
||||||
|
|
||||||
|
Text(L10n.CurrencyConversion.title)
|
||||||
|
.font(.custom(FontFamily.Inter.semiBold.name, size: 16))
|
||||||
|
.foregroundColor(Design.Text.primary.color)
|
||||||
|
.lineLimit(1)
|
||||||
|
.minimumScaleFactor(0.5)
|
||||||
|
}
|
||||||
|
.padding(.trailing, 16)
|
||||||
|
|
||||||
|
Spacer(minLength: 0)
|
||||||
|
|
||||||
|
Button {
|
||||||
|
store.send(.currencyConversionCloseTapped)
|
||||||
|
} label: {
|
||||||
|
Asset.Assets.buttonCloseX.image
|
||||||
|
.renderingMode(.template)
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
.foregroundColor(Design.HintTooltips.defaultFg.color)
|
||||||
|
}
|
||||||
|
.padding(20)
|
||||||
|
.offset(x: 20, y: -20)
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
store.send(.updateDestination(.currencyConversionSetup))
|
||||||
|
} label: {
|
||||||
|
Text(L10n.CurrencyConversion.cardButton)
|
||||||
|
.font(.custom(FontFamily.Inter.semiBold.name, size: 16))
|
||||||
|
.foregroundColor(Design.Btns.Tertiary.fg.color)
|
||||||
|
.frame(height: 24)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.padding(.vertical, 12)
|
||||||
|
.background {
|
||||||
|
RoundedRectangle(cornerRadius: 12)
|
||||||
|
.fill(Design.Btns.Tertiary.bg.color)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.padding(20)
|
|
||||||
.offset(x: 20, y: -20)
|
|
||||||
}
|
}
|
||||||
|
.padding(24)
|
||||||
Button {
|
.background {
|
||||||
store.send(.updateDestination(.currencyConversionSetup))
|
RoundedRectangle(cornerRadius: 12)
|
||||||
} label: {
|
.fill(Design.Surfaces.bgPrimary.color)
|
||||||
Text(L10n.CurrencyConversion.cardButton)
|
|
||||||
.font(.custom(FontFamily.Inter.semiBold.name, size: 16))
|
|
||||||
.foregroundColor(Design.Btns.Tertiary.fg.color)
|
|
||||||
.frame(height: 24)
|
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
.padding(.vertical, 12)
|
|
||||||
.background {
|
.background {
|
||||||
RoundedRectangle(cornerRadius: 12)
|
RoundedRectangle(cornerRadius: 12)
|
||||||
.fill(Design.Btns.Tertiary.bg.color)
|
.stroke(Design.Surfaces.strokeSecondary.color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.frame(width: geometry.size.width - 40)
|
||||||
|
.offset(x: 20, y: geometry[$0].minY + geometry[$0].height)
|
||||||
}
|
}
|
||||||
.padding(24)
|
|
||||||
.background {
|
|
||||||
RoundedRectangle(cornerRadius: 12)
|
|
||||||
.fill(Design.Surfaces.bgPrimary.color)
|
|
||||||
.background {
|
|
||||||
RoundedRectangle(cornerRadius: 12)
|
|
||||||
.stroke(Design.Surfaces.strokeSecondary.color)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.frame(width: geometry.size.width - 40)
|
|
||||||
.offset(x: 20, y: geometry[$0].minY + geometry[$0].height)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,31 +62,33 @@ public struct ZatoshiRepresentationView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
public var body: some View {
|
public var body: some View {
|
||||||
HStack {
|
WithPerceptionTracking {
|
||||||
if isFee {
|
HStack {
|
||||||
Text(zatoshiStringRepresentation.feeFormat)
|
if isFee {
|
||||||
.font(.custom(fontName, size: mostSignificantFontSize))
|
Text(zatoshiStringRepresentation.feeFormat)
|
||||||
} else {
|
.font(.custom(fontName, size: mostSignificantFontSize))
|
||||||
if format == .expanded {
|
|
||||||
Text(couldBeHidden && isSensitiveContentHidden
|
|
||||||
? L10n.General.hideBalancesMost
|
|
||||||
: zatoshiStringRepresentation.mostSignificantDigits
|
|
||||||
)
|
|
||||||
.font(.custom(fontName, size: mostSignificantFontSize))
|
|
||||||
.conditionalStrikethrough(strikethrough)
|
|
||||||
+ Text(couldBeHidden && isSensitiveContentHidden
|
|
||||||
? L10n.General.hideBalancesLeast
|
|
||||||
: zatoshiStringRepresentation.leastSignificantDigits
|
|
||||||
)
|
|
||||||
.font(.custom(fontName, size: leastSignificantFontSize))
|
|
||||||
.conditionalStrikethrough(strikethrough)
|
|
||||||
} else {
|
} else {
|
||||||
Text(couldBeHidden && isSensitiveContentHidden
|
if format == .expanded {
|
||||||
? L10n.General.hideBalancesMostStandalone
|
Text(couldBeHidden && isSensitiveContentHidden
|
||||||
: zatoshiStringRepresentation.mostSignificantDigits
|
? L10n.General.hideBalancesMost
|
||||||
)
|
: zatoshiStringRepresentation.mostSignificantDigits
|
||||||
.font(.custom(fontName, size: mostSignificantFontSize))
|
)
|
||||||
.conditionalStrikethrough(strikethrough)
|
.font(.custom(fontName, size: mostSignificantFontSize))
|
||||||
|
.conditionalStrikethrough(strikethrough)
|
||||||
|
+ Text(couldBeHidden && isSensitiveContentHidden
|
||||||
|
? L10n.General.hideBalancesLeast
|
||||||
|
: zatoshiStringRepresentation.leastSignificantDigits
|
||||||
|
)
|
||||||
|
.font(.custom(fontName, size: leastSignificantFontSize))
|
||||||
|
.conditionalStrikethrough(strikethrough)
|
||||||
|
} else {
|
||||||
|
Text(couldBeHidden && isSensitiveContentHidden
|
||||||
|
? L10n.General.hideBalancesMostStandalone
|
||||||
|
: zatoshiStringRepresentation.mostSignificantDigits
|
||||||
|
)
|
||||||
|
.font(.custom(fontName, size: mostSignificantFontSize))
|
||||||
|
.conditionalStrikethrough(strikethrough)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,13 @@ struct HiddenIfSetModifier: ViewModifier {
|
||||||
@Shared(.appStorage(.sensitiveContent)) var isSensitiveContentHidden = false
|
@Shared(.appStorage(.sensitiveContent)) var isSensitiveContentHidden = false
|
||||||
|
|
||||||
func body(content: Content) -> some View {
|
func body(content: Content) -> some View {
|
||||||
VStack(spacing: 0) {
|
WithPerceptionTracking {
|
||||||
if isSensitiveContentHidden {
|
VStack(spacing: 0) {
|
||||||
Text(L10n.General.hideBalancesMostStandalone)
|
if isSensitiveContentHidden {
|
||||||
} else {
|
Text(L10n.General.hideBalancesMostStandalone)
|
||||||
content
|
} else {
|
||||||
|
content
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue