boot-nemonic-printer 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.
- package/.eslintrc.js +5 -0
- package/README.md +209 -0
- package/ai/example-ui-card-refactor.md +348 -0
- package/android/build.gradle +22 -0
- package/android/libs/NemonicSdk.aar +0 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/net/eventboot/nemonicprinter/BootNemonicPrinterModule.kt +509 -0
- package/build/BootNemonicPrinter.types.d.ts +44 -0
- package/build/BootNemonicPrinter.types.d.ts.map +1 -0
- package/build/BootNemonicPrinter.types.js +2 -0
- package/build/BootNemonicPrinter.types.js.map +1 -0
- package/build/BootNemonicPrinterModule.d.ts +36 -0
- package/build/BootNemonicPrinterModule.d.ts.map +1 -0
- package/build/BootNemonicPrinterModule.js +3 -0
- package/build/BootNemonicPrinterModule.js.map +1 -0
- package/build/constants/NBatteryStatus.d.ts +8 -0
- package/build/constants/NBatteryStatus.d.ts.map +1 -0
- package/build/constants/NBatteryStatus.js +7 -0
- package/build/constants/NBatteryStatus.js.map +1 -0
- package/build/constants/NCartridgeType.d.ts +35 -0
- package/build/constants/NCartridgeType.d.ts.map +1 -0
- package/build/constants/NCartridgeType.js +183 -0
- package/build/constants/NCartridgeType.js.map +1 -0
- package/build/constants/NConnectState.d.ts +8 -0
- package/build/constants/NConnectState.d.ts.map +1 -0
- package/build/constants/NConnectState.js +7 -0
- package/build/constants/NConnectState.js.map +1 -0
- package/build/constants/NPowerSaveMode.d.ts +6 -0
- package/build/constants/NPowerSaveMode.d.ts.map +1 -0
- package/build/constants/NPowerSaveMode.js +5 -0
- package/build/constants/NPowerSaveMode.js.map +1 -0
- package/build/constants/NPrintImageLength.d.ts +12 -0
- package/build/constants/NPrintImageLength.d.ts.map +1 -0
- package/build/constants/NPrintImageLength.js +12 -0
- package/build/constants/NPrintImageLength.js.map +1 -0
- package/build/constants/NPrintQuality.d.ts +7 -0
- package/build/constants/NPrintQuality.d.ts.map +1 -0
- package/build/constants/NPrintQuality.js +6 -0
- package/build/constants/NPrintQuality.js.map +1 -0
- package/build/constants/NPrinterStatus.d.ts +9 -0
- package/build/constants/NPrinterStatus.d.ts.map +1 -0
- package/build/constants/NPrinterStatus.js +8 -0
- package/build/constants/NPrinterStatus.js.map +1 -0
- package/build/constants/NPrinterType.d.ts +9 -0
- package/build/constants/NPrinterType.d.ts.map +1 -0
- package/build/constants/NPrinterType.js +8 -0
- package/build/constants/NPrinterType.js.map +1 -0
- package/build/constants/NResult.d.ts +51 -0
- package/build/constants/NResult.d.ts.map +1 -0
- package/build/constants/NResult.js +50 -0
- package/build/constants/NResult.js.map +1 -0
- package/build/index.d.ts +13 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +13 -0
- package/build/index.js.map +1 -0
- package/expo-module.config.json +9 -0
- package/ios/BootNemonicPrinter.podspec +31 -0
- package/ios/BootNemonicPrinterModule.swift +257 -0
- package/ios/Frameworks/NemonicSdk.framework/Headers/NemonicSdk-Swift.h +797 -0
- package/ios/Frameworks/NemonicSdk.framework/Headers/NemonicSdk.h +18 -0
- package/ios/Frameworks/NemonicSdk.framework/Info.plist +0 -0
- package/ios/Frameworks/NemonicSdk.framework/Modules/NemonicSdk.swiftmodule/Project/arm64-apple-ios.swiftsourceinfo +0 -0
- package/ios/Frameworks/NemonicSdk.framework/Modules/NemonicSdk.swiftmodule/arm64-apple-ios.abi.json +12244 -0
- package/ios/Frameworks/NemonicSdk.framework/Modules/NemonicSdk.swiftmodule/arm64-apple-ios.private.swiftinterface +356 -0
- package/ios/Frameworks/NemonicSdk.framework/Modules/NemonicSdk.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
- package/ios/Frameworks/NemonicSdk.framework/Modules/NemonicSdk.swiftmodule/arm64-apple-ios.swiftinterface +356 -0
- package/ios/Frameworks/NemonicSdk.framework/Modules/NemonicSdk.swiftmodule/arm64-apple-ios.swiftmodule +0 -0
- package/ios/Frameworks/NemonicSdk.framework/Modules/module.modulemap +11 -0
- package/ios/Frameworks/NemonicSdk.framework/NemonicSdk +0 -0
- package/ios/Frameworks/NemonicSdk.framework/_CodeSignature/CodeResources +237 -0
- package/package.json +44 -0
- package/src/BootNemonicPrinter.types.ts +50 -0
- package/src/BootNemonicPrinterModule.ts +48 -0
- package/src/constants/NBatteryStatus.ts +8 -0
- package/src/constants/NCartridgeType.ts +181 -0
- package/src/constants/NConnectState.ts +8 -0
- package/src/constants/NPowerSaveMode.ts +6 -0
- package/src/constants/NPrintImageLength.ts +11 -0
- package/src/constants/NPrintQuality.ts +7 -0
- package/src/constants/NPrinterStatus.ts +9 -0
- package/src/constants/NPrinterType.ts +9 -0
- package/src/constants/NResult.ts +51 -0
- package/src/index.ts +13 -0
- package/tsconfig.json +9 -0
package/.eslintrc.js
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# example 앱 iOS 실기기 설치 트러블슈팅
|
|
2
|
+
|
|
3
|
+
`example/` 앱을 실제 iPhone 에 설치할 때 자주 마주치는 오류와 해결 절차를 정리합니다.
|
|
4
|
+
|
|
5
|
+
실행 명령은 항상 `example/` 디렉터리에서:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
cd example
|
|
9
|
+
npm run ios -- --device
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 1. `No code signing certificates are available to use.`
|
|
15
|
+
|
|
16
|
+
### 원인
|
|
17
|
+
Apple Developer 계정 / 서명 인증서가 Xcode 에 설정되지 않은 상태에서 실기기 빌드를 시도할 때 발생. 시뮬레이터 빌드에서는 발생하지 않음.
|
|
18
|
+
|
|
19
|
+
### 해결 절차
|
|
20
|
+
|
|
21
|
+
**1) Xcode 에 Apple ID 등록** (최초 1 회)
|
|
22
|
+
|
|
23
|
+
1. Xcode 실행
|
|
24
|
+
2. 메뉴 `Xcode` → `Settings…` → `Accounts` 탭
|
|
25
|
+
3. 좌측 하단 `+` 클릭 → `Apple ID` 선택 → 로그인
|
|
26
|
+
4. 등록되면 `Personal Team` (무료 계정) 또는 가입된 `Apple Developer Program` 팀이 표시됨
|
|
27
|
+
|
|
28
|
+
**2) 프로젝트에 Team 지정**
|
|
29
|
+
|
|
30
|
+
프로젝트 루트에서:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm run open:ios
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
→ Xcode 가 `example/ios/bootnemonicprinterexample.xcworkspace` 를 자동으로 엽니다.
|
|
37
|
+
|
|
38
|
+
1. 좌측 Navigator 최상단 `bootnemonicprinterexample` 프로젝트 선택
|
|
39
|
+
2. `TARGETS` → `bootnemonicprinterexample` 타겟 선택
|
|
40
|
+
3. `Signing & Capabilities` 탭 열기
|
|
41
|
+
4. `Automatically manage signing` 체크 유지
|
|
42
|
+
5. `Team` 드롭다운에서 등록한 계정 선택
|
|
43
|
+
6. Xcode 가 provisioning profile 을 자동 생성할 때까지 잠시 대기
|
|
44
|
+
|
|
45
|
+
**3) Bundle Identifier 충돌 시**
|
|
46
|
+
|
|
47
|
+
`net.eventboot.nemonicprinter.example` 가 이미 다른 사람의 계정에 등록돼 있으면 빨간 오류가 표시됨. 본인만 쓰는 식별자로 변경:
|
|
48
|
+
|
|
49
|
+
- `example/app.json` 의 `ios.bundleIdentifier` 를 `net.eventboot.nemonicprinter.example.<이니셜>` 등으로 수정
|
|
50
|
+
- 이후 `example/` 에서 `npx expo prebuild --platform ios --clean` 으로 ios/ 재생성
|
|
51
|
+
(또는 Xcode 의 `Bundle Identifier` 필드를 직접 수정)
|
|
52
|
+
|
|
53
|
+
**4) 무료 계정으로 설치 시 — 기기에서 "신뢰" 설정**
|
|
54
|
+
|
|
55
|
+
첫 설치 후 iPhone 에서 앱 실행 시 "신뢰할 수 없는 개발자" 경고가 뜨면:
|
|
56
|
+
|
|
57
|
+
- iPhone → `설정` → `일반` → `VPN 및 기기 관리` → 본인 Apple ID 선택 → `신뢰`
|
|
58
|
+
|
|
59
|
+
**5) 다시 빌드**
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
cd example
|
|
63
|
+
npm run ios -- --device
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 2. `The developer disk image could not be mounted on this device.`
|
|
69
|
+
|
|
70
|
+
### 원인
|
|
71
|
+
iOS 17+ 부터 Apple 은 Developer Disk Image (DDI) 를 Xcode 가 인터넷에서 자동 다운로드해 마운트합니다. 첫 연결 시, 또는 iOS / Xcode 업데이트 직후 자주 실패합니다.
|
|
72
|
+
|
|
73
|
+
> 버전 호환 확인: `xcodebuild -version` 의 Xcode 메이저 버전이 iPhone 의 iOS 메이저 버전 이상이어야 함. (예: iOS 26.x 디바이스에는 Xcode 26.x 이상 필요)
|
|
74
|
+
|
|
75
|
+
### 해결 절차
|
|
76
|
+
|
|
77
|
+
**1) 기본 점검**
|
|
78
|
+
|
|
79
|
+
- Mac 이 인터넷에 연결돼 있는지 확인 (DDI 다운로드용)
|
|
80
|
+
- iPhone 잠금을 해제하고 그대로 유지 (잠기면 마운트가 중단됨)
|
|
81
|
+
|
|
82
|
+
**2) 케이블 재연결 + 신뢰 재확인**
|
|
83
|
+
|
|
84
|
+
- iPhone 케이블 분리 → 재연결
|
|
85
|
+
- iPhone 에 "이 컴퓨터를 신뢰하시겠습니까?" 가 뜨면 `신뢰` → 암호 입력
|
|
86
|
+
|
|
87
|
+
**3) Xcode 의 디바이스 준비 완료 대기** (가장 중요)
|
|
88
|
+
|
|
89
|
+
- Xcode 메뉴 `Window` → `Devices and Simulators` (단축키 `⇧⌘2`)
|
|
90
|
+
- 좌측 사이드바에서 본인 iPhone 선택
|
|
91
|
+
- 우측 상단에 다음과 같은 진행 표시가 나타남:
|
|
92
|
+
- `Preparing iPhone for development…`
|
|
93
|
+
- `Fetching debug symbols`
|
|
94
|
+
- **5 ~ 15 분 소요** (첫 연결 시 특히 오래 걸림). 끝까지 기다릴 것
|
|
95
|
+
- 완료되면 디바이스 이름 옆 노란 경고 표시가 사라지고 `Connected via …` 만 남음
|
|
96
|
+
|
|
97
|
+
> ⚠️ 이 단계가 완료되기 전에 빌드를 시도하면 그대로 `developer disk image` 오류가 발생합니다.
|
|
98
|
+
|
|
99
|
+
**4) Platforms 다운로드 상태 확인**
|
|
100
|
+
|
|
101
|
+
- Xcode → `Settings` → `Platforms` 탭
|
|
102
|
+
- 본인 iPhone 의 iOS 메이저 버전 (예: `iOS 26.x`) 항목이 표시되고 다운로드 완료 상태인지 확인
|
|
103
|
+
- 누락돼 있으면 `Get` 클릭 후 다운로드
|
|
104
|
+
|
|
105
|
+
**5) 위 절차 후에도 실패 시**
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Xcode 종료 후 DerivedData 삭제
|
|
109
|
+
rm -rf ~/Library/Developer/Xcode/DerivedData/*
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
추가로:
|
|
113
|
+
|
|
114
|
+
- iPhone 재부팅 (전원 끄고 30 초 후 재시작)
|
|
115
|
+
- Mac 재부팅
|
|
116
|
+
- Xcode 재실행 → `Window > Devices and Simulators` 로 다시 준비 대기
|
|
117
|
+
|
|
118
|
+
**6) 재시도**
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
cd example
|
|
122
|
+
npm run ios -- --device
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 3. `print()` 결과가 `-64` 로 떨어짐 (iOS / Android 공통)
|
|
128
|
+
|
|
129
|
+
### 증상
|
|
130
|
+
|
|
131
|
+
BLE 연결 후 인쇄를 호출하면 프린터에서는 라벨이 정상 출력되지만 JS 측에는 짧은 시간 안에 `-64` 가 반환됨:
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
[NemonicPrintTimer-JS] #7 T+5118ms ◀ native print() resolved (result=-64)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
iOS, Android 모두 동일하게 재현됨.
|
|
138
|
+
|
|
139
|
+
### 원인
|
|
140
|
+
|
|
141
|
+
`-64` = NemonicSdk 의 `NResult.TIMEOUT`. SDK 가 한 페이지 인쇄 후 프린터의 완료 ACK 를 기다리다 시간을 초과하면 이 값을 반환.
|
|
142
|
+
|
|
143
|
+
`example/App.tsx` 가 과거에 connect 직후 `setPrintTimeout(false, 100)` 으로 ACK 대기 시간을 100ms 로 짧게 강제하던 워크어라운드를 사용해서, 실제 프린터 ACK 가 도착하기 전에 SDK 가 타임아웃 처리하면서 `-64` 를 반환했음. BLE 로 데이터는 이미 전송됐기 때문에 프린터에서는 출력이 끝까지 진행되지만 JS 입장에서는 성공/실패 구분이 불가능했음.
|
|
144
|
+
|
|
145
|
+
추가로, 짧은 타임아웃은 `onPrintComplete` 이벤트도 timeout 시점에 발화시켜 "프린터 완료 신호로 인쇄 버튼 활성화" 같은 게이팅이 실제 인쇄 끝과 어긋나는 문제도 일으킴.
|
|
146
|
+
|
|
147
|
+
### 해결
|
|
148
|
+
|
|
149
|
+
iOS / Android(BLE) 는 충분히 긴 타임아웃 (30 초), **Android USB 는 3 초** 로 분기 — 이 example 코드에는 이미 적용돼 있음:
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
// example/App.tsx connect() 내부
|
|
153
|
+
const isAndroidUsb = Platform.OS === 'android' && transport === 'usb';
|
|
154
|
+
const PRINT_TIMEOUT_MS = isAndroidUsb ? 3000 : 30000;
|
|
155
|
+
BootNemonicPrinter.setPrintTimeout(false, PRINT_TIMEOUT_MS);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
| 환경 | manualTime | 동작 |
|
|
159
|
+
| --- | --- | --- |
|
|
160
|
+
| iOS (BLE) | 30000 (30 초) | ACK 받고 진짜 결과 코드 반환 (OK / -81 / -101 / ...) |
|
|
161
|
+
| Android (BLE) | 30000 (30 초) | 동일 |
|
|
162
|
+
| Android (USB) | 3000 (3 초) | SDK 가 ACK 못 받아 항상 timeout 발생 — 짧게 잡아 UX 보호. `result=-64` 지만 인쇄는 정상 |
|
|
163
|
+
|
|
164
|
+
### Android USB 의 특수 사항
|
|
165
|
+
|
|
166
|
+
> Android + USB 조합은 SDK 가 인쇄 완료 ACK 를 받지 못해 **`setPrintTimeout` 으로 설정한 시간만큼 무조건 대기 후 `-64` 를 반환**. BLE 처럼 "ACK 도착 즉시 반환" 이 동작하지 않음.
|
|
167
|
+
>
|
|
168
|
+
> SDK 가 클로즈드 소스라 추정 원인:
|
|
169
|
+
>
|
|
170
|
+
> - BLE 는 GATT notification 으로 프린터가 인쇄 완료 신호를 양방향 publish → SDK 가 즉시 인지
|
|
171
|
+
> - USB 는 SDK 의 IN endpoint 응답 처리가 없거나 프린터 펌웨어가 USB 모드에서 상태 응답을 보내지 않음 → SDK 는 timeout 까지 대기
|
|
172
|
+
>
|
|
173
|
+
> 모듈/앱 코드 레벨에서 우회 불가 — `setPrintTimeout` 값을 줄여 대기 시간만 단축하는 게 현실적 해결책.
|
|
174
|
+
|
|
175
|
+
이 때문에 USB 에서는 다음 점도 인지하고 설계할 것:
|
|
176
|
+
|
|
177
|
+
- `print()` 결과로 성공/실패 판정 불가 — 항상 `-64`
|
|
178
|
+
- `onPrintComplete` 이벤트도 timeout 시점 (3 초) 에 발화 — 실제 인쇄 끝과 시간이 다를 수 있음
|
|
179
|
+
- 정확한 완료 시점이 필요하면 별도 메커니즘 필요 (예: 사용자 확인 버튼 등)
|
|
180
|
+
|
|
181
|
+
### 자기 앱에 적용할 때 가이드 (BLE 기준)
|
|
182
|
+
|
|
183
|
+
- **인쇄 성공/실패 판정 + 완료 신호 게이팅이 중요** (기본 권장) → `10000 ~ 30000ms` 로 길게 설정. `await print()` 가 한 페이지당 수 초 블로킹되므로 UI 로딩 상태/취소를 별도로 관리.
|
|
184
|
+
- **빠른 연속 인쇄가 우선**이고 결과 코드 정밀도가 덜 중요하면 짧은 값도 가능 — 단 `-64` 를 "전송 성공, ACK 미수신" 으로 *해석* 만 하면 됨. (Android SDK 일부 버전에서 큰 timeout 값이 다음 print 호출을 늦추는 부작용이 보고된 적 있음. 본인 환경에서 확인 후 결정.)
|
|
185
|
+
|
|
186
|
+
### 참고 — 다른 음수 결과 코드
|
|
187
|
+
|
|
188
|
+
| 코드 | 의미 |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| -64 | TIMEOUT (위 설명) |
|
|
191
|
+
| -81 | UNAVAILABLE_CARTRIDGE (카트리지 미장착/미인식) |
|
|
192
|
+
| -101 | BLUETOOTH_DISABLED |
|
|
193
|
+
| -301 | NOT_CONNECTED |
|
|
194
|
+
|
|
195
|
+
전체 목록은 `ios/Frameworks/NemonicSdk.framework/Headers/NemonicSdk-Swift.h` 의 `NResult` enum, 또는 `src/BootNemonicPrinter.types.ts` 의 `NResult` 참고.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## 빠른 체크리스트
|
|
200
|
+
|
|
201
|
+
실기기 빌드 전:
|
|
202
|
+
|
|
203
|
+
- [ ] Xcode 에 Apple ID 등록 완료
|
|
204
|
+
- [ ] 타겟의 `Signing & Capabilities` 에 Team 지정 완료
|
|
205
|
+
- [ ] `Bundle Identifier` 가 본인 계정에서 사용 가능한 값
|
|
206
|
+
- [ ] iPhone 이 신뢰된 상태로 연결 + 잠금 해제
|
|
207
|
+
- [ ] Xcode `Devices and Simulators` 에서 `Preparing iPhone for development` 완료
|
|
208
|
+
- [ ] Xcode `Settings → Platforms` 에서 iPhone 의 iOS 버전 다운로드 완료
|
|
209
|
+
- [ ] `setPrintTimeout` 값이 충분히 길게(예: 30000ms) 잡혀 있는지 확인 — iOS / Android 공통 (3 번 참고)
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
# example/App.tsx UI 재구성 — bixolon 카드 패턴 도입
|
|
2
|
+
|
|
3
|
+
> 이 문서는 새 세션에서 cold start 로 실행 가능하도록 작성됨. 컨텍스트 / 결정 사항 / 파일 위치 / 검증 절차 전부 포함.
|
|
4
|
+
|
|
5
|
+
## 작업 목적
|
|
6
|
+
|
|
7
|
+
`boot-nemonic-printer/example/App.tsx` 의 UX 를 sibling 프로젝트 `boot-bixolon-printer/example` 의 카드 기반 패턴으로 재편한다. 현재는 "transport 칩(BT/USB) 선택 → 해당 transport 만 스캔 → 리스트 선택 → 하단 설정" 구조인데, 목표는 "디바이스 검색 한 번 → BT/USB 카드 둘 다 보임 → 카드 안 [연결] 탭 → 그 카드가 inline 확장되며 설정/인쇄 노출" 의 1-스텝 흐름.
|
|
8
|
+
|
|
9
|
+
데모/레퍼런스 목적은 유지 — 모든 SDK 호출 패턴/주석/진단 로그는 보존하고 UI 골격만 카드 중심으로 재편한다.
|
|
10
|
+
|
|
11
|
+
## 사용자 확정 결정 사항
|
|
12
|
+
|
|
13
|
+
1. **카드 상호작용**: bixolon 그대로. 카드 안 [연결] 버튼 → 성공 시 설정 패널 inline 노출. **카드 면적 자체를 탭하는 동작은 없음.**
|
|
14
|
+
2. **검색 동작**: 한 번 탭 = BLE 단일-샷 스캔 + USB enumerate 동시 실행, BLE 는 N초 후 자동 stop. (N = 7초 권장; 코드에서 상수로 노출)
|
|
15
|
+
3. **POS/Label 탭 분리**: 채택 안 함. nemonic 은 프린터 타입 1종이므로 BT/USB 섹션 분리로 대체.
|
|
16
|
+
4. **로그 박스, 라벨 미리보기, 명찰 캡쳐+인쇄, 진단 로그**: 전부 현재대로 유지.
|
|
17
|
+
|
|
18
|
+
## 참고 파일 (read-only)
|
|
19
|
+
|
|
20
|
+
새 세션에서 다음 파일들을 먼저 읽어 패턴을 익힐 것:
|
|
21
|
+
|
|
22
|
+
- `/Users/sghong/Documents/work/dev-react-native/boot-bixolon-printer/example/App.tsx` — 컨테이너 패턴 (113줄)
|
|
23
|
+
- `/Users/sghong/Documents/work/dev-react-native/boot-bixolon-printer/example/components/DeviceCardShell.tsx` — 카드 chrome (202줄, 핵심 스타일/구조)
|
|
24
|
+
- `/Users/sghong/Documents/work/dev-react-native/boot-bixolon-printer/example/components/PosDeviceCard.tsx` — 풀 라이프사이클 예시 (필요 시 참고)
|
|
25
|
+
- `/Users/sghong/Documents/work/dev-react-native/boot-nemonic-printer/example/App.tsx` — 현재 nemonic 상태 (출발점)
|
|
26
|
+
|
|
27
|
+
bixolon 의 핵심 시각 신호:
|
|
28
|
+
- 카드 borderLeft: 비연결 `#2196F3`, 연결 `#4caf50` + 배경 `#f1faf1`
|
|
29
|
+
- 권한 pill: 거부 `#ffebee` bg / `#c62828` text, 허용 `#e8f5e9` bg / `#2e7d32` text
|
|
30
|
+
- 카드: `backgroundColor: '#fff'`, `borderRadius: 10`, `padding: 14`, `marginBottom: 12`, `borderLeftWidth: 4`
|
|
31
|
+
|
|
32
|
+
## 파일 구조
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
example/
|
|
36
|
+
App.tsx [대규모 리팩토링 — 컨테이너 역할만]
|
|
37
|
+
components/ [신규 디렉토리]
|
|
38
|
+
atoms.tsx [Btn, Chip, StatusRow, Section + 공유 스타일]
|
|
39
|
+
DeviceCard.tsx [카드 chrome: 헤더 + 연결/해제 + busy 표시 + children 슬롯]
|
|
40
|
+
PrinterPanel.tsx [연결된 카드 안의 본문: 상태 행 + 인쇄 + 명찰 테스트]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
기존 nemonic App.tsx 의 JSX 와 컴포넌트들을 위 3개 파일로 분해. **네이티브 코드 (Kotlin/Swift) 는 변경 없음.**
|
|
44
|
+
|
|
45
|
+
## 상태 모델 변경 (App.tsx)
|
|
46
|
+
|
|
47
|
+
| 기존 | 변경 후 | 메모 |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| `transport: Transport` | **제거** | 카드 자체가 transport 정보 보유 |
|
|
50
|
+
| `printers: NPrinter[]` | `printers: { bluetooth: NPrinter[]; usb: NPrinter[] }` | 섹션 분리용 |
|
|
51
|
+
| `selected: NPrinter \| null` | `connectedKey: string \| null` | 형식: `${transport}:${macAddress\|deviceName}` |
|
|
52
|
+
| `scanning: boolean` + `usbReloading: boolean` | `searching: boolean` | 단일-샷 검색 윈도우 동안 true |
|
|
53
|
+
|
|
54
|
+
**유지되는 state** (그대로): `connecting`, `connectState`, `printerStatus`, `cartridge`, `printerName`, `battery`, `copies`, `quality`, `labelWidthMm`, `labelHeightMm`, `labelText`, `fontSizeInput`, `customFontSize`, `labelPrinting`, `refreshing`, `log`.
|
|
55
|
+
|
|
56
|
+
## 핵심 동작 흐름
|
|
57
|
+
|
|
58
|
+
### 1. 디바이스 검색 (one-shot)
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
const BLE_SCAN_DURATION_MS = 7000;
|
|
62
|
+
|
|
63
|
+
const searchDevices = useCallback(async () => {
|
|
64
|
+
if (searching) return;
|
|
65
|
+
setSearching(true);
|
|
66
|
+
setPrinters({ bluetooth: [], usb: [] });
|
|
67
|
+
pushLog('▶ search start');
|
|
68
|
+
try {
|
|
69
|
+
// USB 는 즉시 결과, BLE 는 async 누적
|
|
70
|
+
const [usbList, scanResult] = await Promise.all([
|
|
71
|
+
BootNemonicPrinter.getUsbPrinterList(),
|
|
72
|
+
BootNemonicPrinter.startScan(),
|
|
73
|
+
]);
|
|
74
|
+
setPrinters(p => ({ ...p, usb: usbList }));
|
|
75
|
+
pushLog(` USB found: ${usbList.length}, BLE scan started (${scanResult})`);
|
|
76
|
+
} catch (e: any) {
|
|
77
|
+
pushLog(`search error: ${e?.message ?? e}`);
|
|
78
|
+
}
|
|
79
|
+
// BLE 결과는 onDeviceFound 리스너가 bluetooth 배열에 누적
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
try { BootNemonicPrinter.stopScan(); } catch {}
|
|
82
|
+
setSearching(false);
|
|
83
|
+
pushLog('◀ search stopped');
|
|
84
|
+
}, BLE_SCAN_DURATION_MS);
|
|
85
|
+
}, [searching, pushLog]);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- `onDeviceFound` 리스너는 기존 패턴 그대로지만 `bluetooth` 배열에 누적: `setPrinters(p => p.bluetooth.some(...) ? p : { ...p, bluetooth: [...p.bluetooth, printer] })`
|
|
89
|
+
- 검색 버튼은 `searching === true` 동안 disabled + "검색 중…" 표시
|
|
90
|
+
- **제거할 기존 코드**: `onSwitchTransport`, `loadUsb`, `startScan`/`stopScan` 토글, transport 칩 JSX
|
|
91
|
+
|
|
92
|
+
### 2. 카드 [연결] 동작
|
|
93
|
+
|
|
94
|
+
기존 `connect(printer: NPrinter)` 로직 거의 그대로 유지 — 단, 호출 측에서 transport 를 직접 넘기도록 시그니처 변경:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
const connectCard = useCallback(
|
|
98
|
+
async (printer: NPrinter, transport: 'bluetooth' | 'usb') => {
|
|
99
|
+
if (connecting) return;
|
|
100
|
+
const thisKey = `${transport}:${printer.macAddress || printer.name}`;
|
|
101
|
+
// 다른 카드가 이미 연결되어 있으면 먼저 disconnect (bixolon 자동 해제 패턴)
|
|
102
|
+
if (connectedKey && connectedKey !== thisKey) {
|
|
103
|
+
pushLog(`▶ auto-disconnect previous (${connectedKey})`);
|
|
104
|
+
BootNemonicPrinter.disconnect();
|
|
105
|
+
// onDisconnected 이벤트가 connectState 를 DISCONNECTED 로 세팅
|
|
106
|
+
setConnectedKey(null);
|
|
107
|
+
}
|
|
108
|
+
// 기존 connect() 본문 그대로 — CONNECTING 강제 전환, USB 권한, setPrintTimeout, finally refreshConnectState 모두 유지
|
|
109
|
+
pushLog(`▶ connect tap (transport=${transport}, name=${printer.name}, type=${printer.type})`);
|
|
110
|
+
try {
|
|
111
|
+
setConnecting(true);
|
|
112
|
+
setConnectState(NConnectState.CONNECTING);
|
|
113
|
+
if (transport === 'usb') {
|
|
114
|
+
const granted = await BootNemonicPrinter.requestUsbPermission(printer);
|
|
115
|
+
if (!granted) return;
|
|
116
|
+
}
|
|
117
|
+
const result = await BootNemonicPrinter.connect({ ...printer, transport });
|
|
118
|
+
if (result === NResult.OK) {
|
|
119
|
+
setConnectedKey(thisKey);
|
|
120
|
+
const isAndroidUsb = Platform.OS === 'android' && transport === 'usb';
|
|
121
|
+
const PRINT_TIMEOUT_MS = isAndroidUsb ? 3000 : 30000;
|
|
122
|
+
try { BootNemonicPrinter.setPrintTimeout(false, PRINT_TIMEOUT_MS); } catch {}
|
|
123
|
+
}
|
|
124
|
+
} finally {
|
|
125
|
+
setConnecting(false);
|
|
126
|
+
await refreshConnectState();
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
[connecting, connectedKey, pushLog, refreshConnectState]
|
|
130
|
+
);
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
핵심: `setConnectedKey(thisKey)` 만 성공 시 호출 — 카드 확장의 단일 진실원.
|
|
134
|
+
|
|
135
|
+
### 3. 카드 확장 (children 렌더)
|
|
136
|
+
|
|
137
|
+
App.tsx 의 렌더 부분 (개념):
|
|
138
|
+
```tsx
|
|
139
|
+
{printers.bluetooth.map(p => {
|
|
140
|
+
const key = `bluetooth:${p.macAddress || p.name}`;
|
|
141
|
+
const isThisConnected = connectedKey === key;
|
|
142
|
+
return (
|
|
143
|
+
<DeviceCard
|
|
144
|
+
key={key}
|
|
145
|
+
printer={p}
|
|
146
|
+
transport="bluetooth"
|
|
147
|
+
isConnected={isThisConnected}
|
|
148
|
+
isAnyBusy={searching || connecting}
|
|
149
|
+
isThisConnecting={connecting && /* 연결 시도중인 카드 식별 */ false}
|
|
150
|
+
onConnect={() => connectCard(p, 'bluetooth')}
|
|
151
|
+
onDisconnect={disconnect}>
|
|
152
|
+
{isThisConnected && <PrinterPanel {...panelProps} />}
|
|
153
|
+
</DeviceCard>
|
|
154
|
+
);
|
|
155
|
+
})}
|
|
156
|
+
```
|
|
157
|
+
- USB 섹션도 동일 패턴
|
|
158
|
+
- `isThisConnected === false` 인 카드는 헤더 + 버튼만 (collapsed)
|
|
159
|
+
- 한 시점에 확장된 카드는 최대 1개 (`connectedKey` 가 단일 값)
|
|
160
|
+
|
|
161
|
+
### 4. 자동 새로고침 (기존 동작 유지)
|
|
162
|
+
|
|
163
|
+
기존 useEffect 그대로:
|
|
164
|
+
```ts
|
|
165
|
+
useEffect(() => {
|
|
166
|
+
if (connectState === NConnectState.CONNECTED) {
|
|
167
|
+
refreshAllStatus();
|
|
168
|
+
}
|
|
169
|
+
}, [connectState, refreshAllStatus]);
|
|
170
|
+
```
|
|
171
|
+
연결 성공 시 PrinterPanel 안의 4개 상태 행이 자동으로 채워짐.
|
|
172
|
+
|
|
173
|
+
## 보존되는 동작 (반드시 회귀하지 말 것)
|
|
174
|
+
|
|
175
|
+
- USB 권한 흐름 (Android 14+ 우회 + hasPermission 폴백) — `android/.../BootNemonicPrinterModule.kt:89-156`
|
|
176
|
+
- CONNECTING → CONNECTED 강제 전환으로 transport 전환 시 useEffect 재발화 보장
|
|
177
|
+
- cartridge priming (refreshAllStatus → queryCartridge 가 동일 역할)
|
|
178
|
+
- Android USB timeout 단축 (3초 vs 30초) 로직
|
|
179
|
+
- 라벨 캡쳐+인쇄 (`captureRef` + `print`)
|
|
180
|
+
- 모든 진단 로그 (네이티브 `emitNativeLog`, JS `pushLog`/`tlog`/`appendLog`)
|
|
181
|
+
- 하단 Log 섹션 (전역, 카드 밖)
|
|
182
|
+
|
|
183
|
+
## 컴포넌트 인터페이스
|
|
184
|
+
|
|
185
|
+
### `components/atoms.tsx`
|
|
186
|
+
|
|
187
|
+
기존 App.tsx 의 `Btn`, `Chip`, `StatusRow`, `Section` 컴포넌트 + 관련 스타일을 그대로 이동. 추가로 카드 관련 새 스타일 (`card`, `cardConnected`, `cardHeader`, `deviceName`, `deviceMeta`, `pill`, `pillOk`, `pillBad`, `disconnectedHint`, `searchBtn`) 정의 — bixolon DeviceCardShell.tsx 의 styles 블록 그대로 차용 가능.
|
|
188
|
+
|
|
189
|
+
App.tsx 와 DeviceCard.tsx, PrinterPanel.tsx 모두 여기서 import.
|
|
190
|
+
|
|
191
|
+
### `components/DeviceCard.tsx`
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
type Props = {
|
|
195
|
+
printer: NPrinter;
|
|
196
|
+
transport: 'bluetooth' | 'usb';
|
|
197
|
+
isConnected: boolean;
|
|
198
|
+
isAnyBusy: boolean;
|
|
199
|
+
onConnect: () => void;
|
|
200
|
+
onDisconnect: () => void;
|
|
201
|
+
children?: ReactNode;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
export function DeviceCard({ printer, transport, isConnected, isAnyBusy, onConnect, onDisconnect, children }: Props) {
|
|
205
|
+
const title = transport === 'usb' ? (printer.name || '(no name)') : (printer.name || '-');
|
|
206
|
+
const sub = transport === 'usb'
|
|
207
|
+
? `USB • type ${printer.type}`
|
|
208
|
+
: `${printer.macAddress || '-'} • BLE • type ${printer.type}`;
|
|
209
|
+
return (
|
|
210
|
+
<View style={[styles.card, isConnected && styles.cardConnected]}>
|
|
211
|
+
<View style={styles.cardHeader}>
|
|
212
|
+
<Text style={styles.deviceName}>{printer.typeName || '(unknown type)'}</Text>
|
|
213
|
+
<Text style={styles.deviceMeta}>{title}</Text>
|
|
214
|
+
<Text style={styles.deviceMeta}>{sub}</Text>
|
|
215
|
+
</View>
|
|
216
|
+
<View style={styles.row}>
|
|
217
|
+
{!isConnected ? (
|
|
218
|
+
<Btn onPress={onConnect} disabled={isAnyBusy}>연결</Btn>
|
|
219
|
+
) : (
|
|
220
|
+
<Btn onPress={onDisconnect} disabled={isAnyBusy}>연결 해제</Btn>
|
|
221
|
+
)}
|
|
222
|
+
</View>
|
|
223
|
+
{!isConnected && <Text style={styles.disconnectedHint}>연결 후 사용 가능합니다.</Text>}
|
|
224
|
+
{isConnected && children}
|
|
225
|
+
</View>
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
USB 권한 별도 UI 는 채택 안 함 (현재 nemonic 의 connect 내부 권한 처리 유지).
|
|
231
|
+
|
|
232
|
+
### `components/PrinterPanel.tsx`
|
|
233
|
+
|
|
234
|
+
연결된 카드 안에 들어가는 본문. 현재 [example/App.tsx](example/App.tsx) 의 Status / Print Quality / Print / 명찰 테스트 4개 섹션을 그대로 가져옴.
|
|
235
|
+
|
|
236
|
+
Props 가 verbose 한 건 의도적 — 데모용으로 hook 추출 안 하고 명시적 props drilling. App.tsx 가 모든 state/handler 의 단일 진실원.
|
|
237
|
+
|
|
238
|
+
```tsx
|
|
239
|
+
type Props = {
|
|
240
|
+
// 상태값
|
|
241
|
+
printerStatus: string; cartridge: string; printerName: string; battery: string;
|
|
242
|
+
refreshing: { all: boolean; printer: boolean; cartridge: boolean; name: boolean; battery: boolean };
|
|
243
|
+
// 핸들러
|
|
244
|
+
refreshAllStatus: () => void;
|
|
245
|
+
queryStatus: () => void; queryCartridge: () => void; queryPrinterName: () => void; queryBattery: () => void;
|
|
246
|
+
// 인쇄 설정
|
|
247
|
+
copies: string; setCopies: (s: string) => void;
|
|
248
|
+
quality: number; setQuality: (n: number) => void;
|
|
249
|
+
labelPrinting: boolean;
|
|
250
|
+
printSample: () => void; clearTemplate: () => void;
|
|
251
|
+
// 명찰
|
|
252
|
+
labelWidthMm: string; setLabelWidthMm: (s: string) => void;
|
|
253
|
+
labelHeightMm: string; setLabelHeightMm: (s: string) => void;
|
|
254
|
+
labelText: string; setLabelText: (s: string) => void;
|
|
255
|
+
fontSizeInput: string; setFontSizeInput: (s: string) => void;
|
|
256
|
+
customFontSize: number | null; autoLabelFontSize: number; effectiveFontSize: number;
|
|
257
|
+
applyFontSize: () => void;
|
|
258
|
+
labelW: number; labelH: number; labelRef: RefObject<View>;
|
|
259
|
+
printLabel: () => void;
|
|
260
|
+
// 게이팅 (모든 버튼 disable 체크에 사용)
|
|
261
|
+
isConnected: boolean;
|
|
262
|
+
};
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
상태/로직은 App.tsx 에 그대로 두고 PrinterPanel 은 presentational 만 — 데모 가독성 위해 hook 추출은 안 함.
|
|
266
|
+
|
|
267
|
+
## 변경되는 파일 요약
|
|
268
|
+
|
|
269
|
+
| 파일 | 변경 | 비고 |
|
|
270
|
+
|---|---|---|
|
|
271
|
+
| `example/App.tsx` | 대규모 — JSX 80% 재작성, transport state 제거, searchDevices 추가, props drilling | 줄 수 800 → 약 500 |
|
|
272
|
+
| `example/components/atoms.tsx` | 신규 (~150줄) | Btn/Chip/StatusRow/Section + 공유 styles |
|
|
273
|
+
| `example/components/DeviceCard.tsx` | 신규 (~100줄) | 카드 chrome |
|
|
274
|
+
| `example/components/PrinterPanel.tsx` | 신규 (~250줄) | 기존 Status/Print/명찰 섹션 |
|
|
275
|
+
| 네이티브 코드 | **변경 없음** | JS-only 리팩토링 |
|
|
276
|
+
|
|
277
|
+
## 작업 순서 권장
|
|
278
|
+
|
|
279
|
+
1. `components/atoms.tsx` 생성 — 기존 Btn/Chip/StatusRow/Section + 스타일 그대로 이동
|
|
280
|
+
2. `components/DeviceCard.tsx` 생성 — bixolon DeviceCardShell 구조 기반, 간소화
|
|
281
|
+
3. `components/PrinterPanel.tsx` 생성 — 기존 Status/Print/명찰 JSX 통째로 옮김 + props 인터페이스
|
|
282
|
+
4. `App.tsx` 리팩토링:
|
|
283
|
+
- state 모델 변경 (printers, connectedKey, searching)
|
|
284
|
+
- `searchDevices`, `connectCard` 추가
|
|
285
|
+
- 기존 `connect`/`onSwitchTransport`/`loadUsb`/`startScan`/`stopScan` 통합/제거
|
|
286
|
+
- 렌더부 재구성 (검색 버튼 + BT 섹션 + USB 섹션 + 로그)
|
|
287
|
+
5. TypeScript 검증
|
|
288
|
+
6. 실기기 검증 (검증 절차 참고)
|
|
289
|
+
|
|
290
|
+
## 검증 절차
|
|
291
|
+
|
|
292
|
+
### 1. TypeScript
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
cd /Users/sghong/Documents/work/dev-react-native/boot-nemonic-printer/example
|
|
296
|
+
./node_modules/.bin/tsc --noEmit
|
|
297
|
+
```
|
|
298
|
+
→ exit 0 확인 (에러 없음)
|
|
299
|
+
|
|
300
|
+
### 2. 빌드 / 실행
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
cd /Users/sghong/Documents/work/dev-react-native/boot-nemonic-printer/example
|
|
304
|
+
npx expo run:android
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### 3. 기능 회귀 시나리오 (실기기)
|
|
308
|
+
|
|
309
|
+
| 시나리오 | 기대 동작 |
|
|
310
|
+
|---|---|
|
|
311
|
+
| `[디바이스 검색]` 한 번 탭 | 버튼이 "검색 중…" + 스피너로 변경, BT 섹션 + USB 섹션 각각에 카드 표시, 7초 후 검색 버튼 재활성화 |
|
|
312
|
+
| BT 카드 `[연결]` 탭 | 카드 borderLeft 가 녹색으로 변경 + 배경색 변경, 카드 안에 상태 4행 + 인쇄 / 명찰 패널 노출, 상태값 자동 채워짐 |
|
|
313
|
+
| 상태 행의 `↻` 탭 | 해당 행만 스피너 → 값 갱신 |
|
|
314
|
+
| `[전체 새로고침]` 탭 | 4행 순차 갱신, 버튼 자체에 스피너 |
|
|
315
|
+
| 인쇄 / 명찰 인쇄 | 정상 작동 (기존 그대로) |
|
|
316
|
+
| USB 카드 `[연결]` 탭 (BT 연결 안 된 상태) | USB 권한 다이얼로그 (필요 시) → 허용 → 카드 확장 → 인쇄 정상 |
|
|
317
|
+
| BT 카드 연결된 상태에서 USB 카드 `[연결]` 탭 | BT 자동 해제 → USB 권한 → USB 연결 → BT 카드 collapse, USB 카드 확장 |
|
|
318
|
+
| `[연결 해제]` 탭 | 카드 collapse, 다른 카드 `[연결]` 활성화 |
|
|
319
|
+
| 검색 중 다른 카드 `[연결]` 탭 시도 | 버튼 disabled (isAnyBusy) |
|
|
320
|
+
|
|
321
|
+
### 4. 진단 로그 확인 (앱 하단 Log 박스)
|
|
322
|
+
|
|
323
|
+
기존 메시지가 그대로 보여야 함:
|
|
324
|
+
- `▶ search start` / `◀ search stopped`
|
|
325
|
+
- `▶ connect tap (transport=…, name=…, type=…)`
|
|
326
|
+
- `▶ awaiting requestUsbPermission …` (USB 만)
|
|
327
|
+
- `▶ usbManager.requestPermission() calling …` (네이티브, USB 권한 첫 요청 시)
|
|
328
|
+
- `connect → 0`
|
|
329
|
+
- `setPrintTimeout(false, …)`
|
|
330
|
+
- `[NemonicPrintTimer-JS] #N T+Nms ▶ tap` (명찰 인쇄)
|
|
331
|
+
|
|
332
|
+
## 예상 작업량 / 위험
|
|
333
|
+
|
|
334
|
+
- 약 **3~4 시간** (UI 재구성 + 컴포넌트 분해)
|
|
335
|
+
- props drilling 으로 PrinterPanel 인터페이스가 verbose — 데모용으로 의도적 허용 (hook 추출 안 함)
|
|
336
|
+
- 회귀 위험 중간 — SDK 호출 경로는 보존되지만 JSX 가 크게 바뀌므로 위 시나리오 전부 실기기 검증 필수
|
|
337
|
+
- 네이티브 코드 변경 없음 → expo run 한 번이면 충분, gradle 재빌드 등 불필요
|
|
338
|
+
|
|
339
|
+
## 참고: 이 세션에서 이미 적용된 변경
|
|
340
|
+
|
|
341
|
+
이전 세션 (이 문서 작성 직전) 에서 다음이 이미 적용됐고 그대로 보존해야 함:
|
|
342
|
+
|
|
343
|
+
1. **example 리팩토링 1차** — `Btn`/`Chip`/`StatusRow` 컴포넌트 추출, `appendLog`/`pushLog` 통합, `printerStatusLabels`/`batteryStatusLabel`/`connectStateLabel` 순수 함수 추출
|
|
344
|
+
2. **USB 권한 우회** — `BootNemonicPrinterModule.kt:89-156` 에서 SDK 의 `printerController.requestUsbPermission()` 우회, Android `UsbManager.requestPermission` 직접 호출 + `setPackage`+`FLAG_IMMUTABLE` PendingIntent + `hasPermission()` 폴백
|
|
345
|
+
3. **상태값 자동 새로고침** — connect 후 useEffect 가 `refreshAllStatus()` 자동 호출, CONNECTING 전이 강제로 transport 전환 시에도 작동
|
|
346
|
+
4. **`[전체 새로고침]` + 행별 `↻`** — Status section UI 가 이미 카드 패턴에 가까운 형태
|
|
347
|
+
|
|
348
|
+
이 변경들은 모두 카드 패턴 리팩토링과 호환되며, PrinterPanel 안으로 통째로 이동되면 됨.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
plugins {
|
|
2
|
+
id 'com.android.library'
|
|
3
|
+
id 'expo-module-gradle-plugin'
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
group = 'net.eventboot.nemonicprinter'
|
|
7
|
+
version = '0.1.0'
|
|
8
|
+
|
|
9
|
+
android {
|
|
10
|
+
namespace 'net.eventboot.nemonicprinter'
|
|
11
|
+
defaultConfig {
|
|
12
|
+
versionCode 1
|
|
13
|
+
versionName '0.1.0'
|
|
14
|
+
}
|
|
15
|
+
lintOptions {
|
|
16
|
+
abortOnError false
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
dependencies {
|
|
21
|
+
implementation fileTree(dir: 'libs', include: ['*.aar'])
|
|
22
|
+
}
|
|
Binary file
|