react-native-mp3 0.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.
Files changed (64) hide show
  1. package/android/build.gradle +111 -0
  2. package/android/src/main/AndroidManifest.xml +44 -0
  3. package/android/src/main/java/com/reactnativemp3/Mp3Package.kt +23 -0
  4. package/android/src/main/java/com/reactnativemp3/Mp3TurboModule.kt +43 -0
  5. package/android/src/main/java/com/reactnativemp3/database/MusicDatabase.kt +48 -0
  6. package/android/src/main/java/com/reactnativemp3/database/dao/SongDao.kt +72 -0
  7. package/android/src/main/java/com/reactnativemp3/database/entities/PlaylistEntity.kt +58 -0
  8. package/android/src/main/java/com/reactnativemp3/database/entities/SongEntity.kt +104 -0
  9. package/android/src/main/java/com/reactnativemp3/database/entities/ThumbnailCacheEntity.kt +43 -0
  10. package/android/src/main/java/com/reactnativemp3/managers/CacheManager.kt +0 -0
  11. package/android/src/main/java/com/reactnativemp3/managers/EqualizerManager.kt +0 -0
  12. package/android/src/main/java/com/reactnativemp3/modules/MetadataModule.kt +330 -0
  13. package/android/src/main/java/com/reactnativemp3/modules/NotificationModule.kt +236 -0
  14. package/android/src/main/java/com/reactnativemp3/modules/PlayerModule.kt +710 -0
  15. package/android/src/main/java/com/reactnativemp3/modules/ScannerModule.kt +640 -0
  16. package/android/src/main/java/com/reactnativemp3/services/AudioFocusService.kt +0 -0
  17. package/android/src/main/java/com/reactnativemp3/services/FileObserverService.kt +0 -0
  18. package/android/src/main/java/com/reactnativemp3/services/MusicService.kt +309 -0
  19. package/android/src/main/java/com/reactnativemp3/utils/MediaStoreUtils.kt +0 -0
  20. package/android/src/main/java/com/reactnativemp3/utils/PermissionUtils.kt +0 -0
  21. package/android/src/main/jni/Mp3TurboModule.cpp +29 -0
  22. package/android/src/main/res/drawable/ic_music_note.xml +11 -0
  23. package/android/src/main/res/drawable/ic_pause.xml +11 -0
  24. package/android/src/main/res/drawable/ic_play.xml +11 -0
  25. package/android/src/main/res/drawable/ic_skip_next.xml +11 -0
  26. package/android/src/main/res/drawable/ic_skip_previous.xml +11 -0
  27. package/android/src/main/res/drawable/ic_stop.xml +11 -0
  28. package/lib/components/MusicList.d.ts +0 -0
  29. package/lib/components/MusicList.js +1 -0
  30. package/lib/components/MusicPlayerUI.d.ts +0 -0
  31. package/lib/components/MusicPlayerUI.js +1 -0
  32. package/lib/hooks/useMusicPlayer.d.ts +38 -0
  33. package/lib/hooks/useMusicPlayer.js +242 -0
  34. package/lib/hooks/useMusicScanner.d.ts +27 -0
  35. package/lib/hooks/useMusicScanner.js +217 -0
  36. package/lib/hooks/usePermissions.d.ts +9 -0
  37. package/lib/hooks/usePermissions.js +55 -0
  38. package/lib/index.d.ts +144 -0
  39. package/lib/index.js +148 -0
  40. package/lib/types/common.types.d.ts +79 -0
  41. package/lib/types/common.types.js +2 -0
  42. package/lib/types/index.d.ts +3 -0
  43. package/lib/types/index.js +2 -0
  44. package/lib/types/player.types.d.ts +35 -0
  45. package/lib/types/player.types.js +2 -0
  46. package/lib/types/scanner.types.d.ts +29 -0
  47. package/lib/types/scanner.types.js +2 -0
  48. package/lib/utils/constants.d.ts +31 -0
  49. package/lib/utils/constants.js +55 -0
  50. package/lib/utils/events.d.ts +0 -0
  51. package/lib/utils/events.js +1 -0
  52. package/package.json +62 -0
  53. package/src/components/MusicList.tsx +0 -0
  54. package/src/components/MusicPlayerUI.tsx +0 -0
  55. package/src/hooks/useMusicPlayer.ts +358 -0
  56. package/src/hooks/useMusicScanner.ts +286 -0
  57. package/src/hooks/usePermissions.ts +64 -0
  58. package/src/index.ts +214 -0
  59. package/src/types/common.types.ts +86 -0
  60. package/src/types/index.ts +4 -0
  61. package/src/types/player.types.ts +37 -0
  62. package/src/types/scanner.types.ts +31 -0
  63. package/src/utils/constants.ts +56 -0
  64. package/src/utils/events.ts +0 -0
