From 8a2f708f32a6a760e64f13ac93f342202c74a9f2 Mon Sep 17 00:00:00 2001 From: Gerson Noboa Date: Thu, 19 Oct 2023 10:31:20 +0300 Subject: [PATCH] Fix empty string shown if company name is empty If the company name is empty in the custom locales set in the web (as is the default), then the widgets tried to get it, but as it is empty, then the fallback was the theme and the configuration. If neither of those was able to provide a non-empty value, then the idea is to use the local fallback. However, for this I was mistakenly using the value from `Localizable.tr`. The problem is that this method first attempts to get it again from the string provider. As we determined in the first step, this is empty. However, `Localizable.tr` doesn't filter empty values, as all other strings can legitimately be empty. So the method returns empty string, and this is shown on the widgets. The solution was to create a new value in the SwiftGen stencil, which is called `companyNameLocalFallbackOnly`. As the name says, this variable sends the string provider as nil, thus ignoring the company name's empty value, and using the value in the `Localizable.strings`, or the hardcoded "Company Name" as fallback. For now, no other string is subject to this matter where the string can come from a lot of various sources, so this approach should be sufficient. If at some point it happens that quite a lot of strings need to be fetched from various sources, what can be done is that the stencil can be changed so that instead of generating `static let`s, we generate `static func`s, and then we can easily send the string provider as needed. MOB-2768 --- GliaWidgets.xcodeproj/project.pbxproj | 6 +-- GliaWidgets/Localization.swift | 2 + .../Public/Glia/Glia+StartEngagement.swift | 2 +- .../Glia/GliaTests+StartEngagement.swift | 43 +++++++++++++++++++ swiftgen-strings.stencil | 4 ++ 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/GliaWidgets.xcodeproj/project.pbxproj b/GliaWidgets.xcodeproj/project.pbxproj index 5b67da6b2..c091d76e9 100644 --- a/GliaWidgets.xcodeproj/project.pbxproj +++ b/GliaWidgets.xcodeproj/project.pbxproj @@ -599,10 +599,10 @@ C06A7586296ECC57006B69A2 /* VisitorCodeStyle.Accessibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = C06A7585296ECC57006B69A2 /* VisitorCodeStyle.Accessibility.swift */; }; C06A7588296ECD75006B69A2 /* Theme+VisitorCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = C06A7587296ECD75006B69A2 /* Theme+VisitorCode.swift */; }; C07F62462ABC322B003EFC97 /* OrientationManager.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07F62452ABC322B003EFC97 /* OrientationManager.Mock.swift */; }; + C07F62772AC1BA2B003EFC97 /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07F62762AC1BA2B003EFC97 /* UIViewController+Extensions.swift */; }; C07F62792AC2D2E8003EFC97 /* BackgroundSwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07F62782AC2D2E8003EFC97 /* BackgroundSwiftUI.swift */; }; C07F627D2AC2F31F003EFC97 /* ScreenSharingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07F627C2AC2F31F003EFC97 /* ScreenSharingViewModel.swift */; }; C07F62812AC3057C003EFC97 /* ScreenSharingViewModel.mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07F62802AC3057C003EFC97 /* ScreenSharingViewModel.mock.swift */; }; - C07F62772AC1BA2B003EFC97 /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07F62762AC1BA2B003EFC97 /* UIViewController+Extensions.swift */; }; C07F62832AC33BB9003EFC97 /* UIView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07F62822AC33BB9003EFC97 /* UIView+Extensions.swift */; }; C07FA04029AF542A00E9FB7F /* ScreenSharingViewStyle+Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84265E0B298AECBA00D65842 /* ScreenSharingViewStyle+Mock.swift */; }; C07FA04B29AF83B900E9FB7F /* ActionButton.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C07FA04929AF83A400E9FB7F /* ActionButton.Mock.swift */; }; @@ -1341,13 +1341,11 @@ C06A7585296ECC57006B69A2 /* VisitorCodeStyle.Accessibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisitorCodeStyle.Accessibility.swift; sourceTree = ""; }; C06A7587296ECD75006B69A2 /* Theme+VisitorCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Theme+VisitorCode.swift"; sourceTree = ""; }; C07F62452ABC322B003EFC97 /* OrientationManager.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrientationManager.Mock.swift; sourceTree = ""; }; + C07F62762AC1BA2B003EFC97 /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extensions.swift"; sourceTree = ""; }; C07F62782AC2D2E8003EFC97 /* BackgroundSwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundSwiftUI.swift; sourceTree = ""; }; C07F627C2AC2F31F003EFC97 /* ScreenSharingViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenSharingViewModel.swift; sourceTree = ""; }; C07F62802AC3057C003EFC97 /* ScreenSharingViewModel.mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenSharingViewModel.mock.swift; sourceTree = ""; }; - C07F62762AC1BA2B003EFC97 /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extensions.swift"; sourceTree = ""; }; C07F62822AC33BB9003EFC97 /* UIView+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Extensions.swift"; sourceTree = ""; }; - C07FA04129AF550500E9FB7F /* ScreenSharingView.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenSharingView.Mock.swift; sourceTree = ""; }; - C07FA04429AF55F600E9FB7F /* ScreenSharingViewController.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenSharingViewController.Mock.swift; sourceTree = ""; }; C07FA04929AF83A400E9FB7F /* ActionButton.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionButton.Mock.swift; sourceTree = ""; }; C07FA04C29B0E41A00E9FB7F /* ScreenShareViewControllerVoiceOverTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScreenShareViewControllerVoiceOverTests.swift; sourceTree = ""; }; C07FA04D29B0E41A00E9FB7F /* VideoCallViewControllerVoiceOverTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoCallViewControllerVoiceOverTests.swift; sourceTree = ""; }; diff --git a/GliaWidgets/Localization.swift b/GliaWidgets/Localization.swift index 3e11b20b3..c8f4390c9 100644 --- a/GliaWidgets/Localization.swift +++ b/GliaWidgets/Localization.swift @@ -413,6 +413,8 @@ internal enum Localization { internal static let comment = Localization.tr("Localizable", "general.comment", fallback: "Comment") /// Company Name internal static let companyName = Localization.tr("Localizable", "general.company_name", fallback: "Company Name") + /// Company Name without asking string provider + internal static let companyNameLocalFallbackOnly = Localization.tr("Localizable", "general.company_name", fallback: "Company Name", stringProviding: nil) /// Decline internal static let decline = Localization.tr("Localizable", "general.decline", fallback: "Decline") /// Download diff --git a/GliaWidgets/Public/Glia/Glia+StartEngagement.swift b/GliaWidgets/Public/Glia/Glia+StartEngagement.swift index c6e4f1566..dc0106fa9 100644 --- a/GliaWidgets/Public/Glia/Glia+StartEngagement.swift +++ b/GliaWidgets/Public/Glia/Glia+StartEngagement.swift @@ -105,7 +105,7 @@ extension Glia { else { // This will return the fallback value every time, because we have // already determined that the remote string is empty. - return Localization.General.companyName + return Localization.General.companyNameLocalFallbackOnly } } diff --git a/GliaWidgetsTests/Sources/Glia/GliaTests+StartEngagement.swift b/GliaWidgetsTests/Sources/Glia/GliaTests+StartEngagement.swift index 0bcafdf2a..df6064d91 100644 --- a/GliaWidgetsTests/Sources/Glia/GliaTests+StartEngagement.swift +++ b/GliaWidgetsTests/Sources/Glia/GliaTests+StartEngagement.swift @@ -4,6 +4,10 @@ import XCTest @testable import GliaWidgets extension GliaTests { + override class func tearDown() { + Glia.sharedInstance.stringProviding = nil + } + func testStartEngagementThrowsErrorWhenEngagementAlreadyExists() throws { let sdk = Glia(environment: .failing) sdk.rootCoordinator = .mock(engagementKind: .chat, screenShareHandler: .mock) @@ -218,4 +222,43 @@ extension GliaTests { XCTAssertEqual(configuredSdkTheme?.call.connect.queue.firstText, "Glia 1") XCTAssertEqual(configuredSdkTheme?.chat.connect.queue.firstText, "Glia 2") } + + func testCompanyNameIsReceivedFromLocalFallbackIfCustomLocalesIsEmpty() throws { + var environment = Glia.Environment.failing + var resultingViewFactory: ViewFactory? + + environment.createRootCoordinator = { _, viewFactory, _, _, _, _, _ in + resultingViewFactory = viewFactory + + return .mock( + interactor: .mock(environment: .failing), + viewFactory: viewFactory, + sceneProvider: nil, + engagementKind: .none, + screenShareHandler: .mock, + features: [], + environment: .failing + ) + } + + environment.coreSdk.localeProvider.getRemoteString = { _ in "" } + environment.coreSdk.configureWithInteractor = { _ in } + environment.coreSdk.configureWithConfiguration = { _, completion in + // Simulating what happens in the Widgets when the configuration gets done + Glia.sharedInstance.stringProviding = StringProviding( + getRemoteString: environment.coreSdk.localeProvider.getRemoteString + ) + completion?() + } + environment.coreSdk.getCurrentEngagement = { nil } + + let sdk = Glia(environment: environment) + try sdk.configure(with: .mock(), completion: {}) + try sdk.startEngagement(engagementKind: .chat, in: ["queueId"]) + + let configuredSdkTheme = resultingViewFactory?.theme + let localFallbackCompanyName = "Company Name" + XCTAssertEqual(configuredSdkTheme?.call.connect.queue.firstText, localFallbackCompanyName) + XCTAssertEqual(configuredSdkTheme?.chat.connect.queue.firstText, localFallbackCompanyName) + } } diff --git a/swiftgen-strings.stencil b/swiftgen-strings.stencil index 3a56d2857..db9773940 100644 --- a/swiftgen-strings.stencil +++ b/swiftgen-strings.stencil @@ -55,6 +55,10 @@ import Foundation {{accessModifier}} static var {{string.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}: String { return {{enumName}}.tr("{{table}}", "{{string.key}}", fallback: "{{translation}}") } {% else %} {{accessModifier}} static let {{string.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{enumName}}.tr("{{table}}", "{{string.key}}", fallback: "{{translation}}") + {% if string.key == "general.company_name" %} + /// {{translation}} without asking string provider + {{accessModifier}} static let {{string.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}LocalFallbackOnly = {{enumName}}.tr("{{table}}", "{{string.key}}", fallback: "{{translation}}", stringProviding: nil) + {% endif %} {% endif %} {% endfor %} {% for child in item.children %}