ios widget showing what is available at chucks
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: fix notifs

+81 -7
+4 -4
ios/wasup-chucks.xcodeproj/project.pbxproj
··· 386 386 ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; 387 387 CODE_SIGN_ENTITLEMENTS = "wasup-chucks/wasup-chucks.entitlements"; 388 388 CODE_SIGN_STYLE = Automatic; 389 - CURRENT_PROJECT_VERSION = 7; 389 + CURRENT_PROJECT_VERSION = 8; 390 390 DEVELOPMENT_TEAM = M67B42LX8D; 391 391 ENABLE_PREVIEWS = YES; 392 392 GENERATE_INFOPLIST_FILE = YES; ··· 422 422 ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; 423 423 CODE_SIGN_ENTITLEMENTS = "wasup-chucks/wasup-chucks.entitlements"; 424 424 CODE_SIGN_STYLE = Automatic; 425 - CURRENT_PROJECT_VERSION = 7; 425 + CURRENT_PROJECT_VERSION = 8; 426 426 DEVELOPMENT_TEAM = M67B42LX8D; 427 427 ENABLE_PREVIEWS = YES; 428 428 GENERATE_INFOPLIST_FILE = YES; ··· 457 457 ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; 458 458 CODE_SIGN_ENTITLEMENTS = widgetExtension.entitlements; 459 459 CODE_SIGN_STYLE = Automatic; 460 - CURRENT_PROJECT_VERSION = 7; 460 + CURRENT_PROJECT_VERSION = 8; 461 461 DEVELOPMENT_TEAM = M67B42LX8D; 462 462 GENERATE_INFOPLIST_FILE = YES; 463 463 INFOPLIST_FILE = widget/Info.plist; ··· 488 488 ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; 489 489 CODE_SIGN_ENTITLEMENTS = widgetExtension.entitlements; 490 490 CODE_SIGN_STYLE = Automatic; 491 - CURRENT_PROJECT_VERSION = 7; 491 + CURRENT_PROJECT_VERSION = 8; 492 492 DEVELOPMENT_TEAM = M67B42LX8D; 493 493 GENERATE_INFOPLIST_FILE = YES; 494 494 INFOPLIST_FILE = widget/Info.plist;
+30
ios/wasup-chucks/ContentView.swift
··· 186 186 @ObservedObject var favoritesStore: FavoritesStore 187 187 @State private var selectedDay: UpcomingDay? = nil 188 188 @State private var newKeyword = "" 189 + @State private var testNotifStatus: String? = nil 189 190 190 191 var upcomingDays: [UpcomingDay] { 191 192 let calendar = CedarvilleTime.calendar ··· 328 329 Label("Favorite Notifications", systemImage: "bell.fill") 329 330 } 330 331 .tint(.orange) 332 + 333 + Button { 334 + NotificationScheduler.shared.scheduleTest { result in 335 + testNotifStatus = result 336 + DispatchQueue.main.asyncAfter(deadline: .now() + 6) { 337 + testNotifStatus = nil 338 + } 339 + } 340 + } label: { 341 + Label("Send Test Notification", systemImage: "bell.badge") 342 + } 343 + .disabled(testNotifStatus != nil) 344 + 345 + if let status = testNotifStatus { 346 + switch status { 347 + case "scheduled": 348 + Text("Scheduled — should arrive in ~5s") 349 + .font(.caption) 350 + .foregroundStyle(.secondary) 351 + case "denied": 352 + Text("Notifications are disabled. Enable in Settings > Wasup Chuck's > Notifications.") 353 + .font(.caption) 354 + .foregroundStyle(.red) 355 + default: 356 + Text(status) 357 + .font(.caption) 358 + .foregroundStyle(.red) 359 + } 360 + } 331 361 } footer: { 332 362 Text("Get notified 1 hour before a meal that has your favorites.") 333 363 }
+46 -2
ios/wasup-chucks/NotificationScheduler.swift
··· 12 12 static let shared = NotificationScheduler() 13 13 private init() {} 14 14 15 + func scheduleTest(completion: @escaping (String) -> Void) { 16 + let center = UNUserNotificationCenter.current() 17 + center.getNotificationSettings { settings in 18 + switch settings.authorizationStatus { 19 + case .denied: 20 + DispatchQueue.main.async { completion("denied") } 21 + case .notDetermined: 22 + center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, _ in 23 + if granted { 24 + self.addTestNotification(center: center, completion: completion) 25 + } else { 26 + DispatchQueue.main.async { completion("denied") } 27 + } 28 + } 29 + default: 30 + self.addTestNotification(center: center, completion: completion) 31 + } 32 + } 33 + } 34 + 35 + private func addTestNotification(center: UNUserNotificationCenter, completion: @escaping (String) -> Void) { 36 + let content = UNMutableNotificationContent() 37 + content.title = "Lunch has your favorites!" 38 + content.body = "Pizza, Chicken Parmesan at Chuck's today." 39 + content.sound = .default 40 + 41 + let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false) 42 + let request = UNNotificationRequest(identifier: "test", content: content, trigger: trigger) 43 + center.add(request) { error in 44 + DispatchQueue.main.async { 45 + if let error = error { 46 + completion("error: \(error.localizedDescription)") 47 + } else { 48 + completion("scheduled") 49 + } 50 + } 51 + } 52 + } 53 + 15 54 func cancelAll() { 16 55 UNUserNotificationCenter.current().removeAllPendingNotificationRequests() 17 56 } ··· 65 104 content.body = "\(shown) +\(itemNames.count - 2) more at Chuck's today." 66 105 } 67 106 68 - let components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: notifyDate) 107 + // Use device calendar so the trigger fires at the correct local time 108 + let components = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: notifyDate) 69 109 let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: false) 70 110 71 111 let requestID = "fav-\(match.dateKey)-\(mealName)" 72 112 let request = UNNotificationRequest(identifier: requestID, content: content, trigger: trigger) 73 - center.add(request) 113 + center.add(request) { error in 114 + if let error = error { 115 + print("Failed to schedule notification \(requestID): \(error)") 116 + } 117 + } 74 118 } 75 119 } 76 120 }
+1 -1
ios/wasup-chucks/wasup_chucksApp.swift
··· 33 33 willPresent notification: UNNotification, 34 34 withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void 35 35 ) { 36 - completionHandler([.banner, .sound]) 36 + completionHandler([.banner, .list, .sound]) 37 37 } 38 38 }