Skip to content

Commit

Permalink
Added: Add support for session action for foreground commands
Browse files Browse the repository at this point in the history
Valid values are defined by `TermuxConstants.TERMUX_APP.TERMUX_SERVICE.VALUE_EXTRA_SESSION_ACTION_*`, currently, between `0` and `3`.
https://github.com/termux/termux-app/blob/v0.117/termux-shared/src/main/java/com/termux/shared/termux/TermuxConstants.java#L856
  • Loading branch information
agnostic-apollo committed Sep 11, 2021
1 parent 49acd10 commit 6f6ddd0
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 40 deletions.
101 changes: 77 additions & 24 deletions app/src/main/java/com/termux/tasker/EditConfigurationActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.termux.shared.models.TextIOInfo;
import com.termux.shared.models.errors.Error;
import com.termux.shared.termux.TermuxConstants;
import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_SERVICE;
import com.termux.shared.file.FileUtils;
import com.termux.shared.termux.TermuxUtils;
import com.termux.tasker.utils.LoggerUtils;
Expand All @@ -34,6 +35,7 @@
import android.widget.AutoCompleteTextView;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;

import java.io.File;
Expand Down Expand Up @@ -61,6 +63,7 @@ public final class EditConfigurationActivity extends AbstractPluginActivity {
private TextInputLayout mWorkingDirectoryPathTextLayout;
private AutoCompleteTextView mWorkingDirectoryPathText;
private TextView mStdinView;
private EditText mSessionAction;
private CheckBox mInTerminalCheckbox;
private CheckBox mWaitForResult;
private TextView mExecutableAbsolutePathText;
Expand Down Expand Up @@ -109,6 +112,7 @@ protected void onCreate(final Bundle savedInstanceState) {
mWorkingDirectoryPathTextLayout = findViewById(R.id.layout_working_directory_path);
mWorkingDirectoryPathText = findViewById(R.id.working_directory_path);
mStdinView = findViewById(R.id.view_stdin);
mSessionAction = findViewById(R.id.session_action);
mInTerminalCheckbox = findViewById(R.id.in_terminal);
mWaitForResult = findViewById(R.id.wait_for_result);
mExecutableAbsolutePathText = findViewById(R.id.executable_absolute_path);
Expand All @@ -121,6 +125,7 @@ protected void onCreate(final Bundle savedInstanceState) {
setExecutionPathViews();
setWorkingDirectoryPathViews();
setStdinView();
setSessionActionViews();
setInTerminalView();

// Currently savedInstanceState bundle is not supported
Expand Down Expand Up @@ -154,6 +159,11 @@ protected void onCreate(final Bundle savedInstanceState) {
updateStdinViewText();
updateStdinViewVisibility(inTerminal);

final String sessionAction = localeBundle.getString(PluginBundleManager.EXTRA_SESSION_ACTION);
mSessionAction.setText(sessionAction);
processSessionAction(sessionAction);
updateSessionActionViewVisibility(inTerminal);

final boolean waitForResult = localeBundle.getBoolean(PluginBundleManager.EXTRA_WAIT_FOR_RESULT);
mWaitForResult.setChecked(waitForResult);
}
Expand Down Expand Up @@ -192,13 +202,7 @@ public boolean onOptionsItemSelected(MenuItem item) {


private void setExecutionPathViews() {
mExecutablePathText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

mExecutablePathText.addTextChangedListener(new AfterTextChangedWatcher() {
@Override
public void afterTextChanged(Editable editable) {
processExecutablePath(editable == null ? null : editable.toString());
Expand All @@ -211,13 +215,7 @@ public void afterTextChanged(Editable editable) {


private void setWorkingDirectoryPathViews() {
mWorkingDirectoryPathText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

mWorkingDirectoryPathText.addTextChangedListener(new AfterTextChangedWatcher() {
@Override
public void afterTextChanged(Editable editable) {
processWorkingDirectoryPath(editable == null ? null : editable.toString());
Expand Down Expand Up @@ -263,10 +261,22 @@ private void updateStdinViewText() {

private void updateStdinViewVisibility(boolean inTerminal) {
if (mStdinView == null) return;
if (inTerminal)
mStdinView.setVisibility(View.GONE);
else
mStdinView.setVisibility(View.VISIBLE);
mStdinView.setVisibility(inTerminal ? View.GONE : View.VISIBLE);
}


private void setSessionActionViews() {
mSessionAction.addTextChangedListener(new AfterTextChangedWatcher() {
@Override
public void afterTextChanged(Editable editable) {
processSessionAction(editable == null ? null : editable.toString());
}
});
}

private void updateSessionActionViewVisibility(boolean inTerminal) {
if (mSessionAction == null) return;
mSessionAction.setVisibility(inTerminal ? View.VISIBLE : View.GONE);
}


Expand All @@ -275,6 +285,7 @@ private void setInTerminalView() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
updateStdinViewVisibility(isChecked);
updateSessionActionViewVisibility(isChecked);
}
});
}
Expand Down Expand Up @@ -566,6 +577,32 @@ else if (workingDirectoryPathText.startsWith("$PREFIX/") || workingDirectoryPath
mWorkingDirectoryPathText.showDropDown();
}

private void processSessionAction(String sessionActionString) {
processIntFieldValue(mSessionAction, sessionActionString,
TERMUX_SERVICE.MIN_VALUE_EXTRA_SESSION_ACTION, TERMUX_SERVICE.MAX_VALUE_EXTRA_SESSION_ACTION);
}

private void processIntFieldValue(EditText editText, String stringValue, int min, int max) {
if (editText == null) return;
editText.setError(null);
if (DataUtils.isNullOrEmpty(stringValue)) return;
if (PluginUtils.isPluginHostAppVariableContainingString(stringValue)) return;

Integer value = null;
boolean invalid = false;

try {
value = Integer.parseInt(stringValue);
}
catch (Exception e) {
invalid = true;
}

if (invalid || value < min || value > max) {
editText.setError(getString(R.string.error_int_not_in_range, min, max));
}
}




Expand All @@ -577,9 +614,10 @@ public void finish() {
return;
}

final String executable = mExecutablePathText.getText() == null ? null : mExecutablePathText.getText().toString();
final String arguments = mArgumentsText.getText() == null ? null : mArgumentsText.getText().toString();
final String workingDirectory = mWorkingDirectoryPathText.getText() == null ? null : mWorkingDirectoryPathText.getText().toString();
final String executable = DataUtils.getDefaultIfUnset(mExecutablePathText.getText() == null ? null : mExecutablePathText.getText().toString(), null);
final String arguments = DataUtils.getDefaultIfUnset(mArgumentsText.getText() == null ? null : mArgumentsText.getText().toString(), null);
final String workingDirectory = DataUtils.getDefaultIfUnset(mWorkingDirectoryPathText.getText() == null ? null : mWorkingDirectoryPathText.getText().toString(), null);
final String sessionAction = DataUtils.getDefaultIfUnset(mSessionAction.getText() == null ? null : mSessionAction.getText().toString(), null);
final boolean inTerminal = mInTerminalCheckbox.isChecked();
final boolean waitForResult = mWaitForResult.isChecked();

Expand All @@ -599,7 +637,7 @@ public void finish() {
* stored in the Bundle, as Locale's classloader will not recognize it).
*/
final Bundle resultBundle = PluginBundleManager.generateBundle(getApplicationContext(),
executable, arguments, workingDirectory, mStdin, inTerminal, waitForResult);
executable, arguments, workingDirectory, mStdin, sessionAction, inTerminal, waitForResult);
if (resultBundle == null) {
Logger.showToast(this, getString(R.string.error_generate_plugin_bundle_failed), true);
setResult(RESULT_CODE_FAILED, resultIntent);
Expand All @@ -610,7 +648,8 @@ public void finish() {
Logger.logDebug(LOG_TAG, "Result bundle size: " + PluginBundleManager.getBundleSize(resultBundle));

// The blurb is a concise status text to be displayed in the host's UI.
final String blurb = PluginBundleManager.generateBlurb(this, executable, arguments, workingDirectory, mStdin, inTerminal, waitForResult);
final String blurb = PluginBundleManager.generateBlurb(this, executable, arguments,
workingDirectory, mStdin, sessionAction, inTerminal, waitForResult);

// If host supports variable replacement when running plugin action, then
// request it to replace variables in following fields
Expand All @@ -619,7 +658,8 @@ public void finish() {
PluginBundleManager.EXTRA_EXECUTABLE,
PluginBundleManager.EXTRA_ARGUMENTS,
PluginBundleManager.EXTRA_WORKDIR,
PluginBundleManager.EXTRA_STDIN
PluginBundleManager.EXTRA_STDIN,
PluginBundleManager.EXTRA_SESSION_ACTION
});
}

Expand Down Expand Up @@ -689,4 +729,17 @@ public void onActivityResult(ActivityResult result) {
});
}


static class AfterTextChangedWatcher implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

@Override
public void afterTextChanged(Editable editable) {
}
}

}
7 changes: 5 additions & 2 deletions app/src/main/java/com/termux/tasker/FireReceiver.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,11 @@ public void onReceive(final Context context, final Intent intent) {
executionCommand.inBackground = !(intent.getBooleanExtra(PluginBundleManager.EXTRA_TERMINAL, false));
final boolean waitForResult = bundle.getBoolean(PluginBundleManager.EXTRA_WAIT_FOR_RESULT, true);

if (executionCommand.inBackground)
if (executionCommand.inBackground) {
executionCommand.stdin = IntentUtils.getStringExtraIfSet(intent, PluginBundleManager.EXTRA_STDIN, null);

} else {
executionCommand.sessionAction = IntentUtils.getStringExtraIfSet(intent, PluginBundleManager.EXTRA_SESSION_ACTION, null);
}

// If Termux app is not installed, enabled or accessible with current context or if
// TermuxConstants.TERMUX_PREFIX_DIR_PATH does not exist or has required permissions, then
Expand Down Expand Up @@ -184,6 +186,7 @@ public void onReceive(final Context context, final Intent intent) {
if (executionCommand.workingDirectory != null && !executionCommand.workingDirectory.isEmpty())
executionIntent.putExtra(TERMUX_SERVICE.EXTRA_WORKDIR, executionCommand.workingDirectory);
executionIntent.putExtra(TERMUX_SERVICE.EXTRA_STDIN, executionCommand.stdin);
executionIntent.putExtra(TERMUX_SERVICE.EXTRA_SESSION_ACTION, executionCommand.sessionAction);
executionIntent.putExtra(TERMUX_SERVICE.EXTRA_BACKGROUND, executionCommand.inBackground);

// Send execution intent to TERMUX_SERVICE
Expand Down
33 changes: 24 additions & 9 deletions app/src/main/java/com/termux/tasker/PluginBundleManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ public class PluginBundleManager {
/** The {@code String} extra for stdin for background commands. */
public static final String EXTRA_STDIN = TermuxConstants.TERMUX_TASKER_PACKAGE_NAME + ".extra.STDIN"; // Default: "com.termux.tasker.extra.STDIN"

/** The {@code String} extra for terminal session action defined by
* {@link com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_SERVICE}
* `VALUE_EXTRA_SESSION_ACTION_*` values.
*/
public static final String EXTRA_SESSION_ACTION = TermuxConstants.TERMUX_TASKER_PACKAGE_NAME + ".extra.SESSION_ACTION"; // Default: "com.termux.tasker.extra.SESSION_ACTION"

/** The {@code boolean} extra for whether the executable should be run inside a terminal. */
public static final String EXTRA_TERMINAL = TermuxConstants.TERMUX_TASKER_PACKAGE_NAME + ".extra.TERMINAL"; // Default: "com.termux.tasker.extra.TERMINAL"

Expand Down Expand Up @@ -73,6 +79,7 @@ public static String parseBundle(@NonNull final Context context, final Bundle bu
* The bundle may optionally contain:
* - EXTRA_WORKDIR
* - EXTRA_STDIN
* - EXTRA_SESSION_ACTION
* - EXTRA_TERMINAL
* - EXTRA_WAIT_FOR_RESULT
* - VARIABLE_REPLACE_KEYS
Expand All @@ -91,13 +98,13 @@ public static String parseBundle(@NonNull final Context context, final Bundle bu
}

/*
* Check if bundle contains at least 3 keys but no more than 8.
* Check if bundle contains at least 3 keys but no more than 9.
* Run this test after checking for required Bundle extras above so that the error message
* is more useful. (E.g. the caller will see what extras are missing, rather than just a
* message that there is the wrong number).
*/
if (bundle.keySet().size() < 3 || bundle.keySet().size() > 8) {
return String.format("The bundle must contain 3-8 keys, but currently contains %d keys.", bundle.keySet().size());
if (bundle.keySet().size() < 3 || bundle.keySet().size() > 9) {
return String.format("The bundle must contain 3-9 keys, but currently contains %d keys.", bundle.keySet().size());
}

if (TextUtils.isEmpty(bundle.getString(EXTRA_EXECUTABLE))) {
Expand All @@ -123,7 +130,7 @@ public static String parseBundle(@NonNull final Context context, final Bundle bu
@Nullable
public static Bundle generateBundle(@NonNull final Context context, final String executable,
final String arguments, final String workingDirectory,
final String stdin,
final String stdin, final String sessionAction,
final boolean inTerminal, final boolean waitForResult) {
final Bundle result = new Bundle();
result.putString(EXTRA_EXECUTABLE, executable);
Expand All @@ -132,8 +139,11 @@ public static Bundle generateBundle(@NonNull final Context context, final String
result.putBoolean(EXTRA_TERMINAL, inTerminal);
result.putBoolean(EXTRA_WAIT_FOR_RESULT, waitForResult);

if (!inTerminal)
if (!inTerminal) {
result.putString(EXTRA_STDIN, stdin);
} else {
result.putString(EXTRA_SESSION_ACTION, sessionAction);
}

Integer versionCode = PackageUtils.getVersionCodeForPackage(context);
if (versionCode == null) {
Expand All @@ -151,14 +161,19 @@ public static Bundle generateBundle(@NonNull final Context context, final String
* @return A blurb for the plug-in.
*/
public static String generateBlurb(@NonNull final Context context, final String executable,
final String arguments, final String workingDirectory, final String stdin,
final boolean inTerminal, final boolean waitForResult) {
final String arguments, final String workingDirectory,
final String stdin, final String sessionAction,
final boolean inTerminal, final boolean waitForResult) {
StringBuilder builder = new StringBuilder();
builder.append(context.getString(R.string.blurb_executable_and_arguments, executable, arguments));
builder.append(context.getString(R.string.blurb_executable_and_arguments, executable, arguments == null ? "" : " " + arguments));
builder.append("\n\n").append(context.getString(R.string.blurb_working_directory, (!DataUtils.isNullOrEmpty(workingDirectory) ? UNICODE_CHECK : UNICODE_UNCHECK)));

if (!inTerminal)
if (!inTerminal) {
builder.append("\n").append(context.getString(R.string.blurb_stdin, (!DataUtils.isNullOrEmpty(stdin) ? UNICODE_CHECK : UNICODE_UNCHECK)));
} else {
if (!DataUtils.isNullOrEmpty(sessionAction))
builder.append("\n").append(context.getString(R.string.blurb_session_action, sessionAction));
}

builder.append("\n").append(context.getString(R.string.blurb_in_terminal, (inTerminal ? UNICODE_CHECK : UNICODE_UNCHECK)));
builder.append("\n").append(context.getString(R.string.blurb_wait_for_result, (waitForResult ? UNICODE_CHECK : UNICODE_UNCHECK)));
Expand Down
36 changes: 36 additions & 0 deletions app/src/main/res/layout/edit_activity.xml
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,42 @@



<!-- Session Action -->
<androidx.cardview.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:padding="@dimen/activity_view_padding_mini"
card_view:cardCornerRadius="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start|center_vertical"
android:textSize="14sp"
android:textStyle="bold"
android:textColor="@android:color/black"
android:text="@string/title_session_action"
tools:labelFor="@id/session_action" />

<EditText
android:id="@+id/session_action"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start|center_vertical"
android:importantForAutofill="no" />

</LinearLayout>
</androidx.cardview.widget.CardView>



<CheckBox
android:id="@+id/in_terminal"
android:layout_width="match_parent"
Expand Down
13 changes: 8 additions & 5 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<string name="title_arguments">Arguments</string>
<string name="title_working_directory_path">Working directory path</string>
<string name="title_stdin">Stdin</string>
<string name="title_session_action">Terminal Session Action</string>
<string name="title_execute_in_terminal">Execute in a terminal session</string>
<string name="title_wait_for_result">Wait for result for commands (Requires timeout > 0)</string>

Expand All @@ -28,6 +29,7 @@

<string name="error_executable_required">Executable required.</string>
<string name="error_null_or_empty_executable">The executable is null or empty.</string>
<string name="error_int_not_in_range">Value must be in between %1$d and %2$d.</string>

<string name="help">Visit %1$s for more info on plugin usage.</string>

Expand All @@ -40,11 +42,12 @@
<string name="error_generate_plugin_bundle_failed">Failed to generate plugin bundle</string>
<string name="error_get_version_code_failed">Failed to get version code for %1$s</string>

<string name="blurb_executable_and_arguments">%1$s %2$s</string>
<string name="blurb_working_directory">%1$s Working Directory</string>
<string name="blurb_stdin">%1$s Stdin</string>
<string name="blurb_in_terminal">%1$s Terminal Session</string>
<string name="blurb_wait_for_result">%1$s Wait For Result</string>
<string name="blurb_executable_and_arguments">%1$s%2$s</string>
<string name="blurb_working_directory">Working Directory %1$s</string>
<string name="blurb_stdin">Stdin %1$s</string>
<string name="blurb_session_action">Session Action %1$s</string>
<string name="blurb_in_terminal">Terminal Session %1$s</string>
<string name="blurb_wait_for_result">Wait For Result %1$s</string>

<!-- From Locale API: -->
<string name="twofortyfouram_locale_breadcrumb_format" tools:ignore="UnusedResources">%1$s%2$s%3$s</string>
Expand Down

0 comments on commit 6f6ddd0

Please sign in to comment.