Skip to content

Commit c6e2868

Browse files
committed
fix: Cannot read properties of undefined (reading 'getEnforcing') in web
1 parent c3f7990 commit c6e2868

File tree

8 files changed

+359
-246
lines changed

8 files changed

+359
-246
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ or
3939
yarn add @nodefinity/react-native-music-library
4040
```
4141

42+
## Platform Support
43+
44+
This library supports multiple platforms with automatic platform detection:
45+
46+
- **Android**: Full native music library access
47+
- **iOS**: Full native music library access (coming soon)
48+
- **Web**: Fallback implementation with warnings (for React Native Web projects)
49+
50+
The library automatically provides the appropriate implementation based on your platform. On web, all methods will return empty results and show development warnings to help with development and testing.
51+
4252
### Android Setup
4353

4454
For Android, add the following permission to your `android/app/src/main/AndroidManifest.xml`:

README_ZH.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,16 @@ npm install @nodefinity/react-native-music-library
3939
yarn add @nodefinity/react-native-music-library
4040
```
4141

42+
## 平台支持
43+
44+
此库支持多个平台,具有自动平台检测功能:
45+
46+
- **Android**:完整的原生音乐库访问
47+
- **iOS**:完整的原生音乐库访问(即将推出)
48+
- **Web**:回退实现并提供警告(适用于 React Native Web 项目)
49+
50+
该库会根据您的平台自动提供相应的实现。在 web 平台上,所有方法都会返回空结果并显示开发警告,以帮助开发和测试。
51+
4252
### Android 设置
4353

