Skip to content
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

일기 작성 흐름 중 음악 검색 부분 작성 #165

Merged
merged 13 commits into from
Dec 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이런 식으로 전달하는 게 최선이지 싶습니다,, 더 좋은 방법을 저도 못떠올리겟네요ㅠ

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이번주의 주제로 삼아 볼까 싶기도 합니다.. ㅋㅋㅋㅋ

case .failure(let error):
self.musicInfoResult.onNext(.failure(error))
}
})
.disposed(by: disposeBag)
}
}
Loading