@sincpro/printer-expo 0.1.2 → 1.0.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/README.md +589 -415
- package/android/.editorconfig +20 -0
- package/android/README.md +103 -0
- package/android/build.gradle +36 -34
- package/android/libs/pdf/Bixolon_pdf.aar +0 -0
- package/android/libs/{jniLibs/x86_64/libbxl_common.so → sincpro-printer-sdk.aar} +0 -0
- package/android/src/main/java/sincpro/expo/printer/entrypoint/PrinterModule.kt +387 -0
- package/build/SincproPrinter.d.ts +191 -0
- package/build/SincproPrinter.d.ts.map +1 -0
- package/build/SincproPrinter.js +120 -0
- package/build/SincproPrinter.js.map +1 -0
- package/build/index.d.ts +11 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +13 -3
- package/build/index.js.map +1 -1
- package/build/types/bluetooth.types.d.ts +19 -0
- package/build/types/bluetooth.types.d.ts.map +1 -0
- package/build/types/bluetooth.types.js +5 -0
- package/build/types/bluetooth.types.js.map +1 -0
- package/build/types/index.d.ts +7 -0
- package/build/types/index.d.ts.map +1 -0
- package/build/types/index.js +7 -0
- package/build/types/index.js.map +1 -0
- package/build/types/printer.types.d.ts +118 -0
- package/build/types/printer.types.d.ts.map +1 -0
- package/build/types/printer.types.js +5 -0
- package/build/types/printer.types.js.map +1 -0
- package/build/types/receipt.types.d.ts +96 -0
- package/build/types/receipt.types.d.ts.map +1 -0
- package/build/types/receipt.types.js +5 -0
- package/build/types/receipt.types.js.map +1 -0
- package/expo-module.config.json +2 -5
- package/package.json +6 -7
- package/android/libs/BixolonLabelPrinterLibrary_V2.0.9.jar +0 -0
- package/android/libs/jniLibs/arm64-v8a/libbxl_common.so +0 -0
- package/android/libs/jniLibs/armeabi-v7a/libbxl_common.so +0 -0
- package/android/libs/jniLibs/x86/libbxl_common.so +0 -0
- package/android/libs/libcommon_V1.4.0.jar +0 -0
- package/android/src/main/java/expo/sincpro/ExpoBixolonModule.kt +0 -271
- package/android/src/main/java/expo/sincpro/bixolon/BixolonQRPrinter.kt +0 -423
- package/android/src/main/java/expo/sincpro/managers/BluetoothManager.kt +0 -139
- package/android/src/main/java/expo/sincpro/managers/ConnectionManager.kt +0 -124
- package/android/src/main/java/expo/sincpro/managers/PermissionManager.kt +0 -122
- package/android/src/main/java/expo/sincpro/managers/PrinterManager.kt +0 -396
- package/android/src/main/jniLibs/arm64-v8a/libbxl_common.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libbxl_common.so +0 -0
- package/android/src/main/jniLibs/x86/libbxl_common.so +0 -0
- package/android/src/main/jniLibs/x86_64/libbxl_common.so +0 -0
- package/build/BixolonPrinter.d.ts +0 -4
- package/build/BixolonPrinter.d.ts.map +0 -1
- package/build/BixolonPrinter.js +0 -12
- package/build/BixolonPrinter.js.map +0 -1
- package/build/ExpoBixolon.types.d.ts +0 -45
- package/build/ExpoBixolon.types.d.ts.map +0 -1
- package/build/ExpoBixolon.types.js +0 -2
- package/build/ExpoBixolon.types.js.map +0 -1
- package/build/ExpoBixolonModule.d.ts +0 -24
- package/build/ExpoBixolonModule.d.ts.map +0 -1
- package/build/ExpoBixolonModule.js +0 -3
- package/build/ExpoBixolonModule.js.map +0 -1
- package/build/QrCodePrinter.d.ts +0 -45
- package/build/QrCodePrinter.d.ts.map +0 -1
- package/build/QrCodePrinter.js +0 -118
- package/build/QrCodePrinter.js.map +0 -1
- package/ios/ExpoBixolon.podspec +0 -29
- package/ios/ExpoBixolonModule.swift +0 -33
- package/ios/ExpoBixolonView.swift +0 -36
- package/src/BixolonPrinter.ts +0 -16
- package/src/ExpoBixolon.types.ts +0 -60
- package/src/ExpoBixolonModule.ts +0 -38
- package/src/QrCodePrinter.ts +0 -201
- package/src/index.ts +0 -3
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*]
|
|
4
|
+
charset = utf-8
|
|
5
|
+
end_of_line = lf
|
|
6
|
+
insert_final_newline = true
|
|
7
|
+
trim_trailing_whitespace = true
|
|
8
|
+
|
|
9
|
+
[*.{kt,kts}]
|
|
10
|
+
indent_size = 4
|
|
11
|
+
indent_style = space
|
|
12
|
+
max_line_length = 120
|
|
13
|
+
ij_kotlin_allow_trailing_comma = true
|
|
14
|
+
ij_kotlin_allow_trailing_comma_on_call_site = true
|
|
15
|
+
|
|
16
|
+
[*.{json,yml,yaml}]
|
|
17
|
+
indent_size = 2
|
|
18
|
+
|
|
19
|
+
[*.md]
|
|
20
|
+
trim_trailing_whitespace = false
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Android Development para Módulo Expo
|
|
2
|
+
|
|
3
|
+
## ⚠️ ERROR CONOCIDO: `debugRuntimeClasspathCopy`
|
|
4
|
+
|
|
5
|
+
Este error **NO tiene solución** y **es normal**. Android Studio intenta sincronizar el módulo como una app Android completa, pero los módulos Expo son bibliotecas.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Cannot select root node 'debugRuntimeClasspathCopy' as a variant
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**IGNORA ESTE ERROR.** El módulo funciona correctamente en apps host.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Lo que SÍ funciona en Android Studio:
|
|
16
|
+
|
|
17
|
+
A pesar del error rojo de Gradle sync, puedes desarrollar normalmente:
|
|
18
|
+
|
|
19
|
+
✅ **Autocompletado de Kotlin** - Funciona
|
|
20
|
+
✅ **Navegación de código** - Cmd+Click en clases/funciones
|
|
21
|
+
✅ **Análisis de errores** - Ve errores de sintaxis y tipos
|
|
22
|
+
✅ **Formateo de código** - Cmd+Opt+L
|
|
23
|
+
✅ **Refactoring** - Renombrar, extraer métodos, etc.
|
|
24
|
+
✅ **Git integration** - Commits, diff, branches
|
|
25
|
+
✅ **Debug** - Puedes poner breakpoints (cuando uses en app host)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Setup rápido
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Desde la raíz del proyecto
|
|
33
|
+
make android-env
|
|
34
|
+
|
|
35
|
+
# Abrir Android Studio
|
|
36
|
+
cd android
|
|
37
|
+
open -a "Android Studio" .
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Ignora el banner rojo de Gradle sync y trabaja normalmente.**
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## ¿Cómo probar el módulo?
|
|
45
|
+
|
|
46
|
+
El módulo se prueba en una **app host**, no standalone:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Crear app de prueba
|
|
50
|
+
cd ..
|
|
51
|
+
npx create-expo-app test-app
|
|
52
|
+
cd test-app
|
|
53
|
+
npm install ../sincpro_printer_expo
|
|
54
|
+
|
|
55
|
+
# Compilar y correr
|
|
56
|
+
npx expo run:android
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## Alternativa sin errores: IntelliJ IDEA
|
|
62
|
+
|
|
63
|
+
Si el error te molesta mucho:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
brew install --cask intellij-idea-ce
|
|
67
|
+
cd android
|
|
68
|
+
open -a "IntelliJ IDEA CE" .
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
IntelliJ **no intenta** sincronizar como app Android, funciona mejor con bibliotecas.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Comandos útiles
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
make clean-android # Limpia caché
|
|
79
|
+
make android-env # Setup ambiente
|
|
80
|
+
make format # Formatear Kotlin
|
|
81
|
+
npm run lint:kotlin # Ver errores de lint
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Estructura
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
android-dev-env/ ← Templates versionados
|
|
90
|
+
├── settings.gradle
|
|
91
|
+
├── gradle.properties
|
|
92
|
+
└── README.md
|
|
93
|
+
|
|
94
|
+
android/
|
|
95
|
+
├── build.gradle ← ✅ Commitear
|
|
96
|
+
├── libs/ ← ✅ Commitear
|
|
97
|
+
├── src/main/ ← ✅ Commitear
|
|
98
|
+
│
|
|
99
|
+
├── settings.gradle ← ❌ Local (copiado)
|
|
100
|
+
├── gradle.properties ← ❌ Local (copiado)
|
|
101
|
+
├── .gradle/, .idea/ ← ❌ Ignorados
|
|
102
|
+
└── build/ ← ❌ Ignorado
|
|
103
|
+
```
|
package/android/build.gradle
CHANGED
|
@@ -1,52 +1,54 @@
|
|
|
1
|
-
|
|
1
|
+
plugins {
|
|
2
|
+
id 'com.android.library'
|
|
3
|
+
id 'org.jetbrains.kotlin.android'
|
|
4
|
+
}
|
|
2
5
|
|
|
3
|
-
group = 'expo.
|
|
6
|
+
group = 'sincpro.expo.printer'
|
|
4
7
|
version = '0.1.0'
|
|
5
8
|
|
|
6
|
-
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
7
|
-
apply from: expoModulesCorePlugin
|
|
8
|
-
applyKotlinExpoModulesCorePlugin()
|
|
9
|
-
useCoreDependencies()
|
|
10
|
-
useExpoPublishing()
|
|
11
|
-
|
|
12
|
-
// If you want to use the managed Android SDK versions from expo-modules-core, set this to true.
|
|
13
|
-
// The Android SDK versions will be bumped from time to time in SDK releases and may introduce breaking changes in your module code.
|
|
14
|
-
// Most of the time, you may like to manage the Android SDK versions yourself.
|
|
15
|
-
def useManagedAndroidSdkVersions = false
|
|
16
|
-
if (useManagedAndroidSdkVersions) {
|
|
17
|
-
useDefaultAndroidSdkVersions()
|
|
18
|
-
} else {
|
|
19
|
-
buildscript {
|
|
20
|
-
// Simple helper that allows the root project to override versions declared by this library.
|
|
21
|
-
ext.safeExtGet = { prop, fallback ->
|
|
22
|
-
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
project.android {
|
|
26
|
-
compileSdkVersion safeExtGet("compileSdkVersion", 34)
|
|
27
|
-
defaultConfig {
|
|
28
|
-
minSdkVersion safeExtGet("minSdkVersion", 21)
|
|
29
|
-
targetSdkVersion safeExtGet("targetSdkVersion", 34)
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
9
|
android {
|
|
35
|
-
namespace "expo.
|
|
10
|
+
namespace "sincpro.expo.printer"
|
|
11
|
+
compileSdk 35
|
|
12
|
+
|
|
36
13
|
defaultConfig {
|
|
14
|
+
minSdk 21
|
|
15
|
+
targetSdk 35
|
|
37
16
|
versionCode 1
|
|
38
17
|
versionName "0.1.0"
|
|
39
18
|
}
|
|
19
|
+
|
|
20
|
+
compileOptions {
|
|
21
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
22
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
kotlinOptions {
|
|
26
|
+
jvmTarget = '17'
|
|
27
|
+
}
|
|
28
|
+
|
|
40
29
|
lintOptions {
|
|
41
30
|
abortOnError false
|
|
42
31
|
}
|
|
43
32
|
}
|
|
44
33
|
|
|
45
34
|
dependencies {
|
|
46
|
-
// Bixolon
|
|
47
|
-
implementation
|
|
35
|
+
// Sincpro Printer SDK (incluye Bixolon JARs + jniLibs embebidos)
|
|
36
|
+
implementation files('libs/sincpro-printer-sdk.aar')
|
|
48
37
|
|
|
49
|
-
//
|
|
38
|
+
// Bixolon PDF support (AAR no puede embeber otro AAR)
|
|
39
|
+
implementation files('libs/pdf/Bixolon_pdf.aar')
|
|
40
|
+
|
|
41
|
+
// Expo modules (provided by host app)
|
|
42
|
+
compileOnly 'expo.modules:modules-core'
|
|
43
|
+
|
|
50
44
|
implementation 'androidx.core:core-ktx:1.12.0'
|
|
51
45
|
implementation 'androidx.appcompat:appcompat:1.6.1'
|
|
46
|
+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
|
|
47
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
|
48
|
+
}
|
|
49
|
+
repositories {
|
|
50
|
+
mavenCentral()
|
|
51
|
+
}
|
|
52
|
+
kotlin {
|
|
53
|
+
jvmToolchain(17)
|
|
52
54
|
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
package sincpro.expo.printer.entrypoint
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import com.sincpro.printer.SincproPrinterSdk
|
|
5
|
+
import com.sincpro.printer.domain.Alignment
|
|
6
|
+
import com.sincpro.printer.domain.BarcodeType
|
|
7
|
+
import com.sincpro.printer.domain.FontSize
|
|
8
|
+
import com.sincpro.printer.domain.MediaConfig
|
|
9
|
+
import com.sincpro.printer.domain.Receipt
|
|
10
|
+
import com.sincpro.printer.domain.ReceiptLine
|
|
11
|
+
import expo.modules.kotlin.modules.Module
|
|
12
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
13
|
+
|
|
14
|
+
class PrinterModule : Module() {
|
|
15
|
+
private lateinit var sdk: SincproPrinterSdk
|
|
16
|
+
|
|
17
|
+
override fun definition() =
|
|
18
|
+
ModuleDefinition {
|
|
19
|
+
Name("SincproPrinter")
|
|
20
|
+
|
|
21
|
+
OnCreate {
|
|
22
|
+
val context = appContext.reactContext as Context
|
|
23
|
+
sdk = SincproPrinterSdk(context)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ============================================================
|
|
27
|
+
// BLUETOOTH API
|
|
28
|
+
// ============================================================
|
|
29
|
+
|
|
30
|
+
Function("getPairedDevices") {
|
|
31
|
+
sdk.bixolon.connectivity
|
|
32
|
+
.getPairedDevices()
|
|
33
|
+
.map { devices ->
|
|
34
|
+
devices.map { device ->
|
|
35
|
+
mapOf(
|
|
36
|
+
"name" to device.name,
|
|
37
|
+
"address" to device.address,
|
|
38
|
+
"isPrinter" to device.isPrinter,
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
}.getOrElse { emptyList() }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
Function("getPairedPrinters") {
|
|
45
|
+
sdk.bixolon.connectivity
|
|
46
|
+
.getPairedPrinters()
|
|
47
|
+
.map { printers ->
|
|
48
|
+
printers.map { printer ->
|
|
49
|
+
mapOf(
|
|
50
|
+
"name" to printer.name,
|
|
51
|
+
"address" to printer.address,
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
}.getOrElse { emptyList() }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ============================================================
|
|
58
|
+
// CONNECTION API
|
|
59
|
+
// ============================================================
|
|
60
|
+
|
|
61
|
+
AsyncFunction("connectBluetooth") { address: String, timeoutMs: Double? ->
|
|
62
|
+
sdk.bixolon.connectivity
|
|
63
|
+
.connectBluetooth(
|
|
64
|
+
address = address,
|
|
65
|
+
timeoutMs = timeoutMs?.toLong() ?: 10000,
|
|
66
|
+
).getOrThrow()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
AsyncFunction("connectWifi") { ip: String, port: Int?, timeoutMs: Double? ->
|
|
70
|
+
sdk.bixolon.connectivity
|
|
71
|
+
.connectWifi(
|
|
72
|
+
ip = ip,
|
|
73
|
+
port = port ?: 9100,
|
|
74
|
+
timeoutMs = timeoutMs?.toLong() ?: 10000,
|
|
75
|
+
).getOrThrow()
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
AsyncFunction("connectUsb") {
|
|
79
|
+
sdk.bixolon.connectivity
|
|
80
|
+
.connectUsb()
|
|
81
|
+
.getOrThrow()
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
AsyncFunction("disconnect") {
|
|
85
|
+
sdk.bixolon.connectivity
|
|
86
|
+
.disconnect()
|
|
87
|
+
.getOrThrow()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
Function("isConnected") {
|
|
91
|
+
sdk.bixolon.connectivity.isConnected()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
AsyncFunction("getStatus") {
|
|
95
|
+
val status =
|
|
96
|
+
sdk.bixolon.connectivity
|
|
97
|
+
.getStatus()
|
|
98
|
+
.getOrThrow()
|
|
99
|
+
mapOf(
|
|
100
|
+
"connectionState" to status.connectionState.name,
|
|
101
|
+
"hasPaper" to status.hasPaper,
|
|
102
|
+
"isCoverOpen" to status.isCoverOpen,
|
|
103
|
+
"isOverheated" to status.isOverheated,
|
|
104
|
+
"hasError" to status.hasError,
|
|
105
|
+
"errorMessage" to status.errorMessage,
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
AsyncFunction("getInfo") {
|
|
110
|
+
val info =
|
|
111
|
+
sdk.bixolon.connectivity
|
|
112
|
+
.getInfo()
|
|
113
|
+
.getOrThrow()
|
|
114
|
+
mapOf(
|
|
115
|
+
"model" to info.model,
|
|
116
|
+
"firmware" to info.firmware,
|
|
117
|
+
"serial" to info.serial,
|
|
118
|
+
"dpi" to info.dpi,
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
Function("getDpi") {
|
|
123
|
+
sdk.bixolon.connectivity.getDpi()
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ============================================================
|
|
127
|
+
// PRINT API - Text
|
|
128
|
+
// ============================================================
|
|
129
|
+
|
|
130
|
+
AsyncFunction("printText") { text: String, options: Map<String, Any?>? ->
|
|
131
|
+
val fontSize = parseFontSize(options?.get("fontSize") as? String)
|
|
132
|
+
val alignment = parseAlignment(options?.get("alignment") as? String)
|
|
133
|
+
val bold = options?.get("bold") as? Boolean ?: false
|
|
134
|
+
val media = parseMediaConfig(options?.get("media") as? Map<String, Any?>)
|
|
135
|
+
|
|
136
|
+
sdk.bixolon.print
|
|
137
|
+
.printText(text, fontSize, alignment, bold, media)
|
|
138
|
+
.getOrThrow()
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
AsyncFunction("printTexts") { texts: List<String>, options: Map<String, Any?>? ->
|
|
142
|
+
val fontSize = parseFontSize(options?.get("fontSize") as? String)
|
|
143
|
+
val media = parseMediaConfig(options?.get("media") as? Map<String, Any?>)
|
|
144
|
+
|
|
145
|
+
sdk.bixolon.print
|
|
146
|
+
.printTexts(texts, fontSize, media)
|
|
147
|
+
.getOrThrow()
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// ============================================================
|
|
151
|
+
// PRINT API - QR & Barcode
|
|
152
|
+
// ============================================================
|
|
153
|
+
|
|
154
|
+
AsyncFunction("printQR") { data: String, options: Map<String, Any?>? ->
|
|
155
|
+
val size = (options?.get("size") as? Number)?.toInt() ?: 5
|
|
156
|
+
val alignment = parseAlignment(options?.get("alignment") as? String)
|
|
157
|
+
val media = parseMediaConfig(options?.get("media") as? Map<String, Any?>)
|
|
158
|
+
|
|
159
|
+
sdk.bixolon.print
|
|
160
|
+
.printQR(data, size, alignment, media)
|
|
161
|
+
.getOrThrow()
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
AsyncFunction("printBarcode") { data: String, options: Map<String, Any?>? ->
|
|
165
|
+
val type = parseBarcodeType(options?.get("type") as? String)
|
|
166
|
+
val height = (options?.get("height") as? Number)?.toInt() ?: 60
|
|
167
|
+
val alignment = parseAlignment(options?.get("alignment") as? String)
|
|
168
|
+
val media = parseMediaConfig(options?.get("media") as? Map<String, Any?>)
|
|
169
|
+
|
|
170
|
+
sdk.bixolon.print
|
|
171
|
+
.printBarcode(data, type, height, alignment, media)
|
|
172
|
+
.getOrThrow()
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ============================================================
|
|
176
|
+
// PRINT API - Images & PDF
|
|
177
|
+
// ============================================================
|
|
178
|
+
|
|
179
|
+
AsyncFunction("printImageBase64") { base64Data: String, options: Map<String, Any?>? ->
|
|
180
|
+
val alignment = parseAlignment(options?.get("alignment") as? String)
|
|
181
|
+
val media = parseMediaConfig(options?.get("media") as? Map<String, Any?>)
|
|
182
|
+
|
|
183
|
+
sdk.bixolon.print
|
|
184
|
+
.printImageBase64(base64Data, alignment, media)
|
|
185
|
+
.getOrThrow()
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
AsyncFunction("printPdfBase64") { base64Data: String, options: Map<String, Any?>? ->
|
|
189
|
+
val page = (options?.get("page") as? Number)?.toInt() ?: 1
|
|
190
|
+
val alignment = parseAlignment(options?.get("alignment") as? String)
|
|
191
|
+
val media = parseMediaConfig(options?.get("media") as? Map<String, Any?>)
|
|
192
|
+
|
|
193
|
+
sdk.bixolon.print
|
|
194
|
+
.printPdfBase64(base64Data, page, alignment, media)
|
|
195
|
+
.getOrThrow()
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
Function("getPdfPageCount") { base64Data: String ->
|
|
199
|
+
sdk.bixolon.print.getPdfPageCount(base64Data)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// ============================================================
|
|
203
|
+
// PRINT API - Receipt (High Level)
|
|
204
|
+
// ============================================================
|
|
205
|
+
|
|
206
|
+
AsyncFunction("printReceipt") { receiptData: Map<String, Any?>, options: Map<String, Any?>? ->
|
|
207
|
+
val receipt = parseReceipt(receiptData)
|
|
208
|
+
val media = parseMediaConfig(options?.get("media") as? Map<String, Any?>)
|
|
209
|
+
val copies = (options?.get("copies") as? Number)?.toInt() ?: 1
|
|
210
|
+
|
|
211
|
+
sdk.bixolon.print
|
|
212
|
+
.printReceipt(receipt, media, copies)
|
|
213
|
+
.getOrThrow()
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ============================================================
|
|
217
|
+
// PRINT API - Columns (Key-Value style)
|
|
218
|
+
// ============================================================
|
|
219
|
+
|
|
220
|
+
AsyncFunction("printKeyValue") { key: String, value: String, options: Map<String, Any?>? ->
|
|
221
|
+
val fontSize = parseFontSize(options?.get("fontSize") as? String)
|
|
222
|
+
val bold = options?.get("bold") as? Boolean ?: false
|
|
223
|
+
val media = parseMediaConfig(options?.get("media") as? Map<String, Any?>)
|
|
224
|
+
|
|
225
|
+
sdk.bixolon.print
|
|
226
|
+
.printKeyValue(key, value, fontSize, bold, media)
|
|
227
|
+
.getOrThrow()
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ============================================================
|
|
232
|
+
// PARSERS
|
|
233
|
+
// ============================================================
|
|
234
|
+
|
|
235
|
+
private fun parseFontSize(value: String?): FontSize =
|
|
236
|
+
when (value?.lowercase()) {
|
|
237
|
+
"small" -> FontSize.SMALL
|
|
238
|
+
"medium" -> FontSize.MEDIUM
|
|
239
|
+
"large" -> FontSize.LARGE
|
|
240
|
+
"xlarge" -> FontSize.XLARGE
|
|
241
|
+
else -> FontSize.MEDIUM
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
private fun parseAlignment(value: String?): Alignment =
|
|
245
|
+
when (value?.lowercase()) {
|
|
246
|
+
"left" -> Alignment.LEFT
|
|
247
|
+
"center" -> Alignment.CENTER
|
|
248
|
+
"right" -> Alignment.RIGHT
|
|
249
|
+
else -> Alignment.LEFT
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
private fun parseBarcodeType(value: String?): BarcodeType =
|
|
253
|
+
when (value?.uppercase()) {
|
|
254
|
+
"CODE128" -> BarcodeType.CODE128
|
|
255
|
+
"CODE39" -> BarcodeType.CODE39
|
|
256
|
+
"EAN13" -> BarcodeType.EAN13
|
|
257
|
+
"EAN8" -> BarcodeType.EAN8
|
|
258
|
+
"UPCA" -> BarcodeType.UPCA
|
|
259
|
+
"UPCE" -> BarcodeType.UPCE
|
|
260
|
+
"CODE93" -> BarcodeType.CODE93
|
|
261
|
+
"CODABAR" -> BarcodeType.CODABAR
|
|
262
|
+
else -> BarcodeType.CODE128
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
private fun parseMediaConfig(data: Map<String, Any?>?): MediaConfig {
|
|
266
|
+
if (data == null) return MediaConfig.continuous80mm()
|
|
267
|
+
|
|
268
|
+
val preset = data["preset"] as? String
|
|
269
|
+
if (preset != null) {
|
|
270
|
+
return when (preset) {
|
|
271
|
+
"continuous58mm" -> MediaConfig.continuous58mm()
|
|
272
|
+
"continuous80mm" -> MediaConfig.continuous80mm()
|
|
273
|
+
else -> MediaConfig.continuous80mm()
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
val widthDots = (data["widthDots"] as? Number)?.toInt() ?: 640
|
|
278
|
+
val heightDots = (data["heightDots"] as? Number)?.toInt() ?: 0
|
|
279
|
+
|
|
280
|
+
return MediaConfig(widthDots, heightDots)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
private fun parseReceipt(data: Map<String, Any?>): Receipt {
|
|
284
|
+
val header = parseReceiptLines(data["header"] as? List<*>)
|
|
285
|
+
val body = parseReceiptLines(data["body"] as? List<*>)
|
|
286
|
+
val footer = parseReceiptLines(data["footer"] as? List<*>)
|
|
287
|
+
|
|
288
|
+
return Receipt(header, body, footer)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private fun parseReceiptLines(data: List<*>?): List<ReceiptLine> {
|
|
292
|
+
if (data == null) return emptyList()
|
|
293
|
+
|
|
294
|
+
return data.mapNotNull { item ->
|
|
295
|
+
val lineData = item as? Map<String, Any?> ?: return@mapNotNull null
|
|
296
|
+
parseReceiptLine(lineData)
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
private fun parseReceiptLine(data: Map<String, Any?>): ReceiptLine? {
|
|
301
|
+
val type = data["type"] as? String ?: return null
|
|
302
|
+
|
|
303
|
+
return when (type) {
|
|
304
|
+
"text" -> {
|
|
305
|
+
ReceiptLine.Text(
|
|
306
|
+
content = data["content"] as? String ?: "",
|
|
307
|
+
fontSize = parseFontSize(data["fontSize"] as? String),
|
|
308
|
+
bold = data["bold"] as? Boolean ?: false,
|
|
309
|
+
alignment = parseAlignment(data["alignment"] as? String),
|
|
310
|
+
)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
"keyValue" -> {
|
|
314
|
+
ReceiptLine.KeyValue(
|
|
315
|
+
key = data["key"] as? String ?: "",
|
|
316
|
+
value = data["value"] as? String ?: "",
|
|
317
|
+
fontSize = parseFontSize(data["fontSize"] as? String),
|
|
318
|
+
bold = data["bold"] as? Boolean ?: false,
|
|
319
|
+
)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
"qr" -> {
|
|
323
|
+
ReceiptLine.QR(
|
|
324
|
+
data = data["data"] as? String ?: "",
|
|
325
|
+
size = (data["size"] as? Number)?.toInt() ?: 5,
|
|
326
|
+
alignment = parseAlignment(data["alignment"] as? String),
|
|
327
|
+
)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
"barcode" -> {
|
|
331
|
+
ReceiptLine.Barcode(
|
|
332
|
+
data = data["data"] as? String ?: "",
|
|
333
|
+
type = parseBarcodeType(data["barcodeType"] as? String),
|
|
334
|
+
height = (data["height"] as? Number)?.toInt() ?: 60,
|
|
335
|
+
alignment = parseAlignment(data["alignment"] as? String),
|
|
336
|
+
)
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
"image" -> {
|
|
340
|
+
val base64 = data["base64"] as? String ?: return null
|
|
341
|
+
val bitmap =
|
|
342
|
+
com.sincpro.printer.infrastructure.BinaryConverter
|
|
343
|
+
.base64ToBitmap(base64)
|
|
344
|
+
?: return null
|
|
345
|
+
ReceiptLine.Image(
|
|
346
|
+
bitmap = bitmap,
|
|
347
|
+
alignment = parseAlignment(data["alignment"] as? String),
|
|
348
|
+
)
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
"separator" -> {
|
|
352
|
+
ReceiptLine.Separator(
|
|
353
|
+
char = (data["char"] as? String)?.firstOrNull() ?: '-',
|
|
354
|
+
length = (data["length"] as? Number)?.toInt() ?: 48,
|
|
355
|
+
)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
"space" -> {
|
|
359
|
+
ReceiptLine.Space(
|
|
360
|
+
lines = (data["lines"] as? Number)?.toInt() ?: 1,
|
|
361
|
+
)
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
"columns" -> {
|
|
365
|
+
val columnsData = data["columns"] as? List<*> ?: return null
|
|
366
|
+
val columns =
|
|
367
|
+
columnsData.mapNotNull { col ->
|
|
368
|
+
val colData = col as? Map<String, Any?> ?: return@mapNotNull null
|
|
369
|
+
ReceiptLine.Column(
|
|
370
|
+
text = colData["text"] as? String ?: "",
|
|
371
|
+
widthRatio = (colData["widthRatio"] as? Number)?.toFloat() ?: 0.5f,
|
|
372
|
+
alignment = parseAlignment(colData["alignment"] as? String),
|
|
373
|
+
)
|
|
374
|
+
}
|
|
375
|
+
ReceiptLine.Columns(
|
|
376
|
+
columns = columns,
|
|
377
|
+
fontSize = parseFontSize(data["fontSize"] as? String),
|
|
378
|
+
bold = data["bold"] as? Boolean ?: false,
|
|
379
|
+
)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
else -> {
|
|
383
|
+
null
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|