Drop the non-ADIF QSL_MANUAL tag from the desktop and iOS exporters - #719
Merged
Conversation
QSL_MANUAL is not a field in the ADIF spec, so strict importers (LoTW's validator, Club Log, other loggers) can reject or silently drop it. PR #701 fixed this on Android by moving the flag to APP_FT8AF_QSL_MANUAL — the spec's APP_<PROGRAMID>_<FIELD> escape hatch — but the desktop and iOS ports were missed and still emit the bare name. Neither port needs the APP_ field, because on both the tag is a hardcoded "N" carrying no information: desktop's QSL_RCVD tracks r.confirmed, but QSL_MANUAL was always N, and iOS's QsoRecord has no confirmation state at all. Nothing reads it back either — desktop has no ADIF import path, and the iOS parser ignores QSL flags. Android's importer keys on the field being present, so an absent field and an explicit N are the same import. Dropping it is therefore lossless. Covers both desktop emitters: the file export and adif_record(), which is what goes out over the WSJT-X "Logged ADIF" UDP message to JTAlert/N1MM — the one most likely to meet a strict parser. Fixes #697 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #719 +/- ##
============================================
+ Coverage 36.12% 36.21% +0.09%
Complexity 286 286
============================================
Files 245 245
Lines 29973 29986 +13
Branches 3930 3930
============================================
+ Hits 10827 10860 +33
+ Misses 18797 18777 -20
Partials 349 349
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR removes the non-standard QSL_MANUAL ADIF tag from the desktop (Rust) and iOS (Swift) exporters so strict ADIF consumers don’t reject or truncate exported records, aligning those ports with the earlier Android fix strategy of not emitting non-spec fields.
Changes:
- Desktop: stop emitting
<QSL_MANUAL:1>Nin both the file exporter and the WSJT-X “Logged ADIF” UDPadif_record()output. - Desktop: add a Rust unit test asserting
QSL_MANUALis absent whileQSL_RCVDstill reflects the confirmed flag. - iOS: remove
QSL_MANUALfrom export output and update string-equality tests accordingly.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| ios/FT8AFKit/Tests/FT8EngineTests/AdifTests.swift | Updates expected ADIF strings to match the removal of QSL_MANUAL. |
| ios/FT8AFKit/Sources/FT8Engine/Adif.swift | Stops emitting the non-spec QSL_MANUAL field in iOS exports. |
| desktop/src-tauri/src/db.rs | Removes QSL_MANUAL from both ADIF emitters and adds coverage to prevent regressions. |
Suppressed comments (1)
ios/FT8AFKit/Sources/FT8Engine/Adif.swift:15
- This docstring says
exportmatches desktopexport_adif"exactly", but iOS hardcodesQSL_RCVDtoNwhile desktop derives it fromr.confirmed. Consider softening this to "matches field set/order" (with theQSL_RCVDexception) to avoid misleading future readers.
/// Render `records` as an ADIF string in the given order. Matches desktop
/// db.rs export_adif exactly: a fixed header, then per record the CALL field,
/// `QSL_RCVD` (iOS has no confirmation state yet, so always `N`), every
/// non-empty optional field, and comment + <eor>.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #697.
What was left
QSL_MANUALis not a field in the ADIF spec, so strict consumers (LoTW's upload validator, Club Log, other loggers) can reject it or silently drop the record's tail.Android was already fixed by #701, which moved the flag to
APP_FT8AF_QSL_MANUAL— the spec'sAPP_<PROGRAMID>_<FIELD>escape hatch — and kept the bare name as a read-only legacy alias so older exports still import. That's a better answer than the issue proposed (drop it / useQSLMSG), becauseQSL_RCVDis not a substitute: it means a QSL was received, which is a different fact from "operator ticked manually confirmed".The two ports were missed and still emitted the bare name:
desktop/src-tauri/src/db.rs:378desktop/src-tauri/src/db.rs:425adif_record()— the WSJT-X "Logged ADIF" UDP message to JTAlert/N1MMios/FT8AFKit/Sources/FT8Engine/Adif.swift:19Why dropping is right here, not the APP_ field
On both ports the tag is a hardcoded
Ncarrying no information:QSL_RCVDdoes vary withr.confirmed, butQSL_MANUALwas alwaysNQsoRecordhas no confirmation state at all, so both QSL flags are constantsAnd nothing reads it back: desktop has no ADIF import path, and the iOS parser explicitly ignores QSL flags (
Adif.swift:103). Android's importer setsisQSLonly when the key is present, so an absent field and an explicitNproduce the identical import. EmittingAPP_FT8AF_QSL_MANUAL:Nfrom these two would just be a conformant way to write nothing.Two corrections to the issue
DatabaseOpr.java:1255-1257as an emitter. On currentdevthose are commented-out dead code (:1158/:1160); the live Android path goes throughAdifRecord.QSLRecord.java:191-192's "present in LoTW" comment as suspect. That comment sits onQSL_RCVD(line 190), which genuinely is a real ADIF field present in LoTW exports — theQSL_MANUALhandling is separate and correctly documented as legacy-compat.Testing
export_omits_the_non_adif_qsl_manual_tagcovers both emitters and assertsQSL_RCVDstill carries the confirmed flag.cargo test --lib: 108 passed, 0 failed.cargo fmt: my changed lines are clean (the file has pre-existing drift at lines 127/203/241 that I deliberately left alone to keep the diff readable).I could not run
swift test— this was done on Windows, which has no Swift toolchain. The iOS changes are a mechanical string edit in one source line and two expected-string assertions, but they need theswift test + simulator buildCI job to confirm.🤖 Generated with Claude Code