react-native-kookit 0.3.5 → 0.3.6

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.
@@ -0,0 +1,130 @@
1
+ # Changelog - Content URI Handler
2
+
3
+ ## [Unreleased] - 2025-10-09
4
+
5
+ ### Added
6
+
7
+ #### Content URI Handler (Android)
8
+ 通过 Android ContentResolver 处理 `content://` URI,解决权限限制问题。
9
+
10
+ **新增 API:**
11
+ - `copyContentUriToCache(contentUri, fileName?)` - 复制 content URI 到缓存目录
12
+ - `getContentUriMetadata(contentUri)` - 获取文件元数据(名称、大小、MIME 类型)
13
+
14
+ **核心功能:**
15
+ - ✅ 使用 ContentResolver 绕过权限限制
16
+ - ✅ 无需 `READ_EXTERNAL_STORAGE` 权限
17
+ - ✅ 支持所有 ContentProvider(文件管理器、下载管理器、第三方应用)
18
+ - ✅ 8KB 缓冲区流式复制
19
+ - ✅ 后台线程执行,避免阻塞 UI
20
+ - ✅ 完整的错误处理和资源清理
21
+ - ✅ TypeScript 类型定义
22
+
23
+ **解决的问题:**
24
+ - `SecurityException: Permission Denial` when accessing content:// URIs
25
+ - 第三方应用未正确授予 URI 读取权限
26
+ - expo-file-system 无法访问某些 content:// URIs
27
+
28
+ **文档:**
29
+ - 📖 [完整文档](./docs/CONTENT_URI_HANDLER.md)
30
+ - 💡 [快速示例](./example/ContentUriQuickExamples.ts)
31
+ - 🎨 [UI 示例组件](./example/ContentUriExample.tsx)
32
+ - 📝 [实现总结](./IMPLEMENTATION_SUMMARY.md)
33
+
34
+ **使用场景:**
35
+ - 处理"打开方式" Intent
36
+ - 处理"分享到" Intent
37
+ - 从文档选择器获取文件
38
+ - 从第三方文件管理器接收文件
39
+ - 与 FTP/SMB 客户端集成上传
40
+
41
+ **技术细节:**
42
+ - Platform: Android (API 19+)
43
+ - 实现语言: Kotlin
44
+ - 异步执行: Coroutines (Dispatchers.IO)
45
+ - 缓存位置: Context.getCacheDir()
46
+
47
+ ### Changed
48
+ - 更新 README.md,添加功能列表和 Content URI Handler 介绍
49
+
50
+ ### Technical Notes
51
+
52
+ **原生模块更改:**
53
+ ```kotlin
54
+ // 新增导入
55
+ import android.net.Uri
56
+ import android.provider.OpenableColumns
57
+ import android.database.Cursor
58
+ import java.io.File
59
+ import java.io.FileOutputStream
60
+ import java.io.InputStream
61
+
62
+ // 新增方法
63
+ AsyncFunction("copyContentUriToCache")
64
+ AsyncFunction("getContentUriMetadata")
65
+
66
+ // 新增辅助方法
67
+ private fun getContentUriMetadataInternal(context: Context, uri: Uri)
68
+ ```
69
+
70
+ **TypeScript 接口更改:**
71
+ ```typescript
72
+ // src/ReactNativeKookitModule.ts
73
+ copyContentUriToCache(contentUri: string, fileName?: string): Promise<{...}>
74
+ getContentUriMetadata(contentUri: string): Promise<{...}>
75
+ ```
76
+
77
+ ### Migration Guide
78
+
79
+ 此为新增功能,无需迁移。现有代码不受影响。
80
+
81
+ ### Example Usage
82
+
83
+ ```typescript
84
+ import ReactNativeKookitModule from 'react-native-kookit';
85
+
86
+ // 复制文件
87
+ const result = await ReactNativeKookitModule.copyContentUriToCache(
88
+ 'content://...',
89
+ 'filename.pdf'
90
+ );
91
+ console.log('Local path:', result.localPath);
92
+
93
+ // 获取元数据
94
+ const metadata = await ReactNativeKookitModule.getContentUriMetadata(
95
+ 'content://...'
96
+ );
97
+ console.log('File info:', metadata);
98
+ ```
99
+
100
+ ### Breaking Changes
101
+
102
+
103
+
104
+ ### Deprecations
105
+
106
+
107
+
108
+ ### Security
109
+
110
+ - 此功能仅访问应用明确接收的 content:// URIs
111
+ - 文件复制到应用私有缓存目录,其他应用无法访问
112
+ - 无需请求存储权限
113
+ - 符合 Android 安全最佳实践
114
+
115
+ ### Performance
116
+
117
+ - 使用 8KB 缓冲区优化复制速度
118
+ - 在后台线程执行,不阻塞 UI
119
+ - 适合处理几 MB 到几百 MB 的文件
120
+ - 对于超大文件,建议添加进度监听(未来版本)
121
+
122
+ ### Known Issues
123
+
124
+ - 仅支持 Android 平台(iOS 不需要此功能)
125
+ - 非常大的文件(> 500MB)可能需要较长时间
126
+ - 缓存文件需要手动清理(或等待系统清理)
127
+
128
+ ### Credits
129
+
130
+ 实现基于 Android ContentResolver API 和 Expo Modules 框架。
@@ -0,0 +1,206 @@
1
+ # Content URI Handler - 实现总结
2
+
3
+ ## 功能概述
4
+
5
+ 为 `react-native-kookit` 添加了 Android ContentResolver 功能,用于处理来自其他应用的 `content://` URI,解决权限拒绝(Permission Denial)问题。
6
+
7
+ ## 实现的文件
8
+
9
+ ### 1. TypeScript 接口 (`src/ReactNativeKookitModule.ts`)
10
+
11
+ 添加了两个新方法:
12
+
13
+ ```typescript
14
+ // 复制 content:// URI 到缓存目录
15
+ copyContentUriToCache(contentUri: string, fileName?: string): Promise<{
16
+ localPath: string;
17
+ fileName: string;
18
+ mimeType?: string;
19
+ size?: number;
20
+ }>;
21
+
22
+ // 获取 content:// URI 的元数据
23
+ getContentUriMetadata(contentUri: string): Promise<{
24
+ displayName?: string;
25
+ mimeType?: string;
26
+ size?: number;
27
+ }>;
28
+ ```
29
+
30
+ ### 2. Android 原生实现 (`android/src/main/java/expo/modules/kookit/ReactNativeKookitModule.kt`)
31
+
32
+ #### 添加的导入
33
+ ```kotlin
34
+ import android.net.Uri
35
+ import android.provider.OpenableColumns
36
+ import android.database.Cursor
37
+ import java.io.File
38
+ import java.io.FileOutputStream
39
+ import java.io.InputStream
40
+ ```
41
+
42
+ #### 实现的功能
43
+
44
+ **`copyContentUriToCache`**
45
+ - 验证 URI scheme 是否为 `content://`
46
+ - 使用 `ContentResolver.openInputStream()` 读取文件流
47
+ - 将数据复制到应用缓存目录
48
+ - 使用 8KB 缓冲区提高效率
49
+ - 在 IO 线程执行,避免阻塞主线程
50
+ - 返回本地文件路径和元数据
51
+
52
+ **`getContentUriMetadata`**
53
+ - 使用 `ContentResolver.query()` 查询文件信息
54
+ - 获取 `DISPLAY_NAME` 和 `SIZE`
55
+ - 获取 MIME 类型
56
+
57
+ **辅助方法 `getContentUriMetadataInternal`**
58
+ - 共享的元数据查询逻辑
59
+ - 使用 Cursor 安全访问数据库
60
+ - 正确处理资源释放
61
+
62
+ ### 3. 文档
63
+
64
+ - **`docs/CONTENT_URI_HANDLER.md`** - 完整的 API 文档和使用指南
65
+ - **`README.md`** - 更新了功能列表,添加了 Content URI Handler 介绍
66
+
67
+ ### 4. 示例代码
68
+
69
+ - **`example/ContentUriExample.tsx`** - 完整的 React Native 示例组件
70
+ - 文件选择和复制
71
+ - 元数据查询
72
+ - UI 展示
73
+ - 错误处理
74
+
75
+ - **`example/ContentUriQuickExamples.ts`** - 快速参考示例
76
+ - 7 个常见使用场景
77
+ - 与 FTP 客户端集成
78
+ - 完整的工作流示例
79
+
80
+ ## 技术亮点
81
+
82
+ ### 1. 解决的核心问题
83
+
84
+ **问题:** 当通过"打开方式"或"分享"接收文件时,第三方应用可能没有正确设置 `FLAG_GRANT_READ_URI_PERMISSION`,导致:
85
+ ```
86
+ java.lang.SecurityException: Permission Denial
87
+ ```
88
+
89
+ **解决方案:** 使用 `ContentResolver` 直接读取输入流,无需文件系统权限。
90
+
91
+ ### 2. 优势
92
+
93
+ ✅ **无需额外权限** - 不需要 `READ_EXTERNAL_STORAGE`
94
+ ✅ **兼容性强** - 适用于所有 ContentProvider
95
+ ✅ **性能优化** - 使用缓冲区,在后台线程执行
96
+ ✅ **错误处理** - 完善的异常处理和资源清理
97
+ ✅ **类型安全** - 完整的 TypeScript 类型定义
98
+
99
+ ### 3. 实现细节
100
+
101
+ **线程管理:**
102
+ ```kotlin
103
+ moduleScope.launch(Dispatchers.IO) {
104
+ // 文件操作在 IO 线程
105
+ withContext(Dispatchers.Main) {
106
+ // 回调在主线程
107
+ promise.resolve(result)
108
+ }
109
+ }
110
+ ```
111
+
112
+ **资源管理:**
113
+ ```kotlin
114
+ try {
115
+ inputStream = context.contentResolver.openInputStream(uri)
116
+ // ... 复制操作
117
+ } finally {
118
+ inputStream?.close()
119
+ outputStream?.close()
120
+ }
121
+ ```
122
+
123
+ **错误处理:**
124
+ ```kotlin
125
+ if (uri.scheme != "content") {
126
+ throw Exception("Only content:// URIs are supported")
127
+ }
128
+ ```
129
+
130
+ ## 使用场景
131
+
132
+ ### 1. 文件选择器集成
133
+ ```typescript
134
+ const result = await DocumentPicker.getDocumentAsync(...);
135
+ const file = await copyContentUriToCache(result.assets[0].uri);
136
+ ```
137
+
138
+ ### 2. 处理 Intent
139
+ ```typescript
140
+ const url = await Linking.getInitialURL();
141
+ if (url?.startsWith('content://')) {
142
+ const file = await copyContentUriToCache(url);
143
+ }
144
+ ```
145
+
146
+ ### 3. 与 FTP/SMB 集成
147
+ ```typescript
148
+ const file = await copyContentUriToCache(contentUri);
149
+ await ftpClient.upload(file.localPath, '/uploads/file.pdf');
150
+ ```
151
+
152
+ ## 测试建议
153
+
154
+ ### 单元测试
155
+ 1. 验证 content:// URI 的处理
156
+ 2. 测试元数据提取
157
+ 3. 测试错误情况(无效 URI、权限问题等)
158
+
159
+ ### 集成测试
160
+ 1. 使用文件选择器选择文件
161
+ 2. 通过"打开方式"分享文件到应用
162
+ 3. 从不同的 ContentProvider 获取文件
163
+ 4. 测试大文件(> 100MB)
164
+
165
+ ### 性能测试
166
+ 1. 不同文件大小的复制速度
167
+ 2. 内存使用情况
168
+ 3. 并发操作
169
+
170
+ ## 兼容性
171
+
172
+ - **最低 Android 版本:** API 19 (Android 4.4)
173
+ - **React Native:** 0.60+
174
+ - **Expo:** SDK 44+
175
+ - **依赖:** 仅标准 Android API,无额外依赖
176
+
177
+ ## 未来改进方向
178
+
179
+ 1. **进度回调** - 为大文件添加复制进度
180
+ 2. **流式处理** - 对于超大文件,提供流式访问而非完整复制
181
+ 3. **缓存管理** - 自动清理旧的缓存文件
182
+ 4. **批量操作** - 同时处理多个 content:// URI
183
+ 5. **iOS 支持** - 为 iOS 添加类似功能(如果需要)
184
+
185
+ ## API 变更
186
+
187
+ ### 新增方法
188
+
189
+ - `copyContentUriToCache(contentUri: string, fileName?: string)`
190
+ - `getContentUriMetadata(contentUri: string)`
191
+
192
+ ### 无破坏性变更
193
+
194
+ 所有现有 API 保持不变,这是一个纯新增功能。
195
+
196
+ ## 文档
197
+
198
+ - 📖 [完整 API 文档](./docs/CONTENT_URI_HANDLER.md)
199
+ - 💡 [快速示例](./example/ContentUriQuickExamples.ts)
200
+ - 🎨 [UI 示例](./example/ContentUriExample.tsx)
201
+
202
+ ## 相关资源
203
+
204
+ - [Android ContentResolver 文档](https://developer.android.com/reference/android/content/ContentResolver)
205
+ - [Android 内容 URI 最佳实践](https://developer.android.com/training/secure-file-sharing)
206
+ - [Expo 文件系统](https://docs.expo.dev/versions/latest/sdk/filesystem/)
package/README.md CHANGED
@@ -1,6 +1,26 @@
1
1
  # react-native-kookit
2
2
 
3
- A React Native module for intercepting volume button presses on both iOS and Android platforms.
3
+ A comprehensive React Native/Expo module with multiple utilities for Android and iOS.
4
+
5
+ ## Features
6
+
7
+ - 🎵 **Volume Key Interception** - Capture volume button presses on both iOS and Android
8
+ - 📁 **FTP Client** - Full-featured FTP client with upload/download capabilities
9
+ - 🗂️ **SMB Client** - Access SMB/CIFS network shares
10
+ - 📱 **Content URI Handler** (Android) - Handle `content://` URIs from other apps, bypassing permission restrictions
11
+
12
+ ### Content URI Handler
13
+
14
+ The Content URI Handler solves a common Android problem: when receiving files via "Open with" or "Share" intents, apps receive `content://` URIs that often trigger `SecurityException: Permission Denial` errors.
15
+
16
+ **Key Benefits:**
17
+ - ✅ Bypass permission restrictions using Android's ContentResolver
18
+ - ✅ No `READ_EXTERNAL_STORAGE` permission needed
19
+ - ✅ Works with all third-party apps and file managers
20
+ - ✅ Get file metadata (name, size, MIME type)
21
+ - ✅ Copy to app cache directory for further processing
22
+
23
+ 📖 [**View Content URI Handler Documentation**](./docs/CONTENT_URI_HANDLER.md)
4
24
 
5
25
  # API documentation
6
26
 
@@ -11,6 +11,12 @@ import expo.modules.kotlin.exception.Exceptions
11
11
  import expo.modules.kotlin.Promise
12
12
  import kotlinx.coroutines.*
13
13
  import java.net.URL
14
+ import android.net.Uri
15
+ import android.provider.OpenableColumns
16
+ import android.database.Cursor
17
+ import java.io.File
18
+ import java.io.FileOutputStream
19
+ import java.io.InputStream
14
20
 
15
21
  class ReactNativeKookitModule : Module() {
16
22
  private var isVolumeListenerEnabled = false
@@ -723,6 +729,89 @@ class ReactNativeKookitModule : Module() {
723
729
  }
724
730
  }
725
731
 
732
+ // ContentResolver functions for handling content:// URIs
733
+ AsyncFunction("copyContentUriToCache") { contentUri: String, fileName: String?, promise: Promise ->
734
+ moduleScope.launch(Dispatchers.IO) {
735
+ try {
736
+ val context = appContext.reactContext ?: throw Exception("React context is not available")
737
+ val uri = Uri.parse(contentUri)
738
+
739
+ if (uri.scheme != "content") {
740
+ throw Exception("Only content:// URIs are supported. Received: ${uri.scheme}://")
741
+ }
742
+
743
+ // Get metadata from ContentResolver
744
+ val metadata = getContentUriMetadataInternal(context, uri)
745
+
746
+ // Determine file name
747
+ val finalFileName = fileName ?: metadata["displayName"] as? String
748
+ ?: "file_${System.currentTimeMillis()}"
749
+
750
+ // Create destination file in cache directory
751
+ val cacheDir = context.cacheDir
752
+ val destFile = File(cacheDir, finalFileName)
753
+
754
+ // Copy file using ContentResolver InputStream
755
+ var inputStream: InputStream? = null
756
+ var outputStream: FileOutputStream? = null
757
+ var totalBytes = 0L
758
+
759
+ try {
760
+ inputStream = context.contentResolver.openInputStream(uri)
761
+ ?: throw Exception("Failed to open input stream for URI: $contentUri")
762
+
763
+ outputStream = FileOutputStream(destFile)
764
+ val buffer = ByteArray(8192)
765
+ var bytesRead: Int
766
+
767
+ while (inputStream.read(buffer).also { bytesRead = it } != -1) {
768
+ outputStream.write(buffer, 0, bytesRead)
769
+ totalBytes += bytesRead
770
+ }
771
+
772
+ outputStream.flush()
773
+
774
+ // Build result
775
+ val result = mapOf(
776
+ "localPath" to destFile.absolutePath,
777
+ "fileName" to finalFileName,
778
+ "mimeType" to metadata["mimeType"],
779
+ "size" to totalBytes
780
+ )
781
+
782
+ withContext(Dispatchers.Main) { promise.resolve(result) }
783
+ } finally {
784
+ inputStream?.close()
785
+ outputStream?.close()
786
+ }
787
+ } catch (e: Exception) {
788
+ withContext(Dispatchers.Main) {
789
+ promise.reject("COPY_CONTENT_URI_ERROR", "Failed to copy content URI: ${e.message}", e)
790
+ }
791
+ }
792
+ }
793
+ }
794
+
795
+ AsyncFunction("getContentUriMetadata") { contentUri: String, promise: Promise ->
796
+ moduleScope.launch(Dispatchers.IO) {
797
+ try {
798
+ val context = appContext.reactContext ?: throw Exception("React context is not available")
799
+ val uri = Uri.parse(contentUri)
800
+
801
+ if (uri.scheme != "content") {
802
+ throw Exception("Only content:// URIs are supported. Received: ${uri.scheme}://")
803
+ }
804
+
805
+ val metadata = getContentUriMetadataInternal(context, uri)
806
+ withContext(Dispatchers.Main) { promise.resolve(metadata) }
807
+ } catch (e: Exception) {
808
+ withContext(Dispatchers.Main) {
809
+ promise.reject("GET_CONTENT_URI_METADATA_ERROR", "Failed to get metadata: ${e.message}", e)
810
+ }
811
+ }
812
+ }
813
+ }
814
+
726
815
  // Enables the module to be used as a native view. Definition components that are accepted as part of
727
816
  // the view definition: Prop, Events.
728
817
  View(ReactNativeKookitView::class) {
@@ -789,4 +878,54 @@ class ReactNativeKookitModule : Module() {
789
878
  // Context might be lost, ignore
790
879
  }
791
880
  }
881
+
882
+ /**
883
+ * Internal helper to query content URI metadata using ContentResolver
884
+ */
885
+ private fun getContentUriMetadataInternal(context: Context, uri: Uri): Map<String, Any?> {
886
+ var cursor: Cursor? = null
887
+ try {
888
+ cursor = context.contentResolver.query(
889
+ uri,
890
+ arrayOf(
891
+ OpenableColumns.DISPLAY_NAME,
892
+ OpenableColumns.SIZE
893
+ ),
894
+ null,
895
+ null,
896
+ null
897
+ )
898
+
899
+ var displayName: String? = null
900
+ var size: Long? = null
901
+
902
+ cursor?.use {
903
+ if (it.moveToFirst()) {
904
+ val nameIndex = it.getColumnIndex(OpenableColumns.DISPLAY_NAME)
905
+ val sizeIndex = it.getColumnIndex(OpenableColumns.SIZE)
906
+
907
+ if (nameIndex != -1) {
908
+ displayName = it.getString(nameIndex)
909
+ }
910
+
911
+ if (sizeIndex != -1 && !it.isNull(sizeIndex)) {
912
+ size = it.getLong(sizeIndex)
913
+ }
914
+ }
915
+ }
916
+
917
+ // Get MIME type
918
+ val mimeType = context.contentResolver.getType(uri)
919
+
920
+ return mapOf(
921
+ "displayName" to displayName,
922
+ "mimeType" to mimeType,
923
+ "size" to size
924
+ )
925
+ } catch (e: Exception) {
926
+ throw Exception("Failed to query content URI metadata: ${e.message}", e)
927
+ } finally {
928
+ cursor?.close()
929
+ }
930
+ }
792
931
  }
@@ -141,6 +141,34 @@ declare class ReactNativeKookitModule extends NativeModule<ReactNativeKookitModu
141
141
  }>;
142
142
  count: number;
143
143
  }>;
