react-native-earl-thermal-printer 1.0.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 (140) hide show
  1. package/README.md +441 -0
  2. package/android/build/.transforms/9bdecbc31aaf57a08a337d36d73153ec/results.bin +1 -0
  3. package/android/build/.transforms/9bdecbc31aaf57a08a337d36d73153ec/transformed/classes/classes_dex/classes.dex +0 -0
  4. package/android/build/.transforms/bc167481fd58833142c92ba32b0fc3e3/results.bin +1 -0
  5. package/android/build/.transforms/bc167481fd58833142c92ba32b0fc3e3/transformed/classes/classes_dex/classes.dex +0 -0
  6. package/android/build/generated/source/buildConfig/debug/com/pinmi/react/printer/BuildConfig.java +10 -0
  7. package/android/build/generated/source/codegen/java/com/pinmi/react/printer/NativeBLEPrinterSpec.java +70 -0
  8. package/android/build/generated/source/codegen/java/com/pinmi/react/printer/NativeNetPrinterSpec.java +70 -0
  9. package/android/build/generated/source/codegen/java/com/pinmi/react/printer/NativeUSBPrinterSpec.java +62 -0
  10. package/android/build/generated/source/codegen/jni/CMakeLists.txt +46 -0
  11. package/android/build/generated/source/codegen/jni/RNThermalReceiptPrinterSpec-generated.cpp +190 -0
  12. package/android/build/generated/source/codegen/jni/RNThermalReceiptPrinterSpec.h +49 -0
  13. package/android/build/generated/source/codegen/jni/react/renderer/components/RNThermalReceiptPrinterSpec/ComponentDescriptors.h +22 -0
  14. package/android/build/generated/source/codegen/jni/react/renderer/components/RNThermalReceiptPrinterSpec/EventEmitters.cpp +18 -0
  15. package/android/build/generated/source/codegen/jni/react/renderer/components/RNThermalReceiptPrinterSpec/EventEmitters.h +19 -0
  16. package/android/build/generated/source/codegen/jni/react/renderer/components/RNThermalReceiptPrinterSpec/Props.cpp +21 -0
  17. package/android/build/generated/source/codegen/jni/react/renderer/components/RNThermalReceiptPrinterSpec/Props.h +20 -0
  18. package/android/build/generated/source/codegen/jni/react/renderer/components/RNThermalReceiptPrinterSpec/RNThermalReceiptPrinterSpecJSI-generated.cpp +205 -0
  19. package/android/build/generated/source/codegen/jni/react/renderer/components/RNThermalReceiptPrinterSpec/RNThermalReceiptPrinterSpecJSI.h +355 -0
  20. package/android/build/generated/source/codegen/jni/react/renderer/components/RNThermalReceiptPrinterSpec/ShadowNodes.cpp +19 -0
  21. package/android/build/generated/source/codegen/jni/react/renderer/components/RNThermalReceiptPrinterSpec/ShadowNodes.h +25 -0
  22. package/android/build/generated/source/codegen/jni/react/renderer/components/RNThermalReceiptPrinterSpec/States.cpp +18 -0
  23. package/android/build/generated/source/codegen/jni/react/renderer/components/RNThermalReceiptPrinterSpec/States.h +23 -0
  24. package/android/build/generated/source/codegen/schema.json +514 -0
  25. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/AndroidManifest.xml +13 -0
  26. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/aapt/output-metadata.json +18 -0
  27. package/android/build/intermediates/aar_metadata/debug/aar-metadata.properties +5 -0
  28. package/android/build/intermediates/annotation_processor_list/debug/annotationProcessors.json +1 -0
  29. package/android/build/intermediates/compile_library_classes_jar/debug/classes.jar +0 -0
  30. package/android/build/intermediates/compile_r_class_jar/debug/R.jar +0 -0
  31. package/android/build/intermediates/compile_symbol_list/debug/R.txt +1 -0
  32. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -0
  33. package/android/build/intermediates/incremental/debug/packageDebugResources/merged.dir/values/values.xml +4 -0
  34. package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +2 -0
  35. package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +2 -0
  36. package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +2 -0
  37. package/android/build/intermediates/incremental/packageDebugAssets/merger.xml +2 -0
  38. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/BuildConfig.class +0 -0
  39. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/NativeBLEPrinterSpec.class +0 -0
  40. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/NativeNetPrinterSpec.class +0 -0
  41. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/NativeUSBPrinterSpec.class +0 -0
  42. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/RNBLEPrinterModule.class +0 -0
  43. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/RNNetPrinterModule.class +0 -0
  44. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/RNPrinterModule.class +0 -0
  45. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/RNPrinterPackage.class +0 -0
  46. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/RNUSBPrinterModule.class +0 -0
  47. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/BLEPrinterAdapter$1.class +0 -0
  48. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/BLEPrinterAdapter.class +0 -0
  49. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/BLEPrinterDevice.class +0 -0
  50. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/BLEPrinterDeviceId.class +0 -0
  51. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/NetPrinterAdapter$1.class +0 -0
  52. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/NetPrinterAdapter$2.class +0 -0
  53. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/NetPrinterAdapter.class +0 -0
  54. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/NetPrinterDevice.class +0 -0
  55. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/NetPrinterDeviceId.class +0 -0
  56. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/PrinterAdapter.class +0 -0
  57. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/PrinterDevice.class +0 -0
  58. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/PrinterDeviceId.class +0 -0
  59. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/USBPrinterAdapter$1.class +0 -0
  60. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/USBPrinterAdapter$2.class +0 -0
  61. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/USBPrinterAdapter.class +0 -0
  62. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/USBPrinterDevice.class +0 -0
  63. package/android/build/intermediates/javac/debug/classes/com/pinmi/react/printer/adapter/USBPrinterDeviceId.class +0 -0
  64. package/android/build/intermediates/local_only_symbol_list/debug/R-def.txt +3 -0
  65. package/android/build/intermediates/manifest_merge_blame_file/debug/manifest-merger-blame-debug-report.txt +23 -0
  66. package/android/build/intermediates/merged_manifest/debug/AndroidManifest.xml +13 -0
  67. package/android/build/intermediates/navigation_json/debug/navigation.json +1 -0
  68. package/android/build/intermediates/packaged_res/debug/values/values.xml +4 -0
  69. package/android/build/intermediates/runtime_library_classes_jar/debug/classes.jar +0 -0
  70. package/android/build/intermediates/symbol_list_with_package_name/debug/package-aware-r.txt +2 -0
  71. package/android/build/outputs/logs/manifest-merger-debug-report.txt +37 -0
  72. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  73. package/android/build.gradle +30 -0
  74. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  75. package/android/gradle/wrapper/gradle-wrapper.properties +6 -0
  76. package/android/gradlew +160 -0
  77. package/android/gradlew.bat +90 -0
  78. package/android/src/androidTest/java/com/pinmi/react/printer/ExampleInstrumentedTest.java +26 -0
  79. package/android/src/main/AndroidManifest.xml +10 -0
  80. package/android/src/main/java/com/pinmi/react/printer/RNBLEPrinterModule.java +91 -0
  81. package/android/src/main/java/com/pinmi/react/printer/RNNetPrinterModule.java +95 -0
  82. package/android/src/main/java/com/pinmi/react/printer/RNPrinterModule.java +24 -0
  83. package/android/src/main/java/com/pinmi/react/printer/RNPrinterPackage.java +57 -0
  84. package/android/src/main/java/com/pinmi/react/printer/RNUSBPrinterModule.java +79 -0
  85. package/android/src/main/java/com/pinmi/react/printer/adapter/BLEPrinterAdapter.java +391 -0
  86. package/android/src/main/java/com/pinmi/react/printer/adapter/BLEPrinterDevice.java +33 -0
  87. package/android/src/main/java/com/pinmi/react/printer/adapter/BLEPrinterDeviceId.java +38 -0
  88. package/android/src/main/java/com/pinmi/react/printer/adapter/NetPrinterAdapter.java +433 -0
  89. package/android/src/main/java/com/pinmi/react/printer/adapter/NetPrinterDevice.java +30 -0
  90. package/android/src/main/java/com/pinmi/react/printer/adapter/NetPrinterDeviceId.java +48 -0
  91. package/android/src/main/java/com/pinmi/react/printer/adapter/PrinterAdapter.java +29 -0
  92. package/android/src/main/java/com/pinmi/react/printer/adapter/PrinterDevice.java +17 -0
  93. package/android/src/main/java/com/pinmi/react/printer/adapter/PrinterDeviceId.java +8 -0
  94. package/android/src/main/java/com/pinmi/react/printer/adapter/USBPrinterAdapter.java +468 -0
  95. package/android/src/main/java/com/pinmi/react/printer/adapter/USBPrinterDevice.java +41 -0
  96. package/android/src/main/java/com/pinmi/react/printer/adapter/USBPrinterDeviceId.java +49 -0
  97. package/android/src/main/res/values/strings.xml +3 -0
  98. package/android/src/test/java/com/pinmi/react/printer/ExampleUnitTest.java +17 -0
  99. package/dist/NativeBLEPrinter.d.ts +15 -0
  100. package/dist/NativeBLEPrinter.d.ts.map +1 -0
  101. package/dist/NativeBLEPrinter.js +3 -0
  102. package/dist/NativeBLEPrinter.js.map +1 -0
  103. package/dist/NativeNetPrinter.d.ts +15 -0
  104. package/dist/NativeNetPrinter.d.ts.map +1 -0
  105. package/dist/NativeNetPrinter.js +3 -0
  106. package/dist/NativeNetPrinter.js.map +1 -0
  107. package/dist/NativeUSBPrinter.d.ts +13 -0
  108. package/dist/NativeUSBPrinter.d.ts.map +1 -0
  109. package/dist/NativeUSBPrinter.js +3 -0
  110. package/dist/NativeUSBPrinter.js.map +1 -0
  111. package/dist/index.d.ts +59 -0
  112. package/dist/index.d.ts.map +1 -0
  113. package/dist/index.js +58 -0
  114. package/dist/index.js.map +1 -0
  115. package/dist/utils/EPToolkit.d.ts +9 -0
  116. package/dist/utils/EPToolkit.d.ts.map +1 -0
  117. package/dist/utils/EPToolkit.js +161 -0
  118. package/dist/utils/EPToolkit.js.map +1 -0
  119. package/dist/utils/buffer-helper.d.ts +12 -0
  120. package/dist/utils/buffer-helper.d.ts.map +1 -0
  121. package/dist/utils/buffer-helper.js +32 -0
  122. package/dist/utils/buffer-helper.js.map +1 -0
  123. package/ios/PrinterSDK/PrinterSDK.h +74 -0
  124. package/ios/PrinterSDK/libPrinterSDK.a +0 -0
  125. package/ios/RNBLEPrinter.h +24 -0
  126. package/ios/RNBLEPrinter.mm +251 -0
  127. package/ios/RNNetPrinter.h +25 -0
  128. package/ios/RNNetPrinter.mm +306 -0
  129. package/ios/RNThermalReceiptPrinter.xcodeproj/project.pbxproj +294 -0
  130. package/ios/RNThermalReceiptPrinter.xcworkspace/contents.xcworkspacedata +9 -0
  131. package/ios/RNUSBPrinter.h +19 -0
  132. package/ios/RNUSBPrinter.mm +80 -0
  133. package/package.json +70 -0
  134. package/react-native-earl-thermal-printer.podspec +22 -0
  135. package/src/NativeBLEPrinter.ts +16 -0
  136. package/src/NativeNetPrinter.ts +16 -0
  137. package/src/NativeUSBPrinter.ts +14 -0
  138. package/src/index.ts +160 -0
  139. package/src/utils/EPToolkit.ts +193 -0
  140. package/src/utils/buffer-helper.ts +42 -0
