react-native-kookit 0.2.1 → 0.2.2

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.
@@ -8,12 +8,16 @@ import android.media.AudioManager
8
8
  import android.view.KeyEvent
9
9
  import expo.modules.kotlin.AppContext
10
10
  import expo.modules.kotlin.exception.Exceptions
11
+ import expo.modules.kotlin.Promise
12
+ import kotlinx.coroutines.*
11
13
  import java.net.URL
12
14
 
13
15
  class ReactNativeKookitModule : Module() {
14
16
  private var isVolumeListenerEnabled = false
15
17
  private var audioManager: AudioManager? = null
16
18
  private var originalStreamVolume: Int = 0
19
+ private var ftpClient: FtpClient? = null
20
+ private val moduleScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
17
21
 
18
22
  // Each module class must implement the definition function. The definition consists of components
19
23
  // that describes the module's functionality and behavior.
@@ -30,7 +34,7 @@ class ReactNativeKookitModule : Module() {
30
34
  )
31
35
 
32
36
  // Defines event names that the module can send to JavaScript.
33
- Events("onChange", "onVolumeButtonPressed")
37
+ Events("onChange", "onVolumeButtonPressed", "onFtpProgress", "onFtpComplete", "onFtpError")
34
38
 
35
39
  // Function to enable volume key interception
36
40
  Function("enableVolumeKeyInterception") {
@@ -56,6 +60,164 @@ class ReactNativeKookitModule : Module() {
56
60
  ))
57
61
  }
58
62
 
