react-native-kookit 0.2.4 → 0.2.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.
- package/ANDROID_FTP_UPDATE.md +161 -0
- package/ANDROID_PARAMETER_FIX.md +0 -0
- package/API_UNIFICATION.md +180 -0
- package/FTP_CLIENT_API.md +301 -0
- package/FTP_EXAMPLE_IMPLEMENTATION.md +0 -0
- package/FTP_FILE_LIST_ENHANCEMENT.md +186 -0
- package/FTP_FILE_OPERATIONS.md +0 -0
- package/android/src/main/java/expo/modules/kookit/FtpClient.kt +2 -0
- package/android/src/main/java/expo/modules/kookit/ReactNativeKookitModule.kt +252 -0
- package/build/FtpClient.d.ts +97 -0
- package/build/FtpClient.d.ts.map +1 -0
- package/build/FtpClient.js +199 -0
- package/build/FtpClient.js.map +1 -0
- package/build/ReactNativeKookit.types.d.ts +13 -5
- package/build/ReactNativeKookit.types.d.ts.map +1 -1
- package/build/ReactNativeKookit.types.js.map +1 -1
- package/build/ReactNativeKookitModule.d.ts +54 -12
- package/build/ReactNativeKookitModule.d.ts.map +1 -1
- package/build/ReactNativeKookitModule.js.map +1 -1
- package/build/index.d.ts +4 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +4 -3
- package/build/index.js.map +1 -1
- package/ios/ReactNativeKookitModule.swift +188 -36
- package/package.json +1 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# FTP 文件列表功能增强
|
|
2
|
+
|
|
3
|
+
本文档描述了对 FTP 客户端示例应用中文件列表功能的增强。
|
|
4
|
+
|
|
5
|
+
## 新增功能
|
|
6
|
+
|
|
7
|
+
### 🗂️ 增强的文件列表显示
|
|
8
|
+
|
|
9
|
+
**文件信息显示:**
|
|
10
|
+
|
|
11
|
+
- 📁 文件夹图标 / 📄 文件图标
|
|
12
|
+
- 文件/文件夹名称
|
|
13
|
+
- 文件大小(字节)
|
|
14
|
+
- 最后修改时间
|
|
15
|
+
- 文件权限信息
|
|
16
|
+
|
|
17
|
+
**交互功能:**
|
|
18
|
+
|
|
19
|
+
- 点击文件夹:直接进入该文件夹
|
|
20
|
+
- 点击文件:显示文件操作菜单
|
|
21
|
+
- 点击菜单按钮(⋮):显示详细操作选项
|
|
22
|
+
|
|
23
|
+
### 📂 目录导航功能
|
|
24
|
+
|
|
25
|
+
**导航按钮:**
|
|
26
|
+
|
|
27
|
+
- **Refresh(刷新)**: 重新加载当前目录的文件列表
|
|
28
|
+
- **Up(向上)**: 返回父目录
|
|
29
|
+
- **Root(根目录)**: 直接跳转到根目录
|
|
30
|
+
- **New Folder(新建文件夹)**: 创建新文件夹
|
|
31
|
+
|
|
32
|
+
**当前路径显示:**
|
|
33
|
+
|
|
34
|
+
- 实时显示当前所在的目录路径
|
|
35
|
+
- 便于用户了解当前位置
|
|
36
|
+
|
|
37
|
+
### 📄 文件操作菜单
|
|
38
|
+
|
|
39
|
+
**对于文件:**
|
|
40
|
+
|
|
41
|
+
- **Download(下载)**: 下载文件到本地临时目录
|
|
42
|
+
- **Delete(删除)**: 删除远程服务器上的文件
|
|
43
|
+
- **Cancel(取消)**: 关闭操作菜单
|
|
44
|
+
|
|
45
|
+
**对于文件夹:**
|
|
46
|
+
|
|
47
|
+
- **Open Directory(打开目录)**: 进入该文件夹
|
|
48
|
+
- **Delete(删除)**: 删除整个文件夹及其内容
|
|
49
|
+
- **Cancel(取消)**: 关闭操作菜单
|
|
50
|
+
|
|
51
|
+
### 📁 新建文件夹功能
|
|
52
|
+
|
|
53
|
+
**操作流程:**
|
|
54
|
+
|
|
55
|
+
1. 点击 "New Folder" 按钮
|
|
56
|
+
2. 在弹出的对话框中输入文件夹名称
|
|
57
|
+
3. 点击 "Create" 创建文件夹
|
|
58
|
+
4. 自动刷新文件列表显示新创建的文件夹
|
|
59
|
+
|
|
60
|
+
### 🔒 安全确认
|
|
61
|
+
|
|
62
|
+
**删除确认:**
|
|
63
|
+
|
|
64
|
+
- 删除任何文件或文件夹前都会弹出确认对话框
|
|
65
|
+
- 防止误删除重要数据
|
|
66
|
+
- 显示将要删除的项目名称
|
|
67
|
+
|
|
68
|
+
## 用户界面改进
|
|
69
|
+
|
|
70
|
+
### 📱 响应式设计
|
|
71
|
+
|
|
72
|
+
**文件列表项:**
|
|
73
|
+
|
|
74
|
+
- 更大的点击区域,便于触摸操作
|
|
75
|
+
- 清晰的视觉层次,信息一目了然
|
|
76
|
+
- 文件夹和文件使用不同的颜色和样式区分
|
|
77
|
+
|
|
78
|
+
**模态对话框:**
|
|
79
|
+
|
|
80
|
+
- 半透明背景,专注于当前操作
|
|
81
|
+
- 居中显示,适合各种屏幕尺寸
|
|
82
|
+
- 清晰的按钮布局,操作直观
|
|
83
|
+
|
|
84
|
+
### 🎨 视觉优化
|
|
85
|
+
|
|
86
|
+
**图标系统:**
|
|
87
|
+
|
|
88
|
+
- 📁 文件夹图标:蓝色文本,便于识别
|
|
89
|
+
- 📄 文件图标:常规颜色
|
|
90
|
+
- ⋮ 菜单图标:灰色,表示更多操作
|
|
91
|
+
|
|
92
|
+
**信息层次:**
|
|
93
|
+
|
|
94
|
+
- 文件名:主要信息,字体较大
|
|
95
|
+
- 文件大小:次要信息,字体中等
|
|
96
|
+
- 修改时间:辅助信息,字体较小,灰色
|
|
97
|
+
|
|
98
|
+
## 操作流程示例
|
|
99
|
+
|
|
100
|
+
### 典型文件浏览流程
|
|
101
|
+
|
|
102
|
+
1. **连接 FTP 服务器**
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
创建客户端 → 输入连接信息 → 点击连接
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
2. **浏览文件**
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
查看文件列表 → 点击文件夹进入 → 查看文件详情
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
3. **文件操作**
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
选择文件 → 选择操作(下载/删除) → 确认操作
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
4. **目录管理**
|
|
121
|
+
```
|
|
122
|
+
新建文件夹 → 输入名称 → 创建 → 查看结果
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 下载文件示例
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
// 用户点击文件 → 选择下载 → 自动执行下载
|
|
129
|
+
const downloadFile = async (file: any) => {
|
|
130
|
+
const localPath = `/tmp/${file.name}`;
|
|
131
|
+
await ftpClient.download(file.name, localPath);
|
|
132
|
+
// 显示成功消息和本地路径
|
|
133
|
+
};
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 创建文件夹示例
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
// 用户输入文件夹名 → 点击创建 → 自动刷新列表
|
|
140
|
+
const createFolder = async () => {
|
|
141
|
+
await ftpClient.createDirectory(newFolderName);
|
|
142
|
+
await listFiles(); // 刷新文件列表
|
|
143
|
+
};
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## 错误处理
|
|
147
|
+
|
|
148
|
+
### 网络错误
|
|
149
|
+
|
|
150
|
+
- 连接超时:显示友好的错误消息
|
|
151
|
+
- 认证失败:提示检查用户名和密码
|
|
152
|
+
- 权限不足:显示权限相关的错误信息
|
|
153
|
+
|
|
154
|
+
### 文件操作错误
|
|
155
|
+
|
|
156
|
+
- 下载失败:显示具体的失败原因
|
|
157
|
+
- 删除失败:可能是权限问题或文件正在使用
|
|
158
|
+
- 创建文件夹失败:可能是名称冲突或权限不足
|
|
159
|
+
|
|
160
|
+
### 用户输入错误
|
|
161
|
+
|
|
162
|
+
- 空文件夹名:禁用创建按钮
|
|
163
|
+
- 无效字符:提示输入有效的文件夹名称
|
|
164
|
+
|
|
165
|
+
## 技术实现要点
|
|
166
|
+
|
|
167
|
+
### 状态管理
|
|
168
|
+
|
|
169
|
+
- `files`: 当前目录的文件列表
|
|
170
|
+
- `selectedFile`: 当前选中的文件
|
|
171
|
+
- `showFileModal`: 文件操作模态框显示状态
|
|
172
|
+
- `showCreateFolder`: 创建文件夹模态框显示状态
|
|
173
|
+
|
|
174
|
+
### 事件处理
|
|
175
|
+
|
|
176
|
+
- 文件点击:区分文件和文件夹的不同处理逻辑
|
|
177
|
+
- 模态框管理:正确的显示和隐藏逻辑
|
|
178
|
+
- 异步操作:proper async/await 处理和错误捕获
|
|
179
|
+
|
|
180
|
+
### 用户体验优化
|
|
181
|
+
|
|
182
|
+
- 操作反馈:每个操作都有相应的日志记录
|
|
183
|
+
- 进度显示:下载和上传操作显示进度
|
|
184
|
+
- 状态保持:操作完成后自动刷新相关状态
|
|
185
|
+
|
|
186
|
+
这些增强功能使得 FTP 客户端示例应用更加实用和用户友好,提供了完整的文件管理体验。
|
|
File without changes
|
|
@@ -39,6 +39,8 @@ class FtpClient {
|
|
|
39
39
|
private var config: FtpConnectionConfig? = null
|
|
40
40
|
private var useUtf8 = false
|
|
41
41
|
|
|
42
|
+
fun isConnected(): Boolean = isConnected
|
|
43
|
+
|
|
42
44
|
@Throws(Exception::class)
|
|
43
45
|
suspend fun connect(config: FtpConnectionConfig) = withContext(Dispatchers.IO) {
|
|
44
46
|
this@FtpClient.config = config
|
|
@@ -17,6 +17,7 @@ class ReactNativeKookitModule : Module() {
|
|
|
17
17
|
private var audioManager: AudioManager? = null
|
|
18
18
|
private var originalStreamVolume: Int = 0
|
|
19
19
|
private var ftpClient: FtpClient? = null
|
|
20
|
+
private val ftpClients = mutableMapOf<String, FtpClient>()
|
|
20
21
|
private val moduleScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
|
21
22
|
|
|
22
23
|
// Each module class must implement the definition function. The definition consists of components
|
|
@@ -82,6 +83,257 @@ class ReactNativeKookitModule : Module() {
|
|
|
82
83
|
}
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
// New FTP Client Management Functions
|
|
87
|
+
AsyncFunction("createFtpClient") { clientId: String, promise: Promise ->
|
|
88
|
+
moduleScope.launch {
|
|
89
|
+
try {
|
|
90
|
+
if (ftpClients.containsKey(clientId)) {
|
|
91
|
+
promise.reject("FTP_CLIENT_EXISTS", "FTP client with ID '$clientId' already exists", null)
|
|
92
|
+
return@launch
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
val client = FtpClient()
|
|
96
|
+
ftpClients[clientId] = client
|
|
97
|
+
promise.resolve(mapOf("clientId" to clientId))
|
|
98
|
+
} catch (e: Exception) {
|
|
99
|
+
promise.reject("FTP_CREATE_CLIENT_ERROR", e.message, e)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
AsyncFunction("disposeFtpClient") { clientId: String, promise: Promise ->
|
|
105
|
+
moduleScope.launch {
|
|
106
|
+
try {
|
|
107
|
+
val client = ftpClients[clientId]
|
|
108
|
+
if (client != null) {
|
|
109
|
+
client.disconnect()
|
|
110
|
+
ftpClients.remove(clientId)
|
|
111
|
+
}
|
|
112
|
+
promise.resolve(null)
|
|
113
|
+
} catch (e: Exception) {
|
|
114
|
+
promise.reject("FTP_DISPOSE_CLIENT_ERROR", e.message, e)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
AsyncFunction("getFtpClientStatus") { clientId: String, promise: Promise ->
|
|
120
|
+
moduleScope.launch {
|
|
121
|
+
try {
|
|
122
|
+
val client = ftpClients[clientId]
|
|
123
|
+
val status = mapOf(
|
|
124
|
+
"exists" to (client != null),
|
|
125
|
+
"connected" to (client?.isConnected() ?: false)
|
|
126
|
+
)
|
|
127
|
+
promise.resolve(status)
|
|
128
|
+
} catch (e: Exception) {
|
|
129
|
+
promise.reject("FTP_CLIENT_STATUS_ERROR", e.message, e)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
AsyncFunction("listFtpClients") { promise: Promise ->
|
|
135
|
+
moduleScope.launch {
|
|
136
|
+
try {
|
|
137
|
+
val clients = mutableMapOf<String, Map<String, Any>>()
|
|
138
|
+
ftpClients.forEach { (id, client) ->
|
|
139
|
+
clients[id] = mapOf("connected" to client.isConnected())
|
|
140
|
+
}
|
|
141
|
+
val result = mapOf(
|
|
142
|
+
"clients" to clients,
|
|
143
|
+
"count" to ftpClients.size
|
|
144
|
+
)
|
|
145
|
+
promise.resolve(result)
|
|
146
|
+
} catch (e: Exception) {
|
|
147
|
+
promise.reject("FTP_LIST_CLIENTS_ERROR", e.message, e)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
AsyncFunction("ftpClientConnect") { clientId: String, config: Map<String, Any>, promise: Promise ->
|
|
153
|
+
moduleScope.launch {
|
|
154
|
+
try {
|
|
155
|
+
val client = ftpClients[clientId]
|
|
156
|
+
?: throw Exception("FTP client with ID '$clientId' not found")
|
|
157
|
+
|
|
158
|
+
val ftpConfig = FtpConnectionConfig(
|
|
159
|
+
host = config["host"] as String,
|
|
160
|
+
port = (config["port"] as? Double)?.toInt() ?: 21,
|
|
161
|
+
username = config["username"] as String,
|
|
162
|
+
password = config["password"] as String,
|
|
163
|
+
passive = config["passive"] as? Boolean ?: true,
|
|
164
|
+
timeout = (config["timeout"] as? Double)?.toInt() ?: 30000
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
client.connect(ftpConfig)
|
|
168
|
+
promise.resolve(null)
|
|
169
|
+
} catch (e: Exception) {
|
|
170
|
+
promise.reject("FTP_CLIENT_CONNECT_ERROR", e.message, e)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
AsyncFunction("ftpClientDisconnect") { clientId: String, promise: Promise ->
|
|
176
|
+
moduleScope.launch {
|
|
177
|
+
try {
|
|
178
|
+
val client = ftpClients[clientId]
|
|
179
|
+
?: throw Exception("FTP client with ID '$clientId' not found")
|
|
180
|
+
client.disconnect()
|
|
181
|
+
promise.resolve(null)
|
|
182
|
+
} catch (e: Exception) {
|
|
183
|
+
promise.reject("FTP_CLIENT_DISCONNECT_ERROR", e.message, e)
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
AsyncFunction("ftpClientList") { clientId: String, path: String?, promise: Promise ->
|
|
189
|
+
moduleScope.launch {
|
|
190
|
+
try {
|
|
191
|
+
val client = ftpClients[clientId]
|
|
192
|
+
?: throw Exception("FTP client with ID '$clientId' not found")
|
|
193
|
+
|
|
194
|
+
val files = client.listFiles(path)
|
|
195
|
+
val result = files.map { file ->
|
|
196
|
+
mapOf(
|
|
197
|
+
"name" to file.name,
|
|
198
|
+
"isDirectory" to file.isDirectory,
|
|
199
|
+
"size" to file.size,
|
|
200
|
+
"lastModified" to file.lastModified,
|
|
201
|
+
"permissions" to file.permissions
|
|
202
|
+
)
|
|
203
|
+
}
|
|
204
|
+
promise.resolve(result)
|
|
205
|
+
} catch (e: Exception) {
|
|
206
|
+
promise.reject("FTP_CLIENT_LIST_ERROR", e.message, e)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
AsyncFunction("ftpClientDownload") { clientId: String, remotePath: String, localPath: String, promise: Promise ->
|
|
212
|
+
moduleScope.launch {
|
|
213
|
+
try {
|
|
214
|
+
val client = ftpClients[clientId]
|
|
215
|
+
?: throw Exception("FTP client with ID '$clientId' not found")
|
|
216
|
+
|
|
217
|
+
val listener = object : FtpProgressListener {
|
|
218
|
+
override fun onProgress(transferred: Long, total: Long) {
|
|
219
|
+
val percentage = if (total > 0) (transferred * 100 / total).toInt() else 0
|
|
220
|
+
sendEvent("onFtpProgress", mapOf(
|
|
221
|
+
"clientId" to clientId,
|
|
222
|
+
"transferred" to transferred,
|
|
223
|
+
"total" to total,
|
|
224
|
+
"percentage" to percentage
|
|
225
|
+
))
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
override fun onComplete() {
|
|
229
|
+
sendEvent("onFtpComplete", mapOf("clientId" to clientId))
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
override fun onError(error: String) {
|
|
233
|
+
sendEvent("onFtpError", mapOf(
|
|
234
|
+
"clientId" to clientId,
|
|
235
|
+
"error" to error
|
|
236
|
+
))
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
client.downloadFile(remotePath, localPath, listener)
|
|
241
|
+
promise.resolve(null)
|
|
242
|
+
} catch (e: Exception) {
|
|
243
|
+
promise.reject("FTP_CLIENT_DOWNLOAD_ERROR", e.message, e)
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
AsyncFunction("ftpClientUpload") { clientId: String, localPath: String, remotePath: String, promise: Promise ->
|
|
249
|
+
moduleScope.launch {
|
|
250
|
+
try {
|
|
251
|
+
val client = ftpClients[clientId]
|
|
252
|
+
?: throw Exception("FTP client with ID '$clientId' not found")
|
|
253
|
+
|
|
254
|
+
val listener = object : FtpProgressListener {
|
|
255
|
+
override fun onProgress(transferred: Long, total: Long) {
|
|
256
|
+
val percentage = if (total > 0) (transferred * 100 / total).toInt() else 0
|
|
257
|
+
sendEvent("onFtpProgress", mapOf(
|
|
258
|
+
"clientId" to clientId,
|
|
259
|
+
"transferred" to transferred,
|
|
260
|
+
"total" to total,
|
|
261
|
+
"percentage" to percentage
|
|
262
|
+
))
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
override fun onComplete() {
|
|
266
|
+
sendEvent("onFtpComplete", mapOf("clientId" to clientId))
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
override fun onError(error: String) {
|
|
270
|
+
sendEvent("onFtpError", mapOf(
|
|
271
|
+
"clientId" to clientId,
|
|
272
|
+
"error" to error
|
|
273
|
+
))
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
client.uploadFile(localPath, remotePath, listener)
|
|
278
|
+
promise.resolve(null)
|
|
279
|
+
} catch (e: Exception) {
|
|
280
|
+
promise.reject("FTP_CLIENT_UPLOAD_ERROR", e.message, e)
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
AsyncFunction("ftpClientDelete") { clientId: String, remotePath: String, isDirectory: Boolean?, promise: Promise ->
|
|
286
|
+
moduleScope.launch {
|
|
287
|
+
try {
|
|
288
|
+
val client = ftpClients[clientId]
|
|
289
|
+
?: throw Exception("FTP client with ID '$clientId' not found")
|
|
290
|
+
client.deleteFile(remotePath, isDirectory ?: false)
|
|
291
|
+
promise.resolve(null)
|
|
292
|
+
} catch (e: Exception) {
|
|
293
|
+
promise.reject("FTP_CLIENT_DELETE_ERROR", e.message, e)
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
AsyncFunction("ftpClientCreateDirectory") { clientId: String, remotePath: String, promise: Promise ->
|
|
299
|
+
moduleScope.launch {
|
|
300
|
+
try {
|
|
301
|
+
val client = ftpClients[clientId]
|
|
302
|
+
?: throw Exception("FTP client with ID '$clientId' not found")
|
|
303
|
+
client.createDirectory(remotePath)
|
|
304
|
+
promise.resolve(null)
|
|
305
|
+
} catch (e: Exception) {
|
|
306
|
+
promise.reject("FTP_CLIENT_CREATE_DIR_ERROR", e.message, e)
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
AsyncFunction("ftpClientChangeDirectory") { clientId: String, remotePath: String, promise: Promise ->
|
|
312
|
+
moduleScope.launch {
|
|
313
|
+
try {
|
|
314
|
+
val client = ftpClients[clientId]
|
|
315
|
+
?: throw Exception("FTP client with ID '$clientId' not found")
|
|
316
|
+
client.changeDirectory(remotePath)
|
|
317
|
+
promise.resolve(null)
|
|
318
|
+
} catch (e: Exception) {
|
|
319
|
+
promise.reject("FTP_CLIENT_CHANGE_DIR_ERROR", e.message, e)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
AsyncFunction("ftpClientGetCurrentDirectory") { clientId: String, promise: Promise ->
|
|
325
|
+
moduleScope.launch {
|
|
326
|
+
try {
|
|
327
|
+
val client = ftpClients[clientId]
|
|
328
|
+
?: throw Exception("FTP client with ID '$clientId' not found")
|
|
329
|
+
val currentDir = client.getCurrentDirectory()
|
|
330
|
+
promise.resolve(currentDir)
|
|
331
|
+
} catch (e: Exception) {
|
|
332
|
+
promise.reject("FTP_CLIENT_PWD_ERROR", e.message, e)
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
85
337
|
AsyncFunction("ftpDisconnect") { promise: Promise ->
|
|
86
338
|
moduleScope.launch {
|
|
87
339
|
try {
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { FtpConnectionConfig, FtpFileInfo } from "./ReactNativeKookit.types";
|
|
2
|
+
export interface FtpClientEventHandlers {
|
|
3
|
+
onProgress?: (progress: {
|
|
4
|
+
transferred: number;
|
|
5
|
+
total: number;
|
|
6
|
+
percentage: number;
|
|
7
|
+
}) => void;
|
|
8
|
+
onComplete?: () => void;
|
|
9
|
+
onError?: (error: Error) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare class FtpClient {
|
|
12
|
+
private clientId;
|
|
13
|
+
private isDisposed;
|
|
14
|
+
private eventHandlers;
|
|
15
|
+
private eventSubscriptions;
|
|
16
|
+
constructor(clientId?: string);
|
|
17
|
+
private setupEventListeners;
|
|
18
|
+
/**
|
|
19
|
+
* Set event handlers
|
|
20
|
+
*/
|
|
21
|
+
setEventHandlers(handlers: FtpClientEventHandlers): void;
|
|
22
|
+
/**
|
|
23
|
+
* Initialize the FTP client instance
|
|
24
|
+
*/
|
|
25
|
+
initialize(): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Connect to the FTP server
|
|
28
|
+
*/
|
|
29
|
+
connect(config: FtpConnectionConfig): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Disconnect from the FTP server
|
|
32
|
+
*/
|
|
33
|
+
disconnect(): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* List files in the specified directory
|
|
36
|
+
*/
|
|
37
|
+
list(path?: string): Promise<FtpFileInfo[]>;
|
|
38
|
+
/**
|
|
39
|
+
* Download a file from the remote server
|
|
40
|
+
*/
|
|
41
|
+
download(remotePath: string, localPath: string): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Upload a file to the remote server
|
|
44
|
+
*/
|
|
45
|
+
upload(localPath: string, remotePath: string): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Delete a file or directory on the remote server
|
|
48
|
+
*/
|
|
49
|
+
delete(remotePath: string, isDirectory?: boolean): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Create a directory on the remote server
|
|
52
|
+
*/
|
|
53
|
+
createDirectory(remotePath: string): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Change the current working directory on the remote server
|
|
56
|
+
*/
|
|
57
|
+
changeDirectory(remotePath: string): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Get the current working directory on the remote server
|
|
60
|
+
*/
|
|
61
|
+
getCurrentDirectory(): Promise<string>;
|
|
62
|
+
/**
|
|
63
|
+
* Get client status information
|
|
64
|
+
* @returns Client status including existence and connection state
|
|
65
|
+
*/
|
|
66
|
+
getStatus(): Promise<{
|
|
67
|
+
clientId: string;
|
|
68
|
+
exists: boolean;
|
|
69
|
+
connected: boolean;
|
|
70
|
+
}>;
|
|
71
|
+
/**
|
|
72
|
+
* Get the client ID
|
|
73
|
+
*/
|
|
74
|
+
getClientId(): string;
|
|
75
|
+
/**
|
|
76
|
+
* Check if the client is connected
|
|
77
|
+
*/
|
|
78
|
+
isConnected(): Promise<boolean>;
|
|
79
|
+
/**
|
|
80
|
+
* Dispose the FTP client and clean up resources
|
|
81
|
+
*/
|
|
82
|
+
dispose(): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Static method to list all FTP clients
|
|
85
|
+
*/
|
|
86
|
+
static listClients(): Promise<{
|
|
87
|
+
clients: Record<string, {
|
|
88
|
+
connected: boolean;
|
|
89
|
+
}>;
|
|
90
|
+
count: number;
|
|
91
|
+
}>;
|
|
92
|
+
/**
|
|
93
|
+
* Static method to create and initialize a new FTP client
|
|
94
|
+
*/
|
|
95
|
+
static create(clientId?: string): Promise<FtpClient>;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=FtpClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FtpClient.d.ts","sourceRoot":"","sources":["../src/FtpClient.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,mBAAmB,EACnB,WAAW,EAIZ,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;KACpB,KAAK,IAAI,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,kBAAkB,CAAqC;gBAEnD,QAAQ,CAAC,EAAE,MAAM;IAO7B,OAAO,CAAC,mBAAmB;IAoC3B;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,sBAAsB,GAAG,IAAI;IAIxD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQjC;;OAEG;IACG,OAAO,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IASzD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQjC;;OAEG;IACG,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAQjD;;OAEG;IACG,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYpE;;OAEG;IACG,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYlE;;OAEG;IACG,MAAM,CACV,UAAU,EAAE,MAAM,EAClB,WAAW,GAAE,OAAe,GAC3B,OAAO,CAAC,IAAI,CAAC;IAYhB;;OAEG;IACG,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxD;;OAEG;IACG,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxD;;OAEG;IACG,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC;IAW5C;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC;QACzB,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,OAAO,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;KACpB,CAAC;IAUF;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAarC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB9B;;OAEG;WACU,WAAW,IAAI,OAAO,CAAC;QAClC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,SAAS,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;QAChD,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IAIF;;OAEG;WACU,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;CAK3D"}
|