Skip to content

Commit

Permalink
Merge branch 'feature/notifications_refresh_p2' into task/likes-detai…
Browse files Browse the repository at this point in the history
…ls-list-redesign
  • Loading branch information
justtwago committed May 10, 2024
2 parents 5d93234 + 09bd4df commit ee2d565
Show file tree
Hide file tree
Showing 128 changed files with 5,422 additions and 1,096 deletions.
5 changes: 3 additions & 2 deletions Modules/Sources/DesignSystem/Foundation/IconName.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ public enum IconName: String, CaseIterable {
case edit
case avatar
case exclamationCircle = "exclamation.circle"
case arrowUp = "arrow.up"
case arrowDown = "arrow.down"
case person
case arrowUp = "arrow.up"
case arrowDown = "arrow.down"
case vector = "vector"
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "gravatar.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "delete_24px.pdf",
"filename" : "trash.pdf",
"idiom" : "universal"
}
],
Expand Down
Binary file not shown.
Binary file not shown.
6 changes: 3 additions & 3 deletions Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ PODS:
- WordPressKit (~> 17.0)
- WordPressShared (~> 2.1-beta)
- WordPressUI (~> 1.7-beta)
- WordPressKit (17.1.0):
- WordPressKit (17.1.1):
- NSObject-SafeExpectations (~> 0.0.4)
- UIDeviceIdentifier (~> 2.0)
- WordPressShared (~> 2.0-beta)
Expand Down Expand Up @@ -132,6 +132,7 @@ SPEC REPOS:
- WordPress-Aztec-iOS
- WordPress-Editor-iOS
- WordPressAuthenticator
- WordPressKit
- WordPressShared
trunk:
- Alamofire
Expand Down Expand Up @@ -160,7 +161,6 @@ SPEC REPOS:
- SVProgressHUD
- SwiftLint
- UIDeviceIdentifier
- WordPressKit
- WordPressUI
- wpxmlrpc
- ZendeskCommonUISDK
Expand Down Expand Up @@ -216,7 +216,7 @@ SPEC CHECKSUMS:
WordPress-Aztec-iOS: 3732c6d865a5c9f35788377bdeda8a80ea10d0a1
WordPress-Editor-iOS: 453345420ced3d3ef20f0051b3df46ff10281e0c
WordPressAuthenticator: 898acaac75c5ade9b900c02622a15b9aef8fde1a
WordPressKit: 4042625f32513a98fe1bc8552f1aa59ef236bcdc
WordPressKit: a4af3d5d071734aaec75ccecefc7850ece6068fc
WordPressShared: 0160364ed24f4d67fed4e85003fefa837faad84f
WordPressUI: ec5ebcf7e63e797ba51d07513e340c1b14cf45a4
wpxmlrpc: 68db063041e85d186db21f674adf08d9c70627fd
Expand Down
22 changes: 22 additions & 0 deletions RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,28 @@
* [*] Add "Parent Page" to "Page Settings" [#23136]
* [*] Add "Slug" and "Excerpt" fields to "Page Settings" [#23135]
* [*] Make it easier to "Share" and "Blaze" a published post with an updated success view [##23128]
* [*] Add support for viewing trashed posts and pages and restoring them from the editor [#23142]
* [***] [Jetpack-only] Reorganized Stats to include updated Traffic and Insights tabs, along with a newly added Subscribers tab to improve subscriber metrics analysis [#23159]
* [*] Impove the "Post Settings" screen groups/ordering to better align with Gutenberg [#23164]
* [*] Update the "More" menu in the Editor to use modern iOS design and update copy to match Gutenberg [#23145]
* [*] Update the "Revisions" list design and fix an issue with the footer displaying incorrect "Date Created" for drafts [#23145]
* [***] Fix multiple post sync issues: [#21895], [#22037], [#8111], [#10168], [#17343], [#14221], [#12800], [#12073], [#14572], [#9319], [#21941], [#3070], [#3978], [#9449], [#13023], [#21472]
* [**] Fix [#4870], [#14798], an issue where the app sometimes overwrites the changes made on the remote. The app will now show a new "Conflict Resolution" screen if there is a conflict. It will also no longer try to auto-upload changes to an existing published post or publish a draft, eliminating multiple possible failure points.
* [**] Fix [#12121], [#13724], [#14251], [#18517], [#17086], [#15767], [#16514], [#13654] and other untracked issues with the "Publish Date" field in Post Settings. The app now has a new date picker that makes it easier to pick and remove the selected date. It also makes it clear if the blog is in a different time zones from your local timezone. The "Publish Date" field was also removed from the Post Settings screen for draft posts – the date needs to be selected right before publishing.
* [**] Add a new "Media Uploads" screen to the "Publishing Sheet" where you can see the status of the pending uploads. It also shows error messages for each individual upload (if any) and allows you to cancel the failing uploads.
* [*] Fix [#21940], [#13432], [#11435], issues where "Discard Changes" would sometimes delete the entire draft or appear when no changes were made
* [*] Fix [#12099] by removing the "Status" field from Post Settings that was leading to multiple unexpected and confusing scenarios. The app now manages the transitions between state the same way as Gutenberg, so it should feel more familiar to the users.
* [*] Fix [#10663], an issue with unclear error messages. The messages for "synchronous" operations will not appear as alerts with detailed information about the error. The error for drafts will also appear more clearly.
* [*] Update the "Autosave Available" dialog to work the same way as in Gutenberg and to better represent what this feature is – it can no longer be confused with a "Data Conflict" dialog (fixes [#13093])
* [*] Fix [#22107], [#19540], [#13632] by removing the "Draft Uploaded" snackbar
* [*] Fix editor state restoration in the Jetpack app
* [*] Update the support for pending posts to have clearer flows for both admins and contributors
* [*] Fix [#19886], an issue with a missing error message when selecting a page author that's not eligible to be a page author
* [*] Fix [#22969] an issue where Post List content occasionally stops updating
* [*] Fix [#3862] by adding a "Password Protected" badge in [#23154]
* [*] Fix [#21093], a rare crash in "View Stats for Posts" – [#23155]
* [*] Fix [#22247], a rare crash in Post List
* [*] Update the app to use `wp.createPost` and `wp.editPost` instead of the respective deprecated `metaWeblog.*` methods (closes [#1385])

24.8
-----
Expand Down
10 changes: 8 additions & 2 deletions WordPress/Classes/Models/AbstractPost+TitleForVisibility.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ extension AbstractPost {
static let publicLabel = NSLocalizedString("Public", comment: "Privacy setting for posts set to 'Public' (default). Should be the same as in core WP.")

/// A title describing the status. Ie.: "Public" or "Private" or "Password protected"
///
/// - warning: deprecated (kahu-offline-mode) (use ``PostVisibility``)
@objc var titleForVisibility: String {
guard FeatureFlag.syncPublishing.enabled else {
return _titleForVisibility
}
return PostVisibility(post: self).localizedTitle
}

/// - warning: deprecated (kahu-offline-mode) (use ``PostVisibility``)
@objc private var _titleForVisibility: String {
if password != nil {
return AbstractPost.passwordProtectedLabel
} else if status == .publishPrivate {
Expand Down
9 changes: 9 additions & 0 deletions WordPress/Classes/Models/AbstractPost.swift
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,15 @@ extension AbstractPost {
}
}

var localizedPostType: String {
switch self {
case is Page:
return NSLocalizedString("postType.page", value: "page", comment: "Localized post type: `Page`")
default:
return NSLocalizedString("postType.post", value: "post", comment: "Localized post type: `Post`")
}
}

// MARK: - Misc

/// Represent the supported properties used to sort posts.
Expand Down
8 changes: 4 additions & 4 deletions WordPress/Classes/Models/Notifications/Actions/Follow.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/// Encapsulates logic to follow a blog
final class Follow: DefaultNotificationActionCommand {
static let title = NSLocalizedString("Follow", comment: "Prompt to follow a blog.")
static let hint = NSLocalizedString("Follows the blog.", comment: "VoiceOver accessibility hint, informing the user the button can be used to follow a blog.")
static let selectedTitle = NSLocalizedString("Following", comment: "User is following the blog.")
static let selectedHint = NSLocalizedString("Unfollows the blog.", comment: "VoiceOver accessibility hint, informing the user the button can be used to unfollow a blog.")
static let title = NSLocalizedString("notifications.action.subscribe.title", value: "Subscribe", comment: "Prompt to subscribe to a blog.")
static let hint = NSLocalizedString("notifications.action.subscribe.hint", value: "Subscribe to the blog.", comment: "VoiceOver accessibility hint, informing the user the button can be used to subscribe to a blog.")
static let selectedTitle = NSLocalizedString("notifications.action.subscribe.selectedTitle", value: "Subscribed", comment: "User is subscribed to the blog.")
static let selectedHint = NSLocalizedString("notifications.action.subscribe.selectedHint", value: "Unsubscribe from the blog.", comment: "VoiceOver accessibility hint, informing the user the button can be used to unsubscribe from a blog.")

override var actionTitle: String {
return Follow.title
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,9 @@ open class NotificationSettings {
comment: "Setting: indicates if Comment Likes will be notified"),
postLiked: NSLocalizedString("Likes on my posts",
comment: "Setting: indicates if Replies to your comments will be notified"),
follower: NSLocalizedString("Site follows",
comment: "Setting: indicates if New Follows will be notified"),
follower: NSLocalizedString("notification.settings.description.subscriber",
value: "Site subscriptions",
comment: "Setting: indicates if New Subscriptions will be notified"),
achievement: NSLocalizedString("Site achievements",
comment: "Setting: indicates if Achievements will be notified"),
mention: NSLocalizedString("Username mentions",
Expand Down
15 changes: 0 additions & 15 deletions WordPress/Classes/Models/Role.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,3 @@ extension Role {
return context.firstObject(ofType: Role.self, matching: predicate)
}
}

extension Role {
@objc var color: UIColor {
switch slug {
case .some("super-admin"):
return WPStyleGuide.People.superAdminColor
case .some("administrator"):
return WPStyleGuide.People.adminColor
case .some("editor"):
return WPStyleGuide.People.editorColor
default:
return WPStyleGuide.People.otherRoleColor
}
}
}
25 changes: 0 additions & 25 deletions WordPress/Classes/Services/PeopleService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,31 +76,6 @@ struct PeopleService {
})
}

/// Loads a page of Email Followers associated to the current blog, starting at the specified offset.
///
/// - Parameters:
/// - offset: Number of records to skip.
/// - count: Number of records to retrieve. By default set to 20.
/// - success: Closure to be executed on success with the number of followers retrieved and a bool indicating if more are available.
/// - failure: Closure to be executed on failure.
///
func loadEmailFollowersPage(_ offset: Int = 0,
count: Int = 20,
success: @escaping ((_ retrieved: Int, _ shouldLoadMore: Bool) -> Void),
failure: ((Error) -> Void)? = nil) {
let page = (offset / count) + 1
remote.getEmailFollowers(siteID, page: page, max: count, success: { followers, hasMore in
self.coreDataStack.performAndSave({ context in
self.mergePeople(followers, in: context)
}, completion: {
success(followers.count, hasMore)
}, on: .main)
}, failure: { error in
DDLogError(String(describing: error))
failure?(error)
})
}

/// Loads a page of Viewers associated to the current blog, starting at the specified offset.
///
/// - Parameters:
Expand Down
36 changes: 26 additions & 10 deletions WordPress/Classes/Services/PostCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ class PostCoordinator: NSObject {
}
}

private func handleError(_ error: Error, for post: AbstractPost) {
func handleError(_ error: Error, for post: AbstractPost) {
guard let topViewController = UIApplication.shared.mainWindow?.topmostPresentedViewController else {
wpAssertionFailure("Failed to show an error alert")
return
Expand Down Expand Up @@ -332,6 +332,16 @@ class PostCoordinator: NSObject {
save(post)
}

/// Restores a trashed post by moving it to draft.
@MainActor
func restore(_ post: AbstractPost) async throws {
wpAssert(post.isOriginal())

var changes = RemotePostUpdateParameters()
changes.status = Post.Status.draft.rawValue
try await _update(post, changes: changes)
}

/// Sets the post state to "updating" and performs the given changes.
private func _performChanges(_ changes: RemotePostUpdateParameters, for post: AbstractPost) {
Task { @MainActor in
Expand Down Expand Up @@ -442,6 +452,9 @@ class PostCoordinator: NSObject {
retryDelay = min(32, retryDelay * 1.5)
return retryDelay
}
func setLongerDelay() {
retryDelay = max(retryDelay, 20)
}
var retryDelay: TimeInterval
weak var retryTimer: Timer?

Expand Down Expand Up @@ -499,10 +512,11 @@ class PostCoordinator: NSObject {
}

private func startSync(for post: AbstractPost) {
guard let revision = post.getLatestRevisionNeedingSync() else {
let worker = getWorker(for: post)
if let worker = workers[post.objectID], worker.error != nil {
worker.error = nil
postDidUpdateNotification(for: post)
}
guard let revision = post.getLatestRevisionNeedingSync() else {
return DDLogInfo("sync: \(post.objectID.shortDescription) is already up to date")
}
startSync(for: post, revision: revision)
Expand Down Expand Up @@ -600,14 +614,16 @@ class PostCoordinator: NSObject {
worker.error = error
postDidUpdateNotification(for: operation.post)

if !PostCoordinator.isTerminalError(error) {
let delay = worker.nextRetryDelay
worker.retryTimer = Timer.scheduledTimer(withTimeInterval: delay, repeats: false) { [weak self, weak worker] _ in
guard let self, let worker else { return }
self.didRetryTimerFire(for: worker)
}
worker.log("scheduled retry with delay: \(delay)s.")
if PostCoordinator.isTerminalError(error) {
worker.setLongerDelay()
}

let delay = worker.nextRetryDelay
worker.retryTimer = Timer.scheduledTimer(withTimeInterval: delay, repeats: false) { [weak self, weak worker] _ in
guard let self, let worker else { return }
self.didRetryTimerFire(for: worker)
}
worker.log("scheduled retry with delay: \(delay)s.")

if let error = error as? PostRepository.PostSaveError, case .deleted = error {
operation.log("post was permanently deleted")
Expand Down
16 changes: 16 additions & 0 deletions WordPress/Classes/Utility/Analytics/WPAnalyticsEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import Foundation
case editorPostSlugChanged
case editorPostExcerptChanged
case editorPostSiteChanged
case editorPostLegacyMoreMenuShown

// Resolve post version conflict
case resolveConflictScreenShown
Expand Down Expand Up @@ -594,6 +595,11 @@ import Foundation
case readingPreferencesSaved
case readingPreferencesClosed

// Stats Subscribers
case statsSubscribersViewMoreTapped
case statsEmailsViewMoreTapped
case statsSubscribersChartTapped

/// A String that represents the event
var value: String {
switch self {
Expand Down Expand Up @@ -661,6 +667,8 @@ import Foundation
return "editor_post_excerpt_changed"
case .editorPostSiteChanged:
return "editor_post_site_changed"
case .editorPostLegacyMoreMenuShown:
return "editor_post_legacy_more_menu_shown"
case .resolveConflictScreenShown:
return "resolve_conflict_screen_shown"
case .resolveConflictSaveTapped:
Expand Down Expand Up @@ -1615,6 +1623,14 @@ import Foundation
case .readingPreferencesClosed:
return "reader_reading_preferences_closed"

// Stats Subscribers
case .statsSubscribersViewMoreTapped:
return "stats_subscribers_view_more_tapped"
case .statsEmailsViewMoreTapped:
return "stats_emails_view_more_tapped"
case .statsSubscribersChartTapped:
return "stats_subscribers_chart_tapped"

} // END OF SWITCH
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/// A flow layout that properly invalidates the layout when the collection view's bounds changed,
/// (e.g., orientation changes).
///
/// This method ensures that we work with the latest/correct bounds after the size change, and potentially
/// avoids race conditions where we might get incorrect bounds while the view is still in transition.
///
/// See: https://developer.apple.com/documentation/uikit/uicollectionviewlayout/1617781-shouldinvalidatelayout
class AdaptiveCollectionViewFlowLayout: UICollectionViewFlowLayout {

override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
// NOTE: Apparently we need to *manually* invalidate the layout because `invalidateLayout()`
// is NOT called after this method returns true.
if let collectionView, collectionView.bounds.size != newBounds.size {
invalidateLayout()
}
return super.shouldInvalidateLayout(forBoundsChange: newBounds)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,6 @@ class AztecPostViewController: UIViewController, PostEditor {
navigationController?.navigationBar.isTranslucent = false
navigationController?.navigationBar.accessibilityIdentifier = "Azctec Editor Navigation Bar"
navigationItem.leftBarButtonItems = navigationBarManager.leftBarButtonItems
navigationItem.rightBarButtonItems = navigationBarManager.rightBarButtonItemsAztec
navigationItem.titleView = navigationBarManager.blogTitleViewLabel
}

Expand Down Expand Up @@ -823,6 +822,7 @@ class AztecPostViewController: UIViewController, PostEditor {
reloadEditorContents()
reloadPublishButton()
refreshTitleViewForMediaUploadIfNeeded()
navigationItem.rightBarButtonItems = post.status == .trash ? [] : navigationBarManager.rightBarButtonItemsAztec
}

func refreshTitleViewForMediaUploadIfNeeded() {
Expand Down Expand Up @@ -1197,7 +1197,7 @@ private extension AztecPostViewController {

if (post.revisions ?? []).count > 0 {
alert.addDefaultActionWithTitle(MoreSheetAlert.historyTitle) { [unowned self] _ in
self.displayHistory()
self.displayRevisionsList()
}
}

Expand Down

0 comments on commit ee2d565

Please sign in to comment.