diff --git a/app/src/main/java/com/neatstudio/tmuxandroid/MainActivity.java b/app/src/main/java/com/neatstudio/tmuxandroid/MainActivity.java index 62a5fe6..a276ab1 100644 --- a/app/src/main/java/com/neatstudio/tmuxandroid/MainActivity.java +++ b/app/src/main/java/com/neatstudio/tmuxandroid/MainActivity.java @@ -79,8 +79,6 @@ public final class MainActivity extends Activity { private static final int STATUS_BUSY = 1; private static final int STATUS_SUCCESS = 2; private static final int STATUS_ERROR = 3; - private static final int TERMINAL_VIEW_CHAT = 0; - private static final int TERMINAL_VIEW_FULL = 1; private static final long TERMINAL_RENDER_INTERVAL_MS = 80L; private static final long[] SOCKET_RECONNECT_DELAYS_MS = {1000L, 2000L, 4000L, 8000L, 15000L}; private static final int COLOR_APP_BG = Color.rgb(18, 20, 24); @@ -174,11 +172,12 @@ public final class MainActivity extends Activity { private boolean terminalRenderPending; private boolean terminalSelectionEnabled; private boolean terminalFollowOutput = true; - private int terminalViewMode = TERMINAL_VIEW_CHAT; private int terminalKeyPage; private int terminalHistoryOffset; private float terminalFontSizeSp = 11f; private float terminalLineHeight = 1.05f; + private float terminalLetterSpacing = 0f; + private int terminalVerticalPaddingDp = 4; private String terminalFontFamily = "monospace"; private String terminalThemeId = "graphite"; private float terminalTouchStartY; @@ -1849,7 +1848,6 @@ public final class MainActivity extends Activity { closeTerminalSocket(); activeSessionName = sessionName; loadTerminalDisplaySettings(sessionName); - terminalViewMode = TERMINAL_VIEW_CHAT; projectList = null; sessionGroupList = null; terminalScreen = new TerminalScreenBuffer(DEFAULT_TERMINAL_COLS, DEFAULT_TERMINAL_ROWS); @@ -1860,9 +1858,6 @@ public final class MainActivity extends Activity { terminalFollowOutput = true; terminalKeyPage = 0; terminalHistoryOffset = 0; - terminalConversationMessages.clear(); - terminalLiveStatusText = null; - terminalLiveOutputText = null; terminalImagePath = ""; terminalImagePreviewBar = null; terminalImagePreview = null; @@ -1890,15 +1885,15 @@ public final class MainActivity extends Activity { terminalText.setIncludeFontPadding(false); terminalText.setHorizontallyScrolling(true); terminalText.setLineSpacing(0, terminalLineHeight); + terminalText.setLetterSpacing(terminalLetterSpacing); terminalText.setGravity(Gravity.BOTTOM | Gravity.START); terminalText.setTextIsSelectable(terminalSelectionEnabled); - terminalText.setPadding(dp(2), dp(8), dp(2), 0); + terminalText.setPadding(dp(2), dp(terminalVerticalPaddingDp), dp(2), dp(terminalVerticalPaddingDp)); terminalText.setBackgroundColor(terminalBackgroundColor()); - terminalChatList = new LinearLayout(this); - terminalChatList.setOrientation(LinearLayout.VERTICAL); - terminalChatList.setPadding(0, dp(12), 0, 0); - terminalChatList.addView(projectStateText("Loading conversation..."), matchWrap()); - showTerminalView(terminalViewMode, false); + terminalScroll.addView(terminalText, new ScrollView.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + )); terminalScroll.addOnLayoutChangeListener((view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> resizeTerminalToViewport(false)); terminalScroll.setOnScrollChangeListener((view, scrollX, scrollY, oldScrollX, oldScrollY) -> @@ -1918,11 +1913,13 @@ public final class MainActivity extends Activity { terminalStatusLineText.setSingleLine(true); terminalStatusLineText.setGravity(Gravity.CENTER_VERTICAL | Gravity.START); terminalStatusLineText.setHorizontallyScrolling(true); - terminalStatusLineText.setPadding(dp(2), 0, dp(2), 0); + terminalStatusLineText.setLetterSpacing(terminalLetterSpacing); + terminalStatusLineText.setPadding(dp(2), dp(terminalVerticalPaddingDp / 2), dp(2), dp(terminalVerticalPaddingDp / 2)); + terminalStatusLineText.setMinHeight(dp(22)); terminalStatusLineText.setBackgroundColor(terminalBackgroundColor()); root.addView(terminalStatusLineText, new LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, - dp(22) + ViewGroup.LayoutParams.WRAP_CONTENT )); terminalAccessoryBar = createAccessoryBar(); root.addView(terminalAccessoryBar, new LinearLayout.LayoutParams( @@ -1936,7 +1933,6 @@ public final class MainActivity extends Activity { connectTerminal(sessionName); refreshTerminalGroupSessions(sessionName); refreshTerminalSessionMeta(sessionName); - refreshTerminalConversation(sessionName); }); inputField.post(() -> { inputField.requestFocus(); @@ -2029,46 +2025,13 @@ public final class MainActivity extends Activity { dp(13) )); bar.addView(titleBlock, new LinearLayout.LayoutParams(0, dp(32), 1)); + Button display = terminalToolButton("Aa", view -> promptSessionSettings("")); + display.setContentDescription("Terminal display settings"); + bar.addView(display); bar.addView(terminalToolButton("☰", view -> showTerminalActions(sessionName))); return bar; } - private void showTerminalView(int mode, boolean announce) { - terminalViewMode = mode; - if (terminalScroll == null || terminalText == null || terminalChatList == null) { - return; - } - terminalScroll.removeAllViews(); - if (mode == TERMINAL_VIEW_CHAT) { - terminalScroll.addView(terminalChatList, new ScrollView.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - )); - renderTerminalConversation(); - } else { - terminalText.setHorizontallyScrolling(true); - terminalText.setMovementMethod(null); - terminalText.setGravity(Gravity.BOTTOM | Gravity.START); - terminalScroll.addView(terminalText, new ScrollView.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - )); - renderTerminalNow(); - } - if (terminalAccessoryBar != null) { - terminalAccessoryBar.setVisibility(View.VISIBLE); - } - if (terminalComposerTabs != null) { - terminalComposerTabs.setVisibility(View.VISIBLE); - } - if (inputField != null) { - inputField.setHint(mode == TERMINAL_VIEW_CHAT ? "message or command" : "type command or text"); - } - if (announce) { - setStatus(mode == TERMINAL_VIEW_CHAT ? "Content view" : "Raw terminal mode"); - } - } - private HorizontalScrollView createTerminalGroupBar() { HorizontalScrollView scroller = new HorizontalScrollView(this); scroller.setHorizontalScrollBarEnabled(false); @@ -2222,7 +2185,7 @@ public final class MainActivity extends Activity { } terminalChatList.addView(conversationLiveTerminalPanel(), matchWrap()); updateTerminalLivePanel(); - if (terminalViewMode == TERMINAL_VIEW_CHAT && terminalFollowOutput && terminalScroll != null) { + if (terminalFollowOutput && terminalScroll != null) { terminalScroll.post(() -> terminalScroll.fullScroll(View.FOCUS_DOWN)); } } @@ -2397,7 +2360,6 @@ public final class MainActivity extends Activity { terminalConnectionText.setText("● connecting"); terminalConnectionText.setTextColor(COLOR_ACCENT_WARM); } - updateTerminalLivePanel(); } private String compactTerminalPath(String path) { @@ -2549,7 +2511,7 @@ public final class MainActivity extends Activity { new SheetAction("◎", "Status", () -> showRaw("Session status", () -> api.sessionStatus(sessionName))), new SheetAction("✎", "Rename", () -> promptRenameSession(sessionName)), new SheetAction("$", "Command", () -> promptSendCommand(sessionName)), - new SheetAction("Aa", "Display", () -> promptSessionSettings(sessionName)), + new SheetAction("Aa", "Display", () -> promptSessionSettings("")), new SheetAction("▰", "Project", () -> promptAddKanbanSession(sessionName)) ); addSheetActionSection(dialog, sheet, "PANES", @@ -2571,13 +2533,10 @@ public final class MainActivity extends Activity { private void showTerminalActions(String sessionName) { Dialog dialog = new Dialog(this); LinearLayout sheet = bottomSheetContent(dialog, sessionName, "Terminal controls"); - addSheetActionSection(dialog, sheet, "VIEW", - new SheetAction("◫", terminalViewMode == TERMINAL_VIEW_CHAT ? "Raw" : "Content", () -> - showTerminalView(terminalViewMode == TERMINAL_VIEW_CHAT - ? TERMINAL_VIEW_FULL : TERMINAL_VIEW_CHAT, true)), + addSheetActionSection(dialog, sheet, "TERMINAL", new SheetAction("↻", "Reconnect", () -> connectTerminal(sessionName)), new SheetAction("◎", "Status", () -> showRaw("Session status", () -> api.sessionStatus(sessionName))), - new SheetAction("Aa", "Display", () -> promptSessionSettings(sessionName)), + new SheetAction("Aa", "Display", () -> promptSessionSettings("")), new SheetAction("↑", "Older", () -> scrollTerminalHistory(-terminalRows)), new SheetAction("↓", "Newer", () -> scrollTerminalHistory(terminalRows)) ); @@ -2652,7 +2611,7 @@ public final class MainActivity extends Activity { inputField = new EditText(this); inputField.setTextColor(COLOR_TEXT); inputField.setHintTextColor(COLOR_TEXT_DIM); - inputField.setHint(terminalViewMode == TERMINAL_VIEW_CHAT ? "Message" : "type command or text"); + inputField.setHint("type command or text"); inputField.setSingleLine(false); inputField.setMinLines(3); inputField.setMaxLines(5); @@ -2876,11 +2835,15 @@ public final class MainActivity extends Activity { } private void promptSessionSettings(String sessionName) { - String key = sessionName.isEmpty() ? "default" : sessionName; + String key = "default"; float currentSize = prefs.getFloat("terminal_font_size:" + key, prefs.getFloat("terminal_font_size:default", 11f)); float currentLineHeight = prefs.getFloat("terminal_line_height:" + key, prefs.getFloat("terminal_line_height:default", 1.05f)); + float currentLetterSpacing = prefs.getFloat("terminal_letter_spacing:" + key, + prefs.getFloat("terminal_letter_spacing:default", 0f)); + int currentPadding = prefs.getInt("terminal_vertical_padding:" + key, + prefs.getInt("terminal_vertical_padding:default", 4)); String currentFamily = prefs.getString("terminal_font_family:" + key, prefs.getString("terminal_font_family:default", "monospace")); String currentTheme = prefs.getString("terminal_theme:" + key, @@ -2890,8 +2853,8 @@ public final class MainActivity extends Activity { Dialog dialog = new Dialog(this); LinearLayout sheet = bottomSheetContent( dialog, - sessionName.isEmpty() ? "Session display" : sessionName, - sessionName.isEmpty() ? "Default terminal typography" : "Terminal typography for this session" + "Terminal display", + "Applied to every terminal session" ); TextView sizeValue = settingValue("" + Math.round(currentSize) + " sp"); @@ -2969,6 +2932,24 @@ public final class MainActivity extends Activity { lineHeight.setOnSeekBarChangeListener(seekListener(value -> lineValue.setText(value + "%"))); sheet.addView(lineHeight, matchWrap()); + TextView letterValue = settingValue(Math.round(currentLetterSpacing * 100f) + "%"); + sheet.addView(settingHeader("LETTER SPACING", letterValue), matchWrap()); + SeekBar letterSpacing = new SeekBar(this); + letterSpacing.setMin(-4); + letterSpacing.setMax(10); + letterSpacing.setProgress(Math.round(currentLetterSpacing * 100f)); + letterSpacing.setOnSeekBarChangeListener(seekListener(value -> letterValue.setText(value + "%"))); + sheet.addView(letterSpacing, matchWrap()); + + TextView paddingValue = settingValue(currentPadding + " dp"); + sheet.addView(settingHeader("VERTICAL PADDING", paddingValue), matchWrap()); + SeekBar padding = new SeekBar(this); + padding.setMin(0); + padding.setMax(12); + padding.setProgress(currentPadding); + padding.setOnSeekBarChangeListener(seekListener(value -> paddingValue.setText(value + " dp"))); + sheet.addView(padding, matchWrap()); + LinearLayout actions = new LinearLayout(this); actions.setOrientation(LinearLayout.HORIZONTAL); Button reset = compactButton("Reset", view -> { @@ -2976,6 +2957,8 @@ public final class MainActivity extends Activity { .remove("terminal_font_size:" + key) .remove("terminal_font_family:" + key) .remove("terminal_line_height:" + key) + .remove("terminal_letter_spacing:" + key) + .remove("terminal_vertical_padding:" + key) .remove("terminal_theme:" + key) .apply(); dialog.dismiss(); @@ -2988,10 +2971,14 @@ public final class MainActivity extends Activity { Button save = primaryButton("Save", view -> { float selectedSize = size.getProgress(); float selectedHeight = lineHeight.getProgress() / 100f; + float selectedLetterSpacing = letterSpacing.getProgress() / 100f; + int selectedPadding = padding.getProgress(); prefs.edit() .putFloat("terminal_font_size:" + key, selectedSize) .putString("terminal_font_family:" + key, selectedFamily[0]) .putFloat("terminal_line_height:" + key, selectedHeight) + .putFloat("terminal_letter_spacing:" + key, selectedLetterSpacing) + .putInt("terminal_vertical_padding:" + key, selectedPadding) .putString("terminal_theme:" + key, selectedTheme[0]) .apply(); dialog.dismiss(); @@ -3014,7 +3001,7 @@ public final class MainActivity extends Activity { } }); } - showMessage("Session display saved"); + showMessage("Terminal display saved"); }); LinearLayout.LayoutParams saveParams = new LinearLayout.LayoutParams(0, dp(44), 1); saveParams.leftMargin = dp(8); @@ -3024,11 +3011,15 @@ public final class MainActivity extends Activity { } private void loadTerminalDisplaySettings(String sessionName) { - String key = sessionName == null || sessionName.isEmpty() ? "default" : sessionName; + String key = "default"; terminalFontSizeSp = prefs.getFloat("terminal_font_size:" + key, prefs.getFloat("terminal_font_size:default", 11f)); terminalLineHeight = prefs.getFloat("terminal_line_height:" + key, prefs.getFloat("terminal_line_height:default", 1.05f)); + terminalLetterSpacing = prefs.getFloat("terminal_letter_spacing:" + key, + prefs.getFloat("terminal_letter_spacing:default", 0f)); + terminalVerticalPaddingDp = prefs.getInt("terminal_vertical_padding:" + key, + prefs.getInt("terminal_vertical_padding:default", 4)); terminalFontFamily = prefs.getString("terminal_font_family:" + key, prefs.getString("terminal_font_family:default", "monospace")); terminalThemeId = prefs.getString("terminal_theme:" + key, @@ -3042,25 +3033,20 @@ public final class MainActivity extends Activity { terminalText.setTextSize(terminalFontSizeSp); terminalText.setTypeface(typeface); terminalText.setLineSpacing(0, terminalLineHeight); + terminalText.setLetterSpacing(terminalLetterSpacing); + terminalText.setPadding(dp(2), dp(terminalVerticalPaddingDp), dp(2), dp(terminalVerticalPaddingDp)); terminalText.setBackgroundColor(terminalBackgroundColor()); } - if (terminalLiveOutputText != null) { - terminalLiveOutputText.setTextSize(terminalFontSizeSp); - terminalLiveOutputText.setTypeface(typeface); - terminalLiveOutputText.setLineSpacing(0, terminalLineHeight); - terminalLiveOutputText.setBackgroundColor(terminalBackgroundColor()); - } if (terminalStatusLineText != null) { terminalStatusLineText.setTextSize(terminalFontSizeSp); terminalStatusLineText.setTypeface(typeface); + terminalStatusLineText.setLetterSpacing(terminalLetterSpacing); + terminalStatusLineText.setPadding(dp(2), dp(terminalVerticalPaddingDp / 2), dp(2), dp(terminalVerticalPaddingDp / 2)); terminalStatusLineText.setBackgroundColor(terminalBackgroundColor()); } if (terminalScroll != null) { terminalScroll.setBackgroundColor(terminalBackgroundColor()); } - if (terminalChatList != null && terminalViewMode == TERMINAL_VIEW_CHAT) { - renderTerminalConversation(); - } resizeTerminalToViewport(true); } @@ -3928,8 +3914,7 @@ public final class MainActivity extends Activity { if (terminalText == null || terminalScroll == null) { return; } - TextView viewportText = terminalViewMode == TERMINAL_VIEW_CHAT && terminalLiveOutputText != null - ? terminalLiveOutputText : terminalText; + TextView viewportText = terminalText; int width = viewportText.getWidth(); if (width <= 0) { width = terminalScroll.getWidth(); @@ -3951,10 +3936,6 @@ public final class MainActivity extends Activity { int usableWidth = Math.max(1, width - horizontalPadding); int cols = clamp((int) Math.floor(usableWidth / charWidth), MIN_TERMINAL_COLS, MAX_TERMINAL_COLS); int rows = clamp((height - verticalPadding) / lineHeight, MIN_TERMINAL_ROWS, MAX_TERMINAL_ROWS); - if (terminalLiveOutputText != null) { - terminalLiveOutputText.setMinHeight(rows * lineHeight); - terminalLiveOutputText.setGravity(Gravity.BOTTOM | Gravity.START); - } if (cols == terminalCols && rows == terminalRows && !forceSend) { return; } @@ -3982,9 +3963,6 @@ public final class MainActivity extends Activity { normalized = normalized + TERMINAL_ENTER; } terminalFollowOutput = true; - if (activeSessionName != null) { - upsertConversationMessage(ConversationMessage.localUser(activeSessionName, text)); - } sendTerminalInput(normalized); inputField.setText(""); setStatus("Sent " + text.length() + " chars"); @@ -4176,7 +4154,7 @@ public final class MainActivity extends Activity { return false; } int movedLocally = Math.abs(terminalScroll.getScrollY() - terminalTouchStartScrollY); - int lineHeight = terminalLiveOutputText == null ? dp(16) : terminalLiveOutputText.getLineHeight(); + int lineHeight = terminalText == null ? dp(16) : terminalText.getLineHeight(); int lines = clamp(Math.round(Math.abs(distance) / Math.max(1, lineHeight)), 4, terminalRows); if (distance > 0 && !terminalScroll.canScrollVertically(-1) && movedLocally <= dp(24)) { terminalScroll.post(() -> scrollTerminalHistory(-lines)); @@ -4236,7 +4214,6 @@ public final class MainActivity extends Activity { if (terminalStatusLineText != null) { terminalStatusLineText.setText(terminalScreen.renderStatusLine()); } - updateTerminalLivePanel(); if (terminalFollowOutput) { terminalScroll.post(() -> terminalScroll.fullScroll(View.FOCUS_DOWN)); } @@ -4804,9 +4781,6 @@ public final class MainActivity extends Activity { return; } if ("conversation-message".equals(type)) { - upsertConversationMessage(ConversationMessage.fromJson(event)); - terminalEventStatus = "message received"; - updateTerminalMeta(); return; } if ("hook-event".equals(type)) {