68 Commits

Author SHA1 Message Date
neon443
d1c1144ad8 you asked for the haptics... 2025-05-21 21:43:47 +01:00
neon443
bcfe23a17e info plist shenanigans for ios 2025-05-21 20:53:35 +01:00
neon443
74ef5db2cf trying to impement a menu bar 2025-05-21 20:50:53 +01:00
neon443
389fdf6812 fix taget memberships and Settings -> NFSettings 2025-05-21 20:41:01 +01:00
neon443
b153d127a6 fix padding on the eventlistView extract settings to Settings.swift rename some files 2025-05-21 20:38:54 +01:00
neon443
62318c5ddc mac ui 2025-05-21 18:10:22 +01:00
neon443
773a083682 making mac ui 2025-05-21 17:21:04 +01:00
neon443
e051d73b7e declared types on all views, trying to make a nice mac app 2025-05-21 17:02:21 +01:00
neon443
4bf33d50d6 moved colours to tints.xcassets 2025-05-21 15:37:32 +01:00
neon443
74603cc588 fixed appkit and uikit conflicts 2025-05-21 15:28:35 +01:00
neon443
ed016217db added item and assets to macnearfuture 2025-05-21 14:52:55 +01:00
neon443
a64eb03cad add Mac target and delet tests 2025-05-21 14:45:04 +01:00
neon443
7c7f72a5d4 more reorgs 2025-05-21 14:40:50 +01:00
neon443
831305ba55 massive reorg: source and assets 2025-05-21 14:20:05 +01:00
neon443
69856e2857 fix concurrency warinings 2025-05-21 14:16:54 +01:00
neon443
7be2e3848a reorg 2025-05-21 14:14:40 +01:00
neon443
db05da3043 add haptic feedback, bump version, update whats new 2025-05-19 15:13:38 +01:00
neon443
940a8f4ebd haptic on tab selection, remove divider 2025-05-19 15:08:34 +01:00
neon443
48071c0791 remove th goof button 2025-05-19 15:03:49 +01:00
neon443
3a94dc7675 app intents make me wanna kms 2025-05-16 09:49:14 +01:00
neon443
08bf56ecbd ajsdlkfjkl;asdjfkl 2025-05-15 18:52:23 +01:00
neon443
008eecb52c ddfsdfsd 2025-05-15 18:41:03 +01:00
neon443
c640c77600 dskljfasdlkfjkl;asjfklajsdkl;fjaksd;jfgkladfjhghadfiughaipehroigjuoeirjgfioejroifjaoigjoiaejoirg 2025-05-15 18:30:02 +01:00
neon443
e9d49cc137 pls pls pls b fixed 2025-05-15 18:00:22 +01:00
neon443
565341c3d0 s 2025-05-15 17:32:04 +01:00
neon443
f9c50df47f s 2025-05-15 17:27:27 +01:00
neon443
bb598250a6 modified: Config.xcconfig 2025-05-15 17:22:25 +01:00
neon443
c7fddda601 ssfdafasfasdfaf 2025-05-15 17:06:58 +01:00
neon443
033a01463f fix icon setting fr this time 2025-05-15 12:31:53 +01:00
neon443
87209f38f3 jfdsa 2025-05-15 07:46:37 +01:00
neon443
7c852fc8ec fix the whats new appearing each settings save 2025-05-14 21:42:22 +01:00
neon443
73b3d9b234 update widget
to imporve readablity and add red for past
bump version
add whats new
2025-05-14 21:20:55 +01:00
neon443
0a17ec6292 bump version adn update whats new 2025-05-14 21:16:35 +01:00
neon443
bb67b0ce98 YESSSSSSSSS
ok now jsut have ot make this scalabel 😭
😭😭😭
2025-05-14 21:04:00 +01:00
neon443
82341f40ef ajkl;dfs;asfjl;laskdjf;ajsf 2025-05-14 20:51:02 +01:00
neon443
f9f030c8b3 app icon yayyyyy 2025-05-14 19:25:22 +01:00
neon443
3ca5017b61 remove basic ui color 2025-05-13 19:36:34 +01:00
neon443
0efcc9e183 bump version to 4.2.1(1) 2025-05-13 11:07:23 +01:00
neon443
595c2b74c5 fixed whatsnewview's horizontal layout 2025-05-13 11:07:03 +01:00
neon443
f252359eb1 bump version, update whats new 2025-05-13 11:00:31 +01:00
neon443
2b266e03ca fix whats new showing every time
prevAppVersoin wasnt being set lol
remove .searchable()
rename WhatsNew -> WhatsNewChunk
2025-05-13 10:59:22 +01:00
neon443
c935d4b1f0 improve whats new
added a global getdevice icon thingy
2025-05-12 21:07:51 +01:00
neon443
c82ce5fa17 Whats New!
add AboutView
move getVersion() and geBuildID()
reorg of presentaion related modifiers
2025-05-12 20:49:28 +01:00
neon443
7bef3bc4e6 animations make me wanna kms
animations!!!!!!!!! on add, delete and ticking yayy
sorts on load
extract contentview to HomeView, its got too indented loll
2025-05-12 19:24:34 +01:00
neon443
025dbf22cd tring to ad animations 2025-05-12 17:26:37 +01:00
neon443
da65c3ac69 asdkjlf 2025-05-09 14:14:15 +01:00
neon443
5f52b423db changes to pending notif checker
add migration, if events dont have notifs
fix runtime error about bg threads by using await MainActor.run
add cancelallnotifs
bump version
2025-05-09 14:09:06 +01:00
neon443
7af96834d6 ok now notifs seem doen
neew event -> notif
edited event- cancel old, new notif
completed events- cancel notif
moved notif granting to settings struct
add: getNotifs, checkPendingNotifs, checkNotif, scheduleEventNotif, getDateComponents, cancelNotif
fix scheduleNotif
migration next
2025-05-07 10:33:35 +01:00
neon443
17ef4f1478 mroe reorg 2025-05-06 22:49:35 +01:00
neon443
785dda0e2b reorg -- long overdue lol 2025-05-06 21:49:21 +01:00
neon443
5f5702d958 ssdlkfjaslkf 2025-05-06 21:05:28 +01:00
neon443
b88bc11b36 yayy notifs!!
made the about app icon better
2025-05-06 21:03:53 +01:00
neon443
f8f5cdde26 symbolpicker presentationdetents 2025-05-06 18:32:59 +01:00
neon443
169d51e6b9 improved app icon getting - now gets the actual app icon 2025-05-06 15:37:10 +01:00
neon443
afd6d23838 bump version 2025-05-06 10:09:16 +01:00
neon443
5877f3b525 fixed no color selected when having no settings
fix helpview always orange
2025-05-06 10:05:01 +01:00
neon443
4157520ff4 accent color picking
added about
added saveSettings()
backported to 16.0
new title bar
2025-05-06 09:37:03 +01:00
neon443
f03ea73813 basic settings done!!!
now can set accent color
2025-05-05 09:57:58 +01:00
neon443
dafd2ae0e8 Merge branch 'feat-accent' 2025-05-05 08:58:10 +01:00
neon443
1bbacd0caa added onappear reset to importVie 2025-05-05 08:57:45 +01:00
Nihaal Sharma
29be23efc2 Update README.md 2025-05-04 12:49:49 +01:00
neon443
ffbd17fad8 rerewrote daysUntillEvent, now acc can count days
inlineLarge titlebar, backwards compatible view extension
competed events go to archive
fix long event name and notes alignemnts
can refresh icloud settings to sync
2025-05-04 12:31:01 +01:00
neon443
c97d37711c Fix import/Export events
rewrote the daysTillEventt()
2025-05-03 10:36:17 +01:00
neon443
80b193f449 ajdshfjkas 2025-05-02 10:03:43 +01:00
neon443
48d086602e fix the negative time when using the long daystill 2025-05-02 09:50:26 +01:00
neon443
3450e8bf1c cleanup 2025-05-01 21:23:14 +01:00
neon443
a08642bcb5 fix day count being wrong, minor updates 2025-05-01 21:05:31 +01:00
neon443
8ea1eda8f4 add xcconfig vars to widget appex 2025-04-29 21:29:21 +01:00
121 changed files with 3266 additions and 1792 deletions

View File

@@ -10,7 +10,8 @@
TEAM_ID = 8JGND254B7 TEAM_ID = 8JGND254B7
BUNDLE_ID = com.neon443.NearFuture BUNDLE_ID = com.neon443.NearFuture
BUNDLE_ID_WIDGETS = com.neon443.NearFuture.widgets
GROUP_ID = group.NearFuture GROUP_ID = group.NearFuture
VERSION = 3.0.1 VERSION = 4.4.0
NAME = Near Future NAME = Near Future
BUILD_NUMBER = 1 BUILD_NUMBER = 1

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 609 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 534 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,18 @@
<?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>com.apple.developer.icloud-container-identifiers</key>
<array/>
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.NearFuture</string>
</array>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,61 @@
//
// MacNearFutureApp.swift
// MacNearFuture
//
// Created by neon443 on 21/05/2025.
//
import Foundation
import SwiftUI
@main
struct NearFutureApp: App {
@StateObject var settingsModel: SettingsViewModel = SettingsViewModel()
var body: some Scene {
WindowGroup {
NavigationSplitView {
List {
NavigationLink {
} label: {
Image(systemName: "house")
Text("Home")
}
NavigationLink {
} label: {
Image(systemName: "tray.full")
Text("Archive")
}
}
} detail: {
ContentView(
viewModel: EventViewModel(),
settingsModel: settingsModel
)
}
.tint(settingsModel.settings.tint.color)
.frame(minWidth: 450, minHeight: 550)
.containerBackground(.ultraThinMaterial, for: .window)
}
.defaultSize(width: 550, height: 650)
.commands {
NearFutureCommands()
Menu("hi") {
Button("hi") {
}
}
}
Window("About Near Future", id: "about") {
}
Settings {
Text("wip")
}
}
}

View File

@@ -0,0 +1,15 @@
//
// NFCommands.swift
// MacNearFuture
//
// Created by neon443 on 21/05/2025.
//
import Foundation
import SwiftUI
struct NearFutureCommands: Commands {
var body: some Commands {
}
}

View File

@@ -0,0 +1,29 @@
//
// ContentView.swift
// MacNearFuture
//
// Created by neon443 on 21/05/2025.
//
import SwiftUI
struct ContentView: View {
@ObservedObject var viewModel: EventViewModel
@ObservedObject var settingsModel: SettingsViewModel
var body: some View {
ScrollView {
ForEach(viewModel.events) { event in
EventListView(viewModel: viewModel, event: event)
}
}
.scrollContentBackground(.hidden)
}
}
#Preview {
ContentView(
viewModel: dummyEventViewModel(),
settingsModel: dummySettingsViewModel()
)
}

View File

@@ -0,0 +1,61 @@
//
// EditEventView.swift
// NearFuture
//
// Created by neon443 on 21/05/2025.
//
import SwiftUI
struct EditEventView: View {
@Environment(\.dismiss) var dismiss
@ObservedObject var viewModel: EventViewModel
@Binding var event: Event
fileprivate func saveEdits() {
//if there is an event in vM.events with the id of the event we r editing,
//firstindex - loops through the arr and finds first element where that events id matches editing event's id
if let index = viewModel.events.firstIndex(where: { xEvent in
xEvent.id == event.id
}) {
viewModel.events[index] = event
}
viewModel.saveEvents()
dismiss()
}
var body: some View {
AddEventView(
viewModel: viewModel,
eventName: $event.name,
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
)
.navigationTitle("Edit Event")
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button() {
saveEdits()
} label: {
Text("Done")
.bold()
}
.disabled(event.name == "")
}
}
}
}
#Preview {
EditEventView(
viewModel: dummyEventViewModel(),
event: .constant(dummyEventViewModel().template)
)
}

View File

@@ -0,0 +1,180 @@
//
// EventListView.swift
// MacNearFuture
//
// Created by neon443 on 21/05/2025.
//
import SwiftUI
struct EventListView: View {
@ObservedObject var viewModel: EventViewModel
@State var event: Event
@State var largeTick: Bool = false
@State var hovering: Bool = false
var body: some View {
ZStack {
Color.black.opacity(hovering ? 0.5 : 0.0)
HStack {
RoundedRectangle(cornerRadius: 5)
.frame(width: 7)
.foregroundStyle(
event.color.color.opacity(
event.complete ? 0.5 : 1
)
)
VStack(alignment: .leading) {
HStack {
Image(systemName: event.symbol)
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
.shadow(radius: 5)
.foregroundStyle(
.one.opacity(
event.complete ? 0.5 : 1
)
)
Text("\(event.name)")
.bold()
.foregroundStyle(.one)
.strikethrough(event.complete)
.multilineTextAlignment(.leading)
}
if !event.notes.isEmpty {
Text(event.notes)
.foregroundStyle(.one.opacity(0.8))
.multilineTextAlignment(.leading)
}
Text(
event.date.formatted(
date: .long,
time: .shortened
)
)
.foregroundStyle(
.one.opacity(
event.complete ? 0.5 : 1
)
)
if event.recurrence != .none {
Text("Occurs \(event.recurrence.rawValue)")
.font(.subheadline)
.foregroundStyle(
.one.opacity(event.complete ? 0.5 : 1))
}
}
Spacer()
VStack {
Text("\(daysUntilEvent(event.date).long)")
.multilineTextAlignment(.trailing)
.foregroundStyle(event.date.timeIntervalSinceNow < 0 ? .red : .one)
}
Button() {
withAnimation {
event.complete.toggle()
}
let eventToModify = viewModel.events.firstIndex() { currEvent in
currEvent.id == event.id
}
if let eventToModify = eventToModify {
viewModel.events[eventToModify] = event
viewModel.saveEvents()
}
} label: {
if event.complete {
ZStack {
Circle()
.foregroundStyle(.green)
Image(systemName: "checkmark")
.resizable()
.foregroundStyle(.white)
.scaledToFit()
.bold()
.frame(width: 15)
}
} else {
Image(systemName: "circle")
.resizable()
.scaledToFit()
.foregroundStyle(event.color.color)
}
}
.onHover() { hovering in
withAnimation {
largeTick.toggle()
}
}
.buttonStyle(.borderless)
.scaleEffect(largeTick ? 1.5 : 1)
.frame(maxWidth: 20)
.shadow(radius: 5)
.padding(.trailing, 15)
.animation(
.spring(response: 0.2, dampingFraction: 0.75, blendDuration: 2),
value: largeTick
)
.apply {
if #available(iOS 17, *) {
$0.sensoryFeedback(.success, trigger: event.complete)
}
}
}
.transition(.opacity)
.fixedSize(horizontal: false, vertical: true)
}
.onHover { isHovering in
withAnimation {
hovering.toggle()
}
}
.contextMenu() {
Button(role: .destructive) {
let eventToModify = viewModel.events.firstIndex() { currEvent in
currEvent.id == event.id
}
if let eventToModify = eventToModify {
viewModel.events.remove(at: eventToModify)
viewModel.saveEvents()
}
} label: {
Label("Delete", systemImage: "trash")
}
}
}
}
#Preview("EventListView") {
let vm = dummyEventViewModel()
ZStack {
Color.black
VStack {
ForEach(0..<50) { _ in
Rectangle()
.foregroundStyle(randomColor().opacity(0.5))
.padding(-10)
}
.ignoresSafeArea(.all)
.blur(radius: 5)
}
VStack {
ForEach(vm.events) { event in
EventListView(
viewModel: vm,
event: event
)
}
}
.padding(.horizontal, 10)
}
}
#Preview {
EventListView(
viewModel: dummyEventViewModel(),
event: dummyEventViewModel().template
)
}

View File

