@greatdayhr/capacitor-datetime-setting 1.2.0 → 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 CHANGED
@@ -3,125 +3,319 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@greatdayhr/capacitor-datetime-setting.svg)](https://www.npmjs.com/package/@greatdayhr/capacitor-datetime-setting)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- Capacitor plugin to get information about auto time and auto timezone settings, and open device settings if needed.
6
+ Capacitor plugin for comprehensive date/time management on iOS. Cloned from [date_change_checker](https://github.com/error404sushant/date_change_checker) Flutter plugin.
7
+
8
+ **Features:**
9
+ - Detect manual date/time changes with network validation
10
+ - Comprehensive change analysis (date-only, time-only, or both)
11
+ - Automatic user notifications for detected changes
12
+ - Fetch accurate internet time from time servers
13
+ - Timestamp management for change tracking
14
+ - Network-optimized with caching and offline fallback
15
+
16
+ **Platform Support:**
17
+ - ✅ **iOS**: Full implementation (10 methods)
18
+ - ❌ **Android**: Not implemented (use native Settings API directly)
19
+ - ❌ **Web**: Not supported
7
20
 
8
21
  ## Installation
9
22
 
10
23
  ```bash
11
24
  npm install @greatdayhr/capacitor-datetime-setting
12
- npx cap sync
25
+ npx cap sync ios
13
26
  ```
14
27
 
15
28
  ## API
16
29
 
17
- ### `timeIsAuto()`
30
+ ### Date/Time Change Detection
18
31
 
19
- Check if automatic time is enabled on the device.
32
+ #### `detectDateTimeChange()`
20
33
 
21
- **Returns:** `Promise<{ value: boolean }>`
34
+ Detects if the device's date/time has been manually changed. Uses network time comparison for accuracy when available, falls back to local time comparison offline.
22
35
 
23
- **Platform Support:**
24
- - ✅ Android: Returns actual setting value using `Settings.Global.AUTO_TIME`
25
- - iOS: Uses network time comparison for reliable detection (with offline fallback)
36
+ **Returns:** `Promise<{ changed: boolean }>`
37
+
38
+ **Platform Support:** iOS only
26
39
 
27
40
  **Example:**
28
41
 
29
42
  ```typescript
30
43
  import { DateTimeSetting } from '@greatdayhr/capacitor-datetime-setting';
31
44
 
32
- const result = await DateTimeSetting.timeIsAuto();
33
- console.log('Auto time enabled:', result.value);
45
+ const result = await DateTimeSetting.detectDateTimeChange();
46
+ if (result.changed) {
47
+ console.log('Date/time has been manually changed!');
48
+ }
34
49
  ```
35
50
 
36
51
  ---
37
52
 
38
- ### `timeZoneIsAuto()`
53
+ #### `detectComprehensiveDateTimeChange()`
39
54
 
40
- Check if automatic timezone is enabled on the device.
55
+ Comprehensive date and time change detection with detailed analysis. Distinguishes between date-only, time-only, and combined changes.
41
56
 
42
- **Returns:** `Promise<{ value: boolean }>`
57
+ **Returns:** `Promise<DateTimeChangeResult>`
43
58
 
44
- **Platform Support:**
45
- - Android: Returns actual setting value using `Settings.Global.AUTO_TIME_ZONE`
46
- - ✅ iOS: Uses network time comparison for reliable detection (with offline fallback)
59
+ ```typescript
60
+ interface DateTimeChangeResult {
61
+ changeType: 'noChange' | 'timeOnly' | 'dateOnly' | 'dateAndTime';
62
+ timeDifference: number;
63
+ dateChanged: boolean;
64
+ timeChanged: boolean;
65
+ isAutoDateTimeEnabled: boolean;
66
+ previousDate?: number;
67
+ currentDate: number;
68
+ }
69
+ ```
70
+
71
+ **Platform Support:** iOS only
72
+
73
+ **Example:**
74
+
75
+ ```typescript
76
+ import { DateTimeSetting } from '@greatdayhr/capacitor-datetime-setting';
77
+
78
+ const result = await DateTimeSetting.detectComprehensiveDateTimeChange();
79
+ console.log('Change type:', result.changeType);
80
+ console.log('Date changed:', result.dateChanged);
81
+ console.log('Time changed:', result.timeChanged);
82
+ console.log('Time difference:', result.timeDifference, 'seconds');
83
+ console.log('Auto time enabled:', result.isAutoDateTimeEnabled);
84
+ ```
85
+
86
+ ---
87
+
88
+ #### `detectDateOnlyChange()`
89
+
90
+ Detects specifically if only the date has been changed while time remains similar. Useful for detecting manual date changes when auto date/time is disabled.
91
+
92
+ **Returns:** `Promise<{ changed: boolean }>`
93
+
94
+ **Platform Support:** iOS only
95
+
96
+ **Example:**
97
+
98
+ ```typescript
99
+ import { DateTimeSetting } from '@greatdayhr/capacitor-datetime-setting';
100
+
101
+ const result = await DateTimeSetting.detectDateOnlyChange();
102
+ if (result.changed) {
103
+ console.log('Only the date was changed!');
104
+ }
105
+ ```
106
+
107
+ ---
108
+
109
+ #### `detectAndNotifyDateTimeChanges()`
110
+
111
+ Comprehensive date and time change detection with automatic user notifications. Shows native iOS notifications when changes are detected.
112
+
113
+ **Returns:** `Promise<DateTimeChangeResult>`
114
+
115
+ **Platform Support:** iOS only
116
+
117
+ **Example:**
118
+
119
+ ```typescript
120
+ import { DateTimeSetting } from '@greatdayhr/capacitor-datetime-setting';
121
+
122
+ const result = await DateTimeSetting.detectAndNotifyDateTimeChanges();
123
+ // User automatically sees notification if changes detected
124
+ console.log('Change type:', result.changeType);
125
+ ```
126
+
127
+ ---
128
+
129
+ ### Time Utilities
130
+
131
+ #### `getLocalTime()`
132
+
133
+ Get the device's current local time as Unix timestamp.
134
+
135
+ **Returns:** `Promise<{ timestamp: number }>`
136
+
137
+ **Platform Support:** iOS only
138
+
139
+ **Example:**
140
+
141
+ ```typescript
142
+ import { DateTimeSetting } from '@greatdayhr/capacitor-datetime-setting';
143
+
144
+ const result = await DateTimeSetting.getLocalTime();
145
+ const date = new Date(result.timestamp * 1000);
146
+ console.log('Current local time:', date);
147
+ ```
148
+
149
+ ---
150
+
151
+ #### `getInternetUTCTime()`
152
+
153
+ Fetch accurate UTC time from internet time server (WorldTimeAPI).
154
+
155
+ **Returns:** `Promise<{ timestamp: number }>`
156
+
157
+ **Platform Support:** iOS only
158
+
159
+ **Example:**
160
+
161
+ ```typescript
162
+ import { DateTimeSetting } from '@greatdayhr/capacitor-datetime-setting';
163
+
164
+ try {
165
+ const result = await DateTimeSetting.getInternetUTCTime();
166
+ const date = new Date(result.timestamp * 1000);
167
+ console.log('Internet UTC time:', date);
168
+ } catch (error) {
169
+ console.error('Failed to fetch internet time:', error);
170
+ }
171
+ ```
172
+
173
+ ---
174
+
175
+ #### `convertToLocalTime(options)`
176
+
177
+ Convert local time to UTC.
178
+
179
+ **Parameters:**
180
+ - `options.timestamp` (number): Unix timestamp to convert
181
+
182
+ **Returns:** `Promise<{ timestamp: number }>`
183
+
184
+ **Platform Support:** iOS only
47
185
 
48
186
  **Example:**
49
187
 
50
188
  ```typescript
51
189
  import { DateTimeSetting } from '@greatdayhr/capacitor-datetime-setting';
52
190
 
53
- const result = await DateTimeSetting.timeZoneIsAuto();
54
- console.log('Auto timezone enabled:', result.value);
191
+ const localTimestamp = Date.now() / 1000;
192
+ const result = await DateTimeSetting.convertToLocalTime({
193
+ timestamp: localTimestamp
194
+ });
195
+ console.log('UTC timestamp:', result.timestamp);
55
196
  ```
56
197
 
57
198
  ---
58
199
 
59
- ### `openSetting()`
200
+ ### Timestamp Management
201
+
202
+ #### `setStoredTimestamp(options)`
60
203
 
61
- Open the device's date and time settings screen.
204
+ Set the stored timestamp for future change detection comparisons.
205
+
206
+ **Parameters:**
207
+ - `options.timestamp` (number): Unix timestamp to store
62
208
 
63
209
  **Returns:** `Promise<void>`
64
210
 
65
- **Platform Support:**
66
- - ✅ Android: Opens Date & Time settings directly
67
- - ⚠️ iOS: Opens main Settings app (cannot open specific settings page)
211
+ **Platform Support:** iOS only
68
212
 
69
213
  **Example:**
70
214
 
71
215
  ```typescript
72
216
  import { DateTimeSetting } from '@greatdayhr/capacitor-datetime-setting';
73
217
 
74
- await DateTimeSetting.openSetting();
218
+ const currentTimestamp = Date.now() / 1000;
219
+ await DateTimeSetting.setStoredTimestamp({
220
+ timestamp: currentTimestamp
221
+ });
75
222
  ```
76
223
 
224
+ ---
225
+
226
+ #### `getStoredTimestamp()`
227
+
228
+ Get the currently stored timestamp used for change detection.
229
+
230
+ **Returns:** `Promise<{ timestamp: number | null }>`
231
+
232
+ **Platform Support:** iOS only
233
+
234
+ **Example:**
235
+
236
+ ```typescript
237
+ import { DateTimeSetting } from '@greatdayhr/capacitor-datetime-setting';
238
+
239
+ const result = await DateTimeSetting.getStoredTimestamp();
240
+ if (result.timestamp) {
241
+ const date = new Date(result.timestamp * 1000);
242
+ console.log('Stored timestamp:', date);
243
+ } else {
244
+ console.log('No timestamp stored');
245
+ }
246
+ ```
247
+
248
+ ---
249
+
250
+ #### `resetDetector()`
251
+
252
+ Reset the detector, clearing all stored data and cache.
253
+
254
+ **Returns:** `Promise<void>`
255
+
256
+ **Platform Support:** iOS only
257
+
258
+ **Example:**
259
+
260
+ ```typescript
261
+ import { DateTimeSetting } from '@greatdayhr/capacitor-datetime-setting';
262
+
263
+ await DateTimeSetting.resetDetector();
264
+ console.log('Detector has been reset');
265
+ ```
266
+
267
+ ---
268
+
77
269
  ## Usage Example
78
270
 
79
- Here's a complete example showing how to check settings and prompt user to enable auto time:
271
+ Here's a complete example showing how to detect and respond to date/time changes:
80
272
 
81
273
  ```typescript
82
274
  import { DateTimeSetting } from '@greatdayhr/capacitor-datetime-setting';
83
275
  import { Capacitor } from '@capacitor/core';
84
276
 
85
- async function checkAutoTimeSettings() {
277
+ async function monitorDateTimeChanges() {
278
+ // Only works on iOS
279
+ if (Capacitor.getPlatform() !== 'ios') {
280
+ console.log('Date/time detection only available on iOS');
281
+ return;
282
+ }
283
+
86
284
  try {
87
- const timeResult = await DateTimeSetting.timeIsAuto();
88
- const timezoneResult = await DateTimeSetting.timeZoneIsAuto();
285
+ // Initialize with current timestamp
286
+ const now = Date.now() / 1000;
287
+ await DateTimeSetting.setStoredTimestamp({ timestamp: now });
89
288
 
90
- const platform = Capacitor.getPlatform();
289
+ // Detect changes with notifications
290
+ const result = await DateTimeSetting.detectAndNotifyDateTimeChanges();
91
291
 
92
- // Both Android and iOS can now detect auto time settings
93
- if (!timeResult.value || !timezoneResult.value) {
94
- // Show alert to user
95
- const shouldOpen = confirm(
96
- 'Please enable automatic date & time and timezone for accurate time tracking.'
97
- );
292
+ if (result.changeType !== 'noChange') {
293
+ console.log('Change detected!');
294
+ console.log('Type:', result.changeType);
295
+ console.log('Auto time enabled:', result.isAutoDateTimeEnabled);
98
296
 
99
- if (shouldOpen) {
100
- await DateTimeSetting.openSetting();
297
+ // Handle the change
298
+ if (!result.isAutoDateTimeEnabled) {
299
+ alert('Please enable automatic date & time in Settings');
101
300
  }
102
301
  }
103
302
  } catch (error) {
104
- console.error('Error checking time settings:', error);
303
+ console.error('Error detecting time changes:', error);
105
304
  }
106
305
  }
306
+
307
+ // Call this periodically or on app resume
308
+ monitorDateTimeChanges();
107
309
  ```
108
310
 
109
311
  ## Platform-Specific Notes
110
312
 
111
- ### Android
112
-
113
- The plugin uses Android's `Settings.Global` API to check the auto time and timezone settings. It supports Android API level 17 (Jelly Bean MR1) and above, with fallback to `Settings.System` for older versions.
114
-
115
- **Permissions:** No special permissions required.
116
-
117
313
  ### iOS
118
314
 
119
- iOS does not provide direct public APIs to check auto date/time settings. This plugin uses a **network-based detection** method for reliable results:
315
+ The plugin uses a comprehensive multi-layered approach for reliable date/time detection:
120
316
 
121
317
  #### Detection Method
122
318
 
123
- The plugin uses a multi-layered approach to detect auto date/time settings:
124
-
125
319
  1. **Cache Check** (Instant)
126
320
  - Returns cached result if available and less than 30 seconds old
127
321
  - Avoids unnecessary network calls for better performance
@@ -143,13 +337,6 @@ The plugin uses a multi-layered approach to detect auto date/time settings:
143
337
  - Considers system uptime for better accuracy
144
338
  - Ensures plugin works without network connection
145
339
 
146
- #### Why Network Comparison?
147
-
148
- The simple `TimeZone.autoupdatingCurrent` check alone is **not reliable** because:
149
- - It can return false positives when timezone is set correctly but time is manually changed
150
- - It doesn't detect when user manually sets the exact same timezone
151
- - Network time comparison provides definitive proof of time synchronization
152
-
153
340
  #### Features
154
341
 
155
342
  - ✅ **High Accuracy**: Detects manual time changes even if timezone is correct
@@ -158,22 +345,36 @@ The simple `TimeZone.autoupdatingCurrent` check alone is **not reliable** becaus
158
345
  - ✅ **Battery Friendly**: Network monitoring prevents unnecessary requests
159
346
  - ✅ **Non-Blocking**: Async operations don't freeze the UI
160
347
  - ✅ **Automatic Cleanup**: Proper resource management on plugin deallocation
348
+ - ✅ **User Notifications**: Automatic native notifications for detected changes
161
349
 
162
350
  #### Limitations
163
351
 
164
- - `openSetting()` opens the main Settings app instead of the specific Date & Time page (iOS restriction)
165
352
  - First call after app launch requires network for best accuracy (cached afterward)
166
353
  - Network check timeout is 3 seconds
167
- - Assumes time difference > 60 seconds means auto-time is disabled (works for most cases)
354
+ - Assumes time difference > 60 seconds means auto-time is disabled
355
+ - Notifications require user permission
168
356
 
169
- #### Technical Implementation
357
+ ### Android
170
358
 
171
- **Network Time Server**: Uses WorldTimeAPI for reliable UTC time
172
- **Caching Strategy**: In-memory cache with 30-second TTL
173
- **Network Monitoring**: Uses Apple's `Network` framework
174
- **Threading**: Main queue dispatch for Capacitor callbacks
359
+ **Not implemented.** The source plugin (date_change_checker) only has basic Settings checks on Android, which can be easily done with native code:
360
+
361
+ ```java
362
+ // Check if auto time is enabled
363
+ boolean isAutoTime = Settings.Global.getInt(
364
+ context.getContentResolver(),
365
+ Settings.Global.AUTO_TIME,
366
+ 0
367
+ ) == 1;
368
+
369
+ // Check if auto timezone is enabled
370
+ boolean isAutoTimeZone = Settings.Global.getInt(
371
+ context.getContentResolver(),
372
+ Settings.Global.AUTO_TIME_ZONE,
373
+ 0
374
+ ) == 1;
375
+ ```
175
376
 
176
- **Credit:** This technique is inspired by the Flutter [date_change_checker](https://github.com/error404sushant/date_change_checker) plugin.
377
+ Android doesn't need the complex network validation that iOS requires because it has direct Settings API access.
177
378
 
178
379
  ### Web
179
380
 
@@ -193,14 +394,11 @@ This plugin is not supported on web. All methods will throw "Not implemented on
193
394
 
194
395
  ### iOS: Slow first response
195
396
 
196
- **Problem**: First call to `timeIsAuto()` takes 3+ seconds.
397
+ **Problem**: First call to detection methods takes 3+ seconds.
197
398
 
198
399
  **Explanation**: This is expected behavior. The first call makes a network request to fetch accurate time. Subsequent calls within 30 seconds use cached results and return instantly.
199
400
 
200
- **Solution**: If you need instant response, consider:
201
- - Pre-warming the cache by calling `timeIsAuto()` during app initialization
202
- - Showing a loading indicator during the first check
203
- - Using the offline fallback (less accurate but instant)
401
+ **Solution**: Pre-warm the cache by calling a detection method during app initialization with a loading indicator.
204
402
 
205
403
  ### iOS: Plugin doesn't work in airplane mode
206
404
 
@@ -210,20 +408,30 @@ This plugin is not supported on web. All methods will throw "Not implemented on
210
408
 
211
409
  **Solution**: This is expected behavior. For best accuracy, ensure network connectivity. The offline fallback is a compromise for offline scenarios.
212
410
 
213
- ### Android: Plugin not detecting changes
411
+ ### iOS: Notifications not showing
214
412
 
215
- **Problem**: Auto time/timezone setting changes are not detected.
413
+ **Problem**: No notifications appear when changes are detected.
216
414
 
217
- **Solution**: Ensure you're testing on a physical device. Some emulators may not properly reflect system setting changes.
415
+ **Solutions**:
416
+ 1. Ensure notification permissions are granted
417
+ 2. Check device notification settings
418
+ 3. The plugin requests permission on first load - user might have denied it
218
419
 
219
420
  ## Version History
220
421
 
221
422
  See [CHANGELOG.md](CHANGELOG.md) for detailed version history.
222
423
 
223
- **Latest version (1.2.0)**:
224
- - Improved iOS detection with network time comparison
225
- - Added caching for better performance
226
- - Better offline support
424
+ **Latest version (2.0.0)**:
425
+ - Cloned all iOS functionality from date_change_checker Flutter plugin
426
+ - Added comprehensive date/time change detection methods (4 methods)
427
+ - Added automatic user notifications for date/time changes (iOS)
428
+ - ✨ Added time utility methods (3 methods)
429
+ - ✨ Added timestamp management for change tracking (3 methods)
430
+ - ✨ Added `NotificationManager` for iOS notifications (259 lines)
431
+ - 🔧 Enhanced `AutoDateTimeDetector` with comprehensive 671-line implementation
432
+ - 📝 Complete TypeScript definitions for all methods
433
+ - 🎯 iOS-only implementation (matches source plugin's platform support)
434
+ - ❌ Removed Android/Web implementations (source plugin has minimal Android support)
227
435
 
228
436
  ## License
229
437
 
@@ -231,4 +439,4 @@ MIT
231
439
 
232
440
  ## Credits
233
441
 
234
- This plugin is based on the Flutter [datetime_setting](https://github.com/fuadarradhi/datetime_setting) plugin by [fuadarradhi](https://github.com/fuadarradhi).
442
+ This plugin is a Capacitor port of the Flutter [date_change_checker](https://github.com/error404sushant/date_change_checker) plugin. All iOS implementation logic is cloned from the original source.
@@ -1,101 +1,20 @@
1
1
  package com.datetimesetting;
2
2
 
3
- import android.content.Intent;
4
- import android.os.Build;
5
- import android.provider.Settings;
6
-
7
- import com.getcapacitor.JSObject;
8
3
  import com.getcapacitor.Plugin;
9
- import com.getcapacitor.PluginCall;
10
- import com.getcapacitor.PluginMethod;
11
4
  import com.getcapacitor.annotation.CapacitorPlugin;
12
5
 
13
6
  /**
14
- * DateTimeSettingPlugin
7
+ * DateTimeSettingPlugin - Android Implementation
8
+ *
9
+ * Note: All date/time detection methods are iOS-only.
10
+ * Android does not implement the comprehensive features from date_change_checker
11
+ * because the source plugin itself only has basic Settings checks on Android.
15
12
  *
16
- * Capacitor plugin to check auto time/timezone settings and open device settings.
13
+ * For Android auto time detection, use native Settings API directly:
14
+ * Settings.Global.getInt(context.getContentResolver(), Settings.Global.AUTO_TIME, 0) == 1
17
15
  */
18
16
  @CapacitorPlugin(name = "DateTimeSetting")
19
17
  public class DateTimeSettingPlugin extends Plugin {
20
-
21
- /**
22
- * Check if automatic time is enabled on the device.
23
- *
24
- * @param call The plugin call
25
- */
26
- @PluginMethod
27
- public void timeIsAuto(PluginCall call) {
28
- try {
29
- boolean isAuto;
30
-
31
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
32
- isAuto = Settings.Global.getInt(
33
- getContext().getContentResolver(),
34
- Settings.Global.AUTO_TIME,
35
- 0
36
- ) == 1;
37
- } else {
38
- isAuto = Settings.System.getInt(
39
- getContext().getContentResolver(),
40
- Settings.System.AUTO_TIME,
41
- 0
42
- ) == 1;
43
- }
44
-
45
- JSObject result = new JSObject();
46
- result.put("value", isAuto);
47
- call.resolve(result);
48
- } catch (Exception e) {
49
- call.reject("Failed to check auto time setting", e);
50
- }
51
- }
52
-
53
- /**
54
- * Check if automatic timezone is enabled on the device.
55
- *
56
- * @param call The plugin call
57
- */
58
- @PluginMethod
59
- public void timeZoneIsAuto(PluginCall call) {
60
- try {
61
- boolean isAuto;
62
-
63
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
64
- isAuto = Settings.Global.getInt(
65
- getContext().getContentResolver(),
66
- Settings.Global.AUTO_TIME_ZONE,
67
- 0
68
- ) == 1;
69
- } else {
70
- isAuto = Settings.System.getInt(
71
- getContext().getContentResolver(),
72
- Settings.System.AUTO_TIME_ZONE,
73
- 0
74
- ) == 1;
75
- }
76
-
77
- JSObject result = new JSObject();
78
- result.put("value", isAuto);
79
- call.resolve(result);
80
- } catch (Exception e) {
81
- call.reject("Failed to check auto timezone setting", e);
82
- }
83
- }
84
-
85
- /**
86
- * Open the device's date and time settings screen.
87
- *
88
- * @param call The plugin call
89
- */
90
- @PluginMethod
91
- public void openSetting(PluginCall call) {
92
- try {
93
- Intent intent = new Intent(Settings.ACTION_DATE_SETTINGS);
94
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
95
- getContext().startActivity(intent);
96
- call.resolve();
97
- } catch (Exception e) {
98
- call.reject("Failed to open date/time settings", e);
99
- }
100
- }
18
+ // All methods are iOS-only
19
+ // Android implementation intentionally left minimal as per date_change_checker source
101
20
  }