From c17020e8e0770322535a954415ce31dde12bf5dd Mon Sep 17 00:00:00 2001 From: makinosp Date: Sat, 21 Sep 2024 15:57:23 +0900 Subject: [PATCH 01/32] feat: make AuthenticationModel conform to Sendable protocol --- Sources/VRCKit/Models/AuthenticationModel.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Sources/VRCKit/Models/AuthenticationModel.swift b/Sources/VRCKit/Models/AuthenticationModel.swift index 1ab2798..4f42da7 100644 --- a/Sources/VRCKit/Models/AuthenticationModel.swift +++ b/Sources/VRCKit/Models/AuthenticationModel.swift @@ -5,23 +5,23 @@ // Created by makinosp on 2024/02/12. // -public enum VerifyType: String, Codable { +public enum VerifyType: String, Codable, Sendable { case emailOtp, totp, otp } -struct ExistsResponse: Codable { +struct ExistsResponse: Codable, Sendable { let userExists: Bool } -struct VerifyRequest: Codable { +struct VerifyRequest: Codable, Sendable { let code: String } -struct VerifyResponse: Codable { +struct VerifyResponse: Codable, Sendable { let verified: Bool } -struct RequiresTwoFactorAuthResponse: Codable { +struct RequiresTwoFactorAuthResponse: Codable, Sendable { let requiresTwoFactorAuth: [VerifyType] var requires: VerifyType? { @@ -29,7 +29,7 @@ struct RequiresTwoFactorAuthResponse: Codable { } } -struct VerifyAuthTokenResponse: Codable { +struct VerifyAuthTokenResponse: Codable, Sendable { let ok: Bool let token: String } From bb593b2403ad810c15ded7453f1f8dcd83cb5278 Mon Sep 17 00:00:00 2001 From: makinosp Date: Sat, 21 Sep 2024 15:58:22 +0900 Subject: [PATCH 02/32] feat: make CommonModels conform to Sendable protocol --- Sources/VRCKit/Models/CommonModels.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/VRCKit/Models/CommonModels.swift b/Sources/VRCKit/Models/CommonModels.swift index a0bd0cf..ddfbd9c 100644 --- a/Sources/VRCKit/Models/CommonModels.swift +++ b/Sources/VRCKit/Models/CommonModels.swift @@ -5,15 +5,15 @@ // Created by makinosp on 2024/08/03. // -public struct ResponseMessage: Codable { +public struct ResponseMessage: Codable, Sendable { let message: String let statusCode: Int } -public struct SuccessResponse: Codable { +public struct SuccessResponse: Codable, Sendable { let success: ResponseMessage } -public struct ErrorResponse: Codable, Error { +public struct ErrorResponse: Codable, Sendable, Error { let error: ResponseMessage } From 4e36ce411d7d644c7750d29df1e3a32b2c559178 Mon Sep 17 00:00:00 2001 From: makinosp Date: Sat, 21 Sep 2024 16:02:42 +0900 Subject: [PATCH 03/32] feat: make SafeDecodingArray conform to Sendable protocol --- Sources/VRCKit/Utils/SafeDecodingArray.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/VRCKit/Utils/SafeDecodingArray.swift b/Sources/VRCKit/Utils/SafeDecodingArray.swift index a6b3114..9e44b42 100644 --- a/Sources/VRCKit/Utils/SafeDecodingArray.swift +++ b/Sources/VRCKit/Utils/SafeDecodingArray.swift @@ -7,7 +7,7 @@ import Foundation -public struct SafeDecodingArray { +public struct SafeDecodingArray: Sendable { public let elements: [Element] } From d8cca47ef0627fca2e013d008757b7c3c8e20fca Mon Sep 17 00:00:00 2001 From: makinosp Date: Sat, 21 Sep 2024 16:03:06 +0900 Subject: [PATCH 04/32] feat: make models for user to sendable protocol --- Sources/VRCKit/Models/EditableUserModel.swift | 2 +- Sources/VRCKit/Models/LanguageTagModel.swift | 2 +- Sources/VRCKit/Models/LocationModel.swift | 2 +- Sources/VRCKit/Models/SystemTagModel.swift | 2 +- Sources/VRCKit/Models/TrustRankModel.swift | 2 +- Sources/VRCKit/Models/UserDetailModel.swift | 2 +- Sources/VRCKit/Models/UserModel.swift | 8 ++++---- Sources/VRCKit/Models/UserNoteModel.swift | 4 ++-- Sources/VRCKit/Models/UserPlatformModel.swift | 2 +- Sources/VRCKit/Models/UserStatusModel.swift | 2 +- Sources/VRCKit/Models/UserTagModel.swift | 2 +- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Sources/VRCKit/Models/EditableUserModel.swift b/Sources/VRCKit/Models/EditableUserModel.swift index 952cdce..9523664 100644 --- a/Sources/VRCKit/Models/EditableUserModel.swift +++ b/Sources/VRCKit/Models/EditableUserModel.swift @@ -7,7 +7,7 @@ import Foundation -public struct EditableUserInfo: Codable, Hashable { +public struct EditableUserInfo: Codable, Sendable, Hashable { public var bio: String public var bioLinks: [URL] public var status: UserStatus diff --git a/Sources/VRCKit/Models/LanguageTagModel.swift b/Sources/VRCKit/Models/LanguageTagModel.swift index ba1ac10..3c56535 100644 --- a/Sources/VRCKit/Models/LanguageTagModel.swift +++ b/Sources/VRCKit/Models/LanguageTagModel.swift @@ -5,7 +5,7 @@ // Created by makinosp on 2024/08/22. // -public enum LanguageTag: String, Hashable, Codable, CaseIterable { +public enum LanguageTag: String, Hashable, Codable, Sendable, CaseIterable { case english = "language_eng" case korean = "language_kor" case russian = "language_rus" diff --git a/Sources/VRCKit/Models/LocationModel.swift b/Sources/VRCKit/Models/LocationModel.swift index 2433ee8..3b9f40b 100644 --- a/Sources/VRCKit/Models/LocationModel.swift +++ b/Sources/VRCKit/Models/LocationModel.swift @@ -9,7 +9,7 @@ public enum Location: Hashable { case id(String), `private`, offline, traveling } -extension Location: Codable { +extension Location: Codable, Sendable { public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let value = try container.decode(String.self) diff --git a/Sources/VRCKit/Models/SystemTagModel.swift b/Sources/VRCKit/Models/SystemTagModel.swift index 1456370..f23f1ed 100644 --- a/Sources/VRCKit/Models/SystemTagModel.swift +++ b/Sources/VRCKit/Models/SystemTagModel.swift @@ -7,7 +7,7 @@ import Foundation -public enum SystemTag: String, Hashable, Codable { +public enum SystemTag: String, Hashable, Codable, Sendable { case adminAvatarAccess = "admin_avatar_access" case adminCanGrantLicenses = "admin_can_grant_licenses" case adminCannyAccess = "admin_canny_access" diff --git a/Sources/VRCKit/Models/TrustRankModel.swift b/Sources/VRCKit/Models/TrustRankModel.swift index 50cefd6..fc05bba 100644 --- a/Sources/VRCKit/Models/TrustRankModel.swift +++ b/Sources/VRCKit/Models/TrustRankModel.swift @@ -5,7 +5,7 @@ // Created by makinosp on 2024/08/04. // -public enum TrustRank: Equatable { +public enum TrustRank: Equatable, Sendable { case trusted, known, user, newUser, visitor, unknown } diff --git a/Sources/VRCKit/Models/UserDetailModel.swift b/Sources/VRCKit/Models/UserDetailModel.swift index 97fdf27..0bac72f 100644 --- a/Sources/VRCKit/Models/UserDetailModel.swift +++ b/Sources/VRCKit/Models/UserDetailModel.swift @@ -7,7 +7,7 @@ import Foundation -public struct UserDetail: ProfileDetailRepresentable, LocationRepresentable { +public struct UserDetail: Sendable, ProfileDetailRepresentable, LocationRepresentable { public var bio: String? public var bioLinks: SafeDecodingArray public let avatarImageUrl: URL? diff --git a/Sources/VRCKit/Models/UserModel.swift b/Sources/VRCKit/Models/UserModel.swift index f4dc629..5cb2494 100644 --- a/Sources/VRCKit/Models/UserModel.swift +++ b/Sources/VRCKit/Models/UserModel.swift @@ -7,7 +7,7 @@ import Foundation -public struct User: ProfileDetailRepresentable { +public struct User: Sendable, ProfileDetailRepresentable { public let activeFriends: [String] public let allowAvatarCopying: Bool public let bio: String? @@ -39,12 +39,12 @@ public struct User: ProfileDetailRepresentable { public let userLanguageCode: String? public let presence: Presence - public struct DisplayName: Codable, Hashable { + public struct DisplayName: Codable, Sendable, Hashable { public let displayName: String public let updatedAt: Date } - public enum State: String, Codable { + public enum State: String, Codable, Sendable { /// User is online in VRChat case online /// User is online, but not in VRChat @@ -53,7 +53,7 @@ public struct User: ProfileDetailRepresentable { case offline } - public struct Presence: Codable, Hashable { + public struct Presence: Codable, Hashable, Sendable { public let groups: [String] public let id: String public let instance: String diff --git a/Sources/VRCKit/Models/UserNoteModel.swift b/Sources/VRCKit/Models/UserNoteModel.swift index 6da34ed..22d22fd 100644 --- a/Sources/VRCKit/Models/UserNoteModel.swift +++ b/Sources/VRCKit/Models/UserNoteModel.swift @@ -7,12 +7,12 @@ import Foundation -struct UserNoteRequest: Codable { +struct UserNoteRequest: Codable, Sendable { var targetUserId: String var note: String } -public struct UserNoteResponse: Codable, Identifiable { +public struct UserNoteResponse: Codable, Sendable, Identifiable { public let id: String public let targetUserId: String public let note: String diff --git a/Sources/VRCKit/Models/UserPlatformModel.swift b/Sources/VRCKit/Models/UserPlatformModel.swift index 3cde960..41db342 100644 --- a/Sources/VRCKit/Models/UserPlatformModel.swift +++ b/Sources/VRCKit/Models/UserPlatformModel.swift @@ -5,7 +5,7 @@ // Created by makinosp on 2024/09/02. // -public enum UserPlatform: String, Codable { +public enum UserPlatform: String, Codable, Sendable { case android, ios, nativemobile, standalonewindows, web case blank = "" } diff --git a/Sources/VRCKit/Models/UserStatusModel.swift b/Sources/VRCKit/Models/UserStatusModel.swift index 666650f..6a48b7b 100644 --- a/Sources/VRCKit/Models/UserStatusModel.swift +++ b/Sources/VRCKit/Models/UserStatusModel.swift @@ -5,7 +5,7 @@ // Created by makinosp on 2024/07/20. // -public enum UserStatus: String, Codable, CaseIterable { +public enum UserStatus: String, Codable, Sendable, CaseIterable { case joinMe = "join me" case active case askMe = "ask me" diff --git a/Sources/VRCKit/Models/UserTagModel.swift b/Sources/VRCKit/Models/UserTagModel.swift index 60214722..4928407 100644 --- a/Sources/VRCKit/Models/UserTagModel.swift +++ b/Sources/VRCKit/Models/UserTagModel.swift @@ -5,7 +5,7 @@ // Created by makinosp on 2024/08/04. // -public struct UserTags: Hashable { +public struct UserTags: Hashable, Sendable { public var systemTags: [SystemTag] public var languageTags: [LanguageTag] public var unknownTags: [String] From ae1781b73dede23108514ec8fe8dcfa0af0a66fc Mon Sep 17 00:00:00 2001 From: makinosp Date: Sat, 21 Sep 2024 16:06:28 +0900 Subject: [PATCH 05/32] feat: make OptionalISO8601Date model to Sendable protocol --- Sources/VRCKit/Utils/OptionalISO8601Date.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/VRCKit/Utils/OptionalISO8601Date.swift b/Sources/VRCKit/Utils/OptionalISO8601Date.swift index ee93369..d081590 100644 --- a/Sources/VRCKit/Utils/OptionalISO8601Date.swift +++ b/Sources/VRCKit/Utils/OptionalISO8601Date.swift @@ -7,7 +7,7 @@ import Foundation -public struct OptionalISO8601Date { +public struct OptionalISO8601Date: Sendable { private let date: Date? private let formatter = DateFormatter.iso8601Full } From 133827a01e1dae9cd7d56103f9193fed5ba9ed8f Mon Sep 17 00:00:00 2001 From: makinosp Date: Sat, 21 Sep 2024 16:07:01 +0900 Subject: [PATCH 06/32] feat: make FavoriteModel, FavoriteWorldModel, WorldModel to Sendable protocol --- Sources/VRCKit/Models/FavoriteModel.swift | 8 ++++---- Sources/VRCKit/Models/FavoriteWorldModel.swift | 2 +- Sources/VRCKit/Models/WorldModel.swift | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Sources/VRCKit/Models/FavoriteModel.swift b/Sources/VRCKit/Models/FavoriteModel.swift index d017204..1e2d866 100644 --- a/Sources/VRCKit/Models/FavoriteModel.swift +++ b/Sources/VRCKit/Models/FavoriteModel.swift @@ -5,18 +5,18 @@ // Created by makinosp on 2024/02/12. // -public enum FavoriteType: String, Codable { +public enum FavoriteType: String, Codable, Sendable { case world, avatar, friend } -public struct Favorite: Codable, Identifiable { +public struct Favorite: Codable, Sendable, Identifiable { public let id: String public let favoriteId: String public let tags: [String] public let type: FavoriteType } -public struct FavoriteDetail: Identifiable { +public struct FavoriteDetail: Sendable, Identifiable { public let id: String public let favorites: [Favorite] @@ -25,7 +25,7 @@ public struct FavoriteDetail: Identifiable { } } -public struct FavoriteGroup: Codable, Identifiable, Hashable { +public struct FavoriteGroup: Codable, Sendable, Identifiable, Hashable { public let id: String public let displayName: String public let name: String diff --git a/Sources/VRCKit/Models/FavoriteWorldModel.swift b/Sources/VRCKit/Models/FavoriteWorldModel.swift index 549b7bd..3b69449 100644 --- a/Sources/VRCKit/Models/FavoriteWorldModel.swift +++ b/Sources/VRCKit/Models/FavoriteWorldModel.swift @@ -9,7 +9,7 @@ import Foundation struct AnyCodable: Codable {} -public struct FavoriteWorldWrapper { +public struct FavoriteWorldWrapper: Sendable { public let worlds: [World] } diff --git a/Sources/VRCKit/Models/WorldModel.swift b/Sources/VRCKit/Models/WorldModel.swift index bd2fa32..602537d 100644 --- a/Sources/VRCKit/Models/WorldModel.swift +++ b/Sources/VRCKit/Models/WorldModel.swift @@ -7,7 +7,7 @@ import Foundation -public struct World: Codable, Identifiable, Hashable { +public struct World: Codable, Sendable, Identifiable, Hashable { public let id: String public let name: String public let description: String? @@ -33,7 +33,7 @@ public struct World: Codable, Identifiable, Hashable { public let favoriteGroup: String? public let version: Int? - public enum ReleaseStatus: String, Codable { + public enum ReleaseStatus: String, Codable, Sendable { case `public`, `private`, hidden, all } } From 77f23af784e87d273d5dfed8075a1cf8fd303ee0 Mon Sep 17 00:00:00 2001 From: makinosp Date: Sat, 21 Sep 2024 16:08:45 +0900 Subject: [PATCH 07/32] feat: make FriendModel to Sendable protocol --- Sources/VRCKit/Models/FriendModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/VRCKit/Models/FriendModel.swift b/Sources/VRCKit/Models/FriendModel.swift index e308153..bfac997 100644 --- a/Sources/VRCKit/Models/FriendModel.swift +++ b/Sources/VRCKit/Models/FriendModel.swift @@ -7,7 +7,7 @@ import Foundation -public struct Friend: ProfileElementRepresentable, LocationRepresentable { +public struct Friend: Sendable, ProfileElementRepresentable, LocationRepresentable { public let bio: String? public var bioLinks: SafeDecodingArray public let avatarImageUrl: URL? From 5cb2312b9eb4d8559a4dd97877db34a4574f9724 Mon Sep 17 00:00:00 2001 From: makinosp Date: Sat, 21 Sep 2024 16:08:58 +0900 Subject: [PATCH 08/32] feat: make ImageResolution model to Sendable protocol --- Sources/VRCKit/Models/ImageResolution.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/VRCKit/Models/ImageResolution.swift b/Sources/VRCKit/Models/ImageResolution.swift index bb5c181..d8a6c7c 100644 --- a/Sources/VRCKit/Models/ImageResolution.swift +++ b/Sources/VRCKit/Models/ImageResolution.swift @@ -5,7 +5,7 @@ // Created by makinosp on 2024/09/02. // -public enum ImageResolution: Int, CustomStringConvertible { +public enum ImageResolution: Int, Sendable, CustomStringConvertible { case x256 = 256 case x512 = 512 case x1024 = 1024 From 30d2158965e92622016e5356217f2125e3db7cd6 Mon Sep 17 00:00:00 2001 From: makinosp Date: Sat, 21 Sep 2024 16:09:10 +0900 Subject: [PATCH 09/32] feat: make InstanceModel to Sendable protocol --- Sources/VRCKit/Models/InstanceModel.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/VRCKit/Models/InstanceModel.swift b/Sources/VRCKit/Models/InstanceModel.swift index a5dba8c..644f736 100644 --- a/Sources/VRCKit/Models/InstanceModel.swift +++ b/Sources/VRCKit/Models/InstanceModel.swift @@ -7,7 +7,7 @@ import Foundation -public struct Instance: Identifiable, Hashable, Decodable { +public struct Instance: Sendable, Identifiable, Hashable, Decodable { public let active: Bool public let capacity: Int public let full: Bool @@ -26,21 +26,21 @@ public struct Instance: Identifiable, Hashable, Decodable { public let userCount: Int public let world: World - public struct Platforms: Hashable, Codable { + public struct Platforms: Sendable, Hashable, Codable { public let android: Int public let ios: Int public let standalonewindows: Int } - public enum GroupAccessType: String, Codable { + public enum GroupAccessType: String, Sendable, Codable { case `public`, plus } - public enum Region: String, Codable { + public enum Region: String, Sendable, Codable { case us, use, eu, jp, unknown } - public enum InstanceType: String, Codable { + public enum InstanceType: String, Sendable, Codable { case `public`, hidden, friends, `private`, group } } From bd97b9b9cc7c6b9fdf6495d992bcd9b47ef8461d Mon Sep 17 00:00:00 2001 From: makinosp Date: Sun, 22 Sep 2024 16:48:50 +0900 Subject: [PATCH 10/32] refact: refactoring --- Sources/VRCKit/Models/LocationModel.swift | 4 ++-- Sources/VRCKit/Protocols/AuthenticationServiceProtocol.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/VRCKit/Models/LocationModel.swift b/Sources/VRCKit/Models/LocationModel.swift index 3b9f40b..a89dcab 100644 --- a/Sources/VRCKit/Models/LocationModel.swift +++ b/Sources/VRCKit/Models/LocationModel.swift @@ -5,11 +5,11 @@ // Created by makinosp on 2024/09/08. // -public enum Location: Hashable { +public enum Location: Sendable, Hashable { case id(String), `private`, offline, traveling } -extension Location: Codable, Sendable { +extension Location: Codable { public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let value = try container.decode(String.self) diff --git a/Sources/VRCKit/Protocols/AuthenticationServiceProtocol.swift b/Sources/VRCKit/Protocols/AuthenticationServiceProtocol.swift index d3d5aa3..fc3a011 100644 --- a/Sources/VRCKit/Protocols/AuthenticationServiceProtocol.swift +++ b/Sources/VRCKit/Protocols/AuthenticationServiceProtocol.swift @@ -5,7 +5,7 @@ // Created by makinosp on 2024/07/14. // -public protocol UserOrRequires {} +public protocol UserOrRequires: Sendable {} extension User: UserOrRequires {} extension VerifyType: UserOrRequires {} From 4d820bf47102ceddd6562073871dd741bb9b86c1 Mon Sep 17 00:00:00 2001 From: makinosp Date: Sun, 22 Sep 2024 16:50:39 +0900 Subject: [PATCH 11/32] feat: update swift-tools-version to 6.0 --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 642b52a..0cf2d46 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.9 +// swift-tools-version: 6.0 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription From 65ea78991629b12859e5df1c40f408339659b7e8 Mon Sep 17 00:00:00 2001 From: makinosp Date: Sun, 22 Sep 2024 16:51:40 +0900 Subject: [PATCH 12/32] feat: replace APIClient, CookieManager class to actor --- Sources/VRCKit/APIClient.swift | 4 ++-- Sources/VRCKit/Services/AuthenticationService.swift | 2 +- Sources/VRCKit/Utils/CookieManager.swift | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/VRCKit/APIClient.swift b/Sources/VRCKit/APIClient.swift index c3b4f1e..124d72d 100644 --- a/Sources/VRCKit/APIClient.swift +++ b/Sources/VRCKit/APIClient.swift @@ -10,7 +10,7 @@ import Foundation import FoundationNetworking #endif -public final class APIClient { +public final actor APIClient { typealias HTTPResponse = (data: Data, response: HTTPURLResponse) private var username: String? @@ -90,7 +90,7 @@ public final class APIClient { } // Add cookies to the request headers. - request.allHTTPHeaderFields = cookieManager.httpField + request.allHTTPHeaderFields = await cookieManager.httpField // Add HTTP body and content type if body is provided. if let body = body { diff --git a/Sources/VRCKit/Services/AuthenticationService.swift b/Sources/VRCKit/Services/AuthenticationService.swift index 398b2db..8a82a21 100644 --- a/Sources/VRCKit/Services/AuthenticationService.swift +++ b/Sources/VRCKit/Services/AuthenticationService.swift @@ -59,6 +59,6 @@ public class AuthenticationService: APIService, AuthenticationServiceProtocol { /// Logout public func logout() async throws { _ = try await client.request(path: "logout", method: .put) - client.cookieManager.deleteCookies() + await client.cookieManager.deleteCookies() } } diff --git a/Sources/VRCKit/Utils/CookieManager.swift b/Sources/VRCKit/Utils/CookieManager.swift index e134886..3c828fb 100644 --- a/Sources/VRCKit/Utils/CookieManager.swift +++ b/Sources/VRCKit/Utils/CookieManager.swift @@ -10,7 +10,7 @@ import Foundation import FoundationNetworking #endif -public final class CookieManager { +public final actor CookieManager { private var domainURL: String? init(domainURL: String) { From bc7144c701434f0dc89de10c47dabc2888f8cb12 Mon Sep 17 00:00:00 2001 From: makinosp Date: Sun, 22 Sep 2024 17:05:14 +0900 Subject: [PATCH 13/32] feat: actor-isolated --- Sources/VRCKit/Models/FriendModel.swift | 2 +- .../PreviewServices/PreviewDataProvider.swift | 2 +- .../Protocols/FriendServiceProtocol.swift | 2 +- .../Services/AuthenticationService.swift | 12 +++++----- Sources/VRCKit/Services/FavoriteService.swift | 22 +++++++++++++------ Sources/VRCKit/Services/FriendService.swift | 11 +++++++--- Sources/VRCKit/Services/InstanceService.swift | 4 ++-- Sources/VRCKit/Services/UserNoteService.swift | 4 ++-- Sources/VRCKit/Services/UserService.swift | 4 ++-- Sources/VRCKit/Services/WorldService.swift | 4 ++-- Sources/VRCKit/Utils/Serializer.swift | 2 +- 11 files changed, 41 insertions(+), 28 deletions(-) diff --git a/Sources/VRCKit/Models/FriendModel.swift b/Sources/VRCKit/Models/FriendModel.swift index bfac997..1cfce4f 100644 --- a/Sources/VRCKit/Models/FriendModel.swift +++ b/Sources/VRCKit/Models/FriendModel.swift @@ -27,7 +27,7 @@ public struct Friend: Sendable, ProfileElementRepresentable, LocationRepresentab public let friendKey: String } -public struct FriendsLocation: LocationRepresentable { +public struct FriendsLocation: Sendable, LocationRepresentable { public let location: Location public let friends: [Friend] } diff --git a/Sources/VRCKit/PreviewServices/PreviewDataProvider.swift b/Sources/VRCKit/PreviewServices/PreviewDataProvider.swift index e6b29d5..91b69d0 100644 --- a/Sources/VRCKit/PreviewServices/PreviewDataProvider.swift +++ b/Sources/VRCKit/PreviewServices/PreviewDataProvider.swift @@ -7,7 +7,7 @@ import Foundation -public final class PreviewDataProvider { +public actor PreviewDataProvider { typealias FriendSet = (friend: Friend, userDetail: UserDetail) public static let shared = PreviewDataProvider() private let previewUserId = UUID() diff --git a/Sources/VRCKit/Protocols/FriendServiceProtocol.swift b/Sources/VRCKit/Protocols/FriendServiceProtocol.swift index 7fedd43..e6c9b2f 100644 --- a/Sources/VRCKit/Protocols/FriendServiceProtocol.swift +++ b/Sources/VRCKit/Protocols/FriendServiceProtocol.swift @@ -9,5 +9,5 @@ public protocol FriendServiceProtocol { func fetchFriends(offset: Int, n: Int, offline: Bool) async throws -> [Friend] func fetchFriends(count: Int, offline: Bool) async throws -> [Friend] func unfriend(id: String) async throws - func friendsGroupedByLocation(_ friends: [Friend]) -> [FriendsLocation] + func friendsGroupedByLocation(_ friends: [Friend]) async -> [FriendsLocation] } diff --git a/Sources/VRCKit/Services/AuthenticationService.swift b/Sources/VRCKit/Services/AuthenticationService.swift index 8a82a21..64d4868 100644 --- a/Sources/VRCKit/Services/AuthenticationService.swift +++ b/Sources/VRCKit/Services/AuthenticationService.swift @@ -15,7 +15,7 @@ public class AuthenticationService: APIService, AuthenticationServiceProtocol { let path = "\(authPath)/exists" let queryItems = [URLQueryItem(name: "username", value: userId.description)] let response = try await client.request(path: path, method: .get, queryItems: queryItems) - let result: ExistsResponse = try Serializer.shared.decode(response.data) + let result: ExistsResponse = try await Serializer.shared.decode(response.data) return result.userExists } @@ -24,10 +24,10 @@ public class AuthenticationService: APIService, AuthenticationServiceProtocol { let path = "\(authPath)/user" let response = try await client.request(path: path, method: .get, basic: true) do { - let user: User = try Serializer.shared.decode(response.data) + let user: User = try await Serializer.shared.decode(response.data) return user } catch _ as DecodingError { - let result: RequiresTwoFactorAuthResponse = try Serializer.shared.decode(response.data) + let result: RequiresTwoFactorAuthResponse = try await Serializer.shared.decode(response.data) guard let requires = result.requires else { throw VRCKitError.unexpected } @@ -39,20 +39,20 @@ public class AuthenticationService: APIService, AuthenticationServiceProtocol { public func verify2FA(verifyType: VerifyType, code: String) async throws -> Bool { guard code.count == 6 else { throw VRCKitError.invalidRequest("Code must be 6 digits") } let path = "\(authPath)/twofactorauth/\(verifyType.rawValue.lowercased())/verify" - let requestData = try Serializer.shared.encode(VerifyRequest(code: code)) + let requestData = try await Serializer.shared.encode(VerifyRequest(code: code)) let response = try await client.request( path: path, method: .post, body: requestData ) - let result: VerifyResponse = try Serializer.shared.decode(response.data) + let result: VerifyResponse = try await Serializer.shared.decode(response.data) return result.verified } /// Verify Auth Token public func verifyAuthToken() async throws -> Bool { let response = try await client.request(path: authPath, method: .get) - let result: VerifyAuthTokenResponse = try Serializer.shared.decode(response.data) + let result: VerifyAuthTokenResponse = try await Serializer.shared.decode(response.data) return result.ok } diff --git a/Sources/VRCKit/Services/FavoriteService.swift b/Sources/VRCKit/Services/FavoriteService.swift index 6016785..0a68749 100644 --- a/Sources/VRCKit/Services/FavoriteService.swift +++ b/Sources/VRCKit/Services/FavoriteService.swift @@ -7,16 +7,21 @@ import Foundation -public class FavoriteService: APIService, FavoriteServiceProtocol { +public final actor FavoriteService: FavoriteServiceProtocol { + let client: APIClient private let path = "favorites" + public init(client: APIClient) { + self.client = client + } + /// Asynchronously retrieves a list of favorite groups from the server. /// - Returns: An array of `FavoriteGroup` objects. /// - Throws: An error if the network request or decoding of the response fails. public func listFavoriteGroups() async throws -> [FavoriteGroup] { let path = "favorite/groups" let response = try await client.request(path: path, method: .get) - return try Serializer.shared.decode(response.data) + return try await Serializer.shared.decode(response.data) } public func listFavorites( @@ -32,7 +37,7 @@ public class FavoriteService: APIService, FavoriteServiceProtocol { queryItems.append(URLQueryItem(name: "tag", value: tag.description)) } let response = try await client.request(path: path, method: .get, queryItems: queryItems) - return try Serializer.shared.decode(response.data) + return try await Serializer.shared.decode(response.data) } /// Fetch a list of favorite IDs for each favorite group @@ -42,7 +47,10 @@ public class FavoriteService: APIService, FavoriteServiceProtocol { var results: [FavoriteDetail] = [] try await withThrowingTaskGroup(of: FavoriteDetail.self) { taskGroup in for favoriteGroup in favoriteGroups.filter({ $0.type == .friend }) { - taskGroup.addTask { + taskGroup.addTask { [weak self] in + guard let self = self else { + throw VRCKitError.unexpected + } let favorites = try await self.listFavorites( type: .friend, tag: favoriteGroup.name @@ -62,17 +70,17 @@ public class FavoriteService: APIService, FavoriteServiceProtocol { favoriteId: String, tag: String ) async throws -> Favorite { - let requestData = try Serializer.shared.encode( + let requestData = try await Serializer.shared.encode( RequestToAddFavorite(type: type, favoriteId: favoriteId, tags: [tag]) ) let response = try await client.request(path: path, method: .post, body: requestData) - return try Serializer.shared.decode(response.data) + return try await Serializer.shared.decode(response.data) } public func removeFavorite( favoriteId: String ) async throws -> SuccessResponse { let response = try await client.request(path: path, method: .delete) - return try Serializer.shared.decode(response.data) + return try await Serializer.shared.decode(response.data) } } diff --git a/Sources/VRCKit/Services/FriendService.swift b/Sources/VRCKit/Services/FriendService.swift index 1a6452e..332a488 100644 --- a/Sources/VRCKit/Services/FriendService.swift +++ b/Sources/VRCKit/Services/FriendService.swift @@ -7,9 +7,14 @@ import Foundation -public class FriendService: APIService, FriendServiceProtocol { +public final actor FriendService: FriendServiceProtocol { + let client: APIClient private let path = "auth/user/friends" + public init(client: APIClient) { + self.client = client + } + /// List information about friends. public func fetchFriends(offset: Int, n: Int = 60, offline: Bool) async throws -> [Friend] { let queryItems = [ @@ -18,7 +23,7 @@ public class FriendService: APIService, FriendServiceProtocol { URLQueryItem(name: "offline", value: offline.description) ] let response = try await client.request(path: path, method: .get, queryItems: queryItems) - return try Serializer.shared.decode(response.data) + return try await Serializer.shared.decode(response.data) } /// A helper function that splits a large API request tasks to fetch friend data concurrently, @@ -53,7 +58,7 @@ public class FriendService: APIService, FriendServiceProtocol { _ = try await client.request(path: "\(path)/\(id)", method: .delete) } - public func friendsGroupedByLocation(_ friends: [Friend]) -> [FriendsLocation] { + public func friendsGroupedByLocation(_ friends: [Friend]) async -> [FriendsLocation] { Dictionary(grouping: friends, by: \.location) .sorted { $0.value.count > $1.value.count } .map { dictionary in diff --git a/Sources/VRCKit/Services/InstanceService.swift b/Sources/VRCKit/Services/InstanceService.swift index 5ad0db2..433ca70 100644 --- a/Sources/VRCKit/Services/InstanceService.swift +++ b/Sources/VRCKit/Services/InstanceService.swift @@ -19,7 +19,7 @@ public class InstanceService: APIService, InstanceServiceProtocol { path: "\(path)/\(worldId):\(instanceId)", method: .get ) - return try Serializer.shared.decode(response.data) + return try await Serializer.shared.decode(response.data) } /// Fetches an instance using the specified location string. @@ -28,6 +28,6 @@ public class InstanceService: APIService, InstanceServiceProtocol { /// - Throws: An error if the request fails or the data cannot be decoded. public func fetchInstance(location: String) async throws -> Instance { let response = try await client.request(path: "\(path)/\(location)", method: .get) - return try Serializer.shared.decode(response.data) + return try await Serializer.shared.decode(response.data) } } diff --git a/Sources/VRCKit/Services/UserNoteService.swift b/Sources/VRCKit/Services/UserNoteService.swift index 6f722a8..2e36db8 100644 --- a/Sources/VRCKit/Services/UserNoteService.swift +++ b/Sources/VRCKit/Services/UserNoteService.swift @@ -16,7 +16,7 @@ public class UserNoteService: APIService, UserNoteServiceProtocol { let response = try await request( userNote: UserNoteRequest(targetUserId: targetUserId, note: note) ) - return try Serializer.shared.decode(response.data) + return try await Serializer.shared.decode(response.data) } public func clearUserNote(targetUserId: String) async throws { @@ -24,7 +24,7 @@ public class UserNoteService: APIService, UserNoteServiceProtocol { } private func request(userNote: UserNoteRequest) async throws -> APIClient.HTTPResponse { - let requestData = try Serializer.shared.encode(userNote) + let requestData = try await Serializer.shared.encode(userNote) return try await client.request(path: path, method: .post, body: requestData) } } diff --git a/Sources/VRCKit/Services/UserService.swift b/Sources/VRCKit/Services/UserService.swift index c418efb..c0405d9 100644 --- a/Sources/VRCKit/Services/UserService.swift +++ b/Sources/VRCKit/Services/UserService.swift @@ -11,12 +11,12 @@ public class UserService: APIService, UserServiceProtocol { /// Fetch a user public func fetchUser(userId: String) async throws -> UserDetail { let response = try await client.request(path: "\(path)/\(userId)", method: .get) - return try Serializer.shared.decode(response.data) + return try await Serializer.shared.decode(response.data) } /// Update user public func updateUser(id: String, editedInfo: EditableUserInfo) async throws { - let requestData = try Serializer.shared.encode(editedInfo) + let requestData = try await Serializer.shared.encode(editedInfo) _ = try await client.request( path: "\(path)/\(id)", method: .put, diff --git a/Sources/VRCKit/Services/WorldService.swift b/Sources/VRCKit/Services/WorldService.swift index 9a93c90..9f1e202 100644 --- a/Sources/VRCKit/Services/WorldService.swift +++ b/Sources/VRCKit/Services/WorldService.swift @@ -10,12 +10,12 @@ public class WorldService: APIService, WorldServiceProtocol { public func fetchWorld(worldId: String) async throws -> World { let response = try await client.request(path: "\(path)/\(worldId)", method: .get) - return try Serializer.shared.decode(response.data) + return try await Serializer.shared.decode(response.data) } public func fetchFavoritedWorlds() async throws -> [World] { let response = try await client.request(path: "\(path)/favorites", method: .get) - let favoriteWorldWrapper: FavoriteWorldWrapper = try Serializer.shared.decode(response.data) + let favoriteWorldWrapper: FavoriteWorldWrapper = try await Serializer.shared.decode(response.data) return favoriteWorldWrapper.worlds } } diff --git a/Sources/VRCKit/Utils/Serializer.swift b/Sources/VRCKit/Utils/Serializer.swift index 9ae5a83..2cf2228 100644 --- a/Sources/VRCKit/Utils/Serializer.swift +++ b/Sources/VRCKit/Utils/Serializer.swift @@ -7,7 +7,7 @@ import Foundation -final class Serializer { +final actor Serializer { static let shared = Serializer() private var decoder = JSONDecoder() private var encoder = JSONEncoder() From 98cee377fe5e3d24cc525215f5cbf9c8167244ff Mon Sep 17 00:00:00 2001 From: makinosp Date: Sun, 22 Sep 2024 22:16:33 +0900 Subject: [PATCH 14/32] feat: replace APIService abstract class to protocol --- Sources/VRCKit/Protocols/APIService.swift | 11 +++++++++++ Sources/VRCKit/Services/APIService.swift | 14 -------------- .../VRCKit/Services/AuthenticationService.swift | 7 ++++++- Sources/VRCKit/Services/FavoriteService.swift | 2 +- Sources/VRCKit/Services/FriendService.swift | 2 +- Sources/VRCKit/Services/InstanceService.swift | 9 +++++++-- Sources/VRCKit/Services/UserNoteService.swift | 9 +++++++-- Sources/VRCKit/Services/UserService.swift | 9 +++++++-- Sources/VRCKit/Services/WorldService.swift | 9 +++++++-- 9 files changed, 47 insertions(+), 25 deletions(-) create mode 100644 Sources/VRCKit/Protocols/APIService.swift delete mode 100644 Sources/VRCKit/Services/APIService.swift diff --git a/Sources/VRCKit/Protocols/APIService.swift b/Sources/VRCKit/Protocols/APIService.swift new file mode 100644 index 0000000..281b62f --- /dev/null +++ b/Sources/VRCKit/Protocols/APIService.swift @@ -0,0 +1,11 @@ +// +// APIService.swift +// VRCKit +// +// Created by makinosp on 2024/07/14. +// + +protocol APIService { + var client: APIClient { get } + init(client: APIClient) +} diff --git a/Sources/VRCKit/Services/APIService.swift b/Sources/VRCKit/Services/APIService.swift deleted file mode 100644 index 3f982c3..0000000 --- a/Sources/VRCKit/Services/APIService.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// APIService.swift -// VRCKit -// -// Created by makinosp on 2024/07/14. -// - -public class APIService { - let client: APIClient - - public init(client: APIClient) { - self.client = client - } -} diff --git a/Sources/VRCKit/Services/AuthenticationService.swift b/Sources/VRCKit/Services/AuthenticationService.swift index 64d4868..50628c3 100644 --- a/Sources/VRCKit/Services/AuthenticationService.swift +++ b/Sources/VRCKit/Services/AuthenticationService.swift @@ -7,9 +7,14 @@ import Foundation -public class AuthenticationService: APIService, AuthenticationServiceProtocol { +public final class AuthenticationService: APIService, AuthenticationServiceProtocol { + let client: APIClient private let authPath = "auth" + init(client: APIClient) { + self.client = client + } + /// Check User Exists public func isExists(userId: String) async throws -> Bool { let path = "\(authPath)/exists" diff --git a/Sources/VRCKit/Services/FavoriteService.swift b/Sources/VRCKit/Services/FavoriteService.swift index 0a68749..a669a80 100644 --- a/Sources/VRCKit/Services/FavoriteService.swift +++ b/Sources/VRCKit/Services/FavoriteService.swift @@ -7,7 +7,7 @@ import Foundation -public final actor FavoriteService: FavoriteServiceProtocol { +public final actor FavoriteService: APIService, FavoriteServiceProtocol { let client: APIClient private let path = "favorites" diff --git a/Sources/VRCKit/Services/FriendService.swift b/Sources/VRCKit/Services/FriendService.swift index 332a488..7f642bc 100644 --- a/Sources/VRCKit/Services/FriendService.swift +++ b/Sources/VRCKit/Services/FriendService.swift @@ -7,7 +7,7 @@ import Foundation -public final actor FriendService: FriendServiceProtocol { +public final actor FriendService: APIService, FriendServiceProtocol { let client: APIClient private let path = "auth/user/friends" diff --git a/Sources/VRCKit/Services/InstanceService.swift b/Sources/VRCKit/Services/InstanceService.swift index 433ca70..b38ebc6 100644 --- a/Sources/VRCKit/Services/InstanceService.swift +++ b/Sources/VRCKit/Services/InstanceService.swift @@ -5,8 +5,13 @@ // Created by makinosp on 2024/02/18. // -public class InstanceService: APIService, InstanceServiceProtocol { - let path = "instances" +public final class InstanceService: APIService, InstanceServiceProtocol { + let client: APIClient + private let path = "instances" + + init(client: APIClient) { + self.client = client + } /// Fetches an instance of a world using the specified world ID and instance ID. /// - Parameters: diff --git a/Sources/VRCKit/Services/UserNoteService.swift b/Sources/VRCKit/Services/UserNoteService.swift index 2e36db8..89f396b 100644 --- a/Sources/VRCKit/Services/UserNoteService.swift +++ b/Sources/VRCKit/Services/UserNoteService.swift @@ -5,8 +5,13 @@ // Created by makinosp on 2024/03/17. // -public class UserNoteService: APIService, UserNoteServiceProtocol { - let path = "userNotes" +public final class UserNoteService: APIService, UserNoteServiceProtocol { + let client: APIClient + private let path = "userNotes" + + init(client: APIClient) { + self.client = client + } /// Update user's note public func updateUserNote( diff --git a/Sources/VRCKit/Services/UserService.swift b/Sources/VRCKit/Services/UserService.swift index c0405d9..f2f1744 100644 --- a/Sources/VRCKit/Services/UserService.swift +++ b/Sources/VRCKit/Services/UserService.swift @@ -5,8 +5,13 @@ // Created by makinosp on 2024/02/18. // -public class UserService: APIService, UserServiceProtocol { - let path = "users" +public final class UserService: APIService, UserServiceProtocol { + let client: APIClient + private let path = "users" + + init(client: APIClient) { + self.client = client + } /// Fetch a user public func fetchUser(userId: String) async throws -> UserDetail { diff --git a/Sources/VRCKit/Services/WorldService.swift b/Sources/VRCKit/Services/WorldService.swift index 9f1e202..11ebe9a 100644 --- a/Sources/VRCKit/Services/WorldService.swift +++ b/Sources/VRCKit/Services/WorldService.swift @@ -5,8 +5,13 @@ // Created by kiripoipoi on 2024/09/07. // -public class WorldService: APIService, WorldServiceProtocol { - let path = "worlds" +public final class WorldService: APIService, WorldServiceProtocol { + let client: APIClient + private let path = "worlds" + + init(client: APIClient) { + self.client = client + } public func fetchWorld(worldId: String) async throws -> World { let response = try await client.request(path: "\(path)/\(worldId)", method: .get) From 5c7b00e40b871880d59928872443d15e028f8dbe Mon Sep 17 00:00:00 2001 From: makinosp Date: Sun, 22 Sep 2024 22:40:01 +0900 Subject: [PATCH 15/32] feat: replace AuthenticationService class to actor --- Sources/VRCKit/Services/AuthenticationService.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/VRCKit/Services/AuthenticationService.swift b/Sources/VRCKit/Services/AuthenticationService.swift index 50628c3..dbedf8d 100644 --- a/Sources/VRCKit/Services/AuthenticationService.swift +++ b/Sources/VRCKit/Services/AuthenticationService.swift @@ -7,7 +7,7 @@ import Foundation -public final class AuthenticationService: APIService, AuthenticationServiceProtocol { +public final actor AuthenticationService: APIService, AuthenticationServiceProtocol { let client: APIClient private let authPath = "auth" From 17747f479935f71cd5274b13faa4cb49463fd0b0 Mon Sep 17 00:00:00 2001 From: makinosp Date: Sun, 22 Sep 2024 22:43:48 +0900 Subject: [PATCH 16/32] feat: replace AuthenticationPreviewService class to actor --- .../AuthenticationPreviewService.swift | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Sources/VRCKit/PreviewServices/AuthenticationPreviewService.swift b/Sources/VRCKit/PreviewServices/AuthenticationPreviewService.swift index 0172a47..a4fde99 100644 --- a/Sources/VRCKit/PreviewServices/AuthenticationPreviewService.swift +++ b/Sources/VRCKit/PreviewServices/AuthenticationPreviewService.swift @@ -5,11 +5,22 @@ // Created by makinosp on 2024/07/06. // -public final class AuthenticationPreviewService: AuthenticationService { - override public func loginUserInfo() async throws -> UserOrRequires { - PreviewDataProvider.shared.previewUser +public final actor AuthenticationPreviewService: APIService, AuthenticationServiceProtocol { + let client: APIClient + + init(client: APIClient) { + self.client = client + } + + public func isExists(userId: String) async throws -> Bool { true } + + public func loginUserInfo() async throws -> UserOrRequires { + await PreviewDataProvider.shared.previewUser } - /// Logout - override public func logout() async throws {} + public func verify2FA(verifyType: VerifyType, code: String) async throws -> Bool { true } + + public func verifyAuthToken() async throws -> Bool { true } + + public func logout() async throws {} } From a29a41e81fa811a4940d5a09db4a1a6c094c7056 Mon Sep 17 00:00:00 2001 From: makinosp Date: Sun, 22 Sep 2024 22:49:22 +0900 Subject: [PATCH 17/32] feat: add location on web image url to constant --- Sources/VRCKit/Utils/Const.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Sources/VRCKit/Utils/Const.swift b/Sources/VRCKit/Utils/Const.swift index 107a0c2..0b9d6e5 100644 --- a/Sources/VRCKit/Utils/Const.swift +++ b/Sources/VRCKit/Utils/Const.swift @@ -14,11 +14,17 @@ public enum Const { static let assetsUrl = "https://assets.vrchat.com/www/images" static let offlineImagePath = "user-location-offline.png" static let privateWorldImagePath = "user-location-private-world.png" + static let locationOnWebImagePath = "user-location-on-web.png" public static var offlineImageUrl: URL? { URL(string: [Const.assetsUrl, Const.offlineImagePath].joined(separator: "/")) } + public static var privateWorldImageUrl: URL? { URL(string: [Const.assetsUrl, Const.privateWorldImagePath].joined(separator: "/")) } + + public static var locationOnWebImageUrl: URL? { + URL(string: [Const.assetsUrl, Const.locationOnWebImagePath].joined(separator: "/")) + } } From 4c31ae707d6da02df8f72ff733bf8d73a66b6dfb Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 08:14:49 +0900 Subject: [PATCH 18/32] feat replace FavoritePreviewService class to actor --- .../FavoritePreviewService.swift | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Sources/VRCKit/PreviewServices/FavoritePreviewService.swift b/Sources/VRCKit/PreviewServices/FavoritePreviewService.swift index 4c32b93..a7bb8df 100644 --- a/Sources/VRCKit/PreviewServices/FavoritePreviewService.swift +++ b/Sources/VRCKit/PreviewServices/FavoritePreviewService.swift @@ -7,8 +7,14 @@ import Foundation -public final class FavoritePreviewService: FavoriteService { - override public func listFavoriteGroups() async throws -> [FavoriteGroup] { +public final actor FavoritePreviewService: APIService, FavoriteServiceProtocol { + let client: APIClient + + init(client: APIClient) { + self.client = client + } + + public func listFavoriteGroups() async throws -> [FavoriteGroup] { [ FavoriteGroup( id: "fvgrp_\(UUID().uuidString)", @@ -21,14 +27,14 @@ public final class FavoritePreviewService: FavoriteService { ] } - override public func listFavorites( + public func listFavorites( n: Int = 60, type: FavoriteType, tag: String? = nil ) async throws -> [Favorite] { switch type { case .friend: - PreviewDataProvider.shared.onlineFriends.prefix(5).map { friend in + await PreviewDataProvider.shared.onlineFriends.prefix(5).map { friend in Favorite(id: UUID().uuidString, favoriteId: friend.id, tags: ["group_1"], type: .friend) } default: @@ -36,7 +42,11 @@ public final class FavoritePreviewService: FavoriteService { } } - override public func addFavorite( + public func fetchFavoriteGroupDetails(favoriteGroups: [FavoriteGroup]) async throws -> [FavoriteDetail] { + [] + } + + public func addFavorite( type: FavoriteType, favoriteId: String, tag: String @@ -44,7 +54,7 @@ public final class FavoritePreviewService: FavoriteService { Favorite(id: UUID().uuidString, favoriteId: favoriteId, tags: [tag], type: type) } - override public func removeFavorite( + public func removeFavorite( favoriteId: String ) async throws -> SuccessResponse { SuccessResponse(success: ResponseMessage(message: "OK", statusCode: 200)) From d105f7b88fb54f3aa53d337f7b070c61e275d0a4 Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 08:23:50 +0900 Subject: [PATCH 19/32] feat: replace FriendPreviewService class to actor --- .../FriendPreviewService.swift | 22 ++++++++++++++++--- .../PreviewServices/PreviewDataProvider.swift | 4 ++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Sources/VRCKit/PreviewServices/FriendPreviewService.swift b/Sources/VRCKit/PreviewServices/FriendPreviewService.swift index fdad247..86061eb 100644 --- a/Sources/VRCKit/PreviewServices/FriendPreviewService.swift +++ b/Sources/VRCKit/PreviewServices/FriendPreviewService.swift @@ -5,8 +5,24 @@ // Created by makinosp on 2024/07/07. // -public final class FriendPreviewService: FriendService { - override public func fetchFriends(offset: Int, n: Int, offline: Bool) async throws -> [Friend] { - offline ? PreviewDataProvider.shared.offlineFriends : PreviewDataProvider.shared.onlineFriends +public final actor FriendPreviewService: APIService, FriendServiceProtocol { + let client: APIClient + + init(client: APIClient) { + self.client = client + } + + public func fetchFriends(offset: Int, n: Int, offline: Bool) async throws -> [Friend] { + offline ? await PreviewDataProvider.shared.offlineFriends : await PreviewDataProvider.shared.onlineFriends + } + + public func fetchFriends(count: Int, offline: Bool) async throws -> [Friend] { + offline ? await PreviewDataProvider.shared.offlineFriends : await PreviewDataProvider.shared.onlineFriends + } + + public func unfriend(id: String) async throws {} + + public func friendsGroupedByLocation(_ friends: [Friend]) async -> [FriendsLocation] { + [] } } diff --git a/Sources/VRCKit/PreviewServices/PreviewDataProvider.swift b/Sources/VRCKit/PreviewServices/PreviewDataProvider.swift index 91b69d0..31489a5 100644 --- a/Sources/VRCKit/PreviewServices/PreviewDataProvider.swift +++ b/Sources/VRCKit/PreviewServices/PreviewDataProvider.swift @@ -141,6 +141,10 @@ public actor PreviewDataProvider { ) } + public static func generateFriend() -> Friend { + generateFriend(id: UUID(), location: .offline, status: .offline) + } + public static func generateUserDetail( id: UUID, location: Location, From 27656d63c0b06b01340e3d0904f15b1f846ce02a Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 08:30:31 +0900 Subject: [PATCH 20/32] refact: refine FriendServiceProtocol --- .../VRCKit/PreviewServices/FriendPreviewService.swift | 4 ---- Sources/VRCKit/Protocols/FriendServiceProtocol.swift | 11 ++++++++++- Sources/VRCKit/Services/FriendService.swift | 8 -------- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Sources/VRCKit/PreviewServices/FriendPreviewService.swift b/Sources/VRCKit/PreviewServices/FriendPreviewService.swift index 86061eb..d12c770 100644 --- a/Sources/VRCKit/PreviewServices/FriendPreviewService.swift +++ b/Sources/VRCKit/PreviewServices/FriendPreviewService.swift @@ -21,8 +21,4 @@ public final actor FriendPreviewService: APIService, FriendServiceProtocol { } public func unfriend(id: String) async throws {} - - public func friendsGroupedByLocation(_ friends: [Friend]) async -> [FriendsLocation] { - [] - } } diff --git a/Sources/VRCKit/Protocols/FriendServiceProtocol.swift b/Sources/VRCKit/Protocols/FriendServiceProtocol.swift index e6c9b2f..63093e0 100644 --- a/Sources/VRCKit/Protocols/FriendServiceProtocol.swift +++ b/Sources/VRCKit/Protocols/FriendServiceProtocol.swift @@ -9,5 +9,14 @@ public protocol FriendServiceProtocol { func fetchFriends(offset: Int, n: Int, offline: Bool) async throws -> [Friend] func fetchFriends(count: Int, offline: Bool) async throws -> [Friend] func unfriend(id: String) async throws - func friendsGroupedByLocation(_ friends: [Friend]) async -> [FriendsLocation] +} + +extension FriendServiceProtocol { + public func friendsGroupedByLocation(_ friends: [Friend]) async -> [FriendsLocation] { + Dictionary(grouping: friends, by: \.location) + .sorted { $0.value.count > $1.value.count } + .map { dictionary in + FriendsLocation(location: dictionary.key, friends: dictionary.value) + } + } } diff --git a/Sources/VRCKit/Services/FriendService.swift b/Sources/VRCKit/Services/FriendService.swift index 7f642bc..8be8c7d 100644 --- a/Sources/VRCKit/Services/FriendService.swift +++ b/Sources/VRCKit/Services/FriendService.swift @@ -57,12 +57,4 @@ public final actor FriendService: APIService, FriendServiceProtocol { public func unfriend(id: String) async throws { _ = try await client.request(path: "\(path)/\(id)", method: .delete) } - - public func friendsGroupedByLocation(_ friends: [Friend]) async -> [FriendsLocation] { - Dictionary(grouping: friends, by: \.location) - .sorted { $0.value.count > $1.value.count } - .map { dictionary in - FriendsLocation(location: dictionary.key, friends: dictionary.value) - } - } } From 8da308d4b53c48b6f1ee2c2de686f297b951f381 Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 09:18:28 +0900 Subject: [PATCH 21/32] feat: replace InstancePreviewService class to actor --- .../PreviewServices/InstancePreviewService.swift | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Sources/VRCKit/PreviewServices/InstancePreviewService.swift b/Sources/VRCKit/PreviewServices/InstancePreviewService.swift index eaa702a..cbaf525 100644 --- a/Sources/VRCKit/PreviewServices/InstancePreviewService.swift +++ b/Sources/VRCKit/PreviewServices/InstancePreviewService.swift @@ -5,12 +5,18 @@ // Created by makinosp on 2024/07/09. // -public final class InstancePreviewService: InstanceService { - override public func fetchInstance(location: String) async throws -> Instance { +public final actor InstancePreviewService: APIService, InstanceServiceProtocol { + let client: APIClient + + init(client: APIClient) { + self.client = client + } + + public func fetchInstance(location: String) async throws -> Instance { PreviewDataProvider.shared.instances[0] } - override public func fetchInstance( + public func fetchInstance( worldId: String, instanceId: String ) async throws -> Instance { From 459402bbc6a68ba8465b75adcb61e3e8e5a1e528 Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 10:44:14 +0900 Subject: [PATCH 22/32] feat: replace PreviewServices class to actor --- .../PreviewServices/UserNotePreviewService.swift | 12 ++++++++++-- .../VRCKit/PreviewServices/UserPreviewService.swift | 12 +++++++++--- .../VRCKit/PreviewServices/WorldPreviewService.swift | 12 +++++++++--- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/Sources/VRCKit/PreviewServices/UserNotePreviewService.swift b/Sources/VRCKit/PreviewServices/UserNotePreviewService.swift index 4a29298..efdae60 100644 --- a/Sources/VRCKit/PreviewServices/UserNotePreviewService.swift +++ b/Sources/VRCKit/PreviewServices/UserNotePreviewService.swift @@ -7,8 +7,14 @@ import Foundation -public final class UserNotePreviewService: UserNoteService { - override public func updateUserNote( +public final actor UserNotePreviewService: APIService, UserNoteServiceProtocol { + let client: APIClient + + init(client: APIClient) { + self.client = client + } + + public func updateUserNote( targetUserId: String, note: String ) async throws -> UserNoteResponse { @@ -20,4 +26,6 @@ public final class UserNotePreviewService: UserNoteService { createdAt: Date() ) } + + public func clearUserNote(targetUserId: String) async throws {} } diff --git a/Sources/VRCKit/PreviewServices/UserPreviewService.swift b/Sources/VRCKit/PreviewServices/UserPreviewService.swift index 4b54357..c16e634 100644 --- a/Sources/VRCKit/PreviewServices/UserPreviewService.swift +++ b/Sources/VRCKit/PreviewServices/UserPreviewService.swift @@ -5,10 +5,16 @@ // Created by makinosp on 2024/07/14. // -public final class UserPreviewService: UserService { - override public func fetchUser(userId: String) async throws -> UserDetail { +public final actor UserPreviewService: APIService, UserServiceProtocol { + let client: APIClient + + init(client: APIClient) { + self.client = client + } + + public func fetchUser(userId: String) async throws -> UserDetail { PreviewDataProvider.shared.userDetails.first { $0.id == userId }! } - override public func updateUser(id: String, editedInfo: EditableUserInfo) async throws {} + public func updateUser(id: String, editedInfo: EditableUserInfo) async throws {} } diff --git a/Sources/VRCKit/PreviewServices/WorldPreviewService.swift b/Sources/VRCKit/PreviewServices/WorldPreviewService.swift index 76d63c6..02e1db0 100644 --- a/Sources/VRCKit/PreviewServices/WorldPreviewService.swift +++ b/Sources/VRCKit/PreviewServices/WorldPreviewService.swift @@ -5,12 +5,18 @@ // Created by makinosp on 2024/09/09. // -public final class WorldPreviewService: WorldService { - override public func fetchWorld(worldId: String) async throws -> World { +public final actor WorldPreviewService: APIService, WorldServiceProtocol { + let client: APIClient + + init(client: APIClient) { + self.client = client + } + + public func fetchWorld(worldId: String) async throws -> World { PreviewDataProvider.generateWorld() } - override public func fetchFavoritedWorlds() async throws -> [World] { + public func fetchFavoritedWorlds() async throws -> [World] { (0..<10).map { _ in PreviewDataProvider.generateWorld() } } } From da64b90678344288ca4f31757eca8c80cae305ed Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 10:45:12 +0900 Subject: [PATCH 23/32] refact: lint --- Sources/VRCKit/Protocols/FriendServiceProtocol.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/VRCKit/Protocols/FriendServiceProtocol.swift b/Sources/VRCKit/Protocols/FriendServiceProtocol.swift index 63093e0..d0e5e09 100644 --- a/Sources/VRCKit/Protocols/FriendServiceProtocol.swift +++ b/Sources/VRCKit/Protocols/FriendServiceProtocol.swift @@ -11,8 +11,8 @@ public protocol FriendServiceProtocol { func unfriend(id: String) async throws } -extension FriendServiceProtocol { - public func friendsGroupedByLocation(_ friends: [Friend]) async -> [FriendsLocation] { +public extension FriendServiceProtocol { + func friendsGroupedByLocation(_ friends: [Friend]) async -> [FriendsLocation] { Dictionary(grouping: friends, by: \.location) .sorted { $0.value.count > $1.value.count } .map { dictionary in From d972cb460985ffef4a39109ef4b965f83927f033 Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 11:22:36 +0900 Subject: [PATCH 24/32] update: GitHub workflow --- .github/workflows/swift.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 82ea6be..522745c 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -1,6 +1,3 @@ -# This workflow will build a Swift project -# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift - name: Swift on: @@ -15,9 +12,19 @@ on: jobs: build: - runs-on: macos-latest + name: Swift ${{ matrix.swift }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + swift: ["6", "5.10"] steps: - uses: actions/checkout@v4 + - uses: SwiftyLab/setup-swift@v1 + with: + swift-version: ${{ matrix.swift }} + - name: Get Swift version + run: swift --version - name: Build run: swift build -v - name: Run tests From 5175005223d6a635077d8842977b9dfdce5dfe3c Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 11:31:35 +0900 Subject: [PATCH 25/32] feat: remove swift 5.10 from GitHub workflow --- .github/workflows/swift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 522745c..514d17d 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -17,7 +17,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] - swift: ["6", "5.10"] + swift: ["6"] steps: - uses: actions/checkout@v4 - uses: SwiftyLab/setup-swift@v1 From 8d33bbf2508b67fa56e696fddc645cb3adde9670 Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 12:02:00 +0900 Subject: [PATCH 26/32] fix: make requestWithFoundationNetworking thread-safe --- Sources/VRCKit/APIClient.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Sources/VRCKit/APIClient.swift b/Sources/VRCKit/APIClient.swift index 124d72d..0b3aa6c 100644 --- a/Sources/VRCKit/APIClient.swift +++ b/Sources/VRCKit/APIClient.swift @@ -107,21 +107,21 @@ public final actor APIClient { #if canImport(FoundationNetworking) private func requestWithFoundationNetworking(_ request: URLRequest) async throws -> HTTPResponse { - var requestError: Error? - let httpResponse = await withCheckedContinuation { continuation in + typealias Continuation = CheckedContinuation + return try await withCheckedThrowingContinuation { (continuation: Continuation) in URLSession.shared.dataTask(with: request) { data, urlResponse, error in + if let error = error { + continuation.resume(throwing: error) + return + } guard let data = data, let reponse = urlResponse as? HTTPURLResponse else { - requestError = error + continuation.resume(throwing: VRCKitError.invalidResponse) return } continuation.resume(returning: (data, reponse)) } .resume() } - if let requestError = requestError { - throw requestError - } - return httpResponse } #else From 6cda47f1e107a544054fcc8a7f160be62408c728 Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 12:14:07 +0900 Subject: [PATCH 27/32] fix: third-party-action-not-pinned-to-commit-sha --- .github/workflows/swift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 514d17d..290fd0b 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -20,7 +20,7 @@ jobs: swift: ["6"] steps: - uses: actions/checkout@v4 - - uses: SwiftyLab/setup-swift@v1 + - uses: SwiftyLab/setup-swift@a0188eaa95c3af0db72e8697c2f0a91c514da86c with: swift-version: ${{ matrix.swift }} - name: Get Swift version From 17504a0f9c6c9c9ffa77eca6a30ca66ef3dc1e1c Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 12:19:20 +0900 Subject: [PATCH 28/32] update: readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 08f5c5a..902ff49 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![License](https://img.shields.io/github/license/makinosp/vrckit.svg)](https://img.shields.io/github/license/makinosp/vrckit.svg) [![Release](https://img.shields.io/github/release/makinosp/vrckit.svg)](https://img.shields.io/github/release/makinosp/vrckit.svg) -![Swift](https://img.shields.io/badge/Swift%205.9+-F05138?logo=Swift&logoColor=white) +![Swift](https://img.shields.io/badge/Swift%206.0-F05138?logo=Swift&logoColor=white) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/5a8b6e5463a044e0b2ee948367df127c)](https://app.codacy.com/gh/makinosp/vrckit/dashboard) A Swift client to interact with the [VRChat API](https://vrchatapi.github.io/). From e6a38c24738ba1c54db30c8ebbddc50b56e9029d Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 13:07:30 +0900 Subject: [PATCH 29/32] fix: access control --- .../VRCKit/PreviewServices/AuthenticationPreviewService.swift | 2 +- Sources/VRCKit/PreviewServices/FavoritePreviewService.swift | 2 +- Sources/VRCKit/PreviewServices/FriendPreviewService.swift | 2 +- Sources/VRCKit/PreviewServices/InstancePreviewService.swift | 2 +- Sources/VRCKit/PreviewServices/UserNotePreviewService.swift | 2 +- Sources/VRCKit/PreviewServices/UserPreviewService.swift | 2 +- Sources/VRCKit/PreviewServices/WorldPreviewService.swift | 2 +- Sources/VRCKit/Services/AuthenticationService.swift | 2 +- Sources/VRCKit/Services/InstanceService.swift | 2 +- Sources/VRCKit/Services/UserNoteService.swift | 4 ++-- Sources/VRCKit/Services/UserService.swift | 4 ++-- Sources/VRCKit/Services/WorldService.swift | 4 ++-- 12 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Sources/VRCKit/PreviewServices/AuthenticationPreviewService.swift b/Sources/VRCKit/PreviewServices/AuthenticationPreviewService.swift index a4fde99..2936351 100644 --- a/Sources/VRCKit/PreviewServices/AuthenticationPreviewService.swift +++ b/Sources/VRCKit/PreviewServices/AuthenticationPreviewService.swift @@ -8,7 +8,7 @@ public final actor AuthenticationPreviewService: APIService, AuthenticationServiceProtocol { let client: APIClient - init(client: APIClient) { + public init(client: APIClient) { self.client = client } diff --git a/Sources/VRCKit/PreviewServices/FavoritePreviewService.swift b/Sources/VRCKit/PreviewServices/FavoritePreviewService.swift index a7bb8df..df9764c 100644 --- a/Sources/VRCKit/PreviewServices/FavoritePreviewService.swift +++ b/Sources/VRCKit/PreviewServices/FavoritePreviewService.swift @@ -10,7 +10,7 @@ import Foundation public final actor FavoritePreviewService: APIService, FavoriteServiceProtocol { let client: APIClient - init(client: APIClient) { + public init(client: APIClient) { self.client = client } diff --git a/Sources/VRCKit/PreviewServices/FriendPreviewService.swift b/Sources/VRCKit/PreviewServices/FriendPreviewService.swift index d12c770..241abc7 100644 --- a/Sources/VRCKit/PreviewServices/FriendPreviewService.swift +++ b/Sources/VRCKit/PreviewServices/FriendPreviewService.swift @@ -8,7 +8,7 @@ public final actor FriendPreviewService: APIService, FriendServiceProtocol { let client: APIClient - init(client: APIClient) { + public init(client: APIClient) { self.client = client } diff --git a/Sources/VRCKit/PreviewServices/InstancePreviewService.swift b/Sources/VRCKit/PreviewServices/InstancePreviewService.swift index cbaf525..edf919a 100644 --- a/Sources/VRCKit/PreviewServices/InstancePreviewService.swift +++ b/Sources/VRCKit/PreviewServices/InstancePreviewService.swift @@ -8,7 +8,7 @@ public final actor InstancePreviewService: APIService, InstanceServiceProtocol { let client: APIClient - init(client: APIClient) { + public init(client: APIClient) { self.client = client } diff --git a/Sources/VRCKit/PreviewServices/UserNotePreviewService.swift b/Sources/VRCKit/PreviewServices/UserNotePreviewService.swift index efdae60..4512970 100644 --- a/Sources/VRCKit/PreviewServices/UserNotePreviewService.swift +++ b/Sources/VRCKit/PreviewServices/UserNotePreviewService.swift @@ -10,7 +10,7 @@ import Foundation public final actor UserNotePreviewService: APIService, UserNoteServiceProtocol { let client: APIClient - init(client: APIClient) { + public init(client: APIClient) { self.client = client } diff --git a/Sources/VRCKit/PreviewServices/UserPreviewService.swift b/Sources/VRCKit/PreviewServices/UserPreviewService.swift index c16e634..00f30d6 100644 --- a/Sources/VRCKit/PreviewServices/UserPreviewService.swift +++ b/Sources/VRCKit/PreviewServices/UserPreviewService.swift @@ -8,7 +8,7 @@ public final actor UserPreviewService: APIService, UserServiceProtocol { let client: APIClient - init(client: APIClient) { + public init(client: APIClient) { self.client = client } diff --git a/Sources/VRCKit/PreviewServices/WorldPreviewService.swift b/Sources/VRCKit/PreviewServices/WorldPreviewService.swift index 02e1db0..2933af0 100644 --- a/Sources/VRCKit/PreviewServices/WorldPreviewService.swift +++ b/Sources/VRCKit/PreviewServices/WorldPreviewService.swift @@ -8,7 +8,7 @@ public final actor WorldPreviewService: APIService, WorldServiceProtocol { let client: APIClient - init(client: APIClient) { + public init(client: APIClient) { self.client = client } diff --git a/Sources/VRCKit/Services/AuthenticationService.swift b/Sources/VRCKit/Services/AuthenticationService.swift index dbedf8d..bb09cc8 100644 --- a/Sources/VRCKit/Services/AuthenticationService.swift +++ b/Sources/VRCKit/Services/AuthenticationService.swift @@ -11,7 +11,7 @@ public final actor AuthenticationService: APIService, AuthenticationServiceProto let client: APIClient private let authPath = "auth" - init(client: APIClient) { + public init(client: APIClient) { self.client = client } diff --git a/Sources/VRCKit/Services/InstanceService.swift b/Sources/VRCKit/Services/InstanceService.swift index b38ebc6..4f8baa4 100644 --- a/Sources/VRCKit/Services/InstanceService.swift +++ b/Sources/VRCKit/Services/InstanceService.swift @@ -9,7 +9,7 @@ public final class InstanceService: APIService, InstanceServiceProtocol { let client: APIClient private let path = "instances" - init(client: APIClient) { + public init(client: APIClient) { self.client = client } diff --git a/Sources/VRCKit/Services/UserNoteService.swift b/Sources/VRCKit/Services/UserNoteService.swift index 89f396b..c06fec3 100644 --- a/Sources/VRCKit/Services/UserNoteService.swift +++ b/Sources/VRCKit/Services/UserNoteService.swift @@ -5,11 +5,11 @@ // Created by makinosp on 2024/03/17. // -public final class UserNoteService: APIService, UserNoteServiceProtocol { +public final actor UserNoteService: APIService, UserNoteServiceProtocol { let client: APIClient private let path = "userNotes" - init(client: APIClient) { + public init(client: APIClient) { self.client = client } diff --git a/Sources/VRCKit/Services/UserService.swift b/Sources/VRCKit/Services/UserService.swift index f2f1744..1968d39 100644 --- a/Sources/VRCKit/Services/UserService.swift +++ b/Sources/VRCKit/Services/UserService.swift @@ -5,11 +5,11 @@ // Created by makinosp on 2024/02/18. // -public final class UserService: APIService, UserServiceProtocol { +public final actor UserService: APIService, UserServiceProtocol { let client: APIClient private let path = "users" - init(client: APIClient) { + public init(client: APIClient) { self.client = client } diff --git a/Sources/VRCKit/Services/WorldService.swift b/Sources/VRCKit/Services/WorldService.swift index 11ebe9a..046b9f8 100644 --- a/Sources/VRCKit/Services/WorldService.swift +++ b/Sources/VRCKit/Services/WorldService.swift @@ -5,11 +5,11 @@ // Created by kiripoipoi on 2024/09/07. // -public final class WorldService: APIService, WorldServiceProtocol { +public final actor WorldService: APIService, WorldServiceProtocol { let client: APIClient private let path = "worlds" - init(client: APIClient) { + public init(client: APIClient) { self.client = client } From dead58a20ddd82b9fb3581dccae997ed5e55ffc5 Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 13:09:03 +0900 Subject: [PATCH 30/32] fix: replace InstanceService class to actor --- Sources/VRCKit/Services/InstanceService.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/VRCKit/Services/InstanceService.swift b/Sources/VRCKit/Services/InstanceService.swift index 4f8baa4..f84db96 100644 --- a/Sources/VRCKit/Services/InstanceService.swift +++ b/Sources/VRCKit/Services/InstanceService.swift @@ -5,7 +5,7 @@ // Created by makinosp on 2024/02/18. // -public final class InstanceService: APIService, InstanceServiceProtocol { +public final actor InstanceService: APIService, InstanceServiceProtocol { let client: APIClient private let path = "instances" From eb67cb9adc119f9f307d81b2af33886c9fc3008f Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 13:16:06 +0900 Subject: [PATCH 31/32] feat: api service protocols conform to Sendable protocol --- Sources/VRCKit/Protocols/AuthenticationServiceProtocol.swift | 2 +- Sources/VRCKit/Protocols/FavoriteServiceProtocol.swift | 2 +- Sources/VRCKit/Protocols/FriendServiceProtocol.swift | 2 +- Sources/VRCKit/Protocols/ImageUrlRepresentableProtocol.swift | 2 +- Sources/VRCKit/Protocols/InstanceServiceProtocol.swift | 2 +- Sources/VRCKit/Protocols/LocationProtocol.swift | 2 +- Sources/VRCKit/Protocols/ProfileProtocols.swift | 2 +- Sources/VRCKit/Protocols/UserNoteServiceProtocol.swift | 2 +- Sources/VRCKit/Protocols/UserServiceProtocol.swift | 2 +- Sources/VRCKit/Protocols/WorldServiceProtocol.swift | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Sources/VRCKit/Protocols/AuthenticationServiceProtocol.swift b/Sources/VRCKit/Protocols/AuthenticationServiceProtocol.swift index fc3a011..fe19032 100644 --- a/Sources/VRCKit/Protocols/AuthenticationServiceProtocol.swift +++ b/Sources/VRCKit/Protocols/AuthenticationServiceProtocol.swift @@ -9,7 +9,7 @@ public protocol UserOrRequires: Sendable {} extension User: UserOrRequires {} extension VerifyType: UserOrRequires {} -public protocol AuthenticationServiceProtocol { +public protocol AuthenticationServiceProtocol: Sendable { func isExists(userId: String) async throws -> Bool func loginUserInfo() async throws -> UserOrRequires func verify2FA(verifyType: VerifyType, code: String) async throws -> Bool diff --git a/Sources/VRCKit/Protocols/FavoriteServiceProtocol.swift b/Sources/VRCKit/Protocols/FavoriteServiceProtocol.swift index 4e2d88b..872cc15 100644 --- a/Sources/VRCKit/Protocols/FavoriteServiceProtocol.swift +++ b/Sources/VRCKit/Protocols/FavoriteServiceProtocol.swift @@ -5,7 +5,7 @@ // Created by makinosp on 2024/07/14. // -public protocol FavoriteServiceProtocol { +public protocol FavoriteServiceProtocol: Sendable { func listFavoriteGroups() async throws -> [FavoriteGroup] func listFavorites(n: Int, type: FavoriteType, tag: String?) async throws -> [Favorite] func fetchFavoriteGroupDetails(favoriteGroups: [FavoriteGroup]) async throws -> [FavoriteDetail] diff --git a/Sources/VRCKit/Protocols/FriendServiceProtocol.swift b/Sources/VRCKit/Protocols/FriendServiceProtocol.swift index d0e5e09..4b46750 100644 --- a/Sources/VRCKit/Protocols/FriendServiceProtocol.swift +++ b/Sources/VRCKit/Protocols/FriendServiceProtocol.swift @@ -5,7 +5,7 @@ // Created by makinosp on 2024/07/14. // -public protocol FriendServiceProtocol { +public protocol FriendServiceProtocol: Sendable { func fetchFriends(offset: Int, n: Int, offline: Bool) async throws -> [Friend] func fetchFriends(count: Int, offline: Bool) async throws -> [Friend] func unfriend(id: String) async throws diff --git a/Sources/VRCKit/Protocols/ImageUrlRepresentableProtocol.swift b/Sources/VRCKit/Protocols/ImageUrlRepresentableProtocol.swift index d7d9c23..e556674 100644 --- a/Sources/VRCKit/Protocols/ImageUrlRepresentableProtocol.swift +++ b/Sources/VRCKit/Protocols/ImageUrlRepresentableProtocol.swift @@ -7,7 +7,7 @@ import Foundation -public protocol ImageUrlRepresentable { +public protocol ImageUrlRepresentable: Sendable { func imageUrl(_ resolution: ImageResolution) -> URL? } diff --git a/Sources/VRCKit/Protocols/InstanceServiceProtocol.swift b/Sources/VRCKit/Protocols/InstanceServiceProtocol.swift index 879672f..47c0e5e 100644 --- a/Sources/VRCKit/Protocols/InstanceServiceProtocol.swift +++ b/Sources/VRCKit/Protocols/InstanceServiceProtocol.swift @@ -5,7 +5,7 @@ // Created by makinosp on 2024/07/14. // -public protocol InstanceServiceProtocol { +public protocol InstanceServiceProtocol: Sendable { func fetchInstance(worldId: String, instanceId: String) async throws -> Instance func fetchInstance(location: String) async throws -> Instance } diff --git a/Sources/VRCKit/Protocols/LocationProtocol.swift b/Sources/VRCKit/Protocols/LocationProtocol.swift index 12e70dd..92f4ae4 100644 --- a/Sources/VRCKit/Protocols/LocationProtocol.swift +++ b/Sources/VRCKit/Protocols/LocationProtocol.swift @@ -6,7 +6,7 @@ // /// Represents a type that has a location string. -public protocol LocationRepresentable { +public protocol LocationRepresentable: Sendable { var location: Location { get } var isVisible: Bool { get } } diff --git a/Sources/VRCKit/Protocols/ProfileProtocols.swift b/Sources/VRCKit/Protocols/ProfileProtocols.swift index 98737d4..e1affdd 100644 --- a/Sources/VRCKit/Protocols/ProfileProtocols.swift +++ b/Sources/VRCKit/Protocols/ProfileProtocols.swift @@ -9,7 +9,7 @@ import Foundation /// A protocol representing common properties for user profile elements. /// This protocol can be adopted by structures such as User, Friend, and UserDetail. -public protocol ProfileElementRepresentable: Hashable, Identifiable, ImageUrlRepresentable { +public protocol ProfileElementRepresentable: Sendable, Hashable, Identifiable, ImageUrlRepresentable { var bio: String? { get } var bioLinks: SafeDecodingArray { get } var avatarImageUrl: URL? { get } diff --git a/Sources/VRCKit/Protocols/UserNoteServiceProtocol.swift b/Sources/VRCKit/Protocols/UserNoteServiceProtocol.swift index 1bb3040..0598152 100644 --- a/Sources/VRCKit/Protocols/UserNoteServiceProtocol.swift +++ b/Sources/VRCKit/Protocols/UserNoteServiceProtocol.swift @@ -5,7 +5,7 @@ // Created by makinosp on 2024/07/14. // -public protocol UserNoteServiceProtocol { +public protocol UserNoteServiceProtocol: Sendable { func updateUserNote(targetUserId: String, note: String) async throws -> UserNoteResponse func clearUserNote(targetUserId: String) async throws } diff --git a/Sources/VRCKit/Protocols/UserServiceProtocol.swift b/Sources/VRCKit/Protocols/UserServiceProtocol.swift index 8b3bebc..0dd1b2c 100644 --- a/Sources/VRCKit/Protocols/UserServiceProtocol.swift +++ b/Sources/VRCKit/Protocols/UserServiceProtocol.swift @@ -5,7 +5,7 @@ // Created by makinosp on 2024/07/14. // -public protocol UserServiceProtocol { +public protocol UserServiceProtocol: Sendable { func fetchUser(userId: String) async throws -> UserDetail func updateUser(id: String, editedInfo: EditableUserInfo) async throws } diff --git a/Sources/VRCKit/Protocols/WorldServiceProtocol.swift b/Sources/VRCKit/Protocols/WorldServiceProtocol.swift index 5b59158..725ea71 100644 --- a/Sources/VRCKit/Protocols/WorldServiceProtocol.swift +++ b/Sources/VRCKit/Protocols/WorldServiceProtocol.swift @@ -5,7 +5,7 @@ // Created by kiripoipoi on 2024/09/07. // -public protocol WorldServiceProtocol { +public protocol WorldServiceProtocol: Sendable { func fetchWorld(worldId: String) async throws -> World func fetchFavoritedWorlds() async throws -> [World] } From 3e8473947c3044297be4647d8230381c16921090 Mon Sep 17 00:00:00 2001 From: makinosp Date: Mon, 23 Sep 2024 13:44:45 +0900 Subject: [PATCH 32/32] feat: replace FriendPreviewProvider actor to final class --- Sources/VRCKit/PreviewServices/FriendPreviewService.swift | 4 ++-- Sources/VRCKit/PreviewServices/PreviewDataProvider.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/VRCKit/PreviewServices/FriendPreviewService.swift b/Sources/VRCKit/PreviewServices/FriendPreviewService.swift index 241abc7..502733e 100644 --- a/Sources/VRCKit/PreviewServices/FriendPreviewService.swift +++ b/Sources/VRCKit/PreviewServices/FriendPreviewService.swift @@ -13,11 +13,11 @@ public final actor FriendPreviewService: APIService, FriendServiceProtocol { } public func fetchFriends(offset: Int, n: Int, offline: Bool) async throws -> [Friend] { - offline ? await PreviewDataProvider.shared.offlineFriends : await PreviewDataProvider.shared.onlineFriends + offline ? PreviewDataProvider.shared.offlineFriends : PreviewDataProvider.shared.onlineFriends } public func fetchFriends(count: Int, offline: Bool) async throws -> [Friend] { - offline ? await PreviewDataProvider.shared.offlineFriends : await PreviewDataProvider.shared.onlineFriends + offline ? PreviewDataProvider.shared.offlineFriends : PreviewDataProvider.shared.onlineFriends } public func unfriend(id: String) async throws {} diff --git a/Sources/VRCKit/PreviewServices/PreviewDataProvider.swift b/Sources/VRCKit/PreviewServices/PreviewDataProvider.swift index 31489a5..09bda9b 100644 --- a/Sources/VRCKit/PreviewServices/PreviewDataProvider.swift +++ b/Sources/VRCKit/PreviewServices/PreviewDataProvider.swift @@ -7,7 +7,7 @@ import Foundation -public actor PreviewDataProvider { +public final class PreviewDataProvider: Sendable { typealias FriendSet = (friend: Friend, userDetail: UserDetail) public static let shared = PreviewDataProvider() private let previewUserId = UUID()