@@ -3,31 +3,56 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 70; objectVersion = 56;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
A90D49382DDE0FAF00781124 /* ContentViewMac.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90D49332DDE0FAF00781124 /* ContentViewMac.swift */; };
A90D493D2DDE10B200781124 /* NearFutureIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = A949F8312DCAAA8A0064DCA0 /* NearFutureIcon.png */; };
A90D493E2DDE10CF00781124 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A920C28D2D24011A00E4F9B1 /* Assets.xcassets */; };
A90D49422DDE114100781124 /* Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C28B2D24011400E4F9B1 /* Events.swift */; };
A90D49442DDE1C7600781124 /* 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 */; };
A90D494B2DDE2C2900781124 /* AddEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949F83C2DCAABE00064DCA0 /* AddEventView.swift */; };
A90D494F2DDE2C8500781124 /* EditEventViewMac.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90D494E2DDE2C8500781124 /* EditEventViewMac.swift */; };
A90D49522DDE2D0000781124 /* 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 */; };
A90D49582DDE2DBD00781124 /* EventListViewMac.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90D49572DDE2DBD00781124 /* EventListViewMac.swift */; };
A90D495B2DDE2EDB00781124 /* MacNearFutureApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90D495A2DDE2EDB00781124 /* MacNearFutureApp.swift */; };
A90D495E2DDE3C7400781124 /* NFCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90D495D2DDE3C7400781124 /* NFCommands.swift */; };
A90D495F2DDE3C7400781124 /* NFCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90D495D2DDE3C7400781124 /* NFCommands.swift */; };
A90D49612DDE626300781124 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90D49602DDE626300781124 /* Settings.swift */; };
A90D49622DDE626300781124 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90D49602DDE626300781124 /* Settings.swift */; };
A90D49632DDE626300781124 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90D49602DDE626300781124 /* Settings.swift */; };
A90D49672DDE6FAF00781124 /* YouAsked.swift in Sources */ = {isa = PBXBuildFile; fileRef = A90D49662DDE6FAF00781124 /* YouAsked.swift */; };
A914FA4B2DD26C6800856265 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A914FA4A2DD26C0F00856265 /* HomeView.swift */; };
A914FA4D2DD2768900856265 /* WhatsNewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A914FA4C2DD2768900856265 /* WhatsNewView.swift */; };
A914FA4F2DD276D200856265 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A914FA4E2DD276D200856265 /* AboutView.swift */; };
A920C2882D24011400E4F9B1 /* NearFutureApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C2872D24011400E4F9B1 /* NearFutureApp.swift */; }; A920C2882D24011400E4F9B1 /* NearFutureApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C2872D24011400E4F9B1 /* NearFutureApp.swift */; };
A920C28C2D24011400E4F9B1 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C28B2D24011400E4F9B1 /* Item.swift */; }; A920C28C2D24011400E4F9B1 /* Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C28B2D24011400E4F9B1 /* Events.swift */; };
A920C28E2D24011A00E4F9B1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A920C28D2D24011A00E4F9B1 /* Assets.xcassets */; }; A920C28E2D24011A00E4F9B1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A920C28D2D24011A00E4F9B1 /* Assets.xcassets */; };
A920C2922D24011A00E4F9B1 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A920C2912D24011A00E4F9B1 /* Preview Assets.xcassets */; }; A920C2922D24011A00E4F9B1 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A920C2912D24011A00E4F9B1 /* Preview Assets.xcassets */; };
A920C2B82D2401A300E4F9B1 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C2B42D2401A100E4F9B1 /* SettingsView.swift */; };
A920C2BB2D2401A400E4F9B1 /* AddEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C2B72D2401A300E4F9B1 /* AddEventView.swift */; };
A920C2BE2D24021A00E4F9B1 /* SFSymbolsPicker in Frameworks */ = {isa = PBXBuildFile; productRef = A920C2BD2D24021A00E4F9B1 /* SFSymbolsPicker */; }; A920C2BE2D24021A00E4F9B1 /* SFSymbolsPicker in Frameworks */ = {isa = PBXBuildFile; productRef = A920C2BD2D24021A00E4F9B1 /* SFSymbolsPicker */; };
A920C2C12D2403CA00E4F9B1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C2C02D2403CA00E4F9B1 /* ContentView.swift */; }; A949F8322DCAAA8A0064DCA0 /* NearFutureIcon.png in Resources */ = {isa = PBXBuildFile; fileRef = A949F8312DCAAA8A0064DCA0 /* NearFutureIcon.png */; };
A93BC0942D2B18A3002E8BBD /* StatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A93BC0932D2B18A3002E8BBD /* StatsView.swift */; }; A949F84B2DCAABE00064DCA0 /* ArchiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949F83A2DCAABE00064DCA0 /* ArchiveView.swift */; };
A977CC922DBBB48000DED8C0 /* ArchiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A977CC912DBBB48000DED8C0 /* ArchiveView.swift */; }; A949F84C2DCAABE00064DCA0 /* AddEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949F83C2DCAABE00064DCA0 /* AddEventView.swift */; };
A977CC9A2DBD74FE00DED8C0 /* HelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A977CC992DBD74FE00DED8C0 /* HelpView.swift */; }; A949F84D2DCAABE00064DCA0 /* EditEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949F83D2DCAABE00064DCA0 /* EditEventView.swift */; };
A979F57F2D26B1300094C0B3 /* EditEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A979F57E2D26B1300094C0B3 /* EditEventView.swift */; }; A949F84E2DCAABE00064DCA0 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949F83F2DCAABE00064DCA0 /* ContentView.swift */; };
A979F6052D270AF00094C0B3 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A979F6042D270AF00094C0B3 /* WidgetKit.framework */; }; A949F84F2DCAABE00064DCA0 /* EventListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949F8402DCAABE00064DCA0 /* EventListView.swift */; };
A979F6072D270AF00094C0B3 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A979F6062D270AF00094C0B3 /* SwiftUI.framework */; }; A949F8502DCAABE00064DCA0 /* HelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949F8412DCAABE00064DCA0 /* HelpView.swift */; };
A949F8512DCAABE00064DCA0 /* ExportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949F8432DCAABE00064DCA0 /* ExportView.swift */; };
A949F8522DCAABE00064DCA0 /* iCloudSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949F8442DCAABE00064DCA0 /* iCloudSettingsView.swift */; };
A949F8532DCAABE00064DCA0 /* ImportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949F8452DCAABE00064DCA0 /* ImportView.swift */; };
A949F8542DCAABE00064DCA0 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949F8462DCAABE00064DCA0 /* SettingsView.swift */; };
A949F8552DCAABE00064DCA0 /* StatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949F8482DCAABE00064DCA0 /* StatsView.swift */; };
A949F85F2DCABB420064DCA0 /* Buttons.swift in Sources */ = {isa = PBXBuildFile; fileRef = A949F85D2DCABB420064DCA0 /* Buttons.swift */; };
A979F60A2D270AF00094C0B3 /* NearFutureWidgetsBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = A979F6092D270AF00094C0B3 /* NearFutureWidgetsBundle.swift */; }; A979F60A2D270AF00094C0B3 /* NearFutureWidgetsBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = A979F6092D270AF00094C0B3 /* NearFutureWidgetsBundle.swift */; };
A979F60C2D270AF00094C0B3 /* NearFutureWidgetsLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = A979F60B2D270AF00094C0B3 /* NearFutureWidgetsLiveActivity.swift */; }; A979F60C2D270AF00094C0B3 /* NearFutureWidgetsLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = A979F60B2D270AF00094C0B3 /* NearFutureWidgetsLiveActivity.swift */; };
A979F6102D270AF90094C0B3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A979F60F2D270AF80094C0B3 /* Assets.xcassets */; }; A979F6102D270AF90094C0B3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A979F60F2D270AF80094C0B3 /* Assets.xcassets */; };
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 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C28B2D24011400E4F9B1 /* Item.swift */; }; A979F6182D2714310094C0B3 /* Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C28B2D24011400E4F9B1 /* Events.swift */; };
A985104E2DB256430013D5FF /* iCloudSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A985104D2DB256430013D5FF /* iCloudSettingsView.swift */; };
A98510502DB263F00013D5FF /* EventListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A985104F2DB263F00013D5FF /* EventListView.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 */
@@ -39,13 +64,6 @@
remoteGlobalIDString = A979F6012D270AF00094C0B3; remoteGlobalIDString = A979F6012D270AF00094C0B3;
remoteInfo = NearFutureWidgetsExtension; remoteInfo = NearFutureWidgetsExtension;
}; };
A980FC3B2D93FB2B006A778F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A920C27C2D24011300E4F9B1 /* Project object */;
proxyType = 1;
remoteGlobalIDString = A920C2832D24011300E4F9B1;
remoteInfo = NearFuture;
};
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */ /* Begin PBXCopyFilesBuildPhase section */
@@ -63,46 +81,60 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
A90D491F2DDE08E400781124 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
A90D49262DDE0FA400781124 /* Near Future.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Near Future.app"; sourceTree = BUILT_PRODUCTS_DIR; };
A90D49332DDE0FAF00781124 /* ContentViewMac.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentViewMac.swift; sourceTree = "<group>"; };
A90D49342DDE0FAF00781124 /* MacNearFuture.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MacNearFuture.entitlements; sourceTree = "<group>"; };
A90D49432DDE1C1100781124 /* Tints.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Tints.xcassets; sourceTree = "<group>"; };
A90D494E2DDE2C8500781124 /* EditEventViewMac.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = EditEventViewMac.swift; path = MacNearFuture/Views/EditEventViewMac.swift; sourceTree = SOURCE_ROOT; };
A90D49512DDE2D0000781124 /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
A90D49572DDE2DBD00781124 /* EventListViewMac.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventListViewMac.swift; sourceTree = "<group>"; };
A90D495A2DDE2EDB00781124 /* MacNearFutureApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MacNearFutureApp.swift; path = MacNearFuture/MacNearFutureApp.swift; sourceTree = SOURCE_ROOT; };
A90D495D2DDE3C7400781124 /* NFCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NFCommands.swift; sourceTree = "<group>"; };
A90D49602DDE626300781124 /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
A90D49652DDE658100781124 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A90D49662DDE6FAF00781124 /* YouAsked.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YouAsked.swift; sourceTree = "<group>"; };
A90FDE222DC0D4310012790C /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; }; A90FDE222DC0D4310012790C /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
A914FA4A2DD26C0F00856265 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = "<group>"; };
A914FA4C2DD2768900856265 /* WhatsNewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WhatsNewView.swift; path = NearFuture/Views/Settings/WhatsNewView.swift; sourceTree = SOURCE_ROOT; };
A914FA4E2DD276D200856265 /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AboutView.swift; path = NearFuture/Views/Misc/AboutView.swift; sourceTree = SOURCE_ROOT; };
A920C2842D24011400E4F9B1 /* NearFuture.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NearFuture.app; sourceTree = BUILT_PRODUCTS_DIR; }; A920C2842D24011400E4F9B1 /* NearFuture.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NearFuture.app; sourceTree = BUILT_PRODUCTS_DIR; };
A920C2872D24011400E4F9B1 /* NearFutureApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureApp.swift; sourceTree = "<group>"; }; A920C2872D24011400E4F9B1 /* NearFutureApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureApp.swift; sourceTree = "<group>"; };
A920C28B2D24011400E4F9B1 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = "<group>"; }; A920C28B2D24011400E4F9B1 /* Events.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Events.swift; sourceTree = "<group>"; };
A920C28D2D24011A00E4F9B1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; A920C28D2D24011A00E4F9B1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
A920C28F2D24011A00E4F9B1 /* NearFuture.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NearFuture.entitlements; sourceTree = "<group>"; };
A920C2912D24011A00E4F9B1 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; }; A920C2912D24011A00E4F9B1 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
A920C2B42D2401A100E4F9B1 /* SettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; }; A949F82E2DCAAA640064DCA0 /* NearFutureIcon.pxd */ = {isa = PBXFileReference; lastKnownFileType = file; path = NearFutureIcon.pxd; sourceTree = "<group>"; };
A920C2B72D2401A300E4F9B1 /* AddEventView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddEventView.swift; sourceTree = "<group>"; }; A949F82F2DCAAA640064DCA0 /* NearFutureIconDark.pxd */ = {isa = PBXFileReference; lastKnownFileType = file; path = NearFutureIconDark.pxd; sourceTree = "<group>"; };
A920C2C02D2403CA00E4F9B1 /* ContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; }; A949F8302DCAAA640064DCA0 /* NearFutureIconTint.pxd */ = {isa = PBXFileReference; lastKnownFileType = file; path = NearFutureIconTint.pxd; sourceTree = "<group>"; };
A93BC0932D2B18A3002E8BBD /* StatsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsView.swift; sourceTree = "<group>"; }; A949F8312DCAAA8A0064DCA0 /* NearFutureIcon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = NearFutureIcon.png; path = Assets.xcassets/AppIcon.appiconset/NearFutureIcon.png; sourceTree = "<group>"; };
A977CC912DBBB48000DED8C0 /* ArchiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArchiveView.swift; sourceTree = "<group>"; }; A949F83A2DCAABE00064DCA0 /* ArchiveView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArchiveView.swift; sourceTree = "<group>"; };
A977CC992DBD74FE00DED8C0 /* HelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpView.swift; sourceTree = "<group>"; }; A949F83C2DCAABE00064DCA0 /* AddEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddEventView.swift; sourceTree = "<group>"; };
A979F57E2D26B1300094C0B3 /* EditEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditEventView.swift; sourceTree = "<group>"; }; A949F83D2DCAABE00064DCA0 /* 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>"; }; A949F83F2DCAABE00064DCA0 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
A979F58D2D2700680094C0B3 /* NearFutureWidgetsLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureWidgetsLiveActivity.swift; sourceTree = "<group>"; }; A949F8402DCAABE00064DCA0 /* EventListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventListView.swift; sourceTree = "<group>"; };
A979F58F2D2700680094C0B3 /* NearFutureWidgets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureWidgets.swift; sourceTree = "<group>"; }; A949F8412DCAABE00064DCA0 /* HelpView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpView.swift; sourceTree = "<group>"; };
A979F5912D2700680094C0B3 /* AppIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIntent.swift; sourceTree = "<group>"; }; A949F8432DCAABE00064DCA0 /* ExportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExportView.swift; sourceTree = "<group>"; };
A979F5932D27006D0094C0B3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; A949F8442DCAABE00064DCA0 /* iCloudSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iCloudSettingsView.swift; sourceTree = "<group>"; };
A979F5952D27006D0094C0B3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; A949F8452DCAABE00064DCA0 /* ImportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportView.swift; sourceTree = "<group>"; };
A949F8462DCAABE00064DCA0 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
A949F8482DCAABE00064DCA0 /* StatsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsView.swift; sourceTree = "<group>"; };
A949F85D2DCABB420064DCA0 /* Buttons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Buttons.swift; sourceTree = "<group>"; };
A979F6022D270AF00094C0B3 /* NearFutureWidgetsExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NearFutureWidgetsExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; A979F6022D270AF00094C0B3 /* NearFutureWidgetsExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NearFutureWidgetsExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
A979F6042D270AF00094C0B3 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
A979F6062D270AF00094C0B3 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
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>"; };
A979F6112D270AF90094C0B3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A980FC302D920097006A778F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A980FC372D93FB2B006A778F /* NearFutureTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NearFutureTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
A985104D2DB256430013D5FF /* iCloudSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iCloudSettingsView.swift; sourceTree = "<group>"; };
A985104F2DB263F00013D5FF /* EventListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventListView.swift; sourceTree = "<group>"; };
A9C05E412D2805D7007DC497 /* NearFutureWidgetsExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NearFutureWidgetsExtension.entitlements; 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 */
/* Begin PBXFileSystemSynchronizedRootGroup section */
A980FC382D93FB2B006A778F /* NearFutureTests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = NearFutureTests; sourceTree = "<group>"; };
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
A90D49232DDE0FA400781124 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A90D49562DDE2D5800781124 /* SFSymbolsPicker in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A920C2812D24011300E4F9B1 /* Frameworks */ = { A920C2812D24011300E4F9B1 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@@ -112,15 +144,6 @@
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
A979F5FF2D270AF00094C0B3 /* Frameworks */ = { A979F5FF2D270AF00094C0B3 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A979F6072D270AF00094C0B3 /* SwiftUI.framework in Frameworks */,
A979F6052D270AF00094C0B3 /* WidgetKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A980FC342D93FB2B006A778F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
@@ -130,14 +153,64 @@
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
A90D49202DDE0A3B00781124 /* Model */ = {
isa = PBXGroup;
children = (
A920C28B2D24011400E4F9B1 /* Events.swift */,
A90D49602DDE626300781124 /* Settings.swift */,
);
path = Model;
sourceTree = "<group>";
};
A90D49362DDE0FAF00781124 /* MacNearFuture */ = {
isa = PBXGroup;
children = (
A90D495A2DDE2EDB00781124 /* MacNearFutureApp.swift */,
A90D495D2DDE3C7400781124 /* NFCommands.swift */,
A90D493F2DDE10EC00781124 /* Views */,
A90D49342DDE0FAF00781124 /* MacNearFuture.entitlements */,
);
path = MacNearFuture;
sourceTree = "<group>";
};
A90D493F2DDE10EC00781124 /* Views */ = {
isa = PBXGroup;
children = (
A90D49332DDE0FAF00781124 /* ContentViewMac.swift */,
A90D49572DDE2DBD00781124 /* EventListViewMac.swift */,
A90D494E2DDE2C8500781124 /* EditEventViewMac.swift */,
);
path = Views;
sourceTree = "<group>";
};
A90D49412DDE112700781124 /* Shared */ = {
isa = PBXGroup;
children = (
A920C2872D24011400E4F9B1 /* NearFutureApp.swift */,
A90D49512DDE2D0000781124 /* Extensions.swift */,
A90D49202DDE0A3B00781124 /* Model */,
);
path = Shared;
sourceTree = "<group>";
};
A90D49542DDE2D5800781124 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
A920C27B2D24011300E4F9B1 = { A920C27B2D24011300E4F9B1 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A90D491F2DDE08E400781124 /* README.md */,
A90FDE222DC0D4310012790C /* Config.xcconfig */, A90FDE222DC0D4310012790C /* Config.xcconfig */,
A90D49412DDE112700781124 /* Shared */,
A920C2862D24011400E4F9B1 /* NearFuture */, A920C2862D24011400E4F9B1 /* NearFuture */,
A90D49362DDE0FAF00781124 /* MacNearFuture */,
A949F8002DCAA0340064DCA0 /* Resources */,
A979F6082D270AF00094C0B3 /* NearFutureWidgets */, A979F6082D270AF00094C0B3 /* NearFutureWidgets */,
A980FC382D93FB2B006A778F /* NearFutureTests */, A90D49542DDE2D5800781124 /* Frameworks */,
A979F6032D270AF00094C0B3 /* Frameworks */,
A920C2852D24011400E4F9B1 /* Products */, A920C2852D24011400E4F9B1 /* Products */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
@@ -147,7 +220,7 @@
children = ( children = (
A920C2842D24011400E4F9B1 /* NearFuture.app */, A920C2842D24011400E4F9B1 /* NearFuture.app */,
A979F6022D270AF00094C0B3 /* NearFutureWidgetsExtension.appex */, A979F6022D270AF00094C0B3 /* NearFutureWidgetsExtension.appex */,
A980FC372D93FB2B006A778F /* NearFutureTests.xctest */, A90D49262DDE0FA400781124 /* Near Future.app */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -155,20 +228,7 @@
A920C2862D24011400E4F9B1 /* NearFuture */ = { A920C2862D24011400E4F9B1 /* NearFuture */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A920C2872D24011400E4F9B1 /* NearFutureApp.swift */, A949F84A2DCAABE00064DCA0 /* Views */,
A920C28B2D24011400E4F9B1 /* Item.swift */,
A920C2C02D2403CA00E4F9B1 /* ContentView.swift */,
A985104F2DB263F00013D5FF /* EventListView.swift */,
A920C2B72D2401A300E4F9B1 /* AddEventView.swift */,
A979F57E2D26B1300094C0B3 /* EditEventView.swift */,
A977CC912DBBB48000DED8C0 /* ArchiveView.swift */,
A93BC0932D2B18A3002E8BBD /* StatsView.swift */,
A977CC992DBD74FE00DED8C0 /* HelpView.swift */,
A920C2B42D2401A100E4F9B1 /* SettingsView.swift */,
A985104D2DB256430013D5FF /* iCloudSettingsView.swift */,
A980FC302D920097006A778F /* Info.plist */,
A920C28D2D24011A00E4F9B1 /* Assets.xcassets */,
A920C28F2D24011A00E4F9B1 /* NearFuture.entitlements */,
A920C2902D24011A00E4F9B1 /* Preview Content */, A920C2902D24011A00E4F9B1 /* Preview Content */,
); );
path = NearFuture; path = NearFuture;
@@ -177,32 +237,93 @@
A920C2902D24011A00E4F9B1 /* Preview Content */ = { A920C2902D24011A00E4F9B1 /* Preview Content */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A979F58A2D2700680094C0B3 /* NearFutureWidgets */,
A920C2912D24011A00E4F9B1 /* Preview Assets.xcassets */, A920C2912D24011A00E4F9B1 /* Preview Assets.xcassets */,
); );
path = "Preview Content"; path = "Preview Content";
sourceTree = "<group>"; sourceTree = "<group>";
}; };
A979F58A2D2700680094C0B3 /* NearFutureWidgets */ = { A949F8002DCAA0340064DCA0 /* Resources */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A979F58B2D2700680094C0B3 /* NearFutureWidgetsBundle.swift */, A949F8312DCAAA8A0064DCA0 /* NearFutureIcon.png */,
A979F58D2D2700680094C0B3 /* NearFutureWidgetsLiveActivity.swift */, A920C28D2D24011A00E4F9B1 /* Assets.xcassets */,
A979F58F2D2700680094C0B3 /* NearFutureWidgets.swift */, A90D49432DDE1C1100781124 /* Tints.xcassets */,
A979F5912D2700680094C0B3 /* AppIntent.swift */, A949F82E2DCAAA640064DCA0 /* NearFutureIcon.pxd */,
A979F5932D27006D0094C0B3 /* Assets.xcassets */, A949F82F2DCAAA640064DCA0 /* NearFutureIconDark.pxd */,
A979F5952D27006D0094C0B3 /* Info.plist */, A949F8302DCAAA640064DCA0 /* NearFutureIconTint.pxd */,
); );
path = NearFutureWidgets; path = Resources;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
A979F6032D270AF00094C0B3 /* Frameworks */ = { A949F83B2DCAABE00064DCA0 /* Archive */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A979F6042D270AF00094C0B3 /* WidgetKit.framework */, A949F83A2DCAABE00064DCA0 /* ArchiveView.swift */,
A979F6062D270AF00094C0B3 /* SwiftUI.framework */,
); );
name = Frameworks; path = Archive;
sourceTree = "<group>";
};
A949F83E2DCAABE00064DCA0 /* Events */ = {
isa = PBXGroup;
children = (
A949F83C2DCAABE00064DCA0 /* AddEventView.swift */,
A949F83D2DCAABE00064DCA0 /* EditEventView.swift */,
);
path = Events;
sourceTree = "<group>";
};
A949F8422DCAABE00064DCA0 /* Home */ = {
isa = PBXGroup;
children = (
A914FA4A2DD26C0F00856265 /* HomeView.swift */,
A949F8402DCAABE00064DCA0 /* EventListView.swift */,
A949F8412DCAABE00064DCA0 /* HelpView.swift */,
);
path = Home;
sourceTree = "<group>";
};
A949F8472DCAABE00064DCA0 /* Settings */ = {
isa = PBXGroup;
children = (
A949F8462DCAABE00064DCA0 /* SettingsView.swift */,
A949F8442DCAABE00064DCA0 /* iCloudSettingsView.swift */,
A914FA4C2DD2768900856265 /* WhatsNewView.swift */,
A949F8452DCAABE00064DCA0 /* ImportView.swift */,
A949F8432DCAABE00064DCA0 /* ExportView.swift */,
);
path = Settings;
sourceTree = "<group>";
};
A949F8492DCAABE00064DCA0 /* Stats */ = {
isa = PBXGroup;
children = (
A949F8482DCAABE00064DCA0 /* StatsView.swift */,
);
path = Stats;
sourceTree = "<group>";
};
A949F84A2DCAABE00064DCA0 /* Views */ = {
isa = PBXGroup;
children = (
A949F83F2DCAABE00064DCA0 /* ContentView.swift */,
A90D49662DDE6FAF00781124 /* YouAsked.swift */,
A949F8422DCAABE00064DCA0 /* Home */,
A949F83E2DCAABE00064DCA0 /* Events */,
A949F83B2DCAABE00064DCA0 /* Archive */,
A949F85E2DCABB420064DCA0 /* Misc */,
A949F8492DCAABE00064DCA0 /* Stats */,
A949F8472DCAABE00064DCA0 /* Settings */,
);
path = Views;
sourceTree = "<group>";
};
A949F85E2DCABB420064DCA0 /* Misc */ = {
isa = PBXGroup;
children = (
A949F85D2DCABB420064DCA0 /* Buttons.swift */,
A914FA4E2DD276D200856265 /* AboutView.swift */,
);
path = Misc;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
A979F6082D270AF00094C0B3 /* NearFutureWidgets */ = { A979F6082D270AF00094C0B3 /* NearFutureWidgets */ = {
@@ -212,8 +333,7 @@
A979F6092D270AF00094C0B3 /* NearFutureWidgetsBundle.swift */, A979F6092D270AF00094C0B3 /* NearFutureWidgetsBundle.swift */,
A979F60B2D270AF00094C0B3 /* NearFutureWidgetsLiveActivity.swift */, A979F60B2D270AF00094C0B3 /* NearFutureWidgetsLiveActivity.swift */,
A979F60F2D270AF80094C0B3 /* Assets.xcassets */, A979F60F2D270AF80094C0B3 /* Assets.xcassets */,
A979F6112D270AF90094C0B3 /* Info.plist */, A90D49652DDE658100781124 /* Info.plist */,
A9C05E412D2805D7007DC497 /* NearFutureWidgetsExtension.entitlements */,
); );
path = NearFutureWidgets; path = NearFutureWidgets;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -221,6 +341,27 @@
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
A90D49252DDE0FA400781124 /* MacNearFuture */ = {
isa = PBXNativeTarget;
buildConfigurationList = A90D492F2DDE0FA600781124 /* Build configuration list for PBXNativeTarget "MacNearFuture" */;
buildPhases = (
A90D49222DDE0FA400781124 /* Sources */,
A90D49232DDE0FA400781124 /* Frameworks */,
A90D49242DDE0FA400781124 /* Resources */,
);
buildRules = (
);
dependencies = (
A90D494D2DDE2C6000781124 /* PBXTargetDependency */,
);
name = MacNearFuture;
packageProductDependencies = (
A90D49552DDE2D5800781124 /* SFSymbolsPicker */,
);
productName = MacNearFuture;
productReference = A90D49262DDE0FA400781124 /* Near Future.app */;
productType = "com.apple.product-type.application";
};
A920C2832D24011300E4F9B1 /* NearFuture */ = { A920C2832D24011300E4F9B1 /* NearFuture */ = {
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = A920C2AB2D24011B00E4F9B1 /* Build configuration list for PBXNativeTarget "NearFuture" */; buildConfigurationList = A920C2AB2D24011B00E4F9B1 /* Build configuration list for PBXNativeTarget "NearFuture" */;
@@ -260,29 +401,6 @@
productReference = A979F6022D270AF00094C0B3 /* NearFutureWidgetsExtension.appex */; productReference = A979F6022D270AF00094C0B3 /* NearFutureWidgetsExtension.appex */;
productType = "com.apple.product-type.app-extension"; productType = "com.apple.product-type.app-extension";
}; };
A980FC362D93FB2B006A778F /* NearFutureTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = A980FC3D2D93FB2B006A778F /* Build configuration list for PBXNativeTarget "NearFutureTests" */;
buildPhases = (
A980FC332D93FB2B006A778F /* Sources */,
A980FC342D93FB2B006A778F /* Frameworks */,
A980FC352D93FB2B006A778F /* Resources */,
);
buildRules = (
);
dependencies = (
A980FC3C2D93FB2B006A778F /* PBXTargetDependency */,
);
fileSystemSynchronizedGroups = (
A980FC382D93FB2B006A778F /* NearFutureTests */,
);
name = NearFutureTests;
packageProductDependencies = (
);
productName = NearFutureTests;
productReference = A980FC372D93FB2B006A778F /* NearFutureTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */ /* End PBXNativeTarget section */
/* Begin PBXProject section */ /* Begin PBXProject section */
@@ -290,19 +408,18 @@
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
BuildIndependentTargetsInParallel = 1; BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1620; LastSwiftUpdateCheck = 1640;
LastUpgradeCheck = 1630; LastUpgradeCheck = 1630;
TargetAttributes = { TargetAttributes = {
A90D49252DDE0FA400781124 = {
CreatedOnToolsVersion = 16.4;
};
A920C2832D24011300E4F9B1 = { A920C2832D24011300E4F9B1 = {
CreatedOnToolsVersion = 15.4; CreatedOnToolsVersion = 15.4;
}; };
A979F6012D270AF00094C0B3 = { A979F6012D270AF00094C0B3 = {
CreatedOnToolsVersion = 15.4; CreatedOnToolsVersion = 15.4;
}; };
A980FC362D93FB2B006A778F = {
CreatedOnToolsVersion = 16.2;
TestTargetID = A920C2832D24011300E4F9B1;
};
}; };
}; };
buildConfigurationList = A920C27F2D24011300E4F9B1 /* Build configuration list for PBXProject "NearFuture" */; buildConfigurationList = A920C27F2D24011300E4F9B1 /* Build configuration list for PBXProject "NearFuture" */;
@@ -322,18 +439,30 @@
projectRoot = ""; projectRoot = "";
targets = ( targets = (
A920C2832D24011300E4F9B1 /* NearFuture */, A920C2832D24011300E4F9B1 /* NearFuture */,
A90D49252DDE0FA400781124 /* MacNearFuture */,
A979F6012D270AF00094C0B3 /* NearFutureWidgetsExtension */, A979F6012D270AF00094C0B3 /* NearFutureWidgetsExtension */,
A980FC362D93FB2B006A778F /* NearFutureTests */,
); );
}; };
/* End PBXProject section */ /* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */ /* Begin PBXResourcesBuildPhase section */
A90D49242DDE0FA400781124 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A90D49452DDE1C7600781124 /* Tints.xcassets in Resources */,
A90D493E2DDE10CF00781124 /* Assets.xcassets in Resources */,
A90D493D2DDE10B200781124 /* NearFutureIcon.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A920C2822D24011300E4F9B1 /* Resources */ = { A920C2822D24011300E4F9B1 /* Resources */ = {
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
A90D49442DDE1C7600781124 /* Tints.xcassets in Resources */,
A920C2922D24011A00E4F9B1 /* Preview Assets.xcassets in Resources */, A920C2922D24011A00E4F9B1 /* Preview Assets.xcassets in Resources */,
A949F8322DCAAA8A0064DCA0 /* NearFutureIcon.png in Resources */,
A920C28E2D24011A00E4F9B1 /* Assets.xcassets in Resources */, A920C28E2D24011A00E4F9B1 /* Assets.xcassets in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@@ -342,35 +471,55 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
A90D49462DDE1C7A00781124 /* Tints.xcassets in Resources */,
A979F6102D270AF90094C0B3 /* Assets.xcassets in Resources */, A979F6102D270AF90094C0B3 /* Assets.xcassets in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
A980FC352D93FB2B006A778F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */
A90D49222DDE0FA400781124 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A90D494B2DDE2C2900781124 /* AddEventView.swift in Sources */,
A90D495E2DDE3C7400781124 /* NFCommands.swift in Sources */,
A90D495B2DDE2EDB00781124 /* MacNearFutureApp.swift in Sources */,
A90D49522DDE2D0000781124 /* Extensions.swift in Sources */,
A90D49422DDE114100781124 /* Events.swift in Sources */,
A90D49382DDE0FAF00781124 /* ContentViewMac.swift in Sources */,
A90D49622DDE626300781124 /* Settings.swift in Sources */,
A90D494F2DDE2C8500781124 /* EditEventViewMac.swift in Sources */,
A90D49582DDE2DBD00781124 /* EventListViewMac.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A920C2802D24011300E4F9B1 /* Sources */ = { A920C2802D24011300E4F9B1 /* Sources */ = {
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
A920C2BB2D2401A400E4F9B1 /* AddEventView.swift in Sources */, A920C28C2D24011400E4F9B1 /* Events.swift in Sources */,
A98510502DB263F00013D5FF /* EventListView.swift in Sources */, A949F84B2DCAABE00064DCA0 /* ArchiveView.swift in Sources */,
A920C2C12D2403CA00E4F9B1 /* ContentView.swift in Sources */, A914FA4F2DD276D200856265 /* AboutView.swift in Sources */,
A920C2B82D2401A300E4F9B1 /* SettingsView.swift in Sources */, A949F84C2DCAABE00064DCA0 /* AddEventView.swift in Sources */,
A977CC9A2DBD74FE00DED8C0 /* HelpView.swift in Sources */, A914FA4B2DD26C6800856265 /* HomeView.swift in Sources */,
A920C28C2D24011400E4F9B1 /* Item.swift in Sources */, A949F84D2DCAABE00064DCA0 /* EditEventView.swift in Sources */,
A949F84E2DCAABE00064DCA0 /* ContentView.swift in Sources */,
A90D49612DDE626300781124 /* Settings.swift in Sources */,
A90D495F2DDE3C7400781124 /* NFCommands.swift in Sources */,
A949F84F2DCAABE00064DCA0 /* EventListView.swift in Sources */,
A949F8502DCAABE00064DCA0 /* HelpView.swift in Sources */,
A949F85F2DCABB420064DCA0 /* Buttons.swift in Sources */,
A914FA4D2DD2768900856265 /* WhatsNewView.swift in Sources */,
A949F8512DCAABE00064DCA0 /* ExportView.swift in Sources */,
A90D49532DDE2D0000781124 /* Extensions.swift in Sources */,
A949F8522DCAABE00064DCA0 /* iCloudSettingsView.swift in Sources */,
A90D49672DDE6FAF00781124 /* YouAsked.swift in Sources */,
A949F8532DCAABE00064DCA0 /* ImportView.swift in Sources */,
A949F8542DCAABE00064DCA0 /* SettingsView.swift in Sources */,
A949F8552DCAABE00064DCA0 /* StatsView.swift in Sources */,
A920C2882D24011400E4F9B1 /* NearFutureApp.swift in Sources */, A920C2882D24011400E4F9B1 /* NearFutureApp.swift in Sources */,
A93BC0942D2B18A3002E8BBD /* StatsView.swift in Sources */,
A977CC922DBBB48000DED8C0 /* ArchiveView.swift in Sources */,
A979F57F2D26B1300094C0B3 /* EditEventView.swift in Sources */,
A985104E2DB256430013D5FF /* iCloudSettingsView.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -378,42 +527,100 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
A979F6182D2714310094C0B3 /* Item.swift in Sources */, A979F6182D2714310094C0B3 /* Events.swift in Sources */,
A979F60A2D270AF00094C0B3 /* NearFutureWidgetsBundle.swift in Sources */, A979F60A2D270AF00094C0B3 /* NearFutureWidgetsBundle.swift in Sources */,
A9FC7EEA2D2823920020D75B /* NearFutureWidgets.swift in Sources */, A9FC7EEA2D2823920020D75B /* NearFutureWidgets.swift in Sources */,
A979F60C2D270AF00094C0B3 /* NearFutureWidgetsLiveActivity.swift in Sources */, A979F60C2D270AF00094C0B3 /* NearFutureWidgetsLiveActivity.swift in Sources */,
); A90D49632DDE626300781124 /* Settings.swift in Sources */,
runOnlyForDeploymentPostprocessing = 0;
};
A980FC332D93FB2B006A778F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
/* End PBXSourcesBuildPhase section */ /* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */ /* Begin PBXTargetDependency section */
A90D494D2DDE2C6000781124 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
productRef = A90D494C2DDE2C6000781124 /* SFSymbolsPicker */;
};
A979F6132D270AF90094C0B3 /* PBXTargetDependency */ = { A979F6132D270AF90094C0B3 /* PBXTargetDependency */ = {
isa = PBXTargetDependency; isa = PBXTargetDependency;
platformFilter = ios; platformFilter = ios;
target = A979F6012D270AF00094C0B3 /* NearFutureWidgetsExtension */; target = A979F6012D270AF00094C0B3 /* NearFutureWidgetsExtension */;
targetProxy = A979F6122D270AF90094C0B3 /* PBXContainerItemProxy */; targetProxy = A979F6122D270AF90094C0B3 /* PBXContainerItemProxy */;
}; };
A980FC3C2D93FB2B006A778F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = A920C2832D24011300E4F9B1 /* NearFuture */;
targetProxy = A980FC3B2D93FB2B006A778F /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */ /* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
A90D49302DDE0FA600781124 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = A90FDE222DC0D4310012790C /* Config.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "bloo blue green pink purple red yellow";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = MacNearFuture/MacNearFuture.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = "$(BUILD_NUMBER)";
DEVELOPMENT_TEAM = 8JGND254B7;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 15.5;
MARKETING_VERSION = "$(VERSION)";
PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFuture;
PRODUCT_NAME = "Near Future";
REGISTER_APP_GROUPS = YES;
SDKROOT = macosx;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
A90D49312DDE0FA600781124 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = A90FDE222DC0D4310012790C /* Config.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "bloo blue green pink purple red yellow";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = MacNearFuture/MacNearFuture.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = "$(BUILD_NUMBER)";
DEVELOPMENT_TEAM = 8JGND254B7;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 15.5;
MARKETING_VERSION = "$(VERSION)";
PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFuture;
PRODUCT_NAME = "Near Future";
REGISTER_APP_GROUPS = YES;
SDKROOT = macosx;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
};
name = Release;
};
A920C2A92D24011B00E4F9B1 /* Debug */ = { A920C2A92D24011B00E4F9B1 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "Bloo Blue Green Pink Purple Red Yellow";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
@@ -473,7 +680,7 @@
); );
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 6.0; SWIFT_VERSION = 5.0;
}; };
name = Debug; name = Debug;
}; };
@@ -481,7 +688,10 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "Bloo Blue Green Pink Purple Red Yellow";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
@@ -529,7 +739,7 @@
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
SWIFT_COMPILATION_MODE = wholemodule; SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_VERSION = 6.0; SWIFT_VERSION = 5.0;
}; };
name = Release; name = Release;
}; };
@@ -537,8 +747,10 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = A90FDE222DC0D4310012790C /* Config.xcconfig */; baseConfigurationReference = A90FDE222DC0D4310012790C /* Config.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "bloo blue green pink purple red yellow";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_USE_OPTIMIZATION_PROFILE = YES;
CODE_SIGN_ENTITLEMENTS = NearFuture/NearFuture.entitlements; CODE_SIGN_ENTITLEMENTS = NearFuture/NearFuture.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(BUILD_NUMBER)";
@@ -548,8 +760,7 @@
ENABLE_HARDENED_RUNTIME = NO; ENABLE_HARDENED_RUNTIME = NO;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = NearFuture/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Near Future";
INFOPLIST_KEY_CFBundleDisplayName = "$(NAME)";
INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO; INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
@@ -561,7 +772,7 @@
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 16.4; IPHONEOS_DEPLOYMENT_TARGET = 16;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 13; MACOSX_DEPLOYMENT_TARGET = 13;
@@ -572,11 +783,11 @@
); );
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID)"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = NO; REGISTER_APP_GROUPS = YES;
SDKROOT = auto; SDKROOT = auto;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO; SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@@ -588,8 +799,10 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = A90FDE222DC0D4310012790C /* Config.xcconfig */; baseConfigurationReference = A90FDE222DC0D4310012790C /* Config.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_ALTERNATE_APPICON_NAMES = "bloo blue green pink purple red yellow";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_USE_OPTIMIZATION_PROFILE = YES;
CODE_SIGN_ENTITLEMENTS = NearFuture/NearFuture.entitlements; CODE_SIGN_ENTITLEMENTS = NearFuture/NearFuture.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(BUILD_NUMBER)";
@@ -599,8 +812,7 @@
ENABLE_HARDENED_RUNTIME = NO; ENABLE_HARDENED_RUNTIME = NO;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = NearFuture/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Near Future";
INFOPLIST_KEY_CFBundleDisplayName = "$(NAME)";
INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO; INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
@@ -612,7 +824,7 @@
"INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 16.4; IPHONEOS_DEPLOYMENT_TARGET = 16;
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 13; MACOSX_DEPLOYMENT_TARGET = 13;
@@ -620,11 +832,11 @@
OTHER_LDFLAGS = ""; OTHER_LDFLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID)"; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = NO; REGISTER_APP_GROUPS = YES;
SDKROOT = auto; SDKROOT = auto;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO; SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@@ -638,11 +850,13 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CLANG_USE_OPTIMIZATION_PROFILE = YES;
CODE_SIGN_ENTITLEMENTS = NearFutureWidgets/NearFutureWidgetsExtension.entitlements; CODE_SIGN_ENTITLEMENTS = NearFutureWidgets/NearFutureWidgetsExtension.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = "$(BUILD_NUMBER)";
DEVELOPMENT_TEAM = "$(TEAM_ID)";
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = NearFutureWidgets/Info.plist; INFOPLIST_FILE = "$(SRCROOT)/NearFutureWidgets/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = NearFutureWidgets; INFOPLIST_KEY_CFBundleDisplayName = NearFutureWidgets;
INFOPLIST_KEY_NSHumanReadableCopyright = ""; INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 17; IPHONEOS_DEPLOYMENT_TARGET = 17;
@@ -651,20 +865,23 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 3.0; MACOSX_DEPLOYMENT_TARGET = 14;
MARKETING_VERSION = "$(VERSION)";
OTHER_LDFLAGS = ( OTHER_LDFLAGS = (
"-Xlinker", "-Xlinker",
"-interposable", "-interposable",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFuture.widgets; PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_WIDGETS)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO; SUPPORTS_MACCATALYST = YES;
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
VERSION = "$(VERSION)";
}; };
name = Debug; name = Debug;
}; };
@@ -674,11 +891,13 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CLANG_USE_OPTIMIZATION_PROFILE = YES;
CODE_SIGN_ENTITLEMENTS = NearFutureWidgets/NearFutureWidgetsExtension.entitlements; CODE_SIGN_ENTITLEMENTS = NearFutureWidgets/NearFutureWidgetsExtension.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = "$(BUILD_NUMBER)";
DEVELOPMENT_TEAM = "$(TEAM_ID)";
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = NearFutureWidgets/Info.plist; INFOPLIST_FILE = "$(SRCROOT)/NearFutureWidgets/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = NearFutureWidgets; INFOPLIST_KEY_CFBundleDisplayName = NearFutureWidgets;
INFOPLIST_KEY_NSHumanReadableCopyright = ""; INFOPLIST_KEY_NSHumanReadableCopyright = "";
IPHONEOS_DEPLOYMENT_TARGET = 17; IPHONEOS_DEPLOYMENT_TARGET = 17;
@@ -687,75 +906,35 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
"@executable_path/../../Frameworks", "@executable_path/../../Frameworks",
); );
MARKETING_VERSION = 3.0; MACOSX_DEPLOYMENT_TARGET = 14;
PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFuture.widgets; MARKETING_VERSION = "$(VERSION)";
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID_WIDGETS)";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SKIP_INSTALL = YES; SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO; SUPPORTS_MACCATALYST = YES;
SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; VERSION = "$(VERSION)";
name = Release;
};
A980FC3E2D93FB2B006A778F /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = A90FDE222DC0D4310012790C /* Config.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16;
MACOSX_DEPLOYMENT_TARGET = 13;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.neon443.NearFutureTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = auto;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NearFuture.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/NearFuture";
XROS_DEPLOYMENT_TARGET = 1;
};
name = Debug;
};
A980FC3F2D93FB2B006A778F /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = A90FDE222DC0D4310012790C /* Config.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16;
MACOSX_DEPLOYMENT_TARGET = 13;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.neon443.NearFutureTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = auto;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NearFuture.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/NearFuture";
XROS_DEPLOYMENT_TARGET = 1;
}; };
name = Release; name = Release;
}; };
/* End XCBuildConfiguration section */ /* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */ /* Begin XCConfigurationList section */
A90D492F2DDE0FA600781124 /* Build configuration list for PBXNativeTarget "MacNearFuture" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A90D49302DDE0FA600781124 /* Debug */,
A90D49312DDE0FA600781124 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A920C27F2D24011300E4F9B1 /* Build configuration list for PBXProject "NearFuture" */ = { A920C27F2D24011300E4F9B1 /* Build configuration list for PBXProject "NearFuture" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
buildConfigurations = ( buildConfigurations = (
@@ -783,15 +962,6 @@
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
A980FC3D2D93FB2B006A778F /* Build configuration list for PBXNativeTarget "NearFutureTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A980FC3E2D93FB2B006A778F /* Debug */,
A980FC3F2D93FB2B006A778F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */ /* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */ /* Begin XCRemoteSwiftPackageReference section */
@@ -806,6 +976,16 @@
/* End XCRemoteSwiftPackageReference section */ /* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */ /* Begin XCSwiftPackageProductDependency section */
A90D494C2DDE2C6000781124 /* SFSymbolsPicker */ = {
isa = XCSwiftPackageProductDependency;
package = A920C2BC2D24021900E4F9B1 /* XCRemoteSwiftPackageReference "SFSymbolsPicker" */;
productName = SFSymbolsPicker;
};
A90D49552DDE2D5800781124 /* SFSymbolsPicker */ = {
isa = XCSwiftPackageProductDependency;
package = A920C2BC2D24021900E4F9B1 /* XCRemoteSwiftPackageReference "SFSymbolsPicker" */;
productName = SFSymbolsPicker;
};
A920C2BD2D24021A00E4F9B1 /* SFSymbolsPicker */ = { A920C2BD2D24021A00E4F9B1 /* SFSymbolsPicker */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
package = A920C2BC2D24021900E4F9B1 /* XCRemoteSwiftPackageReference "SFSymbolsPicker" */; package = A920C2BC2D24021900E4F9B1 /* XCRemoteSwiftPackageReference "SFSymbolsPicker" */;

View File

@@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1630"
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 = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
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>

View File

@@ -4,7 +4,7 @@
<dict> <dict>
<key>SchemeUserState</key> <key>SchemeUserState</key>
<dict> <dict>
<key>NearFuture nodebug.xcscheme_^#shared#^_</key> <key>MacNearFuture.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>2</integer> <integer>2</integer>
@@ -12,12 +12,12 @@
<key>NearFuture.xcscheme_^#shared#^_</key> <key>NearFuture.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>1</integer> <integer>0</integer>
</dict> </dict>
<key>NearFutureWidgetsExtension.xcscheme_^#shared#^_</key> <key>NearFutureWidgetsExtension.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>0</integer> <integer>1</integer>
</dict> </dict>
</dict> </dict>
<key>SuppressBuildableAutocreation</key> <key>SuppressBuildableAutocreation</key>

View File

@@ -1,258 +0,0 @@
//
// AddEventView.swift
// NearFuture
//
// Created by Nihaal Sharma on 25/12/2024.
//
import SwiftUI
import SFSymbolsPicker
struct AddEventView: View {
@ObservedObject var viewModel: EventViewModel
@Binding var eventName: String
@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 eventTime: Bool
@Binding var eventRecurrence: Event.RecurrenceType
@State var adding: Bool
@State var showNeedsNameAlert: Bool = false
@State var isSymbolPickerPresented = false
@FocusState private var focusedField: Field?
private enum Field {
case Name, Notes
}
@Environment(\.dismiss) var dismiss
var body: some View {
NavigationStack {
Form {
Section(
header:
Text("Event Details")
.font(.headline)
.foregroundColor(.accentColor)
) {
// name & symbol
HStack(spacing: 5) {
Button() {
isSymbolPickerPresented.toggle()
} label: {
Image(systemName: eventSymbol)
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
.foregroundStyle(eventColor)
}
.frame(width: 20)
.buttonStyle(.borderless)
.sheet(isPresented: $isSymbolPickerPresented) {
SymbolsPicker(
selection: $eventSymbol,
title: "Choose a Symbol",
searchLabel: "Search...",
autoDismiss: true)
}
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
ZStack {
TextField("Event Notes", text: $eventNotes)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding(.trailing, eventNotes.isEmpty ? 0 : 30)
.animation(.spring, value: eventNotes)
.focused($focusedField, equals: Field.Notes)
.submitLabel(.done)
.onSubmit {
focusedField = nil
}
MagicClearButton(text: $eventNotes)
}
// date picker
HStack {
DatePicker("", selection: $eventDate, displayedComponents: .date)
.datePickerStyle(WheelDatePickerStyle())
Button() {
eventDate = Date()
} label: {
Image(systemName: "arrow.uturn.left")
.resizable()
.scaledToFit()
}
.buttonStyle(BorderlessButtonStyle())
.frame(width: 20)
}
Toggle("Schedule a Time", isOn: $eventTime)
if eventTime {
DatePicker(
"",
selection: $eventDate,
displayedComponents: .hourAndMinute
)
}
// re-ocurrence Picker
Picker("Recurrence", selection: $eventRecurrence) {
ForEach(Event.RecurrenceType.allCases, id: \.self) { recurrence in
Text(recurrence.rawValue.capitalized)
}
}
.pickerStyle(SegmentedPickerStyle())
Text(
describeOccurrence(
date: eventDate,
recurrence: eventRecurrence
)
)
}
}
.scrollContentBackground(.hidden)
.navigationTitle("\(adding ? "Add Event" : "")")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .topBarLeading) {
if adding {
Button() {
resetAddEventView()
dismiss()
} label: {
Image(systemName: "xmark.circle.fill")
.symbolRenderingMode(.hierarchical)
.resizable()
.scaledToFit()
.frame(width: 30)
}
}
}
ToolbarItem(placement: .topBarTrailing) {
if adding {
Button {
viewModel.addEvent(
newEvent: Event(
name: eventName,
complete: eventComplete,
completeDesc: eventCompleteDesc,
symbol: eventSymbol,
color: ColorCodable(eventColor),
notes: eventNotes,
date: eventDate,
time: eventTime,
recurrence: eventRecurrence
)
)
resetAddEventView()
} label: {
Text("Save")
.font(.headline)
.cornerRadius(10)
.buttonStyle(BorderedProminentButtonStyle())
}
.disabled(eventName.isEmpty)
.onTapGesture {
if eventName.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 eventName.isEmpty {
HStack {
Image(systemName: "exclamationmark")
.foregroundStyle(.red)
Text("Give your event a name.")
}
}
}
}
}
}
}
func resetAddEventView() {
//reset addeventView
eventName = viewModel.template.name
eventComplete = viewModel.template.complete
eventCompleteDesc = viewModel.template.completeDesc
eventSymbol = viewModel.template.symbol
eventColor = randomColor()
eventNotes = viewModel.template.notes
eventDate = viewModel.template.date
eventTime = viewModel.template.time
eventRecurrence = viewModel.template.recurrence
dismiss()
}
}
struct MagicClearButton: View {
@Binding var text: String
var body: some View {
HStack {
Spacer()
Button {
text = ""
} label: {
Image(systemName: "xmark.circle.fill")
.resizable()
.scaledToFit()
.frame(width: text.isEmpty ? 0 : 25)
.symbolRenderingMode(.hierarchical)
.padding(.trailing, -5)
.animation(.spring, value: text.isEmpty)
}
.buttonStyle(.borderless)
}
}
}
#Preview {
let vm = dummyEventViewModel()
Color.orange
.ignoresSafeArea(.all)
.sheet(isPresented: .constant(true)) {
AddEventView(
viewModel: vm,
eventName: .constant(vm.template.notes),
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),
eventTime: .constant(vm.template.time),
eventRecurrence: .constant(vm.template.recurrence),
adding: true
)
.presentationDragIndicator(.visible)
.presentationBackground(.ultraThinMaterial)
}
}

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 609 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 534 KiB

