Skip to content

Commit

Permalink
Merge pull request #1300 from wakmusic/1296-duplicate-song-is-crash
Browse files Browse the repository at this point in the history
🔀 :: (#1296) 플레이리스트의 중복곡 처리
  • Loading branch information
baekteun authored Sep 22, 2024
2 parents 65bb58b + 4f0f8bb commit 9757292
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public final class PlayState {
private var subscription = Set<AnyCancellable>()
public var count: Int { playlist.count }
public var isEmpty: Bool { playlist.isEmpty }
public var currentPlaylist: [PlaylistItem] { playlist.list }
public var currentPlaylist: [PlaylistItem] { Array(playlist.list.uniqued()) }
public var listChangedPublisher: AnyPublisher<[PlaylistItem], Never> { playlist.subscribeListChanges() }

private init() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation
import SongsDomainInterface

public struct PlaylistItem: Equatable {
public struct PlaylistItem: Equatable, Hashable {
public let id: String
public let title: String
public let artist: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,13 @@ private extension MyPlaylistDetailReactor {
fetchPlaylistDetailUseCase.execute(id: key, type: .my)
.asObservable()
.flatMap { data -> Observable<Mutation> in
let songs = data.songs.map { PlaylistItemModel(
id: $0.id,
title: $0.title,
artist: $0.artist,
isSelected: false
) }
.uniqued()
return .concat([
Observable.just(Mutation.updateHeader(
PlaylistDetailHeaderModel(
Expand All @@ -220,28 +227,10 @@ private extension MyPlaylistDetailReactor {
)
)),
Observable.just(
Mutation.updatePlaylist(
data.songs.map {
PlaylistItemModel(
id: $0.id,
title: $0.title,
artist: $0.artist,
isSelected: false
)
}
)
Mutation.updatePlaylist(Array(songs))
),
Observable.just(
Mutation.updateBackUpPlaylist(
data.songs.map {
PlaylistItemModel(
id: $0.id,
title: $0.title,
artist: $0.artist,
isSelected: false
)
}
)
Mutation.updateBackUpPlaylist(Array(songs))
)
])
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ private extension UnknownPlaylistDetailReactor {
.asObservable()
.withUnretained(self)
.flatMap { owner, data -> Observable<Mutation> in
let songs = data.songs.uniqued()
return .concat([
Observable.just(Mutation.updateHeader(
PlaylistDetailHeaderModel(
Expand All @@ -181,7 +182,9 @@ private extension UnknownPlaylistDetailReactor {
songCount: data.songs.count
)
)),
Observable.just(Mutation.updateDataSource(data.songs)),
Observable.just(
Mutation.updateDataSource(Array(songs))
),
PreferenceManager.userInfo == nil ? .just(.updateSubscribeState(false)) : owner
.checkSubscription()
])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ final class ListSearchResultViewController: BaseReactorViewController<ListSearch
var bottomSheetView: BottomSheetView!

private let searchSortOptionComponent: SearchSortOptionComponent
private (set) var playlistDetailFactory: any PlaylistDetailFactory
private(set) var playlistDetailFactory: any PlaylistDetailFactory

private let searchGlobalScrollState: any SearchGlobalScrollProtocol

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Utility
final class BeforeSearchContentViewController: BaseReactorViewController<BeforeSearchReactor>, PlaylistDetailNavigator {
private let wakmusicRecommendComponent: WakmusicRecommendComponent
private let textPopupFactory: TextPopupFactory
private (set) var playlistDetailFactory: any PlaylistDetailFactory
private(set) var playlistDetailFactory: any PlaylistDetailFactory

private let tableView: UITableView = UITableView().then {
$0.register(RecentRecordTableViewCell.self, forCellReuseIdentifier: "RecentRecordTableViewCell")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import Foundation

public extension Sequence where Element: Hashable {
@inlinable
func uniqued() -> UniquedSequence<Self, Element> {
UniquedSequence(base: self, projection: { $0 })
}
}

public extension Sequence {
@inlinable
func uniqued<Subject: Hashable>(
on projection: (Element) throws -> Subject
) rethrows -> [Element] {
var seen: Set<Subject> = []
var result: [Element] = []
for element in self {
if try seen.insert(projection(element)).inserted {
result.append(element)
}
}
return result
}
}

public extension LazySequenceProtocol {
@inlinable
func uniqued<Subject: Hashable>(
on projection: @escaping (Element) -> Subject
) -> UniquedSequence<Self, Subject> {
UniquedSequence(base: self, projection: projection)
}
}
54 changes: 54 additions & 0 deletions Projects/Modules/Utility/Sources/Utils/UniquedSequence.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import Foundation

public struct UniquedSequence<Base: Sequence, Subject: Hashable> {
@usableFromInline
internal let base: Base

@usableFromInline
internal let projection: (Base.Element) -> Subject

@usableFromInline
internal init(base: Base, projection: @escaping (Base.Element) -> Subject) {
self.base = base
self.projection = projection
}
}

extension UniquedSequence: Sequence {
public struct Iterator: IteratorProtocol {
@usableFromInline
internal var base: Base.Iterator

@usableFromInline
internal let projection: (Base.Element) -> Subject

@usableFromInline
internal var seen: Set<Subject> = []

@usableFromInline
internal init(
base: Base.Iterator,
projection: @escaping (Base.Element) -> Subject
) {
self.base = base
self.projection = projection
}

@inlinable
public mutating func next() -> Base.Element? {
while let element = base.next() {
if seen.insert(projection(element)).inserted {
return element
}
}
return nil
}
}

@inlinable
public func makeIterator() -> Iterator {
Iterator(base: base.makeIterator(), projection: projection)
}
}

extension UniquedSequence: LazySequenceProtocol where Base: LazySequenceProtocol {}

0 comments on commit 9757292

Please sign in to comment.