top view will shrink and fade into another view

This commit is contained in:
Trey t
2022-01-28 15:18:00 -06:00
parent 3ece2c27a1
commit cffce6a773
6 changed files with 186 additions and 54 deletions

View File

@@ -24,6 +24,7 @@
1C683FCB2792281400745862 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C683FC92792281400745862 /* Stats.swift */; }; 1C683FCB2792281400745862 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C683FC92792281400745862 /* Stats.swift */; };
1C683FCC2792281400745862 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C683FC92792281400745862 /* Stats.swift */; }; 1C683FCC2792281400745862 /* Stats.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C683FC92792281400745862 /* Stats.swift */; };
1C6B377A2799B78A001EF820 /* BGView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C6B37792799B78A001EF820 /* BGView.swift */; }; 1C6B377A2799B78A001EF820 /* BGView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C6B37792799B78A001EF820 /* BGView.swift */; };
1C7190A427A483D300388EDC /* SmallHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C7190A327A483D300388EDC /* SmallHeaderView.swift */; };
1C744F2C278CE15600953A57 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C744F2B278CE15600953A57 /* AppDelegate.swift */; }; 1C744F2C278CE15600953A57 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C744F2B278CE15600953A57 /* AppDelegate.swift */; };
1C747CC9279F06EB00762CBD /* CloudKitSyncMonitor in Frameworks */ = {isa = PBXBuildFile; productRef = 1C747CC8279F06EB00762CBD /* CloudKitSyncMonitor */; }; 1C747CC9279F06EB00762CBD /* CloudKitSyncMonitor in Frameworks */ = {isa = PBXBuildFile; productRef = 1C747CC8279F06EB00762CBD /* CloudKitSyncMonitor */; };
1CA037702799FFA600D26164 /* ContentModeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA0376F2799FFA600D26164 /* ContentModeViewModel.swift */; }; 1CA037702799FFA600D26164 /* ContentModeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CA0376F2799FFA600D26164 /* ContentModeViewModel.swift */; };
@@ -128,6 +129,7 @@
1C5F4977279C945E0092F1B4 /* UserDefaultsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsStore.swift; sourceTree = "<group>"; }; 1C5F4977279C945E0092F1B4 /* UserDefaultsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsStore.swift; sourceTree = "<group>"; };
1C683FC92792281400745862 /* Stats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stats.swift; sourceTree = "<group>"; }; 1C683FC92792281400745862 /* Stats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stats.swift; sourceTree = "<group>"; };
1C6B37792799B78A001EF820 /* BGView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGView.swift; sourceTree = "<group>"; }; 1C6B37792799B78A001EF820 /* BGView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGView.swift; sourceTree = "<group>"; };
1C7190A327A483D300388EDC /* SmallHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmallHeaderView.swift; sourceTree = "<group>"; };
1C744F2B278CE15600953A57 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 1C744F2B278CE15600953A57 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
1CA0376F2799FFA600D26164 /* ContentModeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentModeViewModel.swift; sourceTree = "<group>"; }; 1CA0376F2799FFA600D26164 /* ContentModeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentModeViewModel.swift; sourceTree = "<group>"; };
1CA03772279A293D00D26164 /* OnboardingTime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingTime.swift; sourceTree = "<group>"; }; 1CA03772279A293D00D26164 /* OnboardingTime.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingTime.swift; sourceTree = "<group>"; };
@@ -336,6 +338,7 @@
1CD90B36278C7E38001C4FEA /* HeaderStatsView.swift */, 1CD90B36278C7E38001C4FEA /* HeaderStatsView.swift */,
1CD90B32278C7E38001C4FEA /* SettingsView.swift */, 1CD90B32278C7E38001C4FEA /* SettingsView.swift */,
1C6B37792799B78A001EF820 /* BGView.swift */, 1C6B37792799B78A001EF820 /* BGView.swift */,
1C7190A327A483D300388EDC /* SmallHeaderView.swift */,
); );
path = views; path = views;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -593,6 +596,7 @@
1CD90B3D278C7E38001C4FEA /* ContentView.swift in Sources */, 1CD90B3D278C7E38001C4FEA /* ContentView.swift in Sources */,
1CD90B3F278C7E38001C4FEA /* HeaderStatsView.swift in Sources */, 1CD90B3F278C7E38001C4FEA /* HeaderStatsView.swift in Sources */,
1CD90B3B278C7E38001C4FEA /* AddMoodHeaderView.swift in Sources */, 1CD90B3B278C7E38001C4FEA /* AddMoodHeaderView.swift in Sources */,
1C7190A427A483D300388EDC /* SmallHeaderView.swift in Sources */,
1CC469AC27907D48003E0C6E /* DayChartView.swift in Sources */, 1CC469AC27907D48003E0C6E /* DayChartView.swift in Sources */,
1CD90B37278C7E38001C4FEA /* SettingsView.swift in Sources */, 1CD90B37278C7E38001C4FEA /* SettingsView.swift in Sources */,
1C26190327960CE500FDC148 /* ChartDataBuildable.swift in Sources */, 1C26190327960CE500FDC148 /* ChartDataBuildable.swift in Sources */,