View File

@@ -1,197 +0,0 @@
//
// ContentView.swift
// NearFuture
//
// Created by Nihaal Sharma on 24/12/2024.
//
import SwiftUI
import SwiftData
enum Field {
case Search
}
enum Tab {
case Home
case Archive
case Statistics
case Settings
case Gradient
}
struct ContentView: View {
@StateObject var viewModel: EventViewModel
@State private var eventName = ""
@State private var eventComplete = false
@State private var eventCompleteDesc = ""
@State private var eventSymbol = "star"
@State private var eventColor: Color = randomColor()
@State private var eventNotes = ""
@State private var eventDate = Date()
@State private var eventTime = false
@State private var eventRecurrence: Event.RecurrenceType = .none
@State var hey: UUID = UUID()
@State private var showingAddEventView = false
@State private var searchInput: String = ""
var filteredEvents: [Event] {
if searchInput.isEmpty {
return viewModel.events
} else {
return viewModel.events.filter {
$0.name.localizedCaseInsensitiveContains(searchInput) ||
$0.notes.localizedCaseInsensitiveContains(searchInput)
}
}
}
var noEvents: Bool {
if viewModel.events.count == 0 {
return true
} else {
return false
}
}
@FocusState private var focusedField: Field?
@FocusState private var focusedTab: Tab?
var body: some View {
TabView {
NavigationStack {
ZStack {
backgroundGradient
VStack {
ZStack {
SearchBar(searchInput: $searchInput)
.focused($focusedField, equals: Field.Search)
.onSubmit {
focusedField = nil
}
MagicClearButton(text: $searchInput)
.onTapGesture {
focusedField = nil
}
}
.padding(.horizontal)
if filteredEvents.isEmpty && !searchInput.isEmpty {
HelpView(searchInput: $searchInput, focusedField: focusedField)
} else {
ScrollView {
ForEach(filteredEvents) { event in
EventListView(viewModel: viewModel, event: event)
}
.onDelete(perform: viewModel.removeEvent)
.id(hey)
.onReceive(viewModel.objectWillChange) {
hey = UUID()
}
.padding(.horizontal)
if /*!searchInput.isEmpty && */filteredEvents.isEmpty {
HelpView(searchInput: $searchInput, focusedField: focusedField)
}
Spacer()
}
}
}
.navigationTitle("Near Future")
.navigationBarTitleDisplayMode(.inline)
.sheet(isPresented: $showingAddEventView) {
AddEventView(
viewModel: viewModel,
eventName: $eventName,
eventComplete: $eventComplete,
eventCompleteDesc: $eventCompleteDesc,
eventSymbol: $eventSymbol,
eventColor: $eventColor,
eventNotes: $eventNotes,
eventDate: $eventDate,
eventTime: $eventTime,
eventRecurrence: $eventRecurrence,
adding: true //adding event
)
.presentationDragIndicator(.visible)
.presentationBackground(.ultraThinMaterial)
}
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
AddEventButton(showingAddEventView: $showingAddEventView)
}
}
}
}
.tabItem {
Label("Home", systemImage: "house")
}
.focused($focusedTab, equals: Tab.Home)
ArchiveView(viewModel: viewModel)
.tabItem() {
Label("Archive", systemImage: "tray.full")
}
.focused($focusedTab, equals: Tab.Archive)
StatsView(viewModel: viewModel)
.tabItem {
Label("Statistics", systemImage: "chart.pie")
}
.focused($focusedTab, equals: Tab.Statistics)
SettingsView(viewModel: viewModel)
.tabItem {
Label("Settings", systemImage: "gear")
}
.focused($focusedTab, equals: Tab.Settings)
}
}
}
#Preview {
ContentView(viewModel: dummyEventViewModel())
}
struct SearchBar: View {
@Binding var searchInput: String
var body: some View {
TextField(
"\(Image(systemName: "magnifyingglass")) Search",
text: $searchInput
)
.padding(.trailing, searchInput.isEmpty ? 0 : 30)
.animation(.spring, value: searchInput)
.textFieldStyle(RoundedBorderTextFieldStyle())
.submitLabel(.done)
}
}
struct AddEventButton: View {
@Binding var showingAddEventView: Bool
var body: some View {
Button() {
showingAddEventView.toggle()
} label: {
ZStack {
Circle()
.frame(width: 33)
.foregroundStyle(.one)
Image(systemName: "plus")
.resizable()
.scaledToFit()
.frame(width: 15)
.bold()
.foregroundStyle(.two)
}
}
}
}
extension View {
var appearance: ColorScheme {
return UITraitCollection.current.userInterfaceStyle == .dark ? .dark : .light
}
var backgroundGradient: some View {
return LinearGradient(
gradient: Gradient(colors: [.bgTop, .two]),
startPoint: .top,
endPoint: .bottom
)
.ignoresSafeArea(.all)
}
}

