Skip to content

Commit d10bbdd

Browse files
committed
add support for klyx:// deep links
1 parent 4da523c commit d10bbdd

4 files changed

Lines changed: 73 additions & 17 deletions

File tree

androidApp/src/main/AndroidManifest.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,17 @@
5959
android:scheme="content" />
6060
</intent-filter>
6161

62+
<intent-filter>
63+
<action android:name="android.intent.action.VIEW" />
64+
65+
<category android:name="android.intent.category.DEFAULT" />
66+
<category android:name="android.intent.category.BROWSABLE" />
67+
68+
<data
69+
android:host="open"
70+
android:scheme="klyx" />
71+
</intent-filter>
72+
6273
<meta-data
6374
android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI"
6475
android:value="true" />

build-logic/convention/src/main/kotlin/KotlinMultiplatformConventionPlugin.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ class KotlinMultiplatformConventionPlugin : Plugin<Project> {
3434

3535
listOf(
3636
iosArm64(),
37-
iosX64(),
3837
iosSimulatorArm64()
3938
).forEach { target ->
4039
target.binaries.framework {

klyx/src/androidMain/kotlin/com/klyx/activities/MainActivity.kt

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.klyx.activities
33
import android.annotation.SuppressLint
44
import android.app.ActivityManager
55
import android.content.Intent
6+
import android.net.Uri
67
import android.os.Build
78
import android.os.Bundle
89
import android.view.KeyEvent
@@ -31,11 +32,13 @@ import com.klyx.core.file.openFile
3132
import com.klyx.core.file.toKxFile
3233
import com.klyx.core.theme.LocalIsDarkMode
3334
import com.klyx.filetree.FileTreeViewModel
35+
import com.klyx.project.toWorktree
3436
import com.klyx.terminal.SessionBinder
3537
import com.klyx.terminal.event.TerminateAllSessionEvent
3638
import com.klyx.terminal.service.SessionService
3739
import com.klyx.ui.event.TerminalNotificationTapEvent
3840
import com.klyx.viewmodel.EditorViewModel
41+
import com.klyx.viewmodel.KlyxViewModel
3942
import io.github.vinceglb.filekit.FileKit
4043
import io.github.vinceglb.filekit.dialogs.init
4144
import kotlinx.coroutines.launch
@@ -48,6 +51,7 @@ class MainActivity : KlyxActivity(), Subscriber<CrashEvent> {
4851

4952
private val editorViewModel by viewModel<EditorViewModel>()
5053
private val fileTreeViewModel by viewModel<FileTreeViewModel>()
54+
private val klyxVm by viewModel<KlyxViewModel>()
5155

5256
@OptIn(UnsafeGlobalAccess::class)
5357
private val app by lazy { GlobalApp }
@@ -108,9 +112,39 @@ class MainActivity : KlyxActivity(), Subscriber<CrashEvent> {
108112
}
109113

110114
private fun handleIntent(intent: Intent) {
115+
val uri = intent.data
116+
117+
if (uri != null && uri.scheme == "klyx") {
118+
when (uri.host) {
119+
"open" -> {
120+
val path = uri.getQueryParameter("project")?.let { Uri.decode(it) }
121+
?: uri.getQueryParameter("file")?.let { Uri.decode(it) }
122+
123+
if (!path.isNullOrEmpty()) {
124+
val file = path.toKxFile()
125+
if (file.exists) {
126+
if (file.isDirectory) {
127+
klyxVm.openProject(file.toWorktree())
128+
} else if (file.isFile) {
129+
editorViewModel.openFile(file)
130+
}
131+
} else {
132+
notifier.error(
133+
title = "Invalid path",
134+
message = "${file.absolutePath} does not exist"
135+
)
136+
}
137+
}
138+
}
139+
}
140+
setIntent(Intent())
141+
return
142+
}
143+
111144
if (intent.action == Intent.ACTION_VIEW || intent.action == Intent.ACTION_EDIT) {
112-
val uri = intent.data!!
113-
editorViewModel.openFile(uri.toKxFile())
145+
if (uri != null) {
146+
editorViewModel.openFile(uri.toKxFile())
147+
}
114148
setIntent(Intent())
115149
} else if (intent.action == SessionService.ACTION_NOTIFICATION_TAP) {
116150
EventBus.INSTANCE.tryPost(TerminalNotificationTapEvent)
@@ -120,6 +154,7 @@ class MainActivity : KlyxActivity(), Subscriber<CrashEvent> {
120154
override fun onNewIntent(intent: Intent) {
121155
super.onNewIntent(intent)
122156
setIntent(intent)
157+
handleIntent(intent)
123158
}
124159

125160
@SuppressLint("RestrictedApi")
@@ -141,20 +176,6 @@ class MainActivity : KlyxActivity(), Subscriber<CrashEvent> {
141176
}
142177
}
143178

144-
private fun getSystemSpecs() = buildString {
145-
appendLine("Klyx: ${KlyxBuildConfig.VERSION_NAME} (${KlyxBuildConfig.VERSION_CODE})")
146-
appendLine("Android Version: ${Build.VERSION.RELEASE}")
147-
appendLine("Android SDK: ${Build.VERSION.SDK_INT}")
148-
appendLine("Architecture: ${Build.SUPPORTED_ABIS.first()}")
149-
150-
val activityManager = getSystemService(ActivityManager::class.java)
151-
val memoryInfo = ActivityManager.MemoryInfo()
152-
activityManager.getMemoryInfo(memoryInfo)
153-
154-
appendLine("Memory: ${memoryInfo.totalMem.humanBytes()}")
155-
append("CPU Count: ${Runtime.getRuntime().availableProcessors()}")
156-
}
157-
158179
override suspend fun onEvent(event: CrashEvent) {
159180
val isLogFileSaved = event.logFile != null
160181

scripts/cli/install.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/usr/bin/env bash
2+
3+
echo "Installing Klyx CLI..."
4+
5+
cat > $PREFIX/bin/klyx << 'EOF'
6+
#!/usr/bin/env bash
7+
8+
TARGET="${1:-$PWD}"
9+
TARGET=$(realpath "$TARGET")
10+
ENCODED=$(printf '%s\n' "$TARGET" | sed 's/ /%20/g')
11+
12+
if [ -d "$TARGET" ]; then
13+
TYPE="project"
14+
else
15+
TYPE="file"
16+
fi
17+
18+
am start \
19+
-a android.intent.action.VIEW \
20+
-d "klyx://open?$TYPE=$ENCODED"
21+
EOF
22+
23+
chmod +x $PREFIX/bin/klyx
24+
25+
echo "Done! You can now use: klyx ."

0 commit comments

Comments
 (0)