From bb271360a744a6834ed16bb346d9c178cd4bbd43 Mon Sep 17 00:00:00 2001 From: jos <17252150+jostnes@users.noreply.github.com> Date: Mon, 19 Jun 2023 16:23:03 +0800 Subject: [PATCH 01/23] move all XCTAsserts away from tests, indentation updates, and remove unnecessary lines --- WordPress/UITests/Flows/EditorFlow.swift | 2 +- WordPress/UITests/Flows/LoginFlow.swift | 13 ++++--- .../UITests/Tests/EditorAztecTests.swift | 8 +++-- .../UITests/Tests/EditorGutenbergTests.swift | 6 +++- WordPress/UITests/Tests/LoginTests.swift | 12 ++++--- .../UITests/Tests/MainNavigationTests.swift | 20 ++++++----- WordPress/UITests/Tests/ReaderTests.swift | 6 +++- WordPress/UITests/Tests/SignupTests.swift | 6 ++-- WordPress/UITests/Tests/StatsTests.swift | 6 +++- .../Login/Unified/GetStartedScreen.swift | 2 +- .../Login/Unified/PasswordScreen.swift | 34 ++++++++++++------- .../Screens/MySiteScreen.swift | 2 ++ .../Screens/PeopleScreen.swift | 4 +++ .../Screens/ReaderScreen.swift | 4 +++ 14 files changed, 84 insertions(+), 41 deletions(-) diff --git a/WordPress/UITests/Flows/EditorFlow.swift b/WordPress/UITests/Flows/EditorFlow.swift index 0e184259580a..bf45795feaaf 100644 --- a/WordPress/UITests/Flows/EditorFlow.swift +++ b/WordPress/UITests/Flows/EditorFlow.swift @@ -14,7 +14,7 @@ class EditorFlow { static func toggleBlockEditor(to state: SiteSettingsScreen.Toggle) throws -> SiteSettingsScreen { if !SiteSettingsScreen.isLoaded() { - _ = try TabNavComponent() + try TabNavComponent() .goToMySiteScreen() .goToSettingsScreen() } diff --git a/WordPress/UITests/Flows/LoginFlow.swift b/WordPress/UITests/Flows/LoginFlow.swift index 99f9a16871e0..5d778d81a22c 100644 --- a/WordPress/UITests/Flows/LoginFlow.swift +++ b/WordPress/UITests/Flows/LoginFlow.swift @@ -5,7 +5,8 @@ class LoginFlow { @discardableResult static func login(email: String, password: String, selectedSiteTitle: String? = nil) throws -> MySiteScreen { - return try PrologueScreen().selectContinue() + return try PrologueScreen() + .selectContinue() .proceedWith(email: email) .proceedWithValidPassword() .continueWithSelectedSite(title: selectedSiteTitle) @@ -15,7 +16,8 @@ class LoginFlow { // Login with self-hosted site via Site Address. @discardableResult static func login(siteUrl: String, username: String, password: String) throws -> MySiteScreen { - return try PrologueScreen().selectSiteAddress() + return try PrologueScreen() + .selectSiteAddress() .proceedWith(siteUrl: siteUrl) .proceedWith(username: username, password: password) .continueWithSelectedSite() @@ -25,12 +27,13 @@ class LoginFlow { // Login with WP site via Site Address. @discardableResult static func login(siteUrl: String, email: String, password: String) throws -> MySiteScreen { - return try PrologueScreen().selectSiteAddress() + return try PrologueScreen() + .selectSiteAddress() .proceedWithWP(siteUrl: siteUrl) .proceedWith(email: email) .proceedWithValidPassword() - .continueWithSelectedSite() - .dismissNotificationAlertIfNeeded() + .continueWithSelectedSite() + .dismissNotificationAlertIfNeeded() } // Login with self-hosted site via Site Address. diff --git a/WordPress/UITests/Tests/EditorAztecTests.swift b/WordPress/UITests/Tests/EditorAztecTests.swift index 876e5a8d347f..19bc48550fb5 100644 --- a/WordPress/UITests/Tests/EditorAztecTests.swift +++ b/WordPress/UITests/Tests/EditorAztecTests.swift @@ -7,8 +7,12 @@ class EditorAztecTests: XCTestCase { override func setUpWithError() throws { setUpTestSuite() - _ = try LoginFlow.login(siteUrl: WPUITestCredentials.testWPcomSiteAddress, email: WPUITestCredentials.testWPcomUserEmail, password: WPUITestCredentials.testWPcomPassword) - editorScreen = try EditorFlow + try LoginFlow.login( + siteUrl: WPUITestCredentials.testWPcomSiteAddress, + email: WPUITestCredentials.testWPcomUserEmail, + password: WPUITestCredentials.testWPcomPassword + ) + try EditorFlow .toggleBlockEditor(to: .off) .goBackToMySite() .tabBar.goToAztecEditorScreen() diff --git a/WordPress/UITests/Tests/EditorGutenbergTests.swift b/WordPress/UITests/Tests/EditorGutenbergTests.swift index 6efe45cf6203..7fa174656578 100644 --- a/WordPress/UITests/Tests/EditorGutenbergTests.swift +++ b/WordPress/UITests/Tests/EditorGutenbergTests.swift @@ -5,7 +5,11 @@ class EditorGutenbergTests: XCTestCase { override func setUpWithError() throws { setUpTestSuite() - try LoginFlow.login(siteUrl: WPUITestCredentials.testWPcomSiteAddress, email: WPUITestCredentials.testWPcomUserEmail, password: WPUITestCredentials.testWPcomPassword) + try LoginFlow.login( + siteUrl: WPUITestCredentials.testWPcomSiteAddress, + email: WPUITestCredentials.testWPcomUserEmail, + password: WPUITestCredentials.testWPcomPassword + ) try EditorFlow .goToMySiteScreen() .tabBar.gotoBlockEditorScreen() diff --git a/WordPress/UITests/Tests/LoginTests.swift b/WordPress/UITests/Tests/LoginTests.swift index f17fa17b3373..3e8652103d3f 100644 --- a/WordPress/UITests/Tests/LoginTests.swift +++ b/WordPress/UITests/Tests/LoginTests.swift @@ -14,7 +14,8 @@ class LoginTests: XCTestCase { // Unified email login/out func testWPcomLoginLogout() throws { - try PrologueScreen().selectContinue() + try PrologueScreen() + .selectContinue() .proceedWith(email: WPUITestCredentials.testWPcomUserEmail) .proceedWithValidPassword() .verifyEpilogueDisplays(username: WPUITestCredentials.testWPcomUsername, siteUrl: WPUITestCredentials.testWPcomSitePrimaryAddress) @@ -29,7 +30,8 @@ class LoginTests: XCTestCase { This test opens safari to trigger the mocked magic link redirect */ func testEmailMagicLinkLogin() throws { - try WelcomeScreen().selectLogin() + try WelcomeScreen() + .selectLogin() .selectEmailLogin() .proceedWith(email: WPUITestCredentials.testWPcomUserEmail) .proceedWithLink() @@ -54,7 +56,8 @@ class LoginTests: XCTestCase { // Unified WordPress.com email login failure due to incorrect password func testWPcomInvalidPassword() throws { - try PrologueScreen().selectContinue() + try PrologueScreen() + .selectContinue() .proceedWith(email: WPUITestCredentials.testWPcomUserEmail) .proceedWithInvalidPassword() .verifyLoginError() @@ -63,7 +66,8 @@ class LoginTests: XCTestCase { // Self-Hosted after WordPress.com login. // Login to a WordPress.com account, open site switcher, then add a self-hosted site. func testAddSelfHostedSiteAfterWPcomLogin() throws { - try PrologueScreen().selectContinue() + try PrologueScreen() + .selectContinue() .proceedWith(email: WPUITestCredentials.testWPcomUserEmail) .proceedWithValidPassword() .verifyEpilogueDisplays(username: WPUITestCredentials.testWPcomUsername, siteUrl: WPUITestCredentials.testWPcomSitePrimaryAddress) diff --git a/WordPress/UITests/Tests/MainNavigationTests.swift b/WordPress/UITests/Tests/MainNavigationTests.swift index 45f47ffa212c..611577d39b1b 100644 --- a/WordPress/UITests/Tests/MainNavigationTests.swift +++ b/WordPress/UITests/Tests/MainNavigationTests.swift @@ -5,7 +5,11 @@ class MainNavigationTests: XCTestCase { override func setUpWithError() throws { setUpTestSuite() - try LoginFlow.login(siteUrl: WPUITestCredentials.testWPcomSiteAddress, email: WPUITestCredentials.testWPcomUserEmail, password: WPUITestCredentials.testWPcomPassword) + try LoginFlow.login( + siteUrl: WPUITestCredentials.testWPcomSiteAddress, + email: WPUITestCredentials.testWPcomUserEmail, + password: WPUITestCredentials.testWPcomPassword + ) try TabNavComponent() .goToMySiteScreen() .goToMenu() @@ -20,19 +24,17 @@ class MainNavigationTests: XCTestCase { // // It would be wise to add similar tests for each item in the menu (then remove this comment). func testLoadsPeopleScreen() throws { - XCTAssert(MySiteScreen.isLoaded(), "MySitesScreen screen isn't loaded.") - try MySiteScreen() + .verifyMySiteScreenLoaded() .goToPeople() - - XCTAssertTrue(PeopleScreen.isLoaded(), "PeopleScreen screen isn't loaded.") + .verifyPeopleScreenLoaded() } func testTabBarNavigation() throws { - XCTAssert(MySiteScreen.isLoaded(), "MySitesScreen screen isn't loaded.") - - try TabNavComponent().goToReaderScreen() - XCTAssert(ReaderScreen.isLoaded(), "Reader screen isn't loaded.") + try MySiteScreen() + .verifyMySiteScreenLoaded() + .tabBar.goToReaderScreen() + .verifyReaderScreenLoaded() // We may get a notifications fancy alert when loading the reader for the first time if let alert = try? FancyAlertComponent() { diff --git a/WordPress/UITests/Tests/ReaderTests.swift b/WordPress/UITests/Tests/ReaderTests.swift index 07ceb513a1a4..90c3f49ebc62 100644 --- a/WordPress/UITests/Tests/ReaderTests.swift +++ b/WordPress/UITests/Tests/ReaderTests.swift @@ -5,7 +5,11 @@ class ReaderTests: XCTestCase { override func setUpWithError() throws { setUpTestSuite() - try LoginFlow.login(siteUrl: WPUITestCredentials.testWPcomSiteAddress, email: WPUITestCredentials.testWPcomUserEmail, password: WPUITestCredentials.testWPcomPassword) + try LoginFlow.login( + siteUrl: WPUITestCredentials.testWPcomSiteAddress, + email: WPUITestCredentials.testWPcomUserEmail, + password: WPUITestCredentials.testWPcomPassword + ) try EditorFlow .goToMySiteScreen() .tabBar.goToReaderScreen() diff --git a/WordPress/UITests/Tests/SignupTests.swift b/WordPress/UITests/Tests/SignupTests.swift index 010c5fc98713..8c8f070563ae 100644 --- a/WordPress/UITests/Tests/SignupTests.swift +++ b/WordPress/UITests/Tests/SignupTests.swift @@ -13,7 +13,8 @@ class SignupTests: XCTestCase { } func testEmailSignup() throws { - let mySiteScreen = try WelcomeScreen().selectSignup() + try WelcomeScreen() + .selectSignup() .selectEmailSignup() .proceedWith(email: WPUITestCredentials.signupEmail) .openMagicSignupLink() @@ -21,7 +22,6 @@ class SignupTests: XCTestCase { .setPassword(WPUITestCredentials.signupPassword) .continueWithSignup() .dismissNotificationAlertIfNeeded() - - XCTAssert(mySiteScreen.isLoaded) + .verifyMySiteScreenLoaded() } } diff --git a/WordPress/UITests/Tests/StatsTests.swift b/WordPress/UITests/Tests/StatsTests.swift index 4476adfaf1f1..a32400f56f31 100644 --- a/WordPress/UITests/Tests/StatsTests.swift +++ b/WordPress/UITests/Tests/StatsTests.swift @@ -4,7 +4,11 @@ import XCTest class StatsTests: XCTestCase { override func setUpWithError() throws { setUpTestSuite() - try LoginFlow.login(siteUrl: WPUITestCredentials.testWPcomSiteAddress, email: WPUITestCredentials.testWPcomUserEmail, password: WPUITestCredentials.testWPcomPassword) + try LoginFlow.login( + siteUrl: WPUITestCredentials.testWPcomSiteAddress, + email: WPUITestCredentials.testWPcomUserEmail, + password: WPUITestCredentials.testWPcomPassword + ) try MySiteScreen() .goToMenu() .goToStatsScreen() diff --git a/WordPress/UITestsFoundation/Screens/Login/Unified/GetStartedScreen.swift b/WordPress/UITestsFoundation/Screens/Login/Unified/GetStartedScreen.swift index 871bc6ef286f..5dfd2c9cbd96 100644 --- a/WordPress/UITestsFoundation/Screens/Login/Unified/GetStartedScreen.swift +++ b/WordPress/UITestsFoundation/Screens/Login/Unified/GetStartedScreen.swift @@ -24,7 +24,7 @@ public class GetStartedScreen: ScreenObject { } var navBar: XCUIElement { navBarGetter(app) } - public var emailTextField: XCUIElement { emailTextFieldGetter(app) } + var emailTextField: XCUIElement { emailTextFieldGetter(app) } var continueButton: XCUIElement { continueButtonGetter(app) } var helpButton: XCUIElement { helpButtonGetter(app) } var backButton: XCUIElement { backButtonGetter(app) } diff --git a/WordPress/UITestsFoundation/Screens/Login/Unified/PasswordScreen.swift b/WordPress/UITestsFoundation/Screens/Login/Unified/PasswordScreen.swift index 68c49d51c050..72391366b384 100644 --- a/WordPress/UITestsFoundation/Screens/Login/Unified/PasswordScreen.swift +++ b/WordPress/UITestsFoundation/Screens/Login/Unified/PasswordScreen.swift @@ -3,10 +3,25 @@ import XCTest public class PasswordScreen: ScreenObject { + private let passwordTextFieldGetter: (XCUIApplication) -> XCUIElement = { + $0.secureTextFields["Password"] + } + + private let passwordErrorLabelGetter: (XCUIApplication) -> XCUIElement = { + $0.cells["Password Error"] + } + + private let continueButtonGetter: (XCUIApplication) -> XCUIElement = { + $0.buttons["Continue Button"] + } + + var passwordTextField: XCUIElement { passwordTextFieldGetter(app) } + var passwordErrorLabel: XCUIElement { passwordErrorLabelGetter(app) } + var continueButton: XCUIElement { continueButtonGetter(app) } + public init(app: XCUIApplication = XCUIApplication()) throws { try super.init( - // swiftlint:disable:next opening_brace - expectedElementGetters: [ { $0.secureTextFields["Password"] } ], + expectedElementGetters: [ passwordTextFieldGetter, continueButtonGetter ], app: app, waitTimeout: 10 ) @@ -20,15 +35,13 @@ public class PasswordScreen: ScreenObject { return try LoginEpilogueScreen() } - public func proceedWithInvalidPassword() throws -> PasswordScreen { + public func proceedWithInvalidPassword() throws -> Self { try tryProceed(password: "invalidPswd") - return try PasswordScreen() + return self } public func tryProceed(password: String) throws { - let passwordTextField = expectedElement - // A hack to make tests pass for RtL languages. // // An unintended side effect of calling passwordTextField.tap() while testing a RtL language is that the @@ -47,18 +60,13 @@ public class PasswordScreen: ScreenObject { } passwordTextField.typeText(password) - let continueButton = app.buttons["Continue Button"] continueButton.tap() - app.dismissSavePasswordPrompt() } @discardableResult - public func verifyLoginError() -> PasswordScreen { - let errorLabel = app.cells["Password Error"] - _ = errorLabel.waitForExistence(timeout: 2) - - XCTAssertTrue(errorLabel.exists) + public func verifyLoginError() -> Self { + XCTAssertTrue(passwordErrorLabel.waitForExistence(timeout: 3)) return self } diff --git a/WordPress/UITestsFoundation/Screens/MySiteScreen.swift b/WordPress/UITestsFoundation/Screens/MySiteScreen.swift index 51b65c1c89e6..20c1797f33af 100644 --- a/WordPress/UITestsFoundation/Screens/MySiteScreen.swift +++ b/WordPress/UITestsFoundation/Screens/MySiteScreen.swift @@ -187,6 +187,7 @@ public class MySiteScreen: ScreenObject { return try StatsScreen() } + @discardableResult public func goToSettingsScreen() throws -> SiteSettingsScreen { app.cells[ElementStringIDs.settingsButton].tap() return try SiteSettingsScreen() @@ -224,6 +225,7 @@ public class MySiteScreen: ScreenObject { return try PeopleScreen() } + @discardableResult public func verifyMySiteScreenLoaded() -> Self { XCTAssertTrue(isLoaded) return self diff --git a/WordPress/UITestsFoundation/Screens/PeopleScreen.swift b/WordPress/UITestsFoundation/Screens/PeopleScreen.swift index 2c4c3feec618..95734669ee9e 100644 --- a/WordPress/UITestsFoundation/Screens/PeopleScreen.swift +++ b/WordPress/UITestsFoundation/Screens/PeopleScreen.swift @@ -22,6 +22,10 @@ public class PeopleScreen: ScreenObject { ) } + public func verifyPeopleScreenLoaded() { + XCTAssertTrue(isLoaded) + } + public static func isLoaded() -> Bool { (try? PeopleScreen().isLoaded) ?? false } diff --git a/WordPress/UITestsFoundation/Screens/ReaderScreen.swift b/WordPress/UITestsFoundation/Screens/ReaderScreen.swift index 9f58c4cf948b..a4f810d3b9a3 100644 --- a/WordPress/UITestsFoundation/Screens/ReaderScreen.swift +++ b/WordPress/UITestsFoundation/Screens/ReaderScreen.swift @@ -74,6 +74,10 @@ public class ReaderScreen: ScreenObject { if backButton.isHittable { backButton.tap() } } + public func verifyReaderScreenLoaded() { + XCTAssertTrue(isLoaded) + } + public static func isLoaded() -> Bool { (try? ReaderScreen().isLoaded) ?? false } From 5c703382a44d38275865536052b8f16cd503f724 Mon Sep 17 00:00:00 2001 From: Tony Li Date: Tue, 20 Jun 2023 16:07:15 +1200 Subject: [PATCH 02/23] Set the `selectedNotification` property within `showDetails` --- .../NotificationsViewController.swift | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/WordPress/Classes/ViewRelated/Notifications/Controllers/NotificationsViewController.swift b/WordPress/Classes/ViewRelated/Notifications/Controllers/NotificationsViewController.swift index 9dcbf79faf6c..8c83b9b8b1e5 100644 --- a/WordPress/Classes/ViewRelated/Notifications/Controllers/NotificationsViewController.swift +++ b/WordPress/Classes/ViewRelated/Notifications/Controllers/NotificationsViewController.swift @@ -429,7 +429,6 @@ class NotificationsViewController: UIViewController, UIViewControllerRestoration return } - selectedNotification = note showDetails(for: note) if !splitViewControllerIsHorizontallyCompact { @@ -770,6 +769,27 @@ extension NotificationsViewController { // loadViewIfNeeded() + // The `selectedNotification` property will be set to `note` later in the `selectRow` functioin call. The reason + // we duplicate the assignment here (explicityly before the `markAsRead` function call) is to workaround a crash + // caused by recursive `NSManagedObjectContext.save` calls. + // + // Here is the recursive call chain: + // markAsRead(note) -> NSManagedObjectContext.save -> NSFetchedResultControllerDelegate.controllerDidChangeContent + // -> tableViewDidChangeContent -> markAsRead(selectedNotification) -> NSManagedObjectContext.save + // + // If the two Notication instances passed to the two `markAsRead` function calls are the same object, the last `save` + // call won't happen because `selectedNotification.read` is already true and `markAsRead(selectedNotification)` does nothing. + // + // Considering the `selectedNotification` will be set to `note` later, it should be safe to duplicate that assignment + // here, just for the sake of breaking the recursive calls. + // + // The ideal solution would be not updating and saving `Notification.read` property in the main context. + // Use `CoreDataStack.performAndSave` to do it in a background context instead. However, based on the comments on + // `markAsRead` function call below, it appears we intentionally save the main context to maintain some undocumented + // but appears important "side effects". We may need more careful testing around moving the saving operation from + // the main context to a background context. + selectedNotification = note + /// Note: markAsRead should be the *first* thing we do. This triggers a context save, and may have many side effects that /// could affect the OP's that go below!!!. /// From ad42bf4654b9ce84d575cfb81fab74111c2925db Mon Sep 17 00:00:00 2001 From: jos <17252150+jostnes@users.noreply.github.com> Date: Tue, 20 Jun 2023 12:58:58 +0800 Subject: [PATCH 03/23] abstract verifyScreenLoaded to screenObject extension --- WordPress/UITests/Tests/DashboardTests.swift | 8 ++++---- WordPress/UITests/Tests/LoginTests.swift | 8 ++++---- WordPress/UITests/Tests/MainNavigationTests.swift | 7 +++---- WordPress/UITests/Tests/MenuNavigationTests.swift | 2 +- WordPress/UITests/Tests/SignupTests.swift | 2 +- WordPress/UITestsFoundation/Globals.swift | 6 ++++++ .../UITestsFoundation/Screens/ActivityLogScreen.swift | 6 ------ WordPress/UITestsFoundation/Screens/DomainsScreen.swift | 6 ------ .../Screens/DomainsSuggestionsScreen.swift | 6 ------ .../Screens/Login/Unified/PrologueScreen.swift | 4 ---- .../UITestsFoundation/Screens/Login/WelcomeScreen.swift | 4 ---- WordPress/UITestsFoundation/Screens/MySiteScreen.swift | 6 ------ WordPress/UITestsFoundation/Screens/PagesScreen.swift | 6 ------ WordPress/UITestsFoundation/Screens/PeopleScreen.swift | 4 ---- .../UITestsFoundation/Screens/PlanSelectionScreen.swift | 6 ------ WordPress/UITestsFoundation/Screens/ReaderScreen.swift | 6 +----- 16 files changed, 20 insertions(+), 67 deletions(-) diff --git a/WordPress/UITests/Tests/DashboardTests.swift b/WordPress/UITests/Tests/DashboardTests.swift index b34da6726c48..aac2ae07abd5 100644 --- a/WordPress/UITests/Tests/DashboardTests.swift +++ b/WordPress/UITests/Tests/DashboardTests.swift @@ -22,10 +22,10 @@ class DashboardTests: XCTestCase { .scrollToFreeToPaidPlansCard() .verifyFreeToPaidPlansCard() .tapFreeToPaidPlansCard() - .verifyDomainsSuggestionsScreenLoaded() + .assertScreenIsLoaded() .selectDomain() .goToPlanSelection() - .verifyPlanSelectionScreenLoaded() + .assertScreenIsLoaded() } func testPagesCardHeaderNavigation() throws { @@ -36,7 +36,7 @@ class DashboardTests: XCTestCase { .verifyPagesCard(hasPage: "Shop") .verifyPagesCard(hasPage: "Cart") .tapPagesCardHeader() - .verifyPagesScreenLoaded() + .assertScreenIsLoaded() .verifyPagesScreen(hasPage: "Blog") .verifyPagesScreen(hasPage: "Shop") .verifyPagesScreen(hasPage: "Cart") @@ -50,7 +50,7 @@ class DashboardTests: XCTestCase { .verifyActivityLogCard(hasActivityPartial: "The Jetpack connection") .verifyActivityLogCard(hasActivityPartial: "This site is connected to") .tapActivityLogCardHeader() - .verifyActivityLogScreenLoaded() + .assertScreenIsLoaded() .verifyActivityLogScreen(hasActivityPartial: "Enabled Jetpack Social") .verifyActivityLogScreen(hasActivityPartial: "The Jetpack connection") .verifyActivityLogScreen(hasActivityPartial: "This site is connected to") diff --git a/WordPress/UITests/Tests/LoginTests.swift b/WordPress/UITests/Tests/LoginTests.swift index 3e8652103d3f..1e9203400c13 100644 --- a/WordPress/UITests/Tests/LoginTests.swift +++ b/WordPress/UITests/Tests/LoginTests.swift @@ -23,7 +23,7 @@ class LoginTests: XCTestCase { .dismissNotificationAlertIfNeeded() .tabBar.goToMeScreen() .logoutToPrologue() - .verifyPrologueScreenLoaded() + .assertScreenIsLoaded() } /** @@ -40,7 +40,7 @@ class LoginTests: XCTestCase { .dismissNotificationAlertIfNeeded() .tabBar.goToMeScreen() .logout() - .verifyWelcomeScreenLoaded() + .assertScreenIsLoaded() } // Unified self hosted login/out @@ -51,7 +51,7 @@ class LoginTests: XCTestCase { .proceedWithSelfHosted(username: WPUITestCredentials.selfHostedUsername, password: WPUITestCredentials.selfHostedPassword) .removeSelfHostedSite() try PrologueScreen() - .verifyPrologueScreenLoaded() + .assertScreenIsLoaded() } // Unified WordPress.com email login failure due to incorrect password @@ -83,7 +83,7 @@ class LoginTests: XCTestCase { // Login flow returns MySites modal, which needs to be closed. .closeModal() - .verifyMySiteScreenLoaded() + .assertScreenIsLoaded() .removeSelfHostedSite() } } diff --git a/WordPress/UITests/Tests/MainNavigationTests.swift b/WordPress/UITests/Tests/MainNavigationTests.swift index 611577d39b1b..d977c5008fe3 100644 --- a/WordPress/UITests/Tests/MainNavigationTests.swift +++ b/WordPress/UITests/Tests/MainNavigationTests.swift @@ -25,16 +25,15 @@ class MainNavigationTests: XCTestCase { // It would be wise to add similar tests for each item in the menu (then remove this comment). func testLoadsPeopleScreen() throws { try MySiteScreen() - .verifyMySiteScreenLoaded() + .assertScreenIsLoaded() .goToPeople() - .verifyPeopleScreenLoaded() + .assertScreenIsLoaded() } func testTabBarNavigation() throws { try MySiteScreen() - .verifyMySiteScreenLoaded() .tabBar.goToReaderScreen() - .verifyReaderScreenLoaded() + .assertScreenIsLoaded() // We may get a notifications fancy alert when loading the reader for the first time if let alert = try? FancyAlertComponent() { diff --git a/WordPress/UITests/Tests/MenuNavigationTests.swift b/WordPress/UITests/Tests/MenuNavigationTests.swift index f83ec205b825..d97500cd6a65 100644 --- a/WordPress/UITests/Tests/MenuNavigationTests.swift +++ b/WordPress/UITests/Tests/MenuNavigationTests.swift @@ -22,6 +22,6 @@ final class MenuNavigationTests: XCTestCase { try MySiteScreen() .goToMenu() .goToDomainsScreen() - .verifyDomainsScreenLoaded() + .assertScreenIsLoaded() } } diff --git a/WordPress/UITests/Tests/SignupTests.swift b/WordPress/UITests/Tests/SignupTests.swift index 8c8f070563ae..f661b1facbef 100644 --- a/WordPress/UITests/Tests/SignupTests.swift +++ b/WordPress/UITests/Tests/SignupTests.swift @@ -22,6 +22,6 @@ class SignupTests: XCTestCase { .setPassword(WPUITestCredentials.signupPassword) .continueWithSignup() .dismissNotificationAlertIfNeeded() - .verifyMySiteScreenLoaded() + .assertScreenIsLoaded() } } diff --git a/WordPress/UITestsFoundation/Globals.swift b/WordPress/UITestsFoundation/Globals.swift index a6a1e5de7b9d..91021c1da68e 100644 --- a/WordPress/UITestsFoundation/Globals.swift +++ b/WordPress/UITestsFoundation/Globals.swift @@ -101,6 +101,12 @@ extension ScreenObject { return self } + + @discardableResult + public func assertScreenIsLoaded(file: StaticString = #file, line: UInt = #line) -> Self { + XCTAssertTrue(isLoaded, file: file, line: line) + return self + } } public enum Apps { diff --git a/WordPress/UITestsFoundation/Screens/ActivityLogScreen.swift b/WordPress/UITestsFoundation/Screens/ActivityLogScreen.swift index 69a3cbb84afe..f7d13c501c19 100644 --- a/WordPress/UITestsFoundation/Screens/ActivityLogScreen.swift +++ b/WordPress/UITestsFoundation/Screens/ActivityLogScreen.swift @@ -29,12 +29,6 @@ public class ActivityLogScreen: ScreenObject { (try? ActivityLogScreen().isLoaded) ?? false } - @discardableResult - public func verifyActivityLogScreenLoaded() -> Self { - XCTAssertTrue(ActivityLogScreen.isLoaded(), "\"Activity\" screen isn't loaded.") - return self - } - @discardableResult public func verifyActivityLogScreen(hasActivityPartial activityTitle: String) -> Self { XCTAssertTrue( diff --git a/WordPress/UITestsFoundation/Screens/DomainsScreen.swift b/WordPress/UITestsFoundation/Screens/DomainsScreen.swift index ba5ac1f937c8..f604112f60b3 100644 --- a/WordPress/UITestsFoundation/Screens/DomainsScreen.swift +++ b/WordPress/UITestsFoundation/Screens/DomainsScreen.swift @@ -23,10 +23,4 @@ public class DomainsScreen: ScreenObject { public static func isLoaded() -> Bool { (try? DomainsScreen().isLoaded) ?? false } - - @discardableResult - public func verifyDomainsScreenLoaded() -> Self { - XCTAssertTrue(DomainsScreen.isLoaded(), "\"Domains\" screen isn't loaded.") - return self - } } diff --git a/WordPress/UITestsFoundation/Screens/DomainsSuggestionsScreen.swift b/WordPress/UITestsFoundation/Screens/DomainsSuggestionsScreen.swift index 5b789f76f62b..b9de5528d52b 100644 --- a/WordPress/UITestsFoundation/Screens/DomainsSuggestionsScreen.swift +++ b/WordPress/UITestsFoundation/Screens/DomainsSuggestionsScreen.swift @@ -21,12 +21,6 @@ public class DomainsSuggestionsScreen: ScreenObject { (try? DomainsSuggestionsScreen().isLoaded) ?? false } - @discardableResult - public func verifyDomainsSuggestionsScreenLoaded() -> Self { - XCTAssertTrue(DomainsSuggestionsScreen.isLoaded(), "\"Domains suggestions\" screen isn't loaded.") - return self - } - @discardableResult public func selectDomain() throws -> Self { app.tables["DomainSuggestionsTable"].cells.lastMatch?.tap() diff --git a/WordPress/UITestsFoundation/Screens/Login/Unified/PrologueScreen.swift b/WordPress/UITestsFoundation/Screens/Login/Unified/PrologueScreen.swift index 39791a2f9675..09aaa5754d66 100644 --- a/WordPress/UITestsFoundation/Screens/Login/Unified/PrologueScreen.swift +++ b/WordPress/UITestsFoundation/Screens/Login/Unified/PrologueScreen.swift @@ -36,10 +36,6 @@ public class PrologueScreen: ScreenObject { return try LoginSiteAddressScreen() } - public func verifyPrologueScreenLoaded() { - XCTAssertTrue(isLoaded) - } - public static func isLoaded(app: XCUIApplication = XCUIApplication()) -> Bool { (try? PrologueScreen(app: app).isLoaded) ?? false } diff --git a/WordPress/UITestsFoundation/Screens/Login/WelcomeScreen.swift b/WordPress/UITestsFoundation/Screens/Login/WelcomeScreen.swift index b937160f87f5..ef5359088ae4 100644 --- a/WordPress/UITestsFoundation/Screens/Login/WelcomeScreen.swift +++ b/WordPress/UITestsFoundation/Screens/Login/WelcomeScreen.swift @@ -36,10 +36,6 @@ public class WelcomeScreen: ScreenObject { return try WelcomeScreenLoginComponent() } - public func verifyWelcomeScreenLoaded() { - XCTAssertTrue(isLoaded) - } - static func isLoaded() -> Bool { (try? WelcomeScreen().isLoaded) ?? false } diff --git a/WordPress/UITestsFoundation/Screens/MySiteScreen.swift b/WordPress/UITestsFoundation/Screens/MySiteScreen.swift index 20c1797f33af..3dec24a98350 100644 --- a/WordPress/UITestsFoundation/Screens/MySiteScreen.swift +++ b/WordPress/UITestsFoundation/Screens/MySiteScreen.swift @@ -225,12 +225,6 @@ public class MySiteScreen: ScreenObject { return try PeopleScreen() } - @discardableResult - public func verifyMySiteScreenLoaded() -> Self { - XCTAssertTrue(isLoaded) - return self - } - public static func isLoaded() -> Bool { (try? MySiteScreen().isLoaded) ?? false } diff --git a/WordPress/UITestsFoundation/Screens/PagesScreen.swift b/WordPress/UITestsFoundation/Screens/PagesScreen.swift index 6217b4e6abce..607e6cb68118 100644 --- a/WordPress/UITestsFoundation/Screens/PagesScreen.swift +++ b/WordPress/UITestsFoundation/Screens/PagesScreen.swift @@ -24,12 +24,6 @@ public class PagesScreen: ScreenObject { (try? PagesScreen().isLoaded) ?? false } - @discardableResult - public func verifyPagesScreenLoaded() -> Self { - XCTAssertTrue(PagesScreen.isLoaded(), "\"Pages\" screen isn't loaded.") - return self - } - @discardableResult public func verifyPagesScreen(hasPage pageTitle: String) -> Self { XCTAssertTrue(pagesTable.staticTexts[pageTitle].waitForIsHittable(), "Pages Screen: \"\(pageTitle)\" page not displayed.") diff --git a/WordPress/UITestsFoundation/Screens/PeopleScreen.swift b/WordPress/UITestsFoundation/Screens/PeopleScreen.swift index 95734669ee9e..2c4c3feec618 100644 --- a/WordPress/UITestsFoundation/Screens/PeopleScreen.swift +++ b/WordPress/UITestsFoundation/Screens/PeopleScreen.swift @@ -22,10 +22,6 @@ public class PeopleScreen: ScreenObject { ) } - public func verifyPeopleScreenLoaded() { - XCTAssertTrue(isLoaded) - } - public static func isLoaded() -> Bool { (try? PeopleScreen().isLoaded) ?? false } diff --git a/WordPress/UITestsFoundation/Screens/PlanSelectionScreen.swift b/WordPress/UITestsFoundation/Screens/PlanSelectionScreen.swift index 83072c6264c8..c7f25de4f311 100644 --- a/WordPress/UITestsFoundation/Screens/PlanSelectionScreen.swift +++ b/WordPress/UITestsFoundation/Screens/PlanSelectionScreen.swift @@ -17,10 +17,4 @@ public class PlanSelectionScreen: ScreenObject { public static func isLoaded() -> Bool { (try? PlanSelectionScreen().isLoaded) ?? false } - - @discardableResult - public func verifyPlanSelectionScreenLoaded() -> Self { - XCTAssertTrue(PlanSelectionScreen.isLoaded(), "\"Plan Selection\" screen isn't loaded.") - return self - } } diff --git a/WordPress/UITestsFoundation/Screens/ReaderScreen.swift b/WordPress/UITestsFoundation/Screens/ReaderScreen.swift index a4f810d3b9a3..7a8e88b4670e 100644 --- a/WordPress/UITestsFoundation/Screens/ReaderScreen.swift +++ b/WordPress/UITestsFoundation/Screens/ReaderScreen.swift @@ -74,11 +74,7 @@ public class ReaderScreen: ScreenObject { if backButton.isHittable { backButton.tap() } } - public func verifyReaderScreenLoaded() { - XCTAssertTrue(isLoaded) - } - - public static func isLoaded() -> Bool { + public func isLoaded() -> Bool { (try? ReaderScreen().isLoaded) ?? false } From 33210325bd00cd14daf30c5f5272bb5cccd56f8f Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Tue, 20 Jun 2023 20:03:49 +1000 Subject: [PATCH 04/23] Use MediaEditor 1.2.2 This version has a fix for a possible life-cycle issue. --- Podfile | 2 +- Podfile.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Podfile b/Podfile index 54867b7933c8..b6d7d2d07bb0 100644 --- a/Podfile +++ b/Podfile @@ -154,7 +154,7 @@ abstract_target 'Apps' do # pod 'WordPressAuthenticator', git: 'https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git', commit: '' # pod 'WordPressAuthenticator', path: '../WordPressAuthenticator-iOS' - pod 'MediaEditor', '~> 1.2.1' + pod 'MediaEditor', '~> 1.2', '>= 1.2.2' # pod 'MediaEditor', git: 'https://github.com/wordpress-mobile/MediaEditor-iOS.git', commit: '' # pod 'MediaEditor', path: '../MediaEditor-iOS' diff --git a/Podfile.lock b/Podfile.lock index 4ec1d50289ef..a3a23b3868ea 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -70,7 +70,7 @@ PODS: - libwebp/mux (1.2.4): - libwebp/demux - libwebp/webp (1.2.4) - - MediaEditor (1.2.1): + - MediaEditor (1.2.2): - CropViewController (~> 2.5.3) - MRProgress (0.8.3): - MRProgress/ActivityIndicator (= 0.8.3) @@ -559,7 +559,7 @@ DEPENDENCIES: - Gutenberg (from `https://github.com/wordpress-mobile/gutenberg-mobile.git`, tag `v1.97.1`) - JTAppleCalendar (~> 8.0.2) - Kanvas (~> 1.4.4) - - MediaEditor (~> 1.2.1) + - MediaEditor (>= 1.2.2, ~> 1.2) - MRProgress (= 0.8.3) - NSObject-SafeExpectations (~> 0.0.4) - "NSURL+IDN (~> 0.4)" @@ -825,7 +825,7 @@ SPEC CHECKSUMS: JTAppleCalendar: 932cadea40b1051beab10f67843451d48ba16c99 Kanvas: f932eaed3d3f47aae8aafb6c2d27c968bdd49030 libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef - MediaEditor: 20cdeb46bdecd040b8bc94467ac85a52b53b193a + MediaEditor: d08314cfcbfac74361071a306b4bc3a39b3356ae MRProgress: 16de7cc9f347e8846797a770db102a323fe7ef09 NSObject-SafeExpectations: ab8fe623d36b25aa1f150affa324e40a2f3c0374 "NSURL+IDN": afc873e639c18138a1589697c3add197fe8679ca @@ -900,6 +900,6 @@ SPEC CHECKSUMS: ZendeskSupportSDK: 3a8e508ab1d9dd22dc038df6c694466414e037ba ZIPFoundation: ae5b4b813d216d3bf0a148773267fff14bd51d37 -PODFILE CHECKSUM: 8d45f149d70efe7560994bad2b7d40816dfc12b0 +PODFILE CHECKSUM: 3aafe3a791569455de8949833d0cf31de28aee99 COCOAPODS: 1.12.1 From 50ba522dab58603646e49f5b6ddd2212c6103845 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 20 Jun 2023 11:17:10 -0400 Subject: [PATCH 05/23] Remove unused CommentModerationBar --- .../Classes/Extensions/UIEdgeInsets.swift | 26 -- .../Comments/CommentModerationBar.swift | 327 ------------------ .../Comments/CommentModerationBar.xib | 181 ---------- .../Comments/WPStyleGuide+CommentDetail.swift | 71 ---- WordPress/WordPress.xcodeproj/project.pbxproj | 12 - 5 files changed, 617 deletions(-) delete mode 100644 WordPress/Classes/ViewRelated/Comments/CommentModerationBar.swift delete mode 100644 WordPress/Classes/ViewRelated/Comments/CommentModerationBar.xib diff --git a/WordPress/Classes/Extensions/UIEdgeInsets.swift b/WordPress/Classes/Extensions/UIEdgeInsets.swift index 33df6842bb61..0dc527c945d5 100644 --- a/WordPress/Classes/Extensions/UIEdgeInsets.swift +++ b/WordPress/Classes/Extensions/UIEdgeInsets.swift @@ -28,32 +28,6 @@ extension UIButton { imageEdgeInsets = imageEdgeInsets.flippedForRightToLeftLayoutDirection() titleEdgeInsets = titleEdgeInsets.flippedForRightToLeftLayoutDirection() } - - func verticallyAlignImageAndText(padding: CGFloat = 5) { - guard let imageView = imageView, - let titleLabel = titleLabel else { - return - } - - let imageSize = imageView.frame.size - let titleSize = titleLabel.frame.size - let totalHeight = imageSize.height + titleSize.height + padding - - imageEdgeInsets = UIEdgeInsets( - top: -(totalHeight - imageSize.height), - left: 0, - bottom: 0, - right: -titleSize.width - ) - - titleEdgeInsets = UIEdgeInsets( - top: 0, - left: -imageSize.width, - bottom: -(totalHeight - titleSize.height), - right: 0 - ) - } - } // Hack: Since UIEdgeInsets is a struct in ObjC, you can't have methods on it. diff --git a/WordPress/Classes/ViewRelated/Comments/CommentModerationBar.swift b/WordPress/Classes/ViewRelated/Comments/CommentModerationBar.swift deleted file mode 100644 index 31171537eb6e..000000000000 --- a/WordPress/Classes/ViewRelated/Comments/CommentModerationBar.swift +++ /dev/null @@ -1,327 +0,0 @@ -import UIKit - -protocol CommentModerationBarDelegate: AnyObject { - func statusChangedTo(_ commentStatus: CommentStatusType) -} - -private typealias Style = WPStyleGuide.CommentDetail.ModerationBar - -class CommentModerationBar: UIView { - - // MARK: - Properties - - @IBOutlet private weak var contentView: UIView! - - @IBOutlet private weak var pendingButton: UIButton! - @IBOutlet private weak var approvedButton: UIButton! - @IBOutlet private weak var spamButton: UIButton! - @IBOutlet private weak var trashButton: UIButton! - - @IBOutlet private weak var buttonStackViewLeadingConstraint: NSLayoutConstraint! - @IBOutlet private weak var buttonStackViewTrailingConstraint: NSLayoutConstraint! - - @IBOutlet private weak var firstDivider: UIView! - @IBOutlet private weak var secondDivider: UIView! - @IBOutlet private weak var thirdDivider: UIView! - - private var compactHorizontalPadding: CGFloat = 4 - private let iPadPaddingMultiplier: CGFloat = 0.33 - private let iPhonePaddingMultiplier: CGFloat = 0.15 - - weak var delegate: CommentModerationBarDelegate? - - var commentStatus: CommentStatusType? { - didSet { - guard oldValue != commentStatus else { - return - } - toggleButtonForStatus(oldValue) - toggleButtonForStatus(commentStatus) - } - } - - // MARK: - Init - - required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - - guard let view = loadViewFromNib() else { - DDLogError("CommentModerationBar: Failed loading view from nib.") - return - } - - // Save initial constraint value to use on device rotation. - compactHorizontalPadding = buttonStackViewLeadingConstraint.constant - - view.frame = self.bounds - configureView() - self.addSubview(view) - - NotificationCenter.default.addObserver(self, - selector: #selector(configureStackViewWidth), - name: UIDevice.orientationDidChangeNotification, - object: nil) - } - - deinit { - NotificationCenter.default.removeObserver(self) - } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - - // readjust stack view width when horizontal size class changes. - if let previousTraitCollection = previousTraitCollection, - previousTraitCollection.horizontalSizeClass != traitCollection.horizontalSizeClass { - configureStackViewWidth() - } - } - -} - -// MARK: - Private Extension - -private extension CommentModerationBar { - - // MARK: - Configure - - func loadViewFromNib() -> UIView? { - let nib = UINib(nibName: "\(CommentModerationBar.self)", bundle: Bundle.main) - return nib.instantiate(withOwner: self, options: nil).first as? UIView - } - - func configureView() { - configureBackground() - configureDividers() - configureButtons() - configureStackViewWidth() - } - - func configureBackground() { - contentView.backgroundColor = Style.barBackgroundColor - contentView.layer.cornerRadius = Style.cornerRadius - } - - func configureDividers() { - firstDivider.configureAsDivider() - secondDivider.configureAsDivider() - thirdDivider.configureAsDivider() - } - - func configureButtons() { - pendingButton.configureFor(.pending) - approvedButton.configureFor(.approved) - spamButton.configureFor(.spam) - trashButton.configureFor(.trash) - } - - @objc func configureStackViewWidth() { - // On devices with a lot of horizontal space, increase the buttonStackView margins - // so the buttons are not severely stretched out. Specifically: - // - iPad landscape - // - Non split view iPhone landscape - let horizontalPadding: CGFloat = { - if WPDeviceIdentification.isiPad() && - UIDevice.current.orientation.isLandscape && - !isInMultitasking && - traitCollection.horizontalSizeClass == .regular { - return bounds.width * iPadPaddingMultiplier - } - - if traitCollection.horizontalSizeClass == .compact && - traitCollection.verticalSizeClass == .compact { - return bounds.width * iPhonePaddingMultiplier - } - - return compactHorizontalPadding - }() - - buttonStackViewLeadingConstraint.constant = horizontalPadding - buttonStackViewTrailingConstraint.constant = horizontalPadding - } - - func toggleButtonForStatus(_ status: CommentStatusType?) { - guard let status = status else { - return - } - - switch status { - case .pending: - togglePending() - case .approved: - toggleApproved() - case .unapproved: - toggleTrash() - case .spam: - toggleSpam() - default: - break - } - } - - func togglePending() { - pendingButton.toggleState() - firstDivider.hideDivider(pendingButton.isSelected) - } - - func toggleApproved() { - approvedButton.toggleState() - firstDivider.hideDivider(approvedButton.isSelected) - secondDivider.hideDivider(approvedButton.isSelected) - } - - func toggleSpam() { - spamButton.toggleState() - secondDivider.hideDivider(spamButton.isSelected) - thirdDivider.hideDivider(spamButton.isSelected) - } - - func toggleTrash() { - trashButton.toggleState() - thirdDivider.hideDivider(trashButton.isSelected) - } - - // MARK: - Button Actions - - @IBAction func pendingTapped() { - guard !pendingButton.isSelected else { - return - } - - updateStatusTo(.pending) - } - - @IBAction func approvedTapped() { - guard !approvedButton.isSelected else { - return - } - - updateStatusTo(.approved) - } - - @IBAction func spamTapped() { - guard !spamButton.isSelected else { - return - } - - updateStatusTo(.spam) - } - - @IBAction func trashTapped() { - guard !trashButton.isSelected else { - return - } - - updateStatusTo(.unapproved) - } - - func updateStatusTo(_ status: CommentStatusType) { - ReachabilityUtils.onAvailableInternetConnectionDo { - commentStatus = status - delegate?.statusChangedTo(status) - } - } - -} - -// MARK: - Moderation Button Types - -enum ModerationButtonType { - case pending - case approved - case spam - case trash - - var label: String { - switch self { - case .pending: - return NSLocalizedString("Pending", comment: "Button title for Pending comment state.") - case .approved: - return NSLocalizedString("Approved", comment: "Button title for Approved comment state.") - case .spam: - return NSLocalizedString("Spam", comment: "Button title for Spam comment state.") - case .trash: - return NSLocalizedString("Trash", comment: "Button title for Trash comment state.") - } - } - - var defaultIcon: UIImage? { - return Style.defaultImageFor(self) - } - - var selectedIcon: UIImage? { - return Style.selectedImageFor(self) - } -} - -// MARK: - UIButton Extension - -private extension UIButton { - - func toggleState() { - isSelected.toggle() - configureState() - } - - func configureState() { - if isSelected { - backgroundColor = Style.buttonSelectedBackgroundColor - layer.shadowColor = Style.buttonSelectedShadowColor - } else { - backgroundColor = Style.buttonDefaultBackgroundColor - layer.shadowColor = Style.buttonDefaultShadowColor - } - } - - func configureFor(_ button: ModerationButtonType) { - setTitle(button.label, for: UIControl.State()) - setImage(button.defaultIcon, for: UIControl.State()) - setImage(button.selectedIcon, for: .selected) - - commonConfigure() - } - - func commonConfigure() { - setTitleColor(Style.buttonDefaultTitleColor, for: UIControl.State()) - setTitleColor(Style.buttonSelectedTitleColor, for: .selected) - - layer.cornerRadius = Style.cornerRadius - layer.shadowOffset = Style.buttonShadowOffset - layer.shadowOpacity = Style.buttonShadowOpacity - layer.shadowRadius = Style.buttonShadowRadius - - isExclusiveTouch = true - - verticallyAlignImageAndText() - flipInsetsForRightToLeftLayoutDirection() - configureState() - } - -} - -// MARK: - UIView Extension - -private extension UIView { - - func configureAsDivider() { - hideDivider(false) - - if let existingConstraint = constraint(for: .width, withRelation: .equal) { - existingConstraint.constant = .hairlineBorderWidth - } - } - - func hideDivider(_ hidden: Bool) { - backgroundColor = hidden ? Style.dividerHiddenColor : Style.dividerColor - } - - /// Detects if the current view is displayed in multitasking context. - var isInMultitasking: Bool { - guard let window = window else { - return false - } - - return window.frame.width != window.screen.bounds.width - } - -} diff --git a/WordPress/Classes/ViewRelated/Comments/CommentModerationBar.xib b/WordPress/Classes/ViewRelated/Comments/CommentModerationBar.xib deleted file mode 100644 index cad1dcadf62e..000000000000 --- a/WordPress/Classes/ViewRelated/Comments/CommentModerationBar.xib +++ /dev/null @@ -1,181 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WordPress/Classes/ViewRelated/Comments/WPStyleGuide+CommentDetail.swift b/WordPress/Classes/ViewRelated/Comments/WPStyleGuide+CommentDetail.swift index a75b5fa54af5..9216689530ad 100644 --- a/WordPress/Classes/ViewRelated/Comments/WPStyleGuide+CommentDetail.swift +++ b/WordPress/Classes/ViewRelated/Comments/WPStyleGuide+CommentDetail.swift @@ -80,76 +80,5 @@ extension WPStyleGuide { .withRenderingMode(.alwaysTemplate) .imageFlippedForRightToLeftLayoutDirection() } - - public struct ModerationBar { - static let barBackgroundColor: UIColor = .systemGray6 - static let cornerRadius: CGFloat = 15.0 - - static let dividerColor: UIColor = .systemGray - static let dividerHiddenColor: UIColor = .clear - - static let buttonShadowOffset = CGSize(width: 0, height: 2.0) - static let buttonShadowOpacity: Float = 0.25 - static let buttonShadowRadius: CGFloat = 2.0 - - static let buttonDefaultTitleColor = UIColor(light: .textSubtle, dark: .systemGray) - static let buttonSelectedTitleColor = UIColor(light: .black, dark: .white) - static let buttonDefaultBackgroundColor: UIColor = .clear - static let buttonDefaultShadowColor = UIColor.clear.cgColor - static let buttonSelectedBackgroundColor: UIColor = .tertiaryBackground - static let buttonSelectedShadowColor = UIColor.black.cgColor - - static let pendingImageName = "tray" - static let approvedImageName = "checkmark.circle" - static let spamImageName = "exclamationmark.octagon" - static let trashImageName = "trash" - - static let imageDefaultTintColor = buttonDefaultTitleColor - static let pendingSelectedColor: UIColor = .muriel(name: .yellow, .shade30) - static let approvedSelectedColor: UIColor = .muriel(name: .green, .shade40) - static let spamSelectedColor: UIColor = .muriel(name: .orange, .shade40) - static let trashSelectedColor: UIColor = .muriel(name: .red, .shade40) - - static func defaultImageFor(_ buttonType: ModerationButtonType) -> UIImage? { - return UIImage(systemName: imageNameFor(buttonType))? - .withTintColor(imageDefaultTintColor) - .withRenderingMode(.alwaysOriginal) - } - - static func selectedImageFor(_ buttonType: ModerationButtonType) -> UIImage? { - return UIImage(systemName: imageNameFor(buttonType, selected: true))? - .imageWithTintColor(imageTintColorFor(buttonType)) - } - - static func imageNameFor(_ buttonType: ModerationButtonType, selected: Bool = false) -> String { - let imageName: String = { - switch buttonType { - case .pending: - return pendingImageName - case .approved: - return approvedImageName - case .spam: - return spamImageName - case .trash: - return trashImageName - } - }() - - return selected ? (imageName + ".fill") : imageName - } - - static func imageTintColorFor(_ buttonType: ModerationButtonType) -> UIColor { - switch buttonType { - case .pending: - return pendingSelectedColor - case .approved: - return approvedSelectedColor - case .spam: - return spamSelectedColor - case .trash: - return trashSelectedColor - } - } - } } } diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 9b822f43d848..f69f52e6ad6c 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -2372,8 +2372,6 @@ 9835F16E25E492EE002EFF23 /* CommentsList.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9835F16D25E492EE002EFF23 /* CommentsList.storyboard */; }; 98390AC3254C984700868F0A /* Tracks+StatsWidgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98390AC2254C984700868F0A /* Tracks+StatsWidgets.swift */; }; 98390AD2254C985F00868F0A /* Tracks.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5FA22821C99F6180016CA7C /* Tracks.swift */; }; - 9839CEBB26FAA0530097406E /* CommentModerationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9839CEB926FAA0510097406E /* CommentModerationBar.swift */; }; - 9839CEBC26FAA0530097406E /* CommentModerationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9839CEB926FAA0510097406E /* CommentModerationBar.swift */; }; 983DBBAA22125DD500753988 /* StatsTableFooter.xib in Resources */ = {isa = PBXBuildFile; fileRef = 983DBBA822125DD300753988 /* StatsTableFooter.xib */; }; 983DBBAB22125DD500753988 /* StatsTableFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 983DBBA922125DD300753988 /* StatsTableFooter.swift */; }; 98458CB821A39D350025D232 /* StatsNoDataRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98458CB721A39D350025D232 /* StatsNoDataRow.swift */; }; @@ -2507,8 +2505,6 @@ 98F537A722496CF300B334F9 /* SiteStatsTableHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98F537A622496CF300B334F9 /* SiteStatsTableHeaderView.swift */; }; 98F537A922496D0D00B334F9 /* SiteStatsTableHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 98F537A822496D0D00B334F9 /* SiteStatsTableHeaderView.xib */; }; 98F93182239AF64800E4E96E /* ThisWeekWidgetStats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98F93181239AF64800E4E96E /* ThisWeekWidgetStats.swift */; }; - 98F9FB2E270282C200ADF552 /* CommentModerationBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = 98F9FB2D270282C100ADF552 /* CommentModerationBar.xib */; }; - 98F9FB2F270282C200ADF552 /* CommentModerationBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = 98F9FB2D270282C100ADF552 /* CommentModerationBar.xib */; }; 98FCFC232231DF43006ECDD4 /* PostStatsTitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98FCFC212231DF43006ECDD4 /* PostStatsTitleCell.swift */; }; 98FCFC242231DF43006ECDD4 /* PostStatsTitleCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 98FCFC222231DF43006ECDD4 /* PostStatsTitleCell.xib */; }; 98FF6A3E23A30A250025FD72 /* QuickStartNavigationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98FF6A3D23A30A240025FD72 /* QuickStartNavigationSettings.swift */; }; @@ -7712,7 +7708,6 @@ 9833A29B257AE7CF006B8234 /* WordPress 105.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "WordPress 105.xcdatamodel"; sourceTree = ""; }; 9835F16D25E492EE002EFF23 /* CommentsList.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = CommentsList.storyboard; sourceTree = ""; }; 98390AC2254C984700868F0A /* Tracks+StatsWidgets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Tracks+StatsWidgets.swift"; sourceTree = ""; }; - 9839CEB926FAA0510097406E /* CommentModerationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommentModerationBar.swift; sourceTree = ""; }; 983DBBA822125DD300753988 /* StatsTableFooter.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = StatsTableFooter.xib; sourceTree = ""; }; 983DBBA922125DD300753988 /* StatsTableFooter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatsTableFooter.swift; sourceTree = ""; }; 98458CB721A39D350025D232 /* StatsNoDataRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsNoDataRow.swift; sourceTree = ""; }; @@ -7825,7 +7820,6 @@ 98F537A622496CF300B334F9 /* SiteStatsTableHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteStatsTableHeaderView.swift; sourceTree = ""; }; 98F537A822496D0D00B334F9 /* SiteStatsTableHeaderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SiteStatsTableHeaderView.xib; sourceTree = ""; }; 98F93181239AF64800E4E96E /* ThisWeekWidgetStats.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThisWeekWidgetStats.swift; sourceTree = ""; }; - 98F9FB2D270282C100ADF552 /* CommentModerationBar.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CommentModerationBar.xib; sourceTree = ""; }; 98FB6E9F23074CE5002DDC8D /* Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Common.xcconfig; sourceTree = ""; }; 98FBA05426B228CB004E610A /* WordPress 129.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "WordPress 129.xcdatamodel"; sourceTree = ""; }; 98FCFC212231DF43006ECDD4 /* PostStatsTitleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostStatsTitleCell.swift; sourceTree = ""; }; @@ -18068,8 +18062,6 @@ FE43DAAD26DFAD1C00CFF595 /* CommentContentTableViewCell.swift */, FE43DAAE26DFAD1C00CFF595 /* CommentContentTableViewCell.xib */, FEA7948C26DD136700CEC520 /* CommentHeaderTableViewCell.swift */, - 9839CEB926FAA0510097406E /* CommentModerationBar.swift */, - 98F9FB2D270282C100ADF552 /* CommentModerationBar.xib */, ); name = Detail; sourceTree = ""; @@ -19107,7 +19099,6 @@ 469CE06E24BCED75003BDC8B /* CategorySectionTableViewCell.xib in Resources */, 4034FDEE2007D4F700153B87 /* ExpandableCell.xib in Resources */, 1761F18026209AEE000815EF /* jetpack-green-icon-app-76x76.png in Resources */, - 98F9FB2E270282C200ADF552 /* CommentModerationBar.xib in Resources */, E61507E42220A13B00213D33 /* richEmbedScript.js in Resources */, 17222D96261DDDF90047B163 /* pink-icon-app-60x60@3x.png in Resources */, 1761F18226209AEE000815EF /* jetpack-green-icon-app-60x60@3x.png in Resources */, @@ -19674,7 +19665,6 @@ FABB20BE2602FC2C00C8785C /* SiteSegmentsWizardContent.xib in Resources */, F41E4EAD28F20DF9001880C6 /* stroke-light-icon-app-83.5@2x.png in Resources */, F46597B228E6605E00D5F49A /* neu-green-icon-app-83.5@2x.png in Resources */, - 98F9FB2F270282C200ADF552 /* CommentModerationBar.xib in Resources */, 982D9A0126F922C100AA794C /* InlineEditableMultiLineCell.xib in Resources */, FABB20BF2602FC2C00C8785C /* DetailDataCell.xib in Resources */, F465980028E66A1100D5F49A /* white-on-black-icon-app-83.5@2x.png in Resources */, @@ -21205,7 +21195,6 @@ 3F29EB7224042276005313DE /* MeViewController+UIViewControllerRestoration.swift in Sources */, 74729CAA2057100200D1394D /* SearchIdentifierGenerator.swift in Sources */, 98D52C3222B1CFEC00831529 /* StatsTwoColumnRow.swift in Sources */, - 9839CEBB26FAA0530097406E /* CommentModerationBar.swift in Sources */, D88106FA20C0CFEE001D2F00 /* ReaderSaveForLaterRemovedPosts.swift in Sources */, 1751E5931CE23801000CA08D /* NSAttributedString+StyledHTML.swift in Sources */, 3F8513DF260D091500A4B938 /* RoundRectangleView.swift in Sources */, @@ -25144,7 +25133,6 @@ FABB24F42602FC2C00C8785C /* NoticePresenter.swift in Sources */, FABB24F52602FC2C00C8785C /* ReaderTagTopic.swift in Sources */, FABB24F62602FC2C00C8785C /* Media.swift in Sources */, - 9839CEBC26FAA0530097406E /* CommentModerationBar.swift in Sources */, 837966A3299E9C85004A92B9 /* JetpackInstallPluginHelper.swift in Sources */, 17039227282E6DF500F602E9 /* ViewsVisitorsChartMarker.swift in Sources */, FABB24F72602FC2C00C8785C /* WordPressOrgRestApi+WordPress.swift in Sources */, From d1e147f0dbd9144e5e78e3c63f1b7200f37817d2 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 21 Jun 2023 11:11:44 +1000 Subject: [PATCH 06/23] Bump version number --- config/Version.internal.xcconfig | 4 ++-- config/Version.public.xcconfig | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/Version.internal.xcconfig b/config/Version.internal.xcconfig index 8927b5b4f3ab..ff473ec3fc79 100644 --- a/config/Version.internal.xcconfig +++ b/config/Version.internal.xcconfig @@ -1,4 +1,4 @@ -VERSION_SHORT=22.5 +VERSION_SHORT=22.5.1 // Internal long version example: VERSION_LONG=9.9.0.20180423 -VERSION_LONG=22.5.0.20230609 +VERSION_LONG=22.5.1.20230621 diff --git a/config/Version.public.xcconfig b/config/Version.public.xcconfig index bb9a74d44e8a..278c0ce3a667 100644 --- a/config/Version.public.xcconfig +++ b/config/Version.public.xcconfig @@ -1,4 +1,4 @@ -VERSION_SHORT=22.5 +VERSION_SHORT=22.5.1 // Public long version example: VERSION_LONG=9.9.0.0 -VERSION_LONG=22.5.0.3 +VERSION_LONG=22.5.1.0 From f53369e020cf02cd6485ca466359b8e9b40a55cd Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 20 Jun 2023 21:23:44 -0400 Subject: [PATCH 07/23] Fix an issue with PostMetaButton not visible from Interface Builder --- .../System/WordPress-Bridging-Header.h | 1 + ...utton.swift => PostMetaButton+Swift.swift} | 6 ++---- .../Classes/ViewRelated/Post/PostMetaButton.h | 5 +++++ .../Classes/ViewRelated/Post/PostMetaButton.m | 4 ++++ WordPress/WordPress.xcodeproj/project.pbxproj | 20 +++++++++++++------ 5 files changed, 26 insertions(+), 10 deletions(-) rename WordPress/Classes/ViewRelated/Post/{PostMetaButton.swift => PostMetaButton+Swift.swift} (54%) create mode 100644 WordPress/Classes/ViewRelated/Post/PostMetaButton.h create mode 100644 WordPress/Classes/ViewRelated/Post/PostMetaButton.m diff --git a/WordPress/Classes/System/WordPress-Bridging-Header.h b/WordPress/Classes/System/WordPress-Bridging-Header.h index 7b4ed9c4fd21..edb53eda397d 100644 --- a/WordPress/Classes/System/WordPress-Bridging-Header.h +++ b/WordPress/Classes/System/WordPress-Bridging-Header.h @@ -46,6 +46,7 @@ #import "PostCategoryService.h" #import "PostContentProvider.h" #import "PostListFooterView.h" +#import "PostMetaButton.h" #import "PostService.h" #import "PostServiceOptions.h" #import "PostSettingsViewController.h" diff --git a/WordPress/Classes/ViewRelated/Post/PostMetaButton.swift b/WordPress/Classes/ViewRelated/Post/PostMetaButton+Swift.swift similarity index 54% rename from WordPress/Classes/ViewRelated/Post/PostMetaButton.swift rename to WordPress/Classes/ViewRelated/Post/PostMetaButton+Swift.swift index 69ed7886c7ed..09507ae0fe06 100644 --- a/WordPress/Classes/ViewRelated/Post/PostMetaButton.swift +++ b/WordPress/Classes/ViewRelated/Post/PostMetaButton+Swift.swift @@ -1,9 +1,7 @@ import UIKit -// Temporary converted to Swift silence the compiler warnings that are treated -// as errors in Objective-C files. -final class PostMetaButton: UIButton { - override var intrinsicContentSize: CGSize { +extension PostMetaButton { + open override var intrinsicContentSize: CGSize { var newSize = super.intrinsicContentSize newSize.width += (imageEdgeInsets.left + imageEdgeInsets.right) newSize.width += (titleEdgeInsets.left + titleEdgeInsets.right) diff --git a/WordPress/Classes/ViewRelated/Post/PostMetaButton.h b/WordPress/Classes/ViewRelated/Post/PostMetaButton.h new file mode 100644 index 000000000000..c25ca7ea4376 --- /dev/null +++ b/WordPress/Classes/ViewRelated/Post/PostMetaButton.h @@ -0,0 +1,5 @@ +#import + +@interface PostMetaButton : UIButton + +@end diff --git a/WordPress/Classes/ViewRelated/Post/PostMetaButton.m b/WordPress/Classes/ViewRelated/Post/PostMetaButton.m new file mode 100644 index 000000000000..81f026c1d7e2 --- /dev/null +++ b/WordPress/Classes/ViewRelated/Post/PostMetaButton.m @@ -0,0 +1,4 @@ +#import "PostMetaButton.h" + +@implementation PostMetaButton +@end diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index f69f52e6ad6c..011f609f9cfa 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -351,8 +351,10 @@ 0C391E622A3002950040EA91 /* BlazeCampaignStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C391E602A3002950040EA91 /* BlazeCampaignStatusView.swift */; }; 0C391E642A312DB20040EA91 /* BlazeCampaignViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C391E632A312DB20040EA91 /* BlazeCampaignViewModelTests.swift */; }; 0C63266F2A3D1305000B8C57 /* GutenbergFilesAppMediaSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C63266E2A3D1305000B8C57 /* GutenbergFilesAppMediaSourceTests.swift */; }; - 0C71959E2A3CDC8B002EA18C /* PostMetaButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C71959D2A3CDC8B002EA18C /* PostMetaButton.swift */; }; - 0C71959F2A3CDC8B002EA18C /* PostMetaButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C71959D2A3CDC8B002EA18C /* PostMetaButton.swift */; }; + 0C7E09202A4286A00052324C /* PostMetaButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7E091F2A4286A00052324C /* PostMetaButton.m */; }; + 0C7E09212A4286A00052324C /* PostMetaButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7E091F2A4286A00052324C /* PostMetaButton.m */; }; + 0C7E09242A4286F40052324C /* PostMetaButton+Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C7E09232A4286F40052324C /* PostMetaButton+Swift.swift */; }; + 0C7E09252A4286F40052324C /* PostMetaButton+Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C7E09232A4286F40052324C /* PostMetaButton+Swift.swift */; }; 0CB4056B29C78F06008EED0A /* BlogDashboardPersonalizationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB4056A29C78F06008EED0A /* BlogDashboardPersonalizationService.swift */; }; 0CB4056C29C78F06008EED0A /* BlogDashboardPersonalizationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB4056A29C78F06008EED0A /* BlogDashboardPersonalizationService.swift */; }; 0CB4056E29C7BA63008EED0A /* BlogDashboardPersonalizationServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB4056D29C7BA63008EED0A /* BlogDashboardPersonalizationServiceTests.swift */; }; @@ -6044,7 +6046,9 @@ 0C391E602A3002950040EA91 /* BlazeCampaignStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlazeCampaignStatusView.swift; sourceTree = ""; }; 0C391E632A312DB20040EA91 /* BlazeCampaignViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlazeCampaignViewModelTests.swift; sourceTree = ""; }; 0C63266E2A3D1305000B8C57 /* GutenbergFilesAppMediaSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GutenbergFilesAppMediaSourceTests.swift; sourceTree = ""; }; - 0C71959D2A3CDC8B002EA18C /* PostMetaButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostMetaButton.swift; sourceTree = ""; }; + 0C7E091F2A4286A00052324C /* PostMetaButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PostMetaButton.m; sourceTree = ""; }; + 0C7E09222A4286AA0052324C /* PostMetaButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PostMetaButton.h; sourceTree = ""; }; + 0C7E09232A4286F40052324C /* PostMetaButton+Swift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PostMetaButton+Swift.swift"; sourceTree = ""; }; 0CB4056A29C78F06008EED0A /* BlogDashboardPersonalizationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlogDashboardPersonalizationService.swift; sourceTree = ""; }; 0CB4056D29C7BA63008EED0A /* BlogDashboardPersonalizationServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlogDashboardPersonalizationServiceTests.swift; sourceTree = ""; }; 0CB4057029C8DCF4008EED0A /* BlogDashboardPersonalizationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlogDashboardPersonalizationViewModel.swift; sourceTree = ""; }; @@ -12388,7 +12392,9 @@ 5D732F951AE84E3C00CD89E7 /* PostListFooterView.h */, 5D732F961AE84E3C00CD89E7 /* PostListFooterView.m */, 5D732F981AE84E5400CD89E7 /* PostListFooterView.xib */, - 0C71959D2A3CDC8B002EA18C /* PostMetaButton.swift */, + 0C7E09222A4286AA0052324C /* PostMetaButton.h */, + 0C7E091F2A4286A00052324C /* PostMetaButton.m */, + 0C7E09232A4286F40052324C /* PostMetaButton+Swift.swift */, 17F67C55203D81430072001E /* PostCardStatusViewModel.swift */, 17A28DC42050404C00EA6D9E /* AuthorFilterButton.swift */, 17A28DCA2052FB5D00EA6D9E /* AuthorFilterViewController.swift */, @@ -21001,9 +21007,11 @@ 986CC4D220E1B2F6004F300E /* CustomLogFormatter.swift in Sources */, 3236F77524ABB7770088E8F3 /* ReaderInterestsCollectionViewCell.swift in Sources */, 40A71C6A220E1952002E3D25 /* StatsRecord+CoreDataClass.swift in Sources */, + 0C7E09202A4286A00052324C /* PostMetaButton.m in Sources */, 9826AE8221B5C6A700C851FA /* LatestPostSummaryCell.swift in Sources */, F47E154A29E84A9300B6E426 /* DomainPurchasingWebFlowController.swift in Sources */, 433432521E9ED18900915988 /* LoginEpilogueViewController.swift in Sources */, + 0C7E09242A4286F40052324C /* PostMetaButton+Swift.swift in Sources */, 4395A1592106389800844E8E /* QuickStartTours.swift in Sources */, 9A2B28EE2191B50500458F2A /* RevisionsTableViewFooter.swift in Sources */, 80EF671F27F135EB0063B138 /* WhatIsNewViewAppearance.swift in Sources */, @@ -21144,7 +21152,6 @@ 98BFF57E23984345008A1DCB /* AllTimeWidgetStats.swift in Sources */, 7E40713A2372AD54003627FA /* GutenbergFilesAppMediaSource.swift in Sources */, B532D4EC199D4357006E4DF6 /* NoteBlockTextTableViewCell.swift in Sources */, - 0C71959E2A3CDC8B002EA18C /* PostMetaButton.swift in Sources */, 8B15CDAB27EB89AD00A75749 /* BlogDashboardPostsParser.swift in Sources */, B52F8CD81B43260C00D36025 /* NotificationSettingStreamsViewController.swift in Sources */, 464688D8255C71D200ECA61C /* SiteDesignPreviewViewController.swift in Sources */, @@ -23806,6 +23813,7 @@ FABB211E2602FC2C00C8785C /* UIView+Subviews.m in Sources */, FABB211F2602FC2C00C8785C /* WordPress-20-21.xcmappingmodel in Sources */, 8B55FA002614D980007D618E /* UnifiedPrologueNotificationsContentView.swift in Sources */, + 0C7E09252A4286F40052324C /* PostMetaButton+Swift.swift in Sources */, FABB21202602FC2C00C8785C /* TenorClient.swift in Sources */, FABB21212602FC2C00C8785C /* LoginEpilogueTableViewController.swift in Sources */, FABB21222602FC2C00C8785C /* JetpackRemoteInstallViewModel.swift in Sources */, @@ -24308,6 +24316,7 @@ 1770BD0E267A368100D5F8C0 /* BloggingRemindersPushPromptViewController.swift in Sources */, C7BB601A2863AF9700748FD9 /* QRLoginProtocols.swift in Sources */, FABB22912602FC2C00C8785C /* FilterProvider.swift in Sources */, + 0C7E09212A4286A00052324C /* PostMetaButton.m in Sources */, FABB22922602FC2C00C8785C /* DomainCreditEligibilityChecker.swift in Sources */, FABB22932602FC2C00C8785C /* SiteSettingsViewController.m in Sources */, 987E79CC261F8858000192B7 /* UserProfileSheetViewController.swift in Sources */, @@ -25206,7 +25215,6 @@ FABB25262602FC2C00C8785C /* String+RegEx.swift in Sources */, 175CC17A27230DC900622FB4 /* Bool+StringRepresentation.swift in Sources */, F1BC842F27035A1800C39993 /* BlogService+Domains.swift in Sources */, - 0C71959F2A3CDC8B002EA18C /* PostMetaButton.swift in Sources */, FE7FAABF299A998F0032A6F2 /* EventTracker.swift in Sources */, 8B33BC9627A0C14C00DB5985 /* BlogDetailsViewController+QuickActions.swift in Sources */, FABB25272602FC2C00C8785C /* UIImage+Exporters.swift in Sources */, From 8471c61f8ab6d3ee5c1933934a1271a24d9c3c41 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Wed, 21 Jun 2023 11:20:26 +1000 Subject: [PATCH 08/23] Fix a Core Data concurrency issue when CrashLogging is called from a background thread (#20846) Co-authored-by: Salim --- RELEASE-NOTES.txt | 4 ++ .../Logging/WPCrashLoggingProvider.swift | 17 +++-- WordPress/WordPress.xcodeproj/project.pbxproj | 12 ++++ .../WPCrashLoggingDataProviderTests.swift | 62 +++++++++++++++++++ 4 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 WordPress/WordPressTest/WPCrashLoggingDataProviderTests.swift diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 3cfae22bf9e4..712dc35a11bc 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,6 +1,10 @@ 22.6 ----- +22.5.1 +----- + +* [*] Resolve an issue that was causing the app crash when `CrashLogging.logError` is called from a background thread. [#20846] 22.5 ----- diff --git a/WordPress/Classes/Utility/Logging/WPCrashLoggingProvider.swift b/WordPress/Classes/Utility/Logging/WPCrashLoggingProvider.swift index bf8319dbd521..43770b7f486a 100644 --- a/WordPress/Classes/Utility/Logging/WPCrashLoggingProvider.swift +++ b/WordPress/Classes/Utility/Logging/WPCrashLoggingProvider.swift @@ -35,6 +35,12 @@ struct WPLoggingStack { } struct WPCrashLoggingDataProvider: CrashLoggingDataProvider { + private let contextManager: ContextManager + + init(contextManager: ContextManager = .shared) { + self.contextManager = contextManager + } + let sentryDSN: String = ApiCredentials.sentryDSN var userHasOptedOut: Bool { @@ -48,12 +54,11 @@ struct WPCrashLoggingDataProvider: CrashLoggingDataProvider { } var currentUser: TracksUser? { - let context = ContextManager.sharedInstance().mainContext - - guard let account = try? WPAccount.lookupDefaultWordPressComAccount(in: context) else { - return nil + return contextManager.performQuery { context -> TracksUser? in + guard let account = try? WPAccount.lookupDefaultWordPressComAccount(in: context) else { + return nil + } + return TracksUser(userID: account.userID.stringValue, email: account.email, username: account.username) } - - return TracksUser(userID: account.userID.stringValue, email: account.email, username: account.username) } } diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index e64b4d4d8630..16dea7023f84 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -3546,6 +3546,7 @@ F41E4EEF28F247D3001880C6 /* white-on-green-icon-app-60@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F41E4EEA28F247D3001880C6 /* white-on-green-icon-app-60@2x.png */; }; F41E4EF028F247D3001880C6 /* white-on-green-icon-app-76@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F41E4EEB28F247D3001880C6 /* white-on-green-icon-app-76@2x.png */; }; F42A1D9729928B360059CC70 /* BlockedAuthor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42A1D9629928B360059CC70 /* BlockedAuthor.swift */; }; + F4394D1F2A3AB06F003955C6 /* WPCrashLoggingDataProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4394D1E2A3AB06F003955C6 /* WPCrashLoggingDataProviderTests.swift */; }; F4426FD3287E08C300218003 /* SuggestionServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4426FD2287E08C300218003 /* SuggestionServiceMock.swift */; }; F4426FD9287F02FD00218003 /* SiteSuggestionsServiceMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4426FD8287F02FD00218003 /* SiteSuggestionsServiceMock.swift */; }; F4426FDB287F066400218003 /* site-suggestions.json in Resources */ = {isa = PBXBuildFile; fileRef = F4426FDA287F066400218003 /* site-suggestions.json */; }; @@ -8934,6 +8935,7 @@ F41E4EEB28F247D3001880C6 /* white-on-green-icon-app-76@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "white-on-green-icon-app-76@2x.png"; sourceTree = ""; }; F42A1D9629928B360059CC70 /* BlockedAuthor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockedAuthor.swift; sourceTree = ""; }; F432964A287752690089C4F7 /* WordPress 144.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "WordPress 144.xcdatamodel"; sourceTree = ""; }; + F4394D1E2A3AB06F003955C6 /* WPCrashLoggingDataProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WPCrashLoggingDataProviderTests.swift; sourceTree = ""; }; F4426FD2287E08C300218003 /* SuggestionServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuggestionServiceMock.swift; sourceTree = ""; }; F4426FD8287F02FD00218003 /* SiteSuggestionsServiceMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteSuggestionsServiceMock.swift; sourceTree = ""; }; F4426FDA287F066400218003 /* site-suggestions.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "site-suggestions.json"; sourceTree = ""; }; @@ -13345,6 +13347,7 @@ 852416D01A12ED2D0030700C /* Utility */ = { isa = PBXGroup; children = ( + F4394D202A3B6F43003955C6 /* Crash Logging */, 17AF92241C46634000A99CFB /* BlogSiteVisibilityHelperTest.m */, 93A379EB19FFBF7900415023 /* KeychainTest.m */, 5948AD101AB73D19006E8882 /* WPAppAnalyticsTests.m */, @@ -17098,6 +17101,14 @@ path = "white-on-green"; sourceTree = ""; }; + F4394D202A3B6F43003955C6 /* Crash Logging */ = { + isa = PBXGroup; + children = ( + F4394D1E2A3AB06F003955C6 /* WPCrashLoggingDataProviderTests.swift */, + ); + name = "Crash Logging"; + sourceTree = ""; + }; F44293D428E3B39400D340AF /* App Icons */ = { isa = PBXGroup; children = ( @@ -23429,6 +23440,7 @@ 08A4E12F289D2795001D9EC7 /* UserPersistentStoreTests.swift in Sources */, 436D55F5211632B700CEAA33 /* RegisterDomainDetailsViewModelTests.swift in Sources */, E180BD4C1FB462FF00D0D781 /* CookieJarTests.swift in Sources */, + F4394D1F2A3AB06F003955C6 /* WPCrashLoggingDataProviderTests.swift in Sources */, 9813512E22F0FC2700F7425D /* FileDownloadsStatsRecordValueTests.swift in Sources */, 9363113F19FA996700B0C739 /* AccountServiceTests.swift in Sources */, 17FC0032264D728E00FCBD37 /* SharingServiceTests.swift in Sources */, diff --git a/WordPress/WordPressTest/WPCrashLoggingDataProviderTests.swift b/WordPress/WordPressTest/WPCrashLoggingDataProviderTests.swift new file mode 100644 index 000000000000..8e82948a1e52 --- /dev/null +++ b/WordPress/WordPressTest/WPCrashLoggingDataProviderTests.swift @@ -0,0 +1,62 @@ +import XCTest +import AutomatticTracks + +@testable import WordPress + +final class WPCrashLoggingDataProviderTests: XCTestCase { + + // MARK: - Testing Log Error + + func testReadingTrackUserInMainThread() throws { + // Given + let dataProvider = self.makeCrashLoggingDataProvider() + + // When + let user = try XCTUnwrap(dataProvider.currentUser) + + // Then + XCTAssertEqual(user.userID, "\(Constants.defaultAccountID)") + XCTAssertEqual(user.username, Constants.defaultAccountUsername) + XCTAssertEqual(user.email, Constants.defaultAccountEmail) + } + + func testReadingTrackUserInBackgroundThread() async { + let dataProvider = self.makeCrashLoggingDataProvider() + await withThrowingTaskGroup(of: Void.self) { group in + for _ in 1...1000 { + group.addTask { + let user = try XCTUnwrap(dataProvider.currentUser) + XCTAssertEqual(user.userID, "\(Constants.defaultAccountID)") + XCTAssertEqual(user.username, Constants.defaultAccountUsername) + XCTAssertEqual(user.email, Constants.defaultAccountEmail) + } + } + } + } + + // MARK: - Helpers + + private func makeCrashLoggingDataProvider() -> WPCrashLoggingDataProvider { + let provider = WPCrashLoggingDataProvider(contextManager: makeCoreDataStack()) + return provider + } + + private func makeCoreDataStack() -> ContextManager { + let contextManager = ContextManager.forTesting() + let account = AccountBuilder(contextManager) + .with(id: Constants.defaultAccountID) + .with(email: Constants.defaultAccountEmail) + .with(username: Constants.defaultAccountUsername) + .build() + UserSettings.defaultDotComUUID = account.uuid + return contextManager + } + + // MARK: - Constants + + private enum Constants { + static let defaultAccountID: Int64 = 123 + static let defaultAccountEmail: String = "foo@automattic.com" + static let defaultAccountUsername: String = "foobar" + } +} From 845d2f0d92f40557fb64a9884d3dc6168b6d3d5a Mon Sep 17 00:00:00 2001 From: jos <17252150+jostnes@users.noreply.github.com> Date: Wed, 21 Jun 2023 09:55:28 +0800 Subject: [PATCH 09/23] update indent on login tests --- WordPress/UITests/Tests/LoginTests.swift | 20 ++++++++++++++++---- WordPress/UITests/Tests/SignupTests.swift | 5 ++++- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/WordPress/UITests/Tests/LoginTests.swift b/WordPress/UITests/Tests/LoginTests.swift index 1e9203400c13..00828cc18f0d 100644 --- a/WordPress/UITests/Tests/LoginTests.swift +++ b/WordPress/UITests/Tests/LoginTests.swift @@ -18,7 +18,10 @@ class LoginTests: XCTestCase { .selectContinue() .proceedWith(email: WPUITestCredentials.testWPcomUserEmail) .proceedWithValidPassword() - .verifyEpilogueDisplays(username: WPUITestCredentials.testWPcomUsername, siteUrl: WPUITestCredentials.testWPcomSitePrimaryAddress) + .verifyEpilogueDisplays( + username: WPUITestCredentials.testWPcomUsername, + siteUrl: WPUITestCredentials.testWPcomSitePrimaryAddress + ) .continueWithSelectedSite() .dismissNotificationAlertIfNeeded() .tabBar.goToMeScreen() @@ -48,7 +51,10 @@ class LoginTests: XCTestCase { try PrologueScreen() .selectSiteAddress() .proceedWith(siteUrl: WPUITestCredentials.selfHostedSiteAddress) - .proceedWithSelfHosted(username: WPUITestCredentials.selfHostedUsername, password: WPUITestCredentials.selfHostedPassword) + .proceedWithSelfHosted( + username: WPUITestCredentials.selfHostedUsername, + password: WPUITestCredentials.selfHostedPassword + ) .removeSelfHostedSite() try PrologueScreen() .assertScreenIsLoaded() @@ -70,7 +76,10 @@ class LoginTests: XCTestCase { .selectContinue() .proceedWith(email: WPUITestCredentials.testWPcomUserEmail) .proceedWithValidPassword() - .verifyEpilogueDisplays(username: WPUITestCredentials.testWPcomUsername, siteUrl: WPUITestCredentials.testWPcomSitePrimaryAddress) + .verifyEpilogueDisplays( + username: WPUITestCredentials.testWPcomUsername, + siteUrl: WPUITestCredentials.testWPcomSitePrimaryAddress + ) .continueWithSelectedSite() //returns MySite screen // From here, bring up the sites list and choose to add a new self-hosted site. @@ -79,7 +88,10 @@ class LoginTests: XCTestCase { // Then, go through the self-hosted login flow: .proceedWith(siteUrl: WPUITestCredentials.selfHostedSiteAddress) - .proceedWithSelfHostedSiteAddedFromSitesList(username: WPUITestCredentials.selfHostedUsername, password: WPUITestCredentials.selfHostedPassword) + .proceedWithSelfHostedSiteAddedFromSitesList( + username: WPUITestCredentials.selfHostedUsername, + password: WPUITestCredentials.selfHostedPassword + ) // Login flow returns MySites modal, which needs to be closed. .closeModal() diff --git a/WordPress/UITests/Tests/SignupTests.swift b/WordPress/UITests/Tests/SignupTests.swift index f661b1facbef..eb448762e373 100644 --- a/WordPress/UITests/Tests/SignupTests.swift +++ b/WordPress/UITests/Tests/SignupTests.swift @@ -18,7 +18,10 @@ class SignupTests: XCTestCase { .selectEmailSignup() .proceedWith(email: WPUITestCredentials.signupEmail) .openMagicSignupLink() - .verifyEpilogueContains(username: WPUITestCredentials.signupUsername, displayName: WPUITestCredentials.signupDisplayName) + .verifyEpilogueContains( + username: WPUITestCredentials.signupUsername, + displayName: WPUITestCredentials.signupDisplayName + ) .setPassword(WPUITestCredentials.signupPassword) .continueWithSignup() .dismissNotificationAlertIfNeeded() From dbea18146380bff80595655ce0d5a21ce36dc9e2 Mon Sep 17 00:00:00 2001 From: Momo Ozawa Date: Tue, 13 Jun 2023 09:40:53 +0100 Subject: [PATCH 10/23] call the correct super method --- .../ViewRelated/Reader/Detail/ReaderDetailViewController.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Reader/Detail/ReaderDetailViewController.swift b/WordPress/Classes/ViewRelated/Reader/Detail/ReaderDetailViewController.swift index f258f1b51ff5..058553522902 100644 --- a/WordPress/Classes/ViewRelated/Reader/Detail/ReaderDetailViewController.swift +++ b/WordPress/Classes/ViewRelated/Reader/Detail/ReaderDetailViewController.swift @@ -206,8 +206,7 @@ class ReaderDetailViewController: UIViewController, ReaderDetailView { } override func viewDidDisappear(_ animated: Bool) { - super.viewDidAppear(animated) - + super.viewDidDisappear(animated) ReaderTracker.shared.stop(.readerPost) } From fb108c141c8f8aa57254b3bb5b9e36dc6969bf1c Mon Sep 17 00:00:00 2001 From: Tony Li Date: Wed, 14 Jun 2023 11:47:01 +1200 Subject: [PATCH 11/23] Run the "null blog property sanitization" logic as the very first Core Data operation --- .../Classes/Services/NullBlogPropertySanitizer.swift | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/WordPress/Classes/Services/NullBlogPropertySanitizer.swift b/WordPress/Classes/Services/NullBlogPropertySanitizer.swift index f4120241f319..6472f379833c 100644 --- a/WordPress/Classes/Services/NullBlogPropertySanitizer.swift +++ b/WordPress/Classes/Services/NullBlogPropertySanitizer.swift @@ -39,7 +39,7 @@ import Foundation PostCategory.entityName() ] - context.perform { + let block = { entityNamesWithRequiredBlogProperties.forEach { entityName in let request = NSFetchRequest(entityName: entityName) let predicate = NSPredicate(format: "blog == NULL") @@ -58,6 +58,13 @@ import Foundation try? self.context.save() } + + // Make sure the "sanitization" work is done before any other Core Data reads or writes. + if Thread.isMainThread, context.concurrencyType == .mainQueueConcurrencyType { + block() + } else { + context.perform(block) + } } private func appWasUpdated() -> Bool { From 01b9a869358443e15fa4d1e399e266da41043aed Mon Sep 17 00:00:00 2001 From: Tony Li Date: Wed, 14 Jun 2023 15:07:29 +1200 Subject: [PATCH 12/23] Add a release note --- RELEASE-NOTES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 712dc35a11bc..c1ee49363791 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -5,6 +5,7 @@ ----- * [*] Resolve an issue that was causing the app crash when `CrashLogging.logError` is called from a background thread. [#20846] +* [**] [internal] Make sure a database tidy-up task (null blog property sanitizer) is completed before any other Core Data queries. [#20867] 22.5 ----- From 0df1471c98dc3e2bcc22d766a89c7e33cae750f3 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Tue, 20 Jun 2023 20:03:49 +1000 Subject: [PATCH 13/23] Use MediaEditor 1.2.2 This version has a fix for a possible life-cycle issue. --- Podfile | 2 +- Podfile.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Podfile b/Podfile index 07988c318684..d9f9a94052a5 100644 --- a/Podfile +++ b/Podfile @@ -153,7 +153,7 @@ abstract_target 'Apps' do # pod 'WordPressAuthenticator', git: 'https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git', commit: '' # pod 'WordPressAuthenticator', path: '../WordPressAuthenticator-iOS' - pod 'MediaEditor', '~> 1.2.1' + pod 'MediaEditor', '~> 1.2', '>= 1.2.2' # pod 'MediaEditor', git: 'https://github.com/wordpress-mobile/MediaEditor-iOS.git', commit: '' # pod 'MediaEditor', path: '../MediaEditor-iOS' diff --git a/Podfile.lock b/Podfile.lock index 0fc21fbdc6f4..7d65e6f592c5 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -70,7 +70,7 @@ PODS: - libwebp/mux (1.2.4): - libwebp/demux - libwebp/webp (1.2.4) - - MediaEditor (1.2.1): + - MediaEditor (1.2.2): - CropViewController (~> 2.5.3) - MRProgress (0.8.3): - MRProgress/ActivityIndicator (= 0.8.3) @@ -559,7 +559,7 @@ DEPENDENCIES: - Gutenberg (from `https://github.com/wordpress-mobile/gutenberg-mobile.git`, tag `v1.96.1`) - JTAppleCalendar (~> 8.0.2) - Kanvas (~> 1.4.4) - - MediaEditor (~> 1.2.1) + - MediaEditor (>= 1.2.2, ~> 1.2) - MRProgress (= 0.8.3) - NSObject-SafeExpectations (~> 0.0.4) - "NSURL+IDN (~> 0.4)" @@ -825,7 +825,7 @@ SPEC CHECKSUMS: JTAppleCalendar: 932cadea40b1051beab10f67843451d48ba16c99 Kanvas: f932eaed3d3f47aae8aafb6c2d27c968bdd49030 libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef - MediaEditor: 20cdeb46bdecd040b8bc94467ac85a52b53b193a + MediaEditor: d08314cfcbfac74361071a306b4bc3a39b3356ae MRProgress: 16de7cc9f347e8846797a770db102a323fe7ef09 NSObject-SafeExpectations: ab8fe623d36b25aa1f150affa324e40a2f3c0374 "NSURL+IDN": afc873e639c18138a1589697c3add197fe8679ca @@ -900,6 +900,6 @@ SPEC CHECKSUMS: ZendeskSupportSDK: 3a8e508ab1d9dd22dc038df6c694466414e037ba ZIPFoundation: ae5b4b813d216d3bf0a148773267fff14bd51d37 -PODFILE CHECKSUM: 8f3801df87501615cc7418c5a128cd9136848813 +PODFILE CHECKSUM: 245b75e4e052be1a0aa04f20f875aeaccefa5336 COCOAPODS: 1.11.3 From 7bf791128cedfa031ef7e31b5300c41da38a5626 Mon Sep 17 00:00:00 2001 From: kean Date: Wed, 14 Jun 2023 19:21:36 -0400 Subject: [PATCH 14/23] Add SettingsPicker --- .../Blog/Settings/SettingsCell.swift | 19 +++++ .../Blog/Settings/SettingsPicker.swift | 81 +++++++++++++++++++ WordPress/WordPress.xcodeproj/project.pbxproj | 26 ++++++ 3 files changed, 126 insertions(+) create mode 100644 WordPress/Classes/ViewRelated/Blog/Settings/SettingsCell.swift create mode 100644 WordPress/Classes/ViewRelated/Blog/Settings/SettingsPicker.swift diff --git a/WordPress/Classes/ViewRelated/Blog/Settings/SettingsCell.swift b/WordPress/Classes/ViewRelated/Blog/Settings/SettingsCell.swift new file mode 100644 index 000000000000..c2c1c805d68a --- /dev/null +++ b/WordPress/Classes/ViewRelated/Blog/Settings/SettingsCell.swift @@ -0,0 +1,19 @@ +import SwiftUI + + struct SettingsCell: View { + let title: String + let value: String? + var placeholder: String? + + var body: some View { + HStack { + Text(title) + .layoutPriority(1) + .foregroundColor(.primary) + Spacer() + Text(value ?? (placeholder ?? "")) + .foregroundColor(.secondary) + } + .lineLimit(1) + } + } diff --git a/WordPress/Classes/ViewRelated/Blog/Settings/SettingsPicker.swift b/WordPress/Classes/ViewRelated/Blog/Settings/SettingsPicker.swift new file mode 100644 index 000000000000..f1d119022151 --- /dev/null +++ b/WordPress/Classes/ViewRelated/Blog/Settings/SettingsPicker.swift @@ -0,0 +1,81 @@ +import SwiftUI + +struct SettingsPicker: View { + let title: String + @Binding var selection: T + let values: [SettingsPickerValue] + + private var isEditable = true + + init(title: String, selection: Binding, values: [SettingsPickerValue]) { + self.title = title + self._selection = selection + self.values = values + } + + var body: some View { + let value = values.first { $0.id == selection } + let cell = SettingsCell(title: title, value: value?.title) + if isEditable { + NavigationLink(destination: { + SettingsPickerListView(selection: $selection, values: values) + .navigationTitle(title) + }, label: { + cell + }) + } else { + cell + } + } + + /// Disables editing if set to `false`. By default, the picker is editable. + func editable(_ isEditable: Bool) -> Self { + var copy = self + copy.isEditable = isEditable + return copy + } +} + +struct SettingsPickerValue: Identifiable { + let title: String + let id: T + var hint: String? +} + +struct SettingsPickerListView: View { + @Binding var selection: T + let values: [SettingsPickerValue] + + var body: some View { + List { + Section(content: { + ForEach(values, content: makeRow) + }, footer: { + if let hint = values.first(where: { $0.id == selection })?.hint { + Text(hint) + } + }) + } + .listStyle(.insetGrouped) + } + + private func makeRow(for value: SettingsPickerValue) -> some View { + Button(action: { + guard selection != value.id else { return } + selection = value.id + }) { + HStack { + Text(value.title) + Spacer() + if value.id == selection { + Image(systemName: "checkmark") + .font(.headline) + .foregroundColor(.accentColor) + + } + } + .contentShape(Rectangle()) + } + .buttonStyle(.plain) + } +} diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 011f609f9cfa..90c8934dbc55 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -355,6 +355,12 @@ 0C7E09212A4286A00052324C /* PostMetaButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7E091F2A4286A00052324C /* PostMetaButton.m */; }; 0C7E09242A4286F40052324C /* PostMetaButton+Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C7E09232A4286F40052324C /* PostMetaButton+Swift.swift */; }; 0C7E09252A4286F40052324C /* PostMetaButton+Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C7E09232A4286F40052324C /* PostMetaButton+Swift.swift */; }; + 0C896DDE2A3A762200D7D4E7 /* SettingsPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C896DDD2A3A762200D7D4E7 /* SettingsPicker.swift */; }; + 0C896DE02A3A763400D7D4E7 /* SettingsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C896DDF2A3A763400D7D4E7 /* SettingsCell.swift */; }; + 0C896DE22A3A767200D7D4E7 /* SiteVisibility+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C896DE12A3A767200D7D4E7 /* SiteVisibility+Extensions.swift */; }; + 0C896DE32A3A7BD700D7D4E7 /* SettingsPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C896DDD2A3A762200D7D4E7 /* SettingsPicker.swift */; }; + 0C896DE42A3A7BDC00D7D4E7 /* SettingsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C896DDF2A3A763400D7D4E7 /* SettingsCell.swift */; }; + 0C896DE52A3A7C1F00D7D4E7 /* SiteVisibility+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C896DE12A3A767200D7D4E7 /* SiteVisibility+Extensions.swift */; }; 0CB4056B29C78F06008EED0A /* BlogDashboardPersonalizationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB4056A29C78F06008EED0A /* BlogDashboardPersonalizationService.swift */; }; 0CB4056C29C78F06008EED0A /* BlogDashboardPersonalizationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB4056A29C78F06008EED0A /* BlogDashboardPersonalizationService.swift */; }; 0CB4056E29C7BA63008EED0A /* BlogDashboardPersonalizationServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB4056D29C7BA63008EED0A /* BlogDashboardPersonalizationServiceTests.swift */; }; @@ -6049,6 +6055,9 @@ 0C7E091F2A4286A00052324C /* PostMetaButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PostMetaButton.m; sourceTree = ""; }; 0C7E09222A4286AA0052324C /* PostMetaButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PostMetaButton.h; sourceTree = ""; }; 0C7E09232A4286F40052324C /* PostMetaButton+Swift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PostMetaButton+Swift.swift"; sourceTree = ""; }; + 0C896DDD2A3A762200D7D4E7 /* SettingsPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsPicker.swift; sourceTree = ""; }; + 0C896DDF2A3A763400D7D4E7 /* SettingsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsCell.swift; sourceTree = ""; }; + 0C896DE12A3A767200D7D4E7 /* SiteVisibility+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SiteVisibility+Extensions.swift"; sourceTree = ""; }; 0CB4056A29C78F06008EED0A /* BlogDashboardPersonalizationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlogDashboardPersonalizationService.swift; sourceTree = ""; }; 0CB4056D29C7BA63008EED0A /* BlogDashboardPersonalizationServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlogDashboardPersonalizationServiceTests.swift; sourceTree = ""; }; 0CB4057029C8DCF4008EED0A /* BlogDashboardPersonalizationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlogDashboardPersonalizationViewModel.swift; sourceTree = ""; }; @@ -10003,6 +10012,15 @@ path = Mocks; sourceTree = ""; }; + 0C896DDC2A3A761600D7D4E7 /* Settings */ = { + isa = PBXGroup; + children = ( + 0C896DDF2A3A763400D7D4E7 /* SettingsCell.swift */, + 0C896DDD2A3A762200D7D4E7 /* SettingsPicker.swift */, + ); + path = Settings; + sourceTree = ""; + }; 0CB4056F29C8DCD7008EED0A /* BlogPersonalization */ = { isa = PBXGroup; children = ( @@ -11216,6 +11234,7 @@ 83FEFC7411FF6C5A0078B462 /* SiteSettingsViewController.m */, 8313B9ED298B1ACD000AF26E /* SiteSettingsViewController+Blogging.swift */, 82C420751FE44BD900CFB15B /* SiteSettingsViewController+Swift.swift */, + 0C896DE12A3A767200D7D4E7 /* SiteVisibility+Extensions.swift */, 3F43603723F369A9001DEE70 /* Related Posts */, ); path = "Site Settings"; @@ -14729,6 +14748,7 @@ FA5C74091C596E69000B528C /* Site Management */, FA73D7E72798766300DF24B3 /* Site Picker */, 3F43603823F36A76001DEE70 /* Site Settings */, + 0C896DDC2A3A761600D7D4E7 /* Settings */, BE6AB7FB1BC62E0B00D980FC /* Style */, ); path = Blog; @@ -21139,6 +21159,7 @@ C533CF350E6D3ADA000C3DE8 /* CommentsViewController.m in Sources */, FAFF153D1C98962E007D1C90 /* SiteSettingsViewController+SiteManagement.swift in Sources */, D816C1EE20E0892200C4D82F /* Follow.swift in Sources */, + 0C896DE22A3A767200D7D4E7 /* SiteVisibility+Extensions.swift in Sources */, 3F3DD0B226FD176800F5F121 /* PresentationCard.swift in Sources */, 822D60B91F4CCC7A0016C46D /* BlogJetpackSettingsService.swift in Sources */, F446B843296F2DED008B94B7 /* MigrationState.swift in Sources */, @@ -21415,6 +21436,7 @@ FAB9826E2697038700B172A3 /* StatsViewController+JetpackSettings.swift in Sources */, 43D74AD020F906EE004AD934 /* InlineEditableNameValueCell.swift in Sources */, 4089C51122371B120031CE78 /* TodayStatsRecordValue+CoreDataProperties.swift in Sources */, + 0C896DDE2A3A762200D7D4E7 /* SettingsPicker.swift in Sources */, F928EDA3226140620030D451 /* WPCrashLoggingProvider.swift in Sources */, D8A3A5B3206A49BF00992576 /* StockPhotosMedia.swift in Sources */, 176BB87F20D0068500751DCE /* FancyAlertViewController+SavedPosts.swift in Sources */, @@ -22357,6 +22379,7 @@ 17CE77ED20C6C2F3001DEA5A /* ReaderSiteSearchService.swift in Sources */, 98FF6A3E23A30A250025FD72 /* QuickStartNavigationSettings.swift in Sources */, 5D42A405175E76A7005CFF05 /* WPImageViewController.m in Sources */, + 0C896DE02A3A763400D7D4E7 /* SettingsCell.swift in Sources */, E61084C01B9B47BA008050C5 /* ReaderListTopic.swift in Sources */, E6374DC11C444D8B00F24720 /* PublicizeService.swift in Sources */, 7E4A773C20F80598001C706D /* ActivityContentFactory.swift in Sources */, @@ -23949,6 +23972,7 @@ FABB21812602FC2C00C8785C /* DiffContentValue.swift in Sources */, FABB21822602FC2C00C8785C /* FormattableTextContent.swift in Sources */, 3FFDEF7A29177D8C00B625CE /* MigrationNotificationsViewController.swift in Sources */, + 0C896DE42A3A7BDC00D7D4E7 /* SettingsCell.swift in Sources */, FABB21832602FC2C00C8785C /* WordPress-61-62.xcmappingmodel in Sources */, FABB21842602FC2C00C8785C /* WhatIsNewView.swift in Sources */, FABB21852602FC2C00C8785C /* GravatarService.swift in Sources */, @@ -24487,6 +24511,7 @@ FABB23052602FC2C00C8785C /* WPAnalyticsEvent.swift in Sources */, FABB23062602FC2C00C8785C /* Coordinate.m in Sources */, F1D8C6EC26BABE3E002E3323 /* WeeklyRoundupDebugScreen.swift in Sources */, + 0C896DE52A3A7C1F00D7D4E7 /* SiteVisibility+Extensions.swift in Sources */, FABB23072602FC2C00C8785C /* SiteCreationRotatingMessageView.swift in Sources */, FABB23082602FC2C00C8785C /* SignupUsernameViewController.swift in Sources */, FABB23092602FC2C00C8785C /* MediaItemViewController.swift in Sources */, @@ -24801,6 +24826,7 @@ 80EF928B280D28140064A971 /* Atomic.swift in Sources */, 3FFDEF9129187F2100B625CE /* MigrationActionsConfiguration.swift in Sources */, FABB23FC2602FC2C00C8785C /* SitePromptView.swift in Sources */, + 0C896DE32A3A7BD700D7D4E7 /* SettingsPicker.swift in Sources */, 8B4EDADE27DF9D5E004073B6 /* Blog+MySite.swift in Sources */, FABB23FD2602FC2C00C8785C /* BaseRestoreCompleteViewController.swift in Sources */, FAA4012E27B405DB009E1137 /* DashboardQuickActionsCardCell.swift in Sources */, From dedd1eafff4744d00cc91b2755d52367fa9e30ee Mon Sep 17 00:00:00 2001 From: kean Date: Wed, 14 Jun 2023 19:21:57 -0400 Subject: [PATCH 15/23] Update SiteSettingsViewController to use new SettingsPicker --- .../Site Settings/BlogSiteVisibilityHelper.h | 3 -- .../Site Settings/BlogSiteVisibilityHelper.m | 9 ---- .../SiteSettingsViewController+Swift.swift | 35 +++++++++++++- .../SiteSettingsViewController.h | 1 - .../SiteSettingsViewController.m | 37 --------------- .../SiteVisibility+Extensions.swift | 47 +++++++++++++++++++ 6 files changed, 81 insertions(+), 51 deletions(-) create mode 100644 WordPress/Classes/ViewRelated/Blog/Site Settings/SiteVisibility+Extensions.swift diff --git a/WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.h b/WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.h index af4aa86fdce5..f1c7633bbe8e 100644 --- a/WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.h +++ b/WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.h @@ -15,7 +15,4 @@ /// @returns The associated title for the SiteVisibility value specified. + (NSString *)titleForSiteVisibility:(SiteVisibility)privacy; -/// @returns The title for the current visibility of the specified blog. -+ (NSString *)titleForCurrentSiteVisibilityOfBlog:(Blog *)blog; - @end diff --git a/WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.m b/WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.m index 0f6826939eb9..189cc770d53c 100644 --- a/WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.m +++ b/WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.m @@ -63,13 +63,4 @@ + (NSString *)hintTextForSiteVisibility:(SiteVisibility)privacy } } -+ (NSString *)titleForCurrentSiteVisibilityOfBlog:(Blog *)blog -{ - if (!blog.settings.privacy) { - return [self titleForSiteVisibility:SiteVisibilityUnknown]; - } - - return [self titleForSiteVisibility:[blog.settings.privacy intValue]]; -} - @end diff --git a/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController+Swift.swift b/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController+Swift.swift index ca4c79bba962..07616be964ef 100644 --- a/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController+Swift.swift +++ b/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController+Swift.swift @@ -1,4 +1,5 @@ import Foundation +import SwiftUI import WordPressFlux // This is just a wrapper for the receipts, since Receipt isn't exposed to Obj-C @@ -15,6 +16,32 @@ import WordPressFlux } extension SiteSettingsViewController { + // MARK: - General + + @objc func showPrivacySelector() { + struct SiteSettingsPrivacyPicker: View { + let blog: Blog + @State var selection: SiteVisibility + let onChange: (SiteVisibility) -> Void + + var body: some View { + SettingsPickerListView(selection: $selection, values: SiteVisibility.eligiblePickerValues(for: blog)) + .onChange(of: selection, perform: onChange) + } + } + let view = SiteSettingsPrivacyPicker(blog: blog, selection: blog.siteVisibility) { [weak self] in + guard let self = self, self.blog.siteVisibility != $0 else { return } + self.blog.siteVisibility = $0 + self.saveSettings() + self.trackSettingsChange(fieldName: "site_settings", value: $0.rawValue) + } + let viewController = UIHostingController(rootView: view) + viewController.title = Strings.privacyTitle + navigationController?.pushViewController(viewController, animated: true) + } + + // MARK: - Timezone + @objc func observeTimeZoneStore() { timeZoneObserver = TimeZoneObserver() { [weak self] (oldState, newState) in guard let controller = self else { @@ -279,7 +306,7 @@ extension SiteSettingsViewController { private func configureCellForPrivacy(_ cell: SettingTableViewCell) { cell.editable = blog.isAdmin cell.textLabel?.text = NSLocalizedString("Privacy", comment: "Label for the privacy setting") - cell.textValue = BlogSiteVisibilityHelper.titleForCurrentSiteVisibility(of: blog) + cell.textValue = blog.siteVisibility.localizedTitle } private func configureCellForLanguage(_ cell: SettingTableViewCell) { @@ -376,3 +403,9 @@ extension SiteSettingsViewController { } } + +private extension SiteSettingsViewController { + enum Strings { + static let privacyTitle = NSLocalizedString("siteSettings.privacy.title", value: "Privacy", comment: "Title for screen to select the privacy options for a blog") + } +} diff --git a/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController.h b/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController.h index 4014a5b9d95e..3ce5bd780fd2 100644 --- a/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController.h +++ b/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController.h @@ -29,7 +29,6 @@ typedef NS_ENUM(NSInteger, SiteSettingsSection) { // General Settings: These were made available here to help with the transition to Swift. -- (void)showPrivacySelector; - (void)showLanguageSelectorForBlog:(Blog *)blog; @end diff --git a/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController.m b/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController.m index 5d250eccd5f2..642b474cff41 100644 --- a/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController.m +++ b/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController.m @@ -763,43 +763,6 @@ -(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger) return footerView; } -- (void)showPrivacySelector -{ - NSArray *values = [BlogSiteVisibilityHelper siteVisibilityValuesForBlog:self.blog]; - NSArray *titles = [BlogSiteVisibilityHelper titlesForSiteVisibilityValues:values]; - NSArray *hints = [BlogSiteVisibilityHelper hintsForSiteVisibilityValues:values]; - - NSNumber *currentPrivacy = @(self.blog.siteVisibility); - if (!currentPrivacy) { - currentPrivacy = [values firstObject]; - } - - NSDictionary *settingsSelectionConfiguration = @{ - SettingsSelectionDefaultValueKey : [values firstObject], - SettingsSelectionTitleKey : NSLocalizedString(@"Privacy", @"Title for screen to select the privacy options for a blog"), - SettingsSelectionTitlesKey : titles, - SettingsSelectionValuesKey : values, - SettingsSelectionCurrentValueKey : currentPrivacy, - SettingsSelectionHintsKey : hints - }; - - SettingsSelectionViewController *vc = [[SettingsSelectionViewController alloc] initWithDictionary:settingsSelectionConfiguration]; - __weak __typeof__(self) weakSelf = self; - vc.onItemSelected = ^(NSNumber *status) { - // Check if the object passed is indeed an NSString, otherwise we don't want to try to set it as the post format - if ([status isKindOfClass:[NSNumber class]]) { - SiteVisibility newSiteVisibility = (SiteVisibility)[status integerValue]; - if (weakSelf.blog.siteVisibility != newSiteVisibility) { - weakSelf.blog.siteVisibility = newSiteVisibility; - [weakSelf saveSettings]; - [WPAnalytics trackSettingsChange:@"site_settings" fieldName:@"privacy" value:status]; - } - } - }; - - [self.navigationController pushViewController:vc animated:YES]; -} - - (void)showLanguageSelectorForBlog:(Blog *)blog { NSParameterAssert(blog); diff --git a/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteVisibility+Extensions.swift b/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteVisibility+Extensions.swift new file mode 100644 index 000000000000..69971a5b513c --- /dev/null +++ b/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteVisibility+Extensions.swift @@ -0,0 +1,47 @@ +import Foundation + +extension SiteVisibility { + static func eligiblePickerValues(for blog: Blog) -> [SettingsPickerValue] { + eligibleValues(for: blog).map { + SettingsPickerValue(title: $0.localizedTitle, id: $0, hint: $0.localizedHint) + } + } + + static func eligibleValues(for blog: Blog) -> [SiteVisibility] { + var values: [SiteVisibility] = [.public, .hidden] + if blog.supports(.private) { + values.append(.private) + } + return values + } + + var localizedTitle: String { + switch self { + case .private: + return NSLocalizedString("siteVisibility.private.title", value: "Private", comment: "Text for privacy settings: Private") + case .hidden: + return NSLocalizedString("siteVisibility.hidden.title", value: "Hidden", comment: "Text for privacy settings: Hidden") + case .public: + return NSLocalizedString("siteVisibility.public.title", value: "Public", comment: "Text for privacy settings: Public") + case .unknown: + return NSLocalizedString("siteVisibility.unknown.title", value: "Unknown", comment: "Text for unknown privacy setting") + @unknown default: + return NSLocalizedString("siteVisibility.unknown.title", value: "Unknown", comment: "Text for unknown privacy setting") + } + } + + var localizedHint: String { + switch self { + case .private: + return NSLocalizedString("siteVisibility.private.hint", value: "Your site is only visible to you and users you approve.", comment: "Hint for users when private privacy setting is set") + case .hidden: + return NSLocalizedString("siteVisibility.hidden.hint", value: "Your site is visible to everyone, but asks search engines not to index your site.", comment: "Hint for users when hidden privacy setting is set") + case .public: + return NSLocalizedString("siteVisibility.public.hint", value: "Your site is visible to everyone, and it may be indexed by search engines.", comment: "Hint for users when public privacy setting is set") + case .unknown: + return NSLocalizedString("siteVisibility.unknown.hint", value: "Unknown", comment: "Text for unknown privacy setting") + @unknown default: + return NSLocalizedString("siteVisibility.unknown.hint", value: "Unknown", comment: "Text for unknown privacy setting") + } + } +} From 05fc2d3ad31208494606d9b8c411f2b37b5f4145 Mon Sep 17 00:00:00 2001 From: kean Date: Wed, 14 Jun 2023 19:39:16 -0400 Subject: [PATCH 16/23] Remove BlogSiteVisibilityHelper --- .../System/WordPress-Bridging-Header.h | 1 - .../Site Settings/BlogSiteVisibilityHelper.h | 18 -- .../Site Settings/BlogSiteVisibilityHelper.m | 66 ------- .../SiteSettingsViewController.m | 1 - WordPress/WordPress.xcodeproj/project.pbxproj | 16 +- .../BlogSiteVisibilityHelperTest.m | 184 ------------------ .../WordPressTest/SiteVisibilityTests.swift | 38 ++++ 7 files changed, 42 insertions(+), 282 deletions(-) delete mode 100644 WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.h delete mode 100644 WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.m delete mode 100644 WordPress/WordPressTest/BlogSiteVisibilityHelperTest.m create mode 100644 WordPress/WordPressTest/SiteVisibilityTests.swift diff --git a/WordPress/Classes/System/WordPress-Bridging-Header.h b/WordPress/Classes/System/WordPress-Bridging-Header.h index edb53eda397d..b0002fb00310 100644 --- a/WordPress/Classes/System/WordPress-Bridging-Header.h +++ b/WordPress/Classes/System/WordPress-Bridging-Header.h @@ -14,7 +14,6 @@ #import "BlogSelectorViewController.h" #import "BlogListViewController.h" #import "BlogDetailsViewController.h" -#import "BlogSiteVisibilityHelper.h" #import "CommentService.h" #import "CommentsViewController+Network.h" diff --git a/WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.h b/WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.h deleted file mode 100644 index f1c7633bbe8e..000000000000 --- a/WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.h +++ /dev/null @@ -1,18 +0,0 @@ -#import -#import "Blog.h" - -@interface BlogSiteVisibilityHelper : NSObject - -/// @returns An array of possible SiteVisibility values for the specified blog. -+ (NSArray *)siteVisibilityValuesForBlog:(Blog *)blog; - -/// @returns The associated titles for the SiteVisibility values specified. -+ (NSArray *)titlesForSiteVisibilityValues:(NSArray *)values; - -/// @returns The associated hints for the SiteVisibility values specified. -+ (NSArray *)hintsForSiteVisibilityValues:(NSArray *)values; - -/// @returns The associated title for the SiteVisibility value specified. -+ (NSString *)titleForSiteVisibility:(SiteVisibility)privacy; - -@end diff --git a/WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.m b/WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.m deleted file mode 100644 index 189cc770d53c..000000000000 --- a/WordPress/Classes/ViewRelated/Blog/Site Settings/BlogSiteVisibilityHelper.m +++ /dev/null @@ -1,66 +0,0 @@ -#import "BlogSiteVisibilityHelper.h" -#import "WordPress-Swift.h" - -@implementation BlogSiteVisibilityHelper - -+ (NSArray *)siteVisibilityValuesForBlog:(Blog *)blog -{ - if ([blog supports:BlogFeaturePrivate]) { - return @[ @(SiteVisibilityPublic), @(SiteVisibilityHidden), @(SiteVisibilityPrivate) ]; - } else { - return @[ @(SiteVisibilityPublic), @(SiteVisibilityHidden) ]; - } -} - -+ (NSArray *)titlesForSiteVisibilityValues:(NSArray *)values -{ - NSMutableArray *titles = [NSMutableArray array]; - for (NSNumber *value in values) { - [titles addObject:[self titleForSiteVisibility:[value integerValue]]]; - } - - return titles; -} - -+ (NSArray *)hintsForSiteVisibilityValues:(NSArray *)values -{ - NSMutableArray *hints = [NSMutableArray array]; - for (NSNumber *value in values) { - [hints addObject:[self hintTextForSiteVisibility:[value integerValue]]]; - } - - return hints; -} - -+ (NSString *)titleForSiteVisibility:(SiteVisibility)privacy -{ - switch (privacy) { - case SiteVisibilityPrivate: - return NSLocalizedString(@"Private", @"Text for privacy settings: Private"); - case SiteVisibilityHidden: - return NSLocalizedString(@"Hidden", @"Text for privacy settings: Hidden"); - case SiteVisibilityPublic: - return NSLocalizedString(@"Public", @"Text for privacy settings: Public"); - case SiteVisibilityUnknown: - return NSLocalizedString(@"Unknown", @"Text for unknown privacy setting"); - } -} - -+ (NSString *)hintTextForSiteVisibility:(SiteVisibility)privacy -{ - switch (privacy) { - case SiteVisibilityPrivate: - return NSLocalizedString(@"Your site is only visible to you and users you approve.", - @"Hint for users when private privacy setting is set"); - case SiteVisibilityHidden: - return NSLocalizedString(@"Your site is visible to everyone, but asks search engines not to index your site.", - @"Hint for users when hidden privacy setting is set"); - case SiteVisibilityPublic: - return NSLocalizedString(@"Your site is visible to everyone, and it may be indexed by search engines.", - @"Hint for users when public privacy setting is set"); - case SiteVisibilityUnknown: - return NSLocalizedString(@"Unknown", @"Text for unknown privacy setting"); - } -} - -@end diff --git a/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController.m b/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController.m index 642b474cff41..c70232b92e36 100644 --- a/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController.m +++ b/WordPress/Classes/ViewRelated/Blog/Site Settings/SiteSettingsViewController.m @@ -2,7 +2,6 @@ #import "Blog.h" #import "BlogService.h" -#import "BlogSiteVisibilityHelper.h" #import "CoreDataStack.h" #import "NSURL+IDN.h" #import "PostCategory.h" diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 90c8934dbc55..2fe87e483c4b 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -361,6 +361,7 @@ 0C896DE32A3A7BD700D7D4E7 /* SettingsPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C896DDD2A3A762200D7D4E7 /* SettingsPicker.swift */; }; 0C896DE42A3A7BDC00D7D4E7 /* SettingsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C896DDF2A3A763400D7D4E7 /* SettingsCell.swift */; }; 0C896DE52A3A7C1F00D7D4E7 /* SiteVisibility+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C896DE12A3A767200D7D4E7 /* SiteVisibility+Extensions.swift */; }; + 0C896DE72A3A832B00D7D4E7 /* SiteVisibilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C896DE62A3A832B00D7D4E7 /* SiteVisibilityTests.swift */; }; 0CB4056B29C78F06008EED0A /* BlogDashboardPersonalizationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB4056A29C78F06008EED0A /* BlogDashboardPersonalizationService.swift */; }; 0CB4056C29C78F06008EED0A /* BlogDashboardPersonalizationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB4056A29C78F06008EED0A /* BlogDashboardPersonalizationService.swift */; }; 0CB4056E29C7BA63008EED0A /* BlogDashboardPersonalizationServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CB4056D29C7BA63008EED0A /* BlogDashboardPersonalizationServiceTests.swift */; }; @@ -571,7 +572,6 @@ 17ABD3522811A48900B1E9CB /* StatsMostPopularTimeInsightsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17ABD3512811A48900B1E9CB /* StatsMostPopularTimeInsightsCell.swift */; }; 17ABD3532811A48900B1E9CB /* StatsMostPopularTimeInsightsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17ABD3512811A48900B1E9CB /* StatsMostPopularTimeInsightsCell.swift */; }; 17AD36D51D36C1A60044B10D /* WPStyleGuide+Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17AD36D41D36C1A60044B10D /* WPStyleGuide+Search.swift */; }; - 17AF92251C46634000A99CFB /* BlogSiteVisibilityHelperTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 17AF92241C46634000A99CFB /* BlogSiteVisibilityHelperTest.m */; }; 17B7C89E20EC1D0D0042E260 /* UniversalLinkRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17B7C89D20EC1D0D0042E260 /* UniversalLinkRouter.swift */; }; 17B7C8A020EC1D6A0042E260 /* Route.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17B7C89F20EC1D6A0042E260 /* Route.swift */; }; 17B7C8C120EE2A870042E260 /* Routes+Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17B7C8C020EE2A870042E260 /* Routes+Notifications.swift */; }; @@ -4394,7 +4394,6 @@ FABB220F2602FC2C00C8785C /* MediaHost+AbstractPost.swift in Sources */ = {isa = PBXBuildFile; fileRef = F11C9F75243B3C5E00921DDC /* MediaHost+AbstractPost.swift */; }; FABB22102602FC2C00C8785C /* PageTemplateCategory+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46183D1E251BD6A0004F9AFD /* PageTemplateCategory+CoreDataProperties.swift */; }; FABB22112602FC2C00C8785C /* MyProfileHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1CCB2C204DDD18000EE3AC /* MyProfileHeaderView.swift */; }; - FABB22132602FC2C00C8785C /* BlogSiteVisibilityHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = FFDA7E4F1B8DF6E500B83C56 /* BlogSiteVisibilityHelper.m */; }; FABB22142602FC2C00C8785C /* TitleBadgeDisclosureCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E66E2A671FE432B900788F22 /* TitleBadgeDisclosureCell.swift */; }; FABB22152602FC2C00C8785C /* FormattableContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E4123B220F4097A00DF8486 /* FormattableContent.swift */; }; FABB22162602FC2C00C8785C /* WebAddressWizardContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D82253DD2199418B0014D0E2 /* WebAddressWizardContent.swift */; }; @@ -5632,7 +5631,6 @@ FFC6ADDA1B56F366002F3C84 /* LocalCoreDataService.m in Sources */ = {isa = PBXBuildFile; fileRef = FFC6ADD91B56F366002F3C84 /* LocalCoreDataService.m */; }; FFCB9F4B22A125BD0080A45F /* WPException.m in Sources */ = {isa = PBXBuildFile; fileRef = FFCB9F4A22A125BD0080A45F /* WPException.m */; }; FFD12D5E1FE1998D00F20A00 /* Progress+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFD12D5D1FE1998D00F20A00 /* Progress+Helpers.swift */; }; - FFDA7E501B8DF6E500B83C56 /* BlogSiteVisibilityHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = FFDA7E4F1B8DF6E500B83C56 /* BlogSiteVisibilityHelper.m */; }; FFE3B2C71B2E651400E9F1E0 /* WPAndDeviceMediaLibraryDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = FFE3B2C61B2E651400E9F1E0 /* WPAndDeviceMediaLibraryDataSource.m */; }; FFEECFFC2084DE2B009B8CDB /* PostSettingsViewController+FeaturedImageUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFEECFFB2084DE2B009B8CDB /* PostSettingsViewController+FeaturedImageUpload.swift */; }; /* End PBXBuildFile section */ @@ -6058,6 +6056,7 @@ 0C896DDD2A3A762200D7D4E7 /* SettingsPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsPicker.swift; sourceTree = ""; }; 0C896DDF2A3A763400D7D4E7 /* SettingsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsCell.swift; sourceTree = ""; }; 0C896DE12A3A767200D7D4E7 /* SiteVisibility+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SiteVisibility+Extensions.swift"; sourceTree = ""; }; + 0C896DE62A3A832B00D7D4E7 /* SiteVisibilityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteVisibilityTests.swift; sourceTree = ""; }; 0CB4056A29C78F06008EED0A /* BlogDashboardPersonalizationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlogDashboardPersonalizationService.swift; sourceTree = ""; }; 0CB4056D29C7BA63008EED0A /* BlogDashboardPersonalizationServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlogDashboardPersonalizationServiceTests.swift; sourceTree = ""; }; 0CB4057029C8DCF4008EED0A /* BlogDashboardPersonalizationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlogDashboardPersonalizationViewModel.swift; sourceTree = ""; }; @@ -6231,7 +6230,6 @@ 17A4A36B20EE55320071C2CA /* ReaderCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderCoordinator.swift; sourceTree = ""; }; 17ABD3512811A48900B1E9CB /* StatsMostPopularTimeInsightsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsMostPopularTimeInsightsCell.swift; sourceTree = ""; }; 17AD36D41D36C1A60044B10D /* WPStyleGuide+Search.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "WPStyleGuide+Search.swift"; sourceTree = ""; }; - 17AF92241C46634000A99CFB /* BlogSiteVisibilityHelperTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlogSiteVisibilityHelperTest.m; sourceTree = ""; }; 17B7C89D20EC1D0D0042E260 /* UniversalLinkRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UniversalLinkRouter.swift; sourceTree = ""; }; 17B7C89F20EC1D6A0042E260 /* Route.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Route.swift; sourceTree = ""; }; 17B7C8C020EE2A870042E260 /* Routes+Notifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Routes+Notifications.swift"; sourceTree = ""; }; @@ -9414,8 +9412,6 @@ FFCB9F4A22A125BD0080A45F /* WPException.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WPException.m; sourceTree = ""; }; FFD12D5D1FE1998D00F20A00 /* Progress+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Progress+Helpers.swift"; sourceTree = ""; }; FFD47BDE2474228C00F00660 /* FeaturedImageScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeaturedImageScreen.swift; sourceTree = ""; }; - FFDA7E4E1B8DF6E500B83C56 /* BlogSiteVisibilityHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlogSiteVisibilityHelper.h; sourceTree = ""; }; - FFDA7E4F1B8DF6E500B83C56 /* BlogSiteVisibilityHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlogSiteVisibilityHelper.m; sourceTree = ""; }; FFE3B2C51B2E651400E9F1E0 /* WPAndDeviceMediaLibraryDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WPAndDeviceMediaLibraryDataSource.h; sourceTree = ""; }; FFE3B2C61B2E651400E9F1E0 /* WPAndDeviceMediaLibraryDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPAndDeviceMediaLibraryDataSource.m; sourceTree = ""; }; FFE3B2C81B38081700E9F1E0 /* WordPress 34.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "WordPress 34.xcdatamodel"; sourceTree = ""; }; @@ -11220,8 +11216,6 @@ 3F43603823F36A76001DEE70 /* Site Settings */ = { isa = PBXGroup; children = ( - FFDA7E4E1B8DF6E500B83C56 /* BlogSiteVisibilityHelper.h */, - FFDA7E4F1B8DF6E500B83C56 /* BlogSiteVisibilityHelper.m */, 821738081FE04A9E00BEC94C /* DateAndTimeFormatSettingsViewController.swift */, B5AC00671BE3C4E100F8E7C3 /* DiscussionSettingsViewController.swift */, 17523380246C4F9200870B4A /* HomepageSettingsViewController.swift */, @@ -13386,7 +13380,6 @@ isa = PBXGroup; children = ( F4394D202A3B6F43003955C6 /* Crash Logging */, - 17AF92241C46634000A99CFB /* BlogSiteVisibilityHelperTest.m */, 93A379EB19FFBF7900415023 /* KeychainTest.m */, 5948AD101AB73D19006E8882 /* WPAppAnalyticsTests.m */, E1E4CE0C177439D100430844 /* WPAvatarSourceTest.m */, @@ -13410,6 +13403,7 @@ F565190223CF6D1D003FACAF /* WKCookieJarTests.swift */, 1ABA150722AE5F870039311A /* WordPressUIBundleTests.swift */, FE6BB1452932289B001E5F7A /* ContentMigrationCoordinatorTests.swift */, + 0C896DE62A3A832B00D7D4E7 /* SiteVisibilityTests.swift */, 93B853211B44165B0064FE72 /* Analytics */, DC06DFF727BD52A100969974 /* BackgroundTasks */, FE32E7EF284496F500744D80 /* Blogging Prompts */, @@ -21303,7 +21297,6 @@ 46183D20251BD6A0004F9AFD /* PageTemplateCategory+CoreDataProperties.swift in Sources */, CE1CCB2D204DDD18000EE3AC /* MyProfileHeaderView.swift in Sources */, C7F7BE4C2626301500CE547F /* AuthenticationHandler.swift in Sources */, - FFDA7E501B8DF6E500B83C56 /* BlogSiteVisibilityHelper.m in Sources */, E66E2A691FE432BC00788F22 /* TitleBadgeDisclosureCell.swift in Sources */, 7E4123BF20F4097B00DF8486 /* FormattableContent.swift in Sources */, D82253DF2199418B0014D0E2 /* WebAddressWizardContent.swift in Sources */, @@ -23314,7 +23307,6 @@ 7E53AB0420FE6681005796FE /* ActivityContentRouterTests.swift in Sources */, F11023A323186BCA00C4E84A /* MediaBuilder.swift in Sources */, 803BB99429667CF700B3F6D6 /* JetpackBrandingTextProviderTests.swift in Sources */, - 17AF92251C46634000A99CFB /* BlogSiteVisibilityHelperTest.m in Sources */, 73B6693A21CAD960008456C3 /* ErrorStateViewTests.swift in Sources */, 8BD34F0927D144FF005E931C /* BlogDashboardStateTests.swift in Sources */, 1759F1721FE017F20003EC81 /* QueueTests.swift in Sources */, @@ -23639,6 +23631,7 @@ F4426FD3287E08C300218003 /* SuggestionServiceMock.swift in Sources */, 436D55F02115CB6800CEAA33 /* RegisterDomainDetailsSectionTests.swift in Sources */, 4A17C1A4281A823E0001FFE5 /* NSManagedObject+Fixture.swift in Sources */, + 0C896DE72A3A832B00D7D4E7 /* SiteVisibilityTests.swift in Sources */, E1B921BC1C0ED5A3003EA3CB /* MediaSizeSliderCellTest.swift in Sources */, C314543B262770BE005B216B /* BlogServiceAuthorTests.swift in Sources */, 40F50B80221310D400CBBB73 /* FollowersStatsRecordValueTests.swift in Sources */, @@ -24171,7 +24164,6 @@ FABB220F2602FC2C00C8785C /* MediaHost+AbstractPost.swift in Sources */, FABB22102602FC2C00C8785C /* PageTemplateCategory+CoreDataProperties.swift in Sources */, FABB22112602FC2C00C8785C /* MyProfileHeaderView.swift in Sources */, - FABB22132602FC2C00C8785C /* BlogSiteVisibilityHelper.m in Sources */, FABB22142602FC2C00C8785C /* TitleBadgeDisclosureCell.swift in Sources */, FABB22152602FC2C00C8785C /* FormattableContent.swift in Sources */, 4A358DEA29B5F14C00BFCEBE /* SharingButton+Lookup.swift in Sources */, diff --git a/WordPress/WordPressTest/BlogSiteVisibilityHelperTest.m b/WordPress/WordPressTest/BlogSiteVisibilityHelperTest.m deleted file mode 100644 index f21fb0051ada..000000000000 --- a/WordPress/WordPressTest/BlogSiteVisibilityHelperTest.m +++ /dev/null @@ -1,184 +0,0 @@ - -@import XCTest; - -#import "Blog.h" -#import "BlogSiteVisibilityHelper.h" -#import "WordPressTest-Swift.h" - -@interface BlogSiteVisibilityHelperTest : XCTestCase -@end - -@interface BlogSiteVisibilityHelperTest () -@property (nonatomic, strong) id coreDataStack; -@end - -@implementation BlogSiteVisibilityHelperTest - -- (void)setUp -{ - [super setUp]; - - self.coreDataStack = [self coreDataStackForTesting]; -} - -- (void)tearDown -{ - [super tearDown]; - - self.coreDataStack = nil; -} - -- (void)testSiteVisibilityValuesForJetpackConnectedBlog -{ - Blog *blog = [self newJetpackBlog]; - - NSArray *values = [BlogSiteVisibilityHelper siteVisibilityValuesForBlog:blog]; - NSArray *expected = @[ @(SiteVisibilityPublic), @(SiteVisibilityHidden) ]; - - XCTAssertEqualObjects(values, expected); -} - -- (void)testSiteVisibilityValuesForNonJetpackConnectedBlog -{ - Blog *blog = [self newBlog]; - - NSArray *values = [BlogSiteVisibilityHelper siteVisibilityValuesForBlog:blog]; - NSArray *expected = @[ @(SiteVisibilityPublic), @(SiteVisibilityHidden), @(SiteVisibilityPrivate) ]; - - XCTAssertEqualObjects(values, expected); -} - -- (void)testSiteVisibilityTitlesForJetpackConnectedBlog -{ - Blog *blog = [self newJetpackBlog]; - - NSArray *values = [BlogSiteVisibilityHelper siteVisibilityValuesForBlog:blog]; - NSArray *titles = [BlogSiteVisibilityHelper titlesForSiteVisibilityValues:values]; - NSArray *expected = @[ NSLocalizedString(@"Public", ""), NSLocalizedString(@"Hidden", @"") ]; - - XCTAssertEqualObjects(titles, expected); -} - -- (void)testSiteVisibilityTitlesForNonJetpackConnectedBlog -{ - Blog *blog = [self newBlog]; - - NSArray *values = [BlogSiteVisibilityHelper siteVisibilityValuesForBlog:blog]; - NSArray *titles = [BlogSiteVisibilityHelper titlesForSiteVisibilityValues:values]; - NSArray *expected = @[ NSLocalizedString(@"Public", ""), NSLocalizedString(@"Hidden", @""), NSLocalizedString(@"Private", @"") ]; - - XCTAssertEqualObjects(titles, expected); -} - -- (void)testSiteVisibilityTitlesForCustomValues -{ - NSString *public = NSLocalizedString(@"Public", ""); - NSString *hidden = NSLocalizedString(@"Hidden", ""); - NSString *private = NSLocalizedString(@"Private", ""); - NSString *unknown = NSLocalizedString(@"Unknown", ""); - - NSArray *values = @[ @(SiteVisibilityPublic), - @(SiteVisibilityHidden), - @(SiteVisibilityHidden), - @(SiteVisibilityPrivate), - @(SiteVisibilityUnknown), - @(SiteVisibilityPrivate) ]; - - NSArray *titles = [BlogSiteVisibilityHelper titlesForSiteVisibilityValues:values]; - NSArray *expected = @[ public, hidden, hidden, private, unknown, private ]; - - XCTAssertEqualObjects(titles, expected); -} - -- (void)testSiteVisibilityHintsForJetpackConnectedBlog -{ - Blog *blog = [self newJetpackBlog]; - - NSArray *values = [BlogSiteVisibilityHelper siteVisibilityValuesForBlog:blog]; - NSArray *hints = [BlogSiteVisibilityHelper hintsForSiteVisibilityValues:values]; - NSArray *expected = @[ [self publicHint], [self hiddenHint] ]; - - XCTAssertEqualObjects(hints, expected); -} - -- (void)testSiteVisibilityHintsForNonJetpackConnectedBlog -{ - Blog *blog = [self newBlog]; - - NSArray *values = [BlogSiteVisibilityHelper siteVisibilityValuesForBlog:blog]; - NSArray *hints = [BlogSiteVisibilityHelper hintsForSiteVisibilityValues:values]; - NSArray *expected = @[ [self publicHint], [self hiddenHint], [self privateHint] ]; - - XCTAssertEqualObjects(hints, expected); -} - -- (void)testSiteVisibilityHintsForCustomValues -{ - NSArray *values = @[ @(SiteVisibilityHidden), - @(SiteVisibilityHidden), - @(SiteVisibilityPublic), - @(SiteVisibilityPrivate), - @(SiteVisibilityUnknown), - @(SiteVisibilityHidden), - @(SiteVisibilityPublic) ]; - - NSArray *hints = [BlogSiteVisibilityHelper hintsForSiteVisibilityValues:values]; - NSArray *expected = @[ [self hiddenHint], - [self hiddenHint], - [self publicHint], - [self privateHint], - [self unknownHint], - [self hiddenHint], - [self publicHint] ]; - - XCTAssertEqualObjects(hints, expected); -} - -#pragma mark - Helper Methods - - -- (Blog *)newBlog -{ - Blog *blog = (Blog *)[NSEntityDescription insertNewObjectForEntityForName:@"Blog" - inManagedObjectContext:self.coreDataStack.mainContext]; - - blog.settings = (BlogSettings *)[NSEntityDescription insertNewObjectForEntityForName:@"BlogSettings" - inManagedObjectContext:self.coreDataStack.mainContext]; - blog.isHostedAtWPcom = YES; - - return blog; -} - -- (Blog *)newJetpackBlog -{ - Blog *blog = [self newBlog]; - blog.isHostedAtWPcom = NO; - - // UI in the app hides visibility settings entirely for self-hosted non-Jetpack blogs - // so for the purposes of these tests we can assume that if a blog is self-hosted - // then it's also running Jetpack. - - return blog; -} - -- (NSString *)privateHint -{ - return NSLocalizedString(@"Your site is only visible to you and users you approve.", @""); -} - -- (NSString *)hiddenHint -{ - return NSLocalizedString(@"Your site is visible to everyone, but asks search engines not to index your site.", @""); -} - -- (NSString *)publicHint -{ - return NSLocalizedString(@"Your site is visible to everyone, and it may be indexed by search engines.", @""); -} - -- (NSString *)unknownHint -{ - return NSLocalizedString(@"Unknown", @""); -} - -@end diff --git a/WordPress/WordPressTest/SiteVisibilityTests.swift b/WordPress/WordPressTest/SiteVisibilityTests.swift new file mode 100644 index 000000000000..ffd707781292 --- /dev/null +++ b/WordPress/WordPressTest/SiteVisibilityTests.swift @@ -0,0 +1,38 @@ +import XCTest +import WebKit +@testable import WordPress + +class SiteVisibilityTests: CoreDataTestCase { + func testEligibleValuesForJetpackBlog() { + // Given + let blog = makeJetpackBlog() + + // Then private not eligible + XCTAssertEqual(SiteVisibility.eligibleValues(for: blog), [.public, .hidden]) + } + + func testEligibleValuesForNonJetpackConnectedBlog() { + // Given + let blog = makeBlog() + + // Then private not eligible + XCTAssertEqual(SiteVisibility.eligibleValues(for: blog), [.public, .hidden, .private]) + } + + // MARK: - Helpers + + func makeBlog() -> Blog { + let blog = Blog.createBlankBlog(in: mainContext) + blog.isHostedAtWPcom = true + return blog + } + + func makeJetpackBlog() -> Blog { + let blog = self.makeBlog() + blog.isHostedAtWPcom = false + // UI in the app hides visibility settings entirely for self-hosted non-Jetpack blogs + // so for the purposes of these tests we can assume that if a blog is self-hosted + // then it's also running Jetpack. + return blog + } +} From 9588dfb9cba4e70143ed28d242cf7393ede2ff80 Mon Sep 17 00:00:00 2001 From: kean Date: Wed, 14 Jun 2023 19:51:17 -0400 Subject: [PATCH 17/23] Simplify SettingsPicker --- .../Blog/Settings/SettingsPicker.swift | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Blog/Settings/SettingsPicker.swift b/WordPress/Classes/ViewRelated/Blog/Settings/SettingsPicker.swift index f1d119022151..ef5851417afb 100644 --- a/WordPress/Classes/ViewRelated/Blog/Settings/SettingsPicker.swift +++ b/WordPress/Classes/ViewRelated/Blog/Settings/SettingsPicker.swift @@ -5,8 +5,6 @@ struct SettingsPicker: View { @Binding var selection: T let values: [SettingsPickerValue] - private var isEditable = true - init(title: String, selection: Binding, values: [SettingsPickerValue]) { self.title = title self._selection = selection @@ -14,25 +12,13 @@ struct SettingsPicker: View { } var body: some View { - let value = values.first { $0.id == selection } - let cell = SettingsCell(title: title, value: value?.title) - if isEditable { - NavigationLink(destination: { - SettingsPickerListView(selection: $selection, values: values) - .navigationTitle(title) - }, label: { - cell - }) - } else { - cell - } - } - - /// Disables editing if set to `false`. By default, the picker is editable. - func editable(_ isEditable: Bool) -> Self { - var copy = self - copy.isEditable = isEditable - return copy + NavigationLink(destination: { + SettingsPickerListView(selection: $selection, values: values) + .navigationTitle(title) + }, label: { + let value = values.first { $0.id == selection } + SettingsCell(title: title, value: value?.title) + }) } } From a0482efa00e08f5a529e9832505925fa2eff0ae8 Mon Sep 17 00:00:00 2001 From: Alex Grebenyuk Date: Wed, 21 Jun 2023 11:49:14 -0400 Subject: [PATCH 18/23] Update WordPress/WordPressTest/SiteVisibilityTests.swift Co-authored-by: Momo Ozawa --- WordPress/WordPressTest/SiteVisibilityTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/WordPressTest/SiteVisibilityTests.swift b/WordPress/WordPressTest/SiteVisibilityTests.swift index ffd707781292..36c40c6ab1b1 100644 --- a/WordPress/WordPressTest/SiteVisibilityTests.swift +++ b/WordPress/WordPressTest/SiteVisibilityTests.swift @@ -15,7 +15,7 @@ class SiteVisibilityTests: CoreDataTestCase { // Given let blog = makeBlog() - // Then private not eligible + // Then private is eligible XCTAssertEqual(SiteVisibility.eligibleValues(for: blog), [.public, .hidden, .private]) } From 35e15150e9b29e0f04c65ab33339e343d66567ec Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Thu, 22 Jun 2023 09:39:34 +1000 Subject: [PATCH 19/23] =?UTF-8?q?Update=20app=20translations=20=E2=80=93?= =?UTF-8?q?=20`Localizable.strings`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Resources/it.lproj/Localizable.strings | 87 ++++++++++++++++++- .../Resources/pl.lproj/Localizable.strings | 5 +- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/WordPress/Resources/it.lproj/Localizable.strings b/WordPress/Resources/it.lproj/Localizable.strings index 9533d32a7640..a9f9bae20871 100644 --- a/WordPress/Resources/it.lproj/Localizable.strings +++ b/WordPress/Resources/it.lproj/Localizable.strings @@ -1,4 +1,4 @@ -/* Translation-Revision-Date: 2023-06-01 11:54:09+0000 */ +/* Translation-Revision-Date: 2023-06-20 19:19:56+0000 */ /* Plural-Forms: nplurals=2; plural=n != 1; */ /* Generator: GlotPress/4.0.0-alpha.4 */ /* Language: it */ @@ -4920,6 +4920,9 @@ translators: %s: Select control button label e.g. \"Button width\" */ /* Accessibility label for no currently selected range. */ "No date range selected" = "Nessun intervallo di date selezionato"; +/* No comment provided by engineer. */ +"No description" = "Nessuna descrizione"; + /* Title for the view when there aren't any fixed threats to display */ "No fixed threats" = "Nessuna minaccia risolta"; @@ -5046,6 +5049,9 @@ translators: %s: Select control button label e.g. \"Button width\" */ /* Message for a notice informing the user their scan completed and no threats were found */ "No threats found" = "Nessuna minaccia rilevata"; +/* No comment provided by engineer. */ +"No title" = "Nessun titolo"; + /* Disabled No alignment for an image (default). Should be the same as in core WP. No comment will be autoapproved @@ -6145,7 +6151,7 @@ translators: %s: Select control button label e.g. \"Button width\" */ "Remove Site Icon" = "Rimuovi l'icona del sito"; /* No comment provided by engineer. */ -"Remove as Featured Image" = "Rimuovi da immagine in evidenza "; +"Remove as Featured Image" = "Rimuovi da immagine in evidenza"; /* No comment provided by engineer. */ "Remove block" = "Rimuovi il blocco"; @@ -7582,7 +7588,7 @@ translators: %s: Select control option value e.g: \"Auto, 25%\". */ "The best way to become a better writer is to build a writing habit and share with others - that’s where Prompts come in!" = "Il modo migliore per diventare uno scrittore o una scrittrice migliore è abituarsi a scrivere e condividere questa abitudine con gli altri. È qui che entrano in gioco le Richieste."; /* No comment provided by engineer. */ -"The certificate for this server is invalid. You might be connecting to a server that is pretending to be “%@” which could put your confidential information at risk.\n\nWould you like to trust the certificate anyway?" = "Il certificato per questo server non è valido. Continuando, corri il rischio di connetterti ad un server che finge di essere “%@”, il che potrebbe compromettere la sicurezza di informazioni riservate che ti appartengono.\n\nVuoi accettare comunque il certificato?"; +"The certificate for this server is invalid. You might be connecting to a server that is pretending to be “%@” which could put your confidential information at risk.\n\nWould you like to trust the certificate anyway?" = "Il certificato per questo server non è valido. Continuando, corri il rischio di connetterti ad un server che finge di essere “%@”, il che potrebbe compromettere la sicurezza di informazioni riservate che ti appartengono.\n\nVuoi accettare comunque il certificato?"; /* Message informing the user that posts page cannot be edited */ "The content of your latest posts page is automatically generated and cannot be edited." = "Il contenuto della pagina degli articoli recenti viene generato automaticamente e non può essere modificato."; @@ -9679,6 +9685,21 @@ translators: %s: Select control option value e.g: \"Auto, 25%\". */ /* User action to dismiss media options. */ "aztecPost.mediaAttachmentActionSheet.dismiss" = "Ignora"; +/* Text displayed when there are no Blaze campaigns to display. */ +"blaze.campaigns.empty.subtitle" = "Non hai ancora creato alcuna campagna. Fai clic su Promuovi per iniziare a lavorare."; + +/* Title displayed when there are no Blaze campaigns to display. */ +"blaze.campaigns.empty.title" = "Non hai campagne"; + +/* Displayed while Blaze campaigns are being loaded. */ +"blaze.campaigns.loading.title" = "Caricamento delle campagne in corso..."; + +/* Button title for the button that shows the Blaze flow when tapped. */ +"blaze.campaigns.promote.button.title" = "Promuovi"; + +/* Title for the screen that allows users to manage their Blaze campaigns. */ +"blaze.campaigns.title" = "Campagne di Blaze"; + /* Description for the Blaze dashboard card. */ "blaze.dashboard.card.description" = "Mostra il tuo lavoro su milioni di siti."; @@ -9709,6 +9730,15 @@ translators: %s: Select control option value e.g: \"Auto, 25%\". */ /* Button title for the Blaze overlay prompting users to blaze the selected post. */ "blaze.overlay.withPost.buttonTitle" = "Diffondi questo articolo"; +/* Short status description */ +"blazeCampaign.status.active" = "Attiva"; + +/* Short status description */ +"blazeCampaign.status.finished" = "Pianificato"; + +/* Short status description */ +"blazeCampaign.status.rejected" = "Rifiutato"; + /* Title for the context menu action that hides the dashboard card. */ "blogDashboard.contextMenu.hideThis" = "Nascondi"; @@ -9766,6 +9796,21 @@ translators: %s: Select control option value e.g: \"Auto, 25%\". */ /* Title for the Pages dashboard card. */ "dashboardCard.Pages.title" = "Pagine"; +/* Title for impressions stats view */ +"dashboardCard.blazeCampaigns.clicks" = "Clic"; + +/* Title of a button that starts the campaign creation flow. */ +"dashboardCard.blazeCampaigns.createCampaignButton" = "Crea la campagna"; + +/* Title for impressions stats view */ +"dashboardCard.blazeCampaigns.impressions" = "Impressioni"; + +/* Title for the card displaying blaze campaigns. */ +"dashboardCard.blazeCampaigns.title" = "Campagna di Blaze"; + +/* Title for the View All Campaigns button in the More menu */ +"dashboardCard.blazeCampaigns.viewAllCampaigns" = "Visualizza tutte le campagne"; + /* Title of a button that starts the page creation flow. */ "dashboardCard.pages.add.button.title" = "Aggiungi pagine al sito"; @@ -9841,6 +9886,12 @@ translators: %s: Select control option value e.g: \"Auto, 25%\". */ /* The text to display for paid domains in 'Site Creation > Choose a domain' screen */ "domain.suggestions.row.yearly" = "all'anno"; +/* Action shown in a bottom notice to dismiss it. */ +"domains.failure.dismiss" = "Ignora"; + +/* Content show when the domain selection action fails. */ +"domains.failure.title" = "Siamo spiacenti, il dominio che stai cercando di aggiungere non può essere acquistato sull'app di Jetpack in questo momento."; + /* No comment provided by engineer. */ "double-tap to change unit" = "tocca due volte per modificare l'unità"; @@ -9873,6 +9924,18 @@ translators: %s: Select control option value e.g: \"Auto, 25%\". */ /* Title for the Free to Paid plans dashboard card. */ "freeToPaidPlans.dashboard.card.shortTitle" = "Dominio gratuito con un piano annuale"; +/* Done button title on the domain purchase result screen. Closes the screen. */ +"freeToPaidPlans.resultView.done" = "Fatto"; + +/* Notice on the domain purchase result screen. Tells user how long it might take for their domain to be ready. */ +"freeToPaidPlans.resultView.notice" = "Potrebbero essere necessari fino a 30 minuti prima che il dominio inizi a funzionare correttamente"; + +/* Sub-title for the domain purchase result screen. Tells user their domain is being set up. */ +"freeToPaidPlans.resultView.subtitle" = "Il tuo nuovo dominio %@ è in fase di impostazione."; + +/* Title for the domain purchase result screen. Tells user their domain was obtained. */ +"freeToPaidPlans.resultView.title" = "Tutto pronto."; + /* Title for button that will open up the blogging reminders screen. */ "growAudienceCell.bloggingReminders.actionButton" = "Imposta promemoria relativi al blog"; @@ -10425,6 +10488,12 @@ translators: %s: Select control option value e.g: \"Auto, 25%\". */ /* Card title for the pesonalization menu */ "personalizeHome.dashboardCard.draftPosts" = "Articoli bozza"; +/* Card title for the pesonalization menu */ +"personalizeHome.dashboardCard.getToKnowTheApp" = "Conosci l'app"; + +/* Card title for the pesonalization menu */ +"personalizeHome.dashboardCard.nextSteps" = "Passi successivi"; + /* Card title for the pesonalization menu */ "personalizeHome.dashboardCard.pages" = "Pagine"; @@ -10570,6 +10639,18 @@ Example: given a notice format "Following %@" and empty site name, this will be /* Label for the blogging reminders setting */ "sitesettings.reminders.title" = "Promemoria"; +/* Body text for the Jetpack Social no connection view */ +"social.noconnection.body" = "Aumenta il traffico condividendo automaticamente gli articoli con amici sui social media."; + +/* Title for the connect button to add social sharing for the Jetpack Social no connection view */ +"social.noconnection.connect" = "Connetti i tuoi profili"; + +/* Accessibility label for the social media icons in the Jetpack Social no connection view */ +"social.noconnection.icons.accessibility.label" = "Icone dei social media"; + +/* Title for the not now button to hide the Jetpack Social no connection view */ +"social.noconnection.notnow" = "Non ora"; + /* Section title for the disabled Twitter service in the Social screen */ "social.section.disabledTwitter.header" = "La condivisione automatica di Twitter non è più disponibile"; diff --git a/WordPress/Resources/pl.lproj/Localizable.strings b/WordPress/Resources/pl.lproj/Localizable.strings index c06d0dd23f9e..3fa85c7c6588 100644 --- a/WordPress/Resources/pl.lproj/Localizable.strings +++ b/WordPress/Resources/pl.lproj/Localizable.strings @@ -1,4 +1,4 @@ -/* Translation-Revision-Date: 2023-02-13 11:57:04+0000 */ +/* Translation-Revision-Date: 2023-06-21 05:46:57+0000 */ /* Plural-Forms: nplurals=3; plural=(n == 1) ? 0 : ((n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) ? 1 : 2); */ /* Generator: GlotPress/4.0.0-alpha.4 */ /* Language: pl */ @@ -2918,6 +2918,9 @@ translators: %s: Select control option value e.g: \"Auto, 25%\". */ /* Title of a button style */ "Text Only" = "Tylko tekst"; +/* No comment provided by engineer. */ +"Text color" = "Kolor tekstu"; + /* No comment provided by engineer. */ "That email address has already been used. Please check your inbox for an activation email. If you don't activate you can try again in a few days." = "Podany adres e-mail został już użyty. Proszę sprawdzić czy dostarczona została wiadomość z możliwością potwierdzenia. Ponowne użycie tego adresu będzie możliwe za kilka dni."; From d71bbeb6115fc5d4a90706f7202a651af5b0461b Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Thu, 22 Jun 2023 09:39:58 +1000 Subject: [PATCH 20/23] Update WordPress metadata translations --- fastlane/metadata/ar-SA/release_notes.txt | 5 +++++ fastlane/metadata/de-DE/release_notes.txt | 5 +++++ fastlane/metadata/es-ES/release_notes.txt | 5 +++++ fastlane/metadata/fr-FR/release_notes.txt | 5 +++++ fastlane/metadata/he/release_notes.txt | 5 +++++ fastlane/metadata/id/release_notes.txt | 5 +++++ fastlane/metadata/nl-NL/release_notes.txt | 5 +++++ fastlane/metadata/ru/release_notes.txt | 5 +++++ fastlane/metadata/sv/release_notes.txt | 5 +++++ fastlane/metadata/zh-Hans/release_notes.txt | 5 +++++ fastlane/metadata/zh-Hant/release_notes.txt | 5 +++++ 11 files changed, 55 insertions(+) create mode 100644 fastlane/metadata/ar-SA/release_notes.txt create mode 100644 fastlane/metadata/de-DE/release_notes.txt create mode 100644 fastlane/metadata/es-ES/release_notes.txt create mode 100644 fastlane/metadata/fr-FR/release_notes.txt create mode 100644 fastlane/metadata/he/release_notes.txt create mode 100644 fastlane/metadata/id/release_notes.txt create mode 100644 fastlane/metadata/nl-NL/release_notes.txt create mode 100644 fastlane/metadata/ru/release_notes.txt create mode 100644 fastlane/metadata/sv/release_notes.txt create mode 100644 fastlane/metadata/zh-Hans/release_notes.txt create mode 100644 fastlane/metadata/zh-Hant/release_notes.txt diff --git a/fastlane/metadata/ar-SA/release_notes.txt b/fastlane/metadata/ar-SA/release_notes.txt new file mode 100644 index 000000000000..d34a55254f7c --- /dev/null +++ b/fastlane/metadata/ar-SA/release_notes.txt @@ -0,0 +1,5 @@ +لقد أزلنا خطأ في الأجهزة التي تعمل بنظام التشغيل iOS 16 أو إصدار أعلى، حيث أدت الكتابة في محرّر المكوّنات في أثناء الإملاء إلى فقدان النص الذي تم إملاؤه. يا للروعة. + +مقفلة ومحمّلة - هناك الآن أيقونة قفل تناسب الخلايا المعطَّلة في المحرّر حتى تعرف متى لا تكون قيد الاستخدام. + +أخيرًا، قمنا بتحديث نص العنصر النائب لفيديوهات فيديوبرس التي لا تنتمي إلى موقعك. (نأمل ألا تشعر أنها مهملة). diff --git a/fastlane/metadata/de-DE/release_notes.txt b/fastlane/metadata/de-DE/release_notes.txt new file mode 100644 index 000000000000..520e4a8c1b79 --- /dev/null +++ b/fastlane/metadata/de-DE/release_notes.txt @@ -0,0 +1,5 @@ +Wir haben einen Fehler bei Geräten mit iOS 16 oder neuer behoben, aufgrund dessen diktierter Text im Block-Editor beim Schreiben und gleichzeitigem Diktieren verloren gegangen ist. Was ein Glück. + +Gesperrt und geladen – es gibt ab sofort ein neues Icon für deaktivierte Zellen im Block-Editor, damit du weißt, wann sie nicht verwendet werden. + +Und schließlich haben wir den Platzhaltertext für VideoPress-Videos, die nicht zu deiner Website gehören, aktualisiert. (Hoffentlich fühlen sie sich dadurch nicht ausgeschlossen.) diff --git a/fastlane/metadata/es-ES/release_notes.txt b/fastlane/metadata/es-ES/release_notes.txt new file mode 100644 index 000000000000..b69e5a735b2a --- /dev/null +++ b/fastlane/metadata/es-ES/release_notes.txt @@ -0,0 +1,5 @@ +Hemos eliminado un error en dispositivos con iOS 16 o posterior, por el que al escribir en el editor de bloques mientras se dictaba se perdía el texto dictado. Uf. + +Bloqueado y cargado: ahora hay un icono de bloqueo para las celdas desactivadas en el editor de bloques, para que sepas cuándo no están en uso. + +Por último, hemos actualizado el texto del marcador de posición para los vídeos de VideoPress que no pertenecen a tu sitio. (Esperamos que no se sientan excluidos). diff --git a/fastlane/metadata/fr-FR/release_notes.txt b/fastlane/metadata/fr-FR/release_notes.txt new file mode 100644 index 000000000000..ecc31b6c5caa --- /dev/null +++ b/fastlane/metadata/fr-FR/release_notes.txt @@ -0,0 +1,5 @@ +Nous avons résolu un bogue sur les appareils utilisant iOS 16 ou une version ultérieure, où la saisie de texte dans l’éditeur de blocs pendant la dictée entraînait la perte du texte dicté. Ouf ! + +Cellules verrouillées : l’éditeur de blocs affiche à présent une icône de cadenas pour les cellules désactivées, ce qui vous permet de savoir quand elles ne sont pas utilisées. + +Enfin, nous avons mis à jour le texte indicatif pour les vidéos VideoPress qui n’appartiennent pas à votre site. (Pourvu qu’elles ne se sentent pas exclues.) diff --git a/fastlane/metadata/he/release_notes.txt b/fastlane/metadata/he/release_notes.txt new file mode 100644 index 000000000000..21aa867a60d7 --- /dev/null +++ b/fastlane/metadata/he/release_notes.txt @@ -0,0 +1,5 @@ +הסרנו באג במכשירים עם מערכת ההפעלה iOS 16 ומעלה, שהתרחש במהלך הקלדה בעורך הבלוקים בזמן הכתבה של טקסט במקביל וגרם למחיקת הטקסט המוכתב. אפשר להמשיך בשלווה. + +סגור ומסוגר – הוספנו גם סמל של מנעול בתאים מושבתים בעורך הבלוקים, כדי להציג בבירור שהם אינם בשימוש. + +אחרון חביב, עדכנו את הטקסט של מציין המיקום בסרטונים של VideoPress שאינם שייכים לאתר שלך. (אנחנו מקווים שהם לא ייעלבו.) diff --git a/fastlane/metadata/id/release_notes.txt b/fastlane/metadata/id/release_notes.txt new file mode 100644 index 000000000000..35783d719657 --- /dev/null +++ b/fastlane/metadata/id/release_notes.txt @@ -0,0 +1,5 @@ +Kami sudah mengatasi bug di perangkat yang menjalankan iOS 16 atau yang lebih baru yang menyebabkan teks hasil dikte hilang saat mengetik di editor blok jika fungsi dikte sedang aktif. Fiuh, leganya! + +Tak perlu lagi menduga-duga: di editor blok, kini terdapat ikon gembok untuk sel nonaktif sehingga sel yang sedang tidak digunakan bisa diketahui. + +Terakhir, teks placeholder untuk video VideoPress yang bukan milik situs Anda juga sudah kami perbarui. (Semoga tidak ada yang merasa kehilangan, ya.) diff --git a/fastlane/metadata/nl-NL/release_notes.txt b/fastlane/metadata/nl-NL/release_notes.txt new file mode 100644 index 000000000000..efa6d40d916f --- /dev/null +++ b/fastlane/metadata/nl-NL/release_notes.txt @@ -0,0 +1,5 @@ +We hebben een bug verwijderd in apparaten met iOS 16 of later, waarbij typen in de blokeditor terwijl tegelijkertijd werd gedicteerd ervoor zorgde dat de gedicteerde tekst verloren ging. Gelukkig! + +Vergrendeld en geladen. Er is nu een slotpictogram voor uitgeschakelde cellen in de blok editor zodat je weet wanneer deze niet worden gebruikt. + +Ten slotte hebben we de vervangende tekst bijgewerkt voor VideoPress-video's die niet bij je site horen. (Hopelijk voelen ze zich niet buitengesloten.) diff --git a/fastlane/metadata/ru/release_notes.txt b/fastlane/metadata/ru/release_notes.txt new file mode 100644 index 000000000000..7faa0a36542f --- /dev/null +++ b/fastlane/metadata/ru/release_notes.txt @@ -0,0 +1,5 @@ +Мы устранили ошибку на устройствах под управлением iOS 16 и более поздних версий, из-за которой ввод текста в редакторе блоков во время диктовки приводил к потере продиктованного текста. Вот так вот. + +Заблокировано и загружено — теперь в редакторе блоков есть значок замка для отключенных ячеек, чтобы знать, когда они не используются. + +Наконец, мы обновили текст заполнителя для видеороликов в VideoPress, не относящихся к вашему сайту. (Надеемся, они не почувствуют себя отверженными.) diff --git a/fastlane/metadata/sv/release_notes.txt b/fastlane/metadata/sv/release_notes.txt new file mode 100644 index 000000000000..bc85892fca32 --- /dev/null +++ b/fastlane/metadata/sv/release_notes.txt @@ -0,0 +1,5 @@ +Vi har tagit bort en bugg för enheter som kör iOS 16 eller senare, som gjorde att den dikterade texten försvann om man skrev i blockredigeraren under diktering. Skönt. + +Klappat och klart – det finns nu en låsikon för inaktiverade celler i blockredigeraren så att du vet när de inte används. + +Slutligen har vi uppdaterat platshållartexten för VideoPress-videoklipp som inte tillhör din webbplats. (Förhoppningsvis kommer de inte att känna sig utanför.) diff --git a/fastlane/metadata/zh-Hans/release_notes.txt b/fastlane/metadata/zh-Hans/release_notes.txt new file mode 100644 index 000000000000..d33291c75904 --- /dev/null +++ b/fastlane/metadata/zh-Hans/release_notes.txt @@ -0,0 +1,5 @@ +我们删除了运行 iOS 16 或更高版本的设备中的一个错误,即听写时在区块编辑器中键入内容会导致听写文本丢失。 真是太好了。 + +已锁定并加载—在区块编辑器中,禁用的单元格现在有一个锁形图标,这样您就知道这些单元格何时不能使用。 + +最后,我们更新了不属于您站点的 VideoPress 视频的占位符文本。 (希望它们不会感到被忽视。) diff --git a/fastlane/metadata/zh-Hant/release_notes.txt b/fastlane/metadata/zh-Hant/release_notes.txt new file mode 100644 index 000000000000..3359e3e032d5 --- /dev/null +++ b/fastlane/metadata/zh-Hant/release_notes.txt @@ -0,0 +1,5 @@ +啟用聽寫功能期間在區塊編輯器中輸入內容,會導致聽寫的文字遺失,我們已針對執行 iOS 16 以上版本的裝置移除這項錯誤。 終於搞定。 + +萬事準備就緒 — 編輯器中已停用的儲存格現在會顯示鎖定圖示,方便你判斷哪些儲存格無法使用。 + +最後,我們針對不屬於你網站的 VideoPress 影片更新了預留位置文字 (這樣應該就不會感覺格格不入)。 From c6c8253676c472d5a9d97b1fc5edc19f04749ab3 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Thu, 22 Jun 2023 09:40:05 +1000 Subject: [PATCH 21/23] Update Jetpack metadata translations --- fastlane/jetpack_metadata/ar-SA/release_notes.txt | 9 +++++++++ fastlane/jetpack_metadata/de-DE/release_notes.txt | 9 +++++++++ fastlane/jetpack_metadata/es-ES/release_notes.txt | 9 +++++++++ fastlane/jetpack_metadata/fr-FR/release_notes.txt | 9 +++++++++ fastlane/jetpack_metadata/he/release_notes.txt | 9 +++++++++ fastlane/jetpack_metadata/id/release_notes.txt | 9 +++++++++ fastlane/jetpack_metadata/ko/release_notes.txt | 9 +++++++++ fastlane/jetpack_metadata/nl-NL/release_notes.txt | 9 +++++++++ fastlane/jetpack_metadata/pt-BR/release_notes.txt | 9 +++++++++ fastlane/jetpack_metadata/ru/release_notes.txt | 9 +++++++++ fastlane/jetpack_metadata/tr/release_notes.txt | 9 +++++++++ fastlane/jetpack_metadata/zh-Hans/release_notes.txt | 9 +++++++++ fastlane/jetpack_metadata/zh-Hant/release_notes.txt | 9 +++++++++ 13 files changed, 117 insertions(+) create mode 100644 fastlane/jetpack_metadata/ar-SA/release_notes.txt create mode 100644 fastlane/jetpack_metadata/de-DE/release_notes.txt create mode 100644 fastlane/jetpack_metadata/es-ES/release_notes.txt create mode 100644 fastlane/jetpack_metadata/fr-FR/release_notes.txt create mode 100644 fastlane/jetpack_metadata/he/release_notes.txt create mode 100644 fastlane/jetpack_metadata/id/release_notes.txt create mode 100644 fastlane/jetpack_metadata/ko/release_notes.txt create mode 100644 fastlane/jetpack_metadata/nl-NL/release_notes.txt create mode 100644 fastlane/jetpack_metadata/pt-BR/release_notes.txt create mode 100644 fastlane/jetpack_metadata/ru/release_notes.txt create mode 100644 fastlane/jetpack_metadata/tr/release_notes.txt create mode 100644 fastlane/jetpack_metadata/zh-Hans/release_notes.txt create mode 100644 fastlane/jetpack_metadata/zh-Hant/release_notes.txt diff --git a/fastlane/jetpack_metadata/ar-SA/release_notes.txt b/fastlane/jetpack_metadata/ar-SA/release_notes.txt new file mode 100644 index 000000000000..5d024b873975 --- /dev/null +++ b/fastlane/jetpack_metadata/ar-SA/release_notes.txt @@ -0,0 +1,9 @@ +تأتي خطط ووردبريس.كوم مع تطبيق Jetpack. احصل على الخطة المناسبة لاحتياجات النشر الخاصة بك وقم بإدارتها في المكان نفسه الذي تكتب فيه أفضل الكلمات لديك. + +هناك زر "علامة تبويب تخصيص الصفحة الرئيسية" الجديد الواضح الموجود في الجزء السفلي من لوحة معلومات موقعك حيث يمكنك تخصيص بطاقات لوحة المعلومات المرئية لديك. (هل تريد إخفاء البطاقات التي لا تحتاج إليها؟ ما عليك سوى استخدام قائمة "مزيد"). + +لقد أزلنا خطأ في الأجهزة التي تعمل بنظام التشغيل iOS 16 أو إصدار أعلى، حيث أدت الكتابة في محرّر المكوّنات في أثناء الإملاء إلى فقدان النص الذي تم إملاؤه. هناك أيضًا أيقونة قفل تناسب الخلايا المعطَّلة في المحرّر حتى تعرف متى لا تكون قيد الاستخدام. + +في شاشة "البحث عن النطاقات"، سترى الآن رسالة خطأ في حال اختيار نطاق افتراضي لا يدعمه موقعك. لا مزيد من عجلة التقدّم التي تدور إلى الأبد. + +أخيرًا، قمنا بتحديث نص العنصر النائب لفيديوهات فيديوبرس التي لا تنتمي إلى موقعك. (نأمل ألا تشعر أنها مهملة). diff --git a/fastlane/jetpack_metadata/de-DE/release_notes.txt b/fastlane/jetpack_metadata/de-DE/release_notes.txt new file mode 100644 index 000000000000..e579e0d3e504 --- /dev/null +++ b/fastlane/jetpack_metadata/de-DE/release_notes.txt @@ -0,0 +1,9 @@ +Die WordPress.com-Tarife gibt es jetzt auch in der Jetpack-App. Hol dir den passenden Tarif für deine Blog-Aktivitäten und verwalte ihn dort, wo du auch deine Inhalte erstellst. + +Am Ende deines Website-Dashboards gibt es den brandneuen Button „Startseiten-Tab personalisieren“, mit dem du deine angezeigten Dashboard-Karten anpassen kannst. (Möchtest du die Karten, die du nicht brauchst, ausblenden? Verwende einfach das Menü „Mehr“.) + +Wir haben einen Fehler bei Geräten mit iOS 16 oder neuer behoben, aufgrund dessen diktierter Text im Block-Editor beim Schreiben und gleichzeitigem Diktieren verloren gegangen ist. Zudem gibt es im Editor ein Icon für deaktivierte Zellen, damit du weißt, wann sie nicht verwendet werden. + +Auf dem Bildschirm „Nach verfügbaren Domains suchen“ wird dir jetzt eine Fehlermeldung angezeigt, wenn du eine Standard-Domain auswählst, die von deiner Website nicht unterstützt wird. Es wird kein sich fortwährend drehendes Fortschrittsrad mehr angezeigt. + +Und schließlich haben wir den Platzhaltertext für VideoPress-Videos, die nicht zu deiner Website gehören, aktualisiert. (Hoffentlich fühlen sie sich dadurch nicht ausgeschlossen.) diff --git a/fastlane/jetpack_metadata/es-ES/release_notes.txt b/fastlane/jetpack_metadata/es-ES/release_notes.txt new file mode 100644 index 000000000000..6e2b24820dd8 --- /dev/null +++ b/fastlane/jetpack_metadata/es-ES/release_notes.txt @@ -0,0 +1,9 @@ +Los planes de WordPress.com llegan a la aplicación de Jetpack. Consigue el plan que se ajuste a tus necesidades de publicación y gestiónalo desde el mismo sitio donde escribes tus mejores textos. + +En la parte inferior del escritorio del sitio, verás el botón "Personalizar la pestaña Inicio", con el que podrás personalizar las tarjetas visibles del escritorio. (¿Quieres ocultar las tarjetas que no necesites? Solo tienes que usar el menú "Más"). + +Hemos corregido un error en los dispositivos con iOS 16 o versiones posteriores que provocaba que, al escribir en el editor de bloques mientras se dictaba, se perdiera el texto dictado. Además, en el editor también aparece el icono de un candado para las celdas deshabilitadas, así sabrás cuándo no están en uso. + +En la pantalla "Buscar dominios", ahora aparecerá un mensaje de error si eliges un dominio por defecto que no sea compatible con tu sitio. Se acabó eso de ver una rueda de progreso que gira eternamente. + +Para terminar, hemos actualizado el texto del marcador de posición para los videos de VideoPress que no pertenezcan a tu sitio. (Esperamos que no se sientan marginados). diff --git a/fastlane/jetpack_metadata/fr-FR/release_notes.txt b/fastlane/jetpack_metadata/fr-FR/release_notes.txt new file mode 100644 index 000000000000..0cb6b906d44d --- /dev/null +++ b/fastlane/jetpack_metadata/fr-FR/release_notes.txt @@ -0,0 +1,9 @@ +Les plans WordPress.com sont à présent disponibles dans l’application Jetpack. Choisissez celui qui correspond à vos besoins de publication et gérez-le depuis l’espace de rédaction de votre blog. + +Un tout nouveau bouton « Personnaliser l’onglet d’accueil », situé en bas du tableau de bord de votre site, vous permet de personnaliser les cartes à afficher sur votre tableau de bord. (Vous souhaitez masquer les cartes dont vous n’avez pas besoin ? Utilisez simplement le menu « Plus ».) + +Nous avons résolu un bogue sur les appareils utilisant iOS 16 ou une version ultérieure, où la saisie de texte dans l’éditeur de blocs pendant la dictée entraînait la perte du texte dicté. Aussi, l’éditeur affiche à présent une icône de cadenas pour les cellules désactivées, ce qui vous permet de savoir quand elles ne sont pas utilisées. + +L’écran « Rechercher des domaines » affiche désormais un message d’erreur lorsque vous choisissez un domaine par défaut qui n’est pas pris en charge par votre site. Vous ne verrez plus la roue de progression tourner indéfiniment. + +Enfin, nous avons mis à jour le texte indicatif pour les vidéos VideoPress qui n’appartiennent pas à votre site. (Pourvu qu’elles ne se sentent pas exclues.) diff --git a/fastlane/jetpack_metadata/he/release_notes.txt b/fastlane/jetpack_metadata/he/release_notes.txt new file mode 100644 index 000000000000..d870f7787b78 --- /dev/null +++ b/fastlane/jetpack_metadata/he/release_notes.txt @@ -0,0 +1,9 @@ +התוכניות של WordPress.com מגיעות לאפליקציה של Jetpack. באפשרותך לבחור את התוכנית המתאימה לצורכי הפרסום שלך ולנהל אותה באותו המקום שממנו התוכן הנהדר שלך נערך. + +יש כפתור חדש ונוצץ עם הכיתוב 'התאמה אישית של לשונית הבית' בתחתית לוח הבקרה של האתר שלך, שם אפשר להתאים אישית את הכרטיסים שמוצגים בלוח הבקרה. (רוצה להסתיר את הכרטיסים שאין לך צורך בהם? אפשר להשתמש בתפריט 'עוד'.) + +הסרנו באג במכשירים עם מערכת ההפעלה iOS 16 ומעלה, שהתרחש במהלך הקלדה בעורך הבלוקים בזמן הכתבה של טקסט במקביל וגרם למחיקת הטקסט המוכתב. הוספנו גם סמל של מנעול בתאים מושבתים בעורך, כדי להציג בבירור שהם אינם בשימוש. + +במסך 'לחפש דומיינים', תופיע כעת הודעת שגיאה כאשר בוחרים דומיין בברירת מחדל שאינו נתמך על ידי האתר שלך. כבר לא מוצג גלגל ההתקדמות שהסתובב ללא סוף. + +אחרון חביב, עדכנו את הטקסט של מציין המיקום בסרטונים של VideoPress שאינם שייכים לאתר שלך. (אנחנו מקווים שהם לא ייעלבו.) diff --git a/fastlane/jetpack_metadata/id/release_notes.txt b/fastlane/jetpack_metadata/id/release_notes.txt new file mode 100644 index 000000000000..3c70d7db60bc --- /dev/null +++ b/fastlane/jetpack_metadata/id/release_notes.txt @@ -0,0 +1,9 @@ +Paket WordPress.com kini bisa diakses dari aplikasi Jetpack. Temukan paket yang ideal untuk publikasi konten Anda. Kini menulis kalimat penuh inspirasi dan mengelola paket bisa dilakukan di satu tempat. + +Tombol baru “Sesuaikan Tab Beranda” ada di bagian bawah dasbor situs yang bisa Anda gunakan untuk mengatur kartu dasbor mana yang akan ditampilkan. (Mau menyembunyikan kartu yang tidak Anda butuhkan? Cukup buka menu “Lainnya”.) + +Kami sudah mengatasi bug di perangkat yang menjalankan iOS 16 atau yang lebih baru yang menyebabkan teks hasil dikte hilang saat mengetik di editor blok jika fungsi dikte sedang aktif. Di editor, kini juga terdapat ikon gembok untuk sel nonaktif sehingga sel yang sedang tidak digunakan bisa diketahui. + +Kini, pesan error akan ditampilkan di layar “Cari domain” jika domain default yang Anda pilih tidak didukung situs. Tak akan ada lagi indikator progres yang terus berputar. + +Terakhir, teks placeholder untuk video VideoPress yang bukan milik situs Anda juga sudah kami perbarui. (Semoga tidak ada yang merasa kehilangan, ya.) diff --git a/fastlane/jetpack_metadata/ko/release_notes.txt b/fastlane/jetpack_metadata/ko/release_notes.txt new file mode 100644 index 000000000000..916f2a7d89e6 --- /dev/null +++ b/fastlane/jetpack_metadata/ko/release_notes.txt @@ -0,0 +1,9 @@ +워드프레스닷컴 요금제를 젯팩 앱에서 이용할 수 있습니다. 발행 필요성에 따라 적합한 요금제를 이용하고 모든 최상의 단어를 작성하는 곳에서 똑같이 관리할 수 있습니다. + +표시되는 대시보드 카드를 사용자 정의할 수 있는 참신한 새 "홈 탭 개인 설정" 버튼이 사이트 대시보드 하단에 있습니다. (필요 없는 카드는 숨기고 싶으신가요? "더 보기" 메뉴만 사용하면 됩니다.) + +iOS 16 이상이 실행되는 기기의 블록 편집기에서 받아쓰는 동안 입력하면 받아쓴 텍스트가 손실되는 버그를 제거했습니다. 편집기에 비활성화된 셀의 잠금 아이콘도 있어서 언제 해당 셀이 사용되지 않는지 알 수 있습니다. + +사이트에서 지원되지 않는 기본 도메인을 선택하면 이제는 "도메인 검색" 화면에 오류 메시지가 표시됩니다. 더는 영원히 회전하는 진행률 휠이 없습니다. + +마지막으로, 사이트에 속하지 않는 비디오프레스 비디오의 플레이스홀더 텍스트를 업데이트했습니다. (적극적으로 활용해 주세요.) diff --git a/fastlane/jetpack_metadata/nl-NL/release_notes.txt b/fastlane/jetpack_metadata/nl-NL/release_notes.txt new file mode 100644 index 000000000000..5d63b01ec620 --- /dev/null +++ b/fastlane/jetpack_metadata/nl-NL/release_notes.txt @@ -0,0 +1,9 @@ +WordPress.com-abonnementen worden toegevoegd aan de Jetpack-app. Krijg het abonnement dat past bij jouw publicatiebehoeften en beheer het op dezelfde plaats als waar je je beste werk schrijft. + +Er is een mooie, nieuwe knop 'Startpagina personaliseren' onderaan je sitedashboard waar je je zichtbare dashboardkaarten kunt aanpassen. (Wil je de kaarten die je niet nodig hebt verbergen? Gebruik dan gewoon het menu 'Meer'.) + +We hebben een bug verwijderd in apparaten met iOS 16 of later, waarbij typen in de blokeditor terwijl tegelijkertijd werd gedicteerd ervoor zorgde dat de gedicteerde tekst verloren ging. Er is ook een slotpictogram voor uitgeschakelde cellen in de editor zodat je weet wanneer deze niet worden gebruikt. + +Op het scherm 'Domeinen zoeken' zie je nu een foutmelding als je een standaarddomein kiest dat niet wordt ondersteund door je site. Nooit meer dat eeuwig draaiende voortgangswiel. + +Ten slotte hebben we de vervangende tekst bijgewerkt voor VideoPress-video's die niet bij je site horen. (Hopelijk voelen ze zich niet buitengesloten.) diff --git a/fastlane/jetpack_metadata/pt-BR/release_notes.txt b/fastlane/jetpack_metadata/pt-BR/release_notes.txt new file mode 100644 index 000000000000..7a34ec3cb0ac --- /dev/null +++ b/fastlane/jetpack_metadata/pt-BR/release_notes.txt @@ -0,0 +1,9 @@ +Os planos do WordPress.com estão indo para o aplicativo do Jetpack. Obtenha o plano certo para suas necessidades de publicação e gerencie-o no mesmo lugar em que você cria seu conteúdo. + +Há um novo botão "Personalizar guia de página inicial" na parte inferior do painel do site, onde você pode personalizar os cartões visíveis do painel. (Quer ocultar os cartões de que não precisa? Basta usar o menu "Mais".) + +Removemos um bug em dispositivos com iOS 16 ou posterior, em que digitar no editor de blocos durante o ditado causava a perda do texto. Há também um ícone de cadeado para células desativadas no editor para que você saiba quando elas não estão em uso. + +Na tela "Pesquisar domínios", agora você verá uma mensagem de erro se escolher um domínio padrão que não é compatível com seu site. Sem mais essa de roda de progresso girando para sempre. + +Por fim, atualizamos o espaço reservado para os vídeos do VideoPress que não pertencem ao seu site. (Espero que eles não se sintam excluídos.) diff --git a/fastlane/jetpack_metadata/ru/release_notes.txt b/fastlane/jetpack_metadata/ru/release_notes.txt new file mode 100644 index 000000000000..b92298d26415 --- /dev/null +++ b/fastlane/jetpack_metadata/ru/release_notes.txt @@ -0,0 +1,9 @@ +Планы WordPress.com появятся в приложении Jetpack. Получите план, соответствующий вашим издательским потребностям, и управляйте им там же, где пишутся лучшие слова. + +В нижней части панели администратора сайта есть совершенно новая кнопка «Персонализация вкладки "Главная"», где можно настроить отображаемые карточки панели администратора. (Нужно скрыть ненужные карточки? Воспользуйтесь меню «Дополнительно».) + +Мы устранили ошибку на устройствах под управлением iOS 16 и более поздних версий, из-за которой ввод текста в редакторе блоков во время диктовки приводил к потере продиктованного текста. Также в редакторе есть значок замка для отключенных ячеек, чтобы знать, когда они не используются. + +На экране «Поиск доменов» теперь можно увидеть сообщение об ошибке, если выбрать домен по умолчанию, который не поддерживается сайтом. Колесо прогресса теперь не будет вращаться вечно. + +Наконец, мы обновили текст заполнителя для видеороликов в VideoPress, не относящихся к вашему сайту. (Надеемся, они не почувствуют себя отверженными.) diff --git a/fastlane/jetpack_metadata/tr/release_notes.txt b/fastlane/jetpack_metadata/tr/release_notes.txt new file mode 100644 index 000000000000..80240e08f3ca --- /dev/null +++ b/fastlane/jetpack_metadata/tr/release_notes.txt @@ -0,0 +1,9 @@ +WordPress.com paketleri Jetpack uygulamasına geliyor. Yayımcılık ihtiyaçlarınıza en uygun paketi alın ve en güzel yazılarınızı yazdığınız aynı yerden yönetin. + +Site panonuzun alt kısmında, görünür pano kartlarınızı özelleştirebileceğiniz yepyeni bir "Ana Sayfa Sekmesini Kişiselleştir" düğmesi yer alıyor. (İhtiyacınız olmayan kartları gizlemek ister misiniz? “Daha Fazla” menüsünü kullanabilirsiniz.) + +iOS 16 veya üstü yüklü cihazlarda, blok düzenleyicide dikte ile yazarken dikte edilen metnin kaybolmasına neden olan bir hatayı giderdik. Ayrıca, düzenleyicide devre dışı bırakılan hücreler için bir kilit simgesi bulunuyor. Bu simge sayesinde hücrelerin kullanım dışı olduğunu anlayabilirsiniz. + +"Alan adı ara" ekranında, artık siteniz tarafından desteklenmeyen bir varsayılan alan adı seçtiğinizde bir hata mesajı göreceksiniz. Durmadan dönen ilerleme çarkı artık yok. + +Son olarak, sitenize ait olmayan VideoPress videoları için yer tutucu metnini güncelledik. (Umarız dışlanmış hissetmezler.) diff --git a/fastlane/jetpack_metadata/zh-Hans/release_notes.txt b/fastlane/jetpack_metadata/zh-Hans/release_notes.txt new file mode 100644 index 000000000000..6d61f81df5e2 --- /dev/null +++ b/fastlane/jetpack_metadata/zh-Hans/release_notes.txt @@ -0,0 +1,9 @@ +Jetpack 应用即将支持 WordPress.com 套餐。获取适合您的发布需求的套餐,并在您撰写所有精美文章的同一个位置管理该套餐。 + +在您的站点仪表盘底部有一个闪亮的新“对‘首页’选项卡进行个性化”按钮,您可以在其中定制可见的仪表盘卡片。 (想要隐藏您不需要的卡片? 只需使用“更多”菜单。) + +我们删除了运行 iOS 16 或更高版本的设备中的一个错误,即听写时在区块编辑器中键入内容会导致听写文本丢失。 在编辑器中,禁用的单元格也有一个锁形图标,这样您就知道这些单元格何时不能使用。 + +在“搜索域名”屏幕上,如果您选择站点不支持的默认域名,您现在会看到一条错误消息。 系统不会再显示一直旋转的进度轮。 + +最后,我们更新了不属于您站点的 VideoPress 视频的占位符文本。 (希望它们不会感到被忽视。) diff --git a/fastlane/jetpack_metadata/zh-Hant/release_notes.txt b/fastlane/jetpack_metadata/zh-Hant/release_notes.txt new file mode 100644 index 000000000000..b46ff73fa48f --- /dev/null +++ b/fastlane/jetpack_metadata/zh-Hant/release_notes.txt @@ -0,0 +1,9 @@ +Jetpack 應用程式即將提供 WordPress.com 方案。立即取得符合你內容發佈需求的方案,在你寫下所有優質內容的位置即可輕鬆管理。 + +網站儀表板的底部增設了全新的「打造個人化『首頁』分頁」按鈕,讓你可以自訂儀表板中顯示的卡片。 (想將不需要的卡片隱藏起來? 使用「更多」選單就能輕鬆辦到。) + +啟用聽寫功能期間在區塊編輯器中輸入內容,會導致聽寫的文字遺失,我們已針對執行 iOS 16 以上版本的裝置移除這項錯誤。 編輯器中已停用的儲存格也會顯示鎖定圖示,方便你判斷哪些儲存格無法使用。 + +在「搜尋網域」畫面上,現在只要選擇網站不支援的預設網域,就會看到畫面上出現錯誤訊息。 不會再有轉個不停的環型進度圖示。 + +最後,我們針對不屬於你網站的 VideoPress 影片更新了預留位置文字 (這樣應該就不會感覺格格不入)。 From c43c9669468a2c2d92263ff20beb79e86389d1e3 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Thu, 22 Jun 2023 09:40:18 +1000 Subject: [PATCH 22/23] Bump version number --- config/Version.internal.xcconfig | 2 +- config/Version.public.xcconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/Version.internal.xcconfig b/config/Version.internal.xcconfig index c0cc7df1b310..e603e643d906 100644 --- a/config/Version.internal.xcconfig +++ b/config/Version.internal.xcconfig @@ -1,4 +1,4 @@ VERSION_SHORT=22.6 // Internal long version example: VERSION_LONG=9.9.0.20180423 -VERSION_LONG=22.6.0.20230616 +VERSION_LONG=22.6.0.20230622 diff --git a/config/Version.public.xcconfig b/config/Version.public.xcconfig index ce73b02f2a3c..dddde6980460 100644 --- a/config/Version.public.xcconfig +++ b/config/Version.public.xcconfig @@ -1,4 +1,4 @@ VERSION_SHORT=22.6 // Public long version example: VERSION_LONG=9.9.0.0 -VERSION_LONG=22.6.0.1 +VERSION_LONG=22.6.0.2 From 20e1bfa81cc1f5c91d7440ce6eaa06b62f6219e8 Mon Sep 17 00:00:00 2001 From: Gio Lodi Date: Thu, 22 Jun 2023 12:53:22 +1000 Subject: [PATCH 23/23] Add link to GitHub issue in comment with rationale for workaround --- .../Controllers/NotificationsViewController.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/WordPress/Classes/ViewRelated/Notifications/Controllers/NotificationsViewController.swift b/WordPress/Classes/ViewRelated/Notifications/Controllers/NotificationsViewController.swift index 8c83b9b8b1e5..5b769ed57fc7 100644 --- a/WordPress/Classes/ViewRelated/Notifications/Controllers/NotificationsViewController.swift +++ b/WordPress/Classes/ViewRelated/Notifications/Controllers/NotificationsViewController.swift @@ -786,8 +786,10 @@ extension NotificationsViewController { // The ideal solution would be not updating and saving `Notification.read` property in the main context. // Use `CoreDataStack.performAndSave` to do it in a background context instead. However, based on the comments on // `markAsRead` function call below, it appears we intentionally save the main context to maintain some undocumented - // but appears important "side effects". We may need more careful testing around moving the saving operation from + // but apperently important "side effects". We may need more careful testing around moving the saving operation from // the main context to a background context. + // + // See also https://github.com/wordpress-mobile/WordPress-iOS/issues/20850 selectedNotification = note /// Note: markAsRead should be the *first* thing we do. This triggers a context save, and may have many side effects that