View File

@@ -1,5 +0,0 @@
<?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/>
</plist>

View File

@@ -1,392 +0,0 @@
//
// Item.swift
// NearFuture
//
// Created by Nihaal Sharma on 24/12/2024.
//
import Foundation
import SwiftData
import SwiftUI
import WidgetKit
//@Model
//final class Item {
// var timestamp: Date
//
// init(timestamp: Date) {
// self.timestamp = timestamp
// }
//}
struct Event: Identifiable, Codable {
var id = UUID()
var name: String
var complete: Bool
var completeDesc: String
var symbol: String
var color: ColorCodable
var notes: String
var date: Date
var time: Bool
var recurrence: RecurrenceType
enum RecurrenceType: String, Codable, CaseIterable {
case none, daily, weekly, monthly, yearly
}
}
struct ColorCodable: Codable {
var red: Double
var green: Double
var blue: Double
var color: Color {
Color(red: red, green: green, blue: blue)
}
var colorBind: Color {
get {
return Color(
red: red,
green: green,
blue: blue
)
} set {
let cc = ColorCodable(newValue)
self.red = cc.red
self.green = cc.green
self.blue = cc.blue
}
}
init(_ color: Color) {
let uiColor = UIColor(color)
var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 1.0
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
self.red = Double(r)
self.green = Double(g)
self.blue = Double(b)
}
init(red: Double, green: Double, blue: Double) {
self.red = red
self.green = green
self.blue = blue
}
}
func daysUntilEvent(_ eventDate: Date, short: Bool, sepLines: Bool = false) -> 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 {
if short {
return "\(days)d"
} else {
return "\(-days)\(sepLines ? "\n" : " ")day\(-days == 1 ? "" : "s") ago"
}
}
guard days != 0 else {
return "Today"
}
if short {
return "\(days)d"
} else {
return "\(days)\(sepLines ? "\n" : " ")day\(days == 1 ? "" : "s")"
}
}
class EventViewModel: ObservableObject {
@Published var events: [Event] = []
@Published var icloudData: [Event] = []
public let template: Event = Event(
name: "",
complete: false,
completeDesc: "",
symbol: "star",
color: ColorCodable(randomColor()),
notes: "",
date: Date(),
time: false,
recurrence: .none
)
@Published var editableTemplate: Event = Event(
name: "",
complete: false,
completeDesc: "",
symbol: "star",
color: ColorCodable(randomColor()),
notes: "",
date: Date(),
time: false,
recurrence: .none
)
@Published var example: Event = Event(
name: "event",
complete: false,
completeDesc: "dofajiof",
symbol: "star",
color: ColorCodable(.orange),
notes: "lksdjfakdflkasjlkjl",
date: Date(),
time: true,
recurrence: .daily
)
@Published var lastSync: Date? = nil
@Published var icloudEventCount: Int = 0
@Published var localEventCount: Int = 0
@Published var syncStatus: String = "Not Synced"
init(load: Bool = true) {
if load {
loadEvents()
}
}
//appgroup or regular userdefaults
let appGroupUserDefaults = UserDefaults(suiteName: "group.NearFuture") ?? UserDefaults.standard
//icloud store
let icloudStore = NSUbiquitousKeyValueStore.default
// load from icloud or local
func loadEvents() {
//load icloud 1st
if let icData = icloudStore.data(forKey: "events") {
let decoder = JSONDecoder()
if let decodedIcEvents = try? decoder.decode([Event].self, from: icData) {
self.icloudData = decodedIcEvents
self.events = decodedIcEvents
}
}
if events.isEmpty, let savedData = appGroupUserDefaults.data(forKey: "events") {
let decoder = JSONDecoder()
if let decodedEvents = try? decoder.decode([Event].self, from: savedData) {
self.events = decodedEvents
}
}
updateSyncStatus()
}
// save to local and icloud
func saveEvents() {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(events) {
appGroupUserDefaults.set(encoded, forKey: "events")
//sync
icloudStore.set(encoded, forKey: "events")
icloudStore.synchronize()
updateSyncStatus()
loadEvents()
WidgetCenter.shared.reloadAllTimelines()//reload all widgets when saving events
objectWillChange.send()
}
}
private func updateSyncStatus() {
lastSync = Date()
icloudEventCount = icloudData.count
localEventCount = events.count
if icloudEventCount == localEventCount {
syncStatus = "Successful"
} else {
syncStatus = "Pending"
}
}
func addEvent(newEvent: Event) {
events.append(newEvent)
saveEvents() //sync with icloud
}
func removeEvent(at index: IndexSet) {
events.remove(atOffsets: index)
saveEvents() //sync local and icl
}
func hasUbiquitousKeyValueStore() -> Bool {
let icloud = NSUbiquitousKeyValueStore.default
let key = "com.neon443.NearFuture.testkey"
let value = "testValue"
icloud.set(value, forKey: key)
icloud.synchronize()
if icloud.string(forKey: key) != nil {
icloud.removeObject(forKey: key)
icloud.synchronize()
return true
} else {
print("!has UbiquitousKeyValueStore")
icloud.removeObject(forKey: key)
icloud.synchronize()
return false
}
}
func sync() {
NSUbiquitousKeyValueStore.default.synchronize()
loadEvents()
}
func replaceLocalWithiCloudData() {
icloudStore.synchronize()
self.events = self.icloudData
saveEvents()
}
func replaceiCloudWithLocalData() {
icloudStore.synchronize()
self.icloudData = self.events
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")
appGroupUserDefaults.removeObject(forKey: "events")
events.removeAll()
updateSyncStatus()
}
func dangerCleariCloudData() {
icloudStore.removeObject(forKey: "events")
icloudStore.synchronize()
icloudData.removeAll()
updateSyncStatus()
}
func dangerResetLocalData() {
let userDFDict = UserDefaults.standard.dictionaryRepresentation()
for key in userDFDict.keys {
UserDefaults.standard.removeObject(forKey: key)
}
let appGUSDDict = appGroupUserDefaults.dictionaryRepresentation()
for key in appGUSDDict.keys {
appGroupUserDefaults.removeObject(forKey: key)
}
events.removeAll()
updateSyncStatus()
}
func dangerResetiCloud() {
let icloudDict = icloudStore.dictionaryRepresentation
for key in icloudDict.keys {
icloudStore.removeObject(forKey: key)
}
icloudStore.synchronize()
icloudData.removeAll()
updateSyncStatus()
}
}
class dummyEventViewModel: EventViewModel {
override init(load: Bool = false) {
super.init(load: false)
self.events = [self.example, self.template, self.example, self.template]
self.events[0].complete.toggle()
}
}
func describeOccurrence(date: Date, recurrence: Event.RecurrenceType) -> String {
let dateString = date.formatted(date: .long, time: .omitted)
let recurrenceDescription: String
switch recurrence {
case .none:
recurrenceDescription = "Occurs once on"
case .daily:
recurrenceDescription = "Repeats every day from"
case .weekly:
recurrenceDescription = "Repeats every week from"
case .monthly:
recurrenceDescription = "Repeats every month from"
case .yearly:
recurrenceDescription = "Repeats every year from"
}
return "\(recurrenceDescription) \(dateString)"
}
func randomRainbowColor() -> Color {
return [
Color.red,
Color.orange,
Color.yellow,
Color.green,
Color.blue,
Color.indigo,
Color.purple
].randomElement()!
}
func randomColor() -> Color {
let r = Double.random(in: 0...1)
let g = Double.random(in: 0...1)
let b = Double.random(in: 0...1)
return Color(red: r, green: g, blue: b)
}

