Skip to content

Commit

Permalink
Merge pull request #136 from DeveloperAcademy-POSTECH/develop
Browse files Browse the repository at this point in the history
Update Version 1.3.1
  • Loading branch information
zaehorang authored Dec 4, 2024
2 parents 03225ca + be336bb commit 7854cd6
Show file tree
Hide file tree
Showing 22 changed files with 218 additions and 100 deletions.
4 changes: 2 additions & 2 deletions FiveGuyes/FiveGuyes.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.3.0;
MARKETING_VERSION = 1.3.1;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = com.FiveNorms.FiveNorms;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down Expand Up @@ -834,7 +834,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.3.0;
MARKETING_VERSION = 1.3.1;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = com.FiveNorms.FiveNorms;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1 +1,80 @@
{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"}]}
{
"images" : [
{
"filename" : "40.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"filename" : "60.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"filename" : "29.png",
"idiom" : "iphone",
"scale" : "1x",
"size" : "29x29"
},
{
"filename" : "58.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"filename" : "87.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"filename" : "80.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "120.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"filename" : "57.png",
"idiom" : "iphone",
"scale" : "1x",
"size" : "57x57"
},
{
"filename" : "114.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "57x57"
},
{
"filename" : "120.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"filename" : "180.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"filename" : "1024.png",
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
16 changes: 16 additions & 0 deletions FiveGuyes/FiveGuyes/Sources/Models/ReadingScheduleCalculator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -271,3 +271,19 @@ struct ReadingScheduleCalculator {
return (pagesPerDay, remainder)
}
}

extension ReadingScheduleCalculator {
/// ๊ธฐ๋ก๋œ ๋‚ ์งœ์˜ ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋ฉ”์„œ๋“œ
func calculateRecordedDays<Progress: ReadingProgressProtocol>(
progress: Progress
) -> Int {
return progress.readingRecords.values.filter { $0.pagesRead > 0 }.count
}

func calculateTotalReadingPages<Settings: UserSettingsProtocol>(
setttings: Settings
) -> Int {
return setttings.targetEndPage - setttings.startPage
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import SwiftUI

// TODO: ์ถ”๊ฐ€๋˜๋Š” ๋ทฐ ์ถ”๊ฐ€ํ•˜๊ธฐ
enum Screens: Hashable {
typealias UserBook = UserBookSchemaV2.UserBookV2
case empty
case mainHome
case notiSetting
Expand All @@ -17,6 +18,7 @@ enum Screens: Hashable {
case dailyProgress
case completionCelebration
case completionReview
case completionReviewUpdate(book: UserBook)
}

@Observable
Expand All @@ -42,6 +44,8 @@ final class NavigationCoordinator {
CompletionCelebrationView()
case .completionReview:
CompletionReviewView()
case .completionReviewUpdate(book: let book):
CompletionReviewView(isUpdateMode: true, externalBook: book)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,24 @@ import SwiftUI
struct CompletionListView: View {
typealias UserBook = UserBookSchemaV2.UserBookV2

@Environment(NavigationCoordinator.self) var navigationCoordinator: NavigationCoordinator
@Environment(\.modelContext) private var modelContext

@State private var selectedBookIndex: Int = 0
@State var showCompletionAlert: Bool = false

// ์™„๋…ํ•œ ์ฑ…์„ ๊ฐ€์ ธ์˜ค๋Š” ์ฟผ๋ฆฌ
// TODO: ์ฑ… ์—ญ์ˆœ์œผ๋กœ ๋ฐ›์•„์˜ค๊ธฐ ๐Ÿฏ๐Ÿฏ๐Ÿฏ๐Ÿฏ๐Ÿฏ
@Query(
filter: #Predicate<UserBook> { $0.completionStatus.isCompleted == true }
)
private var completedBooks: [UserBook]
private var fetchCompletedBooks: [UserBook]

let completionAlertMessage = "์ •๋ง๋กœ ๋‚ด์šฉ์„ ์‚ญ์ œํ• ๊นŒ์š”?"
let completionAlertText = "์‚ญ์ œ ํ›„์—๋Š” ๋ณต์›ํ•  ์ˆ˜ ์—†์–ด์š”"

var body: some View {
var completedBooks = Array(fetchCompletedBooks.reversed())

VStack(alignment: .leading, spacing: 16) {
HStack {
Text("์™„๋… ๋ฆฌ์ŠคํŠธ")
Expand Down Expand Up @@ -92,22 +94,34 @@ struct CompletionListView: View {
.fontStyle(.body)
.foregroundStyle(Color.Labels.primaryBlack1)
.padding(.bottom, 10)
// TODO: ์ˆ˜์ • ๋ฒ„ํŠผ ์ถ”๊ฐ€ํ•˜๊ธฐ

HStack {
Text("\(selectedBook.userSettings.targetEndDate.toKoreanDateStringWithoutYear()) ์™„๋…์™„๋ฃŒ")
Spacer()
// TODO: โ—๏ธโ—๏ธโ—๏ธ ์ˆ˜์ •ํ•˜๊ธฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
// ๋ฐ์ดํ„ฐ๋ฅผ ์ง€์šฐ๋‹ˆ๊นŒ ํŠ•๊น€
// Button {
// showCompletionAlert = true
// } label: {
// Image(systemName: "ellipsis")
// .resizable()
// .scaledToFit()
// .frame(width: 20, height: 22)
// .tint(Color.Labels.secondaryBlack2) // ๋””์ž์ธ ์‹œ์Šคํ…œ์œผ๋กœ ์ˆ˜์ •
// .padding(.trailing, 3)
// }

Menu {
Button {
navigationCoordinator.push(.completionReviewUpdate(book: completedBooks[selectedBookIndex]))
} label: {
Label("๋‚ด์šฉ ์ˆ˜์ •ํ•˜๊ธฐ", systemImage: "pencil")
}

Divider()

Button(role: .destructive) {
showCompletionAlert = true
} label: {
Label("์‚ญ์ œ", systemImage: "trash")
}
} label: {
Image(systemName: "ellipsis")
.resizable()
.scaledToFit()
.frame(width: 20, height: 22)
.tint(Color.Labels.secondaryBlack2)
.padding(.trailing, 3)

}
}
.fontStyle(.caption2)
.foregroundStyle(Color.Labels.secondaryBlack2)
Expand All @@ -117,8 +131,7 @@ struct CompletionListView: View {
RoundedRectangle(cornerRadius: 16)
.foregroundStyle(Color.Fills.lightGreen)
}
.padding(.horizontal, 20)

.padding(.horizontal, 20)
}

} else {
Expand All @@ -128,21 +141,29 @@ struct CompletionListView: View {
.padding(.horizontal, 20)
}
}
// TODO: โ—๏ธโ—๏ธโ—๏ธ ์ˆ˜์ •ํ•˜๊ธฐ ๊ธฐ๋Šฅ ์ถ”๊ฐ€
// ๋ฐ์ดํ„ฐ๋ฅผ ์ง€์šฐ๋‹ˆ๊นŒ ํŠ•๊น€
// FontStyle ์ ์šฉํ•ด๋†“์Œ
// .alert(isPresented: $showCompletionAlert) {
// Alert(
// title: Text(completionAlertText)
// .alertFontStyle(.title3, weight: .semibold),
// message: Text(completionAlertMessage)
// .alertFontStyle(.caption1),
// primaryButton: .cancel(Text("์ทจ์†Œํ•˜๊ธฐ")),
// secondaryButton: .destructive(Text("์‚ญ์ œ")) {
// let book = completedBooks[selectedBookIndex]
// modelContext.delete(book)
// }
// )
// }
.alert(isPresented: $showCompletionAlert) {
Alert(
title: Text(completionAlertText)
.alertFontStyle(.title3, weight: .semibold),
message: Text(completionAlertMessage)
.alertFontStyle(.caption1),
primaryButton: .cancel(Text("์ทจ์†Œํ•˜๊ธฐ")),
secondaryButton: .destructive(Text("์‚ญ์ œ")) {
let book = completedBooks[selectedBookIndex]

modelContext.delete(book)

// ์ฒ˜์Œ ์…€๋กœ ์„ ํƒํ•˜๊ธฐ
selectedBookIndex = 0

// ๋ฐ์ด์ € ์ €์žฅ์ด ๋Š๋ ค์„œ ์ง์ ‘ ์ €์žฅํ•ด์ฃผ๊ธฐ
do {
try modelContext.save()
} catch {
print(error.localizedDescription)
}
}
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,28 +28,28 @@ struct CompletionCelebrationView: View {
let userSettings: UserSettingsProtocol = userBook.userSettings
let readingProgress: any ReadingProgressProtocol = userBook.readingProgress

ZStack {
Image("completionBackground").ignoresSafeArea()
VStack(spacing: 0) {
Spacer()
celebrationTitle
.padding(.bottom, 14)

VStack(spacing: 0) {
Spacer()
celebrationTitle
.padding(.bottom, 14)

celebrationMessage
.padding(.bottom, 80)

celebrationBookImage(bookMetadata)
.padding(.bottom, 28)

readingSummary(userSettings: userSettings, readingProgress: readingProgress)

Spacer()

reflectionButton
.padding(.bottom, 42)
}
.padding(.horizontal, 16)
celebrationMessage
.padding(.bottom, 80)

celebrationBookImage(bookMetadata)
.padding(.bottom, 28)

readingSummary(userSettings: userSettings, readingProgress: readingProgress)

Spacer()

reflectionButton
.padding(.bottom, 21)
}
.padding(.horizontal, 16)
.background {
Image("completionBackground")
.ignoresSafeArea()
}
.customNavigationBackButton()
}
Expand Down Expand Up @@ -102,16 +102,15 @@ struct CompletionCelebrationView: View {

private func readingSummary(userSettings: UserSettingsProtocol, readingProgress: any ReadingProgressProtocol) -> some View {
let readingScheduleCalculator = ReadingScheduleCalculator()

// TODO: ์™„๋…์„ ์ˆ˜์ •ํ•  ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์™„๋… ๋‚ ์งœ๊ฐ€ ๋ฐ”๋€” ์ˆ˜ ์žˆ์Œ, ๊ทธ๋ž˜์„œ ์™„๋… ๋‚ ์งœ๋Š” ์ตœ์ข…์—์„œ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ์—ฌ๊ธฐ์„œ๋Š” ์˜ค๋Š˜ ๋‚ ์งœ๋กœ ๋ณด์—ฌ์ฃผ๊ธฐ -> ์ดˆ๊ธฐ ์„ค์ • ๋‚ ๋ณด๋‹ค ๋น ๋ฅผ ์ˆ˜๋„ ์žˆ์Œ ๐Ÿฏ
let endDateText = Date().toKoreanDateString()
var startDateText = userSettings.startDate.toKoreanDateString()
if startDateText > endDateText { startDateText = endDateText }

// TODO: ์œ„์— ์ด์œ ๋กœ ๋‚ ์งœ๊ฐ€ ๋ฐ”๊ปด์„œ ๋ณด์ด๋ฉด ์•„๋ž˜ ๋กœ์ง์— ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’๋„ ๋ฐ”๊ปด์•ผ ํ•œ๋‹ค. ๐Ÿฏ
let pagesPerDay = readingScheduleCalculator.firstCalculatePagesPerDay(settings: userSettings, progress: readingProgress).pagesPerDay

let totalReadingDays = readingScheduleCalculator.firstCalculateTotalReadingDays(settings: userSettings, progress: readingProgress)
let totalReadingDays = readingScheduleCalculator.calculateRecordedDays(progress: readingProgress)
let pagesPerDay = readingScheduleCalculator.calculateTotalReadingPages(setttings: userSettings) / totalReadingDays

return Text("\(startDateText)๋ถ€ํ„ฐ \(endDateText)๊นŒ์ง€\n๊พธ์ค€ํžˆ \(pagesPerDay)์ชฝ์”ฉ \(totalReadingDays)์ผ๋™์•ˆ ์ฝ์—ˆ์–ด์š” ๐ŸŽ‰")
.fontStyle(.caption1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@ struct CompletionReviewView: View {
@Query(filter: #Predicate<UserBook> { $0.completionStatus.isCompleted == false })
private var currentlyReadingBooks: [UserBook] // ํ˜„์žฌ ์ฝ๊ณ  ์žˆ๋Š” ์ฑ…์„ ๊ฐ€์ ธ์˜ค๋Š” ์ฟผ๋ฆฌ

// ์—…๋ฐ์ดํŠธ ์ƒํ™ฉ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ถˆ ๋ณ€์ˆ˜
var isUpdateMode: Bool = false

// ์™ธ๋ถ€์—์„œ ์ฃผ์ž…๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์ฑ… ๋ณ€์ˆ˜
var externalBook: UserBook?

var body: some View {
let userBook = currentlyReadingBooks.first ?? UserBook.dummyUserBookV2
let userBook = isUpdateMode ? (externalBook ?? UserBook.dummyUserBookV2) : (currentlyReadingBooks.first ?? UserBook.dummyUserBookV2)

let bookMetadata: BookMetaDataProtocol = userBook.bookMetaData
let completionStatus: CompletionStatusProtocol = userBook.completionStatus
var completionStatus: CompletionStatusProtocol = userBook.completionStatus
let userSettings = userBook.userSettings

let title = bookMetadata.title
Expand Down Expand Up @@ -58,12 +64,18 @@ struct CompletionReviewView: View {
if reflectionText.isEmpty {
showAlert = true
} else {
completionStatus.markAsCompleted(review: reflectionText)

// TODO: ํ•ด๋‹น ๋กœ์ง ๋ชจ๋ธ๋กœ ์˜ฎ๊ธฐ๊ธฐ ๐Ÿฏ
userSettings.targetEndDate = Date()
if userSettings.startDate > userSettings.targetEndDate {
userSettings.startDate = userSettings.targetEndDate
if !isUpdateMode {
completionStatus.markAsCompleted(review: reflectionText)

// TODO: ํ•ด๋‹น ๋กœ์ง ๋ชจ๋ธ๋กœ ์˜ฎ๊ธฐ๊ธฐ ๐Ÿฏ
userSettings.targetEndDate = Date()
if userSettings.startDate > userSettings.targetEndDate {
userSettings.startDate = userSettings.targetEndDate
}
} else {
// ์—…๋ฐ์ดํŠธ ๋ชจ๋“œ์ธ ๊ฒฝ์šฐ
completionStatus.completionReview = reflectionText
}

navigationCoordinator.popToRoot()
Expand All @@ -86,6 +98,7 @@ struct CompletionReviewView: View {
}
.customNavigationBackButton()
.onAppear {
reflectionText = completionStatus.completionReview
isFocusedTextEditor = true
}
}
Expand Down
Loading

0 comments on commit 7854cd6

Please sign in to comment.