diff --git a/app/src/main/java/com/itsaky/androidide/actions/sidebar/TerminalSidebarAction.kt b/app/src/main/java/com/itsaky/androidide/actions/sidebar/TerminalSidebarAction.kt index d5a623b39..a758af199 100644 --- a/app/src/main/java/com/itsaky/androidide/actions/sidebar/TerminalSidebarAction.kt +++ b/app/src/main/java/com/itsaky/androidide/actions/sidebar/TerminalSidebarAction.kt @@ -26,6 +26,7 @@ import com.itsaky.androidide.actions.ActionData import com.itsaky.androidide.actions.requireContext import com.itsaky.androidide.activities.TerminalActivity import com.itsaky.androidide.projects.IProjectManager +import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_ACTIVITY import java.util.Objects import kotlin.reflect.KClass @@ -36,7 +37,7 @@ import kotlin.reflect.KClass */ class TerminalSidebarAction(context: Context, override val order: Int) : AbstractSidebarAction() { - override val id: String = "ide.editor.sidebar.terminal" + override val id: String = ID override val fragmentClass: KClass? = null init { @@ -44,15 +45,29 @@ class TerminalSidebarAction(context: Context, override val order: Int) : Abstrac icon = ContextCompat.getDrawable(context, R.drawable.ic_terminal) } + companion object { + + const val ID = "ide.editor.sidebar.terminal" + + fun startTerminalActivity(data: ActionData, isFailsafe: Boolean) { + val context = data.requireContext() + val intent = Intent(context, TerminalActivity::class.java).apply { + putExtra( + TerminalActivity.KEY_WORKING_DIRECTORY, + Objects.requireNonNull(IProjectManager.getInstance().projectDirPath) + ) + putExtra( + TerminalActivity.KEY_SESSION_NAME, + IProjectManager.getInstance().rootProject?.rootProject?.name + ) + putExtra(TERMUX_ACTIVITY.EXTRA_FAILSAFE_SESSION, isFailsafe) + } + context.startActivity(intent) + } + } + override suspend fun execAction(data: ActionData): Any { - val context = data.requireContext() - val intent = Intent(context, TerminalActivity::class.java) - intent.putExtra( - TerminalActivity.KEY_WORKING_DIRECTORY, - Objects.requireNonNull(IProjectManager.getInstance().projectDirPath) - ) - intent.putExtra(TerminalActivity.KEY_SESSION_NAME, IProjectManager.getInstance().rootProject?.rootProject?.name) - context.startActivity(intent) + startTerminalActivity(data, false) return true } } \ No newline at end of file diff --git a/app/src/main/java/com/itsaky/androidide/adapters/MainActionsListAdapter.kt b/app/src/main/java/com/itsaky/androidide/adapters/MainActionsListAdapter.kt index 3bf53b69b..7f103b097 100644 --- a/app/src/main/java/com/itsaky/androidide/adapters/MainActionsListAdapter.kt +++ b/app/src/main/java/com/itsaky/androidide/adapters/MainActionsListAdapter.kt @@ -50,6 +50,11 @@ constructor(val actions: List = emptyList()) : setOnClickListener { action.onClick?.invoke(action, it) } + action.onLongClick?.let { onLongClick -> + setOnLongClickListener { + onLongClick(action, it) + } + } } } } diff --git a/app/src/main/java/com/itsaky/androidide/fragments/MainFragment.kt b/app/src/main/java/com/itsaky/androidide/fragments/MainFragment.kt index 0a916d226..3c92abc85 100644 --- a/app/src/main/java/com/itsaky/androidide/fragments/MainFragment.kt +++ b/app/src/main/java/com/itsaky/androidide/fragments/MainFragment.kt @@ -26,6 +26,8 @@ import com.itsaky.androidide.utils.ILogger import com.itsaky.androidide.utils.flashError import com.itsaky.androidide.utils.flashSuccess import com.itsaky.androidide.viewmodel.MainViewModel +import com.termux.shared.termux.TermuxConstants +import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_ACTIVITY import org.eclipse.jgit.api.Git import org.eclipse.jgit.lib.ProgressMonitor import java.io.File @@ -63,7 +65,19 @@ class MainFragment : BaseFragment() { } } - actions.forEach { action -> action.onClick = onClick } + actions.forEach { action -> + action.onClick = onClick + + if (action.id == MainScreenAction.ACTION_OPEN_TERMINAL) { + action.onLongClick = { _: MainScreenAction, _: View -> + val intent = Intent(requireActivity(), TerminalActivity::class.java).apply { + putExtra(TERMUX_ACTIVITY.EXTRA_FAILSAFE_SESSION, true) + } + startActivity(intent) + true + } + } + } } binding!!.actions.adapter = MainActionsListAdapter(actions) diff --git a/app/src/main/java/com/itsaky/androidide/models/MainScreenAction.kt b/app/src/main/java/com/itsaky/androidide/models/MainScreenAction.kt index 6c78dda71..5c61a5193 100644 --- a/app/src/main/java/com/itsaky/androidide/models/MainScreenAction.kt +++ b/app/src/main/java/com/itsaky/androidide/models/MainScreenAction.kt @@ -34,7 +34,8 @@ constructor( val id: Int, @StringRes val text: Int, @DrawableRes val icon: Int, - var onClick: ((MainScreenAction, View) -> Unit)? = null + var onClick: ((MainScreenAction, View) -> Unit)? = null, + var onLongClick: ((MainScreenAction, View) -> Boolean)? = null ) { companion object { diff --git a/app/src/main/java/com/itsaky/androidide/utils/EditorSidebarActions.kt b/app/src/main/java/com/itsaky/androidide/utils/EditorSidebarActions.kt index 973042977..47dbfaec9 100644 --- a/app/src/main/java/com/itsaky/androidide/utils/EditorSidebarActions.kt +++ b/app/src/main/java/com/itsaky/androidide/utils/EditorSidebarActions.kt @@ -19,6 +19,7 @@ package com.itsaky.androidide.utils import android.content.Context import android.os.Bundle +import android.view.View import androidx.annotation.IdRes import androidx.core.view.forEach import androidx.navigation.NavController @@ -30,6 +31,7 @@ import androidx.navigation.fragment.FragmentNavigatorDestinationBuilder import androidx.navigation.fragment.NavHostFragment import androidx.navigation.get import androidx.navigation.navOptions +import com.google.android.material.navigation.NavigationBarMenuView import com.google.android.material.shape.CornerFamily import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.shape.ShapeAppearanceModel @@ -175,6 +177,22 @@ internal object EditorSidebarActions { it.isChecked = true binding.title.text = it.title } + + rail.viewTreeObserver.addOnPreDrawListener { + val railView = railRef.get() + if (railView != null) { + + // set long click action to terminal action + // noinspection RestrictedApi + (railView.menuView as NavigationBarMenuView) + .findViewById(TerminalSidebarAction.ID.hashCode()) + ?.setOnLongClickListener { + TerminalSidebarAction.startTerminalActivity(data, true) + true + } + } + true + } } /** diff --git a/termux/termux-app/src/main/java/com/termux/app/TermuxActivity.java b/termux/termux-app/src/main/java/com/termux/app/TermuxActivity.java index a3787997e..a4cd93a09 100644 --- a/termux/termux-app/src/main/java/com/termux/app/TermuxActivity.java +++ b/termux/termux-app/src/main/java/com/termux/app/TermuxActivity.java @@ -414,13 +414,25 @@ public class TermuxActivity extends BaseIDEActivity implements ServiceConnection mTermuxService.getTermuxSessions().stream().filter(session -> Objects.equals( session.getTerminalSession().getCwd(), workingDir)).findFirst(); + boolean launchFailsafe = + intent != null && intent.getBooleanExtra(TERMUX_ACTIVITY.EXTRA_FAILSAFE_SESSION, + false); + if (existingSession.isPresent()) { // requested to open a session with a specific working directory // a session is already opened with the provided working directory - mTermuxTerminalSessionActivityClient.setCurrentSession(existingSession.get().getTerminalSession()); + final var session = existingSession.get(); + + if (session.getExecutionCommand().isFailsafe != launchFailsafe) { + // the existing session's failsafe status does not match with the requested + // failsafe status, create a new session + mTermuxTerminalSessionActivityClient.addNewSession(launchFailsafe, sessionName, workingDir); + } else { + mTermuxTerminalSessionActivityClient.setCurrentSession(session.getTerminalSession()); + } } else if (workingDir != null) { // working directory is provided, but no session has that specific CWD - mTermuxTerminalSessionActivityClient.addNewSession(false, sessionName, workingDir); + mTermuxTerminalSessionActivityClient.addNewSession(launchFailsafe, sessionName, workingDir); } else { // no working directory provided mTermuxTerminalSessionActivityClient.setCurrentSession(mTermuxTerminalSessionActivityClient.getCurrentStoredSessionOrLast());