View File

@@ -1,32 +0,0 @@
//
// NearFutureApp.swift
// NearFuture
//
// Created by Nihaal Sharma on 24/12/2024.
//
import SwiftUI
import SwiftData
@main
struct NearFutureApp: App {
// var sharedModelContainer: ModelContainer = {
// let schema = Schema([
// Item.self,
// ])
// let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
//
// do {
// return try ModelContainer(for: schema, configurations: [modelConfiguration])
// } catch {
// fatalError("Could not create ModelContainer: \(error)")
// }
// }()
var body: some Scene {
WindowGroup {
ContentView(viewModel: EventViewModel())
}
// .modelContainer(sharedModelContainer)
}
}

View File

@@ -1,18 +0,0 @@
//
// AppIntent.swift
// NearFutureWidgets
//
// Created by Nihaal Sharma on 02/01/2025.
//
import WidgetKit
import AppIntents
struct ConfigurationAppIntent: WidgetConfigurationIntent {
static var title: LocalizedStringResource = "Configuration"
static var description = IntentDescription("This is an example widget.")
// An example configurable parameter.
@Parameter(title: "Favorite Emoji", default: "😃")
var favoriteEmoji: String
}

View File

@@ -1,13 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -1,11 +0,0 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -1,11 +0,0 @@
<?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>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.widgetkit-extension</string>
</dict>
</dict>
</plist>

View File

@@ -1,84 +0,0 @@
//
// NearFutureWidgets.swift
// NearFutureWidgets
//
// Created by Nihaal Sharma on 02/01/2025.
//
import WidgetKit
import SwiftUI
struct Provider: AppIntentTimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), configuration: ConfigurationAppIntent())
}
func snapshot(for configuration: ConfigurationAppIntent, in context: Context) async -> SimpleEntry {
SimpleEntry(date: Date(), configuration: configuration)
}
func timeline(for configuration: ConfigurationAppIntent, in context: Context) async -> Timeline<SimpleEntry> {
var entries: [SimpleEntry] = []
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate, configuration: configuration)
entries.append(entry)
}
return Timeline(entries: entries, policy: .atEnd)
}
}
struct SimpleEntry: TimelineEntry {
let date: Date
let configuration: ConfigurationAppIntent
}
struct NearFutureWidgetsEntryView : View {
var entry: Provider.Entry
var body: some View {
VStack {
Text("Time:")
Text(entry.date, style: .time)
Text("Favorite Emoji:")
Text(entry.configuration.favoriteEmoji)
}
}
}
struct NearFutureWidgets: Widget {
let kind: String = "NearFutureWidgets"
var body: some WidgetConfiguration {
AppIntentConfiguration(kind: kind, intent: ConfigurationAppIntent.self, provider: Provider()) { entry in
NearFutureWidgetsEntryView(entry: entry)
.containerBackground(.fill.tertiary, for: .widget)
}
}
}
extension ConfigurationAppIntent {
fileprivate static var smiley: ConfigurationAppIntent {
let intent = ConfigurationAppIntent()
intent.favoriteEmoji = "😀"
return intent
}
fileprivate static var starEyes: ConfigurationAppIntent {
let intent = ConfigurationAppIntent()
intent.favoriteEmoji = "🤩"
return intent
}
}
#Preview(as: .systemSmall) {
NearFutureWidgets()
} timeline: {
SimpleEntry(date: .now, configuration: .smiley)
SimpleEntry(date: .now, configuration: .starEyes)
}

