Loading app/build.gradle +3 −3 Original line number Diff line number Diff line Loading @@ -56,7 +56,7 @@ android { composeOptions { // Keep this in sync with Kotlin version: // https://developer.android.com/jetpack/androidx/releases/compose-kotlin kotlinCompilerExtensionVersion = "1.5.4" kotlinCompilerExtensionVersion = "1.5.5" } // Java namespace for our classes (not to be confused with Android package ID) Loading Loading @@ -193,7 +193,7 @@ dependencies { implementation 'commons-io:commons-io:2.8.0' //noinspection GradleDependency - dnsjava 3.x requires Android 8 [https://github.com/bitfireAT/davx5/issues/453] implementation 'dnsjava:dnsjava:2.1.9' implementation "io.github.nsk90:kstatemachine-jvm:0.22.1" implementation 'io.github.nsk90:kstatemachine-jvm:0.23.0' implementation 'net.openid:appauth:0.11.1' implementation "org.apache.commons:commons-collections4:${versions.commonsCollections}" implementation "org.apache.commons:commons-lang3:${versions.commonsLang}" Loading app/src/main/kotlin/at/bitfire/davdroid/ui/UiUtils.kt +17 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ import android.net.Uri import android.os.Build import android.text.Spanned import android.text.style.StyleSpan import android.text.style.URLSpan import android.widget.Toast import androidx.annotation.DrawableRes import androidx.appcompat.app.AppCompatDelegate Loading @@ -26,10 +27,13 @@ import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.ExperimentalTextApi import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.UrlAnnotation import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextDecoration import androidx.core.content.getSystemService import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.drawable.toBitmap Loading Loading @@ -120,6 +124,7 @@ object UiUtils { } @OptIn(ExperimentalTextApi::class) @Composable fun Spanned.toAnnotatedString() = buildAnnotatedString { val spanned = this@toAnnotatedString Loading @@ -139,6 +144,18 @@ object UiUtils { start = start, end = end ) } is URLSpan -> { addUrlAnnotation( UrlAnnotation(span.url), start = start, end = end ) addStyle( SpanStyle(textDecoration = TextDecoration.Underline), start = start, end = end ) } else -> Logger.log.warning("Ignoring unknown span type ${span.javaClass.name}") } } } Loading app/src/main/kotlin/at/bitfire/davdroid/ui/setup/GoogleLoginFragment.kt +27 −20 Original line number Diff line number Diff line Loading @@ -10,11 +10,9 @@ import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle import android.text.method.LinkMovementMethod import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.activity.result.contract.ActivityResultContract import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column Loading @@ -24,6 +22,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.ClickableText import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll Loading @@ -44,12 +43,13 @@ import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.ExperimentalTextApi import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import androidx.core.net.toUri import androidx.core.text.HtmlCompat import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels Loading @@ -63,6 +63,7 @@ import at.bitfire.davdroid.R import at.bitfire.davdroid.db.Credentials import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.ui.UiUtils import at.bitfire.davdroid.ui.UiUtils.toAnnotatedString import com.google.accompanist.themeadapter.material.MdcTheme import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint Loading Loading @@ -217,6 +218,7 @@ class GoogleLoginFragment(private val defaultEmail: String? = null): Fragment() } @OptIn(ExperimentalTextApi::class) @Composable fun GoogleLogin( defaultEmail: String?, Loading Loading @@ -326,25 +328,30 @@ fun GoogleLogin( ) } AndroidView({ context -> TextView(context, null, 0, com.google.accompanist.themeadapter.material.R.style.TextAppearance_MaterialComponents_Body2).apply { text = HtmlCompat.fromHtml(context.getString(R.string.login_google_client_privacy_policy, context.getString(R.string.app_name), App.homepageUrl(context, App.HOMEPAGE_PRIVACY) ), 0) movementMethod = LinkMovementMethod.getInstance() val privacyPolicyNote = HtmlCompat.fromHtml( stringResource(R.string.login_google_client_privacy_policy, context.getString(R.string.app_name), App.homepageUrl(context, App.HOMEPAGE_PRIVACY)), 0).toAnnotatedString() ClickableText( privacyPolicyNote, style = MaterialTheme.typography.body2, onClick = { position -> privacyPolicyNote.getUrlAnnotations(position, position).firstOrNull()?.let { UiUtils.launchUri(context, it.item.url.toUri()) } }, modifier = Modifier.padding(top = 12.dp)) AndroidView({ context -> TextView(context, null, 0, com.google.accompanist.themeadapter.material.R.style.TextAppearance_MaterialComponents_Body2).apply { text = HtmlCompat.fromHtml(context.getString(R.string.login_google_client_limited_use, context.getString(R.string.app_name), GoogleLoginFragment.GOOGLE_POLICY_URL ), 0) movementMethod = LinkMovementMethod.getInstance() } }, modifier = Modifier.padding(top = 12.dp)) ) val limitedUseNote = HtmlCompat.fromHtml( stringResource(R.string.login_google_client_limited_use, context.getString(R.string.app_name), GoogleLoginFragment.GOOGLE_POLICY_URL), 0).toAnnotatedString() ClickableText( limitedUseNote, style = MaterialTheme.typography.body2, modifier = Modifier.padding(top = 12.dp), onClick = { position -> limitedUseNote.getUrlAnnotations(position, position).firstOrNull()?.let { UiUtils.launchUri(context, it.item.url.toUri()) } } ) } } } Loading build.gradle +3 −3 Original line number Diff line number Diff line Loading @@ -4,11 +4,11 @@ buildscript { ext.versions = [ aboutLibraries: '10.9.1', accompanist: '0.30.1', aboutLibraries: '10.9.2', accompanist: '0.32.0', appIntro: '7.0.0-beta02', composeBom: '2023.10.01', hilt: '2.48.1', hilt: '2.49', kotlin: '1.9.20', // keep in sync with * app/build.gradle composeOptions.kotlinCompilerExtensionVersion // * com.google.devtools.ksp at the end of this file okhttp: '4.12.0', Loading Loading
app/build.gradle +3 −3 Original line number Diff line number Diff line Loading @@ -56,7 +56,7 @@ android { composeOptions { // Keep this in sync with Kotlin version: // https://developer.android.com/jetpack/androidx/releases/compose-kotlin kotlinCompilerExtensionVersion = "1.5.4" kotlinCompilerExtensionVersion = "1.5.5" } // Java namespace for our classes (not to be confused with Android package ID) Loading Loading @@ -193,7 +193,7 @@ dependencies { implementation 'commons-io:commons-io:2.8.0' //noinspection GradleDependency - dnsjava 3.x requires Android 8 [https://github.com/bitfireAT/davx5/issues/453] implementation 'dnsjava:dnsjava:2.1.9' implementation "io.github.nsk90:kstatemachine-jvm:0.22.1" implementation 'io.github.nsk90:kstatemachine-jvm:0.23.0' implementation 'net.openid:appauth:0.11.1' implementation "org.apache.commons:commons-collections4:${versions.commonsCollections}" implementation "org.apache.commons:commons-lang3:${versions.commonsLang}" Loading
app/src/main/kotlin/at/bitfire/davdroid/ui/UiUtils.kt +17 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ import android.net.Uri import android.os.Build import android.text.Spanned import android.text.style.StyleSpan import android.text.style.URLSpan import android.widget.Toast import androidx.annotation.DrawableRes import androidx.appcompat.app.AppCompatDelegate Loading @@ -26,10 +27,13 @@ import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.ExperimentalTextApi import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.UrlAnnotation import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextDecoration import androidx.core.content.getSystemService import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.drawable.toBitmap Loading Loading @@ -120,6 +124,7 @@ object UiUtils { } @OptIn(ExperimentalTextApi::class) @Composable fun Spanned.toAnnotatedString() = buildAnnotatedString { val spanned = this@toAnnotatedString Loading @@ -139,6 +144,18 @@ object UiUtils { start = start, end = end ) } is URLSpan -> { addUrlAnnotation( UrlAnnotation(span.url), start = start, end = end ) addStyle( SpanStyle(textDecoration = TextDecoration.Underline), start = start, end = end ) } else -> Logger.log.warning("Ignoring unknown span type ${span.javaClass.name}") } } } Loading
app/src/main/kotlin/at/bitfire/davdroid/ui/setup/GoogleLoginFragment.kt +27 −20 Original line number Diff line number Diff line Loading @@ -10,11 +10,9 @@ import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle import android.text.method.LinkMovementMethod import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView import androidx.activity.result.contract.ActivityResultContract import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column Loading @@ -24,6 +22,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.ClickableText import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll Loading @@ -44,12 +43,13 @@ import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.ExperimentalTextApi import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import androidx.core.net.toUri import androidx.core.text.HtmlCompat import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels Loading @@ -63,6 +63,7 @@ import at.bitfire.davdroid.R import at.bitfire.davdroid.db.Credentials import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.ui.UiUtils import at.bitfire.davdroid.ui.UiUtils.toAnnotatedString import com.google.accompanist.themeadapter.material.MdcTheme import com.google.android.material.snackbar.Snackbar import dagger.hilt.android.AndroidEntryPoint Loading Loading @@ -217,6 +218,7 @@ class GoogleLoginFragment(private val defaultEmail: String? = null): Fragment() } @OptIn(ExperimentalTextApi::class) @Composable fun GoogleLogin( defaultEmail: String?, Loading Loading @@ -326,25 +328,30 @@ fun GoogleLogin( ) } AndroidView({ context -> TextView(context, null, 0, com.google.accompanist.themeadapter.material.R.style.TextAppearance_MaterialComponents_Body2).apply { text = HtmlCompat.fromHtml(context.getString(R.string.login_google_client_privacy_policy, context.getString(R.string.app_name), App.homepageUrl(context, App.HOMEPAGE_PRIVACY) ), 0) movementMethod = LinkMovementMethod.getInstance() val privacyPolicyNote = HtmlCompat.fromHtml( stringResource(R.string.login_google_client_privacy_policy, context.getString(R.string.app_name), App.homepageUrl(context, App.HOMEPAGE_PRIVACY)), 0).toAnnotatedString() ClickableText( privacyPolicyNote, style = MaterialTheme.typography.body2, onClick = { position -> privacyPolicyNote.getUrlAnnotations(position, position).firstOrNull()?.let { UiUtils.launchUri(context, it.item.url.toUri()) } }, modifier = Modifier.padding(top = 12.dp)) AndroidView({ context -> TextView(context, null, 0, com.google.accompanist.themeadapter.material.R.style.TextAppearance_MaterialComponents_Body2).apply { text = HtmlCompat.fromHtml(context.getString(R.string.login_google_client_limited_use, context.getString(R.string.app_name), GoogleLoginFragment.GOOGLE_POLICY_URL ), 0) movementMethod = LinkMovementMethod.getInstance() } }, modifier = Modifier.padding(top = 12.dp)) ) val limitedUseNote = HtmlCompat.fromHtml( stringResource(R.string.login_google_client_limited_use, context.getString(R.string.app_name), GoogleLoginFragment.GOOGLE_POLICY_URL), 0).toAnnotatedString() ClickableText( limitedUseNote, style = MaterialTheme.typography.body2, modifier = Modifier.padding(top = 12.dp), onClick = { position -> limitedUseNote.getUrlAnnotations(position, position).firstOrNull()?.let { UiUtils.launchUri(context, it.item.url.toUri()) } } ) } } } Loading
build.gradle +3 −3 Original line number Diff line number Diff line Loading @@ -4,11 +4,11 @@ buildscript { ext.versions = [ aboutLibraries: '10.9.1', accompanist: '0.30.1', aboutLibraries: '10.9.2', accompanist: '0.32.0', appIntro: '7.0.0-beta02', composeBom: '2023.10.01', hilt: '2.48.1', hilt: '2.49', kotlin: '1.9.20', // keep in sync with * app/build.gradle composeOptions.kotlinCompilerExtensionVersion // * com.google.devtools.ksp at the end of this file okhttp: '4.12.0', Loading