Commit 127cf86e authored by Daniel Wolf's avatar Daniel Wolf
Browse files

Merge branch 'master' of https://git.frostnerd.com/PublicAndroidApps/smokescreen into translations

parents 666bb2f5 3c08c754
Pipeline #5982 passed with stage
in 1 minute and 52 seconds
......@@ -49,6 +49,8 @@ The app consists of a few core features:
* Query logging
* DNS rules, where you can specify your own IP addresses for hosts
* Rules can be imported from files and URLs (supports 4 different formats)
* You can block hosts by using 0.0.0.0 and ::1 as targets
* The DNS rules prevent CNAME cloaking
* Highly customizable settings
* Disable IPv4/IPv6
* Allow captive portals
......
......@@ -25,10 +25,14 @@ android {
applicationId "com.frostnerd.smokescreen"
minSdkVersion 21
targetSdkVersion 29
versionCode 51
versionName "1.0.2"
versionCode 53
versionName "1.1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
buildConfigField("Boolean", "FROM_CI", String.valueOf(getSystemVariableOrDefault("CI_COMMIT_SHORT_SHA", "") != ""))
buildConfigField("String", "COMMIT_HASH", '"' + getGitCommitHash() + '"')
buildConfigField("String", "SENTRY_DSN", '"' + getSystemVariableOrDefault("SENTRY_DSN", "dummy") + '"')
kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas".toString())
......@@ -81,7 +85,6 @@ android {
adblocker {
dimension "version"
versionNameSuffix "-adblock"
versionCode 51
}
normal {
dimension "version"
......@@ -107,7 +110,7 @@ android {
configurations.all {
resolutionStrategy {
force 'org.slf4j:slf4j-api:1.7.26'
force 'androidx.recyclerview:recyclerview:1.1.0-rc01'
force 'androidx.recyclerview:recyclerview:1.1.0'
}
}
......@@ -121,7 +124,7 @@ dependencies {
implementation 'com.frostnerd.utilskt:preferences:1.5.17' // https://git.frostnerd.com/AndroidUtils/preferenceskt
implementation 'com.frostnerd.utilskt:navigationdraweractivity:1.3.29' // https://git.frostnerd.com/AndroidUtils/navigationdraweractivity
implementation 'com.frostnerd.utilskt:encrypteddnstunnelproxy:1.5.169' // https://git.frostnerd.com/AndroidUtils/encrypteddnstunnelproxy
implementation 'com.frostnerd.utilskt:encrypteddnstunnelproxy:1.5.172' // https://git.frostnerd.com/AndroidUtils/encrypteddnstunnelproxy
implementation 'com.frostnerd.utilskt:general:1.0.19' // https://git.frostnerd.com/AndroidUtils/generalkt
implementation 'com.frostnerd.utilskt:adapters:1.1.6' // https://git.frostnerd.com/AndroidUtils/Adapters
......@@ -141,10 +144,19 @@ dependencies {
implementation 'com.github.jorgecastilloprz:fabprogresscircle:1.01@aar'
implementation 'com.squareup.leakcanary:leaksentry:2.0-alpha-3'
leakCanaryImplementation 'com.squareup.leakcanary:leakcanary-android:2.0-beta-3'
leakCanaryImplementation 'com.squareup.leakcanary:leakcanary-android:2.0'
testImplementation 'junit:junit:4.12'
testImplementation "org.robolectric:robolectric:4.3.1"
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
def getGitCommitHash() {
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'rev-parse', '--short', 'HEAD'
standardOutput = stdout
}
return stdout.toString().trim()
}
\ No newline at end of file
......@@ -17,11 +17,14 @@
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme_Mono"
tools:ignore="GoogleAppIndexingWarning"
android:fullBackupContent="@xml/backup_descriptor">
<meta-data android:name="io.sentry.auto-init" android:value="false" />
<activity
android:name=".activity.PinActivity"
android:theme="@style/Theme.AppCompat.Light.Dialog.Alert"
......
app/src/main/ic_launcher-web.png

86.2 KB | W: | H:

app/src/main/ic_launcher-web.png

92.6 KB | W: | H:

app/src/main/ic_launcher-web.png
app/src/main/ic_launcher-web.png
app/src/main/ic_launcher-web.png
app/src/main/ic_launcher-web.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -321,7 +321,7 @@ fun HttpsDnsServerInformation.Companion.fromServerUrls(primaryUrl:String, second
)
}
fun DnsServerInformation.Companion.tlsServerFromHosts(primaryHost:String, secondaryHost:String?): DnsServerInformation<TLSUpstreamAddress> {
fun tlsServerFromHosts(primaryHost:String, secondaryHost:String?): DnsServerInformation<TLSUpstreamAddress> {
val serverInfo = mutableListOf<DnsServerConfiguration<TLSUpstreamAddress>>()
serverInfo.add(
DnsServerConfiguration(address = createTlsUpstreamAddress(primaryHost), experimental = false, preferredProtocol = TLS, supportedProtocols = listOf(TLS))
......
......@@ -108,7 +108,7 @@ fun Context.log(e: Throwable, extras: Map<String, String>? = null) {
if (errorFile.createNewFile()) {
val writer = BufferedWriter(FileWriter(errorFile, false))
writer.write("App version: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})\n")
writer.write("App version: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE}, Commit: ${BuildConfig.COMMIT_HASH})\n")
writer.write("Android SDK version: ${Build.VERSION.SDK_INT} (${Build.VERSION.RELEASE} - ${Build.VERSION.CODENAME})\n")
writer.write("Device: ${Build.MODEL} from ${Build.MANUFACTURER} (Device: ${Build.DEVICE}, Product: ${Build.PRODUCT})\n")
writer.write("------------------------------\n")
......
......@@ -22,6 +22,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import leakcanary.LeakSentry
import java.net.InetAddress
import java.util.*
import kotlin.system.exitProcess
......@@ -95,56 +96,63 @@ class SmokeScreen : Application() {
}
fun initSentry(forceStatus: Status = Status.NONE) {
if (!BuildConfig.DEBUG) {
val enabledType = getPreferences().crashreportingType
if (forceStatus != Status.DATASAVING && (enabledType == Crashreporting.FULL || forceStatus == Status.ENABLED)) {
// Enable Sentry in full mode
// This passes some device-related data, but nothing which allows user actions to be tracked across the app
// Info: Some data is attached by the AndroidEventBuilderHelper class, which is present by default
GlobalScope.launch(Dispatchers.IO) {
Sentry.init(
"https://fadeddb58abf408db50809922bf064cc@sentry.frostnerd.com:443/2",
AndroidSentryClientFactory(this@SmokeScreen)
)
Sentry.getContext().user =
User(getPreferences().crashReportingUUID, null, null, null)
Sentry.getStoredClient().apply {
addTag("user.language", Locale.getDefault().displayLanguage)
addTag("app.database_version", AppDatabase.currentVersion.toString())
addTag("app.dns_server_name", getPreferences().dnsServerConfig.name)
addTag(
"app.dns_server_primary",
getPreferences().dnsServerConfig.servers[0].address.formatToString()
)
addTag(
"app.dns_server_secondary",
getPreferences().dnsServerConfig.servers.getOrNull(1)?.address?.formatToString()
if (!BuildConfig.DEBUG && BuildConfig.SENTRY_DSN != "dummy") {
GlobalScope.launch(Dispatchers.IO) {
val hostName = InetAddress.getLocalHost().hostName
if(!hostName.startsWith("mars-sandbox", true)) {
val enabledType = getPreferences().crashreportingType
if (forceStatus != Status.DATASAVING && (enabledType == Crashreporting.FULL || forceStatus == Status.ENABLED)) {
// Enable Sentry in full mode
// This passes some device-related data, but nothing which allows user actions to be tracked across the app
// Info: Some data is attached by the AndroidEventBuilderHelper class, which is present by default
Sentry.init(
BuildConfig.SENTRY_DSN,
AndroidSentryClientFactory(this@SmokeScreen)
)
addTag(
"app.installer_package",
packageManager.getInstallerPackageName(packageName)
Sentry.getContext().user =
User(getPreferences().crashReportingUUID, null, null, null)
Sentry.getStoredClient().apply {
addTag("user.language", Locale.getDefault().displayLanguage)
addTag("app.database_version", AppDatabase.currentVersion.toString())
addTag("app.dns_server_name", getPreferences().dnsServerConfig.name)
addTag(
"app.dns_server_primary",
getPreferences().dnsServerConfig.servers[0].address.formatToString()
)
addTag(
"app.dns_server_secondary",
getPreferences().dnsServerConfig.servers.getOrNull(1)?.address?.formatToString()
)
addTag(
"app.installer_package",
packageManager.getInstallerPackageName(packageName)
)
addTag("richdata", "true")
addTag("app.fromCi", BuildConfig.FROM_CI.toString())
addTag("app.commit", BuildConfig.COMMIT_HASH)
}
} else if (enabledType == Crashreporting.MINIMAL || forceStatus == Status.DATASAVING) {
// Inits Sentry in datasaving mode
// Only data absolutely necessary is transmitted (Android version, app version).
// Only crashes will be reported, no regular events.
Sentry.init(
BuildConfig.SENTRY_DSN,
AndroidSentryClientFactory(this@SmokeScreen)
)
addTag("richdata", "true")
}
}
} else if(enabledType == Crashreporting.MINIMAL || forceStatus == Status.DATASAVING){
// Inits Sentry in datasaving mode
// Only data absolutely necessary is transmitted (Android version, app version).
// Only crashes will be reported, no regular events.
GlobalScope.launch(Dispatchers.IO) {
Sentry.init(
"https://fadeddb58abf408db50809922bf064cc@sentry.frostnerd.com:443/2",
AndroidSentryClientFactory(this@SmokeScreen)
)
Sentry.getContext().user = User("anon-" + BuildConfig.VERSION_CODE, null, null, null)
Sentry.getStoredClient().apply {
addTag("richdata", "false")
addTag("dist", BuildConfig.VERSION_CODE.toString())
addExtra("dist", BuildConfig.VERSION_CODE)
this.builderHelpers.forEach {
this.removeBuilderHelper(it)
Sentry.getContext().user =
User("anon-" + BuildConfig.VERSION_CODE, null, null, null)
Sentry.getStoredClient().apply {
addTag("richdata", "false")
addTag("dist", BuildConfig.VERSION_CODE.toString())
addTag("app.commit", BuildConfig.COMMIT_HASH)
addTag("app.fromCi", BuildConfig.FROM_CI.toString())
addExtra("dist", BuildConfig.VERSION_CODE)
this.builderHelpers.forEach {
this.removeBuilderHelper(it)
}
this.addBuilderHelper(DatasavingSentryEventHelper())
}
this.addBuilderHelper(DatasavingSentryEventHelper())
}
}
}
......
......@@ -168,6 +168,7 @@ class BackgroundVpnConfigureActivity : BaseActivity() {
private fun showPermissionDenialDialog() {
androidx.appcompat.app.AlertDialog.Builder(this, getPreferences().theme.dialogStyle)
.setTitle(getString(R.string.app_name) + " - " + getString(R.string.information))
.setMessage(R.string.dialog_vpn_permission_denied_message)
.setPositiveButton(R.string.open_app) { _, _ ->
val intent = PinActivity.openAppIntent(this)
startActivity(intent)
......
......@@ -170,6 +170,11 @@ class MainActivity : NavigationDrawerActivity() {
registerLocalReceiver(listOf(BROADCAST_RELOAD_MENU), true) {
reloadMenuItems()
}
@Suppress("ConstantConditionIf")
if(!BuildConfig.DEBUG && BuildConfig.SENTRY_DSN == "dummy") {
Toast.makeText(this, "Warning, Sentry DSN is not valid", Toast.LENGTH_LONG).show()
}
}
override fun onDestroy() {
......
......@@ -86,7 +86,7 @@ class DnsQueryRepository(private val dnsQueryDao: DnsQueryDao) {
builder.append(query.type.name).append(",")
builder.append(query.type.value).append(",")
builder.append(query.askedServer).append(",")
builder.append(query.responseSource?.name ?: "").append(",")
builder.append(query.responseSource.name).append(",")
builder.append(query.questionTime).append(",")
builder.append(query.responseTime).append(",")
builder.append("\"").append(responseConverter.someObjectListToString(query.responses).replace(",", ";").replace("\"", "'")).append("\"")
......
......@@ -5,6 +5,8 @@ import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.provider.Settings
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import com.frostnerd.smokescreen.R
......@@ -28,24 +30,60 @@ import com.frostnerd.smokescreen.getPreferences
*
* You can contact the developer at daniel.wolf@frostnerd.com.
*/
class BatteryOptimizationInfoDialog(context:Context) :AlertDialog(context, context.getPreferences().theme.dialogStyle) {
class BatteryOptimizationInfoDialog(context: Context) :
AlertDialog(context, context.getPreferences().theme.dialogStyle) {
private val moreInfoLink = "https://dontkillmyapp.com?app=Nebulo"
init {
setTitle(R.string.dialog_batteryoptimization_title)
setMessage(context.getString(R.string.dialog_servicekilled_message))
setButton(DialogInterface.BUTTON_NEUTRAL, context.getString(android.R.string.ok)) { dialog, _ ->
dialog.dismiss()
val settingsIntent = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS)
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1 -> {
Intent(Settings.ACTION_BATTERY_SAVER_SETTINGS)
}
else -> {
null
}
}
if(settingsIntent?.resolveActivity(context.packageManager) != null) {
setButton(
DialogInterface.BUTTON_NEUTRAL,
context.getString(R.string.menu_settings)
) { dialog, _ ->
dialog.dismiss()
context.startActivity(settingsIntent)
}
} else {
setButton(
DialogInterface.BUTTON_NEUTRAL,
context.getString(android.R.string.ok)
) { dialog, _ ->
dialog.dismiss()
}
}
setButton(DialogInterface.BUTTON_POSITIVE, context.getString(R.string.dialog_servicekilled_more_info)) { dialog, _ ->
setButton(
DialogInterface.BUTTON_POSITIVE,
context.getString(R.string.dialog_servicekilled_more_info)
) { dialog, _ ->
val i = Intent(Intent.ACTION_VIEW)
i.data = Uri.parse(moreInfoLink)
try {
context.startActivity(i)
} catch (e: ActivityNotFoundException) { Toast.makeText(context, R.string.error_no_webbrowser_installed, Toast.LENGTH_LONG).show() }
} catch (e: ActivityNotFoundException) {
Toast.makeText(context, R.string.error_no_webbrowser_installed, Toast.LENGTH_LONG)
.show()
}
dialog.dismiss()
}
setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.dialog_batteryoptimization_ignore)) { dialog, _ ->
setButton(
DialogInterface.BUTTON_NEGATIVE,
context.getString(R.string.dialog_batteryoptimization_ignore)
) { dialog, _ ->
context.getPreferences().ignoreServiceKilled = true
dialog.dismiss()
}
......
......@@ -53,7 +53,14 @@ class NewServerDialog(
private var validationRegex = SERVER_URL_REGEX
companion object {
private val dohAddressPart = "[a-z0-9][a-z0-9-.]*[a-z0-9]"
// Hostpart has to begin with a character or number
// Then has to either:
// - Consist of numbers, characters and dashes AND ends with a character
// - End with a character or number
// => Host part has to be at least 2 characters long
// Host can optionally end with a dot
// - If there is a dot there has to be either a number or a char after it
private val dohAddressPart = "(?:[a-z0-9](?:(?:[a-z0-9-]*[a-z]*[a-z0-9-]*[a-z0-9])|[a-z0-9])(?:.(?=[a-z0-9])|))*"
val SERVER_URL_REGEX =
Regex(
"^\\s*(?:https://)?((?:$dohAddressPart)|(?:\\[[a-z0-9:]+]))(?::[1-9][0-9]{0,4})?(/[a-z0-9-.]+)*(/)?\\s*$",
......
......@@ -41,20 +41,25 @@ import kotlinx.coroutines.launch
*/
class ServerChoosalDialog(
context: AppCompatActivity,
selectedServer:DnsServerInformation<*>?,
showTls:Boolean = selectedServer?.hasTlsServer() ?: true,
onEntrySelected: (config: DnsServerInformation<*>) -> Unit
) :
BaseDialog(context, context.getPreferences().theme.dialogStyle) {
private var populationJob: Job? = null
private var currentSelectedServer: DnsServerInformation<*>
private var currentSelectedServer: DnsServerInformation<*>?
private lateinit var defaultConfig: List<DnsServerInformation<*>>
private lateinit var userConfig: List<UserServerConfiguration>
constructor(context: AppCompatActivity,
onEntrySelected: (config: DnsServerInformation<*>) -> Unit):this(context, context.getPreferences().dnsServerConfig, onEntrySelected=onEntrySelected)
init {
val view = layoutInflater.inflate(R.layout.dialog_server_configuration, null, false)
setTitle(R.string.dialog_serverconfiguration_title)
setView(view)
currentSelectedServer = context.getPreferences().dnsServerConfig
currentSelectedServer = selectedServer
setButton(
DialogInterface.BUTTON_NEUTRAL, context.getString(android.R.string.cancel)
......@@ -62,10 +67,9 @@ class ServerChoosalDialog(
setButton(
DialogInterface.BUTTON_POSITIVE, context.getString(android.R.string.ok)
) { _, _ ->
onEntrySelected.invoke(currentSelectedServer)
currentSelectedServer?.apply(onEntrySelected)
}
val isCurrentServerTls = currentSelectedServer.hasTlsServer()
loadServerData(isCurrentServerTls)
loadServerData(showTls)
val spinnerAdapter = ArrayAdapter<String>(
context, android.R.layout.simple_spinner_item,
......@@ -77,7 +81,7 @@ class ServerChoosalDialog(
spinnerAdapter.setDropDownViewResource(R.layout.item_tasker_action_spinner_dropdown_item)
val spinner = view.findViewById<Spinner>(R.id.spinner)
spinner.adapter = spinnerAdapter
if(isCurrentServerTls) spinner.setSelection(1)
if(showTls) spinner.setSelection(1)
view.findViewById<RadioGroup>(R.id.knownServersGroup).setOnCheckedChangeListener { group, _ ->
val button = view.findViewById(group.checkedRadioButtonId) as RadioButton
val payload = button.tag
......@@ -174,6 +178,7 @@ class ServerChoosalDialog(
}
private fun markCurrentSelectedServer() {
val currentSelectedServer = this.currentSelectedServer ?: return
for (id in 0 until knownServersGroup.childCount) {
val child = knownServersGroup.getChildAt(id) as RadioButton
val payload = child.tag
......@@ -299,7 +304,7 @@ class ServerChoosalDialog(
currentSelectedServer =
if (userConfiguration.isHttpsServer()) AbstractHttpsDNSHandle.KNOWN_DNS_SERVERS.minBy { it.key }!!.value else AbstractTLSDnsHandle.KNOWN_DNS_SERVERS.minBy { it.key }!!.value
markCurrentSelectedServer()
context.getPreferences().dnsServerConfig = currentSelectedServer
context.getPreferences().dnsServerConfig = currentSelectedServer!!
}
knownServersGroup.removeView(button)
}.show()
......@@ -348,7 +353,7 @@ class ServerChoosalDialog(
currentSelectedServer =
if (isHttps) AbstractHttpsDNSHandle.KNOWN_DNS_SERVERS.minBy { it.key }!!.value else AbstractTLSDnsHandle.KNOWN_DNS_SERVERS.minBy { it.key }!!.value
markCurrentSelectedServer()
context.getPreferences().dnsServerConfig = currentSelectedServer
context.getPreferences().dnsServerConfig = currentSelectedServer!!
}
knownServersGroup.removeView(button)
}.show()
......
......@@ -66,7 +66,7 @@ class AboutFragment : Fragment() {
getString(R.string.about_contact_developer),
getString(R.string.app_name),
getString(R.string.support_contact_mail),
"\n\n\n\n\n\nSystem:\nApp version: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})\n" +
"\n\n\n\n\n\nSystem:\nApp version: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE};${BuildConfig.COMMIT_HASH})\n" +
"Android: ${Build.VERSION.SDK_INT} (${Build.VERSION.RELEASE} - ${Build.VERSION.CODENAME})"
)
}
......@@ -89,7 +89,7 @@ class AboutFragment : Fragment() {
getString(R.string.menu_about),
getString(
R.string.about_app,
BuildConfig.VERSION_NAME + if (BuildConfig.DEBUG) " DEBUG" else "",
BuildConfig.VERSION_NAME + (if (BuildConfig.DEBUG) " DEBUG" else "") + " (Commit ${BuildConfig.COMMIT_HASH})",
BuildConfig.VERSION_CODE,
AppDatabase.currentVersion,
if (context!!.getPreferences().crashreportingType == Crashreporting.FULL) context!!.getPreferences().crashReportingUUID else "---"
......
......@@ -178,7 +178,7 @@ class MainFragment : Fragment() {
getPreferences().vpnInformationShown = true
} else {
if (getPreferences().vpnInformationShown) {
requireContext().startService(Intent(requireContext(), DnsVpnService::class.java))
startActivityForResult(prepare, vpnRequestCode)
} else {
showInfoTextDialog(requireContext(),
getString(R.string.dialog_vpninformation_title),
......
......@@ -59,7 +59,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
context?.getPreferences()?.notifyPreferenceChangedFromExternal(key)
}
private val category:SettingsActivity.Category by lazy(LazyThreadSafetyMode.NONE) {
arguments!!.getSerializable("category") as SettingsActivity.Category
(arguments?.getSerializable("category") as SettingsActivity.Category?) ?: SettingsActivity.Category.GENERAL
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
......@@ -223,6 +223,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
dialog.setTitle(R.string.dialog_clearqueries_title)
dialog.setPositiveButton(R.string.all_yes) { d, _ ->
requireContext().getDatabase().dnsQueryDao().deleteAll()
getPreferences().exportedQueryCount = 0
exportQueries.summary =
getString(R.string.summary_export_queries, 0)
d.dismiss()
......@@ -382,9 +383,11 @@ class SettingsFragment : PreferenceFragmentCompat() {
getString(R.string.title_clear_dnscache),
getString(R.string.dialog_cleardnscache_message),
getString(R.string.all_yes) to { dialog, _ ->
GlobalScope.launch {
getDatabase().cachedResponseDao().deleteAll()
DnsVpnService.invalidateDNSCache(context!!)
GlobalScope.launch(Dispatchers.IO) {
context?.also {
getDatabase().cachedResponseDao().deleteAll()
DnsVpnService.invalidateDNSCache(context!!)
}
}
dialog.dismiss()
},
......
......@@ -561,44 +561,50 @@ class DnsVpnService : VpnService(), Runnable {
}
private fun setNotificationText() {
val primaryServer: String
val secondaryServer: String?
if (serverConfig.httpsConfiguration != null) {
notificationBuilder.setContentTitle(getString(R.string.notification_main_title_https))
primaryServer = serverConfig.httpsConfiguration!![0].urlCreator.address.getUrl(true)
secondaryServer =
serverConfig.httpsConfiguration!!.getOrNull(1)?.urlCreator?.address?.getUrl(true)
} else {
notificationBuilder.setContentTitle(getString(R.string.notification_main_title_tls))
primaryServer = serverConfig.tlsConfiguration!![0].formatToString()
secondaryServer = serverConfig.tlsConfiguration!!.getOrNull(1)?.formatToString()
}
val text =
when {
getPreferences().simpleNotification -> getString(R.string.notification_simple_text, serverConfig.name)
secondaryServer != null -> getString(
if (getPreferences().isBypassBlacklist) R.string.notification_main_text_with_secondary else R.string.notification_main_text_with_secondary_whitelist,
primaryServer,
secondaryServer,
packageBypassAmount,
dnsProxy?.cache?.livingCachedEntries() ?: 0
)
else -> getString(
if (getPreferences().isBypassBlacklist) R.string.notification_main_text else R.string.notification_main_text_whitelist,
primaryServer,
packageBypassAmount,
dnsProxy?.cache?.livingCachedEntries() ?: 0
)
if (this::serverConfig.isInitialized) {
val primaryServer: String
val secondaryServer: String?
if (serverConfig.httpsConfiguration != null) {
notificationBuilder.setContentTitle(getString(R.string.notification_main_title_https))
primaryServer = serverConfig.httpsConfiguration!![0].urlCreator.address.getUrl(true)
secondaryServer =
serverConfig.httpsConfiguration!!.getOrNull(1)
?.urlCreator?.address?.getUrl(true)
} else {
notificationBuilder.setContentTitle(getString(R.string.notification_main_title_tls))
primaryServer = serverConfig.tlsConfiguration!![0].formatToString()
secondaryServer = serverConfig.tlsConfiguration!!.getOrNull(1)?.formatToString()
}
if(simpleNotification) {
notificationBuilder.setStyle(null)
notificationBuilder.setContentText(text)
} else {
notificationBuilder.setStyle(
NotificationCompat.BigTextStyle(notificationBuilder).bigText(
text
val text =
when {
getPreferences().simpleNotification -> getString(
R.string.notification_simple_text,
serverConfig.name
)
secondaryServer != null -> getString(
if (getPreferences().isBypassBlacklist) R.string.notification_main_text_with_secondary else R.string.notification_main_text_with_secondary_whitelist,
primaryServer,
secondaryServer,
packageBypassAmount,
dnsProxy?.cache?.livingCachedEntries() ?: 0
)
else -> getString(
if (getPreferences().isBypassBlacklist) R.string.notification_main_text else R.string.notification_main_text_whitelist,