mirror of
https://github.com/neon443/NearFuture.git
synced 2026-03-11 06:49:12 +00:00
can now export events, cant import lol
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
A920C2BB2D2401A400E4F9B1 /* AddEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C2B72D2401A300E4F9B1 /* AddEventView.swift */; };
|
||||
A920C2BE2D24021A00E4F9B1 /* SFSymbolsPicker in Frameworks */ = {isa = PBXBuildFile; productRef = A920C2BD2D24021A00E4F9B1 /* SFSymbolsPicker */; };
|
||||
A920C2C12D2403CA00E4F9B1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C2C02D2403CA00E4F9B1 /* ContentView.swift */; };
|
||||
A93BC0942D2B18A3002E8BBD /* StatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A93BC0932D2B18A3002E8BBD /* StatsView.swift */; };
|
||||
A979F57F2D26B1300094C0B3 /* EditEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A979F57E2D26B1300094C0B3 /* EditEventView.swift */; };
|
||||
A979F6052D270AF00094C0B3 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A979F6042D270AF00094C0B3 /* WidgetKit.framework */; };
|
||||
A979F6072D270AF00094C0B3 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A979F6062D270AF00094C0B3 /* SwiftUI.framework */; };
|
||||
@@ -60,6 +61,7 @@
|
||||
A920C2B42D2401A100E4F9B1 /* SettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
|
||||
A920C2B72D2401A300E4F9B1 /* AddEventView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddEventView.swift; sourceTree = "<group>"; };
|
||||
A920C2C02D2403CA00E4F9B1 /* ContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
A93BC0932D2B18A3002E8BBD /* StatsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsView.swift; sourceTree = "<group>"; };
|
||||
A979F57E2D26B1300094C0B3 /* EditEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditEventView.swift; sourceTree = "<group>"; };
|
||||
A979F58B2D2700680094C0B3 /* NearFutureWidgetsBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureWidgetsBundle.swift; sourceTree = "<group>"; };
|
||||
A979F58D2D2700680094C0B3 /* NearFutureWidgetsLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureWidgetsLiveActivity.swift; sourceTree = "<group>"; };
|
||||
@@ -124,6 +126,7 @@
|
||||
A979F57E2D26B1300094C0B3 /* EditEventView.swift */,
|
||||
A920C2B72D2401A300E4F9B1 /* AddEventView.swift */,
|
||||
A920C2C02D2403CA00E4F9B1 /* ContentView.swift */,
|
||||
A93BC0932D2B18A3002E8BBD /* StatsView.swift */,
|
||||
A920C2B42D2401A100E4F9B1 /* SettingsView.swift */,
|
||||
A920C2872D24011400E4F9B1 /* NearFutureApp.swift */,
|
||||
A920C28B2D24011400E4F9B1 /* Item.swift */,
|
||||
@@ -290,6 +293,7 @@
|
||||
A920C2B82D2401A300E4F9B1 /* SettingsView.swift in Sources */,
|
||||
A920C28C2D24011400E4F9B1 /* Item.swift in Sources */,
|
||||
A920C2882D24011400E4F9B1 /* NearFutureApp.swift in Sources */,
|
||||
A93BC0942D2B18A3002E8BBD /* StatsView.swift in Sources */,
|
||||
A979F57F2D26B1300094C0B3 /* EditEventView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -438,7 +442,7 @@
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = NearFuture/NearFuture.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 11;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"NearFuture/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = P6PV2R9443;
|
||||
ENABLE_HARDENED_RUNTIME = NO;
|
||||
@@ -463,7 +467,9 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.neon443.NearFuture;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = auto;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@@ -478,7 +484,7 @@
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = NearFuture/NearFuture.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 11;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"NearFuture/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = P6PV2R9443;
|
||||
ENABLE_HARDENED_RUNTIME = NO;
|
||||
@@ -503,7 +509,9 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.neon443.NearFuture;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = auto;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@@ -517,7 +525,7 @@
|
||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||
CODE_SIGN_ENTITLEMENTS = NearFutureWidgets/NearFutureWidgetsExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 11;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = P6PV2R9443;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = NearFutureWidgets/Info.plist;
|
||||
@@ -547,7 +555,7 @@
|
||||
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
|
||||
CODE_SIGN_ENTITLEMENTS = NearFutureWidgets/NearFutureWidgetsExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 11;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = P6PV2R9443;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = NearFutureWidgets/Info.plist;
|
||||
|
||||
BIN
NearFuture.xcodeproj/project.xcworkspace/xcuserdata/neon443.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
BIN
NearFuture.xcodeproj/project.xcworkspace/xcuserdata/neon443.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
Binary file not shown.
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1540"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "A920C2832D24011300E4F9B1"
|
||||
BuildableName = "NearFuture.app"
|
||||
BlueprintName = "NearFuture"
|
||||
ReferencedContainer = "container:NearFuture.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "A920C2832D24011300E4F9B1"
|
||||
BuildableName = "NearFuture.app"
|
||||
BlueprintName = "NearFuture"
|
||||
ReferencedContainer = "container:NearFuture.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "A920C2832D24011300E4F9B1"
|
||||
BuildableName = "NearFuture.app"
|
||||
BlueprintName = "NearFuture"
|
||||
ReferencedContainer = "container:NearFuture.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1540"
|
||||
wasCreatedForAppExtension = "YES"
|
||||
version = "2.0">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES"
|
||||
buildArchitectures = "Automatic">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "A979F6012D270AF00094C0B3"
|
||||
BuildableName = "NearFutureWidgetsExtension.appex"
|
||||
BlueprintName = "NearFutureWidgetsExtension"
|
||||
ReferencedContainer = "container:NearFuture.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "A920C2832D24011300E4F9B1"
|
||||
BuildableName = "NearFuture.app"
|
||||
BlueprintName = "NearFuture"
|
||||
ReferencedContainer = "container:NearFuture.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = ""
|
||||
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
|
||||
launchStyle = "0"
|
||||
askForAppToLaunch = "Yes"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "A920C2832D24011300E4F9B1"
|
||||
BuildableName = "NearFuture.app"
|
||||
BlueprintName = "NearFuture"
|
||||
ReferencedContainer = "container:NearFuture.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariable
|
||||
key = "_XCWidgetKind"
|
||||
value = ""
|
||||
isEnabled = "YES">
|
||||
</EnvironmentVariable>
|
||||
<EnvironmentVariable
|
||||
key = "_XCWidgetDefaultView"
|
||||
value = "timeline"
|
||||
isEnabled = "YES">
|
||||
</EnvironmentVariable>
|
||||
<EnvironmentVariable
|
||||
key = "_XCWidgetFamily"
|
||||
value = "systemMedium"
|
||||
isEnabled = "YES">
|
||||
</EnvironmentVariable>
|
||||
</EnvironmentVariables>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
askForAppToLaunch = "Yes"
|
||||
launchAutomaticallySubstyle = "2">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "A920C2832D24011300E4F9B1"
|
||||
BuildableName = "NearFuture.app"
|
||||
BlueprintName = "NearFuture"
|
||||
ReferencedContainer = "container:NearFuture.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Bucket
|
||||
uuid = "81691EC5-53AC-4338-9E2E-C1A8F23D20E5"
|
||||
type = "1"
|
||||
version = "2.0">
|
||||
<Breakpoints>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "4B7F7ADF-35FB-4F84-A9FE-98FB688F18BC"
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "NearFuture/Item.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "245"
|
||||
endingLineNumber = "245"
|
||||
landmarkName = "importEvents(_:)"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
</Breakpoints>
|
||||
</Bucket>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>NearFuture.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<key>NearFutureWidgetsExtension.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>A920C2832D24011300E4F9B1</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>A979F6012D270AF00094C0B3</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
BIN
NearFuture/.DS_Store
vendored
Normal file
BIN
NearFuture/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -45,11 +45,11 @@ struct AddEventView: View {
|
||||
Image(systemName: eventSymbol)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 25, height: 25)
|
||||
.frame(width: 20, height: 20)
|
||||
.foregroundStyle(eventColor)
|
||||
}
|
||||
// .frame(width: 30)
|
||||
.buttonStyle(.bordered)
|
||||
.frame(width: 20)
|
||||
.buttonStyle(.borderless)
|
||||
.sheet(isPresented: $isSymbolPickerPresented) {
|
||||
SymbolsPicker(
|
||||
selection: $eventSymbol,
|
||||
@@ -88,8 +88,12 @@ struct AddEventView: View {
|
||||
|
||||
|
||||
// date picker
|
||||
DatePicker("Event Date", selection: $eventDate, displayedComponents: .date)
|
||||
.datePickerStyle(WheelDatePickerStyle())
|
||||
HStack {
|
||||
Spacer()
|
||||
DatePicker("", selection: $eventDate, displayedComponents: .date)
|
||||
.datePickerStyle(WheelDatePickerStyle())
|
||||
Spacer()
|
||||
}
|
||||
|
||||
// re-ocurrence Picker
|
||||
Picker("Recurrence", selection: $eventRecurrence) {
|
||||
@@ -122,7 +126,6 @@ struct AddEventView: View {
|
||||
Text("Save Event")
|
||||
.font(.headline)
|
||||
.cornerRadius(10)
|
||||
.shadow(radius: 10)
|
||||
.buttonStyle(BorderedProminentButtonStyle())
|
||||
}
|
||||
.disabled(eventName.isEmpty)
|
||||
|
||||
@@ -8,64 +8,6 @@
|
||||
import SwiftUI
|
||||
import SwiftData
|
||||
|
||||
//struct ContentView: View {
|
||||
// @Environment(\.modelContext) private var modelContext
|
||||
// @Query private var items: [Item]
|
||||
//
|
||||
// var body: some View {
|
||||
// NavigationSplitView {
|
||||
// List {
|
||||
// ForEach(items) { item in
|
||||
// NavigationLink {
|
||||
// Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))")
|
||||
// } label: {
|
||||
// Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
|
||||
// }
|
||||
// }
|
||||
// .onDelete(perform: deleteItems)
|
||||
// }
|
||||
//#if os(macOS)
|
||||
// .navigationSplitViewColumnWidth(min: 180, ideal: 200)
|
||||
//#endif
|
||||
// .toolbar {
|
||||
//#if os(iOS)
|
||||
// ToolbarItem(placement: .navigationBarTrailing) {
|
||||
// EditButton()
|
||||
// }
|
||||
//#endif
|
||||
// ToolbarItem {
|
||||
// Button(action: addItem) {
|
||||
// Label("Add Item", systemImage: "plus")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } detail: {
|
||||
// Text("Select an item")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private func addItem() {
|
||||
// withAnimation {
|
||||
// let newItem = Item(timestamp: Date())
|
||||
// modelContext.insert(newItem)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private func deleteItems(offsets: IndexSet) {
|
||||
// withAnimation {
|
||||
// for index in offsets {
|
||||
// modelContext.delete(items[index])
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//#Preview {
|
||||
// ContentView()
|
||||
// .modelContainer(for: Item.self, inMemory: true)
|
||||
//}
|
||||
|
||||
|
||||
struct ContentView: View {
|
||||
@StateObject private var viewModel = EventViewModel()
|
||||
@State private var eventName = ""
|
||||
@@ -124,94 +66,104 @@ struct ContentView: View {
|
||||
private enum Field {
|
||||
case Search
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
ZStack {
|
||||
backgroundGradient
|
||||
.ignoresSafeArea(.all)
|
||||
VStack {
|
||||
ZStack {
|
||||
TextField(
|
||||
"\(Image(systemName: "magnifyingglass")) Search",
|
||||
text: $searchInput
|
||||
)
|
||||
.padding(.trailing, searchInput.isEmpty ? 0 : 30)
|
||||
.animation(.spring, value: searchInput)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.focused($focusedField, equals: Field.Search)
|
||||
.onSubmit {
|
||||
focusedField = nil
|
||||
TabView {
|
||||
NavigationView {
|
||||
ZStack {
|
||||
backgroundGradient
|
||||
.ignoresSafeArea(.all)
|
||||
VStack {
|
||||
ZStack {
|
||||
TextField(
|
||||
"\(Image(systemName: "magnifyingglass")) Search",
|
||||
text: $searchInput
|
||||
)
|
||||
.padding(.trailing, searchInput.isEmpty ? 0 : 30)
|
||||
.animation(.spring, value: searchInput)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
.focused($focusedField, equals: Field.Search)
|
||||
.onSubmit {
|
||||
focusedField = nil
|
||||
}
|
||||
MagicClearButton(text: $searchInput)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
List {
|
||||
ForEach(filteredEvents) { event in
|
||||
EventListView(viewModel: viewModel, event: event)
|
||||
}
|
||||
.onDelete(perform: viewModel.removeEvent)
|
||||
if !searchInput.isEmpty {
|
||||
HStack {
|
||||
Image(systemName: "questionmark.square.dashed")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 30, height: 30)
|
||||
.padding(.trailing)
|
||||
Text("Can't find what you're looking for?")
|
||||
}
|
||||
Text("Tip: The Search bar searches event names and descriptions")
|
||||
Button() {
|
||||
searchInput = ""
|
||||
focusedField = nil
|
||||
} label: {
|
||||
HStack {
|
||||
Image(systemName: "xmark")
|
||||
Text("Clear Filters")
|
||||
}
|
||||
.foregroundStyle(Color.accentColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
MagicClearButton(text: $searchInput)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
List {
|
||||
ForEach(filteredEvents) { event in
|
||||
EventListView(viewModel: viewModel, event: event)
|
||||
}
|
||||
.onDelete(perform: viewModel.removeEvent)
|
||||
if !searchInput.isEmpty {
|
||||
HStack {
|
||||
Image(systemName: "questionmark.square.dashed")
|
||||
.navigationTitle("Near Future")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.sheet(isPresented: $showingAddEventView) {
|
||||
AddEventView(
|
||||
viewModel: viewModel,
|
||||
eventName: $eventName,
|
||||
eventSymbol: $eventSymbol,
|
||||
eventColor: $eventColor,
|
||||
eventDescription: $eventDescription,
|
||||
eventDate: $eventDate,
|
||||
eventRecurrence: $eventRecurrence,
|
||||
adding: true //adding event
|
||||
)
|
||||
}
|
||||
.sheet(
|
||||
isPresented: $showSettings) {
|
||||
SettingsView(
|
||||
viewModel: viewModel
|
||||
)
|
||||
}
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
Button() {
|
||||
showingAddEventView.toggle()
|
||||
} label: {
|
||||
Image(systemName: "plus.circle")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 30, height: 30)
|
||||
.padding(.trailing)
|
||||
Text("Can't find what you're looking for?")
|
||||
}
|
||||
Text("Tip: The Search bar searches event names and descriptions")
|
||||
}
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
Button() {
|
||||
searchInput = ""
|
||||
focusedField = nil
|
||||
showSettings.toggle()
|
||||
} label: {
|
||||
HStack {
|
||||
Image(systemName: "xmark")
|
||||
Text("Clear Filters")
|
||||
}
|
||||
.foregroundStyle(Color.accentColor)
|
||||
Image(systemName: "gear")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Near Future")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.sheet(isPresented: $showingAddEventView) {
|
||||
AddEventView(
|
||||
viewModel: viewModel,
|
||||
eventName: $eventName,
|
||||
eventSymbol: $eventSymbol,
|
||||
eventColor: $eventColor,
|
||||
eventDescription: $eventDescription,
|
||||
eventDate: $eventDate,
|
||||
eventRecurrence: $eventRecurrence,
|
||||
adding: true //adding event
|
||||
)
|
||||
}
|
||||
.sheet(
|
||||
isPresented: $showSettings) {
|
||||
SettingsView(
|
||||
viewModel: viewModel
|
||||
)
|
||||
}
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
Button() {
|
||||
showingAddEventView.toggle()
|
||||
} label: {
|
||||
Image(systemName: "plus.circle")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
}
|
||||
}
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
Button() {
|
||||
showSettings.toggle()
|
||||
} label: {
|
||||
Image(systemName: "gear")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.tabItem {
|
||||
Label("Home", systemImage: "house")
|
||||
}
|
||||
StatsView(viewModel: viewModel)
|
||||
.tabItem {
|
||||
Label("Statistics", systemImage: "chart.pie")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ struct ColorCodable: Codable {
|
||||
var green: Double
|
||||
var blue: Double
|
||||
var alpha: Double
|
||||
//for the brainrotted: alpha is the opacity/transparency of the color,
|
||||
//for the brainrot kids: alpha is the opacity/transparency of the color,
|
||||
//alpha == 0 completely transparent
|
||||
//alpha == 1 completely opaque
|
||||
|
||||
@@ -217,6 +217,60 @@ class EventViewModel: ObservableObject {
|
||||
saveEvents()
|
||||
}
|
||||
|
||||
func exportEvents() -> String? {
|
||||
let encoder = JSONEncoder()
|
||||
|
||||
// Custom date encoding strategy to handle date formatting
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
|
||||
encoder.dateEncodingStrategy = .formatted(dateFormatter)
|
||||
|
||||
do {
|
||||
// Encode the events array to JSON data
|
||||
let encodedData = try encoder.encode(events)
|
||||
|
||||
// Convert the JSON data to a string
|
||||
if let jsonString = String(data: encodedData, encoding: .utf8) {
|
||||
return jsonString
|
||||
} else {
|
||||
print("Failed to convert encoded data to string")
|
||||
return nil
|
||||
}
|
||||
} catch {
|
||||
print("Failed to encode events: \(error.localizedDescription)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func importEvents(_ imp: String) {
|
||||
guard let impData = imp.data(using: .utf8) else {
|
||||
print("Failed to convert string to data")
|
||||
return
|
||||
}
|
||||
|
||||
// Create a JSONDecoder
|
||||
let decoder = JSONDecoder()
|
||||
|
||||
// Add a custom date formatter for decoding the date string
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" // Adjust this to the date format you're using
|
||||
decoder.dateDecodingStrategy = .formatted(dateFormatter)
|
||||
|
||||
do {
|
||||
// Attempt to decode the events from the provided data
|
||||
let decoded = try decoder.decode([Event].self, from: impData)
|
||||
print("Successfully decoded events: \(decoded)")
|
||||
|
||||
// Save and reload after importing events
|
||||
self.events = decoded
|
||||
saveEvents()
|
||||
loadEvents()
|
||||
} catch {
|
||||
// Print error if decoding fails
|
||||
print("Failed to decode events: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: Danger Zone
|
||||
func dangerClearLocalData() {
|
||||
UserDefaults.standard.removeObject(forKey: "events")
|
||||
|
||||
@@ -16,6 +16,7 @@ struct SettingsView: View {
|
||||
@State private var lastSyncWasNormalAgo: Bool = false
|
||||
@State private var localCountEqualToiCloud: Bool = false
|
||||
@State private var icloudCountEqualToLocal: Bool = false
|
||||
@State private var importStr: String = ""
|
||||
|
||||
func updateStatus() {
|
||||
let vm = viewModel
|
||||
@@ -67,6 +68,48 @@ struct SettingsView: View {
|
||||
updateStatus()
|
||||
}
|
||||
|
||||
NavigationLink() {
|
||||
NavigationView() {
|
||||
Button() {
|
||||
UIPasteboard.general.string = "\(viewModel.exportEvents())"
|
||||
print(viewModel.exportEvents())
|
||||
} label: {
|
||||
Text("copy")
|
||||
}
|
||||
Text("\(viewModel.exportEvents())")
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "list.bullet.rectangle")
|
||||
Text("Export events")
|
||||
}
|
||||
NavigationLink() {
|
||||
NavigationView() {
|
||||
VStack {
|
||||
TextEditor(text: $importStr)
|
||||
.foregroundStyle(.foreground, .gray)
|
||||
.background(.gray)
|
||||
.frame(width: 200, height: 400)
|
||||
.shadow(radius: 5)
|
||||
Button() {
|
||||
viewModel.importEvents(importStr)
|
||||
} label: {
|
||||
Text("import events")
|
||||
}
|
||||
.buttonStyle(BorderedProminentButtonStyle())
|
||||
Button() {
|
||||
if let pb = UIPasteboard.general.string {
|
||||
print(pb)
|
||||
}
|
||||
} label: {
|
||||
Text("print pb")
|
||||
}
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "square.and.arrow.down")
|
||||
Text("Import events")
|
||||
}
|
||||
|
||||
Section("Danger Zone") {
|
||||
Button("Delete local data", role: .destructive) {
|
||||
viewModel.dangerClearLocalData()
|
||||
|
||||
67
NearFuture/StatsView.swift
Normal file
67
NearFuture/StatsView.swift
Normal file
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// StatsView.swift
|
||||
// NearFuture
|
||||
//
|
||||
// Created by Nihaal Sharma on 05/01/2025.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Charts
|
||||
|
||||
struct StatsView: View {
|
||||
@ObservedObject var viewModel: EventViewModel
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
List {
|
||||
Section(header: Text("Upcoming Events")) {
|
||||
let upcomingEvents = viewModel.events.filter { $0.date > Date() }
|
||||
Text("\(upcomingEvents.count) upcoming event\(upcomingEvents.count == 1 ? "" : "s")")
|
||||
.font(.headline)
|
||||
.foregroundStyle(Color.accentColor)
|
||||
let pastEvents = viewModel.events.filter { $0.date < Date() }
|
||||
Text("\(pastEvents.count) past event\(pastEvents.count == 1 ? "" : "s")")
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
|
||||
Section("Events by Month") {
|
||||
let eventsByMonth = Dictionary(grouping: viewModel.events, by: { $0.date })
|
||||
ForEach(eventsByMonth.keys.sorted(), id: \.self) { month in
|
||||
let count = eventsByMonth[month]?.count ?? 0
|
||||
Text("\(count) - \(month.formatted(date: .long, time: .omitted))")
|
||||
}
|
||||
}
|
||||
|
||||
Section("Event Count") {
|
||||
let eventCount = viewModel.events.count
|
||||
Text("\(eventCount) event\(eventCount == 1 ? "" : "s")")
|
||||
.font(.headline)
|
||||
.foregroundStyle(Color.accentColor)
|
||||
|
||||
ForEach(Event.RecurrenceType.allCases, id: \.self) { recurrence in
|
||||
let count = viewModel.events.filter { $0.recurrence == recurrence }.count
|
||||
let recurrenceStr = recurrence.rawValue.capitalized
|
||||
var description: String {
|
||||
if recurrenceStr == "None" {
|
||||
return "One-Time event\(count == 1 ? "" : "s")"
|
||||
} else {
|
||||
return "\(recurrenceStr) event\(count == 1 ? "" : "s")"
|
||||
}
|
||||
}
|
||||
Text("\(count) \(description)")
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Color.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Statistics")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
StatsView(
|
||||
viewModel: EventViewModel()
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user