Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

accept proxy address from intent #39

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
<activity
android:name=".main.MainActivity"
android:exported="true"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.kinandcarta.create.proxytoggle.main

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
Expand All @@ -17,12 +19,14 @@ import androidx.core.content.ContextCompat
import com.kinandcarta.create.proxytoggle.core.ui.theme.ProxyToggleTheme
import com.kinandcarta.create.proxytoggle.manager.view.screen.BlockAppScreen
import com.kinandcarta.create.proxytoggle.manager.view.screen.ProxyManagerScreen
import com.kinandcarta.create.proxytoggle.manager.viewmodel.ProxyManagerViewModel
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

private val viewModel: MainViewModel by viewModels()
private val proxyViewModel: ProxyManagerViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -36,6 +40,14 @@ class MainActivity : AppCompatActivity() {
MainScreen(useDarkTheme = useDarkTheme, useVerticalLayout = useVerticalLayout)
}
}

override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
intent?.getStringExtra(ProxyManagerViewModel.PROXY_KEY)?.takeIf { it.isNotBlank() }?.let {
Log.i("Intent", "On new intent $it")
proxyViewModel.onSetProxy(it)
}
}
}

@Composable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.kinandcarta.create.proxytoggle.manager.viewmodel

import android.util.Log
import androidx.annotation.StringRes
import androidx.annotation.VisibleForTesting
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.kinandcarta.create.proxytoggle.core.common.proxy.Proxy
Expand All @@ -16,7 +18,9 @@ import com.kinandcarta.create.proxytoggle.repository.userprefs.UserPreferencesRe
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
import kotlinx.coroutines.yield
import javax.inject.Inject

@Suppress("TooManyFunctions")
Expand All @@ -25,7 +29,8 @@ class ProxyManagerViewModel @Inject constructor(
private val deviceSettingsManager: DeviceSettingsManager,
private val proxyValidator: ProxyValidator,
private val appDataRepository: AppDataRepository,
private val userPreferencesRepository: UserPreferencesRepository
private val userPreferencesRepository: UserPreferencesRepository,
private val savedStateHandle: SavedStateHandle,
) : ViewModel() {

private var _uiState = mutableStateOf<UiState>(
Expand Down Expand Up @@ -63,6 +68,13 @@ class ProxyManagerViewModel @Inject constructor(
}
}
}

viewModelScope.launch {
savedStateHandle.getStateFlow(PROXY_KEY, "").filter { it.isNotBlank() }.collect {
Log.i("Intent", "On start intent $it")
onSetProxy(it)
}
}
}

fun onUserInteraction(userInteraction: UserInteraction) {
Expand All @@ -75,6 +87,31 @@ class ProxyManagerViewModel @Inject constructor(
}
}

fun onSetProxy(proxyStr: String) {
viewModelScope.launch {
if (deviceSettingsManager.proxySetting.value.isEnabled) {
// Turn off proxy before setting the proxy ip and port
deviceSettingsManager.disableProxy()

while (uiState.value is UiState.Connected) {
yield()
}
}
val inputArray = proxyStr.split(':')
val inputIp = inputArray.firstOrNull()
val inputPort = inputArray.getOrNull(1)
inputIp?.takeIf { it.isNotBlank() }?.let {
onAddressChanged(it)
}

inputPort?.takeIf { it.isNotBlank() }?.let {
onPortChanged(it)
}

// Leave it for user to turn on the proxy
}
}

fun onForceFocusExecuted() {
updateDisconnectedState {
it.copy(
Expand Down Expand Up @@ -236,5 +273,7 @@ class ProxyManagerViewModel @Inject constructor(
companion object {
// NOTE: necessary delay to refocus & announce existing error on next attempt to connect!
private const val ERROR_DELAY = 50L

const val PROXY_KEY = "proxy"
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.kinandcarta.create.proxytoggle.manager.viewmodel

import androidx.lifecycle.SavedStateHandle
import com.google.common.truth.Truth.assertThat
import com.kinandcarta.create.proxytoggle.core.common.proxy.Proxy
import com.kinandcarta.create.proxytoggle.core.common.proxy.ProxyValidator
import com.kinandcarta.create.proxytoggle.core.common.stub.Stubs.PROXY_ADDRESS
import com.kinandcarta.create.proxytoggle.core.common.stub.Stubs.PROXY_PORT
import com.kinandcarta.create.proxytoggle.core.common.stub.Stubs.VALID_PROXY
import com.kinandcarta.create.proxytoggle.manager.R
import com.kinandcarta.create.proxytoggle.repository.appdata.AppDataRepository
import com.kinandcarta.create.proxytoggle.repository.devicesettings.DeviceSettingsManager
Expand Down Expand Up @@ -50,6 +52,8 @@ class ProxyManagerViewModelTest {

private val fakeProxyStateFlow = MutableStateFlow(Proxy.Disabled)

private val savedStateHandle = SavedStateHandle()

private lateinit var subject: ProxyManagerViewModel

@Before
Expand Down Expand Up @@ -304,11 +308,65 @@ class ProxyManagerViewModelTest {
}
}

@Test
fun `onSetProxy() - Auto fill in address and port`() {
// WHEN
dispatcher.scheduler.advanceUntilIdle()
every { mockProxyValidator.isValidIP(any()) } returns true
every { mockProxyValidator.isValidPort(any()) } returns true
subject.onSetProxy(VALID_PROXY)
dispatcher.scheduler.advanceUntilIdle()

// THEN
assertThat(subject.uiState.value).isEqualTo(
ProxyManagerViewModel.UiState.Disconnected(
addressState = ProxyManagerViewModel.TextFieldState(text = PROXY_ADDRESS),
portState = ProxyManagerViewModel.TextFieldState(text = PROXY_PORT),
pastProxies = emptyList()
)
)
}

@Test
fun `onSetProxy() - Auto close previous proxy before filling in address and port`() {
// GIVEN
every { mockProxyValidator.isValidIP(any()) } returns true
every { mockProxyValidator.isValidPort(any()) } returns true
givenDisconnectedWith(address = "2.3.4.5", port = "333")
subject.onUserInteraction(ProxyManagerViewModel.UserInteraction.ToggleProxyClicked)
dispatcher.scheduler.advanceUntilIdle()

// Check now is connected
assertThat(subject.uiState.value).isInstanceOf(ProxyManagerViewModel.UiState.Connected::class.java)
coVerify {
mockProxyValidator.isValidIP("2.3.4.5")
mockProxyValidator.isValidPort("333")
mockDeviceSettingsManager.enableProxy(Proxy("2.3.4.5", "333"))
}

// WHEN
subject.onSetProxy(VALID_PROXY)
dispatcher.scheduler.advanceUntilIdle()

// THEN
assertThat(subject.uiState.value).isEqualTo(
ProxyManagerViewModel.UiState.Disconnected(
addressState = ProxyManagerViewModel.TextFieldState(text = PROXY_ADDRESS),
portState = ProxyManagerViewModel.TextFieldState(text = PROXY_PORT),
pastProxies = emptyList()
)
)
verify {
mockDeviceSettingsManager.disableProxy()
}
}

private fun initSubject() = ProxyManagerViewModel(
mockDeviceSettingsManager,
mockProxyValidator,
mockAppDataRepository,
mockUserPreferencesRepository
mockUserPreferencesRepository,
savedStateHandle
)

private fun givenPastProxies(pastProxies: List<Proxy>) {
Expand Down