rn-persistent-timer 1.1.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 +607 -0
- package/android/.gradle/7.4.2/checksums/checksums.lock +0 -0
- package/android/.gradle/7.4.2/fileChanges/last-build.bin +0 -0
- package/android/.gradle/7.4.2/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/7.4.2/gc.properties +0 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/build.gradle +15 -0
- package/android/src/main/java/com/rnpersistenttimer/RNPersistentTimerModule.java +164 -0
- package/android/src/main/java/com/rnpersistenttimer/RNPersistentTimerPackage.java +27 -0
- package/android/src/main/java/com/rnpersistenttimer/TimerForegroundService.java +280 -0
- package/ios/RNPersistentTimer.h +10 -0
- package/ios/RNPersistentTimer.m +221 -0
- package/lib/commonjs/NativeTimerModule.js +46 -0
- package/lib/commonjs/NativeTimerModule.js.map +1 -0
- package/lib/commonjs/PersistentTimerManager.js +337 -0
- package/lib/commonjs/PersistentTimerManager.js.map +1 -0
- package/lib/commonjs/index.js +76 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/types.js +2 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/usePersistentTimer.js +159 -0
- package/lib/commonjs/usePersistentTimer.js.map +1 -0
- package/lib/commonjs/utils.js +112 -0
- package/lib/commonjs/utils.js.map +1 -0
- package/lib/module/NativeTimerModule.js +40 -0
- package/lib/module/NativeTimerModule.js.map +1 -0
- package/lib/module/PersistentTimerManager.js +329 -0
- package/lib/module/PersistentTimerManager.js.map +1 -0
- package/lib/module/index.js +17 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/usePersistentTimer.js +153 -0
- package/lib/module/usePersistentTimer.js.map +1 -0
- package/lib/module/utils.js +100 -0
- package/lib/module/utils.js.map +1 -0
- package/lib/typescript/NativeTimerModule.d.ts +31 -0
- package/lib/typescript/NativeTimerModule.d.ts.map +1 -0
- package/lib/typescript/PersistentTimerManager.d.ts +37 -0
- package/lib/typescript/PersistentTimerManager.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +7 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +167 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/lib/typescript/usePersistentTimer.d.ts +16 -0
- package/lib/typescript/usePersistentTimer.d.ts.map +1 -0
- package/lib/typescript/utils.d.ts +36 -0
- package/lib/typescript/utils.d.ts.map +1 -0
- package/package.json +98 -0
- package/src/NativeTimerModule.ts +73 -0
- package/src/PersistentTimerManager.ts +410 -0
- package/src/index.ts +41 -0
- package/src/types.ts +198 -0
- package/src/usePersistentTimer.tsx +173 -0
- package/src/utils.ts +91 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "NATIVE_EVENTS", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _NativeTimerModule.NATIVE_EVENTS;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "NativeTimerEmitter", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _NativeTimerModule.NativeTimerEmitter;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "NativeTimerModule", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _NativeTimerModule.NativeTimerModule;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "PersistentTimerManager", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _PersistentTimerManager.PersistentTimerManager;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(exports, "cancelAllTimers", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () {
|
|
33
|
+
return _utils.cancelAllTimers;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "formatTime", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () {
|
|
39
|
+
return _utils.formatTime;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(exports, "getActiveTimers", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: function () {
|
|
45
|
+
return _utils.getActiveTimers;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(exports, "isBackgroundTimerSupported", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () {
|
|
51
|
+
return _utils.isBackgroundTimerSupported;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
Object.defineProperty(exports, "isKilledStateTimerSupported", {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get: function () {
|
|
57
|
+
return _utils.isKilledStateTimerSupported;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(exports, "parseTime", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function () {
|
|
63
|
+
return _utils.parseTime;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
Object.defineProperty(exports, "usePersistentTimer", {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
get: function () {
|
|
69
|
+
return _usePersistentTimer.usePersistentTimer;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
var _usePersistentTimer = require("./usePersistentTimer");
|
|
73
|
+
var _PersistentTimerManager = require("./PersistentTimerManager");
|
|
74
|
+
var _utils = require("./utils");
|
|
75
|
+
var _NativeTimerModule = require("./NativeTimerModule");
|
|
76
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_usePersistentTimer","require","_PersistentTimerManager","_utils","_NativeTimerModule"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,IAAAA,mBAAA,GAAAC,OAAA;AAGA,IAAAC,uBAAA,GAAAD,OAAA;AAGA,IAAAE,MAAA,GAAAF,OAAA;AAyBA,IAAAG,kBAAA,GAAAH,OAAA","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.usePersistentTimer = usePersistentTimer;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _PersistentTimerManager = require("./PersistentTimerManager");
|
|
9
|
+
var _utils = require("./utils");
|
|
10
|
+
// rn-persistent-timer — usePersistentTimer Hook
|
|
11
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
function makeInitialSnapshot(config) {
|
|
16
|
+
const mode = config.mode ?? 'stopwatch';
|
|
17
|
+
const duration = config.duration ?? 0;
|
|
18
|
+
return {
|
|
19
|
+
timerId: config.timerId,
|
|
20
|
+
elapsed: 0,
|
|
21
|
+
remaining: mode === 'countdown' ? duration : null,
|
|
22
|
+
state: 'idle',
|
|
23
|
+
appState: 'foreground',
|
|
24
|
+
startedAt: null,
|
|
25
|
+
pausedAt: null,
|
|
26
|
+
formattedElapsed: '00:00:00',
|
|
27
|
+
formattedRemaining: mode === 'countdown' ? (0, _utils.formatTime)(duration) : null,
|
|
28
|
+
progress: mode === 'countdown' ? 0 : null
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* React hook for persistent timers.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* const { snapshot, start, pause, reset, isRunning } = usePersistentTimer({
|
|
40
|
+
* timerId: 'workout-timer',
|
|
41
|
+
* mode: 'stopwatch',
|
|
42
|
+
* runInBackground: true,
|
|
43
|
+
* onTick: (snap) => console.log(snap.formattedElapsed),
|
|
44
|
+
* });
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
function usePersistentTimer(config) {
|
|
48
|
+
const managerRef = (0, _react.useRef)(null);
|
|
49
|
+
const [snapshot, setSnapshot] = (0, _react.useState)(() => makeInitialSnapshot(config));
|
|
50
|
+
|
|
51
|
+
// Stable callback refs — avoids re-creating the manager when callbacks change
|
|
52
|
+
const callbacksRef = (0, _react.useRef)({});
|
|
53
|
+
callbacksRef.current = {
|
|
54
|
+
onTick: config.onTick,
|
|
55
|
+
onStart: config.onStart,
|
|
56
|
+
onPause: config.onPause,
|
|
57
|
+
onResume: config.onResume,
|
|
58
|
+
onReset: config.onReset,
|
|
59
|
+
onComplete: config.onComplete,
|
|
60
|
+
onBackground: config.onBackground,
|
|
61
|
+
onForeground: config.onForeground,
|
|
62
|
+
onRestore: config.onRestore,
|
|
63
|
+
onError: config.onError
|
|
64
|
+
};
|
|
65
|
+
(0, _react.useEffect)(() => {
|
|
66
|
+
const manager = new _PersistentTimerManager.PersistentTimerManager({
|
|
67
|
+
timerId: config.timerId,
|
|
68
|
+
mode: config.mode,
|
|
69
|
+
duration: config.duration,
|
|
70
|
+
runInBackground: config.runInBackground,
|
|
71
|
+
runInKilledState: config.runInKilledState,
|
|
72
|
+
pauseOnBackground: config.pauseOnBackground,
|
|
73
|
+
resetOnForeground: config.resetOnForeground,
|
|
74
|
+
interval: config.interval,
|
|
75
|
+
showNotification: config.showNotification,
|
|
76
|
+
notification: config.notification
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Snapshot callbacks — update React state then call user callback
|
|
80
|
+
|
|
81
|
+
const wire = (managerEvent, cbKey) => {
|
|
82
|
+
manager.on(managerEvent, snap => {
|
|
83
|
+
setSnapshot({
|
|
84
|
+
...snap
|
|
85
|
+
});
|
|
86
|
+
callbacksRef.current[cbKey]?.(snap);
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
wire('onTick', 'onTick');
|
|
90
|
+
wire('onStart', 'onStart');
|
|
91
|
+
wire('onPause', 'onPause');
|
|
92
|
+
wire('onResume', 'onResume');
|
|
93
|
+
wire('onReset', 'onReset');
|
|
94
|
+
wire('onComplete', 'onComplete');
|
|
95
|
+
wire('onBackground', 'onBackground');
|
|
96
|
+
wire('onForeground', 'onForeground');
|
|
97
|
+
wire('onRestore', 'onRestore');
|
|
98
|
+
|
|
99
|
+
// Error callback — receives Error, not TimerSnapshot
|
|
100
|
+
manager.on('error', err => {
|
|
101
|
+
callbacksRef.current.onError?.(err);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Restore from killed state if applicable
|
|
105
|
+
if (config.runInKilledState) {
|
|
106
|
+
_PersistentTimerManager.PersistentTimerManager.restore(config.timerId).then(restored => {
|
|
107
|
+
if (!restored) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Replay internal state onto the manager
|
|
112
|
+
manager._elapsed = restored.elapsed;
|
|
113
|
+
manager._state = restored.state;
|
|
114
|
+
const snap = manager.getSnapshot();
|
|
115
|
+
setSnapshot({
|
|
116
|
+
...snap
|
|
117
|
+
});
|
|
118
|
+
callbacksRef.current.onRestore?.(snap);
|
|
119
|
+
|
|
120
|
+
// Auto-resume if the timer was running when the app was killed
|
|
121
|
+
if (restored.state === 'running') {
|
|
122
|
+
manager.start();
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
managerRef.current = manager;
|
|
127
|
+
return () => {
|
|
128
|
+
manager.destroy();
|
|
129
|
+
managerRef.current = null;
|
|
130
|
+
};
|
|
131
|
+
// Re-create the manager only if timerId changes
|
|
132
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
133
|
+
}, [config.timerId]);
|
|
134
|
+
|
|
135
|
+
// ─── Stable controls ──────────────────────────────────────────────────────
|
|
136
|
+
|
|
137
|
+
const start = (0, _react.useCallback)(() => managerRef.current?.start(), []);
|
|
138
|
+
const pause = (0, _react.useCallback)(() => managerRef.current?.pause(), []);
|
|
139
|
+
const resume = (0, _react.useCallback)(() => managerRef.current?.resume(), []);
|
|
140
|
+
const reset = (0, _react.useCallback)(() => managerRef.current?.reset(), []);
|
|
141
|
+
const stop = (0, _react.useCallback)(() => managerRef.current?.stop(), []);
|
|
142
|
+
const destroy = (0, _react.useCallback)(() => managerRef.current?.destroy(), []);
|
|
143
|
+
const getSnapshot = (0, _react.useCallback)(() => managerRef.current?.getSnapshot() ?? snapshot, [snapshot]);
|
|
144
|
+
return {
|
|
145
|
+
snapshot,
|
|
146
|
+
isRunning: snapshot.state === 'running',
|
|
147
|
+
isPaused: snapshot.state === 'paused',
|
|
148
|
+
isCompleted: snapshot.state === 'completed',
|
|
149
|
+
appState: snapshot.appState,
|
|
150
|
+
start,
|
|
151
|
+
pause,
|
|
152
|
+
resume,
|
|
153
|
+
reset,
|
|
154
|
+
stop,
|
|
155
|
+
destroy,
|
|
156
|
+
getSnapshot
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=usePersistentTimer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","require","_PersistentTimerManager","_utils","makeInitialSnapshot","config","mode","duration","timerId","elapsed","remaining","state","appState","startedAt","pausedAt","formattedElapsed","formattedRemaining","formatTime","progress","usePersistentTimer","managerRef","useRef","snapshot","setSnapshot","useState","callbacksRef","current","onTick","onStart","onPause","onResume","onReset","onComplete","onBackground","onForeground","onRestore","onError","useEffect","manager","PersistentTimerManager","runInBackground","runInKilledState","pauseOnBackground","resetOnForeground","interval","showNotification","notification","wire","managerEvent","cbKey","on","snap","err","restore","then","restored","_elapsed","_state","getSnapshot","start","destroy","useCallback","pause","resume","reset","stop","isRunning","isPaused","isCompleted"],"sourceRoot":"../../src","sources":["usePersistentTimer.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.cancelAllTimers = cancelAllTimers;
|
|
7
|
+
exports.formatTime = formatTime;
|
|
8
|
+
exports.getActiveTimers = getActiveTimers;
|
|
9
|
+
exports.isBackgroundTimerSupported = isBackgroundTimerSupported;
|
|
10
|
+
exports.isKilledStateTimerSupported = isKilledStateTimerSupported;
|
|
11
|
+
exports.parseTime = parseTime;
|
|
12
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
13
|
+
// rn-persistent-timer — Utility Functions
|
|
14
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Format a number of seconds into an `HH:MM:SS` string.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* formatTime(3661); // '01:01:01'
|
|
21
|
+
* formatTime(59); // '00:00:59'
|
|
22
|
+
*/
|
|
23
|
+
function formatTime(seconds) {
|
|
24
|
+
const s = Math.max(0, Math.floor(seconds));
|
|
25
|
+
const h = Math.floor(s / 3600);
|
|
26
|
+
const m = Math.floor(s % 3600 / 60);
|
|
27
|
+
const sec = s % 60;
|
|
28
|
+
return [h, m, sec].map(v => String(v).padStart(2, '0')).join(':');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Parse an `HH:MM:SS` or `MM:SS` string into total seconds.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* parseTime('01:30:00'); // 5400
|
|
36
|
+
* parseTime('05:30'); // 330
|
|
37
|
+
*/
|
|
38
|
+
function parseTime(formatted) {
|
|
39
|
+
const parts = formatted.split(':').map(Number);
|
|
40
|
+
if (parts.length === 3) {
|
|
41
|
+
return parts[0] * 3600 + parts[1] * 60 + parts[2];
|
|
42
|
+
}
|
|
43
|
+
if (parts.length === 2) {
|
|
44
|
+
return parts[0] * 60 + parts[1];
|
|
45
|
+
}
|
|
46
|
+
return parts[0] ?? 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Returns `true` if the native background-timer module is available on this
|
|
51
|
+
* device / build. Always returns `false` in Expo Go.
|
|
52
|
+
*/
|
|
53
|
+
async function isBackgroundTimerSupported() {
|
|
54
|
+
const {
|
|
55
|
+
NativeTimerModule
|
|
56
|
+
} = await Promise.resolve().then(() => _interopRequireWildcard(require('./NativeTimerModule')));
|
|
57
|
+
return Boolean(NativeTimerModule);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Returns `true` if the killed-state persistence feature is supported.
|
|
62
|
+
* Requires the native module **and** platform capabilities
|
|
63
|
+
* (WorkManager on Android, BGTaskScheduler on iOS 13+).
|
|
64
|
+
*/
|
|
65
|
+
async function isKilledStateTimerSupported() {
|
|
66
|
+
const {
|
|
67
|
+
NativeTimerModule
|
|
68
|
+
} = await Promise.resolve().then(() => _interopRequireWildcard(require('./NativeTimerModule')));
|
|
69
|
+
if (!NativeTimerModule) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
return (await NativeTimerModule.isKilledStateSupported?.()) ?? false;
|
|
74
|
+
} catch {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Return the IDs of all timers currently active in the native layer.
|
|
81
|
+
*/
|
|
82
|
+
async function getActiveTimers() {
|
|
83
|
+
const {
|
|
84
|
+
NativeTimerModule
|
|
85
|
+
} = await Promise.resolve().then(() => _interopRequireWildcard(require('./NativeTimerModule')));
|
|
86
|
+
if (!NativeTimerModule) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
return await NativeTimerModule.getActiveTimers();
|
|
91
|
+
} catch {
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Cancel every active timer in both the native layer and JS.
|
|
98
|
+
*/
|
|
99
|
+
async function cancelAllTimers() {
|
|
100
|
+
const {
|
|
101
|
+
NativeTimerModule
|
|
102
|
+
} = await Promise.resolve().then(() => _interopRequireWildcard(require('./NativeTimerModule')));
|
|
103
|
+
if (!NativeTimerModule) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
await NativeTimerModule.cancelAll();
|
|
108
|
+
} catch {
|
|
109
|
+
// Swallow — best-effort cleanup
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["formatTime","seconds","s","Math","max","floor","h","m","sec","map","v","String","padStart","join","parseTime","formatted","parts","split","Number","length","isBackgroundTimerSupported","NativeTimerModule","Promise","resolve","then","_interopRequireWildcard","require","Boolean","isKilledStateTimerSupported","isKilledStateSupported","getActiveTimers","cancelAllTimers","cancelAll"],"sourceRoot":"../../src","sources":["utils.ts"],"mappings":";;;;;;;;;;;;AAAA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASA,UAAUA,CAACC,OAAe,EAAU;EAClD,MAAMC,CAAC,GAAGC,IAAI,CAACC,GAAG,CAAC,CAAC,EAAED,IAAI,CAACE,KAAK,CAACJ,OAAO,CAAC,CAAC;EAC1C,MAAMK,CAAC,GAAGH,IAAI,CAACE,KAAK,CAACH,CAAC,GAAG,IAAI,CAAC;EAC9B,MAAMK,CAAC,GAAGJ,IAAI,CAACE,KAAK,CAAEH,CAAC,GAAG,IAAI,GAAI,EAAE,CAAC;EACrC,MAAMM,GAAG,GAAGN,CAAC,GAAG,EAAE;EAClB,OAAO,CAACI,CAAC,EAAEC,CAAC,EAAEC,GAAG,CAAC,CAACC,GAAG,CAAEC,CAAC,IAAKC,MAAM,CAACD,CAAC,CAAC,CAACE,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAACC,IAAI,CAAC,GAAG,CAAC;AACrE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASC,SAASA,CAACC,SAAiB,EAAU;EACnD,MAAMC,KAAK,GAAGD,SAAS,CAACE,KAAK,CAAC,GAAG,CAAC,CAACR,GAAG,CAACS,MAAM,CAAC;EAC9C,IAAIF,KAAK,CAACG,MAAM,KAAK,CAAC,EAAE;IACtB,OAAOH,KAAK,CAAC,CAAC,CAAC,GAAI,IAAI,GAAGA,KAAK,CAAC,CAAC,CAAC,GAAI,EAAE,GAAGA,KAAK,CAAC,CAAC,CAAE;EACtD;EACA,IAAIA,KAAK,CAACG,MAAM,KAAK,CAAC,EAAE;IACtB,OAAOH,KAAK,CAAC,CAAC,CAAC,GAAI,EAAE,GAAGA,KAAK,CAAC,CAAC,CAAE;EACnC;EACA,OAAOA,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACtB;;AAEA;AACA;AACA;AACA;AACO,eAAeI,0BAA0BA,CAAA,EAAqB;EACnE,MAAM;IAAEC;EAAkB,CAAC,GAAG,MAAAC,OAAA,CAAAC,OAAA,GAAAC,IAAA,OAAAC,uBAAA,CAAAC,OAAA,CAAa,qBAAqB,GAAC;EACjE,OAAOC,OAAO,CAACN,iBAAiB,CAAC;AACnC;;AAEA;AACA;AACA;AACA;AACA;AACO,eAAeO,2BAA2BA,CAAA,EAAqB;EACpE,MAAM;IAAEP;EAAkB,CAAC,GAAG,MAAAC,OAAA,CAAAC,OAAA,GAAAC,IAAA,OAAAC,uBAAA,CAAAC,OAAA,CAAa,qBAAqB,GAAC;EACjE,IAAI,CAACL,iBAAiB,EAAE;IACtB,OAAO,KAAK;EACd;EACA,IAAI;IACF,OAAO,OAAMA,iBAAiB,CAACQ,sBAAsB,GAAG,CAAC,KAAI,KAAK;EACpE,CAAC,CAAC,MAAM;IACN,OAAO,KAAK;EACd;AACF;;AAEA;AACA;AACA;AACO,eAAeC,eAAeA,CAAA,EAAsB;EACzD,MAAM;IAAET;EAAkB,CAAC,GAAG,MAAAC,OAAA,CAAAC,OAAA,GAAAC,IAAA,OAAAC,uBAAA,CAAAC,OAAA,CAAa,qBAAqB,GAAC;EACjE,IAAI,CAACL,iBAAiB,EAAE;IACtB,OAAO,EAAE;EACX;EACA,IAAI;IACF,OAAO,MAAMA,iBAAiB,CAACS,eAAe,CAAC,CAAC;EAClD,CAAC,CAAC,MAAM;IACN,OAAO,EAAE;EACX;AACF;;AAEA;AACA;AACA;AACO,eAAeC,eAAeA,CAAA,EAAkB;EACrD,MAAM;IAAEV;EAAkB,CAAC,GAAG,MAAAC,OAAA,CAAAC,OAAA,GAAAC,IAAA,OAAAC,uBAAA,CAAAC,OAAA,CAAa,qBAAqB,GAAC;EACjE,IAAI,CAACL,iBAAiB,EAAE;IACtB;EACF;EACA,IAAI;IACF,MAAMA,iBAAiB,CAACW,SAAS,CAAC,CAAC;EACrC,CAAC,CAAC,MAAM;IACN;EAAA;AAEJ","ignoreList":[]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// rn-persistent-timer — Native Bridge
|
|
2
|
+
// Bridges TypeScript ↔ Android (ForegroundService) & iOS (BGTaskScheduler)
|
|
3
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
import { NativeModules, NativeEventEmitter, Platform } from 'react-native';
|
|
6
|
+
const {
|
|
7
|
+
RNPersistentTimer
|
|
8
|
+
} = NativeModules;
|
|
9
|
+
if (__DEV__ && !RNPersistentTimer) {
|
|
10
|
+
console.warn('[rn-persistent-timer] Native module not found.\n' + 'iOS → run `npx pod-install` then rebuild.\n' + 'Android → rebuild the Android project.\n' + 'Foreground (JS-only) timers still work; background/kill-state features are disabled.');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// ─── Start options passed to the native layer ────────────────────────────────
|
|
14
|
+
|
|
15
|
+
// ─── Module interface ─────────────────────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
export const NativeTimerModule = RNPersistentTimer ? {
|
|
18
|
+
startTimer: options => RNPersistentTimer.startTimer(options),
|
|
19
|
+
stopTimer: timerId => RNPersistentTimer.stopTimer(timerId),
|
|
20
|
+
getElapsed: timerId => RNPersistentTimer.getElapsed(timerId),
|
|
21
|
+
cancelAll: () => RNPersistentTimer.cancelAll(),
|
|
22
|
+
getActiveTimers: () => RNPersistentTimer.getActiveTimers(),
|
|
23
|
+
isKilledStateSupported: () => RNPersistentTimer.isKilledStateSupported()
|
|
24
|
+
} : null;
|
|
25
|
+
|
|
26
|
+
// ─── Native event emitter (optional background tick push) ────────────────────
|
|
27
|
+
|
|
28
|
+
export const NativeTimerEmitter = RNPersistentTimer ? new NativeEventEmitter(RNPersistentTimer) : null;
|
|
29
|
+
export const NATIVE_EVENTS = {
|
|
30
|
+
TICK: 'RNPersistentTimer_tick',
|
|
31
|
+
COMPLETE: 'RNPersistentTimer_complete',
|
|
32
|
+
ERROR: 'RNPersistentTimer_error',
|
|
33
|
+
BACKGROUND: 'RNPersistentTimer_background',
|
|
34
|
+
FOREGROUND: 'RNPersistentTimer_foreground'
|
|
35
|
+
};
|
|
36
|
+
// ─── Platform helpers ─────────────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
export const isAndroid = Platform.OS === 'android';
|
|
39
|
+
export const isIOS = Platform.OS === 'ios';
|
|
40
|
+
//# sourceMappingURL=NativeTimerModule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["NativeModules","NativeEventEmitter","Platform","RNPersistentTimer","__DEV__","console","warn","NativeTimerModule","startTimer","options","stopTimer","timerId","getElapsed","cancelAll","getActiveTimers","isKilledStateSupported","NativeTimerEmitter","NATIVE_EVENTS","TICK","COMPLETE","ERROR","BACKGROUND","FOREGROUND","isAndroid","OS","isIOS"],"sourceRoot":"../../src","sources":["NativeTimerModule.ts"],"mappings":"AAAA;AACA;AACA;;AAEA,SAASA,aAAa,EAAEC,kBAAkB,EAAEC,QAAQ,QAAQ,cAAc;AAE1E,MAAM;EAAEC;AAAkB,CAAC,GAAGH,aAAa;AAE3C,IAAII,OAAO,IAAI,CAACD,iBAAiB,EAAE;EACjCE,OAAO,CAACC,IAAI,CACV,kDAAkD,GAChD,8CAA8C,GAC9C,0CAA0C,GAC1C,sFACJ,CAAC;AACH;;AAEA;;AAYA;;AAWA,OAAO,MAAMC,iBAA4C,GAAGJ,iBAAiB,GACzE;EACEK,UAAU,EAAGC,OAA2B,IACtCN,iBAAiB,CAACK,UAAU,CAACC,OAAO,CAAC;EACvCC,SAAS,EAAGC,OAAe,IAAKR,iBAAiB,CAACO,SAAS,CAACC,OAAO,CAAC;EACpEC,UAAU,EAAGD,OAAe,IAAKR,iBAAiB,CAACS,UAAU,CAACD,OAAO,CAAC;EACtEE,SAAS,EAAEA,CAAA,KAAMV,iBAAiB,CAACU,SAAS,CAAC,CAAC;EAC9CC,eAAe,EAAEA,CAAA,KAAMX,iBAAiB,CAACW,eAAe,CAAC,CAAC;EAC1DC,sBAAsB,EAAEA,CAAA,KAAMZ,iBAAiB,CAACY,sBAAsB,CAAC;AACzE,CAAC,GACD,IAAI;;AAER;;AAEA,OAAO,MAAMC,kBAA6C,GAAGb,iBAAiB,GAC1E,IAAIF,kBAAkB,CAACE,iBAAiB,CAAC,GACzC,IAAI;AAER,OAAO,MAAMc,aAAa,GAAG;EAC3BC,IAAI,EAAE,wBAAwB;EAC9BC,QAAQ,EAAE,4BAA4B;EACtCC,KAAK,EAAE,yBAAyB;EAChCC,UAAU,EAAE,8BAA8B;EAC1CC,UAAU,EAAE;AACd,CAAU;AAKV;;AAEA,OAAO,MAAMC,SAAS,GAAGrB,QAAQ,CAACsB,EAAE,KAAK,SAAS;AAClD,OAAO,MAAMC,KAAK,GAAGvB,QAAQ,CAACsB,EAAE,KAAK,KAAK","ignoreList":[]}
|