Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
c70bc5a
Implement users endpoints in Swift
crazytonyli Apr 11, 2024
d6ca1dc
Add end-to-end tests to the Swift package
crazytonyli Apr 11, 2024
6edd0a2
Fix Swift code format
crazytonyli Apr 11, 2024
148fc3a
Do not run E2E tests on macOS in CI jobs
crazytonyli Apr 11, 2024
86ef464
Adapt rust library changes
crazytonyli Apr 16, 2024
5b858fb
Add APIs to read view/edit/embed context
crazytonyli Apr 11, 2024
d3097a0
Fix incorrect context
crazytonyli Apr 11, 2024
01ba5c8
Extract protocol to share get and list functions
crazytonyli Apr 17, 2024
3b9431d
build request and parse response for posts
crazytonyli Apr 17, 2024
679348b
PostObject was renamed to SparsePost
crazytonyli Apr 17, 2024
92af228
SparsePost conforms to Contextual
crazytonyli Apr 17, 2024
95225a7
Add end-to-end tests for Posts
crazytonyli Apr 17, 2024
2341e01
Check CI env var instead of BUILDKITE
crazytonyli Apr 17, 2024
0e3e28c
Disable Swift end-to-end tests on Linux
crazytonyli Apr 17, 2024
877e1e8
Rename context type names
crazytonyli Apr 17, 2024
6d753a5
Add `WPContextualField` declarations
crazytonyli Apr 18, 2024
8374782
Create an Endpoints folder
crazytonyli Apr 18, 2024
f96f8fc
Share get current user function in all context namespaces
crazytonyli Apr 18, 2024
b935935
Extract update and create function to context namespaces
crazytonyli Apr 18, 2024
50d7704
Do not use host network for Swift tests on Linux
crazytonyli Apr 18, 2024
064b97f
Fix a copy-paste error
crazytonyli Apr 19, 2024
67dd782
Use u32 as PostId
crazytonyli Apr 19, 2024
9879289
Add delete function
crazytonyli Apr 19, 2024
ae7bf63
Add test for the update function
crazytonyli Apr 19, 2024
1771d5b
Merge branch 'trunk' into swift-package-users-contexts-shared-reading…
crazytonyli Apr 22, 2024
0655722
Fix an compiling issue on iOS
crazytonyli Apr 23, 2024
943360e
Export post types
crazytonyli Apr 23, 2024
fccfbea
Add params to list function
crazytonyli Apr 23, 2024
331bd99
Re-implement posts async sequence
crazytonyli Apr 23, 2024
ea8c86a
Remove an unused variable
crazytonyli Apr 23, 2024
a33954c
Refactor `PostsEndpoint` to be similar as `UsersEndpoint`
crazytonyli Apr 23, 2024
3432c8a
Merge branch 'trunk' into swift-package-users-contexts-shared-reading…
crazytonyli May 1, 2024
7211693
Merge branch 'trunk' into swift-package-users-contexts-shared-reading…
crazytonyli May 6, 2024
e0e66fb
Merge branch 'trunk' into swift-package-users-contexts-shared-reading…
crazytonyli May 21, 2024
6721b17
Remove posts from the library
crazytonyli May 21, 2024
f5aaca4
Change the Example app to fetching users instead of posts
crazytonyli May 22, 2024
c2c08db
Remove End2End tests from Swift package
crazytonyli May 22, 2024
a71c4e5
Remove unneeded step from CI
crazytonyli May 22, 2024
0f52a80
Further clean up Package.swift
crazytonyli May 22, 2024
6f0c3f1
Parsing delete responses
crazytonyli May 22, 2024
5c34e62
Update an unit test
crazytonyli May 22, 2024
ee477a7
Merge branch 'trunk' into swift-package-users-contexts-shared-reading…
crazytonyli May 22, 2024
02b3e35
Fix conflicts resolution errors
crazytonyli May 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions native/swift/Example/Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
2479BF852B621CB70014A01D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2479BF842B621CB70014A01D /* Assets.xcassets */; };
2479BF892B621CB70014A01D /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2479BF882B621CB70014A01D /* Preview Assets.xcassets */; };
2479BF912B621CCA0014A01D /* wordpress-api in Frameworks */ = {isa = PBXBuildFile; productRef = 2479BF902B621CCA0014A01D /* wordpress-api */; };
2479BF932B621E9B0014A01D /* PostListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2479BF922B621E9B0014A01D /* PostListViewModel.swift */; };
2479BF932B621E9B0014A01D /* UserListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2479BF922B621E9B0014A01D /* UserListViewModel.swift */; };
24A3C32F2BA8F96F00162AD1 /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A3C32E2BA8F96F00162AD1 /* LoginView.swift */; };
24A3C3362BAA874C00162AD1 /* LoginManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A3C3352BAA874C00162AD1 /* LoginManager.swift */; };
/* End PBXBuildFile section */
Expand All @@ -23,7 +23,7 @@
2479BF822B621CB60014A01D /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
2479BF842B621CB70014A01D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
2479BF882B621CB70014A01D /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
2479BF922B621E9B0014A01D /* PostListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostListViewModel.swift; sourceTree = "<group>"; };
2479BF922B621E9B0014A01D /* UserListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserListViewModel.swift; sourceTree = "<group>"; };
24A3C32E2BA8F96F00162AD1 /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = "<group>"; };
24A3C3342BAA45B800162AD1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
24A3C3352BAA874C00162AD1 /* LoginManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginManager.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -66,7 +66,7 @@
2479BF822B621CB60014A01D /* ContentView.swift */,
2479BF842B621CB70014A01D /* Assets.xcassets */,
2479BF872B621CB70014A01D /* Preview Content */,
2479BF922B621E9B0014A01D /* PostListViewModel.swift */,
2479BF922B621E9B0014A01D /* UserListViewModel.swift */,
24A3C3352BAA874C00162AD1 /* LoginManager.swift */,
);
path = Example;
Expand Down Expand Up @@ -159,7 +159,7 @@
2479BF832B621CB60014A01D /* ContentView.swift in Sources */,
2479BF812B621CB60014A01D /* ExampleApp.swift in Sources */,
24A3C32F2BA8F96F00162AD1 /* LoginView.swift in Sources */,
2479BF932B621E9B0014A01D /* PostListViewModel.swift in Sources */,
2479BF932B621E9B0014A01D /* UserListViewModel.swift in Sources */,
24A3C3362BAA874C00162AD1 /* LoginManager.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
16 changes: 8 additions & 8 deletions native/swift/Example/Example/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,31 @@ import wordpress_api
struct ContentView: View {

@State
private var viewModel: PostListViewModel
private var viewModel: UserListViewModel

@EnvironmentObject
var loginManager: LoginManager

init(viewModel: PostListViewModel) {
init(viewModel: UserListViewModel) {
self.viewModel = viewModel
}

var body: some View {
Group {
if viewModel.posts.isEmpty {
if viewModel.users.isEmpty {
VStack {
ProgressView().progressViewStyle(.circular)
Text("Fetching Posts")
Text("Fetching users")
}
.padding()
} else {
List(viewModel.posts) { post in
Text(post.title?.raw ?? "")
List(viewModel.users) {
Text($0.name)
}
}
}
.onAppear(perform: viewModel.startFetchingPosts)
// .onDisappear(perform: viewModel.stopFetchingPost)
.onAppear(perform: viewModel.startFetching)
// .onDisappear(perform: viewModel.stopFetching)
.alert(
isPresented: $viewModel.shouldPresentAlert,
error: viewModel.error,
Expand Down
2 changes: 1 addition & 1 deletion native/swift/Example/Example/ExampleApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct ExampleApp: App {
var body: some Scene {
WindowGroup {
if loginManager.isLoggedIn {
ContentView(viewModel: PostListViewModel(loginManager: self.loginManager))
ContentView(viewModel: UserListViewModel(loginManager: self.loginManager))
} else {
LoginView()
}
Expand Down
5 changes: 2 additions & 3 deletions native/swift/Example/Example/LoginView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,8 @@ struct LoginView: View {
appNameValue += " - (\(deviceName))"
}
#else
if let deviceName = UIDevice.current.name {
appNameValue += " - (\(deviceName))"
}
let deviceName = UIDevice.current.name
appNameValue += " - (\(deviceName))"
#endif

authURL.append(queryItems: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import Foundation
import SwiftUI
import wordpress_api

@Observable class PostListViewModel {
extension SparseUser.ViewContext: Identifiable {}

var posts: PostCollection
var fetchPostsTask: Task<Void, Never>?
@Observable class UserListViewModel {

var users: [SparseUser.ViewContext]
var fetchUsersTask: Task<Void, Never>?
var error: MyError?
var shouldPresentAlert = false

Expand All @@ -21,20 +23,18 @@ import wordpress_api
}
// swiftlint:enable force_try

init(loginManager: LoginManager, posts: PostCollection = PostCollection()) {
init(loginManager: LoginManager, users: [SparseUser.ViewContext] = []) {
self.loginManager = loginManager
self.posts = posts
self.users = users
}

func startFetchingPosts() {
func startFetching() {
self.error = nil
self.shouldPresentAlert = false

self.fetchPostsTask = Task { @MainActor in
self.fetchUsersTask = Task { @MainActor in
do {
for try await post in api.listPosts() {
posts.append(post)
}
users = try await api.users.forViewing.list()
} catch let error {
shouldPresentAlert = true
self.error = MyError(underlyingError: error)
Expand All @@ -43,8 +43,8 @@ import wordpress_api
}
}

func stopFetchingPost() {
self.fetchPostsTask?.cancel()
func stopFetching() {
self.fetchUsersTask?.cancel()
}
}

Expand All @@ -56,7 +56,7 @@ struct MyError: LocalizedError {
}

var errorDescription: String? {
"Unable to fetch posts"
"Unable to fetch users"
}

var failureReason: String? {
Expand Down
93 changes: 93 additions & 0 deletions native/swift/Sources/wordpress-api/Endpoints/Users.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import Foundation
import wordpress_api_wrapper

extension SparseUser: Contextual {
public typealias ID = UserId
public typealias ViewContext = UserWithViewContext
public typealias EditContext = UserWithEditContext
public typealias EmbedContext = UserWithEmbedContext

public static func retrieveRequest(id: UserId, using helper: WpApiHelperProtocol, context: WpContext) -> WpNetworkRequest {
helper.retrieveUserRequest(userId: id, context: context)
}

public static func listRequest(params: UserListParams?, using helper: WpApiHelperProtocol, context: WpContext) -> WpNetworkRequest {
helper.listUsersRequest(context: context, params: params)
}

public static func updateRequest(id: UserId, params: UserUpdateParams, using helper: any WpApiHelperProtocol) -> WpNetworkRequest {
helper.updateUserRequest(userId: id, params: params)
}

public static func createRequest(params: UserCreateParams, using helper: any WpApiHelperProtocol) -> WpNetworkRequest {
helper.createUserRequest(params: params)
}

public static func deleteRequest(id: ID, params: UserDeleteParams, using helper: WpApiHelperProtocol) -> WpNetworkRequest {
helper.deleteUserRequest(userId: id, params: params)
}

public static func parseResponse(_ response: WpNetworkResponse) throws -> UserWithViewContext {
try parseRetrieveUserResponseWithViewContext(response: response)
}

public static func parseResponse(_ response: WpNetworkResponse) throws -> UserWithEditContext {
try parseRetrieveUserResponseWithEditContext(response: response)
}

public static func parseResponse(_ response: WpNetworkResponse) throws -> UserWithEmbedContext {
try parseRetrieveUserResponseWithEmbedContext(response: response)
}

public static func parseResponse(_ response: WpNetworkResponse) throws -> [UserWithViewContext] {
try parseListUsersResponseWithViewContext(response: response)
}

public static func parseResponse(_ response: WpNetworkResponse) throws -> [UserWithEditContext] {
try parseListUsersResponseWithEditContext(response: response)
}

public static func parseResponse(_ response: WpNetworkResponse) throws -> [UserWithEmbedContext] {
try parseListUsersResponseWithEmbedContext(response: response)
}

public static func parseDeletionResponse(_ response: WpNetworkResponse) throws -> UserDeleteResponse {
try parseDeleteUserResponse(response: response)
}
}

extension WordPressAPI {
public var users: AnyNamespace<SparseUser> {
.init(api: self)
}
}

extension ContextualNamespace where T == SparseUser {
public func getCurrent() async throws -> R {
let request = self.api.helper.retrieveCurrentUserRequest(context: context)
let response = try await api.perform(request: request)
return try parseResponse(response)
}
}

// MARK: - Edit context

extension AnyNamespace where T == SparseUser {

public func delete(id: T.ID, reassignTo userID: T.ID) async throws -> T.DeleteResult {
try await self.delete(id: id, params: .init(reassign: userID))
}

public func deleteCurrent(reassignTo userID: T.ID) async throws -> T.DeleteResult {
let request = self.api.helper.deleteCurrentUserRequest(params: .init(reassign: userID))
let response = try await api.perform(request: request)
return try T.parseDeletionResponse(response)
}

public func updateCurrent(with params: UserUpdateParams) async throws -> T.EditContext {
let request = self.api.helper.updateCurrentUserRequest(params: params)
let response = try await self.api.perform(request: request)
return try parseRetrieveUserResponseWithEditContext(response: response)
}

}
15 changes: 15 additions & 0 deletions native/swift/Sources/wordpress-api/Exports.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Expose necessary Rust APIs as public API to the Swift package's consumers.
//
// We could export all of them using `@_exported import`, but that probably puts
// us in a position where we need to make major releases due to Rust code changes.

import wordpress_api_wrapper

public typealias WpApiError = wordpress_api_wrapper.WpApiError

// MARK: - Users

public typealias SparseUser = wordpress_api_wrapper.SparseUser
public typealias UserWithViewContext = wordpress_api_wrapper.UserWithViewContext
public typealias UserWithEditContext = wordpress_api_wrapper.UserWithEditContext
public typealias UserWithEmbedContext = wordpress_api_wrapper.UserWithEmbedContext
Loading