4454
对于 Android,在 `android/app/src/main/AndroidManifest.xml` 中添加以下权限:

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,10 @@
103103
"commitlint": {
104104
"extends": [
105105
"@commitlint/config-conventional"
106-
]
106+
],
107+
"rules": {
108+
"subject-case": [0]
109+
}
107110
},
108111
"release-it": {
109112
"git": {

src/MusicLibraryImpl.native.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { TurboModule } from 'react-native';
2+
import { TurboModuleRegistry } from 'react-native';
3+
import type {
4+
MusicLibraryModule,
5+
InternalAssetsOptions,
6+
TrackResult,
7+
AlbumResult,
8+
ArtistResult,
9+
GenreResult,
10+
} from './types';
11+
12+
interface Spec extends TurboModule, MusicLibraryModule {
13+
getTracksAsync(options: InternalAssetsOptions): Promise<TrackResult>;
14+
getAlbumsAsync(options: InternalAssetsOptions): Promise<AlbumResult>;
15+
getArtistsAsync(options: InternalAssetsOptions): Promise<ArtistResult>;
16+
getGenresAsync(options: InternalAssetsOptions): Promise<GenreResult>;
17+
}
18+
19+
export default TurboModuleRegistry.getEnforcing<Spec>('MusicLibrary');

src/MusicLibraryImpl.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// This is the default implementation that exports the native module
2+
// React Native Metro bundler will pick platform-specific versions when available:
3+
// - MusicLibraryImpl.native.ts for iOS/Android
4+
// - MusicLibraryImpl.web.ts for web
5+
export { default } from './MusicLibraryImpl.native';

src/MusicLibraryImpl.web.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import type {
2+
MusicLibraryModule,
3+
TrackResult,
4+
AlbumResult,
5+
ArtistResult,
6+
GenreResult,
7+
} from './types';
8+
9+
const showWebWarning = () => {
10+
if (__DEV__) {
11+
console.warn(
12+
'MusicLibrary: This library is not supported on web platform. ' +
13+
'Music library access is only available on iOS and Android.'
14+
);
15+
}
16+
};
17+
18+
// Web fallback implementation
19+
const MusicLibrary: MusicLibraryModule = {
20+
async getTracksAsync(): Promise<TrackResult> {
21+
showWebWarning();
22+
return {
23+
items: [],
24+
hasNextPage: false,
25+
endCursor: undefined,
26+
totalCount: 0,
27+
};
28+
},
29+
30+
async getAlbumsAsync(): Promise<AlbumResult> {
31+
showWebWarning();
32+
return {
33+
items: [],
34+
hasNextPage: false,
35+
endCursor: undefined,
36+
totalCount: 0,
37+
};
38+
},
39+
40+
async getArtistsAsync(): Promise<ArtistResult> {
41+
showWebWarning();
42+
return {
43+
items: [],
44+
hasNextPage: false,
45+
endCursor: undefined,
46+
totalCount: 0,
47+
};
48+
},
49+
50+
async getGenresAsync(): Promise<GenreResult> {
51+
showWebWarning();
52+
return {
53+
items: [],
54+
hasNextPage: false,
55+
endCursor: undefined,
56+
totalCount: 0,
57+
};
58+
},
59+
};
60+
61+
export default MusicLibrary;

src/NativeMusicLibrary.ts

Lines changed: 8 additions & 245 deletions
Original file line numberDiff line numberDiff line change
@@ -1,247 +1,10 @@
1-
import type { TurboModule } from 'react-native';
2-
import { TurboModuleRegistry } from 'react-native';
1+
// Re-export all types from the shared types file
2+
export * from './types';
33

4-
/**
5-
* Sorting keys for music library items
6-
*/
7-
export type SortByKey =
8-
| 'default'
9-
| 'artist'
10-
| 'album'
11-
| 'duration'
12-
| 'createdAt'
13-
| 'modifiedAt'
14-
| 'genre'
15-
| 'trackCount';
16-
export type SortByValue = [SortByKey, boolean] | SortByKey;
4+
// Platform-specific module import
5+
// React Native Metro bundler will automatically pick the right file based on platform:
6+
// - MusicLibraryImpl.native.ts for iOS/Android
7+
// - MusicLibraryImpl.web.ts for web
8+
import MusicLibrary from './MusicLibraryImpl';
179

18-
export type InternalSortByValue = `${SortByKey} ${'ASC' | 'DESC'}`;
19-
20-
export const SortByObject = {
21-
default: 'default',
22-
artist: 'artist',
23-
album: 'album',
24-
duration: 'duration',
25-
createdAt: 'createdAt',
26-
modifiedAt: 'modifiedAt',
27-
genre: 'genre',
28-
trackCount: 'trackCount',
29-
};
30-
31-
/**
32-
* Basic assets options
33-
*/
34-
export interface AssetsOptions {
35-
/**
36-
* Cursor for pagination - ID of the last item from previous page
37-
* @default undefined
38-
*/
39-
after?: string;
40-
41-
/**
42-
* Maximum number of items to return
43-
* @default 20
44-
*/
45-
first?: number;
46-
47-
/**
48-
* Sorting configuration
49-
* Can be a single key or a tuple of [key, ascending]
50-
* @example
51-
* 'title' // Sort by title descending (default)
52-
* ['title', true] // Sort by title ascending
53-
*/
54-
sortBy?: SortByValue | SortByValue[];
55-
56-
/**
57-
* Directory path to search for tracks
58-
* @default undefined
59-
*/
60-
directory?: string;
61-
}
62-
63-
/**
64-
* Internal assets options used by native module
65-
*/
66-
export interface InternalAssetsOptions {
67-
after?: string;
68-
first: number;
69-
sortBy: InternalSortByValue[];
70-
directory?: string;
71-
}
72-
73-
export interface IPaginatedResult<T> {
74-
/**
75-
* Array of items returned
76-
* @default []
77-
*/
78-
items: T[];
79-
80-
/**
81-
* Whether there are more items available
82-
* @default false
83-
*/
84-
hasNextPage: boolean;
85-
86-
/**
87-
* Cursor for next page (ID of last item)
88-
* @default undefined
89-
*/
90-
endCursor?: string;
91-
92-
/**
93-
* Total count of items (optional, may be expensive to compute)
94-
* @default undefined
95-
*/
96-
totalCount?: number;
97-
}
98-
99-
export interface Track {
100-
id: string;
101-
102-
/**
103-
* Track title
104-
* @default ''
105-
*/
106-
title: string;
107-
108-
/** Track artwork (file URI) */
109-
artwork: string;
110-
111-
/**
112-
* Artist name
113-
* @default ''
114-
*/
115-
artist: string;
116-
117-
/**
118-
* Album name
119-
* @default ''
120-
*/
121-
album: string;
122-
123-
/** Music genre */
124-
genre: string;
125-
126-
/**
127-
* Duration in seconds
128-
* @default 0
129-
*/
130-
duration: number;
131-
132-
/**
133-
* File URI or path
134-
* @default ''
135-
*/
136-
uri: string;
137-
138-
/**
139-
* Date added to library (Unix timestamp, optional)
140-
* @default undefined
141-
*/
142-
createdAt?: number;
143-
144-
/**
145-
* Date modified (Unix timestamp, optional)
146-
* @default undefined
147-
*/
148-
modifiedAt?: number;
149-
150-
/**
151-
* File size in bytes (optional)
152-
* @default undefined
153-
*/
154-
fileSize?: number;
155-
}
156-
157-
export interface Album {
158-
id: string;
159-
160-
/**
161-
* Album name
162-
* @default ''
163-
*/
164-
title: string;
165-
166-
/**
167-
* Primary artist
168-
* @default ''
169-
*/
170-
artist: string;
171-
172-
/**
173-
* Album artwork (base64 encoded image or URL, optional)
174-
* @default undefined
175-
*/
176-
artwork?: string;
177-
178-
/**
179-
* Number of tracks in album
180-
* @default 0
181-
*/
182-
trackCount: number;
183-
184-
/**
185-
* Total duration in seconds
186-
* @default 0
187-
*/
188-
duration: number;
189-
190-
/**
191-
* Release year (optional)
192-
* @default undefined
193-
*/
194-
year?: number;
195-
}
196-
197-
export interface Artist {
198-
id: string;
199-
200-
/**
201-
* Artist name
202-
* @default ''
203-
*/
204-
title: string;
205-
206-
/**
207-
* Number of albums
208-
* @default 0
209-
*/
210-
albumCount: number;
211-
212-
/**
213-
* Total number of tracks
214-
* @default 0
215-
*/
216-
trackCount: number;
217-
}
218-
219-
export interface Genre {
220-
id: string;
221-
222-
/**
223-
* Genre name
224-
* @default ''
225-
*/
226-
title: string;
227-
228-
/**
229-
* Number of tracks in this genre
230-
* @default 0
231-
*/
232-
trackCount: number;
233-
}
234-
235-
export type TrackResult = IPaginatedResult<Track>;
236-
export type AlbumResult = IPaginatedResult<Album>;
237-
export type ArtistResult = IPaginatedResult<Artist>;
238-
export type GenreResult = IPaginatedResult<Genre>;
239-
240-
export interface Spec extends TurboModule {
241-
getTracksAsync(options: InternalAssetsOptions): Promise<TrackResult>;
242-
getAlbumsAsync(options: InternalAssetsOptions): Promise<AlbumResult>;
243-
getArtistsAsync(options: InternalAssetsOptions): Promise<ArtistResult>;
244-
getGenresAsync(options: InternalAssetsOptions): Promise<GenreResult>;
245-
}
246-
247-
export default TurboModuleRegistry.getEnforcing<Spec>('MusicLibrary');
10+
export default MusicLibrary;

0 commit comments

Comments
 (0)