Skip to content

Commit

Permalink
fix: [FC-0078] Bugfixes part 1 (#570)
Browse files Browse the repository at this point in the history
* feat: init branch

* fix: fc78-part1

* fix: tests

* fix: address feedback

* fix: increase timeout for download helper tests

* fix: address feedback

* fix: address feedback

* fix: update tests
  • Loading branch information
IvanStepanok authored Feb 25, 2025
1 parent 0a267b5 commit 54f1105
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 39 deletions.
3 changes: 2 additions & 1 deletion Core/Core/Data/Model/Data_UserProfile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,13 @@ public enum AccountPrivacy: String, Codable, Sendable {
case privateAccess = "private"
case allUsers = "all_users"
case allUsersBig = "ALL_USERS"
case custom = "custom"

public var boolValue: Bool {
switch self {
case .privateAccess:
return false
case .allUsers, .allUsersBig:
case .allUsers, .allUsersBig, .custom:
return true
}
}
Expand Down
10 changes: 8 additions & 2 deletions Course/Course/Presentation/Subviews/CustomDisclosureGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,6 @@ struct CustomDisclosureGroup: View {
private func assignmentStatusText(
sequential: CourseSequential
) -> String? {

guard let sequentialProgress = sequential.sequentialProgress,
let assignmentType = sequentialProgress.assignmentType,
let due = sequential.due else {
Expand All @@ -217,7 +216,14 @@ struct CustomDisclosureGroup: View {

let daysRemaining = getAssignmentStatus(for: due)

return "\(assignmentType) - \(daysRemaining)"
let progress: String = {
guard let numPointsEarned = sequentialProgress.numPointsEarned,
let numPointsPossible = sequentialProgress.numPointsPossible else {
return ""
}
return " - \(numPointsEarned) / \(numPointsPossible)"
}()
return "\(assignmentType) - \(daysRemaining)\(progress)"
}

private func downloadAllSubsections(in chapter: CourseChapter, state: DownloadViewState) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ final class CourseDownloadHelperTests: XCTestCase {
var sequential: CourseSequential!
var task: DownloadDataTask!
var value: CourseDownloadValue!
var timeout: TimeInterval = 5
var timeout: TimeInterval = 15

override func setUp() {
super.setUp()
Expand Down
2 changes: 1 addition & 1 deletion Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 231e03216f446b4695e43a4c85a29e2127fd674b

COCOAPODS: 1.15.2
COCOAPODS: 1.16.2
28 changes: 20 additions & 8 deletions Profile/Profile/Presentation/EditProfile/EditProfileView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,34 @@ public struct EditProfileView: View {
.font(Theme.Fonts.titleSmall)
.foregroundColor(Theme.Colors.textSecondary)
.accessibilityIdentifier("profile_type_text")
Button(action: {
withAnimation {
showingBottomSheet.toggle()
}
}, label: {
UserAvatar(url: viewModel.userModel.avatarUrl, image: $viewModel.inputImage)
Button(
action: {
withAnimation {
showingBottomSheet.toggle()
}
},
label: {
UserAvatar(
url: viewModel.profileChanges.profileType == .full
? viewModel.userModel.avatarUrl
: "",
image: viewModel.profileChanges.profileType == .full
? $viewModel.inputImage
: .constant(nil)
)
.padding(.top, 30)
.overlay(
ZStack {
Circle().frame(width: 36, height: 36)
.foregroundColor(Theme.Colors.accentXColor)
CoreAssets.addPhoto.swiftUIImage.renderingMode(.template)
.foregroundColor(Theme.Colors.primaryButtonTextColor)
}.offset(x: 36, y: 50)
}
.offset(x: 36, y: 50)
.saturation(viewModel.canEditAvatar ? 1.0 : 0)
)
})
})
.disabled(!viewModel.canEditAvatar)
.accessibilityIdentifier("change_profile_image_button")

Text(viewModel.userModel.name)
Expand Down
47 changes: 30 additions & 17 deletions Profile/Profile/Presentation/EditProfile/EditProfileViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class EditProfileViewModel: ObservableObject {
var profileDidEdit: (((UserProfile?, UIImage?)) -> Void)?
var oldAvatar: UIImage?

private let minimumFullAccountAge = 13
private let currentYear = Calendar.current.component(.year, from: Date())
public let profileTypes: [ProfileType] = [.full, .limited]
private var years: [PickerFields.Option] = []
Expand Down Expand Up @@ -79,6 +80,16 @@ public class EditProfileViewModel: ObservableObject {
}
}

public var canEditAvatar: Bool {
guard let year = yearsConfiguration.text != "" ? Int(yearsConfiguration.text) : userModel.yearOfBirth else {
return false
}
if currentYear - year < minimumFullAccountAge {
return false
}
return profileChanges.profileType == .full
}

let router: ProfileRouter

private let interactor: ProfileInteractorProtocol
Expand All @@ -97,6 +108,7 @@ public class EditProfileViewModel: ObservableObject {
self.spokenLanguages = interactor.getSpokenLanguages()
self.countries = interactor.getCountries()
generateYears()
profileChanges.profileType = userModel.isFullProfile ? .full : .limited
}

func resizeImage(image: UIImage, longSideSize: Double) {
Expand Down Expand Up @@ -126,7 +138,6 @@ public class EditProfileViewModel: ObservableObject {
isShowProgress = true
do {
if try await interactor.deleteProfilePicture() {
inputImage = CoreAssets.noAvatar.image
isShowProgress = false
}
} catch {
Expand Down Expand Up @@ -162,7 +173,7 @@ public class EditProfileViewModel: ObservableObject {
} else {
yearOfBirth = userModel.yearOfBirth
}
if yearOfBirth == 0 || currentYear - yearOfBirth < 13 {
if yearOfBirth == 0 || currentYear - yearOfBirth < minimumFullAccountAge {
alertMessage = ProfileLocalization.Edit.tooYongUser
} else {
profileChanges.profileType.toggle()
Expand All @@ -174,7 +185,7 @@ public class EditProfileViewModel: ObservableObject {
func checkProfileType() {
if yearsConfiguration.text != "" {
let yearOfBirth = yearsConfiguration.text
if currentYear - (Int(yearOfBirth) ?? 0) < 13 {
if currentYear - (Int(yearOfBirth) ?? 0) < minimumFullAccountAge {
profileChanges.profileType = .limited
isYongUser = true
} else {
Expand All @@ -183,7 +194,7 @@ public class EditProfileViewModel: ObservableObject {
}
}
} else {
if (currentYear - userModel.yearOfBirth) < 13 {
if (currentYear - userModel.yearOfBirth) < minimumFullAccountAge {
profileChanges.profileType = .limited
isYongUser = true
} else {
Expand Down Expand Up @@ -234,24 +245,14 @@ public class EditProfileViewModel: ObservableObject {
@MainActor
func uploadData(parameters: [String: any Any & Sendable]) async {
do {
if profileChanges.isAvatarDeleted {
if profileChanges.isAvatarDeleted || profileChanges.profileType == .limited {
try await deleteAvatar()
profileChanges.isAvatarChanged = false
profileChanges.isAvatarDeleted = false
profileChanges.isAvatarSaved = true
checkChanges()
}
if profileChanges.isAvatarChanged {
if let newImage = inputImage?.jpegData(compressionQuality: 80) {
isShowProgress = true
try await interactor.uploadProfilePicture(pictureData: newImage)
isShowProgress = false
profileChanges.isAvatarChanged = false
profileChanges.isAvatarSaved = true
checkChanges()
}
}

checkChanges()

if isChanged {
if !parameters.isEmpty {
isShowProgress = true
Expand All @@ -264,6 +265,18 @@ public class EditProfileViewModel: ObservableObject {
}
isChanged = false
}

if profileChanges.profileType == .full {
if let newImage = inputImage?.jpegData(compressionQuality: 80) {
isShowProgress = true
try await interactor.uploadProfilePicture(pictureData: newImage)
isShowProgress = false
profileChanges.isAvatarChanged = false
profileChanges.isAvatarSaved = true
checkChanges()
}
}

} catch {
isShowProgress = false
if error.isInternetError {
Expand Down
21 changes: 18 additions & 3 deletions Profile/Profile/Presentation/Profile/ProfileView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,18 @@ public struct ProfileView: View {
.accessibilityIdentifier("progress_bar")
} else {
HStack(alignment: .center, spacing: 12) {
UserAvatar(url: viewModel.userModel?.avatarUrl ?? "", image: $viewModel.updatedAvatar)
if let userModel = viewModel.userModel {
UserAvatar(
url: userModel.isFullProfile
? userModel.avatarUrl
: "",
image: userModel.isFullProfile
? $viewModel.updatedAvatar
: .constant(nil)
)
.accessibilityIdentifier("user_avatar_image")
}

VStack(alignment: .leading, spacing: 4) {
Text(viewModel.userModel?.name ?? "")
.font(Theme.Fonts.headlineSmall)
Expand Down Expand Up @@ -203,9 +213,14 @@ struct ProfileView_Previews: PreviewProvider {
struct UserAvatar: View {
private var url: URL?
private var borderColor: Color

private let defaultAvatarKeyword = "default"

@Binding private var image: UIImage?
init(url: String, image: Binding<UIImage?>, borderColor: Color = Theme.Colors.avatarStroke) {
if let rightUrl = URL(string: url) {
if url.contains(defaultAvatarKeyword) {
self.url = nil
} else if let rightUrl = URL(string: url) {
self.url = rightUrl
} else {
self.url = nil
Expand All @@ -227,7 +242,7 @@ struct UserAvatar: View {
}
} else {
KFImage(url)
.onFailureImage(CoreAssets.noCourseImage.image)
.onFailureImage(CoreAssets.noAvatar.image)
.resizable()
.scaledToFill()
.frame(width: 80, height: 80)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,11 +373,11 @@ final class EditProfileViewModelTests: XCTestCase {
name: "Test",
username: "Name",
dateJoined: Date(),
yearOfBirth: 1986,
yearOfBirth: 0,
country: "UA",
spokenLanguage: "UA",
shortBiography: "Bio",
isFullProfile: true,
isFullProfile: false,
email: ""
)

Expand Down Expand Up @@ -413,7 +413,7 @@ final class EditProfileViewModelTests: XCTestCase {
country: "UA",
spokenLanguage: "UA",
shortBiography: "Bio",
isFullProfile: true,
isFullProfile: false,
email: ""
)

Expand Down Expand Up @@ -530,7 +530,6 @@ final class EditProfileViewModelTests: XCTestCase {
// Verify(interactor, 0, .uploadProfilePicture(pictureData: .any))
Verify(interactor, 1, .deleteProfilePicture())
Verify(interactor, 1, .updateUserProfile(parameters: .any))
XCTAssertEqual(viewModel.inputImage?.cgImage, CoreAssets.noAvatar.image.cgImage)
}

func testSaveProfileUpdatesNoInternetError() async {
Expand Down Expand Up @@ -581,7 +580,7 @@ final class EditProfileViewModelTests: XCTestCase {

await viewModel.saveProfileUpdates()

Verify(interactor, 1, .uploadProfilePicture(pictureData: .any))
Verify(interactor, 0, .uploadProfilePicture(pictureData: .any))
Verify(interactor, 1, .updateUserProfile(parameters: .any))

XCTAssertTrue(viewModel.showError)
Expand Down Expand Up @@ -638,7 +637,7 @@ final class EditProfileViewModelTests: XCTestCase {

await Task.yield()

Verify(interactor, 1, .uploadProfilePicture(pictureData: .any))
Verify(interactor, 0, .uploadProfilePicture(pictureData: .any))
Verify(interactor, 1, .updateUserProfile(parameters: .any))

XCTAssertTrue(viewModel.showError)
Expand Down

0 comments on commit 54f1105

Please sign in to comment.