semi rewrite
fixed adding events new icon add archive view fixed sync between contentView & archiveview new help view new eventlistview new addeventbutton fixed widgets
16
Config.xcconfig
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// Config.xcconfig
|
||||||
|
// NearFuture
|
||||||
|
//
|
||||||
|
// Created by neon443 on 29/04/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Configuration settings file format documentation can be found at:
|
||||||
|
// https://developer.apple.com/documentation/xcode/adding-a-build-configuration-file-to-your-project
|
||||||
|
|
||||||
|
TEAM_ID = 8JGND254B7
|
||||||
|
BUNDLE_ID = com.neon443.NearFuture
|
||||||
|
GROUP_ID = group.NearFuture
|
||||||
|
VERSION = 3.0.1
|
||||||
|
NAME = Near Future
|
||||||
|
BUILD_NUMBER = 1
|
||||||
BIN
Images/NearFutureIcon.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
Images/NearFutureIcon.pxd
Normal file
BIN
Images/NearFutureIconDark.png
Normal file
|
After Width: | Height: | Size: 609 KiB |
BIN
Images/NearFutureIconDark.pxd
Normal file
BIN
Images/NearFutureIconTint.png
Normal file
|
After Width: | Height: | Size: 534 KiB |
BIN
Images/NearFutureIconTint.pxd
Normal file
BIN
Images/appstore.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
@@ -16,6 +16,8 @@
|
|||||||
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 */; };
|
A920C2C12D2403CA00E4F9B1 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C2C02D2403CA00E4F9B1 /* ContentView.swift */; };
|
||||||
A93BC0942D2B18A3002E8BBD /* StatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A93BC0932D2B18A3002E8BBD /* StatsView.swift */; };
|
A93BC0942D2B18A3002E8BBD /* StatsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A93BC0932D2B18A3002E8BBD /* StatsView.swift */; };
|
||||||
|
A977CC922DBBB48000DED8C0 /* ArchiveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A977CC912DBBB48000DED8C0 /* ArchiveView.swift */; };
|
||||||
|
A977CC9A2DBD74FE00DED8C0 /* HelpView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A977CC992DBD74FE00DED8C0 /* HelpView.swift */; };
|
||||||
A979F57F2D26B1300094C0B3 /* EditEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A979F57E2D26B1300094C0B3 /* EditEventView.swift */; };
|
A979F57F2D26B1300094C0B3 /* EditEventView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A979F57E2D26B1300094C0B3 /* EditEventView.swift */; };
|
||||||
A979F6052D270AF00094C0B3 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A979F6042D270AF00094C0B3 /* WidgetKit.framework */; };
|
A979F6052D270AF00094C0B3 /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A979F6042D270AF00094C0B3 /* WidgetKit.framework */; };
|
||||||
A979F6072D270AF00094C0B3 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A979F6062D270AF00094C0B3 /* SwiftUI.framework */; };
|
A979F6072D270AF00094C0B3 /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A979F6062D270AF00094C0B3 /* SwiftUI.framework */; };
|
||||||
@@ -61,6 +63,7 @@
|
|||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
A90FDE222DC0D4310012790C /* Config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Config.xcconfig; sourceTree = "<group>"; };
|
||||||
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 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = "<group>"; };
|
||||||
@@ -71,6 +74,8 @@
|
|||||||
A920C2B72D2401A300E4F9B1 /* AddEventView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddEventView.swift; sourceTree = "<group>"; };
|
A920C2B72D2401A300E4F9B1 /* AddEventView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddEventView.swift; sourceTree = "<group>"; };
|
||||||
A920C2C02D2403CA00E4F9B1 /* ContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
A920C2C02D2403CA00E4F9B1 /* ContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||||
A93BC0932D2B18A3002E8BBD /* StatsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsView.swift; sourceTree = "<group>"; };
|
A93BC0932D2B18A3002E8BBD /* StatsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatsView.swift; sourceTree = "<group>"; };
|
||||||
|
A977CC912DBBB48000DED8C0 /* 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>"; };
|
||||||
A979F57E2D26B1300094C0B3 /* EditEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditEventView.swift; sourceTree = "<group>"; };
|
A979F57E2D26B1300094C0B3 /* EditEventView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditEventView.swift; sourceTree = "<group>"; };
|
||||||
A979F58B2D2700680094C0B3 /* NearFutureWidgetsBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureWidgetsBundle.swift; sourceTree = "<group>"; };
|
A979F58B2D2700680094C0B3 /* NearFutureWidgetsBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureWidgetsBundle.swift; sourceTree = "<group>"; };
|
||||||
A979F58D2D2700680094C0B3 /* NearFutureWidgetsLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureWidgetsLiveActivity.swift; sourceTree = "<group>"; };
|
A979F58D2D2700680094C0B3 /* NearFutureWidgetsLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearFutureWidgetsLiveActivity.swift; sourceTree = "<group>"; };
|
||||||
@@ -128,6 +133,7 @@
|
|||||||
A920C27B2D24011300E4F9B1 = {
|
A920C27B2D24011300E4F9B1 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
A90FDE222DC0D4310012790C /* Config.xcconfig */,
|
||||||
A920C2862D24011400E4F9B1 /* NearFuture */,
|
A920C2862D24011400E4F9B1 /* NearFuture */,
|
||||||
A979F6082D270AF00094C0B3 /* NearFutureWidgets */,
|
A979F6082D270AF00094C0B3 /* NearFutureWidgets */,
|
||||||
A980FC382D93FB2B006A778F /* NearFutureTests */,
|
A980FC382D93FB2B006A778F /* NearFutureTests */,
|
||||||
@@ -149,16 +155,18 @@
|
|||||||
A920C2862D24011400E4F9B1 /* NearFuture */ = {
|
A920C2862D24011400E4F9B1 /* NearFuture */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
A979F57E2D26B1300094C0B3 /* EditEventView.swift */,
|
A920C2872D24011400E4F9B1 /* NearFutureApp.swift */,
|
||||||
A920C2B72D2401A300E4F9B1 /* AddEventView.swift */,
|
A920C28B2D24011400E4F9B1 /* Item.swift */,
|
||||||
A920C2C02D2403CA00E4F9B1 /* ContentView.swift */,
|
A920C2C02D2403CA00E4F9B1 /* ContentView.swift */,
|
||||||
A985104F2DB263F00013D5FF /* EventListView.swift */,
|
A985104F2DB263F00013D5FF /* EventListView.swift */,
|
||||||
|
A920C2B72D2401A300E4F9B1 /* AddEventView.swift */,
|
||||||
|
A979F57E2D26B1300094C0B3 /* EditEventView.swift */,
|
||||||
|
A977CC912DBBB48000DED8C0 /* ArchiveView.swift */,
|
||||||
A93BC0932D2B18A3002E8BBD /* StatsView.swift */,
|
A93BC0932D2B18A3002E8BBD /* StatsView.swift */,
|
||||||
|
A977CC992DBD74FE00DED8C0 /* HelpView.swift */,
|
||||||
A920C2B42D2401A100E4F9B1 /* SettingsView.swift */,
|
A920C2B42D2401A100E4F9B1 /* SettingsView.swift */,
|
||||||
A985104D2DB256430013D5FF /* iCloudSettingsView.swift */,
|
A985104D2DB256430013D5FF /* iCloudSettingsView.swift */,
|
||||||
A980FC302D920097006A778F /* Info.plist */,
|
A980FC302D920097006A778F /* Info.plist */,
|
||||||
A920C2872D24011400E4F9B1 /* NearFutureApp.swift */,
|
|
||||||
A920C28B2D24011400E4F9B1 /* Item.swift */,
|
|
||||||
A920C28D2D24011A00E4F9B1 /* Assets.xcassets */,
|
A920C28D2D24011A00E4F9B1 /* Assets.xcassets */,
|
||||||
A920C28F2D24011A00E4F9B1 /* NearFuture.entitlements */,
|
A920C28F2D24011A00E4F9B1 /* NearFuture.entitlements */,
|
||||||
A920C2902D24011A00E4F9B1 /* Preview Content */,
|
A920C2902D24011A00E4F9B1 /* Preview Content */,
|
||||||
@@ -283,7 +291,7 @@
|
|||||||
attributes = {
|
attributes = {
|
||||||
BuildIndependentTargetsInParallel = 1;
|
BuildIndependentTargetsInParallel = 1;
|
||||||
LastSwiftUpdateCheck = 1620;
|
LastSwiftUpdateCheck = 1620;
|
||||||
LastUpgradeCheck = 1620;
|
LastUpgradeCheck = 1630;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
A920C2832D24011300E4F9B1 = {
|
A920C2832D24011300E4F9B1 = {
|
||||||
CreatedOnToolsVersion = 15.4;
|
CreatedOnToolsVersion = 15.4;
|
||||||
@@ -356,9 +364,11 @@
|
|||||||
A98510502DB263F00013D5FF /* EventListView.swift in Sources */,
|
A98510502DB263F00013D5FF /* EventListView.swift in Sources */,
|
||||||
A920C2C12D2403CA00E4F9B1 /* ContentView.swift in Sources */,
|
A920C2C12D2403CA00E4F9B1 /* ContentView.swift in Sources */,
|
||||||
A920C2B82D2401A300E4F9B1 /* SettingsView.swift in Sources */,
|
A920C2B82D2401A300E4F9B1 /* SettingsView.swift in Sources */,
|
||||||
|
A977CC9A2DBD74FE00DED8C0 /* HelpView.swift in Sources */,
|
||||||
A920C28C2D24011400E4F9B1 /* Item.swift in Sources */,
|
A920C28C2D24011400E4F9B1 /* Item.swift in Sources */,
|
||||||
A920C2882D24011400E4F9B1 /* NearFutureApp.swift in Sources */,
|
A920C2882D24011400E4F9B1 /* NearFutureApp.swift in Sources */,
|
||||||
A93BC0942D2B18A3002E8BBD /* StatsView.swift in Sources */,
|
A93BC0942D2B18A3002E8BBD /* StatsView.swift in Sources */,
|
||||||
|
A977CC922DBBB48000DED8C0 /* ArchiveView.swift in Sources */,
|
||||||
A979F57F2D26B1300094C0B3 /* EditEventView.swift in Sources */,
|
A979F57F2D26B1300094C0B3 /* EditEventView.swift in Sources */,
|
||||||
A985104E2DB256430013D5FF /* iCloudSettingsView.swift in Sources */,
|
A985104E2DB256430013D5FF /* iCloudSettingsView.swift in Sources */,
|
||||||
);
|
);
|
||||||
@@ -435,6 +445,7 @@
|
|||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
DEVELOPMENT_TEAM = 8JGND254B7;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
@@ -462,6 +473,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;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@@ -501,6 +513,7 @@
|
|||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
DEVELOPMENT_TEAM = 8JGND254B7;
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
@@ -516,25 +529,27 @@
|
|||||||
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;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
A920C2AC2D24011B00E4F9B1 /* Debug */ = {
|
A920C2AC2D24011B00E4F9B1 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = A90FDE222DC0D4310012790C /* Config.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = NearFuture/NearFuture.entitlements;
|
CODE_SIGN_ENTITLEMENTS = NearFuture/NearFuture.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 25;
|
CURRENT_PROJECT_VERSION = "$(BUILD_NUMBER)";
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"NearFuture/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"NearFuture/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = 85Q9QG6DN7;
|
DEVELOPMENT_TEAM = "$(TEAM_ID)";
|
||||||
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_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;
|
||||||
@@ -546,16 +561,16 @@
|
|||||||
"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;
|
IPHONEOS_DEPLOYMENT_TARGET = 16.4;
|
||||||
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;
|
||||||
MARKETING_VERSION = 2.0;
|
MARKETING_VERSION = "$(VERSION)";
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"-Xlinker",
|
"-Xlinker",
|
||||||
"-interposable",
|
"-interposable",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.vape.NearFuture;
|
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID)";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
REGISTER_APP_GROUPS = NO;
|
REGISTER_APP_GROUPS = NO;
|
||||||
SDKROOT = auto;
|
SDKROOT = auto;
|
||||||
@@ -571,20 +586,21 @@
|
|||||||
};
|
};
|
||||||
A920C2AD2D24011B00E4F9B1 /* Release */ = {
|
A920C2AD2D24011B00E4F9B1 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = A90FDE222DC0D4310012790C /* Config.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = NearFuture/NearFuture.entitlements;
|
CODE_SIGN_ENTITLEMENTS = NearFuture/NearFuture.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 25;
|
CURRENT_PROJECT_VERSION = "$(BUILD_NUMBER)";
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"NearFuture/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"NearFuture/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = 85Q9QG6DN7;
|
DEVELOPMENT_TEAM = "$(TEAM_ID)";
|
||||||
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_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;
|
||||||
@@ -596,13 +612,13 @@
|
|||||||
"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;
|
IPHONEOS_DEPLOYMENT_TARGET = 16.4;
|
||||||
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;
|
||||||
MARKETING_VERSION = 2.0;
|
MARKETING_VERSION = "$(VERSION)";
|
||||||
OTHER_LDFLAGS = "";
|
OTHER_LDFLAGS = "";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.vape.NearFuture;
|
PRODUCT_BUNDLE_IDENTIFIER = "$(BUNDLE_ID)";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
REGISTER_APP_GROUPS = NO;
|
REGISTER_APP_GROUPS = NO;
|
||||||
SDKROOT = auto;
|
SDKROOT = auto;
|
||||||
@@ -618,13 +634,13 @@
|
|||||||
};
|
};
|
||||||
A979F6162D270AF90094C0B3 /* Debug */ = {
|
A979F6162D270AF90094C0B3 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = A90FDE222DC0D4310012790C /* Config.xcconfig */;
|
||||||
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;
|
||||||
CODE_SIGN_ENTITLEMENTS = NearFutureWidgets/NearFutureWidgetsExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = NearFutureWidgets/NearFutureWidgetsExtension.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 25;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = 85Q9QG6DN7;
|
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = NearFutureWidgets/Info.plist;
|
INFOPLIST_FILE = NearFutureWidgets/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = NearFutureWidgets;
|
INFOPLIST_KEY_CFBundleDisplayName = NearFutureWidgets;
|
||||||
@@ -635,12 +651,12 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 2.0;
|
MARKETING_VERSION = 3.0;
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"-Xlinker",
|
"-Xlinker",
|
||||||
"-interposable",
|
"-interposable",
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.vape.NearFuture.NearFutureWidgets;
|
PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFuture.widgets;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@@ -654,13 +670,13 @@
|
|||||||
};
|
};
|
||||||
A979F6172D270AF90094C0B3 /* Release */ = {
|
A979F6172D270AF90094C0B3 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = A90FDE222DC0D4310012790C /* Config.xcconfig */;
|
||||||
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;
|
||||||
CODE_SIGN_ENTITLEMENTS = NearFutureWidgets/NearFutureWidgetsExtension.entitlements;
|
CODE_SIGN_ENTITLEMENTS = NearFutureWidgets/NearFutureWidgetsExtension.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 25;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = 85Q9QG6DN7;
|
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = NearFutureWidgets/Info.plist;
|
INFOPLIST_FILE = NearFutureWidgets/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = NearFutureWidgets;
|
INFOPLIST_KEY_CFBundleDisplayName = NearFutureWidgets;
|
||||||
@@ -671,8 +687,8 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
"@executable_path/../../Frameworks",
|
"@executable_path/../../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 2.0;
|
MARKETING_VERSION = 3.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.vape.NearFuture.NearFutureWidgets;
|
PRODUCT_BUNDLE_IDENTIFIER = com.neon443.NearFuture.widgets;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
@@ -687,11 +703,11 @@
|
|||||||
};
|
};
|
||||||
A980FC3E2D93FB2B006A778F /* Debug */ = {
|
A980FC3E2D93FB2B006A778F /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = A90FDE222DC0D4310012790C /* Config.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = P6PV2R9443;
|
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 16;
|
IPHONEOS_DEPLOYMENT_TARGET = 16;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 13;
|
MACOSX_DEPLOYMENT_TARGET = 13;
|
||||||
@@ -713,11 +729,11 @@
|
|||||||
};
|
};
|
||||||
A980FC3F2D93FB2B006A778F /* Release */ = {
|
A980FC3F2D93FB2B006A778F /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = A90FDE222DC0D4310012790C /* Config.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
DEVELOPMENT_TEAM = P6PV2R9443;
|
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 16;
|
IPHONEOS_DEPLOYMENT_TARGET = 16;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 13;
|
MACOSX_DEPLOYMENT_TARGET = 13;
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
<?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>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1620"
|
LastUpgradeVersion = "1630"
|
||||||
version = "1.7">
|
version = "1.7">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1620"
|
LastUpgradeVersion = "1630"
|
||||||
wasCreatedForAppExtension = "YES"
|
wasCreatedForAppExtension = "YES"
|
||||||
version = "2.0">
|
version = "2.0">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
|
|||||||
@@ -4,6 +4,11 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>SchemeUserState</key>
|
<key>SchemeUserState</key>
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>NearFuture nodebug.xcscheme_^#shared#^_</key>
|
||||||
|
<dict>
|
||||||
|
<key>orderHint</key>
|
||||||
|
<integer>2</integer>
|
||||||
|
</dict>
|
||||||
<key>NearFuture.xcscheme_^#shared#^_</key>
|
<key>NearFuture.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
|
|||||||
@@ -21,12 +21,13 @@ struct AddEventView: View {
|
|||||||
@Binding var eventTime: Bool
|
@Binding var eventTime: Bool
|
||||||
@Binding var eventRecurrence: Event.RecurrenceType
|
@Binding var eventRecurrence: Event.RecurrenceType
|
||||||
|
|
||||||
@State var adding : Bool
|
@State var adding: Bool
|
||||||
|
@State var showNeedsNameAlert: Bool = false
|
||||||
@State var isSymbolPickerPresented = false
|
@State var isSymbolPickerPresented = false
|
||||||
|
|
||||||
@FocusState private var focusedField: Field?
|
@FocusState private var focusedField: Field?
|
||||||
private enum Field {
|
private enum Field {
|
||||||
case Name, Description
|
case Name, Notes
|
||||||
}
|
}
|
||||||
|
|
||||||
@Environment(\.dismiss) var dismiss
|
@Environment(\.dismiss) var dismiss
|
||||||
@@ -60,9 +61,8 @@ struct AddEventView: View {
|
|||||||
searchLabel: "Search...",
|
searchLabel: "Search...",
|
||||||
autoDismiss: true)
|
autoDismiss: true)
|
||||||
}
|
}
|
||||||
ColorPicker("", selection: $eventColor, supportsOpacity: true)
|
ColorPicker("", selection: $eventColor, supportsOpacity: false)
|
||||||
.fixedSize()
|
.fixedSize()
|
||||||
Divider()
|
|
||||||
ZStack {
|
ZStack {
|
||||||
TextField("Event Name", text: $eventName)
|
TextField("Event Name", text: $eventName)
|
||||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||||
@@ -71,7 +71,7 @@ struct AddEventView: View {
|
|||||||
.focused($focusedField, equals: Field.Name)
|
.focused($focusedField, equals: Field.Name)
|
||||||
.submitLabel(.next)
|
.submitLabel(.next)
|
||||||
.onSubmit {
|
.onSubmit {
|
||||||
focusedField = .Description
|
focusedField = .Notes
|
||||||
}
|
}
|
||||||
MagicClearButton(text: $eventName)
|
MagicClearButton(text: $eventName)
|
||||||
}
|
}
|
||||||
@@ -79,11 +79,11 @@ struct AddEventView: View {
|
|||||||
|
|
||||||
// dscription
|
// dscription
|
||||||
ZStack {
|
ZStack {
|
||||||
TextField("Event Description", text: $eventNotes)
|
TextField("Event Notes", text: $eventNotes)
|
||||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||||
.padding(.trailing, eventNotes.isEmpty ? 0 : 30)
|
.padding(.trailing, eventNotes.isEmpty ? 0 : 30)
|
||||||
.animation(.spring, value: eventNotes)
|
.animation(.spring, value: eventNotes)
|
||||||
.focused($focusedField, equals: Field.Description)
|
.focused($focusedField, equals: Field.Notes)
|
||||||
.submitLabel(.done)
|
.submitLabel(.done)
|
||||||
.onSubmit {
|
.onSubmit {
|
||||||
focusedField = nil
|
focusedField = nil
|
||||||
@@ -130,8 +130,26 @@ struct AddEventView: View {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// save button only show iff adding new event
|
.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 {
|
if adding {
|
||||||
Button {
|
Button {
|
||||||
viewModel.addEvent(
|
viewModel.addEvent(
|
||||||
@@ -149,12 +167,25 @@ struct AddEventView: View {
|
|||||||
)
|
)
|
||||||
resetAddEventView()
|
resetAddEventView()
|
||||||
} label: {
|
} label: {
|
||||||
Text("Save Event")
|
Text("Save")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
.cornerRadius(10)
|
.cornerRadius(10)
|
||||||
.buttonStyle(BorderedProminentButtonStyle())
|
.buttonStyle(BorderedProminentButtonStyle())
|
||||||
}
|
}
|
||||||
.disabled(eventName.isEmpty)
|
.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 {
|
if eventName.isEmpty {
|
||||||
HStack {
|
HStack {
|
||||||
Image(systemName: "exclamationmark")
|
Image(systemName: "exclamationmark")
|
||||||
@@ -164,32 +195,23 @@ struct AddEventView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle("\(adding ? "Add Event" : "")")
|
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
|
||||||
.toolbar {
|
|
||||||
ToolbarItem(placement: .topBarTrailing) {
|
|
||||||
if adding {
|
|
||||||
Button() {
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
Image(systemName: "xmark.circle.fill")
|
|
||||||
.symbolRenderingMode(.hierarchical)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func resetAddEventView() {
|
func resetAddEventView() {
|
||||||
//reset addeventView
|
//reset addeventView
|
||||||
eventName = ""
|
eventName = viewModel.template.name
|
||||||
eventSymbol = "star"
|
eventComplete = viewModel.template.complete
|
||||||
|
eventCompleteDesc = viewModel.template.completeDesc
|
||||||
|
eventSymbol = viewModel.template.symbol
|
||||||
eventColor = randomColor()
|
eventColor = randomColor()
|
||||||
eventNotes = ""
|
eventNotes = viewModel.template.notes
|
||||||
eventDate = Date()
|
eventDate = viewModel.template.date
|
||||||
eventRecurrence = .none
|
eventTime = viewModel.template.time
|
||||||
|
eventRecurrence = viewModel.template.recurrence
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
struct MagicClearButton: View {
|
struct MagicClearButton: View {
|
||||||
@Binding var text: String
|
@Binding var text: String
|
||||||
@@ -213,17 +235,24 @@ struct MagicClearButton: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
|
let vm = dummyEventViewModel()
|
||||||
|
Color.orange
|
||||||
|
.ignoresSafeArea(.all)
|
||||||
|
.sheet(isPresented: .constant(true)) {
|
||||||
AddEventView(
|
AddEventView(
|
||||||
viewModel: EventViewModel(),
|
viewModel: vm,
|
||||||
eventName: .constant("Birthday"),
|
eventName: .constant(vm.template.notes),
|
||||||
eventComplete: .constant(false),
|
eventComplete: .constant(vm.template.complete),
|
||||||
eventCompleteDesc: .constant(""),
|
eventCompleteDesc: .constant(vm.template.completeDesc),
|
||||||
eventSymbol: .constant("star"),
|
eventSymbol: .constant(vm.template.symbol),
|
||||||
eventColor: .constant(Color.red),
|
eventColor: .constant(vm.template.color.color),
|
||||||
eventNotes: .constant("A very special day"),
|
eventNotes: .constant(vm.template.notes),
|
||||||
eventDate: .constant(Date()),
|
eventDate: .constant(vm.template.date),
|
||||||
eventTime: .constant(true),
|
eventTime: .constant(vm.template.time),
|
||||||
eventRecurrence: .constant(.monthly),
|
eventRecurrence: .constant(vm.template.recurrence),
|
||||||
adding: true
|
adding: true
|
||||||
)
|
)
|
||||||
|
.presentationDragIndicator(.visible)
|
||||||
|
.presentationBackground(.ultraThinMaterial)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
66
NearFuture/ArchiveView.swift
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// ArchiveView.swift
|
||||||
|
// NearFuture
|
||||||
|
//
|
||||||
|
// Created by neon443 on 25/04/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ArchiveView: View {
|
||||||
|
@ObservedObject var viewModel: EventViewModel
|
||||||
|
@State var showAddEvent: Bool = false
|
||||||
|
@State var hey: UUID = UUID()
|
||||||
|
init(viewModel: EventViewModel) {
|
||||||
|
self.viewModel = viewModel
|
||||||
|
}
|
||||||
|
var body: some View {
|
||||||
|
NavigationStack {
|
||||||
|
ZStack {
|
||||||
|
backgroundGradient
|
||||||
|
if viewModel.events.filter({$0.complete}).isEmpty {
|
||||||
|
HelpView(showAddEvent: $showAddEvent)
|
||||||
|
} else {
|
||||||
|
ScrollView {
|
||||||
|
ForEach(viewModel.events.filter({$0.complete})) { event in
|
||||||
|
EventListView(viewModel: viewModel, event: event)
|
||||||
|
}
|
||||||
|
.padding(.horizontal)
|
||||||
|
.id(hey)
|
||||||
|
.onReceive(viewModel.objectWillChange) {
|
||||||
|
hey = UUID()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.scrollContentBackground(.hidden)
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .topBarTrailing) {
|
||||||
|
AddEventButton(showingAddEventView: $showAddEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sheet(isPresented: $showAddEvent) {
|
||||||
|
AddEventView(
|
||||||
|
viewModel: viewModel,
|
||||||
|
eventName: $viewModel.editableTemplate.name,
|
||||||
|
eventComplete: $viewModel.editableTemplate.complete,
|
||||||
|
eventCompleteDesc: $viewModel.editableTemplate.completeDesc,
|
||||||
|
eventSymbol: $viewModel.editableTemplate.symbol,
|
||||||
|
eventColor: $viewModel.editableTemplate.color.colorBind,
|
||||||
|
eventNotes: $viewModel.editableTemplate.notes,
|
||||||
|
eventDate: $viewModel.editableTemplate.date,
|
||||||
|
eventTime: $viewModel.editableTemplate.time,
|
||||||
|
eventRecurrence: $viewModel.editableTemplate.recurrence,
|
||||||
|
adding: true
|
||||||
|
)
|
||||||
|
.presentationDragIndicator(.visible)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
ArchiveView(viewModel: dummyEventViewModel())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "0.000",
|
"blue" : "0.000",
|
||||||
"green" : "0.375",
|
"green" : "0.376",
|
||||||
"red" : "1.000"
|
"red" : "1.000"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,31 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "telescope-pointed-at-the-milky-way-galaxy-royalty-free-image-93204189-1533148569-2899733190.jpg",
|
"filename" : "NearFutureIcon.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "NearFutureIconDark.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "tinted"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "NearFutureIconTint.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"platform" : "ios",
|
"platform" : "ios",
|
||||||
"size" : "1024x1024"
|
"size" : "1024x1024"
|
||||||
|
|||||||
BIN
NearFuture/Assets.xcassets/AppIcon.appiconset/NearFutureIcon.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 609 KiB |
|
After Width: | Height: | Size: 534 KiB |
|
Before Width: | Height: | Size: 218 KiB |
38
NearFuture/Assets.xcassets/bgTop.colorset/Contents.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "0.800",
|
||||||
|
"blue" : "0.576",
|
||||||
|
"green" : "0.557",
|
||||||
|
"red" : "0.557"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "0.300",
|
||||||
|
"blue" : "0.576",
|
||||||
|
"green" : "0.557",
|
||||||
|
"red" : "0.557"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
38
NearFuture/Assets.xcassets/one.colorset/Contents.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.000",
|
||||||
|
"green" : "0.000",
|
||||||
|
"red" : "0.000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "1.000",
|
||||||
|
"green" : "1.000",
|
||||||
|
"red" : "1.000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
38
NearFuture/Assets.xcassets/two.colorset/Contents.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "1.000",
|
||||||
|
"green" : "1.000",
|
||||||
|
"red" : "1.000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.000",
|
||||||
|
"green" : "0.000",
|
||||||
|
"red" : "0.000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,9 +11,16 @@ import SwiftData
|
|||||||
enum Field {
|
enum Field {
|
||||||
case Search
|
case Search
|
||||||
}
|
}
|
||||||
|
enum Tab {
|
||||||
|
case Home
|
||||||
|
case Archive
|
||||||
|
case Statistics
|
||||||
|
case Settings
|
||||||
|
case Gradient
|
||||||
|
}
|
||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
@StateObject private var viewModel = EventViewModel()
|
@StateObject var viewModel: EventViewModel
|
||||||
@State private var eventName = ""
|
@State private var eventName = ""
|
||||||
@State private var eventComplete = false
|
@State private var eventComplete = false
|
||||||
@State private var eventCompleteDesc = ""
|
@State private var eventCompleteDesc = ""
|
||||||
@@ -23,6 +30,7 @@ struct ContentView: View {
|
|||||||
@State private var eventDate = Date()
|
@State private var eventDate = Date()
|
||||||
@State private var eventTime = false
|
@State private var eventTime = false
|
||||||
@State private var eventRecurrence: Event.RecurrenceType = .none
|
@State private var eventRecurrence: Event.RecurrenceType = .none
|
||||||
|
@State var hey: UUID = UUID()
|
||||||
@State private var showingAddEventView = false
|
@State private var showingAddEventView = false
|
||||||
@State private var searchInput: String = ""
|
@State private var searchInput: String = ""
|
||||||
var filteredEvents: [Event] {
|
var filteredEvents: [Event] {
|
||||||
@@ -36,31 +44,6 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Environment(\.colorScheme) var appearance
|
|
||||||
private var backgroundGradient: LinearGradient {
|
|
||||||
switch appearance {
|
|
||||||
case .light:
|
|
||||||
return LinearGradient(
|
|
||||||
gradient: Gradient(colors: [.gray.opacity(0.2), .white]),
|
|
||||||
startPoint: .top,
|
|
||||||
endPoint: .bottom
|
|
||||||
)
|
|
||||||
case .dark:
|
|
||||||
return LinearGradient(
|
|
||||||
gradient: Gradient(colors: [.gray.opacity(0.2), .black]),
|
|
||||||
startPoint: .top,
|
|
||||||
endPoint: .bottom)
|
|
||||||
@unknown default:
|
|
||||||
//red bg gradient for uknown appearance
|
|
||||||
return LinearGradient(
|
|
||||||
gradient: Gradient(colors: [.red, .black]),
|
|
||||||
startPoint: .bottom,
|
|
||||||
endPoint: .top
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@State var showSettings: Bool = false
|
|
||||||
|
|
||||||
var noEvents: Bool {
|
var noEvents: Bool {
|
||||||
if viewModel.events.count == 0 {
|
if viewModel.events.count == 0 {
|
||||||
return true
|
return true
|
||||||
@@ -70,40 +53,43 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@FocusState private var focusedField: Field?
|
@FocusState private var focusedField: Field?
|
||||||
|
@FocusState private var focusedTab: Tab?
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
TabView {
|
TabView {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
ZStack {
|
ZStack {
|
||||||
backgroundGradient
|
backgroundGradient
|
||||||
.ignoresSafeArea(.all)
|
|
||||||
VStack {
|
VStack {
|
||||||
ZStack {
|
ZStack {
|
||||||
TextField(
|
SearchBar(searchInput: $searchInput)
|
||||||
"\(Image(systemName: "magnifyingglass")) Search",
|
|
||||||
text: $searchInput
|
|
||||||
)
|
|
||||||
.padding(.trailing, searchInput.isEmpty ? 0 : 30)
|
|
||||||
.animation(.spring, value: searchInput)
|
|
||||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
|
||||||
.focused($focusedField, equals: Field.Search)
|
.focused($focusedField, equals: Field.Search)
|
||||||
.onSubmit {
|
.onSubmit {
|
||||||
focusedField = nil
|
focusedField = nil
|
||||||
}
|
}
|
||||||
.submitLabel(.done)
|
|
||||||
MagicClearButton(text: $searchInput)
|
MagicClearButton(text: $searchInput)
|
||||||
|
.onTapGesture {
|
||||||
|
focusedField = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
List {
|
if filteredEvents.isEmpty && !searchInput.isEmpty {
|
||||||
|
HelpView(searchInput: $searchInput, focusedField: focusedField)
|
||||||
|
} else {
|
||||||
|
ScrollView {
|
||||||
ForEach(filteredEvents) { event in
|
ForEach(filteredEvents) { event in
|
||||||
EventListView(viewModel: viewModel, event: event)
|
EventListView(viewModel: viewModel, event: event)
|
||||||
}
|
}
|
||||||
.onDelete(perform: viewModel.removeEvent)
|
.onDelete(perform: viewModel.removeEvent)
|
||||||
if !searchInput.isEmpty {
|
.id(hey)
|
||||||
SearchHelp(
|
.onReceive(viewModel.objectWillChange) {
|
||||||
searchInput: $searchInput,
|
hey = UUID()
|
||||||
focusedField: _focusedField
|
}
|
||||||
)
|
.padding(.horizontal)
|
||||||
|
if /*!searchInput.isEmpty && */filteredEvents.isEmpty {
|
||||||
|
HelpView(searchInput: $searchInput, focusedField: focusedField)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,16 +109,12 @@ struct ContentView: View {
|
|||||||
eventRecurrence: $eventRecurrence,
|
eventRecurrence: $eventRecurrence,
|
||||||
adding: true //adding event
|
adding: true //adding event
|
||||||
)
|
)
|
||||||
|
.presentationDragIndicator(.visible)
|
||||||
|
.presentationBackground(.ultraThinMaterial)
|
||||||
}
|
}
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem(placement: .topBarTrailing) {
|
ToolbarItem(placement: .topBarTrailing) {
|
||||||
Button() {
|
AddEventButton(showingAddEventView: $showingAddEventView)
|
||||||
showingAddEventView.toggle()
|
|
||||||
} label: {
|
|
||||||
Image(systemName: "plus.circle")
|
|
||||||
.resizable()
|
|
||||||
.scaledToFit()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,44 +122,76 @@ struct ContentView: View {
|
|||||||
.tabItem {
|
.tabItem {
|
||||||
Label("Home", systemImage: "house")
|
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)
|
StatsView(viewModel: viewModel)
|
||||||
.tabItem {
|
.tabItem {
|
||||||
Label("Statistics", systemImage: "chart.pie")
|
Label("Statistics", systemImage: "chart.pie")
|
||||||
}
|
}
|
||||||
|
.focused($focusedTab, equals: Tab.Statistics)
|
||||||
SettingsView(viewModel: viewModel)
|
SettingsView(viewModel: viewModel)
|
||||||
.tabItem {
|
.tabItem {
|
||||||
Label("Settings", systemImage: "gear")
|
Label("Settings", systemImage: "gear")
|
||||||
}
|
}
|
||||||
}
|
.focused($focusedTab, equals: Tab.Settings)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SearchHelp: View {
|
|
||||||
@Binding var searchInput: String
|
|
||||||
@FocusState var focusedField: Field?
|
|
||||||
var body: some View {
|
|
||||||
HStack {
|
|
||||||
Image(systemName: "questionmark.square.dashed")
|
|
||||||
.resizable()
|
|
||||||
.scaledToFit()
|
|
||||||
.frame(width: 30, height: 30)
|
|
||||||
.padding(.trailing)
|
|
||||||
Text("Can't find what you're looking for?")
|
|
||||||
}
|
|
||||||
Text("Tip: The Search bar searches event names and notes")
|
|
||||||
Button() {
|
|
||||||
searchInput = ""
|
|
||||||
focusedField = nil
|
|
||||||
} label: {
|
|
||||||
HStack {
|
|
||||||
Image(systemName: "xmark")
|
|
||||||
Text("Clear Filters")
|
|
||||||
}
|
|
||||||
.foregroundStyle(Color.accentColor)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
ContentView()
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,38 +12,7 @@ struct EditEventView: View {
|
|||||||
@ObservedObject var viewModel: EventViewModel
|
@ObservedObject var viewModel: EventViewModel
|
||||||
@Binding var event: Event
|
@Binding var event: Event
|
||||||
|
|
||||||
@State private var eventName: String
|
|
||||||
@State private var eventComplete: Bool
|
|
||||||
@State private var eventCompleteDesc: String
|
|
||||||
@State private var eventSymbol: String
|
|
||||||
@State private var eventColor: Color
|
|
||||||
@State private var eventNotes: String
|
|
||||||
@State private var eventDate: Date
|
|
||||||
@State private var eventTime: Bool
|
|
||||||
@State private var eventRecurrence: Event.RecurrenceType
|
|
||||||
|
|
||||||
init(viewModel: EventViewModel, event: Binding<Event>) {
|
|
||||||
self.viewModel = viewModel
|
|
||||||
_event = event
|
|
||||||
_eventName = State(initialValue: event.wrappedValue.name)
|
|
||||||
_eventComplete = State(initialValue: event.wrappedValue.complete)
|
|
||||||
_eventCompleteDesc = State(initialValue: event.wrappedValue.completeDesc)
|
|
||||||
_eventSymbol = State(initialValue: event.wrappedValue.symbol)
|
|
||||||
_eventColor = State(initialValue: event.wrappedValue.color.color)
|
|
||||||
_eventNotes = State(initialValue: event.wrappedValue.notes)
|
|
||||||
_eventDate = State(initialValue: event.wrappedValue.date)
|
|
||||||
_eventTime = State(initialValue: event.wrappedValue.time)
|
|
||||||
_eventRecurrence = State(initialValue: event.wrappedValue.recurrence)
|
|
||||||
}
|
|
||||||
|
|
||||||
fileprivate func saveEdits() {
|
fileprivate func saveEdits() {
|
||||||
event.name = eventName
|
|
||||||
event.symbol = eventSymbol
|
|
||||||
event.color = ColorCodable(eventColor)
|
|
||||||
event.notes = eventNotes
|
|
||||||
event.date = eventDate
|
|
||||||
event.recurrence = eventRecurrence
|
|
||||||
|
|
||||||
//if there is an event in vM.events with the id of the event we r editing,
|
//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
|
//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
|
if let index = viewModel.events.firstIndex(where: { xEvent in
|
||||||
@@ -59,15 +28,15 @@ struct EditEventView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
AddEventView(
|
AddEventView(
|
||||||
viewModel: viewModel,
|
viewModel: viewModel,
|
||||||
eventName: $eventName,
|
eventName: $event.name,
|
||||||
eventComplete: $eventComplete,
|
eventComplete: $event.complete,
|
||||||
eventCompleteDesc: $eventCompleteDesc,
|
eventCompleteDesc: $event.completeDesc,
|
||||||
eventSymbol: $eventSymbol,
|
eventSymbol: $event.symbol,
|
||||||
eventColor: $eventColor,
|
eventColor: $event.color.colorBind,
|
||||||
eventNotes: $eventNotes,
|
eventNotes: $event.notes,
|
||||||
eventDate: $eventDate,
|
eventDate: $event.date,
|
||||||
eventTime: $eventTime,
|
eventTime: $event.time,
|
||||||
eventRecurrence: $eventRecurrence,
|
eventRecurrence: $event.recurrence,
|
||||||
adding: false //bc we editing existing event
|
adding: false //bc we editing existing event
|
||||||
)
|
)
|
||||||
.navigationTitle("Edit Event")
|
.navigationTitle("Edit Event")
|
||||||
@@ -77,18 +46,18 @@ struct EditEventView: View {
|
|||||||
saveEdits()
|
saveEdits()
|
||||||
} label: {
|
} label: {
|
||||||
Text("Done")
|
Text("Done")
|
||||||
|
.bold()
|
||||||
}
|
}
|
||||||
.disabled(eventName == "")
|
.disabled(event.name == "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
|
let vm = dummyEventViewModel()
|
||||||
EditEventView(
|
EditEventView(
|
||||||
viewModel: EventViewModel(),
|
viewModel: vm,
|
||||||
event: .constant(
|
event: .constant(vm.example)
|
||||||
EventViewModel().example
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,78 +19,64 @@ struct EventListView: View {
|
|||||||
event: $event
|
event: $event
|
||||||
)
|
)
|
||||||
} label: {
|
} label: {
|
||||||
|
ZStack {
|
||||||
HStack {
|
HStack {
|
||||||
RoundedRectangle(cornerRadius: 5)
|
RoundedRectangle(cornerRadius: 5)
|
||||||
.frame(width: 5)
|
.frame(width: 7)
|
||||||
.foregroundStyle(
|
.foregroundStyle(
|
||||||
event.color.color.opacity(
|
event.color.color.opacity(
|
||||||
event.complete ? 0.5 : 1
|
event.complete ? 0.5 : 1
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.padding(.leading, -10)
|
|
||||||
.padding(.vertical, 5)
|
|
||||||
.animation(.spring, value: event.complete)
|
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
HStack {
|
HStack {
|
||||||
Image(systemName: event.symbol)
|
Image(systemName: event.symbol)
|
||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(width: 20, height: 20)
|
.frame(width: 20, height: 20)
|
||||||
|
.shadow(radius: 5)
|
||||||
.foregroundStyle(
|
.foregroundStyle(
|
||||||
event.color.color.opacity(
|
.one.opacity(
|
||||||
event.complete ? 0.5 : 1
|
event.complete ? 0.5 : 1
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.animation(.spring, value: event.complete)
|
|
||||||
Text("\(event.name)")
|
Text("\(event.name)")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
|
.foregroundStyle(.one)
|
||||||
.strikethrough(event.complete)
|
.strikethrough(event.complete)
|
||||||
.animation(.spring, value: event.complete)
|
|
||||||
}
|
}
|
||||||
if !event.notes.isEmpty {
|
if !event.notes.isEmpty {
|
||||||
Text(event.notes)
|
Text(event.notes)
|
||||||
.font(.subheadline)
|
.font(.subheadline)
|
||||||
.foregroundColor(.gray)
|
.foregroundStyle(.one.opacity(0.8))
|
||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
event.date.formatted(
|
event.date.formatted(
|
||||||
date: .long,
|
date: .long,
|
||||||
time: event.time ? .standard : .omitted
|
time: event.time ? .shortened : .omitted
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.font(.subheadline)
|
.font(.subheadline)
|
||||||
.foregroundStyle(
|
.foregroundStyle(
|
||||||
event.color.color.opacity(
|
.one.opacity(
|
||||||
event.complete ? 0.5 : 1
|
event.complete ? 0.5 : 1
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.animation(.spring, value: event.complete)
|
|
||||||
if event.recurrence != .none {
|
if event.recurrence != .none {
|
||||||
Text("Recurs \(event.recurrence.rawValue)")
|
Text("Occurs \(event.recurrence.rawValue)")
|
||||||
.font(.subheadline)
|
.font(.subheadline)
|
||||||
.foregroundStyle(
|
.foregroundStyle(
|
||||||
.primary.opacity(
|
.one.opacity(event.complete ? 0.5 : 1))
|
||||||
event.complete ? 0.5 : 1
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.animation(.spring, value: event.complete)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
Text("\(daysUntilEvent(event.date, short: false))")
|
Text("\(daysUntilEvent(event.date, short: false))")
|
||||||
.font(.subheadline)
|
.font(.subheadline)
|
||||||
.foregroundStyle(
|
.foregroundStyle(.one)
|
||||||
event.color.color.opacity(
|
|
||||||
event.complete ? 0.5 : 1
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.animation(.spring, value: event.complete)
|
|
||||||
}
|
}
|
||||||
Button() {
|
Button() {
|
||||||
withAnimation(.spring) {
|
withAnimation {
|
||||||
event.complete.toggle()
|
event.complete.toggle()
|
||||||
}
|
}
|
||||||
let eventToModify = viewModel.events.firstIndex() { currEvent in
|
let eventToModify = viewModel.events.firstIndex() { currEvent in
|
||||||
@@ -99,7 +85,6 @@ struct EventListView: View {
|
|||||||
if let eventToModify = eventToModify {
|
if let eventToModify = eventToModify {
|
||||||
viewModel.events[eventToModify] = event
|
viewModel.events[eventToModify] = event
|
||||||
viewModel.saveEvents()
|
viewModel.saveEvents()
|
||||||
viewModel.loadEvents()
|
|
||||||
}
|
}
|
||||||
} label: {
|
} label: {
|
||||||
if event.complete {
|
if event.complete {
|
||||||
@@ -110,6 +95,7 @@ struct EventListView: View {
|
|||||||
.resizable()
|
.resizable()
|
||||||
.foregroundStyle(.white)
|
.foregroundStyle(.white)
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
|
.bold()
|
||||||
.frame(width: 15)
|
.frame(width: 15)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -121,16 +107,61 @@ struct EventListView: View {
|
|||||||
}
|
}
|
||||||
.buttonStyle(.borderless)
|
.buttonStyle(.borderless)
|
||||||
.frame(maxWidth: 25, maxHeight: 25)
|
.frame(maxWidth: 25, maxHeight: 25)
|
||||||
.animation(.spring, value: event.complete)
|
.shadow(radius: 5)
|
||||||
|
.padding(.trailing, 5)
|
||||||
|
}
|
||||||
|
.padding(.vertical, 5)
|
||||||
|
.background(.ultraThinMaterial)
|
||||||
|
.overlay(
|
||||||
|
RoundedRectangle(cornerRadius: 10)
|
||||||
|
.stroke(
|
||||||
|
.one.opacity(appearance == .dark ? 0.5 : 1),
|
||||||
|
lineWidth: 1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.clipShape(
|
||||||
|
RoundedRectangle(cornerRadius: 10)
|
||||||
|
)
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
}
|
||||||
|
.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") {
|
#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(
|
EventListView(
|
||||||
viewModel: EventViewModel(),
|
viewModel: vm,
|
||||||
event:
|
event: event
|
||||||
EventViewModel().example
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 10)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
112
NearFuture/HelpView.swift
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
//
|
||||||
|
// ArchiveHelp.swift
|
||||||
|
// NearFuture
|
||||||
|
//
|
||||||
|
// Created by neon443 on 26/04/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
enum HelpType {
|
||||||
|
case Search
|
||||||
|
case Archive
|
||||||
|
}
|
||||||
|
|
||||||
|
struct HelpView: View {
|
||||||
|
/// initialises a Search HelpView
|
||||||
|
///
|
||||||
|
init(searchInput: Binding<String>, focusedField: Field?) {
|
||||||
|
_searchInput = searchInput
|
||||||
|
self.helpType = .Search
|
||||||
|
_showAddEvent = .constant(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// initialises an Archive HelpView
|
||||||
|
///
|
||||||
|
init(showAddEvent: Binding<Bool>) {
|
||||||
|
_showAddEvent = showAddEvent
|
||||||
|
self.helpType = .Archive
|
||||||
|
_searchInput = .constant("")
|
||||||
|
self.focusedField = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
@Binding var searchInput: String
|
||||||
|
@FocusState var focusedField: Field?
|
||||||
|
|
||||||
|
@Binding var showAddEvent: Bool
|
||||||
|
|
||||||
|
var helpType: HelpType
|
||||||
|
var details: (
|
||||||
|
symbol: String,
|
||||||
|
title: String,
|
||||||
|
body: String,
|
||||||
|
buttonAction: () -> (),
|
||||||
|
buttonSymbol: String,
|
||||||
|
buttonText: String
|
||||||
|
) {
|
||||||
|
switch helpType {
|
||||||
|
case .Search:
|
||||||
|
return (
|
||||||
|
symbol: "questionmark.app.dashed",
|
||||||
|
title: "Looking for something?",
|
||||||
|
body: "Tip: The Search bar searches event names and notes.",
|
||||||
|
buttonAction: {
|
||||||
|
searchInput = ""
|
||||||
|
focusedField = nil
|
||||||
|
},
|
||||||
|
buttonSymbol: "xmark",
|
||||||
|
buttonText: "Clear Filters"
|
||||||
|
)
|
||||||
|
case .Archive:
|
||||||
|
return (
|
||||||
|
symbol: "eyes",
|
||||||
|
title: "Nothing to see here...",
|
||||||
|
body: "The Archive contains events that have been marked as complete.",
|
||||||
|
buttonAction: {
|
||||||
|
showAddEvent.toggle()
|
||||||
|
},
|
||||||
|
buttonSymbol: "plus",
|
||||||
|
buttonText: "Create an event"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var body: some View {
|
||||||
|
List {
|
||||||
|
ZStack {
|
||||||
|
Color(.accent)
|
||||||
|
.opacity(0.4)
|
||||||
|
.padding(.horizontal, -15)
|
||||||
|
.blur(radius: 5)
|
||||||
|
HStack {
|
||||||
|
Image(systemName: details.symbol)
|
||||||
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
|
.frame(width: 30, height: 30)
|
||||||
|
.padding(.trailing)
|
||||||
|
Text(details.title)
|
||||||
|
.bold()
|
||||||
|
.font(.title2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.listRowSeparator(.hidden)
|
||||||
|
Text(details.body)
|
||||||
|
Button() {
|
||||||
|
details.buttonAction()
|
||||||
|
} label: {
|
||||||
|
HStack {
|
||||||
|
Image(systemName: details.buttonSymbol)
|
||||||
|
.bold()
|
||||||
|
Text(details.buttonText)
|
||||||
|
}
|
||||||
|
.foregroundStyle(Color.accentColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.scrollContentBackground(.hidden)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
HelpView(searchInput: .constant(""), focusedField: nil)
|
||||||
|
HelpView(showAddEvent: .constant(false))
|
||||||
|
}
|
||||||
@@ -40,57 +40,38 @@ struct ColorCodable: Codable {
|
|||||||
var red: Double
|
var red: Double
|
||||||
var green: Double
|
var green: Double
|
||||||
var blue: Double
|
var blue: Double
|
||||||
var alpha: Double
|
|
||||||
//for the brainrot kids: alpha is the opacity/transparency of the color,
|
|
||||||
//alpha == 0 completely transparent
|
|
||||||
//alpha == 1 completely opaque
|
|
||||||
|
|
||||||
// var color: Color {
|
|
||||||
// get {
|
|
||||||
// Color(red: red, green: green, blue: blue, opacity: alpha)
|
|
||||||
// }
|
|
||||||
// set {
|
|
||||||
// self.red = newValue.resolve(in: red)
|
|
||||||
// self.green = newValue.resolve(in: green)
|
|
||||||
// self.blue = newValue.resolve(in: blue)
|
|
||||||
// self.alpha = newValue.resolve(in: alpha)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
var color: Color {
|
var color: Color {
|
||||||
Color(red: red, green: green, blue: blue, opacity: alpha)
|
Color(red: red, green: green, blue: blue)
|
||||||
}
|
}
|
||||||
var colorBind: Color {
|
var colorBind: Color {
|
||||||
get {
|
get {
|
||||||
return Color(
|
return Color(
|
||||||
red: red,
|
red: red,
|
||||||
green: green,
|
green: green,
|
||||||
blue: blue,
|
blue: blue
|
||||||
opacity: alpha
|
|
||||||
)
|
)
|
||||||
} set {
|
} set {
|
||||||
let cc = ColorCodable(newValue)
|
let cc = ColorCodable(newValue)
|
||||||
red = cc.red
|
self.red = cc.red
|
||||||
green = cc.green
|
self.green = cc.green
|
||||||
blue = cc.blue
|
self.blue = cc.blue
|
||||||
alpha = cc.alpha
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(_ color: Color) {
|
init(_ color: Color) {
|
||||||
let uiColor = UIColor(color)
|
let uiColor = UIColor(color)
|
||||||
var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
|
var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 1.0
|
||||||
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
|
uiColor.getRed(&r, green: &g, blue: &b, alpha: &a)
|
||||||
|
|
||||||
self.red = Double(r)
|
self.red = Double(r)
|
||||||
self.green = Double(g)
|
self.green = Double(g)
|
||||||
self.blue = Double(b)
|
self.blue = Double(b)
|
||||||
self.alpha = Double(a)
|
|
||||||
}
|
}
|
||||||
init(red: Double, green: Double, blue: Double, alpha: Double = 1.0) {
|
init(red: Double, green: Double, blue: Double) {
|
||||||
self.red = red
|
self.red = red
|
||||||
self.green = green
|
self.green = green
|
||||||
self.blue = blue
|
self.blue = blue
|
||||||
self.alpha = alpha
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +101,18 @@ class EventViewModel: ObservableObject {
|
|||||||
@Published var events: [Event] = []
|
@Published var events: [Event] = []
|
||||||
@Published var icloudData: [Event] = []
|
@Published var icloudData: [Event] = []
|
||||||
|
|
||||||
@Published var template: Event = 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: "",
|
name: "",
|
||||||
complete: false,
|
complete: false,
|
||||||
completeDesc: "",
|
completeDesc: "",
|
||||||
@@ -148,12 +140,14 @@ class EventViewModel: ObservableObject {
|
|||||||
@Published var localEventCount: Int = 0
|
@Published var localEventCount: Int = 0
|
||||||
@Published var syncStatus: String = "Not Synced"
|
@Published var syncStatus: String = "Not Synced"
|
||||||
|
|
||||||
init() {
|
init(load: Bool = true) {
|
||||||
|
if load {
|
||||||
loadEvents()
|
loadEvents()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//appgroup or regular userdefaults
|
//appgroup or regular userdefaults
|
||||||
let appGroupUserDefaults = UserDefaults(suiteName: "group.com.neon443.NearFuture") ?? UserDefaults.standard
|
let appGroupUserDefaults = UserDefaults(suiteName: "group.NearFuture") ?? UserDefaults.standard
|
||||||
|
|
||||||
//icloud store
|
//icloud store
|
||||||
let icloudStore = NSUbiquitousKeyValueStore.default
|
let icloudStore = NSUbiquitousKeyValueStore.default
|
||||||
@@ -191,6 +185,7 @@ class EventViewModel: ObservableObject {
|
|||||||
updateSyncStatus()
|
updateSyncStatus()
|
||||||
loadEvents()
|
loadEvents()
|
||||||
WidgetCenter.shared.reloadAllTimelines()//reload all widgets when saving events
|
WidgetCenter.shared.reloadAllTimelines()//reload all widgets when saving events
|
||||||
|
objectWillChange.send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,6 +344,14 @@ class EventViewModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
func describeOccurrence(date: Date, recurrence: Event.RecurrenceType) -> String {
|
||||||
let dateString = date.formatted(date: .long, time: .omitted)
|
let dateString = date.formatted(date: .long, time: .omitted)
|
||||||
let recurrenceDescription: String
|
let recurrenceDescription: String
|
||||||
@@ -385,6 +388,5 @@ func randomColor() -> Color {
|
|||||||
let r = Double.random(in: 0...1)
|
let r = Double.random(in: 0...1)
|
||||||
let g = Double.random(in: 0...1)
|
let g = Double.random(in: 0...1)
|
||||||
let b = Double.random(in: 0...1)
|
let b = Double.random(in: 0...1)
|
||||||
let a = Double.random(in: 0...1)
|
return Color(red: r, green: g, blue: b)
|
||||||
return Color(red: r, green: g, blue: b, opacity: a)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict/>
|
<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.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.NearFuture</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ struct NearFutureApp: App {
|
|||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup {
|
WindowGroup {
|
||||||
ContentView()
|
ContentView(viewModel: EventViewModel())
|
||||||
}
|
}
|
||||||
// .modelContainer(sharedModelContainer)
|
// .modelContainer(sharedModelContainer)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ struct SettingsView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
|
ZStack {
|
||||||
|
backgroundGradient
|
||||||
List {
|
List {
|
||||||
NavigationLink() {
|
NavigationLink() {
|
||||||
iCloudSettingsView(
|
iCloudSettingsView(
|
||||||
@@ -134,16 +136,16 @@ struct SettingsView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.scrollContentBackground(.hidden)
|
||||||
.navigationTitle("Settings")
|
.navigationTitle("Settings")
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
SettingsView(
|
SettingsView(viewModel: dummyEventViewModel())
|
||||||
viewModel: EventViewModel()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func test() -> Void {
|
func test() -> Void {
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ struct StatsView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
|
ZStack {
|
||||||
|
backgroundGradient
|
||||||
List {
|
List {
|
||||||
Section(header: Text("Upcoming Events")) {
|
Section(header: Text("Upcoming Events")) {
|
||||||
let upcomingEvents = viewModel.events.filter { $0.date > Date() }
|
let upcomingEvents = viewModel.events.filter { $0.date > Date() }
|
||||||
@@ -54,14 +56,16 @@ struct StatsView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.scrollContentBackground(.hidden)
|
||||||
.navigationTitle("Statistics")
|
.navigationTitle("Statistics")
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
StatsView(
|
StatsView(
|
||||||
viewModel: EventViewModel()
|
viewModel: dummyEventViewModel()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ struct iCloudSettingsView: View {
|
|||||||
var updateStatus: () -> Void
|
var updateStatus: () -> Void
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
ZStack {
|
||||||
|
backgroundGradient
|
||||||
List {
|
List {
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
@@ -174,14 +176,16 @@ struct iCloudSettingsView: View {
|
|||||||
.bold()
|
.bold()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.scrollContentBackground(.hidden)
|
||||||
.navigationTitle("iCloud")
|
.navigationTitle("iCloud")
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview("iCloudSettingsView") {
|
#Preview("iCloudSettingsView") {
|
||||||
iCloudSettingsView(
|
iCloudSettingsView(
|
||||||
viewModel: EventViewModel(),
|
viewModel: dummyEventViewModel(),
|
||||||
hasUbiquitous: .constant(true),
|
hasUbiquitous: .constant(true),
|
||||||
lastSyncWasSuccessful: .constant(true),
|
lastSyncWasSuccessful: .constant(true),
|
||||||
lastSyncWasNormalAgo: .constant(true),
|
lastSyncWasNormalAgo: .constant(true),
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ struct EventWidgetView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
let isLarge = widgetFamily == .systemLarge
|
let isLarge = widgetFamily == .systemLarge
|
||||||
let events = entry.events
|
let events = entry.events.filter(){!$0.complete}
|
||||||
ZStack {
|
ZStack {
|
||||||
bgGradient
|
bgGradient
|
||||||
.padding(.top, 4)
|
.padding(.top, 4)
|
||||||
@@ -90,7 +90,6 @@ struct EventWidgetView: View {
|
|||||||
.padding(.top, -12)
|
.padding(.top, -12)
|
||||||
|
|
||||||
ForEach(events.prefix(showedEventsNum), id: \.id) { event in
|
ForEach(events.prefix(showedEventsNum), id: \.id) { event in
|
||||||
if !event.complete {
|
|
||||||
HStack {
|
HStack {
|
||||||
RoundedRectangle(cornerRadius: 5)
|
RoundedRectangle(cornerRadius: 5)
|
||||||
.frame(width: 5)
|
.frame(width: 5)
|
||||||
@@ -105,7 +104,7 @@ struct EventWidgetView: View {
|
|||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(width: 15, height: 15)
|
.frame(width: 15, height: 15)
|
||||||
.foregroundStyle(event.color.color)
|
.foregroundStyle(event.color.color)
|
||||||
Text("\(event.name)")
|
Text("\(event.name.isEmpty ? " " : event.name)")
|
||||||
.foregroundStyle(.white)
|
.foregroundStyle(.white)
|
||||||
.font(.footnote)
|
.font(.footnote)
|
||||||
.padding(.leading, -5)
|
.padding(.leading, -5)
|
||||||
@@ -136,7 +135,6 @@ struct EventWidgetView: View {
|
|||||||
.padding(.trailing, -12)
|
.padding(.trailing, -12)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Spacer()
|
Spacer()
|
||||||
if showedEventsNum < events.count {
|
if showedEventsNum < events.count {
|
||||||
let xMoreEvents = events.count - showedEventsNum
|
let xMoreEvents = events.count - showedEventsNum
|
||||||
@@ -152,14 +150,8 @@ struct EventWidgetView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct Widget_Previews: PreviewProvider {
|
struct Widget_Previews: PreviewProvider {
|
||||||
static var events = [
|
static var events = dummyEventViewModel().events
|
||||||
EventViewModel().example,
|
|
||||||
EventViewModel().example,
|
|
||||||
EventViewModel().example,
|
|
||||||
EventViewModel().example
|
|
||||||
]
|
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
Group {
|
|
||||||
EventWidgetView(
|
EventWidgetView(
|
||||||
entry: EventWidgetEntry(
|
entry: EventWidgetEntry(
|
||||||
date: Date(),
|
date: Date(),
|
||||||
@@ -185,5 +177,4 @@ struct Widget_Previews: PreviewProvider {
|
|||||||
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
||||||
.previewDisplayName("Small")
|
.previewDisplayName("Small")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>com.apple.security.app-sandbox</key>
|
<key>com.apple.security.app-sandbox</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>com.apple.security.application-groups</key>
|
||||||
|
<array>
|
||||||
|
<string>group.NearFuture</string>
|
||||||
|
</array>
|
||||||
<key>com.apple.security.network.client</key>
|
<key>com.apple.security.network.client</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# NearFuture
|
# NearFuture
|
||||||
|
[](https://apps.apple.com/us/app/near-future-event-tracker/id6744963429)
|
||||||
|
|
||||||
Near Future is a SwiftUI App to help people to 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.
|
||||||
|
|
||||||
## Roadmap
|
## Roadmap
|
||||||
- [x] Add and delete events
|
- [x] Add and delete events
|
||||||
@@ -19,6 +20,7 @@ Near Future is a SwiftUI App to help people to track upcoming events - Holidays,
|
|||||||
- [ ] Archive
|
- [ ] Archive
|
||||||
- [ ] Collaboration
|
- [ ] Collaboration
|
||||||
- [ ] Autocomplete tasks
|
- [ ] Autocomplete tasks
|
||||||
|
- [ ] Settings
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
- **Event Creation**: Create events with a name, description, date, recurrence, and an icon
|
- **Event Creation**: Create events with a name, description, date, recurrence, and an icon
|
||||||
@@ -43,7 +45,7 @@ Near Future is a SwiftUI App to help people to track upcoming events - Holidays,
|
|||||||
4. Hit `Command + R` to Build and Run the Project
|
4. Hit `Command + R` to Build and Run the Project
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
Contributions are welcome! just follow these:
|
Contributions are welcome! Just follow these steps:
|
||||||
1. Follow [#Compiling] to get a copy on your machine
|
1. Follow [#Compiling] to get a copy on your machine
|
||||||
2. Optionally create a feature branch for your additions
|
2. Optionally create a feature branch for your additions
|
||||||
3. Open a pull request
|
3. Open a pull request
|
||||||
|
|||||||