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

Bugfix: weekDay tooltip with considering user locale settings, start of dates as the key of dict etc. #13

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,4 @@ fastlane/test_output
# https://github.com/johnno1962/injectionforxcode

iOSInjectionProject/
.swiftpm/
18 changes: 9 additions & 9 deletions Sources/AxisContribution/AxisContribution.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public struct AxisContribution<B, F>: 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
Expand All @@ -71,7 +71,7 @@ public struct AxisContribution<B, F>: View where B: View, F: View {
}
}
.contentShape(Rectangle())
}else {
} else {
VStack(spacing: 0) {
content
}
Expand Down Expand Up @@ -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`
Expand All @@ -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
}
Expand All @@ -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: [])
}
}
49 changes: 37 additions & 12 deletions Sources/AxisContribution/View/ACGridStack.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ struct ACGridStack<B, F>: 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)
}
Expand All @@ -77,11 +77,11 @@ struct ACGridStack<B, F>: 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
Expand Down Expand Up @@ -110,10 +110,15 @@ struct ACGridStack<B, F>: 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)
}
}
}

Expand Down Expand Up @@ -145,7 +150,26 @@ struct ACGridStack<B, F>: 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
Expand Down Expand Up @@ -196,7 +220,8 @@ struct ACGridStack_Previews: PreviewProvider {
static var previews: some View {
AxisContribution(
constant: .init(),
source: [:]
source: []
)
.padding()
}
}
16 changes: 13 additions & 3 deletions Sources/AxisContribution/ViewModel/ACDataProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,27 @@ 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]] {
var newDatas = [[ACData]]()
var dateWeekly = Date.datesWeekly(from: constant.fromDate, to: constant.toDate)
if constant.axisMode == .vertical {
dateWeekly = dateWeekly.reversed()
}
// 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
if let data = sourceDates[date] {
if let data = cleanDatas[date] {
return data
} else {
return ACData(date: date, count: 0)
Expand Down
8 changes: 4 additions & 4 deletions Sources/AxisContribution/ViewModel/ACDataStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ 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 sourceDates: [Date: ACData]? = nil) {
/// - sourceDatas: An array of contributed dates.
func setup(constant: ACConstant, source sourceDatas: [Date]? = 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)
}
}
}