Skip to content

Commit 5133b73

Browse files
authored
ADFA-3645 | Open terminal in adjacent window on large screens (#1173)
* feat: open terminal in adjacent window on large screens Extract multi-window intent flags and handle new intents in TerminalActivity. * fix: potential race condition with TermuxService, fixed file indentation
1 parent a6531a4 commit 5133b73

File tree

5 files changed

+101
-32
lines changed

5 files changed

+101
-32
lines changed

app/src/main/java/com/itsaky/androidide/actions/main/OpenTerminalAction.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.itsaky.androidide.actions.ActionItem
1010
import com.itsaky.androidide.actions.markInvisible
1111
import com.itsaky.androidide.activities.TerminalActivity
1212
import com.itsaky.androidide.idetooltips.TooltipTag
13+
import com.itsaky.androidide.utils.applyMultiWindowFlags
1314

1415
class OpenTerminalAction(context: Context) : ActionItem {
1516

@@ -38,7 +39,9 @@ class OpenTerminalAction(context: Context) : ActionItem {
3839

3940
override suspend fun execAction(data: ActionData): Any {
4041
val context = data.get(Context::class.java) ?: return false
41-
context.startActivity(Intent(context, TerminalActivity::class.java))
42+
val intent = Intent(context, TerminalActivity::class.java)
43+
.applyMultiWindowFlags(context)
44+
context.startActivity(intent)
4245
return true
4346
}
4447
}

app/src/main/java/com/itsaky/androidide/actions/sidebar/TerminalSidebarAction.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import com.itsaky.androidide.actions.requireContext
2727
import com.itsaky.androidide.activities.TerminalActivity
2828
import com.itsaky.androidide.idetooltips.TooltipTag
2929
import com.itsaky.androidide.projects.IProjectManager
30+
import com.itsaky.androidide.utils.applyMultiWindowFlags
3031
import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_ACTIVITY
3132
import java.util.Objects
3233
import kotlin.reflect.KClass
@@ -71,7 +72,7 @@ class TerminalSidebarAction(
7172
?.name,
7273
)
7374
putExtra(TERMUX_ACTIVITY.EXTRA_FAILSAFE_SESSION, isFailsafe)
74-
}
75+
}.applyMultiWindowFlags(context)
7576
context.startActivity(intent)
7677
}
7778
}

common/src/main/java/com/itsaky/androidide/activities/editor/HelpActivity.kt

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import com.itsaky.androidide.common.databinding.ActivityHelpBinding
3333
import com.itsaky.androidide.utils.DeviceFormFactorUtils
3434
import com.itsaky.androidide.utils.isSystemInDarkMode
3535
import com.itsaky.androidide.utils.UrlManager
36+
import com.itsaky.androidide.utils.applyMultiWindowFlags
3637
import org.adfa.constants.CONTENT_TITLE_KEY
3738

3839
class HelpActivity : BaseIDEActivity() {
@@ -46,20 +47,10 @@ class HelpActivity : BaseIDEActivity() {
4647
putExtra(CONTENT_KEY, url)
4748
putExtra(CONTENT_TITLE_KEY, title)
4849

49-
val formFactor = DeviceFormFactorUtils.getCurrent(context)
50-
51-
if (formFactor.isLargeScreenLike) {
52-
addFlags(
53-
Intent.FLAG_ACTIVITY_NEW_TASK or
54-
Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
55-
Intent.FLAG_ACTIVITY_SINGLE_TOP or
56-
Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT
57-
)
50+
if (DeviceFormFactorUtils.getCurrent(context).isLargeScreenLike) {
5851
data = MULTI_WINDOW_URI.toUri()
59-
} else if (context !is Activity) {
60-
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
6152
}
62-
}
53+
}.applyMultiWindowFlags(context)
6354
context.startActivity(intent)
6455
}
6556
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.itsaky.androidide.utils
2+
3+
import android.app.Activity
4+
import android.content.Context
5+
import android.content.Intent
6+
7+
8+
fun Intent.applyMultiWindowFlags(context: Context): Intent = apply {
9+
val formFactor = DeviceFormFactorUtils.getCurrent(context)
10+
11+
if (formFactor.isLargeScreenLike) {
12+
addFlags(
13+
Intent.FLAG_ACTIVITY_NEW_TASK or
14+
Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
15+
Intent.FLAG_ACTIVITY_SINGLE_TOP or
16+
Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT
17+
)
18+
} else if (context !is Activity) {
19+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
20+
}
21+
}

termux/termux-app/src/main/java/com/itsaky/androidide/activities/TerminalActivity.kt

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,38 +18,91 @@
1818
package com.itsaky.androidide.activities
1919

