- Grid-mode top bar replaced with award filter chips (All/DXCC/VUCC/
WAPC/WAJA/WAZ/WAS) showing live progress (count/target)
- New AwardBoundaryOverlay renders real administrative boundaries
(provinces/prefectures/CQ zones/states/countries) with the VUCC visual
language: yellow boundary lines, green fill for worked regions, labels
- Boundary assets packaged from public GeoJSON (DataV China, Japan land,
HB9HIL CQ zones, Natural Earth states/countries) with ADIF match keys:
WAPC province codes, WAJA ADIF prefecture numbers, US state abbrs,
ARRL DXCC entity codes
- GridQso extended with dxcc/country/cqz/state parsed from LoTW report
(qso_qsldetail); AwardCalculator derives six-award progress; STATE is
interpreted per DXCC entity (ADIF 'STATE depends on DXCC')
- Grid-mode toggle pill floated at map top-right (Grid mode / Satellite mode)
- New tests: AwardCalculatorTest (9 cases), LoTW award-field parsing (3 cases)
Expanded per-callsign rows previously read '2 · FO-29 · CW · V/U · 11:30Z'
(ordinal + summary, no date). Now each expanded line is
'yyyy-MM-dd · FO-29 · CW · V/U · 11:30Z' — the first QSO's date already
lives in the header row, so only subsequent QSOs carry a date prefix.
- Tap-to-show-QSOs now works as soon as 4-char grid lines appear (zoom 6),
not only when 4-char labels show (was zoom 7). Selection outline already
used GRID_ZOOM_SUB, so feedback is immediate.
- 4-char labels now appear from zoom 6.5 (was 7.0), so the sub-square name
shows shortly after the lines appear instead of a full zoom level later.
Pixel analysis of the user's screenshot: worked-cell green measured RGB(57,160,74)
against background RGB(16,16,15), which matches alpha≈178 — i.e. the alpha=90
fill painted ~3 times in place. Root cause: at low zoom colRepeats>0 and every
turn loop shifted the cell by dLon=turn*360°, but projectionToX() normalizes
longitude back into [-180,180), so all turns collapsed onto the SAME screen x
and each cell/line/label was painted 2*colRepeats+1 times at one spot.
Fix: keep the turn offset as a pixel shift (turn * worldWidthPx) on the x
coordinate in ALL turn loops (worked fills at both zooms, vertical lines,
horizontal lines, labels). World-repeat copies now land on their true screen
positions instead of stacking on top of each other.
The previous fixes only handled sub-square zoom lines. At field zoom the 20°x10°
grid lines were drawn unconditionally: cellLabel(zoom<6) returns 2-char fields
which never match the 4-char workedGrids set, so every field line crossed every
worked 2°x1° square. Bright-yellow (alpha 160) lines through the green fill is
what read as 'green got brighter' — the fill color itself never changed.
Now both line passes iterate the finer 2°x1° sub-grid (forced 4-char labels via
GRID_ZOOM_SUB) and skip segments bordering worked cells, at field zoom and
sub-square zoom alike. Revert the alpha softening (c2e496c4) — the fill was
never the problem; also restores worked-cell labels (7afce7ee revert).
Reverting the label-skip from 7afce7ee: worked cells keep their 4-char
labels. The 'green too bright' report is an area effect, not an overlay
overdraw — the same alpha=90 fill that reads as a small patch at field zoom
covers half the viewport at sub-square zoom. Use a softer fill (alpha 50)
for the sub-square branch, field zoom unchanged.
The previous fix skipped grid LINES through worked cells, but each worked cell
still got a bright-yellow (alpha 220 + black shadow) 4-char label drawn dead
center on the green fill at zoom>=7. Field zoom never shows this because 2-char
labels sit at field centers and almost never overlap a worked 2x1 square. Now
worked cells stay completely label-free, matching the field-zoom look.
Rate limit classification per ARRL policy (one download in progress per user
id; HTTP 503 'Page request limit' observed on throttled pulls) and the HTML
login-error page returned for wrong credentials. Settings screen now shows a
specific message per cause instead of one generic 'check callsign/password/network'.
Lines (alpha 160 yellow) were drawn AFTER the worked fills (alpha 90 green),
so at zoom>=6 every worked cell's four borders got yellow-on-green
composited — the cells looked brighter than the same cells at field zoom
(no square lines there). Segments bordering a worked cell are now skipped
in both meridian and parallel passes.
The antimeridian unwrap (span > 180 => shift left edge +360) misfired on
every global view (span is legitimately > 180): the range inverted and the
meridian loop drew nothing. Anchor the bbox on the view-center longitude
plus half viewport width in degrees instead; continuous unwrapped range
handles both antimeridian crossing and world repeats.
Maidenhead field index 0 spans -90..-80 lat / -180..-160 lon, so the
field-center must subtract those bases. Without them, entering grid mode
centered a hemisphere away (OL62 -> 115N/290E instead of 25N/110E).
- LoTW sync now stores per-QSO detail (call/time/sat/mode/bands) grouped by
gridsquare (PROP_MODE=SAT only), single JSON blob in SharedPreferences
- GridQso model derives band label (V/U, U/V, V/A...) from BAND_RX/BAND
- Tap detection via osmdroid MapEventsOverlay; selected grid outlined green
- Centered dialog: calls sorted by first-contact time, first-QSO summary,
expandable call rows list subsequent QSOs in that grid; tap outside closes
Add a full-screen update checker accessible from a button at the
bottom of the settings page. It queries the fork's GitHub latest
release and can download + install the APK in place.
- UpdateRepository (core/data): fetch releases/latest via GitHub API,
parse tag/description/APK asset, stream APK download to cacheDir
- VersionComparator (core/domain): compare 4.4.6-ba7opf.N style tags
(base version first, then build number; v-prefix tolerant) + tests
- IMainContainer/MainContainer: inject updateRepo
- UpdateCheckerScreen (feature/settings): shows current version,
checks for updates, displays latest version + release notes, and a
Download & install button; FileProvider hands the APK to the
system installer
- SettingsScreen: bottom entry button, full-screen page toggle
- AndroidManifest: REQUEST_INSTALL_PACKAGES permission + FileProvider
- i18n strings (en/zh)
Port the upstream drag-reorder pattern (dragHandle/draggedVisual/
autoScroll/DragRowState) so custom data source rows can be reordered
by long-pressing the handle icon, replacing the old move-up button.
- Add 40dp drag-handle box at row start with long-press gesture
- Live reorder while dragging (neighbour squeeze + spring settle)
- Edge auto-scroll during drag
- Keep per-source enabled checkbox + HTTP status label
This file also carries the #242 data-source dialog UI (enabled
checkbox, status code label, restore-default button) which shares
the same sourceSection function and cannot be cleanly split.
- onStationAGrid/onStationBGrid store the trimmed upper-cased grid instead
of the raw input (ol63 used to stay lowercase in the UI)
- drop the local latLonToGrid/gridToLatLon copies and reuse the domain
QthConverter, removing the drift risk between two implementations
- inject computeDispatcher (default Dispatchers.Default, no behaviour
change) so the pass computation is unit-testable on a test scheduler
- add MutualViewModelTest (15 cases): init prefill, grid/lat-lon linkage,
error paths, main-list reuse, fallback search, sorting, clearError
Replace the radar page calendar action with the map icon and route the action through the Passes map flow so the Passes navigation item remains selected.
When adjusting RX in passband mode (via +/- buttons or slider), the old
code used TransponderMapper.mapDownlinkToUplink (pure passband mapping
without Doppler compensation), producing ~10kHz error at LEO velocities.
Fix: use DopplerFrequencyCalculator.computeUplinkFromDownlinkWithOffset
for the full TX-from-RX round-trip, matching the RX→PASSBAND button
onClick logic. Also fixed frame mismatch: position now uses txLow/txRange
(Doppler-shifted frame) consistently.
Store the offset (kHz) per NORAD catalog id in SharedPreferences so
each satellite's last entered offset is restored when reopening the
frequency calculator.
Port upstream PR #234 to fork main:
- New feature:status module (SatStatusScreen, SatStatusViewModel)
- New AmSatRepository + IAmSatRepository + SatStatus models
- RemoteSource: AMSAT API methods (getAmSatCatalog, getAmSatReports)
- MainContainer/IMainContainer: DI injection
- MainTheme: AMSAT status colors (tertiary slots)
- Chinese translations added for all AMSAT strings
- 26 unit tests passing
Note: navigation entry not included — upstream PR #234 intentionally
left it out pending UI restructuring. Add AMSAT to your nav bar or
menu as desired.
- isNamedLinearTransponder: match ' Lin' prefix (AO-7 style) and
add fallback branch (hasLinearName && hasLinearMode) for entries
with 'Linear'/'Lin' but no 'transponder' word (AO-7, AO-73)
- add deduplicateTransponders: merge entries sharing the same
uplink/downlink frequency range, preferring non-CW entry
(AO-7 Mode A had separate SSB and CW entries; JO-97 had
separate CW and SSB Transponder entries)
- apply dedup in CalculatorPage filter chain
- 6 new tests, 23 total, all passing