@@ -0,0 +1,251 @@
1
+ //
2
+ // RNBLEPrinter.mm
3
+ // react-native-earl-thermal-printer
4
+ //
5
+ // BLE (Bluetooth) printer module for iOS using PrinterSDK.
6
+ // Migrated to Promise-based API for React Native New Architecture (TurboModules).
7
+ //
8
+ // Author: Ordovez, Earl Romeo
9
+ //
10
+
11
+ #import <Foundation/Foundation.h>
12
+ #import <UIKit/UIKit.h>
13
+
14
+ #import "RNBLEPrinter.h"
15
+ #import "PrinterSDK.h"
16
+
17
+ #ifdef RCT_NEW_ARCH_ENABLED
18
+ #import "RNThermalReceiptPrinterSpec.h"
19
+ #endif
20
+
21
+ @implementation RNBLEPrinter
22
+
23
+ - (dispatch_queue_t)methodQueue
24
+ {
25
+ return dispatch_get_main_queue();
26
+ }
27
+
28
+ RCT_EXPORT_MODULE()
29
+
30
+ - (NSArray<NSString *> *)supportedEvents
31
+ {
32
+ return @[];
33
+ }
34
+
35
+ RCT_EXPORT_METHOD(init:(RCTPromiseResolveBlock)resolve
36
+ reject:(RCTPromiseRejectBlock)reject)
37
+ {
38
+ @try {
39
+ _printerArray = [NSMutableArray new];
40
+ m_printer = [[NSObject alloc] init];
41
+ [[NSNotificationCenter defaultCenter] addObserver:self
42
+ selector:@selector(handleNetPrinterConnectedNotification:)
43
+ name:@"NetPrinterConnected"
44
+ object:nil];
45
+ [[PrinterSDK defaultPrinterSDK] scanPrintersWithCompletion:^(Printer* printer){}];
46
+ resolve(@"RNBLEPrinter initialized");
47
+ } @catch (NSException *exception) {
48
+ reject(@"ERR_BT_ADAPTER", exception.reason ?: @"No bluetooth adapter available", nil);
49
+ }
50
+ }
51
+
52
+ - (void)handleNetPrinterConnectedNotification:(NSNotification *)notification
53
+ {
54
+ m_printer = nil;
55
+ }
56
+
57
+ RCT_EXPORT_METHOD(getDeviceList:(RCTPromiseResolveBlock)resolve
58
+ reject:(RCTPromiseRejectBlock)reject)
59
+ {
60
+ @try {
61
+ if (!_printerArray) {
62
+ reject(@"ERR_NOT_INIT", @"Must call init function first", nil);
63
+ return;
64
+ }
65
+ [[PrinterSDK defaultPrinterSDK] scanPrintersWithCompletion:^(Printer* printer){
66
+ [self->_printerArray addObject:printer];
67
+ NSMutableArray *mapped = [NSMutableArray arrayWithCapacity:[self->_printerArray count]];
68
+ [self->_printerArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
69
+ NSDictionary *dict = @{
70
+ @"device_name" : printer.name ?: @"",
71
+ @"inner_mac_address" : printer.UUIDString ?: @""
72
+ };
73
+ [mapped addObject:dict];
74
+ }];
75
+ NSArray *uniqueArray = [[NSSet setWithArray:mapped] allObjects];
76
+ resolve(uniqueArray);
77
+ }];
78
+ } @catch (NSException *exception) {
79
+ reject(@"ERR_SCAN", exception.reason ?: @"Failed to scan devices", nil);
80
+ }
81
+ }
82
+
83
+ RCT_EXPORT_METHOD(connectPrinter:(NSString *)innerAddress
84
+ resolve:(RCTPromiseResolveBlock)resolve
85
+ reject:(RCTPromiseRejectBlock)reject)
86
+ {
87
+ @try {
88
+ __block BOOL found = NO;
89
+ __block Printer *selectedPrinter = nil;
90
+ [_printerArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
91
+ selectedPrinter = (Printer *)obj;
92
+ if ([innerAddress isEqualToString:(selectedPrinter.UUIDString)]) {
93
+ found = YES;
94
+ *stop = YES;
95
+ }
96
+ }];
97
+
98
+ if (found) {
99
+ [[PrinterSDK defaultPrinterSDK] connectBT:selectedPrinter];
100
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"BLEPrinterConnected" object:nil];
101
+ m_printer = selectedPrinter;
102
+ NSDictionary *result = @{
103
+ @"device_name" : selectedPrinter.name ?: @"",
104
+ @"inner_mac_address" : selectedPrinter.UUIDString ?: @""
105
+ };
106
+ resolve(result);
107
+ } else {
108
+ reject(@"ERR_NOT_FOUND",
109
+ [NSString stringWithFormat:@"Can't find printer %@, please pair it in system settings first", innerAddress],
110
+ nil);
111
+ }
112
+ } @catch (NSException *exception) {
113
+ reject(@"ERR_CONNECT", exception.reason ?: @"Failed to connect", nil);
114
+ }
115
+ }
116
+
117
+ RCT_EXPORT_METHOD(printRawData:(NSString *)base64Data
118
+ resolve:(RCTPromiseResolveBlock)resolve
119
+ reject:(RCTPromiseRejectBlock)reject)
120
+ {
121
+ @try {
122
+ if (!m_printer) {
123
+ reject(@"ERR_NO_CONN", @"Not connected to a printer", nil);
124
+ return;
125
+ }
126
+ [[PrinterSDK defaultPrinterSDK] printText:base64Data];
127
+ resolve(nil);
128
+ } @catch (NSException *exception) {
129
+ reject(@"ERR_PRINT", exception.reason ?: @"Failed to print raw data", nil);
130
+ }
131
+ }
132
+
133
+ RCT_EXPORT_METHOD(printImageData:(NSString *)imageUrl
134
+ resolve:(RCTPromiseResolveBlock)resolve
135
+ reject:(RCTPromiseRejectBlock)reject)
136
+ {
137
+ @try {
138
+ if (!m_printer) {
139
+ reject(@"ERR_NO_CONN", @"Not connected to a printer", nil);
140
+ return;
141
+ }
142
+ NSURL *url = [NSURL URLWithString:imageUrl];
143
+ NSData *imageData = [NSData dataWithContentsOfURL:url];
144
+ if (imageData != nil) {
145
+ UIImage *image = [UIImage imageWithData:imageData];
146
+ UIImage *printImage = [self getPrintImage:image width:150 paddingX:250];
147
+ [[PrinterSDK defaultPrinterSDK] setPrintWidth:576];
148
+ [[PrinterSDK defaultPrinterSDK] printImage:printImage];
149
+ resolve(nil);
150
+ } else {
151
+ reject(@"ERR_IMAGE", @"Image not found", nil);
152
+ }
153
+ } @catch (NSException *exception) {
154
+ reject(@"ERR_PRINT_IMAGE", exception.reason ?: @"Failed to print image", nil);
155
+ }
156
+ }
157
+
158
+ RCT_EXPORT_METHOD(printQrCode:(NSString *)qrCode
159
+ resolve:(RCTPromiseResolveBlock)resolve
160
+ reject:(RCTPromiseRejectBlock)reject)
161
+ {
162
+ @try {
163
+ if (!m_printer) {
164
+ reject(@"ERR_NO_CONN", @"Not connected to a printer", nil);
165
+ return;
166
+ }
167
+ if (qrCode != nil) {
168
+ [[PrinterSDK defaultPrinterSDK] setPrintWidth:576];
169
+ [[PrinterSDK defaultPrinterSDK] printQrCode:qrCode];
170
+ resolve(nil);
171
+ } else {
172
+ reject(@"ERR_QR", @"QR code data is nil", nil);
173
+ }
174
+ } @catch (NSException *exception) {
175
+ reject(@"ERR_PRINT_QR", exception.reason ?: @"Failed to print QR code", nil);
176
+ }
177
+ }
178
+
179
+ RCT_EXPORT_METHOD(closeConn)
180
+ {
181
+ @try {
182
+ if (m_printer) {
183
+ [[PrinterSDK defaultPrinterSDK] disconnect];
184
+ m_printer = nil;
185
+ }
186
+ } @catch (NSException *exception) {
187
+ NSLog(@"%@", exception.reason);
188
+ }
189
+ }
190
+
191
+ RCT_EXPORT_METHOD(addListener:(NSString *)eventName)
192
+ {
193
+ // Required by RCTEventEmitter — no-op for BLE
194
+ }
195
+
196
+ RCT_EXPORT_METHOD(removeListeners:(double)count)
197
+ {
198
+ // Required by RCTEventEmitter — no-op for BLE
199
+ }
200
+
201
+ #pragma mark - Image Helpers
202
+
203
+ - (UIImage *)getPrintImage:(UIImage *)image width:(CGFloat)newWidth paddingX:(CGFloat)paddingX
204
+ {
205
+ CGFloat newHeight = (newWidth / image.size.width) * image.size.height;
206
+ CGSize newSize = CGSizeMake(newWidth, newHeight);
207
+ UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0);
208
+ CGContextRef context = UIGraphicsGetCurrentContext();
209
+ CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
210
+ CGImageRef imageRef = image.CGImage;
211
+ CGContextDrawImage(context, CGRectMake(0, 0, newWidth, newHeight), imageRef);
212
+ CGImageRef newImageRef = CGBitmapContextCreateImage(context);
213
+ UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
214
+ CGImageRelease(newImageRef);
215
+ UIGraphicsEndImageContext();
216
+
217
+ UIImage *paddedImage = [self addImagePadding:newImage paddingX:paddingX paddingY:0];
218
+ return paddedImage;
219
+ }
220
+
221
+ - (UIImage *)addImagePadding:(UIImage *)image paddingX:(CGFloat)paddingX paddingY:(CGFloat)paddingY
222
+ {
223
+ CGFloat width = image.size.width + paddingX;
224
+ CGFloat height = image.size.height + paddingY;
225
+
226
+ UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), true, 0.0);
227
+ CGContextRef context = UIGraphicsGetCurrentContext();
228
+ CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
229
+ CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
230
+ CGContextFillRect(context, CGRectMake(0, 0, width, height));
231
+ CGFloat originX = (width - image.size.width) / 2;
232
+ CGFloat originY = (height - image.size.height) / 2;
233
+ CGImageRef imageRef = image.CGImage;
234
+ CGContextDrawImage(context, CGRectMake(originX, originY, image.size.width, image.size.height), imageRef);
235
+ CGImageRef newImageRef = CGBitmapContextCreateImage(context);
236
+ UIImage *paddedImage = [UIImage imageWithCGImage:newImageRef];
237
+ CGImageRelease(newImageRef);
238
+ UIGraphicsEndImageContext();
239
+
240
+ return paddedImage;
241
+ }
242
+
243
+ #ifdef RCT_NEW_ARCH_ENABLED
244
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
245
+ (const facebook::react::ObjCTurboModule::InitParams &)params
246
+ {
247
+ return std::make_shared<facebook::react::NativeBLEPrinterSpecJSI>(params);
248
+ }
249
+ #endif
250
+
251
+ @end
@@ -0,0 +1,25 @@
1
+ //
2
+ // RNNetPrinter.h
3
+ // react-native-earl-thermal-printer
4
+ //
5
+ // Author: Ordovez, Earl Romeo
6
+ //
7
+
8
+ #pragma once
9
+
10
+ #import <React/RCTBridgeModule.h>
11
+ #import <React/RCTEventEmitter.h>
12
+
13
+ #ifdef RCT_NEW_ARCH_ENABLED
14
+ #import <RNThermalReceiptPrinterSpec/RNThermalReceiptPrinterSpec.h>
15
+ @interface RNNetPrinter : RCTEventEmitter <NativeNetPrinterSpec>
16
+ #else
17
+ @interface RNNetPrinter : RCTEventEmitter <RCTBridgeModule>
18
+ #endif
19
+ {
20
+ NSString *connected_ip;
21
+ NSString *current_scan_ip;
22
+ NSMutableArray *_printerArray;
23
+ bool is_scanning;
24
+ }
25
+ @end
@@ -0,0 +1,306 @@
1
+ //
2
+ // RNNetPrinter.mm
3
+ // react-native-earl-thermal-printer
4
+ //
5
+ // Network (TCP/IP) printer module for iOS using PrinterSDK.
6
+ // Migrated to Promise-based API for React Native New Architecture (TurboModules).
7
+ //
8
+ // Author: Ordovez, Earl Romeo
9
+ //
10
+
11
+ #import "RNNetPrinter.h"
12
+ #import "PrinterSDK.h"
13
+ #include <ifaddrs.h>
14
+ #include <arpa/inet.h>
15
+ #import <Foundation/Foundation.h>
16
+ #import <UIKit/UIKit.h>
17
+
18
+ #ifdef RCT_NEW_ARCH_ENABLED
19
+ #import "RNThermalReceiptPrinterSpec.h"
20
+ #endif
21
+
22
+ NSString *const EVENT_SCANNER_RESOLVED = @"scannerResolved";
23
+ NSString *const EVENT_SCANNER_RUNNING = @"scannerRunning";
24
+
25
+ #pragma mark - PrivateIP Helper
26
+
27
+ @interface PrivateIP : NSObject
28
+ - (NSString *)getIPAddress;
29
+ @end
30
+
31
+ @implementation PrivateIP
32
+
33
+ - (NSString *)getIPAddress
34
+ {
35
+ NSString *address = @"error";
36
+ struct ifaddrs *interfaces = NULL;
37
+ struct ifaddrs *temp_addr = NULL;
38
+ int success = getifaddrs(&interfaces);
39
+ if (success == 0) {
40
+ temp_addr = interfaces;
41
+ while (temp_addr != NULL) {
42
+ if (temp_addr->ifa_addr->sa_family == AF_INET) {
43
+ if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
44
+ address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
45
+ }
46
+ }
47
+ temp_addr = temp_addr->ifa_next;
48
+ }
49
+ }
50
+ freeifaddrs(interfaces);
51
+ return address;
52
+ }
53
+
54
+ @end
55
+
56
+ #pragma mark - RNNetPrinter
57
+
58
+ @implementation RNNetPrinter
59
+
60
+ - (dispatch_queue_t)methodQueue
61
+ {
62
+ return dispatch_get_main_queue();
63
+ }
64
+
65
+ RCT_EXPORT_MODULE()
66
+
67
+ - (NSArray<NSString *> *)supportedEvents
68
+ {
69
+ return @[EVENT_SCANNER_RESOLVED, EVENT_SCANNER_RUNNING];
70
+ }
71
+
72
+ RCT_EXPORT_METHOD(init:(RCTPromiseResolveBlock)resolve
73
+ reject:(RCTPromiseRejectBlock)reject)
74
+ {
75
+ connected_ip = nil;
76
+ is_scanning = NO;
77
+ _printerArray = [NSMutableArray new];
78
+ resolve(@"RNNetPrinter initialized");
79
+ }
80
+
81
+ RCT_EXPORT_METHOD(getDeviceList:(RCTPromiseResolveBlock)resolve
82
+ reject:(RCTPromiseRejectBlock)reject)
83
+ {
84
+ [[NSNotificationCenter defaultCenter] addObserver:self
85
+ selector:@selector(handlePrinterConnectedNotification:)
86
+ name:PrinterConnectedNotification
87
+ object:nil];
88
+ [[NSNotificationCenter defaultCenter] addObserver:self
89
+ selector:@selector(handleBLEPrinterConnectedNotification:)
90
+ name:@"BLEPrinterConnected"
91
+ object:nil];
92
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
93
+ [self scan];
94
+ });
95
+
96
+ // Resolve immediately with empty array; discovered printers arrive via events
97
+ resolve(@[]);
98
+ }
99
+
100
+ - (void)scan
101
+ {
102
+ @try {
103
+ PrivateIP *privateIP = [[PrivateIP alloc] init];
104
+ NSString *localIP = [privateIP getIPAddress];
105
+ is_scanning = YES;
106
+ [self sendEventWithName:EVENT_SCANNER_RUNNING body:@YES];
107
+ _printerArray = [NSMutableArray new];
108
+
109
+ NSString *prefix = [localIP substringToIndex:([localIP rangeOfString:@"." options:NSBackwardsSearch].location)];
110
+ NSInteger suffix = [[localIP substringFromIndex:([localIP rangeOfString:@"." options:NSBackwardsSearch].location)] intValue];
111
+
112
+ for (NSInteger i = 1; i < 255; i++) {
113
+ if (i == suffix) continue;
114
+ NSString *testIP = [NSString stringWithFormat:@"%@.%ld", prefix, (long)i];
115
+ current_scan_ip = testIP;
116
+ [[PrinterSDK defaultPrinterSDK] connectIP:testIP];
117
+ [NSThread sleepForTimeInterval:0.5];
118
+ }
119
+
120
+ NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:_printerArray];
121
+ NSArray *arrayWithoutDuplicates = [orderedSet array];
122
+ _printerArray = [arrayWithoutDuplicates mutableCopy];
123
+
124
+ [self sendEventWithName:EVENT_SCANNER_RESOLVED body:_printerArray];
125
+ } @catch (NSException *exception) {
126
+ NSLog(@"No connection");
127
+ }
128
+ [[PrinterSDK defaultPrinterSDK] disconnect];
129
+ is_scanning = NO;
130
+ [self sendEventWithName:EVENT_SCANNER_RUNNING body:@NO];
131
+ }
132
+
133
+ - (void)handlePrinterConnectedNotification:(NSNotification *)notification
134
+ {
135
+ if (is_scanning) {
136
+ [_printerArray addObject:@{@"host": current_scan_ip, @"port": @9100}];
137
+ }
138
+ }
139
+
140
+ - (void)handleBLEPrinterConnectedNotification:(NSNotification *)notification
141
+ {
142
+ connected_ip = nil;
143
+ }
144
+
145
+ RCT_EXPORT_METHOD(connectPrinter:(NSString *)host
146
+ port:(double)port
147
+ resolve:(RCTPromiseResolveBlock)resolve
148
+ reject:(RCTPromiseRejectBlock)reject)
149
+ {
150
+ @try {
151
+ BOOL isConnectSuccess = [[PrinterSDK defaultPrinterSDK] connectIP:host];
152
+ if (!isConnectSuccess) {
153
+ reject(@"ERR_CONNECT",
154
+ [NSString stringWithFormat:@"Can't connect to printer %@:%d", host, (int)port],
155
+ nil);
156
+ return;
157
+ }
158
+
159
+ connected_ip = host;
160
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"NetPrinterConnected" object:nil];
161
+ NSDictionary *result = @{
162
+ @"device_name" : [NSString stringWithFormat:@"%@:%d", host, (int)port],
163
+ @"host" : host,
164
+ @"port" : @((int)port)
165
+ };
166
+ resolve(result);
167
+ } @catch (NSException *exception) {
168
+ reject(@"ERR_CONNECT", exception.reason ?: @"Failed to connect", nil);
169
+ }
170
+ }
171
+
172
+ RCT_EXPORT_METHOD(printRawData:(NSString *)base64Data
173
+ resolve:(RCTPromiseResolveBlock)resolve
174
+ reject:(RCTPromiseRejectBlock)reject)
175
+ {
176
+ @try {
177
+ if (!connected_ip) {
178
+ reject(@"ERR_NO_CONN", @"Not connected to a printer", nil);
179
+ return;
180
+ }
181
+ [[PrinterSDK defaultPrinterSDK] printText:base64Data];
182
+ resolve(nil);
183
+ } @catch (NSException *exception) {
184
+ reject(@"ERR_PRINT", exception.reason ?: @"Failed to print raw data", nil);
185
+ }
186
+ }
187
+
188
+ RCT_EXPORT_METHOD(printImageData:(NSString *)imageUrl
189
+ resolve:(RCTPromiseResolveBlock)resolve
190
+ reject:(RCTPromiseRejectBlock)reject)
191
+ {
192
+ @try {
193
+ if (!connected_ip) {
194
+ reject(@"ERR_NO_CONN", @"Not connected to a printer", nil);
195
+ return;
196
+ }
197
+ NSURL *url = [NSURL URLWithString:imageUrl];
198
+ NSData *imageData = [NSData dataWithContentsOfURL:url];
199
+ if (imageData != nil) {
200
+ UIImage *image = [UIImage imageWithData:imageData];
201
+ UIImage *printImage = [self getPrintImage:image width:150 paddingX:250];
202
+ [[PrinterSDK defaultPrinterSDK] setPrintWidth:576];
203
+ [[PrinterSDK defaultPrinterSDK] printImage:printImage];
204
+ resolve(nil);
205
+ } else {
206
+ reject(@"ERR_IMAGE", @"Image not found", nil);
207
+ }
208
+ } @catch (NSException *exception) {
209
+ reject(@"ERR_PRINT_IMAGE", exception.reason ?: @"Failed to print image", nil);
210
+ }
211
+ }
212
+
213
+ RCT_EXPORT_METHOD(printQrCode:(NSString *)qrCode
214
+ resolve:(RCTPromiseResolveBlock)resolve
215
+ reject:(RCTPromiseRejectBlock)reject)
216
+ {
217
+ @try {
218
+ if (!connected_ip) {
219
+ reject(@"ERR_NO_CONN", @"Not connected to a printer", nil);
220
+ return;
221
+ }
222
+ if (qrCode != nil) {
223
+ [[PrinterSDK defaultPrinterSDK] setPrintWidth:576];
224
+ [[PrinterSDK defaultPrinterSDK] printQrCode:qrCode];
225
+ resolve(nil);
226
+ } else {
227
+ reject(@"ERR_QR", @"QR code data is nil", nil);
228
+ }
229
+ } @catch (NSException *exception) {
230
+ reject(@"ERR_PRINT_QR", exception.reason ?: @"Failed to print QR code", nil);
231
+ }
232
+ }
233
+
234
+ RCT_EXPORT_METHOD(closeConn)
235
+ {
236
+ @try {
237
+ if (connected_ip) {
238
+ [[PrinterSDK defaultPrinterSDK] disconnect];
239
+ connected_ip = nil;
240
+ }
241
+ } @catch (NSException *exception) {
242
+ NSLog(@"%@", exception.reason);
243
+ }
244
+ }
245
+
246
+ RCT_EXPORT_METHOD(addListener:(NSString *)eventName)
247
+ {
248
+ // Required by RCTEventEmitter
249
+ }
250
+
251
+ RCT_EXPORT_METHOD(removeListeners:(double)count)
252
+ {
253
+ // Required by RCTEventEmitter
254
+ }
255
+
256
+ #pragma mark - Image Helpers
257
+
258
+ - (UIImage *)getPrintImage:(UIImage *)image width:(CGFloat)newWidth paddingX:(CGFloat)paddingX
259
+ {
260
+ CGFloat newHeight = (newWidth / image.size.width) * image.size.height;
261
+ CGSize newSize = CGSizeMake(newWidth, newHeight);
262
+ UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0);
263
+ CGContextRef context = UIGraphicsGetCurrentContext();
264
+ CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
265
+ CGImageRef imageRef = image.CGImage;
266
+ CGContextDrawImage(context, CGRectMake(0, 0, newWidth, newHeight), imageRef);
267
+ CGImageRef newImageRef = CGBitmapContextCreateImage(context);
268
+ UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
269
+ CGImageRelease(newImageRef);
270
+ UIGraphicsEndImageContext();
271
+
272
+ UIImage *paddedImage = [self addImagePadding:newImage paddingX:paddingX paddingY:0];
273
+ return paddedImage;
274
+ }
275
+
276
+ - (UIImage *)addImagePadding:(UIImage *)image paddingX:(CGFloat)paddingX paddingY:(CGFloat)paddingY
277
+ {
278
+ CGFloat width = image.size.width + paddingX;
279
+ CGFloat height = image.size.height + paddingY;
280
+
281
+ UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), true, 0.0);
282
+ CGContextRef context = UIGraphicsGetCurrentContext();
283
+ CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
284
+ CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
285
+ CGContextFillRect(context, CGRectMake(0, 0, width, height));
286
+ CGFloat originX = (width - image.size.width) / 2;
287
+ CGFloat originY = (height - image.size.height) / 2;
288
+ CGImageRef imageRef = image.CGImage;
289
+ CGContextDrawImage(context, CGRectMake(originX, originY, image.size.width, image.size.height), imageRef);
290
+ CGImageRef newImageRef = CGBitmapContextCreateImage(context);
291
+ UIImage *paddedImage = [UIImage imageWithCGImage:newImageRef];
292
+ CGImageRelease(newImageRef);
293
+ UIGraphicsEndImageContext();
294
+
295
+ return paddedImage;
296
+ }
297
+
298
+ #ifdef RCT_NEW_ARCH_ENABLED
299
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
300
+ (const facebook::react::ObjCTurboModule::InitParams &)params
301
+ {
302
+ return std::make_shared<facebook::react::NativeNetPrinterSpecJSI>(params);
303
+ }
304
+ #endif
305
+
306
+ @end