View File

@@ -31,7 +31,6 @@ struct FeelsApp: App {
}.onChange(of: scenePhase) { phase in }.onChange(of: scenePhase) { phase in
if phase == .background { if phase == .background {
BGTask.scheduleBackgroundProcessing() BGTask.scheduleBackgroundProcessing()
print("background")
WidgetCenter.shared.reloadAllTimelines() WidgetCenter.shared.reloadAllTimelines()
} }

View File

@@ -34,7 +34,7 @@ struct AddMoodHeaderView: View {
}, label: { }, label: {
mood.icon mood.icon
.resizable() .resizable()
.frame(width: 50, height: 50, alignment: .center) .frame(width: CGFloat(50), height: CGFloat(50), alignment: .center)
.foregroundColor(mood.color) .foregroundColor(mood.color)
}) })
@@ -42,13 +42,12 @@ struct AddMoodHeaderView: View {
}.frame(minWidth: 0, maxWidth: .infinity) }.frame(minWidth: 0, maxWidth: .infinity)
} }
} }
.padding([.leading, .trailing, .bottom])
} }
.padding([.leading, .trailing, .bottom])
} }
.clipShape(RoundedRectangle(cornerRadius: 25, style: .continuous)) .clipShape(RoundedRectangle(cornerRadius: 25, style: .continuous))
.frame(minHeight: 85, maxHeight: 140) .frame(minHeight: 88, maxHeight: 150)
.frame(minWidth: 0, maxWidth: .infinity) .frame(minWidth: 0, maxWidth: .infinity)
.padding()
} }
private func getTitle() -> String { private func getTitle() -> String {

View File

@@ -17,6 +17,11 @@ struct ContentView: View {
@State private var showTodayInput = true @State private var showTodayInput = true
@State private var selectedEntry: MoodEntry? @State private var selectedEntry: MoodEntry?
@State private var showUpdateEntryAlert = false @State private var showUpdateEntryAlert = false
@State private var headerHeight: CGFloat = 150
let minHeaderHeight = 88.0
let maxHeaderHeight = 150.0
@State private var headerOpacity: Double = 1.0
@ObservedObject var viewModel = ContentModeViewModel() @ObservedObject var viewModel = ContentModeViewModel()
@@ -106,50 +111,86 @@ struct ContentView: View {
return formatter.string(from: NSNumber(integerLiteral: day)) ?? "" return formatter.string(from: NSNumber(integerLiteral: day)) ?? ""
} }
private var listView: some View { func calcuateViewAlpha() {
VStack { let perc = (((Double(headerHeight) - minHeaderHeight) * 100) / (maxHeaderHeight - minHeaderHeight)) / 100
List { headerOpacity = perc
// for reach year }
ForEach(viewModel.grouped.sorted(by: {
$0.key > $1.key
}), id: \.key) { year, months in
// for reach month func calculateHeight(minHeight: CGFloat, maxHeight: CGFloat, yOffset: CGFloat) {
ForEach(months.sorted(by: { calcuateViewAlpha()
let newValue = maxHeight + yOffset
// If scrolling up, yOffset will be a negative number
if newValue < minHeight {
// SCROLLING UP
// Never go smaller than our minimum height
headerHeight = minHeight
return
}
if newValue > maxHeight {
// SCROLLING UP
// Never go smaller than our minimum height
headerHeight = maxHeight
return
}
// SCROLLING DOWN
headerHeight = newValue
}
private var listView: some View {
ScrollView {
ZStack {
Color(.systemBackground).edgesIgnoringSafeArea(.bottom)
.cornerRadius(10)
LazyVStack {
// for reach year
ForEach(viewModel.grouped.sorted(by: {
$0.key > $1.key $0.key > $1.key
}), id: \.key) { month, entries in }), id: \.key) { year, months in
Section(header:
HStack{ // for reach month
Text(monthName(fromMonthInt: month)) ForEach(months.sorted(by: {
.font(.title2) $0.key > $1.key
.foregroundColor(Color(UIColor.label)) }), id: \.key) { month, entries in
Text(String(year)) Section(header:
.font(.title2) HStack{
.foregroundColor(Color(UIColor.label)) Text(monthName(fromMonthInt: month))
}) { .font(.title2)
// for reach all entries .foregroundColor(Color(UIColor.label))
ForEach(entries.sorted(by: { Text(String(year))
return $0.forDate! > $1.forDate! .font(.title2)
}), id: \.self) { entry in .foregroundColor(Color(UIColor.label))
entryListView(entry: entry) }) {
.onTapGesture(perform: { // for reach all entries
selectedEntry = entry ForEach(entries.sorted(by: {
showUpdateEntryAlert = true return $0.forDate! > $1.forDate!
}) }), id: \.self) { entry in
}.onDelete(perform: { offsets in entryListView(entry: entry)
withAnimation { .onTapGesture(perform: {
viewModel.delete(offsets: offsets, inMonth: month, inYear: year) selectedEntry = entry
} showUpdateEntryAlert = true
}) })
}.onDelete(perform: { offsets in
withAnimation {
viewModel.delete(offsets: offsets, inMonth: month, inYear: year)
}
})
}
} }
} }
} }
GeometryReader { proxy in
let offset = proxy.frame(in: .named("scroll")).minY
Color.clear.preference(key: ViewOffsetKey.self, value: offset)
}
} }
.background(Color.clear.ignoresSafeArea()) }
.onAppear { .coordinateSpace(name: "scroll")
// Set the default to clear .onPreferenceChange(ViewOffsetKey.self) { value in
UITableView.appearance().backgroundColor = .clear calculateHeight(minHeight: 88, maxHeight: 180, yOffset: value)
}
} }
} }
@@ -191,12 +232,13 @@ struct ContentView: View {
viewModel.add(mood: mood, forDate: date) viewModel.add(mood: mood, forDate: date)
} }
}) })
.frame(height: 180) .frame(height: headerHeight)
.frame(minWidth: 0, maxWidth: .infinity) .frame(minWidth: 0, maxWidth: .infinity)
} else { } else {
HeaderStatsView(fakeData: false, backDays: 30) HeaderStatsView(fakeData: false, backDays: 30)
.frame(height: 180) .frame(height: headerHeight)
// should match backDays above
// should match backDays above
Text(String(format: String(localized: "content_view_header_title"), 30)) Text(String(format: String(localized: "content_view_header_title"), 30))
.font(.body) .font(.body)
.foregroundColor(Color(UIColor.systemGray)) .foregroundColor(Color(UIColor.systemGray))
@@ -233,26 +275,50 @@ struct ContentView: View {
private var mainView: some View { private var mainView: some View {
ZStack { ZStack {
BGView().equatable() BGView().equatable()
VStack{ VStack{
settingsButtonView settingsButtonView
.padding(.top, 50) .padding(.top, 50)
if viewModel.hasNoData { if viewModel.hasNoData {
Spacer() Spacer()
emptyView emptyView
Spacer() Spacer()
} else { } else {
headerView ZStack {
listView VStack {
headerView
Spacer()
}
.opacity(headerOpacity)
VStack {
SmallRollUpHeaderView(fakeData: false, backDays: 30)
.padding([.leading, .trailing])
Spacer()
}
.opacity(1 - headerOpacity)
listView
.padding([.leading, .trailing])
.padding(.top, headerHeight+10)
.padding(.bottom, 60)
}
} }
} }
.padding(.bottom)
} }
} }
} }
struct ViewOffsetKey: PreferenceKey {
typealias Value = CGFloat
static var defaultValue = CGFloat.zero
static func reduce(value: inout Value, nextValue: () -> Value) {
value += nextValue()
}
}
private let itemFormatter: DateFormatter = { private let itemFormatter: DateFormatter = {
let formatter = DateFormatter() let formatter = DateFormatter()
formatter.dateStyle = .short formatter.dateStyle = .short

View File

@@ -206,7 +206,6 @@ struct SettingsView: View {
Toggle(String(localized: "settings_use_cloudkit_title"), Toggle(String(localized: "settings_use_cloudkit_title"),
isOn: $useCloudKit) isOn: $useCloudKit)
.onChange(of: useCloudKit) { value in .onChange(of: useCloudKit) { value in
print(value)
PersistenceController.shared.switchContainer() PersistenceController.shared.switchContainer()
} }
.padding() .padding()

View File

@@ -0,0 +1,65 @@
//
// SmallHeaderView.swift
// Feels (iOS)
//
// Created by Trey Tartt on 1/28/22.
//
import SwiftUI
struct SmallRollUpHeaderView: View {
var entries = [(Mood, Int)]()
let backDays: Int
init(fakeData: Bool, backDays: Int) {
self.backDays = backDays
var moodEntries: [MoodEntry]?
if fakeData {
moodEntries = PersistenceController.shared.randomEntries(count: 10)
} else {
var daysAgo = Calendar.current.date(byAdding: .day, value: -backDays, to: Date())!
daysAgo = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: daysAgo)!
moodEntries = PersistenceController.shared.getData(startDate: daysAgo, endDate: Date(), includedDays: [1,2,3,4,5,6,7])
}
if let moodEntries = moodEntries {
for (_, mood) in Mood.allValues.enumerated() {
entries.append((mood, moodEntries.filter({
Int($0.moodValue) == mood.rawValue
}).count))
}
}
entries = entries.sorted(by: {
$0.0.rawValue > $1.0.rawValue
})
}
var body: some View {
VStack {
HStack {
ForEach(entries, id: \.0) { (mood, value) in
Text(String(value))
.font(.title)
.fontWeight(.bold)
.foregroundColor(mood.color)
.frame(maxWidth: .infinity)
}
}
Text(String(format: String(localized: "content_view_header_title"), self.backDays))
.font(.body)
.foregroundColor(Color(UIColor.systemGray))
.frame(maxWidth: .infinity, alignment: .center)
.padding(.top, 2)
}
.padding([.top])
}
}
struct SmallHeaderView_Previews: PreviewProvider {
static var previews: some View {
SmallRollUpHeaderView(fakeData: true, backDays: 30)
}
}