diff --git a/AxisContributionExample/AxisContributionExample.xcodeproj/project.pbxproj b/AxisContributionExample/AxisContributionExample.xcodeproj/project.pbxproj index 395c811..c52481f 100644 --- a/AxisContributionExample/AxisContributionExample.xcodeproj/project.pbxproj +++ b/AxisContributionExample/AxisContributionExample.xcodeproj/project.pbxproj @@ -361,7 +361,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = SM6445X39C; + DEVELOPMENT_TEAM = 5FRV5G4F5S; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; @@ -391,7 +391,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = SM6445X39C; + DEVELOPMENT_TEAM = 5FRV5G4F5S; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; @@ -424,7 +424,7 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = SM6445X39C; + DEVELOPMENT_TEAM = 5FRV5G4F5S; ENABLE_HARDENED_RUNTIME = YES; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; diff --git a/AxisContributionExample/Shared/ContentView.swift b/AxisContributionExample/Shared/ContentView.swift index 8095948..403afd5 100644 --- a/AxisContributionExample/Shared/ContentView.swift +++ b/AxisContributionExample/Shared/ContentView.swift @@ -16,13 +16,13 @@ struct ContentView: View { @State private var constant: ACConstant = .init(axisMode: .horizontal, levelLabel: .number) @State private var rowSize: CGFloat = 11 @State private var rowImageName: String = "" - @State private var dates: [Date] = [] + @State private var dataSet: [Date: ACData] = [:] var body: some View { VStack { Spacer() // AxisContribution(constant: constant, source: getDates()) - AxisContribution(constant: constant, source: dates) { indexSet, data in + AxisContribution(constant: constant, source: dataSet) { indexSet, data in if rowImageName.isEmpty { defaultBackground }else { @@ -64,13 +64,13 @@ struct ContentView: View { } .pickerStyle(.segmented) Button("Refresh Dates") { - dates = getDates() + dataSet = getDates() } .padding() } .padding() .onAppear { - dates = getDates() + dataSet = getDates() } } @@ -103,11 +103,11 @@ struct ContentView: View { .frame(width: rowSize, height: rowSize) } - private func getDates() -> [Date] { - var sequenceDatas = [Date]() + private func getDates() -> [Date: ACData] { + var sequenceDatas = [Date: ACData]() for _ in 0..<300 { let date = Date.randomBetween(start: Date().dateHalfAyear, end: Date()) - sequenceDatas.append(date) + sequenceDatas[date.startOfDay] = .init(date: date.startOfDay, count: Int.random(in: 0...10)) } return sequenceDatas } diff --git a/Sources/AxisContribution/AxisContribution.swift b/Sources/AxisContribution/AxisContribution.swift index 9027fc6..a66ab57 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]? = nil + private var sourceDatas: [Date: ACData] = [:] private var externalDatas: [[ACData]]? = nil public var background: ((ACIndexSet?, ACData?) -> B)? = nil @@ -190,7 +190,7 @@ public extension AxisContribution where B == EmptyView, F == EmptyView { /// - Parameters: /// - constant: Settings that define the contribution view. /// - sourceDates: An array of contributed dates. - init(constant: ACConstant = .init(), source sourceDates: [Date] = []) { + init(constant: ACConstant = .init(), source sourceDates: [Date: ACData] = [:]) { self.constant = constant self.sourceDatas = sourceDates } @@ -214,7 +214,7 @@ public extension AxisContribution where B : View, F : View { /// - 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] = [], + source sourceDates: [Date: ACData] = [:], @ViewBuilder background: @escaping (ACIndexSet?, ACData?) -> B, @ViewBuilder foreground: @escaping (ACIndexSet?, ACData?) -> F) { self.constant = constant @@ -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/Model/ACData.swift b/Sources/AxisContribution/Model/ACData.swift index a0a7eb6..741cbc5 100644 --- a/Sources/AxisContribution/Model/ACData.swift +++ b/Sources/AxisContribution/Model/ACData.swift @@ -38,7 +38,7 @@ public class ACData: Equatable { /// - Parameters: /// - date: Current date. /// - count: The number contributed to the current date. The default value is `0`. - init(date: Date, count: Int = 0) { + public init(date: Date, count: Int = 0) { self.date = date self.count = count } diff --git a/Sources/AxisContribution/View/ACGridStack.swift b/Sources/AxisContribution/View/ACGridStack.swift index 96cca32..87399cc 100644 --- a/Sources/AxisContribution/View/ACGridStack.swift +++ b/Sources/AxisContribution/View/ACGridStack.swift @@ -27,12 +27,11 @@ import SwiftUI /// A view that represents a grid view. struct ACGridStack: View where B: View, F: View { - @EnvironmentObject private var store: ACDataStore let constant: ACConstant - var background: ((ACIndexSet?, ACData?) -> B)? = nil - var foreground: ((ACIndexSet?, ACData?) -> F)? = nil + var background: ((ACIndexSet?, ACData?) -> B)? + var foreground: ((ACIndexSet?, ACData?) -> F)? @State private var rowSize: CGSize = .zero @State private var titleWidth: CGFloat = .zero @@ -43,7 +42,8 @@ struct ACGridStack: View where B: View, F: View { .font(store.constant.font) } - //MARK: - Properties + // MARK: - Properties + /// Property that displays the grid view. private var content: some View { let spacing = store.constant.spacing @@ -66,14 +66,14 @@ struct ACGridStack: View where B: View, F: View { Rectangle() .fill(Color.clear) .frame(width: rowSize.height, height: rowSize.height) - .overlay(getMonthTitle(column) ,alignment: .leading) + .overlay(getMonthTitle(column), alignment: .leading) ForEach(Array(datas.enumerated()), id: \.offset) { row, data in getRowView(column: column, row: row, data: data) } } } } - }else { + } else { VStack(alignment: .leading, spacing: spacing) { ZStack(alignment: .bottom) { let size = titleWidth @@ -100,7 +100,7 @@ struct ACGridStack: View where B: View, F: View { } } - //MARK: - Methods + // MARK: - Methods /// A method that returns a row view. /// - Parameters: @@ -110,15 +110,10 @@ struct ACGridStack: View where B: View, F: View { /// - Returns: - private func getRowView(column: Int, row: Int, data: ACData) -> some View { ZStack { - if data.date.startOfDay > Date().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) - } + background?(ACIndexSet(column: column, row: row), data) + foreground?(ACIndexSet(column: column, row: row), data) + .opacity(getOpacity(count: data.count)) + .takeSize($rowSize) } } @@ -135,15 +130,18 @@ struct ACGridStack: View where B: View, F: View { .fixedSize(horizontal: true, vertical: false) .takeSize($_titleSize) } - }else { - Text(store.datas[column][0].date.monthTitle) - .lineLimit(1) - .fixedSize(horizontal: true, vertical: false) - .takeSize($_titleSize) + } else { + let date = store.datas[column][0].date + if date > constant.fromDate && date < constant.toDate { + Text(date.monthTitle) + .lineLimit(1) + .fixedSize(horizontal: true, vertical: false) + .takeSize($_titleSize) + } } } } - .onChange(of: _titleSize) { newValue in + .onChange(of: _titleSize) { _ in titleWidth = max(titleWidth, _titleSize.width) } } @@ -154,21 +152,20 @@ struct ACGridStack: View where B: View, F: View { private func getOpacity(count: Int) -> CGFloat { if count == 0 { return ACLevel.zero.opacity - }else if ACLevel.first.rawValue * store.constant.levelSpacing >= count { + } else if ACLevel.first.rawValue * store.constant.levelSpacing >= count { return ACLevel.first.opacity - }else if ACLevel.second.rawValue * store.constant.levelSpacing >= count { + } else if ACLevel.second.rawValue * store.constant.levelSpacing >= count { return ACLevel.second.opacity - }else if ACLevel.third.rawValue * store.constant.levelSpacing >= count { + } else if ACLevel.third.rawValue * store.constant.levelSpacing >= count { return ACLevel.third.opacity - }else if ACLevel.fourth.rawValue * store.constant.levelSpacing >= count { + } else if ACLevel.fourth.rawValue * store.constant.levelSpacing >= count { return ACLevel.fourth.opacity } return 1.0 } } -extension ACGridStack where B : View, F : View { - +extension ACGridStack where B: View, F: View { /// Initializes `ACGridStack` /// - Parameters: /// - constant: Settings that define the contribution view. @@ -176,7 +173,8 @@ extension ACGridStack where B : View, F : View { /// - foreground: The view that is the foreground of the row view. init(constant: ACConstant, @ViewBuilder background: @escaping (ACIndexSet?, ACData?) -> B, - @ViewBuilder foreground: @escaping (ACIndexSet?, ACData?) -> F) { + @ViewBuilder foreground: @escaping (ACIndexSet?, ACData?) -> F) + { self.constant = constant self.background = background self.foreground = foreground @@ -185,6 +183,9 @@ extension ACGridStack where B : View, F : View { struct ACGridStack_Previews: PreviewProvider { static var previews: some View { - AxisContribution(constant: .init(), source: []) + AxisContribution( + constant: .init(), + source: [:] + ) } } diff --git a/Sources/AxisContribution/ViewModel/ACDataProvider.swift b/Sources/AxisContribution/ViewModel/ACDataProvider.swift index b33f10f..541e558 100644 --- a/Sources/AxisContribution/ViewModel/ACDataProvider.swift +++ b/Sources/AxisContribution/ViewModel/ACDataProvider.swift @@ -35,7 +35,7 @@ public class ACDataProvider { /// - constant: Settings that define the contribution view. /// - sourceDates: An array of contributed dates. /// - Returns: mapped data - public func mappedData(constant: ACConstant, source sourceDates: [Date]) -> [[ACData]] { + public func mappedData(constant: ACConstant, source sourceDates: [Date: ACData]) -> [[ACData]] { var newDatas = [[ACData]]() var dateWeekly = Date.datesWeekly(from: constant.fromDate, to: constant.toDate) if constant.axisMode == .vertical { @@ -43,23 +43,14 @@ public class ACDataProvider { } dateWeekly.forEach { date in let datas = date.datesInWeek.map { date -> ACData in - let data = ACData(date: date, count: getDateCount(sourceDates: sourceDates, date: date)) - return data + if let data = sourceDates[date] { + return data + } else { + return ACData(date: date, count: 0) + } } newDatas.append(datas) } return newDatas } - - /// Returns data corresponding to the date you pass in. - /// - Parameters: - /// - sourceDates: An array of contributed dates. - /// - date: The date required to return the data. - /// - Returns: - - private func getDateCount(sourceDates: [Date], date: Date) -> Int { - let dates = sourceDates.filter { d in - Calendar.current.isDate(d, inSameDayAs: date) - } - return dates.count - } } diff --git a/Sources/AxisContribution/ViewModel/ACDataStore.swift b/Sources/AxisContribution/ViewModel/ACDataStore.swift index f8a22ec..4d5d70f 100644 --- a/Sources/AxisContribution/ViewModel/ACDataStore.swift +++ b/Sources/AxisContribution/ViewModel/ACDataStore.swift @@ -44,7 +44,7 @@ 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]? = nil) { + func setup(constant: ACConstant, source sourceDates: [Date: ACData]? = nil) { self.constant = constant if let sourceDates = sourceDates { self.datas = ACDataProvider.shared.mappedData(constant: constant, source: sourceDates)