diff --git a/NearFuture.xcodeproj/project.pbxproj b/NearFuture.xcodeproj/project.pbxproj index 75e8591..ed3bf40 100644 --- a/NearFuture.xcodeproj/project.pbxproj +++ b/NearFuture.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 77; + objectVersion = 70; objects = { /* Begin PBXBuildFile section */ @@ -34,21 +34,9 @@ /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ - A9B4BFCA2D1AE66000212CE2 /* NearFuture */ = { - isa = PBXFileSystemSynchronizedRootGroup; - path = NearFuture; - sourceTree = ""; - }; - A9B4BFDE2D1AE66700212CE2 /* NearFutureTests */ = { - isa = PBXFileSystemSynchronizedRootGroup; - path = NearFutureTests; - sourceTree = ""; - }; - A9B4BFE82D1AE66700212CE2 /* NearFutureUITests */ = { - isa = PBXFileSystemSynchronizedRootGroup; - path = NearFutureUITests; - sourceTree = ""; - }; + A9B4BFCA2D1AE66000212CE2 /* NearFuture */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = NearFuture; sourceTree = ""; }; + A9B4BFDE2D1AE66700212CE2 /* NearFutureTests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = NearFutureTests; sourceTree = ""; }; + A9B4BFE82D1AE66700212CE2 /* NearFutureUITests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = NearFutureUITests; sourceTree = ""; }; /* End PBXFileSystemSynchronizedRootGroup section */ /* Begin PBXFrameworksBuildPhase section */ @@ -193,6 +181,7 @@ }; }; buildConfigurationList = A9B4BFC32D1AE66000212CE2 /* Build configuration list for PBXProject "NearFuture" */; + compatibilityVersion = "Xcode 15.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -204,7 +193,6 @@ packageReferences = ( A91288572D1C7E3000912B3C /* XCRemoteSwiftPackageReference "SFSymbolsPicker" */, ); - preferredProjectObjectVersion = 77; productRefGroup = A9B4BFC92D1AE66000212CE2 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -313,6 +301,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_HARDENED_RUNTIME = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -374,6 +363,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_HARDENED_RUNTIME = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -403,7 +393,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"NearFuture/Preview Content\""; - DEVELOPMENT_TEAM = 85Q9QG6DN7; + DEVELOPMENT_TEAM = P6PV2R9443; ENABLE_HARDENED_RUNTIME = NO; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -422,7 +412,7 @@ "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 14.0; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFuture; + PRODUCT_BUNDLE_IDENTIFIER = com.hack.NearFuture; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = auto; @@ -444,7 +434,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"NearFuture/Preview Content\""; - DEVELOPMENT_TEAM = 85Q9QG6DN7; + DEVELOPMENT_TEAM = P6PV2R9443; ENABLE_HARDENED_RUNTIME = NO; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -463,7 +453,7 @@ "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; MACOSX_DEPLOYMENT_TARGET = 14.0; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFuture; + PRODUCT_BUNDLE_IDENTIFIER = com.hack.NearFuture; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; @@ -480,12 +470,12 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 8626DL2GW3; + DEVELOPMENT_TEAM = 85Q9QG6DN7; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 18.2; - MACOSX_DEPLOYMENT_TARGET = 15.1; + IPHONEOS_DEPLOYMENT_TARGET = 17; + MACOSX_DEPLOYMENT_TARGET = 14; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFutureTests; + PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFuture; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; @@ -493,7 +483,7 @@ SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2,7"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NearFuture.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/NearFuture"; - XROS_DEPLOYMENT_TARGET = 2.2; + XROS_DEPLOYMENT_TARGET = 1; }; name = Debug; }; @@ -503,12 +493,12 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 8626DL2GW3; + DEVELOPMENT_TEAM = 85Q9QG6DN7; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 18.2; - MACOSX_DEPLOYMENT_TARGET = 15.1; + IPHONEOS_DEPLOYMENT_TARGET = 17; + MACOSX_DEPLOYMENT_TARGET = 14; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFutureTests; + PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFuture; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; @@ -516,7 +506,7 @@ SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2,7"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NearFuture.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/NearFuture"; - XROS_DEPLOYMENT_TARGET = 2.2; + XROS_DEPLOYMENT_TARGET = 1; }; name = Release; }; @@ -525,12 +515,12 @@ buildSettings = { CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 8626DL2GW3; + DEVELOPMENT_TEAM = 85Q9QG6DN7; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 18.2; - MACOSX_DEPLOYMENT_TARGET = 15.1; + IPHONEOS_DEPLOYMENT_TARGET = 17; + MACOSX_DEPLOYMENT_TARGET = 14; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFutureUITests; + PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFuture; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; @@ -538,7 +528,7 @@ SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2,7"; TEST_TARGET_NAME = NearFuture; - XROS_DEPLOYMENT_TARGET = 2.2; + XROS_DEPLOYMENT_TARGET = 1; }; name = Debug; }; @@ -547,12 +537,12 @@ buildSettings = { CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 8626DL2GW3; + DEVELOPMENT_TEAM = 85Q9QG6DN7; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 18.2; - MACOSX_DEPLOYMENT_TARGET = 15.1; + IPHONEOS_DEPLOYMENT_TARGET = 17; + MACOSX_DEPLOYMENT_TARGET = 14; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFutureUITests; + PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFuture; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = auto; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; @@ -560,7 +550,7 @@ SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2,7"; TEST_TARGET_NAME = NearFuture; - XROS_DEPLOYMENT_TARGET = 2.2; + XROS_DEPLOYMENT_TARGET = 1; }; name = Release; }; diff --git a/NearFuture.xcodeproj/xcshareddata/xcschemes/NearFuture.xcscheme b/NearFuture.xcodeproj/xcshareddata/xcschemes/NearFuture.xcscheme deleted file mode 100644 index 527730f..0000000 --- a/NearFuture.xcodeproj/xcshareddata/xcschemes/NearFuture.xcscheme +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/NearFuture/AddEventView.swift b/NearFuture/AddEventView.swift index ce2729e..2ea943e 100644 --- a/NearFuture/AddEventView.swift +++ b/NearFuture/AddEventView.swift @@ -12,6 +12,7 @@ struct AddEventView: View { @ObservedObject var viewModel: EventViewModel @Binding var eventName: String @Binding var eventSymbol: String + @Binding var eventColor: Color @Binding var eventDescription: String @Binding var eventDate: Date @Binding var eventRecurrence: Event.RecurrenceType @@ -29,8 +30,9 @@ struct AddEventView: View { Image(systemName: eventSymbol) .resizable() .scaledToFit() - .frame(width: 30, height: 30) + .frame(width: 25, height: 25) } +// .frame(width: 30) .buttonStyle(.bordered) .sheet(isPresented: $isSymbolPickerPresented) { SymbolsPicker( @@ -39,6 +41,8 @@ struct AddEventView: View { searchLabel: "Search...", autoDismiss: true) } + ColorPicker("", selection: $eventColor, supportsOpacity: true) + .fixedSize() Divider() ZStack { TextField("Event Name", text: $eventName) @@ -48,6 +52,7 @@ struct AddEventView: View { MagicClearButton(text: $eventName) } } + Text(eventColor.description) // dscription ZStack { @@ -83,12 +88,23 @@ struct AddEventView: View { viewModel.addEvent( name: eventName, symbol: eventSymbol, + color: ColorCodable(eventColor), description: eventDescription, date: eventDate, recurrence: eventRecurrence ) + //reset addeventView eventName = "" eventSymbol = "star" + eventColor = [ + Color.red, + Color.orange, + Color.yellow, + Color.green, + Color.blue, + Color.indigo, + Color.purple + ].randomElement() ?? Color.red eventDescription = "" eventDate = Date() eventRecurrence = .none @@ -135,12 +151,14 @@ struct MagicClearButton: View { struct AddEvent_Preview: PreviewProvider { @State static var symbol = "star" @State static var date = Date() + @State static var color = Color(.red) static var previews: some View { AddEventView( viewModel: EventViewModel(), eventName: .constant("Birthday"), eventSymbol: $symbol, + eventColor: $color, eventDescription: .constant("A very special day"), eventDate: $date, eventRecurrence: .constant(.monthly), diff --git a/NearFuture/ContentView.swift b/NearFuture/ContentView.swift index eebda99..bee8fec 100644 --- a/NearFuture/ContentView.swift +++ b/NearFuture/ContentView.swift @@ -70,6 +70,15 @@ struct ContentView: View { @StateObject private var viewModel = EventViewModel() @State private var eventName = "" @State private var eventSymbol = "star" + @State private var eventColor: Color = [ + Color.red, + Color.orange, + Color.yellow, + Color.green, + Color.blue, + Color.indigo, + Color.purple + ].randomElement() ?? Color.red @State private var eventDescription = "" @State private var eventDate = Date() @State private var eventRecurrence: Event.RecurrenceType = .none @@ -85,52 +94,87 @@ struct ContentView: View { } } } + @Environment(\.colorScheme) var appearance + private var backgroundGradient: LinearGradient { + switch appearance { + case .light: + return LinearGradient( + gradient: Gradient(colors: [.gray.opacity(0.2), .white]), + startPoint: .top, + endPoint: .bottom + ) + case .dark: + return LinearGradient( + gradient: Gradient(colors: [.gray.opacity(0.2), .black]), + startPoint: .top, + endPoint: .bottom) + @unknown default: + //red bg gradient for uknown appearance + return LinearGradient( + gradient: Gradient(colors: [.red, .black]), + startPoint: .bottom, + endPoint: .top + ) + } + } var body: some View { NavigationView { - VStack { - ZStack { - TextField( - "\(Image(systemName: "magnifyingglass")) Search", - text: $searchInput - ) - .padding(.trailing, searchInput.isEmpty ? 0 : 30) - .animation(.spring, value: searchInput) - .textFieldStyle(RoundedBorderTextFieldStyle()) - MagicClearButton(text: $searchInput) - } - .padding(.horizontal) - List { - ForEach(filteredEvents) { event in - EventListView(event: event) + 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()) + MagicClearButton(text: $searchInput) + } + .padding(.horizontal) + List { + ForEach(filteredEvents) { event in + var eventBackgroundGradient: LinearGradient { + return LinearGradient( + colors: [ + event.color.color, + Color.black + ], + startPoint: .leading, + endPoint: .trailing + ) + } + EventListView(event: event) + } + .onDelete(perform: viewModel.removeEvent) } - .onDelete(perform: viewModel.removeEvent) } - } - .navigationTitle("Near Future") -// .navigationTitle() { -// Text("hi") -// } - .navigationBarTitleDisplayMode(.inline) - .sheet(isPresented: $showingAddEventView) { - AddEventView( - viewModel: viewModel, - eventName: $eventName, - eventSymbol: $eventSymbol, - eventDescription: $eventDescription, - eventDate: $eventDate, - eventRecurrence: $eventRecurrence, - isPresented: $showingAddEventView - ) - } - .toolbar { - ToolbarItem(placement: .topBarTrailing) { - Button(action: { - showingAddEventView.toggle() - }) { - Image(systemName: "plus.circle") - .resizable() - .scaledToFit() + .navigationTitle("Near Future") + .navigationBarTitleDisplayMode(.inline) + .sheet(isPresented: $showingAddEventView) { + AddEventView( + viewModel: viewModel, + eventName: $eventName, + eventSymbol: $eventSymbol, + eventColor: $eventColor, + eventDescription: $eventDescription, + eventDate: $eventDate, + eventRecurrence: $eventRecurrence, + isPresented: $showingAddEventView + ) + } + .toolbar { + ToolbarItem(placement: .topBarTrailing) { + Button(action: { + showingAddEventView.toggle() + }) { + Image(systemName: "plus.circle") + .resizable() + .scaledToFit() + } } } } @@ -143,35 +187,45 @@ struct EventListView: View { @State var event: Event var body: some View { - HStack { - VStack(alignment: .leading) { - HStack { - Image(systemName: event.symbol) - Text(event.name) - .font(.headline) - .padding(.bottom, 2) - } - Text(event.description) - .font(.subheadline) - .foregroundColor(.gray) - Text("Recurring: \(event.recurrence.rawValue.capitalized)") +// var testColor = Color.red +// var codableColor = ColorCodable(testColor) +// Text("\(codableColor.red), \(codableColor.green), \(codableColor.blue), \(codableColor.alpha)") + ZStack { + HStack { + RoundedRectangle(cornerRadius: 5) + .frame(width: 5) + .foregroundStyle(event.color.color) + .padding(.leading, -5) + VStack(alignment: .leading) { + HStack { + Image(systemName: event.symbol) + Text(event.name) + .font(.headline) + .padding(.bottom, 2) + } + Text(event.description) + .font(.subheadline) + .foregroundColor(.gray) + if event.recurrence != .none { + Text("Recurring: \(event.recurrence.rawValue.capitalized)") + .font(.subheadline) + .foregroundColor(.blue) + } + Text(event.date.formatted(date: .long, time: .omitted)) .font(.subheadline) .foregroundColor(.blue) - Text("In \(daysUntilEvent(event.date))") + } + + Spacer() + + Text("\(daysUntilEvent(event.date))") .font(.subheadline) .foregroundColor(.gray) } - - Spacer() - - Text(event.date.formatted(date: .long, time: .omitted)) - .font(.subheadline) - .foregroundColor(.blue) + .padding(.vertical, 8) } - .padding(.vertical, 8) } } - #Preview { ContentView() } diff --git a/NearFuture/Item.swift b/NearFuture/Item.swift index 8a4671c..efcebc9 100644 --- a/NearFuture/Item.swift +++ b/NearFuture/Item.swift @@ -7,6 +7,7 @@ import Foundation import SwiftData +import SwiftUI @Model final class Item { @@ -21,6 +22,7 @@ struct Event: Identifiable, Codable { var id = UUID() var name: String var symbol: String + var color: ColorCodable var description: String var date: Date var recurrence: RecurrenceType @@ -30,11 +32,49 @@ struct Event: Identifiable, Codable { } } +struct ColorCodable: Codable { + var red: Double + var green: Double + var blue: Double + var alpha: Double + //for the brainrotted: alpha is the opacity/transparency of the color, + //alpha == 0 completely transparent + //alpha == 1 completely opaque + + var color: Color { + Color(red: red, green: green, blue: blue, opacity: alpha) + } + + init(_ color: Color) { + let uiColor = UIColor(color) + var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0 + uiColor.getRed(&r, green: &g, blue: &b, alpha: &a) + + self.red = Double(r) + self.green = Double(g) + self.blue = Double(b) + self.alpha = Double(a) + + } + init(red: Double, green: Double, blue: Double, alpha: Double = 1.0) { + self.red = red + self.green = green + self.blue = blue + self.alpha = alpha + } +} + func daysUntilEvent(_ eventDate: Date) -> String { let calendar = Calendar.current let currentDate = Date() let components = calendar.dateComponents([.day], from: currentDate, to: eventDate) guard let days = components.day else { return "N/A" } + guard days >= 0 else { + return "\(days) days ago" + } + guard days != 0 else { + return "Today" + } return "\(days) days" } @@ -61,10 +101,18 @@ class EventViewModel: ObservableObject { } } - func addEvent(name: String, symbol: String, description: String, date: Date, recurrence: Event.RecurrenceType) { + func addEvent( + name: String, + symbol: String, + color: ColorCodable, + description: String, + date: Date, + recurrence: Event.RecurrenceType + ) { let newEvent = Event( name: name, symbol: symbol, + color: color, description: description, date: date, recurrence: recurrence diff --git a/README.md b/README.md index 746b9ed..b661a3e 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,10 @@ Near Future is a SwiftUI App to help people to track upcoming events - Holidays, - [x] Add and delete events - [x] Descriptions - [x] Icons -- [ ] Event colors +- [x] Event colors - [ ] Recurrence - [x] Search +- [ ] Apple Watch App - [ ] Home Screen Widgets - [ ] Lock Screen Widgets @@ -41,5 +42,5 @@ Contributions are welcome! just follow these: 3. Open a pull request ## Used Tools/Frameworks -- Swift & SwiftUI - Apple -- **SFSymbolsPicker** - [alessiorubicini/SFSymbolsPickerForSwiftUI]. +- Swift & SwiftUI by Apple +- **SFSymbolsPicker** by [alessiorubicini/SFSymbolsPickerForSwiftUI].