Skip to content

Commit

Permalink
Added: Add support for Share selected text of terminal in long hold…
Browse files Browse the repository at this point in the history
… `MORE` menu so that users don't have to copy and paste to move text between apps
  • Loading branch information
agnostic-apollo committed Oct 3, 2022
1 parent 0c14c29 commit 21804bc
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 7 deletions.
17 changes: 16 additions & 1 deletion app/src/main/java/com/termux/app/TermuxActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.termux.shared.activity.media.AppCompatActivityUtils;
import com.termux.shared.data.IntentUtils;
import com.termux.shared.android.PermissionUtils;
import com.termux.shared.data.DataUtils;
import com.termux.shared.termux.TermuxConstants;
import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_ACTIVITY;
import com.termux.app.activities.HelpActivity;
Expand Down Expand Up @@ -179,6 +180,7 @@ public final class TermuxActivity extends AppCompatActivity implements ServiceCo

private static final int CONTEXT_MENU_SELECT_URL_ID = 0;
private static final int CONTEXT_MENU_SHARE_TRANSCRIPT_ID = 1;
private static final int CONTEXT_MENU_SHARE_SELECTED_TEXT = 10;
private static final int CONTEXT_MENU_AUTOFILL_ID = 2;
private static final int CONTEXT_MENU_RESET_TERMINAL_ID = 3;
private static final int CONTEXT_MENU_KILL_PROCESS_ID = 4;
Expand Down Expand Up @@ -640,7 +642,10 @@ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuIn

menu.add(Menu.NONE, CONTEXT_MENU_SELECT_URL_ID, Menu.NONE, R.string.action_select_url);
menu.add(Menu.NONE, CONTEXT_MENU_SHARE_TRANSCRIPT_ID, Menu.NONE, R.string.action_share_transcript);
if (addAutoFillMenu) menu.add(Menu.NONE, CONTEXT_MENU_AUTOFILL_ID, Menu.NONE, R.string.action_autofill_password);
if (!DataUtils.isNullOrEmpty(mTerminalView.getStoredSelectedText()))
menu.add(Menu.NONE, CONTEXT_MENU_SHARE_SELECTED_TEXT, Menu.NONE, R.string.action_share_selected_text);
if (addAutoFillMenu)
menu.add(Menu.NONE, CONTEXT_MENU_AUTOFILL_ID, Menu.NONE, R.string.action_autofill_password);
menu.add(Menu.NONE, CONTEXT_MENU_RESET_TERMINAL_ID, Menu.NONE, R.string.action_reset_terminal);
menu.add(Menu.NONE, CONTEXT_MENU_KILL_PROCESS_ID, Menu.NONE, getResources().getString(R.string.action_kill_process, getCurrentSession().getPid())).setEnabled(currentSession.isRunning());
menu.add(Menu.NONE, CONTEXT_MENU_STYLING_ID, Menu.NONE, R.string.action_style_terminal);
Expand Down Expand Up @@ -668,6 +673,9 @@ public boolean onContextItemSelected(MenuItem item) {
case CONTEXT_MENU_SHARE_TRANSCRIPT_ID:
mTermuxTerminalViewClient.shareSessionTranscript();
return true;
case CONTEXT_MENU_SHARE_SELECTED_TEXT:
mTermuxTerminalViewClient.shareSelectedText();
return true;
case CONTEXT_MENU_AUTOFILL_ID:
requestAutoFill();
return true;
Expand Down Expand Up @@ -697,6 +705,13 @@ public boolean onContextItemSelected(MenuItem item) {
}
}

@Override
public void onContextMenuClosed(Menu menu) {
super.onContextMenuClosed(menu);
// onContextMenuClosed() is triggered twice if back button is pressed to dismiss instead of tap for some reason
mTerminalView.onContextMenuClosed(menu);
}

private void showKillSessionDialog(TerminalSession session) {
if (session == null) return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,13 @@ public void shareSessionTranscript() {
transcriptText, mActivity.getString(R.string.title_share_transcript_with));
}

public void shareSelectedText() {
String selectedText = mActivity.getTerminalView().getStoredSelectedText();
if (DataUtils.isNullOrEmpty(selectedText)) return;
ShareUtils.shareText(mActivity, mActivity.getString(R.string.title_share_selected_text),
selectedText, mActivity.getString(R.string.title_share_selected_text_with));
}

public void showUrlSelection() {
TerminalSession session = mActivity.getCurrentSession();
if (session == null) return;
Expand Down
30 changes: 30 additions & 0 deletions terminal-view/src/main/java/com/termux/view/TerminalView.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
Expand All @@ -19,6 +20,7 @@
import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
Expand All @@ -30,6 +32,7 @@
import android.view.inputmethod.InputConnection;
import android.widget.Scroller;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.termux.terminal.KeyHandler;
Expand Down Expand Up @@ -456,6 +459,14 @@ public void onScreenUpdated(boolean skipScrolling) {
if (mAccessibilityEnabled) setContentDescription(getText());
}

/** This must be called by the hosting activity in {@link Activity#onContextMenuClosed(Menu)}
* when context menu for the {@link TerminalView} is started by
* {@link TextSelectionCursorController#ACTION_MORE} is closed. */
public void onContextMenuClosed(Menu menu) {
// Unset the stored text since it shouldn't be used anymore and should be cleared from memory
unsetStoredSelectedText();
}

/**
* Sets the text size, which in turn sets the number of rows and columns.
*
Expand Down Expand Up @@ -1206,6 +1217,25 @@ public boolean isSelectingText() {
}
}

/** Get the currently selected text if selecting. */
public String getSelectedText() {
if (isSelectingText() && mTextSelectionCursorController != null)
return mTextSelectionCursorController.getSelectedText();
else
return null;
}

/** Get the selected text stored before "MORE" button was pressed on the context menu. */
@Nullable
public String getStoredSelectedText() {
return mTextSelectionCursorController != null ? mTextSelectionCursorController.getStoredSelectedText() : null;
}

/** Unset the selected text stored before "MORE" button was pressed on the context menu. */
public void unsetStoredSelectedText() {
if (mTextSelectionCursorController != null) mTextSelectionCursorController.unsetStoredSelectedText();
}

private ActionMode getTextSelectionActionMode() {
if (mTextSelectionCursorController != null) {
return mTextSelectionCursorController.getActionMode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

import com.termux.terminal.TerminalBuffer;
import com.termux.terminal.WcWidth;
import com.termux.view.R;
Expand All @@ -20,16 +22,17 @@ public class TextSelectionCursorController implements CursorController {

private final TerminalView terminalView;
private final TextSelectionHandleView mStartHandle, mEndHandle;
private String mStoredSelectedText;
private boolean mIsSelectingText = false;
private long mShowStartTime = System.currentTimeMillis();

private final int mHandleHeight;
private int mSelX1 = -1, mSelX2 = -1, mSelY1 = -1, mSelY2 = -1;

private ActionMode mActionMode;
private final int ACTION_COPY = 1;
private final int ACTION_PASTE = 2;
private final int ACTION_MORE = 3;
public final int ACTION_COPY = 1;
public final int ACTION_PASTE = 2;
public final int ACTION_MORE = 3;

public TextSelectionCursorController(TerminalView terminalView) {
this.terminalView = terminalView;
Expand Down Expand Up @@ -112,7 +115,7 @@ public boolean onCreateActionMode(ActionMode mode, Menu menu) {

ClipboardManager clipboard = (ClipboardManager) terminalView.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
menu.add(Menu.NONE, ACTION_COPY, Menu.NONE, R.string.copy_text).setShowAsAction(show);
menu.add(Menu.NONE, ACTION_PASTE, Menu.NONE, R.string.paste_text).setEnabled(clipboard.hasPrimaryClip()).setShowAsAction(show);
menu.add(Menu.NONE, ACTION_PASTE, Menu.NONE, R.string.paste_text).setEnabled(clipboard != null && clipboard.hasPrimaryClip()).setShowAsAction(show);
menu.add(Menu.NONE, ACTION_MORE, Menu.NONE, R.string.text_selection_more);
return true;
}
Expand All @@ -131,7 +134,7 @@ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

switch (item.getItemId()) {
case ACTION_COPY:
String selectedText = terminalView.mEmulator.getSelectedText(mSelX1, mSelY1, mSelX2, mSelY2).trim();
String selectedText = getSelectedText();
terminalView.mTermSession.onCopyTextToClipboard(selectedText);
terminalView.stopTextSelectionMode();
break;
Expand All @@ -140,7 +143,13 @@ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
terminalView.mTermSession.onPasteTextFromClipboard();
break;
case ACTION_MORE:
terminalView.stopTextSelectionMode(); //we stop text selection first, otherwise handles will show above popup
// We first store the selected text in case TerminalViewClient needs the
// selected text before MORE button was pressed since we are going to
// stop selection mode
mStoredSelectedText = getSelectedText();
// The text selection needs to be stopped before showing context menu,
// otherwise handles will show above popup
terminalView.stopTextSelectionMode();
terminalView.showContextMenu();
break;
}
Expand Down Expand Up @@ -361,6 +370,22 @@ public void getSelectors(int[] sel) {
sel[3] = mSelX2;
}

/** Get the currently selected text. */
public String getSelectedText() {
return terminalView.mEmulator.getSelectedText(mSelX1, mSelY1, mSelX2, mSelY2);
}

/** Get the selected text stored before "MORE" button was pressed on the context menu. */
@Nullable
public String getStoredSelectedText() {
return mStoredSelectedText;
}

/** Unset the selected text stored before "MORE" button was pressed on the context menu. */
public void unsetStoredSelectedText() {
mStoredSelectedText = null;
}

public ActionMode getActionMode() {
return mActionMode;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ public static CharSequence getTextFromClipboard(Context context, boolean coerceT



/**
* Open a url.
*
* @param context The context for operations.
Expand Down

0 comments on commit 21804bc

Please sign in to comment.