This commit is contained in:
2026-08-16 03:57:11 -03:00
parent 8486e54329
commit bb8b966a75
5 changed files with 74 additions and 35 deletions
@@ -19,6 +19,7 @@ import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
@@ -121,8 +122,10 @@ public class MainActivity extends Activity {
root.setOrientation(LinearLayout.VERTICAL);
root.setBackgroundColor(BG);
root.setPadding(dp(16), dp(14), dp(16), dp(12));
root.setClipChildren(true);
root.setClipToPadding(true);
// Fixed header: never moves when logs are appended.
// Header is outside both scrolling regions.
LinearLayout header = new LinearLayout(this);
header.setOrientation(LinearLayout.HORIZONTAL);
header.setGravity(Gravity.CENTER_VERTICAL);
@@ -131,7 +134,7 @@ public class MainActivity extends Activity {
LinearLayout heading = new LinearLayout(this);
heading.setOrientation(LinearLayout.VERTICAL);
TextView title = text("DragonTCP Lite", 25, TEXT, true);
TextView subtitle = text("Adaptive XOR tunnel over TCP/53", 12, MUTED, false);
TextView subtitle = text("Adaptive tunnel over TCP/53", 12, MUTED, false);
subtitle.setPadding(0, dp(2), 0, 0);
heading.addView(title);
heading.addView(subtitle);
@@ -144,11 +147,30 @@ public class MainActivity extends Activity {
header.addView(statusChip);
root.addView(header);
// Only the settings area scrolls. The log panel below has its own independent scroll.
// The remaining screen is an explicit vertical split. The settings pane and
// Live Log pane are siblings; neither is drawn over the other.
LinearLayout split = new LinearLayout(this);
split.setOrientation(LinearLayout.VERTICAL);
split.setClipChildren(true);
split.setClipToPadding(true);
root.addView(split, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
0,
1f
));
FrameLayout settingsPane = new FrameLayout(this);
settingsPane.setBackgroundColor(BG);
settingsPane.setClipChildren(true);
settingsPane.setClipToPadding(true);
ScrollView settingsScroll = new ScrollView(this);
settingsScroll.setFillViewport(false);
settingsScroll.setClipToPadding(false);
settingsScroll.setClipToPadding(true);
settingsScroll.setClipChildren(true);
settingsScroll.setOverScrollMode(View.OVER_SCROLL_IF_CONTENT_SCROLLS);
// Avoid a scrollbar visually continuing into the separate log pane.
settingsScroll.setVerticalScrollBarEnabled(false);
LinearLayout settings = new LinearLayout(this);
settings.setOrientation(LinearLayout.VERTICAL);
@@ -157,6 +179,10 @@ public class MainActivity extends Activity {
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
));
settingsPane.addView(settingsScroll, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
));
LinearLayout connectionCard = card("CONNECTION");
server = addField(connectionCard, "Server", "Server IP or hostname", "", false, false);
@@ -177,7 +203,7 @@ public class MainActivity extends Activity {
timeout = addFieldToRow(timing, "Timeout (s)", "2", "2", true, false, 0.42f);
transportCard.addView(timing);
TextView fixed = text("1 poller • Start = Max chunk • XOR 0xAD always on", 11, MUTED, false);
TextView fixed = text("1 poller • Start = Max chunk", 11, MUTED, false);
fixed.setPadding(dp(2), dp(6), dp(2), dp(2));
transportCard.addView(fixed);
settings.addView(transportCard, cardParams());
@@ -202,15 +228,28 @@ public class MainActivity extends Activity {
note.setPadding(dp(4), dp(2), dp(4), dp(6));
settings.addView(note);
root.addView(settingsScroll, new LinearLayout.LayoutParams(
// Give settings the upper portion of the available body. This FrameLayout
// clips its ScrollView, making it impossible for settings to draw behind logs.
split.addView(settingsPane, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
0,
1f
0.58f
));
// Fixed log panel. New lines can never change the position/size of the settings area.
View divider = new View(this);
divider.setBackgroundColor(BORDER);
LinearLayout.LayoutParams dividerParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
dp(1)
);
dividerParams.setMargins(dp(6), dp(7), dp(6), dp(7));
split.addView(divider, dividerParams);
// Live Log is a true sibling below settings, not an overlay.
LinearLayout logPanel = new LinearLayout(this);
logPanel.setOrientation(LinearLayout.VERTICAL);
logPanel.setClipChildren(true);
logPanel.setClipToPadding(true);
logPanel.setBackground(roundRect(CARD, 16, BORDER, 1));
logPanel.setPadding(dp(10), dp(8), dp(10), dp(10));
@@ -225,6 +264,8 @@ public class MainActivity extends Activity {
logScroll = new ScrollView(this);
logScroll.setFillViewport(true);
logScroll.setFocusable(false);
logScroll.setClipChildren(true);
logScroll.setClipToPadding(true);
logScroll.setOverScrollMode(View.OVER_SCROLL_IF_CONTENT_SCROLLS);
logScroll.setBackground(roundRect(LOG_BG, 11, Color.rgb(30, 38, 49), 1));
@@ -244,9 +285,11 @@ public class MainActivity extends Activity {
0,
1f
));
root.addView(logPanel, new LinearLayout.LayoutParams(
split.addView(logPanel, new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
dp(238)
0,
0.42f
));
clear.setOnClickListener(v -> {