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

๐Ÿ”€ :: (#1306) Long Press ํŽธ์ง‘๋ชจ๋“œ ์ง„์ž…์  ์ถ”๊ฐ€ #1307

Merged
merged 4 commits into from
Oct 12, 2024
8 changes: 4 additions & 4 deletions Projects/App/Support/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@
<false/>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>naversearchapp</string>
<string>naversearchthirdlogin</string>
<string>naversearchapp</string>
<string>naversearchthirdlogin</string>
<string>youtube</string>
<string>youtubemusic</string>
</array>
Expand All @@ -74,8 +74,8 @@
<string>$(BASE_DEV_URL)</string>
<key>BASE_PROD_URL</key>
<string>$(BASE_PROD_URL)</string>
<key>CDN_DOMAIN_URL</key>
<string>$(CDN_DOMAIN_URL)</string>
<key>CDN_DOMAIN_URL</key>
<string>$(CDN_DOMAIN_URL)</string>
<key>GOOGLE_CLIENT_ID</key>
<string>$(GOOGLE_CLIENT_ID)</string>
<key>GOOGLE_URL_SCHEME</key>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ final class MyPlaylistDetailReactor: Reactor {
case editButtonDidTap
case privateButtonDidTap
case completionButtonDidTap
case didLongPressedPlaylist(IndexPath)
case restore
case itemDidMoved(Int, Int)
case forceSave
Expand Down Expand Up @@ -120,6 +121,9 @@ final class MyPlaylistDetailReactor: Reactor {
case .editButtonDidTap:
return beginEditing()

case let .didLongPressedPlaylist(indexPath):
return didLongPressedPlaylist(indexPath: indexPath)

case .privateButtonDidTap:
return updatePrivate()

Expand Down Expand Up @@ -244,6 +248,14 @@ private extension MyPlaylistDetailReactor {
])
}

func didLongPressedPlaylist(indexPath: IndexPath) -> Observable<Mutation> {
guard !currentState.isEditing else { return .empty() }
return .concat(
beginEditing(),
updateItemSelected(indexPath.row)
)
}

func endEditingWithSave() -> Observable<Mutation> {
let state = currentState
let currentPlaylists = state.playlistModels
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ final class MyPlaylistDetailViewController: BaseReactorViewController<MyPlaylist
$0.tableHeaderView = headerView
$0.separatorStyle = .none
$0.contentInset = .init(top: .zero, left: .zero, bottom: 60.0, right: .zero)
$0.allowsSelectionDuringEditing = true
}

private lazy var completionButton: RectangleButton = RectangleButton().then {
Expand Down Expand Up @@ -159,10 +160,6 @@ final class MyPlaylistDetailViewController: BaseReactorViewController<MyPlaylist
}
}

override func configureUI() {
super.configureUI()
}

override func bind(reactor: MyPlaylistDetailReactor) {
super.bind(reactor: reactor)
tableView.rx.setDelegate(self)
Expand Down Expand Up @@ -256,13 +253,17 @@ final class MyPlaylistDetailViewController: BaseReactorViewController<MyPlaylist

tableView.rx.itemSelected
.bind(with: self) { owner, indexPath in
if owner.reactor?.currentState.isEditing == true {
owner.tableView.deselectRow(at: IndexPath(row: indexPath.row, section: 0), animated: false)
owner.reactor?.action.onNext(.itemDidTap(indexPath.row))
} else {
guard let model = owner.dataSource.itemIdentifier(for: indexPath) else { return }

guard let model = owner.dataSource.itemIdentifier(for: indexPath) else { return }

PlayState.shared.append(item: .init(id: model.id, title: model.title, artist: model.artist))
let playlistIDs = PlayState.shared.currentPlaylist
.map(\.id)
owner.songDetailPresenter.present(ids: playlistIDs, selectedID: model.id)
PlayState.shared.append(item: .init(id: model.id, title: model.title, artist: model.artist))
let playlistIDs = PlayState.shared.currentPlaylist
.map(\.id)
owner.songDetailPresenter.present(ids: playlistIDs, selectedID: model.id)
}
}
.disposed(by: disposeBag)
}
Expand Down Expand Up @@ -533,6 +534,21 @@ extension MyPlaylistDetailViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false // ํŽธ์ง‘๋ชจ๋“œ ์‹œ ์…€์˜ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ์—†์• ๋ ค๋ฉด false๋ฅผ ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค.
}

func tableView(
_ tableView: UITableView,
contextMenuConfigurationForRowAt indexPath: IndexPath,
point: CGPoint
) -> UIContextMenuConfiguration? {
if reactor?.currentState.isEditing == true {
return nil
} else {
return UIContextMenuConfiguration(identifier: nil, previewProvider: { [reactor] in
reactor?.action.onNext(.didLongPressedPlaylist(indexPath))
return nil
})
}
}
}