View File

@@ -1,17 +0,0 @@
//
// NearFutureWidgetsBundle.swift
// NearFutureWidgets
//
// Created by Nihaal Sharma on 02/01/2025.
//
import WidgetKit
import SwiftUI
@main
struct NearFutureWidgetsBundle: WidgetBundle {
var body: some Widget {
NearFutureWidgets()
NearFutureWidgetsLiveActivity()
}
}

View File

@@ -1,80 +0,0 @@
//
// NearFutureWidgetsLiveActivity.swift
// NearFutureWidgets
//
// Created by Nihaal Sharma on 02/01/2025.
//
import ActivityKit
import WidgetKit
import SwiftUI
struct NearFutureWidgetsAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
// Dynamic stateful properties about your activity go here!
var emoji: String
}
// Fixed non-changing properties about your activity go here!
var name: String
}
struct NearFutureWidgetsLiveActivity: Widget {
var body: some WidgetConfiguration {
ActivityConfiguration(for: NearFutureWidgetsAttributes.self) { context in
// Lock screen/banner UI goes here
VStack {
Text("Hello \(context.state.emoji)")
}
.activityBackgroundTint(Color.cyan)
.activitySystemActionForegroundColor(Color.black)
} dynamicIsland: { context in
DynamicIsland {
// Expanded UI goes here. Compose the expanded UI through
// various regions, like leading/trailing/center/bottom
DynamicIslandExpandedRegion(.leading) {
Text("Leading")
}
DynamicIslandExpandedRegion(.trailing) {
Text("Trailing")
}
DynamicIslandExpandedRegion(.bottom) {
Text("Bottom \(context.state.emoji)")
// more content
}
} compactLeading: {
Text("L")
} compactTrailing: {
Text("T \(context.state.emoji)")
} minimal: {
Text(context.state.emoji)
}
.widgetURL(URL(string: "http://www.apple.com"))
.keylineTint(Color.red)
}
}
}
extension NearFutureWidgetsAttributes {
fileprivate static var preview: NearFutureWidgetsAttributes {
NearFutureWidgetsAttributes(name: "World")
}
}
extension NearFutureWidgetsAttributes.ContentState {
fileprivate static var smiley: NearFutureWidgetsAttributes.ContentState {
NearFutureWidgetsAttributes.ContentState(emoji: "😀")
}
fileprivate static var starEyes: NearFutureWidgetsAttributes.ContentState {
NearFutureWidgetsAttributes.ContentState(emoji: "🤩")
}
}
#Preview("Notification", as: .content, using: NearFutureWidgetsAttributes.preview) {
NearFutureWidgetsLiveActivity()
} contentStates: {
NearFutureWidgetsAttributes.ContentState.smiley
NearFutureWidgetsAttributes.ContentState.starEyes
}

View File

@@ -10,9 +10,8 @@ import SwiftUI
struct ArchiveView: View { struct ArchiveView: View {
@ObservedObject var viewModel: EventViewModel @ObservedObject var viewModel: EventViewModel
@State var showAddEvent: Bool = false @State var showAddEvent: Bool = false
@State var hey: UUID = UUID() var filteredEvents: [Event] {
init(viewModel: EventViewModel) { return viewModel.events.filter() {$0.complete}
self.viewModel = viewModel
} }
var body: some View { var body: some View {
NavigationStack { NavigationStack {
@@ -22,15 +21,14 @@ struct ArchiveView: View {
HelpView(showAddEvent: $showAddEvent) HelpView(showAddEvent: $showAddEvent)
} else { } else {
ScrollView { ScrollView {
ForEach(viewModel.events.filter({$0.complete})) { event in ForEach(filteredEvents) { event in
EventListView(viewModel: viewModel, event: event) EventListView(viewModel: viewModel, event: event)
.transition(.moveAndFadeReversed)
.id(event.complete)
} }
.padding(.horizontal) .padding(.horizontal)
.id(hey)
.onReceive(viewModel.objectWillChange) {
hey = UUID()
}
} }
.animation(.default, value: filteredEvents)
} }
} }
.scrollContentBackground(.hidden) .scrollContentBackground(.hidden)
@@ -39,6 +37,14 @@ struct ArchiveView: View {
AddEventButton(showingAddEventView: $showAddEvent) AddEventButton(showingAddEventView: $showAddEvent)
} }
} }
.navigationTitle("Archive")
.apply {
if #available(iOS 17, *) {
$0.toolbarTitleDisplayMode(.inlineLarge)
} else {
$0.navigationBarTitleDisplayMode(.inline)
}
}
} }
.sheet(isPresented: $showAddEvent) { .sheet(isPresented: $showAddEvent) {
AddEventView( AddEventView(
@@ -50,11 +56,9 @@ struct ArchiveView: View {
eventColor: $viewModel.editableTemplate.color.colorBind, eventColor: $viewModel.editableTemplate.color.colorBind,
eventNotes: $viewModel.editableTemplate.notes, eventNotes: $viewModel.editableTemplate.notes,
eventDate: $viewModel.editableTemplate.date, eventDate: $viewModel.editableTemplate.date,
eventTime: $viewModel.editableTemplate.time,
eventRecurrence: $viewModel.editableTemplate.recurrence, eventRecurrence: $viewModel.editableTemplate.recurrence,
adding: true adding: true
) )
.presentationDragIndicator(.visible)
} }
} }
} }
@@ -62,5 +66,3 @@ struct ArchiveView: View {
#Preview { #Preview {
ArchiveView(viewModel: dummyEventViewModel()) ArchiveView(viewModel: dummyEventViewModel())
} }

View File

@@ -0,0 +1,69 @@
//
// ContentView.swift
// NearFuture
//
// Created by neon443 on 24/12/2024.
//
import SwiftUI
import UserNotifications
import SwiftData
enum Field {
case Search
}
enum Tab {
case home
case archive
case stats
case settings
}
struct ContentView: View {
@StateObject var viewModel: EventViewModel
@StateObject var settingsModel: SettingsViewModel
@State var selection: Tab = .home
var body: some View {
if #available(iOS 17.5, *) {
YouAsked()
}
TabView(selection: $selection) {
HomeView(viewModel: viewModel, settingsModel: settingsModel)
.tabItem {
Label("Home", systemImage: "house")
}
.tag(Tab.home)
ArchiveView(viewModel: viewModel)
.tabItem() {
Label("Archive", systemImage: "tray.full")
}
.tag(Tab.archive)
StatsView(viewModel: viewModel)
.tabItem {
Label("Statistics", systemImage: "chart.pie")
}
.tag(Tab.stats)
SettingsView(viewModel: viewModel, settingsModel: settingsModel)
.tabItem {
Label("Settings", systemImage: "gear")
}
.tag(Tab.settings)
}
.apply {
if #available(iOS 17, *) {
$0.sensoryFeedback(.impact(weight: .heavy, intensity: 1), trigger: selection)
}
}
.sheet(isPresented: $settingsModel.settings.showWhatsNew) {
WhatsNewView(settingsModel: settingsModel)
}
}
}
#Preview {
ContentView(
viewModel: dummyEventViewModel(),
settingsModel: dummySettingsViewModel()
)
}

View File

@@ -0,0 +1,257 @@
//
// AddEventView.swift
// NearFuture
//
// Created by neon443 on 25/12/2024.
//
import SwiftUI
import SFSymbolsPicker
struct AddEventView: View {
@ObservedObject var viewModel: EventViewModel
@Binding var eventName: String
@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 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
}
NavigationStack {
Form {
Section(
header:
Text("Event Details")
.font(.headline)
.foregroundColor(.accentColor)
) {
// name & symbol
HStack(spacing: 5) {
Button() {
isSymbolPickerPresented.toggle()
} label: {
Image(systemName: eventSymbol)
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
.foregroundStyle(eventColor)
}
.frame(width: 20)
.buttonStyle(.borderless)
.sheet(isPresented: $isSymbolPickerPresented) {
SymbolsPicker(
selection: $eventSymbol,
title: "Choose a Symbol",
searchLabel: "Search...",
autoDismiss: true)
.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
ZStack {
TextField("Event Notes", text: $eventNotes)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding(.trailing, eventNotes.isEmpty ? 0 : 30)
.animation(.spring, value: eventNotes)
.focused($focusedField, equals: Field.Notes)
.submitLabel(.done)
.onSubmit {
focusedField = nil
}
// MagicClearButton(text: $eventNotes)
}
// date picker
HStack {
Spacer()
DatePicker("", selection: $eventDate, displayedComponents: .date)
// .datePickerStyle(datepickersty)
Spacer()
Button() {
eventDate = Date()
} label: {
Image(systemName: "arrow.uturn.left")
.resizable()
.scaledToFit()
}
.buttonStyle(BorderlessButtonStyle())
.frame(width: 20)
}
DatePicker(
"",
selection: $eventDate,
displayedComponents: .hourAndMinute
)
// re-ocurrence Picker
Picker("Recurrence", selection: $eventRecurrence) {
ForEach(Event.RecurrenceType.allCases, id: \.self) { recurrence in
Text(recurrence.rawValue.capitalized)
}
}
.pickerStyle(SegmentedPickerStyle())
Text(
describeOccurrence(
date: eventDate,
recurrence: eventRecurrence
)
)
}
}
.scrollContentBackground(.hidden)
.navigationTitle("\(adding ? "Add Event" : "")")
// .navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(/*placement: .topBarLeading*/) {
if adding {
Button() {
resetAddEventView()
dismiss()
} label: {
Image(systemName: "xmark.circle.fill")
.symbolRenderingMode(.hierarchical)
.resizable()
.scaledToFit()
.frame(width: 30)
}
}
}
ToolbarItem/*(placement: .topBarTrailing)*/ {
if adding {
Button {
viewModel.addEvent(
newEvent: Event(
name: eventName,
complete: eventComplete,
completeDesc: eventCompleteDesc,
symbol: eventSymbol,
color: ColorCodable(eventColor),
notes: eventNotes,
date: eventDate,
recurrence: eventRecurrence
)
)
bye.toggle()
resetAddEventView()
} label: {
Text("Save")
.font(.headline)
.cornerRadius(10)
.buttonStyle(BorderedProminentButtonStyle())
}
.apply {
if #available(iOS 17, *) {
$0.sensoryFeedback(.success, trigger: bye)
}
}
.disabled(eventName.isEmpty)
.onTapGesture {
if eventName.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 eventName.isEmpty {
HStack {
Image(systemName: "exclamationmark")
.foregroundStyle(.red)
Text("Give your event a name.")
}
}
}
}
}
}
.presentationDragIndicator(.visible)
.scrollContentBackground(.hidden)
}
.apply {
if #available(iOS 16.4, *) {
$0.presentationBackground(.ultraThinMaterial)
}
}
}
func resetAddEventView() {
//reset addeventView
eventName = viewModel.template.name
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()
}
}
#Preview {
let vm = dummyEventViewModel()
Color.orange
.ignoresSafeArea(.all)
.sheet(isPresented: .constant(true)) {
AddEventView(
viewModel: vm,
eventName: .constant(vm.template.notes),
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
)
}
}

View File

@@ -2,7 +2,7 @@
// EditEventView.swift // EditEventView.swift
// NearFuture // NearFuture
// //
// Created by Nihaal Sharma on 02/01/2025. // Created by neon443 on 02/01/2025.
// //
import SwiftUI import SwiftUI
@@ -35,7 +35,6 @@ struct EditEventView: View {
eventColor: $event.color.colorBind, eventColor: $event.color.colorBind,
eventNotes: $event.notes, eventNotes: $event.notes,
eventDate: $event.date, eventDate: $event.date,
eventTime: $event.time,
eventRecurrence: $event.recurrence, eventRecurrence: $event.recurrence,
adding: false //bc we editing existing event adding: false //bc we editing existing event
) )

View File

@@ -44,16 +44,18 @@ struct EventListView: View {
.font(.headline) .font(.headline)
.foregroundStyle(.one) .foregroundStyle(.one)
.strikethrough(event.complete) .strikethrough(event.complete)
.multilineTextAlignment(.leading)
} }
if !event.notes.isEmpty { if !event.notes.isEmpty {
Text(event.notes) Text(event.notes)
.font(.subheadline) .font(.subheadline)
.foregroundStyle(.one.opacity(0.8)) .foregroundStyle(.one.opacity(0.8))
.multilineTextAlignment(.leading)
} }
Text( Text(
event.date.formatted( event.date.formatted(
date: .long, date: .long,
time: event.time ? .shortened : .omitted time: .shortened
) )
) )
.font(.subheadline) .font(.subheadline)
@@ -71,9 +73,10 @@ struct EventListView: View {
} }
Spacer() Spacer()
VStack { VStack {
Text("\(daysUntilEvent(event.date, short: false))") Text("\(daysUntilEvent(event.date).long)")
.font(.subheadline) .font(.subheadline)
.foregroundStyle(.one) .foregroundStyle(event.date.timeIntervalSinceNow < 0 ? .red : .one)
.multilineTextAlignment(.trailing)
} }
Button() { Button() {
withAnimation { withAnimation {
@@ -109,13 +112,19 @@ struct EventListView: View {
.frame(maxWidth: 25, maxHeight: 25) .frame(maxWidth: 25, maxHeight: 25)
.shadow(radius: 5) .shadow(radius: 5)
.padding(.trailing, 5) .padding(.trailing, 5)
.apply {
if #available(iOS 17, *) {
$0.sensoryFeedback(.success, trigger: event.complete)
}
}
} }
.transition(.opacity)
.padding(.vertical, 5) .padding(.vertical, 5)
.background(.ultraThinMaterial) .background(.ultraThinMaterial)
.overlay( .overlay(
RoundedRectangle(cornerRadius: 10) RoundedRectangle(cornerRadius: 10)
.stroke( .stroke(
.one.opacity(appearance == .dark ? 0.5 : 1), .one.opacity(0.5),
lineWidth: 1 lineWidth: 1
) )
) )

View File

@@ -74,7 +74,7 @@ struct HelpView: View {
var body: some View { var body: some View {
List { List {
ZStack { ZStack {
Color(.accent) Color(.tintColor)
.opacity(0.4) .opacity(0.4)
.padding(.horizontal, -15) .padding(.horizontal, -15)
.blur(radius: 5) .blur(radius: 5)

View File

@@ -0,0 +1,129 @@
//
// HomeView.swift
// NearFuture
//
// Created by neon443 on 12/05/2025.
//
import SwiftUI;import AppIntents
struct HomeView: View {
@ObservedObject var viewModel: EventViewModel
@ObservedObject var settingsModel: SettingsViewModel
@State private var eventName: String = ""
@State private var eventComplete: Bool = false
@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 searchInput: String = ""
@Environment(\.colorScheme) var appearance
var darkMode: Bool {
return appearance == .dark
}
var filteredEvents: [Event] {
if searchInput.isEmpty {
if settingsModel.settings.showCompletedInHome {
return viewModel.events
} else {
return viewModel.events.filter() {!$0.complete}
}
} else {
return viewModel.events.filter {
$0.name.localizedCaseInsensitiveContains(searchInput) ||
$0.notes.localizedCaseInsensitiveContains(searchInput)
}
}
}
@State private var focusedTab: Tab = .home
@FocusState private var focusedField: Field?
var body: some View {
NavigationStack {
ZStack {
backgroundGradient
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 {
HelpView(searchInput: $searchInput, focusedField: focusedField)
} else {
ScrollView {
ForEach(filteredEvents) { event in
EventListView(viewModel: viewModel, event: event)
.transition(.moveAndFade)
.id(event.complete)
}
.padding(.horizontal)
if filteredEvents.isEmpty {
HelpView(
searchInput: $searchInput,
focusedField: focusedField
)
}
Spacer()
}
.animation(.default, value: filteredEvents)
}
}
.navigationTitle("Near Future")
.apply {
if #available(iOS 17, *) {
$0.toolbarTitleDisplayMode(.inlineLarge)
} else {
$0.navigationBarTitleDisplayMode(.inline)
}
}
.sheet(isPresented: $showingAddEventView) {
AddEventView(
viewModel: viewModel,
eventName: $eventName,
eventComplete: $eventComplete,
eventCompleteDesc: $eventCompleteDesc,
eventSymbol: $eventSymbol,
eventColor: $eventColor,
eventNotes: $eventNotes,
eventDate: $eventDate,
eventRecurrence: $eventRecurrence,
adding: true //adding event
)
}
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
AddEventButton(showingAddEventView: $showingAddEventView)
}
}
}
}
}
}
#Preview {
HomeView(
viewModel: dummyEventViewModel(),
settingsModel: dummySettingsViewModel()
)
}

View File

@@ -0,0 +1,31 @@
//
// AboutView.swift
// NearFuture
//
// Created by neon443 on 12/05/2025.
//
import SwiftUI
struct AboutView: View {
var body: some View {
VStack {
Image(uiImage: #imageLiteral(resourceName: "NearFutureIcon.png"))
.resizable()
.scaledToFit()
.frame(width: 100)
.clipShape(RoundedRectangle(cornerRadius: 25))
Text("Near Future")
.bold()
.monospaced()
.font(.title)
.frame(maxWidth: .infinity)
Text("Version " + getVersion() + " (\(getBuildID()))")
.frame(maxWidth: .infinity)
}
}
}
#Preview {
AboutView()
}

View File

@@ -0,0 +1,58 @@
//
// MagicClearButton.swift
// NearFuture
//
// Created by neon443 on 06/05/2025.
//
import SwiftUI
struct MagicClearButton: View {
@Binding var text: String
var body: some View {
HStack {
Spacer()
Button {
text = ""
} label: {
Image(systemName: "xmark.circle.fill")
.resizable()
.scaledToFit()
.frame(width: text.isEmpty ? 0 : 25)
.symbolRenderingMode(.hierarchical)
.padding(.trailing, -5)
.animation(.spring, value: text.isEmpty)
}
.buttonStyle(.borderless)
}
}
}
struct AddEventButton: View {
@Binding var showingAddEventView: Bool
var body: some View {
Button() {
showingAddEventView.toggle()
} label: {
ZStack {
Circle()
.frame(width: 33)
.foregroundStyle(.one)
Image(systemName: "plus")
.resizable()
.scaledToFit()
.frame(width: 15)
.bold()
.foregroundStyle(.two)
}
}
}
}
#Preview {
MagicClearButton(text: .constant("s"))
}
#Preview {
AddEventButton(showingAddEventView: .constant(false))
}

View File

@@ -0,0 +1,27 @@
//
// ExportView.swift
// NearFuture
//
// Created by neon443 on 02/05/2025.
//
import SwiftUI
struct ExportView: View {
@ObservedObject var viewModel: EventViewModel
var body: some View {
List {
Button() {
UIPasteboard.general.string = viewModel.exportEvents()
} label: {
Label("Copy Events", systemImage: "document.on.clipboard")
}
Text(viewModel.exportEvents())
.textSelection(.enabled)
}
}
}
#Preview {
ExportView(viewModel: dummyEventViewModel())
}

View File

@@ -0,0 +1,67 @@
//
// ImportView.swift
// NearFuture
//
// Created by neon443 on 02/05/2025.
//
import SwiftUI
struct ImportView: View {
@ObservedObject var viewModel: EventViewModel
@Binding var importStr: String
@State private var image: String = "clock.fill"
@State private var text: String = "Ready..."
@State private var fgColor: Color = .yellow
var body: some View {
List {
Section("Status") {
Label(text, systemImage: image)
.contentTransition(.numericText())
.foregroundStyle(fgColor)
}
TextField("", text: $importStr)
Button() {
do throws {
try viewModel.importEvents(importStr)
withAnimation {
image = "checkmark.circle.fill"
text = "Complete"
fgColor = .green
}
} catch importError.invalidB64 {
withAnimation {
image = "xmark.app.fill"
text = "Invalid base64 input."
fgColor = .red
}
} catch {
withAnimation {
image = "xmark.app.fill"
text = error.localizedDescription
fgColor = .red
}
}
} label: {
Label("Import", systemImage: "tray.and.arrow.down.fill")
}
.disabled(importStr.isEmpty)
.onAppear() {
importStr = ""
image = "clock.fill"
text = "Ready..."
fgColor = .yellow
}
}
}
}
#Preview {
ImportView(
viewModel: dummyEventViewModel(),
importStr: .constant("kljadfskljafdlkj;==")
)
}

