Skip to content
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

Merge UserDataProvider and UserManagementActionDispatcher into one type #23792

Open
wants to merge 6 commits into
base: fix/self-hosted-site-user-delete
Choose a base branch
from

Conversation

crazytonyli
Copy link
Contributor

@crazytonyli crazytonyli commented Nov 10, 2024

Note

This PR is built on top of #23791.

Uses one UserService for all user management actions.

The user list is cached in the type, which fixes the issue where deleted users show in the user list.

I will add unit tests to the service and view model types in a separate PR. I have added some unit tests for UserService, but not sure what's the best practice/easiest way to test ObservableObject (the view models).

Regression Notes

  1. Potential unintended areas of impact

  2. What I did to test those areas of impact (or what existing automated tests I relied on)

  3. What automated tests I added (or what prevented me from doing so)

PR submission checklist:

  • I have completed the Regression Notes.
  • I have considered adding unit tests for my changes.
  • I have considered adding accessibility improvements for my changes.
  • I have considered if this change warrants user-facing release notes and have added them to RELEASE-NOTES.txt if necessary.

Testing checklist:

  • WordPress.com sites and self-hosted Jetpack sites.
  • Portrait and landscape orientations.
  • Light and dark modes.
  • Fonts: Larger, smaller and bold text.
  • High contrast.
  • VoiceOver.
  • Languages with large words or with letters/accents not frequently used in English.
  • Right-to-left languages. (Even if translation isn’t complete, formatting should still respect the right-to-left layout)
  • iPhone and iPad.
  • Multi-tasking: Split view and Slide over. (iPad)

@crazytonyli crazytonyli added this to the 25.6 milestone Nov 10, 2024
@dangermattic
Copy link
Collaborator

dangermattic commented Nov 10, 2024

2 Warnings
⚠️ View files have been modified, but no screenshot or video is included in the pull request. Consider adding some for clarity.
⚠️ This PR is larger than 500 lines of changes. Please consider splitting it into smaller PRs for easier and faster reviews.

Generated by 🚫 Danger

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Nov 11, 2024

WordPress Alpha📲 You can test the changes from this Pull Request in WordPress Alpha by scanning the QR code below to install the corresponding build.
App NameWordPress Alpha WordPress Alpha
ConfigurationRelease-Alpha
Build Numberpr23792-b13e441
Version25.4.2
Bundle IDorg.wordpress.alpha
Commitb13e441
App Center BuildWPiOS - One-Offs #11033
Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.

@wpmobilebot
Copy link
Contributor

wpmobilebot commented Nov 11, 2024

Jetpack Alpha📲 You can test the changes from this Pull Request in Jetpack Alpha by scanning the QR code below to install the corresponding build.
App NameJetpack Alpha Jetpack Alpha
ConfigurationRelease-Alpha
Build Numberpr23792-b13e441
Version25.4.2
Bundle IDcom.jetpack.alpha
Commitb13e441
App Center Buildjetpack-installable-builds #10073
Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.


// Remove the deleted user from the cached users list.
if result.deleted {
await MainActor.run {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit) This should be declarative. If fetched and usersSubject can only be used form the main thread, perhaps this entire class need to by isolated on the main actor.

final actor UserCache {
var users: [DisplayUser] = []
private func finishFetchingUsers(_ result: Result<[DisplayUser], Error>) {
fetchUserslock.lock()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the other comment – perhaps it would be clearer to simply synchronize this entire class on the main actor. It can still perform expensive work in the background, but I think it's totally fine if the state is syncronized on main since it's going to be called from the UI anyway.


public protocol UserDataProvider {
public protocol UserServiceProtocol {
var users: AnyPublisher<Result<[DisplayUser], Error>, Never> { get }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This results in a pretty awkward code on the caller side. I'd suggest modeling it as:

var users: [DisplayUser] { get }
func fetchUsers() async throws -> [DisplayUser]

// If you also need `users` to be observable:
var usersPublisher: AnyPublisher<[DisplayUser], Never> { get }

I wish Swift allowed using property wrappers like @Published in protocol 😞

If you want to make sure that fetchUsers doesn't perform more than one operation, I'd suggest taking advantage of the Task:

private var refreshTask: Task<[DisplayUser], Error>?

    func refresh() async throws {
        if let task = refreshTask {
            try await task.value
        }
        let task = Task {
            try await _refresh()
        }
        refreshTask = task
        return await task.value
    }

    private func _refresh() async {
        error = nil
        isRefreshing = true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants