diff --git a/app/src/main/java/com/itsaky/androidide/TerminalActivity.java b/app/src/main/java/com/itsaky/androidide/TerminalActivity.java index d2c51761f..566e0bc5a 100755 --- a/app/src/main/java/com/itsaky/androidide/TerminalActivity.java +++ b/app/src/main/java/com/itsaky/androidide/TerminalActivity.java @@ -24,6 +24,7 @@ import static com.itsaky.androidide.utils.Environment.PREFIX; import static com.itsaky.androidide.utils.Environment.getEnvironment; import android.os.Bundle; +import android.util.TypedValue; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -34,7 +35,6 @@ import androidx.annotation.NonNull; import com.blankj.utilcode.util.ClipboardUtils; import com.blankj.utilcode.util.KeyboardUtils; -import com.blankj.utilcode.util.SizeUtils; import com.blankj.utilcode.util.ThrowableUtils; import com.itsaky.androidide.app.StudioActivity; import com.itsaky.androidide.databinding.ActivityTerminalBinding; @@ -63,19 +63,24 @@ import java.io.File; import java.io.FileOutputStream; import java.util.Map; -public class TerminalActivity extends StudioActivity { +public class TerminalActivity extends StudioActivity + implements TerminalViewClient, TerminalSessionClient { public static final String KEY_WORKING_DIRECTORY = "terminal_workingDirectory"; private static final ILogger LOG = ILogger.newInstance("TerminalActivity"); private static final byte[] SOURCES_LIST_CONTENT = "deb https://androidide.com/packages/apt/termux-main/ stable main".getBytes(); - private final Client client = new Client(); private ActivityTerminalBinding binding; private TerminalView terminal; private TerminalSession session; private boolean isVisible = false; private KeyListener listener; + private int MIN_FONT_SIZE; + private int MAX_FONT_SIZE; + private int DEFAULT_FONT_SIZE; + private static final String KEY_FONT_SIZE = "terminal_fontSize"; + @Override protected View bindLayout() { binding = ActivityTerminalBinding.inflate(getLayoutInflater()); @@ -154,11 +159,12 @@ public class TerminalActivity extends StudioActivity { } private void setupTerminalView() { + setFontVariables(); terminal = new TerminalView(this, null); - terminal.setTerminalViewClient(client); + terminal.setTerminalViewClient(this); terminal.attachSession(createSession(getWorkingDirectory())); terminal.setKeepScreenOn(true); - terminal.setTextSize(SizeUtils.dp2px(10)); + terminal.setTextSize(getFontSize()); terminal.setTypeface(TypefaceUtils.jetbrainsMono()); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-1, 0); @@ -222,10 +228,10 @@ public class TerminalActivity extends StudioActivity { } private TerminalSession createSession(final String workingDirectory) { - final Map envs = getEnvironment(); - final String[] env = new String[envs.size()]; + final Map environment = getEnvironment(); + final String[] env = new String[environment.size()]; int i = 0; - for (Map.Entry entry : envs.entrySet()) { + for (Map.Entry entry : environment.entrySet()) { env[i] = entry.getKey() + "=" + entry.getValue(); i++; } @@ -237,7 +243,7 @@ public class TerminalActivity extends StudioActivity { new String[] {}, // Arguments env, // Environment variables TerminalEmulator.DEFAULT_TERMINAL_TRANSCRIPT_ROWS, // Transcript rows - client // TerminalSessionClient + this // TerminalSessionClient ); try { @@ -270,6 +276,46 @@ public class TerminalActivity extends StudioActivity { return "/system/bin/sh"; } + public void setFontVariables() { + int[] sizes = getDefaultFontSizes(); + + DEFAULT_FONT_SIZE = sizes[0]; + MIN_FONT_SIZE = sizes[1]; + MAX_FONT_SIZE = sizes[2]; + } + + // https://github.com/termux/termux-app/blob/82b15803126138eef8899e0c7b582713f872cd09/termux-shared/src/main/java/com/termux/shared/termux/settings/preferences/TermuxAppSharedPreferences.java + private int[] getDefaultFontSizes() { + float dipInPixels = + TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics()); + + int[] sizes = new int[3]; + + // This is a bit arbitrary and sub-optimal. We want to give a sensible default for minimum font + // size + // to prevent invisible text due to zoom be mistake: + sizes[1] = (int) (4f * dipInPixels); // min + + // http://www.google.com/design/spec/style/typography.html#typography-line-height + int defaultFontSize = Math.round(9 * dipInPixels); + // Make it divisible by 2 since that is the minimal adjustment step: + if (defaultFontSize % 2 == 1) defaultFontSize--; + + sizes[0] = defaultFontSize; // default + + sizes[2] = 256; // max + + if (getApp() + .getPrefManager() + .getString(KEY_FONT_SIZE, "") + .equals("")) { + setFontSize(defaultFontSize, false); + } + + return sizes; + } + private static final class KeyListener implements VirtualKeysView.IVirtualKeysView { private final TerminalView terminal; @@ -311,7 +357,7 @@ public class TerminalActivity extends StudioActivity { } } - protected void onTerminalExtraKeyButtonClick( + private void onTerminalExtraKeyButtonClick( String key, boolean ctrlDown, boolean altDown, boolean shiftDown, boolean fnDown) { if (VirtualKeysConstants.PRIMARY_KEY_CODES_FOR_STRINGS.containsKey(key)) { Integer keyCode = VirtualKeysConstants.PRIMARY_KEY_CODES_FOR_STRINGS.get(key); @@ -353,160 +399,204 @@ public class TerminalActivity extends StudioActivity { } } - private final class Client implements TerminalViewClient, TerminalSessionClient { + @Override + public boolean onKeyUp(int keyCode, KeyEvent e) { + return false; + } - @Override - public boolean onKeyUp(int keyCode, KeyEvent e) { - return false; - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent e, TerminalSession session) { - if (keyCode == KeyEvent.KEYCODE_ENTER && !session.isRunning()) { - finish(); - return true; - } - return false; - } - - @Override - public boolean onCodePoint(int codePoint, boolean ctrlDown, TerminalSession session) { - return false; - } - - @Override - public void onTextChanged(TerminalSession changedSession) { - terminal.onScreenUpdated(); - } - - @Override - public void onTitleChanged(TerminalSession changedSession) {} - - @Override - public void onSessionFinished(TerminalSession finishedSession) { + @Override + public boolean onKeyDown(int keyCode, KeyEvent e, TerminalSession session) { + if (keyCode == KeyEvent.KEYCODE_ENTER && !session.isRunning()) { finish(); + return true; } + return false; + } - @Override - public void onCopyTextToClipboard(TerminalSession session, String text) { - ClipboardUtils.copyText("AndroidIDE Terminal", text); + @Override + public boolean onCodePoint(int codePoint, boolean ctrlDown, TerminalSession session) { + return false; + } + + @Override + public void onTextChanged(TerminalSession changedSession) { + terminal.onScreenUpdated(); + } + + @Override + public void onTitleChanged(TerminalSession changedSession) {} + + @Override + public void onSessionFinished(TerminalSession finishedSession) { + finish(); + } + + @Override + public void onCopyTextToClipboard(TerminalSession session, String text) { + ClipboardUtils.copyText("AndroidIDE Terminal", text); + } + + @Override + public void onPasteTextFromClipboard(TerminalSession session) { + String clip = ClipboardUtils.getText().toString(); + if (clip.trim().length() > 0 && terminal != null && terminal.mEmulator != null) { + terminal.mEmulator.paste(clip); } + } - @Override - public void onPasteTextFromClipboard(TerminalSession session) { - String clip = ClipboardUtils.getText().toString(); - if (clip.trim().length() > 0 && terminal != null && terminal.mEmulator != null) { - terminal.mEmulator.paste(clip); - } - } + @Override + public void onBell(TerminalSession session) {} - @Override - public void onBell(TerminalSession session) {} + @Override + public void onColorsChanged(TerminalSession session) {} - @Override - public void onColorsChanged(TerminalSession session) {} + @Override + public void onTerminalCursorStateChange(boolean state) {} - @Override - public void onTerminalCursorStateChange(boolean state) {} + @Override + public Integer getTerminalCursorStyle() { + return TerminalEmulator.DEFAULT_TERMINAL_CURSOR_STYLE; + } - @Override - public Integer getTerminalCursorStyle() { - return TerminalEmulator.DEFAULT_TERMINAL_CURSOR_STYLE; - } - - @Override - public float onScale(float scale) { + @Override + public float onScale(float scale) { + if (scale < 0.9f || scale > 1.1f) { + boolean increase = scale > 1.f; + changeFontSize(increase); return 1.0f; } + return scale; + } - @Override - public void onSingleTapUp(MotionEvent e) { - KeyboardUtils.showSoftInput(terminal); + private void changeFontSize(final boolean increase) { + int fontSize = getFontSize(); + fontSize += (increase ? 1 : -1) * 2; + fontSize = Math.max(MIN_FONT_SIZE, Math.min(fontSize, MAX_FONT_SIZE)); + setFontSize(fontSize, true); + } + + public int getFontSize() { + int fontSize; + try { + fontSize = + Integer.parseInt( + getApp() + .getPrefManager() + .getString(KEY_FONT_SIZE, String.valueOf(DEFAULT_FONT_SIZE))); + } catch (NumberFormatException | ClassCastException e) { + fontSize = DEFAULT_FONT_SIZE; } - @Override - public boolean shouldBackButtonBeMappedToEscape() { - return false; + return Math.min(Math.max(fontSize, MIN_FONT_SIZE), MAX_FONT_SIZE); + } + + public void setFontSize(int value, boolean apply) { + getApp().getPrefManager().putString(KEY_FONT_SIZE, String.valueOf(value)); + + if (apply) { + terminal.setTextSize(getFontSize()); } + } - @Override - public boolean shouldEnforceCharBasedInput() { - return true; + @Override + public void onSingleTapUp(MotionEvent e) { + KeyboardUtils.showSoftInput(terminal); + } + + @Override + public boolean shouldBackButtonBeMappedToEscape() { + return false; + } + + @Override + public boolean shouldEnforceCharBasedInput() { + return true; + } + + @Override + public boolean shouldUseCtrlSpaceWorkaround() { + return false; + } + + @Override + public boolean isTerminalViewSelected() { + return true; + } + + @Override + public void copyModeChanged(boolean copyMode) {} + + @Override + public boolean onLongPress(MotionEvent event) { + return false; + } + + @Override + public boolean readControlKey() { + Boolean state = binding.virtualKeyTable.readSpecialButton(SpecialButton.CTRL, true); + return state != null && state; + } + + @Override + public boolean readAltKey() { + Boolean state = binding.virtualKeyTable.readSpecialButton(SpecialButton.ALT, true); + return state != null && state; + } + + @Override + public boolean readFnKey() { + return false; + } + + @Override + public boolean readShiftKey() { + return false; + } + + @Override + public void onEmulatorSet() { + setTerminalCursorBlinkingState(true); + + if (session != null) { + binding + .getRoot() + .setBackgroundColor( + session.getEmulator().mColors.mCurrentColors[TextStyle.COLOR_INDEX_BACKGROUND]); } + } - @Override - public boolean shouldUseCtrlSpaceWorkaround() { - return false; - } + @Override + public void logError(String tag, String message) { + LOG.error(tag + ":", message); + } - @Override - public boolean isTerminalViewSelected() { - return true; - } + @Override + public void logWarn(String tag, String message) { + LOG.warn(tag + ":", message); + } - @Override - public void copyModeChanged(boolean copyMode) {} + @Override + public void logInfo(String tag, String message) { + LOG.info(tag + ":", message); + } - @Override - public boolean onLongPress(MotionEvent event) { - return false; - } + @Override + public void logDebug(String tag, String message) { + LOG.debug(tag + ":", message); + } - @Override - public boolean readControlKey() { - Boolean state = binding.virtualKeyTable.readSpecialButton(SpecialButton.CTRL, true); - return state != null && state; - } + @Override + public void logVerbose(String tag, String message) { + LOG.verbose(tag + ":", message); + } - @Override - public boolean readAltKey() { - Boolean state = binding.virtualKeyTable.readSpecialButton(SpecialButton.ALT, true); - return state != null && state; - } + @Override + public void logStackTraceWithMessage(String tag, String message, Exception e) { + LOG.error(tag + ":", message, e); + } - @Override - public boolean readFnKey() { - return false; - } - - @Override - public boolean readShiftKey() { - return false; - } - - @Override - public void onEmulatorSet() { - setTerminalCursorBlinkingState(true); - - if (session != null) { - binding - .getRoot() - .setBackgroundColor( - session.getEmulator().mColors.mCurrentColors[TextStyle.COLOR_INDEX_BACKGROUND]); - } - } - - @Override - public void logError(String tag, String message) { - // No logs - } - - @Override - public void logWarn(String tag, String message) {} - - @Override - public void logInfo(String tag, String message) {} - - @Override - public void logDebug(String tag, String message) {} - - @Override - public void logVerbose(String tag, String message) {} - - @Override - public void logStackTraceWithMessage(String tag, String message, Exception e) {} - - @Override - public void logStackTrace(String tag, Exception e) {} + @Override + public void logStackTrace(String tag, Exception e) { + LOG.error(tag + ":", e); } } diff --git a/build-tools/tooling-api-impl/src/test/test-home/.androidide/init/model.jar b/build-tools/tooling-api-impl/src/test/test-home/.androidide/init/model.jar index fce972f86..3fd94c14c 100644 Binary files a/build-tools/tooling-api-impl/src/test/test-home/.androidide/init/model.jar and b/build-tools/tooling-api-impl/src/test/test-home/.androidide/init/model.jar differ diff --git a/common/src/main/java/com/itsaky/androidide/managers/PreferenceManager.java b/common/src/main/java/com/itsaky/androidide/managers/PreferenceManager.java index 84b836c49..0694d3ddf 100755 --- a/common/src/main/java/com/itsaky/androidide/managers/PreferenceManager.java +++ b/common/src/main/java/com/itsaky/androidide/managers/PreferenceManager.java @@ -58,6 +58,11 @@ public class PreferenceManager { this.prefs = androidx.preference.PreferenceManager.getDefaultSharedPreferences(ctx); } + public PreferenceManager remove(String key) { + prefs.edit().remove(key).apply(); + return this; + } + public PreferenceManager putInt(String key, int val) { prefs.edit().putInt(key, val).apply(); return this;