View File

@@ -2,13 +2,14 @@
// SettingsView.swift // SettingsView.swift
// NearFuture // NearFuture
// //
// Created by Nihaal Sharma on 29/12/2024. // Created by neon443 on 29/12/2024.
// //
import SwiftUI import SwiftUI
struct SettingsView: View { struct SettingsView: View {
@State var viewModel: EventViewModel @ObservedObject var viewModel: EventViewModel
@ObservedObject var settingsModel: SettingsViewModel
@State private var hasUbiquitous: Bool = false @State private var hasUbiquitous: Bool = false
@State private var lastSyncWasSuccessful: Bool = false @State private var lastSyncWasSuccessful: Bool = false
@@ -39,14 +40,80 @@ struct SettingsView: View {
} }
} }
func changeIcon(to: String) {
guard UIApplication.shared.supportsAlternateIcons else {
print("doesnt tsupport alternate icons")
return
}
guard to != "orange" else {
UIApplication.shared.setAlternateIconName(nil) { error in
print(error as Any)
}
return
}
UIApplication.shared.setAlternateIconName(to) { error in
print(error as Any)
}
}
var body: some View { var body: some View {
NavigationStack { NavigationStack {
ZStack { ZStack {
backgroundGradient backgroundGradient
List { List {
ScrollView(.horizontal) {
HStack {
ForEach(settingsModel.accentChoices, id: \.self) { choice in
let color = Color(uiColor: UIColor(named: "uiColors/\(choice)")!)
ZStack {
Button() {
settingsModel.changeTint(to: choice)
changeIcon(to: choice)
} label: {
Circle()
.foregroundStyle(color)
.frame(width: 30)
}
if ColorCodable(color) == settingsModel.settings.tint {
let needContrast: Bool = ColorCodable(color) == settingsModel.settings.tint
Circle()
.foregroundStyle(needContrast ? .two : .one)
.frame(width: 10)
}
}
}
}
}
Button("Show What's New") {
settingsModel.settings.showWhatsNew = true
}
Toggle("Show completed Events in Home", isOn: $settingsModel.settings.showCompletedInHome)
.onChange(of: settingsModel.settings.showCompletedInHome) { _ in
settingsModel.saveSettings()
}
NavigationLink() {
List {
if !settingsModel.notifsGranted {
Button("Request Notifications") {
Task {
settingsModel.notifsGranted = await requestNotifs()
}
}
Text("\(Image(systemName: "xmark")) Notifications disabled for Near Future")
.foregroundStyle(.red)
} else {
Text("\(Image(systemName: "checkmark")) Notifications enabled for Near Future")
.foregroundStyle(.green)
}
}
} label: {
Image(systemName: "bell.badge.fill")
Text("Notifications")
}
NavigationLink() { NavigationLink() {
iCloudSettingsView( iCloudSettingsView(
viewModel: viewModel, viewModel: viewModel,
settingsModel: settingsModel,
hasUbiquitous: $hasUbiquitous, hasUbiquitous: $hasUbiquitous,
lastSyncWasSuccessful: $lastSyncWasSuccessful, lastSyncWasSuccessful: $lastSyncWasSuccessful,
lastSyncWasNormalAgo: $lastSyncWasNormalAgo, lastSyncWasNormalAgo: $lastSyncWasNormalAgo,
@@ -68,47 +135,17 @@ struct SettingsView: View {
viewModel.sync() viewModel.sync()
updateStatus() updateStatus()
} }
NavigationLink() { NavigationLink() {
NavigationStack() { ImportView(viewModel: viewModel, importStr: $importStr)
Button() {
UIPasteboard.general.string = "\(viewModel.exportEvents() ?? "")"
print(viewModel.exportEvents() as Any)
} label: {
Text("copy")
}
Text("\(viewModel.exportEvents() ?? "")")
}
} label: { } label: {
Image(systemName: "list.bullet.rectangle") Label("Import Events", systemImage: "tray.and.arrow.down.fill")
Text("Export events") .foregroundStyle(.one)
} }
NavigationLink() { NavigationLink() {
NavigationStack() { ExportView(viewModel: viewModel)
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: { } label: {
Image(systemName: "square.and.arrow.down") Label("Export Events", systemImage: "square.and.arrow.up")
Text("Import events") .foregroundStyle(.one)
} }
Section("Tip") { Section("Tip") {
@@ -135,19 +172,27 @@ struct SettingsView: View {
viewModel.dangerResetiCloud() viewModel.dangerResetiCloud()
} }
} }
Section("About") {
AboutView()
}
}
}
.scrollContentBackground(.hidden)
.navigationTitle("Settings")
.apply {
if #available(iOS 17, *) {
$0.toolbarTitleDisplayMode(.inlineLarge)
} else {
$0.navigationBarTitleDisplayMode(.inline)
} }
.scrollContentBackground(.hidden)
.navigationTitle("Settings")
.navigationBarTitleDisplayMode(.inline)
} }
} }
} }
} }
#Preview { #Preview {
SettingsView(viewModel: dummyEventViewModel()) SettingsView(
} viewModel: dummyEventViewModel(),
settingsModel: dummySettingsViewModel()
func test() -> Void { )
} }

View File

@@ -0,0 +1,138 @@
//
// WhatsNewView.swift
// NearFuture
//
// Created by neon443 on 12/05/2025.
//
import SwiftUI
struct WhatsNewView: View {
@ObservedObject var settingsModel: SettingsViewModel
@Environment(\.dismiss) var dismiss
struct WhatsNewChunk: Identifiable {
var id: UUID = UUID()
var symbol: String
var title: String
var subtitle: String
}
@State var bye: Bool = false
var whatsNewChunks: [WhatsNewChunk] {
return [
WhatsNewChunk(
symbol: "iphone.radiowaves.left.and.right",
title: "Haptic Feedback",
subtitle: "Lovely haptic feedback when completing and adding events, and selecting tabs"
),
WhatsNewChunk(
symbol: "app",
title: "App Icons",
subtitle: "You now get a special app icon that matches the color you choose in settings!"
),
WhatsNewChunk(
symbol: "apps.iphone",
title: "Widgets Day Count Fix",
subtitle: "The day count for widgets are now red for overdue events, just like the app, and are now more readable"
),
WhatsNewChunk(
symbol: settingsModel.device.sf,
title: "This Screen",
subtitle: "This update add a Whats New page that will tell you (suprise!) What's New"
),
WhatsNewChunk(
symbol: "bell.badge.fill",
title: "Notifications",
subtitle: "Events now have notifications, reminding you to complete them!"
),
WhatsNewChunk(
symbol: "list.bullet.indent",
title: "Animations!",
subtitle: "I added animations for adding, removing and ticking events - animations are definitely the most important change"
)
]
}
var body: some View {
NavigationStack {
List {
VStack {
Text("What's New")
.font(.largeTitle)
.bold()
AboutView()
Divider()
VStack(alignment: .leading) {
ForEach(whatsNewChunks) { new in
WhatsNewChunkView(
symbol: new.symbol,
title: new.title,
subtitle: new.subtitle
)
}
}
}
}
Button() {
bye.toggle()
dismiss()
} label: {
Text("Continue")
.font(.headline)
.frame(height: 40)
.bold()
.frame(maxWidth: .infinity)
}
.buttonStyle(BorderedProminentButtonStyle())
.clipShape(RoundedRectangle(cornerRadius: 15))
.padding().padding()
.apply {
if #available(iOS 17, *) {
$0.sensoryFeedback(.impact(weight: .heavy, intensity: 1), trigger: bye)
}
}
}
.scrollContentBackground(.hidden)
.presentationDragIndicator(.visible)
.apply {
if #available(iOS 16.4, *) {
$0.presentationBackground(.ultraThinMaterial)
}
}
.onDisappear {
settingsModel.settings.prevAppVersion = getVersion()+getBuildID()
settingsModel.saveSettings()
}
}
}
#Preview {
Color.accent
.ignoresSafeArea(.all)
.sheet(isPresented: .constant(true)) {
WhatsNewView(settingsModel: dummySettingsViewModel())
}
}
struct WhatsNewChunkView: View {
@State var symbol: String
@State var title: String
@State var subtitle: String
var body: some View {
HStack {
Image(systemName: symbol)
.resizable()
.scaledToFit()
.frame(width: 30, height: 30)
.foregroundStyle(Color.accentColor)
.padding(.trailing, 15)
VStack(alignment: .leading) {
Text(title)
.font(.headline)
.bold()
Text(subtitle)
.foregroundStyle(.gray)
.font(.subheadline)
.fixedSize(horizontal: false, vertical: true)
}
}
}
}

View File

@@ -0,0 +1,195 @@
//
// iCloudSettingsView.swift
// NearFuture
//
// Created by neon443 on 18/04/2025.
//
import SwiftUI
struct iCloudSettingsView: View {
@ObservedObject var viewModel: EventViewModel
@ObservedObject var settingsModel: SettingsViewModel
@State var showPushAlert: Bool = false
@State var showPullAlert: Bool = false
@Binding var hasUbiquitous: Bool
@Binding var lastSyncWasSuccessful: Bool
@Binding var lastSyncWasNormalAgo: Bool
@Binding var localCountEqualToiCloud: Bool
@Binding var icloudCountEqualToLocal: Bool
var updateStatus: () -> Void
var body: some View {
ZStack {
backgroundGradient
List {
Section {
HStack {
Spacer()
VStack {
ZStack {
Image(systemName: "icloud")
.resizable()
.scaledToFit()
.frame(width: 75, height: 55)
.symbolRenderingMode(.multicolor)
Text("\(viewModel.icloudEventCount)")
.font(.title2)
.monospaced()
.bold()
}
Text("iCloud")
HStack {
Button(role: .destructive) {
showPushAlert.toggle()
} label: {
Image(systemName: "arrow.up")
.resizable()
.scaledToFit()
.frame(width: 30, height: 40)
}
.buttonStyle(BorderedButtonStyle())
.alert("Warning", isPresented: $showPushAlert) {
Button("OK", role: .destructive) {
viewModel.replaceiCloudWithLocalData()
viewModel.sync()
updateStatus()
}
Button("Cancel", role: .cancel) {}
} message: {
Text("This will replace Events stored in iCloud with Events stored locally.")
}
Button() {
viewModel.sync()
updateStatus()
} label: {
Image(systemName: "arrow.triangle.2.circlepath")
.resizable()
.scaledToFit()
.frame(width: 30, height: 40)
.foregroundStyle(Color.accentColor)
}
.buttonStyle(BorderedButtonStyle())
Button(role: .destructive) {
showPullAlert.toggle()
} label: {
Image(systemName: "arrow.down")
.resizable()
.scaledToFit()
.frame(width: 30, height: 40)
}
.buttonStyle(BorderedButtonStyle())
.alert("Warning", isPresented: $showPullAlert) {
Button("OK", role: .destructive) {
viewModel.replaceLocalWithiCloudData()
viewModel.sync()
updateStatus()
}
Button("Cancel", role: .cancel) {}
} message: {
Text("This will replace Events stored locally with Events stored in iCloud.")
}
}
ZStack {
Image(systemName: settingsModel.device.sf)
.resizable()
.scaledToFit()
.frame(width: 75, height: 75)
.symbolRenderingMode(.monochrome)
Text("\(viewModel.localEventCount)")
.font(.title2)
.monospaced()
.bold()
}
Text(settingsModel.device.label)
}
Spacer()
}
.listRowSeparator(.hidden)
.onAppear {
viewModel.sync()
updateStatus()
}
HStack {
Circle()
.frame(width: 20, height: 20)
.foregroundStyle(hasUbiquitous ? .green : .red)
Text("iCloud")
Spacer()
Text("\(hasUbiquitous ? "" : "Not ")Working")
.bold()
}
HStack {
Circle()
.frame(width: 20, height: 20)
.foregroundStyle(lastSyncWasSuccessful ? .green : .red)
Text("Sync Status")
Spacer()
Text("\(viewModel.syncStatus)")
.bold()
}
HStack {
Circle()
.frame(width: 20, height: 20)
.foregroundStyle(lastSyncWasNormalAgo ? .green : .red)
Text("Last Sync")
Spacer()
Text("\(viewModel.lastSync?.formatted(date: .long, time: .standard) ?? "Never")")
.bold()
}
HStack {
Circle()
.frame(width: 20, height: 20)
.foregroundStyle(localCountEqualToiCloud ? .green : .red)
Text("Local Events")
Spacer()
Text("\(viewModel.localEventCount)")
.bold()
}
HStack {
Circle()
.frame(width: 20, height: 20)
.foregroundStyle(icloudCountEqualToLocal ? .green : .red)
Text("Events in iCloud")
Spacer()
Text("\(viewModel.icloudEventCount)")
.bold()
}
} header: {
Text("Sync Status")
} footer: {
Text("Pull to sync\nOr use the arrows to force push/pull")
}
}
.refreshable {
viewModel.sync()
updateStatus()
}
.scrollContentBackground(.hidden)
.navigationTitle("iCloud")
.navigationBarTitleDisplayMode(.inline)
}
}
}
#Preview("iCloudSettingsView") {
iCloudSettingsView(
viewModel: dummyEventViewModel(),
settingsModel: dummySettingsViewModel(),
hasUbiquitous: .constant(true),
lastSyncWasSuccessful: .constant(true),
lastSyncWasNormalAgo: .constant(true),
localCountEqualToiCloud: .constant(true),
icloudCountEqualToLocal: .constant(true),
updateStatus: {}
)
}

