Compare commits

...
2 Commits
Author SHA1 Message Date
n0tst3v3andClaude Opus 5 be517f56a5 fix(map): bring back the compact filter button and floating layers control
The split carried over the wrong versions of two bits of chrome.

The filter toggle had become a full-width grey TextView bar, 48dp of
"Map Filters ▼" sitting above the map. Restored to what it was: a
small "☰  Filters" button on a wrap-content row.

The Leaflet layers control was being created with collapsed:false,
which pins the whole Streets/Satellite list open as a box over the
map. collapsed:true is what renders it as the floating corner button
that opens on tap. Its 13px font rule came back with it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 09:30:45 -06:00
n0tst3v3andClaude Opus 5 655b01be50 fix(map): make the filter panel scroll, and tighten it up
The panel is taller than a phone screen, and it was a LinearLayout
child with WRAP_CONTENT and no weight - so the excess was simply
clipped at the bottom edge. Everything from the accuracy multiplier
down was unreachable, which is where Apply, Reset, Export Raw and
Export Normalized had gone. Nothing was missing from the build; it
was drawn off-screen.

Wrap it in a ScrollView carrying the layout weight, so it shares the
screen with the map and scrolls to the rest. setFiltersExpanded now
hides the scroller rather than the panel inside it, or the collapsed
state would leave an empty scroller holding half the screen.