@@ -0,0 +1,242 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useMusicPlayer = void 0;
4
+ const react_1 = require("react");
5
+ const index_1 = require("../index");
6
+ const defaultPlaybackState = {
7
+ isPlaying: false,
8
+ currentTime: 0,
9
+ duration: 0,
10
+ buffered: 0,
11
+ playbackRate: 1.0,
12
+ volume: 1.0,
13
+ repeatMode: 'none',
14
+ shuffleMode: false,
15
+ currentSong: undefined,
16
+ queue: [],
17
+ queuePosition: -1,
18
+ error: undefined,
19
+ };
20
+ const useMusicPlayer = ({ autoSetup = true, playerOptions, } = {}) => {
21
+ const [playbackState, setPlaybackState] = (0, react_1.useState)(defaultPlaybackState);
22
+ const [currentSong, setCurrentSong] = (0, react_1.useState)(null);
23
+ const [queue, setQueue] = (0, react_1.useState)([]);
24
+ const [isPlaying, setIsPlaying] = (0, react_1.useState)(false);
25
+ const [isLoading, setIsLoading] = (0, react_1.useState)(false);
26
+ const [error, setError] = (0, react_1.useState)(null);
27
+ // Initialize player
28
+ const initializePlayer = (0, react_1.useCallback)(async () => {
29
+ var _a, _b;
30
+ try {
31
+ setIsLoading(true);
32
+ setError(null);
33
+ // Setup background playback if options specify
34
+ if ((playerOptions === null || playerOptions === void 0 ? void 0 : playerOptions.audioFocus) !== false) {
35
+ index_1.Player.setupBackgroundPlayback({
36
+ keepAwake: (_a = playerOptions === null || playerOptions === void 0 ? void 0 : playerOptions.keepAwake) !== null && _a !== void 0 ? _a : true,
37
+ ducking: (_b = playerOptions === null || playerOptions === void 0 ? void 0 : playerOptions.ducking) !== null && _b !== void 0 ? _b : true,
38
+ });
39
+ }
40
+ // Get initial state
41
+ const state = await index_1.Player.getPlaybackState();
42
+ updateStateFromNative(state);
43
+ }
44
+ catch (err) {
45
+ setError(err.message || 'Failed to initialize player');
46
+ console.error('Error initializing player:', err);
47
+ }
48
+ finally {
49
+ setIsLoading(false);
50
+ }
51
+ }, [playerOptions]);
52
+ // Update state from native response
53
+ const updateStateFromNative = (0, react_1.useCallback)((state) => {
54
+ setPlaybackState({
55
+ isPlaying: state.isPlaying,
56
+ currentTime: state.currentTime,
57
+ duration: state.duration,
58
+ playbackRate: state.playbackRate,
59
+ volume: state.volume,
60
+ repeatMode: state.repeatMode,
61
+ shuffleMode: state.shuffleMode,
62
+ currentSong: state.currentSong,
63
+ queue: state.queue || [],
64
+ queuePosition: state.queuePosition,
65
+ });
66
+ setIsPlaying(state.isPlaying);
67
+ setCurrentSong(state.currentSong || null);
68
+ setQueue(state.queue || []);
69
+ }, []);
70
+ // Play a song by URI
71
+ const play = (0, react_1.useCallback)(async (uri) => {
72
+ try {
73
+ setIsLoading(true);
74
+ setError(null);
75
+ await index_1.Player.play(uri);
76
+ }
77
+ catch (err) {
78
+ setError(err.message || 'Failed to play song');
79
+ console.error('Error playing song:', err);
80
+ throw err;
81
+ }
82
+ finally {
83
+ setIsLoading(false);
84
+ }
85
+ }, []);
86
+ // Play a song object
87
+ const playSong = (0, react_1.useCallback)(async (song) => {
88
+ await play(song.uri);
89
+ }, [play]);
90
+ // Play from queue
91
+ const playFromQueue = (0, react_1.useCallback)((index) => {
92
+ index_1.Player.playFromQueue(index);
93
+ }, []);
94
+ // Pause playback
95
+ const pause = (0, react_1.useCallback)(() => {
96
+ index_1.Player.pause();
97
+ }, []);
98
+ // Stop playback
99
+ const stop = (0, react_1.useCallback)(() => {
100
+ index_1.Player.stop();
101
+ }, []);
102
+ // Seek to position
103
+ const seekTo = (0, react_1.useCallback)((position) => {
104
+ index_1.Player.seekTo(position);
105
+ }, []);
106
+ // Skip to next
107
+ const skipToNext = (0, react_1.useCallback)(() => {
108
+ index_1.Player.skipToNext();
109
+ }, []);
110
+ // Skip to previous
111
+ const skipToPrevious = (0, react_1.useCallback)(() => {
112
+ index_1.Player.skipToPrevious();
113
+ }, []);
114
+ // Set volume
115
+ const setVolume = (0, react_1.useCallback)((volume) => {
116
+ index_1.Player.setVolume(volume);
117
+ }, []);
118
+ // Set playback rate
119
+ const setPlaybackRate = (0, react_1.useCallback)((rate) => {
120
+ index_1.Player.setPlaybackRate(rate);
121
+ }, []);
122
+ // Set queue
123
+ const setQueueCallback = (0, react_1.useCallback)((songs) => {
124
+ index_1.Player.setQueue(songs);
125
+ }, []);
126
+ // Add to queue
127
+ const addToQueue = (0, react_1.useCallback)((songs) => {
128
+ index_1.Player.addToQueue(songs);
129
+ }, []);
130
+ // Clear queue
131
+ const clearQueue = (0, react_1.useCallback)(() => {
132
+ index_1.Player.clearQueue();
133
+ }, []);
134
+ // Get queue
135
+ const getQueue = (0, react_1.useCallback)(async () => {
136
+ return await index_1.Player.getQueue();
137
+ }, []);
138
+ // Set repeat mode
139
+ const setRepeatMode = (0, react_1.useCallback)((mode) => {
140
+ index_1.Player.setRepeatMode(mode);
141
+ }, []);
142
+ // Set shuffle mode
143
+ const setShuffleMode = (0, react_1.useCallback)((enabled) => {
144
+ index_1.Player.setShuffleMode(enabled);
145
+ }, []);
146
+ // Equalizer controls
147
+ const setEqualizerPreset = (0, react_1.useCallback)((preset) => {
148
+ index_1.Player.setEqualizerPreset(preset);
149
+ }, []);
150
+ const setEqualizerBands = (0, react_1.useCallback)((bands) => {
151
+ index_1.Player.setEqualizerBands(bands);
152
+ }, []);
153
+ const enableEqualizer = (0, react_1.useCallback)((enabled) => {
154
+ index_1.Player.enableEqualizer(enabled);
155
+ }, []);
156
+ // Background playback
157
+ const setupBackgroundPlayback = (0, react_1.useCallback)((config) => {
158
+ index_1.Player.setupBackgroundPlayback(config);
159
+ }, []);
160
+ const stopBackgroundPlayback = (0, react_1.useCallback)(() => {
161
+ index_1.Player.stopBackgroundPlayback();
162
+ }, []);
163
+ // Sleep timer
164
+ const setSleepTimer = (0, react_1.useCallback)((minutes) => {
165
+ index_1.Player.setSleepTimer(minutes);
166
+ }, []);
167
+ const cancelSleepTimer = (0, react_1.useCallback)(() => {
168
+ index_1.Player.cancelSleepTimer();
169
+ }, []);
170
+ // Set up event listeners
171
+ (0, react_1.useEffect)(() => {
172
+ if (!autoSetup)
173
+ return;
174
+ const playbackStateSub = index_1.Player.addEventListener(index_1.PlayerEvents.PLAYBACK_STATE_CHANGED, (data) => {
175
+ setPlaybackState(prev => (Object.assign(Object.assign({}, prev), { isPlaying: data.isPlaying, currentTime: data.currentTime, duration: data.duration, volume: data.volume, playbackRate: data.playbackRate })));
176
+ setIsPlaying(data.isPlaying);
177
+ });
178
+ const queueChangedSub = index_1.Player.addEventListener(index_1.PlayerEvents.PLAYBACK_QUEUE_CHANGED, (data) => {
179
+ setQueue(data.queue || []);
180
+ setPlaybackState(prev => (Object.assign(Object.assign({}, prev), { queue: data.queue || [], queuePosition: data.position })));
181
+ });
182
+ const playbackErrorSub = index_1.Player.addEventListener(index_1.PlayerEvents.PLAYBACK_ERROR, (data) => {
183
+ setError(data.error || 'Playback error');
184
+ setPlaybackState(prev => (Object.assign(Object.assign({}, prev), { error: data.error })));
185
+ });
186
+ const playbackCompleteSub = index_1.Player.addEventListener(index_1.PlayerEvents.PLAYBACK_COMPLETE, () => {
187
+ // Auto-play next is handled by native module
188
+ });
189
+ // Initialize player
190
+ initializePlayer();
191
+ return () => {
192
+ // Remove specific listeners
193
+ playbackStateSub.remove();
194
+ queueChangedSub.remove();
195
+ playbackErrorSub.remove();
196
+ playbackCompleteSub.remove();
197
+ // Clean up background playback if it was set up
198
+ if (autoSetup && (playerOptions === null || playerOptions === void 0 ? void 0 : playerOptions.audioFocus) !== false) {
199
+ index_1.Player.stopBackgroundPlayback();
200
+ }
201
+ };
202
+ }, [autoSetup, initializePlayer, playerOptions]);
203
+ return {
204
+ // State
205
+ playbackState,
206
+ currentSong,
207
+ queue,
208
+ isPlaying,
209
+ isLoading,
210
+ error,
211
+ // Playback Controls
212
+ play,
213
+ playSong,
214
+ playFromQueue,
215
+ pause,
216
+ stop,
217
+ seekTo,
218
+ skipToNext,
219
+ skipToPrevious,
220
+ setVolume,
221
+ setPlaybackRate,
222
+ // Queue Management
223
+ setQueue: setQueueCallback,
224
+ addToQueue,
225
+ clearQueue,
226
+ getQueue,
227
+ // Playback Modes
228
+ setRepeatMode,
229
+ setShuffleMode,
230
+ // Equalizer
231
+ setEqualizerPreset,
232
+ setEqualizerBands,
233
+ enableEqualizer,
234
+ // Background Playback
235
+ setupBackgroundPlayback,
236
+ stopBackgroundPlayback,
237
+ // Sleep Timer
238
+ setSleepTimer,
239
+ cancelSleepTimer,
240
+ };
241
+ };
242
+ exports.useMusicPlayer = useMusicPlayer;
@@ -0,0 +1,27 @@
1
+ import type { Song, Album, Artist, ScannerOptions } from '../types/common.types';
2
+ interface UseMusicScannerProps {
3
+ autoScan?: boolean;
4
+ scanOptions?: ScannerOptions;
5
+ }
6
+ interface UseMusicScannerReturn {
7
+ songs: Song[];
8
+ albums: Album[];
9
+ artists: Artist[];
10
+ isLoading: boolean;
11
+ isScanning: boolean;
12
+ scanProgress: number;
13
+ permissionGranted: boolean;
14
+ error: string | null;
15
+ scanMusic: (options?: ScannerOptions) => Promise<void>;
16
+ refresh: () => Promise<void>;
17
+ search: (query: string) => Promise<Song[]>;
18
+ deleteSong: (songId: string) => Promise<boolean>;
19
+ addToFavorites: (songId: string) => Promise<void>;
20
+ removeFromFavorites: (songId: string) => Promise<void>;
21
+ requestPermission: () => Promise<boolean>;
22
+ checkPermission: () => Promise<boolean>;
23
+ onScanProgress?: (progress: number) => void;
24
+ onScanComplete?: (totalSongs: number) => void;
25
+ }
26
+ export declare const useMusicScanner: ({ autoScan, scanOptions, }?: UseMusicScannerProps) => UseMusicScannerReturn;
27
+ export {};
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useMusicScanner = void 0;
4
+ const react_1 = require("react");
5
+ const index_1 = require("../index");
6
+ const useMusicScanner = ({ autoScan = true, scanOptions, } = {}) => {
7
+ const [songs, setSongs] = (0, react_1.useState)([]);
8
+ const [albums, setAlbums] = (0, react_1.useState)([]);
9
+ const [artists, setArtists] = (0, react_1.useState)([]);
10
+ const [isLoading, setIsLoading] = (0, react_1.useState)(false);
11
+ const [isScanning, setIsScanning] = (0, react_1.useState)(false);
12
+ const [scanProgress, setScanProgress] = (0, react_1.useState)(0);
13
+ const [permissionGranted, setPermissionGranted] = (0, react_1.useState)(false);
14
+ const [error, setError] = (0, react_1.useState)(null);
15
+ // Load initial data
16
+ const loadInitialData = (0, react_1.useCallback)(async () => {
17
+ try {
18
+ setIsLoading(true);
19
+ setError(null);
20
+ const hasPermission = await index_1.Scanner.checkPermissionStatus();
21
+ setPermissionGranted(hasPermission);
22
+ if (hasPermission) {
23
+ const cachedSongs = await index_1.Scanner.getCachedSongs();
24
+ setSongs(cachedSongs);
25
+ const [albumsList, artistsList] = await Promise.all([
26
+ index_1.Scanner.getAlbums(),
27
+ index_1.Scanner.getArtists(),
28
+ ]);
29
+ setAlbums(albumsList);
30
+ setArtists(artistsList);
31
+ }
32
+ }
33
+ catch (err) {
34
+ setError(err.message || 'Failed to load music library');
35
+ console.error('Error loading music library:', err);
36
+ }
37
+ finally {
38
+ setIsLoading(false);
39
+ }
40
+ }, []);
41
+ // Scan music files
42
+ const scanMusic = (0, react_1.useCallback)(async (options) => {
43
+ try {
44
+ setIsScanning(true);
45
+ setScanProgress(0);
46
+ setError(null);
47
+ const hasPermission = await index_1.Scanner.checkPermissionStatus();
48
+ if (!hasPermission) {
49
+ const granted = await index_1.Scanner.requestStoragePermission();
50
+ if (!granted) {
51
+ setError('Storage permission is required to scan music files');
52
+ setIsScanning(false);
53
+ return;
54
+ }
55
+ setPermissionGranted(true);
56
+ }
57
+ const scanOpts = options || scanOptions || {};
58
+ const result = await index_1.Scanner.scanMusicFiles(scanOpts);
59
+ // Reload data after scan
60
+ await loadInitialData();
61
+ return result;
62
+ }
63
+ catch (err) {
64
+ setError(err.message || 'Failed to scan music files');
65
+ console.error('Error scanning music files:', err);
66
+ throw err;
67
+ }
68
+ finally {
69
+ setIsScanning(false);
70
+ setScanProgress(0);
71
+ }
72
+ }, [scanOptions, loadInitialData]);
73
+ // Refresh data
74
+ const refresh = (0, react_1.useCallback)(async () => {
75
+ await loadInitialData();
76
+ }, [loadInitialData]);
77
+ // Search songs
78
+ const search = (0, react_1.useCallback)(async (query) => {
79
+ if (!query.trim()) {
80
+ return songs;
81
+ }
82
+ try {
83
+ const results = await index_1.Scanner.searchSongs(query);
84
+ return results;
85
+ }
86
+ catch (err) {
87
+ setError(err.message || 'Search failed');
88
+ console.error('Error searching songs:', err);
89
+ return [];
90
+ }
91
+ }, [songs]);
92
+ // Delete song
93
+ const deleteSong = (0, react_1.useCallback)(async (songId) => {
94
+ try {
95
+ const success = await index_1.Scanner.deleteSong(songId);
96
+ if (success) {
97
+ // Remove from local state
98
+ setSongs(prev => prev.filter(song => song.id !== songId));
99
+ // Update albums and artists
100
+ await refresh();
101
+ }
102
+ return success;
103
+ }
104
+ catch (err) {
105
+ setError(err.message || 'Failed to delete song');
106
+ console.error('Error deleting song:', err);
107
+ return false;
108
+ }
109
+ }, [refresh]);
110
+ // Add to favorites
111
+ const addToFavorites = (0, react_1.useCallback)(async (songId) => {
112
+ try {
113
+ await index_1.Scanner.addToFavorites(songId);
114
+ // Update local state
115
+ setSongs(prev => prev.map(song => song.id === songId ? Object.assign(Object.assign({}, song), { isFavorite: true }) : song));
116
+ }
117
+ catch (err) {
118
+ setError(err.message || 'Failed to add to favorites');
119
+ console.error('Error adding to favorites:', err);
120
+ }
121
+ }, []);
122
+ // Remove from favorites
123
+ const removeFromFavorites = (0, react_1.useCallback)(async (songId) => {
124
+ try {
125
+ await index_1.Scanner.removeFromFavorites(songId);
126
+ // Update local state
127
+ setSongs(prev => prev.map(song => song.id === songId ? Object.assign(Object.assign({}, song), { isFavorite: false }) : song));
128
+ }
129
+ catch (err) {
130
+ setError(err.message || 'Failed to remove from favorites');
131
+ console.error('Error removing from favorites:', err);
132
+ }
133
+ }, []);
134
+ // Request permission
135
+ const requestPermission = (0, react_1.useCallback)(async () => {
136
+ try {
137
+ const granted = await index_1.Scanner.requestStoragePermission();
138
+ setPermissionGranted(granted);
139
+ return granted;
140
+ }
141
+ catch (err) {
142
+ setError(err.message || 'Failed to request permission');
143
+ console.error('Error requesting permission:', err);
144
+ return false;
145
+ }
146
+ }, []);
147
+ // Check permission
148
+ const checkPermission = (0, react_1.useCallback)(async () => {
149
+ try {
150
+ const granted = await index_1.Scanner.checkPermissionStatus();
151
+ setPermissionGranted(granted);
152
+ return granted;
153
+ }
154
+ catch (err) {
155
+ setError(err.message || 'Failed to check permission');
156
+ console.error('Error checking permission:', err);
157
+ return false;
158
+ }
159
+ }, []);
160
+ // Set up event listeners
161
+ (0, react_1.useEffect)(() => {
162
+ const scanProgressSub = index_1.Scanner.addEventListener(index_1.ScannerEvents.SCAN_PROGRESS, (data) => {
163
+ setScanProgress(data.percentage);
164
+ });
165
+ const scanCompleteSub = index_1.Scanner.addEventListener(index_1.ScannerEvents.SCAN_COMPLETE, () => {
166
+ loadInitialData();
167
+ });
168
+ const fileAddedSub = index_1.Scanner.addEventListener(index_1.ScannerEvents.FILE_ADDED, () => {
169
+ loadInitialData();
170
+ });
171
+ const fileDeletedSub = index_1.Scanner.addEventListener(index_1.ScannerEvents.FILE_DELETED, () => {
172
+ loadInitialData();
173
+ });
174
+ const permissionSub = index_1.Scanner.addEventListener(index_1.ScannerEvents.PERMISSION_STATUS, (data) => {
175
+ setPermissionGranted(data.granted);
176
+ });
177
+ // Auto scan on mount if enabled
178
+ if (autoScan && permissionGranted) {
179
+ loadInitialData();
180
+ }
181
+ return () => {
182
+ // Remove specific listeners instead of all
183
+ scanProgressSub.remove();
184
+ scanCompleteSub.remove();
185
+ fileAddedSub.remove();
186
+ fileDeletedSub.remove();
187
+ permissionSub.remove();
188
+ // If you want to remove all listeners:
189
+ // Scanner.removeAllListeners(ScannerEvents.SCAN_PROGRESS);
190
+ // Scanner.removeAllListeners(ScannerEvents.SCAN_COMPLETE);
191
+ // Scanner.removeAllListeners(ScannerEvents.FILE_ADDED);
192
+ // Scanner.removeAllListeners(ScannerEvents.FILE_DELETED);
193
+ // Scanner.removeAllListeners(ScannerEvents.PERMISSION_STATUS);
194
+ };
195
+ }, [autoScan, loadInitialData, permissionGranted]);
196
+ return {
197
+ // State
198
+ songs,
199
+ albums,
200
+ artists,
201
+ isLoading,
202
+ isScanning,
203
+ scanProgress,
204
+ permissionGranted,
205
+ error,
206
+ // Methods
207
+ scanMusic,
208
+ refresh,
209
+ search,
210
+ deleteSong,
211
+ addToFavorites,
212
+ removeFromFavorites,
213
+ requestPermission,
214
+ checkPermission,
215
+ };
216
+ };
217
+ exports.useMusicScanner = useMusicScanner;
@@ -0,0 +1,9 @@
1
+ interface UsePermissionsReturn {
2
+ permissionGranted: boolean;
3
+ isChecking: boolean;
4
+ error: string | null;
5
+ requestPermission: () => Promise<boolean>;
6
+ checkPermission: () => Promise<boolean>;
7
+ }
8
+ export declare const usePermissions: () => UsePermissionsReturn;
9
+ export {};
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.usePermissions = void 0;
4
+ const react_1 = require("react");
5
+ const index_1 = require("../index");
6
+ const usePermissions = () => {
7
+ const [permissionGranted, setPermissionGranted] = (0, react_1.useState)(false);
8
+ const [isChecking, setIsChecking] = (0, react_1.useState)(false);
9
+ const [error, setError] = (0, react_1.useState)(null);
10
+ const checkPermission = async () => {
11
+ try {
12
+ setIsChecking(true);
13
+ setError(null);
14
+ const granted = await index_1.Scanner.checkPermissionStatus();
15
+ setPermissionGranted(granted);
16
+ return granted;
17
+ }
18
+ catch (err) {
19
+ setError(err.message || 'Failed to check permission');
20
+ console.error('Error checking permission:', err);
21
+ return false;
22
+ }
23
+ finally {
24
+ setIsChecking(false);
25
+ }
26
+ };
27
+ const requestPermission = async () => {
28
+ try {
29
+ setIsChecking(true);
30
+ setError(null);
31
+ const granted = await index_1.Scanner.requestStoragePermission();
32
+ setPermissionGranted(granted);
33
+ return granted;
34
+ }
35
+ catch (err) {
36
+ setError(err.message || 'Failed to request permission');
37
+ console.error('Error requesting permission:', err);
38
+ return false;
39
+ }
40
+ finally {
41
+ setIsChecking(false);
42
+ }
43
+ };
44
+ (0, react_1.useEffect)(() => {
45
+ checkPermission();
46
+ }, []);
47
+ return {
48
+ permissionGranted,
49
+ isChecking,
50
+ error,
51
+ requestPermission,
52
+ checkPermission,
53
+ };
54
+ };
55
+ exports.usePermissions = usePermissions;