[#1262][#1083][#1241] Privacy policy link

- Closes #1262
- Closes #1083
- Closes #1241
This commit is contained in:
Honza Rychnovský 2024-03-04 18:01:24 +01:00 committed by GitHub
parent 45ab8ce8c9
commit 5bf7a635ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 168 additions and 121 deletions

View File

@ -14,6 +14,7 @@ directly impact users rather than highlighting other key architectural updates.*
Choose server Choose server
- A new Server switching screen was added. Its purpose is to enable switching between predefined and custom - A new Server switching screen was added. Its purpose is to enable switching between predefined and custom
lightwalletd servers in runtime. lightwalletd servers in runtime.
- The About screen now contains a link to the new Zashi Privacy Policy website
## [0.2.0 (560)] - 2024-02-27 ## [0.2.0 (560)] - 2024-02-27

View File

@ -165,6 +165,7 @@ data class ExtendedTypography(
val buttonTextSmall: TextStyle, val buttonTextSmall: TextStyle,
val checkboxText: TextStyle, val checkboxText: TextStyle,
val securityWarningText: TextStyle, val securityWarningText: TextStyle,
val securityWarningFootnote: TextStyle,
val textFieldHint: TextStyle, val textFieldHint: TextStyle,
val textFieldValue: TextStyle, val textFieldValue: TextStyle,
val textFieldBirthday: TextStyle, val textFieldBirthday: TextStyle,
@ -250,7 +251,13 @@ val LocalExtendedTypography =
), ),
securityWarningText = securityWarningText =
PrimaryTypography.bodySmall.copy( PrimaryTypography.bodySmall.copy(
lineHeight = 22.32.sp fontSize = 16.sp,
fontWeight = FontWeight.Medium
),
securityWarningFootnote =
PrimaryTypography.bodySmall.copy(
fontSize = 11.sp,
fontWeight = FontWeight.Medium
), ),
textFieldHint = textFieldHint =
PrimaryTypography.bodySmall.copy( PrimaryTypography.bodySmall.copy(

View File

@ -1,4 +1,4 @@
package co.electriccoin.zcash.ui.screen.securitywarning.util package co.electriccoin.zcash.ui.screen.about.util
import android.content.Intent import android.content.Intent
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest

View File

@ -1,5 +1,6 @@
package co.electriccoin.zcash.ui.screen.about.view package co.electriccoin.zcash.ui.screen.about.view
import androidx.compose.material3.SnackbarHostState
import androidx.compose.ui.test.junit4.ComposeContentTestRule import androidx.compose.ui.test.junit4.ComposeContentTestRule
import co.electriccoin.zcash.ui.common.model.VersionInfo import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@ -24,7 +25,9 @@ class AboutViewTestSetup(
About( About(
onBack = { onBackCount.incrementAndGet() }, onBack = { onBackCount.incrementAndGet() },
versionInfo = versionInfo, versionInfo = versionInfo,
configInfo = configInfo configInfo = configInfo,
onPrivacyPolicy = {},
snackbarHostState = SnackbarHostState()
) )
} }
} }

View File

@ -44,11 +44,6 @@ class SecurityWarningViewTest : UiTestPrerequisites() {
it.assertHasClickAction() it.assertHasClickAction()
it.assertIsNotEnabled() it.assertIsNotEnabled()
} }
composeTestRule.onNodeWithTag(SecurityScreenTag.WARNING_TEXT_TAG).also {
it.assertExists()
it.assertIsDisplayed()
}
} }
@Test @Test

View File

