code clean up
This commit is contained in:
@@ -28,6 +28,27 @@ class Random {
|
||||
}
|
||||
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 {
|
||||
|
||||
@@ -16,23 +16,34 @@ struct ContentViewConstants {
|
||||
|
||||
struct ContentView: View {
|
||||
@Environment(\.managedObjectContext) private var viewContext
|
||||
|
||||
@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.mainViewTopHeaderIndex.rawValue, store: GroupUserDefaults.groupDefaults) private var mainViewTopHeaderIndex = 0
|
||||
|
||||
@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.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.contentViewHeaderTag.rawValue, store: GroupUserDefaults.groupDefaults) private var switchableViewSelectedIndex = 1
|
||||
|
||||
//
|
||||
|
||||
// edit row
|
||||
@State private var showingSheet = false
|
||||
@State private var showTodayInput = true
|
||||
@State private var selectedEntry: MoodEntry?
|
||||
//
|
||||
|
||||
@State private var showTodayInput = true
|
||||
@State private var showUpdateEntryAlert = false
|
||||
|
||||
// header properties
|
||||
@State private var headerHeight: CGFloat = ContentViewConstants.maxHeaderHeight
|
||||
@State private var headerViewType: MainSwitchableViewType = .total
|
||||
@State private var currentSelectedHeaderViewViewType: MainSwitchableViewType = .total
|
||||
@State private var headerOpacity: Double = 1.0
|
||||
//
|
||||
|
||||
let minHeaderHeight = ContentViewConstants.minHeaderHeight
|
||||
let maxHeaderHeight = ContentViewConstants.maxHeaderHeight
|
||||
@@ -97,67 +108,7 @@ struct ContentView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private func updateTitleHeader(forEntry entry: MoodEntry?) -> String {
|
||||
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)) ?? ""
|
||||
}
|
||||
|
||||
// MARK: functions that do view type work
|
||||
func calcuateViewAlpha() {
|
||||
let perc = (((Double(headerHeight) - minHeaderHeight) * 100) / (maxHeaderHeight - minHeaderHeight)) / 100
|
||||
headerOpacity = perc
|
||||
@@ -186,98 +137,44 @@ struct ContentView: View {
|
||||
headerHeight = newValue
|
||||
}
|
||||
|
||||
private var listView: some View {
|
||||
ScrollView {
|
||||
LazyVStack(spacing: 5, pinnedViews: [.sectionHeaders]) {
|
||||
ForEach(viewModel.grouped.sorted(by: {
|
||||
$0.key > $1.key
|
||||
}), id: \.key) { year, months in
|
||||
|
||||
// for reach month
|
||||
ForEach(months.sorted(by: {
|
||||
$0.key > $1.key
|
||||
}), id: \.key) { month, entries in
|
||||
Section(header: SectionHeaderView(month: month, year: year)) {
|
||||
monthListView(month: month, year: year, entries: entries)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.background(
|
||||
GeometryReader { proxy in
|
||||
let offset = proxy.frame(in: .named("scroll")).minY
|
||||
Color.clear.preference(key: ViewOffsetKey.self, value: offset)
|
||||
}
|
||||
)
|
||||
private func updateTitleHeader(forEntry entry: MoodEntry?) -> String {
|
||||
guard let entry = entry else {
|
||||
return ""
|
||||
}
|
||||
.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])
|
||||
|
||||
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 = Random.monthName(fromMonthInt: month)
|
||||
let weekday = Random.weekdayName(fromDate:entry.forDate!)
|
||||
let dayz = Random.dayFormat(fromDate:entry.forDate!)
|
||||
|
||||
let string = weekday + " " + monthName + " " + dayz + " " + String(year)
|
||||
|
||||
return String(format: String(localized: "content_view_fill_in_missing_entry"), string)
|
||||
}
|
||||
|
||||
private func SectionHeaderView(month: Int, year: Int) -> some View {
|
||||
Text("\(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 {
|
||||
// MARK: Views
|
||||
private var settingsButtonView: 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(weekdayName(fromDate:entry.forDate!))
|
||||
.font(.title3)
|
||||
.foregroundColor(Color(UIColor.label))
|
||||
Text(" - ")
|
||||
.padding([.leading, .trailing], -10)
|
||||
Text(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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,30 +230,41 @@ struct ContentView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var emptyView: 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)
|
||||
private var listView: some View {
|
||||
ScrollView {
|
||||
LazyVStack(spacing: 5, pinnedViews: [.sectionHeaders]) {
|
||||
ForEach(viewModel.grouped.sorted(by: {
|
||||
$0.key > $1.key
|
||||
}), id: \.key) { year, months in
|
||||
|
||||
// for reach month
|
||||
ForEach(months.sorted(by: {
|
||||
$0.key > $1.key
|
||||
}), id: \.key) { month, entries in
|
||||
Section(header: SectionHeaderView(month: month, year: year)) {
|
||||
monthListView(month: month, year: year, entries: entries)
|
||||
}
|
||||
}
|
||||
}, 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, .bottomLeft, .bottomRight])
|
||||
.padding()
|
||||
.cornerRadius(10, corners: [.topLeft, .topRight])
|
||||
}
|
||||
|
||||
private var mainView: some View {
|
||||
@@ -364,7 +272,7 @@ struct ContentView: View {
|
||||
settingsButtonView
|
||||
if viewModel.hasNoData {
|
||||
Spacer()
|
||||
emptyView
|
||||
EmptyView(viewModel: viewModel)
|
||||
Spacer()
|
||||
} else {
|
||||
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 {
|
||||
typealias Value = CGFloat
|
||||
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