mirror of
https://github.com/T8RIN/ImageToolbox.git
synced 2025-05-21 23:46:31 +08:00
Code refactor
This commit is contained in:
@ -21,14 +21,14 @@ import android.content.Intent
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import com.arkivanov.decompose.retainedComponent
|
import com.arkivanov.decompose.retainedComponent
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import ru.tech.imageresizershrinker.core.ui.utils.M3Activity
|
import ru.tech.imageresizershrinker.core.ui.utils.ComposeActivity
|
||||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.parseImageFromIntent
|
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.parseImageFromIntent
|
||||||
import ru.tech.imageresizershrinker.feature.root.presentation.RootContent
|
import ru.tech.imageresizershrinker.feature.root.presentation.RootContent
|
||||||
import ru.tech.imageresizershrinker.feature.root.presentation.screenLogic.RootComponent
|
import ru.tech.imageresizershrinker.feature.root.presentation.screenLogic.RootComponent
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class AppActivity : M3Activity() {
|
class AppActivity : ComposeActivity() {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var rootComponentFactory: RootComponent.Factory
|
lateinit var rootComponentFactory: RootComponent.Factory
|
||||||
|
@ -23,11 +23,11 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||||||
import ru.tech.imageresizershrinker.core.crash.presentation.components.CrashHandler
|
import ru.tech.imageresizershrinker.core.crash.presentation.components.CrashHandler
|
||||||
import ru.tech.imageresizershrinker.core.crash.presentation.components.CrashRootContent
|
import ru.tech.imageresizershrinker.core.crash.presentation.components.CrashRootContent
|
||||||
import ru.tech.imageresizershrinker.core.crash.presentation.screenLogic.CrashComponent
|
import ru.tech.imageresizershrinker.core.crash.presentation.screenLogic.CrashComponent
|
||||||
import ru.tech.imageresizershrinker.core.ui.utils.M3Activity
|
import ru.tech.imageresizershrinker.core.ui.utils.ComposeActivity
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class CrashActivity : M3Activity(), CrashHandler {
|
class CrashActivity : ComposeActivity(), CrashHandler {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var componentFactory: CrashComponent.Factory
|
lateinit var componentFactory: CrashComponent.Factory
|
||||||
|
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* ImageToolbox is an image editor for android
|
||||||
|
* Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the Apache License
|
||||||
|
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ru.tech.imageresizershrinker.core.crash.presentation.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.automirrored.rounded.MobileScreenShare
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.platform.LocalUriHandler
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import ru.tech.imageresizershrinker.core.domain.TELEGRAM_GROUP_LINK
|
||||||
|
import ru.tech.imageresizershrinker.core.resources.R
|
||||||
|
import ru.tech.imageresizershrinker.core.resources.icons.Github
|
||||||
|
import ru.tech.imageresizershrinker.core.resources.icons.Telegram
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.theme.Black
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.theme.Blue
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.theme.White
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.theme.outlineVariant
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.widget.text.AutoSizeText
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun CrashActionButtons(
|
||||||
|
onCopyCrashInfo: () -> Unit,
|
||||||
|
onShareLogs: () -> Unit,
|
||||||
|
githubLink: String
|
||||||
|
) {
|
||||||
|
BoxWithConstraints(
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
val containerWidth = maxWidth
|
||||||
|
Column {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
val linkHandler = LocalUriHandler.current
|
||||||
|
LargeEnhancedButton(
|
||||||
|
onClick = {
|
||||||
|
onCopyCrashInfo()
|
||||||
|
linkHandler.openUri(TELEGRAM_GROUP_LINK)
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.width(containerWidth / 2f)
|
||||||
|
.padding(end = 8.dp),
|
||||||
|
containerColor = Blue,
|
||||||
|
contentColor = White,
|
||||||
|
icon = Icons.Rounded.Telegram,
|
||||||
|
text = stringResource(R.string.contact_me)
|
||||||
|
)
|
||||||
|
LargeEnhancedButton(
|
||||||
|
onClick = {
|
||||||
|
onCopyCrashInfo()
|
||||||
|
linkHandler.openUri(githubLink)
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.width(containerWidth / 2f),
|
||||||
|
containerColor = Black,
|
||||||
|
contentColor = White,
|
||||||
|
icon = Icons.Rounded.Github,
|
||||||
|
text = stringResource(id = R.string.create_issue),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
LargeEnhancedButton(
|
||||||
|
onClick = {
|
||||||
|
onCopyCrashInfo()
|
||||||
|
onShareLogs()
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
containerColor = MaterialTheme.colorScheme.primary,
|
||||||
|
contentColor = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
icon = Icons.AutoMirrored.Rounded.MobileScreenShare,
|
||||||
|
text = stringResource(id = R.string.send_logs),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun LargeEnhancedButton(
|
||||||
|
onClick: () -> Unit,
|
||||||
|
containerColor: Color,
|
||||||
|
contentColor: Color,
|
||||||
|
icon: ImageVector,
|
||||||
|
text: String,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
EnhancedButton(
|
||||||
|
onClick = onClick,
|
||||||
|
modifier = modifier
|
||||||
|
.height(48.dp),
|
||||||
|
containerColor = containerColor,
|
||||||
|
contentColor = contentColor,
|
||||||
|
borderColor = MaterialTheme.colorScheme.outlineVariant(
|
||||||
|
onTopOf = containerColor
|
||||||
|
),
|
||||||
|
contentPadding = ButtonDefaults.ButtonWithIconContentPadding
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = icon,
|
||||||
|
contentDescription = text
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
AutoSizeText(
|
||||||
|
text = text,
|
||||||
|
maxLines = 1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* ImageToolbox is an image editor for android
|
||||||
|
* Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the Apache License
|
||||||
|
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ru.tech.imageresizershrinker.core.crash.presentation.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.statusBarsPadding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import ru.tech.imageresizershrinker.core.resources.R
|
||||||
|
import ru.tech.imageresizershrinker.core.resources.icons.ImageToolboxBroken
|
||||||
|
import ru.tech.imageresizershrinker.core.settings.presentation.provider.LocalSettingsState
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.theme.blend
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.theme.takeColorFromScheme
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun CrashAttentionCard() {
|
||||||
|
val isNightMode = LocalSettingsState.current.isNightMode
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.container(
|
||||||
|
shape = RoundedCornerShape(size = 20.dp),
|
||||||
|
resultPadding = 16.dp,
|
||||||
|
color = takeColorFromScheme {
|
||||||
|
if (isNightMode) {
|
||||||
|
errorContainer.blend(surfaceContainerLow, 0.75f)
|
||||||
|
} else {
|
||||||
|
errorContainer.blend(surfaceContainerLow, 0.65f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
val contentColor = takeColorFromScheme {
|
||||||
|
if (isNightMode) {
|
||||||
|
onError.blend(onSurface, 0.75f)
|
||||||
|
} else {
|
||||||
|
error.blend(onSurface, 0.6f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Outlined.ImageToolboxBroken,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(80.dp)
|
||||||
|
.statusBarsPadding(),
|
||||||
|
tint = contentColor
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.crash_title),
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = 22.sp,
|
||||||
|
lineHeight = 26.sp,
|
||||||
|
color = contentColor
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.crash_subtitle),
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
lineHeight = 20.sp,
|
||||||
|
color = contentColor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* ImageToolbox is an image editor for android
|
||||||
|
* Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the Apache License
|
||||||
|
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ru.tech.imageresizershrinker.core.crash.presentation.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.displayCutoutPadding
|
||||||
|
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.ContentCopy
|
||||||
|
import androidx.compose.material.icons.rounded.RestartAlt
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import ru.tech.imageresizershrinker.core.resources.R
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedFloatingActionButton
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.widget.text.AutoSizeText
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun CrashBottomButtons(
|
||||||
|
modifier: Modifier,
|
||||||
|
onCopy: () -> Unit,
|
||||||
|
onRestartApp: () -> Unit
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = modifier
|
||||||
|
.padding(8.dp)
|
||||||
|
.navigationBarsPadding()
|
||||||
|
.displayCutoutPadding()
|
||||||
|
) {
|
||||||
|
EnhancedFloatingActionButton(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f, false),
|
||||||
|
onClick = onRestartApp,
|
||||||
|
content = {
|
||||||
|
Spacer(Modifier.width(16.dp))
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Rounded.RestartAlt,
|
||||||
|
contentDescription = stringResource(R.string.restart_app)
|
||||||
|
)
|
||||||
|
Spacer(Modifier.width(16.dp))
|
||||||
|
AutoSizeText(
|
||||||
|
text = stringResource(R.string.restart_app),
|
||||||
|
maxLines = 1
|
||||||
|
)
|
||||||
|
Spacer(Modifier.width(16.dp))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Spacer(Modifier.width(8.dp))
|
||||||
|
EnhancedFloatingActionButton(
|
||||||
|
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
|
||||||
|
onClick = onCopy
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Rounded.ContentCopy,
|
||||||
|
contentDescription = stringResource(R.string.copy)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* ImageToolbox is an image editor for android
|
||||||
|
* Copyright (c) 2025 T8RIN (Malik Mukhametzyanov)
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the Apache License
|
||||||
|
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ru.tech.imageresizershrinker.core.crash.presentation.components
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.rounded.BugReport
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.widget.other.ExpandableItem
|
||||||
|
import ru.tech.imageresizershrinker.core.ui.widget.text.AutoSizeText
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun CrashInfoCard(crashInfo: CrashInfo) {
|
||||||
|
ExpandableItem(
|
||||||
|
shape = RoundedCornerShape(24.dp),
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
visibleContent = {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Rounded.BugReport,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.padding(
|
||||||
|
start = 16.dp,
|
||||||
|
top = 16.dp,
|
||||||
|
bottom = 16.dp
|
||||||
|
)
|
||||||
|
)
|
||||||
|
AutoSizeText(
|
||||||
|
text = crashInfo.exceptionName,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
textAlign = TextAlign.Start,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
.weight(1f)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
expandableContent = {
|
||||||
|
AnimatedVisibility(visible = it) {
|
||||||
|
SelectionContainer {
|
||||||
|
Text(
|
||||||
|
text = crashInfo.stackTrace,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier.padding(16.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
@ -18,65 +18,28 @@
|
|||||||
package ru.tech.imageresizershrinker.core.crash.presentation.components
|
package ru.tech.imageresizershrinker.core.crash.presentation.components
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.displayCutoutPadding
|
import androidx.compose.foundation.layout.displayCutoutPadding
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.layout.statusBarsPadding
|
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.rounded.MobileScreenShare
|
|
||||||
import androidx.compose.material.icons.rounded.BugReport
|
|
||||||
import androidx.compose.material.icons.rounded.ContentCopy
|
import androidx.compose.material.icons.rounded.ContentCopy
|
||||||
import androidx.compose.material.icons.rounded.RestartAlt
|
|
||||||
import androidx.compose.material3.ButtonDefaults
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalUriHandler
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import ru.tech.imageresizershrinker.core.crash.presentation.screenLogic.CrashComponent
|
import ru.tech.imageresizershrinker.core.crash.presentation.screenLogic.CrashComponent
|
||||||
import ru.tech.imageresizershrinker.core.domain.TELEGRAM_GROUP_LINK
|
|
||||||
import ru.tech.imageresizershrinker.core.resources.R
|
import ru.tech.imageresizershrinker.core.resources.R
|
||||||
import ru.tech.imageresizershrinker.core.resources.icons.Github
|
|
||||||
import ru.tech.imageresizershrinker.core.resources.icons.ImageToolboxBroken
|
|
||||||
import ru.tech.imageresizershrinker.core.resources.icons.Telegram
|
|
||||||
import ru.tech.imageresizershrinker.core.settings.presentation.model.toUiState
|
import ru.tech.imageresizershrinker.core.settings.presentation.model.toUiState
|
||||||
import ru.tech.imageresizershrinker.core.settings.presentation.provider.LocalSettingsState
|
|
||||||
import ru.tech.imageresizershrinker.core.ui.theme.Black
|
|
||||||
import ru.tech.imageresizershrinker.core.ui.theme.Blue
|
|
||||||
import ru.tech.imageresizershrinker.core.ui.theme.White
|
|
||||||
import ru.tech.imageresizershrinker.core.ui.theme.blend
|
|
||||||
import ru.tech.imageresizershrinker.core.ui.theme.outlineVariant
|
|
||||||
import ru.tech.imageresizershrinker.core.ui.theme.takeColorFromScheme
|
|
||||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.AppActivityClass
|
import ru.tech.imageresizershrinker.core.ui.utils.helper.AppActivityClass
|
||||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.ImageToolboxCompositionLocals
|
import ru.tech.imageresizershrinker.core.ui.utils.provider.ImageToolboxCompositionLocals
|
||||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalComponentActivity
|
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalComponentActivity
|
||||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalScreenSize
|
|
||||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.rememberLocalEssentials
|
import ru.tech.imageresizershrinker.core.ui.utils.provider.rememberLocalEssentials
|
||||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
|
|
||||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedFloatingActionButton
|
|
||||||
import ru.tech.imageresizershrinker.core.ui.widget.modifier.container
|
|
||||||
import ru.tech.imageresizershrinker.core.ui.widget.other.ExpandableItem
|
|
||||||
import ru.tech.imageresizershrinker.core.ui.widget.text.AutoSizeText
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun CrashRootContent(component: CrashComponent) {
|
internal fun CrashRootContent(component: CrashComponent) {
|
||||||
@ -95,249 +58,36 @@ internal fun CrashRootContent(component: CrashComponent) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val linkHandler = LocalUriHandler.current
|
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.Center)
|
.align(Alignment.Center)
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
.padding(bottom = 80.dp)
|
||||||
|
.navigationBarsPadding()
|
||||||
.displayCutoutPadding(),
|
.displayCutoutPadding(),
|
||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
val isNightMode = LocalSettingsState.current.isNightMode
|
CrashAttentionCard()
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
Column(
|
CrashActionButtons(
|
||||||
modifier = Modifier
|
onCopyCrashInfo = copyCrashInfo,
|
||||||
.fillMaxWidth()
|
onShareLogs = component::shareLogs,
|
||||||
.padding(horizontal = 16.dp)
|
githubLink = crashInfo.githubLink
|
||||||
.container(
|
)
|
||||||
shape = RoundedCornerShape(size = 20.dp),
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
resultPadding = 16.dp,
|
CrashInfoCard(crashInfo = crashInfo)
|
||||||
color = takeColorFromScheme {
|
|
||||||
if (isNightMode) {
|
|
||||||
errorContainer.blend(surfaceContainerLow, 0.75f)
|
|
||||||
} else {
|
|
||||||
errorContainer.blend(surfaceContainerLow, 0.65f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
),
|
|
||||||
verticalArrangement = Arrangement.Center,
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
|
||||||
val contentColor = takeColorFromScheme {
|
|
||||||
if (isNightMode) {
|
|
||||||
onError.blend(onSurface, 0.75f)
|
|
||||||
} else {
|
|
||||||
error.blend(onSurface, 0.6f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Icon(
|
CrashBottomButtons(
|
||||||
imageVector = Icons.Outlined.ImageToolboxBroken,
|
modifier = Modifier.align(Alignment.BottomCenter),
|
||||||
contentDescription = null,
|
onCopy = copyCrashInfo,
|
||||||
modifier = Modifier
|
onRestartApp = {
|
||||||
.size(80.dp)
|
|
||||||
.statusBarsPadding(),
|
|
||||||
tint = contentColor
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.crash_title),
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
fontSize = 22.sp,
|
|
||||||
lineHeight = 26.sp,
|
|
||||||
color = contentColor
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.crash_subtitle),
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
fontSize = 16.sp,
|
|
||||||
lineHeight = 20.sp,
|
|
||||||
color = contentColor
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
|
||||||
val screenWidth = LocalScreenSize.current.width - 32.dp
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(horizontal = 16.dp)
|
|
||||||
.fillMaxWidth(),
|
|
||||||
horizontalArrangement = Arrangement.Center,
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
EnhancedButton(
|
|
||||||
onClick = {
|
|
||||||
copyCrashInfo()
|
|
||||||
linkHandler.openUri(TELEGRAM_GROUP_LINK)
|
|
||||||
},
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(end = 8.dp)
|
|
||||||
.weight(1f)
|
|
||||||
.width(screenWidth / 2f)
|
|
||||||
.height(48.dp),
|
|
||||||
containerColor = Blue,
|
|
||||||
contentColor = White,
|
|
||||||
borderColor = MaterialTheme.colorScheme.outlineVariant(
|
|
||||||
onTopOf = Blue
|
|
||||||
),
|
|
||||||
contentPadding = ButtonDefaults.ButtonWithIconContentPadding
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.Center
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Rounded.Telegram,
|
|
||||||
contentDescription = stringResource(R.string.telegram)
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
|
||||||
AutoSizeText(
|
|
||||||
text = stringResource(id = R.string.contact_me),
|
|
||||||
maxLines = 1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EnhancedButton(
|
|
||||||
onClick = {
|
|
||||||
copyCrashInfo()
|
|
||||||
linkHandler.openUri(crashInfo.githubLink)
|
|
||||||
},
|
|
||||||
modifier = Modifier
|
|
||||||
.weight(1f)
|
|
||||||
.width(screenWidth / 2f)
|
|
||||||
.height(48.dp),
|
|
||||||
containerColor = Black,
|
|
||||||
contentColor = White,
|
|
||||||
borderColor = MaterialTheme.colorScheme.outlineVariant(
|
|
||||||
onTopOf = Black
|
|
||||||
),
|
|
||||||
contentPadding = ButtonDefaults.ButtonWithIconContentPadding
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.Center
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Rounded.Github,
|
|
||||||
contentDescription = stringResource(R.string.github)
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
|
||||||
AutoSizeText(
|
|
||||||
text = stringResource(id = R.string.create_issue),
|
|
||||||
maxLines = 1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
|
||||||
EnhancedButton(
|
|
||||||
onClick = {
|
|
||||||
copyCrashInfo()
|
|
||||||
component.shareLogs()
|
|
||||||
},
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = 16.dp)
|
|
||||||
.height(48.dp),
|
|
||||||
contentPadding = ButtonDefaults.ButtonWithIconContentPadding
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.Center
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.AutoMirrored.Rounded.MobileScreenShare,
|
|
||||||
contentDescription = stringResource(R.string.send_logs)
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
|
||||||
AutoSizeText(
|
|
||||||
text = stringResource(id = R.string.send_logs),
|
|
||||||
maxLines = 1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
|
||||||
ExpandableItem(
|
|
||||||
shape = RoundedCornerShape(24.dp),
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = 16.dp)
|
|
||||||
.navigationBarsPadding(),
|
|
||||||
visibleContent = {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Rounded.BugReport,
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.padding(
|
|
||||||
start = 16.dp,
|
|
||||||
top = 16.dp,
|
|
||||||
bottom = 16.dp
|
|
||||||
)
|
|
||||||
)
|
|
||||||
AutoSizeText(
|
|
||||||
text = crashInfo.exceptionName,
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
textAlign = TextAlign.Start,
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(16.dp)
|
|
||||||
.weight(1f)
|
|
||||||
)
|
|
||||||
},
|
|
||||||
expandableContent = {
|
|
||||||
AnimatedVisibility(visible = it) {
|
|
||||||
SelectionContainer {
|
|
||||||
Text(
|
|
||||||
text = crashInfo.stackTrace,
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
modifier = Modifier.padding(16.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(80.dp))
|
|
||||||
}
|
|
||||||
Row(
|
|
||||||
Modifier
|
|
||||||
.padding(8.dp)
|
|
||||||
.navigationBarsPadding()
|
|
||||||
.displayCutoutPadding()
|
|
||||||
.align(Alignment.BottomCenter)
|
|
||||||
) {
|
|
||||||
EnhancedFloatingActionButton(
|
|
||||||
modifier = Modifier
|
|
||||||
.weight(1f, false),
|
|
||||||
onClick = {
|
|
||||||
context.startActivity(
|
context.startActivity(
|
||||||
Intent(context, AppActivityClass)
|
Intent(context, AppActivityClass)
|
||||||
)
|
)
|
||||||
},
|
|
||||||
content = {
|
|
||||||
Spacer(Modifier.width(16.dp))
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Rounded.RestartAlt,
|
|
||||||
contentDescription = stringResource(R.string.restart_app)
|
|
||||||
)
|
|
||||||
Spacer(Modifier.width(16.dp))
|
|
||||||
AutoSizeText(
|
|
||||||
text = stringResource(R.string.restart_app),
|
|
||||||
maxLines = 1
|
|
||||||
)
|
|
||||||
Spacer(Modifier.width(16.dp))
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
Spacer(Modifier.width(8.dp))
|
|
||||||
EnhancedFloatingActionButton(
|
|
||||||
containerColor = MaterialTheme.colorScheme.tertiaryContainer,
|
|
||||||
onClick = copyCrashInfo
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Rounded.ContentCopy,
|
|
||||||
contentDescription = stringResource(R.string.copy)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -58,7 +58,7 @@ import ru.tech.imageresizershrinker.core.ui.utils.state.update
|
|||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
abstract class M3Activity : AppCompatActivity() {
|
abstract class ComposeActivity : AppCompatActivity() {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var analyticsManager: AnalyticsManager
|
lateinit var analyticsManager: AnalyticsManager
|
||||||
@ -115,7 +115,7 @@ abstract class M3Activity : AppCompatActivity() {
|
|||||||
updateFirebaseParams()
|
updateFirebaseParams()
|
||||||
val colorTuple = state.appColorTuple.asColorTuple()
|
val colorTuple = state.appColorTuple.asColorTuple()
|
||||||
DynamicColors.applyToActivitiesIfAvailable(
|
DynamicColors.applyToActivitiesIfAvailable(
|
||||||
this@M3Activity.application,
|
this@ComposeActivity.application,
|
||||||
DynamicColorsOptions.Builder()
|
DynamicColorsOptions.Builder()
|
||||||
.setContentBasedSource(colorTuple.primary.toArgb())
|
.setContentBasedSource(colorTuple.primary.toArgb())
|
||||||
.build()
|
.build()
|
@ -19,13 +19,13 @@ package ru.tech.imageresizershrinker.feature.media_picker.presentation
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import com.arkivanov.decompose.retainedComponent
|
import com.arkivanov.decompose.retainedComponent
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import ru.tech.imageresizershrinker.core.ui.utils.M3Activity
|
import ru.tech.imageresizershrinker.core.ui.utils.ComposeActivity
|
||||||
import ru.tech.imageresizershrinker.feature.media_picker.presentation.components.MediaPickerRootContent
|
import ru.tech.imageresizershrinker.feature.media_picker.presentation.components.MediaPickerRootContent
|
||||||
import ru.tech.imageresizershrinker.feature.media_picker.presentation.screenLogic.MediaPickerComponent
|
import ru.tech.imageresizershrinker.feature.media_picker.presentation.screenLogic.MediaPickerComponent
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MediaPickerActivity : M3Activity() {
|
class MediaPickerActivity : ComposeActivity() {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var componentFactory: MediaPickerComponent.Factory
|
lateinit var componentFactory: MediaPickerComponent.Factory
|
||||||
|
@ -26,6 +26,7 @@ import androidx.datastore.preferences.core.MutablePreferences
|
|||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import androidx.datastore.preferences.core.edit
|
import androidx.datastore.preferences.core.edit
|
||||||
import com.t8rin.logger.Logger
|
import com.t8rin.logger.Logger
|
||||||
|
import com.t8rin.logger.makeLog
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
@ -461,6 +462,8 @@ internal class AndroidSettingsManager @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun createLogsExport(): ByteArray = withContext(ioDispatcher) {
|
override suspend fun createLogsExport(): ByteArray = withContext(ioDispatcher) {
|
||||||
|
"Start Logs Export".makeLog("SettingsManager")
|
||||||
|
|
||||||
val logsFile = Logger.getLogsFile().toFile()
|
val logsFile = Logger.getLogsFile().toFile()
|
||||||
val settingsFile = createBackupFile()
|
val settingsFile = createBackupFile()
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user