Add configurable deployment system with VPN and Tor support
Features: - Hidden config.json in assets for per-deployment customization - Configure target URL, app name, and branding - Optional WireGuard VPN with auto-connect - Optional Tor routing via Orbot - Custom theme colors - Configuration-driven app behavior Configuration file location: app/src/main/assets/config.json Example configuration: config.example.json 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
package uk.silverlabs.silverdroid.config
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Application configuration that can be customized per deployment
|
||||
*/
|
||||
@Serializable
|
||||
data class AppConfig(
|
||||
// App branding
|
||||
val appName: String = "SilverDROID",
|
||||
val appVersion: String = "1.0.0",
|
||||
|
||||
// Target URL configuration
|
||||
val targetUrl: String,
|
||||
val showUrlBar: Boolean = false,
|
||||
val allowNavigation: Boolean = true,
|
||||
|
||||
// VPN configuration (optional)
|
||||
val vpn: VpnConfig? = null,
|
||||
|
||||
// Tor configuration (optional)
|
||||
val tor: TorConfig? = null,
|
||||
|
||||
// Theme customization
|
||||
val theme: ThemeConfig = ThemeConfig()
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class VpnConfig(
|
||||
val enabled: Boolean = false,
|
||||
val autoConnect: Boolean = true,
|
||||
val privateKey: String,
|
||||
val address: String,
|
||||
val dns: List<String> = emptyList(),
|
||||
val peers: List<PeerConfig>
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class PeerConfig(
|
||||
val publicKey: String,
|
||||
val endpoint: String,
|
||||
val allowedIps: List<String> = listOf("0.0.0.0/0"),
|
||||
val persistentKeepalive: Int = 25
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class TorConfig(
|
||||
val enabled: Boolean = false,
|
||||
val autoConnect: Boolean = true,
|
||||
val useBridges: Boolean = false,
|
||||
val bridges: List<String> = emptyList(),
|
||||
val socksPort: Int = 9050,
|
||||
val controlPort: Int = 9051
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ThemeConfig(
|
||||
val primaryColor: String? = null,
|
||||
val backgroundColor: String? = null,
|
||||
val statusBarColor: String? = null
|
||||
)
|
||||
@@ -0,0 +1,82 @@
|
||||
package uk.silverlabs.silverdroid.config
|
||||
|
||||
import android.content.Context
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
* Loads app configuration from assets/config.json
|
||||
* Falls back to default configuration if file doesn't exist
|
||||
*/
|
||||
object ConfigLoader {
|
||||
|
||||
private const val CONFIG_FILE = "config.json"
|
||||
|
||||
private val json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
isLenient = true
|
||||
prettyPrint = true
|
||||
}
|
||||
|
||||
fun loadConfig(context: Context): AppConfig {
|
||||
return try {
|
||||
val configJson = context.assets.open(CONFIG_FILE).bufferedReader().use { it.readText() }
|
||||
json.decodeFromString<AppConfig>(configJson)
|
||||
} catch (e: IOException) {
|
||||
// File doesn't exist, return default config
|
||||
getDefaultConfig()
|
||||
} catch (e: Exception) {
|
||||
// Parsing error, log and return default
|
||||
android.util.Log.e("ConfigLoader", "Error loading config", e)
|
||||
getDefaultConfig()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDefaultConfig() = AppConfig(
|
||||
appName = "SilverDROID",
|
||||
targetUrl = "https://silverdesk-staging.silverlabs.uk/",
|
||||
showUrlBar = false,
|
||||
allowNavigation = true
|
||||
)
|
||||
|
||||
/**
|
||||
* Example configuration for reference
|
||||
*/
|
||||
fun getExampleConfig() = """
|
||||
{
|
||||
"appName": "SilverDesk Staging",
|
||||
"appVersion": "1.0.0",
|
||||
"targetUrl": "https://silverdesk-staging.silverlabs.uk/",
|
||||
"showUrlBar": false,
|
||||
"allowNavigation": true,
|
||||
"vpn": {
|
||||
"enabled": true,
|
||||
"autoConnect": true,
|
||||
"privateKey": "YOUR_PRIVATE_KEY_HERE",
|
||||
"address": "10.0.0.2/24",
|
||||
"dns": ["1.1.1.1", "1.0.0.1"],
|
||||
"peers": [
|
||||
{
|
||||
"publicKey": "SERVER_PUBLIC_KEY_HERE",
|
||||
"endpoint": "vpn.example.com:51820",
|
||||
"allowedIps": ["0.0.0.0/0"],
|
||||
"persistentKeepalive": 25
|
||||
}
|
||||
]
|
||||
},
|
||||
"tor": {
|
||||
"enabled": false,
|
||||
"autoConnect": false,
|
||||
"useBridges": false,
|
||||
"bridges": [],
|
||||
"socksPort": 9050,
|
||||
"controlPort": 9051
|
||||
},
|
||||
"theme": {
|
||||
"primaryColor": "#1976D2",
|
||||
"backgroundColor": "#FFFFFF",
|
||||
"statusBarColor": "#1976D2"
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
Reference in New Issue
Block a user