Whats New!

add AboutView
move getVersion() and geBuildID()
reorg of presentaion related modifiers
This commit is contained in:
neon443
2025-05-12 20:49:28 +01:00
parent 7bef3bc4e6
commit c82ce5fa17
12 changed files with 189 additions and 131 deletions

View File

@@ -14,4 +14,4 @@ BUNDLE_ID_WIDGETS = com.neon443.NearFuture.widgets
GROUP_ID = group.NearFuture GROUP_ID = group.NearFuture
VERSION = 4.0.0 VERSION = 4.0.0
NAME = Near Future NAME = Near Future
BUILD_NUMBER = 0 BUILD_NUMBER = 2

View File

@@ -8,6 +8,8 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
A914FA4B2DD26C6800856265 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A914FA4A2DD26C0F00856265 /* HomeView.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 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = A920C28B2D24011400E4F9B1 /* Item.swift */; };
A920C28E2D24011A00E4F9B1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A920C28D2D24011A00E4F9B1 /* Assets.xcassets */; }; A920C28E2D24011A00E4F9B1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A920C28D2D24011A00E4F9B1 /* Assets.xcassets */; };
@@ -72,6 +74,8 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
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>"; }; 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 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = "<group>"; };
@@ -232,6 +236,7 @@
children = ( children = (
A949F8462DCAABE00064DCA0 /* SettingsView.swift */, A949F8462DCAABE00064DCA0 /* SettingsView.swift */,
A949F8442DCAABE00064DCA0 /* iCloudSettingsView.swift */, A949F8442DCAABE00064DCA0 /* iCloudSettingsView.swift */,
A914FA4C2DD2768900856265 /* WhatsNewView.swift */,
A949F8452DCAABE00064DCA0 /* ImportView.swift */, A949F8452DCAABE00064DCA0 /* ImportView.swift */,
A949F8432DCAABE00064DCA0 /* ExportView.swift */, A949F8432DCAABE00064DCA0 /* ExportView.swift */,
); );
@@ -271,6 +276,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A949F85D2DCABB420064DCA0 /* Buttons.swift */, A949F85D2DCABB420064DCA0 /* Buttons.swift */,
A914FA4E2DD276D200856265 /* AboutView.swift */,
); );
path = Misc; path = Misc;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -452,6 +458,7 @@
files = ( files = (
A920C28C2D24011400E4F9B1 /* Item.swift in Sources */, A920C28C2D24011400E4F9B1 /* Item.swift in Sources */,
A949F84B2DCAABE00064DCA0 /* ArchiveView.swift in Sources */, A949F84B2DCAABE00064DCA0 /* ArchiveView.swift in Sources */,
A914FA4F2DD276D200856265 /* AboutView.swift in Sources */,
A949F84C2DCAABE00064DCA0 /* AddEventView.swift in Sources */, A949F84C2DCAABE00064DCA0 /* AddEventView.swift in Sources */,
A914FA4B2DD26C6800856265 /* HomeView.swift in Sources */, A914FA4B2DD26C6800856265 /* HomeView.swift in Sources */,
A949F84D2DCAABE00064DCA0 /* EditEventView.swift in Sources */, A949F84D2DCAABE00064DCA0 /* EditEventView.swift in Sources */,
@@ -459,6 +466,7 @@
A949F84F2DCAABE00064DCA0 /* EventListView.swift in Sources */, A949F84F2DCAABE00064DCA0 /* EventListView.swift in Sources */,
A949F8502DCAABE00064DCA0 /* HelpView.swift in Sources */, A949F8502DCAABE00064DCA0 /* HelpView.swift in Sources */,
A949F85F2DCABB420064DCA0 /* Buttons.swift in Sources */, A949F85F2DCABB420064DCA0 /* Buttons.swift in Sources */,
A914FA4D2DD2768900856265 /* WhatsNewView.swift in Sources */,
A949F8512DCAABE00064DCA0 /* ExportView.swift in Sources */, A949F8512DCAABE00064DCA0 /* ExportView.swift in Sources */,
A949F8522DCAABE00064DCA0 /* iCloudSettingsView.swift in Sources */, A949F8522DCAABE00064DCA0 /* iCloudSettingsView.swift in Sources */,
A949F8532DCAABE00064DCA0 /* ImportView.swift in Sources */, A949F8532DCAABE00064DCA0 /* ImportView.swift in Sources */,

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,11 +4,6 @@
<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>

View File

@@ -107,12 +107,16 @@ func daysUntilEvent(_ eventDate: Date) -> (long: String, short: String) {
struct Settings: Codable, Equatable { struct Settings: Codable, Equatable {
var showCompletedInHome: Bool var showCompletedInHome: Bool
var tint: ColorCodable var tint: ColorCodable
var showWhatsNew: Bool
var prevAppVersion: String
} }
class SettingsViewModel: ObservableObject { class SettingsViewModel: ObservableObject {
@Published var settings: Settings = Settings( @Published var settings: Settings = Settings(
showCompletedInHome: false, showCompletedInHome: false,
tint: ColorCodable(uiColor: UIColor(named: "AccentColor")!) tint: ColorCodable(uiColor: UIColor(named: "AccentColor")!),
showWhatsNew: true,
prevAppVersion: getVersion()+getBuildID()
) )
@Published var notifsGranted: Bool = false @Published var notifsGranted: Bool = false
@@ -152,6 +156,9 @@ class SettingsViewModel: ObservableObject {
self.settings = decodedSetts self.settings = decodedSetts
} }
} }
if self.settings.prevAppVersion != getVersion()+getBuildID() {
self.settings.showWhatsNew = true
}
} }
func saveSettings() { func saveSettings() {
@@ -528,3 +535,17 @@ func cancelNotif(_ id: String) {
func cancelAllNotifs() { func cancelAllNotifs() {
UNUserNotificationCenter.current().removeAllPendingNotificationRequests() UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
} }
func getVersion() -> String {
guard let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] else {
fatalError("no bundle id wtf lol")
}
return "\(version)"
}
func getBuildID() -> String {
guard let build = Bundle.main.infoDictionary?["CFBundleVersion"] else {
fatalError("wtf did u do w the build number")
}
return "\(build)"
}

View File

@@ -59,12 +59,6 @@ struct ArchiveView: View {
eventRecurrence: $viewModel.editableTemplate.recurrence, eventRecurrence: $viewModel.editableTemplate.recurrence,
adding: true adding: true
) )
.presentationDragIndicator(.visible)
.apply {
if #available(iOS 16.4, *) {
$0.presentationBackground(.ultraThinMaterial)
}
}
} }
} }
} }

