diff --git a/Modules/Package.swift b/Modules/Package.swift index 6eaf9bef42b4..e5297f2f6462 100644 --- a/Modules/Package.swift +++ b/Modules/Package.swift @@ -48,7 +48,7 @@ let package = Package( .package(url: "https://github.com/zendesk/support_sdk_ios", from: "8.0.3"), // We can't use wordpress-rs branches nor commits here. Only tags work. .package(url: "https://github.com/Automattic/wordpress-rs", revision: "alpha-20241116"), - .package(url: "https://github.com/wordpress-mobile/GutenbergKit", revision: "4476d597b271778d001a26c50d74e527b54ebfef"), + .package(url: "https://github.com/wordpress-mobile/GutenbergKit", revision: "cc52214a50893b41898607ac0bff7f2787b085bb"), .package(url: "https://github.com/Automattic/color-studio", branch: "trunk"), .package(url: "https://github.com/allenhumphreys/AztecEditor-iOS", branch: "ah/spm"), ], diff --git a/Modules/Sources/AsyncImageKit/ImagePrefetcher.swift b/Modules/Sources/AsyncImageKit/ImagePrefetcher.swift index 623d60ac2aa2..7b807ec0dd99 100644 --- a/Modules/Sources/AsyncImageKit/ImagePrefetcher.swift +++ b/Modules/Sources/AsyncImageKit/ImagePrefetcher.swift @@ -89,6 +89,7 @@ public final class ImagePrefetcher { value.task?.cancel() } queue.removeAll() + numberOfActiveTasks = 0 } } diff --git a/Modules/Sources/AsyncImageKit/ImageRequest.swift b/Modules/Sources/AsyncImageKit/ImageRequest.swift index 5a4ada4df736..9573ab0edbd2 100644 --- a/Modules/Sources/AsyncImageKit/ImageRequest.swift +++ b/Modules/Sources/AsyncImageKit/ImageRequest.swift @@ -51,29 +51,34 @@ public struct ImageRequestOptions: Hashable, Sendable { /// Image size in **pixels**. public struct ImageSize: Hashable, Sendable { - public let width: CGFloat - public let height: CGFloat + /// Width in **pixels**. + public var width: Int + /// Height in **pixels**. + public var height: Int - public init(width: CGFloat, height: CGFloat) { + /// Initializes the struct with given size in **pixels**. + public init(width: Int, height: Int) { self.width = width self.height = height } - public init(_ size: CGSize) { - self.width = size.width - self.height = size.height + /// Initializes the struct with given size in **pixels**. + public init(pixels size: CGSize) { + self.width = Int(size.width) + self.height = Int(size.height) } - /// Initializes `ImageSize` with the given size scaled for the given view. + /// A convenience initializer that creates `ImageSize` with the given size + /// in **points** scaled for the given view. @MainActor public init(scaling size: CGSize, in view: UIView) { - self.init(size.scaled(by: view.traitCollection.displayScale)) + self.init(scaling: size, scale: view.traitCollection.displayScale) } - /// Initializes `ImageSize` with the given size scaled for the current trait - /// collection display scale. - public init(scaling size: CGSize) { - self.init(size.scaled(by: UITraitCollection.current.displayScale)) + /// Initializes `ImageSize` with the given size in **points** scaled for the + /// current trait collection display scale. + public init(scaling size: CGSize, scale: CGFloat) { + self.init(pixels: size.scaled(by: max(1, scale))) } } diff --git a/Modules/Sources/AsyncImageKit/Views/AsyncImageView.swift b/Modules/Sources/AsyncImageKit/Views/AsyncImageView.swift index 464490a0bfb2..df8c49bd1fcb 100644 --- a/Modules/Sources/AsyncImageKit/Views/AsyncImageView.swift +++ b/Modules/Sources/AsyncImageKit/Views/AsyncImageView.swift @@ -30,6 +30,7 @@ public final class AsyncImageView: UIView { /// By default, `background`. public var loadingStyle = LoadingStyle.background + // TODO: remove when WPRichTextImage is removed public var passTouchesToSuperview = false public init() {} diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 7ca6344db2a7..4416a3000569 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,8 +1,9 @@ 25.7 ----- * [**] Add Image Playground support (part of Apple Intelligence suite) for adding images to your posts, generated featured image, site icons, and more [#23688] -* [**] Add new lightbox screen for images with modern transitions and enhanced performance [#23922] +* [**] Enable history navigation (undo and redo) for the experimental editor. [#23961] * [**] Enhance the Gravatar Quick Editor by adding features that allow users to delete and share their avatars. [#23868] +* [**] Add new lightbox screen for images with modern transitions and enhanced performance [#23922] * [**] Add the capability to create an avatar using Apple Image Playground through the Gravatar Quick Editor. [#23868] * [**] Various bug fixes and improvements in the new experimental editor [#23919] * [*] Fix sorting in Stats Subscriber Emails (latest first) [#23913] @@ -39,6 +40,14 @@ * [*] Fix small tap area for “More” button in the Subscriptions screen in Reader [#23964] * [*] Fix “Notification Settings” for individual posts sometimes being clipped [#23964] * [*] Add context menu (long-press) and previews for subscriptions with quick access to “Share”, “Copy Link”, “Add to Favorites”, “Notification Settings”, and “Unsubscribe” buttons in both the Subscriptions view and the Sidebar in Reader [#23964] +* [*] Fix an issue with fullscreen button in reply view clipped by the notch [#23965] +* [*] Remove "Lazy Images" option that is no longer part of the Jetpack plugin [#23966] +* [*] Fix an issue with "Speed up your site" section not refreshing (fails silently) [#23966] +* [*] Fix an issue with small tap area of the ellipsis in the post list [#23973] +* [*] Avoid unexpectedly marking post content as unsaved. [#23969] +* [*] Fix an issue with Mastodon connection not working [#23981] +* [**] Send feedback from within the experimental editor "more" options menu. [#23980] +* [**] Support accessing the code editor within the experimental editor. [#23979] 25.6 ----- @@ -98,7 +107,7 @@ * [*] [internal] Incorporate a parser to handle Gutenberg blocks more efficiently for improved performance [#22886] * [**] Improve performance of Image and Gallery block processors to avoid long delay when saving a post [#22896] * [*] Improve performance of File block processor [#22897] -* [*] [internal] Prompt users to keep the app up to date on their devices, so they can try new features, as well as benefit from performance improvements and bug fixes [#23195, #23216, #23218, #23211] +* [*] [internal] Prompt users to keep the app up to date on their devices, so they can try new features, as well as benefit from performance improvements and bug fixes [#23195, #23216, #23218, #23211] * [**] [Jetpack-only] Reader: Add a new feed dedicated to tags [#23242] 24.9.1 diff --git a/WordPress.xcworkspace/xcshareddata/swiftpm/Package.resolved b/WordPress.xcworkspace/xcshareddata/swiftpm/Package.resolved index ed7e6362bd38..5ae8f5ac883b 100644 --- a/WordPress.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/WordPress.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "c6c4224bb9091cbaed87a958001b2435576248fec163dc8ce6be041f8e1da166", + "originHash" : "d8a7faa1972ab73744be3161f236c4bae7faf7c44f840b7bd0a52b3ee1ee6d6c", "pins" : [ { "identity" : "alamofire", @@ -150,7 +150,7 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/wordpress-mobile/GutenbergKit", "state" : { - "revision" : "4476d597b271778d001a26c50d74e527b54ebfef" + "revision" : "cc52214a50893b41898607ac0bff7f2787b085bb" } }, { @@ -392,7 +392,7 @@ "location" : "https://github.com/wordpress-mobile/WordPressKit-iOS", "state" : { "branch" : "wpios-edition", - "revision" : "908d96a6ff4eb38217e57c03996bf1f3e9cdb114" + "revision" : "a9a057ea6fba8080c146497336951dc805409771" } }, { diff --git a/WordPress/Classes/Models/Blog/BlogSettings.swift b/WordPress/Classes/Models/Blog/BlogSettings.swift index d07e8368719d..ff1f175d26b8 100644 --- a/WordPress/Classes/Models/Blog/BlogSettings.swift +++ b/WordPress/Classes/Models/Blog/BlogSettings.swift @@ -71,6 +71,7 @@ open class BlogSettings: NSManagedObject { /// Jetpack Setting: lazy load images. /// + @available(*, deprecated) @NSManaged var jetpackLazyLoadImages: Bool // MARK: - Discussion diff --git a/WordPress/Classes/Models/ReaderTagTopic.swift b/WordPress/Classes/Models/ReaderTagTopic.swift index 9151484d576d..7bb43246d362 100644 --- a/WordPress/Classes/Models/ReaderTagTopic.swift +++ b/WordPress/Classes/Models/ReaderTagTopic.swift @@ -52,6 +52,10 @@ import Foundation return topic } + var formattedTitle: String { + title.split(separator: "-").map(\.capitalized).joined(separator: " ") + } + /// Convenience method to update the tag's `following` state and also updates `showInMenu`. @objc func toggleFollowing(_ isFollowing: Bool) { following = isFollowing diff --git a/WordPress/Classes/Services/BlogJetpackSettingsService.swift b/WordPress/Classes/Services/BlogJetpackSettingsService.swift index e8a58a197868..f300c8aae2ef 100644 --- a/WordPress/Classes/Services/BlogJetpackSettingsService.swift +++ b/WordPress/Classes/Services/BlogJetpackSettingsService.swift @@ -142,29 +142,6 @@ struct BlogJetpackSettingsService { ) } - func updateJetpackLazyImagesModuleSettingForBlog(_ blog: Blog, success: @escaping () -> Void, failure: @escaping (Error?) -> Void) { - guard let blogSettings = blog.settings else { - failure(nil) - return - } - - let isActive = blogSettings.jetpackLazyLoadImages - updateJetpackModuleActiveSettingForBlog( - blog, - module: BlogJetpackSettingsServiceRemote.Keys.lazyLoadImages, - active: isActive, - success: { - self.coreDataStack.performAndSave({ context in - guard let blogSettingsInContext = Blog.lookup(withObjectID: blog.objectID, in: context)?.settings else { - return - } - blogSettingsInContext.jetpackLazyLoadImages = isActive - }, completion: success, on: .main) - }, - failure: failure - ) - } - func updateJetpackServeImagesFromOurServersModuleSettingForBlog(_ blog: Blog, success: @escaping () -> Void, failure: @escaping (Error?) -> Void) { guard let blogSettings = blog.settings else { failure(nil) @@ -235,7 +212,6 @@ private extension BlogJetpackSettingsService { } func updateJetpackModulesSettings(_ settings: BlogSettings, remoteSettings: RemoteBlogJetpackModulesSettings) { - settings.jetpackLazyLoadImages = remoteSettings.lazyLoadImages settings.jetpackServeImagesFromOurServers = remoteSettings.serveImagesFromOurServers } diff --git a/WordPress/Classes/System/Root View/ReaderPresenter.swift b/WordPress/Classes/System/Root View/ReaderPresenter.swift index 6e48fd7c208d..d9fe311ba90a 100644 --- a/WordPress/Classes/System/Root View/ReaderPresenter.swift +++ b/WordPress/Classes/System/Root View/ReaderPresenter.swift @@ -15,7 +15,6 @@ final class ReaderPresenter: NSObject, SplitViewDisplayable { /// The navigation controller for the main content when shown using tabs. private var mainNavigationController = UINavigationController() - private var latestContentVC: UIViewController? private var viewContext: NSManagedObjectContext { ContextManager.shared.mainContext @@ -58,8 +57,8 @@ final class ReaderPresenter: NSObject, SplitViewDisplayable { // -warning: List occasionally sets the selection to `nil` when switching items. selectionObserver = sidebarViewModel.$selection.compactMap { $0 } .removeDuplicates { [weak self] in - guard $0 == $1 else { return false } - self?.popMainNavigationController() + guard $0 == $1, let self, let splitViewController else { return false } + self.popMainNavigationController(in: splitViewController) return true } .sink { [weak self] in self?.configure(for: $0) } @@ -84,17 +83,10 @@ final class ReaderPresenter: NSObject, SplitViewDisplayable { hideSupplementaryColumnIfNeeded() } - private func popMainNavigationController() { - if let splitViewController { - let secondaryVC = splitViewController.viewController(for: .secondary) - (secondaryVC as? UINavigationController)?.popToRootViewController(animated: true) - hideSupplementaryColumnIfNeeded() - } else { - if let latestContentVC { - // Return to the previous view controller preserving its state - mainNavigationController.safePushViewController(latestContentVC, animated: true) - } - } + private func popMainNavigationController(in splitViewController: UISplitViewController) { + let secondaryVC = splitViewController.viewController(for: .secondary) + (secondaryVC as? UINavigationController)?.popToRootViewController(animated: true) + hideSupplementaryColumnIfNeeded() } private func hideSupplementaryColumnIfNeeded() { @@ -190,7 +182,6 @@ final class ReaderPresenter: NSObject, SplitViewDisplayable { } splitViewController.setViewController(navigationVC, for: .secondary) } else { - latestContentVC = viewController mainNavigationController.safePushViewController(viewController, animated: true) } } diff --git a/WordPress/Classes/Utility/In-App Feedback/SubmitFeedbackViewController.swift b/WordPress/Classes/Utility/In-App Feedback/SubmitFeedbackViewController.swift index 0129e0cf7c38..9808ef547e0f 100644 --- a/WordPress/Classes/Utility/In-App Feedback/SubmitFeedbackViewController.swift +++ b/WordPress/Classes/Utility/In-App Feedback/SubmitFeedbackViewController.swift @@ -4,9 +4,11 @@ import WordPressShared final class SubmitFeedbackViewController: UIViewController { private var source: String + private var feedbackPrefix: String? - init(source: String) { + init(source: String, feedbackPrefix: String? = nil) { self.source = source + self.feedbackPrefix = feedbackPrefix super.init(nibName: nil, bundle: nil) self.modalPresentationStyle = .formSheet } @@ -18,7 +20,7 @@ final class SubmitFeedbackViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - let viewController = UIHostingController(rootView: SubmitFeedbackView(presentingViewController: self, source: source)) + let viewController = UIHostingController(rootView: SubmitFeedbackView(presentingViewController: self, source: source, feedbackPrefix: feedbackPrefix)) let navigationController = UINavigationController(rootViewController: viewController) @@ -33,6 +35,7 @@ final class SubmitFeedbackViewController: UIViewController { private struct SubmitFeedbackView: View { weak var presentingViewController: UIViewController? let source: String + let feedbackPrefix: String? @State private var text = "" @State private var isSubmitting = false @@ -141,9 +144,10 @@ private struct SubmitFeedbackView: View { isSubmitting = true + let descriptionPrefix = feedbackPrefix.map { "[\($0)] " } ?? "" ZendeskUtils.sharedInstance.createNewRequest( in: presentingViewController, - description: text.trim(), + description: descriptionPrefix + text.trim(), tags: ["appreview_jetpack", "in_app_feedback"], attachments: attachmentsViewModel.attachments.compactMap(\.response), alertOptions: nil @@ -195,6 +199,6 @@ private enum Strings { #Preview { NavigationView { - SubmitFeedbackView(source: "preview") + SubmitFeedbackView(source: "preview", feedbackPrefix: nil) } } diff --git a/WordPress/Classes/Utility/SharedStrings.swift b/WordPress/Classes/Utility/SharedStrings.swift index 32c4c32adcc8..d22a5186b5ec 100644 --- a/WordPress/Classes/Utility/SharedStrings.swift +++ b/WordPress/Classes/Utility/SharedStrings.swift @@ -23,6 +23,7 @@ enum SharedStrings { enum Error { static let generic = NSLocalizedString("shared.error.geneirc", value: "Something went wrong", comment: "A generic error message") + static let refreshFailed = NSLocalizedString("shared.error.failiedToReloadData", value: "Failed to update data", comment: "A generic error title indicating that a screen failed to fetch the latest data") } enum Reader { diff --git a/WordPress/Classes/Utility/WebViewController/WPWebViewController.m b/WordPress/Classes/Utility/WebViewController/WPWebViewController.m index b35ec6873039..5b61051a5a89 100644 --- a/WordPress/Classes/Utility/WebViewController/WPWebViewController.m +++ b/WordPress/Classes/Utility/WebViewController/WPWebViewController.m @@ -177,6 +177,7 @@ - (void)setupTitle - (void)setupWebView { + self.webView.customUserAgent = [WPUserAgent wordPressUserAgent]; self.webView.navigationDelegate = self; } diff --git a/WordPress/Classes/ViewRelated/Blog/Blog Details/Detail Header/BlogDetailHeaderView.swift b/WordPress/Classes/ViewRelated/Blog/Blog Details/Detail Header/BlogDetailHeaderView.swift index 9be29e8fc727..0101ea0b21d4 100644 --- a/WordPress/Classes/ViewRelated/Blog/Blog Details/Detail Header/BlogDetailHeaderView.swift +++ b/WordPress/Classes/ViewRelated/Blog/Blog Details/Detail Header/BlogDetailHeaderView.swift @@ -131,6 +131,9 @@ class BlogDetailHeaderView: UIView { private func makeSiteLinkMenu() -> UIMenu { UIMenu(children: [ + UIAction(title: SharedStrings.Button.share, image: UIImage(systemName: "square.and.arrow.up"), handler: { [weak self] _ in + self?.delegate?.buttonShareSiteTapped() + }), UIAction(title: Strings.visitSite, image: UIImage(systemName: "safari"), handler: { [weak self] _ in self?.delegate?.visitSiteTapped() }), diff --git a/WordPress/Classes/ViewRelated/Blog/My Site/Header/HomeSiteHeaderViewController+SiteActions.swift b/WordPress/Classes/ViewRelated/Blog/My Site/Header/HomeSiteHeaderViewController+SiteActions.swift index 0f8966bb6ffa..f98b62bc690b 100644 --- a/WordPress/Classes/ViewRelated/Blog/My Site/Header/HomeSiteHeaderViewController+SiteActions.swift +++ b/WordPress/Classes/ViewRelated/Blog/My Site/Header/HomeSiteHeaderViewController+SiteActions.swift @@ -108,7 +108,7 @@ private enum MenuItem { var title: String { switch self { case .visitSite: return Strings.visitSite - case .shareSite: return SharedStrings.Button.share + "…" + case .shareSite: return SharedStrings.Button.share case .siteTitle: return Strings.siteTitle case .personalizeHome: return Strings.personalizeHome } diff --git a/WordPress/Classes/ViewRelated/Blog/Sharing/SharingConnectionsViewController.m b/WordPress/Classes/ViewRelated/Blog/Sharing/SharingConnectionsViewController.m index 27061ce4c1ae..d4aec707d768 100644 --- a/WordPress/Classes/ViewRelated/Blog/Sharing/SharingConnectionsViewController.m +++ b/WordPress/Classes/ViewRelated/Blog/Sharing/SharingConnectionsViewController.m @@ -232,11 +232,6 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath - (void)handleConnectTapped:(NSIndexPath *)indexPath { - if (![ReachabilityUtils isInternetReachable]) { - [ReachabilityUtils showAlertNoInternetConnection]; - return; - } - if ([UIDevice isPad]) { UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; self.helper.popoverSourceView = cell.textLabel; diff --git a/WordPress/Classes/ViewRelated/Blog/Sharing/SharingDetailViewController.m b/WordPress/Classes/ViewRelated/Blog/Sharing/SharingDetailViewController.m index 67f06758b3e9..6e4824379d89 100644 --- a/WordPress/Classes/ViewRelated/Blog/Sharing/SharingDetailViewController.m +++ b/WordPress/Classes/ViewRelated/Blog/Sharing/SharingDetailViewController.m @@ -238,11 +238,6 @@ - (void)updateSharedGlobally:(BOOL)shared - (void)reconnectPublicizeConnection { - if (![ReachabilityUtils isInternetReachable]) { - [ReachabilityUtils showAlertNoInternetConnection]; - return; - } - SharingService *sharingService = [[SharingService alloc] initWithContextManager:[ContextManager sharedInstance]]; __weak __typeof(self) weakSelf = self; @@ -273,11 +268,6 @@ - (void)disconnectPublicizeConnection - (void)promptToConfirmDisconnect { - if (![ReachabilityUtils isInternetReachable]) { - [ReachabilityUtils showAlertNoInternetConnection]; - return; - } - NSString *message = NSLocalizedString(@"Disconnecting this account means published posts will no longer be automatically shared to %@", @"Explanatory text for the user. The `%@` is a placeholder for the name of a third-party sharing service."); message = [NSString stringWithFormat:message, self.publicizeConnection.label]; UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil diff --git a/WordPress/Classes/ViewRelated/EEUUSCompliance/ComplianceLocationService.swift b/WordPress/Classes/ViewRelated/EEUUSCompliance/ComplianceLocationService.swift index 806fa6ec2a91..a1b1f1977616 100644 --- a/WordPress/Classes/ViewRelated/EEUUSCompliance/ComplianceLocationService.swift +++ b/WordPress/Classes/ViewRelated/EEUUSCompliance/ComplianceLocationService.swift @@ -1,7 +1,9 @@ import WordPressKit class ComplianceLocationService { + private let session = URLSession(configuration: .ephemeral) + func getIPCountryCode(completion: @escaping (Result) -> Void) { - IPLocationRemote().fetchIPCountryCode(completion: completion) + IPLocationRemote(urlSession: session).fetchIPCountryCode(completion: completion) } } diff --git a/WordPress/Classes/ViewRelated/Gutenberg/EditorMediaUtility.swift b/WordPress/Classes/ViewRelated/Gutenberg/EditorMediaUtility.swift index db8140d79a04..a338f13e481f 100644 --- a/WordPress/Classes/ViewRelated/Gutenberg/EditorMediaUtility.swift +++ b/WordPress/Classes/ViewRelated/Gutenberg/EditorMediaUtility.swift @@ -87,7 +87,7 @@ class EditorMediaUtility { callbackQueue.async { failure(error) } - return MeediaUtilityTask { /* do nothing */ } + return MediaUtilityTask { /* do nothing */ } case let .success((imageURL, host)): let task = Task { @MainActor in do { @@ -98,7 +98,7 @@ class EditorMediaUtility { } } - return MeediaUtilityTask { task.cancel() } + return MediaUtilityTask { task.cancel() } } } @@ -202,7 +202,7 @@ class EditorMediaUtility { } } -private struct MeediaUtilityTask: ImageDownloaderTask { +private struct MediaUtilityTask: ImageDownloaderTask { let closure: @Sendable () -> Void func cancel() { diff --git a/WordPress/Classes/ViewRelated/Jetpack/Jetpack Settings/JetpackSpeedUpSiteSettingsViewController.swift b/WordPress/Classes/ViewRelated/Jetpack/Jetpack Settings/JetpackSpeedUpSiteSettingsViewController.swift index 38741318ab74..b15d4f330b2d 100644 --- a/WordPress/Classes/ViewRelated/Jetpack/Jetpack Settings/JetpackSpeedUpSiteSettingsViewController.swift +++ b/WordPress/Classes/ViewRelated/Jetpack/Jetpack Settings/JetpackSpeedUpSiteSettingsViewController.swift @@ -24,6 +24,7 @@ open class JetpackSpeedUpSiteSettingsViewController: UITableViewController { @objc public convenience init(blog: Blog) { self.init(style: .insetGrouped) + self.blog = blog self.service = BlogJetpackSettingsService(coreDataStack: ContextManager.shared) } @@ -32,6 +33,7 @@ open class JetpackSpeedUpSiteSettingsViewController: UITableViewController { open override func viewDidLoad() { super.viewDidLoad() + title = NSLocalizedString("Speed up your site", comment: "Title for the Speed up your site Settings Screen") ImmuTable.registerRows([SwitchRow.self], tableView: tableView) WPStyleGuide.configureColors(view: view, tableView: tableView) @@ -40,6 +42,7 @@ open class JetpackSpeedUpSiteSettingsViewController: UITableViewController { open override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + reloadViewModel() refreshSettings() } @@ -51,34 +54,18 @@ open class JetpackSpeedUpSiteSettingsViewController: UITableViewController { } func tableViewModel() -> ImmuTable { - - let serveImagesFromOurServers = SwitchRow(title: NSLocalizedString("Serve images from our servers", - comment: "Title for the Serve images from our servers setting"), - value: self.settings.jetpackServeImagesFromOurServers, - onChange: self.serveImagesFromOurServersValueChanged()) - - let lazyLoadImages = SwitchRow(title: NSLocalizedString("\"Lazy-load\" images", - comment: "Title for the lazy load images setting"), - value: self.settings.jetpackLazyLoadImages, - onChange: self.lazyLoadImagesValueChanged()) + let serveImagesFromOurServers = SwitchRow( + title: NSLocalizedString("Serve images from our servers", + comment: "Title for the Serve images from our servers setting"), + value: self.settings.jetpackServeImagesFromOurServers, + onChange: self.serveImagesFromOurServersValueChanged()) return ImmuTable(sections: [ ImmuTableSection( headerText: "", rows: [serveImagesFromOurServers], - footerText: NSLocalizedString("Jetpack will optimize your images and serve them from the server " + - "location nearest to your visitors. Using our global content delivery " + - "network will boost the loading speed of your site.", - comment: "Footer for the Serve images from our servers setting")), - - ImmuTableSection( - headerText: "", - rows: [lazyLoadImages], - footerText: NSLocalizedString("Improve your site's speed by only loading images visible on the screen. " + - "New images will load just before they scroll into view. This prevents " + - "viewers from having to download all the images on a page all at once, " + - "even ones they can't see.", - comment: "Footer for the Serve images from our servers setting")), + footerText: NSLocalizedString("Jetpack will optimize your images and serve them from the server location nearest to your visitors. Using our global content delivery network will boost the loading speed of your site.", comment: "Footer for the Serve images from our servers setting") + ) ]) } @@ -92,36 +79,25 @@ open class JetpackSpeedUpSiteSettingsViewController: UITableViewController { self.service.updateJetpackServeImagesFromOurServersModuleSettingForBlog(self.blog, success: {}, - failure: { [weak self] (_) in + failure: { [weak self] _ in self?.refreshSettingsAfterSavingError() }) } } - fileprivate func lazyLoadImagesValueChanged() -> (_ newValue: Bool) -> Void { - return { [unowned self] newValue in - self.settings.jetpackLazyLoadImages = newValue - self.reloadViewModel() - WPAnalytics.trackSettingsChange("jetpack_speed_up_site", fieldName: "lazy_load_images", value: newValue as Any) - self.service.updateJetpackLazyImagesModuleSettingForBlog(self.blog, - success: {}, - failure: { [weak self] (_) in - self?.refreshSettingsAfterSavingError() - }) - } - } - // MARK: - Persistance fileprivate func refreshSettings() { - service.syncJetpackModulesForBlog(blog, - success: { [weak self] in - self?.reloadViewModel() - DDLogInfo("Reloaded Speed up site settings") - }, - failure: { (error: Error?) in - DDLogError("Error while syncing blog Speed up site settings: \(String(describing: error))") - }) + service.syncJetpackModulesForBlog( + blog, + success: { [weak self] in + self?.reloadViewModel() + DDLogInfo("Reloaded Speed up site settings") + }, + failure: { (error: Error?) in + Notice(title: SharedStrings.Error.refreshFailed, message: error?.localizedDescription).post() + DDLogError("Error while syncing blog Speed up site settings: \(String(describing: error))") + }) } fileprivate func refreshSettingsAfterSavingError() { diff --git a/WordPress/Classes/ViewRelated/Media/External/ExternalMediaPickerViewController.swift b/WordPress/Classes/ViewRelated/Media/External/ExternalMediaPickerViewController.swift index b0ad72b0d00a..d4def47f7823 100644 --- a/WordPress/Classes/ViewRelated/Media/External/ExternalMediaPickerViewController.swift +++ b/WordPress/Classes/ViewRelated/Media/External/ExternalMediaPickerViewController.swift @@ -236,7 +236,7 @@ final class ExternalMediaPickerViewController: UIViewController, UICollectionVie func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Self.cellReuseID, for: indexPath) as! ExternalMediaPickerCollectionCell let item = dataSource.assets[indexPath.item] - cell.configure(imageURL: item.thumbnailURL, size: ImageSize(scaling: flowLayout.itemSize)) + cell.configure(imageURL: item.thumbnailURL, size: ImageSize(scaling: flowLayout.itemSize, in: self.view)) return cell } diff --git a/WordPress/Classes/ViewRelated/NewGutenberg/NewGutenbergViewController.swift b/WordPress/Classes/ViewRelated/NewGutenberg/NewGutenbergViewController.swift index 567c69365271..466d07ece773 100644 --- a/WordPress/Classes/ViewRelated/NewGutenberg/NewGutenbergViewController.swift +++ b/WordPress/Classes/ViewRelated/NewGutenberg/NewGutenbergViewController.swift @@ -1,4 +1,5 @@ import UIKit +import WordPressUI import AsyncImageKit import AutomatticTracks import GutenbergKit @@ -69,18 +70,6 @@ class NewGutenbergViewController: UIViewController, PostEditor, PublishingEditor private let editorViewController: GutenbergKit.EditorViewController private weak var autosaveTimer: Timer? - var editorHasChanges: Bool { - var changes = post.changes - // TODO: cleanup (+ it doesn't handle scenarios like load from a revision) - // - warning: it has to compare two version serialized using the same system - if editorViewController.initialContent != post.content { - changes.content = post.content - } else { - changes.content = nil // yes, it needs to be set to .none manually - } - return !changes.isEmpty - } - // TODO: remove (none of these APIs are needed for the new editor) var autosaver = Autosaver(action: {}) func prepopulateMediaItems(_ media: [Media]) {} @@ -243,22 +232,8 @@ class NewGutenbergViewController: UIViewController, PostEditor, PublishingEditor } private func reloadBlogIconView() { - let blog = post.blog - -// if blog.hasIcon == true { -// let size = CGSize(width: 24, height: 24) -// navigationBarManager.siteIconView.imageView.downloadSiteIcon(for: blog, imageSize: size) -// } else if blog.isWPForTeams() { -// navigationBarManager.siteIconView.imageView.tintColor = UIColor.secondaryLabel -// navigationBarManager.siteIconView.imageView.image = UIImage.gridicon(.p2) -// } else { -// navigationBarManager.siteIconView.imageView.image = UIImage.siteIconPlaceholder -// } - - // TODO: implement - // Docs: https://wordpress.org/gutenberg-framework/docs/basic-concepts/undo-redo - navigationBarManager.undoButton.isHidden = true - navigationBarManager.redoButton.isHidden = true + let viewModel = SiteIconViewModel(blog: post.blog, size: .small) + navigationBarManager.siteIconView.imageView.setIcon(with: viewModel) } // TODO: this should not be called on viewDidLoad @@ -313,6 +288,10 @@ class NewGutenbergViewController: UIViewController, PostEditor, PublishingEditor guard let url = URL(string: "https://wordpress.com/support/wordpress-editor/") else { return } present(SFSafariViewController(url: url), animated: true) } + + func showFeedbackView() { + self.present(SubmitFeedbackViewController(source: "gutenberg_kit", feedbackPrefix: "Editor"), animated: true) + } } extension NewGutenbergViewController: GutenbergKit.EditorViewControllerDelegate { @@ -347,6 +326,11 @@ extension NewGutenbergViewController: GutenbergKit.EditorViewControllerDelegate } } + func editor(_ viewController: GutenbergKit.EditorViewController, didUpdateHistoryState state: GutenbergKit.EditorState) { + gutenbergDidRequestToggleRedoButton(!state.hasRedo) + gutenbergDidRequestToggleUndoButton(!state.hasUndo) + } + func editor(_ viewController: GutenbergKit.EditorViewController, performRequest: GutenbergKit.EditorNetworkRequest) async throws -> GutenbergKit.EditorNetworkResponse { throw URLError(.unknown) } @@ -610,13 +594,11 @@ extension NewGutenbergViewController: PostEditorNavigationBarManagerDelegate { } func navigationBarManager(_ manager: PostEditorNavigationBarManager, undoWasPressed sender: UIButton) { - // TODO: reimplement - // self.gutenberg.onUndoPressed() + editorViewController.undo() } func navigationBarManager(_ manager: PostEditorNavigationBarManager, redoWasPressed sender: UIButton) { - // TODO: reimplement - // self.gutenberg.onRedoPressed() + editorViewController.redo() } func navigationBarManager(_ manager: PostEditorNavigationBarManager, moreWasPressed sender: UIButton) { @@ -728,6 +710,9 @@ extension NewGutenbergViewController { actions.append(UIAction(title: helpTitle, image: UIImage(systemName: "questionmark.circle")) { [weak self] _ in self?.showEditorHelp() }) + actions.append(UIAction(title: Strings.sendFeedback, image: UIImage(systemName: "envelope")) { [weak self] _ in + self?.showFeedbackView() + }) return actions } @@ -767,6 +752,7 @@ private enum Strings { static let postSettings = NSLocalizedString("postEditor.moreMenu.postSettings", value: "Post Settings", comment: "Post Editor / Button in the 'More' menu") static let helpAndSupport = NSLocalizedString("postEditor.moreMenu.helpAndSupport", value: "Help & Support", comment: "Post Editor / Button in the 'More' menu") static let help = NSLocalizedString("postEditor.moreMenu.help", value: "Help", comment: "Post Editor / Button in the 'More' menu") + static let sendFeedback = NSLocalizedString("postEditor.moreMenu.sendFeedback", value: "Send Feedback", comment: "Post Editor / Button in the 'More' menu") static let saveDraft = NSLocalizedString("postEditor.moreMenu.saveDraft", value: "Save Draft", comment: "Post Editor / Button in the 'More' menu") static let contentStructure = NSLocalizedString("postEditor.moreMenu.contentStructure", value: "Blocks: %li, Words: %li, Characters: %li", comment: "Post Editor / 'More' menu details labels with 'Blocks', 'Words' and 'Characters' counts as parameters (in that order)") } diff --git a/WordPress/Classes/ViewRelated/Notifications/ReplyTextView/ReplyTextView.xib b/WordPress/Classes/ViewRelated/Notifications/ReplyTextView/ReplyTextView.xib index 873787813b75..b64ae72ebdee 100644 --- a/WordPress/Classes/ViewRelated/Notifications/ReplyTextView/ReplyTextView.xib +++ b/WordPress/Classes/ViewRelated/Notifications/ReplyTextView/ReplyTextView.xib @@ -23,7 +23,7 @@ - + @@ -35,7 +35,7 @@ - + @@ -63,16 +63,16 @@ - + - + - +