/// ์ „์ฒด์žฌ์ƒ , ๋žœ๋ค ์žฌ์ƒ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ
Expand Down Expand Up @@ -585,11 +601,6 @@ extension MyPlaylistDetailViewController: PlaylistTableViewCellDelegate {
playPlatform: model.title.isContainShortsTagTitle ? .youtube : .automatic
).play()
}

func superButtonTapped(index: Int) {
tableView.deselectRow(at: IndexPath(row: index, section: 0), animated: false)
reactor?.action.onNext(.itemDidTap(index))
}
}

/// swipe pop ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ , ํŽธ์ง‘๋ชจ๋“œ ์‹œ ๋ง‰๊ธฐ
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,21 @@ extension PlaylistViewController: UITableViewDelegate {
}
return proposedDestinationIndexPath
}

public func tableView(
_ tableView: UITableView,
contextMenuConfigurationForRowAt indexPath: IndexPath,
point: CGPoint
) -> UIContextMenuConfiguration? {
if output.editState.value == true {
return nil
} else {
return UIContextMenuConfiguration(identifier: nil, previewProvider: { [didLongPressedSongSubject] in
didLongPressedSongSubject.onNext(indexPath.row)
return nil
})
}
}
}

extension PlaylistViewController: PlaylistTableViewCellDelegate {
Expand All @@ -132,8 +147,4 @@ extension PlaylistViewController: PlaylistTableViewCellDelegate {
playPlatform: model.title.isContainShortsTagTitle ? .youtube : .automatic
).play()
}