63
+ // FTP Functions
64
+ AsyncFunction("ftpConnect") { config: Map<String, Any>, promise: Promise ->
65
+ moduleScope.launch {
66
+ try {
67
+ val ftpConfig = FtpConnectionConfig(
68
+ host = config["host"] as String,
69
+ port = (config["port"] as? Double)?.toInt() ?: 21,
70
+ username = config["username"] as String,
71
+ password = config["password"] as String,
72
+ passive = config["passive"] as? Boolean ?: true,
73
+ timeout = (config["timeout"] as? Double)?.toInt() ?: 30000
74
+ )
75
+
76
+ ftpClient = FtpClient()
77
+ ftpClient?.connect(ftpConfig)
78
+ promise.resolve(null)
79
+ } catch (e: Exception) {
80
+ promise.reject("FTP_CONNECT_ERROR", e.message, e)
81
+ }
82
+ }
83
+ }
84
+
85
+ AsyncFunction("ftpDisconnect") { promise: Promise ->
86
+ moduleScope.launch {
87
+ try {
88
+ ftpClient?.disconnect()
89
+ ftpClient = null
90
+ promise.resolve(null)
91
+ } catch (e: Exception) {
92
+ promise.reject("FTP_DISCONNECT_ERROR", e.message, e)
93
+ }
94
+ }
95
+ }
96
+
97
+ AsyncFunction("ftpList") { path: String?, promise: Promise ->
98
+ moduleScope.launch {
99
+ try {
100
+ val files = ftpClient?.listFiles(path) ?: emptyList()
101
+ val result = files.map { file ->
102
+ mapOf(
103
+ "name" to file.name,
104
+ "isDirectory" to file.isDirectory,
105
+ "size" to file.size,
106
+ "lastModified" to file.lastModified,
107
+ "permissions" to file.permissions
108
+ )
109
+ }
110
+ promise.resolve(result)
111
+ } catch (e: Exception) {
112
+ promise.reject("FTP_LIST_ERROR", e.message, e)
113
+ }
114
+ }
115
+ }
116
+
117
+ AsyncFunction("ftpDownload") { remotePath: String, localPath: String, promise: Promise ->
118
+ moduleScope.launch {
119
+ try {
120
+ val listener = object : FtpProgressListener {
121
+ override fun onProgress(transferred: Long, total: Long) {
122
+ val percentage = if (total > 0) (transferred * 100 / total).toInt() else 0
123
+ sendEvent("onFtpProgress", mapOf(
124
+ "transferred" to transferred,
125
+ "total" to total,
126
+ "percentage" to percentage
127
+ ))
128
+ }
129
+
130
+ override fun onComplete() {
131
+ sendEvent("onFtpComplete")
132
+ }
133
+
134
+ override fun onError(error: String) {
135
+ sendEvent("onFtpError", mapOf("error" to error))
136
+ }
137
+ }
138
+
139
+ ftpClient?.downloadFile(remotePath, localPath, listener)
140
+ promise.resolve(null)
141
+ } catch (e: Exception) {
142
+ promise.reject("FTP_DOWNLOAD_ERROR", e.message, e)
143
+ }
144
+ }
145
+ }
146
+
147
+ AsyncFunction("ftpUpload") { localPath: String, remotePath: String, promise: Promise ->
148
+ moduleScope.launch {
149
+ try {
150
+ val listener = object : FtpProgressListener {
151
+ override fun onProgress(transferred: Long, total: Long) {
152
+ val percentage = if (total > 0) (transferred * 100 / total).toInt() else 0
153
+ sendEvent("onFtpProgress", mapOf(
154
+ "transferred" to transferred,
155
+ "total" to total,
156
+ "percentage" to percentage
157
+ ))
158
+ }
159
+
160
+ override fun onComplete() {
161
+ sendEvent("onFtpComplete")
162
+ }
163
+
164
+ override fun onError(error: String) {
165
+ sendEvent("onFtpError", mapOf("error" to error))
166
+ }
167
+ }
168
+
169
+ ftpClient?.uploadFile(localPath, remotePath, listener)
170
+ promise.resolve(null)
171
+ } catch (e: Exception) {
172
+ promise.reject("FTP_UPLOAD_ERROR", e.message, e)
173
+ }
174
+ }
175
+ }
176
+
177
+ AsyncFunction("ftpDelete") { remotePath: String, isDirectory: Boolean?, promise: Promise ->
178
+ moduleScope.launch {
179
+ try {
180
+ ftpClient?.deleteFile(remotePath, isDirectory ?: false)
181
+ promise.resolve(null)
182
+ } catch (e: Exception) {
183
+ promise.reject("FTP_DELETE_ERROR", e.message, e)
184
+ }
185
+ }
186
+ }
187
+
188
+ AsyncFunction("ftpCreateDirectory") { remotePath: String, promise: Promise ->
189
+ moduleScope.launch {
190
+ try {
191
+ ftpClient?.createDirectory(remotePath)
192
+ promise.resolve(null)
193
+ } catch (e: Exception) {
194
+ promise.reject("FTP_CREATE_DIR_ERROR", e.message, e)
195
+ }
196
+ }
197
+ }
198
+
199
+ AsyncFunction("ftpChangeDirectory") { remotePath: String, promise: Promise ->
200
+ moduleScope.launch {
201
+ try {
202
+ ftpClient?.changeDirectory(remotePath)
203
+ promise.resolve(null)
204
+ } catch (e: Exception) {
205
+ promise.reject("FTP_CHANGE_DIR_ERROR", e.message, e)
206
+ }
207
+ }
208
+ }
209
+
210
+ AsyncFunction("ftpGetCurrentDirectory") { promise: Promise ->
211
+ moduleScope.launch {
212
+ try {
213
+ val currentDir = ftpClient?.getCurrentDirectory() ?: "/"
214
+ promise.resolve(currentDir)
215
+ } catch (e: Exception) {
216
+ promise.reject("FTP_PWD_ERROR", e.message, e)
217
+ }
218
+ }
219
+ }
220
+
59
221
  // Enables the module to be used as a native view. Definition components that are accepted as part of
60
222
  // the view definition: Prop, Events.
