@hot-updater/react-native 0.17.0 → 0.18.1
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/HotUpdater.podspec +7 -11
- package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +200 -0
- package/android/src/main/java/com/hotupdater/FileManagerService.kt +104 -0
- package/android/src/main/java/com/hotupdater/HotUpdater.kt +62 -305
- package/android/src/main/java/com/hotupdater/HotUpdaterFactory.kt +49 -0
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +176 -0
- package/android/src/main/java/com/hotupdater/HttpDownloadService.kt +98 -0
- package/android/src/main/java/com/hotupdater/VersionedPreferencesService.kt +69 -0
- package/android/src/main/java/com/hotupdater/ZipFileUnzipService.kt +52 -0
- package/android/src/newarch/HotUpdaterModule.kt +31 -34
- package/android/src/oldarch/HotUpdaterModule.kt +32 -34
- package/android/src/oldarch/HotUpdaterSpec.kt +2 -9
- package/ios/HotUpdater/Internal/BundleFileStorageService.swift +593 -0
- package/ios/HotUpdater/Internal/FileManagerService.swift +97 -0
- package/ios/HotUpdater/Internal/HotUpdater-Bridging-Header.h +8 -0
- package/ios/HotUpdater/Internal/HotUpdater.mm +241 -0
- package/ios/HotUpdater/Internal/HotUpdaterFactory.swift +24 -0
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +143 -0
- package/ios/HotUpdater/Internal/NotificationExtension.swift +6 -0
- package/ios/HotUpdater/Internal/SSZipArchiveUnzipService.swift +25 -0
- package/ios/HotUpdater/Internal/URLSessionDownloadService.swift +101 -0
- package/ios/HotUpdater/Internal/VersionedPreferencesService.swift +82 -0
- package/ios/HotUpdater/Public/HotUpdater.h +29 -0
- package/lib/commonjs/checkForUpdate.js +70 -0
- package/lib/commonjs/checkForUpdate.js.map +1 -0
- package/lib/commonjs/error.js +14 -0
- package/lib/commonjs/error.js.map +1 -0
- package/lib/commonjs/fetchUpdateInfo.js +74 -0
- package/lib/commonjs/fetchUpdateInfo.js.map +1 -0
- package/lib/commonjs/hooks/useEventCallback.js +17 -0
- package/lib/commonjs/hooks/useEventCallback.js.map +1 -0
- package/lib/commonjs/index.js +234 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/native.js +132 -0
- package/lib/commonjs/native.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/runUpdateProcess.js +69 -0
- package/lib/commonjs/runUpdateProcess.js.map +1 -0
- package/lib/commonjs/specs/NativeHotUpdater.js +9 -0
- package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -0
- package/lib/commonjs/store.js +48 -0
- package/lib/commonjs/store.js.map +1 -0
- package/lib/commonjs/wrap.js +98 -0
- package/lib/commonjs/wrap.js.map +1 -0
- package/lib/module/checkForUpdate.js +64 -0
- package/lib/module/checkForUpdate.js.map +1 -0
- package/lib/module/error.js +9 -0
- package/lib/module/error.js.map +1 -0
- package/lib/module/fetchUpdateInfo.js +69 -0
- package/lib/module/fetchUpdateInfo.js.map +1 -0
- package/lib/module/hooks/useEventCallback.js +13 -0
- package/lib/module/hooks/useEventCallback.js.map +1 -0
- package/lib/module/index.js +211 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/native.js +119 -0
- package/lib/module/native.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/runUpdateProcess.js +64 -0
- package/lib/module/runUpdateProcess.js.map +1 -0
- package/lib/module/specs/NativeHotUpdater.js +5 -0
- package/lib/module/specs/NativeHotUpdater.js.map +1 -0
- package/lib/module/store.js +42 -0
- package/lib/module/store.js.map +1 -0
- package/lib/module/wrap.js +94 -0
- package/lib/module/wrap.js.map +1 -0
- package/lib/typescript/commonjs/checkForUpdate.d.ts +22 -0
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -0
- package/{dist → lib/typescript/commonjs}/error.d.ts +1 -0
- package/lib/typescript/commonjs/error.d.ts.map +1 -0
- package/lib/typescript/commonjs/fetchUpdateInfo.d.ts +4 -0
- package/lib/typescript/commonjs/fetchUpdateInfo.d.ts.map +1 -0
- package/{dist → lib/typescript/commonjs}/hooks/useEventCallback.d.ts +1 -0
- package/lib/typescript/commonjs/hooks/useEventCallback.d.ts.map +1 -0
- package/{dist → lib/typescript/commonjs}/index.d.ts +38 -12
- package/lib/typescript/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/native.d.ts +64 -0
- package/lib/typescript/commonjs/native.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/{dist → lib/typescript/commonjs}/runUpdateProcess.d.ts +1 -0
- package/lib/typescript/commonjs/runUpdateProcess.d.ts.map +1 -0
- package/{dist → lib/typescript/commonjs}/specs/NativeHotUpdater.d.ts +8 -9
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -0
- package/{dist → lib/typescript/commonjs}/store.d.ts +1 -0
- package/lib/typescript/commonjs/store.d.ts.map +1 -0
- package/{dist → lib/typescript/commonjs}/wrap.d.ts +3 -2
- package/lib/typescript/commonjs/wrap.d.ts.map +1 -0
- package/lib/typescript/module/checkForUpdate.d.ts +22 -0
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -0
- package/lib/typescript/module/error.d.ts +4 -0
- package/lib/typescript/module/error.d.ts.map +1 -0
- package/lib/typescript/module/fetchUpdateInfo.d.ts +4 -0
- package/lib/typescript/module/fetchUpdateInfo.d.ts.map +1 -0
- package/lib/typescript/module/hooks/useEventCallback.d.ts +5 -0
- package/lib/typescript/module/hooks/useEventCallback.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +202 -0
- package/lib/typescript/module/index.d.ts.map +1 -0
- package/lib/typescript/module/native.d.ts +64 -0
- package/lib/typescript/module/native.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/runUpdateProcess.d.ts +49 -0
- package/lib/typescript/module/runUpdateProcess.d.ts.map +1 -0
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts +19 -0
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -0
- package/lib/typescript/module/store.d.ts +11 -0
- package/lib/typescript/module/store.d.ts.map +1 -0
- package/lib/typescript/module/wrap.d.ts +51 -0
- package/lib/typescript/module/wrap.d.ts.map +1 -0
- package/package.json +59 -30
- package/src/checkForUpdate.ts +59 -9
- package/src/fetchUpdateInfo.ts +40 -12
- package/src/index.ts +37 -11
- package/src/native.ts +87 -41
- package/src/runUpdateProcess.ts +2 -2
- package/src/specs/NativeHotUpdater.ts +8 -10
- package/src/wrap.tsx +9 -13
- package/android/generated/java/com/hotupdater/NativeHotUpdaterSpec.java +0 -93
- package/android/generated/jni/CMakeLists.txt +0 -36
- package/android/generated/jni/HotUpdaterSpec-generated.cpp +0 -68
- package/android/generated/jni/HotUpdaterSpec.h +0 -31
- package/android/generated/jni/react/renderer/components/HotUpdaterSpec/HotUpdaterSpecJSI-generated.cpp +0 -70
- package/android/generated/jni/react/renderer/components/HotUpdaterSpec/HotUpdaterSpecJSI.h +0 -121
- package/android/src/main/java/com/hotupdater/HotUpdaterPrefs.kt +0 -42
- package/dist/checkForUpdate.d.ts +0 -12
- package/dist/fetchUpdateInfo.d.ts +0 -3
- package/dist/index.js +0 -341
- package/dist/index.mjs +0 -301
- package/dist/native.d.ts +0 -41
- package/ios/HotUpdater/HotUpdater.h +0 -15
- package/ios/HotUpdater/HotUpdater.mm +0 -468
- package/ios/HotUpdater/HotUpdater.modulemap +0 -6
- package/ios/HotUpdater/HotUpdaterPrefs.h +0 -9
- package/ios/HotUpdater/HotUpdaterPrefs.mm +0 -45
- package/ios/generated/HotUpdaterSpec/HotUpdaterSpec-generated.mm +0 -81
- package/ios/generated/HotUpdaterSpec/HotUpdaterSpec.h +0 -112
- package/ios/generated/HotUpdaterSpecJSI-generated.cpp +0 -70
- package/ios/generated/HotUpdaterSpecJSI.h +0 -121
- package/react-native.config.js +0 -12
- package/src/global.d.ts +0 -3
package/HotUpdater.podspec
CHANGED
|
@@ -13,19 +13,15 @@ Pod::Spec.new do |s|
|
|
|
13
13
|
|
|
14
14
|
s.platforms = { :ios => min_ios_version_supported }
|
|
15
15
|
s.source = { :git => "https://github.com/gronxb/hot-updater.git", :tag => "#{s.version}" }
|
|
16
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
17
|
+
s.public_header_files = "ios/HotUpdater/Public/*.h"
|
|
18
|
+
s.private_header_files = "ios/HotUpdater/Internal/*.h"
|
|
19
|
+
s.exclude_files = "ios/HotUpdater/Package.swift", "ios/HotUpdater/Test/**/*.{swift,h,m,mm}"
|
|
16
20
|
|
|
17
21
|
s.pod_target_xcconfig = {
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
"DEFINES_MODULE" => "YES",
|
|
23
|
+
"OTHER_SWIFT_FLAGS" => "-enable-experimental-feature AccessLevelOnImport"
|
|
20
24
|
}
|
|
21
|
-
|
|
22
|
-
s.module_map = 'ios/HotUpdater/HotUpdater.modulemap'
|
|
23
|
-
|
|
24
|
-
s.source_files = "ios/**/*.{h,m,mm}"
|
|
25
|
-
if ENV['RCT_NEW_ARCH_ENABLED'] != '1' then
|
|
26
|
-
s.exclude_files = "ios/generated/**/*"
|
|
27
|
-
end
|
|
28
|
-
|
|
29
25
|
s.dependency "SSZipArchive", "~> 2.2.2"
|
|
30
26
|
|
|
31
27
|
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
|
@@ -36,7 +32,7 @@ Pod::Spec.new do |s|
|
|
|
36
32
|
s.dependency "React-Core"
|
|
37
33
|
|
|
38
34
|
# Don't install the dependencies when we run `pod install` in the old architecture.
|
|
39
|
-
if ENV[
|
|
35
|
+
if ENV["RCT_NEW_ARCH_ENABLED"] == "1" then
|
|
40
36
|
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
41
37
|
s.pod_target_xcconfig = {
|
|
42
38
|
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
package com.hotupdater
|
|
2
|
+
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import kotlinx.coroutines.Dispatchers
|
|
5
|
+
import kotlinx.coroutines.withContext
|
|
6
|
+
import java.io.File
|
|
7
|
+
import java.net.URL
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Interface for bundle storage operations
|
|
11
|
+
*/
|
|
12
|
+
interface BundleStorageService {
|
|
13
|
+
/**
|
|
14
|
+
* Sets the current bundle URL
|
|
15
|
+
* @param localPath Path to the bundle file (or null to reset)
|
|
16
|
+
* @return true if the operation was successful
|
|
17
|
+
*/
|
|
18
|
+
fun setBundleURL(localPath: String?): Boolean
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Gets the URL to the cached bundle file
|
|
22
|
+
* @return The path to the cached bundle or null if not found
|
|
23
|
+
*/
|
|
24
|
+
fun getCachedBundleURL(): String?
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Gets the URL to the fallback bundle included in the app
|
|
28
|
+
* @return The fallback bundle path
|
|
29
|
+
*/
|
|
30
|
+
fun getFallbackBundleURL(): String
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Gets the URL to the bundle file (cached or fallback)
|
|
34
|
+
* @return The path to the bundle file
|
|
35
|
+
*/
|
|
36
|
+
fun getBundleURL(): String
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Updates the bundle from the specified URL
|
|
40
|
+
* @param bundleId ID of the bundle to update
|
|
41
|
+
* @param fileUrl URL of the bundle file to download (or null to reset)
|
|
42
|
+
* @param progressCallback Callback for download progress updates
|
|
43
|
+
* @return true if the update was successful
|
|
44
|
+
*/
|
|
45
|
+
suspend fun updateBundle(
|
|
46
|
+
bundleId: String,
|
|
47
|
+
fileUrl: String?,
|
|
48
|
+
progressCallback: (Double) -> Unit,
|
|
49
|
+
): Boolean
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Implementation of BundleStorageService
|
|
54
|
+
*/
|
|
55
|
+
class BundleFileStorageService(
|
|
56
|
+
private val fileSystem: FileSystemService,
|
|
57
|
+
private val downloadService: DownloadService,
|
|
58
|
+
private val unzipService: UnzipService,
|
|
59
|
+
private val preferences: PreferencesService,
|
|
60
|
+
) : BundleStorageService {
|
|
61
|
+
override fun setBundleURL(localPath: String?): Boolean {
|
|
62
|
+
preferences.setItem("HotUpdaterBundleURL", localPath)
|
|
63
|
+
return true
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
override fun getCachedBundleURL(): String? {
|
|
67
|
+
val urlString = preferences.getItem("HotUpdaterBundleURL")
|
|
68
|
+
if (urlString.isNullOrEmpty()) {
|
|
69
|
+
return null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
val file = File(urlString)
|
|
73
|
+
if (!file.exists()) {
|
|
74
|
+
preferences.setItem("HotUpdaterBundleURL", null)
|
|
75
|
+
return null
|
|
76
|
+
}
|
|
77
|
+
return urlString
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
override fun getFallbackBundleURL(): String = "assets://index.android.bundle"
|
|
81
|
+
|
|
82
|
+
override fun getBundleURL(): String = getCachedBundleURL() ?: getFallbackBundleURL()
|
|
83
|
+
|
|
84
|
+
override suspend fun updateBundle(
|
|
85
|
+
bundleId: String,
|
|
86
|
+
fileUrl: String?,
|
|
87
|
+
progressCallback: (Double) -> Unit,
|
|
88
|
+
): Boolean {
|
|
89
|
+
Log.d("BundleStorage", "updateBundle bundleId $bundleId fileUrl $fileUrl")
|
|
90
|
+
|
|
91
|
+
if (fileUrl.isNullOrEmpty()) {
|
|
92
|
+
setBundleURL(null)
|
|
93
|
+
return true
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
val baseDir = fileSystem.getExternalFilesDir()
|
|
97
|
+
val bundleStoreDir = File(baseDir, "bundle-store")
|
|
98
|
+
if (!bundleStoreDir.exists()) {
|
|
99
|
+
bundleStoreDir.mkdirs()
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
val finalBundleDir = File(bundleStoreDir, bundleId)
|
|
103
|
+
if (finalBundleDir.exists()) {
|
|
104
|
+
Log.d("BundleStorage", "Bundle for bundleId $bundleId already exists. Using cached bundle.")
|
|
105
|
+
val existingIndexFile = finalBundleDir.walk().find { it.name == "index.android.bundle" }
|
|
106
|
+
if (existingIndexFile != null) {
|
|
107
|
+
finalBundleDir.setLastModified(System.currentTimeMillis())
|
|
108
|
+
setBundleURL(existingIndexFile.absolutePath)
|
|
109
|
+
cleanupOldBundles(bundleStoreDir)
|
|
110
|
+
return true
|
|
111
|
+
} else {
|
|
112
|
+
finalBundleDir.deleteRecursively()
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
val tempDir = File(baseDir, "bundle-temp")
|
|
117
|
+
if (tempDir.exists()) {
|
|
118
|
+
tempDir.deleteRecursively()
|
|
119
|
+
}
|
|
120
|
+
tempDir.mkdirs()
|
|
121
|
+
|
|
122
|
+
val tempZipFile = File(tempDir, "bundle.zip")
|
|
123
|
+
val extractedDir = File(tempDir, "extracted")
|
|
124
|
+
extractedDir.mkdirs()
|
|
125
|
+
|
|
126
|
+
return withContext(Dispatchers.IO) {
|
|
127
|
+
val downloadUrl = URL(fileUrl)
|
|
128
|
+
|
|
129
|
+
// Download the file
|
|
130
|
+
val downloadResult =
|
|
131
|
+
downloadService.downloadFile(
|
|
132
|
+
downloadUrl,
|
|
133
|
+
tempZipFile,
|
|
134
|
+
progressCallback,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
when (downloadResult) {
|
|
138
|
+
is DownloadResult.Error -> {
|
|
139
|
+
Log.d("BundleStorage", "Download failed: ${downloadResult.exception.message}")
|
|
140
|
+
tempDir.deleteRecursively()
|
|
141
|
+
return@withContext false
|
|
142
|
+
}
|
|
143
|
+
is DownloadResult.Success -> {
|
|
144
|
+
// Extract the zip file
|
|
145
|
+
if (!unzipService.extractZipFile(tempZipFile.absolutePath, extractedDir.absolutePath)) {
|
|
146
|
+
Log.d("BundleStorage", "Failed to extract zip file.")
|
|
147
|
+
tempDir.deleteRecursively()
|
|
148
|
+
return@withContext false
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Find the bundle file
|
|
152
|
+
val indexFileExtracted = extractedDir.walk().find { it.name == "index.android.bundle" }
|
|
153
|
+
if (indexFileExtracted == null) {
|
|
154
|
+
Log.d("BundleStorage", "index.android.bundle not found in extracted files.")
|
|
155
|
+
tempDir.deleteRecursively()
|
|
156
|
+
return@withContext false
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Move to final location
|
|
160
|
+
if (finalBundleDir.exists()) {
|
|
161
|
+
finalBundleDir.deleteRecursively()
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (!fileSystem.moveItem(extractedDir.absolutePath, finalBundleDir.absolutePath)) {
|
|
165
|
+
fileSystem.copyItem(extractedDir.absolutePath, finalBundleDir.absolutePath)
|
|
166
|
+
extractedDir.deleteRecursively()
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
val finalIndexFile = finalBundleDir.walk().find { it.name == "index.android.bundle" }
|
|
170
|
+
if (finalIndexFile == null) {
|
|
171
|
+
Log.d("BundleStorage", "index.android.bundle not found in final directory.")
|
|
172
|
+
tempDir.deleteRecursively()
|
|
173
|
+
return@withContext false
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
finalBundleDir.setLastModified(System.currentTimeMillis())
|
|
177
|
+
val bundlePath = finalIndexFile.absolutePath
|
|
178
|
+
Log.d("BundleStorage", "Setting bundle URL: $bundlePath")
|
|
179
|
+
setBundleURL(bundlePath)
|
|
180
|
+
cleanupOldBundles(bundleStoreDir)
|
|
181
|
+
tempDir.deleteRecursively()
|
|
182
|
+
|
|
183
|
+
Log.d("BundleStorage", "Downloaded and extracted file successfully.")
|
|
184
|
+
return@withContext true
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private fun cleanupOldBundles(bundleStoreDir: File) {
|
|
191
|
+
val bundles = bundleStoreDir.listFiles { file -> file.isDirectory }?.toList() ?: return
|
|
192
|
+
val sortedBundles = bundles.sortedByDescending { it.lastModified() }
|
|
193
|
+
if (sortedBundles.size > 1) {
|
|
194
|
+
sortedBundles.drop(1).forEach { oldBundle ->
|
|
195
|
+
Log.d("BundleStorage", "Removing old bundle: ${oldBundle.name}")
|
|
196
|
+
oldBundle.deleteRecursively()
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
package com.hotupdater
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import java.io.File
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Interface for file system operations
|
|
8
|
+
*/
|
|
9
|
+
interface FileSystemService {
|
|
10
|
+
/**
|
|
11
|
+
* Checks if a file exists at the given path
|
|
12
|
+
*/
|
|
13
|
+
fun fileExists(path: String): Boolean
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates directory at the given path, including any necessary parent directories
|
|
17
|
+
*/
|
|
18
|
+
fun createDirectory(path: String): Boolean
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Removes a file or directory at the given path
|
|
22
|
+
*/
|
|
23
|
+
fun removeItem(path: String): Boolean
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Moves a file or directory from source path to destination path
|
|
27
|
+
*/
|
|
28
|
+
fun moveItem(
|
|
29
|
+
sourcePath: String,
|
|
30
|
+
destinationPath: String,
|
|
31
|
+
): Boolean
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Copies a file or directory from source path to destination path
|
|
35
|
+
*/
|
|
36
|
+
fun copyItem(
|
|
37
|
+
sourcePath: String,
|
|
38
|
+
destinationPath: String,
|
|
39
|
+
): Boolean
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Lists the contents of a directory
|
|
43
|
+
*/
|
|
44
|
+
fun contentsOfDirectory(path: String): List<String>
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Gets the external files directory for the application
|
|
48
|
+
*/
|
|
49
|
+
fun getExternalFilesDir(): File?
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Implementation of FileSystemService using standard File API
|
|
54
|
+
*/
|
|
55
|
+
class FileManagerService(
|
|
56
|
+
private val context: Context,
|
|
57
|
+
) : FileSystemService {
|
|
58
|
+
override fun fileExists(path: String): Boolean = File(path).exists()
|
|
59
|
+
|
|
60
|
+
override fun createDirectory(path: String): Boolean = File(path).mkdirs()
|
|
61
|
+
|
|
62
|
+
override fun removeItem(path: String): Boolean = File(path).deleteRecursively()
|
|
63
|
+
|
|
64
|
+
override fun moveItem(
|
|
65
|
+
sourcePath: String,
|
|
66
|
+
destinationPath: String,
|
|
67
|
+
): Boolean {
|
|
68
|
+
val source = File(sourcePath)
|
|
69
|
+
val destination = File(destinationPath)
|
|
70
|
+
|
|
71
|
+
return try {
|
|
72
|
+
if (destination.exists()) {
|
|
73
|
+
destination.deleteRecursively()
|
|
74
|
+
}
|
|
75
|
+
source.renameTo(destination)
|
|
76
|
+
} catch (e: Exception) {
|
|
77
|
+
false
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
override fun copyItem(
|
|
82
|
+
sourcePath: String,
|
|
83
|
+
destinationPath: String,
|
|
84
|
+
): Boolean {
|
|
85
|
+
val source = File(sourcePath)
|
|
86
|
+
val destination = File(destinationPath)
|
|
87
|
+
|
|
88
|
+
return try {
|
|
89
|
+
if (destination.exists()) {
|
|
90
|
+
destination.deleteRecursively()
|
|
91
|
+
}
|
|
92
|
+
source.copyRecursively(target = destination, overwrite = true)
|
|
93
|
+
} catch (e: Exception) {
|
|
94
|
+
false
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
override fun contentsOfDirectory(path: String): List<String> {
|
|
99
|
+
val directory = File(path)
|
|
100
|
+
return directory.listFiles()?.map { it.name } ?: listOf()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
override fun getExternalFilesDir(): File? = context.getExternalFilesDir(null)
|
|
104
|
+
}
|