feat: write permission dialog
and few other fixes along the way
This commit is contained in:
parent
869eb0f163
commit
a0ff2b2eeb
34 changed files with 416 additions and 173 deletions
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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<Set<Long>> = 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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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<DialogColorPickerBinding?>(null) }
|
||||
val currentColorHsv by remember { derivedStateOf { Hsv(FloatArray(3)).apply { Color.colorToHSV(color, this.value) } } }
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -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<Int>? = 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<DialogLineColorPickerBinding?>(null) }
|
||||
|
|
|
@ -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 += "<br><br>${stringResource(R.string.shared_theme_note)}"
|
||||
}
|
||||
LinkifyText(
|
||||
LinkifyTextComponent(
|
||||
fontSize = 16.sp,
|
||||
removeUnderlines = false,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
stringFromHTML(text)
|
||||
text.fromHtml()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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<WritePermissionDialog.WritePermissionDialogMode> {
|
||||
override val values: Sequence<WritePermissionDialog.WritePermissionDialogMode>
|
||||
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 = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(".")){
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue