react-native-nitro-unzip 0.1.0

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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +107 -0
  3. package/android/CMakeLists.txt +16 -0
  4. package/android/build.gradle +70 -0
  5. package/android/src/main/cpp/cpp-adapter.cpp +6 -0
  6. package/android/src/main/java/com/margelo/nitro/unzip/HybridUnzip.kt +29 -0
  7. package/android/src/main/java/com/margelo/nitro/unzip/HybridUnzipTask.kt +256 -0
  8. package/android/src/main/java/com/margelo/nitro/unzip/HybridZipTask.kt +157 -0
  9. package/ios/HybridUnzip.swift +33 -0
  10. package/ios/HybridUnzipTask.swift +238 -0
  11. package/ios/HybridZipTask.swift +266 -0
  12. package/lib/commonjs/index.js +31 -0
  13. package/lib/commonjs/index.js.map +1 -0
  14. package/lib/commonjs/specs/Unzip.nitro.js +6 -0
  15. package/lib/commonjs/specs/Unzip.nitro.js.map +1 -0
  16. package/lib/module/index.js +27 -0
  17. package/lib/module/index.js.map +1 -0
  18. package/lib/module/package.json +1 -0
  19. package/lib/module/specs/Unzip.nitro.js +4 -0
  20. package/lib/module/specs/Unzip.nitro.js.map +1 -0
  21. package/lib/typescript/index.d.ts +24 -0
  22. package/lib/typescript/index.d.ts.map +1 -0
  23. package/lib/typescript/specs/Unzip.nitro.d.ts +170 -0
  24. package/lib/typescript/specs/Unzip.nitro.d.ts.map +1 -0
  25. package/nitro.json +26 -0
  26. package/nitrogen/generated/.gitattributes +1 -0
  27. package/nitrogen/generated/android/NitroUnzip+autolinking.cmake +85 -0
  28. package/nitrogen/generated/android/NitroUnzip+autolinking.gradle +27 -0
  29. package/nitrogen/generated/android/NitroUnzipOnLoad.cpp +71 -0
  30. package/nitrogen/generated/android/NitroUnzipOnLoad.hpp +34 -0
  31. package/nitrogen/generated/android/c++/JFunc_void_UnzipProgress.hpp +77 -0
  32. package/nitrogen/generated/android/c++/JFunc_void_ZipProgress.hpp +77 -0
  33. package/nitrogen/generated/android/c++/JHybridUnzipSpec.cpp +82 -0
  34. package/nitrogen/generated/android/c++/JHybridUnzipSpec.hpp +69 -0
  35. package/nitrogen/generated/android/c++/JHybridUnzipTaskSpec.cpp +94 -0
  36. package/nitrogen/generated/android/c++/JHybridUnzipTaskSpec.hpp +68 -0
  37. package/nitrogen/generated/android/c++/JHybridZipTaskSpec.cpp +94 -0
  38. package/nitrogen/generated/android/c++/JHybridZipTaskSpec.hpp +68 -0
  39. package/nitrogen/generated/android/c++/JUnzipProgress.hpp +73 -0
  40. package/nitrogen/generated/android/c++/JUnzipResult.hpp +73 -0
  41. package/nitrogen/generated/android/c++/JZipProgress.hpp +69 -0
  42. package/nitrogen/generated/android/c++/JZipResult.hpp +73 -0
  43. package/nitrogen/generated/android/kotlin/com/margelo/nitro/unzip/Func_void_UnzipProgress.kt +80 -0
  44. package/nitrogen/generated/android/kotlin/com/margelo/nitro/unzip/Func_void_ZipProgress.kt +80 -0
  45. package/nitrogen/generated/android/kotlin/com/margelo/nitro/unzip/HybridUnzipSpec.kt +69 -0
  46. package/nitrogen/generated/android/kotlin/com/margelo/nitro/unzip/HybridUnzipTaskSpec.kt +73 -0
  47. package/nitrogen/generated/android/kotlin/com/margelo/nitro/unzip/HybridZipTaskSpec.kt +73 -0
  48. package/nitrogen/generated/android/kotlin/com/margelo/nitro/unzip/NitroUnzipOnLoad.kt +35 -0
  49. package/nitrogen/generated/android/kotlin/com/margelo/nitro/unzip/UnzipProgress.kt +50 -0
  50. package/nitrogen/generated/android/kotlin/com/margelo/nitro/unzip/UnzipResult.kt +50 -0
  51. package/nitrogen/generated/android/kotlin/com/margelo/nitro/unzip/ZipProgress.kt +47 -0
  52. package/nitrogen/generated/android/kotlin/com/margelo/nitro/unzip/ZipResult.kt +50 -0
  53. package/nitrogen/generated/ios/NitroUnzip+autolinking.rb +60 -0
  54. package/nitrogen/generated/ios/NitroUnzip-Swift-Cxx-Bridge.cpp +107 -0
  55. package/nitrogen/generated/ios/NitroUnzip-Swift-Cxx-Bridge.hpp +270 -0
  56. package/nitrogen/generated/ios/NitroUnzip-Swift-Cxx-Umbrella.hpp +68 -0
  57. package/nitrogen/generated/ios/NitroUnzipAutolinking.mm +49 -0
  58. package/nitrogen/generated/ios/NitroUnzipAutolinking.swift +50 -0
  59. package/nitrogen/generated/ios/c++/HybridUnzipSpecSwift.cpp +11 -0
  60. package/nitrogen/generated/ios/c++/HybridUnzipSpecSwift.hpp +112 -0
  61. package/nitrogen/generated/ios/c++/HybridUnzipTaskSpecSwift.cpp +11 -0
  62. package/nitrogen/generated/ios/c++/HybridUnzipTaskSpecSwift.hpp +104 -0
  63. package/nitrogen/generated/ios/c++/HybridZipTaskSpecSwift.cpp +11 -0
  64. package/nitrogen/generated/ios/c++/HybridZipTaskSpecSwift.hpp +104 -0
  65. package/nitrogen/generated/ios/swift/Func_void_UnzipProgress.swift +46 -0
  66. package/nitrogen/generated/ios/swift/Func_void_UnzipResult.swift +46 -0
  67. package/nitrogen/generated/ios/swift/Func_void_ZipProgress.swift +46 -0
  68. package/nitrogen/generated/ios/swift/Func_void_ZipResult.swift +46 -0
  69. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
  70. package/nitrogen/generated/ios/swift/HybridUnzipSpec.swift +58 -0
  71. package/nitrogen/generated/ios/swift/HybridUnzipSpec_cxx.swift +186 -0
  72. package/nitrogen/generated/ios/swift/HybridUnzipTaskSpec.swift +57 -0
  73. package/nitrogen/generated/ios/swift/HybridUnzipTaskSpec_cxx.swift +177 -0
  74. package/nitrogen/generated/ios/swift/HybridZipTaskSpec.swift +57 -0
  75. package/nitrogen/generated/ios/swift/HybridZipTaskSpec_cxx.swift +177 -0
  76. package/nitrogen/generated/ios/swift/UnzipProgress.swift +49 -0
  77. package/nitrogen/generated/ios/swift/UnzipResult.swift +49 -0
  78. package/nitrogen/generated/ios/swift/ZipProgress.swift +44 -0
  79. package/nitrogen/generated/ios/swift/ZipResult.swift +49 -0
  80. package/nitrogen/generated/shared/c++/HybridUnzipSpec.cpp +24 -0
  81. package/nitrogen/generated/shared/c++/HybridUnzipSpec.hpp +71 -0
  82. package/nitrogen/generated/shared/c++/HybridUnzipTaskSpec.cpp +24 -0
  83. package/nitrogen/generated/shared/c++/HybridUnzipTaskSpec.hpp +71 -0
  84. package/nitrogen/generated/shared/c++/HybridZipTaskSpec.cpp +24 -0
  85. package/nitrogen/generated/shared/c++/HybridZipTaskSpec.hpp +71 -0
  86. package/nitrogen/generated/shared/c++/UnzipProgress.hpp +99 -0
  87. package/nitrogen/generated/shared/c++/UnzipResult.hpp +99 -0
  88. package/nitrogen/generated/shared/c++/ZipProgress.hpp +95 -0
  89. package/nitrogen/generated/shared/c++/ZipResult.hpp +99 -0
  90. package/package.json +165 -0
  91. package/react-native-nitro-unzip.podspec +24 -0
  92. package/src/index.ts +36 -0
  93. package/src/specs/Unzip.nitro.ts +193 -0