Then cut roughly 145dp of height out of the panel so most of it fits
without scrolling at all: the threshold readout goes from five lines
to two, the normalization summary from six to two (the level and
percentage are already on the line above it), button rows 48dp ->
40dp, the slider 42dp -> 28dp, and the section labels and paddings
lose a few dp each.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 09:27:12 -06:00
2 changed files with 145 additions and 115 deletions
@@ -31,7 +31,8 @@ private float phoneHeading;
private boolean mapReady; private boolean mapReady;
private LinearLayout filterPanel; private LinearLayout filterPanel;
private TextView filterHeader; private ScrollView filterScroll;
private Button filterButton;
private boolean filtersExpanded = false; private boolean filtersExpanded = false;
private Spinner deviceSpinner; private Spinner deviceSpinner;
@@ -170,36 +171,47 @@ protected void onCreate(Bundle state) {
) )
); );
filterHeader = /*
new TextView(this); * Compact filter button -- a small button that sits on its own row,
* not a full-width grey bar eating 48dp above the map.
*/
LinearLayout filterHeaderRow =
new LinearLayout(this);
filterHeader.setText( filterHeaderRow.setOrientation(
"Map Filters ▼" LinearLayout.HORIZONTAL
); );
filterHeader.setTextSize(16); filterHeaderRow.setGravity(
filterHeader.setTextColor(Color.DKGRAY);
filterHeader.setGravity(
Gravity.CENTER_VERTICAL Gravity.CENTER_VERTICAL
); );
filterHeader.setPadding( filterHeaderRow.setPadding(
dp(14), dp(8),
dp(10), dp(2),
dp(14), dp(8),
dp(10) dp(2)
); );
filterHeader.setBackgroundColor( filterButton =
Color.rgb(238, 238, 238) new Button(this);
filterButton.setText("☰ Filters");
filterButton.setTextSize(13);
filterHeaderRow.addView(
filterButton,
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
)
); );
root.addView( root.addView(
filterHeader, filterHeaderRow,
new LinearLayout.LayoutParams( new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT,
dp(48) LinearLayout.LayoutParams.WRAP_CONTENT
) )
); );
@@ -211,10 +223,10 @@ protected void onCreate(Bundle state) {
); );
filterPanel.setPadding( filterPanel.setPadding(
dp(10), dp(8),
dp(6), dp(2),
dp(10), dp(8),
dp(8) dp(4)
); );
filterPanel.setBackgroundColor( filterPanel.setBackgroundColor(
@@ -223,15 +235,38 @@ protected void onCreate(Bundle state) {
buildFilterPanel(); buildFilterPanel();
root.addView( /*
* The panel is taller than the screen on a phone, and a LinearLayout
* child with WRAP_CONTENT and no weight simply gets clipped at the
* bottom edge -- which is where Apply/Reset and both Export buttons
* were disappearing to. Inside a ScrollView with a weight it shares
* the screen with the map and scrolls to reach the rest.
*/
filterScroll =
new ScrollView(this);
filterScroll.setBackgroundColor(
Color.WHITE
);
filterScroll.addView(
filterPanel, filterPanel,
new LinearLayout.LayoutParams( new ScrollView.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, ScrollView.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT ScrollView.LayoutParams.WRAP_CONTENT
) )
); );
filterHeader.setOnClickListener( root.addView(
filterScroll,
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
0,
1
)
);
filterButton.setOnClickListener(
new View.OnClickListener() { new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
@@ -652,14 +687,14 @@ private void buildFilterPanel() {
normalizationSeekBar, normalizationSeekBar,
new LinearLayout.LayoutParams( new LinearLayout.LayoutParams(
-1, -1,
dp(42) dp(28)
) )
); );
normalizationValueText = normalizationValueText =
new TextView(this); new TextView(this);
normalizationValueText.setTextSize(13); normalizationValueText.setTextSize(12);
normalizationValueText.setTextColor( normalizationValueText.setTextColor(
Color.DKGRAY Color.DKGRAY
); );
@@ -668,7 +703,7 @@ private void buildFilterPanel() {
dp(4), dp(4),
dp(0), dp(0),
dp(4), dp(4),
dp(6) dp(2)
); );
filterPanel.addView( filterPanel.addView(
@@ -685,9 +720,9 @@ private void buildFilterPanel() {
normalizationStatsText.setPadding( normalizationStatsText.setPadding(
dp(4), dp(4),
dp(2), dp(1),
dp(4), dp(4),
dp(8) dp(4)
); );
filterPanel.addView( filterPanel.addView(
@@ -1002,23 +1037,20 @@ private void updateNormalizationControls() {
); );
normalizationStatsText.setText( normalizationStatsText.setText(
"Current thresholds:\n" + "Max speed " +
"Maximum movement speed: " +
MapFormat.number( MapFormat.number(
normalizer.maxSpeedKmh() normalizer.maxSpeedKmh()
) + ) +
" km/h\n" + " km/h • duplicate " +
"Duplicate tolerance: " +
MapFormat.number( MapFormat.number(
normalizer.duplicateDistance() normalizer.duplicateDistance()
) + ) +
" m\n" + " m\n" +
"Same-time tolerance: " + "Same-time " +
MapFormat.number( MapFormat.number(
normalizer.sameTimeDistance() normalizer.sameTimeDistance()
) + ) +
" m\n" + " m • accuracy ×" +
"GPS accuracy multiplier: " +
MapFormat.number( MapFormat.number(
normalizer.accuracyMultiplier() normalizer.accuracyMultiplier()
) )
@@ -1036,17 +1068,16 @@ private void setFiltersExpanded(
filtersExpanded = expanded; filtersExpanded = expanded;
filterPanel.setVisibility( // The ScrollView is the child with the layout weight, so it is the one
// that has to go away -- hiding the panel inside it would leave the
// empty scroller still holding half the screen.
filterScroll.setVisibility(
expanded expanded
? View.VISIBLE ? View.VISIBLE
: View.GONE : View.GONE
); );
filterHeader.setText( filterButton.setText("☰ Filters");
expanded
? "Map Filters ▲"
: "Map Filters ▼"
);
} }
private TextView filterLabel( private TextView filterLabel(
@@ -1056,14 +1087,14 @@ private TextView filterLabel(
new TextView(this); new TextView(this);
label.setText(text); label.setText(text);
label.setTextSize(14); label.setTextSize(13);
label.setTextColor(Color.DKGRAY); label.setTextColor(Color.DKGRAY);
label.setPadding( label.setPadding(
dp(2), dp(2),
dp(6), dp(3),
dp(2), dp(2),
dp(2) dp(1)
); );
return label; return label;
@@ -1085,7 +1116,7 @@ private LinearLayout.LayoutParams weightParams() {
return new LinearLayout.LayoutParams( return new LinearLayout.LayoutParams(
0, 0,
dp(48), dp(40),
1 1
); );
} }
@@ -1362,28 +1393,23 @@ private void updateNormalizationSummary() {
if (normalizationStatsText == null) if (normalizationStatsText == null)
return; return;
// The level and the slider percentage are already on the line above
// this one, so the summary only carries what normalization actually did.
normalizationStatsText.setText( normalizationStatsText.setText(
"Level: " + "Kept " +
normalizer.levelName() + normalizer.retainedCount() +
" (" + " of " +
normalizer.getAggressiveness() + normalizer.examinedCount() +
"%)\n" + " points • max " +
"Maximum movement speed: " +
MapFormat.number( MapFormat.number(
normalizer.maxSpeedKmh() normalizer.maxSpeedKmh()
) + ) +
" km/h\n" + " km/h\n" +
"Raw points examined: " + "Removed " +
normalizer.examinedCount() +
"\n" +
"Points retained: " +
normalizer.retainedCount() +
"\n" +
"Duplicates suppressed: " +
normalizer.duplicateCount() + normalizer.duplicateCount() +
"\n" + " duplicate • " +
"GPS jumps rejected: " + normalizer.rejectedCount() +
normalizer.rejectedCount() " GPS jump"
); );
} }
@@ -549,6 +549,7 @@ public final class MapHtmlBuilder {
+ "<style>" + "<style>"
+ "html,body,#map{height:100%;margin:0}" + "html,body,#map{height:100%;margin:0}"
+ ".leaflet-popup-content{font:14px sans-serif;line-height:1.5}" + ".leaflet-popup-content{font:14px sans-serif;line-height:1.5}"
+ ".leaflet-control-layers{font:13px sans-serif}"
+ ".phone-bearing{" + ".phone-bearing{"
+ "position:relative;" + "position:relative;"
@@ -600,10 +601,13 @@ public final class MapHtmlBuilder {
+ "map=L.map('map',{layers:[streets]}).setView([20,0],2);" + "map=L.map('map',{layers:[streets]}).setView([20,0],2);"
// collapsed:true is what makes this the floating corner button
// that opens on tap. collapsed:false pins the whole list open
// over the map as a permanent box.
+ "L.control.layers({" + "L.control.layers({"
+ "'Streets':streets," + "'Streets':streets,"
+ "'Satellite':sat" + "'Satellite':sat"
+ "},null,{collapsed:false}).addTo(map);" + "},null,{collapsed:true}).addTo(map);"
+ "var phone=null,phoneShown=false," + "var phone=null,phoneShown=false,"