View File

@@ -35,7 +35,9 @@ struct AddEventView: View {
var body: some View { var body: some View {
ZStack { ZStack {
if !adding {
backgroundGradient backgroundGradient
}
NavigationStack { NavigationStack {
Form { Form {
Section( Section(
@@ -210,6 +212,13 @@ struct AddEventView: View {
} }
} }
} }
.presentationDragIndicator(.visible)
.scrollContentBackground(.hidden)
}
.apply {
if #available(iOS 16.4, *) {
$0.presentationBackground(.ultraThinMaterial)
}
} }
} }
func resetAddEventView() { func resetAddEventView() {
@@ -244,11 +253,5 @@ struct AddEventView: View {
eventRecurrence: .constant(vm.template.recurrence), eventRecurrence: .constant(vm.template.recurrence),
adding: true adding: true
) )
.presentationDragIndicator(.visible)
.apply {
if #available(iOS 16.4, *) {
$0.presentationBackground(.ultraThinMaterial)
}
}
} }
} }

View File

@@ -46,6 +46,9 @@ struct ContentView: View {
} }
.tag(Tab.settings) .tag(Tab.settings)
} }
.sheet(isPresented: $settingsModel.settings.showWhatsNew) {
WhatsNewView(settingsModel: settingsModel)
}
} }
} }

View File

@@ -111,12 +111,6 @@ struct HomeView: View {
eventRecurrence: $eventRecurrence, eventRecurrence: $eventRecurrence,
adding: true //adding event adding: true //adding event
) )
.presentationDragIndicator(.visible)
.apply {
if #available(iOS 16.4, *) {
$0.presentationBackground(.ultraThinMaterial)
}
}
} }
.toolbar { .toolbar {
ToolbarItem(placement: .topBarTrailing) { ToolbarItem(placement: .topBarTrailing) {

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

@@ -148,20 +148,7 @@ struct SettingsView: View {
} }
} }
Section("About") { Section("About") {
VStack { AboutView()
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)
}
} }
} }
} }
@@ -185,16 +172,3 @@ struct SettingsView: View {
) )
} }
func getVersion() -> String {
guard let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] else {
fatalError("no bundle id wtf lol")
}
return "\(version)"
}
func getBuildID() -> String {
guard let build = Bundle.main.infoDictionary?["CFBundleVersion"] else {
fatalError("wtf did u do w the build number")
}
return "\(build)"
}

View File

@@ -0,0 +1,113 @@
//
// WhatsNewView.swift
// NearFuture
//
// Created by neon443 on 12/05/2025.
//
import SwiftUI
struct WhatsNewView: View {
@ObservedObject var settingsModel: SettingsViewModel
@Environment(\.dismiss) var dismiss
struct WhatsNew: Identifiable {
var id: UUID = UUID()
var symbol: String
var title: String
var subtitle: String
}
var whatsNew: [WhatsNew] = [
WhatsNew(
symbol: "bell.badge.fill",
title: "Notifications",
subtitle: "Events now have notifications, reminding you to complete them!"
),
WhatsNew(
symbol: "list.bullet.indent",
title: "Animations!",
subtitle: "I added animations for adding, removing and ticking events, fixing "
),
WhatsNew(
symbol: "list.bullet.indent",
title: "Animations!",
subtitle: "I added animations for adding, removing and ticking events, fixing "
)
]
var body: some View {
NavigationStack {
List {
VStack {
Text("What's New")
.font(.largeTitle)
.bold()
AboutView()
Divider()
ForEach(whatsNew) { new in
WhatsNewChunk(
symbol: new.symbol,
title: new.title,
subtitle: new.subtitle
)
}
}
.onDisappear {
settingsModel.saveSettings()
}
}
Button() {
dismiss()
} label: {
Text("Continue")
.font(.headline)
.frame(height: 40)
.bold()
.frame(maxWidth: .infinity)
}
.buttonStyle(BorderedProminentButtonStyle())
.clipShape(RoundedRectangle(cornerRadius: 15))
.padding().padding()
}
.scrollContentBackground(.hidden)
.presentationDragIndicator(.visible)
.apply {
if #available(iOS 16.4, *) {
$0.presentationBackground(.ultraThinMaterial)
}
}
}
}
#Preview {
Color.accent
.ignoresSafeArea(.all)
.sheet(isPresented: .constant(true)) {
WhatsNewView(settingsModel: dummySettingsViewModel())
}
}
struct WhatsNewChunk: View {
@State var symbol: String
@State var title: String
@State var subtitle: String
var body: some View {
// GeometryReader { geo in
HStack {
Image(systemName: symbol)
.resizable()
.scaledToFit()
.frame(width: 30, height: 30)
.foregroundStyle(.accent)
.padding(.trailing, 5)
VStack(alignment: .leading) {
Text(title)
.font(.headline)
.bold()
Text(subtitle)
.foregroundStyle(.gray)
.font(.subheadline)
}
}
// }
}
}