-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Notifications Refresh] Comment Moderation Content Header #23117
[Notifications Refresh] Comment Moderation Content Header #23117
Conversation
import UIKit | ||
import SwiftUI | ||
|
||
final class CommentContentView: UIView { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class is still WIP and will open another PR to finalize it.
📲 You can test the changes from this Pull Request in WordPress Alpha by scanning the QR code below to install the corresponding build.
|
📲 You can test the changes from this Pull Request in Jetpack Alpha by scanning the QR code below to install the corresponding build.
|
4624595
to
1bf164c
Compare
@@ -92,6 +92,7 @@ public struct ContentPreview: View { | |||
} | |||
} | |||
|
|||
#if DEBUG |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, this is redundant but won't cause any harm for sure. Compiler should be removing all the Previews and code that isn't used by the application on release version. So effectively, this should only be relevant to the developer and never to the AppStore version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved in 17738c5
WordPress/Classes/ViewRelated/Comments/Content/CommentContentHeaderView.swift
Show resolved
Hide resolved
let avatarURL: URL? | ||
let username: String | ||
let handleAndTimestamp: String | ||
let menu: [[MenuItem]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it isn't very obvious why menu is an array of arrays. Could we improve the data structure to make the use case more explicit? Or perhaps rename it to highlight the sections & rows structure?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved in c5ba22d
button(for: menuItem) | ||
} | ||
} | ||
if sectionIndex < menu.count - 1 && !menu[sectionIndex + 1].isEmpty { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we improve this by using a compactMap or filter logic to remove sections which have no items? Then we could always place the divider after the last index available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved in 57e22b4
} | ||
} label: { | ||
Image.DS.icon(named: .ellipsisHorizontal) | ||
.imageScale(.small) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This disables dynamic font sizing for the image. I am not sure if that's desired. I just wanted to highlight.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Button(action: action) { | ||
Label { | ||
Text(Strings.userInfo) | ||
} icon: { | ||
Image.DS.icon(named: .avatar) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can extract this into a function that accepts a text
and IconName
and reduce the duplication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved in dd9db3f
enum Item { | ||
case userInfo(() -> Void) | ||
case share(() -> Void) | ||
case editComment(() -> Void) | ||
case changeStatus((Status) -> Void) | ||
|
||
enum Status { | ||
case approve, trash, spam, pending | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't a ViewModel be more scalable here? The view can report to actions there. Instead of dealing with closures, we the VM could implement all the cases. For 1 or 2 events I think closures are fine but this to me feels a bit rigid in terms of scalability. Wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tried having only 1 closure to report menu events, something like this:
enum Item {
case userInfo
case share
case editComment
case changeStatus(Status)
enum Status {
case approve, trash, spam, pending
}
}
Then I wanted to have a closure with this signature that callers will implement
let onItemSelected: (Item) -> Void = { item in
...
}
The challenge arises with the .changeStatus(Status) case in our Item enum. When configuring the menu:
let menu = [.userInfo, .share, .editComment, .changeStatus(???)]
It's unclear how to specify a status for .changeStatus
statically, as it represents multiple potential actions (approve, trash, spam, pending).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you share a pseudo-code of how the VM approach would work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finally managed to test the previews and they look awesome! I like the sub-menu under the "Change status" section! ❤️
Looking forward to seeing this in practice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the improvement. It's definitely clearer to have a separate menu configuration class. Great job!
Just left one minor Swift-related question.
} | ||
|
||
private var shouldShowMenu: Bool { | ||
return [menu.userInfo, menu.share, menu.editComment, menu.changeStatus].reduce(false) { $0 || $1 } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious if this function checks whether one of the menu items is true
.
.reduce(false) { $0 || $1 }
part seems to be not entirely intuitive, and I'm wondering if .contains { _ in true }
would have a similar result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved in 7154ae5
7924ea1
into
feature/notifications_refresh_p2
Part of https://github.com/Automattic/wordpress-mobile/issues/31 and https://github.com/Automattic/wordpress-mobile/issues/38
This PR implements the header part of the comment content view. The rest of the view will addressed in a separate PR.
Test Instructions
WordPressAppDelegate.swift
file.didFinishLaunchingWithOptions
andwillFinishLaunchingWithOptions
methods.CommentContentHeaderView.swift
file.Regression Notes
Potential unintended areas of impact
N/A
What I did to test those areas of impact (or what existing automated tests I relied on)
N/A
What automated tests I added (or what prevented me from doing so)
N/A
PR submission checklist:
RELEASE-NOTES.txt
if necessary.Testing checklist: