Skip to content

Commit

Permalink
feat :: [#102] 프로필 사진 업로드 로직 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
cyj513 committed Oct 15, 2024
1 parent cfe0418 commit 91dbe3c
Show file tree
Hide file tree
Showing 16 changed files with 154 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public enum UserDefaultKeys: String {
case pickerTimeMode
case userInfoData
case userNameData
case userProfileImageData
}

public struct UserDefaultStorage: UserDefault {
Expand Down
2 changes: 1 addition & 1 deletion Projects/Data/Sources/API/AuthAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ extension AuthAPI: PiCKAPI {
public typealias ErrorType = PiCKError

public var urlType: PiCKURL {
.user
return .user
}

public var urlPath: String {
Expand Down
2 changes: 1 addition & 1 deletion Projects/Data/Sources/API/BugAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ extension BugAPI: PiCKAPI {
public typealias ErrorType = PiCKError

public var urlType: PiCKURL {
.bug
return .bug
}

public var urlPath: String {
Expand Down
25 changes: 23 additions & 2 deletions Projects/Data/Sources/API/ProfileAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import AppNetwork
public enum ProfileAPI {
case fetchSimpleProfile
case fetchDetailProfile
case uploadProfileImage(image: Data)
}

extension ProfileAPI: PiCKAPI {
Expand All @@ -24,15 +25,35 @@ extension ProfileAPI: PiCKAPI {
return "/simple"
case .fetchDetailProfile:
return "/details"
case .uploadProfileImage:
return "/profile"
}
}

public var method: Moya.Method {
return .get
switch self {
case .uploadProfileImage:
return .patch
default:
return .get
}
}

public var task: Moya.Task {
return .requestPlain
switch self {
case .uploadProfileImage(let image):
var multiformData: [MultipartFormData] = []
multiformData.append(.init(
provider: .data(image),
name: "file",
fileName: "file.jpg",
mimeType: "file/jpg"
))

return .uploadMultipart(multiformData)
default:
return .requestPlain
}
}

public var pickHeader: TokenType {
Expand Down
3 changes: 3 additions & 0 deletions Projects/Data/Sources/DI/UseCaseAssembly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ public final class UseCaseAssembly: Assembly {
container.register(FetchDetailProfileUseCase.self) { resolver in
FetchDetailProfileUseCase(repository: resolver.resolve(ProfileRepository.self)!)
}
container.register(UploadProfileImageUseCase.self) { resolver in
UploadProfileImageUseCase(repository: resolver.resolve(ProfileRepository.self)!)
}
// bug
container.register(BugImageUploadUseCase.self) { resolver in
BugImageUploadUseCase(repository: resolver.resolve(BugRepository.self)!)
Expand Down
7 changes: 7 additions & 0 deletions Projects/Data/Sources/DataSource/ProfileDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Domain
protocol ProfileDataSource {
func fetchSimpleProfile() -> Single<Response>
func fetchDetailProfile() -> Single<Response>
func uploadProfileImage(image: Data) -> Completable
}

class ProfileDataSourceImpl: BaseDataSource<ProfileAPI>, ProfileDataSource {
Expand All @@ -23,4 +24,10 @@ class ProfileDataSourceImpl: BaseDataSource<ProfileAPI>, ProfileDataSource {
.filterSuccessfulStatusCodes()
}

func uploadProfileImage(image: Data) -> Completable {
return request(.uploadProfileImage(image: image))
.filterSuccessfulStatusCodes()
.asCompletable()
}

}
4 changes: 4 additions & 0 deletions Projects/Data/Sources/Repository/ProfileRepositoryImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ class ProfileRepositoryImpl: ProfileRepository {
.map { $0.toDomain() }
}

func uploadProfileImage(image: Data) -> Completable {
return remoteDataSource.uploadProfileImage(image: image)
}

}
1 change: 1 addition & 0 deletions Projects/Domain/Sources/Repository/ProfileRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ import RxSwift
public protocol ProfileRepository {
func fetchSimpleProfile() -> Single<SimpleProfileEntity>
func fetchDetailProfile() -> Single<DetailProfileEntity>
func uploadProfileImage(image: Data) -> Completable
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Foundation

import RxSwift

public class UploadProfileImageUseCase {
let repository: ProfileRepository

public init(repository: ProfileRepository) {
self.repository = repository
}

public func execute(image: Data) -> Completable {
return repository.uploadProfileImage(image: image)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import RxSwift
import RxCocoa
import RxGesture

import Kingfisher

import Core

public class PiCKProfileView: BaseView {
Expand All @@ -18,10 +20,13 @@ public class PiCKProfileView: BaseView {
)

public func setup(
image: UIImage,
image: String,
info: String
) {
self.profileImageView.image = image
self.profileImageView.kf.setImage(
with: URL(string: image),
placeholder: UIImage.profile
)
self.userInfoLabel.text = "대덕소프트웨어마이스터고\n\(info)"
}

Expand Down
3 changes: 2 additions & 1 deletion Projects/Presentation/Sources/DI/PresentationAssembly.swift
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ public final class PresentationAssembly: Assembly {
}
container.register(MyPageViewModel.self) { resolver in
MyPageViewModel(
profileUsecase: resolver.resolve(FetchDetailProfileUseCase.self)!
profileUsecase: resolver.resolve(FetchDetailProfileUseCase.self)!,
uploadProfileImageUseCase: resolver.resolve(UploadProfileImageUseCase.self)!
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,15 @@ public class AllTabViewController: BaseViewController<AllTabViewModel> {
}

public override func setLayoutData() {
let userInfoData = UserDefaultStorage.shared.get(forKey: .userInfoData) as? String
self.profileView.setup(image: .profile, info: userInfoData ?? "정보가 없는 사용자")
let userDefaultStorage = UserDefaultStorage.shared

let userInfoData = userDefaultStorage.get(forKey: .userInfoData) as? String
let userInfoImage = userDefaultStorage.get(forKey: .userProfileImageData) as? String

self.profileView.setup(
image: userInfoImage ?? "",
info: userInfoData ?? "정보가 없는 사용자"
)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,25 @@ import UIKit

import SnapKit
import Then

import RxSwift
import RxCocoa

import Kingfisher

import Core
import DesignSystem

public class MyPageViewController: BaseViewController<MyPageViewModel> {
private let profileImageView = UIImageView(image: .profile)
private var profileImageData = PublishRelay<Data>()

private let profileImageView = UIImageView().then {
$0.contentMode = .scaleToFill
$0.layer.cornerRadius = 40
$0.clipsToBounds = true
}
private let changeButton = UIButton(type: .system).then {
// $0.setTitle("변경하기", for: .normal)
$0.setTitle("", for: .normal)
$0.setTitle("변경하기", for: .normal)
$0.setTitleColor(.gray500, for: .normal)
$0.titleLabel?.font = .body1
}
Expand Down Expand Up @@ -47,17 +55,33 @@ public class MyPageViewController: BaseViewController<MyPageViewModel> {
}
public override func bind() {
let input = MyPageViewModel.Input(
viewWillAppear: viewWillAppearRelay.asObservable()
viewWillAppear: viewWillAppearRelay.asObservable(),
profileImage: profileImageData.asObservable()
)
let output = viewModel.transform(input: input)

output.profileData.asObservable()
.bind(onNext: { [weak self] profileData in
self?.userNameLabel.text = profileData.name
self?.userBirthDayLabel.text = "\(profileData.birthDay.toDate(type: .fullDate).toString(type: .fullDateKorForCalendar))"
self?.userSchoolIDLabel.text = "\(profileData.grade)학년 \(profileData.classNum)\(profileData.num)"
self?.userIDLabel.text = profileData.accountID
}).disposed(by: disposeBag)
.withUnretained(self)
.bind { owner, profileData in
owner.profileImageView.kf.setImage(
with: URL(string: profileData.profile ?? ""),
placeholder: UIImage.profile
)
owner.userNameLabel.text = profileData.name
owner.userBirthDayLabel.text = "\(profileData.birthDay.toDate(type: .fullDate).toString(type: .fullDateKorForCalendar))"
owner.userSchoolIDLabel.text = "\(profileData.grade)학년 \(profileData.classNum)\(profileData.num)"
owner.userIDLabel.text = profileData.accountID
}.disposed(by: disposeBag)
}
public override func bindAction() {
changeButton.rx.tap
.bind {
let picker = UIImagePickerController()
picker.sourceType = .photoLibrary
picker.allowsEditing = true
picker.delegate = self
self.present(picker, animated: true)
}.disposed(by: disposeBag)
}

public override func addView() {
Expand All @@ -72,6 +96,7 @@ public class MyPageViewController: BaseViewController<MyPageViewModel> {
profileImageView.snp.makeConstraints {
$0.centerX.equalToSuperview()
$0.top.equalTo(view.safeAreaLayoutGuide).offset(40)
$0.size.equalTo(80)
}
changeButton.snp.makeConstraints {
$0.centerX.equalToSuperview()
Expand Down Expand Up @@ -99,3 +124,16 @@ public class MyPageViewController: BaseViewController<MyPageViewModel> {
}

}

extension MyPageViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
public func imagePickerController(
_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]
) {
picker.dismiss(animated: true) {
let image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage
self.profileImageView.image = image
self.profileImageData.accept(info[UIImagePickerController.InfoKey.editedImage] as? Data ?? Data())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,19 @@ public class MyPageViewModel: BaseViewModel, Stepper {
public var steps = PublishRelay<Step>()

private let profileUsecase: FetchDetailProfileUseCase
private let uploadProfileImageUseCase: UploadProfileImageUseCase

public init(profileUsecase: FetchDetailProfileUseCase) {
public init(
profileUsecase: FetchDetailProfileUseCase,
uploadProfileImageUseCase: UploadProfileImageUseCase
) {
self.profileUsecase = profileUsecase
self.uploadProfileImageUseCase = uploadProfileImageUseCase
}

public struct Input {
let viewWillAppear: Observable<Void>
let profileImage: Observable<Data>
}
public struct Output {
let profileData: Signal<DetailProfileEntity>
Expand All @@ -38,6 +44,17 @@ public class MyPageViewModel: BaseViewModel, Stepper {
.bind(to: profileData)
.disposed(by: disposeBag)

input.profileImage
.flatMap { image in
self.uploadProfileImageUseCase.execute(image: image)
.catch {
print($0.localizedDescription)
return .never()
}
}
.subscribe()
.disposed(by: disposeBag)

return Output(profileData: profileData.asSignal())
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,15 @@ public class HomeViewController: BaseViewController<HomeViewModel> {
}

public override func setLayoutData() {
let userInfoData = UserDefaultStorage.shared.get(forKey: .userInfoData) as? String
self.profileView.setup(image: .profile, info: userInfoData ?? "정보가 없는 사용자")
let userDefaultStorage = UserDefaultStorage.shared

let userInfoData = userDefaultStorage.get(forKey: .userInfoData) as? String
let userInfoImage = userDefaultStorage.get(forKey: .userProfileImageData) as? String

self.profileView.setup(
image: userInfoImage ?? "",
info: userInfoData ?? "정보가 없는 사용자"
)
}

private func setupViewType(type: HomeViewType) {
Expand Down
6 changes: 4 additions & 2 deletions Projects/Presentation/Sources/Scene/Home/HomeViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,11 @@ public class HomeViewModel: BaseViewModel, Stepper {
}
}
.subscribe(onNext: { data in
let value = "\(data.grade)학년 \(data.classNum)\(data.num)\(data.name)"
self.userDefaultStorage.set(to: value, forKey: .userInfoData)
let infoValue = "\(data.grade)학년 \(data.classNum)\(data.num)\(data.name)"

self.userDefaultStorage.set(to: infoValue, forKey: .userInfoData)
self.userDefaultStorage.set(to: data.name, forKey: .userNameData)
// self.userDefaultStorage.set(to: data.profile, forKey: .userProfileImageData)
}).disposed(by: disposeBag)

input.viewWillAppear
Expand Down

0 comments on commit 91dbe3c

Please sign in to comment.