mirror of
https://github.com/neon443/NearFuture.git
synced 2026-03-11 06:49:12 +00:00
Compare commits
2 Commits
5ce48a4bc2
...
ee2e05c523
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee2e05c523 | ||
|
|
e9e19e2659 |
199
MacNearFuture/Views/Events/AddEventView.swift
Normal file
199
MacNearFuture/Views/Events/AddEventView.swift
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
//
|
||||||
|
// AddEventView.swift
|
||||||
|
// MacNearFuture
|
||||||
|
//
|
||||||
|
// Created by neon443 on 11/06/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import SFSymbolsPicker
|
||||||
|
|
||||||
|
struct AddEventView: View {
|
||||||
|
@ObservedObject var viewModel: EventViewModel
|
||||||
|
|
||||||
|
@Binding var event: Event
|
||||||
|
|
||||||
|
@State var adding: Bool
|
||||||
|
@State var showNeedsNameAlert: Bool = false
|
||||||
|
@State var isSymbolPickerPresented: Bool = false
|
||||||
|
|
||||||
|
@State private var bye: Bool = false
|
||||||
|
|
||||||
|
@FocusState private var focusedField: Field?
|
||||||
|
private enum Field {
|
||||||
|
case Name, Notes
|
||||||
|
}
|
||||||
|
|
||||||
|
@Environment(\.dismiss) var dismiss
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ZStack {
|
||||||
|
if !adding {
|
||||||
|
backgroundGradient
|
||||||
|
}
|
||||||
|
List {
|
||||||
|
Section(
|
||||||
|
header:
|
||||||
|
Text("Event Details")
|
||||||
|
.font(.headline)
|
||||||
|
.foregroundColor(.accentColor)
|
||||||
|
) {
|
||||||
|
// name & symbol
|
||||||
|
HStack(spacing: 5) {
|
||||||
|
Button() {
|
||||||
|
isSymbolPickerPresented.toggle()
|
||||||
|
} label: {
|
||||||
|
Image(systemName: event.symbol)
|
||||||
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
.foregroundStyle(event.color.color)
|
||||||
|
}
|
||||||
|
.frame(width: 20)
|
||||||
|
.buttonStyle(.borderless)
|
||||||
|
.sheet(isPresented: $isSymbolPickerPresented) {
|
||||||
|
SymbolsPicker(
|
||||||
|
selection: $event.symbol,
|
||||||
|
title: "Choose a Symbol",
|
||||||
|
searchLabel: "Search...",
|
||||||
|
autoDismiss: true)
|
||||||
|
.presentationDetents([.medium])
|
||||||
|
}
|
||||||
|
|
||||||
|
// dscription
|
||||||
|
ZStack {
|
||||||
|
TextField("Event Notes", text: $event.notes)
|
||||||
|
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||||
|
.padding(.trailing, event.notes.isEmpty ? 0 : 30)
|
||||||
|
.animation(.spring, value: event.notes)
|
||||||
|
.focused($focusedField, equals: Field.Notes)
|
||||||
|
.submitLabel(.done)
|
||||||
|
.onSubmit {
|
||||||
|
focusedField = nil
|
||||||
|
}
|
||||||
|
// MagicClearButton(text: $eventNotes)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// date picker
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
DatePicker("", selection: $event.date, displayedComponents: .date)
|
||||||
|
Spacer()
|
||||||
|
Button() {
|
||||||
|
event.date = Date()
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "arrow.uturn.left")
|
||||||
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
|
}
|
||||||
|
.buttonStyle(BorderlessButtonStyle())
|
||||||
|
.frame(width: 20)
|
||||||
|
}
|
||||||
|
|
||||||
|
DatePicker(
|
||||||
|
"",
|
||||||
|
selection: $event.date,
|
||||||
|
displayedComponents: .hourAndMinute
|
||||||
|
)
|
||||||
|
|
||||||
|
// re-ocurrence Picker
|
||||||
|
Picker("Recurrence", selection: $event.recurrence) {
|
||||||
|
ForEach(Event.RecurrenceType.allCases, id: \.self) { recurrence in
|
||||||
|
Text(recurrence.rawValue.capitalized)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.pickerStyle(SegmentedPickerStyle())
|
||||||
|
Text(
|
||||||
|
describeOccurrence(
|
||||||
|
date: event.date,
|
||||||
|
recurrence: event.recurrence
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.scrollContentBackground(.hidden)
|
||||||
|
.navigationTitle("\(adding ? "Add Event" : "")")
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItem() {
|
||||||
|
if adding {
|
||||||
|
Button() {
|
||||||
|
resetAddEventView()
|
||||||
|
dismiss()
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "xmark")
|
||||||
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
|
.frame(width: 30)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ToolbarItem/*(placement: .topBarTrailing)*/ {
|
||||||
|
if adding {
|
||||||
|
Button {
|
||||||
|
viewModel.addEvent(
|
||||||
|
newEvent: event
|
||||||
|
)
|
||||||
|
bye.toggle()
|
||||||
|
resetAddEventView()
|
||||||
|
} label: {
|
||||||
|
Text("Save")
|
||||||
|
.font(.headline)
|
||||||
|
.cornerRadius(10)
|
||||||
|
.buttonStyle(BorderedProminentButtonStyle())
|
||||||
|
}
|
||||||
|
.tint(.accent)
|
||||||
|
.apply {
|
||||||
|
if #available(iOS 17, *) {
|
||||||
|
$0.sensoryFeedback(.success, trigger: bye)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.disabled(event.name.isEmpty)
|
||||||
|
.onTapGesture {
|
||||||
|
if event.name.isEmpty {
|
||||||
|
showNeedsNameAlert.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.alert("Missing Name", isPresented: $showNeedsNameAlert) {
|
||||||
|
Button("OK", role: .cancel) {
|
||||||
|
showNeedsNameAlert.toggle()
|
||||||
|
focusedField = .Name
|
||||||
|
}
|
||||||
|
} message: {
|
||||||
|
Text("Give your Event a name before saving.")
|
||||||
|
}
|
||||||
|
if event.name.isEmpty {
|
||||||
|
HStack {
|
||||||
|
Image(systemName: "exclamationmark")
|
||||||
|
.foregroundStyle(.red)
|
||||||
|
Text("Give your event a name.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.scrollContentBackground(.hidden)
|
||||||
|
.presentationDragIndicator(.visible)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func resetAddEventView() {
|
||||||
|
//reset addeventView
|
||||||
|
event = viewModel.template
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
let vm = dummyEventViewModel()
|
||||||
|
Color.orange
|
||||||
|
.ignoresSafeArea(.all)
|
||||||
|
.sheet(isPresented: .constant(true)) {
|
||||||
|
AddEventView(
|
||||||
|
viewModel: vm,
|
||||||
|
event: .constant(vm.template),
|
||||||
|
adding: true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,14 +15,7 @@ struct EditEventView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
AddEventView(
|
AddEventView(
|
||||||
viewModel: viewModel,
|
viewModel: viewModel,
|
||||||
eventName: $event.name,
|
event: $event,
|
||||||
eventComplete: $event.complete,
|
|
||||||
eventCompleteDesc: $event.completeDesc,
|
|
||||||
eventSymbol: $event.symbol,
|
|
||||||
eventColor: $event.color.colorBind,
|
|
||||||
eventNotes: $event.notes,
|
|
||||||
eventDate: $event.date,
|
|
||||||
eventRecurrence: $event.recurrence,
|
|
||||||
adding: false //bc we editing existing event
|
adding: false //bc we editing existing event
|
||||||
)
|
)
|
||||||
.navigationTitle("Edit Event")
|
.navigationTitle("Edit Event")
|
||||||
@@ -14,7 +14,6 @@
|
|||||||
A90D49442DDE1C7600781124 /* Tints.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A90D49432DDE1C1100781124 /* Tints.xcassets */; };
|
A90D49442DDE1C7600781124 /* Tints.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A90D49432DDE1C1100781124 /* Tints.xcassets */; };
|
||||||
A90D49452DDE1C7600781124 /* Tints.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A90D49432DDE1C1100781124 /* Tints.xcassets */; };
|
A90D49452DDE1C7600781124 /* Tints.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A90D49432DDE1C1100781124 /* Tints.xcassets */; };
|
||||||
A90D49462DDE1C7A00781124 /* Tints.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A90D49432DDE1C1100781124 /* Tints.xcassets */; };
|
A90D49462DDE1C7A00781124 /* Tints.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A90D49432DDE1C1100781124 /* Tints.xcassets */; };
|
||||||
A90D494B2DDE2C2900781124 /* AddEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949F83C2DCAABE00064DCA0 /* AddEventView.swift */; };
|
|
||||||
A90D49522DDE2D0000781124 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90D49512DDE2D0000781124 /* Extensions.swift */; };
|
A90D49522DDE2D0000781124 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90D49512DDE2D0000781124 /* Extensions.swift */; };
|
||||||
A90D49532DDE2D0000781124 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90D49512DDE2D0000781124 /* Extensions.swift */; };
|
A90D49532DDE2D0000781124 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90D49512DDE2D0000781124 /* Extensions.swift */; };
|
||||||
A90D49562DDE2D5800781124 /* SFSymbolsPicker in Frameworks */ = {isa = PBXBuildFile; productRef = A90D49552DDE2D5800781124 /* SFSymbolsPicker */; };
|
A90D49562DDE2D5800781124 /* SFSymbolsPicker in Frameworks */ = {isa = PBXBuildFile; productRef = A90D49552DDE2D5800781124 /* SFSymbolsPicker */; };
|
||||||
@@ -51,10 +50,11 @@
|
|||||||
A979F6142D270AF90094C0B3 /* NearFutureWidgetsExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = A979F6022D270AF00094C0B3 /* NearFutureWidgetsExtension.appex */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
A979F6142D270AF90094C0B3 /* NearFutureWidgetsExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = A979F6022D270AF00094C0B3 /* NearFutureWidgetsExtension.appex */; platformFilter = ios; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
A979F6182D2714310094C0B3 /* Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C28B2D24011400E4F9B1 /* Events.swift */; };
|
A979F6182D2714310094C0B3 /* Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C28B2D24011400E4F9B1 /* Events.swift */; };
|
||||||
A98C20CB2DE730740008D61C /* EventListViewMac.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20CA2DE730740008D61C /* EventListViewMac.swift */; };
|
A98C20CB2DE730740008D61C /* EventListViewMac.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20CA2DE730740008D61C /* EventListViewMac.swift */; };
|
||||||
A98C20CC2DE730740008D61C /* EditEventViewMac.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20C92DE730740008D61C /* EditEventViewMac.swift */; };
|
A98C20CC2DE730740008D61C /* EditEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20C92DE730740008D61C /* EditEventView.swift */; };
|
||||||
A98C20CE2DE7308E0008D61C /* ArchiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20CD2DE7308E0008D61C /* ArchiveView.swift */; };
|
A98C20CE2DE7308E0008D61C /* ArchiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20CD2DE7308E0008D61C /* ArchiveView.swift */; };
|
||||||
A98C20D02DE731BD0008D61C /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20CF2DE731BD0008D61C /* HomeView.swift */; };
|
A98C20D02DE731BD0008D61C /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20CF2DE731BD0008D61C /* HomeView.swift */; };
|
||||||
A98C20D42DE7339E0008D61C /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20D32DE7339E0008D61C /* AboutView.swift */; };
|
A98C20D42DE7339E0008D61C /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A98C20D32DE7339E0008D61C /* AboutView.swift */; };
|
||||||
|
A9B78B942DF9F3CF00647399 /* AddEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B78B932DF9F3CF00647399 /* AddEventView.swift */; };
|
||||||
A9FC7EEA2D2823920020D75B /* NearFutureWidgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9FC7EE92D28238A0020D75B /* NearFutureWidgets.swift */; };
|
A9FC7EEA2D2823920020D75B /* NearFutureWidgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9FC7EE92D28238A0020D75B /* NearFutureWidgets.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
@@ -129,11 +129,12 @@
|
|||||||
A979F6092D270AF00094C0B3 /* NearFutureWidgetsBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureWidgetsBundle.swift; sourceTree = "<group>"; };
|
A979F6092D270AF00094C0B3 /* NearFutureWidgetsBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureWidgetsBundle.swift; sourceTree = "<group>"; };
|
||||||
A979F60B2D270AF00094C0B3 /* NearFutureWidgetsLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureWidgetsLiveActivity.swift; sourceTree = "<group>"; };
|
A979F60B2D270AF00094C0B3 /* NearFutureWidgetsLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureWidgetsLiveActivity.swift; sourceTree = "<group>"; };
|
||||||
A979F60F2D270AF80094C0B3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
A979F60F2D270AF80094C0B3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
A98C20C92DE730740008D61C /* EditEventViewMac.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditEventViewMac.swift; sourceTree = "<group>"; };
|
A98C20C92DE730740008D61C /* EditEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditEventView.swift; sourceTree = "<group>"; };
|
||||||
A98C20CA2DE730740008D61C /* EventListViewMac.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventListViewMac.swift; sourceTree = "<group>"; };
|
A98C20CA2DE730740008D61C /* EventListViewMac.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventListViewMac.swift; sourceTree = "<group>"; };
|
||||||
A98C20CD2DE7308E0008D61C /* ArchiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArchiveView.swift; sourceTree = "<group>"; };
|
A98C20CD2DE7308E0008D61C /* ArchiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArchiveView.swift; sourceTree = "<group>"; };
|
||||||
A98C20CF2DE731BD0008D61C /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = "<group>"; };
|
A98C20CF2DE731BD0008D61C /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = "<group>"; };
|
||||||
A98C20D32DE7339E0008D61C /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
|
A98C20D32DE7339E0008D61C /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
|
||||||
|
A9B78B932DF9F3CF00647399 /* AddEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddEventView.swift; sourceTree = "<group>"; };
|
||||||
A9FC7EE92D28238A0020D75B /* NearFutureWidgets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureWidgets.swift; sourceTree = "<group>"; };
|
A9FC7EE92D28238A0020D75B /* NearFutureWidgets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureWidgets.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
@@ -192,7 +193,7 @@
|
|||||||
A98C20CF2DE731BD0008D61C /* HomeView.swift */,
|
A98C20CF2DE731BD0008D61C /* HomeView.swift */,
|
||||||
A98C20CA2DE730740008D61C /* EventListViewMac.swift */,
|
A98C20CA2DE730740008D61C /* EventListViewMac.swift */,
|
||||||
A98C20CD2DE7308E0008D61C /* ArchiveView.swift */,
|
A98C20CD2DE7308E0008D61C /* ArchiveView.swift */,
|
||||||
A98C20C82DE730420008D61C /* Modification */,
|
A98C20C82DE730420008D61C /* Events */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -351,12 +352,13 @@
|
|||||||
path = NearFutureWidgets;
|
path = NearFutureWidgets;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
A98C20C82DE730420008D61C /* Modification */ = {
|
A98C20C82DE730420008D61C /* Events */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
A98C20C92DE730740008D61C /* EditEventViewMac.swift */,
|
A9B78B932DF9F3CF00647399 /* AddEventView.swift */,
|
||||||
|
A98C20C92DE730740008D61C /* EditEventView.swift */,
|
||||||
);
|
);
|
||||||
path = Modification;
|
path = Events;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
@@ -506,13 +508,13 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
A98C20CB2DE730740008D61C /* EventListViewMac.swift in Sources */,
|
A98C20CB2DE730740008D61C /* EventListViewMac.swift in Sources */,
|
||||||
A98C20CC2DE730740008D61C /* EditEventViewMac.swift in Sources */,
|
A98C20CC2DE730740008D61C /* EditEventView.swift in Sources */,
|
||||||
A90D494B2DDE2C2900781124 /* AddEventView.swift in Sources */,
|
|
||||||
A90D495E2DDE3C7400781124 /* NFCommands.swift in Sources */,
|
A90D495E2DDE3C7400781124 /* NFCommands.swift in Sources */,
|
||||||
A98C20D42DE7339E0008D61C /* AboutView.swift in Sources */,
|
A98C20D42DE7339E0008D61C /* AboutView.swift in Sources */,
|
||||||
A98C20CE2DE7308E0008D61C /* ArchiveView.swift in Sources */,
|
A98C20CE2DE7308E0008D61C /* ArchiveView.swift in Sources */,
|
||||||
A98C20D02DE731BD0008D61C /* HomeView.swift in Sources */,
|
A98C20D02DE731BD0008D61C /* HomeView.swift in Sources */,
|
||||||
A90D495B2DDE2EDB00781124 /* MacNearFutureApp.swift in Sources */,
|
A90D495B2DDE2EDB00781124 /* MacNearFutureApp.swift in Sources */,
|
||||||
|
A9B78B942DF9F3CF00647399 /* AddEventView.swift in Sources */,
|
||||||
A90D49522DDE2D0000781124 /* Extensions.swift in Sources */,
|
A90D49522DDE2D0000781124 /* Extensions.swift in Sources */,
|
||||||
A90D49422DDE114100781124 /* Events.swift in Sources */,
|
A90D49422DDE114100781124 /* Events.swift in Sources */,
|
||||||
A90D49382DDE0FAF00781124 /* ContentViewMac.swift in Sources */,
|
A90D49382DDE0FAF00781124 /* ContentViewMac.swift in Sources */,
|
||||||
|
|||||||
@@ -49,14 +49,7 @@ struct ArchiveView: View {
|
|||||||
.sheet(isPresented: $showAddEvent) {
|
.sheet(isPresented: $showAddEvent) {
|
||||||
AddEventView(
|
AddEventView(
|
||||||
viewModel: viewModel,
|
viewModel: viewModel,
|
||||||
eventName: $viewModel.editableTemplate.name,
|
event: $viewModel.editableTemplate,
|
||||||
eventComplete: $viewModel.editableTemplate.complete,
|
|
||||||
eventCompleteDesc: $viewModel.editableTemplate.completeDesc,
|
|
||||||
eventSymbol: $viewModel.editableTemplate.symbol,
|
|
||||||
eventColor: $viewModel.editableTemplate.color.colorBind,
|
|
||||||
eventNotes: $viewModel.editableTemplate.notes,
|
|
||||||
eventDate: $viewModel.editableTemplate.date,
|
|
||||||
eventRecurrence: $viewModel.editableTemplate.recurrence,
|
|
||||||
adding: true
|
adding: true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,14 +11,7 @@ import SFSymbolsPicker
|
|||||||
struct AddEventView: View {
|
struct AddEventView: View {
|
||||||
@ObservedObject var viewModel: EventViewModel
|
@ObservedObject var viewModel: EventViewModel
|
||||||
|
|
||||||
@Binding var eventName: String
|
@Binding var event: Event
|
||||||
@Binding var eventComplete: Bool
|
|
||||||
@Binding var eventCompleteDesc: String
|
|
||||||
@Binding var eventSymbol: String
|
|
||||||
@Binding var eventColor: Color
|
|
||||||
@Binding var eventNotes: String
|
|
||||||
@Binding var eventDate: Date
|
|
||||||
@Binding var eventRecurrence: Event.RecurrenceType
|
|
||||||
|
|
||||||
@State var adding: Bool
|
@State var adding: Bool
|
||||||
@State var showNeedsNameAlert: Bool = false
|
@State var showNeedsNameAlert: Bool = false
|
||||||
@@ -38,9 +31,7 @@ struct AddEventView: View {
|
|||||||
if !adding {
|
if !adding {
|
||||||
backgroundGradient
|
backgroundGradient
|
||||||
}
|
}
|
||||||
NavigationStack {
|
List {
|
||||||
Form {
|
|
||||||
LazyVStack {
|
|
||||||
Section(
|
Section(
|
||||||
header:
|
header:
|
||||||
Text("Event Details")
|
Text("Event Details")
|
||||||
@@ -52,49 +43,30 @@ struct AddEventView: View {
|
|||||||
Button() {
|
Button() {
|
||||||
isSymbolPickerPresented.toggle()
|
isSymbolPickerPresented.toggle()
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: eventSymbol)
|
Image(systemName: event.symbol)
|
||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(width: 20, height: 20)
|
.frame(width: 20, height: 20)
|
||||||
.foregroundStyle(eventColor)
|
.foregroundStyle(event.color.color)
|
||||||
}
|
}
|
||||||
.frame(width: 20)
|
.frame(width: 20)
|
||||||
.buttonStyle(.borderless)
|
.buttonStyle(.borderless)
|
||||||
.sheet(isPresented: $isSymbolPickerPresented) {
|
.sheet(isPresented: $isSymbolPickerPresented) {
|
||||||
SymbolsPicker(
|
SymbolsPicker(
|
||||||
selection: $eventSymbol,
|
selection: $event.symbol,
|
||||||
title: "Choose a Symbol",
|
title: "Choose a Symbol",
|
||||||
searchLabel: "Search...",
|
searchLabel: "Search...",
|
||||||
autoDismiss: true)
|
autoDismiss: true)
|
||||||
.presentationDetents([.medium])
|
.presentationDetents([.medium])
|
||||||
.apply {
|
|
||||||
if #available(iOS 16.4, *) {
|
|
||||||
$0.presentationBackground(.ultraThinMaterial)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ColorPicker("", selection: $eventColor, supportsOpacity: false)
|
|
||||||
.fixedSize()
|
|
||||||
ZStack {
|
|
||||||
TextField("Event Name", text: $eventName)
|
|
||||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
|
||||||
.padding(.trailing, eventName.isEmpty ? 0 : 30)
|
|
||||||
.animation(.spring, value: eventName)
|
|
||||||
.focused($focusedField, equals: Field.Name)
|
|
||||||
.submitLabel(.next)
|
|
||||||
.onSubmit {
|
|
||||||
focusedField = .Notes
|
|
||||||
}
|
|
||||||
// MagicClearButton(text: $eventName)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dscription
|
// dscription
|
||||||
ZStack {
|
ZStack {
|
||||||
TextField("Event Notes", text: $eventNotes)
|
TextField("Event Notes", text: $event.notes)
|
||||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||||
.padding(.trailing, eventNotes.isEmpty ? 0 : 30)
|
.padding(.trailing, event.notes.isEmpty ? 0 : 30)
|
||||||
.animation(.spring, value: eventNotes)
|
.animation(.spring, value: event.notes)
|
||||||
.focused($focusedField, equals: Field.Notes)
|
.focused($focusedField, equals: Field.Notes)
|
||||||
.submitLabel(.done)
|
.submitLabel(.done)
|
||||||
.onSubmit {
|
.onSubmit {
|
||||||
@@ -107,11 +79,11 @@ struct AddEventView: View {
|
|||||||
// date picker
|
// date picker
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
DatePicker("", selection: $eventDate, displayedComponents: .date)
|
DatePicker("", selection: $event.date, displayedComponents: .date)
|
||||||
// .datePickerStyle(datepickersty)
|
.datePickerStyle(.wheel)
|
||||||
Spacer()
|
Spacer()
|
||||||
Button() {
|
Button() {
|
||||||
eventDate = Date()
|
event.date = Date()
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: "arrow.uturn.left")
|
Image(systemName: "arrow.uturn.left")
|
||||||
.resizable()
|
.resizable()
|
||||||
@@ -123,12 +95,13 @@ struct AddEventView: View {
|
|||||||
|
|
||||||
DatePicker(
|
DatePicker(
|
||||||
"",
|
"",
|
||||||
selection: $eventDate,
|
selection: $event.date,
|
||||||
displayedComponents: .hourAndMinute
|
displayedComponents: .hourAndMinute
|
||||||
)
|
)
|
||||||
|
.datePickerStyle(.wheel)
|
||||||
|
|
||||||
// re-ocurrence Picker
|
// re-ocurrence Picker
|
||||||
Picker("Recurrence", selection: $eventRecurrence) {
|
Picker("Recurrence", selection: $event.recurrence) {
|
||||||
ForEach(Event.RecurrenceType.allCases, id: \.self) { recurrence in
|
ForEach(Event.RecurrenceType.allCases, id: \.self) { recurrence in
|
||||||
Text(recurrence.rawValue.capitalized)
|
Text(recurrence.rawValue.capitalized)
|
||||||
}
|
}
|
||||||
@@ -136,18 +109,15 @@ struct AddEventView: View {
|
|||||||
.pickerStyle(SegmentedPickerStyle())
|
.pickerStyle(SegmentedPickerStyle())
|
||||||
Text(
|
Text(
|
||||||
describeOccurrence(
|
describeOccurrence(
|
||||||
date: eventDate,
|
date: event.date,
|
||||||
recurrence: eventRecurrence
|
recurrence: event.recurrence
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
.scrollContentBackground(.hidden)
|
.scrollContentBackground(.hidden)
|
||||||
.navigationTitle("\(adding ? "Add Event" : "")")
|
.navigationTitle("\(adding ? "Add Event" : "")")
|
||||||
// .navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
#if canImport(UIKit)
|
|
||||||
ToolbarItem(placement: .topBarLeading) {
|
ToolbarItem(placement: .topBarLeading) {
|
||||||
if adding {
|
if adding {
|
||||||
Button() {
|
Button() {
|
||||||
@@ -161,35 +131,11 @@ struct AddEventView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
ToolbarItem(placement: .topBarTrailing) {
|
||||||
ToolbarItem() {
|
|
||||||
if adding {
|
|
||||||
Button() {
|
|
||||||
resetAddEventView()
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
Image(systemName: "xmark")
|
|
||||||
.resizable()
|
|
||||||
.scaledToFit()
|
|
||||||
.frame(width: 30)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
ToolbarItem/*(placement: .topBarTrailing)*/ {
|
|
||||||
if adding {
|
if adding {
|
||||||
Button {
|
Button {
|
||||||
viewModel.addEvent(
|
viewModel.addEvent(
|
||||||
newEvent: Event(
|
newEvent: event
|
||||||
name: eventName,
|
|
||||||
complete: eventComplete,
|
|
||||||
completeDesc: eventCompleteDesc,
|
|
||||||
symbol: eventSymbol,
|
|
||||||
color: ColorCodable(eventColor),
|
|
||||||
notes: eventNotes,
|
|
||||||
date: eventDate,
|
|
||||||
recurrence: eventRecurrence
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
bye.toggle()
|
bye.toggle()
|
||||||
resetAddEventView()
|
resetAddEventView()
|
||||||
@@ -205,9 +151,9 @@ struct AddEventView: View {
|
|||||||
$0.sensoryFeedback(.success, trigger: bye)
|
$0.sensoryFeedback(.success, trigger: bye)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.disabled(eventName.isEmpty)
|
.disabled(event.name.isEmpty)
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
if eventName.isEmpty {
|
if event.name.isEmpty {
|
||||||
showNeedsNameAlert.toggle()
|
showNeedsNameAlert.toggle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,7 +165,7 @@ struct AddEventView: View {
|
|||||||
} message: {
|
} message: {
|
||||||
Text("Give your Event a name before saving.")
|
Text("Give your Event a name before saving.")
|
||||||
}
|
}
|
||||||
if eventName.isEmpty {
|
if event.name.isEmpty {
|
||||||
HStack {
|
HStack {
|
||||||
Image(systemName: "exclamationmark")
|
Image(systemName: "exclamationmark")
|
||||||
.foregroundStyle(.red)
|
.foregroundStyle(.red)
|
||||||
@@ -230,25 +176,13 @@ struct AddEventView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.presentationDragIndicator(.visible)
|
|
||||||
.scrollContentBackground(.hidden)
|
.scrollContentBackground(.hidden)
|
||||||
}
|
.presentationDragIndicator(.visible)
|
||||||
.apply {
|
|
||||||
if #available(iOS 16.4, *) {
|
|
||||||
$0.presentationBackground(.ultraThinMaterial)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func resetAddEventView() {
|
func resetAddEventView() {
|
||||||
//reset addeventView
|
//reset addeventView
|
||||||
eventName = viewModel.template.name
|
event = viewModel.template
|
||||||
eventComplete = viewModel.template.complete
|
|
||||||
eventCompleteDesc = viewModel.template.completeDesc
|
|
||||||
eventSymbol = viewModel.template.symbol
|
|
||||||
eventColor = randomColor()
|
|
||||||
eventNotes = viewModel.template.notes
|
|
||||||
eventDate = viewModel.template.date
|
|
||||||
eventRecurrence = viewModel.template.recurrence
|
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,14 +195,7 @@ struct AddEventView: View {
|
|||||||
.sheet(isPresented: .constant(true)) {
|
.sheet(isPresented: .constant(true)) {
|
||||||
AddEventView(
|
AddEventView(
|
||||||
viewModel: vm,
|
viewModel: vm,
|
||||||
eventName: .constant(vm.template.notes),
|
event: .constant(vm.template),
|
||||||
eventComplete: .constant(vm.template.complete),
|
|
||||||
eventCompleteDesc: .constant(vm.template.completeDesc),
|
|
||||||
eventSymbol: .constant(vm.template.symbol),
|
|
||||||
eventColor: .constant(vm.template.color.color),
|
|
||||||
eventNotes: .constant(vm.template.notes),
|
|
||||||
eventDate: .constant(vm.template.date),
|
|
||||||
eventRecurrence: .constant(vm.template.recurrence),
|
|
||||||
adding: true
|
adding: true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,14 +28,7 @@ struct EditEventView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
AddEventView(
|
AddEventView(
|
||||||
viewModel: viewModel,
|
viewModel: viewModel,
|
||||||
eventName: $event.name,
|
event: $event,
|
||||||
eventComplete: $event.complete,
|
|
||||||
eventCompleteDesc: $event.completeDesc,
|
|
||||||
eventSymbol: $event.symbol,
|
|
||||||
eventColor: $event.color.colorBind,
|
|
||||||
eventNotes: $event.notes,
|
|
||||||
eventDate: $event.date,
|
|
||||||
eventRecurrence: $event.recurrence,
|
|
||||||
adding: false //bc we editing existing event
|
adding: false //bc we editing existing event
|
||||||
)
|
)
|
||||||
.navigationTitle("Edit Event")
|
.navigationTitle("Edit Event")
|
||||||
|
|||||||
@@ -120,7 +120,6 @@ struct EventListView: View {
|
|||||||
}
|
}
|
||||||
.transition(.opacity)
|
.transition(.opacity)
|
||||||
.padding(.vertical, 5)
|
.padding(.vertical, 5)
|
||||||
.background(.ultraThinMaterial)
|
|
||||||
.overlay(
|
.overlay(
|
||||||
RoundedRectangle(cornerRadius: 10)
|
RoundedRectangle(cornerRadius: 10)
|
||||||
.stroke(
|
.stroke(
|
||||||
|
|||||||
@@ -5,19 +5,14 @@
|
|||||||
// Created by neon443 on 12/05/2025.
|
// Created by neon443 on 12/05/2025.
|
||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI;import AppIntents
|
import SwiftUI
|
||||||
|
import AppIntents
|
||||||
|
|
||||||
struct HomeView: View {
|
struct HomeView: View {
|
||||||
@ObservedObject var viewModel: EventViewModel
|
@ObservedObject var viewModel: EventViewModel
|
||||||
@ObservedObject var settingsModel: SettingsViewModel
|
@ObservedObject var settingsModel: SettingsViewModel
|
||||||
@State private var eventName: String = ""
|
|
||||||
@State private var eventComplete: Bool = false
|
@State private var event: Event = dummyEventViewModel().template
|
||||||
@State private var eventCompleteDesc: String = ""
|
|
||||||
@State private var eventSymbol: String = "star"
|
|
||||||
@State private var eventColor: Color = randomColor()
|
|
||||||
@State private var eventNotes: String = ""
|
|
||||||
@State private var eventDate = Date()
|
|
||||||
@State private var eventRecurrence: Event.RecurrenceType = .none
|
|
||||||
@State private var showingAddEventView: Bool = false
|
@State private var showingAddEventView: Bool = false
|
||||||
@State private var searchInput: String = ""
|
@State private var searchInput: String = ""
|
||||||
@Environment(\.colorScheme) var appearance
|
@Environment(\.colorScheme) var appearance
|
||||||
@@ -47,36 +42,18 @@ struct HomeView: View {
|
|||||||
ZStack {
|
ZStack {
|
||||||
backgroundGradient
|
backgroundGradient
|
||||||
VStack {
|
VStack {
|
||||||
ZStack {
|
|
||||||
TextField(
|
|
||||||
"\(Image(systemName: "magnifyingglass")) Search",
|
|
||||||
text: $searchInput
|
|
||||||
)
|
|
||||||
.padding(.trailing, searchInput.isEmpty ? 0 : 30)
|
|
||||||
.animation(.spring, value: searchInput)
|
|
||||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
|
||||||
.submitLabel(.done)
|
|
||||||
.focused($focusedField, equals: Field.Search)
|
|
||||||
.onSubmit {
|
|
||||||
focusedField = nil
|
|
||||||
}
|
|
||||||
MagicClearButton(text: $searchInput)
|
|
||||||
.onTapGesture {
|
|
||||||
focusedField = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(.horizontal)
|
|
||||||
|
|
||||||
if filteredEvents.isEmpty && !searchInput.isEmpty {
|
if filteredEvents.isEmpty && !searchInput.isEmpty {
|
||||||
HelpView(searchInput: $searchInput, focusedField: focusedField)
|
HelpView(searchInput: $searchInput, focusedField: focusedField)
|
||||||
} else {
|
} else {
|
||||||
ScrollView {
|
ScrollView {
|
||||||
|
// LazyVStack {
|
||||||
ForEach(filteredEvents) { event in
|
ForEach(filteredEvents) { event in
|
||||||
EventListView(viewModel: viewModel, event: event)
|
EventListView(viewModel: viewModel, event: event)
|
||||||
.transition(.moveAndFade)
|
.transition(.moveAndFade)
|
||||||
.id(event.complete)
|
.id(event.complete)
|
||||||
}
|
}
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
|
// }
|
||||||
if filteredEvents.isEmpty {
|
if filteredEvents.isEmpty {
|
||||||
HelpView(
|
HelpView(
|
||||||
searchInput: $searchInput,
|
searchInput: $searchInput,
|
||||||
@@ -88,6 +65,7 @@ struct HomeView: View {
|
|||||||
.animation(.default, value: filteredEvents)
|
.animation(.default, value: filteredEvents)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.searchable(text: $searchInput)
|
||||||
.navigationTitle("Near Future")
|
.navigationTitle("Near Future")
|
||||||
.apply {
|
.apply {
|
||||||
if #available(iOS 17, *) {
|
if #available(iOS 17, *) {
|
||||||
@@ -99,14 +77,7 @@ struct HomeView: View {
|
|||||||
.sheet(isPresented: $showingAddEventView) {
|
.sheet(isPresented: $showingAddEventView) {
|
||||||
AddEventView(
|
AddEventView(
|
||||||
viewModel: viewModel,
|
viewModel: viewModel,
|
||||||
eventName: $eventName,
|
event: $event,
|
||||||
eventComplete: $eventComplete,
|
|
||||||
eventCompleteDesc: $eventCompleteDesc,
|
|
||||||
eventSymbol: $eventSymbol,
|
|
||||||
eventColor: $eventColor,
|
|
||||||
eventNotes: $eventNotes,
|
|
||||||
eventDate: $eventDate,
|
|
||||||
eventRecurrence: $eventRecurrence,
|
|
||||||
adding: true //adding event
|
adding: true //adding event
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ struct AddEventButton: View {
|
|||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(width: 15)
|
.frame(width: 15)
|
||||||
.bold()
|
.bold()
|
||||||
.foregroundStyle(.two)
|
.foregroundStyle(.one)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ struct ImportView: View {
|
|||||||
.ignoresSafeArea()
|
.ignoresSafeArea()
|
||||||
ZStack {
|
ZStack {
|
||||||
Rectangle()
|
Rectangle()
|
||||||
.background(.ultraThinMaterial)
|
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 25))
|
.clipShape(RoundedRectangle(cornerRadius: 25))
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
Text("Are you sure?")
|
Text("Are you sure?")
|
||||||
|
|||||||
@@ -92,11 +92,6 @@ struct WhatsNewView: View {
|
|||||||
}
|
}
|
||||||
.scrollContentBackground(.hidden)
|
.scrollContentBackground(.hidden)
|
||||||
.presentationDragIndicator(.visible)
|
.presentationDragIndicator(.visible)
|
||||||
.apply {
|
|
||||||
if #available(iOS 16.4, *) {
|
|
||||||
$0.presentationBackground(.ultraThinMaterial)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.onDisappear {
|
.onDisappear {
|
||||||
settingsModel.settings.prevAppVersion = getVersion()+getBuildID()
|
settingsModel.settings.prevAppVersion = getVersion()+getBuildID()
|
||||||
settingsModel.saveSettings()
|
settingsModel.saveSettings()
|
||||||
|
|||||||
Reference in New Issue
Block a user