From 05454401f85fba2196dd762f6bc386bdfc03200c Mon Sep 17 00:00:00 2001 From: Gaurav Ujjwal Date: Mon, 4 Mar 2024 22:32:12 +0530 Subject: [PATCH] Add option to auto-connect to a server on app start Re: #204 --- .../com/gaurav/avnc/ui/home/BasicHomeTest.kt | 23 +++++++++++++++++++ .../com/gaurav/avnc/model/ServerProfile.kt | 7 ++++++ .../gaurav/avnc/model/db/ServerProfileDao.kt | 3 +++ .../com/gaurav/avnc/ui/home/HomeActivity.kt | 6 +++++ .../gaurav/avnc/viewmodel/HomeViewModel.kt | 4 ++++ app/src/main/res/drawable/ic_auto_connect.xml | 10 ++++++++ .../fragment_profile_editor_advanced.xml | 12 +++++++++- app/src/main/res/layout/server_item.xml | 6 +++++ app/src/main/res/values/strings.xml | 1 + 9 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/drawable/ic_auto_connect.xml diff --git a/app/src/androidTest/java/com/gaurav/avnc/ui/home/BasicHomeTest.kt b/app/src/androidTest/java/com/gaurav/avnc/ui/home/BasicHomeTest.kt index 6382bf44..e0270283 100644 --- a/app/src/androidTest/java/com/gaurav/avnc/ui/home/BasicHomeTest.kt +++ b/app/src/androidTest/java/com/gaurav/avnc/ui/home/BasicHomeTest.kt @@ -11,16 +11,22 @@ package com.gaurav.avnc.ui.home import android.app.Activity import android.app.Instrumentation import android.content.Intent +import androidx.test.core.app.ActivityScenario import androidx.test.espresso.Espresso.onView import androidx.test.espresso.intent.Intents import androidx.test.espresso.intent.matcher.IntentMatchers.* import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.gaurav.avnc.EmptyDatabaseRule import com.gaurav.avnc.R +import com.gaurav.avnc.TestServer +import com.gaurav.avnc.checkWillBeDisplayed import com.gaurav.avnc.doClick +import com.gaurav.avnc.model.ServerProfile import com.gaurav.avnc.ui.about.AboutActivity import com.gaurav.avnc.ui.prefs.PrefsActivity +import kotlinx.coroutines.runBlocking import org.hamcrest.Matchers.containsString import org.hamcrest.core.AllOf.allOf import org.junit.After @@ -90,4 +96,21 @@ class BasicHomeTest { )) Intents.assertNoUnverifiedIntents() } +} + +class AutoConnectTest { + @Rule + @JvmField + val dbRule = EmptyDatabaseRule() + + @Test + fun autoConnectOnStartup() { + val server = TestServer().apply { start() } + val profile = ServerProfile(host = server.host, port = server.port).apply { fConnectOnAppStart = true } + runBlocking { dbRule.db.serverProfileDao.insert(profile) } + ActivityScenario.launch(HomeActivity::class.java).use { + // Starting HomeActivity should automatically launch the connection + onView(withId(R.id.frame_view)).checkWillBeDisplayed() + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/gaurav/avnc/model/ServerProfile.kt b/app/src/main/java/com/gaurav/avnc/model/ServerProfile.kt index c3c49ee2..4844764f 100644 --- a/app/src/main/java/com/gaurav/avnc/model/ServerProfile.kt +++ b/app/src/main/java/com/gaurav/avnc/model/ServerProfile.kt @@ -191,6 +191,7 @@ data class ServerProfile( private const val FLAG_LEGACY_KEYSYM = 0x01L private const val FLAG_BUTTON_UP_DELAY = 0x02L private const val FLAG_ZOOM_LOCKED = 0x04L + const val FLAG_CONNECT_ON_APP_START = 0x08L } /** @@ -221,4 +222,10 @@ data class ServerProfile( */ @IgnoredOnParcel var fZoomLocked by Flag(FLAG_ZOOM_LOCKED) + + /** + * Try to automatically connect to this server when app starts. + */ + @IgnoredOnParcel + var fConnectOnAppStart by Flag(FLAG_CONNECT_ON_APP_START) } diff --git a/app/src/main/java/com/gaurav/avnc/model/db/ServerProfileDao.kt b/app/src/main/java/com/gaurav/avnc/model/db/ServerProfileDao.kt index 99a04418..3fc29321 100644 --- a/app/src/main/java/com/gaurav/avnc/model/db/ServerProfileDao.kt +++ b/app/src/main/java/com/gaurav/avnc/model/db/ServerProfileDao.kt @@ -35,6 +35,9 @@ interface ServerProfileDao { @Query("SELECT * FROM profiles WHERE name = :name") suspend fun getByName(name: String): List + @Query("SELECT * FROM profiles WHERE flags & ${ServerProfile.FLAG_CONNECT_ON_APP_START} != 0") + suspend fun getConnectableOnAppStart(): List + @Query("SELECT * FROM profiles WHERE name LIKE :query OR host LIKE :query OR sshHost LIKE :query ORDER BY useCount DESC") fun search(query: String): LiveData> diff --git a/app/src/main/java/com/gaurav/avnc/ui/home/HomeActivity.kt b/app/src/main/java/com/gaurav/avnc/ui/home/HomeActivity.kt index 7c1bc0ae..9f7f6e9f 100644 --- a/app/src/main/java/com/gaurav/avnc/ui/home/HomeActivity.kt +++ b/app/src/main/java/com/gaurav/avnc/ui/home/HomeActivity.kt @@ -73,6 +73,7 @@ class HomeActivity : AppCompatActivity() { setupSplashTheme() showWelcomeMsg() + maybeAutoConnect(savedInstanceState == null) } override fun onStart() { @@ -195,6 +196,11 @@ class HomeActivity : AppCompatActivity() { } } + private fun maybeAutoConnect(isNewStart: Boolean) { + if (isNewStart) + viewModel.maybeConnectOnAppStart() + } + /************************************************************************************ * Shortcuts ************************************************************************************/ diff --git a/app/src/main/java/com/gaurav/avnc/viewmodel/HomeViewModel.kt b/app/src/main/java/com/gaurav/avnc/viewmodel/HomeViewModel.kt index e61aa256..661d4288 100644 --- a/app/src/main/java/com/gaurav/avnc/viewmodel/HomeViewModel.kt +++ b/app/src/main/java/com/gaurav/avnc/viewmodel/HomeViewModel.kt @@ -62,6 +62,10 @@ class HomeViewModel(app: Application) : BaseViewModel(app) { */ fun startConnection(profile: ServerProfile) = newConnectionEvent.fire(profile) + fun maybeConnectOnAppStart() = launch { + serverProfileDao.getConnectableOnAppStart().firstOrNull()?.let { startConnection(it) } + } + /************************************************************************** * Server Discovery * diff --git a/app/src/main/res/drawable/ic_auto_connect.xml b/app/src/main/res/drawable/ic_auto_connect.xml new file mode 100644 index 00000000..bca269c2 --- /dev/null +++ b/app/src/main/res/drawable/ic_auto_connect.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/fragment_profile_editor_advanced.xml b/app/src/main/res/layout/fragment_profile_editor_advanced.xml index 8f7fffc6..8e38a4b3 100644 --- a/app/src/main/res/layout/fragment_profile_editor_advanced.xml +++ b/app/src/main/res/layout/fragment_profile_editor_advanced.xml @@ -143,6 +143,16 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/use_repeater" /> + + + + app:layout_constraintTop_toBottomOf="@id/auto_connect" /> + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 845d8269..6fafa9f5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -29,6 +29,7 @@ Export Import View-only + Auto-connect when app starts Hide remote pointer Send legacy key events Send delayed click events