Skip to content

Commit

Permalink
feat: ui update with full config edit
Browse files Browse the repository at this point in the history
feat: Change config screen UI to accommodate editing of all fields.
Change config screen to allow the addition of new peers.
Closes #31

Change main screen to denote primary tunnel with star.
Change main screen tunnel options to allow changing tunnel to primary.

feat: Change settings screen UI to improve usability.
Closes #32

fix: Change application shortcuts to static shortcuts for the primary tunnel.
Remove dynamic shortcuts.
Closes #38

fix: Database changes from the previous version causing crashes.
#40 #37

fix: bug on detail screen where tunnel name was not showing

feat: Change button color when hovering on AndroidTV to improve visibility
#36

fix: Change file importing method to fix bug on FireTV
Closes #39

docs: update README with new screenshots
  • Loading branch information
zaneschepke committed Oct 10, 2023
1 parent ca3f3fd commit c8f2cfd
Show file tree
Hide file tree
Showing 53 changed files with 1,616 additions and 859 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ This is an alternative Android Application for [WireGuard](https://www.wireguard

<p float="center">
<img label="Main" style="padding-right:25px" src="asset/main_screen.png" width="200" />
<img label="Config" style="padding-left:25px" src="./asset/config_screen.png" width="200" />
<img label="Config" style="padding-left:25px" src="asset/config_screen.png" width="200" />
<img label="Settings" style="padding-left:25px" src="asset/settings_screen.png" width="200" />
<img label="Support" style="padding-left:25px" src="asset/support_screen.png" width="200" />
</p>
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ android {
applicationId = "com.zaneschepke.wireguardautotunnel"
minSdk = 26
targetSdk = 34
versionCode = 30003
versionName = "3.0.3"
versionCode = 31000
versionName = "3.1.0"

multiDexEnabled = true

Expand Down
6 changes: 5 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES"/>
</intent-filter>
<meta-data android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
</activity>
<activity
android:name=".ui.CaptureActivityPortrait"
Expand All @@ -67,6 +69,8 @@
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:finishOnTaskLaunch="true"
android:enabled="true"
android:exported="true"
android:theme="@android:style/Theme.NoDisplay"
android:name=".service.shortcut.ShortcutsActivity"/>
<service
Expand Down Expand Up @@ -100,7 +104,7 @@
<action android:name="android.net.VpnService"/>
</intent-filter>
<meta-data android:name="android.net.VpnService.SUPPORTS_ALWAYS_ON"
android:value="true"/>
android:value="true" />
</service>
<service
android:name=".service.foreground.WireGuardConnectivityWatcherService"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.zaneschepke.wireguardautotunnel

object Constants {
const val MANUAL_TUNNEL_CONFIG_ID = "0"
const val VPN_CONNECTIVITY_CHECK_INTERVAL = 3000L
const val VPN_STATISTIC_CHECK_INTERVAL = 10000L
const val SNACKBAR_DELAY = 3000L
const val TOGGLE_TUNNEL_DELAY = 500L
const val FADE_IN_ANIMATION_DURATION = 1000
const val SLIDE_IN_ANIMATION_DURATION = 500
Expand All @@ -12,6 +12,5 @@ object Constants {
const val URI_CONTENT_SCHEME = "content"
const val URI_PACKAGE_SCHEME = "package"
const val ALLOWED_FILE_TYPES = "*/*"
const val FILES_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED"
const val ANDROID_TV_STUBS = "com.google.android.tv.frameworkpackagestubs"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,35 @@ package com.zaneschepke.wireguardautotunnel
import android.app.Application
import android.content.Context
import android.content.pm.PackageManager
import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa
import com.zaneschepke.wireguardautotunnel.repository.model.Settings
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject

@HiltAndroidApp
class WireGuardAutoTunnel : Application() {

@Inject
lateinit var settingsRepo : SettingsDoa

override fun onCreate() {
super.onCreate()
if(BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}
initSettings()
}

private fun initSettings() {
CoroutineScope(Dispatchers.IO).launch {
if(settingsRepo.getAll().isEmpty()) {
settingsRepo.save(Settings())
}
}
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ class DatabaseModule {
fun provideDatabase(@ApplicationContext context : Context) : AppDatabase {
return Room.databaseBuilder(
context,
AppDatabase::class.java, context.getString(R.string.db_name)
).build()
AppDatabase::class.java, context.getString(R.string.db_name))
.fallbackToDestructiveMigration()
.build()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,4 @@ class TunnelModule {
fun provideVpnService(backend: Backend) : VpnService {
return WireGuardTunnel(backend)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,13 @@ data class Settings(
@ColumnInfo(name = "default_tunnel") var defaultTunnel : String? = null,
@ColumnInfo(name = "is_always_on_vpn_enabled") var isAlwaysOnVpnEnabled : Boolean = false,
@ColumnInfo(name = "is_tunnel_on_ethernet_enabled") var isTunnelOnEthernetEnabled : Boolean = false,
)
) {
fun isTunnelConfigDefault(tunnelConfig: TunnelConfig) : Boolean {
return if (defaultTunnel != null) {
val defaultConfig = TunnelConfig.from(defaultTunnel!!)
(tunnelConfig.id == defaultConfig.id)
} else {
false
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,57 +22,7 @@ data class TunnelConfig(
}

companion object {
private const val INCLUDED_APPLICATIONS = "IncludedApplications = "
private const val EXCLUDED_APPLICATIONS = "ExcludedApplications = "
private const val INTERFACE = "[Interface]"
private const val NEWLINE_CHAR = "\n"
private const val APP_CONFIG_SEPARATOR = ", "

private fun addApplicationsToConfig(appConfig : String, wgQuick : String) : String {
val configList = wgQuick.split(NEWLINE_CHAR).toMutableList()
val interfaceIndex = configList.indexOf(INTERFACE)
configList.add(interfaceIndex + 1, appConfig)
return configList.joinToString(NEWLINE_CHAR)
}

fun clearAllApplicationsFromConfig(wgQuick : String) : String {
val configList = wgQuick.split(NEWLINE_CHAR).toMutableList()
val itr = configList.iterator()
while (itr.hasNext()) {
val next = itr.next()
if(next.contains(INCLUDED_APPLICATIONS) || next.contains(EXCLUDED_APPLICATIONS)) {
itr.remove()
}
}
return configList.joinToString(NEWLINE_CHAR)
}


fun setExcludedApplicationsOnQuick(packages : List<String>, wgQuick: String) : String {
if(packages.isEmpty()) {
return wgQuick
}
val clearedWgQuick = clearAllApplicationsFromConfig(wgQuick)
val excludeConfig = buildExcludedApplicationsString(packages)
return addApplicationsToConfig(excludeConfig, clearedWgQuick)
}

fun setIncludedApplicationsOnQuick(packages : List<String>, wgQuick: String) : String {
if(packages.isEmpty()) {
return wgQuick
}
val clearedWgQuick = clearAllApplicationsFromConfig(wgQuick)
val includeConfig = buildIncludedApplicationsString(packages)
return addApplicationsToConfig(includeConfig, clearedWgQuick)
}

private fun buildExcludedApplicationsString(packages : List<String>) : String {
return EXCLUDED_APPLICATIONS + packages.joinToString(APP_CONFIG_SEPARATOR)
}

private fun buildIncludedApplicationsString(packages : List<String>) : String {
return INCLUDED_APPLICATIONS + packages.joinToString(APP_CONFIG_SEPARATOR)
}
fun from(string : String) : TunnelConfig {
return Json.decodeFromString<TunnelConfig>(string)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,76 @@
package com.zaneschepke.wireguardautotunnel.service.shortcut

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.zaneschepke.wireguardautotunnel.R
import androidx.activity.ComponentActivity
import com.zaneschepke.wireguardautotunnel.repository.SettingsDoa
import com.zaneschepke.wireguardautotunnel.repository.TunnelConfigDao
import com.zaneschepke.wireguardautotunnel.repository.model.Settings
import com.zaneschepke.wireguardautotunnel.repository.model.TunnelConfig
import com.zaneschepke.wireguardautotunnel.service.foreground.Action
import com.zaneschepke.wireguardautotunnel.service.foreground.ServiceManager
import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardTunnelService
import com.zaneschepke.wireguardautotunnel.util.WgTunnelException
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject

@AndroidEntryPoint
class ShortcutsActivity : AppCompatActivity() {
class ShortcutsActivity : ComponentActivity() {

@Inject
lateinit var settingsRepo : SettingsDoa

@Inject
lateinit var tunnelConfigRepo : TunnelConfigDao

private val scope = CoroutineScope(Dispatchers.Main);

private fun attemptWatcherServiceToggle(tunnelConfig : String) {
scope.launch {
val settings = settingsRepo.getAll()
if (settings.isNotEmpty()) {
val setting = settings.first()
if(setting.isAutoTunnelEnabled) {
ServiceManager.toggleWatcherServiceForeground(this@ShortcutsActivity, tunnelConfig)
}
val settings = getSettings()
if(settings.isAutoTunnelEnabled) {
ServiceManager.toggleWatcherServiceForeground(this@ShortcutsActivity, tunnelConfig)
}
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if(intent.getStringExtra(ShortcutsManager.CLASS_NAME_EXTRA_KEY)
.equals(WireGuardTunnelService::class.java.name)) {

intent.getStringExtra(getString(R.string.tunnel_extras_key))?.let {
attemptWatcherServiceToggle(it)
}
when(intent.action){
Action.STOP.name -> ServiceManager.stopVpnService(this)
Action.START.name -> intent.getStringExtra(getString(R.string.tunnel_extras_key))
?.let { ServiceManager.startVpnService(this, it) }
if(intent.getStringExtra(CLASS_NAME_EXTRA_KEY)
.equals(WireGuardTunnelService::class.java.simpleName)) {
scope.launch {
try {
val settings = getSettings()
val tunnelConfig = if(settings.defaultTunnel == null) {
tunnelConfigRepo.getAll().first()
} else {
TunnelConfig.from(settings.defaultTunnel!!)
}
attemptWatcherServiceToggle(tunnelConfig.toString())
when(intent.action){
Action.STOP.name -> ServiceManager.stopVpnService(this@ShortcutsActivity)
Action.START.name -> ServiceManager.startVpnService(this@ShortcutsActivity, tunnelConfig.toString())
}
} catch (e : Exception) {
Timber.e(e.message)
}
}
}
finish()
}

private suspend fun getSettings() : Settings {
val settings = settingsRepo.getAll()
return if (settings.isNotEmpty()) {
settings.first()
} else {
throw WgTunnelException("Settings empty")
}
}
companion object {
const val CLASS_NAME_EXTRA_KEY = "className"
}
}

This file was deleted.

Loading

0 comments on commit c8f2cfd

Please sign in to comment.