mirror of
https://github.com/T8RIN/ImageToolbox.git
synced 2025-08-06 15:49:35 +08:00
Refactor foss/market APIs
This commit is contained in:
@ -30,15 +30,15 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.findActivity
|
||||
|
||||
object ReviewHandler {
|
||||
internal object ReviewHandlerImpl : ReviewHandler {
|
||||
private val Context.dataStore by preferencesDataStore("saves_count")
|
||||
private val SAVES_COUNT = intPreferencesKey("SAVES_COUNT")
|
||||
private val NOT_SHOW_AGAIN = booleanPreferencesKey("NOT_SHOW_AGAIN")
|
||||
|
||||
private val _showNotShowAgainButton = mutableStateOf(false)
|
||||
val showNotShowAgainButton: Boolean by _showNotShowAgainButton
|
||||
override val showNotShowAgainButton: Boolean by _showNotShowAgainButton
|
||||
|
||||
fun showReview(
|
||||
override fun showReview(
|
||||
context: Context,
|
||||
onComplete: () -> Unit = {}
|
||||
) {
|
||||
@ -68,7 +68,7 @@ object ReviewHandler {
|
||||
}
|
||||
}
|
||||
|
||||
fun notShowReviewAgain(context: Context) {
|
||||
override fun notShowReviewAgain(context: Context) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
context.dataStore.edit {
|
||||
it[NOT_SHOW_AGAIN] = true
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.ui.widget.sheets
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
@Composable
|
||||
fun UpdateSheet(
|
||||
changelog: String,
|
||||
tag: String,
|
||||
visible: Boolean,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
DefaultUpdateSheet(
|
||||
changelog = changelog,
|
||||
tag = tag,
|
||||
visible = visible,
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
}
|
@ -26,7 +26,7 @@ import ru.tech.imageresizershrinker.core.domain.saving.model.SaveResult
|
||||
import ru.tech.imageresizershrinker.core.domain.utils.ListUtils.firstOfType
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.requestStoragePermission
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ReviewHandler.showReview
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ReviewHandler.Companion.showReview
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalEssentials
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.other.ToastDuration
|
||||
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.ui.utils.helper
|
||||
|
||||
import android.content.Context
|
||||
|
||||
interface ReviewHandler {
|
||||
|
||||
val showNotShowAgainButton: Boolean
|
||||
|
||||
fun showReview(
|
||||
context: Context,
|
||||
onComplete: () -> Unit = {}
|
||||
)
|
||||
|
||||
fun notShowReviewAgain(context: Context)
|
||||
|
||||
companion object : ReviewHandler by ReviewHandlerImpl
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ImageToolbox is an image editor for android
|
||||
* Copyright (c) 2024 T8RIN (Malik Mukhametzyanov)
|
||||
* 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.
|
||||
@ -15,10 +15,8 @@
|
||||
* along with this program. If not, see <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||
*/
|
||||
|
||||
package ru.tech.imageresizershrinker.core.ui.widget
|
||||
package ru.tech.imageresizershrinker.core.ui.widget.sheets
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@ -36,10 +34,9 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.net.toUri
|
||||
import ru.tech.imageresizershrinker.core.domain.APP_RELEASES
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
|
||||
@ -50,14 +47,12 @@ import ru.tech.imageresizershrinker.core.ui.widget.text.HtmlText
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.text.TitleItem
|
||||
|
||||
@Composable
|
||||
fun UpdateSheet(
|
||||
internal fun DefaultUpdateSheet(
|
||||
changelog: String,
|
||||
tag: String,
|
||||
visible: Boolean,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
EnhancedModalBottomSheet(
|
||||
visible = visible,
|
||||
onDismiss = {
|
||||
@ -90,27 +85,31 @@ fun UpdateSheet(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Column(Modifier.verticalScroll(rememberScrollState())) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
val linkHandler = LocalUriHandler.current
|
||||
HtmlText(
|
||||
html = changelog.trimIndent(),
|
||||
modifier = Modifier.padding(start = 24.dp, end = 24.dp, top = 24.dp)
|
||||
) { uri ->
|
||||
context.startActivity(Intent(Intent.ACTION_VIEW, uri.toUri()))
|
||||
}
|
||||
modifier = Modifier.padding(
|
||||
start = 24.dp,
|
||||
end = 24.dp,
|
||||
top = 24.dp
|
||||
),
|
||||
onHyperlinkClick = linkHandler::openUri
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
val linkHandler = LocalUriHandler.current
|
||||
EnhancedButton(
|
||||
onClick = {
|
||||
context.startActivity(
|
||||
Intent(
|
||||
Intent.ACTION_VIEW,
|
||||
Uri.parse("$APP_RELEASES/tag/${tag}")
|
||||
)
|
||||
)
|
||||
linkHandler.openUri("$APP_RELEASES/tag/${tag}")
|
||||
}
|
||||
) {
|
||||
AutoSizeText(stringResource(id = R.string.update))
|
@ -21,13 +21,13 @@ import android.app.Activity
|
||||
import android.content.Context
|
||||
import com.google.android.play.core.review.ReviewManagerFactory
|
||||
|
||||
object ReviewHandler {
|
||||
internal object ReviewHandlerImpl : ReviewHandler {
|
||||
|
||||
val showNotShowAgainButton: Boolean = false
|
||||
override val showNotShowAgainButton: Boolean = false
|
||||
|
||||
fun showReview(
|
||||
override fun showReview(
|
||||
context: Context,
|
||||
onComplete: () -> Unit = {}
|
||||
onComplete: () -> Unit
|
||||
) {
|
||||
runCatching {
|
||||
val reviewManager = ReviewManagerFactory.create(context)
|
||||
@ -46,6 +46,6 @@ object ReviewHandler {
|
||||
}
|
||||
}
|
||||
|
||||
fun notShowReviewAgain(context: Context) = Unit
|
||||
override fun notShowReviewAgain(context: Context) = Unit
|
||||
|
||||
}
|
@ -1,173 +0,0 @@
|
||||
/*
|
||||
* ImageToolbox is an image editor for android
|
||||
* Copyright (c) 2024 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.ui.widget
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.FileDownloadOff
|
||||
import androidx.compose.material.icons.rounded.NewReleases
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ProvideTextStyle
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
|
||||
import com.google.android.play.core.appupdate.AppUpdateOptions
|
||||
import com.google.android.play.core.install.model.AppUpdateType
|
||||
import com.google.android.play.core.install.model.UpdateAvailability
|
||||
import kotlinx.coroutines.launch
|
||||
import ru.tech.imageresizershrinker.core.domain.APP_RELEASES
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.isInstalledFromPlayStore
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedModalBottomSheet
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedModalSheetDragHandle
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.other.LocalToastHostState
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.text.AutoSizeText
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.text.HtmlText
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.text.TitleItem
|
||||
|
||||
@Composable
|
||||
fun UpdateSheet(
|
||||
changelog: String,
|
||||
tag: String,
|
||||
visible: Boolean,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val toastHostState = LocalToastHostState.current
|
||||
|
||||
if (context.isInstalledFromPlayStore()) {
|
||||
LaunchedEffect(visible) {
|
||||
if (visible) {
|
||||
runCatching {
|
||||
val appUpdateManager = AppUpdateManagerFactory.create(context)
|
||||
|
||||
val appUpdateInfoTask = appUpdateManager.appUpdateInfo
|
||||
|
||||
appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
|
||||
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
|
||||
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
|
||||
) {
|
||||
appUpdateManager.startUpdateFlow(
|
||||
appUpdateInfo,
|
||||
context as Activity,
|
||||
AppUpdateOptions.defaultOptions(AppUpdateType.IMMEDIATE)
|
||||
)
|
||||
} else {
|
||||
scope.launch {
|
||||
toastHostState.showToast(
|
||||
icon = Icons.Rounded.FileDownloadOff,
|
||||
message = context.getString(R.string.no_updates)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
scope.launch {
|
||||
toastHostState.showToast(
|
||||
icon = Icons.Rounded.FileDownloadOff,
|
||||
message = context.getString(R.string.no_updates)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
EnhancedModalBottomSheet(
|
||||
visible = visible,
|
||||
onDismiss = {
|
||||
if (!it) onDismiss()
|
||||
},
|
||||
title = {},
|
||||
dragHandle = {
|
||||
EnhancedModalSheetDragHandle {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
CompositionLocalProvider(
|
||||
LocalContentColor.provides(MaterialTheme.colorScheme.onSurface),
|
||||
LocalTextStyle.provides(MaterialTheme.typography.bodyLarge)
|
||||
) {
|
||||
TitleItem(
|
||||
text = stringResource(R.string.new_version, tag),
|
||||
icon = Icons.Rounded.NewReleases
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
sheetContent = {
|
||||
ProvideTextStyle(value = MaterialTheme.typography.bodyMedium) {
|
||||
Box {
|
||||
Column(
|
||||
modifier = Modifier.align(Alignment.TopCenter),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
val linkHandler = LocalUriHandler.current
|
||||
HtmlText(
|
||||
html = changelog.trimIndent(),
|
||||
modifier = Modifier.padding(
|
||||
start = 24.dp,
|
||||
end = 24.dp,
|
||||
top = 24.dp
|
||||
),
|
||||
onHyperlinkClick = linkHandler::openUri
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
val linkHandler = LocalUriHandler.current
|
||||
EnhancedButton(
|
||||
onClick = {
|
||||
linkHandler.openUri("$APP_RELEASES/tag/${tag}")
|
||||
}
|
||||
) {
|
||||
AutoSizeText(stringResource(id = R.string.update))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.ui.widget.sheets
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.FileDownloadOff
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import com.google.android.play.core.appupdate.AppUpdateManagerFactory
|
||||
import com.google.android.play.core.appupdate.AppUpdateOptions
|
||||
import com.google.android.play.core.install.model.AppUpdateType
|
||||
import com.google.android.play.core.install.model.UpdateAvailability
|
||||
import kotlinx.coroutines.launch
|
||||
import ru.tech.imageresizershrinker.core.resources.R
|
||||
import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.isInstalledFromPlayStore
|
||||
import ru.tech.imageresizershrinker.core.ui.widget.other.LocalToastHostState
|
||||
|
||||
@Composable
|
||||
fun UpdateSheet(
|
||||
changelog: String,
|
||||
tag: String,
|
||||
visible: Boolean,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
val toastHostState = LocalToastHostState.current
|
||||
|
||||
if (context.isInstalledFromPlayStore()) {
|
||||
LaunchedEffect(visible) {
|
||||
if (visible) {
|
||||
runCatching {
|
||||
val appUpdateManager = AppUpdateManagerFactory.create(context)
|
||||
|
||||
val appUpdateInfoTask = appUpdateManager.appUpdateInfo
|
||||
|
||||
appUpdateInfoTask.addOnSuccessListener { appUpdateInfo ->
|
||||
if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE
|
||||
&& appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)
|
||||
) {
|
||||
appUpdateManager.startUpdateFlow(
|
||||
appUpdateInfo,
|
||||
context as Activity,
|
||||
AppUpdateOptions.defaultOptions(AppUpdateType.IMMEDIATE)
|
||||
)
|
||||
} else {
|
||||
scope.launch {
|
||||
toastHostState.showToast(
|
||||
icon = Icons.Rounded.FileDownloadOff,
|
||||
message = context.getString(R.string.no_updates)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
scope.launch {
|
||||
toastHostState.showToast(
|
||||
icon = Icons.Rounded.FileDownloadOff,
|
||||
message = context.getString(R.string.no_updates)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DefaultUpdateSheet(
|
||||
changelog = changelog,
|
||||
tag = tag,
|
||||
visible = visible,
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user