From eae6db349328dd574973530bb652da4668ab16f9 Mon Sep 17 00:00:00 2001 From: Maples7 Date: Tue, 2 Apr 2024 17:07:05 +0800 Subject: [PATCH 1/3] Fix the bug of weekDay tooltip with considering user locale settings --- .../AxisContribution/View/ACGridStack.swift | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/Sources/AxisContribution/View/ACGridStack.swift b/Sources/AxisContribution/View/ACGridStack.swift index cd424da..9bde501 100644 --- a/Sources/AxisContribution/View/ACGridStack.swift +++ b/Sources/AxisContribution/View/ACGridStack.swift @@ -51,13 +51,13 @@ struct ACGridStack: View where B: View, F: View { if constant.axisMode == .horizontal { HStack(alignment: .top, spacing: spacing) { VStack(alignment: .trailing, spacing: 0) { - Text("M") + Text("\(getWeekDayTitleAt(2))") .frame(height: rowSize.height) .padding(.top, rowSize.height * 2 + spacing * 2) - Text("W") + Text("\(getWeekDayTitleAt(4))") .frame(height: rowSize.height) .padding(.top, rowSize.height + spacing * 2) - Text("F") + Text("\(getWeekDayTitleAt(6))") .frame(height: rowSize.height) .padding(.top, rowSize.height + spacing * 2) } @@ -77,11 +77,11 @@ struct ACGridStack: View where B: View, F: View { VStack(alignment: .leading, spacing: spacing) { ZStack(alignment: .bottom) { let size = titleWidth - Text("M") + Text("\(getWeekDayTitleAt(2))") .offset(x: size + (rowSize.width * 1 + spacing * 2)) - Text("W") + Text("\(getWeekDayTitleAt(4))") .offset(x: size + (rowSize.width * 3 + spacing * 4)) - Text("F") + Text("\(getWeekDayTitleAt(6))") .offset(x: size + (rowSize.width * 5 + spacing * 5)) } ForEach(Array(store.datas.enumerated()), id: \.offset) { column, datas in @@ -145,7 +145,26 @@ struct ACGridStack: View where B: View, F: View { titleWidth = max(titleWidth, _titleSize.width) } } - + + /// A method that returns the very short symbol for the weekDay. + /// + /// - Parameters: + /// - weekDay: weekDay index, **should be in range 1...7**, e.g. 1 for the first day of week wth considering user settings + /// + /// > Note: calendar.veryShortWeekdaySymbols is always ["S", "M", "T", "W", "T", "F", "S"] with Sunday being the 1st element, + /// and calendar.firstWeekday indicates the first week day that user chooses. If user sets Monday as the first week day, + /// calendar.firstWeekday would be 2, the second element of calendar.veryShortWeekdaySymbols. + /// In this case, if you want to get the symbol of the first week day (e.g. Monday), you should call `getWeekDayTitle(1)`, + /// the index in calendar.veryShortWeekdaySymbols should be calendar.firstWeekday (2) + weekDay (1) - 2, + /// which returns the second element of calendar.veryShortWeekdaySymbols, being exactly Monday in this case. + /// + /// - Returns: the very short symbol for the weekDay. + private func getWeekDayTitleAt(_ weekDayIndex: Int) -> String { + let calendar = Calendar.current + let index = (calendar.firstWeekday + weekDayIndex - 2) % 7 + return calendar.veryShortWeekdaySymbols[index] + } + private func monthTitle(_ date: Date) -> String { let calendar = Calendar.current let monthTitles = calendar.shortMonthSymbols From 5f3861f16430e1797f94f7657fbdfbf76d35c324 Mon Sep 17 00:00:00 2001 From: Maples7 Date: Wed, 3 Apr 2024 01:14:50 +0800 Subject: [PATCH 2/3] Bugfix: start of the date as the key and don't show data after the to date --- .gitignore | 1 + Sources/AxisContribution/AxisContribution.swift | 2 +- Sources/AxisContribution/View/ACGridStack.swift | 14 ++++++++++---- .../ViewModel/ACDataProvider.swift | 11 ++++++++--- .../AxisContribution/ViewModel/ACDataStore.swift | 6 +++--- 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 330d167..0926cf4 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,4 @@ fastlane/test_output # https://github.com/johnno1962/injectionforxcode iOSInjectionProject/ +.swiftpm/ diff --git a/Sources/AxisContribution/AxisContribution.swift b/Sources/AxisContribution/AxisContribution.swift index a66ab57..d0b6e14 100644 --- a/Sources/AxisContribution/AxisContribution.swift +++ b/Sources/AxisContribution/AxisContribution.swift @@ -71,7 +71,7 @@ public struct AxisContribution: View where B: View, F: View { } } .contentShape(Rectangle()) - }else { + } else { VStack(spacing: 0) { content } diff --git a/Sources/AxisContribution/View/ACGridStack.swift b/Sources/AxisContribution/View/ACGridStack.swift index 9bde501..a3fd8aa 100644 --- a/Sources/AxisContribution/View/ACGridStack.swift +++ b/Sources/AxisContribution/View/ACGridStack.swift @@ -110,10 +110,15 @@ struct ACGridStack: View where B: View, F: View { /// - Returns: - private func getRowView(column: Int, row: Int, data: ACData) -> some View { ZStack { - background?(ACIndexSet(column: column, row: row), data) - foreground?(ACIndexSet(column: column, row: row), data) - .opacity(getOpacity(count: data.count)) - .takeSize($rowSize) + if data.date.startOfDay > constant.toDate.startOfDay { + background?(ACIndexSet(column: column, row: row), data) + .hidden() + } else { + background?(ACIndexSet(column: column, row: row), data) + foreground?(ACIndexSet(column: column, row: row), data) + .opacity(getOpacity(count: data.count)) + .takeSize($rowSize) + } } } @@ -217,5 +222,6 @@ struct ACGridStack_Previews: PreviewProvider { constant: .init(), source: [:] ) + .padding() } } diff --git a/Sources/AxisContribution/ViewModel/ACDataProvider.swift b/Sources/AxisContribution/ViewModel/ACDataProvider.swift index 541e558..3c6d42b 100644 --- a/Sources/AxisContribution/ViewModel/ACDataProvider.swift +++ b/Sources/AxisContribution/ViewModel/ACDataProvider.swift @@ -33,17 +33,22 @@ public class ACDataProvider { /// Generate data from start date to end date. /// - Parameters: /// - constant: Settings that define the contribution view. - /// - sourceDates: An array of contributed dates. + /// - sourceDatas: An dict of contributed dates and counts. /// - Returns: mapped data - public func mappedData(constant: ACConstant, source sourceDates: [Date: ACData]) -> [[ACData]] { + public func mappedData(constant: ACConstant, source sourceDatas: [Date: ACData]) -> [[ACData]] { var newDatas = [[ACData]]() var dateWeekly = Date.datesWeekly(from: constant.fromDate, to: constant.toDate) if constant.axisMode == .vertical { dateWeekly = dateWeekly.reversed() } + // make dates to the start of the day + var cleanDatas: [Date: ACData] = [:] + sourceDatas.forEach { date, count in + cleanDatas[date.startOfDay] = count + } dateWeekly.forEach { date in let datas = date.datesInWeek.map { date -> ACData in - if let data = sourceDates[date] { + if let data = cleanDatas[date] { return data } else { return ACData(date: date, count: 0) diff --git a/Sources/AxisContribution/ViewModel/ACDataStore.swift b/Sources/AxisContribution/ViewModel/ACDataStore.swift index 4d5d70f..73c7b6b 100644 --- a/Sources/AxisContribution/ViewModel/ACDataStore.swift +++ b/Sources/AxisContribution/ViewModel/ACDataStore.swift @@ -44,10 +44,10 @@ public class ACDataStore: ObservableObject { /// - Parameters: /// - constant: Settings that define the contribution view. /// - sourceDates: An array of contributed dates. - func setup(constant: ACConstant, source sourceDates: [Date: ACData]? = nil) { + func setup(constant: ACConstant, source sourceDatas: [Date: ACData]? = nil) { self.constant = constant - if let sourceDates = sourceDates { - self.datas = ACDataProvider.shared.mappedData(constant: constant, source: sourceDates) + if let sourceDatas = sourceDatas { + self.datas = ACDataProvider.shared.mappedData(constant: constant, source: sourceDatas) } } } From 32702733644bfcc78f8798c551e3e94ecbbfc39c Mon Sep 17 00:00:00 2001 From: Maples7 Date: Wed, 3 Apr 2024 01:37:28 +0800 Subject: [PATCH 3/3] reset the paramter type of sourceDatas back to [Date] --- Sources/AxisContribution/AxisContribution.swift | 16 ++++++++-------- Sources/AxisContribution/View/ACGridStack.swift | 2 +- .../ViewModel/ACDataProvider.swift | 15 ++++++++++----- .../AxisContribution/ViewModel/ACDataStore.swift | 4 ++-- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/Sources/AxisContribution/AxisContribution.swift b/Sources/AxisContribution/AxisContribution.swift index d0b6e14..e8bc19b 100644 --- a/Sources/AxisContribution/AxisContribution.swift +++ b/Sources/AxisContribution/AxisContribution.swift @@ -47,7 +47,7 @@ public struct AxisContribution: View where B: View, F: View { @StateObject private var store = ACDataStore() private var constant: ACConstant = .init() - private var sourceDatas: [Date: ACData] = [:] + private var sourceDatas: [Date] = [] private var externalDatas: [[ACData]]? = nil public var background: ((ACIndexSet?, ACData?) -> B)? = nil @@ -189,10 +189,10 @@ public extension AxisContribution where B == EmptyView, F == EmptyView { /// Initializes `AxisContribution` /// - Parameters: /// - constant: Settings that define the contribution view. - /// - sourceDates: An array of contributed dates. - init(constant: ACConstant = .init(), source sourceDates: [Date: ACData] = [:]) { + /// - sourceDatas: An array of contributed dates. + init(constant: ACConstant = .init(), source sourceDatas: [Date] = []) { self.constant = constant - self.sourceDatas = sourceDates + self.sourceDatas = sourceDatas } /// Initializes `AxisContribution` @@ -210,15 +210,15 @@ public extension AxisContribution where B : View, F : View { /// Initializes `AxisContribution` /// - Parameters: /// - constant: Settings that define the contribution view. - /// - sourceDates: An array of contributed dates. + /// - sourceDatas: An array of contributed dates. /// - background: The view that is the background of the row view. /// - foreground: The view that is the foreground of the row view. init(constant: ACConstant = .init(), - source sourceDates: [Date: ACData] = [:], + source sourceDatas: [Date] = [], @ViewBuilder background: @escaping (ACIndexSet?, ACData?) -> B, @ViewBuilder foreground: @escaping (ACIndexSet?, ACData?) -> F) { self.constant = constant - self.sourceDatas = sourceDates + self.sourceDatas = sourceDatas self.background = background self.foreground = foreground } @@ -241,6 +241,6 @@ public extension AxisContribution where B : View, F : View { struct AxisContribution_Previews: PreviewProvider { static var previews: some View { - AxisContribution(constant: .init(), source: [:]) + AxisContribution(constant: .init(), source: []) } } diff --git a/Sources/AxisContribution/View/ACGridStack.swift b/Sources/AxisContribution/View/ACGridStack.swift index a3fd8aa..50d76c0 100644 --- a/Sources/AxisContribution/View/ACGridStack.swift +++ b/Sources/AxisContribution/View/ACGridStack.swift @@ -220,7 +220,7 @@ struct ACGridStack_Previews: PreviewProvider { static var previews: some View { AxisContribution( constant: .init(), - source: [:] + source: [] ) .padding() } diff --git a/Sources/AxisContribution/ViewModel/ACDataProvider.swift b/Sources/AxisContribution/ViewModel/ACDataProvider.swift index 3c6d42b..be1dbcf 100644 --- a/Sources/AxisContribution/ViewModel/ACDataProvider.swift +++ b/Sources/AxisContribution/ViewModel/ACDataProvider.swift @@ -35,16 +35,21 @@ public class ACDataProvider { /// - constant: Settings that define the contribution view. /// - sourceDatas: An dict of contributed dates and counts. /// - Returns: mapped data - public func mappedData(constant: ACConstant, source sourceDatas: [Date: ACData]) -> [[ACData]] { + public func mappedData(constant: ACConstant, source sourceDatas: [Date]) -> [[ACData]] { var newDatas = [[ACData]]() var dateWeekly = Date.datesWeekly(from: constant.fromDate, to: constant.toDate) if constant.axisMode == .vertical { dateWeekly = dateWeekly.reversed() } - // make dates to the start of the day - var cleanDatas: [Date: ACData] = [:] - sourceDatas.forEach { date, count in - cleanDatas[date.startOfDay] = count + // NOTE: make dates a hash table with keys to be the start of days + var cleanDatas: [Date:ACData] = [:] + sourceDatas.forEach { date in + let startOfDate = date.startOfDay + if cleanDatas[startOfDate] == nil { + cleanDatas[startOfDate] = ACData(date: startOfDate, count: 1) + } else { + cleanDatas[startOfDate]?.count += 1 + } } dateWeekly.forEach { date in let datas = date.datesInWeek.map { date -> ACData in diff --git a/Sources/AxisContribution/ViewModel/ACDataStore.swift b/Sources/AxisContribution/ViewModel/ACDataStore.swift index 73c7b6b..a03d291 100644 --- a/Sources/AxisContribution/ViewModel/ACDataStore.swift +++ b/Sources/AxisContribution/ViewModel/ACDataStore.swift @@ -43,8 +43,8 @@ public class ACDataStore: ObservableObject { /// A method that creates data. /// - Parameters: /// - constant: Settings that define the contribution view. - /// - sourceDates: An array of contributed dates. - func setup(constant: ACConstant, source sourceDatas: [Date: ACData]? = nil) { + /// - sourceDatas: An array of contributed dates. + func setup(constant: ACConstant, source sourceDatas: [Date]? = nil) { self.constant = constant if let sourceDatas = sourceDatas { self.datas = ACDataProvider.shared.mappedData(constant: constant, source: sourceDatas)