diff --git a/app/src/main/java/net/nymtech/nymvpn/NymVPN.kt b/app/src/main/java/net/nymtech/nymvpn/NymVPN.kt
index 7009dc3..245739f 100644
--- a/app/src/main/java/net/nymtech/nymvpn/NymVPN.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/NymVPN.kt
@@ -1,9 +1,6 @@
package net.nymtech.nymvpn
-import android.annotation.SuppressLint
import android.app.Application
-import android.content.res.Configuration
-import android.system.Os
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.TextUnit
import dagger.hilt.android.HiltAndroidApp
diff --git a/app/src/main/java/net/nymtech/nymvpn/module/AppModule.kt b/app/src/main/java/net/nymtech/nymvpn/module/AppModule.kt
index 32fa1d8..078de95 100644
--- a/app/src/main/java/net/nymtech/nymvpn/module/AppModule.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/module/AppModule.kt
@@ -1,22 +1,10 @@
package net.nymtech.nymvpn.module
-
-import android.net.VpnService
import dagger.Module
-import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
-import net.nymtech.vpn.NymVpnClient
-import net.nymtech.vpn.NymVpnService
-import net.nymtech.vpn.VpnClient
-import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
class AppModule {
- @Singleton
- @Provides
- fun provideVpnClient(): VpnClient {
- return NymVpnClient()
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/AppViewModel.kt b/app/src/main/java/net/nymtech/nymvpn/ui/AppViewModel.kt
index da62470..e1ef046 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/AppViewModel.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/AppViewModel.kt
@@ -2,7 +2,6 @@ package net.nymtech.nymvpn.ui
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import com.squareup.moshi.Json
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted
@@ -14,8 +13,8 @@ import net.nymtech.nymvpn.model.Country
import net.nymtech.nymvpn.service.gateway.GatewayApiService
import net.nymtech.nymvpn.ui.theme.Theme
import net.nymtech.nymvpn.util.Constants
+import timber.log.Timber
import java.util.Locale
-import java.util.Locale.IsoCountryCode
import javax.inject.Inject
@HiltViewModel
@@ -34,12 +33,16 @@ class AppViewModel @Inject constructor(
fun updateCountryListCache() {
viewModelScope.launch(Dispatchers.IO) {
- val gateways = gatewayApiService.getDescribedGateways()
- val countries = gateways.map {
- val countryIso = it.bond.gateway.location
- Country(countryIso, Locale(countryIso.lowercase(), countryIso).displayCountry)
- }.toSet()
- dataStoreManager.saveToDataStore(DataStoreManager.NODE_COUNTRIES, countries.toString())
+ try {
+ val gateways = gatewayApiService.getDescribedGateways()
+ val countries = gateways.map {
+ val countryIso = it.bond.gateway.location
+ Country(countryIso, Locale(countryIso.lowercase(), countryIso).displayCountry)
+ }.toSet()
+ dataStoreManager.saveToDataStore(DataStoreManager.NODE_COUNTRIES, countries.toString())
+ } catch (e : Exception) {
+ Timber.e(e.message)
+ }
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/MainActivity.kt b/app/src/main/java/net/nymtech/nymvpn/ui/MainActivity.kt
index 70fe89f..b10826a 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/MainActivity.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/MainActivity.kt
@@ -1,12 +1,9 @@
package net.nymtech.nymvpn.ui
import android.Manifest
-import android.net.VpnService
import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
-import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
-import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
@@ -17,9 +14,7 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.hilt.navigation.compose.hiltViewModel
@@ -35,7 +30,6 @@ import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import net.nymtech.nymvpn.data.datastore.DataStoreManager
-import net.nymtech.nymvpn.model.Country
import net.nymtech.nymvpn.ui.common.labels.CustomSnackBar
import net.nymtech.nymvpn.ui.common.navigation.NavBar
import net.nymtech.nymvpn.ui.screens.hop.HopScreen
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/common/SearchBar.kt b/app/src/main/java/net/nymtech/nymvpn/ui/common/SearchBar.kt
index 89a8496..d16ca10 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/common/SearchBar.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/common/SearchBar.kt
@@ -1,24 +1,17 @@
package net.nymtech.nymvpn.ui.common
import androidx.compose.foundation.background
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.interaction.InteractionSource
import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.layout.PaddingValues
-import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
-import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Search
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.ShapeDefaults
import androidx.compose.material3.Text
@@ -29,19 +22,13 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
-import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
-import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.VisualTransformation
-import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import net.nymtech.nymvpn.R
import net.nymtech.nymvpn.ui.theme.iconSize
-import net.nymtech.nymvpn.util.scaledHeight
@OptIn(ExperimentalMaterial3Api::class)
@Composable
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/common/buttons/ListOptionSelectionButton.kt b/app/src/main/java/net/nymtech/nymvpn/ui/common/buttons/ListOptionSelectionButton.kt
index 1713397..3f54dea 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/common/buttons/ListOptionSelectionButton.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/common/buttons/ListOptionSelectionButton.kt
@@ -4,22 +4,16 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.defaultMinSize
-import androidx.compose.foundation.layout.displayCutoutPadding
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.safeContentPadding
-import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.ShapeDefaults
import androidx.compose.material3.Text
-import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
@@ -29,9 +23,7 @@ import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
-import androidx.window.core.layout.WindowHeightSizeClass
import net.nymtech.nymvpn.R
-import net.nymtech.nymvpn.ui.MainActivity
import net.nymtech.nymvpn.util.scaledHeight
@OptIn(ExperimentalMaterial3Api::class)
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/common/buttons/RadioSurfaceButton.kt b/app/src/main/java/net/nymtech/nymvpn/ui/common/buttons/RadioSurfaceButton.kt
index 907b33d..cefcf73 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/common/buttons/RadioSurfaceButton.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/common/buttons/RadioSurfaceButton.kt
@@ -4,7 +4,6 @@ import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
@@ -24,8 +23,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.dp
-import androidx.window.core.layout.WindowHeightSizeClass
-import net.nymtech.nymvpn.ui.MainActivity
import net.nymtech.nymvpn.ui.theme.iconSize
import net.nymtech.nymvpn.util.scaledHeight
import net.nymtech.nymvpn.util.scaledWidth
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/common/buttons/SurfaceSelectionGroupButton.kt b/app/src/main/java/net/nymtech/nymvpn/ui/common/buttons/SurfaceSelectionGroupButton.kt
index bf6e50a..4b7fe58 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/common/buttons/SurfaceSelectionGroupButton.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/common/buttons/SurfaceSelectionGroupButton.kt
@@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
-import androidx.compose.material3.Divider
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
@@ -24,9 +23,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.dp
-import androidx.window.core.layout.WindowHeightSizeClass
import net.nymtech.nymvpn.R
-import net.nymtech.nymvpn.ui.MainActivity
import net.nymtech.nymvpn.ui.theme.iconSize
import net.nymtech.nymvpn.util.scaledHeight
import net.nymtech.nymvpn.util.scaledWidth
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/common/labels/GroupLabel.kt b/app/src/main/java/net/nymtech/nymvpn/ui/common/labels/GroupLabel.kt
index c6edc2d..40fc476 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/common/labels/GroupLabel.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/common/labels/GroupLabel.kt
@@ -2,12 +2,10 @@ package net.nymtech.nymvpn.ui.common.labels
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
@Composable
fun GroupLabel(title: String) {
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/common/labels/PillLabel.kt b/app/src/main/java/net/nymtech/nymvpn/ui/common/labels/PillLabel.kt
index 863252d..406fd0f 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/common/labels/PillLabel.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/common/labels/PillLabel.kt
@@ -1,11 +1,8 @@
package net.nymtech.nymvpn.ui.common.labels
-import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
@@ -17,10 +14,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
-import androidx.window.core.layout.WindowHeightSizeClass
-import net.nymtech.nymvpn.ui.MainActivity
import net.nymtech.nymvpn.util.scaledHeight
-import net.nymtech.nymvpn.util.scaledWidth
@Composable
fun PillLabel(text: String, backgroundColor : Color, textColor : Color) {
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/common/navigation/NavBar.kt b/app/src/main/java/net/nymtech/nymvpn/ui/common/navigation/NavBar.kt
index f6e02ad..12abd48 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/common/navigation/NavBar.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/common/navigation/NavBar.kt
@@ -1,6 +1,5 @@
package net.nymtech.nymvpn.ui.common.navigation
-import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
@@ -12,12 +11,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import androidx.navigation.compose.currentBackStackEntryAsState
-import androidx.window.core.layout.WindowHeightSizeClass
-import net.nymtech.nymvpn.ui.MainActivity
import net.nymtech.nymvpn.ui.NavItem
import net.nymtech.nymvpn.ui.theme.iconSize
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/model/ConnectionState.kt b/app/src/main/java/net/nymtech/nymvpn/ui/model/ConnectionState.kt
index 7e937ca..d4cca0b 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/model/ConnectionState.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/model/ConnectionState.kt
@@ -2,10 +2,37 @@ package net.nymtech.nymvpn.ui.model
import net.nymtech.nymvpn.R
import net.nymtech.nymvpn.util.StringValue
+import net.nymtech.vpn.model.VpnState
sealed class ConnectionState(val status: StringValue) {
- data object Connected : ConnectionState(StringValue.StringResource(R.string.connected))
- data object Connecting : ConnectionState(StringValue.StringResource(R.string.connecting))
- data object Disconnecting : ConnectionState(StringValue.StringResource(R.string.disconnecting))
- data object Disconnected : ConnectionState(StringValue.StringResource(R.string.disconnected))
+
+ abstract val stateMessage : StateMessage
+ data object Connected : ConnectionState(StringValue.StringResource(R.string.connected)){
+ override val stateMessage: StateMessage
+ get() = StateMessage.Info(StringValue.StringResource(R.string.connection_time))
+ }
+ data object Connecting : ConnectionState(StringValue.StringResource(R.string.connecting)) {
+ override val stateMessage: StateMessage
+ get() = StateMessage.Info(StringValue.StringResource(R.string.init_client))
+ }
+ data object Disconnecting : ConnectionState(StringValue.StringResource(R.string.disconnecting)) {
+ override val stateMessage: StateMessage
+ get() = StateMessage.Info(StringValue.Empty)
+ }
+ data object Disconnected : ConnectionState(StringValue.StringResource(R.string.disconnected)) {
+ override val stateMessage: StateMessage
+ get() = StateMessage.Info(StringValue.Empty)
+ }
+
+
+ companion object {
+ fun from(vpnState: VpnState) : ConnectionState {
+ return when(vpnState) {
+ VpnState.DOWN -> Disconnected
+ VpnState.UP -> Connected
+ VpnState.CONNECTING -> Connecting
+ VpnState.DISCONNECTING -> Disconnecting
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/screens/main/MainScreen.kt b/app/src/main/java/net/nymtech/nymvpn/ui/screens/main/MainScreen.kt
index d88f2e3..cef3886 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/screens/main/MainScreen.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/screens/main/MainScreen.kt
@@ -13,7 +13,6 @@ import androidx.compose.foundation.layout.size
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -29,12 +28,10 @@ import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavController
-import androidx.window.core.layout.WindowHeightSizeClass
import net.nymtech.nymvpn.R
import net.nymtech.nymvpn.model.Country
import net.nymtech.nymvpn.model.NetworkMode
import net.nymtech.nymvpn.ui.AppUiState
-import net.nymtech.nymvpn.ui.MainActivity
import net.nymtech.nymvpn.ui.NavItem
import net.nymtech.nymvpn.ui.common.animations.SpinningIcon
import net.nymtech.nymvpn.ui.common.buttons.ListOptionSelectionButton
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/screens/main/MainViewModel.kt b/app/src/main/java/net/nymtech/nymvpn/ui/screens/main/MainViewModel.kt
index bc3e7ae..097e333 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/screens/main/MainViewModel.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/screens/main/MainViewModel.kt
@@ -4,26 +4,22 @@ import android.app.Application
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
-import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
-import net.nymtech.nymvpn.R
import net.nymtech.nymvpn.data.datastore.DataStoreManager
import net.nymtech.nymvpn.model.Country
import net.nymtech.nymvpn.model.NetworkMode
import net.nymtech.nymvpn.ui.model.ConnectionState
-import net.nymtech.nymvpn.ui.model.StateMessage
import net.nymtech.nymvpn.util.Constants
import net.nymtech.nymvpn.util.NumberUtils
-import net.nymtech.nymvpn.util.StringValue
-import net.nymtech.vpn.NymVpnClient
-import net.nymtech.vpn.ServiceManager
-import net.nymtech.vpn.VpnClient
+import net.nymtech.vpn.NymVpn
+import net.nymtech.vpn.model.EntryPoint
+import net.nymtech.vpn.model.ExitPoint
+import javax.inject.Inject
@HiltViewModel
class MainViewModel
@@ -31,40 +27,41 @@ class MainViewModel
constructor(
private val dataStoreManager: DataStoreManager,
private val application: Application,
- private val vpnClient: VpnClient
) : ViewModel() {
private val _uiState = MutableStateFlow(MainUiState())
val uiState =
- combine(dataStoreManager.preferencesFlow, _uiState, vpnClient.statistics) {
+ combine(dataStoreManager.preferencesFlow, _uiState, NymVpn.stateFlow, NymVpn.statistics) {
prefs,
- state,
+ uiState,
+ vpnState,
stats ->
val lastHopCountry =
Country.from(
prefs?.get(DataStoreManager.LAST_HOP_COUNTRY)
- ?: state.lastHopCountry.toString())
+ ?: uiState.lastHopCountry.toString())
val firstHopCountry =
Country.from(
prefs?.get(DataStoreManager.FIRST_HOP_COUNTRY)
- ?: state.firstHopCounty.toString())
+ ?: uiState.firstHopCounty.toString())
val connectionTime =
stats.connectionSeconds?.let { NumberUtils.convertSecondsToTimeString(it) }
val networkMode =
NetworkMode.valueOf(
- prefs?.get(DataStoreManager.NETWORK_MODE) ?: state.networkMode.name)
+ prefs?.get(DataStoreManager.NETWORK_MODE) ?: uiState.networkMode.name)
val firstHopEnabled: Boolean =
(prefs?.get(DataStoreManager.FIRST_HOP_SELECTION) ?: false)
+ val connectionState = ConnectionState.from(vpnState)
MainUiState(
false,
lastHopCountry = lastHopCountry,
firstHopCounty = firstHopCountry,
connectionTime = connectionTime ?: "",
networkMode = networkMode,
- connectionState = state.connectionState,
+ connectionState = connectionState,
firstHopEnabled = firstHopEnabled,
- stateMessage = state.stateMessage)
+ stateMessage = connectionState.stateMessage)
}
.stateIn(
viewModelScope,
@@ -85,39 +82,14 @@ constructor(
fun onConnect() =
viewModelScope.launch(Dispatchers.IO) {
- ServiceManager.startVpnService(application.applicationContext)
- _uiState.value =
- _uiState.value.copy(
- connectionState = ConnectionState.Connecting,
- stateMessage = StateMessage.Info(StringValue.StringResource(R.string.init_client)))
- delay(1000)
- _uiState.value =
- _uiState.value.copy(
- connectionState = ConnectionState.Connecting,
- stateMessage =
- StateMessage.Info(StringValue.StringResource(R.string.establishing_connection)))
- delay(1000)
- _uiState.value =
- _uiState.value.copy(
- connectionState = ConnectionState.Connected,
- stateMessage =
- StateMessage.Info(StringValue.StringResource(R.string.connection_time)))
- vpnClient.connect()
- }
+ NymVpn.connect(application,EntryPoint.Location(uiState.value.firstHopCounty.isoCode),
+ ExitPoint.Location(uiState.value.lastHopCountry.isoCode),
+ isTwoHop = (uiState.value.networkMode == NetworkMode.TWO_HOP_WIREGUARD))
+ }
+
fun onDisconnect() =
viewModelScope.launch {
- ServiceManager.stopVpnService(application)
- vpnClient.disconnect()
- _uiState.value =
- _uiState.value.copy(
- connectionState = ConnectionState.Disconnecting,
- stateMessage = StateMessage.Info(StringValue.Empty),
- )
- delay(1000)
- _uiState.value =
- _uiState.value.copy(
- connectionState = ConnectionState.Disconnected,
- stateMessage = StateMessage.Info(StringValue.Empty))
+ NymVpn.disconnect(application)
}
}
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/screens/settings/SettingsScreen.kt b/app/src/main/java/net/nymtech/nymvpn/ui/screens/settings/SettingsScreen.kt
index 2cd1cce..e583f30 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/screens/settings/SettingsScreen.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/screens/settings/SettingsScreen.kt
@@ -1,15 +1,11 @@
package net.nymtech.nymvpn.ui.screens.settings
import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/screens/settings/account/AccountScreen.kt b/app/src/main/java/net/nymtech/nymvpn/ui/screens/settings/account/AccountScreen.kt
index 50520ea..917e77e 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/screens/settings/account/AccountScreen.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/screens/settings/account/AccountScreen.kt
@@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/screens/settings/feedback/FeedbackViewModel.kt b/app/src/main/java/net/nymtech/nymvpn/ui/screens/settings/feedback/FeedbackViewModel.kt
index afba986..e0741ea 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/screens/settings/feedback/FeedbackViewModel.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/screens/settings/feedback/FeedbackViewModel.kt
@@ -8,7 +8,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import net.nymtech.nymvpn.data.datastore.DataStoreManager
-import net.nymtech.nymvpn.ui.screens.settings.SettingsUiState
import net.nymtech.nymvpn.util.Constants
import javax.inject.Inject
diff --git a/app/src/main/java/net/nymtech/nymvpn/ui/theme/Theme.kt b/app/src/main/java/net/nymtech/nymvpn/ui/theme/Theme.kt
index 9861c88..60f2635 100644
--- a/app/src/main/java/net/nymtech/nymvpn/ui/theme/Theme.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/ui/theme/Theme.kt
@@ -14,7 +14,6 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
-import androidx.compose.ui.unit.dp
import androidx.core.view.WindowCompat
enum class Theme {
diff --git a/app/src/main/java/net/nymtech/nymvpn/util/StringUtils.kt b/app/src/main/java/net/nymtech/nymvpn/util/StringUtils.kt
index fcfc17d..e7b71c0 100644
--- a/app/src/main/java/net/nymtech/nymvpn/util/StringUtils.kt
+++ b/app/src/main/java/net/nymtech/nymvpn/util/StringUtils.kt
@@ -4,7 +4,6 @@ import android.content.Context
import androidx.compose.ui.text.buildAnnotatedString
import net.nymtech.nymvpn.R
import net.nymtech.nymvpn.model.Country
-import timber.log.Timber
object StringUtils {
fun buildCountryNameString(country : Country, context : Context) : String {
diff --git a/app/src/main/res/drawable-anydpi/ic_stat_name.xml b/app/src/main/res/drawable-anydpi/ic_stat_name.xml
new file mode 100644
index 0000000..792d07b
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_stat_name.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable-hdpi/ic_stat_name.png b/app/src/main/res/drawable-hdpi/ic_stat_name.png
new file mode 100644
index 0000000..064717d
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_stat_name.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_stat_name.png b/app/src/main/res/drawable-mdpi/ic_stat_name.png
new file mode 100644
index 0000000..fcfad7b
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_stat_name.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_stat_name.png b/app/src/main/res/drawable-xhdpi/ic_stat_name.png
new file mode 100644
index 0000000..01f33ab
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_stat_name.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_stat_name.png b/app/src/main/res/drawable-xxhdpi/ic_stat_name.png
new file mode 100644
index 0000000..d801bb0
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_stat_name.png differ
diff --git a/buildSrc/src/main/kotlin/Constants.kt b/buildSrc/src/main/kotlin/Constants.kt
index 250ff85..ff9981c 100644
--- a/buildSrc/src/main/kotlin/Constants.kt
+++ b/buildSrc/src/main/kotlin/Constants.kt
@@ -27,4 +27,6 @@ object Constants {
const val FDROID = "fdroid"
const val GENERAL = "general"
const val BUILD_LIB_TASK = "buildDeps"
+
+ const val SANDBOX_URL = "https://sandbox-nym-api1.nymtech.net/api"
}
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/changelogs/4.txt b/fastlane/metadata/android/en-US/changelogs/4.txt
new file mode 100644
index 0000000..681fda9
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/4.txt
@@ -0,0 +1,4 @@
+What's new:
+- Refactor VPN client
+- Add image assets
+- Fix UI state sync with VPN
\ No newline at end of file
diff --git a/fastlane/metadata/android/en-US/images/featureGraphic.jpg b/fastlane/metadata/android/en-US/images/featureGraphic.jpg
new file mode 100644
index 0000000..3d3c62a
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/featureGraphic.jpg differ
diff --git a/fastlane/metadata/android/en-US/images/icon.png b/fastlane/metadata/android/en-US/images/icon.png
new file mode 100644
index 0000000..ed47d88
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/icon.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/countryScreen.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/countryScreen.png
new file mode 100644
index 0000000..0fc5338
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/countryScreen.png differ
diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/homeScreen.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/homeScreen.png
new file mode 100644
index 0000000..3b25301
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/phoneScreenshots/homeScreen.png differ
diff --git a/fastlane/metadata/android/en-US/images/tenInchScreenshots/countryScreenTablet10.png b/fastlane/metadata/android/en-US/images/tenInchScreenshots/countryScreenTablet10.png
new file mode 100644
index 0000000..f241af6
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/tenInchScreenshots/countryScreenTablet10.png differ
diff --git a/fastlane/metadata/android/en-US/images/tenInchScreenshots/homeScreenTablet10.png b/fastlane/metadata/android/en-US/images/tenInchScreenshots/homeScreenTablet10.png
new file mode 100644
index 0000000..f06cd8c
Binary files /dev/null and b/fastlane/metadata/android/en-US/images/tenInchScreenshots/homeScreenTablet10.png differ
diff --git a/vpn-client/build.gradle.kts b/vpn-client/build.gradle.kts
index 86c83a4..1178710 100644
--- a/vpn-client/build.gradle.kts
+++ b/vpn-client/build.gradle.kts
@@ -26,6 +26,8 @@ android {
ndk {
abiFilters += listOf("arm64-v8a", "armeabi-v7a", "x86_64", "x86")
}
+ //TODO change this later to sandbox and mainnet switch depending on build
+ buildConfigField("String", "API_URL", "\"${Constants.SANDBOX_URL}\"")
}
buildTypes {
@@ -50,6 +52,9 @@ android {
kotlinOptions {
jvmTarget = Constants.JVM_TARGET
}
+ buildFeatures {
+ buildConfig = true
+ }
}
dependencies {
diff --git a/vpn-client/src/main/java/net/nymtech/vpn/ConnectivityListener.kt b/vpn-client/src/main/java/net/nymtech/vpn/ConnectivityListener.kt
index 06f3969..b5f4381 100644
--- a/vpn-client/src/main/java/net/nymtech/vpn/ConnectivityListener.kt
+++ b/vpn-client/src/main/java/net/nymtech/vpn/ConnectivityListener.kt
@@ -6,8 +6,8 @@ import android.net.ConnectivityManager.NetworkCallback
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
-import kotlin.properties.Delegates.observable
import net.nymtech.vpn.util.EventNotifier
+import kotlin.properties.Delegates.observable
class ConnectivityListener {
private val availableNetworks = HashSet()
diff --git a/vpn-client/src/main/java/net/nymtech/vpn/NymVpn.kt b/vpn-client/src/main/java/net/nymtech/vpn/NymVpn.kt
new file mode 100644
index 0000000..32d4433
--- /dev/null
+++ b/vpn-client/src/main/java/net/nymtech/vpn/NymVpn.kt
@@ -0,0 +1,72 @@
+package net.nymtech.vpn
+
+import android.content.Context
+import android.content.Intent
+import android.net.VpnService
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.launch
+import net.nymtech.vpn.model.EntryPoint
+import net.nymtech.vpn.model.ExitPoint
+import net.nymtech.vpn.model.VpnState
+import net.nymtech.vpn.model.VpnStatistics
+import net.nymtech.vpn.util.ServiceManager
+
+object NymVpn : VpnClient {
+
+ private val _state = MutableStateFlow(VpnState.DOWN)
+ override val stateFlow: Flow = _state.asStateFlow()
+
+ private val _statistics = MutableStateFlow(VpnStatistics())
+ override val statistics: StateFlow = _statistics.asStateFlow()
+
+ private val scope = CoroutineScope(Dispatchers.IO)
+
+ private var statsJob: Job? = null
+ override fun prepare(context : Context): Intent? {
+ return VpnService.prepare(context)
+ }
+
+ override fun connect(context: Context, entryPoint: EntryPoint, exitPoint: ExitPoint, isTwoHop: Boolean) {
+ val extras = mapOf(
+ ENTRY_POINT_EXTRA_KEY to entryPoint.toString(),
+ EXIT_POINT_EXTRA_KEY to exitPoint.toString(),
+ TWO_HOP_EXTRA_KEY to isTwoHop.toString()
+ )
+ statsJob = gatherStatistics()
+ ServiceManager.startVpnService(context, extras)
+ }
+
+ private fun gatherStatistics() = scope.launch {
+ var seconds = 0L
+ do {
+ _statistics.value = _statistics.value.copy(
+ connectionSeconds = seconds
+ )
+ delay(1000)
+ seconds++
+ } while (true)
+ }
+
+ internal fun setState(state : VpnState) = scope.launch {
+ _state.value = state
+ }
+
+
+ override fun disconnect(context: Context) {
+ statsJob?.cancel()
+ _statistics.value = _statistics.value.copy(
+ connectionSeconds = null
+ )
+ ServiceManager.stopVpnService(context)
+ }
+ const val ENTRY_POINT_EXTRA_KEY = "entryPoint"
+ const val EXIT_POINT_EXTRA_KEY = "exitPoint"
+ const val TWO_HOP_EXTRA_KEY = "twoHop"
+}
\ No newline at end of file
diff --git a/vpn-client/src/main/java/net/nymtech/vpn/NymVpnClient.kt b/vpn-client/src/main/java/net/nymtech/vpn/NymVpnClient.kt
deleted file mode 100644
index 4400ec7..0000000
--- a/vpn-client/src/main/java/net/nymtech/vpn/NymVpnClient.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-package net.nymtech.vpn
-
-import android.content.Context
-import android.content.Intent
-import android.net.VpnService
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.DelicateCoroutinesApi
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.launch
-
-import timber.log.Timber
-
-class NymVpnClient : VpnClient {
-
- private val _statistics = MutableStateFlow(VpnStatistics())
- override val statistics: StateFlow = _statistics.asStateFlow()
- val scope = CoroutineScope(Dispatchers.IO)
-
-
- private var job : Job? = null
- override fun prepare(context: Context) : Intent? {
- return VpnService.prepare(context)
- }
-
- override fun connect() {
- job = scope.launch {
- var seconds = 0L
- do {
- _statistics.value = _statistics.value.copy(
- connectionSeconds = seconds
- )
- delay(1000)
- seconds++
- } while (true)
- }
- }
-
- override fun disconnect() {
- //TODO reset statistics here too
- _statistics.value = _statistics.value.copy(
- connectionSeconds = null
- )
- job?.cancel()
- }
-}
\ No newline at end of file
diff --git a/vpn-client/src/main/java/net/nymtech/vpn/NymVpnService.kt b/vpn-client/src/main/java/net/nymtech/vpn/NymVpnService.kt
index d08424e..ead033e 100644
--- a/vpn-client/src/main/java/net/nymtech/vpn/NymVpnService.kt
+++ b/vpn-client/src/main/java/net/nymtech/vpn/NymVpnService.kt
@@ -15,7 +15,11 @@ import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
+import net.nymtech.vpn.model.VpnState
import net.nymtech.vpn.tun_provider.TunConfig
+import net.nymtech.vpn.util.Action
+import net.nymtech.vpn_client.BuildConfig
+import net.nymtech.vpn_client.R
import timber.log.Timber
import java.net.Inet4Address
import java.net.Inet6Address
@@ -23,7 +27,7 @@ import java.net.InetAddress
import kotlin.properties.Delegates.observable
-open class NymVpnService : VpnService() {
+class NymVpnService : VpnService() {
companion object {
init {
@@ -67,22 +71,32 @@ open class NymVpnService : VpnService() {
}
val notificationBuilder = NotificationCompat.Builder(this, channelId)
val notification = notificationBuilder.setOngoing(true)
- .setSmallIcon(androidx.core.R.drawable.notification_bg)
+ .setContentTitle("NymVpn")
+ .setContentText("Running")
+ .setSmallIcon(R.drawable.ic_stat_name)
.setCategory(Notification.CATEGORY_SERVICE)
.build()
startForeground(123, notification)
Timber.d("new vpn action")
return if (intent?.action == Action.START.name) {
+ NymVpn.setState(VpnState.CONNECTING)
currentTunConfig = defaultTunConfig()
Timber.d("VPN start")
try {
if(prepare(this) == null) {
- val entry = "{ \"Location\": { \"location\": \"DE\" }}"
- val exit = "{ \"Location\": { \"location\": \"DE\" }}"
- initVPN(false, "https://sandbox-nym-api1.nymtech.net/api",entry,exit,this)
- GlobalScope.launch(Dispatchers.IO) {
- runVPN()
+ val isTwoHop = intent.extras?.getString(NymVpn.TWO_HOP_EXTRA_KEY).toBoolean()
+ val entry = intent.extras?.getString(NymVpn.ENTRY_POINT_EXTRA_KEY)
+ val exit = intent.extras?.getString(NymVpn.EXIT_POINT_EXTRA_KEY)
+ if(!entry.isNullOrBlank() && !exit.isNullOrBlank()) {
+ initVPN(isTwoHop, BuildConfig.API_URL, entry, exit,this)
+ GlobalScope.launch(Dispatchers.IO) {
+ launch {
+ runVPN()
+ }
+ //TODO fix to where we know if it is actually up
+ NymVpn.setState(VpnState.UP)
+ }
}
}
} catch (e : Exception) {
@@ -90,9 +104,11 @@ open class NymVpnService : VpnService() {
}
START_STICKY
} else {
+ NymVpn.setState(VpnState.DISCONNECTING)
Timber.d("VPN stop")
stopVPN()
stopSelf()
+ NymVpn.setState(VpnState.DOWN)
START_NOT_STICKY
}
}
@@ -113,20 +129,20 @@ open class NymVpnService : VpnService() {
override fun onCreate() {
connectivityListener.register(this)
- val channelId =
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- createNotificationChannel()
- } else {
- // If earlier version channel ID is not used
- // https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
- ""
- }
- val notificationBuilder = NotificationCompat.Builder(this, channelId)
- val notification = notificationBuilder.setOngoing(true)
- .setSmallIcon(androidx.core.R.drawable.notification_bg)
- .setCategory(Notification.CATEGORY_SERVICE)
- .build()
- startForeground(123, notification)
+// val channelId =
+// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+// createNotificationChannel()
+// } else {
+// // If earlier version channel ID is not used
+// // https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)
+// ""
+// }
+// val notificationBuilder = NotificationCompat.Builder(this, channelId)
+// val notification = notificationBuilder.setOngoing(true)
+// .setSmallIcon(R.drawable.ic_stat_name)
+// .setCategory(Notification.CATEGORY_SERVICE)
+// .build()
+// startForeground(123, notification)
}
override fun onDestroy() {
diff --git a/vpn-client/src/main/java/net/nymtech/vpn/VpnClient.kt b/vpn-client/src/main/java/net/nymtech/vpn/VpnClient.kt
index 7a5e9d3..5d0ee81 100644
--- a/vpn-client/src/main/java/net/nymtech/vpn/VpnClient.kt
+++ b/vpn-client/src/main/java/net/nymtech/vpn/VpnClient.kt
@@ -3,10 +3,15 @@ package net.nymtech.vpn
import android.content.Context
import android.content.Intent
import kotlinx.coroutines.flow.Flow
+import net.nymtech.vpn.model.EntryPoint
+import net.nymtech.vpn.model.ExitPoint
+import net.nymtech.vpn.model.VpnState
+import net.nymtech.vpn.model.VpnStatistics
interface VpnClient {
fun prepare(context : Context) : Intent?
- fun connect()
- fun disconnect()
+ fun connect(context: Context, entryPoint: EntryPoint, exitPoint: ExitPoint, isTwoHop: Boolean)
+ fun disconnect(context: Context)
val statistics : Flow
+ val stateFlow : Flow
}
\ No newline at end of file
diff --git a/vpn-client/src/main/java/net/nymtech/vpn/model/EntryPoint.kt b/vpn-client/src/main/java/net/nymtech/vpn/model/EntryPoint.kt
new file mode 100644
index 0000000..f7c2f7c
--- /dev/null
+++ b/vpn-client/src/main/java/net/nymtech/vpn/model/EntryPoint.kt
@@ -0,0 +1,14 @@
+package net.nymtech.vpn.model
+
+sealed class EntryPoint {
+ //TODO enforce only two char countryISO
+ data class Location(private val location: String) : EntryPoint() {
+
+ //TODO make this serialize later
+ override fun toString(): String {
+ return "{ \"Location\": { \"location\": \"${location}\" }}"
+ }
+ }
+ //TODO impl later
+ private sealed class Gateway() : EntryPoint()
+}
\ No newline at end of file
diff --git a/vpn-client/src/main/java/net/nymtech/vpn/model/ExitPoint.kt b/vpn-client/src/main/java/net/nymtech/vpn/model/ExitPoint.kt
new file mode 100644
index 0000000..67eecfe
--- /dev/null
+++ b/vpn-client/src/main/java/net/nymtech/vpn/model/ExitPoint.kt
@@ -0,0 +1,13 @@
+package net.nymtech.vpn.model
+
+sealed class ExitPoint {
+ data class Location(private val location: String) : ExitPoint() {
+ override fun toString(): String {
+ return "{ \"Location\": { \"location\": \"${location}\" }}"
+ }
+ }
+ //TODO impl later
+ private sealed class Gateway() : ExitPoint()
+ private sealed class Address() : ExitPoint()
+
+}
\ No newline at end of file
diff --git a/vpn-client/src/main/java/net/nymtech/vpn/model/VpnState.kt b/vpn-client/src/main/java/net/nymtech/vpn/model/VpnState.kt
new file mode 100644
index 0000000..3953356
--- /dev/null
+++ b/vpn-client/src/main/java/net/nymtech/vpn/model/VpnState.kt
@@ -0,0 +1,8 @@
+package net.nymtech.vpn.model
+
+enum class VpnState {
+ UP,
+ DOWN,
+ CONNECTING,
+ DISCONNECTING
+}
\ No newline at end of file
diff --git a/vpn-client/src/main/java/net/nymtech/vpn/VpnStatistics.kt b/vpn-client/src/main/java/net/nymtech/vpn/model/VpnStatistics.kt
similarity index 78%
rename from vpn-client/src/main/java/net/nymtech/vpn/VpnStatistics.kt
rename to vpn-client/src/main/java/net/nymtech/vpn/model/VpnStatistics.kt
index 77da636..2a1baa0 100644
--- a/vpn-client/src/main/java/net/nymtech/vpn/VpnStatistics.kt
+++ b/vpn-client/src/main/java/net/nymtech/vpn/model/VpnStatistics.kt
@@ -1,4 +1,4 @@
-package net.nymtech.vpn
+package net.nymtech.vpn.model
data class VpnStatistics(
val connectionSeconds: Long? = null,
diff --git a/vpn-client/src/main/java/net/nymtech/vpn/net/Endpoint.kt b/vpn-client/src/main/java/net/nymtech/vpn/net/Endpoint.kt
index b5cdf4d..d23bbf2 100644
--- a/vpn-client/src/main/java/net/nymtech/vpn/net/Endpoint.kt
+++ b/vpn-client/src/main/java/net/nymtech/vpn/net/Endpoint.kt
@@ -1,8 +1,8 @@
package net.nymtech.vpn.net
import android.os.Parcelable
-import java.net.InetSocketAddress
import kotlinx.parcelize.Parcelize
+import java.net.InetSocketAddress
@Parcelize
data class Endpoint(val address: InetSocketAddress, val protocol: TransportProtocol) : Parcelable
\ No newline at end of file
diff --git a/vpn-client/src/main/java/net/nymtech/vpn/tunnel/ErrorStateCause.kt b/vpn-client/src/main/java/net/nymtech/vpn/tunnel/ErrorStateCause.kt
index 53ac474..104577c 100644
--- a/vpn-client/src/main/java/net/nymtech/vpn/tunnel/ErrorStateCause.kt
+++ b/vpn-client/src/main/java/net/nymtech/vpn/tunnel/ErrorStateCause.kt
@@ -1,8 +1,8 @@
package net.nymtech.vpn.tunnel
import android.os.Parcelable
-import java.net.InetAddress
import kotlinx.parcelize.Parcelize
+import java.net.InetAddress
private const val AUTH_FAILED_REASON_EXPIRED_ACCOUNT = "[EXPIRED_ACCOUNT]"
diff --git a/vpn-client/src/main/java/net/nymtech/vpn/Action.kt b/vpn-client/src/main/java/net/nymtech/vpn/util/Action.kt
similarity index 68%
rename from vpn-client/src/main/java/net/nymtech/vpn/Action.kt
rename to vpn-client/src/main/java/net/nymtech/vpn/util/Action.kt
index 03cc0cb..a6eabe4 100644
--- a/vpn-client/src/main/java/net/nymtech/vpn/Action.kt
+++ b/vpn-client/src/main/java/net/nymtech/vpn/util/Action.kt
@@ -1,4 +1,4 @@
-package net.nymtech.vpn
+package net.nymtech.vpn.util
enum class Action {
START,
diff --git a/vpn-client/src/main/java/net/nymtech/vpn/ServiceManager.kt b/vpn-client/src/main/java/net/nymtech/vpn/util/ServiceManager.kt
similarity index 88%
rename from vpn-client/src/main/java/net/nymtech/vpn/ServiceManager.kt
rename to vpn-client/src/main/java/net/nymtech/vpn/util/ServiceManager.kt
index c2ed280..021f74b 100644
--- a/vpn-client/src/main/java/net/nymtech/vpn/ServiceManager.kt
+++ b/vpn-client/src/main/java/net/nymtech/vpn/util/ServiceManager.kt
@@ -1,9 +1,10 @@
-package net.nymtech.vpn
+package net.nymtech.vpn.util
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
+import net.nymtech.vpn.NymVpnService
import timber.log.Timber
@@ -39,12 +40,13 @@ object ServiceManager {
}
}
- fun startVpnService(context: Context) {
+ fun startVpnService(context: Context, extras : Map?) {
Timber.d("Called start vpn service")
actionOnService(
Action.START,
context,
NymVpnService::class.java,
+ extras = extras
)
}
diff --git a/vpn-client/src/main/res/drawable-anydpi/ic_stat_name.xml b/vpn-client/src/main/res/drawable-anydpi/ic_stat_name.xml
new file mode 100644
index 0000000..792d07b
--- /dev/null
+++ b/vpn-client/src/main/res/drawable-anydpi/ic_stat_name.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
diff --git a/vpn-client/src/main/res/drawable-hdpi/ic_stat_name.png b/vpn-client/src/main/res/drawable-hdpi/ic_stat_name.png
new file mode 100644
index 0000000..064717d
Binary files /dev/null and b/vpn-client/src/main/res/drawable-hdpi/ic_stat_name.png differ
diff --git a/vpn-client/src/main/res/drawable-mdpi/ic_stat_name.png b/vpn-client/src/main/res/drawable-mdpi/ic_stat_name.png
new file mode 100644
index 0000000..fcfad7b
Binary files /dev/null and b/vpn-client/src/main/res/drawable-mdpi/ic_stat_name.png differ
diff --git a/vpn-client/src/main/res/drawable-xhdpi/ic_stat_name.png b/vpn-client/src/main/res/drawable-xhdpi/ic_stat_name.png
new file mode 100644
index 0000000..01f33ab
Binary files /dev/null and b/vpn-client/src/main/res/drawable-xhdpi/ic_stat_name.png differ
diff --git a/vpn-client/src/main/res/drawable-xxhdpi/ic_stat_name.png b/vpn-client/src/main/res/drawable-xxhdpi/ic_stat_name.png
new file mode 100644
index 0000000..d801bb0
Binary files /dev/null and b/vpn-client/src/main/res/drawable-xxhdpi/ic_stat_name.png differ