2020
import android.content.ComponentName
21+
import android.content.Intent
2122
import android.os.Bundle
2223
import android.os.IBinder
2324
import androidx.core.content.ContextCompat
2425
import androidx.core.view.WindowCompat
2526
import androidx.lifecycle.lifecycleScope
2627
import com.itsaky.androidide.utils.Environment
2728
import com.termux.app.TermuxActivity
29+
import com.termux.app.TermuxService
30+
import com.termux.shared.termux.TermuxConstants
2831
import kotlinx.coroutines.Dispatchers
2932
import kotlinx.coroutines.launch
3033

3134
/**
3235
* @author Akash Yadav
3336
*/
3437
class TerminalActivity : TermuxActivity() {
38+
private var pendingWorkingDir: String? = null
39+
private var pendingSessionName: String? = null
40+
private var pendingIsFailsafe: Boolean = false
3541

36-
override val navigationBarColor: Int
37-
get() = ContextCompat.getColor(this, android.R.color.black)
38-
override val statusBarColor: Int
39-
get() = ContextCompat.getColor(this, android.R.color.black)
40-
41-
override fun onCreate(savedInstanceState: Bundle?) {
42-
val controller = WindowCompat.getInsetsController(
43-
window, window.decorView)
44-
controller.isAppearanceLightNavigationBars = false
45-
controller.isAppearanceLightStatusBars = false
46-
super.onCreate(savedInstanceState)
47-
}
48-
49-
override fun onServiceConnected(componentName: ComponentName?, service: IBinder?) {
50-
super.onServiceConnected(componentName, service)
51-
lifecycleScope.launch(Dispatchers.IO) {
52-
Environment.mkdirIfNotExists(Environment.TMP_DIR)
42+
override val navigationBarColor: Int
43+
get() = ContextCompat.getColor(this, android.R.color.black)
44+
override val statusBarColor: Int
45+
get() = ContextCompat.getColor(this, android.R.color.black)
46+
47+
override fun onCreate(savedInstanceState: Bundle?) {
48+
val controller = WindowCompat.getInsetsController(window, window.decorView)
49+
controller.isAppearanceLightNavigationBars = false
50+
controller.isAppearanceLightStatusBars = false
51+
super.onCreate(savedInstanceState)
52+
}
53+
54+
override fun onServiceConnected(componentName: ComponentName?, service: IBinder?) {
55+
super.onServiceConnected(componentName, service)
56+
lifecycleScope.launch(Dispatchers.IO) {
57+
Environment.mkdirIfNotExists(Environment.TMP_DIR)
58+
}
59+
60+
val termuxService = mTermuxService
61+
if (termuxService != null && (pendingWorkingDir != null || pendingSessionName != null)) {
62+
createAndSetSession(termuxService, pendingWorkingDir, pendingSessionName, pendingIsFailsafe)
63+
64+
pendingWorkingDir = null
65+
pendingSessionName = null
66+
pendingIsFailsafe = false
67+
}
68+
}
69+
70+
override fun onNewIntent(intent: Intent?) {
71+
super.onNewIntent(intent)
72+
setIntent(intent)
73+
if (intent == null) return
74+
75+
val newWorkingDir = intent.getStringExtra(TermuxConstants.TERMUX_APP.TERMUX_ACTIVITY.EXTRA_SESSION_WORKING_DIR)
76+
val newSessionName = intent.getStringExtra(TermuxConstants.TERMUX_APP.TERMUX_ACTIVITY.EXTRA_SESSION_NAME)
77+
val isFailsafe = intent.getBooleanExtra(TermuxConstants.TERMUX_APP.TERMUX_ACTIVITY.EXTRA_FAILSAFE_SESSION, false)
78+
79+
val service = mTermuxService
80+
if (service != null) {
81+
createAndSetSession(service, newWorkingDir, newSessionName, isFailsafe)
82+
} else {
83+
pendingWorkingDir = newWorkingDir
84+
pendingSessionName = newSessionName
85+
pendingIsFailsafe = isFailsafe
86+
}
87+
}
88+
89+
private fun createAndSetSession(
90+
service: TermuxService,
91+
workingDir: String?,
92+
sessionName: String?,
93+
isFailsafe: Boolean
94+
) {
95+
val newSession = service.createTermuxSession(
96+
null,
97+
null,
98+
null,
99+
workingDir,
100+
isFailsafe,
101+
sessionName
102+
)
103+
104+
if (newSession != null) {
105+
mTermuxTerminalSessionActivityClient.setCurrentSession(newSession.terminalSession)
106+
}
53107
}
54-
}
55108
}

0 commit comments

Comments
 (0)