You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Replaces stub implementations with working WebUSB PN533 transport (card
detection via poll loop), browser file picker for JSON/binary import, and
synchronous XHR-based MDST resource loading for wasmJs. Updates tests to
use runTest instead of runBlocking for wasmJs compatibility. Adds web
build step to CI and updates CLAUDE.md to reflect web target and
FormattedString conventions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CLAUDE.md
+36-25Lines changed: 36 additions & 25 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
3
3
## Project Overview
4
4
5
-
FareBot is a Kotlin Multiplatform (KMP) Android/iOS app for reading NFC transit cards. It is being ported from/aligned with [Metrodroid](https://github.com/metrodroid/metrodroid).
5
+
FareBot is a Kotlin Multiplatform (KMP) Android/iOS/Web app for reading NFC transit cards. It is being ported from/aligned with [Metrodroid](https://github.com/metrodroid/metrodroid). The web target uses Kotlin/Wasm (wasmJs) with WebUSB for NFC reader support.
6
6
7
7
**Metrodroid source code is in the `metrodroid/` directory in this repo.** Always use this local copy for comparisons and porting — do not fetch from GitHub.
8
8
@@ -32,10 +32,11 @@ When porting code from Metrodroid: **do a faithful port**. Do not simplify, abbr
-`String` (user-facing) → `FormattedString` (sealed class in `base/util/`)
39
40
40
41
Do NOT:
41
42
- Skip features "for later"
@@ -57,24 +58,30 @@ Do NOT make speculative changes hoping they fix the issue. Each failed guess was
57
58
58
59
### 5. All code in commonMain unless it requires OS APIs
59
60
60
-
Write all code in `src/commonMain/kotlin/`. Only use `androidMain`or `iosMain` for code that directly interfaces with platform APIs (NFC hardware, file system, UI system dialogs). No Objective-C. Tests use `kotlin.test`.
61
+
Write all code in `src/commonMain/kotlin/`. Only use `androidMain`, `iosMain`, or `wasmJsMain` for code that directly interfaces with platform APIs (NFC hardware, file system, UI system dialogs, WebUSB). No Objective-C. Tests use `kotlin.test`.
61
62
62
-
### 6. Use StringResource for all user-facing strings
63
+
### 6. Use FormattedString for all user-facing strings
64
+
65
+
All user-facing strings use the `FormattedString` sealed class, which defers string resolution to the UI layer (avoiding `runBlocking` that blocks the JS event loop on wasmJs).
63
66
64
-
All user-facing strings must go through Compose Multiplatform resources:
65
67
- Define strings in `src/commonMain/composeResources/values/strings.xml`
66
-
- For UI labels in `TransitInfo.getInfo()`, use `ListItem(Res.string.xxx, value)` or `HeaderListItem(Res.string.xxx)` directly
67
-
- For dynamic string formatting, use `runBlocking { getString(Res.string.xxx) }`
68
-
- Legacy pattern: Pass `StringResource` to factories — still works but not required for new code
68
+
- Use `FormattedString(Res.string.xxx)` for resource-backed strings
69
+
- Use `FormattedString("literal")` for dynamic/computed strings
70
+
- Use `FormattedString(Res.string.xxx, arg1, arg2)` for formatted strings
71
+
- Use `FormattedString.plural(Res.plurals.xxx, count, args...)` for plurals
72
+
- Concatenate with `+` operator: `FormattedString("a") + FormattedString("b")`
73
+
74
+
The UI resolves strings via `@Composable formattedString.resolve()` or `suspend formattedString.resolveAsync()`.
69
75
70
76
Example patterns:
71
77
```kotlin
72
-
//Preferred for static labels
73
-
ListItem(Res.string.card_type, cardType)
74
-
HeaderListItem(Res.string.card_details)
78
+
//In transit modules — return FormattedString, not String
-`/Users/eric/Code/farebot/REMAINING-WORK.md` — tracked remaining work
109
-
- Session transcripts in `/Users/eric/.claude/projects/-Users-eric-Code-farebot/`
110
-
111
-
When continuing from a previous session, read these files to recover context rather than starting from scratch.
113
+
When continuing from a previous session, check for implementation plans and session transcripts in `~/.claude/` to recover context rather than starting from scratch.
112
114
113
115
## Build Commands
114
116
115
117
```bash
116
-
./gradlew allTests # Run all tests
117
-
./gradlew assemble # Full build (Android + iOS frameworks)
118
+
./gradlew allTests # Run all tests
119
+
./gradlew assemble # Full build (Android + iOS + Web)
118
120
./gradlew :app:android:assembleDebug # Android only
121
+
./gradlew :app:web:wasmJsBrowserDistribution # Web (Wasm) only
0 commit comments