View File

@@ -2,7 +2,7 @@
// StatsView.swift // StatsView.swift
// NearFuture // NearFuture
// //
// Created by Nihaal Sharma on 05/01/2025. // Created by neon443 on 05/01/2025.
// //
import SwiftUI import SwiftUI
@@ -58,7 +58,13 @@ struct StatsView: View {
} }
.scrollContentBackground(.hidden) .scrollContentBackground(.hidden)
.navigationTitle("Statistics") .navigationTitle("Statistics")
.navigationBarTitleDisplayMode(.inline) .apply {
if #available(iOS 17, *) {
$0.toolbarTitleDisplayMode(.inlineLarge)
} else {
$0.navigationBarTitleDisplayMode(.inline)
}
}
} }
} }
} }

View File

@@ -0,0 +1,44 @@
//
// YouAsked.swift
// NearFuture
//
// Created by neon443 on 21/05/2025.
//
import SwiftUI
import AudioToolbox
@available(iOS 17.5, *)
struct YouAsked: View {
let startDate: Date = Date()
@State var timeElapsed: Int = 0
let timer = Timer.publish(every: 0.3, on: .current, in: .common).autoconnect()
var body: some View {
Text("\(timeElapsed)")
.onReceive(timer) { firedDate in
timeElapsed = Int(firedDate.timeIntervalSince(startDate))
}
.sensoryFeedback(.alignment, trigger: timeElapsed)
.sensoryFeedback(.decrease, trigger: timeElapsed)
.sensoryFeedback(.error, trigger: timeElapsed)
.sensoryFeedback(.impact, trigger: timeElapsed)
.sensoryFeedback(.increase, trigger: timeElapsed)
.sensoryFeedback(.levelChange, trigger: timeElapsed)
.sensoryFeedback(.pathComplete, trigger: timeElapsed)
.sensoryFeedback(.selection, trigger: timeElapsed)
.sensoryFeedback(.start, trigger: timeElapsed)
.sensoryFeedback(.stop, trigger: timeElapsed)
.sensoryFeedback(.success, trigger: timeElapsed)
.sensoryFeedback(.warning, trigger: timeElapsed)
.sensoryFeedback(.warning, trigger: timeElapsed)
}
}
#Preview {
if #available(iOS 17.5, *) {
YouAsked()
} else {
Text("update to ios 17 lil bro")
}
}

View File

@@ -1,196 +0,0 @@
//
// iCloudSettingsView.swift
// NearFuture
//
// Created by neon443 on 18/04/2025.
//
import SwiftUI
struct iCloudSettingsView: View {
@State var viewModel: EventViewModel
@State var showPushAlert: Bool = false
@State var showPullAlert: Bool = false
@Binding var hasUbiquitous: Bool
@Binding var lastSyncWasSuccessful: Bool
@Binding var lastSyncWasNormalAgo: Bool
@Binding var localCountEqualToiCloud: Bool
@Binding var icloudCountEqualToLocal: Bool
let asi = ProcessInfo().isiOSAppOnMac
let model = UIDevice().model
var device: (sf: String, label: String) {
if asi {
return (sf: "laptopcomputer", label: "Computer")
} else if model == "iPhone" {
return (sf: model.lowercased(), label: model)
} else if model == "iPad" {
return (sf: model.lowercased(), label: model)
}
return (sf: "iphone", label: "iPhone")
}
var updateStatus: () -> Void
var body: some View {
ZStack {
backgroundGradient
List {
HStack {
Spacer()
VStack {
ZStack {
Image(systemName: "icloud")
.resizable()
.scaledToFit()
.frame(width: 75, height: 55)
.symbolRenderingMode(.multicolor)
Text("\(viewModel.icloudEventCount)")
.font(.title2)
.monospaced()
.bold()
}
Text("iCloud")
HStack {
Button(role: .destructive) {
showPushAlert.toggle()
} label: {
Image(systemName: "arrow.up")
.resizable()
.scaledToFit()
.frame(width: 30, height: 40)
}
.buttonStyle(BorderedButtonStyle())
.alert("Warning", isPresented: $showPushAlert) {
Button("OK", role: .destructive) {
viewModel.replaceiCloudWithLocalData()
viewModel.sync()
updateStatus()
}
Button("Cancel", role: .cancel) {}
} message: {
Text("This will replace Events stored in iCloud with Events stored locally.")
}
Button() {
viewModel.sync()
updateStatus()
} label: {
Image(systemName: "arrow.triangle.2.circlepath")
.resizable()
.scaledToFit()
.frame(width: 30, height: 40)
.foregroundStyle(Color.accentColor)
}
.buttonStyle(BorderedButtonStyle())
Button(role: .destructive) {
showPullAlert.toggle()
} label: {
Image(systemName: "arrow.down")
.resizable()
.scaledToFit()
.frame(width: 30, height: 40)
}
.buttonStyle(BorderedButtonStyle())
.alert("Warning", isPresented: $showPullAlert) {
Button("OK", role: .destructive) {
viewModel.replaceLocalWithiCloudData()
viewModel.sync()
updateStatus()
}
Button("Cancel", role: .cancel) {}
} message: {
Text("This will replace Events stored locally with Events stored in iCloud.")
}
}
ZStack {
Image(systemName: device.sf)
.resizable()
.scaledToFit()
.frame(width: 75, height: 75)
.symbolRenderingMode(.monochrome)
Text("\(viewModel.localEventCount)")
.font(.title2)
.monospaced()
.bold()
}
Text(device.label)
}
Spacer()
}
.listRowSeparator(.hidden)
.onAppear {
viewModel.sync()
updateStatus()
}
HStack {
Circle()
.frame(width: 20, height: 20)
.foregroundStyle(hasUbiquitous ? .green : .red)
Text("iCloud")
Spacer()
Text("\(hasUbiquitous ? "" : "Not ")Working")
.bold()
}
HStack {
Circle()
.frame(width: 20, height: 20)
.foregroundStyle(lastSyncWasSuccessful ? .green : .red)
Text("Sync Status")
Spacer()
Text("\(viewModel.syncStatus)")
.bold()
}
HStack {
Circle()
.frame(width: 20, height: 20)
.foregroundStyle(lastSyncWasNormalAgo ? .green : .red)
Text("Last Sync")
Spacer()
Text("\(viewModel.lastSync?.formatted() ?? "Never")")
.bold()
}
HStack {
Circle()
.frame(width: 20, height: 20)
.foregroundStyle(localCountEqualToiCloud ? .green : .red)
Text("Local Events")
Spacer()
Text("\(viewModel.localEventCount)")
.bold()
}
HStack {
Circle()
.frame(width: 20, height: 20)
.foregroundStyle(icloudCountEqualToLocal ? .green : .red)
Text("Events in iCloud")
Spacer()
Text("\(viewModel.icloudEventCount)")
.bold()
}
}
.scrollContentBackground(.hidden)
.navigationTitle("iCloud")
.navigationBarTitleDisplayMode(.inline)
}
}
}
#Preview("iCloudSettingsView") {
iCloudSettingsView(
viewModel: dummyEventViewModel(),
hasUbiquitous: .constant(true),
lastSyncWasSuccessful: .constant(true),
lastSyncWasNormalAgo: .constant(true),
localCountEqualToiCloud: .constant(true),
icloudCountEqualToLocal: .constant(true),
updateStatus: test
)
}

View File

@@ -1,16 +0,0 @@
//
// NearFutureTests.swift
// NearFutureTests
//
// Created by neon443 on 26/03/2025.
//
import Testing
struct NearFutureTests {
@Test func example() async throws {
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
}
}

View File

@@ -2,11 +2,12 @@
// NearFutureWidgets.swift // NearFutureWidgets.swift
// NearFutureWidgets // NearFutureWidgets
// //
// Created by Nihaal Sharma on 02/01/2025. // Created by neon443 on 02/01/2025.
// //
import WidgetKit import WidgetKit
import SwiftUI import SwiftUI
import AppIntents
// Timeline Entry for Widget // Timeline Entry for Widget
struct EventWidgetEntry: TimelineEntry { struct EventWidgetEntry: TimelineEntry {
@@ -46,6 +47,24 @@ struct EventWidgetProvider: TimelineProvider {
} }
} }
// Event Widget View // Event Widget View
struct EventWidgetView: View { struct EventWidgetView: View {
var entry: EventWidgetEntry var entry: EventWidgetEntry
@@ -128,11 +147,38 @@ struct EventWidgetView: View {
Spacer() Spacer()
//short days till if not large widget //short days till if not large widget
Text(daysUntilEvent(event.date, short: !isLarge, sepLines: true)) if !isLarge {
.font(.caption) Text(daysUntilEvent(event.date).short)
.multilineTextAlignment(.trailing) .font(.caption)
.foregroundColor(event.color.color) .multilineTextAlignment(.trailing)
.padding(.trailing, -12) .foregroundColor(event.date < Date() ? .red : .primary)
.padding(.trailing, -12)
} else {
Button(
intent: CompleteEvent(
eventID: IntentParameter(
title: LocalizedStringResource(
stringLiteral: event.id.uuidString
)
)
)
) {
if event.complete {
Circle()
.frame(width: 10)
.foregroundStyle(.green)
} else {
Circle()
.frame(width: 10)
.foregroundStyle(.gray)
}
}
Text(daysUntilEvent(event.date).long)
.font(.caption)
.multilineTextAlignment(.trailing)
.foregroundColor(event.date < Date() ? .red : .primary)
.padding(.trailing, -12)
}
} }
} }
Spacer() Spacer()

View File

@@ -2,7 +2,7 @@
// NearFutureWidgetsBundle.swift // NearFutureWidgetsBundle.swift
// NearFutureWidgets // NearFutureWidgets
// //
// Created by Nihaal Sharma on 02/01/2025. // Created by neon443 on 02/01/2025.
// //
import WidgetKit import WidgetKit

View File

@@ -2,79 +2,79 @@
// NearFutureWidgetsLiveActivity.swift // NearFutureWidgetsLiveActivity.swift
// NearFutureWidgets // NearFutureWidgets
// //
// Created by Nihaal Sharma on 02/01/2025. // Created by neon443 on 02/01/2025.
// //
import ActivityKit //import ActivityKit
import WidgetKit import WidgetKit
import SwiftUI import SwiftUI
struct NearFutureWidgetsAttributes: ActivityAttributes { //struct NearFutureWidgetsAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable { // public struct ContentState: Codable, Hashable {
// Dynamic stateful properties about your activity go here! // // Dynamic stateful properties about your activity go here!
var emoji: String // var emoji: String
} // }
//
// // Fixed non-changing properties about your activity go here!
// var name: String
//}
// Fixed non-changing properties about your activity go here! //struct NearFutureWidgetsLiveActivity: Widget {
var name: String // var body: some WidgetConfiguration {
} // ActivityConfiguration(for: NearFutureWidgetsAttributes.self) { context in
// // Lock screen/banner UI goes here
// VStack {
// Text("Hello \(context.state.emoji)")
// }
// .activityBackgroundTint(Color.cyan)
// .activitySystemActionForegroundColor(Color.black)
//
// } dynamicIsland: { context in
// DynamicIsland {
// // Expanded UI goes here. Compose the expanded UI through
// // various regions, like leading/trailing/center/bottom
// DynamicIslandExpandedRegion(.leading) {
// Text("Leading")
// }
// DynamicIslandExpandedRegion(.trailing) {
// Text("Trailing")
// }
// DynamicIslandExpandedRegion(.bottom) {
// Text("Bottom \(context.state.emoji)")
// // more content
// }
// } compactLeading: {
// Text("L")
// } compactTrailing: {
// Text("T \(context.state.emoji)")
// } minimal: {
// Text(context.state.emoji)
// }
// .widgetURL(URL(string: "http://www.apple.com"))
// .keylineTint(Color.red)
// }
// }
//}
//
//extension NearFutureWidgetsAttributes {
// fileprivate static var preview: NearFutureWidgetsAttributes {
// NearFutureWidgetsAttributes(name: "World")
// }
//}
struct NearFutureWidgetsLiveActivity: Widget { //extension NearFutureWidgetsAttributes.ContentState {
var body: some WidgetConfiguration { // fileprivate static var smiley: NearFutureWidgetsAttributes.ContentState {
ActivityConfiguration(for: NearFutureWidgetsAttributes.self) { context in // NearFutureWidgetsAttributes.ContentState(emoji: "😀")
// Lock screen/banner UI goes here // }
VStack { //
Text("Hello \(context.state.emoji)") // fileprivate static var starEyes: NearFutureWidgetsAttributes.ContentState {
} // NearFutureWidgetsAttributes.ContentState(emoji: "🤩")
.activityBackgroundTint(Color.cyan) // }
.activitySystemActionForegroundColor(Color.black) //}
//
} dynamicIsland: { context in //#Preview("Notification", as: .content, using: NearFutureWidgetsAttributes.preview) {
DynamicIsland { // NearFutureWidgetsLiveActivity()
// Expanded UI goes here. Compose the expanded UI through //} contentStates: {
// various regions, like leading/trailing/center/bottom // NearFutureWidgetsAttributes.ContentState.smiley
DynamicIslandExpandedRegion(.leading) { // NearFutureWidgetsAttributes.ContentState.starEyes
Text("Leading") //}
}
DynamicIslandExpandedRegion(.trailing) {
Text("Trailing")
}
DynamicIslandExpandedRegion(.bottom) {
Text("Bottom \(context.state.emoji)")
// more content
}
} compactLeading: {
Text("L")
} compactTrailing: {
Text("T \(context.state.emoji)")
} minimal: {
Text(context.state.emoji)
}
.widgetURL(URL(string: "http://www.apple.com"))
.keylineTint(Color.red)
}
}
}
extension NearFutureWidgetsAttributes {
fileprivate static var preview: NearFutureWidgetsAttributes {
NearFutureWidgetsAttributes(name: "World")
}
}
extension NearFutureWidgetsAttributes.ContentState {
fileprivate static var smiley: NearFutureWidgetsAttributes.ContentState {
NearFutureWidgetsAttributes.ContentState(emoji: "😀")
}
fileprivate static var starEyes: NearFutureWidgetsAttributes.ContentState {
NearFutureWidgetsAttributes.ContentState(emoji: "🤩")
}
}
#Preview("Notification", as: .content, using: NearFutureWidgetsAttributes.preview) {
NearFutureWidgetsLiveActivity()
} contentStates: {
NearFutureWidgetsAttributes.ContentState.smiley
NearFutureWidgetsAttributes.ContentState.starEyes
}

View File

@@ -1,5 +1,6 @@
# NearFuture # NearFuture
[![AppStore Link](https://github.com/neon443/NearFuture/blob/main/NearFuture/Images/appstore.png?raw=true)](https://apps.apple.com/us/app/near-future-event-tracker/id6744963429)
[App Store](https://apps.apple.com/us/app/near-future-event-tracker/id6744963429)
**Near Future** is a SwiftUI App to help people track upcoming events - Holidays, Trips, Birthdays, Weddings, Anniversaries. **Near Future** is a SwiftUI App to help people track upcoming events - Holidays, Trips, Birthdays, Weddings, Anniversaries.

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 729 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

View File

@@ -0,0 +1,38 @@
{
"images" : [
{
"filename" : "bloo.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "blooDark.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"filename" : "NearFutureIconTint.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 712 KiB

View File

@@ -0,0 +1,38 @@
{
"images" : [
{
"filename" : "blue.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "blueDark.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"filename" : "NearFutureIconTint.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 KiB

View File

@@ -0,0 +1,38 @@
{
"images" : [
{
"filename" : "green.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "greenDark.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"filename" : "NearFutureIconTint.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 734 KiB

View File

@@ -0,0 +1,38 @@
{
"images" : [
{
"filename" : "pink.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "pinkDark.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"filename" : "NearFutureIconTint.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 KiB

View File

@@ -0,0 +1,38 @@
{
"images" : [
{
"filename" : "purple.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "purpleDark.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"filename" : "NearFutureIconTint.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 KiB

View File

@@ -0,0 +1,38 @@
{
"images" : [
{
"filename" : "red.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "redDark.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"filename" : "NearFutureIconTint.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 751 KiB

View File

@@ -0,0 +1,38 @@
{
"images" : [
{
"filename" : "yellow.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "yellowDark.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"filename" : "NearFutureIconTint.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 KiB

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

BIN
Resources/Grue.pxd Normal file
View File

Binary file not shown.

BIN
Resources/GrueDark.pxd Normal file
View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More