From a0ff2b2eebea48e197d2500eaaa66a381a3fc444 Mon Sep 17 00:00:00 2001 From: FunkyMuse Date: Mon, 9 Oct 2023 19:10:06 +0200 Subject: [PATCH] feat: write permission dialog and few other fixes along the way --- commons/build.gradle.kts | 2 + .../commons/activities/BaseSimpleActivity.kt | 4 +- .../components/LinkifyTextComponent.kt | 56 +++++ .../components/RadioButtonDialogComponent.kt | 2 +- .../extensions/ComposeActivityExtensions.kt | 2 +- .../compose/extensions/ComposeExtensions.kt | 13 + .../compose/lists/SimpleScaffoldTopBar.kt | 8 +- .../commons/compose/menus/ActionMenu.kt | 4 +- .../compose/screens/ContributorsScreen.kt | 12 +- .../commons/compose/screens/FAQScreen.kt | 59 +---- .../commons/compose/screens/LicenseScreen.kt | 4 +- .../screens/ManageBlockedNumbersScreen.kt | 22 +- .../settings/SettingsCheckBoxComponent.kt | 4 +- .../commons/compose/settings/SettingsGroup.kt | 2 +- .../compose/settings/SettingsListItem.kt | 4 +- .../settings/SettingsTitleTextComponent.kt | 4 +- .../commons/compose/theme/Dimensions.kt | 2 +- .../commons/compose/theme/model/Dimensions.kt | 4 +- .../commons/dialogs/AppSideloadedDialog.kt | 12 +- .../dialogs/ChangeDateTimeFormatDialog.kt | 6 +- .../commons/dialogs/ChangeViewTypeDialog.kt | 6 +- .../commons/dialogs/ColorPickerDialog.kt | 2 +- .../commons/dialogs/DonateDialog.kt | 7 +- .../commons/dialogs/FeatureLockedDialog.kt | 15 +- .../commons/dialogs/LineColorPickerDialog.kt | 11 +- .../commons/dialogs/PurchaseThankYouDialog.kt | 15 +- .../commons/dialogs/RadioGroupDialog.kt | 6 +- .../commons/dialogs/RateStarsDialog.kt | 6 +- .../commons/dialogs/UpgradeToProDialog.kt | 2 +- .../commons/dialogs/WritePermissionDialog.kt | 238 ++++++++++++++++-- .../commons/extensions/Activity.kt | 10 +- .../commons/extensions/String.kt | 30 ++- .../samples/activities/MainActivity.kt | 2 +- .../samples/activities/TestDialogActivity.kt | 13 + 34 files changed, 416 insertions(+), 173 deletions(-) create mode 100644 commons/src/main/kotlin/com/simplemobiletools/commons/compose/components/LinkifyTextComponent.kt diff --git a/commons/build.gradle.kts b/commons/build.gradle.kts index 93ca6e7d2..d9b5d2cd7 100644 --- a/commons/build.gradle.kts +++ b/commons/build.gradle.kts @@ -51,6 +51,7 @@ android { "-opt-in=androidx.compose.material3.ExperimentalMaterial3Api", "-opt-in=androidx.compose.material.ExperimentalMaterialApi", "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi", + "-opt-in=com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi", "-Xcontext-receivers" ) } @@ -98,6 +99,7 @@ dependencies { api(libs.material) api(libs.gson) + implementation(libs.glide.compose) api(libs.glide) ksp(libs.glide.compiler) diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/activities/BaseSimpleActivity.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/activities/BaseSimpleActivity.kt index bfdc29fc3..1f27ae708 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/activities/BaseSimpleActivity.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/activities/BaseSimpleActivity.kt @@ -43,7 +43,7 @@ import com.simplemobiletools.commons.R import com.simplemobiletools.commons.asynctasks.CopyMoveTask import com.simplemobiletools.commons.compose.extensions.DEVELOPER_PLAY_STORE_URL import com.simplemobiletools.commons.dialogs.* -import com.simplemobiletools.commons.dialogs.WritePermissionDialog.Mode +import com.simplemobiletools.commons.dialogs.WritePermissionDialog.WritePermissionDialogMode import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.interfaces.CopyMoveListener @@ -760,7 +760,7 @@ abstract class BaseSimpleActivity : AppCompatActivity() { } funAfterSAFPermission = callback - WritePermissionDialog(this, Mode.Otg) { + WritePermissionDialog(this, WritePermissionDialogMode.Otg) { Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply { try { startActivityForResult(this, OPEN_DOCUMENT_TREE_OTG) diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/components/LinkifyTextComponent.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/components/LinkifyTextComponent.kt new file mode 100644 index 000000000..aaefed1f7 --- /dev/null +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/components/LinkifyTextComponent.kt @@ -0,0 +1,56 @@ +package com.simplemobiletools.commons.compose.components + +import android.text.Spanned +import android.text.method.LinkMovementMethod +import android.widget.TextView +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.sp +import androidx.compose.ui.viewinterop.AndroidView +import com.simplemobiletools.commons.R +import com.simplemobiletools.commons.compose.extensions.MyDevices +import com.simplemobiletools.commons.compose.theme.AppThemeSurface +import com.simplemobiletools.commons.compose.theme.SimpleTheme +import com.simplemobiletools.commons.extensions.fromHtml +import com.simplemobiletools.commons.extensions.removeUnderlines + +@Composable +fun LinkifyTextComponent( + modifier: Modifier = Modifier, + fontSize: TextUnit = 14.sp, + removeUnderlines: Boolean = true, + textAlignment: Int = TextView.TEXT_ALIGNMENT_TEXT_START, + text: () -> Spanned +) { + val context = LocalContext.current + val customLinkifyTextView = remember { + TextView(context) + } + val textColor = SimpleTheme.colorScheme.onSurface + val linkTextColor = SimpleTheme.colorScheme.primary + AndroidView(modifier = modifier, factory = { customLinkifyTextView }) { textView -> + textView.setTextColor(textColor.toArgb()) + textView.setLinkTextColor(linkTextColor.toArgb()) + textView.text = text() + textView.textAlignment = textAlignment + textView.textSize = fontSize.value + textView.movementMethod = LinkMovementMethod.getInstance() + if (removeUnderlines) { + customLinkifyTextView.removeUnderlines() + } + } +} + +@Composable +@MyDevices +private fun LinkifyTextComponentPreview() = AppThemeSurface { + val source = stringResource(id = R.string.contributors_label) + LinkifyTextComponent { + source.fromHtml() + } +} diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/components/RadioButtonDialogComponent.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/components/RadioButtonDialogComponent.kt index c8a730202..c32112c43 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/components/RadioButtonDialogComponent.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/components/RadioButtonDialogComponent.kt @@ -46,7 +46,7 @@ fun RadioButtonDialogComponent( ) Text( text = item, - modifier = Modifier.padding(start = SimpleTheme.dimens.margin.medium), + modifier = Modifier.padding(start = SimpleTheme.dimens.padding.medium), color = dialogTextColor ) } diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/extensions/ComposeActivityExtensions.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/extensions/ComposeActivityExtensions.kt index a11004bca..c2c4e0282 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/extensions/ComposeActivityExtensions.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/extensions/ComposeActivityExtensions.kt @@ -10,7 +10,7 @@ import com.simplemobiletools.commons.extensions.launchViewIntent @Composable fun FakeVersionCheck() { - val context = LocalContext.current.getActivity() + val context = LocalContext.current val confirmationDialogAlertDialogState = rememberAlertDialogState().apply { DialogMember { ConfirmationAlertDialog( diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/extensions/ComposeExtensions.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/extensions/ComposeExtensions.kt index 0dff7ee98..fdc71e0fc 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/extensions/ComposeExtensions.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/extensions/ComposeExtensions.kt @@ -12,7 +12,9 @@ import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.runtime.* import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.platform.LocalView import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp @@ -22,10 +24,12 @@ import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.compose.LifecycleEventEffect import androidx.lifecycle.compose.LifecycleResumeEffect import androidx.lifecycle.compose.LifecycleStartEffect +import com.simplemobiletools.commons.R import com.simplemobiletools.commons.compose.system_ui_controller.rememberSystemUiController import com.simplemobiletools.commons.compose.theme.SimpleTheme import com.simplemobiletools.commons.compose.theme.isLitWell import com.simplemobiletools.commons.extensions.darkenColor +import com.simplemobiletools.commons.extensions.launchViewIntent fun Context.getActivity(): Activity { return when (this) { @@ -158,3 +162,12 @@ internal fun TransparentSystemBars(darkIcons: Boolean = !isSystemInDarkTheme()) onDispose { } } } + +@Composable +fun composeDonateIntent(): () -> Unit { + val localContext = LocalContext.current + val localView = LocalView.current + return { + if (localView.isInEditMode) Unit else localContext.getActivity().launchViewIntent(R.string.thank_you_url) + } +} diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/lists/SimpleScaffoldTopBar.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/lists/SimpleScaffoldTopBar.kt index 78be5d22d..330a75070 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/lists/SimpleScaffoldTopBar.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/lists/SimpleScaffoldTopBar.kt @@ -39,7 +39,7 @@ fun SimpleScaffoldTopBar( Text( text = title, modifier = Modifier - .padding(start = SimpleTheme.dimens.margin.medium) + .padding(start = SimpleTheme.dimens.padding.medium) .fillMaxWidth(), color = scrolledColor, maxLines = 1, @@ -157,7 +157,7 @@ fun SimpleNavigationIcon( ) { Box( modifier - .padding(start = SimpleTheme.dimens.margin.medium) + .padding(start = SimpleTheme.dimens.padding.medium) .clip(RoundedCornerShape(50)) .clickable( navigationIconInteractionSource, rememberRipple( @@ -175,13 +175,13 @@ fun SimpleBackIcon(iconColor: Color?) { if (iconColor == null) { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(id = R.string.back), - modifier = Modifier.padding(SimpleTheme.dimens.margin.small) + modifier = Modifier.padding(SimpleTheme.dimens.padding.small) ) } else { Icon( imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(id = R.string.back), tint = iconColor, - modifier = Modifier.padding(SimpleTheme.dimens.margin.small) + modifier = Modifier.padding(SimpleTheme.dimens.padding.small) ) } } diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/menus/ActionMenu.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/menus/ActionMenu.kt index c4077e097..1ea6780e4 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/menus/ActionMenu.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/menus/ActionMenu.kt @@ -96,7 +96,7 @@ fun ActionMenu( Text( text = name, fontSize = 14.sp, - modifier = Modifier.padding(SimpleTheme.dimens.margin.medium), + modifier = Modifier.padding(SimpleTheme.dimens.padding.medium), ) } }, @@ -125,7 +125,7 @@ fun ActionMenu( Text( text = stringResource(id = R.string.more_options), fontSize = 14.sp, - modifier = Modifier.padding(SimpleTheme.dimens.margin.medium), + modifier = Modifier.padding(SimpleTheme.dimens.padding.medium), ) } }, diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/ContributorsScreen.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/ContributorsScreen.kt index f2e7287f9..9c9e9d870 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/ContributorsScreen.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/ContributorsScreen.kt @@ -16,6 +16,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.simplemobiletools.commons.R +import com.simplemobiletools.commons.compose.components.LinkifyTextComponent import com.simplemobiletools.commons.compose.extensions.MyDevices import com.simplemobiletools.commons.compose.lists.SimpleLazyListScaffold import com.simplemobiletools.commons.compose.settings.SettingsGroupTitle @@ -24,6 +25,7 @@ import com.simplemobiletools.commons.compose.settings.SettingsListItem import com.simplemobiletools.commons.compose.settings.SettingsTitleTextComponent import com.simplemobiletools.commons.compose.theme.AppThemeSurface import com.simplemobiletools.commons.compose.theme.SimpleTheme +import com.simplemobiletools.commons.extensions.fromHtml import com.simplemobiletools.commons.models.LanguageContributor import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList @@ -64,7 +66,7 @@ internal fun ContributorsScreen( ) } item { - Spacer(modifier = Modifier.padding(vertical = SimpleTheme.dimens.margin.medium)) + Spacer(modifier = Modifier.padding(vertical = SimpleTheme.dimens.padding.medium)) } item { SettingsHorizontalDivider() @@ -85,15 +87,15 @@ internal fun ContributorsScreen( icon = R.drawable.ic_heart_vector, text = { val source = stringResource(id = R.string.contributors_label) - LinkifyText { - stringFromHTML(source) + LinkifyTextComponent { + source.fromHtml() } }, tint = SimpleTheme.colorScheme.onSurface ) } item { - Spacer(modifier = Modifier.padding(bottom = SimpleTheme.dimens.margin.medium)) + Spacer(modifier = Modifier.padding(bottom = SimpleTheme.dimens.padding.medium)) } } @@ -117,7 +119,7 @@ private fun ContributorItem( leadingContent = { val imageSize = Modifier .size(SimpleTheme.dimens.icon.medium) - .padding(SimpleTheme.dimens.margin.medium) + .padding(SimpleTheme.dimens.padding.medium) Image( modifier = imageSize, painter = painterResource(id = languageContributor.iconId), diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/FAQScreen.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/FAQScreen.kt index 99e939c98..4dd92b9bd 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/FAQScreen.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/FAQScreen.kt @@ -1,31 +1,22 @@ package com.simplemobiletools.commons.compose.screens -import android.os.Build -import android.text.Html -import android.text.Spanned -import android.text.method.LinkMovementMethod -import android.widget.TextView import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material3.ListItem import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.compose.ui.viewinterop.AndroidView import com.simplemobiletools.commons.R +import com.simplemobiletools.commons.compose.components.LinkifyTextComponent import com.simplemobiletools.commons.compose.extensions.MyDevices import com.simplemobiletools.commons.compose.lists.SimpleLazyListScaffold import com.simplemobiletools.commons.compose.settings.SettingsHorizontalDivider import com.simplemobiletools.commons.compose.theme.AppThemeSurface import com.simplemobiletools.commons.compose.theme.SimpleTheme -import com.simplemobiletools.commons.extensions.removeUnderlines +import com.simplemobiletools.commons.extensions.fromHtml import com.simplemobiletools.commons.models.FAQItem import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList @@ -38,7 +29,7 @@ internal fun FAQScreen( SimpleLazyListScaffold( title = stringResource(id = R.string.frequently_asked_questions), goBack = goBack, - contentPadding = PaddingValues(bottom = SimpleTheme.dimens.margin.medium) + contentPadding = PaddingValues(bottom = SimpleTheme.dimens.padding.medium) ) { itemsIndexed(faqItems) { index, faqItem -> Column(modifier = Modifier.fillMaxWidth()) { @@ -56,8 +47,8 @@ internal fun FAQScreen( }, supportingContent = { if (faqItem.text is Int) { - val text = stringFromHTML(stringResource(id = faqItem.text)) - LinkifyText( + val text = stringResource(id = faqItem.text).fromHtml() + LinkifyTextComponent( text = { text }, modifier = Modifier.fillMaxWidth(), fontSize = 14.sp @@ -71,12 +62,12 @@ internal fun FAQScreen( } }, ) - Spacer(modifier = Modifier.padding(bottom = SimpleTheme.dimens.margin.medium)) + Spacer(modifier = Modifier.padding(bottom = SimpleTheme.dimens.padding.medium)) if (index != faqItems.lastIndex) { SettingsHorizontalDivider( modifier = Modifier .fillMaxWidth() - .padding(bottom = SimpleTheme.dimens.margin.small) + .padding(bottom = SimpleTheme.dimens.padding.small) ) } } @@ -84,42 +75,6 @@ internal fun FAQScreen( } } -@Suppress("deprecation") -fun stringFromHTML(source: String): Spanned { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY) - } else { - Html.fromHtml(source) - } -} - -@Composable -fun LinkifyText( - modifier: Modifier = Modifier, - fontSize: TextUnit = 14.sp, - removeUnderlines: Boolean = true, - textAlignment: Int = TextView.TEXT_ALIGNMENT_TEXT_START, - text: () -> Spanned -) { - val context = LocalContext.current - val customLinkifyTextView = remember { - TextView(context) - } - val textColor = SimpleTheme.colorScheme.onSurface - val linkTextColor = SimpleTheme.colorScheme.primary - AndroidView(modifier = modifier, factory = { customLinkifyTextView }) { textView -> - textView.setTextColor(textColor.toArgb()) - textView.setLinkTextColor(linkTextColor.toArgb()) - textView.text = text() - textView.textAlignment = textAlignment - textView.textSize = fontSize.value - textView.movementMethod = LinkMovementMethod.getInstance() - if (removeUnderlines) { - customLinkifyTextView.removeUnderlines() - } - } -} - @MyDevices @Composable private fun FAQScreenPreview() { diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/LicenseScreen.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/LicenseScreen.kt index ace9c863b..c21fcf3bd 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/LicenseScreen.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/LicenseScreen.kt @@ -35,7 +35,7 @@ internal fun LicenseScreen( Column { LicenseItem(license, onLicenseClick) if (index != thirdPartyLicenses.lastIndex) { - SettingsHorizontalDivider(modifier = Modifier.padding(bottom = SimpleTheme.dimens.margin.small)) + SettingsHorizontalDivider(modifier = Modifier.padding(bottom = SimpleTheme.dimens.padding.small)) } } } @@ -58,7 +58,7 @@ private fun LicenseItem( }, supportingContent = { Text( text = stringResource(id = license.textId), - modifier = Modifier.padding(top = SimpleTheme.dimens.margin.extraSmall), + modifier = Modifier.padding(top = SimpleTheme.dimens.padding.extraSmall), ) }, colors = ListItemDefaults.colors(headlineColor = SimpleTheme.colorScheme.primary, supportingColor = SimpleTheme.colorScheme.onSurface)) } diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/ManageBlockedNumbersScreen.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/ManageBlockedNumbersScreen.kt index c440b5347..904233ae3 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/ManageBlockedNumbersScreen.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/screens/ManageBlockedNumbersScreen.kt @@ -86,7 +86,7 @@ internal fun ManageBlockedNumbersScreen( onCopy: (BlockedNumber) -> Unit, ) { val dimens = SimpleTheme.dimens - val startingPadding = remember { Modifier.padding(horizontal = dimens.margin.small) } + val startingPadding = remember { Modifier.padding(horizontal = dimens.padding.small) } val selectedIds: MutableState> = rememberSaveable { mutableStateOf(emptySet()) } val hapticFeedback = LocalHapticFeedback.current val isInActionMode by remember { derivedStateOf { selectedIds.value.isNotEmpty() } } @@ -194,7 +194,7 @@ internal fun ManageBlockedNumbersScreen( ids = blockedNumbers?.map { blockedNumber -> blockedNumber.id }.orEmpty() ) }, - verticalArrangement = Arrangement.spacedBy(SimpleTheme.dimens.margin.extraSmall), + verticalArrangement = Arrangement.spacedBy(SimpleTheme.dimens.padding.extraSmall), contentPadding = PaddingValues(bottom = paddingValues.calculateBottomPadding()) ) { when { @@ -324,7 +324,7 @@ private fun BlockedNumber( movableContentOf { Text( text = blockedNumber.contactName.toString(), - modifier = modifier.padding(horizontal = SimpleTheme.dimens.margin.medium, vertical = SimpleTheme.dimens.margin.extraSmall) + modifier = modifier.padding(horizontal = SimpleTheme.dimens.padding.medium, vertical = SimpleTheme.dimens.padding.extraSmall) ) } } @@ -381,7 +381,7 @@ private fun blockedNumberListItemColors( private fun BlockedNumberHeadlineContent(modifier: Modifier = Modifier, blockedNumber: BlockedNumber, hasContactName: Boolean) { Text( text = blockedNumber.number, - modifier = modifier.padding(horizontal = SimpleTheme.dimens.margin.medium), + modifier = modifier.padding(horizontal = SimpleTheme.dimens.padding.medium), color = if (hasContactName) LocalContentColor.current.copy(alpha = 0.7f) else LocalContentColor.current ) } @@ -548,7 +548,7 @@ private fun NonActionModeToolbar( title = { scrolledTextColor -> Text( text = stringResource(id = R.string.manage_blocked_numbers), - modifier = Modifier.padding(start = SimpleTheme.dimens.margin.extraLarge), + modifier = Modifier.padding(start = SimpleTheme.dimens.padding.extraLarge), maxLines = 1, overflow = TextOverflow.Ellipsis, color = scrolledTextColor @@ -584,8 +584,8 @@ private fun LazyListScope.emptyBlockedNumbers( style = TextStyle(fontStyle = FontStyle.Italic, textAlign = TextAlign.Center, color = SimpleTheme.colorScheme.onSurface), modifier = Modifier .fillMaxWidth() - .padding(top = SimpleTheme.dimens.margin.extraLarge, bottom = SimpleTheme.dimens.margin.small) - .padding(horizontal = SimpleTheme.dimens.margin.extraLarge) + .padding(top = SimpleTheme.dimens.padding.extraLarge, bottom = SimpleTheme.dimens.padding.small) + .padding(horizontal = SimpleTheme.dimens.padding.extraLarge) ) } item { @@ -606,7 +606,7 @@ private fun LazyListScope.emptyBlockedNumbers( color = SimpleTheme.colorScheme.primary, fontSize = 18.sp ), - modifier = Modifier.padding(SimpleTheme.dimens.margin.medium) + modifier = Modifier.padding(SimpleTheme.dimens.padding.medium) ) } } @@ -622,8 +622,8 @@ private fun LazyListScope.noPermissionToBlock( style = TextStyle(fontStyle = FontStyle.Italic, textAlign = TextAlign.Center), modifier = Modifier .fillMaxWidth() - .padding(top = SimpleTheme.dimens.margin.extraLarge) - .padding(horizontal = SimpleTheme.dimens.margin.extraLarge) + .padding(top = SimpleTheme.dimens.padding.extraLarge) + .padding(horizontal = SimpleTheme.dimens.padding.extraLarge) ) } item { @@ -644,7 +644,7 @@ private fun LazyListScope.noPermissionToBlock( color = SimpleTheme.colorScheme.primary, fontSize = 18.sp ), - modifier = Modifier.padding(SimpleTheme.dimens.margin.extraLarge) + modifier = Modifier.padding(SimpleTheme.dimens.padding.extraLarge) ) } } diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsCheckBoxComponent.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsCheckBoxComponent.kt index aa5853f6e..6c1e22a88 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsCheckBoxComponent.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsCheckBoxComponent.kt @@ -57,7 +57,7 @@ fun SettingsCheckBoxComponent( Text( modifier = Modifier .fillMaxWidth() - .padding(end = SimpleTheme.dimens.margin.extraLarge), + .padding(end = SimpleTheme.dimens.padding.extraLarge), text = label, color = preferenceLabelColor(isEnabled = isPreferenceEnabled), fontSize = 14.sp @@ -67,7 +67,7 @@ fun SettingsCheckBoxComponent( text = value.toString(), modifier = Modifier .fillMaxWidth() - .padding(end = SimpleTheme.dimens.margin.extraLarge), + .padding(end = SimpleTheme.dimens.padding.extraLarge), color = preferenceValueColor(isEnabled = isPreferenceEnabled), ) } diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsGroup.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsGroup.kt index feb99d297..9d2ddf16a 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsGroup.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsGroup.kt @@ -35,7 +35,7 @@ fun SettingsGroupTitle( Box( modifier = modifier .fillMaxWidth() - .padding(horizontal = SimpleTheme.dimens.margin.extraLarge), + .padding(horizontal = SimpleTheme.dimens.padding.extraLarge), contentAlignment = Alignment.CenterStart ) { val primary = SimpleTheme.colorScheme.primary diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsListItem.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsListItem.kt index 858ff6562..452ba77e4 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsListItem.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsListItem.kt @@ -51,7 +51,7 @@ fun SettingsListItem( leadingContent = { val imageSize = Modifier .size(SimpleTheme.dimens.icon.medium) - .padding(SimpleTheme.dimens.margin.medium) + .padding(SimpleTheme.dimens.padding.medium) when { icon != null && isImage && tint != null -> Image( modifier = imageSize, @@ -107,7 +107,7 @@ fun SettingsListItem( leadingContent = { val imageSize = Modifier .size(SimpleTheme.dimens.icon.medium) - .padding(SimpleTheme.dimens.margin.medium) + .padding(SimpleTheme.dimens.padding.medium) when { icon != null && isImage && tint != null -> Image( modifier = imageSize, diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsTitleTextComponent.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsTitleTextComponent.kt index 09bf3e113..1693848e3 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsTitleTextComponent.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/settings/SettingsTitleTextComponent.kt @@ -20,11 +20,11 @@ fun SettingsTitleTextComponent( maxLines: Int = 1, overflow: TextOverflow = TextOverflow.Ellipsis ) { - Box(modifier = Modifier.padding(top = SimpleTheme.dimens.margin.extraLarge)) { + Box(modifier = Modifier.padding(top = SimpleTheme.dimens.padding.extraLarge)) { Text( text = text.uppercase(), modifier = modifier - .padding(horizontal = SimpleTheme.dimens.margin.small), + .padding(horizontal = SimpleTheme.dimens.padding.small), color = color, fontSize = 14.sp, maxLines = maxLines, diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/theme/Dimensions.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/theme/Dimensions.kt index 5bf3b4299..ab4769390 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/theme/Dimensions.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/theme/Dimensions.kt @@ -6,7 +6,7 @@ import androidx.compose.ui.unit.dp import com.simplemobiletools.commons.compose.theme.model.Dimensions internal val CommonDimensions = Dimensions( - margin = Dimensions.Margins( + padding = Dimensions.Paddings( extraSmall = 2.dp, small = 4.dp, medium = 8.dp, diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/theme/model/Dimensions.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/theme/model/Dimensions.kt index ee83430f4..255b5a7ee 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/compose/theme/model/Dimensions.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/compose/theme/model/Dimensions.kt @@ -5,11 +5,11 @@ import androidx.compose.ui.unit.Dp @Immutable data class Dimensions( - val margin: Margins, + val padding: Paddings, val icon: IconSizes ) { @Immutable - data class Margins( + data class Paddings( val extraSmall: Dp, val small: Dp, val medium: Dp, diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/AppSideloadedDialog.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/AppSideloadedDialog.kt index 4e74b7efe..e417ee514 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/AppSideloadedDialog.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/AppSideloadedDialog.kt @@ -18,15 +18,11 @@ import androidx.compose.ui.unit.sp import com.simplemobiletools.commons.R import com.simplemobiletools.commons.compose.alert_dialog.AlertDialogState import com.simplemobiletools.commons.compose.alert_dialog.rememberAlertDialogState +import com.simplemobiletools.commons.compose.components.LinkifyTextComponent import com.simplemobiletools.commons.compose.extensions.MyDevices -import com.simplemobiletools.commons.compose.screens.LinkifyText -import com.simplemobiletools.commons.compose.screens.stringFromHTML import com.simplemobiletools.commons.compose.theme.AppThemeSurface import com.simplemobiletools.commons.databinding.DialogTextviewBinding -import com.simplemobiletools.commons.extensions.getAlertDialogBuilder -import com.simplemobiletools.commons.extensions.getStringsPackageName -import com.simplemobiletools.commons.extensions.launchViewIntent -import com.simplemobiletools.commons.extensions.setupDialogStuff +import com.simplemobiletools.commons.extensions.* class AppSideloadedDialog(val activity: Activity, val callback: () -> Unit) { private var dialog: AlertDialog? = null @@ -96,8 +92,8 @@ fun AppSideLoadedAlertDialog( shape = dialogShape, text = { val source = stringResource(id = R.string.sideloaded_app, url) - LinkifyText(fontSize = 16.sp, removeUnderlines = false) { - stringFromHTML(source) + LinkifyTextComponent(fontSize = 16.sp, removeUnderlines = false) { + source.fromHtml() } }, title = { diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/ChangeDateTimeFormatDialog.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/ChangeDateTimeFormatDialog.kt index abe1acf00..e19a6947e 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/ChangeDateTimeFormatDialog.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/ChangeDateTimeFormatDialog.kt @@ -147,7 +147,7 @@ fun ChangeDateTimeFormatAlertDialog( items = kinds, selected = selected, setSelected = setSelected, modifier = Modifier.padding( - vertical = SimpleTheme.dimens.margin.extraLarge, + vertical = SimpleTheme.dimens.padding.extraLarge, ) ) SettingsHorizontalDivider() @@ -157,7 +157,7 @@ fun ChangeDateTimeFormatAlertDialog( label = stringResource(id = R.string.use_24_hour_time_format), initialValue = is24HoursSelected, onChange = { is24HoursSelected = it }, - modifier = Modifier.padding(horizontal = SimpleTheme.dimens.margin.medium) + modifier = Modifier.padding(horizontal = SimpleTheme.dimens.padding.medium) ) } } @@ -167,7 +167,7 @@ fun ChangeDateTimeFormatAlertDialog( horizontalArrangement = Arrangement.End, modifier = Modifier .fillMaxWidth() - .padding(top = SimpleTheme.dimens.margin.extraLarge, bottom = SimpleTheme.dimens.margin.extraLarge, end = SimpleTheme.dimens.margin.extraLarge) + .padding(top = SimpleTheme.dimens.padding.extraLarge, bottom = SimpleTheme.dimens.padding.extraLarge, end = SimpleTheme.dimens.padding.extraLarge) .align(Alignment.BottomStart) ) { TextButton(onClick = { diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/ChangeViewTypeDialog.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/ChangeViewTypeDialog.kt index 60e167840..ebfc555d1 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/ChangeViewTypeDialog.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/ChangeViewTypeDialog.kt @@ -98,16 +98,16 @@ fun ChangeViewTypeAlertDialog( setSelected(selectedTitle) }, modifier = Modifier.padding( - vertical = SimpleTheme.dimens.margin.extraLarge, + vertical = SimpleTheme.dimens.padding.extraLarge, ), - verticalPadding = SimpleTheme.dimens.margin.extraLarge, + verticalPadding = SimpleTheme.dimens.padding.extraLarge, ) Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.End, modifier = Modifier .fillMaxWidth() - .padding(end = SimpleTheme.dimens.margin.extraLarge) + .padding(end = SimpleTheme.dimens.padding.extraLarge) ) { TextButton(onClick = { alertDialogState.hide() diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/ColorPickerDialog.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/ColorPickerDialog.kt index 8d1b8a0d8..d8e52c690 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/ColorPickerDialog.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/ColorPickerDialog.kt @@ -165,7 +165,7 @@ fun ColorPickerAlertDialog( Column( Modifier .fillMaxWidth(0.95f) - .padding(SimpleTheme.dimens.margin.extraLarge) + .padding(SimpleTheme.dimens.padding.extraLarge) ) { var dialogColorPickerBinding by remember { mutableStateOf(null) } val currentColorHsv by remember { derivedStateOf { Hsv(FloatArray(3)).apply { Color.colorToHSV(color, this.value) } } } diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/DonateDialog.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/DonateDialog.kt index 4a13353e3..200953496 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/DonateDialog.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/DonateDialog.kt @@ -24,11 +24,10 @@ import androidx.compose.ui.window.DialogProperties import com.simplemobiletools.commons.R import com.simplemobiletools.commons.compose.alert_dialog.AlertDialogState import com.simplemobiletools.commons.compose.alert_dialog.rememberAlertDialogState +import com.simplemobiletools.commons.compose.components.LinkifyTextComponent import com.simplemobiletools.commons.compose.extensions.MyDevices import com.simplemobiletools.commons.compose.extensions.getActivity import com.simplemobiletools.commons.compose.extensions.rememberMutableInteractionSource -import com.simplemobiletools.commons.compose.screens.LinkifyText -import com.simplemobiletools.commons.compose.screens.stringFromHTML import com.simplemobiletools.commons.compose.theme.AppThemeSurface import com.simplemobiletools.commons.compose.theme.SimpleTheme import com.simplemobiletools.commons.databinding.DialogDonateBinding @@ -110,13 +109,13 @@ fun DonateAlertDialog( }, text = { val source = stringResource(id = R.string.donate_short) - LinkifyText( + LinkifyTextComponent( fontSize = 16.sp, removeUnderlines = false, textAlignment = TextView.TEXT_ALIGNMENT_CENTER, modifier = Modifier.fillMaxWidth() ) { - stringFromHTML(source) + source.fromHtml() } } ) diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/FeatureLockedDialog.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/FeatureLockedDialog.kt index 03c524adb..8a0fa2c85 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/FeatureLockedDialog.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/FeatureLockedDialog.kt @@ -18,18 +18,16 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.sp import androidx.compose.ui.window.DialogProperties import com.simplemobiletools.commons.R import com.simplemobiletools.commons.compose.alert_dialog.AlertDialogState import com.simplemobiletools.commons.compose.alert_dialog.rememberAlertDialogState +import com.simplemobiletools.commons.compose.components.LinkifyTextComponent import com.simplemobiletools.commons.compose.extensions.MyDevices -import com.simplemobiletools.commons.compose.extensions.getActivity +import com.simplemobiletools.commons.compose.extensions.composeDonateIntent import com.simplemobiletools.commons.compose.extensions.rememberMutableInteractionSource -import com.simplemobiletools.commons.compose.screens.LinkifyText -import com.simplemobiletools.commons.compose.screens.stringFromHTML import com.simplemobiletools.commons.compose.theme.AppThemeSurface import com.simplemobiletools.commons.compose.theme.SimpleTheme import com.simplemobiletools.commons.databinding.DialogFeatureLockedBinding @@ -71,10 +69,7 @@ fun FeatureLockedAlertDialog( modifier: Modifier = Modifier, cancelCallback: () -> Unit ) { - val localContext = LocalContext.current.getActivity() - val donateIntent = { - localContext.launchViewIntent(R.string.thank_you_url) - } + val donateIntent = composeDonateIntent() androidx.compose.material3.AlertDialog( containerColor = dialogContainerColor, modifier = modifier @@ -121,13 +116,13 @@ fun FeatureLockedAlertDialog( }, text = { val source = stringResource(id = R.string.features_locked) - LinkifyText( + LinkifyTextComponent( fontSize = 16.sp, removeUnderlines = false, modifier = Modifier.fillMaxWidth(), textAlignment = TextView.TEXT_ALIGNMENT_CENTER ) { - stringFromHTML(source) + source.fromHtml() } } ) diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/LineColorPickerDialog.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/LineColorPickerDialog.kt index bf4216e0f..34bebddc9 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/LineColorPickerDialog.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/LineColorPickerDialog.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.viewinterop.AndroidViewBinding import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogWindowProvider +import androidx.core.content.ContextCompat import androidx.core.view.updateLayoutParams import com.google.android.material.appbar.MaterialToolbar import com.simplemobiletools.commons.R @@ -166,8 +167,7 @@ class LineColorPickerDialog( fun LineColorPickerAlertDialog( alertDialogState: AlertDialogState, modifier: Modifier = Modifier, - @ColorInt - color: Int, + @ColorInt color: Int, isPrimaryColorPicker: Boolean, primaryColors: Int = R.array.md_primary_colors, appIconIDs: ArrayList? = null, @@ -179,11 +179,10 @@ fun LineColorPickerAlertDialog( var wasDimmedBackgroundRemoved by remember { mutableStateOf(false) } val defaultColor = remember { - context.resources.getColor(R.color.color_primary) + ContextCompat.getColor(context, R.color.color_primary) } AlertDialog( - modifier = modifier - .dialogBorder, + modifier = modifier, onDismissRequest = alertDialogState::hide, properties = DialogProperties(usePlatformDefaultWidth = false) ) { @@ -191,7 +190,7 @@ fun LineColorPickerAlertDialog( Column( Modifier .fillMaxWidth(0.95f) - .padding(SimpleTheme.dimens.margin.extraLarge) + .padding(SimpleTheme.dimens.padding.extraLarge) ) { val dialogTextColor = dialogTextColor var dialogLineColorPickerBinding by remember { mutableStateOf(null) } diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/PurchaseThankYouDialog.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/PurchaseThankYouDialog.kt index 8d8ad7261..0d94d5e71 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/PurchaseThankYouDialog.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/PurchaseThankYouDialog.kt @@ -16,11 +16,10 @@ import androidx.compose.ui.window.DialogProperties import com.simplemobiletools.commons.R import com.simplemobiletools.commons.compose.alert_dialog.AlertDialogState import com.simplemobiletools.commons.compose.alert_dialog.rememberAlertDialogState +import com.simplemobiletools.commons.compose.components.LinkifyTextComponent import com.simplemobiletools.commons.compose.extensions.MyDevices +import com.simplemobiletools.commons.compose.extensions.composeDonateIntent import com.simplemobiletools.commons.compose.extensions.config -import com.simplemobiletools.commons.compose.extensions.getActivity -import com.simplemobiletools.commons.compose.screens.LinkifyText -import com.simplemobiletools.commons.compose.screens.stringFromHTML import com.simplemobiletools.commons.compose.theme.AppThemeSurface import com.simplemobiletools.commons.databinding.DialogPurchaseThankYouBinding import com.simplemobiletools.commons.extensions.* @@ -52,10 +51,8 @@ fun PurchaseThankYouAlertDialog( alertDialogState: AlertDialogState, modifier: Modifier = Modifier, ) { - val localContext = LocalContext.current.getActivity() - val donateIntent = { - localContext.launchViewIntent(R.string.thank_you_url) - } + val localContext = LocalContext.current + val donateIntent = composeDonateIntent() val appId = remember { localContext.config.appId } @@ -87,12 +84,12 @@ fun PurchaseThankYouAlertDialog( if (appId.removeSuffix(".debug").endsWith(".pro")) { text += "

${stringResource(R.string.shared_theme_note)}" } - LinkifyText( + LinkifyTextComponent( fontSize = 16.sp, removeUnderlines = false, modifier = Modifier.fillMaxWidth() ) { - stringFromHTML(text) + text.fromHtml() } } ) diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/RadioGroupDialog.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/RadioGroupDialog.kt index cd7da0257..9bb74a5fd 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/RadioGroupDialog.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/RadioGroupDialog.kt @@ -132,7 +132,7 @@ fun RadioGroupAlertDialog( text = stringResource(id = titleId), modifier = Modifier .fillMaxWidth() - .padding(top = 24.dp, bottom = SimpleTheme.dimens.margin.medium) + .padding(top = 24.dp, bottom = SimpleTheme.dimens.padding.medium) .padding(horizontal = 24.dp), color = dialogTextColor, fontSize = 21.sp @@ -147,7 +147,7 @@ fun RadioGroupAlertDialog( alertDialogState.hide() }, modifier = Modifier.padding( - vertical = SimpleTheme.dimens.margin.extraLarge, + vertical = SimpleTheme.dimens.padding.extraLarge, ) ) } @@ -159,7 +159,7 @@ fun RadioGroupAlertDialog( }, modifier = Modifier .align(Alignment.BottomEnd) - .padding(top = SimpleTheme.dimens.margin.extraLarge, bottom = SimpleTheme.dimens.margin.extraLarge, end = SimpleTheme.dimens.margin.extraLarge) + .padding(top = SimpleTheme.dimens.padding.extraLarge, bottom = SimpleTheme.dimens.padding.extraLarge, end = SimpleTheme.dimens.padding.extraLarge) ) { Text(text = stringResource(id = R.string.ok)) } diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/RateStarsDialog.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/RateStarsDialog.kt index 60fc5f27e..d02e3bd37 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/RateStarsDialog.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/RateStarsDialog.kt @@ -97,7 +97,7 @@ fun RateStarsAlertDialog( text = stringResource(id = R.string.rate_our_app), modifier = Modifier .fillMaxWidth() - .padding(top = SimpleTheme.dimens.margin.extraLarge, bottom = SimpleTheme.dimens.margin.large), + .padding(top = SimpleTheme.dimens.padding.extraLarge, bottom = SimpleTheme.dimens.padding.large), textAlign = TextAlign.Center, color = dialogTextColor, fontSize = 16.sp @@ -105,7 +105,7 @@ fun RateStarsAlertDialog( StarRating( modifier = Modifier .align(CenterHorizontally) - .padding(SimpleTheme.dimens.margin.extraLarge), + .padding(SimpleTheme.dimens.padding.extraLarge), currentRating = currentRating, onRatingChanged = { stars -> currentRating = stars @@ -120,7 +120,7 @@ fun RateStarsAlertDialog( onClick = alertDialogState::hide, modifier = Modifier .align(End) - .padding(end = SimpleTheme.dimens.margin.extraLarge, bottom = SimpleTheme.dimens.margin.medium) + .padding(end = SimpleTheme.dimens.padding.extraLarge, bottom = SimpleTheme.dimens.padding.medium) ) { Text(text = stringResource(id = R.string.later)) } diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/UpgradeToProDialog.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/UpgradeToProDialog.kt index 2d114078f..79d6a185c 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/UpgradeToProDialog.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/UpgradeToProDialog.kt @@ -99,7 +99,7 @@ fun UpgradeToProAlertDialog( } TextButton( onClick = alertDialogState::hide, - modifier = Modifier.padding(horizontal = SimpleTheme.dimens.margin.medium) + modifier = Modifier.padding(horizontal = SimpleTheme.dimens.padding.medium) ) { Text(text = stringResource(id = R.string.later)) } diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/WritePermissionDialog.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/WritePermissionDialog.kt index adb155d12..40a5c5ab8 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/WritePermissionDialog.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/dialogs/WritePermissionDialog.kt @@ -2,39 +2,64 @@ package com.simplemobiletools.commons.dialogs import android.app.Activity import android.text.Html +import android.text.Spanned +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes import androidx.appcompat.app.AlertDialog -import androidx.compose.runtime.Composable -import androidx.compose.runtime.Immutable +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.DialogProperties import com.bumptech.glide.Glide +import com.bumptech.glide.integration.compose.GlideImage import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions +import com.bumptech.glide.request.transition.DrawableCrossFadeFactory import com.simplemobiletools.commons.R import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.compose.alert_dialog.AlertDialogState import com.simplemobiletools.commons.compose.alert_dialog.rememberAlertDialogState +import com.simplemobiletools.commons.compose.components.LinkifyTextComponent import com.simplemobiletools.commons.compose.extensions.MyDevices +import com.simplemobiletools.commons.compose.extensions.andThen import com.simplemobiletools.commons.compose.theme.AppThemeSurface +import com.simplemobiletools.commons.compose.theme.SimpleTheme import com.simplemobiletools.commons.databinding.DialogWritePermissionBinding import com.simplemobiletools.commons.databinding.DialogWritePermissionOtgBinding +import com.simplemobiletools.commons.extensions.fromHtml import com.simplemobiletools.commons.extensions.getAlertDialogBuilder import com.simplemobiletools.commons.extensions.humanizePath import com.simplemobiletools.commons.extensions.setupDialogStuff -class WritePermissionDialog(activity: Activity, val mode: Mode, val callback: () -> Unit) { +class WritePermissionDialog(activity: Activity, val writePermissionDialogMode: WritePermissionDialogMode, val callback: () -> Unit) { @Immutable - sealed class Mode { + sealed class WritePermissionDialogMode { @Immutable - data object Otg : Mode() + data object Otg : WritePermissionDialogMode() @Immutable - data object SdCard : Mode() + data object SdCard : WritePermissionDialogMode() @Immutable - data class OpenDocumentTreeSDK30(val path: String) : Mode() + data class OpenDocumentTreeSDK30(val path: String) : WritePermissionDialogMode() @Immutable - data object CreateDocumentSDK30 : Mode() + data object CreateDocumentSDK30 : WritePermissionDialogMode() } private var dialog: AlertDialog? = null @@ -51,20 +76,20 @@ class WritePermissionDialog(activity: Activity, val mode: Mode, val callback: () val glide = Glide.with(activity) val crossFade = DrawableTransitionOptions.withCrossFade() - when (mode) { - Mode.Otg -> { + when (writePermissionDialogMode) { + WritePermissionDialogMode.Otg -> { otgView.writePermissionsDialogOtgText.setText(R.string.confirm_usb_storage_access_text) glide.load(R.drawable.img_write_storage_otg).transition(crossFade).into(otgView.writePermissionsDialogOtgImage) } - Mode.SdCard -> { + WritePermissionDialogMode.SdCard -> { glide.load(R.drawable.img_write_storage).transition(crossFade).into(sdCardView.writePermissionsDialogImage) glide.load(R.drawable.img_write_storage_sd).transition(crossFade).into(sdCardView.writePermissionsDialogImageSd) } - is Mode.OpenDocumentTreeSDK30 -> { + is WritePermissionDialogMode.OpenDocumentTreeSDK30 -> { dialogTitle = R.string.confirm_folder_access_title - val humanizedPath = activity.humanizePath(mode.path) + val humanizedPath = activity.humanizePath(writePermissionDialogMode.path) otgView.writePermissionsDialogOtgText.text = Html.fromHtml(activity.getString(R.string.confirm_storage_access_android_text_specific, humanizedPath)) glide.load(R.drawable.img_write_storage_sdk_30).transition(crossFade).into(otgView.writePermissionsDialogOtgImage) @@ -74,7 +99,7 @@ class WritePermissionDialog(activity: Activity, val mode: Mode, val callback: () } } - Mode.CreateDocumentSDK30 -> { + WritePermissionDialogMode.CreateDocumentSDK30 -> { dialogTitle = R.string.confirm_folder_access_title otgView.writePermissionsDialogOtgText.text = Html.fromHtml(activity.getString(R.string.confirm_create_doc_for_new_folder_text)) glide.load(R.drawable.img_write_storage_create_doc_sdk_30).transition(crossFade).into(otgView.writePermissionsDialogOtgImage) @@ -92,7 +117,11 @@ class WritePermissionDialog(activity: Activity, val mode: Mode, val callback: () BaseSimpleActivity.funAfterSAFPermission = null } .apply { - activity.setupDialogStuff(if (mode == Mode.SdCard) sdCardView.root else otgView.root, this, dialogTitle) { alertDialog -> + activity.setupDialogStuff( + if (writePermissionDialogMode == WritePermissionDialogMode.SdCard) sdCardView.root else otgView.root, + this, + dialogTitle + ) { alertDialog -> dialog = alertDialog } } @@ -107,15 +136,186 @@ class WritePermissionDialog(activity: Activity, val mode: Mode, val callback: () @Composable fun WritePermissionAlertDialog( alertDialogState: AlertDialogState, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + writePermissionDialogMode: WritePermissionDialog.WritePermissionDialogMode, + callback: () -> Unit, + onCancelCallback: () -> Unit ) { - //todo in progress + val dialogTitle = remember { + adjustDialogTitle( + writePermissionDialogMode = writePermissionDialogMode, + dialogTitle = R.string.confirm_storage_access_title + ) + } + val crossFadeTransition = remember { + DrawableTransitionOptions().crossFade(DrawableCrossFadeFactory.Builder(350).setCrossFadeEnabled(true).build()) + } + + AlertDialog( + onDismissRequest = alertDialogState::hide andThen onCancelCallback, + modifier = modifier + .fillMaxWidth(0.9f), + properties = DialogProperties(usePlatformDefaultWidth = false) + ) { + DialogSurface { + Box { + Column( + modifier = modifier + .padding(bottom = 64.dp) + .verticalScroll(rememberScrollState()) + ) { + Text( + text = stringResource(id = dialogTitle), + color = dialogTextColor, + modifier = Modifier + .padding(horizontal = SimpleTheme.dimens.padding.extraLarge.plus(SimpleTheme.dimens.padding.large)) + .padding(top = SimpleTheme.dimens.padding.extraLarge.plus(SimpleTheme.dimens.padding.small)), + fontSize = 21.sp, + fontWeight = FontWeight.Bold, + ) + + when (writePermissionDialogMode) { + WritePermissionDialog.WritePermissionDialogMode.CreateDocumentSDK30 -> CreateDocumentSDK30( + crossFadeTransition = crossFadeTransition, + onImageClick = alertDialogState::hide andThen callback + ) + + is WritePermissionDialog.WritePermissionDialogMode.OpenDocumentTreeSDK30 -> OpenDocumentTreeSDK30( + crossFadeTransition = crossFadeTransition, + onImageClick = alertDialogState::hide andThen callback, + path = writePermissionDialogMode.path + ) + + WritePermissionDialog.WritePermissionDialogMode.Otg -> OTG(crossFadeTransition) + WritePermissionDialog.WritePermissionDialogMode.SdCard -> SDCard(crossFadeTransition) + } + Spacer(Modifier.padding(vertical = SimpleTheme.dimens.padding.extraLarge)) + } + + TextButton( + onClick = alertDialogState::hide andThen callback, + modifier = Modifier + .padding( + top = SimpleTheme.dimens.padding.extraLarge, + bottom = SimpleTheme.dimens.padding.extraLarge, + end = SimpleTheme.dimens.padding.extraLarge + ) + .align(Alignment.BottomEnd) + ) { + Text(text = stringResource(id = R.string.ok)) + } + } + } + } +} + +@Composable +private fun CreateDocumentSDK30(crossFadeTransition: DrawableTransitionOptions, onImageClick: () -> Unit) { + WritePermissionText(stringResource(R.string.confirm_create_doc_for_new_folder_text).fromHtml()) + WritePermissionImage( + crossFadeTransition = crossFadeTransition, + drawable = R.drawable.img_write_storage_create_doc_sdk_30, + modifier = Modifier.clickable(onClick = onImageClick) + ) +} + +@Composable +private fun OpenDocumentTreeSDK30(crossFadeTransition: DrawableTransitionOptions, onImageClick: () -> Unit, path: String) { + val context = LocalContext.current + val view = LocalView.current + + val humanizedPath = remember { if (!view.isInEditMode) context.humanizePath(path) else "" } + WritePermissionText(stringResource(R.string.confirm_storage_access_android_text_specific, humanizedPath).fromHtml()) + WritePermissionImage( + crossFadeTransition = crossFadeTransition, + drawable = R.drawable.img_write_storage_sdk_30, + modifier = Modifier.clickable(onClick = onImageClick) + ) +} + +@Composable +private fun SDCard(crossFadeTransition: DrawableTransitionOptions) { + WritePermissionText(R.string.confirm_storage_access_text) + WritePermissionImage(crossFadeTransition = crossFadeTransition, drawable = R.drawable.img_write_storage) + WritePermissionText(R.string.confirm_storage_access_text_sd) + WritePermissionImage(crossFadeTransition = crossFadeTransition, drawable = R.drawable.img_write_storage_sd) +} + +@Composable +private fun OTG( + crossFadeTransition: DrawableTransitionOptions +) { + WritePermissionText(R.string.confirm_usb_storage_access_text) + WritePermissionImage(crossFadeTransition = crossFadeTransition, drawable = R.drawable.img_write_storage_otg) +} + +@Composable +private fun WritePermissionImage( + modifier: Modifier = Modifier, + crossFadeTransition: DrawableTransitionOptions, + @DrawableRes drawable: Int +) { + GlideImage( + modifier = modifier + .padding(horizontal = SimpleTheme.dimens.padding.extraLarge.plus(SimpleTheme.dimens.padding.large)), + model = drawable, + contentDescription = null, + ) { requestBuilder -> + requestBuilder.transition(crossFadeTransition) + } +} + +@Composable +private fun WritePermissionText(@StringRes text: Int) { + Text( + text = stringResource(id = text), + color = dialogTextColor, + modifier = Modifier + .padding(horizontal = SimpleTheme.dimens.padding.extraLarge.plus(SimpleTheme.dimens.padding.medium)) + .padding(vertical = SimpleTheme.dimens.padding.extraLarge), + ) +} + +@Composable +private fun WritePermissionText(text: Spanned) { + LinkifyTextComponent( + modifier = Modifier + .padding(horizontal = SimpleTheme.dimens.padding.extraLarge.plus(SimpleTheme.dimens.padding.medium)) + .padding(vertical = SimpleTheme.dimens.padding.extraLarge), + ) { + text + } +} + +private fun adjustDialogTitle( + writePermissionDialogMode: WritePermissionDialog.WritePermissionDialogMode, + dialogTitle: Int +): Int = + when (writePermissionDialogMode) { + WritePermissionDialog.WritePermissionDialogMode.CreateDocumentSDK30 -> R.string.confirm_folder_access_title + is WritePermissionDialog.WritePermissionDialogMode.OpenDocumentTreeSDK30 -> R.string.confirm_folder_access_title + else -> dialogTitle + } + +private class WritePermissionDialogModePreviewParameter : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + WritePermissionDialog.WritePermissionDialogMode.SdCard, + WritePermissionDialog.WritePermissionDialogMode.Otg, + WritePermissionDialog.WritePermissionDialogMode.CreateDocumentSDK30, + WritePermissionDialog.WritePermissionDialogMode.OpenDocumentTreeSDK30(""), + ) } @Composable @MyDevices -private fun WritePermissionAlertDialogPreview() { +private fun WritePermissionAlertDialogPreview(@PreviewParameter(WritePermissionDialogModePreviewParameter::class) mode: WritePermissionDialog.WritePermissionDialogMode) { AppThemeSurface { - WritePermissionAlertDialog(rememberAlertDialogState()) + WritePermissionAlertDialog( + alertDialogState = rememberAlertDialogState(), + writePermissionDialogMode = WritePermissionDialog.WritePermissionDialogMode.OpenDocumentTreeSDK30("."), + callback = {}, + onCancelCallback = {} + ) } } diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/extensions/Activity.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/extensions/Activity.kt index 3fef38d0d..b7211c3d7 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/extensions/Activity.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/extensions/Activity.kt @@ -39,7 +39,7 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.compose.extensions.DEVELOPER_PLAY_STORE_URL import com.simplemobiletools.commons.databinding.DialogTitleBinding import com.simplemobiletools.commons.dialogs.* -import com.simplemobiletools.commons.dialogs.WritePermissionDialog.Mode +import com.simplemobiletools.commons.dialogs.WritePermissionDialog.WritePermissionDialogMode import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.models.* import com.simplemobiletools.commons.views.MyTextView @@ -113,7 +113,7 @@ fun BaseSimpleActivity.isShowingSAFDialog(path: String): Boolean { return if ((!isRPlus() && isPathOnSD(path) && !isSDCardSetAsDefaultStorage() && (baseConfig.sdTreeUri.isEmpty() || !hasProperStoredTreeUri(false)))) { runOnUiThread { if (!isDestroyed && !isFinishing) { - WritePermissionDialog(this, Mode.SdCard) { + WritePermissionDialog(this, WritePermissionDialogMode.SdCard) { Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply { putExtra(EXTRA_SHOW_ADVANCED, true) try { @@ -148,7 +148,7 @@ fun BaseSimpleActivity.isShowingSAFDialogSdk30(path: String): Boolean { runOnUiThread { if (!isDestroyed && !isFinishing) { val level = getFirstParentLevel(path) - WritePermissionDialog(this, Mode.OpenDocumentTreeSDK30(path.getFirstParentPath(this, level))) { + WritePermissionDialog(this, WritePermissionDialogMode.OpenDocumentTreeSDK30(path.getFirstParentPath(this, level))) { Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply { putExtra(EXTRA_SHOW_ADVANCED, true) putExtra(DocumentsContract.EXTRA_INITIAL_URI, createFirstParentTreeUriUsingRootTree(path)) @@ -183,7 +183,7 @@ fun BaseSimpleActivity.isShowingSAFCreateDocumentDialogSdk30(path: String): Bool return if (!hasProperStoredDocumentUriSdk30(path)) { runOnUiThread { if (!isDestroyed && !isFinishing) { - WritePermissionDialog(this, Mode.CreateDocumentSDK30) { + WritePermissionDialog(this, WritePermissionDialogMode.CreateDocumentSDK30) { Intent(Intent.ACTION_CREATE_DOCUMENT).apply { type = DocumentsContract.Document.MIME_TYPE_DIR putExtra(EXTRA_SHOW_ADVANCED, true) @@ -264,7 +264,7 @@ fun BaseSimpleActivity.isShowingOTGDialog(path: String): Boolean { fun BaseSimpleActivity.showOTGPermissionDialog(path: String) { runOnUiThread { if (!isDestroyed && !isFinishing) { - WritePermissionDialog(this, Mode.Otg) { + WritePermissionDialog(this, WritePermissionDialogMode.Otg) { Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply { try { startActivityForResult(this, OPEN_DOCUMENT_TREE_OTG) diff --git a/commons/src/main/kotlin/com/simplemobiletools/commons/extensions/String.kt b/commons/src/main/kotlin/com/simplemobiletools/commons/extensions/String.kt index 47489a44e..4012b1edf 100644 --- a/commons/src/main/kotlin/com/simplemobiletools/commons/extensions/String.kt +++ b/commons/src/main/kotlin/com/simplemobiletools/commons/extensions/String.kt @@ -4,25 +4,25 @@ import android.content.Context import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Point +import android.os.Build import android.os.StatFs import android.provider.MediaStore import android.telephony.PhoneNumberUtils -import android.text.Spannable -import android.text.SpannableString -import android.text.TextUtils +import android.text.* import android.text.style.ForegroundColorSpan import android.widget.TextView import com.bumptech.glide.signature.ObjectKey import com.simplemobiletools.commons.helpers.* -import org.joda.time.DateTime -import org.joda.time.Years -import org.joda.time.format.DateTimeFormat import java.io.File import java.text.DateFormat import java.text.Normalizer import java.text.SimpleDateFormat -import java.util.* +import java.util.Locale import java.util.regex.Pattern +import org.joda.time.DateTime +import org.joda.time.Years +import org.joda.time.format.DateTimeFormat + fun String.getFilenameFromPath() = substring(lastIndexOf("/") + 1) @@ -928,3 +928,19 @@ fun String.getMimeType(): String { } fun String.isBlockedNumberPattern() = contains("*") + +fun String?.fromHtml(): Spanned = + when { + this == null -> { + // return an empty spannable if the html is null + SpannableString("") + } + + Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> { + Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY) + } + + else -> { + Html.fromHtml(this) + } + } diff --git a/samples/src/main/kotlin/com/simplemobiletools/commons/samples/activities/MainActivity.kt b/samples/src/main/kotlin/com/simplemobiletools/commons/samples/activities/MainActivity.kt index ba6c2b490..976e8cae2 100644 --- a/samples/src/main/kotlin/com/simplemobiletools/commons/samples/activities/MainActivity.kt +++ b/samples/src/main/kotlin/com/simplemobiletools/commons/samples/activities/MainActivity.kt @@ -48,7 +48,7 @@ class MainActivity : BaseSimpleActivity() { startActivity(Intent(this, TestDialogActivity::class.java)) } binding.testButton.setOnClickListener { - WritePermissionDialog(this, mode = WritePermissionDialog.Mode.OpenDocumentTreeSDK30("")){ + WritePermissionDialog(this, writePermissionDialogMode = WritePermissionDialog.WritePermissionDialogMode.OpenDocumentTreeSDK30(".")){ } } diff --git a/samples/src/main/kotlin/com/simplemobiletools/commons/samples/activities/TestDialogActivity.kt b/samples/src/main/kotlin/com/simplemobiletools/commons/samples/activities/TestDialogActivity.kt index 0c48e64f8..9828de43f 100644 --- a/samples/src/main/kotlin/com/simplemobiletools/commons/samples/activities/TestDialogActivity.kt +++ b/samples/src/main/kotlin/com/simplemobiletools/commons/samples/activities/TestDialogActivity.kt @@ -62,12 +62,25 @@ class TestDialogActivity : ComponentActivity() { ShowButton(getUpgradeToProAlertDialogState(), text = "Upgrade to pro") ShowButton(getWhatsNewAlertDialogState(), text = "What's new") ShowButton(getChangeViewTypeAlertDialogState(), text = "Change view type") + ShowButton(getWritePermissionAlertDialogState(), text = "Write permission dialog") Spacer(modifier = Modifier.padding(bottom = 16.dp)) } } } } + @Composable + private fun getWritePermissionAlertDialogState() = rememberAlertDialogState().apply { + DialogMember { + WritePermissionAlertDialog( + alertDialogState = this, + writePermissionDialogMode = WritePermissionDialog.WritePermissionDialogMode.OpenDocumentTreeSDK30("."), + callback = {}, + onCancelCallback = {} + ) + } + } + @Composable private fun getChangeViewTypeAlertDialogState() = rememberAlertDialogState().apply { DialogMember {