Skip to content

Commit

Permalink
Merge branch 'iOS/release' into iOS/task/RewindJourney-Music
Browse files Browse the repository at this point in the history
  • Loading branch information
SwiftyJunnos authored Dec 10, 2023
2 parents 188a0bf + 01743cc commit f6dca56
Show file tree
Hide file tree
Showing 30 changed files with 556 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -147,16 +147,30 @@ public final class HomeViewController: HomeBottomSheetViewController {

self.viewModel.state.isStartButtonLoading
.receive(on: DispatchQueue.main)
.sink { isStartButtonLoading in
self.startButton.configuration?.showsActivityIndicator = isStartButtonLoading
.sink { [weak self] isStartButtonLoading in
self?.startButton.configuration?.showsActivityIndicator = isStartButtonLoading
}
.store(in: &self.cancellables)

self.viewModel.state.isRefreshButtonHidden
.removeDuplicates(by: { $0 == $1 })
.receive(on: DispatchQueue.main)
.sink { [weak self] isHidden in
self?.refreshButton.isHidden = isHidden
}
.store(in: &self.cancellables)

self.viewModel.state.overlaysShouldBeCleared
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
self?.contentViewController.clearOverlays()
}
.store(in: &self.cancellables)
}

// MARK: - Functions

private func updateButtonMode(isRecording: Bool) {
self.refreshButton.isHidden = isRecording
UIView.transition(with: startButton, duration: 0.5,
options: .transitionCrossDissolve,
animations: {
Expand Down Expand Up @@ -197,18 +211,15 @@ extension HomeViewController: RecordJourneyButtonViewDelegate {
guard let coordinates = self?.contentViewController.visibleCoordinates else { return }

self?.viewModel.trigger(.refreshButtonDidTap(visibleCoordinates: coordinates))
self?.refreshButton.isHidden = true
}
self.refreshButton.addAction(refreshButtonAction, for: .touchUpInside)
}

public func backButtonDidTap(_ button: MSRectButton) {
guard self.viewModel.state.isRecording.value == true else { return }

self.contentViewController.clearOverlays()
self.viewModel.trigger(.backButtonDidTap)
self.contentViewController.journeyDidCancelled()
// TODO: 여정 취소
}

public func spotButtonDidTap(_ button: MSRectButton) {
Expand All @@ -233,6 +244,16 @@ extension HomeViewController: RecordJourneyButtonViewDelegate {

}

// MARK: - MapViewController

extension HomeViewController: MapViewControllerDelegate {

public func mapViewControllerDidChangeVisibleRegion(_ mapViewController: MapViewController) {
self.viewModel.trigger(.mapViewDidChange)
}

}

// MARK: - UI Configuration

private extension HomeViewController {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,18 @@ public final class HomeViewModel {
case startButtonDidTap(Coordinate)
case refreshButtonDidTap(visibleCoordinates: (minCoordinate: Coordinate, maxCoordinate: Coordinate))
case backButtonDidTap
case mapViewDidChange
}

public struct State {
// Passthrough
public var startedJourney = PassthroughSubject<RecordingJourney, Never>()
public var visibleJourneys = PassthroughSubject<[Journey], Never>()
public var overlaysShouldBeCleared = PassthroughSubject<Bool, Never>()

// CurrentValue
public var isRecording = CurrentValueSubject<Bool, Never>(false)
public var isRefreshButtonHidden = CurrentValueSubject<Bool, Never>(false)
public var isStartButtonLoading = CurrentValueSubject<Bool, Never>(false)
}

Expand Down Expand Up @@ -80,9 +83,13 @@ public final class HomeViewModel {
#endif
self.startJourney(at: coordinate)
case .refreshButtonDidTap(visibleCoordinates: (let minCoordinate, let maxCoordinate)):
self.state.isRefreshButtonHidden.send(true)
self.fetchJourneys(minCoordinate: minCoordinate, maxCoordinate: maxCoordinate)
case .backButtonDidTap:
self.state.isRecording.send(false)
self.state.overlaysShouldBeCleared.send(true)
case .mapViewDidChange:
self.state.isRefreshButtonHidden.send(false)
}
}

Expand Down Expand Up @@ -122,6 +129,7 @@ private extension HomeViewModel {
switch result {
case .success(let recordingJourney):
self.state.startedJourney.send(recordingJourney)
self.journeyRepository
self.state.isRecording.send(true)
case .failure(let error):
MSLogger.make(category: .home).error("\(error)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,21 @@ extension MapViewController {
extension MapViewController {

public func journeyDidStarted(_ startedJourney: RecordingJourney) {
let userRepository = UserRepositoryImplementation()
let journeyRepository = JourneyRepositoryImplementation()
let viewModel = RecordJourneyViewModel(startedJourney: startedJourney, journeyRepository: journeyRepository)
let viewModel = RecordJourneyViewModel(startedJourney: startedJourney,
userRepository: userRepository,
journeyRepository: journeyRepository)
self.swapViewModel(to: viewModel)
}

public func journeyDidCancelled() {
guard let viewModel = self.viewModel as? RecordJourneyViewModel else { return }
viewModel.trigger(.recordingDidCancelled)

let journeyRepository = JourneyRepositoryImplementation()
let navigateMapViewModel = NavigateMapViewModel(repository: journeyRepository)
self.swapViewModel(to: navigateMapViewModel)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public final class MapViewController: UIViewController {

// MARK: - Properties

public weak var delegate: MapViewControllerDelegate?
var viewModel: (any MapViewModel)?

private let locationManager = CLLocationManager()
Expand Down Expand Up @@ -115,7 +116,6 @@ public final class MapViewController: UIViewController {
public override func viewDidLoad() {
super.viewDidLoad()

guard let viewModel = self.viewModel else { return }
self.configureLayout()
self.configureCoreLocation()
self.bind(viewModel)
Expand All @@ -130,7 +130,7 @@ public final class MapViewController: UIViewController {
self.bind(viewModel)
}

private func bind(_ viewModel: any MapViewModel) {
private func bind(_ viewModel: (any MapViewModel)?) {
self.viewModel = viewModel

if let navigateMapViewModel = viewModel as? NavigateMapViewModel {
Expand Down Expand Up @@ -171,10 +171,9 @@ public final class MapViewController: UIViewController {

// MARK: - Functions: Annotation

// 식별자를 갖고 Annotation view 생성
/// 식별자를 갖고 Annotation view 생성
func addAnnotationView(using annotation: CustomAnnotation,
on mapView: MKMapView) -> MKAnnotationView {
// dequeueReusableAnnotationView: 식별자를 확인하여 사용가능한 뷰가 있으면 해당 뷰를 반환
return mapView.dequeueReusableAnnotationView(withIdentifier: CustomAnnotationView.identifier,
for: annotation)
}
Expand Down Expand Up @@ -294,7 +293,6 @@ extension MapViewController: CLLocationManagerDelegate {
recordJourneyViewModel.trigger(.locationDidUpdated(coordinate2D))
}

/// iOS 버젼에 따른 분기 처리 후 'iOS 위치 서비스 사용 중 여부' 확인
private func handleAuthorizationChange(_ manager: CLLocationManager) {
switch manager.authorizationStatus {
case .notDetermined:
Expand Down Expand Up @@ -373,26 +371,27 @@ extension MapViewController: MKMapViewDelegate {
return annotationView
}

public func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
self.delegate?.mapViewControllerDidChangeVisibleRegion(self)
}

}

// MARK: - ButtonView

extension MapViewController: ButtonStackViewDelegate {

/// 현재 지도에서 보이는 범위 내의 모든 Spot들을 보여줌.
public func mapButtonDidTap() {
MSLogger.make(category: .navigateMap).debug("현재 지도에서 보이는 범위 내의 모든 Spot들을 보여줍니다.")
}

/// 현재 내 위치를 중앙에 위치.
public func userLocationButtonDidTap() {
switch self.mapView.userTrackingMode {
case .none, .followWithHeading:
self.mapView.setUserTrackingMode(.follow, animated: true)
case .follow:
self.mapView.setUserTrackingMode(.followWithHeading, animated: true)
@unknown default:
break
@unknown default: break
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// MapViewControllerDelegate.swift
// NavigateMap
//
// Created by 이창준 on 2023.12.10.
//

import Foundation

public protocol MapViewControllerDelegate: AnyObject {

func mapViewControllerDidChangeVisibleRegion(_ mapViewController: MapViewController)

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public final class RecordJourneyViewModel: MapViewModel {
case viewNeedsLoaded
case locationDidUpdated(CLLocationCoordinate2D)
case locationsShouldRecorded([CLLocationCoordinate2D])
case recordingDidCancelled
}

public struct State {
Expand All @@ -30,14 +31,17 @@ public final class RecordJourneyViewModel: MapViewModel {

// MARK: - Properties

private let journeyRepository: JourneyRepository
private let userRepository: UserRepository
private var journeyRepository: JourneyRepository

public var state: State

// MARK: - Initializer

public init(startedJourney: RecordingJourney,
userRepository: UserRepository,
journeyRepository: JourneyRepository) {
self.userRepository = userRepository
self.journeyRepository = journeyRepository
self.state = State(recordingJourney: CurrentValueSubject<RecordingJourney, Never>(startedJourney))
}
Expand Down Expand Up @@ -67,6 +71,20 @@ public final class RecordJourneyViewModel: MapViewModel {
MSLogger.make(category: .home).error("\(error)")
}
}
case .recordingDidCancelled:
Task {
let userID = try self.userRepository.fetchUUID()
let recordingJourney = self.state.recordingJourney.value
let result = await self.journeyRepository.deleteJourney(recordingJourney, userID: userID)
switch result {
case .success(let cancelledJourney):
#if DEBUG
MSLogger.make(category: .home).debug("여정이 취소 되었습니다: \(cancelledJourney)")
#endif
case .failure(let error):
MSLogger.make(category: .home).error("\(error)")
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public final class RewindJourneyViewController: UIViewController {

// MARK: - Properties

public weak var navigationDelegate: RewindJourneyNavigationDelegate?
private let viewModel: RewindJourneyViewModel

private var cancellables: Set<AnyCancellable> = []
Expand All @@ -56,7 +57,7 @@ public final class RewindJourneyViewController: UIViewController {
private var timerSubscriber: Set<AnyCancellable> = []

// MARK: - Properties: Gesture
public weak var navigationDelegate: RewindJourneyNavigationDelegate?

var initialTouchPoint = CGPoint(x: 0, y: 0)

// MARK: - UI Components
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ public final class SpotSaveViewController: UIViewController {
MSLogger.make(category: .spot).debug("현재 이미지를 Data로 변환할 수 없습니다.")
return
}
self.viewModel.trigger(.startUploadSpot, using: jpegData)
self.viewModel.trigger(.startUploadSpot(jpegData))
self.navigationDelegate?.popToHome()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import MSLogger
public final class SpotSaveViewModel {

public enum Action {
case startUploadSpot
case startUploadSpot(Data)
}

// MARK: - Properties
Expand Down Expand Up @@ -43,14 +43,14 @@ public final class SpotSaveViewModel {

internal extension SpotSaveViewModel {

func trigger(_ action: Action, using data: Data) {
func trigger(_ action: Action) {
switch action {
case .startUploadSpot:
case .startUploadSpot(let data):
Task {
guard let recordingJourneyID = self.journeyRepository.fetchRecordingJourneyID() else {
MSLogger.make(category: .spot).error("recoding 중인 journeyID를 찾지 못하였습니다.")
return
}

let spot = CreateSpotRequestDTO(journeyId: recordingJourneyID,
coordinate: CoordinateDTO(self.coordinate),
timestamp: .now,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// SpotViewController+Gesture.swift
// Spot
//
// Created by 전민건 on 12/10/23.
//

import Foundation
import UIKit

// MARK: - Constants

private enum Metric {

static let movedXPositionToBackScene: CGFloat = 50.0
static let animationDuration: Double = 0.3

}

// MARK: - Gesture

internal extension SpotViewController {

func configureLeftToRightSwipeGesture() {
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panGestureDismiss(_:)))
self.view.addGestureRecognizer(panGesture)
}

@objc
private func panGestureDismiss(_ sender: UIPanGestureRecognizer) {
let touchPoint = sender.location(in: self.view.window)
let width = self.view.frame.width
let height = self.view.frame.height
switch sender.state {
case .began:
self.initialTouchPoint = touchPoint
case .changed:
if touchPoint.x - self.initialTouchPoint.x > .zero {
self.view.frame = CGRect(x: touchPoint.x - self.initialTouchPoint.x,
y: .zero,
width: width,
height: height)
}
case .ended, .cancelled:
if touchPoint.x - self.initialTouchPoint.x > Metric.movedXPositionToBackScene {
self.navigationDelegate?.popToHome()
} else {
self.view.frame = CGRect(x: .zero,
y: .zero,
width: width,
height: height)
}
default:
UIView.animate(withDuration: Metric.animationDuration) {
self.view.frame = CGRect(x: .zero,
y: .zero,
width: width,
height: height)
}
}
}

}
Loading

0 comments on commit f6dca56

Please sign in to comment.