summaryrefslogtreecommitdiffhomepage
path: root/android
diff options
context:
space:
mode:
authorAlbin <albin@mullvad.net>2023-04-11 11:20:38 +0200
committerAlbin <albin@mullvad.net>2023-04-11 11:20:38 +0200
commit50a474c5be424577b674d9ac927abc5494503a9f (patch)
treea465bb3184fe8d84a259990b42b257f7932d65e6 /android
parent2cc9013dfe0b5336d7b7c3146a5c8702e3007477 (diff)
parent60cd3692c6215b4e215739d4af9e17249e941397 (diff)
downloadmullvadvpn-50a474c5be424577b674d9ac927abc5494503a9f.tar.xz
mullvadvpn-50a474c5be424577b674d9ac927abc5494503a9f.zip
Merge branch 'add-dns-content-blockers-droid-10'
Diffstat (limited to 'android')
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/BaseCell.kt11
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/CustomDnsComposeCell.kt76
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/ExpandableComposeCell.kt111
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SwitchComposeCell.kt142
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/Chevron.kt36
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/HtmlText.kt14
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/Switch.kt21
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ContentBlockersInfoDialog.kt14
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/InfoDialog.kt111
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MalwareInfoDialog.kt10
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/extensions/LazyListExtensions.kt13
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingScreen.kt153
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AdvancedSettingsUiState.kt25
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/theme/Color.kt3
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/model/DefaultDnsOptions.kt6
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt8
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AdvancedFragment.kt8
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModel.kt73
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModelState.kt30
-rw-r--r--android/app/src/main/res/drawable/icon_info.xml8
-rw-r--r--android/app/src/main/res/values-da/strings.xml11
-rw-r--r--android/app/src/main/res/values-de/strings.xml11
-rw-r--r--android/app/src/main/res/values-es/strings.xml11
-rw-r--r--android/app/src/main/res/values-fi/strings.xml11
-rw-r--r--android/app/src/main/res/values-fr/strings.xml11
-rw-r--r--android/app/src/main/res/values-it/strings.xml11
-rw-r--r--android/app/src/main/res/values-ja/strings.xml11
-rw-r--r--android/app/src/main/res/values-ko/strings.xml11
-rw-r--r--android/app/src/main/res/values-my/strings.xml11
-rw-r--r--android/app/src/main/res/values-nb/strings.xml11
-rw-r--r--android/app/src/main/res/values-nl/strings.xml11
-rw-r--r--android/app/src/main/res/values-pl/strings.xml11
-rw-r--r--android/app/src/main/res/values-pt/strings.xml11
-rw-r--r--android/app/src/main/res/values-ru/strings.xml11
-rw-r--r--android/app/src/main/res/values-sv/strings.xml11
-rw-r--r--android/app/src/main/res/values-th/strings.xml11
-rw-r--r--android/app/src/main/res/values-tr/strings.xml11
-rw-r--r--android/app/src/main/res/values-zh-rCN/strings.xml11
-rw-r--r--android/app/src/main/res/values-zh-rTW/strings.xml11
-rw-r--r--android/app/src/main/res/values/strings.xml19
40 files changed, 982 insertions, 119 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/BaseCell.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/BaseCell.kt
index e07a34bef1..bab992bcc1 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/BaseCell.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/BaseCell.kt
@@ -26,6 +26,7 @@ fun BaseCell(
title: @Composable () -> Unit,
bodyView: @Composable () -> Unit,
modifier: Modifier = Modifier,
+ isRowEnabled: Boolean = true,
onCellClicked: () -> Unit = {},
subtitle: @Composable (() -> Unit)? = null,
subtitleModifier: Modifier = Modifier,
@@ -38,13 +39,19 @@ fun BaseCell(
val subtitleVerticalSpacing = dimensionResource(id = R.dimen.cell_footer_top_padding)
Column(modifier = Modifier.fillMaxWidth().wrapContentHeight().background(background)) {
+ val rowModifier =
+ Modifier.let {
+ if (isRowEnabled) {
+ it.clickable { onCellClicked() }
+ } else it
+ }
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Start,
modifier =
- Modifier.height(cellHeight)
+ rowModifier
+ .height(cellHeight)
.fillMaxWidth()
- .clickable { onCellClicked.invoke() }
.padding(start = startPadding, end = endPadding)
) {
title()
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/CustomDnsComposeCell.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/CustomDnsComposeCell.kt
deleted file mode 100644
index 3ed13f812f..0000000000
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/CustomDnsComposeCell.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-package net.mullvad.mullvadvpn.compose.cell
-
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.wrapContentHeight
-import androidx.compose.foundation.layout.wrapContentWidth
-import androidx.compose.material.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.dimensionResource
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.sp
-import net.mullvad.mullvadvpn.R
-import net.mullvad.mullvadvpn.compose.component.CellSwitch
-import net.mullvad.mullvadvpn.compose.theme.MullvadWhite
-import net.mullvad.mullvadvpn.compose.theme.MullvadWhite60
-
-@Preview
-@Composable
-private fun PreviewDnsComposeCell() {
- CustomDnsComposeCell(checkboxDefaultState = true, onToggle = {})
-}
-
-@Composable
-fun CustomDnsComposeCell(checkboxDefaultState: Boolean, onToggle: (Boolean) -> Unit) {
- val titleModifier = Modifier
- val bodyViewModifier = Modifier
- val subtitleModifier = Modifier
-
- BaseCell(
- title = { CustomDnsCellTitle(modifier = titleModifier) },
- bodyView = {
- CustomDnsCellView(
- switchTriggered = { onToggle(it) },
- isToggled = checkboxDefaultState,
- modifier = bodyViewModifier
- )
- },
- onCellClicked = { onToggle(!checkboxDefaultState) },
- subtitleModifier = subtitleModifier
- )
-}
-
-@Composable
-fun CustomDnsCellTitle(modifier: Modifier) {
- val textSize = dimensionResource(id = R.dimen.text_medium_plus).value.sp
- Text(
- text = stringResource(R.string.enable_custom_dns),
- textAlign = TextAlign.Center,
- fontWeight = FontWeight.Bold,
- fontSize = textSize,
- color = MullvadWhite,
- modifier = modifier.wrapContentWidth(align = Alignment.End).wrapContentHeight()
- )
-}
-
-@Composable
-fun CustomDnsCellView(switchTriggered: (Boolean) -> Unit, isToggled: Boolean, modifier: Modifier) {
- Row(modifier = modifier.wrapContentWidth().wrapContentHeight()) {
- CellSwitch(isChecked = isToggled, onCheckedChange = null)
- }
-}
-
-@Composable
-fun CustomDnsCellSubtitle(modifier: Modifier) {
- val textSize = dimensionResource(id = R.dimen.text_small).value.sp
- Text(
- text = stringResource(R.string.custom_dns_footer),
- fontSize = textSize,
- color = MullvadWhite60,
- modifier = modifier
- )
-}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/ExpandableComposeCell.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/ExpandableComposeCell.kt
new file mode 100644
index 0000000000..3a27adf2a9
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/ExpandableComposeCell.kt
@@ -0,0 +1,111 @@
+package net.mullvad.mullvadvpn.compose.cell
+
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.layout.wrapContentWidth
+import androidx.compose.material.Icon
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.alpha
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.res.dimensionResource
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import net.mullvad.mullvadvpn.R
+import net.mullvad.mullvadvpn.compose.component.ChevronView
+import net.mullvad.mullvadvpn.compose.component.HtmlText
+import net.mullvad.mullvadvpn.compose.component.textResource
+import net.mullvad.mullvadvpn.compose.theme.AlphaActive
+import net.mullvad.mullvadvpn.compose.theme.AlphaInactive
+import net.mullvad.mullvadvpn.compose.theme.MullvadWhite
+import net.mullvad.mullvadvpn.compose.theme.MullvadWhite60
+
+@Preview
+@Composable
+private fun PreviewExpandedEnabledExpandableComposeCell() {
+ ExpandableComposeCell(
+ title = "Expandable row title",
+ isExpanded = true,
+ isEnabled = true,
+ onCellClicked = {},
+ onInfoClicked = {}
+ )
+}
+
+@Composable
+fun ExpandableComposeCell(
+ title: String,
+ isExpanded: Boolean,
+ isEnabled: Boolean = true,
+ onCellClicked: (Boolean) -> Unit = {},
+ onInfoClicked: (() -> Unit)? = null
+) {
+ val titleModifier = Modifier.alpha(if (isEnabled) AlphaActive else AlphaInactive)
+ val bodyViewModifier = Modifier
+
+ BaseCell(
+ title = { SwitchCellTitle(title = title, modifier = titleModifier) },
+ bodyView = {
+ ExpandableComposeCellBody(
+ isExpanded = isExpanded,
+ modifier = bodyViewModifier,
+ onInfoClicked = onInfoClicked
+ )
+ },
+ onCellClicked = { onCellClicked(!isExpanded) }
+ )
+}
+
+@Composable
+private fun ExpandableComposeCellBody(
+ isExpanded: Boolean,
+ modifier: Modifier,
+ onInfoClicked: (() -> Unit)? = null
+) {
+ val horizontalPadding = dimensionResource(id = R.dimen.medium_padding)
+ val verticalPadding = 13.dp
+ Row(
+ modifier = modifier.wrapContentWidth().wrapContentHeight(),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ if (onInfoClicked != null) {
+ Icon(
+ modifier =
+ Modifier.clickable { onInfoClicked() }
+ .padding(
+ start = horizontalPadding,
+ end = horizontalPadding,
+ top = verticalPadding,
+ bottom = verticalPadding
+ )
+ .align(Alignment.CenterVertically),
+ painter = painterResource(id = R.drawable.icon_info),
+ contentDescription = null,
+ tint = MullvadWhite
+ )
+ }
+
+ ChevronView(isExpanded)
+ }
+}
+
+@Composable
+fun ContentBlockersDisableModeCellSubtitle(modifier: Modifier) {
+ val textSize = dimensionResource(id = R.dimen.text_small).value
+
+ HtmlText(
+ htmlFormattedString =
+ textResource(
+ id = R.string.dns_content_blockers_subtitle,
+ stringResource(id = R.string.enable_custom_dns)
+ ),
+ textSize = textSize,
+ textColor = MullvadWhite60.toArgb(),
+ modifier = modifier
+ )
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SwitchComposeCell.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SwitchComposeCell.kt
new file mode 100644
index 0000000000..e41fed10ad
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/SwitchComposeCell.kt
@@ -0,0 +1,142 @@
+package net.mullvad.mullvadvpn.compose.cell
+
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.layout.wrapContentWidth
+import androidx.compose.material.Icon
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.alpha
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.res.dimensionResource
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import net.mullvad.mullvadvpn.R
+import net.mullvad.mullvadvpn.compose.component.CellSwitch
+import net.mullvad.mullvadvpn.compose.component.HtmlText
+import net.mullvad.mullvadvpn.compose.component.textResource
+import net.mullvad.mullvadvpn.compose.theme.AlphaActive
+import net.mullvad.mullvadvpn.compose.theme.AlphaInactive
+import net.mullvad.mullvadvpn.compose.theme.MullvadBlue
+import net.mullvad.mullvadvpn.compose.theme.MullvadWhite
+import net.mullvad.mullvadvpn.compose.theme.MullvadWhite60
+
+@Preview
+@Composable
+private fun PreviewSwitchComposeCell() {
+ SwitchComposeCell(
+ title = "Checkbox Title",
+ isEnabled = true,
+ isToggled = true,
+ onCellClicked = {},
+ onInfoClicked = {}
+ )
+}
+
+@Composable
+fun SwitchComposeCell(
+ title: String,
+ isToggled: Boolean,
+ isEnabled: Boolean = true,
+ background: Color = MullvadBlue,
+ onCellClicked: (Boolean) -> Unit = {},
+ onInfoClicked: (() -> Unit)? = null
+) {
+ val alpha = if (isEnabled) AlphaActive else AlphaInactive
+ val titleModifier = Modifier.alpha(alpha)
+ val bodyViewModifier = Modifier.alpha(alpha)
+ val subtitleModifier = Modifier
+
+ BaseCell(
+ title = { SwitchCellTitle(title = title, modifier = titleModifier) },
+ isRowEnabled = isEnabled,
+ bodyView = {
+ SwitchCellView(
+ onSwitchClicked = null,
+ isEnabled = isEnabled,
+ isToggled = isToggled,
+ modifier = bodyViewModifier,
+ onInfoClicked = onInfoClicked
+ )
+ },
+ background = background,
+ onCellClicked = { onCellClicked(!isToggled) },
+ subtitleModifier = subtitleModifier
+ )
+}
+
+@Composable
+fun SwitchCellTitle(title: String, modifier: Modifier) {
+ val textSize = dimensionResource(id = R.dimen.text_medium_plus).value.sp
+ Text(
+ text = title,
+ textAlign = TextAlign.Center,
+ fontWeight = FontWeight.Bold,
+ fontSize = textSize,
+ color = MullvadWhite,
+ modifier = modifier.wrapContentWidth(align = Alignment.End).wrapContentHeight()
+ )
+}
+
+@Composable
+fun SwitchCellView(
+ isEnabled: Boolean,
+ isToggled: Boolean,
+ modifier: Modifier,
+ onSwitchClicked: ((Boolean) -> Unit)? = null,
+ onInfoClicked: (() -> Unit)? = null
+) {
+ val horizontalPadding = dimensionResource(id = R.dimen.medium_padding)
+ val verticalPadding = 13.dp
+ Row(
+ modifier = modifier.wrapContentWidth().wrapContentHeight(),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ if (onInfoClicked != null) {
+ Icon(
+ modifier =
+ Modifier.clickable { onInfoClicked() }
+ .padding(
+ start = horizontalPadding,
+ end = horizontalPadding,
+ top = verticalPadding,
+ bottom = verticalPadding,
+ )
+ .align(Alignment.CenterVertically),
+ painter = painterResource(id = R.drawable.icon_info),
+ contentDescription = null,
+ tint = MullvadWhite
+ )
+ }
+
+ CellSwitch(isChecked = isToggled, isEnabled = isEnabled, onCheckedChange = onSwitchClicked)
+ }
+}
+
+@Composable
+fun CustomDnsCellSubtitle(isCellClickable: Boolean, modifier: Modifier) {
+ val textSize = dimensionResource(id = R.dimen.text_small).value
+
+ HtmlText(
+ htmlFormattedString =
+ textResource(
+ if (isCellClickable) {
+ R.string.custom_dns_footer
+ } else {
+ R.string.custom_dns_disable_mode_subtitle
+ }
+ ),
+ textSize = textSize,
+ textColor = MullvadWhite60.toArgb(),
+ modifier = modifier
+ )
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/Chevron.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/Chevron.kt
new file mode 100644
index 0000000000..8d458c7077
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/Chevron.kt
@@ -0,0 +1,36 @@
+package net.mullvad.mullvadvpn.compose.component
+
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.LinearEasing
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.rotate
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.unit.dp
+import net.mullvad.mullvadvpn.R
+
+@Composable
+fun ChevronView(isExpanded: Boolean) {
+ val resourceId = R.drawable.icon_chevron
+ val rotation = remember { Animatable(90f) }
+
+ LaunchedEffect(isExpanded) {
+ rotation.animateTo(
+ targetValue = 90f + if (isExpanded) 0f else 180f,
+ animationSpec = tween(100, easing = LinearEasing)
+ )
+ }
+
+ Image(
+ painterResource(id = resourceId),
+ contentDescription = null,
+ modifier = Modifier.size(30.dp).rotate(rotation.value),
+ )
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/HtmlText.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/HtmlText.kt
index b22390cfa8..2042c04278 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/HtmlText.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/HtmlText.kt
@@ -4,15 +4,25 @@ import android.util.TypedValue
import android.widget.TextView
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.text.HtmlCompat
@Composable
-fun HtmlText(htmlFormattedString: String, textSize: Float, modifier: Modifier = Modifier) {
+fun HtmlText(
+ htmlFormattedString: String,
+ textSize: Float,
+ modifier: Modifier = Modifier,
+ textColor: Int = Color.White.toArgb(),
+) {
AndroidView(
modifier = modifier,
factory = { context ->
- TextView(context).apply { setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize) }
+ TextView(context).apply {
+ setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize)
+ setTextColor(textColor)
+ }
},
update = {
it.text = HtmlCompat.fromHtml(htmlFormattedString, HtmlCompat.FROM_HTML_MODE_COMPACT)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/Switch.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/Switch.kt
index 1b1117afb9..2c0adcf4cf 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/Switch.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/Switch.kt
@@ -3,6 +3,7 @@ package net.mullvad.mullvadvpn.compose.component
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.gestures.detectTapGestures
+import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
@@ -20,6 +21,8 @@ import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
+import net.mullvad.mullvadvpn.compose.theme.AlphaActive
+import net.mullvad.mullvadvpn.compose.theme.AlphaInactive
import net.mullvad.mullvadvpn.compose.theme.MullvadGreen
import net.mullvad.mullvadvpn.compose.theme.MullvadRed
import net.mullvad.mullvadvpn.compose.theme.MullvadWhite
@@ -27,7 +30,10 @@ import net.mullvad.mullvadvpn.compose.theme.MullvadWhite
@Preview
@Composable
private fun PreviewSwitch() {
- CellSwitch(isChecked = false, onCheckedChange = null)
+ Column {
+ CellSwitch(isChecked = true, onCheckedChange = null)
+ CellSwitch(isChecked = false, onCheckedChange = null, isEnabled = false)
+ }
}
@Composable
@@ -36,6 +42,7 @@ fun CellSwitch(
onCheckedChange: ((Boolean) -> Unit)?,
modifier: Modifier = Modifier,
scale: Float = 1f,
+ isEnabled: Boolean = true,
thumbCheckedTrackColor: Color = MullvadGreen,
thumbUncheckedTrackColor: Color = MullvadRed,
thumbColor: Color = MullvadWhite
@@ -66,7 +73,7 @@ fun CellSwitch(
.size(width = width, height = height)
.scale(scale = scale)
.pointerInput(Unit) {
- if (onCheckedChange != null) {
+ if (onCheckedChange != null && isEnabled) {
detectTapGestures(onTap = { onCheckedChange(!isChecked) })
}
}
@@ -74,20 +81,26 @@ fun CellSwitch(
// Track
drawRoundRect(
color = thumbColor,
+ alpha = if (isEnabled) AlphaActive else AlphaInactive,
cornerRadius = CornerRadius(x = 15.dp.toPx(), y = 15.dp.toPx()),
style =
Stroke(
width = 2.dp.toPx(),
miter = 6.dp.toPx(),
cap = StrokeCap.Square,
- ),
+ )
)
// Thumb
drawCircle(
color = if (isChecked) thumbCheckedTrackColor else thumbUncheckedTrackColor,
+ alpha = if (isEnabled) AlphaActive else AlphaInactive,
radius = thumbRadius.toPx(),
- center = Offset(x = animatePosition.value, y = size.height / 2)
+ center =
+ Offset(
+ x = animatePosition.value,
+ y = size.height / 2,
+ )
)
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ContentBlockersInfoDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ContentBlockersInfoDialog.kt
new file mode 100644
index 0000000000..652c67e66e
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ContentBlockersInfoDialog.kt
@@ -0,0 +1,14 @@
+package net.mullvad.mullvadvpn.compose.dialog
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.res.stringResource
+import net.mullvad.mullvadvpn.R
+
+@Composable
+fun ContentBlockersInfoDialog(onDismiss: () -> Unit) {
+ InfoDialog(
+ message = stringResource(id = R.string.dns_content_blockers_info),
+ additionalInfo = stringResource(id = R.string.dns_content_blockers_warning),
+ onDismiss = onDismiss
+ )
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/InfoDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/InfoDialog.kt
new file mode 100644
index 0000000000..1c9870b50f
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/InfoDialog.kt
@@ -0,0 +1,111 @@
+package net.mullvad.mullvadvpn.compose.dialog
+
+import androidx.compose.foundation.layout.Column
+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.wrapContentHeight
+import androidx.compose.material.AlertDialog
+import androidx.compose.material.Button
+import androidx.compose.material.ButtonDefaults
+import androidx.compose.material.Icon
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.res.dimensionResource
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.font.FontStyle
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.compose.ui.window.DialogProperties
+import net.mullvad.mullvadvpn.R
+import net.mullvad.mullvadvpn.compose.theme.MullvadWhite
+
+@Preview
+@Composable
+private fun PreviewChangelogDialogWithTwoLongItems() {
+ val longPreviewText =
+ "This is a sample changelog item of a Compose Preview visualization. " +
+ "The purpose of this specific sample text is to visualize a long text that will " +
+ "result in multiple lines in the changelog dialog."
+
+ InfoDialog(
+ message = longPreviewText,
+ additionalInfo = longPreviewText,
+ onDismiss = {},
+ )
+}
+
+@Composable
+fun InfoDialog(message: String, additionalInfo: String? = null, onDismiss: () -> Unit) {
+ val verticalSpacing = 24.dp
+ val iconHeight = 44.dp
+ AlertDialog(
+ onDismissRequest = { onDismiss() },
+ title = {
+ Icon(
+ modifier = Modifier.fillMaxWidth().height(iconHeight),
+ painter = painterResource(id = R.drawable.icon_info),
+ contentDescription = "",
+ tint = MullvadWhite,
+ )
+ },
+ text = {
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
+ modifier = Modifier.padding(top = verticalSpacing),
+ ) {
+ Text(
+ text = message,
+ color = colorResource(id = R.color.white),
+ fontSize = dimensionResource(id = R.dimen.text_small).value.sp,
+ fontStyle = FontStyle.Normal,
+ textAlign = TextAlign.Start,
+ modifier = Modifier.padding(bottom = verticalSpacing).fillMaxWidth()
+ )
+ if (additionalInfo != null) {
+ Text(
+ text = additionalInfo,
+ color = colorResource(id = R.color.white),
+ fontSize = dimensionResource(id = R.dimen.text_small).value.sp,
+ fontStyle = FontStyle.Normal,
+ textAlign = TextAlign.Start,
+ modifier = Modifier.fillMaxWidth()
+ )
+ }
+ }
+ },
+ buttons = {
+ Button(
+ modifier =
+ Modifier.wrapContentHeight()
+ .padding(all = dimensionResource(id = R.dimen.medium_padding))
+ .defaultMinSize(minHeight = dimensionResource(id = R.dimen.button_height))
+ .fillMaxWidth(),
+ colors =
+ ButtonDefaults.buttonColors(
+ backgroundColor = colorResource(id = R.color.blue),
+ contentColor = colorResource(id = R.color.white),
+ ),
+ onClick = { onDismiss() },
+ ) {
+ Text(
+ text = stringResource(R.string.changes_dialog_dismiss_button),
+ fontSize = dimensionResource(id = R.dimen.text_medium_plus).value.sp,
+ )
+ }
+ },
+ properties =
+ DialogProperties(
+ dismissOnClickOutside = true,
+ dismissOnBackPress = true,
+ ),
+ backgroundColor = colorResource(id = R.color.darkBlue),
+ )
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MalwareInfoDialog.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MalwareInfoDialog.kt
new file mode 100644
index 0000000000..985b63e5c5
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/MalwareInfoDialog.kt
@@ -0,0 +1,10 @@
+package net.mullvad.mullvadvpn.compose.dialog
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.res.stringResource
+import net.mullvad.mullvadvpn.R
+
+@Composable
+fun MalwareInfoDialog(onDismiss: () -> Unit) {
+ InfoDialog(message = stringResource(id = R.string.malware_info), onDismiss = onDismiss)
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/extensions/LazyListExtensions.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/extensions/LazyListExtensions.kt
new file mode 100644
index 0000000000..5fe6a6d509
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/extensions/LazyListExtensions.kt
@@ -0,0 +1,13 @@
+package net.mullvad.mullvadvpn.compose.extensions
+
+import androidx.compose.foundation.lazy.LazyItemScope
+import androidx.compose.foundation.lazy.LazyListScope
+import androidx.compose.material.Divider
+import androidx.compose.runtime.Composable
+
+inline fun LazyListScope.itemWithDivider(
+ crossinline itemContent: @Composable LazyItemScope.() -> Unit
+) = item {
+ itemContent()
+ Divider()
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingScreen.kt
index bd115447d6..110a20aa09 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AdvancedSettingScreen.kt
@@ -3,8 +3,10 @@ package net.mullvad.mullvadvpn.compose.screen
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Spacer
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.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
@@ -14,6 +16,10 @@ import androidx.compose.material.Divider
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@@ -25,16 +31,21 @@ import me.onebone.toolbar.ScrollStrategy
import me.onebone.toolbar.rememberCollapsingToolbarScaffoldState
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.compose.cell.BaseCell
+import net.mullvad.mullvadvpn.compose.cell.ContentBlockersDisableModeCellSubtitle
import net.mullvad.mullvadvpn.compose.cell.CustomDnsCellSubtitle
-import net.mullvad.mullvadvpn.compose.cell.CustomDnsComposeCell
import net.mullvad.mullvadvpn.compose.cell.DnsCell
+import net.mullvad.mullvadvpn.compose.cell.ExpandableComposeCell
import net.mullvad.mullvadvpn.compose.cell.MtuComposeCell
import net.mullvad.mullvadvpn.compose.cell.NavigationComposeCell
+import net.mullvad.mullvadvpn.compose.cell.SwitchComposeCell
import net.mullvad.mullvadvpn.compose.component.CollapsableAwareToolbarScaffold
import net.mullvad.mullvadvpn.compose.component.CollapsingTopBar
import net.mullvad.mullvadvpn.compose.component.drawVerticalScrollbar
+import net.mullvad.mullvadvpn.compose.dialog.ContentBlockersInfoDialog
import net.mullvad.mullvadvpn.compose.dialog.DnsDialog
+import net.mullvad.mullvadvpn.compose.dialog.MalwareInfoDialog
import net.mullvad.mullvadvpn.compose.dialog.MtuDialog
+import net.mullvad.mullvadvpn.compose.extensions.itemWithDivider
import net.mullvad.mullvadvpn.compose.state.AdvancedSettingsUiState
import net.mullvad.mullvadvpn.compose.theme.CollapsingToolbarTheme
import net.mullvad.mullvadvpn.compose.theme.MullvadBlue20
@@ -59,12 +70,20 @@ private fun PreviewAdvancedSettings() {
onCancelMtuDialogClicked = {},
onSplitTunnelingNavigationClick = {},
onToggleDnsClick = {},
+ onToggleBlockAds = {},
+ onToggleBlockTrackers = {},
+ onToggleBlockMalware = {},
+ onToggleBlockAdultContent = {},
+ onToggleBlockGambling = {},
onDnsClick = {},
onDnsInputChange = {},
onSaveDnsClick = {},
onRemoveDnsClick = {},
onCancelDnsDialogClick = {},
- onBackClick = {},
+ onContentsBlockersInfoClicked = {},
+ onMalwareInfoClicked = {},
+ onDismissInfoClicked = {},
+ onBackClick = {}
)
}
@@ -80,11 +99,19 @@ fun AdvancedSettingScreen(
onCancelMtuDialogClicked: () -> Unit = {},
onSplitTunnelingNavigationClick: () -> Unit = {},
onToggleDnsClick: (Boolean) -> Unit = {},
+ onToggleBlockAds: (Boolean) -> Unit = {},
+ onToggleBlockTrackers: (Boolean) -> Unit = {},
+ onToggleBlockMalware: (Boolean) -> Unit = {},
+ onToggleBlockAdultContent: (Boolean) -> Unit = {},
+ onToggleBlockGambling: (Boolean) -> Unit = {},
onDnsClick: (index: Int?) -> Unit = {},
onDnsInputChange: (String) -> Unit = {},
onSaveDnsClick: () -> Unit = {},
onRemoveDnsClick: () -> Unit = {},
onCancelDnsDialogClick: () -> Unit = {},
+ onContentsBlockersInfoClicked: () -> Unit = {},
+ onMalwareInfoClicked: () -> Unit = {},
+ onDismissInfoClicked: () -> Unit = {},
onBackClick: () -> Unit = {}
) {
val cellVerticalSpacing = dimensionResource(id = R.dimen.cell_label_vertical_padding)
@@ -107,18 +134,24 @@ fun AdvancedSettingScreen(
onIpAddressChanged = { onDnsInputChange(it) },
onAttemptToSave = { onSaveDnsClick() },
onRemove = { onRemoveDnsClick() },
- onDismiss = { onCancelDnsDialogClick() },
+ onDismiss = { onCancelDnsDialogClick() }
)
}
+ is AdvancedSettingsUiState.ContentBlockersInfoDialogUiState -> {
+ ContentBlockersInfoDialog(onDismissInfoClicked)
+ }
+ is AdvancedSettingsUiState.MalwareInfoDialogUiState -> {
+ MalwareInfoDialog(onDismissInfoClicked)
+ }
else -> {
// NOOP
}
}
val lazyListState = rememberLazyListState()
+ var expandContentBlockersState by remember { mutableStateOf(false) }
val biggerPadding = 54.dp
val topPadding = 6.dp
-
CollapsingToolbarTheme {
val state = rememberCollapsingToolbarScaffoldState()
val progress = state.toolbarState.progress
@@ -141,7 +174,7 @@ fun AdvancedSettingScreen(
title = stringResource(id = R.string.settings_advanced),
progress = progress,
modifier = scaffoldModifier,
- backTitle = stringResource(id = R.string.settings),
+ backTitle = stringResource(id = R.string.settings)
)
}
) {
@@ -155,20 +188,94 @@ fun AdvancedSettingScreen(
) {
item { MtuComposeCell(mtuValue = uiState.mtu, onEditMtu = { onMtuCellClick() }) }
- item {
+ itemWithDivider {
NavigationComposeCell(
title = stringResource(id = R.string.split_tunneling),
onClick = { onSplitTunnelingNavigationClick.invoke() }
)
- Divider()
+ }
+
+ itemWithDivider {
+ ExpandableComposeCell(
+ title = stringResource(R.string.dns_content_blockers_title),
+ isExpanded = !expandContentBlockersState,
+ isEnabled = !uiState.isCustomDnsEnabled,
+ onInfoClicked = { onContentsBlockersInfoClicked() },
+ onCellClicked = { expandContentBlockersState = !expandContentBlockersState }
+ )
+ }
+
+ if (expandContentBlockersState) {
+ itemWithDivider {
+ SwitchComposeCell(
+ title = stringResource(R.string.block_ads_title),
+ isToggled = uiState.contentBlockersOptions.blockAds,
+ isEnabled = !uiState.isCustomDnsEnabled,
+ onCellClicked = { onToggleBlockAds(it) },
+ background = MullvadBlue20
+ )
+ }
+ itemWithDivider {
+ SwitchComposeCell(
+ title = stringResource(R.string.block_trackers_title),
+ isToggled = uiState.contentBlockersOptions.blockTrackers,
+ isEnabled = !uiState.isCustomDnsEnabled,
+ onCellClicked = { onToggleBlockTrackers(it) },
+ background = MullvadBlue20
+ )
+ }
+ itemWithDivider {
+ SwitchComposeCell(
+ title = stringResource(R.string.block_malware_title),
+ isToggled = uiState.contentBlockersOptions.blockMalware,
+ isEnabled = !uiState.isCustomDnsEnabled,
+ onCellClicked = { onToggleBlockMalware(it) },
+ onInfoClicked = { onMalwareInfoClicked() },
+ background = MullvadBlue20
+ )
+ }
+ itemWithDivider {
+ SwitchComposeCell(
+ title = stringResource(R.string.block_gambling_title),
+ isToggled = uiState.contentBlockersOptions.blockGambling,
+ isEnabled = !uiState.isCustomDnsEnabled,
+ onCellClicked = { onToggleBlockGambling(it) },
+ background = MullvadBlue20
+ )
+ }
+ itemWithDivider {
+ SwitchComposeCell(
+ title = stringResource(R.string.block_adult_content_title),
+ isToggled = uiState.contentBlockersOptions.blockAdultContent,
+ isEnabled = !uiState.isCustomDnsEnabled,
+ onCellClicked = { onToggleBlockAdultContent(it) },
+ background = MullvadBlue20
+ )
+ }
+ }
+
+ if (uiState.isCustomDnsEnabled) {
+ item {
+ ContentBlockersDisableModeCellSubtitle(
+ Modifier.background(MullvadDarkBlue)
+ .padding(
+ start = cellHorizontalSpacing,
+ top = topPadding,
+ end = cellHorizontalSpacing,
+ bottom = cellVerticalSpacing,
+ )
+ )
+ }
}
item {
- CustomDnsComposeCell(
- checkboxDefaultState = uiState.isCustomDnsEnabled,
- onToggle = { newValue -> onToggleDnsClick(newValue) }
+ Spacer(modifier = Modifier.height(cellVerticalSpacing))
+ SwitchComposeCell(
+ title = stringResource(R.string.enable_custom_dns),
+ isToggled = uiState.isCustomDnsEnabled,
+ isEnabled = uiState.contentBlockersOptions.isAnyBlockerEnabled().not(),
+ onCellClicked = { newValue -> onToggleDnsClick(newValue) }
)
- Divider()
}
if (uiState.isCustomDnsEnabled) {
@@ -178,18 +285,18 @@ fun AdvancedSettingScreen(
isUnreachableLocalDnsWarningVisible =
item.isLocal && uiState.isAllowLanEnabled.not(),
onClick = { onDnsClick(index) },
- modifier = Modifier.animateItemPlacement(),
+ modifier = Modifier.animateItemPlacement()
)
Divider()
}
- item {
+ itemWithDivider {
BaseCell(
onCellClicked = { onDnsClick(null) },
title = {
Text(
text = stringResource(id = R.string.add_a_server),
- color = Color.White
+ color = Color.White,
)
},
bodyView = {},
@@ -197,19 +304,21 @@ fun AdvancedSettingScreen(
background = MullvadBlue20,
startPadding = biggerPadding
)
- Divider()
}
}
item {
CustomDnsCellSubtitle(
- Modifier.background(MullvadDarkBlue)
- .padding(
- start = cellHorizontalSpacing,
- top = topPadding,
- end = cellHorizontalSpacing,
- bottom = cellVerticalSpacing
- )
+ isCellClickable =
+ uiState.contentBlockersOptions.isAnyBlockerEnabled().not(),
+ modifier =
+ Modifier.background(MullvadDarkBlue)
+ .padding(
+ start = cellHorizontalSpacing,
+ top = topPadding,
+ end = cellHorizontalSpacing,
+ bottom = cellVerticalSpacing
+ )
)
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AdvancedSettingsUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AdvancedSettingsUiState.kt
index 59c3551eb3..71b608b51b 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AdvancedSettingsUiState.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/AdvancedSettingsUiState.kt
@@ -1,5 +1,6 @@
package net.mullvad.mullvadvpn.compose.state
+import net.mullvad.mullvadvpn.model.DefaultDnsOptions
import net.mullvad.mullvadvpn.viewmodel.CustomDnsItem
import net.mullvad.mullvadvpn.viewmodel.StagedDns
@@ -7,13 +8,15 @@ sealed interface AdvancedSettingsUiState {
val mtu: String
val isCustomDnsEnabled: Boolean
val customDnsItems: List<CustomDnsItem>
+ val contentBlockersOptions: DefaultDnsOptions
val isAllowLanEnabled: Boolean
data class DefaultUiState(
override val mtu: String = "",
override val isCustomDnsEnabled: Boolean = false,
override val isAllowLanEnabled: Boolean = false,
- override val customDnsItems: List<CustomDnsItem> = listOf()
+ override val customDnsItems: List<CustomDnsItem> = listOf(),
+ override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions()
) : AdvancedSettingsUiState
data class MtuDialogUiState(
@@ -21,6 +24,7 @@ sealed interface AdvancedSettingsUiState {
override val isCustomDnsEnabled: Boolean = false,
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
+ override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
val mtuEditValue: String
) : AdvancedSettingsUiState
@@ -29,6 +33,23 @@ sealed interface AdvancedSettingsUiState {
override val isCustomDnsEnabled: Boolean = false,
override val isAllowLanEnabled: Boolean = false,
override val customDnsItems: List<CustomDnsItem> = listOf(),
- val stagedDns: StagedDns,
+ override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions(),
+ val stagedDns: StagedDns
+ ) : AdvancedSettingsUiState
+
+ data class ContentBlockersInfoDialogUiState(
+ override val mtu: String = "",
+ override val isCustomDnsEnabled: Boolean = false,
+ override val isAllowLanEnabled: Boolean = false,
+ override val customDnsItems: List<CustomDnsItem> = listOf(),
+ override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions()
+ ) : AdvancedSettingsUiState
+
+ data class MalwareInfoDialogUiState(
+ override val mtu: String = "",
+ override val isCustomDnsEnabled: Boolean = false,
+ override val isAllowLanEnabled: Boolean = false,
+ override val customDnsItems: List<CustomDnsItem> = listOf(),
+ override val contentBlockersOptions: DefaultDnsOptions = DefaultDnsOptions()
) : AdvancedSettingsUiState
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/theme/Color.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/theme/Color.kt
index 2c542951ab..503fc4dd02 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/theme/Color.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/theme/Color.kt
@@ -17,3 +17,6 @@ val MullvadWhite10 = Color(0x1AFFFFFF)
val MullvadWhite20 = Color(0x33FFFFFF)
val MullvadWhite40 = Color(0x66FFFFFF)
val MullvadWhite60 = Color(0x99FFFFFF)
+
+const val AlphaActive = 1f
+const val AlphaInactive = 0.2f
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/model/DefaultDnsOptions.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/model/DefaultDnsOptions.kt
index 6b24f363cc..eb22c93994 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/model/DefaultDnsOptions.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/model/DefaultDnsOptions.kt
@@ -10,4 +10,8 @@ data class DefaultDnsOptions(
val blockMalware: Boolean = false,
val blockAdultContent: Boolean = false,
val blockGambling: Boolean = false,
-) : Parcelable
+) : Parcelable {
+ fun isAnyBlockerEnabled(): Boolean {
+ return blockAds || blockTrackers || blockMalware || blockAdultContent || blockGambling
+ }
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt
index 6eef99ecce..1e00efc3c5 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/SettingsRepository.kt
@@ -32,7 +32,11 @@ class SettingsRepository(
.onStart { serviceConnectionManager.settingsListener()?.settingsNotifier?.latestEvent }
.stateIn(CoroutineScope(dispatcher), SharingStarted.WhileSubscribed(), null)
- fun setDnsOptions(isCustomDnsEnabled: Boolean, dnsList: List<InetAddress>) {
+ fun setDnsOptions(
+ isCustomDnsEnabled: Boolean,
+ dnsList: List<InetAddress>,
+ contentBlockersOptions: DefaultDnsOptions
+ ) {
serviceConnectionManager
.customDns()
?.setDnsOptions(
@@ -40,7 +44,7 @@ class SettingsRepository(
DnsOptions(
state = if (isCustomDnsEnabled) DnsState.Custom else DnsState.Default,
customOptions = CustomDnsOptions(ArrayList(dnsList)),
- defaultOptions = DefaultDnsOptions()
+ defaultOptions = contentBlockersOptions
)
)
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AdvancedFragment.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AdvancedFragment.kt
index 018aa2fc6d..6eee351e78 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AdvancedFragment.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/fragment/AdvancedFragment.kt
@@ -33,11 +33,19 @@ class AdvancedFragment : BaseFragment() {
onCancelMtuDialogClicked = vm::onCancelDialogClick,
onSplitTunnelingNavigationClick = ::openSplitTunnelingFragment,
onToggleDnsClick = vm::onToggleDnsClick,
+ onToggleBlockAds = vm::onToggleBlockAds,
+ onToggleBlockTrackers = vm::onToggleBlockTrackers,
+ onToggleBlockMalware = vm::onToggleBlockMalware,
+ onToggleBlockAdultContent = vm::onToggleBlockAdultContent,
+ onToggleBlockGambling = vm::onToggleBlockGambling,
onDnsClick = vm::onDnsClick,
onDnsInputChange = vm::onDnsInputChange,
onSaveDnsClick = vm::onSaveDnsClick,
onRemoveDnsClick = vm::onRemoveDnsClick,
onCancelDnsDialogClick = vm::onCancelDialogClick,
+ onContentsBlockersInfoClicked = vm::onContentsBlockerInfoClick,
+ onMalwareInfoClicked = vm::onMalwareInfoClick,
+ onDismissInfoClicked = vm::onDismissInfoClick,
onBackClick = { activity?.onBackPressed() }
)
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModel.kt
index c29573e819..17679b6e29 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModel.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModel.kt
@@ -14,6 +14,7 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import net.mullvad.mullvadvpn.compose.state.AdvancedSettingsUiState
+import net.mullvad.mullvadvpn.model.DefaultDnsOptions
import net.mullvad.mullvadvpn.model.DnsState
import net.mullvad.mullvadvpn.model.Settings
import net.mullvad.mullvadvpn.repository.SettingsRepository
@@ -30,13 +31,15 @@ class AdvancedSettingsViewModel(
MutableStateFlow<AdvancedSettingsDialogState>(AdvancedSettingsDialogState.NoDialog)
private val vmState =
- combine(repository.settingsUpdates, dialogState) { settings, interaction ->
+ combine(repository.settingsUpdates, dialogState) { settings, dialogState ->
AdvancedSettingsViewModelState(
mtuValue = settings?.mtuString() ?: "",
isCustomDnsEnabled = settings?.isCustomDnsEnabled() ?: false,
customDnsList = settings?.addresses()?.asStringAddressList() ?: listOf(),
+ contentBlockersOptions = settings?.contentBlockersSettings()
+ ?: DefaultDnsOptions(),
isAllowLanEnabled = settings?.allowLan ?: false,
- dialogState = interaction
+ dialogState = dialogState
)
}
.stateIn(
@@ -83,6 +86,18 @@ class AdvancedSettingsViewModel(
hideDialog()
}
+ fun onContentsBlockerInfoClick() {
+ dialogState.update { AdvancedSettingsDialogState.ContentBlockersInfoDialog }
+ }
+
+ fun onMalwareInfoClick() {
+ dialogState.update { AdvancedSettingsDialogState.MalwareInfoDialog }
+ }
+
+ fun onDismissInfoClick() {
+ hideDialog()
+ }
+
fun onDnsClick(index: Int? = null) {
val stagedDns =
if (index == null) {
@@ -165,7 +180,11 @@ class AdvancedSettingsViewModel(
}
}
- repository.setDnsOptions(isCustomDnsEnabled = true, dnsList = updatedList)
+ repository.setDnsOptions(
+ isCustomDnsEnabled = true,
+ dnsList = updatedList,
+ contentBlockersOptions = vmState.value.contentBlockersOptions
+ )
hideDialog()
}
@@ -174,10 +193,41 @@ class AdvancedSettingsViewModel(
viewModelScope.launch(dispatcher) {
repository.setDnsOptions(
isEnabled,
- dnsList = vmState.value.customDnsList.map { it.address }.asInetAddressList()
+ dnsList = vmState.value.customDnsList.map { it.address }.asInetAddressList(),
+ contentBlockersOptions = vmState.value.contentBlockersOptions
)
}
+ fun onToggleBlockAds(isEnabled: Boolean) {
+ updateDefaultDnsOptionsViaRepository(
+ vmState.value.contentBlockersOptions.copy(blockAds = isEnabled)
+ )
+ }
+
+ fun onToggleBlockTrackers(isEnabled: Boolean) {
+ updateDefaultDnsOptionsViaRepository(
+ vmState.value.contentBlockersOptions.copy(blockTrackers = isEnabled)
+ )
+ }
+
+ fun onToggleBlockMalware(isEnabled: Boolean) {
+ updateDefaultDnsOptionsViaRepository(
+ vmState.value.contentBlockersOptions.copy(blockMalware = isEnabled)
+ )
+ }
+
+ fun onToggleBlockAdultContent(isEnabled: Boolean) {
+ updateDefaultDnsOptionsViaRepository(
+ vmState.value.contentBlockersOptions.copy(blockAdultContent = isEnabled)
+ )
+ }
+
+ fun onToggleBlockGambling(isEnabled: Boolean) {
+ updateDefaultDnsOptionsViaRepository(
+ vmState.value.contentBlockersOptions.copy(blockGambling = isEnabled)
+ )
+ }
+
fun onRemoveDnsClick() =
viewModelScope.launch(dispatcher) {
val dialog =
@@ -192,12 +242,21 @@ class AdvancedSettingsViewModel(
repository.setDnsOptions(
isCustomDnsEnabled = vmState.value.isCustomDnsEnabled && updatedList.isNotEmpty(),
- dnsList = updatedList
+ dnsList = updatedList,
+ contentBlockersOptions = vmState.value.contentBlockersOptions
)
-
hideDialog()
}
+ private fun updateDefaultDnsOptionsViaRepository(contentBlockersOption: DefaultDnsOptions) =
+ viewModelScope.launch(dispatcher) {
+ repository.setDnsOptions(
+ isCustomDnsEnabled = vmState.value.isCustomDnsEnabled,
+ dnsList = vmState.value.customDnsList.map { it.address }.asInetAddressList(),
+ contentBlockersOptions = contentBlockersOption
+ )
+ }
+
private fun hideDialog() {
dialogState.update { AdvancedSettingsDialogState.NoDialog }
}
@@ -229,6 +288,8 @@ class AdvancedSettingsViewModel(
private fun Settings.addresses() = tunnelOptions.dnsOptions.customOptions.addresses
+ private fun Settings.contentBlockersSettings() = tunnelOptions.dnsOptions.defaultOptions
+
private fun String.isValidIp(): Boolean {
return inetAddressValidator.isValid(this)
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModelState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModelState.kt
index 002d478b8f..109e518ad5 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModelState.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AdvancedSettingsViewModelState.kt
@@ -1,12 +1,14 @@
package net.mullvad.mullvadvpn.viewmodel
import net.mullvad.mullvadvpn.compose.state.AdvancedSettingsUiState
+import net.mullvad.mullvadvpn.model.DefaultDnsOptions
data class AdvancedSettingsViewModelState(
val mtuValue: String,
val isCustomDnsEnabled: Boolean,
val isAllowLanEnabled: Boolean,
val customDnsList: List<CustomDnsItem>,
+ val contentBlockersOptions: DefaultDnsOptions,
val dialogState: AdvancedSettingsDialogState
) {
fun toUiState(): AdvancedSettingsUiState {
@@ -17,7 +19,8 @@ data class AdvancedSettingsViewModelState(
isCustomDnsEnabled = isCustomDnsEnabled,
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
- mtuEditValue = dialogState.mtuEditValue,
+ contentBlockersOptions = contentBlockersOptions,
+ mtuEditValue = dialogState.mtuEditValue
)
is AdvancedSettingsDialogState.DnsDialog ->
AdvancedSettingsUiState.DnsDialogUiState(
@@ -25,7 +28,24 @@ data class AdvancedSettingsViewModelState(
isCustomDnsEnabled = isCustomDnsEnabled,
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
- stagedDns = dialogState.stagedDns,
+ contentBlockersOptions = contentBlockersOptions,
+ stagedDns = dialogState.stagedDns
+ )
+ is AdvancedSettingsDialogState.ContentBlockersInfoDialog ->
+ AdvancedSettingsUiState.ContentBlockersInfoDialogUiState(
+ mtu = mtuValue,
+ isCustomDnsEnabled = isCustomDnsEnabled,
+ isAllowLanEnabled = isAllowLanEnabled,
+ customDnsItems = customDnsList,
+ contentBlockersOptions = contentBlockersOptions
+ )
+ is AdvancedSettingsDialogState.MalwareInfoDialog ->
+ AdvancedSettingsUiState.MalwareInfoDialogUiState(
+ mtu = mtuValue,
+ isCustomDnsEnabled = isCustomDnsEnabled,
+ isAllowLanEnabled = isAllowLanEnabled,
+ customDnsItems = customDnsList,
+ contentBlockersOptions = contentBlockersOptions
)
else ->
AdvancedSettingsUiState.DefaultUiState(
@@ -33,6 +53,7 @@ data class AdvancedSettingsViewModelState(
isCustomDnsEnabled = isCustomDnsEnabled,
isAllowLanEnabled = isAllowLanEnabled,
customDnsItems = customDnsList,
+ contentBlockersOptions = contentBlockersOptions
)
}
}
@@ -45,6 +66,7 @@ data class AdvancedSettingsViewModelState(
mtuValue = EMPTY_STRING,
isCustomDnsEnabled = false,
customDnsList = listOf(),
+ contentBlockersOptions = DefaultDnsOptions(),
isAllowLanEnabled = false,
dialogState = AdvancedSettingsDialogState.NoDialog
)
@@ -57,6 +79,10 @@ sealed class AdvancedSettingsDialogState {
data class MtuDialog(val mtuEditValue: String) : AdvancedSettingsDialogState()
data class DnsDialog(val stagedDns: StagedDns) : AdvancedSettingsDialogState()
+
+ object ContentBlockersInfoDialog : AdvancedSettingsDialogState()
+
+ object MalwareInfoDialog : AdvancedSettingsDialogState()
}
sealed interface StagedDns {
diff --git a/android/app/src/main/res/drawable/icon_info.xml b/android/app/src/main/res/drawable/icon_info.xml
new file mode 100644
index 0000000000..98f45776a3
--- /dev/null
+++ b/android/app/src/main/res/drawable/icon_info.xml
@@ -0,0 +1,8 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:pathData="M12,24A12,12 0,0 1,3.515 3.515a12,12 0,1 1,16.97 16.97A11.922,11.922 0,0 1,12 24zM12,9a1.5,1.5 0,0 0,-1.5 1.5L10.5,18a1.5,1.5 0,1 0,3 0v-7.5A1.5,1.5 0,0 0,12 9zM12,4.5A1.5,1.5 0,1 0,13.5 6,1.5 1.5,0 0,0 12,4.5z"
+ android:fillColor="#294d73" />
+</vector>
diff --git a/android/app/src/main/res/values-da/strings.xml b/android/app/src/main/res/values-da/strings.xml
index c6d1953dbe..64683a5c26 100644
--- a/android/app/src/main/res/values-da/strings.xml
+++ b/android/app/src/main/res/values-da/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">Auto-tilslutning</string>
<string name="auto_connect_footer">Opret automatisk forbindelse til en server, når appen starter.</string>
<string name="back">Tilbage</string>
+ <string name="block_ads_title">Annoncer</string>
+ <string name="block_adult_content_title">Voksenindhold</string>
+ <string name="block_gambling_title">Hasardspil</string>
+ <string name="block_malware_title">Malware</string>
+ <string name="block_trackers_title">Trackere</string>
<string name="blocked_connection">FORBINDELSE BLOKERET</string>
<string name="blocking_all_connections">Blokerer alle forbindelser</string>
<string name="blocking_internet">Blokerer internettet</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">Opretter konto...</string>
<string name="creating_secure_connection">OPRETTER SIKKER FORBINDELSE</string>
<string name="critical_error">Kritisk fejl (som kræver din opmærksomhed)</string>
+ <string name="custom_dns_disable_mode_subtitle">Deaktiver alle &lt;b&gt;DNS-indholdsblokkere&lt;/b&gt; ovenfor for at aktivere denne indstilling.</string>
<string name="custom_dns_footer">Aktiver for at tilføje mindst én DNS-server.</string>
<string name="custom_dns_hint">Indtast IP</string>
<string name="custom_tunnel_host_resolution_error">Kunne ikke fortolke værtsnavnet på den tilpassede server</string>
@@ -51,6 +57,10 @@
<string name="disconnect">Afbryd forbindelse</string>
<string name="disconnecting">Afbryder</string>
<string name="dismiss">Afvis</string>
+ <string name="dns_content_blockers_info">Når denne funktion er aktiveret, forhindrer den enheden i at kontakte bestemte domæner eller websteder, der er kendt for at distribuere annoncer, malware, trackere og lignende.</string>
+ <string name="dns_content_blockers_subtitle">Deaktiver &lt;b&gt;%1$s&lt;/b&gt; nedenfor for at aktivere disse indstillinger.</string>
+ <string name="dns_content_blockers_title">DNS-indholdsblokkere</string>
+ <string name="dns_content_blockers_warning">Dette kan forårsage problemer på visse websteder, tjenester og programmer.</string>
<string name="dont_have_an_account">Har du ikke noget kontonummer?</string>
<string name="edit_message">Rediger meddelelse</string>
<string name="enable">Aktiver</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">Ugyldigt kontonummer</string>
<string name="login_fail_title">Login mislykkedes</string>
<string name="login_title">Log ind</string>
+ <string name="malware_info">Advarsel: Malware-blokkeren er ikke antivirus og bør ikke behandles som sådan. Dette er blot et ekstra lag af beskyttelse.</string>
<string name="max_devices_confirm_removal_description">Er du sikker på, at du vil logge &lt;b&gt;%1$s&lt;/b&gt; ud?</string>
<string name="max_devices_resolved_description">Du kan nu fortsætte med at logge ind på denne enhed.</string>
<string name="max_devices_resolved_title">Super!</string>
diff --git a/android/app/src/main/res/values-de/strings.xml b/android/app/src/main/res/values-de/strings.xml
index 76a1425fb1..903121b42e 100644
--- a/android/app/src/main/res/values-de/strings.xml
+++ b/android/app/src/main/res/values-de/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">Automatische Verbindung</string>
<string name="auto_connect_footer">Stellt automatisch eine Verbindung zum Server her, wenn die App startet.</string>
<string name="back">Zurück</string>
+ <string name="block_ads_title">Werbung</string>
+ <string name="block_adult_content_title">Inhalte für Erwachsene</string>
+ <string name="block_gambling_title">Glücksspiel</string>
+ <string name="block_malware_title">Malware</string>
+ <string name="block_trackers_title">Tracker</string>
<string name="blocked_connection">GESPERRTE VERBINDUNG</string>
<string name="blocking_all_connections">Alle Verbindungen werden blockiert</string>
<string name="blocking_internet">Internet wird gesperrt</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">Konto wird erstellt ...</string>
<string name="creating_secure_connection">SICHERE VERBINDUNG WIRD ERSTELLT</string>
<string name="critical_error">Kritischer Fehler (Ihre Aufmerksamkeit ist erforderlich)</string>
+ <string name="custom_dns_disable_mode_subtitle">Deaktivieren Sie oben alle &lt;b&gt;DNS-Inhaltssperren&lt;/b&gt;, um diese Einstellung zu aktivieren.</string>
<string name="custom_dns_footer">Aktivieren, um mindestens einen DNS-Server hinzuzufügen.</string>
<string name="custom_dns_hint">IP eingeben</string>
<string name="custom_tunnel_host_resolution_error">Der Hostname des benutzerdefinierten Servers konnte nicht aufgelöst werden</string>
@@ -51,6 +57,10 @@
<string name="disconnect">Verbindung trennen</string>
<string name="disconnecting">Verbindung wird getrennt</string>
<string name="dismiss">Ausblenden</string>
+ <string name="dns_content_blockers_info">Wenn diese Funktion aktiviert ist, wird das Gerät daran gehindert, bestimmte Domains oder Websites zu kontaktieren, die für die Verbreitung von Werbung, Malware, Trackern und mehr bekannt sind.</string>
+ <string name="dns_content_blockers_subtitle">Deaktivieren Sie unten &lt;b&gt;%1$s&lt;/b&gt;, um diese Einstellungen zu aktivieren.</string>
+ <string name="dns_content_blockers_title">DNS-Inhaltssperren</string>
+ <string name="dns_content_blockers_warning">Dies kann bei bestimmten Websites, Diensten und Programmen zu Problemen führen.</string>
<string name="dont_have_an_account">Sie haben keine Kontonummer?</string>
<string name="edit_message">Nachricht bearbeiten</string>
<string name="enable">Aktivieren</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">Ungültige Kontonummer</string>
<string name="login_fail_title">Anmeldung fehlgeschlagen</string>
<string name="login_title">Anmelden</string>
+ <string name="malware_info">Der Malware-Blocker ist kein Antivirusprogramm und sollte auch nicht als solches behandelt werden. Es dient lediglich als zusätzliche Schutzschicht.</string>
<string name="max_devices_confirm_removal_description">Möchten Sie &lt;b&gt;%1$s&lt;/b&gt; wirklich abmelden?</string>
<string name="max_devices_resolved_description">Sie können jetzt mit der Anmeldung auf diesem Gerät fortfahren.</string>
<string name="max_devices_resolved_title">Super!</string>
diff --git a/android/app/src/main/res/values-es/strings.xml b/android/app/src/main/res/values-es/strings.xml
index 8095b85289..7e5989dea0 100644
--- a/android/app/src/main/res/values-es/strings.xml
+++ b/android/app/src/main/res/values-es/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">Conexión automática</string>
<string name="auto_connect_footer">Al iniciarse la aplicación, se conecta automáticamente a un servidor.</string>
<string name="back">Volver</string>
+ <string name="block_ads_title">Anuncios</string>
+ <string name="block_adult_content_title">Contenido para adultos</string>
+ <string name="block_gambling_title">Juegos de azar</string>
+ <string name="block_malware_title">Malware</string>
+ <string name="block_trackers_title">Rastreadores</string>
<string name="blocked_connection">CONEXIÓN BLOQUEADA</string>
<string name="blocking_all_connections">Bloqueando todas las conexiones</string>
<string name="blocking_internet">Internet bloqueado</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">Creando cuenta…</string>
<string name="creating_secure_connection">CREANDO CONEXIÓN SEGURA</string>
<string name="critical_error">Error crítico (precisa su atención)</string>
+ <string name="custom_dns_disable_mode_subtitle">Deshabilite todos los &lt;b&gt;bloqueadores de contenido DNS&lt;/b&gt; de arriba para activar este ajuste.</string>
<string name="custom_dns_footer">Active esta opción para agregar como mínimo un servidor DNS.</string>
<string name="custom_dns_hint">Escriba la IP</string>
<string name="custom_tunnel_host_resolution_error">No se puede resolver el nombre de host del servidor personalizado</string>
@@ -51,6 +57,10 @@
<string name="disconnect">Desconectar</string>
<string name="disconnecting">Desconectando</string>
<string name="dismiss">Descartar</string>
+ <string name="dns_content_blockers_info">Al activar esta opción se evita que el dispositivo contacte con determinados dominios o sitios web que se sabe que distribuyen anuncios, malware, rastreadores y más.</string>
+ <string name="dns_content_blockers_subtitle">Deshabilite &lt;b&gt;%1$s&lt;/b&gt; abajo para activar estos ajustes.</string>
+ <string name="dns_content_blockers_title">Bloqueadores de contenido DNS</string>
+ <string name="dns_content_blockers_warning">Esto podría causar problemas con determinados sitios web, servicios y programas.</string>
<string name="dont_have_an_account">¿No tiene un número de cuenta?</string>
<string name="edit_message">Editar mensaje</string>
<string name="enable">Habilitar</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">Número de cuenta no válido</string>
<string name="login_fail_title">Error de inicio de sesión</string>
<string name="login_title">Iniciar sesión</string>
+ <string name="malware_info">Advertencia: El bloqueador de malware no es un antivirus y no debe considerarse como tal, tan solo es un nivel de protección adicional.</string>
<string name="max_devices_confirm_removal_description">¿Seguro que quiere cerrar la sesión de &lt;b&gt;%1$s&lt;/b&gt;?</string>
<string name="max_devices_resolved_description">Ya puede iniciar sesión en este dispositivo.</string>
<string name="max_devices_resolved_title">¡Genial!</string>
diff --git a/android/app/src/main/res/values-fi/strings.xml b/android/app/src/main/res/values-fi/strings.xml
index fdf9a7ffb9..dea15889a8 100644
--- a/android/app/src/main/res/values-fi/strings.xml
+++ b/android/app/src/main/res/values-fi/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">Automaattinen yhteys</string>
<string name="auto_connect_footer">Muodosta yhteys palvelimeen automaattisesti, kun sovellus avataan.</string>
<string name="back">Takaisin</string>
+ <string name="block_ads_title">Mainokset</string>
+ <string name="block_adult_content_title">Aikuisille suunnattu sisältö</string>
+ <string name="block_gambling_title">Uhkapelaaminen</string>
+ <string name="block_malware_title">Haittaohjelmat</string>
+ <string name="block_trackers_title">Seurantapalvelimet</string>
<string name="blocked_connection">ESTETTY YHTEYS</string>
<string name="blocking_all_connections">Kaikki yhteydet estetään</string>
<string name="blocking_internet">Verkkoyhteys estetään</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">Luodaan tiliä...</string>
<string name="creating_secure_connection">LUODAAN SUOJATTU YHTEYS</string>
<string name="critical_error">Vakava virhe (vaatii huomiotasi)</string>
+ <string name="custom_dns_disable_mode_subtitle">Voit ottaa asetuksen käyttöön poistamalla ensin kaikki &lt;b&gt;DNS-sisällönestotoiminnot&lt;/b&gt; käytöstä yltä.</string>
<string name="custom_dns_footer">Ota käyttöön lisätäksesi vähintään yhden DNS-palvelimen.</string>
<string name="custom_dns_hint">Anna IP-osoite</string>
<string name="custom_tunnel_host_resolution_error">Mukautetun palvelimen isäntänimen selvittäminen epäonnistui</string>
@@ -51,6 +57,10 @@
<string name="disconnect">Katkaise yhteys</string>
<string name="disconnecting">Katkaistaan yhteyttä</string>
<string name="dismiss">Jätä huomiotta</string>
+ <string name="dns_content_blockers_info">Kun tämä ominaisuus on käytössä, se estää laitetta ottamasta yhteyttä tiettyihin verkkotunnuksiin tai -sivustoihin, jotka tunnetaan mainosten, haittaohjelmien, seurantaohjelmien tai muiden vastaavien jakelijoina.</string>
+ <string name="dns_content_blockers_subtitle">Ota nämä asetukset käyttöön poistamalla &lt;b&gt;%1$s&lt;/b&gt; käytöstä alta.</string>
+ <string name="dns_content_blockers_title">DNS-sisällönestotoiminnot</string>
+ <string name="dns_content_blockers_warning">Tämä voi aiheuttaa ongelmia tietyillä verkkosivustoilla, palveluissa ja ohjelmissa.</string>
<string name="dont_have_an_account">Eikö sinulla ole tilinumeroa?</string>
<string name="edit_message">Muokkaa viestiä</string>
<string name="enable">Ota käyttöön</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">Virheellinen tilin numero</string>
<string name="login_fail_title">Sisäänkirjautuminen epäonnistui</string>
<string name="login_title">Kirjaudu sisään</string>
+ <string name="malware_info">Varoitus: haittaohjelmien estotoiminto ei ole virustorjuntaohjelma, eikä sitä pidä käyttää sellaisena – kyseessä on vain ylimääräinen suojauskerros.</string>
<string name="max_devices_confirm_removal_description">Haluatko varmasti kirjautua ulos laitteelta &lt;b&gt;%1$s&lt;/b&gt;?</string>
<string name="max_devices_resolved_description">Voit nyt jatkaa kirjautumista tällä laitteella.</string>
<string name="max_devices_resolved_title">Mahtavaa!</string>
diff --git a/android/app/src/main/res/values-fr/strings.xml b/android/app/src/main/res/values-fr/strings.xml
index f501d2f5ce..3e30a8dfff 100644
--- a/android/app/src/main/res/values-fr/strings.xml
+++ b/android/app/src/main/res/values-fr/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">Connexion automatique</string>
<string name="auto_connect_footer">Connexion automatique à un serveur dès le démarrage de l\'application.</string>
<string name="back">Retour</string>
+ <string name="block_ads_title">Publicités</string>
+ <string name="block_adult_content_title">Contenu pour adultes</string>
+ <string name="block_gambling_title">Jeux d\'argent</string>
+ <string name="block_malware_title">Malware</string>
+ <string name="block_trackers_title">Trackers</string>
<string name="blocked_connection">CONNEXION BLOQUÉE</string>
<string name="blocking_all_connections">Blocage de toutes les connexions</string>
<string name="blocking_internet">Internet bloqué</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">Création du compte…</string>
<string name="creating_secure_connection">CRÉATION D\'UNE CONNEXION SÉCURISÉE</string>
<string name="critical_error">Erreur critique (votre attention est requise)</string>
+ <string name="custom_dns_disable_mode_subtitle">Désactivez tous les &lt;b&gt;bloqueurs de contenu DNS&lt;/b&gt; pour activer ce paramètre.</string>
<string name="custom_dns_footer">Activez pour ajouter au moins un serveur DNS.</string>
<string name="custom_dns_hint">Saisir l\'IP</string>
<string name="custom_tunnel_host_resolution_error">Échec de la résolution du nom d\'hôte du serveur personnalisé</string>
@@ -51,6 +57,10 @@
<string name="disconnect">Déconnexion</string>
<string name="disconnecting">Déconnexion en cours</string>
<string name="dismiss">Ignorer</string>
+ <string name="dns_content_blockers_info">Lorsque cette fonctionnalité est activée, elle empêche l\'appareil de contacter certains domaines ou sites Web connus pour distribuer des publicités, des logiciels malveillants, des trackers et plus.</string>
+ <string name="dns_content_blockers_subtitle">Désactivez &lt;b&gt;%1$s&lt;/b&gt; ci-dessous pour activer ces paramètres.</string>
+ <string name="dns_content_blockers_title">Bloqueurs de contenu DNS</string>
+ <string name="dns_content_blockers_warning">Cela peut causer des problèmes sur certains sites Web, services et programmes.</string>
<string name="dont_have_an_account">Vous n\'avez pas de numéro de compte ?</string>
<string name="edit_message">Modifier le message</string>
<string name="enable">Activer</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">Numéro de compte non valide</string>
<string name="login_fail_title">Échec de la connexion</string>
<string name="login_title">Connexion</string>
+ <string name="malware_info">Avertissement : le bloqueur de malware n\'est pas un anti-virus et ne doit pas être traité comme tel, il s\'agit juste d\'une couche de protection supplémentaire.</string>
<string name="max_devices_confirm_removal_description">Voulez-vous vraiment déconnecter &lt;b&gt;%1$s&lt;/b&gt; ?</string>
<string name="max_devices_resolved_description">Vous pouvez maintenant continuer la connexion sur cet appareil.</string>
<string name="max_devices_resolved_title">Super !</string>
diff --git a/android/app/src/main/res/values-it/strings.xml b/android/app/src/main/res/values-it/strings.xml
index 82def46b78..342383f67b 100644
--- a/android/app/src/main/res/values-it/strings.xml
+++ b/android/app/src/main/res/values-it/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">Connessione automatica</string>
<string name="auto_connect_footer">Connettiti automaticamente al server all\'avvio dell\'app.</string>
<string name="back">Indietro</string>
+ <string name="block_ads_title">Annunci</string>
+ <string name="block_adult_content_title">Contenuti per adulti</string>
+ <string name="block_gambling_title">Gioco d\'azzardo</string>
+ <string name="block_malware_title">Malware</string>
+ <string name="block_trackers_title">Tracker</string>
<string name="blocked_connection">CONNESSIONE BLOCCATA</string>
<string name="blocking_all_connections">Blocco di tutte le connessioni</string>
<string name="blocking_internet">Blocco di Internet</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">Creazione account...</string>
<string name="creating_secure_connection">CREAZIONE CONNESSIONE PROTETTA</string>
<string name="critical_error">Errore critico (è necessario intervenire)</string>
+ <string name="custom_dns_disable_mode_subtitle">Disabilita tutti i &lt;b&gt;blocchi dei contenuti DNS&lt;/b&gt; per attivare questa impostazione.</string>
<string name="custom_dns_footer">Abilita per aggiungere almeno un server DNS.</string>
<string name="custom_dns_hint">Inserisci IP</string>
<string name="custom_tunnel_host_resolution_error">Impossibile risolvere il nome host del server personalizzato</string>
@@ -51,6 +57,10 @@
<string name="disconnect">Disconnetti</string>
<string name="disconnecting">Disconnessione</string>
<string name="dismiss">Ignora</string>
+ <string name="dns_content_blockers_info">Quando è abilitata, questa funzionalità impedisce al dispositivo di contattare determinati domini o siti Web noti per la distribuzione di annunci, malware, tracker e altro.</string>
+ <string name="dns_content_blockers_subtitle">Disabilita &lt;b&gt;%1$s&lt;/b&gt; di seguito per attivare queste impostazioni.</string>
+ <string name="dns_content_blockers_title">Blocchi dei contenuti DNS</string>
+ <string name="dns_content_blockers_warning">Ciò potrebbe causare problemi su determinati siti Web, servizi e programmi.</string>
<string name="dont_have_an_account">Non hai un numero di account?</string>
<string name="edit_message">Modifica messaggio</string>
<string name="enable">Abilita</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">Numero di account non valido</string>
<string name="login_fail_title">Accesso non riuscito</string>
<string name="login_title">Accedi</string>
+ <string name="malware_info">Avvertenza: questa protezione dai malware non è un antivirus e non deve essere trattata come tale, è solo un ulteriore livello di protezione.</string>
<string name="max_devices_confirm_removal_description">Vuoi davvero disconnettere &lt;b&gt;%1$s&lt;/b&gt;?</string>
<string name="max_devices_resolved_description">Ora puoi continuare ad accedere su questo dispositivo.</string>
<string name="max_devices_resolved_title">Fantastico!</string>
diff --git a/android/app/src/main/res/values-ja/strings.xml b/android/app/src/main/res/values-ja/strings.xml
index eccdfa3610..888fbac831 100644
--- a/android/app/src/main/res/values-ja/strings.xml
+++ b/android/app/src/main/res/values-ja/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">自動接続</string>
<string name="auto_connect_footer">アプリ起動時に自動的にサーバーに接続します。</string>
<string name="back">戻る</string>
+ <string name="block_ads_title">広告</string>
+ <string name="block_adult_content_title">アダルトコンテンツ</string>
+ <string name="block_gambling_title">ギャンブル</string>
+ <string name="block_malware_title">マルウェア</string>
+ <string name="block_trackers_title">トラッカー</string>
<string name="blocked_connection">ブロックされた接続</string>
<string name="blocking_all_connections">すべての接続をブロックしています</string>
<string name="blocking_internet">インターネットをブロック中</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">アカウントを作成中...</string>
<string name="creating_secure_connection">セキュリティ保護接続を確立中</string>
<string name="critical_error">重大なエラー (ご注意ください)</string>
+ <string name="custom_dns_disable_mode_subtitle">この設定を有効にするには、すべての&lt;b&gt;DNSコンテンツブロッカー&lt;/b&gt;を無効にしてください。</string>
<string name="custom_dns_footer">1つ以上のDNSサーバーを追加するには有効にしてください。</string>
<string name="custom_dns_hint">IPを入力</string>
<string name="custom_tunnel_host_resolution_error">カスタムサーバーのホスト名を解決できませんでした</string>
@@ -51,6 +57,10 @@
<string name="disconnect">接続解除</string>
<string name="disconnecting">接続解除中</string>
<string name="dismiss">閉じる</string>
+ <string name="dns_content_blockers_info">この機能を有効にすると、広告、マルウェア、トラッカーなどの配信が確認されている特定のドメインまたはWebサイトへのデバイスの接続が阻止されます。</string>
+ <string name="dns_content_blockers_subtitle">これらの設定を有効にするには、以下で&lt;b&gt;%1$s&lt;/b&gt;を無効にしてください。</string>
+ <string name="dns_content_blockers_title">DNSコンテンツブロッカー</string>
+ <string name="dns_content_blockers_warning">これにより、特定のWebサイト、サービス、プログラムで問題が発生する可能性があります。</string>
<string name="dont_have_an_account">アカウント番号を持っていませんか?</string>
<string name="edit_message">メッセージを編集する</string>
<string name="enable">有効にする</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">アカウント番号が正しくありません</string>
<string name="login_fail_title">ログインに失敗しました</string>
<string name="login_title">ログイン</string>
+ <string name="malware_info">警告: マルウェアブロッカーはウィルス対策ではありませんので、そのような用途には使用しないでください。あくまで追加の保護レイヤーに過ぎません。</string>
<string name="max_devices_confirm_removal_description">本当に&lt;b&gt;%1$s&lt;/b&gt;をログアウトしますか?</string>
<string name="max_devices_resolved_description">このデバイスでログインを続けられるようになりました。</string>
<string name="max_devices_resolved_title">素晴らしい!</string>
diff --git a/android/app/src/main/res/values-ko/strings.xml b/android/app/src/main/res/values-ko/strings.xml
index a0defd153e..8a5d117322 100644
--- a/android/app/src/main/res/values-ko/strings.xml
+++ b/android/app/src/main/res/values-ko/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">자동 연결</string>
<string name="auto_connect_footer">앱이 시작되면 자동으로 서버에 연결합니다.</string>
<string name="back">뒤로</string>
+ <string name="block_ads_title">광고</string>
+ <string name="block_adult_content_title">성인 콘텐츠</string>
+ <string name="block_gambling_title">도박</string>
+ <string name="block_malware_title">맬웨어</string>
+ <string name="block_trackers_title">트래커</string>
<string name="blocked_connection">연결 차단됨</string>
<string name="blocking_all_connections">모든 연결 차단 중</string>
<string name="blocking_internet">인터넷 차단</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">계정 생성 중...</string>
<string name="creating_secure_connection">보안 연결 생성 중</string>
<string name="critical_error">심각한 오류(주의가 필요함)</string>
+ <string name="custom_dns_disable_mode_subtitle">이 설정을 활성화하려면 위의 모든 &lt;b&gt;DNS 콘텐츠 차단기&lt;/b&gt;를 비활성화하세요.</string>
<string name="custom_dns_footer">하나 이상의 DNS 서버를 추가하려면 활성화합니다.</string>
<string name="custom_dns_hint">IP 입력</string>
<string name="custom_tunnel_host_resolution_error">사용자 지정 서버의 호스트 이름을 확인하지 못함</string>
@@ -51,6 +57,10 @@
<string name="disconnect">연결 끊기</string>
<string name="disconnecting">연결 해제 중</string>
<string name="dismiss">해제</string>
+ <string name="dns_content_blockers_info">이 기능이 활성화되면 광고, 맬웨어, 트래커 등을 배포하는 것으로 알려진 특정 도메인이나 웹사이트에 장치가 연결하지 않게 방지됩니다.</string>
+ <string name="dns_content_blockers_subtitle">이 설정을 활성화하려면 아래의 &lt;b&gt;%1$s&lt;/b&gt;을(를) 비활성화하세요.</string>
+ <string name="dns_content_blockers_title">DNS 콘텐츠 차단기</string>
+ <string name="dns_content_blockers_warning">이 기능을 사용하면 특정 웹 사이트, 서비스 및 프로그램에서 문제가 발생할 수 있습니다.</string>
<string name="dont_have_an_account">계정 번호가 없으신가요?</string>
<string name="edit_message">메시지 편집</string>
<string name="enable">사용</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">유효하지 않은 계정 번호</string>
<string name="login_fail_title">로그인 실패</string>
<string name="login_title">로그인</string>
+ <string name="malware_info">경고: 맬웨어 차단기는 안티바이러스가 아니며 하나의 추가 보호 계층일 뿐입니다.</string>
<string name="max_devices_confirm_removal_description">&lt;b&gt;%1$s&lt;/b&gt;에서 로그아웃하시겠습니까?</string>
<string name="max_devices_resolved_description">이제 이 장치에 계속 로그인할 수 있습니다.</string>
<string name="max_devices_resolved_title">좋습니다!</string>
diff --git a/android/app/src/main/res/values-my/strings.xml b/android/app/src/main/res/values-my/strings.xml
index 84c51c424f..78ed4902ae 100644
--- a/android/app/src/main/res/values-my/strings.xml
+++ b/android/app/src/main/res/values-my/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">အော်တို ချိတ်ဆက်မှု</string>
<string name="auto_connect_footer">အက်ပ် စတင်ဆောင်ရွက်ချိန်တွင် ဆာဗာနှင့် အော်တို ချိတ်ဆက်သွားပါမည်။</string>
<string name="back">နောက်သို့</string>
+ <string name="block_ads_title">ကြောငြာများ</string>
+ <string name="block_adult_content_title">လူကြီး အကြောင်းအရာ</string>
+ <string name="block_gambling_title">လောင်းကစား</string>
+ <string name="block_malware_title">မဲလ်ဝဲရ်</string>
+ <string name="block_trackers_title">ခြေရာခံများ</string>
<string name="blocked_connection">ပိတ်ဆို့ထားသည့် ချိတ်ဆက်မှု</string>
<string name="blocking_all_connections">ချိတ်ဆက်မှု အားလုံးကို ပိတ်ဆို့ထားပါသည်</string>
<string name="blocking_internet">အင်တာနက် ပိတ်ဆို့နေပါသည်</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">အကောင့် ဖန်တီးနေဆဲ...</string>
<string name="creating_secure_connection">လုံခြုံသည့် ချိတ်ဆက်မှုကို ဖန်တီးနေပါသည်</string>
<string name="critical_error">အလွန်အရေးပါသည့် ချို့ယွင်းချက် (သင့်အာရုံစိုက်မှု လိုအပ်ပါသည်)</string>
+ <string name="custom_dns_disable_mode_subtitle">ဤဆက်တင်ကို သက်ဝင်လုပ်ဆောင်ရန် အထက်ပါ &lt;b&gt;DNS content blockers&lt;/b&gt; အားလုံးကို ပိတ်ပါ။</string>
<string name="custom_dns_footer">အနည်းဆုံး DNS ဆာဗာတစ်ခုကို ပေါင်းထည့်ပါ။</string>
<string name="custom_dns_hint">IP ဖြည့်ပါ</string>
<string name="custom_tunnel_host_resolution_error">စိတ်ကြိုက် ဆာဗာ၏ Hostname ကို ဖြေရှင်း၍ မရနိုင်ပါ</string>
@@ -51,6 +57,10 @@
<string name="disconnect">ချိတ်ဆက်မှုဖြုတ်ရန်</string>
<string name="disconnecting">ချိတ်ဆက်မှုဖြုတ်နေပါသည်</string>
<string name="dismiss">ဖယ်ပစ်ရန်</string>
+ <string name="dns_content_blockers_info">ဤလုပ်ဆောင်ချက်ကို ဖွင့်ထားသည့်အခါ အနှောင့်အယှက်ဖြစ်စေသည့် ကြော်ငြာများ၊ မဲလ်ဝဲရ်၊ ခြေရာခံများနှင့် အစရှိသည်တို့နှင့်စပ်လျဉ်း၍ သိရှိထားသော အချို့သော Domain များ သို့မဟုတ် ဝဘ်ဆိုက်များနှင့် ဆက်သွယ်ခြင်းမှ စက်ကို ရပ်တန့်ပေးပါသည်။</string>
+ <string name="dns_content_blockers_subtitle">ဤဆက်တင်တို့ကို သက်ဝင်လုပ်ဆောင်ရန် အောက်ပါ &lt;b&gt;%1$s&lt;/b&gt; ကို ပိတ်ပါ။</string>
+ <string name="dns_content_blockers_title">DNS အကြောင်းအရာ ပိတ်ဆို့မှုများ</string>
+ <string name="dns_content_blockers_warning">၎င်းသည် အချို့သော ဝဘ်ဆိုက်များ၊ ဝန်ဆောင်မှုများနှင့် ပရိုဂရမ်များတွင် ပြဿနာများကို ဖြစ်စေနိုင်သည်။</string>
<string name="dont_have_an_account">အကောင့်နံပါတ် မရှိ ဖြစ်နေပါသလား။</string>
<string name="edit_message">မက်ဆေ့ချ် တည်းဖြတ်ရန်</string>
<string name="enable">ဖွင့်ရန်</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">အကောင့်နံပါတ် မှားယွင်းနေပါသည်</string>
<string name="login_fail_title">ဝင်ရောက်မှု မအောင်မြင်ပါ</string>
<string name="login_title">ဝင်ရန်</string>
+ <string name="malware_info">သတိပေးချက်- မဲလ်ဝဲရ် ပိတ်ဆို့မှုသည် အပိုအကာအကွယ်လွှာ တစ်ခုသာဖြစ်ပြီး ဗိုင်းရပ်စ် ကာကွယ်ရေး (anti-virus) မဟုတ်၍ ၎င်းအဖြစ် မမှတ်ယူသင့်ပါ။</string>
<string name="max_devices_confirm_removal_description">&lt;b&gt;%1$s&lt;/b&gt; မှ ထွက်လိုသည်မှာ သေချာပါသလား။</string>
<string name="max_devices_resolved_description">သင်သည် ယခု ဤစက်တွင် ဆက်လက် ဝင်ရောက်နိုင်သည်။</string>
<string name="max_devices_resolved_title">အလွန်ကောင်း။</string>
diff --git a/android/app/src/main/res/values-nb/strings.xml b/android/app/src/main/res/values-nb/strings.xml
index 5f136b7b55..554421b685 100644
--- a/android/app/src/main/res/values-nb/strings.xml
+++ b/android/app/src/main/res/values-nb/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">Automatisk tilkobling</string>
<string name="auto_connect_footer">Kobler automatisk til en server når appen starter.</string>
<string name="back">Tilbake</string>
+ <string name="block_ads_title">Annonser</string>
+ <string name="block_adult_content_title">Vokseninnhold</string>
+ <string name="block_gambling_title">Pengespill</string>
+ <string name="block_malware_title">Skadelig programvare</string>
+ <string name="block_trackers_title">Sporing</string>
<string name="blocked_connection">TILKOBLING BLOKKERT</string>
<string name="blocking_all_connections">Blokkerer alle tilkoblinger</string>
<string name="blocking_internet">Blokkerer internettet</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">Oppretter konto ...</string>
<string name="creating_secure_connection">OPPRETTER SIKKER TILKOBLING</string>
<string name="critical_error">Kritisk feil (krever din oppmerksomhet)</string>
+ <string name="custom_dns_disable_mode_subtitle">Deaktiver all &lt;b&gt;DNS-innholdsblokkering&lt;/b&gt; over for å aktivere innstillingen.</string>
<string name="custom_dns_footer">Aktiver for å legge til minst én DNS-server.</string>
<string name="custom_dns_hint">Angi IP</string>
<string name="custom_tunnel_host_resolution_error">Kunne ikke løse vertsnavnet til den egendefinerte serveren</string>
@@ -51,6 +57,10 @@
<string name="disconnect">Koble fra</string>
<string name="disconnecting">Kobler fra</string>
<string name="dismiss">Ignorer</string>
+ <string name="dns_content_blockers_info">Når denne funksjonen er aktivert, forhindrer den enheten fra å kontakte bestemte domener og nettsteder som er kjent for å spre annonser, skadelig programvare, sporingsenheter og mer.</string>
+ <string name="dns_content_blockers_subtitle">Deaktiver &lt;b&gt;%1$s&lt;/b&gt; under for å aktivere innstillingene.</string>
+ <string name="dns_content_blockers_title">DNS-innholdsblokkering</string>
+ <string name="dns_content_blockers_warning">Dette kan føre til problemer på enkelte nettsteder, tjenester og programmer.</string>
<string name="dont_have_an_account">Har du ikke et kontonummer?</string>
<string name="edit_message">Rediger melding</string>
<string name="enable">Aktiver</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">Ugyldig kontonummer</string>
<string name="login_fail_title">Kunne ikke logge inn</string>
<string name="login_title">Logg inn</string>
+ <string name="malware_info">Advarsel: Blokkeringen av skadelig programvare er ikke et antivirusprogram og skal ikke brukes som dette. Det er bare et ekstra lag med beskyttelse.</string>
<string name="max_devices_confirm_removal_description">Vil du virkelig logge av &lt;b&gt;%1$s&lt;/b&gt;?</string>
<string name="max_devices_resolved_description">Du kan nå fortsette med å logge på denne enheten.</string>
<string name="max_devices_resolved_title">Supert!</string>
diff --git a/android/app/src/main/res/values-nl/strings.xml b/android/app/src/main/res/values-nl/strings.xml
index 5089823a58..39d29ed5d9 100644
--- a/android/app/src/main/res/values-nl/strings.xml
+++ b/android/app/src/main/res/values-nl/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">Automatisch verbinden</string>
<string name="auto_connect_footer">Automatisch verbinden met een server wanneer de app wordt gestart.</string>
<string name="back">Terug</string>
+ <string name="block_ads_title">Advertenties</string>
+ <string name="block_adult_content_title">Content voor volwassenen</string>
+ <string name="block_gambling_title">Gokken</string>
+ <string name="block_malware_title">Malware</string>
+ <string name="block_trackers_title">Trackers</string>
<string name="blocked_connection">VERBINDING GEBLOKKEERD</string>
<string name="blocking_all_connections">Alle verbindingen worden geblokkeerd</string>
<string name="blocking_internet">Internet blokkeren</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">Account aanmaken...</string>
<string name="creating_secure_connection">BEVEILIGDE VERBINDING AANMAKEN</string>
<string name="critical_error">Kritieke fout (uw aandacht is vereist)</string>
+ <string name="custom_dns_disable_mode_subtitle">Schakel alle &lt;b&gt;DNS-contentblokkeringen&lt;/b&gt; hierboven uit om deze instelling te activeren.</string>
<string name="custom_dns_footer">Schakel in om minimaal één DNS-server toe te voegen.</string>
<string name="custom_dns_hint">Voer IP-adres in</string>
<string name="custom_tunnel_host_resolution_error">Kon de hostnaam van de aangepaste server niet omzetten</string>
@@ -51,6 +57,10 @@
<string name="disconnect">Verbinding verbreken</string>
<string name="disconnecting">Verbinding wordt verbroken</string>
<string name="dismiss">Negeren</string>
+ <string name="dns_content_blockers_info">Als deze functie is ingeschakeld, maakt het apparaat geen contact meer met bepaalde domeinen of websites waarvan bekend is dat ze advertenties, malware, trackers en meer verspreiden.</string>
+ <string name="dns_content_blockers_subtitle">Schakel &lt;b&gt;%1$s&lt;/b&gt; hieronder uit om deze instellingen te activeren.</string>
+ <string name="dns_content_blockers_title">DNS-contentblokkeringen</string>
+ <string name="dns_content_blockers_warning">Dit kan problemen veroorzaken met bepaalde websites, diensten en programma\'s.</string>
<string name="dont_have_an_account">Hebt u geen accountnummer?</string>
<string name="edit_message">Bericht bewerken</string>
<string name="enable">Inschakelen</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">Ongeldig accountnummer</string>
<string name="login_fail_title">Aanmelden mislukt</string>
<string name="login_title">Aanmelden</string>
+ <string name="malware_info">Waarschuwing: de malwareblocker is geen antivirus en mag niet als zodanig behandeld worden. Dit is slechts een extra beschermingslaag.</string>
<string name="max_devices_confirm_removal_description">Weet u zeker dat u &lt;b&gt;%1$s&lt;/b&gt; wilt afmelden?</string>
<string name="max_devices_resolved_description">U kunt nu doorgaan met het aanmelden bij dit apparaat.</string>
<string name="max_devices_resolved_title">Super!</string>
diff --git a/android/app/src/main/res/values-pl/strings.xml b/android/app/src/main/res/values-pl/strings.xml
index 323e5f92c9..07b4ce6525 100644
--- a/android/app/src/main/res/values-pl/strings.xml
+++ b/android/app/src/main/res/values-pl/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">Automatyczne łączenie</string>
<string name="auto_connect_footer">Automatycznie łącz z serwerem po uruchomieniu aplikacji.</string>
<string name="back">Wstecz</string>
+ <string name="block_ads_title">Reklamy</string>
+ <string name="block_adult_content_title">Treści dla dorosłych</string>
+ <string name="block_gambling_title">Hazard</string>
+ <string name="block_malware_title">Złośliwe oprogramowanie</string>
+ <string name="block_trackers_title">Trackery</string>
<string name="blocked_connection">ZABLOKOWANE POŁĄCZENIE</string>
<string name="blocking_all_connections">Blokowanie wszystkich połączeń</string>
<string name="blocking_internet">Blokowanie Internetu</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">Tworzenie konta...</string>
<string name="creating_secure_connection">TWORZENIE BEZPIECZNEGO POŁĄCZENIA</string>
<string name="critical_error">Błąd krytyczny (wymagana uwaga)</string>
+ <string name="custom_dns_disable_mode_subtitle">Aby to aktywować to ustawienie, wyłącz wszystkie &lt;b&gt;funkcje blokowania treści DNS&lt;/b&gt;.</string>
<string name="custom_dns_footer">Włącz, aby dodać co najmniej jeden serwer DNS.</string>
<string name="custom_dns_hint">Wprowadź adres IP</string>
<string name="custom_tunnel_host_resolution_error">Nie można rozpoznać nazwy hosta serwera niestandardowego</string>
@@ -51,6 +57,10 @@
<string name="disconnect">Rozłącz</string>
<string name="disconnecting">Rozłączanie</string>
<string name="dismiss">Odrzuć</string>
+ <string name="dns_content_blockers_info">Po włączeniu funkcja ta uniemożliwia urządzeniu kontakt z określonymi domenami lub witrynami internetowymi, które rozpowszechniają reklamy, złośliwe oprogramowanie itd.</string>
+ <string name="dns_content_blockers_subtitle">Aby aktywować te ustawienia, wyłącz &lt;b&gt;%1$s&lt;/b&gt; poniżej.</string>
+ <string name="dns_content_blockers_title">Funkcje blokowania treści DNS</string>
+ <string name="dns_content_blockers_warning">Może to powodować problemy z niektórymi witrynami, usługami i programami.</string>
<string name="dont_have_an_account">Nie masz numeru konta?</string>
<string name="edit_message">Edytuj wiadomość</string>
<string name="enable">Włącz</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">Nieprawidłowy numer konta</string>
<string name="login_fail_title">Błąd logowania</string>
<string name="login_title">Logowanie</string>
+ <string name="malware_info">Ostrzeżenie: funkcja blokowania złośliwego oprogramowania nie jest programem antywirusowym i nie należy jej tak traktować. To jedynie dodatkowa warstwa zabezpieczeń.</string>
<string name="max_devices_confirm_removal_description">Czy na pewno chcesz wylogować &lt;b&gt;%1$s&lt;/b&gt;?</string>
<string name="max_devices_resolved_description">Teraz można kontynuować logowanie się na tym urządzeniu.</string>
<string name="max_devices_resolved_title">Super!</string>
diff --git a/android/app/src/main/res/values-pt/strings.xml b/android/app/src/main/res/values-pt/strings.xml
index 9bf0c8a942..59a310f3b2 100644
--- a/android/app/src/main/res/values-pt/strings.xml
+++ b/android/app/src/main/res/values-pt/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">Ligação automática</string>
<string name="auto_connect_footer">Liga-se automaticamente a um servidor quando a app inicia.</string>
<string name="back">Retroceder</string>
+ <string name="block_ads_title">Anúncios</string>
+ <string name="block_adult_content_title">Conteúdo para adultos</string>
+ <string name="block_gambling_title">Jogos de azar</string>
+ <string name="block_malware_title">Malware</string>
+ <string name="block_trackers_title">Trackers</string>
<string name="blocked_connection">LIGAÇÃO BLOQUEADA</string>
<string name="blocking_all_connections">A bloquear todas as ligações</string>
<string name="blocking_internet">A bloquear a Internet</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">A criar conta...</string>
<string name="creating_secure_connection">A CRIAR LIGAÇÃO SEGURA</string>
<string name="critical_error">Erro crítico (é necessária a sua atenção)</string>
+ <string name="custom_dns_disable_mode_subtitle">Desative todos os &lt;b&gt;bloqueadores de conteúdo de DNS&lt;/b&gt; acima para ativar esta definição.</string>
<string name="custom_dns_footer">Ativar para adicionar pelo menos um servidor DNS.</string>
<string name="custom_dns_hint">Introduzir IP</string>
<string name="custom_tunnel_host_resolution_error">Não foi possível resolver o nome do anfitrião do servidor personalizado</string>
@@ -51,6 +57,10 @@
<string name="disconnect">Desligar</string>
<string name="disconnecting">A desligar</string>
<string name="dismiss">Dispensar</string>
+ <string name="dns_content_blockers_info">Quando esta funcionalidade é ativada, impede que o dispositivo contacte certos domínios ou sites conhecidos por distribuir anúncios, malware, trackers e muito mais.</string>
+ <string name="dns_content_blockers_subtitle">Desative &lt;b&gt;%1$s&lt;/b&gt; abaixo para ativar estas definições.</string>
+ <string name="dns_content_blockers_title">Bloqueadores de conteúdo de DNS</string>
+ <string name="dns_content_blockers_warning">Pode causar problemas em alguns sites, serviços e programas.</string>
<string name="dont_have_an_account">Não tem um número de conta?</string>
<string name="edit_message">Editar mensagem</string>
<string name="enable">Ativar</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">Número de conta inválido</string>
<string name="login_fail_title">Erro ao iniciar sessão</string>
<string name="login_title">Iniciar sessão</string>
+ <string name="malware_info">Aviso: o bloqueador de malware não é um antivírus e não deve ser tratado como tal, é apenas uma camada extra de proteção.</string>
<string name="max_devices_confirm_removal_description">Tem a certeza de que quer terminar a sessão de &lt;b&gt;%1$s&lt;/b&gt;?</string>
<string name="max_devices_resolved_description">Agora pode continuar a ligação neste dispositivo.</string>
<string name="max_devices_resolved_title">Excelente!</string>
diff --git a/android/app/src/main/res/values-ru/strings.xml b/android/app/src/main/res/values-ru/strings.xml
index 1d5da1695c..4e6c803faf 100644
--- a/android/app/src/main/res/values-ru/strings.xml
+++ b/android/app/src/main/res/values-ru/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">Автоподключение</string>
<string name="auto_connect_footer">Автоматически подключаться к серверу при запуске приложения.</string>
<string name="back">Назад</string>
+ <string name="block_ads_title">Реклама</string>
+ <string name="block_adult_content_title">Контент для взрослых</string>
+ <string name="block_gambling_title">Азартные игры</string>
+ <string name="block_malware_title">Вредоносное ПО</string>
+ <string name="block_trackers_title">Трекеры</string>
<string name="blocked_connection">ПОДКЛЮЧЕНИЕ ЗАБЛОКИРОВАНО</string>
<string name="blocking_all_connections">Блокируются все подключения</string>
<string name="blocking_internet">Блокируется доступ в Интернет</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">Создание учетной записи...</string>
<string name="creating_secure_connection">СОЗДАНИЕ ЗАЩИЩЕННОГО ПОДКЛЮЧЕНИЯ</string>
<string name="critical_error">Критическая ошибка (требуется ваше участие)</string>
+ <string name="custom_dns_disable_mode_subtitle">Чтобы активировать эту опцию, отключите все &lt;b&gt;DNS-блокировщики контента&lt;/b&gt;.</string>
<string name="custom_dns_footer">Чтобы добавить как минимум один DNS-сервер, включите этот параметр.</string>
<string name="custom_dns_hint">Введите IP-адрес</string>
<string name="custom_tunnel_host_resolution_error">Не удалось преобразовать имя узла пользовательского сервера</string>
@@ -51,6 +57,10 @@
<string name="disconnect">Отключить</string>
<string name="disconnecting">Отключение</string>
<string name="dismiss">Закрыть</string>
+ <string name="dns_content_blockers_info">При включенной опции устройство не будет устанавливать соединение с определенными доменами и сайтами, известными распространением рекламы, вредоносного ПО, трекеров и т. д.</string>
+ <string name="dns_content_blockers_subtitle">Чтобы активировать эти параметры, отключите опцию &lt;b&gt;%1$s&lt;/b&gt; ниже.</string>
+ <string name="dns_content_blockers_title">DNS-блокировщики контента</string>
+ <string name="dns_content_blockers_warning">Это может привести к проблемам при использовании некоторых сайтов, служб и программ.</string>
<string name="dont_have_an_account">У вас нет номера учетной записи?</string>
<string name="edit_message">Изменить сообщение</string>
<string name="enable">Включить</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">Недействительный номер учетной записи</string>
<string name="login_fail_title">Ошибка входа</string>
<string name="login_title">Вход</string>
+ <string name="malware_info">Внимание! Блокировщик вредоносного ПО — это просто дополнительный уровень защиты, а не антивирус.</string>
<string name="max_devices_confirm_removal_description">Действительно выйти из профиля на устройстве &lt;b&gt;%1$s&lt;/b&gt;?</string>
<string name="max_devices_resolved_description">Теперь можно войти в учетную запись на этом устройстве.</string>
<string name="max_devices_resolved_title">Отлично!</string>
diff --git a/android/app/src/main/res/values-sv/strings.xml b/android/app/src/main/res/values-sv/strings.xml
index 30cd54d409..c14d953e1b 100644
--- a/android/app/src/main/res/values-sv/strings.xml
+++ b/android/app/src/main/res/values-sv/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">Anslut automatiskt</string>
<string name="auto_connect_footer">Anslut automatiskt till en server när appen startas.</string>
<string name="back">Tillbaka</string>
+ <string name="block_ads_title">Annonser</string>
+ <string name="block_adult_content_title">Vuxet innehåll</string>
+ <string name="block_gambling_title">Hasardspel</string>
+ <string name="block_malware_title">Skadlig kod</string>
+ <string name="block_trackers_title">Spårare</string>
<string name="blocked_connection">ANSLUTNINGEN BLOCKERAD</string>
<string name="blocking_all_connections">Blockerar alla anslutningar</string>
<string name="blocking_internet">Blockerar internet</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">Skapar konto...</string>
<string name="creating_secure_connection">SKAPAR SÄKER ANSLUTNING</string>
<string name="critical_error">Kritiskt fel (kräver din uppmärksamhet)</string>
+ <string name="custom_dns_disable_mode_subtitle">Inaktivera alla &lt;b&gt;DNS-innehållsblockerare&lt;/b&gt; ovan för att aktivera den här inställningen.</string>
<string name="custom_dns_footer">Aktivera för att lägga till minst en DNS-server.</string>
<string name="custom_dns_hint">Ange IP</string>
<string name="custom_tunnel_host_resolution_error">Det gick inte att lösa värdnamnet för den anpassade servern</string>
@@ -51,6 +57,10 @@
<string name="disconnect">Koppla från</string>
<string name="disconnecting">Kopplar från</string>
<string name="dismiss">Ignorera</string>
+ <string name="dns_content_blockers_info">När den här funktionen är aktiverad stoppas enheten från att kontakta vissa domäner eller webbplatser som är kända för att sprida annonser, skadlig kod, spårare med mera.</string>
+ <string name="dns_content_blockers_subtitle">Inaktivera &lt;b&gt;%1$s&lt;/b&gt; nedan för att aktivera dessa inställningar.</string>
+ <string name="dns_content_blockers_title">DNS-innehållsblockerare</string>
+ <string name="dns_content_blockers_warning">Detta kan orsaka problem på vissa webbplatser, tjänster och program.</string>
<string name="dont_have_an_account">Har du inget kontonummer?</string>
<string name="edit_message">Redigera meddelande</string>
<string name="enable">Aktivera</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">Ogiltigt kontonummer</string>
<string name="login_fail_title">Inloggningen misslyckades</string>
<string name="login_title">Logga in</string>
+ <string name="malware_info">Varning! Blockering av skadlig kod är inte ett antivirusprogram och bör inte behandlas som ett. Det här är bara ett extra skyddslager.</string>
<string name="max_devices_confirm_removal_description">Vill du verkligen logga ut &lt;b&gt;%1$s&lt;/b&gt;?</string>
<string name="max_devices_resolved_description">Du kan nu fortsätta med att logga in på den här enheten.</string>
<string name="max_devices_resolved_title">Super!</string>
diff --git a/android/app/src/main/res/values-th/strings.xml b/android/app/src/main/res/values-th/strings.xml
index a4759648f3..926f7a35d1 100644
--- a/android/app/src/main/res/values-th/strings.xml
+++ b/android/app/src/main/res/values-th/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">เชื่อมต่ออัตโนมัติ</string>
<string name="auto_connect_footer">เชื่อมต่อเซิร์ฟเวอร์โดยอัตโนมัติทันทีที่เปิดแอป</string>
<string name="back">ย้อนกลับ</string>
+ <string name="block_ads_title">โฆษณา</string>
+ <string name="block_adult_content_title">เนื้อหาสำหรับผู้ใหญ่</string>
+ <string name="block_gambling_title">การพนัน</string>
+ <string name="block_malware_title">มัลแวร์</string>
+ <string name="block_trackers_title">ตัวติดตาม</string>
<string name="blocked_connection">การเชื่อมต่อที่ถูกบล็อก</string>
<string name="blocking_all_connections">บล็อกการเชื่อมต่อทั้งหมด</string>
<string name="blocking_internet">กำลังบล็อกอินเทอร์เน็ต</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">กำลังสร้างบัญชี...</string>
<string name="creating_secure_connection">กำลังสร้างการเชื่อมต่อที่ปลอดภัย</string>
<string name="critical_error">ข้อผิดพลาดร้ายแรง (คุณจำเป็นต้องตรวจสอบ)</string>
+ <string name="custom_dns_disable_mode_subtitle">ปิดใช้งาน&lt;b&gt;ตัวบล็อกเนื้อหา DNS&lt;/b&gt; ทั้งหมดด้านบน เพื่อเปิดใช้งานการตั้งค่านี้</string>
<string name="custom_dns_footer">เปิดเพื่อเพิ่มเซิร์ฟเวอร์ DNS อย่างน้อยหนึ่งรายการ</string>
<string name="custom_dns_hint">ป้อน IP</string>
<string name="custom_tunnel_host_resolution_error">ไม่พบชื่อโฮสต์ของเซิร์ฟเวอร์แบบกำหนดเอง</string>
@@ -51,6 +57,10 @@
<string name="disconnect">ตัดการเชื่อมต่อ</string>
<string name="disconnecting">กำลังตัดการเชื่อมต่อ</string>
<string name="dismiss">ละทิ้ง</string>
+ <string name="dns_content_blockers_info">ในขณะที่เปิดใช้งานคุณสมบัตินี้ คุณสมบัตินี้จะหยุดไม่ให้อุปกรณ์ติดต่อโดเมน หรือเว็บไซต์ใดๆ ที่เป็นที่ทราบกันว่า ใช้ในการเผยแพร่โฆษณา มัลแวร์ ตัวติดตาม และอื่นๆ</string>
+ <string name="dns_content_blockers_subtitle">ปิดใช้งาน &lt;b&gt;%1$s&lt;/b&gt; ด้านล่าง เพื่อเปิดใช้การตั้งค่าเหล่านี้</string>
+ <string name="dns_content_blockers_title">ตัวบล็อกเนื้อหา DNS</string>
+ <string name="dns_content_blockers_warning">นี่อาจก่อให้เกิดปัญหากับเว็บไซต์ บริการ และโปรแกรมบางอย่างได้</string>
<string name="dont_have_an_account">ยังไม่มีหมายเลขบัญชีใช่ไหม</string>
<string name="edit_message">แก้ไขข้อความ</string>
<string name="enable">เปิดใช้งาน</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">หมายเลขบัญชีไม่ถูกต้อง</string>
<string name="login_fail_title">การเข้าสู่ระบบล้มเหลว</string>
<string name="login_title">เข้าสู่ระบบ</string>
+ <string name="malware_info">คำเตือน: ตัวบล็อกมัลแวร์ไม่ใช่แอนตี้ไวรัส และไม่ควรนำมาใช้ในรูปแบบดังกล่าว นี่เป็นเพียงชั้นการป้องกันเพิ่มเติมเท่านั้น</string>
<string name="max_devices_confirm_removal_description">คุณแน่ใจหรือไม่ว่าต้องการออกจากระบบบน &lt;b&gt;%1$s&lt;/b&gt;</string>
<string name="max_devices_resolved_description">คุณสามารถดำเนินการเข้าสู่ระบบต่อบนอุปกรณ์เครื่องนี้ได้แล้ว</string>
<string name="max_devices_resolved_title">เยี่ยมยอด!</string>
diff --git a/android/app/src/main/res/values-tr/strings.xml b/android/app/src/main/res/values-tr/strings.xml
index 7fb6438320..c216691300 100644
--- a/android/app/src/main/res/values-tr/strings.xml
+++ b/android/app/src/main/res/values-tr/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">Otomatik Bağlan</string>
<string name="auto_connect_footer">Uygulama başladığında bir sunucuya otomatik olarak bağlan.</string>
<string name="back">Geri</string>
+ <string name="block_ads_title">Reklamlar</string>
+ <string name="block_adult_content_title">Yetişkinlere özel içerik</string>
+ <string name="block_gambling_title">Kumar</string>
+ <string name="block_malware_title">Kötü amaçlı yazılım</string>
+ <string name="block_trackers_title">İzleyiciler</string>
<string name="blocked_connection">ENGELLENEN BAĞLANTI</string>
<string name="blocking_all_connections">Tüm bağlantılar engelleniyor</string>
<string name="blocking_internet">İnternet bağlantısı engelleniyor</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">Hesap oluşturuluyor...</string>
<string name="creating_secure_connection">GÜVENLİ BAĞLANTI OLUŞTURULUYOR</string>
<string name="critical_error">Kritik hata (Lütfen dikkatli olun)</string>
+ <string name="custom_dns_disable_mode_subtitle">Bu ayarı etkinleştirmek için yukarıdaki tüm &lt;b&gt;DNS içerik engelleyicileri&lt;/b&gt; devre dışı bırakın.</string>
<string name="custom_dns_footer">En az bir DNS sunucusu eklemek için etkinleştirin.</string>
<string name="custom_dns_hint">IP\'yi girin</string>
<string name="custom_tunnel_host_resolution_error">Özel sunucu ana bilgisayar adı çözülemiyor</string>
@@ -51,6 +57,10 @@
<string name="disconnect">Bağlantıyı Kes</string>
<string name="disconnecting">Bağlantı kesiliyor</string>
<string name="dismiss">Reddet</string>
+ <string name="dns_content_blockers_info">Bu özellik etkinleştirildiğinde, cihazınızın reklamlar, kötü amaçlı yazılımlar, izleyiciler ve daha fazlasını dağıttığı bilinen belirli alan adlarıyla veya web siteleriyle iletişim kurmasını durdurur.</string>
+ <string name="dns_content_blockers_subtitle">Bu ayarları etkinleştirmek için aşağıdaki &lt;b&gt;%1$s&lt;/b&gt; seçeneğini devre dışı bırakın.</string>
+ <string name="dns_content_blockers_title">DNS içerik engelleyiciler</string>
+ <string name="dns_content_blockers_warning">Bu özellik belirli web sitelerinde, hizmetlerde ve programlarda sorunlara neden olabilir.</string>
<string name="dont_have_an_account">Hesap numaranız yok mu?</string>
<string name="edit_message">Mesajı düzenle</string>
<string name="enable">Etkinleştir</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">Geçersiz hesap numarası</string>
<string name="login_fail_title">Oturum açma başarısız</string>
<string name="login_title">Oturum Aç</string>
+ <string name="malware_info">Uyarı: Kötü amaçlı yazılım engelleyici, virüsten koruma yazılımı değildir ve bu şekilde değerlendirilmemelidir. Sadece ek bir koruma seviyesi sağlamaktadır.</string>
<string name="max_devices_confirm_removal_description">&lt;b&gt;%1$s&lt;/b&gt; adlı cihazdan çıkış yapmak istediğinizden emin misiniz?</string>
<string name="max_devices_resolved_description">Artık bu cihazda oturum açmaya devam edebilirsiniz.</string>
<string name="max_devices_resolved_title">Süper!</string>
diff --git a/android/app/src/main/res/values-zh-rCN/strings.xml b/android/app/src/main/res/values-zh-rCN/strings.xml
index 9c5f98c8e1..62cba3caff 100644
--- a/android/app/src/main/res/values-zh-rCN/strings.xml
+++ b/android/app/src/main/res/values-zh-rCN/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">自动连接</string>
<string name="auto_connect_footer">在应用启动时自动连接到服务器。</string>
<string name="back">返回</string>
+ <string name="block_ads_title">广告</string>
+ <string name="block_adult_content_title">成人内容</string>
+ <string name="block_gambling_title">博彩</string>
+ <string name="block_malware_title">恶意软件</string>
+ <string name="block_trackers_title">跟踪器</string>
<string name="blocked_connection">已阻止连接</string>
<string name="blocking_all_connections">正在阻止所有连接</string>
<string name="blocking_internet">正在阻止网络</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">正在创建帐户…</string>
<string name="creating_secure_connection">正在创建安全连接</string>
<string name="critical_error">严重错误(需要注意)</string>
+ <string name="custom_dns_disable_mode_subtitle">禁用上方的所有 &lt;b&gt;DNS 内容阻止程序&lt;/b&gt;以激活此设置。</string>
<string name="custom_dns_footer">启用以添加至少一个 DNS 服务器。</string>
<string name="custom_dns_hint">输入 IP</string>
<string name="custom_tunnel_host_resolution_error">无法解析自定义服务器的主机名</string>
@@ -51,6 +57,10 @@
<string name="disconnect">断开连接</string>
<string name="disconnecting">正在断开连接</string>
<string name="dismiss">关闭</string>
+ <string name="dns_content_blockers_info">启用此功能后,它将阻止设备与已知的分发广告、恶意软件、跟踪器等内容的特定域或网站联系。</string>
+ <string name="dns_content_blockers_subtitle">禁用下方的&lt;b&gt;%1$s&lt;/b&gt;以激活这些设置。</string>
+ <string name="dns_content_blockers_title">DNS 内容阻止程序</string>
+ <string name="dns_content_blockers_warning">这可能会导致某些网站、服务和程序出现问题。</string>
<string name="dont_have_an_account">没有帐号?</string>
<string name="edit_message">编辑消息</string>
<string name="enable">启用</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">帐号无效</string>
<string name="login_fail_title">登录失败</string>
<string name="login_title">登录</string>
+ <string name="malware_info">警告:恶意软件阻止程序不是防病毒软件,也不应被视为防病毒软件,这只是提供了一层额外的保护。</string>
<string name="max_devices_confirm_removal_description">确定要退出&lt;b&gt;%1$s&lt;/b&gt;吗?</string>
<string name="max_devices_resolved_description">您现在可以继续在此设备上登录。</string>
<string name="max_devices_resolved_title">太棒了!</string>
diff --git a/android/app/src/main/res/values-zh-rTW/strings.xml b/android/app/src/main/res/values-zh-rTW/strings.xml
index 02056bee04..c086b24941 100644
--- a/android/app/src/main/res/values-zh-rTW/strings.xml
+++ b/android/app/src/main/res/values-zh-rTW/strings.xml
@@ -18,6 +18,11 @@
<string name="auto_connect">自動連線</string>
<string name="auto_connect_footer">啟動應用程式時,自動連線伺服器。</string>
<string name="back">返回</string>
+ <string name="block_ads_title">廣告</string>
+ <string name="block_adult_content_title">成人內容</string>
+ <string name="block_gambling_title">賭博</string>
+ <string name="block_malware_title">惡意軟體</string>
+ <string name="block_trackers_title">追蹤程式</string>
<string name="blocked_connection">被封鎖的連線</string>
<string name="blocking_all_connections">正在封鎖所有連線</string>
<string name="blocking_internet">正在封鎖網路</string>
@@ -41,6 +46,7 @@
<string name="creating_new_account">正在建立帳戶…</string>
<string name="creating_secure_connection">建立安全連線</string>
<string name="critical_error">嚴重錯誤 (需注意)</string>
+ <string name="custom_dns_disable_mode_subtitle">停用上方所有 &lt;b&gt;DNS 內容封鎖程式&lt;/b&gt;,以便啟動此設定。</string>
<string name="custom_dns_footer">啟用以新增至少一個 DNS 伺服器。</string>
<string name="custom_dns_hint">輸入 IP</string>
<string name="custom_tunnel_host_resolution_error">無法解析自訂伺服器的主機名稱</string>
@@ -51,6 +57,10 @@
<string name="disconnect">中斷連線</string>
<string name="disconnecting">正在中斷連線</string>
<string name="dismiss">取消</string>
+ <string name="dns_content_blockers_info">此功能啟用後,便會禁止裝置聯繫某些已知會傳播廣告、惡意軟體、追蹤程式等內容的網域或網站。</string>
+ <string name="dns_content_blockers_subtitle">停用下方的 &lt;b&gt;%1$s&lt;/b&gt; 以啟動這些設定。</string>
+ <string name="dns_content_blockers_title">DNS 內容封鎖程式</string>
+ <string name="dns_content_blockers_warning">這可能會導致某些網站、服務和程式出現問題。</string>
<string name="dont_have_an_account">沒有帳號?</string>
<string name="edit_message">編輯訊息</string>
<string name="enable">啟用</string>
@@ -89,6 +99,7 @@
<string name="login_fail_description">帳號無效</string>
<string name="login_fail_title">登入失敗</string>
<string name="login_title">登入</string>
+ <string name="malware_info">警告:惡意軟體封鎖程式並非防毒軟體,只是提供了一層額外保護,不應將其視為防毒軟體。</string>
<string name="max_devices_confirm_removal_description">確定要將 &lt;b&gt;%1$s&lt;/b&gt; 登出嗎?</string>
<string name="max_devices_resolved_description">現在,您可以繼續在此裝置上登入。</string>
<string name="max_devices_resolved_title">太好了!</string>
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index 747c3ee31e..477c299513 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -209,4 +209,23 @@
<string name="add_dns_server_dialog_title">Add DNS server</string>
<string name="update_dns_server_dialog_title">Update DNS server</string>
<string name="duplicate_address_warning">This address has already been entered.</string>
+ <string name="dns_content_blockers_title">DNS content blockers</string>
+ <string name="dns_content_blockers_info">When this feature is enabled it stops the device from
+ contacting certain domains or websites known for distributing ads, malware, trackers and
+ more.</string>
+ <string name="dns_content_blockers_warning">This might cause issues on certain websites,
+ services, and programs.</string>
+ <string name="block_ads_title">Ads</string>
+ <string name="block_trackers_title">Trackers</string>
+ <string name="block_malware_title">Malware</string>
+ <string name="malware_info">Warning: The malware blocker is not an anti-virus and should not be
+ treated as such, this is just an extra layer of protection.</string>
+ <string name="block_gambling_title">Gambling</string>
+ <string name="block_adult_content_title">Adult content</string>
+ <string name="dns_content_blockers_subtitle">
+<![CDATA[Disable <b>%s</b> below to activate these settings.]]>
+ </string>
+ <string name="custom_dns_disable_mode_subtitle">
+<![CDATA[Disable all <b>DNS content blockers</b> above to activate this setting.]]>
+ </string>
</resources>