@ -1,6 +1,5 @@
package co.electriccoin.zcash.ui.screen.securitywarning.view package co.electriccoin.zcash.ui.screen.securitywarning.view
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.test.junit4.ComposeContentTestRule import androidx.compose.ui.test.junit4.ComposeContentTestRule
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
@ -34,13 +33,9 @@ class SecurityWarningViewTestSetup(private val composeTestRule: ComposeContentTe
@Suppress("TestFunctionName") @Suppress("TestFunctionName")
fun DefaultContent() { fun DefaultContent() {
SecurityWarning( SecurityWarning(
SnackbarHostState(),
onBack = { onBack = {
onBackCount.incrementAndGet() onBackCount.incrementAndGet()
}, },
onPrivacyPolicy = {
// Not tested yet. UI testing of clicking on an AnnotatedString Text part is complicated.
},
onAcknowledged = { onAcknowledged = {
onAcknowledged.getAndSet(it) onAcknowledged.getAndSet(it)
}, },

View File

@ -2,14 +2,22 @@
package co.electriccoin.zcash.ui.screen.about package co.electriccoin.zcash.ui.screen.about
import android.content.Context
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import co.electriccoin.zcash.configuration.AndroidConfigurationFactory import co.electriccoin.zcash.configuration.AndroidConfigurationFactory
import co.electriccoin.zcash.ui.MainActivity import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.VersionInfo import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.screen.about.util.WebBrowserUtil
import co.electriccoin.zcash.ui.screen.about.view.About import co.electriccoin.zcash.ui.screen.about.view.About
import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@Composable @Composable
internal fun MainActivity.WrapAbout(goBack: () -> Unit) { internal fun MainActivity.WrapAbout(goBack: () -> Unit) {
@ -29,9 +37,37 @@ internal fun WrapAbout(
AndroidConfigurationFactory.getInstance(activity.applicationContext).hintToRefresh() AndroidConfigurationFactory.getInstance(activity.applicationContext).hintToRefresh()
} }
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
About( About(
onBack = goBack, onBack = goBack,
versionInfo = versionInfo, versionInfo = versionInfo,
configInfo = configInfo configInfo = configInfo,
onPrivacyPolicy = {
openPrivacyPolicyInWebBrowser(
activity.applicationContext,
snackbarHostState,
scope
)
},
snackbarHostState = snackbarHostState,
) )
} }
fun openPrivacyPolicyInWebBrowser(
context: Context,
snackbarHostState: SnackbarHostState,
scope: CoroutineScope
) {
val storeIntent = WebBrowserUtil.newActivityIntent(WebBrowserUtil.ZCASH_PRIVACY_POLICY_URI)
runCatching {
context.startActivity(storeIntent)
}.onFailure {
scope.launch {
snackbarHostState.showSnackbar(
message = context.getString(R.string.about_unable_to_web_browser)
)
}
}
}

View File

@ -1,4 +1,4 @@
package co.electriccoin.zcash.ui.screen.securitywarning.util package co.electriccoin.zcash.ui.screen.about.util
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
@ -9,7 +9,7 @@ object WebBrowserUtil {
Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_MULTIPLE_TASK Intent.FLAG_ACTIVITY_MULTIPLE_TASK
const val ZCASH_PRIVACY_POLICY_URI = "https://z.cash/privacy-policy/" // NON-NLS const val ZCASH_PRIVACY_POLICY_URI = "https://electriccoin.co/zashi-privacy-policy/" // NON-NLS
/** /**
* Returns new action view app intent. We assume the a web browser app is installed. * Returns new action view app intent. We assume the a web browser app is installed.

View File

@ -5,4 +5,5 @@ package co.electriccoin.zcash.ui.screen.about.view
*/ */
object AboutTag { object AboutTag {
const val DEBUG_MENU_TAG = "debug_menu" const val DEBUG_MENU_TAG = "debug_menu"
const val PP_TEXT_TAG = "pp_text"
} }

View File

@ -5,10 +5,12 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.ClickableText
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.filled.MoreVert
@ -17,6 +19,8 @@ import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -30,6 +34,10 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.VersionInfo import co.electriccoin.zcash.ui.common.model.VersionInfo
@ -48,7 +56,9 @@ private fun AboutPreview() {
About( About(
onBack = {}, onBack = {},
versionInfo = VersionInfoFixture.new(), versionInfo = VersionInfoFixture.new(),
configInfo = ConfigInfoFixture.new() configInfo = ConfigInfoFixture.new(),
snackbarHostState = SnackbarHostState(),
onPrivacyPolicy = {},
) )
} }
} }
@ -57,18 +67,24 @@ private fun AboutPreview() {
@Composable @Composable
fun About( fun About(
onBack: () -> Unit, onBack: () -> Unit,
configInfo: ConfigInfo,
onPrivacyPolicy: () -> Unit,
snackbarHostState: SnackbarHostState,
versionInfo: VersionInfo, versionInfo: VersionInfo,
configInfo: ConfigInfo
) { ) {
Scaffold(topBar = { Scaffold(
AboutTopAppBar( topBar = {
onBack = onBack, AboutTopAppBar(
versionInfo = versionInfo, onBack = onBack,
configInfo = configInfo versionInfo = versionInfo,
) configInfo = configInfo
}) { paddingValues -> )
},
snackbarHost = { SnackbarHost(snackbarHostState) },
) { paddingValues ->
AboutMainContent( AboutMainContent(
versionInfo = versionInfo, versionInfo = versionInfo,
onPrivacyPolicy = onPrivacyPolicy,
modifier = modifier =
Modifier Modifier
.fillMaxHeight() .fillMaxHeight()
@ -143,6 +159,7 @@ private fun DebugMenu(
@Composable @Composable
fun AboutMainContent( fun AboutMainContent(
onPrivacyPolicy: () -> Unit,
versionInfo: VersionInfo, versionInfo: VersionInfo,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
@ -188,5 +205,49 @@ fun AboutMainContent(
color = ZcashTheme.colors.aboutTextColor, color = ZcashTheme.colors.aboutTextColor,
style = ZcashTheme.extendedTypography.aboutText style = ZcashTheme.extendedTypography.aboutText
) )
PrivacyPolicyLink(onPrivacyPolicy)
}
}
@Composable
fun PrivacyPolicyLink(onPrivacyPolicy: () -> Unit) {
Column {
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
val textPart1 = stringResource(R.string.about_pp_part_1)
val textPart2 = stringResource(R.string.about_pp_part_2)
val textPart3 = stringResource(R.string.about_pp_part_3)
ClickableText(
text =
buildAnnotatedString {
withStyle(SpanStyle(color = ZcashTheme.colors.aboutTextColor)) {
append(textPart1)
}
withStyle(
SpanStyle(
textDecoration = TextDecoration.Underline,
color = ZcashTheme.colors.aboutTextColor,
)
) {
append(textPart2)
}
withStyle(SpanStyle(color = ZcashTheme.colors.aboutTextColor)) {
append(textPart3)
}
},
style = ZcashTheme.extendedTypography.aboutText,
modifier =
Modifier
.fillMaxWidth()
.testTag(AboutTag.PP_TEXT_TAG),
onClick = { letterOffset ->
// Call the callback only if user clicked the underlined part
if (letterOffset >= textPart1.length && letterOffset <= (textPart1.length + textPart2.length)) {
onPrivacyPolicy()
}
}
)
} }
} }

View File

@ -1,20 +1,12 @@
package co.electriccoin.zcash.ui.screen.securitywarning package co.electriccoin.zcash.ui.screen.securitywarning
import android.content.Context
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import co.electriccoin.zcash.configuration.AndroidConfigurationFactory import co.electriccoin.zcash.configuration.AndroidConfigurationFactory
import co.electriccoin.zcash.ui.MainActivity import co.electriccoin.zcash.ui.MainActivity
import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.VersionInfo import co.electriccoin.zcash.ui.common.model.VersionInfo
import co.electriccoin.zcash.ui.screen.securitywarning.util.WebBrowserUtil
import co.electriccoin.zcash.ui.screen.securitywarning.view.SecurityWarning import co.electriccoin.zcash.ui.screen.securitywarning.view.SecurityWarning
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@Composable @Composable
internal fun MainActivity.WrapSecurityWarning( internal fun MainActivity.WrapSecurityWarning(
@ -34,23 +26,12 @@ internal fun WrapSecurityWarning(
onBack: () -> Unit, onBack: () -> Unit,
onConfirm: () -> Unit onConfirm: () -> Unit
) { ) {
val snackbarHostState = remember { SnackbarHostState() }
val scope = rememberCoroutineScope()
SecurityWarning( SecurityWarning(
snackbarHostState = snackbarHostState,
versionInfo = VersionInfo.new(activity.applicationContext), versionInfo = VersionInfo.new(activity.applicationContext),
onBack = onBack, onBack = onBack,
onAcknowledged = { onAcknowledged = {
// Needed for UI testing only // Needed for UI testing only
}, },
onPrivacyPolicy = {
openPrivacyPolicyInWebBrowser(
activity.applicationContext,
snackbarHostState,
scope
)
},
onConfirm = onConfirm onConfirm = onConfirm
) )
@ -58,20 +39,3 @@ internal fun WrapSecurityWarning(
AndroidConfigurationFactory.getInstance(activity.applicationContext).hintToRefresh() AndroidConfigurationFactory.getInstance(activity.applicationContext).hintToRefresh()
} }
} }
fun openPrivacyPolicyInWebBrowser(
context: Context,
snackbarHostState: SnackbarHostState,
scope: CoroutineScope
) {
val storeIntent = WebBrowserUtil.newActivityIntent(WebBrowserUtil.ZCASH_PRIVACY_POLICY_URI)
runCatching {
context.startActivity(storeIntent)
}.onFailure {
scope.launch {
snackbarHostState.showSnackbar(
message = context.getString(R.string.security_warning_unable_to_web_browser)
)
}
}
}

View File

@ -5,5 +5,4 @@ package co.electriccoin.zcash.ui.screen.securitywarning.view
*/ */
object SecurityScreenTag { object SecurityScreenTag {
const val ACKNOWLEDGE_CHECKBOX_TAG = "acknowledge_checkbox" const val ACKNOWLEDGE_CHECKBOX_TAG = "acknowledge_checkbox"
const val WARNING_TEXT_TAG = "warning_text"
} }

View File

@ -8,22 +8,18 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.ClickableText
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost import androidx.compose.material3.Text
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.withStyle import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.R
@ -43,11 +39,9 @@ private fun SecurityWarningPreview() {
ZcashTheme(forceDarkMode = false) { ZcashTheme(forceDarkMode = false) {
GradientSurface { GradientSurface {
SecurityWarning( SecurityWarning(
snackbarHostState = SnackbarHostState(),
versionInfo = VersionInfoFixture.new(), versionInfo = VersionInfoFixture.new(),
onBack = {}, onBack = {},
onAcknowledged = {}, onAcknowledged = {},
onPrivacyPolicy = {},
onConfirm = {}, onConfirm = {},
) )
} }
@ -60,20 +54,16 @@ private fun SecurityWarningPreview() {
@Composable @Composable
@Suppress("LongParameterList") @Suppress("LongParameterList")
fun SecurityWarning( fun SecurityWarning(
snackbarHostState: SnackbarHostState,
versionInfo: VersionInfo, versionInfo: VersionInfo,
onBack: () -> Unit, onBack: () -> Unit,
onAcknowledged: (Boolean) -> Unit, onAcknowledged: (Boolean) -> Unit,
onPrivacyPolicy: () -> Unit,
onConfirm: () -> Unit, onConfirm: () -> Unit,
) { ) {
Scaffold( Scaffold(
topBar = { SecurityWarningTopAppBar(onBack = onBack) }, topBar = { SecurityWarningTopAppBar(onBack = onBack) },
snackbarHost = { SnackbarHost(snackbarHostState) },
) { paddingValues -> ) { paddingValues ->
SecurityWarningContent( SecurityWarningContent(
versionInfo = versionInfo, versionInfo = versionInfo,
onPrivacyPolicy = onPrivacyPolicy,
onAcknowledged = onAcknowledged, onAcknowledged = onAcknowledged,
onConfirm = onConfirm, onConfirm = onConfirm,
modifier = modifier =
@ -102,7 +92,6 @@ private fun SecurityWarningTopAppBar(onBack: () -> Unit) {
@Composable @Composable
private fun SecurityWarningContent( private fun SecurityWarningContent(
versionInfo: VersionInfo, versionInfo: VersionInfo,
onPrivacyPolicy: () -> Unit,
onAcknowledged: (Boolean) -> Unit, onAcknowledged: (Boolean) -> Unit,
onConfirm: () -> Unit, onConfirm: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -119,11 +108,10 @@ private fun SecurityWarningContent(
Spacer(Modifier.height(ZcashTheme.dimens.spacingLarge)) Spacer(Modifier.height(ZcashTheme.dimens.spacingLarge))
SecurityWarningContentText( SecurityWarningContentText(
versionInfo = versionInfo, versionInfo = versionInfo
onPrivacyPolicy = onPrivacyPolicy
) )
Spacer(Modifier.height(ZcashTheme.dimens.spacingDefault)) Spacer(Modifier.height(ZcashTheme.dimens.spacingLarge))
val checkedState = rememberSaveable { mutableStateOf(false) } val checkedState = rememberSaveable { mutableStateOf(false) }
CheckBox( CheckBox(
@ -158,35 +146,28 @@ private fun SecurityWarningContent(
} }
@Composable @Composable
fun SecurityWarningContentText( fun SecurityWarningContentText(versionInfo: VersionInfo) {
versionInfo: VersionInfo, Column {
onPrivacyPolicy: () -> Unit, Text(
) { text = stringResource(id = R.string.security_warning_text, versionInfo.versionName),
val textPart1 = stringResource(R.string.security_warning_text_part_1, versionInfo.versionName) style = ZcashTheme.extendedTypography.securityWarningText
val textPart2 = stringResource(R.string.security_warning_text_part_2) )
ClickableText(
text = Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingLarge))
buildAnnotatedString {
append(textPart1) val textPart1 = stringResource(R.string.security_warning_text_footnote_part_1)
withStyle(SpanStyle(textDecoration = TextDecoration.Underline)) { val textPart2 = stringResource(R.string.security_warning_text_footnote_part_2)
Text(
text =
buildAnnotatedString {
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
append(textPart1)
}
append(textPart2) append(textPart2)
} },
append(stringResource(R.string.security_warning_text_part_3)) style = ZcashTheme.extendedTypography.securityWarningFootnote,
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { modifier = Modifier.fillMaxWidth()
append(stringResource(R.string.security_warning_text_part_4)) )
} }
append(stringResource(R.string.security_warning_text_part_5))
},
style = ZcashTheme.extendedTypography.securityWarningText,
modifier =
Modifier
.fillMaxWidth()
.testTag(SecurityScreenTag.WARNING_TEXT_TAG),
onClick = { letterOffset ->
// Call the callback only if user clicked the underlined part
if (letterOffset >= textPart1.length && letterOffset <= (textPart1.length + textPart2.length)) {
onPrivacyPolicy()
}
}
)
} }

View File

@ -12,4 +12,9 @@
shielded wallet that keeps your transaction history and wallet balance private. Built by Zcashers, for shielded wallet that keeps your transaction history and wallet balance private. Built by Zcashers, for
Zcashers. Developed and maintained by Electric Coin Co., the inventor of Zcash, Zashi features a built-in Zcashers. Developed and maintained by Electric Coin Co., the inventor of Zcash, Zashi features a built-in
user-feedback mechanism to enable more features, more quickly.</string> user-feedback mechanism to enable more features, more quickly.</string>
<string name="about_pp_part_1">See our Privacy Policy\u0020</string>
<string name="about_pp_part_2">here</string>
<string name="about_pp_part_3">.</string>
<string name="about_unable_to_web_browser">Unable to find a web browser app.</string>
</resources> </resources>

View File

@ -1,18 +1,17 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="security_warning_text_part_1" formatted="true">Zashi <xliff:g example="0.2.0" id="version_name">%1$s
</xliff:g>is a Zcash-only shielded wallet, built by Zcashers for Zcashers. The purpose of this release is
primarily to test functionality and collect feedback. While Zashi has been engineered for your privacy and
safety (read the privacy policy\u0020</string>
<string name="security_warning_text_part_2">here</string>
<string name="security_warning_text_part_3">), this release has not yet been security audited.</string>
<string name="security_warning_text_part_4">\u0020Users are cautioned to deposit, send, and receive only small
amounts
of ZEC.</string>
<string name="security_warning_text_part_5">\u0020Please click below to proceed.</string>
<string name="security_warning_confirm">confirm</string>
<string name="security_warning_acknowledge">I acknowledge</string>
<string name="security_warning_back_content_description">Back</string>
<string name="security_warning_header">Security warning:</string> <string name="security_warning_header">Security warning:</string>
<string name="security_warning_back">Back</string> <string name="security_warning_back">Back</string>
<string name="security_warning_unable_to_web_browser">Unable to find a web browser app.</string> <string name="security_warning_back_content_description">Back</string>
<string name="security_warning_text" formatted="true">Zashi <xliff:g example="0.2.0" id="version_name">%1$s
</xliff:g>is a Zcash-only, shielded wallet — built by Zcashers for Zcashers. Zashi has been engineered for your
privacy and safety. By installing and using Zashi, you consent to share crash reports with Electric Coin Co.
(the wallet developer), which will help us improve the Zashi user experience.*\n\nPlease acknowledge and
confirm below to proceed.</string>
<string name="security_warning_text_footnote_part_1">*Note:</string>
<string name="security_warning_text_footnote_part_2">\u0020Crash reports might reveal the timing of the crash and
what events occurred, but it would not reveal spending or viewing keys.</string>
<string name="security_warning_confirm">Confirm</string>
<string name="security_warning_acknowledge">I acknowledge</string>
</resources> </resources>