func superButtonTapped(index: Int) {
tappedCellIndex.onNext(index)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public final class PlaylistViewController: UIViewController, SongCartViewType {
var isSelectedAllSongs = PublishSubject<Bool>()
var tappedAddPlaylist = PublishSubject<Void>()
var tappedRemoveSongs = PublishSubject<Void>()
var didLongPressedSongSubject = PublishSubject<Int>()

private(set) var containSongsFactory: any ContainSongsFactory
private(set) var songDetailPresenter: any SongDetailPresentable
Expand All @@ -48,7 +49,8 @@ public final class PlaylistViewController: UIViewController, SongCartViewType {
selectAllSongsButtonDidTapEvent: isSelectedAllSongs.asObservable(),
addPlaylistButtonDidTapEvent: tappedAddPlaylist.asObservable(),
removeSongsButtonDidTapEvent: tappedRemoveSongs.asObservable(),
itemMovedEvent: playlistView.playlistTableView.rx.itemMoved.asObservable()
itemMovedEvent: playlistView.playlistTableView.rx.itemMoved.asObservable(),
didLongPressedSongEvent: didLongPressedSongSubject
)
lazy var output = self.viewModel.transform(from: input)

Expand Down Expand Up @@ -220,18 +222,31 @@ private extension PlaylistViewController {

playlistView.playlistTableView.rx.itemSelected
.withLatestFrom(output.playlists) { ($0, $1) }
.map { $0.1[$0.0.row] }
.bind(with: self, onNext: { [songDetailPresenter] owner, item in
let currentSongs = output.playlists.value
.map(\.id)

owner.dismiss(animated: true) {
songDetailPresenter.present(
ids: Array(currentSongs),
selectedID: item.id
)
.bind(with: self) { [
songDetailPresenter,
isEditingSubject = output.editState,
tappedCellIndex
] owner, item in

let isEditing = isEditingSubject.value
let (indexPath, playlists) = item

if isEditing {
tappedCellIndex.onNext(indexPath.row)
} else {
guard let selectedSong = playlists[safe: indexPath.row] else { return }

let currentSongs = playlists
.map(\.id)

owner.dismiss(animated: true) {
songDetailPresenter.present(
ids: Array(currentSongs),
selectedID: selectedSong.id
)
}
}
})
}
.disposed(by: disposeBag)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ final class PlaylistViewModel: ViewModelType {
let addPlaylistButtonDidTapEvent: Observable<Void>
let removeSongsButtonDidTapEvent: Observable<Void>
let itemMovedEvent: Observable<(sourceIndex: IndexPath, destinationIndex: IndexPath)>
let didLongPressedSongEvent: Observable<Int>
}

struct Output {
Expand Down Expand Up @@ -152,6 +153,23 @@ final class PlaylistViewModel: ViewModelType {
playlists.insert(movedData, at: destIndex)
output.playlists.accept(playlists)
}.disposed(by: disposeBag)

input.didLongPressedSongEvent
.compactMap { output.playlists.value[safe: $0] }
.bind(with: self) { owner, item in
owner.isEditing.toggle()

var mutableSelectedSongIds = output.selectedSongIds.value
if mutableSelectedSongIds.contains(item.id) {
mutableSelectedSongIds.remove(item.id)
} else {
mutableSelectedSongIds.insert(item.id)
}

output.editState.send(owner.isEditing)
output.selectedSongIds.accept(mutableSelectedSongIds)
}
.disposed(by: disposeBag)
}

private func bindTableView(output: Output) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public final class PlaylistView: UIView {
$0.sectionHeaderTopPadding = 0
$0.backgroundColor = DesignSystemAsset.BlueGrayColor.blueGray100.color
$0.showsVerticalScrollIndicator = true
$0.allowsSelectionDuringEditing = true
}

override init(frame: CGRect) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import UIKit
import Utility

internal protocol PlaylistTableViewCellDelegate: AnyObject {
func superButtonTapped(index: Int)
func playButtonDidTap(model: PlaylistItemModel)
}

Expand Down Expand Up @@ -78,10 +77,6 @@ internal class PlaylistTableViewCell: UITableViewCell {
fatalError("")
}

override func prepareForReuse() {
super.prepareForReuse()
}

private func configureContents() {
self.backgroundColor = .clear
self.contentView.addSubview(self.thumbnailImageView)
Expand Down Expand Up @@ -110,11 +105,6 @@ internal class PlaylistTableViewCell: UITableViewCell {
$0.centerY.equalTo(contentView.snp.centerY)
$0.right.equalTo(contentView.snp.right).offset(-20)
}

superButton.snp.makeConstraints {
$0.left.top.bottom.equalToSuperview()
$0.right.equalToSuperview()
}
}
}

Expand Down Expand Up @@ -151,10 +141,6 @@ extension PlaylistTableViewCell {
owner.delegate?.playButtonDidTap(model: song)
}
.disposed(by: disposeBag)

superButton.addAction { [weak self] in
self?.delegate?.superButtonTapped(index: self?.model.index ?? 0)
}
}

private func updateButtonHidden(isEditing: Bool) {
Expand All @@ -163,7 +149,6 @@ extension PlaylistTableViewCell {
} else {
playImageView.isHidden = false
}
superButton.isHidden = !isEditing
}

private func updateConstraintPlayImageView(isEditing: Bool) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ final class LikeStorageReactor: Reactor {
case itemMoved(ItemMovedEvent)
case songDidTap(Int)
case tapAll(isSelecting: Bool)
case didLongPressedPlaylist(IndexPath)
case playDidTap(song: FavoriteSongEntity)
case addToPlaylistButtonDidTap // ๋…ธ๋ž˜๋‹ด๊ธฐ
case presentAddToPlaylistPopup
Expand Down Expand Up @@ -104,6 +105,9 @@ final class LikeStorageReactor: Reactor {
case let .songDidTap(index):
return changeSelectingState(index)

case let .didLongPressedPlaylist(indexPath):
return didLongPressedPlaylist(indexPath: indexPath)

case let .playDidTap(song):
return playWithAddToCurrentPlaylist(song: song)

Expand Down Expand Up @@ -285,6 +289,13 @@ extension LikeStorageReactor {
return .just(.showAddToPlaylistPopup(selectedItemIDs))
}

func didLongPressedPlaylist(indexPath: IndexPath) -> Observable<Mutation> {
guard !currentState.isEditing else { return .empty() }
storageCommonService.isEditingState.onNext(true)
changeSelectingState(indexPath.row)
return .just(.switchEditingState(true))
}

func presentAddToPlaylistPopup() -> Observable<Mutation> {
guard var tmp = currentState.dataSource.first?.items else {
LogManager.printError("favorite datasource is empty")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ final class ListStorageReactor: Reactor {
case viewDidLoad
case refresh
case itemMoved(ItemMovedEvent)
case cellDidTap(Int)
case listDidTap(IndexPath)
case didSelectPlaylist(IndexPath)
case didLongPressedPlaylist(IndexPath)
case playDidTap(Int)
case tapAll(isSelecting: Bool)
case loginButtonDidTap
Expand Down Expand Up @@ -117,11 +117,11 @@ final class ListStorageReactor: Reactor {
case let .itemMoved((sourceIndex, destinationIndex)):
return updateOrder(src: sourceIndex.row, dest: destinationIndex.row)

case let .cellDidTap(index):
return changeSelectingState(index)
case let .didSelectPlaylist(indexPath):
return didSelectPlaylistCell(indexPath: indexPath)

case let .listDidTap(indexPath):
return showDetail(indexPath)
case let .didLongPressedPlaylist(indexPath):
return didLongPressedPlaylist(indexPath: indexPath)

case let .playDidTap(index):
return playWithAddToCurrentPlaylist(index)
Expand Down Expand Up @@ -333,6 +333,23 @@ extension ListStorageReactor {
)
}

func didLongPressedPlaylist(indexPath: IndexPath) -> Observable<Mutation> {
guard !currentState.isEditing else { return .empty() }
storageCommonService.isEditingState.onNext(true)
return .concat(
changeSelectingState(indexPath.row),
.just(.switchEditingState(true))
)
}

func didSelectPlaylistCell(indexPath: IndexPath) -> Observable<Mutation> {
if currentState.isEditing {
return changeSelectingState(indexPath.row)
} else {
return showDetail(indexPath)
}
}

func showDetail(_ indexPath: IndexPath) -> Observable<Mutation> {
let selectedList = currentState.dataSource[indexPath.section].items[indexPath.row]
let key = selectedList.key
Expand Down
Loading
Loading