@@ -0,0 +1,238 @@
1
+ import Foundation
2
+ import NitroModules
3
+ import SSZipArchive
4
+ import UIKit
5
+
6
+ /**
7
+ * A single extraction operation as a proper HybridObject instance.
8
+ *
9
+ * Each call to `HybridUnzip.extract()` creates one of these.
10
+ * The caller can observe progress, cancel, or await the result — all scoped
11
+ * to this specific extraction, no global event emitters needed.
12
+ *
13
+ * Performance (350MB archive, 10k+ files):
14
+ * - Speed: 400-500 files/second
15
+ * - Memory: <30MB peak via SSZipArchive streaming
16
+ * - Background task support for continued extraction when app is backgrounded
17
+ */
18
+ class HybridUnzipTask: HybridUnzipTaskSpec {
19
+ // MARK: - HybridObject requirements
20
+
21
+ var hybridContext = margelo.nitro.HybridContext()
22
+ var memorySize: Int { return getSizeOf(self) }
23
+
24
+ // MARK: - Spec properties
25
+
26
+ let taskId: String
27
+
28
+ // MARK: - Internal state
29
+
30
+ private let zipPath: String
31
+ private let destinationPath: String
32
+ private let password: String?
33
+ private var progressCallback: ((_ progress: UnzipProgress) -> Void)?
34
+ private var shouldCancel = false
35
+ private var backgroundTaskId: UIBackgroundTaskIdentifier = .invalid
36
+ private let lock = NSLock()
37
+ private let progressThrottle: TimeInterval = 1.0
38
+
39
+ // Promise resolution — held until extraction completes or fails
40
+ private var resolvePromise: ((UnzipResult) -> Void)?
41
+ private var rejectPromise: ((Error) -> Void)?
42
+ private var hasStarted = false
43
+
44
+ init(zipPath: String, destinationPath: String, password: String? = nil) {
45
+ self.taskId = "unzip_\(ProcessInfo.processInfo.globallyUniqueString)"
46
+ self.zipPath = zipPath
47
+ self.destinationPath = destinationPath
48
+ self.password = password
49
+ super.init()
50
+ }
51
+
52
+ // MARK: - Spec methods
53
+
54
+ func onProgress(callback: @escaping (_ progress: UnzipProgress) -> Void) throws {
55
+ lock.lock()
56
+ self.progressCallback = callback
57
+ lock.unlock()
58
+ }
59
+
60
+ func cancel() throws {
61
+ lock.lock()
62
+ shouldCancel = true
63
+ lock.unlock()
64
+ }
65
+
66
+ func await() throws -> Promise<UnzipResult> {
67
+ return Promise.async { [self] resolve, reject in
68
+ self.lock.lock()
69
+ self.resolvePromise = resolve
70
+ self.rejectPromise = reject
71
+
72
+ guard !self.hasStarted else {
73
+ self.lock.unlock()
74
+ return
75
+ }
76
+ self.hasStarted = true
77
+ self.lock.unlock()
78
+
79
+ self.startExtraction()
80
+ }
81
+ }
82
+
83
+ // MARK: - Extraction
84
+
85
+ private func startExtraction() {
86
+ beginBackgroundTask()
87
+
88
+ DispatchQueue.global(qos: .userInitiated).async { [self] in
89
+ do {
90
+ let result = try self.extract()
91
+ self.endBackgroundTask()
92
+ self.lock.lock()
93
+ let resolve = self.resolvePromise
94
+ self.lock.unlock()
95
+ resolve?(result)
96
+ } catch {
97
+ self.endBackgroundTask()
98
+ self.lock.lock()
99
+ let reject = self.rejectPromise
100
+ self.lock.unlock()
101
+ reject?(error)
102
+ }
103
+ }
104
+ }
105
+
106
+ private func extract() throws -> UnzipResult {
107
+ let startTime = Date()
108
+ let fileManager = FileManager.default
109
+
110
+ // Normalise file:// URIs to filesystem paths
111
+ let cleanZip = zipPath.replacingOccurrences(of: "file://", with: "")
112
+ let cleanDest = destinationPath.replacingOccurrences(of: "file://", with: "")
113
+
114
+ // Ensure destination exists
115
+ if !fileManager.fileExists(atPath: cleanDest) {
116
+ try fileManager.createDirectory(
117
+ atPath: cleanDest,
118
+ withIntermediateDirectories: true,
119
+ attributes: nil
120
+ )
121
+ }
122
+
123
+ // Verify source exists
124
+ guard fileManager.fileExists(atPath: cleanZip) else {
125
+ throw NSError(
126
+ domain: "NitroUnzip",
127
+ code: 1,
128
+ userInfo: [NSLocalizedDescriptionKey: "Source ZIP file not found: \(cleanZip)"]
129
+ )
130
+ }
131
+
132
+ var extractedFiles = 0
133
+ var lastProgressUpdate = Date()
134
+
135
+ // SSZipArchive progress handler — called per file
136
+ let progressHandler: (String, unz_file_info, Int, Int) -> Void = { [weak self] _, _, entryNumber, total in
137
+ guard let self = self else { return }
138
+
139
+ // Check cancellation
140
+ self.lock.lock()
141
+ let cancelled = self.shouldCancel
142
+ let callback = self.progressCallback
143
+ self.lock.unlock()
144
+ if cancelled { return }
145
+
146
+ extractedFiles = entryNumber
147
+
148
+ // Throttle progress updates
149
+ let now = Date()
150
+ let shouldUpdate = now.timeIntervalSince(lastProgressUpdate) >= self.progressThrottle
151
+ || entryNumber == total
152
+ || entryNumber == 1
153
+
154
+ if shouldUpdate, let callback = callback {
155
+ let progress = total > 0 ? Double(entryNumber) / Double(total) : 0
156
+ let elapsed = now.timeIntervalSince(startTime)
157
+ let speed = elapsed > 0 ? Double(entryNumber) / elapsed : 0
158
+
159
+ callback(UnzipProgress(
160
+ extractedFiles: Double(entryNumber),
161
+ totalFiles: Double(total),
162
+ progress: progress,
163
+ speed: speed,
164
+ processedBytes: 0
165
+ ))
166
+ lastProgressUpdate = now
167
+ }
168
+ }
169
+
170
+ // Run extraction
171
+ let success = SSZipArchive.unzipFile(
172
+ atPath: cleanZip,
173
+ toDestination: cleanDest,
174
+ overwrite: true,
175
+ password: password,
176
+ progressHandler: progressHandler,
177
+ completionHandler: nil
178
+ )
179
+
180
+ // Check cancellation
181
+ lock.lock()
182
+ let wasCancelled = shouldCancel
183
+ lock.unlock()
184
+
185
+ if wasCancelled {
186
+ throw NSError(
187
+ domain: "NitroUnzip",
188
+ code: 2,
189
+ userInfo: [NSLocalizedDescriptionKey: "Extraction cancelled"]
190
+ )
191
+ }
192
+
193
+ guard success else {
194
+ throw NSError(
195
+ domain: "NitroUnzip",
196
+ code: 3,
197
+ userInfo: [NSLocalizedDescriptionKey: "SSZipArchive extraction failed"]
198
+ )
199
+ }
200
+
201
+ let duration = Date().timeIntervalSince(startTime) * 1000 // ms
202
+ let finalCount = extractedFiles
203
+ let averageSpeed = duration > 0 ? Double(finalCount) / (duration / 1000) : 0
204
+
205
+ return UnzipResult(
206
+ success: true,
207
+ extractedFiles: Double(finalCount),
208
+ duration: duration,
209
+ averageSpeed: averageSpeed,
210
+ totalBytes: 0
211
+ )
212
+ }
213
+
214
+ // MARK: - Background task management
215
+
216
+ private func beginBackgroundTask() {
217
+ let bgId = UIApplication.shared.beginBackgroundTask(withName: "NitroUnzip-\(taskId)") { [weak self] in
218
+ self?.lock.lock()
219
+ self?.shouldCancel = true
220
+ self?.lock.unlock()
221
+ self?.endBackgroundTask()
222
+ }
223
+ lock.lock()
224
+ backgroundTaskId = bgId
225
+ lock.unlock()
226
+ }
227
+
228
+ private func endBackgroundTask() {
229
+ lock.lock()
230
+ let bgId = backgroundTaskId
231
+ backgroundTaskId = .invalid
232
+ lock.unlock()
233
+
234
+ if bgId != .invalid {
235
+ UIApplication.shared.endBackgroundTask(bgId)
236
+ }
237
+ }
238
+ }
@@ -0,0 +1,266 @@
1
+ import Foundation
2
+ import NitroModules
3
+ import SSZipArchive
4
+ import UIKit
5
+
6
+ /**
7
+ * A single zip creation operation as a proper HybridObject instance.
8
+ *
9
+ * Each call to `HybridUnzip.zip()` creates one of these.
10
+ * The caller can observe progress, cancel, or await the result.
11
+ */
12
+ class HybridZipTask: HybridZipTaskSpec {
13
+ // MARK: - HybridObject requirements
14
+
15
+ var hybridContext = margelo.nitro.HybridContext()
16
+ var memorySize: Int { return getSizeOf(self) }
17
+
18
+ // MARK: - Spec properties
19
+
20
+ let taskId: String
21
+
22
+ // MARK: - Internal state
23
+
24
+ private let sourcePath: String
25
+ private let destinationZipPath: String
26
+ private let password: String?
27
+ private var progressCallback: ((_ progress: ZipProgress) -> Void)?
28
+ private var shouldCancel = false
29
+ private var backgroundTaskId: UIBackgroundTaskIdentifier = .invalid
30
+ private let lock = NSLock()
31
+ private let progressThrottle: TimeInterval = 1.0
32
+
33
+ private var resolvePromise: ((ZipResult) -> Void)?
34
+ private var rejectPromise: ((Error) -> Void)?
35
+ private var hasStarted = false
36
+
37
+ init(sourcePath: String, destinationZipPath: String, password: String? = nil) {
38
+ self.taskId = "zip_\(ProcessInfo.processInfo.globallyUniqueString)"
39
+ self.sourcePath = sourcePath
40
+ self.destinationZipPath = destinationZipPath
41
+ self.password = password
42
+ super.init()
43
+ }
44
+
45
+ // MARK: - Spec methods
46
+
47
+ func onProgress(callback: @escaping (_ progress: ZipProgress) -> Void) throws {
48
+ lock.lock()
49
+ self.progressCallback = callback
50
+ lock.unlock()
51
+ }
52
+
53
+ func cancel() throws {
54
+ lock.lock()
55
+ shouldCancel = true
56
+ lock.unlock()
57
+ }
58
+
59
+ func await() throws -> Promise<ZipResult> {
60
+ return Promise.async { [self] resolve, reject in
61
+ self.lock.lock()
62
+ self.resolvePromise = resolve
63
+ self.rejectPromise = reject
64
+
65
+ guard !self.hasStarted else {
66
+ self.lock.unlock()
67
+ return
68
+ }
69
+ self.hasStarted = true
70
+ self.lock.unlock()
71
+
72
+ self.startCompression()
73
+ }
74
+ }
75
+
76
+ // MARK: - Compression
77
+
78
+ private func startCompression() {
79
+ beginBackgroundTask()
80
+
81
+ DispatchQueue.global(qos: .userInitiated).async { [self] in
82
+ do {
83
+ let result = try self.compress()
84
+ self.endBackgroundTask()
85
+ self.lock.lock()
86
+ let resolve = self.resolvePromise
87
+ self.lock.unlock()
88
+ resolve?(result)
89
+ } catch {
90
+ self.endBackgroundTask()
91
+ self.lock.lock()
92
+ let reject = self.rejectPromise
93
+ self.lock.unlock()
94
+ reject?(error)
95
+ }
96
+ }
97
+ }
98
+
99
+ private func compress() throws -> ZipResult {
100
+ let startTime = Date()
101
+ let fileManager = FileManager.default
102
+
103
+ let cleanSource = sourcePath.replacingOccurrences(of: "file://", with: "")
104
+ let cleanDest = destinationZipPath.replacingOccurrences(of: "file://", with: "")
105
+
106
+ guard fileManager.fileExists(atPath: cleanSource) else {
107
+ throw NSError(
108
+ domain: "NitroUnzip",
109
+ code: 1,
110
+ userInfo: [NSLocalizedDescriptionKey: "Source path not found: \(cleanSource)"]
111
+ )
112
+ }
113
+
114
+ // Collect all files to compress for progress tracking
115
+ var allFiles: [String] = []
116
+ if var enumerator = fileManager.enumerator(atPath: cleanSource) {
117
+ while let file = enumerator.nextObject() as? String {
118
+ let fullPath = (cleanSource as NSString).appendingPathComponent(file)
119
+ var isDir: ObjCBool = false
120
+ if fileManager.fileExists(atPath: fullPath, isDirectory: &isDir), !isDir.boolValue {
121
+ allFiles.append(file)
122
+ }
123
+ }
124
+ }
125
+
126
+ let totalFiles = allFiles.count
127
+ var compressedCount = 0
128
+ var lastProgressUpdate = Date()
129
+
130
+ // SSZipArchive createZipFile with progress
131
+ let success: Bool
132
+ if let password = password {
133
+ success = SSZipArchive.createZipFile(
134
+ atPath: cleanDest,
135
+ withContentsOfDirectory: cleanSource,
136
+ keepParentDirectory: false,
137
+ withPassword: password,
138
+ andProgressHandler: { [weak self] entryNumber, total in
139
+ self?.handleZipProgress(
140
+ entryNumber: entryNumber,
141
+ total: total,
142
+ startTime: startTime,
143
+ compressedCount: &compressedCount,
144
+ lastProgressUpdate: &lastProgressUpdate
145
+ )
146
+ }
147
+ )
148
+ } else {
149
+ success = SSZipArchive.createZipFile(
150
+ atPath: cleanDest,
151
+ withContentsOfDirectory: cleanSource,
152
+ keepParentDirectory: false,
153
+ compressionLevel: -1,
154
+ password: nil,
155
+ aes: false,
156
+ progressHandler: { [weak self] entryNumber, total in
157
+ self?.handleZipProgress(
158
+ entryNumber: entryNumber,
159
+ total: total,
160
+ startTime: startTime,
161
+ compressedCount: &compressedCount,
162
+ lastProgressUpdate: &lastProgressUpdate
163
+ )
164
+ }
165
+ )
166
+ }
167
+
168
+ lock.lock()
169
+ let wasCancelled = shouldCancel
170
+ lock.unlock()
171
+
172
+ if wasCancelled {
173
+ // Clean up partial zip file
174
+ try? fileManager.removeItem(atPath: cleanDest)
175
+ throw NSError(
176
+ domain: "NitroUnzip",
177
+ code: 2,
178
+ userInfo: [NSLocalizedDescriptionKey: "Zip creation cancelled"]
179
+ )
180
+ }
181
+
182
+ guard success else {
183
+ throw NSError(
184
+ domain: "NitroUnzip",
185
+ code: 3,
186
+ userInfo: [NSLocalizedDescriptionKey: "SSZipArchive zip creation failed"]
187
+ )
188
+ }
189
+
190
+ let duration = Date().timeIntervalSince(startTime) * 1000
191
+ let finalCount = totalFiles
192
+ let averageSpeed = duration > 0 ? Double(finalCount) / (duration / 1000) : 0
193
+
194
+ // Get output file size
195
+ let attrs = try? fileManager.attributesOfItem(atPath: cleanDest)
196
+ let totalBytes = (attrs?[.size] as? Double) ?? 0
197
+
198
+ return ZipResult(
199
+ success: true,
200
+ compressedFiles: Double(finalCount),
201
+ duration: duration,
202
+ averageSpeed: averageSpeed,
203
+ totalBytes: totalBytes
204
+ )
205
+ }
206
+
207
+ private func handleZipProgress(
208
+ entryNumber: UInt,
209
+ total: UInt,
210
+ startTime: Date,
211
+ compressedCount: inout Int,
212
+ lastProgressUpdate: inout Date
213
+ ) {
214
+ lock.lock()
215
+ let cancelled = shouldCancel
216
+ let callback = progressCallback
217
+ lock.unlock()
218
+ if cancelled { return }
219
+
220
+ compressedCount = Int(entryNumber)
221
+
222
+ let now = Date()
223
+ let shouldUpdate = now.timeIntervalSince(lastProgressUpdate) >= progressThrottle
224
+ || entryNumber == total
225
+ || entryNumber == 1
226
+
227
+ if shouldUpdate, let callback = callback {
228
+ let progress = total > 0 ? Double(entryNumber) / Double(total) : 0
229
+ let elapsed = now.timeIntervalSince(startTime)
230
+ let speed = elapsed > 0 ? Double(entryNumber) / elapsed : 0
231
+
232
+ callback(ZipProgress(
233
+ compressedFiles: Double(entryNumber),
234
+ totalFiles: Double(total),
235
+ progress: progress,
236
+ speed: speed
237
+ ))
238
+ lastProgressUpdate = now
239
+ }
240
+ }
241
+
242
+ // MARK: - Background task management
243
+
244
+ private func beginBackgroundTask() {
245
+ let bgId = UIApplication.shared.beginBackgroundTask(withName: "NitroZip-\(taskId)") { [weak self] in
246
+ self?.lock.lock()
247
+ self?.shouldCancel = true
248
+ self?.lock.unlock()
249
+ self?.endBackgroundTask()
250
+ }
251
+ lock.lock()
252
+ backgroundTaskId = bgId
253
+ lock.unlock()
254
+ }
255
+
256
+ private func endBackgroundTask() {
257
+ lock.lock()
258
+ let bgId = backgroundTaskId
259
+ backgroundTaskId = .invalid
260
+ lock.unlock()
261
+
262
+ if bgId != .invalid {
263
+ UIApplication.shared.endBackgroundTask(bgId)
264
+ }
265
+ }
266
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getUnzip = getUnzip;
7
+ var _reactNativeNitroModules = require("react-native-nitro-modules");
8
+ /**
9
+ * Create an `Unzip` instance. Each instance is a factory for
10
+ * extraction and compression tasks.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { getUnzip } from 'react-native-nitro-unzip'
15
+ *
16
+ * const unzip = getUnzip()
17
+ *
18
+ * // Extract
19
+ * const task = unzip.extract('/path/to/archive.zip', '/output')
20
+ * task.onProgress((p) => console.log(`${(p.progress * 100).toFixed(0)}%`))
21
+ * const result = await task.await()
22
+ *
23
+ * // Zip
24
+ * const zipTask = unzip.zip('/path/to/folder', '/output.zip')
25
+ * const zipResult = await zipTask.await()
26
+ * ```
27
+ */
28
+ function getUnzip() {
29
+ return _reactNativeNitroModules.NitroModules.createHybridObject("Unzip");
30
+ }
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_reactNativeNitroModules","require","getUnzip","NitroModules","createHybridObject"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;AAAA,IAAAA,wBAAA,GAAAC,OAAA;AAaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASC,QAAQA,CAAA,EAAU;EAChC,OAAOC,qCAAY,CAACC,kBAAkB,CAAQ,OAAO,CAAC;AACxD","ignoreList":[]}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ //# sourceMappingURL=Unzip.nitro.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../../src","sources":["specs/Unzip.nitro.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ import { NitroModules } from "react-native-nitro-modules";
4
+ /**
5
+ * Create an `Unzip` instance. Each instance is a factory for
6
+ * extraction and compression tasks.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { getUnzip } from 'react-native-nitro-unzip'
11
+ *
12
+ * const unzip = getUnzip()
13
+ *
14
+ * // Extract
15
+ * const task = unzip.extract('/path/to/archive.zip', '/output')
16
+ * task.onProgress((p) => console.log(`${(p.progress * 100).toFixed(0)}%`))
17
+ * const result = await task.await()
18
+ *
19
+ * // Zip
20
+ * const zipTask = unzip.zip('/path/to/folder', '/output.zip')
21
+ * const zipResult = await zipTask.await()
22
+ * ```
23
+ */
24
+ export function getUnzip() {
25
+ return NitroModules.createHybridObject("Unzip");
26
+ }
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NitroModules","getUnzip","createHybridObject"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,SAASA,YAAY,QAAQ,4BAA4B;AAazD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,QAAQA,CAAA,EAAU;EAChC,OAAOD,YAAY,CAACE,kBAAkB,CAAQ,OAAO,CAAC;AACxD","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export {};
4
+ //# sourceMappingURL=Unzip.nitro.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../../src","sources":["specs/Unzip.nitro.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,24 @@
1
+ import type { Unzip } from "./specs/Unzip.nitro";
2
+ export type { UnzipProgress, UnzipResult, UnzipTask, ZipProgress, ZipResult, ZipTask, Unzip, } from "./specs/Unzip.nitro";
3
+ /**
4
+ * Create an `Unzip` instance. Each instance is a factory for
5
+ * extraction and compression tasks.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { getUnzip } from 'react-native-nitro-unzip'
10
+ *
11
+ * const unzip = getUnzip()
12
+ *
13
+ * // Extract
14
+ * const task = unzip.extract('/path/to/archive.zip', '/output')
15
+ * task.onProgress((p) => console.log(`${(p.progress * 100).toFixed(0)}%`))
16
+ * const result = await task.await()
17
+ *
18
+ * // Zip
19
+ * const zipTask = unzip.zip('/path/to/folder', '/output.zip')
20
+ * const zipResult = await zipTask.await()
21
+ * ```
22
+ */
23
+ export declare function getUnzip(): Unzip;
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAEjD,YAAY,EACV,aAAa,EACb,WAAW,EACX,SAAS,EACT,WAAW,EACX,SAAS,EACT,OAAO,EACP,KAAK,GACN,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,QAAQ,IAAI,KAAK,CAEhC"}