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

[Feat] #33 - RunningRecordVC UI #42

Merged
merged 13 commits into from
Jan 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
13 commits
Select commit Hold shift + click to select a range
90e602d
[Feat] #33 - RunningRecordVC ๊ธฐ์ดˆ UI ๊ตฌํ˜„
lsj8706 Jan 4, 2023
3dad36f
[Feat] #30 - ๋Ÿฌ๋‹ ๊ธฐ๋ก์„ ์œ„ํ•œ ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€
lsj8706 Jan 4, 2023
468e2ac
[Feat] #33 - RNTimeFormatter ์ถ”๊ฐ€
lsj8706 Jan 4, 2023
2eb91eb
[Feat] #33 - RunningRecordVC ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ
lsj8706 Jan 4, 2023
ef4b25b
[Chore] #33 - stopwatch ์ž‘๋™ ์‹œ์ ์„ viewWillAppear๋กœ ๋ณ€๊ฒฝ
lsj8706 Jan 4, 2023
fe2571d
[Feat] #33 - ์ฝ”์Šค ์ด๋ฏธ์ง€ ๋ฐ”์ธ๋”ฉ
lsj8706 Jan 4, 2023
c1703bc
[Feat] #33 - ์ง€๋„ ์บก์ณ ๋กœ์ง ๊ฐœ์„ 
lsj8706 Jan 4, 2023
a908591
[Feat] #33 - ๋”๋ฏธ ์ง€๋„ ์คŒ ๋ ˆ๋ฒจ ๋ณ€๊ฒฝ
lsj8706 Jan 4, 2023
b208cfc
[Feat] #33 - ์ง€๋„ ์บก์ณ ์‹œ์  ๋ณ€๊ฒฝ
lsj8706 Jan 5, 2023
551d1af
[Feat] #33 - CourseDrawingVC์—์„œ ์ง€๋„ ์บก์ณ ๊ฐ€๋Šฅํ•˜๋„๋ก ์ˆ˜์ •
lsj8706 Jan 5, 2023
d0a3a66
[Chore] #33 - RunTrackingVC๋กœ ์บก์ณ ์ด๋ฏธ์ง€ ์ „๋‹ฌ
lsj8706 Jan 5, 2023
f717b6f
[Fix] #33 - ์žฌ์บก์ณํ•  ๋•Œ ๊ธฐ์กด์˜ ๋งˆ์ปค๊ฐ€ ์ง€์›Œ์ง€์ง€ ์•Š์•˜๋˜ ๋ฌธ์ œ ํ•ด๊ฒฐ
lsj8706 Jan 5, 2023
d65fc62
[Merge] #33 - pull develop
lsj8706 Jan 5, 2023
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
16 changes: 16 additions & 0 deletions Runnect-iOS/Runnect-iOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
CE146770296568DC00DCEA1B /* RunTrackingVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE14676F296568DC00DCEA1B /* RunTrackingVC.swift */; };
CE14677829658C7200DCEA1B /* Stopwatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE14677729658C7200DCEA1B /* Stopwatch.swift */; };
CE14677A2965A80700DCEA1B /* CustomBottomSheetVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE1467792965A80700DCEA1B /* CustomBottomSheetVC.swift */; };
CE14677C2965C1B100DCEA1B /* RunningRecordVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE14677B2965C1B100DCEA1B /* RunningRecordVC.swift */; };
CE17F02D2961BBA100E1DED0 /* ColorLiterals.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE17F02C2961BBA100E1DED0 /* ColorLiterals.swift */; };
CE17F0332961BEF800E1DED0 /* Pretendard-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = CE17F02F2961BEF800E1DED0 /* Pretendard-Medium.otf */; };
CE17F0342961BEF800E1DED0 /* Pretendard-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = CE17F0302961BEF800E1DED0 /* Pretendard-Bold.otf */; };
Expand Down Expand Up @@ -78,6 +79,9 @@
CE665610295D92C200C64E12 /* setTextLineHeight.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE66560F295D92C200C64E12 /* setTextLineHeight.swift */; };
CE665612295D92E400C64E12 /* UserDefaultWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE665611295D92E400C64E12 /* UserDefaultWrapper.swift */; };
CE665615295D989A00C64E12 /* .swiftlint.yml in Resources */ = {isa = PBXBuildFile; fileRef = CE665614295D989A00C64E12 /* .swiftlint.yml */; };
CE9291252965C9FB0010959C /* CourseDetailInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE9291242965C9FB0010959C /* CourseDetailInfoView.swift */; };
CE9291272965D0ED0010959C /* StatsInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE9291262965D0ED0010959C /* StatsInfoView.swift */; };
CE9291292965E01D0010959C /* RNTimeFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE9291282965E01D0010959C /* RNTimeFormatter.swift */; };
CEB8416E2962C45300BF8080 /* LocationSearchResultTVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEB8416D2962C45300BF8080 /* LocationSearchResultTVC.swift */; };
CEB841702963360800BF8080 /* CountDownVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEB8416F2963360800BF8080 /* CountDownVC.swift */; };
CEC2A6852961F92C00160BF7 /* CustomButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEC2A6842961F92C00160BF7 /* CustomButton.swift */; };
Expand Down Expand Up @@ -119,6 +123,7 @@
CE14676F296568DC00DCEA1B /* RunTrackingVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunTrackingVC.swift; sourceTree = "<group>"; };
CE14677729658C7200DCEA1B /* Stopwatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stopwatch.swift; sourceTree = "<group>"; };
CE1467792965A80700DCEA1B /* CustomBottomSheetVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomBottomSheetVC.swift; sourceTree = "<group>"; };
CE14677B2965C1B100DCEA1B /* RunningRecordVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunningRecordVC.swift; sourceTree = "<group>"; };
CE17F02C2961BBA100E1DED0 /* ColorLiterals.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorLiterals.swift; sourceTree = "<group>"; };
CE17F02F2961BEF800E1DED0 /* Pretendard-Medium.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Medium.otf"; sourceTree = "<group>"; };
CE17F0302961BEF800E1DED0 /* Pretendard-Bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Bold.otf"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -182,6 +187,9 @@
CE66560F295D92C200C64E12 /* setTextLineHeight.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = setTextLineHeight.swift; sourceTree = "<group>"; };
CE665611295D92E400C64E12 /* UserDefaultWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultWrapper.swift; sourceTree = "<group>"; };
CE665614295D989A00C64E12 /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = "<group>"; };
CE9291242965C9FB0010959C /* CourseDetailInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CourseDetailInfoView.swift; sourceTree = "<group>"; };
CE9291262965D0ED0010959C /* StatsInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsInfoView.swift; sourceTree = "<group>"; };
CE9291282965E01D0010959C /* RNTimeFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNTimeFormatter.swift; sourceTree = "<group>"; };
CEB8416D2962C45300BF8080 /* LocationSearchResultTVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationSearchResultTVC.swift; sourceTree = "<group>"; };
CEB8416F2963360800BF8080 /* CountDownVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountDownVC.swift; sourceTree = "<group>"; };
CEC2A6842961F92C00160BF7 /* CustomButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomButton.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -377,6 +385,7 @@
CEC2A6912962BE2900160BF7 /* DepartureSearchVC.swift */,
CE29D581296402B500F47542 /* CourseDrawingVC.swift */,
CEB8416F2963360800BF8080 /* CountDownVC.swift */,
CE14677B2965C1B100DCEA1B /* RunningRecordVC.swift */,
);
path = VC;
sourceTree = "<group>";
Expand Down Expand Up @@ -604,6 +613,7 @@
CEC2A68F2962B06C00160BF7 /* convertLocationObject.swift */,
CE29D583296416D800F47542 /* caculateStatusBarHeight.swift */,
CE14677729658C7200DCEA1B /* Stopwatch.swift */,
CE9291282965E01D0010959C /* RNTimeFormatter.swift */,
);
path = Utils;
sourceTree = "<group>";
Expand Down Expand Up @@ -656,6 +666,8 @@
CEC2A6842961F92C00160BF7 /* CustomButton.swift */,
CE0D9FD229648DA300CEB5CD /* CustomAlertVC.swift */,
CE1467792965A80700DCEA1B /* CustomBottomSheetVC.swift */,
CE9291242965C9FB0010959C /* CourseDetailInfoView.swift */,
CE9291262965D0ED0010959C /* StatsInfoView.swift */,
);
path = UIComponents;
sourceTree = "<group>";
Expand Down Expand Up @@ -903,6 +915,7 @@
CE665604295D91B100C64E12 /* makeAlert.swift in Sources */,
A3BC2F2F2962C40A00198261 /* UploadedCourseInfoVC.swift in Sources */,
CE6655EA295D88B200C64E12 /* UITabBar+.swift in Sources */,
CE9291272965D0ED0010959C /* StatsInfoView.swift in Sources */,
CEC2A68729629B9B00160BF7 /* SignInVC.swift in Sources */,
CE665602295D918000C64E12 /* JsonCoder.swift in Sources */,
CE4545CD295D7AF4003201E1 /* TaBarController.swift in Sources */,
Expand All @@ -918,6 +931,7 @@
CE66560A295D924A00C64E12 /* Result+.swift in Sources */,
DA20D847296697A600F1581F /* PlusDetailViewController.swift in Sources */,
CE66560E295D92A500C64E12 /* setStatusBarBackgroundColor.swift in Sources */,
CE9291292965E01D0010959C /* RNTimeFormatter.swift in Sources */,
CE6655D7295D86F900C64E12 /* String+.swift in Sources */,
CE58759E29601476005D967E /* LoadingIndicator.swift in Sources */,
CE5875A2296015A2005D967E /* NetworkLoggerPlugin.swift in Sources */,
Expand All @@ -930,6 +944,7 @@
CE17F0382961BF8B00E1DED0 /* FontLiterals.swift in Sources */,
CE6655E8295D889600C64E12 /* UISwitch+.swift in Sources */,
CE5875A029601500005D967E /* Toast.swift in Sources */,
CE14677C2965C1B100DCEA1B /* RunningRecordVC.swift in Sources */,
CE6655F6295D90B600C64E12 /* addToolBar.swift in Sources */,
CEC2A68A2962ADCD00160BF7 /* RNMapView.swift in Sources */,
CE6655F0295D891B00C64E12 /* UITextView+.swift in Sources */,
Expand Down Expand Up @@ -981,6 +996,7 @@
CEB8416E2962C45300BF8080 /* LocationSearchResultTVC.swift in Sources */,
CE6655CA295D84DD00C64E12 /* UserDefaultKeyList.swift in Sources */,
CE6655F2295D894D00C64E12 /* UIView+.swift in Sources */,
CE9291252965C9FB0010959C /* CourseDetailInfoView.swift in Sources */,
CE665600295D915D00C64E12 /* getClassName.swift in Sources */,
A3BC2F2D2962C3F200198261 /* ActivityRecordInfoVC.swift in Sources */,
CE6655FC295D90F500C64E12 /* calculatePastTime.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,13 @@ extension UITextField {
attributedStr.addAttribute(NSAttributedString.Key.kern, value: spacing, range: NSMakeRange(0, attributedStr.length))
self.attributedText = attributedStr
}

/// ํ•˜๋‹จ์— Border ์ƒ์„ฑ
func addBottomBorder(height: CGFloat) {
let bottomLine = CALayer()
bottomLine.frame = CGRect(x: 0, y: self.frame.size.height - height, width: self.frame.size.width, height: height)
bottomLine.backgroundColor = UIColor.g5.cgColor
borderStyle = .none
layer.addSublayer(bottomLine)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//
// CourseDetailInfoView.swift
// Runnect-iOS
//
// Created by sejin on 2023/01/04.
//

import UIKit

final class CourseDetailInfoView: UIView {

// MARK: - UI Components

private let leftImageView = UIImageView().then {
$0.image = ImageLiterals.icStar
}

private let titleLabel = UILabel().then {
$0.font = .b5
$0.textColor = .g1
}

private let descriptionLabel = UILabel().then {
$0.font = .b6
$0.textColor = .g1
}

// MARK: - initialization

init(title: String, description: String) {
super.init(frame: .zero)
self.setUI(title: title, description: description)
self.setLayout()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

// MARK: - Methods

extension CourseDetailInfoView {
@discardableResult
func setDescriptionText(description: String) -> Self {
self.descriptionLabel.text = description
return self
}
}

// MARK: - UI & Layout

extension CourseDetailInfoView {
private func setUI(title: String, description: String) {
self.backgroundColor = .w1
self.titleLabel.text = title
self.descriptionLabel.text = description
}

private func setLayout() {
self.addSubviews(leftImageView, titleLabel, descriptionLabel)

leftImageView.snp.makeConstraints { make in
make.top.leading.bottom.equalToSuperview()
make.width.equalTo(leftImageView.snp.height)
}

titleLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.leading.equalTo(leftImageView.snp.trailing).offset(9)
}

descriptionLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.leading.equalTo(titleLabel.snp.leading).offset(57)
make.trailing.greaterThanOrEqualToSuperview()
}
}
}
67 changes: 48 additions & 19 deletions Runnect-iOS/Runnect-iOS/Global/UIComponents/MapView/RNMapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ final class RNMapView: UIView {
@Published var pathDistance: Double = 0
@Published var markerCount = 0

let pathImage = PassthroughSubject<UIImage, Never>()
let pathImage = PassthroughSubject<UIImage?, Never>()
var cancelBag = Set<AnyCancellable>()

let locationManager = CLLocationManager()
Expand All @@ -37,6 +37,10 @@ final class RNMapView: UIView {
private var bottomPadding: CGFloat = 0
private let locationOverlayIcon = NMFOverlayImage(image: ImageLiterals.icLocationOverlay)

private lazy var dummyMap = RNMapView(frame: CGRect(x: 0, y: 0, width: 300, height: 300)).then {
$0.isUserInteractionEnabled = false
}

// MARK: - UI Components

let map = NMFNaverMapView()
Expand Down Expand Up @@ -137,15 +141,39 @@ extension RNMapView {

/// NMGLatLng ์–ด๋ ˆ์ด๋ฅผ ๋ฐ›์•„์„œ ์ฒซ ์œ„์น˜๋ฅผ startMarker๋กœ ์„ค์ •ํ•˜๊ณ  ๋‚˜๋จธ์ง€๋ฅผ ์ผ๋ฐ˜ ๋งˆ์ปค๋กœ ์ƒ์„ฑ
@discardableResult
func makeMarkersWithStartMarker(at locations: [NMGLatLng]) -> Self {
func makeMarkersWithStartMarker(at locations: [NMGLatLng], moveCameraToStartMarker: Bool) -> Self {
removeMarkers()
if locations.count < 2 { return self }
makeStartMarker(at: locations[0], withCameraMove: true)
makeStartMarker(at: locations[0], withCameraMove: moveCameraToStartMarker)
locations[1...].forEach { location in
makeMarker(at: location)
}

return self
}

/// ์บก์ฒ˜๋ฅผ ์œ„ํ•œ ์ขŒํ‘œ ์„ค์ • ๋ฐ ์นด๋ฉ”๋ผ ์ด๋™
func makeDummyMarkerAndCameraMove(at locations: [NMGLatLng]) {
addSubview(dummyMap)
sendSubviewToBack(dummyMap)
dummyMap.makeMarkersWithStartMarker(at: locations, moveCameraToStartMarker: false)
let bounds = makeMBR(at: locations)
let cameraUpdate = NMFCameraUpdate(fit: bounds, padding: 100)
cameraUpdate.animation = .none
dummyMap.map.mapView.moveCamera(cameraUpdate) { isCancelled in
if isCancelled {
print("์นด๋ฉ”๋ผ ์ด๋™ ์ทจ์†Œ")
} else {
LoadingIndicator.showLoading()
DispatchQueue.main.asyncAfter(deadline: .now()+2) {
self.dummyMap.map.mapView.zoomLevel -= 1
self.makePathImage()
LoadingIndicator.hideLoading()
}
}
}
}

/// ์‚ฌ์šฉ์ž ์œ„์น˜๋กœ ์นด๋ฉ”๋ผ ์ด๋™
@discardableResult
func moveToUserLocation() -> Self {
Expand Down Expand Up @@ -216,27 +244,21 @@ extension RNMapView {
return pathDistance
}

/// ๊ฒฝ๋กœ ๋ทฐ๋ฅผ UIImage๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ pathImage์— send
func getPathImage() {
let bounds = makeMBR()
let dummyMap = RNMapView(frame: CGRect(x: 50, y: 50, width: 300, height: 250))
.makeMarkersWithStartMarker(at: self.markersLatLngs)
addSubview(dummyMap)
sendSubviewToBack(dummyMap)
let cameraUpdate = NMFCameraUpdate(fit: bounds, padding: 150)
cameraUpdate.animation = .none
dummyMap.map.mapView.moveCamera(cameraUpdate)

DispatchQueue.main.asyncAfter(deadline: .now()+1) {
self.pathImage.send(UIImage(view: dummyMap.map.mapView))
}
/// ๋”๋ฏธ ๋ทฐ๋ฅผ UIImage๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ pathImage์— send
func makePathImage() {
self.pathImage.send(UIImage(view: dummyMap.map.mapView))
}

/// ํ˜„์žฌ ์‹œ์ ๊นŒ์ง€์˜ ๋งˆ์ปค๋“ค์„ ์บก์ณํ•˜์—ฌ pahImage์— send
func capturePathImage() {
makeDummyMarkerAndCameraMove(at: self.markersLatLngs)
}

/// ๋ฐ”์šด๋”๋ฆฌ(MBR) ์ƒ์„ฑ
func makeMBR() -> NMGLatLngBounds {
func makeMBR(at locations: [NMGLatLng]) -> NMGLatLngBounds {
var latitudes = [Double]()
var longitudes = [Double]()
self.markersLatLngs.forEach { latLng in
locations.forEach { latLng in
latitudes.append(latLng.lat)
longitudes.append(latLng.lng)
}
Expand All @@ -253,6 +275,13 @@ extension RNMapView {
lastMarker.mapView = nil
}

/// ์ถœ๋ฐœ์ง€ ๋งˆ์ปค๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ๋งˆ์ปค ์ œ๊ฑฐ
func removeMarkers() {
while self.markers.count != 0 {
undo()
}
}

// ๋‘ ์ง€์  ์‚ฌ์ด์˜ ๊ฑฐ๋ฆฌ(m) ์ถ”๊ฐ€
private func addDistance(with newLocation: NMGLatLng) {
let lastCLLoc = markersLatLngs.last?.toCLLocation()
Expand Down
90 changes: 90 additions & 0 deletions Runnect-iOS/Runnect-iOS/Global/UIComponents/StatsInfoView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//
// StatsInfoView.swift
// Runnect-iOS
//
// Created by sejin on 2023/01/05.
//

import UIKit

final class StatsInfoView: UIView {

// MARK: - UI Components

private let titleLabel = UILabel().then {
$0.font = .b4
$0.textColor = .g2
}

private let statsLabel = UILabel().then {
$0.font = .h3
$0.textColor = .g1
}

private lazy var statsContainerStackView = UIStackView(
arrangedSubviews: [titleLabel, statsLabel]
).then {
$0.axis = .vertical
$0.alignment = .center
$0.spacing = 9
}

// MARK: - initialization

init(title: String, stats: String) {
super.init(frame: .zero)
self.setUI(title: title, stats: stats)
self.setLayout()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

// MARK: - Methods

extension StatsInfoView {
/// statsLabel์˜ text๋ฅผ attributedString์œผ๋กœ ๋ณ€๊ฒฝ (๊ธฐ๋ณธ ๊ฐ’์€ Km)
@discardableResult
func setAttributedStats(stats: String, unit: String = " Km") -> Self {
let attributedString = NSMutableAttributedString(
string: stats,
attributes: [.font: UIFont.h3, .foregroundColor: UIColor.g1]
)

attributedString.append(
NSAttributedString(
string: unit,
attributes: [.font: UIFont.b4, .foregroundColor: UIColor.g2]
)
)

self.statsLabel.attributedText = attributedString
return self
}

@discardableResult
func setStats(stats: String) -> Self {
self.statsLabel.text = stats
return self
}
}

// MARK: - UI & Layout

extension StatsInfoView {
private func setUI(title: String, stats: String) {
self.backgroundColor = .w1
self.titleLabel.text = title
self.statsLabel.text = stats
}

private func setLayout() {
self.addSubviews(statsContainerStackView)

statsContainerStackView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
}
Loading