Skip to content

Commit

Permalink
Merge branch 'develop' into fix/image-qa
Browse files Browse the repository at this point in the history
  • Loading branch information
k2645 committed Dec 4, 2024
2 parents 502e578 + 6a7dc63 commit 5609f49
Show file tree
Hide file tree
Showing 43 changed files with 259 additions and 122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,12 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
try registerUseCaseDependency()
try registerViewModelFactoryDependency()
} catch let error as MHCoreError {
MHLogger.error("\(error.description)")
MHLogger.error(error.description + #function)
} catch {
MHLogger.error("\(error.localizedDescription)")
MHLogger.error(error.localizedDescription + #function)
}
}

private func registerStorageDepedency() throws {
DIContainer.shared.register(CoreDataStorage.self, object: CoreDataStorage())

Expand Down Expand Up @@ -239,6 +240,10 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
TemporaryStoreMediaUseCase.self,
object: DefaultTemporaryStoreMediaUseCase(repository: mediaRepository)
)
DIContainer.shared.register(
DeleteTemporaryMediaUseCase.self,
object: DefaultDeleteTemporaryMediaUseCase(repository: mediaRepository)
)
}

private func registerViewModelFactoryDependency() throws {

Check warning on line 249 in MemorialHouse/MHApplication/MHApplication/Source/App/SceneDelegate.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Function Body Length Violation: Function body should span 50 lines or less excluding comments and whitespace: currently spans 87 lines (function_body_length)

Check warning on line 249 in MemorialHouse/MHApplication/MHApplication/Source/App/SceneDelegate.swift

View workflow job for this annotation

GitHub Actions / SwiftLint

Function Body Length Violation: Function body should span 50 lines or less excluding comments and whitespace: currently spans 87 lines (function_body_length)
Expand Down Expand Up @@ -315,6 +320,7 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// MARK: - EditBook ViewModel
let updateBookUseCase = try DIContainer.shared.resolve(UpdateBookUseCase.self)
let storeMediaUseCase = try DIContainer.shared.resolve(PersistentlyStoreMediaUseCase.self)
let deleteTemporaryMediaUseCase = try DIContainer.shared.resolve(DeleteTemporaryMediaUseCase.self)
let createMediaUseCase = try DIContainer.shared.resolve(CreateMediaUseCase.self)
let fetchMediaUseCase = try DIContainer.shared.resolve(FetchMediaUseCase.self)
let deleteMediaUseCase = try DIContainer.shared.resolve(DeleteMediaUseCase.self)
Expand All @@ -324,6 +330,7 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate {
fetchBookUseCase: fetchBookUseCase,
updateBookUseCase: updateBookUseCase,
storeMediaUseCase: storeMediaUseCase,
deleteTemporaryMediaUseCase: deleteTemporaryMediaUseCase,
createMediaUseCase: createMediaUseCase,
fetchMediaUseCase: fetchMediaUseCase,
deleteMediaUseCase: deleteMediaUseCase
Expand Down
16 changes: 16 additions & 0 deletions MemorialHouse/MHDomain/MHDomain/UseCase/DefaultMediaUseCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,19 @@ public struct DefaultTemporaryStoreMediaUseCase: TemporaryStoreMediaUseCase {
return try await repository.getURL(media: media, from: nil).get()
}
}

public struct DefaultDeleteTemporaryMediaUseCase: DeleteTemporaryMediaUseCase {
// MARK: - Property
let repository: MediaRepository

// MARK: - Initializer
public init(repository: MediaRepository) {
self.repository = repository
}

// MARK: - Method
public func execute(media: MediaDescription) async throws {
try await repository.delete(media: media, at: nil).get()
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ public protocol PersistentlyStoreMediaUseCase: Sendable {
public protocol TemporaryStoreMediaUseCase: Sendable {
func execute(media: MediaDescription) async throws -> URL
}

public protocol DeleteTemporaryMediaUseCase: Sendable {
func execute(media: MediaDescription) async throws
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,22 @@ final class CreateAudioViewController: UIViewController {
return button
}()
private let saveButton: UIButton = {
let button = UIButton(
frame: CGRect(origin: .zero, size: CGSize(width: 60, height: 21))
)
var attributedString = AttributedString(stringLiteral: "저장")
attributedString.font = UIFont.ownglyphBerry(size: 21)
attributedString.foregroundColor = UIColor.black
button.setAttributedTitle(NSAttributedString(attributedString), for: .normal)
let button = UIButton(frame: CGRect(origin: .zero, size: CGSize(width: 60, height: 21)))
button.contentHorizontalAlignment = .center
button.setAttributedTitle(
NSAttributedString(
string: "저장",
attributes: [.font: UIFont.ownglyphBerry(size: 21), .foregroundColor: UIColor.mhTitle]
),
for: .normal
)
button.setAttributedTitle(
NSAttributedString(
string: "저장",
attributes: [.font: UIFont.ownglyphBerry(size: 21), .foregroundColor: UIColor.systemGray2]
),
for: .disabled
)
return button
}()
// audio metering
Expand Down Expand Up @@ -98,7 +106,9 @@ final class CreateAudioViewController: UIViewController {
}

required init?(coder: NSCoder) {
guard let viewModelFactory = try? DIContainer.shared.resolve(CreateAudioViewModelFactory.self) else { return nil }
guard let viewModelFactory = try? DIContainer.shared.resolve(CreateAudioViewModelFactory.self) else {
return nil
}
self.viewModel = viewModelFactory.make { _ in }
super.init(nibName: nil, bundle: nil)
}
Expand All @@ -112,7 +122,7 @@ final class CreateAudioViewController: UIViewController {
configureAddSubviews()
configureConstraints()
configureAddActions()
input.send(.viewDidLoad)
input.send(.prepareTemporaryAudio)
}

// MARK: - Setup
Expand All @@ -128,7 +138,7 @@ final class CreateAudioViewController: UIViewController {

for index in 0..<numberOfBars {
let upMeteringLayer = CALayer()
upMeteringLayer.backgroundColor = UIColor.orange.cgColor
upMeteringLayer.backgroundColor = UIColor.mhOrange.cgColor
upMeteringLayer.frame = CGRect(
x: index * (width + barSpacing),
y: Int(volumeHalfHeight),
Expand Down Expand Up @@ -264,19 +274,11 @@ final class CreateAudioViewController: UIViewController {

// MARK: - Helper
private func requestMicrophonePermission() {
let alert = UIAlertController(
title: "마이크 권한 필요",
message: "설정에서 마이크 권한을 허용해주세요.",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .default) { [weak self] _ in
self?.dismiss(animated: true)
})
Task {
AVAudioSession.sharedInstance().requestRecordPermission { @Sendable granted in
Task { @MainActor in
if !granted {
self.present(alert, animated: true, completion: nil)
self.showRedirectSettingAlert(with: .audio)
}
}
}
Expand Down Expand Up @@ -310,6 +312,8 @@ final class CreateAudioViewController: UIViewController {
audioButton.setWidthAndHeight(width: 32, height: 32)
audioButton.setCenter(view: audioButtonBackground)
NSLayoutConstraint.activate(audioButton.constraints)

saveButton.isEnabled = false
}

private func stopRecording() {
Expand All @@ -327,6 +331,8 @@ final class CreateAudioViewController: UIViewController {
audioButton.setWidthAndHeight(width: 48, height: 48)
audioButton.setCenter(view: audioButtonBackground)
NSLayoutConstraint.activate(audioButton.constraints)

saveButton.isEnabled = true
}

private func updateAudioMetering() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import MHDomain
public final class CreateAudioViewModel: ViewModelType {
// MARK: - Type
enum Input {
case viewDidLoad
case prepareTemporaryAudio
case audioButtonTapped
case saveButtonTapped
case recordCancelled
Expand Down Expand Up @@ -39,8 +39,8 @@ public final class CreateAudioViewModel: ViewModelType {
func transform(input: AnyPublisher<Input, Never>) -> AnyPublisher<Output, Never> {
input.sink { [weak self] event in
switch event {
case .viewDidLoad:
Task { await self?.viewDidLoad() }
case .prepareTemporaryAudio:
Task { await self?.prepareTemporaryAudio() }
case .audioButtonTapped:
self?.audioButtonTapped()
case .saveButtonTapped:
Expand All @@ -54,14 +54,14 @@ public final class CreateAudioViewModel: ViewModelType {
}

// MARK: - Helper
private func viewDidLoad() async {
private func prepareTemporaryAudio() async {
let mediaDescription = MediaDescription(type: .audio)
self.mediaDescription = mediaDescription
do {
let url = try await temporaryStoreMediaUsecase.execute(media: mediaDescription)
output.send(.audioFileURL(url: url))
} catch {
MHLogger.error("Error in store audio file url: \(error.localizedDescription)")
MHLogger.error(error.localizedDescription + #function)
completion(nil)
output.send(.recordCompleted)
}
Expand All @@ -81,6 +81,9 @@ public final class CreateAudioViewModel: ViewModelType {
output.send(.audioStop)
}
output.send(.recordCompleted)
completion(mediaDescription)

if withCompletion {
completion(mediaDescription)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,3 @@ public struct CreateAudioViewModelFactory {
)
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,14 @@ final class MHAudioPlayerView: UIView {
private var progressViewConstraints: [NSLayoutConstraint] = []
private let audioStateButton: UIButton = {
let button = UIButton()
button.setImage(UIImage(systemName: "play.fill"), for: .normal)
button.setImage(UIImage(systemName: "play.fill")?
.withTintColor(.captionPlaceHolder, renderingMode: .alwaysOriginal), for: .normal)
return button
}()
private let playImage = UIImage(systemName: "play.fill")
private let pauseImage = UIImage(systemName: "pause.fill")
private let playImage = UIImage(systemName: "play.fill")?
.withTintColor(.captionPlaceHolder, renderingMode: .alwaysOriginal)
private let pauseImage = UIImage(systemName: "pause.fill")?
.withTintColor(.captionPlaceHolder, renderingMode: .alwaysOriginal)
private let audioPlayTimeLabel: UILabel = {
let label = UILabel()
label.text = "00:00"
Expand All @@ -59,6 +62,7 @@ final class MHAudioPlayerView: UIView {

return label
}()
private var playerWidth: CGFloat = 0

public override init(frame: CGRect) {
super.init(frame: frame)
Expand Down Expand Up @@ -109,7 +113,7 @@ final class MHAudioPlayerView: UIView {
)

audioProgressView.translatesAutoresizingMaskIntoConstraints = false
progressViewWidthConstraint = audioProgressView.widthAnchor.constraint(equalToConstant: 290)
progressViewWidthConstraint = audioProgressView.widthAnchor.constraint(equalToConstant: frame.width - 9)
NSLayoutConstraint.activate([
audioProgressView.topAnchor.constraint(equalTo: topAnchor, constant: 29),
audioProgressView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 4),
Expand Down Expand Up @@ -156,20 +160,21 @@ final class MHAudioPlayerView: UIView {

private func updatePlayAudioProgress() {
guard let audioPlayer else { return }
let width = ceil(Float(audioPlayer.currentTime) / Float(audioPlayer.duration) * Float(299))
let width = ceil(Float(audioPlayer.currentTime) / Float(audioPlayer.duration) * Float(frame.width))

progressViewWidthConstraint?.constant = CGFloat(width)
self.layoutIfNeeded()
let seconds = ceil(Double(audioPlayer.currentTime))
self.setTimeLabel(seconds: Int(seconds))
}

private func startTimer() {
timer?.invalidate()
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
guard let audioPlayer = self?.audioPlayer else { return }
Task { @MainActor in
if audioPlayer.isPlaying {
self?.updatePlayAudioProgress()
self?.setTimeLabel(seconds: Int(audioPlayer.currentTime))
}
}
}
Expand All @@ -196,10 +201,8 @@ extension MHAudioPlayerView: AVAudioPlayerDelegate {

stopTimer()

progressViewWidthConstraint?.constant = CGFloat(290)
UIView.animate(withDuration: 0) {
self.layoutIfNeeded()
}
progressViewWidthConstraint?.constant = CGFloat(frame.width - 9)
self.layoutIfNeeded()
}
}
}
Expand All @@ -209,13 +212,13 @@ extension MHAudioPlayerView: @preconcurrency MediaAttachable {
audioPlayer = try? AVAudioPlayer(data: data)
guard let audioPlayer else { return }
audioPlayer.delegate = self
self.setTimeLabel(seconds: Int(audioPlayer.duration.rounded()))
self.setTimeLabel(seconds: Int(ceil(Double(audioPlayer.duration))))
}

func configureSource(with mediaDescription: MediaDescription, url: URL) {
audioPlayer = try? AVAudioPlayer(contentsOf: url)
guard let audioPlayer else { return }
audioPlayer.delegate = self
self.setTimeLabel(seconds: Int(audioPlayer.duration.rounded()))
self.setTimeLabel(seconds: Int(ceil(Double(audioPlayer.duration))))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ final class BookViewController: UIViewController {
let editBookViewController = EditBookViewController(viewModel: editBookViewModel, mode: .modify)
navigationController?.pushViewController(editBookViewController, animated: true)
} catch {
MHLogger.error(error)
MHLogger.error(error.localizedDescription + #function)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ final class BookCoverViewController: UIViewController {
configureAddSubviews()
configureConstraints()
configureAction()
createInput.send(.viewDidAppear)
createInput.send(.setBookCover)
modifyInput.send(.loadBookCover)
}

Expand Down Expand Up @@ -233,7 +233,7 @@ final class BookCoverViewController: UIViewController {
let editBookViewController = EditBookViewController(viewModel: editBookViewModel)
navigationController?.pushViewController(editBookViewController, animated: true)
} catch {
MHLogger.error(error)
MHLogger.error(error.localizedDescription + #function)
}
}
}
Expand Down Expand Up @@ -489,7 +489,7 @@ extension BookCoverViewController: BookCategoryViewControllerDelegate {

self.present(navigationController, animated: true)
} catch {
MHLogger.error(error)
MHLogger.error(error.localizedDescription + #function)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Photos
// TODO: - 에러 처리 필요
final class CreateBookCoverViewModel: ViewModelType {
enum Input {
case viewDidAppear
case setBookCover
case changedBookTitle(title: String?)
case changedBookColor(colorIndex: Int)
case changedBookImage(bookImage: Data?)
Expand Down Expand Up @@ -60,7 +60,7 @@ final class CreateBookCoverViewModel: ViewModelType {
func transform(input: AnyPublisher<Input, Never>) -> AnyPublisher<Output, Never> {
input.sink { [weak self] event in
switch event {
case .viewDidAppear:
case .setBookCover:
self?.setBookColor(nowIndex: 0)
Task { try await self?.fetchMemorialHouseName() }
case .changedBookTitle(let title):
Expand Down
Loading

0 comments on commit 5609f49

Please sign in to comment.