react-native-alarmageddon 1.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/LICENSE +21 -0
- package/README.md +292 -0
- package/android/build.gradle +69 -0
- package/android/gradle.properties +13 -0
- package/android/src/main/AndroidManifest.xml +55 -0
- package/android/src/main/java/com/rnalarmmodule/AlarmActivity.kt +79 -0
- package/android/src/main/java/com/rnalarmmodule/AlarmModule.kt +485 -0
- package/android/src/main/java/com/rnalarmmodule/AlarmPackage.kt +17 -0
- package/android/src/main/java/com/rnalarmmodule/AlarmReceiver.kt +183 -0
- package/android/src/main/java/com/rnalarmmodule/AlarmService.kt +290 -0
- package/android/src/main/java/com/rnalarmmodule/BootReceiver.kt +156 -0
- package/android/src/main/res/raw/README.md +36 -0
- package/ios/AlarmModule.swift +79 -0
- package/ios/RNAlarmModule-Bridging-Header.h +3 -0
- package/ios/RNAlarmModule.m +48 -0
- package/lib/index.d.ts +147 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +189 -0
- package/lib/index.js.map +1 -0
- package/package.json +63 -0
- package/react-native-alarmageddon.podspec +25 -0
- package/react-native.config.js +12 -0
- package/src/index.ts +317 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NativeModules,
|
|
3
|
+
NativeEventEmitter,
|
|
4
|
+
PermissionsAndroid,
|
|
5
|
+
Platform,
|
|
6
|
+
EmitterSubscription,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Parameters for scheduling an alarm
|
|
11
|
+
*/
|
|
12
|
+
export type AlarmParams = {
|
|
13
|
+
/** Unique identifier for the alarm */
|
|
14
|
+
id: string;
|
|
15
|
+
/** ISO 8601 datetime string for when the alarm should trigger */
|
|
16
|
+
datetimeISO: string;
|
|
17
|
+
/** Title shown in the notification */
|
|
18
|
+
title?: string;
|
|
19
|
+
/** Body text shown in the notification */
|
|
20
|
+
body?: string;
|
|
21
|
+
/** URI of the sound to play (uses default alarm sound if not provided) */
|
|
22
|
+
soundUri?: string;
|
|
23
|
+
/** Whether to vibrate when alarm triggers (default: true) */
|
|
24
|
+
vibrate?: boolean;
|
|
25
|
+
/** Number of minutes for snooze (default: 5) */
|
|
26
|
+
snoozeMinutes?: number;
|
|
27
|
+
/** Number of seconds before alarm auto-stops (default: 60) */
|
|
28
|
+
autoStopSeconds?: number;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Stored alarm data returned from listAlarms
|
|
33
|
+
*/
|
|
34
|
+
export type StoredAlarm = {
|
|
35
|
+
id: string;
|
|
36
|
+
datetimeISO: string;
|
|
37
|
+
title: string;
|
|
38
|
+
body: string;
|
|
39
|
+
vibrate: boolean;
|
|
40
|
+
snoozeMinutes: number;
|
|
41
|
+
autoStopSeconds: number;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Permission request result
|
|
46
|
+
*/
|
|
47
|
+
export type PermissionResult = {
|
|
48
|
+
granted: boolean;
|
|
49
|
+
exactAlarmGranted?: boolean;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Active alarm info
|
|
54
|
+
*/
|
|
55
|
+
export type ActiveAlarmInfo = {
|
|
56
|
+
activeAlarmId: string;
|
|
57
|
+
} | null;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Native module interface
|
|
61
|
+
*/
|
|
62
|
+
interface AlarmModuleInterface {
|
|
63
|
+
scheduleAlarm(alarm: AlarmParams): Promise<void>;
|
|
64
|
+
cancelAlarm(id: string): Promise<void>;
|
|
65
|
+
listAlarms(): Promise<StoredAlarm[]>;
|
|
66
|
+
requestPermissions(): Promise<PermissionResult>;
|
|
67
|
+
checkExactAlarmPermission(): Promise<boolean>;
|
|
68
|
+
openExactAlarmSettings(): Promise<void>;
|
|
69
|
+
snoozeAlarm(id: string, minutes: number): Promise<void>;
|
|
70
|
+
stopCurrentAlarm(id: string): Promise<void>;
|
|
71
|
+
snoozeCurrentAlarm(id: string, minutes: number): Promise<void>;
|
|
72
|
+
getCurrentAlarmPlaying(): Promise<ActiveAlarmInfo>;
|
|
73
|
+
addListener(eventName: string): void;
|
|
74
|
+
removeListeners(count: number): void;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const { AlarmModule } = NativeModules as { AlarmModule: AlarmModuleInterface };
|
|
78
|
+
|
|
79
|
+
// Validate module exists
|
|
80
|
+
if (!AlarmModule) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
'react-native-alarmageddon: NativeModule is null. ' +
|
|
83
|
+
'Ensure you have linked the native module correctly. ' +
|
|
84
|
+
'On Android, run `npx react-native run-android` to rebuild.'
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const eventEmitter = new NativeEventEmitter(NativeModules.AlarmModule);
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Request notification permission (required on Android 13+)
|
|
92
|
+
* @returns Promise resolving to true if permission granted
|
|
93
|
+
*/
|
|
94
|
+
async function requestNotificationPermission(): Promise<boolean> {
|
|
95
|
+
if (Platform.OS !== 'android') {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
if (Platform.Version >= 33) {
|
|
101
|
+
const status = await PermissionsAndroid.request(
|
|
102
|
+
'android.permission.POST_NOTIFICATIONS' as any
|
|
103
|
+
);
|
|
104
|
+
return status === PermissionsAndroid.RESULTS.GRANTED;
|
|
105
|
+
}
|
|
106
|
+
return true;
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.warn('Failed to request notification permission:', error);
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Request exact alarm permission (required on Android 12+)
|
|
115
|
+
* Opens system settings if not granted
|
|
116
|
+
* @returns Promise resolving to permission result
|
|
117
|
+
*/
|
|
118
|
+
async function requestExactAlarmPermission(): Promise<PermissionResult> {
|
|
119
|
+
if (Platform.OS !== 'android') {
|
|
120
|
+
return { granted: true, exactAlarmGranted: true };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return AlarmModule.requestPermissions();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Check if exact alarm permission is granted
|
|
128
|
+
* @returns Promise resolving to true if permission granted
|
|
129
|
+
*/
|
|
130
|
+
async function checkExactAlarmPermission(): Promise<boolean> {
|
|
131
|
+
if (Platform.OS !== 'android') {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return AlarmModule.checkExactAlarmPermission();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Open system settings for exact alarm permission
|
|
140
|
+
*/
|
|
141
|
+
async function openExactAlarmSettings(): Promise<void> {
|
|
142
|
+
if (Platform.OS === 'android') {
|
|
143
|
+
return AlarmModule.openExactAlarmSettings();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Ensure all required permissions are granted
|
|
149
|
+
* Requests both notification and exact alarm permissions
|
|
150
|
+
* @returns Promise resolving to true if all permissions granted
|
|
151
|
+
*/
|
|
152
|
+
async function ensurePermissions(): Promise<boolean> {
|
|
153
|
+
if (Platform.OS !== 'android') {
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const [notificationGranted, exactAlarmResult] = await Promise.all([
|
|
158
|
+
requestNotificationPermission(),
|
|
159
|
+
requestExactAlarmPermission(),
|
|
160
|
+
]);
|
|
161
|
+
|
|
162
|
+
return notificationGranted && exactAlarmResult.granted;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Schedule an alarm
|
|
167
|
+
* @param alarm - Alarm parameters
|
|
168
|
+
*/
|
|
169
|
+
async function scheduleAlarm(alarm: AlarmParams): Promise<void> {
|
|
170
|
+
if (!alarm.id) {
|
|
171
|
+
throw new Error('Alarm ID is required');
|
|
172
|
+
}
|
|
173
|
+
if (!alarm.datetimeISO) {
|
|
174
|
+
throw new Error('datetimeISO is required');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return AlarmModule.scheduleAlarm(alarm);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Cancel a scheduled alarm
|
|
182
|
+
* @param id - Alarm ID to cancel
|
|
183
|
+
*/
|
|
184
|
+
async function cancelAlarm(id: string): Promise<void> {
|
|
185
|
+
if (!id) {
|
|
186
|
+
throw new Error('Alarm ID is required');
|
|
187
|
+
}
|
|
188
|
+
return AlarmModule.cancelAlarm(id);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* List all scheduled alarms
|
|
193
|
+
* @returns Promise resolving to array of stored alarms
|
|
194
|
+
*/
|
|
195
|
+
async function listAlarms(): Promise<StoredAlarm[]> {
|
|
196
|
+
return AlarmModule.listAlarms();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Snooze an alarm for a specified number of minutes
|
|
201
|
+
* @param id - Alarm ID to snooze
|
|
202
|
+
* @param minutes - Number of minutes to snooze (default: 5)
|
|
203
|
+
*/
|
|
204
|
+
async function snoozeAlarm(id: string, minutes: number = 5): Promise<void> {
|
|
205
|
+
if (!id) {
|
|
206
|
+
throw new Error('Alarm ID is required');
|
|
207
|
+
}
|
|
208
|
+
return AlarmModule.snoozeAlarm(id, minutes);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Stop the currently playing alarm
|
|
213
|
+
* @param id - Alarm ID to stop
|
|
214
|
+
*/
|
|
215
|
+
async function stopCurrentAlarm(id: string): Promise<void> {
|
|
216
|
+
if (!id) {
|
|
217
|
+
throw new Error('Alarm ID is required');
|
|
218
|
+
}
|
|
219
|
+
return AlarmModule.stopCurrentAlarm(id);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Snooze the currently playing alarm
|
|
224
|
+
* @param id - Alarm ID to snooze
|
|
225
|
+
* @param minutes - Number of minutes to snooze (default: 5)
|
|
226
|
+
*/
|
|
227
|
+
async function snoozeCurrentAlarm(id: string, minutes: number = 5): Promise<void> {
|
|
228
|
+
if (!id) {
|
|
229
|
+
throw new Error('Alarm ID is required');
|
|
230
|
+
}
|
|
231
|
+
return AlarmModule.snoozeCurrentAlarm(id, minutes);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Get the currently playing alarm (if any)
|
|
236
|
+
* @returns Promise resolving to active alarm info or null
|
|
237
|
+
*/
|
|
238
|
+
async function getCurrentAlarmPlaying(): Promise<ActiveAlarmInfo> {
|
|
239
|
+
return AlarmModule.getCurrentAlarmPlaying();
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Subscribe to alarm state changes
|
|
244
|
+
* Callback receives the alarm ID when an alarm starts, or null when stopped
|
|
245
|
+
* @param callback - Function called when alarm state changes
|
|
246
|
+
* @returns Cleanup function to remove the subscription
|
|
247
|
+
*/
|
|
248
|
+
function onAlarmStateChange(
|
|
249
|
+
callback: (alarmId: string | null) => void
|
|
250
|
+
): () => void {
|
|
251
|
+
const subscription: EmitterSubscription = eventEmitter.addListener(
|
|
252
|
+
'activeAlarmId',
|
|
253
|
+
callback
|
|
254
|
+
);
|
|
255
|
+
return () => subscription.remove();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Add event listener for alarm state changes
|
|
260
|
+
* @param event - Event name ('activeAlarmId')
|
|
261
|
+
* @param callback - Callback function
|
|
262
|
+
* @returns EmitterSubscription for removal
|
|
263
|
+
*/
|
|
264
|
+
function addEventListener(
|
|
265
|
+
event: 'activeAlarmId',
|
|
266
|
+
callback: (alarmId: string | null) => void
|
|
267
|
+
): EmitterSubscription {
|
|
268
|
+
return eventEmitter.addListener(event, callback);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Main module export with all alarm functions
|
|
273
|
+
*/
|
|
274
|
+
const RNAlarmModule = {
|
|
275
|
+
// Permissions
|
|
276
|
+
ensurePermissions,
|
|
277
|
+
requestNotificationPermission,
|
|
278
|
+
requestExactAlarmPermission,
|
|
279
|
+
checkExactAlarmPermission,
|
|
280
|
+
openExactAlarmSettings,
|
|
281
|
+
|
|
282
|
+
// Alarm management
|
|
283
|
+
scheduleAlarm,
|
|
284
|
+
cancelAlarm,
|
|
285
|
+
listAlarms,
|
|
286
|
+
snoozeAlarm,
|
|
287
|
+
|
|
288
|
+
// Active alarm control
|
|
289
|
+
stopCurrentAlarm,
|
|
290
|
+
snoozeCurrentAlarm,
|
|
291
|
+
getCurrentAlarmPlaying,
|
|
292
|
+
|
|
293
|
+
// Event handling
|
|
294
|
+
onAlarmStateChange,
|
|
295
|
+
addEventListener,
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
export default RNAlarmModule;
|
|
299
|
+
export { RNAlarmModule };
|
|
300
|
+
|
|
301
|
+
// Export individual functions for tree-shaking
|
|
302
|
+
export {
|
|
303
|
+
ensurePermissions,
|
|
304
|
+
requestNotificationPermission,
|
|
305
|
+
requestExactAlarmPermission,
|
|
306
|
+
checkExactAlarmPermission,
|
|
307
|
+
openExactAlarmSettings,
|
|
308
|
+
scheduleAlarm,
|
|
309
|
+
cancelAlarm,
|
|
310
|
+
listAlarms,
|
|
311
|
+
snoozeAlarm,
|
|
312
|
+
stopCurrentAlarm,
|
|
313
|
+
snoozeCurrentAlarm,
|
|
314
|
+
getCurrentAlarmPlaying,
|
|
315
|
+
onAlarmStateChange,
|
|
316
|
+
addEventListener,
|
|
317
|
+
};
|