diff --git a/Announcer/Announcement VC/AnnouncementSearchBar.swift b/Announcer/Announcement VC/AnnouncementSearchBar.swift
index 28ebcb1..94ec6e1 100644
--- a/Announcer/Announcement VC/AnnouncementSearchBar.swift
+++ b/Announcer/Announcement VC/AnnouncementSearchBar.swift
@@ -19,6 +19,10 @@ extension AnnouncementsViewController: UISearchBarDelegate {
// When text changes, update search results with searchText
// Seach results automatically reloads when value changed
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
+ // Handling when posts are missing because reloading
+ if posts == nil { return }
+
+ // It takes a bit to search so just run it in the background
DispatchQueue.global(qos: .background).async {
// Set color of labels
// Update labels/textview with data
diff --git a/Announcer/Announcement VC/AnnouncementsViewController.swift b/Announcer/Announcement VC/AnnouncementsViewController.swift
index cdd3df3..c396c24 100644
--- a/Announcer/Announcement VC/AnnouncementsViewController.swift
+++ b/Announcer/Announcement VC/AnnouncementsViewController.swift
@@ -168,17 +168,28 @@ class AnnouncementsViewController: UIViewController {
}
func addItemsToCoreSpotlight() {
+
+ /// So that it does not crash when `posts` gets forced unwrapped
+ if posts == nil {
+ return
+ }
+
+ /// `posts` converted to `CSSearchableItems`
let items: [CSSearchableItem] = posts.map({ post in
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeText as String)
attributeSet.title = post.title
attributeSet.contentDescription = post.content.condenseLinebreaks().htmlToString
-
- return CSSearchableItem(uniqueIdentifier: "\(post.title)",
- domainIdentifier: Bundle.main.bundleIdentifier!,
- attributeSet: attributeSet)
+
+ let item = CSSearchableItem(uniqueIdentifier: "\(post.title)", domainIdentifier: Bundle.main.bundleIdentifier!, attributeSet: attributeSet)
+
+ item.expirationDate = Date.distantFuture
+
+ return item
})
+ // Index the items
CSSearchableIndex.default().indexSearchableItems(items) { error in
+ // Make sure there is no error indexing everything
if let error = error {
print("Indexing error: \(error.localizedDescription)")
} else {
diff --git a/Announcer/Storyboards/Base.lproj/LaunchScreen.storyboard b/Announcer/Storyboards/Base.lproj/LaunchScreen.storyboard
index 5e91fb4..4b9e8c4 100644
--- a/Announcer/Storyboards/Base.lproj/LaunchScreen.storyboard
+++ b/Announcer/Storyboards/Base.lproj/LaunchScreen.storyboard
@@ -58,7 +58,7 @@
-
+
@@ -89,11 +89,11 @@
-
-
-
+
+
+
diff --git a/Announcer/Storyboards/Base.lproj/Main.storyboard b/Announcer/Storyboards/Base.lproj/Main.storyboard
index 55d48f1..2ec6ffb 100644
--- a/Announcer/Storyboards/Base.lproj/Main.storyboard
+++ b/Announcer/Storyboards/Base.lproj/Main.storyboard
@@ -37,7 +37,7 @@
-
+
@@ -72,7 +72,7 @@
-
+
@@ -138,7 +138,7 @@
-
+
@@ -199,7 +199,7 @@
-
+
diff --git a/Announcer/Storyboards/Content.storyboard b/Announcer/Storyboards/Content.storyboard
index 4e2747e..441b00e 100644
--- a/Announcer/Storyboards/Content.storyboard
+++ b/Announcer/Storyboards/Content.storyboard
@@ -349,7 +349,7 @@
-
+
@@ -414,7 +414,7 @@
-
+
diff --git a/Announcer/Storyboards/Filter.storyboard b/Announcer/Storyboards/Filter.storyboard
index edf151a..3f70982 100644
--- a/Announcer/Storyboards/Filter.storyboard
+++ b/Announcer/Storyboards/Filter.storyboard
@@ -14,7 +14,7 @@
-
+
@@ -42,7 +42,7 @@
-
+
@@ -98,7 +98,7 @@
-
+
diff --git a/Announcer/Support Files/Delegates/AppDelegate.swift b/Announcer/Support Files/Delegates/AppDelegate.swift
index cd49516..f7c9f14 100644
--- a/Announcer/Support Files/Delegates/AppDelegate.swift
+++ b/Announcer/Support Files/Delegates/AppDelegate.swift
@@ -35,6 +35,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
center.requestAuthorization(options: options) {
(granted, error) in
if !granted {
+ // User did not give us notification access :(
print("Something went wrong")
print("noooo i demand notifications!!!!!")
}
@@ -66,12 +67,32 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
// Start background task
scheduleBackgroundTaskIfNeeded()
+ // Set project version
+ let versionNumber = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String
+ UserDefaults.standard.set(versionNumber, forKey: "versionNumber")
+
+ // Set project build
+ let buildNumber = Bundle.main.infoDictionary?["CFBundleVersion"] as! String
+ UserDefaults.standard.set(buildNumber, forKey: "buildNumber")
+
return true
}
- // Testing if background task works
- // Run this below in debugger
- // e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"sg.edu.sst.panziyue.Announcer.new-announcement"]
+ /**
+ Schedules the new announcement background task
+
+ The identifier is `sg.edu.sst.panziyue.Announcer.new-announcement`
+
+ ---
+ # Debugging Background Tasks
+ Running this line in the debugger to instantly manually background refresh. Background refresh takes a while so this is the easier way to do it and test it out.
+
+ [Developer Article](https://developer.apple.com/documentation/backgroundtasks/starting_and_terminating_tasks_during_development)
+
+ ```
+ e -l objc -- (void)[[BGTaskScheduler sharedScheduler] _simulateLaunchForTaskWithIdentifier:@"sg.edu.sst.panziyue.Announcer.new-announcement"]
+ ```
+ */
func scheduleBackgroundTaskIfNeeded() {
let taskRequest = BGProcessingTaskRequest(identifier: AppDelegate.backgroundTaskIdentifier)
taskRequest.requiresNetworkConnectivity = true
@@ -131,9 +152,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
}
// Calls when user opens app from a notification
- func userNotificationCenter(_ center: UNUserNotificationCenter,
- didReceive response: UNNotificationResponse,
- withCompletionHandler completionHandler: @escaping () -> Void) {
+ func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
openPost(with: response.notification)
diff --git a/Announcer/Support Files/Globals.swift b/Announcer/Support Files/Globals.swift
index f6a323b..152bee9 100644
--- a/Announcer/Support Files/Globals.swift
+++ b/Announcer/Support Files/Globals.swift
@@ -20,10 +20,10 @@ import SafariServices
- important: Ensure that the URL is set to the correct blog before production.
# Production Blog URL
- http://studentsblog.sst.edu.sg
+ [http://studentsblog.sst.edu.sg](http://studentsblog.sst.edu.sg)
# Development Blog URL
- https://testannouncer.blogspot.com
+ [https://testannouncer.blogspot.com](https://testannouncer.blogspot.com)
This constant stores the URL for the blog linked to the RSS feed.
*/
@@ -428,7 +428,6 @@ func launchPost(withTitle postTitle: String) {
if let post = post {
// Handles when post is found
-
announcementVC.receivePost(with: post)
} else {
diff --git a/Announcer/Support Files/Settings.bundle/Acknowledgements.plist b/Announcer/Support Files/Settings.bundle/Acknowledgements.plist
index 5a59720..d21311d 100644
--- a/Announcer/Support Files/Settings.bundle/Acknowledgements.plist
+++ b/Announcer/Support Files/Settings.bundle/Acknowledgements.plist
@@ -107,8 +107,6 @@ SOFTWARE.
Type
PSGroupSpecifier
- Title
- Generated by Cocoapods - https://cocoapods.org
diff --git a/Announcer/Support Files/Settings.bundle/Root.plist b/Announcer/Support Files/Settings.bundle/Root.plist
index 0ace9ae..f48f44e 100644
--- a/Announcer/Support Files/Settings.bundle/Root.plist
+++ b/Announcer/Support Files/Settings.bundle/Root.plist
@@ -6,6 +6,32 @@
Root
PreferenceSpecifiers
+
+ Type
+ PSGroupSpecifier
+ Title
+ App Information
+
+
+ Type
+ PSTitleValueSpecifier
+ Title
+ Version
+ Key
+ versionNumber
+ DefaultValue
+ 0
+
+
+ Type
+ PSTitleValueSpecifier
+ Title
+ Build
+ Key
+ buildNumber
+ DefaultValue
+ 0
+
Type
PSChildPaneSpecifier
diff --git a/README.md b/README.md
index 73ac144..fe56643 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# SST Announcer (iOS)
[![Language](http://img.shields.io/badge/swift-5-orange.svg?style=flat)](https://developer.apple.com/swift)
-[![Xcode](http://img.shields.io/badge/xcode-11.4-red.svg?style=flat)](https://developer.apple.com/xcode)
+[![Xcode](http://img.shields.io/badge/xcode-11.5-red.svg?style=flat)](https://developer.apple.com/xcode)
[![Cocoapods](http://img.shields.io/badge/pod-v1.8.4-darkgray.svg?style=flat)](https://cocoapods.org/)
[![iOS](http://img.shields.io/badge/platform-iOS%2013-blue.svg?style=flat)](https://developer.apple.com/iphone/index.action)
@@ -79,10 +79,10 @@ These colors are used for different parts of the app such as backgrounds and lab
|Color Name |Identifier|Light Theme|Dark Theme |
|-----------|----------|-----------|-----------|
-|Background |`background`|![](https://via.placeholder.com/15/F5F4F6/F5F4F6) - #F5F4F6|![](https://via.placeholder.com/15/060400/060400) - #060400|
-|Global Tint|`Global Tint`|![](https://via.placeholder.com/15/A9A9A9/A9A9A9) - #A9A9A9|![](https://via.placeholder.com/15/A9A9A9/A9A9A9) - #A9A9A9|
-|Grey 1 |`Grey 1`|![](https://via.placeholder.com/15/434343/434343) - #434343|![](https://via.placeholder.com/15/B8BABB/B8BABB) - #B8BABB|
-|Grey 2 |`Grey 2`|![](https://via.placeholder.com/15/DCDADB/DCDADB) - #DCDADB|![](https://via.placeholder.com/15/252628/252628) - #252628|
+|Background |`"background"`|![](https://via.placeholder.com/15/F5F4F6/F5F4F6) - #F5F4F6|![](https://via.placeholder.com/15/060400/060400) - #060400|
+|Global Tint|`"Global Tint"`|![](https://via.placeholder.com/15/A9A9A9/A9A9A9) - #A9A9A9|![](https://via.placeholder.com/15/A9A9A9/A9A9A9) - #A9A9A9|
+|Grey 1 |`"Grey 1"`|![](https://via.placeholder.com/15/434343/434343) - #434343|![](https://via.placeholder.com/15/B8BABB/B8BABB) - #B8BABB|
+|Grey 2 |`"Grey 2"`|![](https://via.placeholder.com/15/DCDADB/DCDADB) - #DCDADB|![](https://via.placeholder.com/15/252628/252628) - #252628|
### Apple Colors
These colors are the ones as part of Apple's [UIColor Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/color/)
@@ -97,6 +97,6 @@ These colors are used for loading content using KALoader
|Color Name |Identifier|Light Theme|Dark Theme |
|-----------|----------|-----------|-----------|
-|First Load Color|`First Load Color`|![](https://via.placeholder.com/15/DEDEDE/DEDEDE) - #DEDEDE|![](https://via.placeholder.com/15/202020/202020) - #202020|
-|Second Load Color|`Second Load Color`|![](https://via.placeholder.com/15/DDDDDD/DDDDDD) - #DDDDDD|![](https://via.placeholder.com/15/212121/212121) - #212121|
-|Back Gray Color |`Back Gray Color`|![](https://via.placeholder.com/15/F6F6F6/F6F6F6) - #F6F6F6|![](https://via.placeholder.com/15/080808/080808) - #080808|
+|First Load Color|`"First Load Color"`|![](https://via.placeholder.com/15/DEDEDE/DEDEDE) - #DEDEDE|![](https://via.placeholder.com/15/202020/202020) - #202020|
+|Second Load Color|`"Second Load Color"`|![](https://via.placeholder.com/15/DDDDDD/DDDDDD) - #DDDDDD|![](https://via.placeholder.com/15/212121/212121) - #212121|
+|Back Gray Color |`"Back Gray Color"`|![](https://via.placeholder.com/15/F6F6F6/F6F6F6) - #F6F6F6|![](https://via.placeholder.com/15/080808/080808) - #080808|