Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>zmessaging2.135.0.xcdatamodel</string>
<string>zmessaging2.136.0.xcdatamodel</string>
</dict>
</plist>

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ public struct NewUserInfo: Equatable, Sendable {
let serviceID: UUID?
let serviceProvider: UUID?
let supportedProtocols: Set<WireDataModel.MessageProtocol>?
let textStatus: String?
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ public struct UserUpdateInfo: Sendable {
let previewAssetKey: String?
let completeAssetKey: String?
let supportedProtocols: Set<WireDataModel.MessageProtocol>?
let textStatus: String?
let isTextStatusPresent: Bool
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ public protocol UserLocalStoreProtocol {
isReadReceiptsEnabledChangedRemotely: Bool
) async

/// Update text status for self user locally and mark for upstream sync.

func updateSelfUserTextStatus(_ textStatus: String?) async

/// Persist the supported protocols for the self user.

func updateSelfUserSupportedProtocols(supportedProtocols: Set<WireDataModel.MessageProtocol>) async
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ public final class UserLocalStore: UserLocalStoreProtocol {
}
}

public func updateSelfUserTextStatus(_ textStatus: String?) async {
let selfUser = await fetchSelfUser()
await context.perform {
selfUser.textStatus = textStatus
selfUser.setLocallyModifiedKeys(["textStatus"])
}
}

public func updateSelfUserSupportedProtocols(supportedProtocols: Set<WireDataModel.MessageProtocol>) async {
await context.perform { [context] in
let selfUser = ZMUser.selfUser(in: context)
Expand Down Expand Up @@ -355,6 +363,7 @@ public final class UserLocalStore: UserLocalStoreProtocol {
persistedUser.serviceIdentifier = userInfo.serviceID?.transportString()
persistedUser.providerIdentifier = userInfo.serviceProvider?.transportString()
persistedUser.supportedProtocols = userInfo.supportedProtocols ?? [.proteus]
persistedUser.textStatus = userInfo.textStatus?.trimmingCharacters(in: .whitespaces)
persistedUser.needsToBeUpdatedFromBackend = false
// `type` only exists in v12 or later
let fallbackType: TypeOfUser = persistedUser.serviceIdentifier != nil ? .bot : .regular
Expand Down Expand Up @@ -413,6 +422,10 @@ public final class UserLocalStore: UserLocalStoreProtocol {

user.supportedProtocols = userUpdateInfo.supportedProtocols ?? [.proteus]

if userUpdateInfo.isTextStatusPresent {
user.textStatus = userUpdateInfo.textStatus?.trimmingCharacters(in: .whitespaces)
}

user.isPendingMetadataRefresh = false
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,9 @@ extension WireNetwork.UserUpdateEvent {
completeAssetKey: assets?
.first(where: { $0.size == .complete })
.map(\.key),
supportedProtocols: supportedProtocols?.toDomainModel()
supportedProtocols: supportedProtocols?.toDomainModel(),
textStatus: textStatus,
isTextStatusPresent: isTextStatusPresent
)
}

Expand Down Expand Up @@ -165,7 +167,8 @@ extension WireNetwork.User {
appCategory: app?.category,
serviceID: service?.id,
serviceProvider: service?.provider,
supportedProtocols: supportedProtocols?.toDomainModel()
supportedProtocols: supportedProtocols?.toDomainModel(),
textStatus: textStatus
)

}
Expand Down Expand Up @@ -195,7 +198,8 @@ extension WireNetwork.SelfUser {
appCategory: app?.category,
serviceID: service?.id,
serviceProvider: service?.provider,
supportedProtocols: supportedProtocols?.toDomainModel()
supportedProtocols: supportedProtocols?.toDomainModel(),
textStatus: textStatus
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ public protocol SelfUserAPI {
func updateHandle(handle: String) async throws
#endif

/// Update the custom text status for self user
/// - Parameter textStatus: the new text status
func updateTextStatus(_ textStatus: String) async throws

/// Delete a team
/// - Parameters:
/// - teamId: teamId fetched by user
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,22 @@ class SelfUserAPIV0: SelfUserAPI, VersionedAPI {
.parse(code: response.statusCode, data: data)
}

func updateTextStatus(_ textStatus: String) async throws {
let body = try JSONEncoder.defaultEncoder.encode(
UpdateTextStatusRequestBodyV0(textStatus: textStatus)
)

let request = try URLRequestBuilder(path: resourcePath)
.withMethod(.put)
.withBody(body, contentType: .json)
.build()

let (data, response) = try await apiService.executeRequest(request, requiringAccessToken: true)
return try ResponseParser()
.success(code: .ok)
.parse(code: response.statusCode, data: data)
}

func updateHandle(handle: String) async throws {
let body = try JSONEncoder.defaultEncoder.encode(
UpdateHandleRequestBodyV0(handle: handle)
Expand Down Expand Up @@ -122,6 +138,7 @@ struct SelfUserV0: Decodable, ToAPIModelConvertible {
let service: ServiceResponseV0?
let ssoID: SSOIDV0?
let teamID: UUID?
let textStatus: String?

enum CodingKeys: String, CodingKey {
case accentID = "accent_id"
Expand All @@ -134,6 +151,7 @@ struct SelfUserV0: Decodable, ToAPIModelConvertible {
case service
case ssoID = "sso_id"
case teamID = "team"
case textStatus = "text_status"
}

func toAPIModel() -> SelfUser {
Expand All @@ -153,7 +171,8 @@ struct SelfUserV0: Decodable, ToAPIModelConvertible {
expiresAt: expiresAt?.date,
app: nil, // introduced with API v15
service: service?.toAPIModel(),
supportedProtocols: [.proteus] /// default to Proteus for api versions < v5
supportedProtocols: [.proteus], /// default to Proteus for api versions < v5
textStatus: textStatus
)
}
}
Expand Down Expand Up @@ -200,6 +219,13 @@ private struct UpdateHandleRequestBodyV0: Encodable {
var handle: String
}

private struct UpdateTextStatusRequestBodyV0: Encodable {
let textStatus: String
enum CodingKeys: String, CodingKey {
case textStatus = "text_status"
}
}

private struct DeleteTeamRequestBodyV0: Encodable {
var password: String
var verificationCode: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ struct SelfUserV4: Decodable, ToAPIModelConvertible {
let ssoID: SSOIDV0?
let supportedProtocols: Set<MessageProtocolV0>?
let teamID: UUID?
let textStatus: String?

enum CodingKeys: String, CodingKey {
case accentID = "accent_id"
Expand All @@ -73,6 +74,7 @@ struct SelfUserV4: Decodable, ToAPIModelConvertible {
case ssoID = "sso_id"
case teamID = "team"
case supportedProtocols = "supported_protocols"
case textStatus = "text_status"
}

func toAPIModel() -> SelfUser {
Expand All @@ -93,7 +95,8 @@ struct SelfUserV4: Decodable, ToAPIModelConvertible {
expiresAt: expiresAt?.date,
app: nil, // introduced with API v15
service: service?.toAPIModel(),
supportedProtocols: Set(supportedProtocols)
supportedProtocols: Set(supportedProtocols),
textStatus: textStatus
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ struct UserUpdateEventDecoder {
email: payload.email,
isSSOIDDeleted: payload.isSSOIDDeleted,
assets: payload.assets?.map { $0.toAPIModel() },
supportedProtocols: supportedProtocols.flatMap { Set($0) }
supportedProtocols: supportedProtocols.flatMap { Set($0) },
textStatus: payload.textStatus,
isTextStatusPresent: payload.isTextStatusPresent
)
}

Expand All @@ -51,6 +53,8 @@ struct UserUpdateEventDecoder {
let isSSOIDDeleted: Bool?
let assets: [UserAssetV0]?
let supportedProtocols: Set<MessageProtocolV0>?
let textStatus: String?
let isTextStatusPresent: Bool

enum CodingKeys: String, CodingKey {

Expand All @@ -62,9 +66,24 @@ struct UserUpdateEventDecoder {
case isSSOIDDeleted = "sso_id_deleted"
case assets
case supportedProtocols = "supported_protocols"
case textStatus = "text_status"

}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
userID = try container.decode(UUID.self, forKey: .userID)
accentColorID = try container.decodeIfPresent(Int.self, forKey: .accentColorID)
name = try container.decodeIfPresent(String.self, forKey: .name)
handle = try container.decodeIfPresent(String.self, forKey: .handle)
email = try container.decodeIfPresent(String.self, forKey: .email)
isSSOIDDeleted = try container.decodeIfPresent(Bool.self, forKey: .isSSOIDDeleted)
assets = try container.decodeIfPresent([UserAssetV0].self, forKey: .assets)
supportedProtocols = try container.decodeIfPresent(Set<MessageProtocolV0>.self, forKey: .supportedProtocols)
isTextStatusPresent = container.contains(.textStatus)
textStatus = try container.decodeIfPresent(String.self, forKey: .textStatus)
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ struct UserResponseV0: Decodable, ToAPIModelConvertible {
let expiresAt: UTCTime?
let service: ServiceResponseV0?
let legalholdStatus: LegalholdStatusV0
let textStatus: String?

enum CodingKeys: String, CodingKey {

Expand All @@ -99,6 +100,7 @@ struct UserResponseV0: Decodable, ToAPIModelConvertible {
case expiresAt = "expires_at"
case service
case legalholdStatus = "legalhold_status"
case textStatus = "text_status"

}

Expand All @@ -117,7 +119,8 @@ struct UserResponseV0: Decodable, ToAPIModelConvertible {
app: nil,
service: service?.toAPIModel(),
supportedProtocols: [.proteus],
legalholdStatus: legalholdStatus.toAPIModel()
legalholdStatus: legalholdStatus.toAPIModel(),
textStatus: textStatus
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ private struct UserResponseV12: Decodable, ToAPIModelConvertible {
let service: ServiceResponseV0?
let supportedProtocols: Set<MessageProtocolV0>?
let legalholdStatus: LegalholdStatusV0
let textStatus: String?

enum CodingKeys: String, CodingKey {

Expand All @@ -113,6 +114,7 @@ private struct UserResponseV12: Decodable, ToAPIModelConvertible {
case service
case supportedProtocols = "supported_protocols"
case legalholdStatus = "legalhold_status"
case textStatus = "text_status"

}

Expand All @@ -132,7 +134,8 @@ private struct UserResponseV12: Decodable, ToAPIModelConvertible {
app: nil,
service: service?.toAPIModel(),
supportedProtocols: supportedProtocols.flatMap { Set($0) },
legalholdStatus: legalholdStatus.toAPIModel()
legalholdStatus: legalholdStatus.toAPIModel(),
textStatus: textStatus
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ struct UserResponseV15: Decodable, ToAPIModelConvertible {
let supportedProtocols: Set<MessageProtocolV0>?
let legalholdStatus: LegalholdStatusV0
let app: UserAppV15? // introduced in v15
let textStatus: String?

enum CodingKeys: String, CodingKey {

Expand All @@ -114,6 +115,7 @@ struct UserResponseV15: Decodable, ToAPIModelConvertible {
case supportedProtocols = "supported_protocols"
case legalholdStatus = "legalhold_status"
case app
case textStatus = "text_status"

}

Expand All @@ -133,7 +135,8 @@ struct UserResponseV15: Decodable, ToAPIModelConvertible {
app: app?.toAPIModel(),
service: service?.toAPIModel(),
supportedProtocols: supportedProtocols.flatMap { Set($0) },
legalholdStatus: legalholdStatus.toAPIModel()
legalholdStatus: legalholdStatus.toAPIModel(),
textStatus: textStatus
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ struct UserResponseV4: Decodable, ToAPIModelConvertible {
let service: ServiceResponseV0?
let supportedProtocols: Set<MessageProtocolV0>?
let legalholdStatus: LegalholdStatusV0
let textStatus: String?

enum CodingKeys: String, CodingKey {

Expand All @@ -111,6 +112,7 @@ struct UserResponseV4: Decodable, ToAPIModelConvertible {
case service
case supportedProtocols = "supported_protocols"
case legalholdStatus = "legalhold_status"
case textStatus = "text_status"

}

Expand All @@ -130,7 +132,8 @@ struct UserResponseV4: Decodable, ToAPIModelConvertible {
app: nil,
service: service?.toAPIModel(),
supportedProtocols: supportedProtocols.flatMap { Set($0) },
legalholdStatus: legalholdStatus.toAPIModel()
legalholdStatus: legalholdStatus.toAPIModel(),
textStatus: textStatus
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,8 @@ public struct SelfUser: Equatable, Sendable {

public let supportedProtocols: Set<MessageProtocol>?

/// The custom text status of the self user

public let textStatus: String?

}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ public struct UserUpdateEvent: Equatable, Sendable {

public let supportedProtocols: Set<MessageProtocol>?

/// The new text status.

public let textStatus: String?

/// Whether `text_status` key was present in the event payload.
/// `true` means the field was explicitly sent (even if empty/null) and should be applied.
/// `false` means the field was absent and the local value should be left unchanged.

public let isTextStatusPresent: Bool

public init(
userID: UUID,
accentColorID: Int?,
Expand All @@ -62,7 +72,9 @@ public struct UserUpdateEvent: Equatable, Sendable {
email: String?,
isSSOIDDeleted: Bool?,
assets: [UserAsset]?,
supportedProtocols: Set<MessageProtocol>?
supportedProtocols: Set<MessageProtocol>?,
textStatus: String? = nil,
isTextStatusPresent: Bool = false
) {
self.userID = userID
self.accentColorID = accentColorID
Expand All @@ -72,6 +84,8 @@ public struct UserUpdateEvent: Equatable, Sendable {
self.isSSOIDDeleted = isSSOIDDeleted
self.assets = assets
self.supportedProtocols = supportedProtocols
self.textStatus = textStatus
self.isTextStatusPresent = isTextStatusPresent
}

}
Loading
Loading