Skip to content

Commit

Permalink
Merge pull request #165 from boostcampwm-2022/feature/diary-edit-flow
Browse files Browse the repository at this point in the history
일기 작성 흐름 중 음악 검색 부분 작성
  • Loading branch information
radiantchoi authored Dec 7, 2022
2 parents d76b7f6 + cd0fd14 commit 760c97e
Show file tree
Hide file tree
Showing 12 changed files with 253 additions and 120 deletions.
22 changes: 21 additions & 1 deletion Segno/Segno.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
4F4E0D7629252236005ABA8F /* LoginEndpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F4E0D7529252236005ABA8F /* LoginEndpoint.swift */; };
4F4E0D79292522B7005ABA8F /* BaseURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F4E0D78292522B7005ABA8F /* BaseURL.swift */; };
4F4E0D7B29252526005ABA8F /* TokenDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F4E0D7A29252526005ABA8F /* TokenDTO.swift */; };
4F5291DE293F065D00DF930A /* DiaryEditViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F5291DD293F065D00DF930A /* DiaryEditViewModel.swift */; };
4F589DD6293FB9AB00DB39E5 /* ShazamSongDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F589DD5293FB9AB00DB39E5 /* ShazamSongDTO.swift */; };
4F589DD9293FBA0900DB39E5 /* ShazamError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F589DD8293FBA0900DB39E5 /* ShazamError.swift */; };
4F6F74B1292C9BF3007E7AC1 /* UserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F6F74B0292C9BF3007E7AC1 /* UserInfo.swift */; };
4F9A001B292227D7007D9057 /* NetworkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F9A001A292227D7007D9057 /* NetworkManager.swift */; };
4F9A001D29222B1B007D9057 /* Endpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F9A001C29222B1B007D9057 /* Endpoint.swift */; };
Expand Down Expand Up @@ -118,6 +121,9 @@
4F4E0D7529252236005ABA8F /* LoginEndpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginEndpoint.swift; sourceTree = "<group>"; };
4F4E0D78292522B7005ABA8F /* BaseURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseURL.swift; sourceTree = "<group>"; };
4F4E0D7A29252526005ABA8F /* TokenDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenDTO.swift; sourceTree = "<group>"; };
4F5291DD293F065D00DF930A /* DiaryEditViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiaryEditViewModel.swift; sourceTree = "<group>"; };
4F589DD5293FB9AB00DB39E5 /* ShazamSongDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShazamSongDTO.swift; sourceTree = "<group>"; };
4F589DD8293FBA0900DB39E5 /* ShazamError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShazamError.swift; sourceTree = "<group>"; };
4F6F74B0292C9BF3007E7AC1 /* UserInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserInfo.swift; sourceTree = "<group>"; };
4F9A001A292227D7007D9057 /* NetworkManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkManager.swift; sourceTree = "<group>"; };
4F9A001C29222B1B007D9057 /* Endpoint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Endpoint.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -340,6 +346,7 @@
children = (
9841D61A2926131200318EA9 /* LoginViewModel.swift */,
982B3B7E292E68FB0077A44B /* DiaryDetailViewModel.swift */,
4F5291DD293F065D00DF930A /* DiaryEditViewModel.swift */,
988414D829235345007C9132 /* DiaryCollectionViewModel.swift */,
983AE9D72935CEE2006547BD /* SettingsViewModel.swift */,
66A8CF602935F44100C17F84 /* MyPageViewModel.swift */,
Expand Down Expand Up @@ -391,11 +398,11 @@
4F31779F291BF1780019BDFC /* Network */ = {
isa = PBXGroup;
children = (
4F589DD7293FB9F300DB39E5 /* Errors */,
4F4E0D77292522AC005ABA8F /* Namespaces */,
4FA324292923646200DB04D5 /* Endpoints */,
4F9A001A292227D7007D9057 /* NetworkManager.swift */,
4F9A001C29222B1B007D9057 /* Endpoint.swift */,
4F9A001E29222C97007D9057 /* NetworkError.swift */,
);
path = Network;
sourceTree = "<group>";
Expand Down Expand Up @@ -423,6 +430,15 @@
path = Namespaces;
sourceTree = "<group>";
};
4F589DD7293FB9F300DB39E5 /* Errors */ = {
isa = PBXGroup;
children = (
4F9A001E29222C97007D9057 /* NetworkError.swift */,
4F589DD8293FBA0900DB39E5 /* ShazamError.swift */,
);
path = Errors;
sourceTree = "<group>";
};
4FA3242429235FF800DB04D5 /* DTO */ = {
isa = PBXGroup;
children = (
Expand All @@ -432,6 +448,7 @@
4F4E0D7A29252526005ABA8F /* TokenDTO.swift */,
66A8CF6A2937947A00C17F84 /* UserDetailDTO.swift */,
791529DB29332CF2005A8DDB /* ImageDTO.swift */,
4F589DD5293FB9AB00DB39E5 /* ShazamSongDTO.swift */,
);
path = DTO;
sourceTree = "<group>";
Expand Down Expand Up @@ -599,6 +616,7 @@
66A8CF6B2937947A00C17F84 /* UserDetailDTO.swift in Sources */,
4F9A001B292227D7007D9057 /* NetworkManager.swift in Sources */,
9894EAF529373385005F2B15 /* SettingsUseCase.swift in Sources */,
4F5291DE293F065D00DF930A /* DiaryEditViewModel.swift in Sources */,
9841D6172925FACC00318EA9 /* LoginUseCase.swift in Sources */,
66A8CF6D29379A9900C17F84 /* UserDetailEndpoint.swift in Sources */,
4FEBFAAD291CF62E00E78139 /* DiaryDetail.swift in Sources */,
Expand All @@ -608,6 +626,7 @@
988414AE2922235B007C9132 /* LocalUtilityRepository.swift in Sources */,
66A8CF612935F44100C17F84 /* MyPageViewModel.swift in Sources */,
988414D929235345007C9132 /* DiaryCollectionViewModel.swift in Sources */,
4F589DD6293FB9AB00DB39E5 /* ShazamSongDTO.swift in Sources */,
4FEBFAAF291CF9F300E78139 /* MusicInfo.swift in Sources */,
4FEBFAAB291CF30E00E78139 /* DiaryListItem.swift in Sources */,
7918380829233F7100BC6992 /* UIButton+.swift in Sources */,
Expand Down Expand Up @@ -640,6 +659,7 @@
98FDF8A1292F56580083FA05 /* Location.swift in Sources */,
7940FB33292E065F00276EFC /* DiaryDetailUseCase.swift in Sources */,
6692A9EF292F605E00DDA835 /* SettingsViewController.swift in Sources */,
4F589DD9293FBA0900DB39E5 /* ShazamError.swift in Sources */,
666E6F8E291CFADD00CECD4B /* MyPageViewController.swift in Sources */,
4F6F74B1292C9BF3007E7AC1 /* UserInfo.swift in Sources */,
98FDF8A5292F7A350083FA05 /* UIView+.swift in Sources */,
Expand Down
4 changes: 2 additions & 2 deletions Segno/Segno/Application/AppCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ final class AppCoordinator: Coordinator {

func start() {
// TODO: login이 안되어있으면 LoginCoordinator 실행
// startLoginCoordinator()
startLoginCoordinator()
// TODO: login이 되어있으면 TabBarCoordinator 실행
startTabBarCoordinator()
// startTabBarCoordinator()
}

func startLoginCoordinator() {
Expand Down
File renamed without changes.
25 changes: 25 additions & 0 deletions Segno/Segno/Data/Network/Errors/ShazamError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// ShazamError.swift
// Segno
//
// Created by Gordon Choi on 2022/12/07.
//

import Foundation

enum ShazamError: Error, LocalizedError {
case recordDenied
case unknown
case matchFailed

var errorDescription: String {
switch self {
case .recordDenied:
return "Record permission is denied. Please enable it in Settings."
case .matchFailed:
return "No song found or internet connection is bad."
case .unknown:
return "Unknown error occured."
}
}
}
31 changes: 31 additions & 0 deletions Segno/Segno/Data/Repository/DTO/ShazamSongDTO.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// ShazamSongDTO.swift
// Segno
//
// Created by Gordon Choi on 2022/12/07.
//

import Foundation
import ShazamKit

struct ShazamSongDTO {
let isrc: String
let title: String
let artist: String
let album: String
let imageURL: URL?

init?(mediaItem: SHMatchedMediaItem) {
guard let isrc = mediaItem.isrc,
let title = mediaItem.title,
let artist = mediaItem.artist,
let album = mediaItem.album
else { return nil }

self.isrc = isrc
self.title = title
self.artist = artist
self.album = album
self.imageURL = mediaItem.artworkURL
}
}
36 changes: 32 additions & 4 deletions Segno/Segno/Data/Repository/MusicRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,47 @@
import RxSwift

protocol MusicRepository {
func searchMusic()
var shazamSearchResult: PublishSubject<ShazamSearchResult> { get set }

func startSearchingMusic()
func stopSearchingMusic()
func playMusic()
}

final class MusicRepositoryImpl: MusicRepository {
private let shazamSession = ShazamSession()
private let musicSession = MusicSession()
private let shazamSession: ShazamSession
private let musicSession: MusicSession
private let disposeBag = DisposeBag()

var shazamSearchResult = PublishSubject<ShazamSearchResult>()

func searchMusic() {
init(shazamSession: ShazamSession = ShazamSession(),
musicSession: MusicSession = MusicSession()) {
self.shazamSession = shazamSession
self.musicSession = musicSession

subscribeSearchresult()
}

func startSearchingMusic() {
shazamSession.start()
}

func stopSearchingMusic() {
shazamSession.stop()
}

func playMusic() {

}
}

extension MusicRepositoryImpl {
private func subscribeSearchresult() {
shazamSession.result
.subscribe(onNext: {
self.shazamSearchResult.onNext($0)
})
.disposed(by: disposeBag)
}
}
81 changes: 7 additions & 74 deletions Segno/Segno/Data/Session/ShazamSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import ShazamKit

import RxSwift

typealias ShazamSearchResult = Result<ShazamSong, ShazamError>
typealias ShazamSearchResult = Result<ShazamSongDTO, ShazamError>

final class ShazamSession: NSObject {
var result = PublishSubject<ShazamSearchResult>()
var isSearching = BehaviorSubject(value: false)
private let disposeBag = DisposeBag()

private lazy var audioSession: AVAudioSession = .sharedInstance()
Expand All @@ -27,51 +26,26 @@ final class ShazamSession: NSObject {
super.init()

session.delegate = self
bindRecord()
}

func bindRecord() {
isSearching
.subscribe(onNext: {
switch $0 {
case true:
self.start()
case false:
self.stop()
}
})
.disposed(by: disposeBag)
}

func toggleSearch() {
guard let currentState = try? isSearching.value() else { return }

switch currentState {
case true:
isSearching.onNext(false)
case false:
isSearching.onNext(true)
}
}

func start() {
switch audioSession.recordPermission {
case .granted:
record()
case .denied:
isSearching.onNext(false)
stop()
result.onNext(.failure(.recordDenied))
case .undetermined:
audioSession.requestRecordPermission { granted in
if granted {
self.record()
} else {
self.isSearching.onNext(false)
self.stop()
self.result.onNext(.failure(.recordDenied))
}
}
@unknown default:
isSearching.onNext(false)
stop()
result.onNext(.failure(.unknown))
}
}
Expand All @@ -97,10 +71,10 @@ final class ShazamSession: NSObject {

extension ShazamSession: SHSessionDelegate {
func session(_ session: SHSession, didFind match: SHMatch) {
isSearching.onNext(false)
stop()

guard let mediaItem = match.mediaItems.first,
let shazamSong = ShazamSong(mediaItem: mediaItem) else {
let shazamSong = ShazamSongDTO(mediaItem: mediaItem) else {
result.onNext(.failure(.matchFailed))
return
}
Expand All @@ -109,48 +83,7 @@ extension ShazamSession: SHSessionDelegate {
}

func session(_ session: SHSession, didNotFindMatchFor signature: SHSignature, error: Error?) {
isSearching.onNext(false)
stop()
result.onNext(.failure(.matchFailed))
}
}

// TODO: DTO가 될지 안 될지 판단해서, 파일로 따로 빼 주기
struct ShazamSong {
let isrc: String
let title: String
let artist: String
let album: String
let imageURL: URL?

init?(mediaItem: SHMatchedMediaItem) {
guard let isrc = mediaItem.isrc,
let title = mediaItem.title,
let artist = mediaItem.artist,
let album = mediaItem.album
else { return nil }

self.isrc = isrc
self.title = title
self.artist = artist
self.album = album
self.imageURL = mediaItem.artworkURL
}
}

// TODO: 파일로 빼 주기
enum ShazamError: Error, LocalizedError {
case recordDenied
case unknown
case matchFailed

var errorDescription: String {
switch self {
case .recordDenied:
return "Record permission is denied. Please enable it in Settings."
case .matchFailed:
return "No song found or internet connection is bad."
case .unknown:
return "Unknown error occured."
}
}
}
44 changes: 38 additions & 6 deletions Segno/Segno/Domain/UseCase/SearchMusicUseCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,48 @@

import RxSwift

typealias MusicInfoResult = Result<MusicInfo, Error>

protocol SearchMusicUseCase {
func searchMusic() -> Single<MusicInfo>
var musicInfoResult: PublishSubject<MusicInfoResult> { get set }

func startSearching()
func stopSearching()
}

final class SearchMusicUseCaseImpl: SearchMusicUseCase {
func searchMusic() -> Single<MusicInfo> {
// 음악을 검색해줄 것을 레포지토리에 요청
private let disposeBag = DisposeBag()

let musicRepository: MusicRepository
var musicInfoResult = PublishSubject<MusicInfoResult>()

init(musicRepository: MusicRepository = MusicRepositoryImpl()) {
self.musicRepository = musicRepository

return Single.create { _ in
return Disposables.create()
}
subscribeShazamResult()
}

func startSearching() {
musicRepository.startSearchingMusic()
}

func stopSearching() {
musicRepository.stopSearchingMusic()
}
}

extension SearchMusicUseCaseImpl {
private func subscribeShazamResult() {
musicRepository.shazamSearchResult
.subscribe(onNext: {
switch $0 {
case .success(let shazamSongDTO):
let musicInfo = MusicInfo(shazamSong: shazamSongDTO)
self.musicInfoResult.onNext(.success(musicInfo))
case .failure(let error):
self.musicInfoResult.onNext(.failure(error))
}
})
.disposed(by: disposeBag)
}
}
Loading

0 comments on commit 760c97e

Please sign in to comment.