-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merge Ratings into AtlText #595
Changes from 28 commits
0d83dd4
83f1de6
242ccf1
b948f51
c287476
eade506
b2dfa18
32698cc
9cd0a37
338c965
ed91a63
8f690dd
4d8222d
18701f3
5cd6c41
2eb1a9b
a840f86
89751be
72329da
b535bac
2c54ae0
9dc960e
64531f4
8547560
7f1fc02
ff3f1a2
71abf01
c115df7
175f490
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -90,15 +90,22 @@ public struct AvatarService: Sendable { | |
} | ||
} | ||
|
||
package func update(_ altText: String?, rating: AvatarRating?, avatarID: String, accessToken: String) async throws { | ||
@discardableResult | ||
package func update( | ||
_ altText: String?, | ||
rating: AvatarRating?, | ||
avatarID: String, | ||
accessToken: String | ||
) async throws -> Avatar { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't currently use this return data. But since the API defines a return type for this, I thought we probably should return it, and make it @discardableRersult. That does mean that if we can't decode it (which I would expect to be quite rare since it would be a backend error that breaks the API), this will throw an error. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eventually, if (when?) we make this part of the API public, we can follow the pattern of: public update(::::) --> AvatarType
package update(::::) --> Avatar There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good! 👍 |
||
var request = URLRequest(url: .avatarsURL.appendingPathComponent(avatarID)) | ||
request.httpMethod = "PATCH" | ||
let updateBody = UpdateAvatarRequest(rating: rating, altText: altText) | ||
request.httpBody = try JSONEncoder().encode(updateBody) | ||
|
||
let authorizedRequest = request.settingAuthorizationHeaderField(with: accessToken) | ||
do { | ||
_ = try await client.data(with: authorizedRequest) | ||
let (data, _) = try await client.data(with: authorizedRequest) | ||
return try data.decode() | ||
} catch { | ||
throw error.apiError() | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
extension Avatar { | ||
/// Transforms `Avatar.Rating` into `AvatarRating` | ||
/// This is only necessary while we maintain both enums. For our next major realease, `Avatar` will use the `AvatarRating` enum | ||
/// rather than defining its own. | ||
var avatarRating: AvatarRating { | ||
switch self.rating { | ||
case .g: .g | ||
case .pg: .pg | ||
case .r: .r | ||
case .x: .x | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -207,7 +207,7 @@ class AvatarPickerViewModel: ObservableObject { | |
|
||
let localID = UUID().uuidString | ||
|
||
let localImageModel = AvatarImageModel(id: localID, source: .local(image: image), state: .loading) | ||
let localImageModel = AvatarImageModel(id: localID, source: .local(image: image), state: .loading, rating: .g) | ||
grid.append(localImageModel) | ||
|
||
await doUpload(squareImage: image, localID: localID, accessToken: authToken) | ||
|
@@ -290,7 +290,8 @@ class AvatarPickerViewModel: ObservableObject { | |
let newModel = AvatarImageModel( | ||
id: imageID, | ||
source: .local(image: squareImage), | ||
state: .error(supportsRetry: supportsRetry, errorMessage: errorMessage) | ||
state: .error(supportsRetry: supportsRetry, errorMessage: errorMessage), | ||
rating: grid.model(with: imageID)?.rating ?? .g | ||
) | ||
grid.replaceModel(withID: imageID, with: newModel) | ||
} | ||
|
@@ -337,6 +338,7 @@ class AvatarPickerViewModel: ObservableObject { | |
await profile | ||
} | ||
|
||
@discardableResult | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reasonable? Or do we want to check the result? |
||
func update(_ avatar: AvatarImageModel, altText: String) async -> Bool { | ||
guard let token = self.authToken else { return false } | ||
do { | ||
|
@@ -359,6 +361,35 @@ class AvatarPickerViewModel: ObservableObject { | |
return false | ||
} | ||
|
||
@discardableResult | ||
func update(_ avatar: AvatarImageModel, rating: AvatarRating) async -> Bool { | ||
guard let authToken else { return false } | ||
|
||
do { | ||
let updatedAvatar = try await avatarService.update( | ||
nil, | ||
rating: rating, | ||
avatarID: avatar.id, | ||
accessToken: authToken | ||
) | ||
withAnimation { | ||
grid.replaceModel(withID: avatar.id, with: .init(with: updatedAvatar)) | ||
toastManager.showToast(Localized.avatarRatingUpdateSuccess, type: .info) | ||
} | ||
return true | ||
} catch APIError.responseError(let reason) where reason.urlSessionErrorLocalizedDescription != nil { | ||
handleError(message: reason.urlSessionErrorLocalizedDescription ?? Localized.avatarRatingError) | ||
} catch { | ||
handleError(message: Localized.avatarRatingError) | ||
} | ||
|
||
func handleError(message: String) { | ||
toastManager.showToast(message, type: .error) | ||
} | ||
|
||
return false | ||
} | ||
|
||
func delete(_ avatar: AvatarImageModel) async -> Bool { | ||
guard let token = self.authToken else { return false } | ||
defer { | ||
|
@@ -446,6 +477,16 @@ extension AvatarPickerViewModel { | |
value: "Image alt text was changed successfully", | ||
comment: "This confirmation message shows when the user has updated the alt text." | ||
) | ||
static let avatarRatingUpdateSuccess = SDKLocalizedString( | ||
"AvatarPickerViewModel.RatingUpdate.Success", | ||
value: "Avatar rating was changed successfully.", | ||
comment: "This confirmation message shows when the user picks a different avatar rating and the change was applied successfully." | ||
) | ||
static let avatarRatingError = SDKLocalizedString( | ||
"AvatarPickerViewModel.Rating.Error", | ||
value: "Oops, something didn't quite work out while trying to rate your avatar.", | ||
comment: "This error message shows when the user attempts to change the rating of an avatar and fails." | ||
) | ||
} | ||
} | ||
|
||
|
@@ -468,5 +509,6 @@ extension AvatarImageModel { | |
state = .loaded | ||
isSelected = avatar.isSelected | ||
altText = avatar.altText | ||
rating = avatar.avatarRating | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"image_id": "991a7b71cf9f34...", | ||
"image_url": "https://2.gravatar.com/userimage/1/991a7b71cf934ea2...?size=512", | ||
"rating": "PG", | ||
"updated_date": "2024-09-18T10:17:53Z", | ||
"alt_text": "John Appleseed's avatar" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that we have multiple parameters that we can "update", I think the calling site might read better if we name the first parameter. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's go with this change 👍