@greatdayhr/capacitor-datetime-setting 1.1.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +359 -58
- package/android/src/main/java/com/datetimesetting/DateTimeSettingPlugin.java +9 -90
- package/dist/esm/definitions.d.ts +185 -19
- package/dist/esm/definitions.d.ts.map +1 -1
- package/dist/esm/web.d.ts +25 -6
- package/dist/esm/web.d.ts.map +1 -1
- package/dist/esm/web.js +27 -3
- package/dist/plugin.cjs.js +27 -3
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +27 -3
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/AutoDateTimeDetector.swift +671 -0
- package/ios/Plugin/DateTimeSettingPlugin.m +17 -3
- package/ios/Plugin/DateTimeSettingPlugin.swift +184 -46
- package/ios/Plugin/NotificationManager.swift +259 -0
- package/package.json +8 -5
|
@@ -4,75 +4,213 @@ import Capacitor
|
|
|
4
4
|
/**
|
|
5
5
|
* DateTimeSettingPlugin
|
|
6
6
|
*
|
|
7
|
-
* Capacitor plugin
|
|
7
|
+
* Capacitor plugin for comprehensive date/time change detection and management.
|
|
8
|
+
* Cloned from date_change_checker Flutter plugin.
|
|
8
9
|
*
|
|
9
|
-
* iOS implementation uses
|
|
10
|
-
*
|
|
10
|
+
* iOS implementation uses network time comparison with AutoDateTimeDetector
|
|
11
|
+
* for reliable detection of automatic date/time settings and changes.
|
|
11
12
|
*/
|
|
12
13
|
@objc(DateTimeSettingPlugin)
|
|
13
14
|
public class DateTimeSettingPlugin: CAPPlugin {
|
|
14
15
|
|
|
16
|
+
override public func load() {
|
|
17
|
+
super.load()
|
|
18
|
+
// Initialize the AutoDateTimeDetector
|
|
19
|
+
AutoDateTimeDetector.initialize()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
deinit {
|
|
23
|
+
// Clean up network monitoring when plugin is deallocated
|
|
24
|
+
AutoDateTimeDetector.stopNetworkMonitoring()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// MARK: - Date/Time Change Detection
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Detects if the device's date/time has been manually changed
|
|
31
|
+
*/
|
|
32
|
+
@objc func detectDateTimeChange(_ call: CAPPluginCall) {
|
|
33
|
+
AutoDateTimeDetector.detectDateTimeChange { changeDetected in
|
|
34
|
+
DispatchQueue.main.async {
|
|
35
|
+
call.resolve([
|
|
36
|
+
"changed": changeDetected
|
|
37
|
+
])
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Comprehensive date and time change detection with detailed analysis
|
|
44
|
+
*/
|
|
45
|
+
@objc func detectComprehensiveDateTimeChange(_ call: CAPPluginCall) {
|
|
46
|
+
AutoDateTimeDetector.detectComprehensiveDateTimeChange { result in
|
|
47
|
+
DispatchQueue.main.async {
|
|
48
|
+
let changeTypeString: String
|
|
49
|
+
switch result.changeType {
|
|
50
|
+
case .noChange:
|
|
51
|
+
changeTypeString = "noChange"
|
|
52
|
+
case .timeOnly:
|
|
53
|
+
changeTypeString = "timeOnly"
|
|
54
|
+
case .dateOnly:
|
|
55
|
+
changeTypeString = "dateOnly"
|
|
56
|
+
case .dateAndTime:
|
|
57
|
+
changeTypeString = "dateAndTime"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
var resultDict: [String: Any] = [
|
|
61
|
+
"changeType": changeTypeString,
|
|
62
|
+
"timeDifference": result.timeDifference,
|
|
63
|
+
"dateChanged": result.dateChanged,
|
|
64
|
+
"timeChanged": result.timeChanged,
|
|
65
|
+
"isAutoDateTimeEnabled": result.isAutoDateTimeEnabled,
|
|
66
|
+
"currentDate": result.currentDate.timeIntervalSince1970
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
if let previousDate = result.previousDate {
|
|
70
|
+
resultDict["previousDate"] = previousDate.timeIntervalSince1970
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
call.resolve(resultDict)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Detects specifically if only the date has been changed
|
|
80
|
+
*/
|
|
81
|
+
@objc func detectDateOnlyChange(_ call: CAPPluginCall) {
|
|
82
|
+
AutoDateTimeDetector.detectDateOnlyChange { changeDetected in
|
|
83
|
+
DispatchQueue.main.async {
|
|
84
|
+
call.resolve([
|
|
85
|
+
"changed": changeDetected
|
|
86
|
+
])
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
15
91
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* iOS implementation uses TimeZone.autoupdatingCurrent to determine
|
|
19
|
-
* if the device is set to automatically update its time zone and date/time settings.
|
|
92
|
+
* Comprehensive date and time change detection with automatic notifications
|
|
20
93
|
*/
|
|
21
|
-
@objc func
|
|
22
|
-
|
|
94
|
+
@objc func detectAndNotifyDateTimeChanges(_ call: CAPPluginCall) {
|
|
95
|
+
AutoDateTimeDetector.detectAndNotifyDateTimeChanges { result in
|
|
96
|
+
DispatchQueue.main.async {
|
|
97
|
+
let changeTypeString: String
|
|
98
|
+
switch result.changeType {
|
|
99
|
+
case .noChange:
|
|
100
|
+
changeTypeString = "noChange"
|
|
101
|
+
case .timeOnly:
|
|
102
|
+
changeTypeString = "timeOnly"
|
|
103
|
+
case .dateOnly:
|
|
104
|
+
changeTypeString = "dateOnly"
|
|
105
|
+
case .dateAndTime:
|
|
106
|
+
changeTypeString = "dateAndTime"
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
var resultDict: [String: Any] = [
|
|
110
|
+
"changeType": changeTypeString,
|
|
111
|
+
"timeDifference": result.timeDifference,
|
|
112
|
+
"dateChanged": result.dateChanged,
|
|
113
|
+
"timeChanged": result.timeChanged,
|
|
114
|
+
"isAutoDateTimeEnabled": result.isAutoDateTimeEnabled,
|
|
115
|
+
"currentDate": result.currentDate.timeIntervalSince1970
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
if let previousDate = result.previousDate {
|
|
119
|
+
resultDict["previousDate"] = previousDate.timeIntervalSince1970
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
call.resolve(resultDict)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// MARK: - Time Utilities
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get the device's current local time
|
|
131
|
+
*/
|
|
132
|
+
@objc func getLocalTime(_ call: CAPPluginCall) {
|
|
133
|
+
let currentTime = AutoDateTimeDetector.getCurrentLocalTime()
|
|
134
|
+
let timestamp = currentTime.timeIntervalSince1970
|
|
23
135
|
call.resolve([
|
|
24
|
-
"
|
|
136
|
+
"timestamp": timestamp
|
|
25
137
|
])
|
|
26
138
|
}
|
|
27
139
|
|
|
28
140
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* iOS implementation uses TimeZone.autoupdatingCurrent to determine
|
|
32
|
-
* if the device is set to automatically update its time zone.
|
|
141
|
+
* Fetch accurate UTC time from internet time server
|
|
33
142
|
*/
|
|
34
|
-
@objc func
|
|
35
|
-
|
|
143
|
+
@objc func getInternetUTCTime(_ call: CAPPluginCall) {
|
|
144
|
+
AutoDateTimeDetector.fetchInternetUTCTime { result in
|
|
145
|
+
DispatchQueue.main.async {
|
|
146
|
+
switch result {
|
|
147
|
+
case .success(let utcTime):
|
|
148
|
+
let timestamp = utcTime.timeIntervalSince1970
|
|
149
|
+
call.resolve([
|
|
150
|
+
"timestamp": timestamp
|
|
151
|
+
])
|
|
152
|
+
case .failure(let error):
|
|
153
|
+
call.reject("Failed to fetch internet time", nil, error)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Convert local time to UTC
|
|
161
|
+
*/
|
|
162
|
+
@objc func convertToLocalTime(_ call: CAPPluginCall) {
|
|
163
|
+
guard let timestamp = call.getDouble("timestamp") else {
|
|
164
|
+
call.reject("Missing timestamp parameter")
|
|
165
|
+
return
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let localTime = Date(timeIntervalSince1970: timestamp)
|
|
169
|
+
let utcTime = AutoDateTimeDetector.convertLocalTimeToUTC(localTime)
|
|
170
|
+
let utcTimestamp = utcTime.timeIntervalSince1970
|
|
171
|
+
|
|
36
172
|
call.resolve([
|
|
37
|
-
"
|
|
173
|
+
"timestamp": utcTimestamp
|
|
38
174
|
])
|
|
39
175
|
}
|
|
40
176
|
|
|
177
|
+
// MARK: - Timestamp Management
|
|
178
|
+
|
|
41
179
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* Compares the autoupdating timezone with the system timezone.
|
|
45
|
-
* If they are equal, auto date/time is enabled.
|
|
180
|
+
* Set the stored timestamp for future change detection
|
|
46
181
|
*/
|
|
47
|
-
|
|
48
|
-
let
|
|
49
|
-
|
|
50
|
-
|
|
182
|
+
@objc func setStoredTimestamp(_ call: CAPPluginCall) {
|
|
183
|
+
guard let timestamp = call.getDouble("timestamp") else {
|
|
184
|
+
call.reject("Missing timestamp parameter")
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
let date = Date(timeIntervalSince1970: timestamp)
|
|
189
|
+
AutoDateTimeDetector.setStoredTimestamp(date)
|
|
190
|
+
call.resolve()
|
|
51
191
|
}
|
|
52
192
|
|
|
53
193
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* On iOS, this opens the main Settings app as there's no direct way
|
|
57
|
-
* to open the Date & Time settings page.
|
|
194
|
+
* Get the currently stored timestamp
|
|
58
195
|
*/
|
|
59
|
-
@objc func
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
} else {
|
|
71
|
-
call.reject("Cannot open settings URL")
|
|
72
|
-
}
|
|
73
|
-
} else {
|
|
74
|
-
call.reject("Invalid settings URL")
|
|
75
|
-
}
|
|
196
|
+
@objc func getStoredTimestamp(_ call: CAPPluginCall) {
|
|
197
|
+
if let storedTime = AutoDateTimeDetector.getStoredTimestamp() {
|
|
198
|
+
let timestamp = storedTime.timeIntervalSince1970
|
|
199
|
+
call.resolve([
|
|
200
|
+
"timestamp": timestamp
|
|
201
|
+
])
|
|
202
|
+
} else {
|
|
203
|
+
call.resolve([
|
|
204
|
+
"timestamp": NSNull()
|
|
205
|
+
])
|
|
76
206
|
}
|
|
77
207
|
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Reset the detector (clears all stored data and cache)
|
|
211
|
+
*/
|
|
212
|
+
@objc func resetDetector(_ call: CAPPluginCall) {
|
|
213
|
+
AutoDateTimeDetector.reset()
|
|
214
|
+
call.resolve()
|
|
215
|
+
}
|
|
78
216
|
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UserNotifications
|
|
3
|
+
import UIKit
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* NotificationManager handles displaying notifications for date/time change detection
|
|
7
|
+
* Supports iOS 10+ with UserNotifications framework and fallback for older versions
|
|
8
|
+
*/
|
|
9
|
+
class NotificationManager: NSObject {
|
|
10
|
+
|
|
11
|
+
static let shared = NotificationManager()
|
|
12
|
+
|
|
13
|
+
private override init() {
|
|
14
|
+
super.init()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Requests notification permission from the user
|
|
19
|
+
* Should be called during app initialization
|
|
20
|
+
*/
|
|
21
|
+
func requestNotificationPermission(completion: @escaping (Bool) -> Void) {
|
|
22
|
+
if #available(iOS 10.0, *) {
|
|
23
|
+
let center = UNUserNotificationCenter.current()
|
|
24
|
+
center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
|
|
25
|
+
DispatchQueue.main.async {
|
|
26
|
+
if let error = error {
|
|
27
|
+
print("Notification permission error: \(error.localizedDescription)")
|
|
28
|
+
completion(false)
|
|
29
|
+
} else {
|
|
30
|
+
completion(granted)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
// Fallback for iOS 9 and earlier
|
|
36
|
+
let settings = UIUserNotificationSettings(types: [.alert, .sound, .badge], categories: nil)
|
|
37
|
+
UIApplication.shared.registerUserNotificationSettings(settings)
|
|
38
|
+
completion(true)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Displays a notification when automatic date/time is disabled
|
|
44
|
+
*/
|
|
45
|
+
func showAutoDateTimeDisabledNotification() {
|
|
46
|
+
let title = "Automatic Date & Time Disabled"
|
|
47
|
+
let body = "Your device's automatic date and time setting appears to be disabled. Please enable it in Settings > General > Date & Time for accurate time synchronization."
|
|
48
|
+
|
|
49
|
+
showNotification(title: title, body: body, identifier: "auto_datetime_disabled")
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Displays a notification when date-only change is detected
|
|
54
|
+
*/
|
|
55
|
+
func showDateOnlyChangeNotification() {
|
|
56
|
+
let title = "Date Change Detected"
|
|
57
|
+
let body = "The date has been manually changed while the time remained unchanged. This may indicate that automatic date and time is disabled."
|
|
58
|
+
|
|
59
|
+
showNotification(title: title, body: body, identifier: "date_only_change")
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Displays a notification when time-only change is detected
|
|
64
|
+
*/
|
|
65
|
+
func showTimeOnlyChangeNotification() {
|
|
66
|
+
let title = "Time Change Detected"
|
|
67
|
+
let body = "The time has been manually changed. This may indicate that automatic date and time is disabled."
|
|
68
|
+
|
|
69
|
+
showNotification(title: title, body: body, identifier: "time_only_change")
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Displays a notification when both date and time changes are detected
|
|
74
|
+
*/
|
|
75
|
+
func showDateTimeChangeNotification() {
|
|
76
|
+
let title = "Date & Time Change Detected"
|
|
77
|
+
let body = "Both date and time have been manually changed. Please ensure automatic date and time is enabled for accurate synchronization."
|
|
78
|
+
|
|
79
|
+
showNotification(title: title, body: body, identifier: "datetime_change")
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Displays a custom notification with specified parameters
|
|
84
|
+
*/
|
|
85
|
+
func showCustomNotification(title: String, body: String, identifier: String? = nil) {
|
|
86
|
+
let notificationId = identifier ?? "custom_notification_\(Date().timeIntervalSince1970)"
|
|
87
|
+
showNotification(title: title, body: body, identifier: notificationId)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Core notification display method that handles iOS version compatibility
|
|
92
|
+
*/
|
|
93
|
+
private func showNotification(title: String, body: String, identifier: String) {
|
|
94
|
+
if #available(iOS 10.0, *) {
|
|
95
|
+
showModernNotification(title: title, body: body, identifier: identifier)
|
|
96
|
+
} else {
|
|
97
|
+
showLegacyNotification(title: title, body: body)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Shows notification using UserNotifications framework (iOS 10+)
|
|
103
|
+
*/
|
|
104
|
+
@available(iOS 10.0, *)
|
|
105
|
+
private func showModernNotification(title: String, body: String, identifier: String) {
|
|
106
|
+
let center = UNUserNotificationCenter.current()
|
|
107
|
+
|
|
108
|
+
// Check if notifications are authorized
|
|
109
|
+
center.getNotificationSettings { settings in
|
|
110
|
+
guard settings.authorizationStatus == .authorized else {
|
|
111
|
+
print("Notifications not authorized")
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Create notification content
|
|
116
|
+
let content = UNMutableNotificationContent()
|
|
117
|
+
content.title = title
|
|
118
|
+
content.body = body
|
|
119
|
+
content.sound = .default
|
|
120
|
+
content.badge = NSNumber(value: UIApplication.shared.applicationIconBadgeNumber + 1)
|
|
121
|
+
|
|
122
|
+
// Create trigger (immediate delivery)
|
|
123
|
+
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.1, repeats: false)
|
|
124
|
+
|
|
125
|
+
// Create request
|
|
126
|
+
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
|
|
127
|
+
|
|
128
|
+
// Schedule notification
|
|
129
|
+
center.add(request) { error in
|
|
130
|
+
if let error = error {
|
|
131
|
+
print("Failed to schedule notification: \(error.localizedDescription)")
|
|
132
|
+
} else {
|
|
133
|
+
print("Notification scheduled successfully: \(title)")
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Shows notification using legacy UILocalNotification (iOS 9 and earlier)
|
|
141
|
+
*/
|
|
142
|
+
private func showLegacyNotification(title: String, body: String) {
|
|
143
|
+
DispatchQueue.main.async {
|
|
144
|
+
if #available(iOS 8.0, *) {
|
|
145
|
+
let notification = UILocalNotification()
|
|
146
|
+
notification.alertTitle = title
|
|
147
|
+
notification.alertBody = body
|
|
148
|
+
notification.soundName = UILocalNotificationDefaultSoundName
|
|
149
|
+
notification.applicationIconBadgeNumber = UIApplication.shared.applicationIconBadgeNumber + 1
|
|
150
|
+
notification.fireDate = Date(timeIntervalSinceNow: 0.1)
|
|
151
|
+
|
|
152
|
+
UIApplication.shared.scheduleLocalNotification(notification)
|
|
153
|
+
print("Legacy notification scheduled: \(title)")
|
|
154
|
+
} else {
|
|
155
|
+
// For iOS 7 and earlier, show an alert
|
|
156
|
+
let alert = UIAlertView(title: title, message: body, delegate: nil, cancelButtonTitle: "OK")
|
|
157
|
+
alert.show()
|
|
158
|
+
print("Alert shown for iOS 7: \(title)")
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Cancels all pending notifications
|
|
165
|
+
*/
|
|
166
|
+
func cancelAllNotifications() {
|
|
167
|
+
if #available(iOS 10.0, *) {
|
|
168
|
+
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
|
|
169
|
+
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
|
|
170
|
+
} else {
|
|
171
|
+
UIApplication.shared.cancelAllLocalNotifications()
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Reset badge count
|
|
175
|
+
DispatchQueue.main.async {
|
|
176
|
+
UIApplication.shared.applicationIconBadgeNumber = 0
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Cancels notifications with specific identifier
|
|
182
|
+
*/
|
|
183
|
+
func cancelNotification(withIdentifier identifier: String) {
|
|
184
|
+
if #available(iOS 10.0, *) {
|
|
185
|
+
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [identifier])
|
|
186
|
+
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [identifier])
|
|
187
|
+
} else {
|
|
188
|
+
// For legacy notifications, we need to cancel all and reschedule others
|
|
189
|
+
// This is a limitation of the older notification system
|
|
190
|
+
let scheduledNotifications = UIApplication.shared.scheduledLocalNotifications ?? []
|
|
191
|
+
for notification in scheduledNotifications {
|
|
192
|
+
if notification.userInfo?["identifier"] as? String == identifier {
|
|
193
|
+
UIApplication.shared.cancelLocalNotification(notification)
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Checks current notification authorization status
|
|
201
|
+
*/
|
|
202
|
+
func checkNotificationPermission(completion: @escaping (Bool) -> Void) {
|
|
203
|
+
if #available(iOS 10.0, *) {
|
|
204
|
+
UNUserNotificationCenter.current().getNotificationSettings { settings in
|
|
205
|
+
DispatchQueue.main.async {
|
|
206
|
+
completion(settings.authorizationStatus == .authorized)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
} else {
|
|
210
|
+
// For older iOS versions, check if notification types are enabled
|
|
211
|
+
let settings = UIApplication.shared.currentUserNotificationSettings
|
|
212
|
+
completion(settings?.types != [])
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// MARK: - UNUserNotificationCenterDelegate
|
|
218
|
+
|
|
219
|
+
@available(iOS 10.0, *)
|
|
220
|
+
extension NotificationManager: UNUserNotificationCenterDelegate {
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Handle notification when app is in foreground
|
|
224
|
+
*/
|
|
225
|
+
func userNotificationCenter(_ center: UNUserNotificationCenter,
|
|
226
|
+
willPresent notification: UNNotification,
|
|
227
|
+
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
|
228
|
+
// Show notification even when app is in foreground
|
|
229
|
+
if #available(iOS 14.0, *) {
|
|
230
|
+
completionHandler([.banner, .sound, .badge])
|
|
231
|
+
} else {
|
|
232
|
+
completionHandler([.alert, .sound, .badge])
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Handle notification tap
|
|
238
|
+
*/
|
|
239
|
+
func userNotificationCenter(_ center: UNUserNotificationCenter,
|
|
240
|
+
didReceive response: UNNotificationResponse,
|
|
241
|
+
withCompletionHandler completionHandler: @escaping () -> Void) {
|
|
242
|
+
let identifier = response.notification.request.identifier
|
|
243
|
+
print("Notification tapped: \(identifier)")
|
|
244
|
+
|
|
245
|
+
// Handle specific notification actions here if needed
|
|
246
|
+
switch identifier {
|
|
247
|
+
case "auto_datetime_disabled":
|
|
248
|
+
// Could open settings or show more information
|
|
249
|
+
break
|
|
250
|
+
case "date_only_change", "time_only_change", "datetime_change":
|
|
251
|
+
// Could show detailed change information
|
|
252
|
+
break
|
|
253
|
+
default:
|
|
254
|
+
break
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
completionHandler()
|
|
258
|
+
}
|
|
259
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@greatdayhr/capacitor-datetime-setting",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Capacitor plugin
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Capacitor plugin for comprehensive iOS date/time change detection. Cloned from date_change_checker Flutter plugin.",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
7
7
|
"types": "dist/esm/index.d.ts",
|
|
@@ -27,9 +27,12 @@
|
|
|
27
27
|
"plugin",
|
|
28
28
|
"native",
|
|
29
29
|
"datetime",
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
30
|
+
"time-detection",
|
|
31
|
+
"date-change",
|
|
32
|
+
"ios",
|
|
33
|
+
"date-change-checker",
|
|
34
|
+
"automatic-time",
|
|
35
|
+
"network-time"
|
|
33
36
|
],
|
|
34
37
|
"scripts": {
|
|
35
38
|
"verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
|