61
223
  View(ReactNativeKookitView::class) {
@@ -5,9 +5,39 @@ export type OnLoadEventPayload = {
5
5
  export type VolumeKeyEventPayload = {
6
6
  key: "up" | "down";
7
7
  };
8
+ export type FtpConnectionConfig = {
9
+ host: string;
10
+ port?: number;
11
+ username: string;
12
+ password: string;
13
+ passive?: boolean;
14
+ timeout?: number;
15
+ };
16
+ export type FtpFileInfo = {
17
+ name: string;
18
+ isDirectory: boolean;
19
+ size: number;
20
+ lastModified: string;
21
+ permissions?: string;
22
+ };
23
+ export type FtpProgressInfo = {
24
+ transferred: number;
25
+ total: number;
26
+ percentage: number;
27
+ };
28
+ export type FtpEventPayload = {
29
+ onProgress?: (progress: FtpProgressInfo) => void;
30
+ onComplete?: () => void;
31
+ onError?: (error: string) => void;
32
+ };
8
33
  export type ReactNativeKookitModuleEvents = {
9
34
  onChange: (params: ChangeEventPayload) => void;
10
35
  onVolumeButtonPressed: (params: VolumeKeyEventPayload) => void;
36
+ onFtpProgress: (params: FtpProgressInfo) => void;
37
+ onFtpComplete: () => void;
38
+ onFtpError: (params: {
39
+ error: string;
40
+ }) => void;
11
41
  };
12
42
  export type ChangeEventPayload = {
13
43
  value: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ReactNativeKookit.types.d.ts","sourceRoot":"","sources":["../src/ReactNativeKookit.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,EAAE,IAAI,GAAG,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,QAAQ,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC/C,qBAAqB,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,IAAI,CAAC;CAChE,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,kBAAkB,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7D,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B,CAAC"}
1
+ {"version":3,"file":"ReactNativeKookit.types.d.ts","sourceRoot":"","sources":["../src/ReactNativeKookit.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,EAAE,IAAI,GAAG,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,eAAe,KAAK,IAAI,CAAC;IACjD,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,QAAQ,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC/C,qBAAqB,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC/D,aAAa,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,CAAC;IACjD,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,UAAU,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,kBAAkB,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7D,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReactNativeKookit.types.js","sourceRoot":"","sources":["../src/ReactNativeKookit.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { StyleProp, ViewStyle } from \"react-native\";\n\nexport type OnLoadEventPayload = {\n url: string;\n};\n\nexport type VolumeKeyEventPayload = {\n key: \"up\" | \"down\";\n};\n\nexport type ReactNativeKookitModuleEvents = {\n onChange: (params: ChangeEventPayload) => void;\n onVolumeButtonPressed: (params: VolumeKeyEventPayload) => void;\n};\n\nexport type ChangeEventPayload = {\n value: string;\n};\n\nexport type ReactNativeKookitViewProps = {\n url: string;\n onLoad: (event: { nativeEvent: OnLoadEventPayload }) => void;\n style?: StyleProp<ViewStyle>;\n};\n"]}
1
+ {"version":3,"file":"ReactNativeKookit.types.js","sourceRoot":"","sources":["../src/ReactNativeKookit.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { StyleProp, ViewStyle } from \"react-native\";\n\nexport type OnLoadEventPayload = {\n url: string;\n};\n\nexport type VolumeKeyEventPayload = {\n key: \"up\" | \"down\";\n};\n\nexport type FtpConnectionConfig = {\n host: string;\n port?: number;\n username: string;\n password: string;\n passive?: boolean;\n timeout?: number;\n};\n\nexport type FtpFileInfo = {\n name: string;\n isDirectory: boolean;\n size: number;\n lastModified: string;\n permissions?: string;\n};\n\nexport type FtpProgressInfo = {\n transferred: number;\n total: number;\n percentage: number;\n};\n\nexport type FtpEventPayload = {\n onProgress?: (progress: FtpProgressInfo) => void;\n onComplete?: () => void;\n onError?: (error: string) => void;\n};\n\nexport type ReactNativeKookitModuleEvents = {\n onChange: (params: ChangeEventPayload) => void;\n onVolumeButtonPressed: (params: VolumeKeyEventPayload) => void;\n onFtpProgress: (params: FtpProgressInfo) => void;\n onFtpComplete: () => void;\n onFtpError: (params: { error: string }) => void;\n};\n\nexport type ChangeEventPayload = {\n value: string;\n};\n\nexport type ReactNativeKookitViewProps = {\n url: string;\n onLoad: (event: { nativeEvent: OnLoadEventPayload }) => void;\n style?: StyleProp<ViewStyle>;\n};\n"]}
@@ -1,5 +1,5 @@
1
1
  import { NativeModule } from "expo";
2
- import { ReactNativeKookitModuleEvents } from "./ReactNativeKookit.types";
2
+ import { ReactNativeKookitModuleEvents, FtpConnectionConfig, FtpFileInfo } from "./ReactNativeKookit.types";
3
3
  declare class ReactNativeKookitModule extends NativeModule<ReactNativeKookitModuleEvents> {
4
4
  PI: number;
5
5
  /**
@@ -22,6 +22,61 @@ declare class ReactNativeKookitModule extends NativeModule<ReactNativeKookitModu
22
22
  * Disables volume key interception
23
23
  */
24
24
  disableVolumeKeyInterception(): void;
25
+ /**
26
+ * Connect to FTP server
27
+ * @param config FTP connection configuration
28
+ * @returns Promise that resolves when connected
29
+ */
30
+ ftpConnect(config: FtpConnectionConfig): Promise<void>;
31
+ /**
32
+ * Disconnect from FTP server
33
+ * @returns Promise that resolves when disconnected
34
+ */
35
+ ftpDisconnect(): Promise<void>;
36
+ /**
37
+ * List files and directories in the current directory
38
+ * @param path Optional path to list (defaults to current directory)
39
+ * @returns Promise that resolves with array of file information
40
+ */
41
+ ftpList(path?: string): Promise<FtpFileInfo[]>;
42
+ /**
43
+ * Download a file from FTP server
44
+ * @param remotePath Remote file path on FTP server
45
+ * @param localPath Local file path to save the downloaded file
46
+ * @returns Promise that resolves when download is complete
47
+ */
48
+ ftpDownload(remotePath: string, localPath: string): Promise<void>;
49
+ /**
50
+ * Upload a file to FTP server
51
+ * @param localPath Local file path to upload
52
+ * @param remotePath Remote file path on FTP server
53
+ * @returns Promise that resolves when upload is complete
54
+ */
55
+ ftpUpload(localPath: string, remotePath: string): Promise<void>;
56
+ /**
57
+ * Delete a file or directory on FTP server
58
+ * @param remotePath Remote file or directory path to delete
59
+ * @param isDirectory Whether the path is a directory (default: false)
60
+ * @returns Promise that resolves when deletion is complete
61
+ */
62
+ ftpDelete(remotePath: string, isDirectory?: boolean): Promise<void>;
63
+ /**
64
+ * Create a directory on FTP server
65
+ * @param remotePath Remote directory path to create
66
+ * @returns Promise that resolves when directory is created
67
+ */
68
+ ftpCreateDirectory(remotePath: string): Promise<void>;
69
+ /**
70
+ * Change current working directory on FTP server
71
+ * @param remotePath Remote directory path to change to
72
+ * @returns Promise that resolves when directory is changed
73
+ */
74
+ ftpChangeDirectory(remotePath: string): Promise<void>;
75
+ /**
76
+ * Get current working directory on FTP server
77
+ * @returns Promise that resolves with current directory path
78
+ */
79
+ ftpGetCurrentDirectory(): Promise<string>;
25
80
  }
26
81
  declare const _default: ReactNativeKookitModule;
27
82
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"ReactNativeKookitModule.d.ts","sourceRoot":"","sources":["../src/ReactNativeKookitModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,MAAM,CAAC;AAEzD,OAAO,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAE1E,OAAO,OAAO,uBAAwB,SAAQ,YAAY,CAAC,6BAA6B,CAAC;IACvF,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,KAAK,IAAI,MAAM;IAEf;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAE3C;;;;;;OAMG;IACH,2BAA2B,IAAI,IAAI;IAEnC;;OAEG;IACH,4BAA4B,IAAI,IAAI;CACrC;;AAGD,wBAEE"}
1
+ {"version":3,"file":"ReactNativeKookitModule.d.ts","sourceRoot":"","sources":["../src/ReactNativeKookitModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,MAAM,CAAC;AAEzD,OAAO,EACL,6BAA6B,EAC7B,mBAAmB,EACnB,WAAW,EACZ,MAAM,2BAA2B,CAAC;AAEnC,OAAO,OAAO,uBAAwB,SAAQ,YAAY,CAAC,6BAA6B,CAAC;IACvF,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,KAAK,IAAI,MAAM;IAEf;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAE3C;;;;;;OAMG;IACH,2BAA2B,IAAI,IAAI;IAEnC;;OAEG;IACH,4BAA4B,IAAI,IAAI;IAIpC;;;;OAIG;IACH,UAAU,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAEtD;;;OAGG;IACH,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAE9B;;;;OAIG;IACH,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAE9C;;;;;OAKG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAEjE;;;;;OAKG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/D;;;;;OAKG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAEnE;;;;OAIG;IACH,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAErD;;;;OAIG;IACH,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAErD;;;OAGG;IACH,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC;CAC1C;;AAGD,wBAEE"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReactNativeKookitModule.js","sourceRoot":"","sources":["../src/ReactNativeKookitModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAgCzD,yDAAyD;AACzD,eAAe,mBAAmB,CAChC,mBAAmB,CACpB,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from \"expo\";\n\nimport { ReactNativeKookitModuleEvents } 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\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;AAsGzD,yDAAyD;AACzD,eAAe,mBAAmB,CAChC,mBAAmB,CACpB,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from \"expo\";\n\nimport {\n ReactNativeKookitModuleEvents,\n FtpConnectionConfig,\n FtpFileInfo,\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 // FTP Methods\n\n /**\n * Connect to FTP server\n * @param config FTP connection configuration\n * @returns Promise that resolves when connected\n */\n ftpConnect(config: FtpConnectionConfig): Promise<void>;\n\n /**\n * Disconnect from FTP server\n * @returns Promise that resolves when disconnected\n */\n ftpDisconnect(): Promise<void>;\n\n /**\n * List files and directories in the current directory\n * @param path Optional path to list (defaults to current directory)\n * @returns Promise that resolves with array of file information\n */\n ftpList(path?: string): Promise<FtpFileInfo[]>;\n\n /**\n * Download a file from FTP server\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 ftpDownload(remotePath: string, localPath: string): Promise<void>;\n\n /**\n * Upload a file to FTP server\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 ftpUpload(localPath: string, remotePath: string): Promise<void>;\n\n /**\n * Delete a file or directory on FTP server\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 ftpDelete(remotePath: string, isDirectory?: boolean): Promise<void>;\n\n /**\n * Create a directory on FTP server\n * @param remotePath Remote directory path to create\n * @returns Promise that resolves when directory is created\n */\n ftpCreateDirectory(remotePath: string): Promise<void>;\n\n /**\n * Change current working directory on FTP server\n * @param remotePath Remote directory path to change to\n * @returns Promise that resolves when directory is changed\n */\n ftpChangeDirectory(remotePath: string): Promise<void>;\n\n /**\n * Get current working directory on FTP server\n * @returns Promise that resolves with current directory path\n */\n ftpGetCurrentDirectory(): Promise<string>;\n}\n\n// This call loads the native module object from the JSI.\nexport default requireNativeModule<ReactNativeKookitModule>(\n \"ReactNativeKookit\"\n);\n"]}
@@ -1,5 +1,5 @@
1
1
  import { NativeModule } from "expo";
2
- import { ReactNativeKookitModuleEvents } from "./ReactNativeKookit.types";
2
+ import { ReactNativeKookitModuleEvents, FtpConnectionConfig, FtpFileInfo } from "./ReactNativeKookit.types";
3
3
  declare class ReactNativeKookitModule extends NativeModule<ReactNativeKookitModuleEvents> {
4
4
  PI: number;
5
5
  setValueAsync(value: string): Promise<void>;
@@ -7,6 +7,15 @@ declare class ReactNativeKookitModule extends NativeModule<ReactNativeKookitModu
7
7
  enableVolumeKeyInterception(): void;
8
8
  disableVolumeKeyInterception(): void;
9
9
  private handleKeyDown;
10
+ ftpConnect(config: FtpConnectionConfig): Promise<void>;
11
+ ftpDisconnect(): Promise<void>;
12
+ ftpList(path?: string): Promise<FtpFileInfo[]>;
13
+ ftpDownload(remotePath: string, localPath: string): Promise<void>;
14
+ ftpUpload(localPath: string, remotePath: string): Promise<void>;
15
+ ftpDelete(remotePath: string, isDirectory?: boolean): Promise<void>;
16
+ ftpCreateDirectory(remotePath: string): Promise<void>;
17
+ ftpChangeDirectory(remotePath: string): Promise<void>;
18
+ ftpGetCurrentDirectory(): Promise<string>;
10
19
  }
11
20
  declare const _default: typeof ReactNativeKookitModule;
12
21
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"ReactNativeKookitModule.web.d.ts","sourceRoot":"","sources":["../src/ReactNativeKookitModule.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAE,MAAM,MAAM,CAAC;AAEvD,OAAO,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAE1E,cAAM,uBAAwB,SAAQ,YAAY,CAAC,6BAA6B,CAAC;IAC/E,EAAE,SAAW;IACP,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAGjD,KAAK;IAGL,2BAA2B;IAO3B,4BAA4B;IAO5B,OAAO,CAAC,aAAa;CAgBtB;;AAED,wBAGE"}
1
+ {"version":3,"file":"ReactNativeKookitModule.web.d.ts","sourceRoot":"","sources":["../src/ReactNativeKookitModule.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAE,MAAM,MAAM,CAAC;AAEvD,OAAO,EACL,6BAA6B,EAC7B,mBAAmB,EACnB,WAAW,EACZ,MAAM,2BAA2B,CAAC;AAEnC,cAAM,uBAAwB,SAAQ,YAAY,CAAC,6BAA6B,CAAC;IAC/E,EAAE,SAAW;IACP,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAGjD,KAAK;IAGL,2BAA2B;IAO3B,4BAA4B;IAO5B,OAAO,CAAC,aAAa;IAmBf,UAAU,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtD,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAM9B,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAM9C,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjE,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/D,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnE,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrD,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrD,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC;CAKhD;;AAED,wBAGE"}
@@ -35,6 +35,34 @@ class ReactNativeKookitModule extends NativeModule {
35
35
  this.emit("onVolumeButtonPressed", { key: keyType });
36
36
  }
37
37
  }
38
+ // FTP Methods - Web implementations (limited functionality due to browser security)
39
+ async ftpConnect(config) {
40
+ throw new Error("FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.");
41
+ }
42
+ async ftpDisconnect() {
43
+ throw new Error("FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.");
44
+ }
45
+ async ftpList(path) {
46
+ throw new Error("FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.");
47
+ }
48
+ async ftpDownload(remotePath, localPath) {
49
+ throw new Error("FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.");
50
+ }
51
+ async ftpUpload(localPath, remotePath) {
52
+ throw new Error("FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.");
53
+ }
54
+ async ftpDelete(remotePath, isDirectory) {
55
+ throw new Error("FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.");
56
+ }
57
+ async ftpCreateDirectory(remotePath) {
58
+ throw new Error("FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.");
59
+ }
60
+ async ftpChangeDirectory(remotePath) {
61
+ throw new Error("FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.");
62
+ }
63
+ async ftpGetCurrentDirectory() {
64
+ throw new Error("FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.");
65
+ }
38
66
  }
39
67
  export default registerWebModule(ReactNativeKookitModule, "ReactNativeKookitModule");
40
68
  //# sourceMappingURL=ReactNativeKookitModule.web.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReactNativeKookitModule.web.js","sourceRoot":"","sources":["../src/ReactNativeKookitModule.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAIvD,MAAM,uBAAwB,SAAQ,YAA2C;IAC/E,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;IACb,KAAK,CAAC,aAAa,CAAC,KAAa;QAC/B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACnC,CAAC;IACD,KAAK;QACH,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IACD,2BAA2B;QACzB,kDAAkD;QAClD,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnD,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IACD,4BAA4B;QAC1B,uDAAuD;QACvD,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACxD,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAEO,aAAa,CAAC,KAAoB;QACxC,mEAAmE;QACnE,yEAAyE;QACzE,IAAI,OAAO,GAAyB,IAAI,CAAC;QAEzC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAC7C,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACtD,OAAO,GAAG,MAAM,CAAC;QACnB,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF;AAED,eAAe,iBAAiB,CAC9B,uBAAuB,EACvB,yBAAyB,CAC1B,CAAC","sourcesContent":["import { registerWebModule, NativeModule } from \"expo\";\n\nimport { ReactNativeKookitModuleEvents } from \"./ReactNativeKookit.types\";\n\nclass ReactNativeKookitModule extends NativeModule<ReactNativeKookitModuleEvents> {\n PI = Math.PI;\n async setValueAsync(value: string): Promise<void> {\n this.emit(\"onChange\", { value });\n }\n hello() {\n return \"Hello world! 👋\";\n }\n enableVolumeKeyInterception() {\n // Web implementation - listen for keyboard events\n if (typeof window !== \"undefined\") {\n this.handleKeyDown = this.handleKeyDown.bind(this);\n window.addEventListener(\"keydown\", this.handleKeyDown);\n }\n }\n disableVolumeKeyInterception() {\n // Web implementation - remove keyboard event listeners\n if (typeof window !== \"undefined\" && this.handleKeyDown) {\n window.removeEventListener(\"keydown\", this.handleKeyDown);\n }\n }\n\n private handleKeyDown(event: KeyboardEvent) {\n // On web, we can simulate volume key detection using specific keys\n // This is a fallback since web doesn't have direct access to volume keys\n let keyType: \"up\" | \"down\" | null = null;\n\n if (event.code === \"ArrowUp\" && event.altKey) {\n keyType = \"up\";\n } else if (event.code === \"ArrowDown\" && event.altKey) {\n keyType = \"down\";\n }\n\n if (keyType) {\n event.preventDefault();\n this.emit(\"onVolumeButtonPressed\", { key: keyType });\n }\n }\n}\n\nexport default registerWebModule(\n ReactNativeKookitModule,\n \"ReactNativeKookitModule\"\n);\n"]}
1
+ {"version":3,"file":"ReactNativeKookitModule.web.js","sourceRoot":"","sources":["../src/ReactNativeKookitModule.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAQvD,MAAM,uBAAwB,SAAQ,YAA2C;IAC/E,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;IACb,KAAK,CAAC,aAAa,CAAC,KAAa;QAC/B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACnC,CAAC;IACD,KAAK;QACH,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IACD,2BAA2B;QACzB,kDAAkD;QAClD,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnD,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IACD,4BAA4B;QAC1B,uDAAuD;QACvD,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACxD,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAEO,aAAa,CAAC,KAAoB;QACxC,mEAAmE;QACnE,yEAAyE;QACzE,IAAI,OAAO,GAAyB,IAAI,CAAC;QAEzC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YAC7C,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACtD,OAAO,GAAG,MAAM,CAAC;QACnB,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,oFAAoF;IAEpF,KAAK,CAAC,UAAU,CAAC,MAA2B;QAC1C,MAAM,IAAI,KAAK,CACb,0HAA0H,CAC3H,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,MAAM,IAAI,KAAK,CACb,0HAA0H,CAC3H,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAa;QACzB,MAAM,IAAI,KAAK,CACb,0HAA0H,CAC3H,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,UAAkB,EAAE,SAAiB;QACrD,MAAM,IAAI,KAAK,CACb,0HAA0H,CAC3H,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,SAAiB,EAAE,UAAkB;QACnD,MAAM,IAAI,KAAK,CACb,0HAA0H,CAC3H,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,UAAkB,EAAE,WAAqB;QACvD,MAAM,IAAI,KAAK,CACb,0HAA0H,CAC3H,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,UAAkB;QACzC,MAAM,IAAI,KAAK,CACb,0HAA0H,CAC3H,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,UAAkB;QACzC,MAAM,IAAI,KAAK,CACb,0HAA0H,CAC3H,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,sBAAsB;QAC1B,MAAM,IAAI,KAAK,CACb,0HAA0H,CAC3H,CAAC;IACJ,CAAC;CACF;AAED,eAAe,iBAAiB,CAC9B,uBAAuB,EACvB,yBAAyB,CAC1B,CAAC","sourcesContent":["import { registerWebModule, NativeModule } from \"expo\";\n\nimport {\n ReactNativeKookitModuleEvents,\n FtpConnectionConfig,\n FtpFileInfo,\n} from \"./ReactNativeKookit.types\";\n\nclass ReactNativeKookitModule extends NativeModule<ReactNativeKookitModuleEvents> {\n PI = Math.PI;\n async setValueAsync(value: string): Promise<void> {\n this.emit(\"onChange\", { value });\n }\n hello() {\n return \"Hello world! 👋\";\n }\n enableVolumeKeyInterception() {\n // Web implementation - listen for keyboard events\n if (typeof window !== \"undefined\") {\n this.handleKeyDown = this.handleKeyDown.bind(this);\n window.addEventListener(\"keydown\", this.handleKeyDown);\n }\n }\n disableVolumeKeyInterception() {\n // Web implementation - remove keyboard event listeners\n if (typeof window !== \"undefined\" && this.handleKeyDown) {\n window.removeEventListener(\"keydown\", this.handleKeyDown);\n }\n }\n\n private handleKeyDown(event: KeyboardEvent) {\n // On web, we can simulate volume key detection using specific keys\n // This is a fallback since web doesn't have direct access to volume keys\n let keyType: \"up\" | \"down\" | null = null;\n\n if (event.code === \"ArrowUp\" && event.altKey) {\n keyType = \"up\";\n } else if (event.code === \"ArrowDown\" && event.altKey) {\n keyType = \"down\";\n }\n\n if (keyType) {\n event.preventDefault();\n this.emit(\"onVolumeButtonPressed\", { key: keyType });\n }\n }\n\n // FTP Methods - Web implementations (limited functionality due to browser security)\n\n async ftpConnect(config: FtpConnectionConfig): Promise<void> {\n throw new Error(\n \"FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.\"\n );\n }\n\n async ftpDisconnect(): Promise<void> {\n throw new Error(\n \"FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.\"\n );\n }\n\n async ftpList(path?: string): Promise<FtpFileInfo[]> {\n throw new Error(\n \"FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.\"\n );\n }\n\n async ftpDownload(remotePath: string, localPath: string): Promise<void> {\n throw new Error(\n \"FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.\"\n );\n }\n\n async ftpUpload(localPath: string, remotePath: string): Promise<void> {\n throw new Error(\n \"FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.\"\n );\n }\n\n async ftpDelete(remotePath: string, isDirectory?: boolean): Promise<void> {\n throw new Error(\n \"FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.\"\n );\n }\n\n async ftpCreateDirectory(remotePath: string): Promise<void> {\n throw new Error(\n \"FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.\"\n );\n }\n\n async ftpChangeDirectory(remotePath: string): Promise<void> {\n throw new Error(\n \"FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.\"\n );\n }\n\n async ftpGetCurrentDirectory(): Promise<string> {\n throw new Error(\n \"FTP operations are not supported in web browsers due to security restrictions. Please use the mobile version of the app.\"\n );\n }\n}\n\nexport default registerWebModule(\n ReactNativeKookitModule,\n \"ReactNativeKookitModule\"\n);\n"]}
@@ -19,6 +19,9 @@ Pod::Spec.new do |s|
19
19
  s.static_framework = true
20
20
 
21
21
  s.dependency 'ExpoModulesCore'
22
+
23
+ # Add Network framework for FTP functionality
24
+ s.frameworks = 'Network'
22
25
 
23
26
  # Swift/Objective-C compatibility
24
27
  s.pod_target_xcconfig = {