code clean up
This commit is contained in:
@@ -41,6 +41,7 @@
|
|||||||
1CAD603B27A5C1C800C520BD /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CAD603227A5C1C800C520BD /* ContentView.swift */; };
|
1CAD603B27A5C1C800C520BD /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CAD603227A5C1C800C520BD /* ContentView.swift */; };
|
||||||
1CAD603C27A5C1C800C520BD /* HeaderStatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CAD603327A5C1C800C520BD /* HeaderStatsView.swift */; };
|
1CAD603C27A5C1C800C520BD /* HeaderStatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CAD603327A5C1C800C520BD /* HeaderStatsView.swift */; };
|
||||||
1CAD603E27A6ECCD00C520BD /* SwitchableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CAD603D27A6ECCD00C520BD /* SwitchableView.swift */; };
|
1CAD603E27A6ECCD00C520BD /* SwitchableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CAD603D27A6ECCD00C520BD /* SwitchableView.swift */; };
|
||||||
|
1CB101C527B62A2D00D1C033 /* EmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CB101C427B62A2D00D1C033 /* EmptyView.swift */; };
|
||||||
1CC469AA278F30A0003E0C6E /* BGTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC469A9278F30A0003E0C6E /* BGTask.swift */; };
|
1CC469AA278F30A0003E0C6E /* BGTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC469A9278F30A0003E0C6E /* BGTask.swift */; };
|
||||||
1CC469AC27907D48003E0C6E /* DayChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC469AB27907D48003E0C6E /* DayChartView.swift */; };
|
1CC469AC27907D48003E0C6E /* DayChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CC469AB27907D48003E0C6E /* DayChartView.swift */; };
|
||||||
1CD90B07278C7DE0001C4FEA /* Tests_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B06278C7DE0001C4FEA /* Tests_iOS.swift */; };
|
1CD90B07278C7DE0001C4FEA /* Tests_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD90B06278C7DE0001C4FEA /* Tests_iOS.swift */; };
|
||||||
@@ -142,6 +143,7 @@
|
|||||||
1CAD603227A5C1C800C520BD /* ContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
1CAD603227A5C1C800C520BD /* ContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||||
1CAD603327A5C1C800C520BD /* HeaderStatsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderStatsView.swift; sourceTree = "<group>"; };
|
1CAD603327A5C1C800C520BD /* HeaderStatsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderStatsView.swift; sourceTree = "<group>"; };
|
||||||
1CAD603D27A6ECCD00C520BD /* SwitchableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchableView.swift; sourceTree = "<group>"; };
|
1CAD603D27A6ECCD00C520BD /* SwitchableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchableView.swift; sourceTree = "<group>"; };
|
||||||
|
1CB101C427B62A2D00D1C033 /* EmptyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyView.swift; sourceTree = "<group>"; };
|
||||||
1CC03FA627B5865600B530AF /* Shared 2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Shared 2.xcdatamodel"; sourceTree = "<group>"; };
|
1CC03FA627B5865600B530AF /* Shared 2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Shared 2.xcdatamodel"; sourceTree = "<group>"; };
|
||||||
1CC469A9278F30A0003E0C6E /* BGTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGTask.swift; sourceTree = "<group>"; };
|
1CC469A9278F30A0003E0C6E /* BGTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGTask.swift; sourceTree = "<group>"; };
|
||||||
1CC469AB27907D48003E0C6E /* DayChartView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DayChartView.swift; sourceTree = "<group>"; };
|
1CC469AB27907D48003E0C6E /* DayChartView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DayChartView.swift; sourceTree = "<group>"; };
|
||||||
@@ -258,6 +260,7 @@
|
|||||||
1CAD602F27A5C1C800C520BD /* AddMoodHeaderView.swift */,
|
1CAD602F27A5C1C800C520BD /* AddMoodHeaderView.swift */,
|
||||||
1CAD603127A5C1C800C520BD /* BGView.swift */,
|
1CAD603127A5C1C800C520BD /* BGView.swift */,
|
||||||
1CAD603227A5C1C800C520BD /* ContentView.swift */,
|
1CAD603227A5C1C800C520BD /* ContentView.swift */,
|
||||||
|
1CB101C427B62A2D00D1C033 /* EmptyView.swift */,
|
||||||
1CAD602E27A5C1C800C520BD /* FilterView.swift */,
|
1CAD602E27A5C1C800C520BD /* FilterView.swift */,
|
||||||
1CAD602D27A5C1C800C520BD /* GraphView.swift */,
|
1CAD602D27A5C1C800C520BD /* GraphView.swift */,
|
||||||
1CAD603027A5C1C800C520BD /* HeaderPercView.swift */,
|
1CAD603027A5C1C800C520BD /* HeaderPercView.swift */,
|
||||||
@@ -606,6 +609,7 @@
|
|||||||
1CD90B53278C7E7A001C4FEA /* FeelsWidget.intentdefinition in Sources */,
|
1CD90B53278C7E7A001C4FEA /* FeelsWidget.intentdefinition in Sources */,
|
||||||
1CC469AC27907D48003E0C6E /* DayChartView.swift in Sources */,
|
1CC469AC27907D48003E0C6E /* DayChartView.swift in Sources */,
|
||||||
1C26190327960CE500FDC148 /* ChartDataBuildable.swift in Sources */,
|
1C26190327960CE500FDC148 /* ChartDataBuildable.swift in Sources */,
|
||||||
|
1CB101C527B62A2D00D1C033 /* EmptyView.swift in Sources */,
|
||||||
1CAD603627A5C1C800C520BD /* GraphView.swift in Sources */,
|
1CAD603627A5C1C800C520BD /* GraphView.swift in Sources */,
|
||||||
1CD90B66278C7EBA001C4FEA /* MoodEntryExtension.swift in Sources */,
|
1CD90B66278C7EBA001C4FEA /* MoodEntryExtension.swift in Sources */,
|
||||||
1CD90B1C278C7DE0001C4FEA /* Persistence.swift in Sources */,
|
1CD90B1C278C7DE0001C4FEA /* Persistence.swift in Sources */,
|
||||||
|
|||||||
@@ -28,6 +28,27 @@ class Random {
|
|||||||
}
|
}
|
||||||
return updateTime
|
return updateTime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func weekdayName(fromDate date: Date) -> String {
|
||||||
|
let weekday = Calendar.current.component(.weekday, from: date)
|
||||||
|
let calendar = Calendar.current
|
||||||
|
let dayIndex = ((weekday - 1) + (calendar.firstWeekday - 1)) % 7
|
||||||
|
return calendar.weekdaySymbols[dayIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
static func monthName(fromMonthInt: Int) -> String {
|
||||||
|
let monthName = DateFormatter().monthSymbols[fromMonthInt-1]
|
||||||
|
return monthName
|
||||||
|
}
|
||||||
|
|
||||||
|
static func dayFormat(fromDate date: Date) -> String {
|
||||||
|
let components = Calendar.current.dateComponents([.day], from: date)
|
||||||
|
let day = components.day!
|
||||||
|
|
||||||
|
let formatter = NumberFormatter()
|
||||||
|
formatter.numberStyle = .ordinal
|
||||||
|
return formatter.string(from: NSNumber(integerLiteral: day)) ?? ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Date: RawRepresentable {
|
extension Date: RawRepresentable {
|
||||||
|
|||||||
@@ -16,23 +16,34 @@ struct ContentViewConstants {
|
|||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
@Environment(\.managedObjectContext) private var viewContext
|
@Environment(\.managedObjectContext) private var viewContext
|
||||||
|
|
||||||
@AppStorage(UserDefaultsStore.Keys.needsOnboarding.rawValue, store: GroupUserDefaults.groupDefaults) private var needsOnboarding = true
|
@AppStorage(UserDefaultsStore.Keys.needsOnboarding.rawValue, store: GroupUserDefaults.groupDefaults) private var needsOnboarding = true
|
||||||
|
|
||||||
@AppStorage(UserDefaultsStore.Keys.deleteEnable.rawValue, store: GroupUserDefaults.groupDefaults) private var deleteEnabled = true
|
@AppStorage(UserDefaultsStore.Keys.deleteEnable.rawValue, store: GroupUserDefaults.groupDefaults) private var deleteEnabled = true
|
||||||
@AppStorage(UserDefaultsStore.Keys.mainViewTopHeaderIndex.rawValue, store: GroupUserDefaults.groupDefaults) private var mainViewTopHeaderIndex = 0
|
|
||||||
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
|
||||||
|
// top header storage
|
||||||
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var currentSelectedHeaderViewBackDays: Int = 30
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var currentSelectedHeaderViewBackDays: Int = 30
|
||||||
@AppStorage(UserDefaultsStore.Keys.contentViewHeaderTagViewOneViewType.rawValue, store: GroupUserDefaults.groupDefaults) private var firstSwichableHeaderViewType: MainSwitchableViewType = .total
|
@AppStorage(UserDefaultsStore.Keys.contentViewHeaderTagViewOneViewType.rawValue, store: GroupUserDefaults.groupDefaults) private var firstSwichableHeaderViewType: MainSwitchableViewType = .total
|
||||||
@AppStorage(UserDefaultsStore.Keys.contentViewHeaderTagViewTwoViewType.rawValue, store: GroupUserDefaults.groupDefaults) private var secondSwichableHeaderViewType: MainSwitchableViewType = .total
|
@AppStorage(UserDefaultsStore.Keys.contentViewHeaderTagViewTwoViewType.rawValue, store: GroupUserDefaults.groupDefaults) private var secondSwichableHeaderViewType: MainSwitchableViewType = .total
|
||||||
@AppStorage(UserDefaultsStore.Keys.contentViewHeaderTag.rawValue, store: GroupUserDefaults.groupDefaults) private var switchableViewSelectedIndex = 1
|
@AppStorage(UserDefaultsStore.Keys.contentViewHeaderTag.rawValue, store: GroupUserDefaults.groupDefaults) private var switchableViewSelectedIndex = 1
|
||||||
|
//
|
||||||
|
|
||||||
|
// edit row
|
||||||
@State private var showingSheet = false
|
@State private var showingSheet = false
|
||||||
@State private var showTodayInput = true
|
|
||||||
@State private var selectedEntry: MoodEntry?
|
@State private var selectedEntry: MoodEntry?
|
||||||
|
//
|
||||||
|
|
||||||
|
@State private var showTodayInput = true
|
||||||
@State private var showUpdateEntryAlert = false
|
@State private var showUpdateEntryAlert = false
|
||||||
|
|
||||||
|
// header properties
|
||||||
@State private var headerHeight: CGFloat = ContentViewConstants.maxHeaderHeight
|
@State private var headerHeight: CGFloat = ContentViewConstants.maxHeaderHeight
|
||||||
@State private var headerViewType: MainSwitchableViewType = .total
|
@State private var headerViewType: MainSwitchableViewType = .total
|
||||||
@State private var currentSelectedHeaderViewViewType: MainSwitchableViewType = .total
|
@State private var currentSelectedHeaderViewViewType: MainSwitchableViewType = .total
|
||||||
@State private var headerOpacity: Double = 1.0
|
@State private var headerOpacity: Double = 1.0
|
||||||
|
//
|
||||||
|
|
||||||
let minHeaderHeight = ContentViewConstants.minHeaderHeight
|
let minHeaderHeight = ContentViewConstants.minHeaderHeight
|
||||||
let maxHeaderHeight = ContentViewConstants.maxHeaderHeight
|
let maxHeaderHeight = ContentViewConstants.maxHeaderHeight
|
||||||
@@ -97,67 +108,7 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateTitleHeader(forEntry entry: MoodEntry?) -> String {
|
// MARK: functions that do view type work
|
||||||
guard let entry = entry else {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
let components = Calendar.current.dateComponents([.day, .month, .year], from: entry.forDate!)
|
|
||||||
// let day = components.day!
|
|
||||||
let month = components.month!
|
|
||||||
let year = components.year!
|
|
||||||
|
|
||||||
let monthName = monthName(fromMonthInt: month)
|
|
||||||
let weekday = weekdayName(fromDate:entry.forDate!)
|
|
||||||
let dayz = dayFormat(fromDate:entry.forDate!)
|
|
||||||
|
|
||||||
let string = weekday + " " + monthName + " " + dayz + " " + String(year)
|
|
||||||
|
|
||||||
return String(format: String(localized: "content_view_fill_in_missing_entry"), string)
|
|
||||||
}
|
|
||||||
|
|
||||||
private var settingsButtonView: some View {
|
|
||||||
HStack {
|
|
||||||
Spacer()
|
|
||||||
Button(action: {
|
|
||||||
showingSheet.toggle()
|
|
||||||
}, label: {
|
|
||||||
Image(systemName: "gear")
|
|
||||||
.foregroundColor(Color(UIColor.darkGray))
|
|
||||||
.font(.system(size: 20))
|
|
||||||
}).sheet(isPresented: $showingSheet) {
|
|
||||||
SettingsView(editedDataClosure: {
|
|
||||||
withAnimation{
|
|
||||||
viewModel.updateData()
|
|
||||||
}
|
|
||||||
}, updateBoardingDataClosure: { onboardingData in
|
|
||||||
viewModel.updateOnboardingData(onboardingData: onboardingData)
|
|
||||||
})
|
|
||||||
}.padding(.trailing)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func weekdayName(fromDate date: Date) -> String {
|
|
||||||
let weekday = Calendar.current.component(.weekday, from: date)
|
|
||||||
let calendar = Calendar.current
|
|
||||||
let dayIndex = ((weekday - 1) + (calendar.firstWeekday - 1)) % 7
|
|
||||||
return calendar.weekdaySymbols[dayIndex]
|
|
||||||
}
|
|
||||||
|
|
||||||
private func monthName(fromMonthInt: Int) -> String {
|
|
||||||
let monthName = DateFormatter().monthSymbols[fromMonthInt-1]
|
|
||||||
return monthName
|
|
||||||
}
|
|
||||||
|
|
||||||
private func dayFormat(fromDate date: Date) -> String {
|
|
||||||
let components = Calendar.current.dateComponents([.day], from: date)
|
|
||||||
let day = components.day!
|
|
||||||
|
|
||||||
let formatter = NumberFormatter()
|
|
||||||
formatter.numberStyle = .ordinal
|
|
||||||
return formatter.string(from: NSNumber(integerLiteral: day)) ?? ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func calcuateViewAlpha() {
|
func calcuateViewAlpha() {
|
||||||
let perc = (((Double(headerHeight) - minHeaderHeight) * 100) / (maxHeaderHeight - minHeaderHeight)) / 100
|
let perc = (((Double(headerHeight) - minHeaderHeight) * 100) / (maxHeaderHeight - minHeaderHeight)) / 100
|
||||||
headerOpacity = perc
|
headerOpacity = perc
|
||||||
@@ -186,98 +137,44 @@ struct ContentView: View {
|
|||||||
headerHeight = newValue
|
headerHeight = newValue
|
||||||
}
|
}
|
||||||
|
|
||||||
private var listView: some View {
|
private func updateTitleHeader(forEntry entry: MoodEntry?) -> String {
|
||||||
ScrollView {
|
guard let entry = entry else {
|
||||||
LazyVStack(spacing: 5, pinnedViews: [.sectionHeaders]) {
|
return ""
|
||||||
ForEach(viewModel.grouped.sorted(by: {
|
}
|
||||||
$0.key > $1.key
|
|
||||||
}), id: \.key) { year, months in
|
|
||||||
|
|
||||||
// for reach month
|
let components = Calendar.current.dateComponents([.day, .month, .year], from: entry.forDate!)
|
||||||
ForEach(months.sorted(by: {
|
// let day = components.day!
|
||||||
$0.key > $1.key
|
let month = components.month!
|
||||||
}), id: \.key) { month, entries in
|
let year = components.year!
|
||||||
Section(header: SectionHeaderView(month: month, year: year)) {
|
|
||||||
monthListView(month: month, year: year, entries: entries)
|
let monthName = Random.monthName(fromMonthInt: month)
|
||||||
}
|
let weekday = Random.weekdayName(fromDate:entry.forDate!)
|
||||||
}
|
let dayz = Random.dayFormat(fromDate:entry.forDate!)
|
||||||
}
|
|
||||||
}.background(
|
let string = weekday + " " + monthName + " " + dayz + " " + String(year)
|
||||||
GeometryReader { proxy in
|
|
||||||
let offset = proxy.frame(in: .named("scroll")).minY
|
return String(format: String(localized: "content_view_fill_in_missing_entry"), string)
|
||||||
Color.clear.preference(key: ViewOffsetKey.self, value: offset)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.background(
|
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
|
||||||
)
|
|
||||||
.coordinateSpace(name: "scroll")
|
|
||||||
.onPreferenceChange(ViewOffsetKey.self) { value in
|
|
||||||
if viewModel.numberOfItems > 10 {
|
|
||||||
calculateHeight(minHeight: ContentViewConstants.minHeaderHeight,
|
|
||||||
maxHeight: ContentViewConstants.maxHeaderHeight,
|
|
||||||
yOffset: value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.cornerRadius(10, corners: [.topLeft, .topRight])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func SectionHeaderView(month: Int, year: Int) -> some View {
|
// MARK: Views
|
||||||
Text("\(monthName(fromMonthInt: month)) \(String(year))")
|
private var settingsButtonView: some View {
|
||||||
.font(.title)
|
|
||||||
.foregroundColor(Color(UIColor.label))
|
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
.padding()
|
|
||||||
.background(
|
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func monthListView(month: Int, year: Int, entries: [MoodEntry]) -> some View {
|
|
||||||
VStack {
|
|
||||||
// for reach all entries
|
|
||||||
ForEach(entries.sorted(by: {
|
|
||||||
return $0.forDate! > $1.forDate!
|
|
||||||
}), id: \.self) { entry in
|
|
||||||
entryListView(entry: entry)
|
|
||||||
.contentShape(Rectangle())
|
|
||||||
.onTapGesture(perform: {
|
|
||||||
selectedEntry = entry
|
|
||||||
showUpdateEntryAlert = true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func entryListView(entry: MoodEntry) -> some View {
|
|
||||||
HStack {
|
HStack {
|
||||||
entry.mood.icon
|
Spacer()
|
||||||
.resizable()
|
Button(action: {
|
||||||
.aspectRatio(contentMode: .fit)
|
showingSheet.toggle()
|
||||||
.frame(width: 40, height: 40, alignment: .center)
|
}, label: {
|
||||||
.foregroundColor(entry.mood.color)
|
Image(systemName: "gear")
|
||||||
.padding(.leading, 5)
|
.foregroundColor(Color(UIColor.darkGray))
|
||||||
|
.font(.system(size: 20))
|
||||||
VStack {
|
}).sheet(isPresented: $showingSheet) {
|
||||||
HStack {
|
SettingsView(editedDataClosure: {
|
||||||
Text(weekdayName(fromDate:entry.forDate!))
|
withAnimation{
|
||||||
.font(.title3)
|
viewModel.updateData()
|
||||||
.foregroundColor(Color(UIColor.label))
|
}
|
||||||
Text(" - ")
|
}, updateBoardingDataClosure: { onboardingData in
|
||||||
.padding([.leading, .trailing], -10)
|
viewModel.updateOnboardingData(onboardingData: onboardingData)
|
||||||
Text(dayFormat(fromDate:entry.forDate!))
|
})
|
||||||
.font(.title3)
|
}.padding(.trailing)
|
||||||
.foregroundColor(Color(UIColor.label))
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
.multilineTextAlignment(.leading)
|
|
||||||
|
|
||||||
Text(entry.moodValue == Mood.missing.rawValue ? String(localized: "mood_value_missing_tap_to_add") : "\(entry.moodString)")
|
|
||||||
.font(.body)
|
|
||||||
.foregroundColor(Color(UIColor.systemGray))
|
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,30 +230,41 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var emptyView: some View {
|
private var listView: some View {
|
||||||
ZStack {
|
ScrollView {
|
||||||
Color(theme.currentTheme.secondaryBGColor)
|
LazyVStack(spacing: 5, pinnedViews: [.sectionHeaders]) {
|
||||||
|
ForEach(viewModel.grouped.sorted(by: {
|
||||||
|
$0.key > $1.key
|
||||||
|
}), id: \.key) { year, months in
|
||||||
|
|
||||||
VStack {
|
// for reach month
|
||||||
Text(String(localized: "content_view_empty_title"))
|
ForEach(months.sorted(by: {
|
||||||
.font(.title)
|
$0.key > $1.key
|
||||||
.foregroundColor(Color(UIColor.label))
|
}), id: \.key) { month, entries in
|
||||||
.padding()
|
Section(header: SectionHeaderView(month: month, year: year)) {
|
||||||
|
monthListView(month: month, year: year, entries: entries)
|
||||||
Text(String(localized: "content_view_empty_title"))
|
}
|
||||||
.font(.body)
|
|
||||||
.foregroundColor(Color(UIColor.label))
|
|
||||||
.padding()
|
|
||||||
AddMoodHeaderView(addItemHeaderClosure: { (mood, date) in
|
|
||||||
withAnimation {
|
|
||||||
viewModel.add(mood: mood, forDate: date, entryType: .header)
|
|
||||||
}
|
}
|
||||||
}, overrideDay: viewModel.shouldShowVotingHeader() ? .Today : .Previous)
|
}
|
||||||
|
}.background(
|
||||||
|
GeometryReader { proxy in
|
||||||
|
let offset = proxy.frame(in: .named("scroll")).minY
|
||||||
|
Color.clear.preference(key: ViewOffsetKey.self, value: offset)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.background(
|
||||||
|
Color(theme.currentTheme.secondaryBGColor)
|
||||||
|
)
|
||||||
|
.coordinateSpace(name: "scroll")
|
||||||
|
.onPreferenceChange(ViewOffsetKey.self) { value in
|
||||||
|
if viewModel.numberOfItems > 10 {
|
||||||
|
calculateHeight(minHeight: ContentViewConstants.minHeaderHeight,
|
||||||
|
maxHeight: ContentViewConstants.maxHeaderHeight,
|
||||||
|
yOffset: value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
.cornerRadius(10, corners: [.topLeft, .topRight])
|
||||||
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
|
||||||
.padding()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private var mainView: some View {
|
private var mainView: some View {
|
||||||
@@ -364,7 +272,7 @@ struct ContentView: View {
|
|||||||
settingsButtonView
|
settingsButtonView
|
||||||
if viewModel.hasNoData {
|
if viewModel.hasNoData {
|
||||||
Spacer()
|
Spacer()
|
||||||
emptyView
|
EmptyView(viewModel: viewModel)
|
||||||
Spacer()
|
Spacer()
|
||||||
} else {
|
} else {
|
||||||
ZStack {
|
ZStack {
|
||||||
@@ -407,6 +315,67 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// view that make up the list body
|
||||||
|
extension ContentView {
|
||||||
|
private func SectionHeaderView(month: Int, year: Int) -> some View {
|
||||||
|
Text("\(Random.monthName(fromMonthInt: month)) \(String(year))")
|
||||||
|
.font(.title)
|
||||||
|
.foregroundColor(Color(UIColor.label))
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.padding()
|
||||||
|
.background(
|
||||||
|
Color(theme.currentTheme.secondaryBGColor)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func monthListView(month: Int, year: Int, entries: [MoodEntry]) -> some View {
|
||||||
|
VStack {
|
||||||
|
// for reach all entries
|
||||||
|
ForEach(entries.sorted(by: {
|
||||||
|
return $0.forDate! > $1.forDate!
|
||||||
|
}), id: \.self) { entry in
|
||||||
|
entryListView(entry: entry)
|
||||||
|
.contentShape(Rectangle())
|
||||||
|
.onTapGesture(perform: {
|
||||||
|
selectedEntry = entry
|
||||||
|
showUpdateEntryAlert = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func entryListView(entry: MoodEntry) -> some View {
|
||||||
|
HStack {
|
||||||
|
entry.mood.icon
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: 40, height: 40, alignment: .center)
|
||||||
|
.foregroundColor(entry.mood.color)
|
||||||
|
.padding(.leading, 5)
|
||||||
|
|
||||||
|
VStack {
|
||||||
|
HStack {
|
||||||
|
Text(Random.weekdayName(fromDate:entry.forDate!))
|
||||||
|
.font(.title3)
|
||||||
|
.foregroundColor(Color(UIColor.label))
|
||||||
|
Text(" - ")
|
||||||
|
.padding([.leading, .trailing], -10)
|
||||||
|
Text(Random.dayFormat(fromDate:entry.forDate!))
|
||||||
|
.font(.title3)
|
||||||
|
.foregroundColor(Color(UIColor.label))
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.multilineTextAlignment(.leading)
|
||||||
|
|
||||||
|
Text(entry.moodValue == Mood.missing.rawValue ? String(localized: "mood_value_missing_tap_to_add") : "\(entry.moodString)")
|
||||||
|
.font(.body)
|
||||||
|
.foregroundColor(Color(UIColor.systemGray))
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ViewOffsetKey: PreferenceKey {
|
struct ViewOffsetKey: PreferenceKey {
|
||||||
typealias Value = CGFloat
|
typealias Value = CGFloat
|
||||||
static var defaultValue = CGFloat.zero
|
static var defaultValue = CGFloat.zero
|
||||||
|
|||||||
45
Shared/views/EmptyView.swift
Normal file
45
Shared/views/EmptyView.swift
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// EmptyView.swift
|
||||||
|
// Feels (iOS)
|
||||||
|
//
|
||||||
|
// Created by Trey Tartt on 2/10/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct EmptyView: View {
|
||||||
|
@AppStorage(UserDefaultsStore.Keys.theme.rawValue, store: GroupUserDefaults.groupDefaults) private var theme: Theme = .system
|
||||||
|
|
||||||
|
let viewModel: ContentModeViewModel
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ZStack {
|
||||||
|
Color(theme.currentTheme.secondaryBGColor)
|
||||||
|
|
||||||
|
VStack {
|
||||||
|
Text(String(localized: "content_view_empty_title"))
|
||||||
|
.font(.title)
|
||||||
|
.foregroundColor(Color(UIColor.label))
|
||||||
|
.padding()
|
||||||
|
|
||||||
|
Text(String(localized: "content_view_empty_title"))
|
||||||
|
.font(.body)
|
||||||
|
.foregroundColor(Color(UIColor.label))
|
||||||
|
.padding()
|
||||||
|
AddMoodHeaderView(addItemHeaderClosure: { (mood, date) in
|
||||||
|
withAnimation {
|
||||||
|
viewModel.add(mood: mood, forDate: date, entryType: .header)
|
||||||
|
}
|
||||||
|
}, overrideDay: viewModel.shouldShowVotingHeader() ? .Today : .Previous)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
.cornerRadius(10, corners: [.topLeft, .topRight, .bottomLeft, .bottomRight])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct EmptyView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
EmptyView(viewModel: ContentModeViewModel())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user