144
+ /**
145
+ * Copy a file from content:// URI to local cache directory.
146
+ * This method uses Android's ContentResolver to read the file stream,
147
+ * bypassing permission restrictions when receiving content URIs from other apps.
148
+ *
149
+ * @param contentUri The content:// URI received from another app (e.g., via Intent)
150
+ * @param fileName Optional filename for the destination file. If not provided, tries to extract from URI
151
+ * @returns Promise that resolves with the local file path (file://)
152
+ * @platform android
153
+ */
154
+ copyContentUriToCache(contentUri: string, fileName?: string): Promise<{
155
+ localPath: string;
156
+ fileName: string;
157
+ mimeType?: string;
158
+ size?: number;
159
+ }>;
160
+ /**
161
+ * Get metadata about a content:// URI without copying the file.
162
+ *
163
+ * @param contentUri The content:// URI to query
164
+ * @returns Promise that resolves with file metadata
165
+ * @platform android
166
+ */
167
+ getContentUriMetadata(contentUri: string): Promise<{
168
+ displayName?: string;
169
+ mimeType?: string;
170
+ size?: number;
171
+ }>;
144
172
  }
145
173
  declare const _default: ReactNativeKookitModule;
146
174
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"ReactNativeKookitModule.d.ts","sourceRoot":"","sources":["../src/ReactNativeKookitModule.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ReactNativeKookitModule.d.ts","sourceRoot":"","sources":["../src/ReactNativeKookitModule.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReactNativeKookitModule.js","sourceRoot":"","sources":["../src/ReactNativeKookitModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAmMzD,yDAAyD;AACzD,eAAe,mBAAmB,CAChC,mBAAmB,CACpB,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from \"expo\";\n\nimport {\n ReactNativeKookitModuleEvents,\n FtpConnectionConfig,\n FtpFileInfo,\n SmbConnectionConfig,\n SmbFileInfo,\n} from \"./ReactNativeKookit.types\";\n\ndeclare class ReactNativeKookitModule extends NativeModule<ReactNativeKookitModuleEvents> {\n PI: number;\n\n /**\n * Returns a hello world string\n */\n hello(): string;\n\n /**\n * Test async function that sends a change event\n */\n setValueAsync(value: string): Promise<void>;\n\n /**\n * Enables volume key interception.\n * On Android, your MainActivity must implement VolumeKeyInterceptActivity interface.\n * On iOS, this works automatically.\n *\n * @throws Error if MainActivity doesn't implement VolumeKeyInterceptActivity on Android\n */\n enableVolumeKeyInterception(): void;\n\n /**\n * Disables volume key interception\n */\n disableVolumeKeyInterception(): void;\n\n // New FTP Client API Methods\n\n /**\n * Create a new FTP client instance\n * @param clientId Unique identifier for the FTP client\n * @returns Promise that resolves with client creation result\n */\n createFtpClient(clientId: string): Promise<{ clientId: string }>;\n\n /**\n * Connect FTP client to server\n * @param clientId FTP client identifier\n * @param config FTP connection configuration\n * @returns Promise that resolves when connected\n */\n ftpClientConnect(\n clientId: string,\n config: FtpConnectionConfig\n ): Promise<void>;\n\n /**\n * Disconnect FTP client from server\n * @param clientId FTP client identifier\n * @returns Promise that resolves when disconnected\n */\n ftpClientDisconnect(clientId: string): Promise<void>;\n\n /**\n * Dispose FTP client and clean up resources\n * @param clientId FTP client identifier\n * @returns Promise that resolves when disposed\n */\n disposeFtpClient(clientId: string): Promise<void>;\n\n /**\n * List files and directories\n * @param clientId FTP client identifier\n * @param path Optional path to list (defaults to current directory)\n * @returns Promise that resolves with array of file information\n */\n ftpClientList(clientId: string, path?: string): Promise<FtpFileInfo[]>;\n\n /**\n * Download a file from FTP server\n * @param clientId FTP client identifier\n * @param remotePath Remote file path on FTP server\n * @param localPath Local file path to save the downloaded file\n * @returns Promise that resolves when download is complete\n */\n ftpClientDownload(\n clientId: string,\n remotePath: string,\n localPath: string\n ): Promise<void>;\n\n /**\n * Upload a file to FTP server\n * @param clientId FTP client identifier\n * @param localPath Local file path to upload\n * @param remotePath Remote file path on FTP server\n * @returns Promise that resolves when upload is complete\n */\n ftpClientUpload(\n clientId: string,\n localPath: string,\n remotePath: string\n ): Promise<void>;\n\n /**\n * Delete a file or directory on FTP server\n * @param clientId FTP client identifier\n * @param remotePath Remote file or directory path to delete\n * @param isDirectory Whether the path is a directory (default: false)\n * @returns Promise that resolves when deletion is complete\n */\n ftpClientDelete(\n clientId: string,\n remotePath: string,\n isDirectory?: boolean\n ): Promise<void>;\n\n /**\n * Create a directory on FTP server\n * @param clientId FTP client identifier\n * @param remotePath Remote directory path to create\n * @returns Promise that resolves when directory is created\n */\n ftpClientCreateDirectory(clientId: string, remotePath: string): Promise<void>;\n\n /**\n * Change current working directory on FTP server\n * @param clientId FTP client identifier\n * @param remotePath Remote directory path to change to\n * @returns Promise that resolves when directory is changed\n */\n ftpClientChangeDirectory(clientId: string, remotePath: string): Promise<void>;\n\n /**\n * Get current working directory on FTP server\n * @param clientId FTP client identifier\n * @returns Promise that resolves with current directory path\n */\n ftpClientGetCurrentDirectory(clientId: string): Promise<string>;\n\n /**\n * Get FTP client status\n * @param clientId FTP client identifier\n * @returns Client status information\n */\n getFtpClientStatus(\n clientId: string\n ): Promise<{ exists: boolean; connected: boolean }>;\n\n /**\n * List all FTP clients\n * @returns Object containing all clients and their status\n */\n listFtpClients(): Promise<{\n clients: Record<string, { connected: boolean }>;\n count: number;\n }>;\n\n // SMB Client API\n\n createSmbClient(clientId: string): Promise<{ clientId: string }>;\n smbClientConnect(\n clientId: string,\n config: SmbConnectionConfig\n ): Promise<void>;\n smbClientConnectShare(clientId: string, shareName: string): Promise<void>;\n smbClientDisconnect(clientId: string): Promise<void>;\n disposeSmbClient(clientId: string): Promise<void>;\n smbClientList(clientId: string, path?: string): Promise<SmbFileInfo[]>;\n smbClientDownload(\n clientId: string,\n remotePath: string,\n localPath: string\n ): Promise<void>;\n smbClientUpload(\n clientId: string,\n localPath: string,\n remotePath: string\n ): Promise<void>;\n smbClientDelete(\n clientId: string,\n remotePath: string,\n isDirectory?: boolean\n ): Promise<void>;\n smbClientCreateDirectory(clientId: string, remotePath: string): Promise<void>;\n getSmbClientStatus(\n clientId: string\n ): Promise<{ exists: boolean; connected: boolean }>;\n listSmbClients(): Promise<{\n clients: Record<string, { connected: boolean }>;\n count: number;\n }>;\n}\n\n// This call loads the native module object from the JSI.\nexport default requireNativeModule<ReactNativeKookitModule>(\n \"ReactNativeKookit\"\n);\n"]}
1
+ {"version":3,"file":"ReactNativeKookitModule.js","sourceRoot":"","sources":["../src/ReactNativeKookitModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAiOzD,yDAAyD;AACzD,eAAe,mBAAmB,CAChC,mBAAmB,CACpB,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from \"expo\";\n\nimport {\n ReactNativeKookitModuleEvents,\n FtpConnectionConfig,\n FtpFileInfo,\n SmbConnectionConfig,\n SmbFileInfo,\n} from \"./ReactNativeKookit.types\";\n\ndeclare class ReactNativeKookitModule extends NativeModule<ReactNativeKookitModuleEvents> {\n PI: number;\n\n /**\n * Returns a hello world string\n */\n hello(): string;\n\n /**\n * Test async function that sends a change event\n */\n setValueAsync(value: string): Promise<void>;\n\n /**\n * Enables volume key interception.\n * On Android, your MainActivity must implement VolumeKeyInterceptActivity interface.\n * On iOS, this works automatically.\n *\n * @throws Error if MainActivity doesn't implement VolumeKeyInterceptActivity on Android\n */\n enableVolumeKeyInterception(): void;\n\n /**\n * Disables volume key interception\n */\n disableVolumeKeyInterception(): void;\n\n // New FTP Client API Methods\n\n /**\n * Create a new FTP client instance\n * @param clientId Unique identifier for the FTP client\n * @returns Promise that resolves with client creation result\n */\n createFtpClient(clientId: string): Promise<{ clientId: string }>;\n\n /**\n * Connect FTP client to server\n * @param clientId FTP client identifier\n * @param config FTP connection configuration\n * @returns Promise that resolves when connected\n */\n ftpClientConnect(\n clientId: string,\n config: FtpConnectionConfig\n ): Promise<void>;\n\n /**\n * Disconnect FTP client from server\n * @param clientId FTP client identifier\n * @returns Promise that resolves when disconnected\n */\n ftpClientDisconnect(clientId: string): Promise<void>;\n\n /**\n * Dispose FTP client and clean up resources\n * @param clientId FTP client identifier\n * @returns Promise that resolves when disposed\n */\n disposeFtpClient(clientId: string): Promise<void>;\n\n /**\n * List files and directories\n * @param clientId FTP client identifier\n * @param path Optional path to list (defaults to current directory)\n * @returns Promise that resolves with array of file information\n */\n ftpClientList(clientId: string, path?: string): Promise<FtpFileInfo[]>;\n\n /**\n * Download a file from FTP server\n * @param clientId FTP client identifier\n * @param remotePath Remote file path on FTP server\n * @param localPath Local file path to save the downloaded file\n * @returns Promise that resolves when download is complete\n */\n ftpClientDownload(\n clientId: string,\n remotePath: string,\n localPath: string\n ): Promise<void>;\n\n /**\n * Upload a file to FTP server\n * @param clientId FTP client identifier\n * @param localPath Local file path to upload\n * @param remotePath Remote file path on FTP server\n * @returns Promise that resolves when upload is complete\n */\n ftpClientUpload(\n clientId: string,\n localPath: string,\n remotePath: string\n ): Promise<void>;\n\n /**\n * Delete a file or directory on FTP server\n * @param clientId FTP client identifier\n * @param remotePath Remote file or directory path to delete\n * @param isDirectory Whether the path is a directory (default: false)\n * @returns Promise that resolves when deletion is complete\n */\n ftpClientDelete(\n clientId: string,\n remotePath: string,\n isDirectory?: boolean\n ): Promise<void>;\n\n /**\n * Create a directory on FTP server\n * @param clientId FTP client identifier\n * @param remotePath Remote directory path to create\n * @returns Promise that resolves when directory is created\n */\n ftpClientCreateDirectory(clientId: string, remotePath: string): Promise<void>;\n\n /**\n * Change current working directory on FTP server\n * @param clientId FTP client identifier\n * @param remotePath Remote directory path to change to\n * @returns Promise that resolves when directory is changed\n */\n ftpClientChangeDirectory(clientId: string, remotePath: string): Promise<void>;\n\n /**\n * Get current working directory on FTP server\n * @param clientId FTP client identifier\n * @returns Promise that resolves with current directory path\n */\n ftpClientGetCurrentDirectory(clientId: string): Promise<string>;\n\n /**\n * Get FTP client status\n * @param clientId FTP client identifier\n * @returns Client status information\n */\n getFtpClientStatus(\n clientId: string\n ): Promise<{ exists: boolean; connected: boolean }>;\n\n /**\n * List all FTP clients\n * @returns Object containing all clients and their status\n */\n listFtpClients(): Promise<{\n clients: Record<string, { connected: boolean }>;\n count: number;\n }>;\n\n // SMB Client API\n\n createSmbClient(clientId: string): Promise<{ clientId: string }>;\n smbClientConnect(\n clientId: string,\n config: SmbConnectionConfig\n ): Promise<void>;\n smbClientConnectShare(clientId: string, shareName: string): Promise<void>;\n smbClientDisconnect(clientId: string): Promise<void>;\n disposeSmbClient(clientId: string): Promise<void>;\n smbClientList(clientId: string, path?: string): Promise<SmbFileInfo[]>;\n smbClientDownload(\n clientId: string,\n remotePath: string,\n localPath: string\n ): Promise<void>;\n smbClientUpload(\n clientId: string,\n localPath: string,\n remotePath: string\n ): Promise<void>;\n smbClientDelete(\n clientId: string,\n remotePath: string,\n isDirectory?: boolean\n ): Promise<void>;\n smbClientCreateDirectory(clientId: string, remotePath: string): Promise<void>;\n getSmbClientStatus(\n clientId: string\n ): Promise<{ exists: boolean; connected: boolean }>;\n listSmbClients(): Promise<{\n clients: Record<string, { connected: boolean }>;\n count: number;\n }>;\n\n /**\n * Copy a file from content:// URI to local cache directory.\n * This method uses Android's ContentResolver to read the file stream,\n * bypassing permission restrictions when receiving content URIs from other apps.\n * \n * @param contentUri The content:// URI received from another app (e.g., via Intent)\n * @param fileName Optional filename for the destination file. If not provided, tries to extract from URI\n * @returns Promise that resolves with the local file path (file://)\n * @platform android\n */\n copyContentUriToCache(contentUri: string, fileName?: string): Promise<{ \n localPath: string;\n fileName: string;\n mimeType?: string;\n size?: number;\n }>;\n\n /**\n * Get metadata about a content:// URI without copying the file.\n * \n * @param contentUri The content:// URI to query\n * @returns Promise that resolves with file metadata\n * @platform android\n */\n getContentUriMetadata(contentUri: string): Promise<{\n displayName?: string;\n mimeType?: string;\n size?: number;\n }>;\n}\n\n// This call loads the native module object from the JSI.\nexport default requireNativeModule<ReactNativeKookitModule>(\n \"ReactNativeKookit\"\n);\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-kookit",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "description": "React Native module for intercepting volume button presses on iOS and Android, with FTP client functionality",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",