Skip to content

Commit

Permalink
Merge branch 'iOS/release' into iOS/task/SaveJourney-Using-Local
Browse files Browse the repository at this point in the history
  • Loading branch information
SwiftyJunnos authored Dec 10, 2023
2 parents e96490c + 01743cc commit f5ac89c
Show file tree
Hide file tree
Showing 11 changed files with 319 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public final class RewindJourneyViewController: UIViewController {

// MARK: - Properties

public weak var navigationDelegate: RewindJourneyNavigationDelegate?
private let viewModel: RewindJourneyViewModel
public var images: [UIImage] = []
private let cache: MSCacheStorage
Expand All @@ -63,7 +64,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 @@ -48,12 +48,9 @@ internal extension SpotSaveViewModel {
case .startUploadSpot(let data):
Task {
guard let recordingJourneyID = self.journeyRepository.fetchRecordingJourneyID() else {
#if DEBUG
MSLogger.make(category: .network).error("ν˜„μž¬ μ—¬μ • 정보λ₯Ό κ°€μ Έμ˜€λŠ”λ° μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€.")
#endif
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)
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ public final class SpotViewController: UIViewController, UINavigationControllerD

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

// MARK: - Properties: Haptic

private let haptic = UIImpactFeedbackGenerator(style: .medium)

// MARK: - UI Components

private let backButton = UIButton()
Expand All @@ -81,6 +85,7 @@ public final class SpotViewController: UIViewController, UINavigationControllerD
public override func viewDidLoad() {
super.viewDidLoad()
self.configure()
self.haptic.prepare()
}

public override func viewDidAppear(_ animated: Bool) {
Expand Down Expand Up @@ -248,7 +253,7 @@ private extension SpotViewController {
self.configureBackButtonAction()
self.configureGalleryButtonAction()

self.configureUpToDownSwipeGesture()
self.configureLeftToRightSwipeGesture()
}

func configureCameraSetting() {
Expand Down Expand Up @@ -283,39 +288,6 @@ private extension SpotViewController {
self.backButton.addAction(backButtonAction, for: .touchUpInside)
}

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

@objc
func panGestureDismiss(_ sender: UIPanGestureRecognizer) {
let touchPoint = sender.location(in: self.view.window)

switch sender.state {
case .began:
self.initialTouchPoint = touchPoint
case .changed:
if touchPoint.y - self.initialTouchPoint.y > .zero {
self.view.frame = CGRect(x: .zero,
y: touchPoint.y - self.initialTouchPoint.y,
width: self.view.frame.width,
height: self.view.frame.height)
}
case .ended, .cancelled:
if touchPoint.y - self.initialTouchPoint.y > 200 {
self.navigationDelegate?.popToHome()
}
default:
UIView.animate(withDuration: 0.3) {
self.view.frame = CGRect(x: .zero,
y: .zero,
width: self.view.frame.width,
height: self.view.frame.height)
}
}
}

}

// MARK: - Button Actions
Expand All @@ -324,6 +296,7 @@ private extension SpotViewController {

func shotButtonTapped() {
self.viewModel.shot()
self.haptic.impactOccurred()
}

func swapButtonTapped() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ public final class FileManagerStorage: NSObject, MSPersistentStorage {
dateFormatter.formatOptions = [.withFractionalSeconds, .withTimeZone, .withInternetDateTime]
encoder.dateEncodingStrategy = .custom({ date, encoder in
var container = encoder.singleValueContainer()
try container.encode(date)
let dateString = dateFormatter.string(from: date)
try container.encode(dateString)
})
return encoder
}()

private let decoder: JSONDecoder = {
let decoder = JSONDecoder()
let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = [.withFractionalSeconds, .withTimeZone, .withInternetDateTime]
dateFormatter.formatOptions.insert(.withFractionalSeconds)
decoder.dateDecodingStrategy = .custom({ decoder in
let container = try decoder.singleValueContainer()
let dateString = try container.decode(String.self)
Expand All @@ -41,6 +42,7 @@ public final class FileManagerStorage: NSObject, MSPersistentStorage {
throw DecodingError.dataCorruptedError(in: container,
debugDescription: "Date λ””μ½”λ”© μ‹€νŒ¨: \(dateString)")
})
decoder.keyDecodingStrategy = .convertFromSnakeCase
return decoder
}()

Expand Down Expand Up @@ -74,9 +76,20 @@ public final class FileManagerStorage: NSObject, MSPersistentStorage {
if let path = self.storageURL()?.path,
let contents = try? self.fileManager.contentsOfDirectory(atPath: path) {
let allDecodedData: [T] = contents.compactMap { content in
guard let dataPath = URL(string: (path as NSString).appendingPathComponent(content)),
let data = try? Data(contentsOf: dataPath),
let decodedData = try? self.decoder.decode(T.self, from: data) else { return nil }
let key = String(content.dropLast(".json".count))
guard let dataPath =
fileURL(forKey: key) else {
MSLogger.make(category: .fileManager).error("경둜의 Dataλ₯Ό κ°€μ Έμ˜€μ§€ λͺ»ν•˜μ˜€μŠ΅λ‹ˆλ‹€.")
return nil
}
MSLogger.make(category: .fileManager).error("경둜의 Dataλ₯Ό μ„±κ³΅μ μœΌλ‘œ κ°€μ Έμ™”μŠ΅λ‹ˆλ‹€.")

print(dataPath.description)
guard let data = try? Data(contentsOf: dataPath),
let decodedData = try? self.decoder.decode(T.self, from: data) else {
MSLogger.make(category: .fileManager).error("decode에 μ‹€νŒ¨ν•˜μ˜€μŠ΅λ‹ˆλ‹€.")
return nil
}
return decodedData
}
return allDecodedData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,21 +101,54 @@ final class MSPersistentStorageTests: XCTestCase {
}

func test_FileManagerStorageμ—μ„œ_λͺ¨λ“ λ°μ΄ν„°μ €μž₯뢈러였기_성곡() {
let sut = MockCodableData(title: "boostcamp", content: "wm8")
let key = "S045"
self.fileStorage.set(value: sut, forKey: key)
self.fileStorage.set(value: sut, forKey: key)
self.fileStorage.set(value: sut, forKey: key)
let sut1 = MockCodableData(title: "boostcamp", content: "wm8")
let sut2 = MockCodableData(title: "boostcamp", content: "wm8")
let key1 = "S045"
let key2 = "S034"

self.fileStorage.set(value: sut1, forKey: key1)
self.fileStorage.set(value: sut2, forKey: key2)

guard let allStoredData = self.fileStorage.getAllOf(MockCodableData.self) else {
XCTFail("데이터 읽기에 μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€.")
return
}

XCTAssertEqual(allStoredData.count, 2, "데이터 μ €μž₯에 μ‹€νŒ¨ν•˜μ˜€μŠ΅λ‹ˆλ‹€.")
XCTAssertTrue(allStoredData.allSatisfy { $0 == sut1 || $0 == sut2 })
}

func test_FileManagerStorageμ—μ„œ_λͺ¨λ“ λ°μ΄ν„°μ €μž₯λΆˆλŸ¬μ˜¬λ•Œ_ν΄λ”ν•˜μœ„ν•­λͺ©κΉŒμ§€_μ½μ„μˆ˜μžˆλŠ”μ§€_μ‹€νŒ¨() {
let sut1 = MockCodableData(title: "boostcamp", content: "wm8")
let sut2 = MockCodableData(title: "boostcamp", content: "wm8")
let key1 = "S045"
let key2 = "/handsome/jeonmingun/S034"

self.fileStorage.set(value: sut1, forKey: key1)
self.fileStorage.set(value: sut2, forKey: key2)

guard let allStoredData = self.fileStorage.getAllOf(MockCodableData.self) else {
XCTFail("데이터 읽기에 μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€.")
return
}

XCTAssertEqual(allStoredData.count, 2, "데이터 μ €μž₯에 μ‹€νŒ¨ν•˜μ˜€μŠ΅λ‹ˆλ‹€.")
XCTAssertFalse(allStoredData.allSatisfy { $0 == sut1 || $0 == sut2 })
}

func test_Dateν˜•μ‹_μ €μž₯ν• _수_μžˆλŠ”μ§€_성곡() {
let sut = Date.now
let key = "S034"

allStoredData.forEach { storedData in
XCTAssertEqual(sut, storedData,
"λͺ©ν‘œ 데이터와 뢈러온 값이 λ‹€λ¦…λ‹ˆλ‹€.")
self.fileStorage.set(value: sut, forKey: key)

guard let storedData = self.fileStorage.get(Date.self, forKey: key) else {
XCTFail("데이터 읽기에 μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€.")
return
}

XCTAssertEqual(sut.description, storedData.description,
"λͺ©ν‘œ 데이터와 뢈러온 값이 λ‹€λ¦…λ‹ˆλ‹€.")
}

}
10 changes: 10 additions & 0 deletions iOS/MSData/.swiftpm/xcode/xcshareddata/xcschemes/MSData.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "RepositoryTests"
BuildableName = "RepositoryTests"
BlueprintName = "RepositoryTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
Expand Down
Loading

0 comments on commit f5ac89c

Please sign in to comment.