mirror of
https://github.com/ReVanced/revanced-manager.git
synced 2025-07-08 11:38:19 +08:00
Compare commits
1 Commits
compose-de
...
feat/toolt
Author | SHA1 | Date | |
---|---|---|---|
111c74329f |
@ -40,8 +40,6 @@ class DownloadedAppRepository(
|
|||||||
data: Parcelable,
|
data: Parcelable,
|
||||||
expectedPackageName: String,
|
expectedPackageName: String,
|
||||||
expectedVersion: String?,
|
expectedVersion: String?,
|
||||||
appCompatibilityCheck: Boolean,
|
|
||||||
patchesCompatibilityCheck: Boolean,
|
|
||||||
onDownload: suspend (downloadProgress: Pair<Long, Long?>) -> Unit,
|
onDownload: suspend (downloadProgress: Pair<Long, Long?>) -> Unit,
|
||||||
): File {
|
): File {
|
||||||
// Converted integers cannot contain / or .. unlike the package name or version, so they are safer to use here.
|
// Converted integers cannot contain / or .. unlike the package name or version, so they are safer to use here.
|
||||||
@ -98,12 +96,7 @@ class DownloadedAppRepository(
|
|||||||
val pkgInfo =
|
val pkgInfo =
|
||||||
pm.getPackageInfo(targetFile.toFile()) ?: error("Downloaded APK file is invalid")
|
pm.getPackageInfo(targetFile.toFile()) ?: error("Downloaded APK file is invalid")
|
||||||
if (pkgInfo.packageName != expectedPackageName) error("Downloaded APK has the wrong package name. Expected: $expectedPackageName, Actual: ${pkgInfo.packageName}")
|
if (pkgInfo.packageName != expectedPackageName) error("Downloaded APK has the wrong package name. Expected: $expectedPackageName, Actual: ${pkgInfo.packageName}")
|
||||||
expectedVersion?.let {
|
if (expectedVersion != null && pkgInfo.versionName != expectedVersion) error("Downloaded APK has the wrong version. Expected: $expectedVersion, Actual: ${pkgInfo.versionName}")
|
||||||
if (
|
|
||||||
pkgInfo.versionName != expectedVersion &&
|
|
||||||
(appCompatibilityCheck || patchesCompatibilityCheck)
|
|
||||||
) error("The selected app version ($pkgInfo.versionName) doesn't match the suggested version. Please use the suggested version ($expectedVersion), or adjust your settings by disabling \"Require suggested app version\" and enabling \"Disable version compatibility check\".")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete the previous copy (if present).
|
// Delete the previous copy (if present).
|
||||||
dao.get(pkgInfo.packageName, pkgInfo.versionName!!)?.directory?.let {
|
dao.get(pkgInfo.packageName, pkgInfo.versionName!!)?.directory?.let {
|
||||||
|
@ -14,9 +14,9 @@ import android.os.Parcelable
|
|||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.activity.result.ActivityResult
|
import androidx.activity.result.ActivityResult
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.work.ForegroundInfo
|
import androidx.work.ForegroundInfo
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import app.revanced.manager.MainActivity
|
|
||||||
import app.revanced.manager.R
|
import app.revanced.manager.R
|
||||||
import app.revanced.manager.data.platform.Filesystem
|
import app.revanced.manager.data.platform.Filesystem
|
||||||
import app.revanced.manager.data.room.apps.installed.InstallType
|
import app.revanced.manager.data.room.apps.installed.InstallType
|
||||||
@ -88,25 +88,22 @@ class PatcherWorker(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private fun createNotification(): Notification {
|
private fun createNotification(): Notification {
|
||||||
val notificationIntent = Intent(applicationContext, MainActivity::class.java).apply {
|
val notificationIntent = Intent(applicationContext, PatcherWorker::class.java)
|
||||||
flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
val pendingIntent: PendingIntent = PendingIntent.getActivity(
|
||||||
}
|
|
||||||
val pendingIntent = PendingIntent.getActivity(
|
|
||||||
applicationContext, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE
|
applicationContext, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE
|
||||||
)
|
)
|
||||||
val channel = NotificationChannel(
|
val channel = NotificationChannel(
|
||||||
"revanced-patcher-patching", "Patching", NotificationManager.IMPORTANCE_LOW
|
"revanced-patcher-patching", "Patching", NotificationManager.IMPORTANCE_HIGH
|
||||||
)
|
)
|
||||||
val notificationManager =
|
val notificationManager =
|
||||||
applicationContext.getSystemService(NotificationManager::class.java)
|
ContextCompat.getSystemService(applicationContext, NotificationManager::class.java)
|
||||||
notificationManager.createNotificationChannel(channel)
|
notificationManager!!.createNotificationChannel(channel)
|
||||||
return Notification.Builder(applicationContext, channel.id)
|
return Notification.Builder(applicationContext, channel.id)
|
||||||
.setContentTitle(applicationContext.getText(R.string.patcher_notification_title))
|
.setContentTitle(applicationContext.getText(R.string.app_name))
|
||||||
.setContentText(applicationContext.getText(R.string.patcher_notification_text))
|
.setContentText(applicationContext.getText(R.string.patcher_notification_message))
|
||||||
|
.setLargeIcon(Icon.createWithResource(applicationContext, R.drawable.ic_notification))
|
||||||
.setSmallIcon(Icon.createWithResource(applicationContext, R.drawable.ic_notification))
|
.setSmallIcon(Icon.createWithResource(applicationContext, R.drawable.ic_notification))
|
||||||
.setContentIntent(pendingIntent)
|
.setContentIntent(pendingIntent).build()
|
||||||
.setCategory(Notification.CATEGORY_SERVICE)
|
|
||||||
.build()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun doWork(): Result {
|
override suspend fun doWork(): Result {
|
||||||
@ -161,8 +158,6 @@ class PatcherWorker(
|
|||||||
data,
|
data,
|
||||||
args.packageName,
|
args.packageName,
|
||||||
args.input.version,
|
args.input.version,
|
||||||
prefs.suggestedVersionSafeguard.get(),
|
|
||||||
!prefs.disablePatchVersionCompatCheck.get(),
|
|
||||||
onDownload = args.onDownloadProgress
|
onDownload = args.onDownloadProgress
|
||||||
).also {
|
).also {
|
||||||
args.setInputFile(it)
|
args.setInputFile(it)
|
||||||
|
@ -69,10 +69,15 @@ fun AppTopBar(
|
|||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
if (onBackClick != null) {
|
if (onBackClick != null) {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.back),
|
||||||
|
) {
|
||||||
IconButton(onClick = onBackClick) {
|
IconButton(onClick = onBackClick) {
|
||||||
backIcon()
|
backIcon()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
actions = actions,
|
actions = actions,
|
||||||
colors = TopAppBarDefaults.topAppBarColors(
|
colors = TopAppBarDefaults.topAppBarColors(
|
||||||
@ -108,10 +113,15 @@ fun AppTopBar(
|
|||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
if (onBackClick != null) {
|
if (onBackClick != null) {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.back),
|
||||||
|
) {
|
||||||
IconButton(onClick = onBackClick) {
|
IconButton(onClick = onBackClick) {
|
||||||
backIcon()
|
backIcon()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
actions = actions,
|
actions = actions,
|
||||||
colors = TopAppBarDefaults.topAppBarColors(
|
colors = TopAppBarDefaults.topAppBarColors(
|
||||||
|
@ -27,6 +27,10 @@ fun ArrowButton(
|
|||||||
)
|
)
|
||||||
|
|
||||||
onClick?.let {
|
onClick?.let {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(description),
|
||||||
|
) {
|
||||||
IconButton(onClick = it) {
|
IconButton(onClick = it) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Filled.KeyboardArrowUp,
|
imageVector = Icons.Filled.KeyboardArrowUp,
|
||||||
@ -36,6 +40,7 @@ fun ArrowButton(
|
|||||||
.then(modifier)
|
.then(modifier)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} ?: Icon(
|
} ?: Icon(
|
||||||
imageVector = Icons.Filled.KeyboardArrowUp,
|
imageVector = Icons.Filled.KeyboardArrowUp,
|
||||||
contentDescription = stringResource(description),
|
contentDescription = stringResource(description),
|
||||||
|
@ -39,6 +39,10 @@ fun ExceptionViewerDialog(text: String, onDismiss: () -> Unit) {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.share),
|
||||||
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
val sendIntent: Intent = Intent().apply {
|
val sendIntent: Intent = Intent().apply {
|
||||||
@ -60,6 +64,7 @@ fun ExceptionViewerDialog(text: String, onDismiss: () -> Unit) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
|
@ -138,6 +138,10 @@ fun NotificationCard(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (onDismiss != null) {
|
if (onDismiss != null) {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = modifier,
|
||||||
|
tooltip = stringResource(R.string.close),
|
||||||
|
) {
|
||||||
IconButton(onClick = onDismiss) {
|
IconButton(onClick = onDismiss) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Outlined.Close,
|
imageVector = Icons.Outlined.Close,
|
||||||
@ -149,6 +153,7 @@ fun NotificationCard(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun NotificationCardInstance(
|
private fun NotificationCardInstance(
|
||||||
|
@ -33,6 +33,10 @@ fun PasswordField(modifier: Modifier = Modifier, value: String, onValueChange: (
|
|||||||
label = label,
|
label = label,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = modifier,
|
||||||
|
tooltip = if (visible) stringResource(R.string.show_password_field) else stringResource(R.string.hide_password_field),
|
||||||
|
) {
|
||||||
IconButton(onClick = {
|
IconButton(onClick = {
|
||||||
visible = !visible
|
visible = !visible
|
||||||
}) {
|
}) {
|
||||||
@ -41,6 +45,7 @@ fun PasswordField(modifier: Modifier = Modifier, value: String, onValueChange: (
|
|||||||
}
|
}
|
||||||
Icon(icon, stringResource(description))
|
Icon(icon, stringResource(description))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions = KeyboardOptions(
|
||||||
keyboardType = KeyboardType.Password
|
keyboardType = KeyboardType.Password
|
||||||
|
@ -48,6 +48,10 @@ fun SearchView(
|
|||||||
onExpandedChange = onActiveChange,
|
onExpandedChange = onActiveChange,
|
||||||
placeholder = placeholder,
|
placeholder = placeholder,
|
||||||
leadingIcon = {
|
leadingIcon = {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.back),
|
||||||
|
) {
|
||||||
IconButton(onClick = { onActiveChange(false) }) {
|
IconButton(onClick = { onActiveChange(false) }) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.AutoMirrored.Filled.ArrowBack,
|
Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
@ -55,6 +59,7 @@ fun SearchView(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
expanded = true,
|
expanded = true,
|
||||||
|
@ -0,0 +1,94 @@
|
|||||||
|
package app.revanced.manager.ui.component
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.PlainTooltip
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TooltipBox
|
||||||
|
import androidx.compose.material3.TooltipDefaults
|
||||||
|
import androidx.compose.material3.rememberTooltipState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||||
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.window.PopupPositionProvider
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a composable with a tooltip.
|
||||||
|
*
|
||||||
|
* @param modifier the [Modifier] to be applied to the [TooltipBox]
|
||||||
|
* @param tooltip the text to be displayed in the [TooltipBox]
|
||||||
|
* @param positionProvider Anchor point for the tooltip, defaults to [TooltipDefaults.rememberPlainTooltipPositionProvider]
|
||||||
|
* @param content The composable UI to be wrapped with [TooltipBox]
|
||||||
|
*
|
||||||
|
* @see [TooltipBox]
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
fun TooltipWrap(
|
||||||
|
modifier: Modifier,
|
||||||
|
tooltip: String,
|
||||||
|
positionProvider: PopupPositionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
|
||||||
|
content: @Composable () -> Unit
|
||||||
|
) {
|
||||||
|
val tooltipState = rememberTooltipState()
|
||||||
|
val haptic = LocalHapticFeedback.current
|
||||||
|
|
||||||
|
LaunchedEffect(tooltipState.isVisible) {
|
||||||
|
if (tooltipState.isVisible) {
|
||||||
|
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TooltipBox(
|
||||||
|
modifier = modifier,
|
||||||
|
positionProvider = positionProvider,
|
||||||
|
tooltip = {
|
||||||
|
PlainTooltip { Text(tooltip) }
|
||||||
|
},
|
||||||
|
state = tooltipState
|
||||||
|
) {
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a composable with a tooltip.
|
||||||
|
*
|
||||||
|
* @param modifier the [Modifier] to be applied to the [TooltipBox]
|
||||||
|
* @param tooltip the R.string to be displayed in the [TooltipBox]
|
||||||
|
* @param positionProvider Anchor point for the tooltip, defaults to [TooltipDefaults.rememberPlainTooltipPositionProvider]
|
||||||
|
* @param content The composable UI to be wrapped with [TooltipBox]
|
||||||
|
*
|
||||||
|
* @see [TooltipBox]
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
fun TooltipWrap(
|
||||||
|
modifier: Modifier,
|
||||||
|
@StringRes tooltip: Int,
|
||||||
|
positionProvider: PopupPositionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
|
||||||
|
content: @Composable () -> Unit
|
||||||
|
) {
|
||||||
|
val tooltipState = rememberTooltipState()
|
||||||
|
val haptic = LocalHapticFeedback.current
|
||||||
|
|
||||||
|
LaunchedEffect(tooltipState.isVisible) {
|
||||||
|
if (tooltipState.isVisible) {
|
||||||
|
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TooltipBox(
|
||||||
|
modifier = modifier,
|
||||||
|
positionProvider = positionProvider,
|
||||||
|
tooltip = {
|
||||||
|
PlainTooltip { Text(stringResource(tooltip)) }
|
||||||
|
},
|
||||||
|
state = tooltipState
|
||||||
|
) {
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,7 @@ import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.isDefaul
|
|||||||
import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.nameState
|
import app.revanced.manager.domain.bundles.PatchBundleSource.Extensions.nameState
|
||||||
import app.revanced.manager.ui.component.ExceptionViewerDialog
|
import app.revanced.manager.ui.component.ExceptionViewerDialog
|
||||||
import app.revanced.manager.ui.component.FullscreenDialog
|
import app.revanced.manager.ui.component.FullscreenDialog
|
||||||
|
import app.revanced.manager.ui.component.TooltipWrap
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
|
|
||||||
@ -72,6 +73,10 @@ fun BundleInformationDialog(
|
|||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
if (!bundle.isDefault) {
|
if (!bundle.isDefault) {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.delete),
|
||||||
|
) {
|
||||||
IconButton(onClick = onDeleteRequest) {
|
IconButton(onClick = onDeleteRequest) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.Outlined.DeleteOutline,
|
Icons.Outlined.DeleteOutline,
|
||||||
@ -79,7 +84,12 @@ fun BundleInformationDialog(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!isLocal && hasNetwork) {
|
if (!isLocal && hasNetwork) {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.refresh),
|
||||||
|
) {
|
||||||
IconButton(onClick = onUpdate) {
|
IconButton(onClick = onUpdate) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.Outlined.Update,
|
Icons.Outlined.Update,
|
||||||
@ -88,6 +98,7 @@ fun BundleInformationDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
|
@ -10,7 +10,11 @@ import androidx.compose.material3.TopAppBarDefaults
|
|||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.material3.surfaceColorAtElevation
|
import androidx.compose.material3.surfaceColorAtElevation
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import app.revanced.manager.R
|
||||||
|
import app.revanced.manager.ui.component.TooltipWrap
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@ -33,10 +37,15 @@ fun BundleTopBar(
|
|||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
if (onBackClick != null) {
|
if (onBackClick != null) {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.back),
|
||||||
|
) {
|
||||||
IconButton(onClick = onBackClick) {
|
IconButton(onClick = onBackClick) {
|
||||||
backIcon()
|
backIcon()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
actions = actions,
|
actions = actions,
|
||||||
colors = TopAppBarDefaults.topAppBarColors(
|
colors = TopAppBarDefaults.topAppBarColors(
|
||||||
|
@ -189,6 +189,7 @@ fun ImportBundleStep(
|
|||||||
},
|
},
|
||||||
supportingContent = { Text(stringResource(if (patchBundle != null) R.string.file_field_set else R.string.file_field_not_set)) },
|
supportingContent = { Text(stringResource(if (patchBundle != null) R.string.file_field_set else R.string.file_field_not_set)) },
|
||||||
trailingContent = {
|
trailingContent = {
|
||||||
|
// TODO: Determine if this button should be [TooltipWrap]'ped
|
||||||
IconButton(onClick = launchPatchActivity) {
|
IconButton(onClick = launchPatchActivity) {
|
||||||
Icon(imageVector = Icons.Default.Topic, contentDescription = null)
|
Icon(imageVector = Icons.Default.Topic, contentDescription = null)
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,7 @@ import app.revanced.manager.ui.component.FloatInputDialog
|
|||||||
import app.revanced.manager.ui.component.FullscreenDialog
|
import app.revanced.manager.ui.component.FullscreenDialog
|
||||||
import app.revanced.manager.ui.component.IntInputDialog
|
import app.revanced.manager.ui.component.IntInputDialog
|
||||||
import app.revanced.manager.ui.component.LongInputDialog
|
import app.revanced.manager.ui.component.LongInputDialog
|
||||||
|
import app.revanced.manager.ui.component.TooltipWrap
|
||||||
import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionButton
|
import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionButton
|
||||||
import app.revanced.manager.ui.component.haptics.HapticRadioButton
|
import app.revanced.manager.ui.component.haptics.HapticRadioButton
|
||||||
import app.revanced.manager.ui.component.haptics.HapticSwitch
|
import app.revanced.manager.ui.component.haptics.HapticSwitch
|
||||||
@ -74,13 +75,11 @@ import app.revanced.manager.util.saver.snapshotStateListSaver
|
|||||||
import app.revanced.manager.util.saver.snapshotStateSetSaver
|
import app.revanced.manager.util.saver.snapshotStateSetSaver
|
||||||
import app.revanced.manager.util.toast
|
import app.revanced.manager.util.toast
|
||||||
import app.revanced.manager.util.transparentListItemColors
|
import app.revanced.manager.util.transparentListItemColors
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
import org.koin.core.component.KoinComponent
|
import org.koin.core.component.KoinComponent
|
||||||
import org.koin.core.component.get
|
import org.koin.core.component.get
|
||||||
import sh.calvin.reorderable.ReorderableItem
|
import sh.calvin.reorderable.ReorderableItem
|
||||||
import sh.calvin.reorderable.rememberReorderableLazyColumnState
|
|
||||||
import sh.calvin.reorderable.rememberReorderableLazyListState
|
import sh.calvin.reorderable.rememberReorderableLazyListState
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
@ -113,10 +112,15 @@ private interface OptionEditor<T : Any> {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ListItemTrailingContent(scope: OptionEditorScope<T>) {
|
fun ListItemTrailingContent(scope: OptionEditorScope<T>) {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.edit),
|
||||||
|
) {
|
||||||
IconButton(onClick = { clickAction(scope) }) {
|
IconButton(onClick = { clickAction(scope) }) {
|
||||||
Icon(Icons.Outlined.Edit, stringResource(R.string.edit))
|
Icon(Icons.Outlined.Edit, stringResource(R.string.edit))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Dialog(scope: OptionEditorScope<T>)
|
fun Dialog(scope: OptionEditorScope<T>)
|
||||||
@ -249,6 +253,10 @@ private object StringOptionEditor : OptionEditor<String> {
|
|||||||
},
|
},
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
var showDropdownMenu by rememberSaveable { mutableStateOf(false) }
|
var showDropdownMenu by rememberSaveable { mutableStateOf(false) }
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.string_option_menu_description),
|
||||||
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = { showDropdownMenu = true }
|
onClick = { showDropdownMenu = true }
|
||||||
) {
|
) {
|
||||||
@ -257,6 +265,7 @@ private object StringOptionEditor : OptionEditor<String> {
|
|||||||
stringResource(R.string.string_option_menu_description)
|
stringResource(R.string.string_option_menu_description)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DropdownMenu(
|
DropdownMenu(
|
||||||
expanded = showDropdownMenu,
|
expanded = showDropdownMenu,
|
||||||
@ -551,6 +560,10 @@ private class ListOptionEditor<T : Serializable>(private val elementEditor: Opti
|
|||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
if (deleteMode) {
|
if (deleteMode) {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.select_deselect_all),
|
||||||
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (items.size == deletionTargets.size) deletionTargets.clear()
|
if (items.size == deletionTargets.size) deletionTargets.clear()
|
||||||
@ -562,6 +575,11 @@ private class ListOptionEditor<T : Serializable>(private val elementEditor: Opti
|
|||||||
stringResource(R.string.select_deselect_all)
|
stringResource(R.string.select_deselect_all)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.delete),
|
||||||
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
items.removeIf { it.key in deletionTargets }
|
items.removeIf { it.key in deletionTargets }
|
||||||
@ -574,12 +592,18 @@ private class ListOptionEditor<T : Serializable>(private val elementEditor: Opti
|
|||||||
stringResource(R.string.delete)
|
stringResource(R.string.delete)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.reset),
|
||||||
|
) {
|
||||||
IconButton(onClick = items::clear) {
|
IconButton(onClick = items::clear) {
|
||||||
Icon(Icons.Outlined.Restore, stringResource(R.string.reset))
|
Icon(Icons.Outlined.Restore, stringResource(R.string.reset))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
@ -643,6 +667,10 @@ private class ListOptionEditor<T : Serializable>(private val elementEditor: Opti
|
|||||||
),
|
),
|
||||||
tonalElevation = if (deleteMode && item.key in deletionTargets) 8.dp else 0.dp,
|
tonalElevation = if (deleteMode && item.key in deletionTargets) 8.dp else 0.dp,
|
||||||
leadingContent = {
|
leadingContent = {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.drag_handle),
|
||||||
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
modifier = Modifier.draggableHandle(interactionSource = interactionSource),
|
modifier = Modifier.draggableHandle(interactionSource = interactionSource),
|
||||||
onClick = {},
|
onClick = {},
|
||||||
@ -652,6 +680,7 @@ private class ListOptionEditor<T : Serializable>(private val elementEditor: Opti
|
|||||||
stringResource(R.string.drag_handle)
|
stringResource(R.string.drag_handle)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
headlineContent = {
|
headlineContent = {
|
||||||
if (item.value == null) return@ListItem Text(
|
if (item.value == null) return@ListItem Text(
|
||||||
|
@ -17,6 +17,7 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import app.revanced.manager.R
|
import app.revanced.manager.R
|
||||||
import app.revanced.manager.domain.manager.base.Preference
|
import app.revanced.manager.domain.manager.base.Preference
|
||||||
import app.revanced.manager.ui.component.IntInputDialog
|
import app.revanced.manager.ui.component.IntInputDialog
|
||||||
|
import app.revanced.manager.ui.component.TooltipWrap
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@ -65,6 +66,10 @@ fun IntegerItem(
|
|||||||
headlineContent = stringResource(headline),
|
headlineContent = stringResource(headline),
|
||||||
supportingContent = stringResource(description),
|
supportingContent = stringResource(description),
|
||||||
trailingContent = {
|
trailingContent = {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.edit),
|
||||||
|
) {
|
||||||
IconButton(onClick = { dialogOpen = true }) {
|
IconButton(onClick = { dialogOpen = true }) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.Outlined.Edit,
|
Icons.Outlined.Edit,
|
||||||
@ -72,5 +77,6 @@ fun IntegerItem(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -44,6 +44,7 @@ import app.revanced.manager.ui.component.LazyColumnWithScrollbar
|
|||||||
import app.revanced.manager.ui.component.LoadingIndicator
|
import app.revanced.manager.ui.component.LoadingIndicator
|
||||||
import app.revanced.manager.ui.component.NonSuggestedVersionDialog
|
import app.revanced.manager.ui.component.NonSuggestedVersionDialog
|
||||||
import app.revanced.manager.ui.component.SearchView
|
import app.revanced.manager.ui.component.SearchView
|
||||||
|
import app.revanced.manager.ui.component.TooltipWrap
|
||||||
import app.revanced.manager.ui.model.SelectedApp
|
import app.revanced.manager.ui.model.SelectedApp
|
||||||
import app.revanced.manager.ui.viewmodel.AppSelectorViewModel
|
import app.revanced.manager.ui.viewmodel.AppSelectorViewModel
|
||||||
import app.revanced.manager.util.APK_MIMETYPE
|
import app.revanced.manager.util.APK_MIMETYPE
|
||||||
@ -162,10 +163,15 @@ fun AppSelectorScreen(
|
|||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
onBackClick = onBackClick,
|
onBackClick = onBackClick,
|
||||||
actions = {
|
actions = {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.search_patches),
|
||||||
|
) {
|
||||||
IconButton(onClick = { search = true }) {
|
IconButton(onClick = { search = true }) {
|
||||||
Icon(Icons.Outlined.Search, stringResource(R.string.search))
|
Icon(Icons.Outlined.Search, stringResource(R.string.search))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
|
@ -62,8 +62,9 @@ import app.revanced.manager.ui.component.AlertDialogExtended
|
|||||||
import app.revanced.manager.ui.component.AppTopBar
|
import app.revanced.manager.ui.component.AppTopBar
|
||||||
import app.revanced.manager.ui.component.AutoUpdatesDialog
|
import app.revanced.manager.ui.component.AutoUpdatesDialog
|
||||||
import app.revanced.manager.ui.component.AvailableUpdateDialog
|
import app.revanced.manager.ui.component.AvailableUpdateDialog
|
||||||
import app.revanced.manager.ui.component.NotificationCard
|
|
||||||
import app.revanced.manager.ui.component.ConfirmDialog
|
import app.revanced.manager.ui.component.ConfirmDialog
|
||||||
|
import app.revanced.manager.ui.component.NotificationCard
|
||||||
|
import app.revanced.manager.ui.component.TooltipWrap
|
||||||
import app.revanced.manager.ui.component.bundle.BundleTopBar
|
import app.revanced.manager.ui.component.bundle.BundleTopBar
|
||||||
import app.revanced.manager.ui.component.bundle.ImportPatchBundleDialog
|
import app.revanced.manager.ui.component.bundle.ImportPatchBundleDialog
|
||||||
import app.revanced.manager.ui.component.haptics.HapticFloatingActionButton
|
import app.revanced.manager.ui.component.haptics.HapticFloatingActionButton
|
||||||
@ -183,6 +184,10 @@ fun DashboardScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.delete),
|
||||||
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
showDeleteConfirmationDialog = true
|
showDeleteConfirmationDialog = true
|
||||||
@ -193,6 +198,11 @@ fun DashboardScreen(
|
|||||||
stringResource(R.string.delete)
|
stringResource(R.string.delete)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.refresh),
|
||||||
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
vm.selectedSources.forEach { vm.update(it) }
|
vm.selectedSources.forEach { vm.update(it) }
|
||||||
@ -205,12 +215,17 @@ fun DashboardScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
AppTopBar(
|
AppTopBar(
|
||||||
title = stringResource(R.string.app_name),
|
title = stringResource(R.string.app_name),
|
||||||
actions = {
|
actions = {
|
||||||
if (!vm.updatedManagerVersion.isNullOrEmpty()) {
|
if (!vm.updatedManagerVersion.isNullOrEmpty()) {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.update),
|
||||||
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = onUpdateClick,
|
onClick = onUpdateClick,
|
||||||
) {
|
) {
|
||||||
@ -223,15 +238,25 @@ fun DashboardScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.settings),
|
||||||
|
) {
|
||||||
IconButton(onClick = onSettingsClick) {
|
IconButton(onClick = onSettingsClick) {
|
||||||
Icon(Icons.Outlined.Settings, stringResource(R.string.settings))
|
Icon(Icons.Outlined.Settings, stringResource(R.string.settings))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
applyContainerColor = true
|
applyContainerColor = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.add),
|
||||||
|
) {
|
||||||
HapticFloatingActionButton(
|
HapticFloatingActionButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
vm.cancelSourceSelection()
|
vm.cancelSourceSelection()
|
||||||
@ -262,6 +287,7 @@ fun DashboardScreen(
|
|||||||
}
|
}
|
||||||
) { Icon(Icons.Default.Add, stringResource(R.string.add)) }
|
) { Icon(Icons.Default.Add, stringResource(R.string.add)) }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Column(Modifier.padding(paddingValues)) {
|
Column(Modifier.padding(paddingValues)) {
|
||||||
TabRow(
|
TabRow(
|
||||||
|
@ -48,6 +48,7 @@ import app.revanced.manager.ui.component.AppScaffold
|
|||||||
import app.revanced.manager.ui.component.AppTopBar
|
import app.revanced.manager.ui.component.AppTopBar
|
||||||
import app.revanced.manager.ui.component.ConfirmDialog
|
import app.revanced.manager.ui.component.ConfirmDialog
|
||||||
import app.revanced.manager.ui.component.InstallerStatusDialog
|
import app.revanced.manager.ui.component.InstallerStatusDialog
|
||||||
|
import app.revanced.manager.ui.component.TooltipWrap
|
||||||
import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionButton
|
import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionButton
|
||||||
import app.revanced.manager.ui.component.patcher.InstallPickerDialog
|
import app.revanced.manager.ui.component.patcher.InstallPickerDialog
|
||||||
import app.revanced.manager.ui.component.patcher.Steps
|
import app.revanced.manager.ui.component.patcher.Steps
|
||||||
@ -164,18 +165,28 @@ fun PatcherScreen(
|
|||||||
bottomBar = {
|
bottomBar = {
|
||||||
BottomAppBar(
|
BottomAppBar(
|
||||||
actions = {
|
actions = {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.save_apk),
|
||||||
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = { exportApkLauncher.launch("${viewModel.packageName}_${viewModel.version}_revanced_patched.apk") },
|
onClick = { exportApkLauncher.launch("${viewModel.packageName}_${viewModel.version}_revanced_patched.apk") },
|
||||||
enabled = patcherSucceeded == true
|
enabled = patcherSucceeded == true
|
||||||
) {
|
) {
|
||||||
Icon(Icons.Outlined.Save, stringResource(id = R.string.save_apk))
|
Icon(Icons.Outlined.Save, stringResource(id = R.string.save_apk))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.save_logs),
|
||||||
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = { viewModel.exportLogs(context) },
|
onClick = { viewModel.exportLogs(context) },
|
||||||
enabled = patcherSucceeded != null
|
enabled = patcherSucceeded != null
|
||||||
) {
|
) {
|
||||||
Icon(Icons.Outlined.PostAdd, stringResource(id = R.string.save_logs))
|
Icon(Icons.Outlined.PostAdd, stringResource(id = R.string.save_logs))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
floatingActionButton = {
|
floatingActionButton = {
|
||||||
AnimatedVisibility(visible = canInstall) {
|
AnimatedVisibility(visible = canInstall) {
|
||||||
|
@ -69,6 +69,7 @@ import app.revanced.manager.ui.component.FullscreenDialog
|
|||||||
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
|
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
|
||||||
import app.revanced.manager.ui.component.SafeguardDialog
|
import app.revanced.manager.ui.component.SafeguardDialog
|
||||||
import app.revanced.manager.ui.component.SearchBar
|
import app.revanced.manager.ui.component.SearchBar
|
||||||
|
import app.revanced.manager.ui.component.TooltipWrap
|
||||||
import app.revanced.manager.ui.component.haptics.HapticCheckbox
|
import app.revanced.manager.ui.component.haptics.HapticCheckbox
|
||||||
import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionButton
|
import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionButton
|
||||||
import app.revanced.manager.ui.component.haptics.HapticTab
|
import app.revanced.manager.ui.component.haptics.HapticTab
|
||||||
@ -259,6 +260,10 @@ fun PatchesSelectorScreen(
|
|||||||
animationSpec = tween(durationMillis = 400, easing = EaseInOut),
|
animationSpec = tween(durationMillis = 400, easing = EaseInOut),
|
||||||
label = "SearchBar back button"
|
label = "SearchBar back button"
|
||||||
)
|
)
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.back),
|
||||||
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (searchExpanded) {
|
if (searchExpanded) {
|
||||||
@ -274,6 +279,7 @@ fun PatchesSelectorScreen(
|
|||||||
contentDescription = stringResource(R.string.back)
|
contentDescription = stringResource(R.string.back)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
AnimatedContent(
|
AnimatedContent(
|
||||||
@ -282,6 +288,10 @@ fun PatchesSelectorScreen(
|
|||||||
transitionSpec = { fadeIn() togetherWith fadeOut() }
|
transitionSpec = { fadeIn() togetherWith fadeOut() }
|
||||||
) { searchExpanded ->
|
) { searchExpanded ->
|
||||||
if (searchExpanded) {
|
if (searchExpanded) {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.clear),
|
||||||
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = { setQuery("") },
|
onClick = { setQuery("") },
|
||||||
enabled = query.isNotEmpty()
|
enabled = query.isNotEmpty()
|
||||||
@ -291,7 +301,12 @@ fun PatchesSelectorScreen(
|
|||||||
contentDescription = stringResource(R.string.clear)
|
contentDescription = stringResource(R.string.clear)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.more),
|
||||||
|
) {
|
||||||
IconButton(onClick = { showBottomSheet = true }) {
|
IconButton(onClick = { showBottomSheet = true }) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Outlined.FilterList,
|
imageVector = Icons.Outlined.FilterList,
|
||||||
@ -301,6 +316,7 @@ fun PatchesSelectorScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
val bundle = bundles[pagerState.currentPage]
|
val bundle = bundles[pagerState.currentPage]
|
||||||
|
|
||||||
@ -353,6 +369,10 @@ fun PatchesSelectorScreen(
|
|||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.End,
|
horizontalAlignment = Alignment.End,
|
||||||
verticalArrangement = Arrangement.spacedBy(4.dp)
|
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
|
) {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.reset),
|
||||||
) {
|
) {
|
||||||
SmallFloatingActionButton(
|
SmallFloatingActionButton(
|
||||||
onClick = viewModel::reset,
|
onClick = viewModel::reset,
|
||||||
@ -360,6 +380,7 @@ fun PatchesSelectorScreen(
|
|||||||
) {
|
) {
|
||||||
Icon(Icons.Outlined.Restore, stringResource(R.string.reset))
|
Icon(Icons.Outlined.Restore, stringResource(R.string.reset))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
HapticExtendedFloatingActionButton(
|
HapticExtendedFloatingActionButton(
|
||||||
text = {
|
text = {
|
||||||
Text(
|
Text(
|
||||||
@ -516,6 +537,7 @@ private fun PatchItem(
|
|||||||
supportingContent = patch.description?.let { { Text(it) } },
|
supportingContent = patch.description?.let { { Text(it) } },
|
||||||
trailingContent = {
|
trailingContent = {
|
||||||
if (patch.options?.isNotEmpty() == true) {
|
if (patch.options?.isNotEmpty() == true) {
|
||||||
|
// TODO: Determine if this button should be [TooltipWrap]
|
||||||
IconButton(onClick = onOptionsDialog, enabled = compatible) {
|
IconButton(onClick = onOptionsDialog, enabled = compatible) {
|
||||||
Icon(Icons.Outlined.Settings, null)
|
Icon(Icons.Outlined.Settings, null)
|
||||||
}
|
}
|
||||||
@ -539,6 +561,10 @@ fun ListHeader(
|
|||||||
},
|
},
|
||||||
trailingContent = onHelpClick?.let {
|
trailingContent = onHelpClick?.let {
|
||||||
{
|
{
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.help),
|
||||||
|
) {
|
||||||
IconButton(onClick = it) {
|
IconButton(onClick = it) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.AutoMirrored.Outlined.HelpOutline,
|
Icons.AutoMirrored.Outlined.HelpOutline,
|
||||||
@ -546,6 +572,7 @@ fun ListHeader(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
colors = transparentListItemColors
|
colors = transparentListItemColors
|
||||||
)
|
)
|
||||||
@ -618,10 +645,15 @@ private fun OptionsDialog(
|
|||||||
title = patch.name,
|
title = patch.name,
|
||||||
onBackClick = onDismissRequest,
|
onBackClick = onDismissRequest,
|
||||||
actions = {
|
actions = {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.reset),
|
||||||
|
) {
|
||||||
IconButton(onClick = reset) {
|
IconButton(onClick = reset) {
|
||||||
Icon(Icons.Outlined.Restore, stringResource(R.string.reset))
|
Icon(Icons.Outlined.Restore, stringResource(R.string.reset))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
|
@ -49,6 +49,7 @@ import app.revanced.manager.R
|
|||||||
import app.revanced.manager.network.dto.ReVancedSocial
|
import app.revanced.manager.network.dto.ReVancedSocial
|
||||||
import app.revanced.manager.ui.component.AppTopBar
|
import app.revanced.manager.ui.component.AppTopBar
|
||||||
import app.revanced.manager.ui.component.ColumnWithScrollbar
|
import app.revanced.manager.ui.component.ColumnWithScrollbar
|
||||||
|
import app.revanced.manager.ui.component.TooltipWrap
|
||||||
import app.revanced.manager.ui.component.settings.SettingsListItem
|
import app.revanced.manager.ui.component.settings.SettingsListItem
|
||||||
import app.revanced.manager.ui.model.navigation.Settings
|
import app.revanced.manager.ui.model.navigation.Settings
|
||||||
import app.revanced.manager.ui.viewmodel.AboutViewModel
|
import app.revanced.manager.ui.viewmodel.AboutViewModel
|
||||||
@ -252,6 +253,10 @@ fun AboutSettingsScreen(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally)
|
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally)
|
||||||
) {
|
) {
|
||||||
socialButtons.forEach { (icon, text, onClick) ->
|
socialButtons.forEach { (icon, text, onClick) ->
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = text,
|
||||||
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
modifier = Modifier.padding(end = 8.dp),
|
modifier = Modifier.padding(end = 8.dp),
|
||||||
@ -265,6 +270,7 @@ fun AboutSettingsScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
OutlinedCard(
|
OutlinedCard(
|
||||||
modifier = Modifier.padding(horizontal = 16.dp),
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant)
|
border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant)
|
||||||
|
@ -48,6 +48,7 @@ import app.revanced.manager.R
|
|||||||
import app.revanced.manager.ui.component.AppTopBar
|
import app.revanced.manager.ui.component.AppTopBar
|
||||||
import app.revanced.manager.ui.component.ColumnWithScrollbar
|
import app.revanced.manager.ui.component.ColumnWithScrollbar
|
||||||
import app.revanced.manager.ui.component.GroupHeader
|
import app.revanced.manager.ui.component.GroupHeader
|
||||||
|
import app.revanced.manager.ui.component.TooltipWrap
|
||||||
import app.revanced.manager.ui.component.settings.BooleanItem
|
import app.revanced.manager.ui.component.settings.BooleanItem
|
||||||
import app.revanced.manager.ui.component.settings.IntegerItem
|
import app.revanced.manager.ui.component.settings.IntegerItem
|
||||||
import app.revanced.manager.ui.component.settings.SafeguardBooleanItem
|
import app.revanced.manager.ui.component.settings.SafeguardBooleanItem
|
||||||
@ -243,10 +244,15 @@ private fun APIUrlDialog(currentUrl: String, defaultUrl: String, onSubmit: (Stri
|
|||||||
onValueChange = { url = it },
|
onValueChange = { url = it },
|
||||||
label = { Text(stringResource(R.string.api_url)) },
|
label = { Text(stringResource(R.string.api_url)) },
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.api_url_dialog_reset),
|
||||||
|
) {
|
||||||
IconButton(onClick = { url = defaultUrl }) {
|
IconButton(onClick = { url = defaultUrl }) {
|
||||||
Icon(Icons.Outlined.Restore, stringResource(R.string.api_url_dialog_reset))
|
Icon(Icons.Outlined.Restore, stringResource(R.string.api_url_dialog_reset))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ import app.revanced.manager.ui.component.ExceptionViewerDialog
|
|||||||
import app.revanced.manager.ui.component.GroupHeader
|
import app.revanced.manager.ui.component.GroupHeader
|
||||||
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
|
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
|
||||||
import app.revanced.manager.ui.component.ConfirmDialog
|
import app.revanced.manager.ui.component.ConfirmDialog
|
||||||
|
import app.revanced.manager.ui.component.TooltipWrap
|
||||||
import app.revanced.manager.ui.component.haptics.HapticCheckbox
|
import app.revanced.manager.ui.component.haptics.HapticCheckbox
|
||||||
import app.revanced.manager.ui.component.settings.SettingsListItem
|
import app.revanced.manager.ui.component.settings.SettingsListItem
|
||||||
import app.revanced.manager.ui.viewmodel.DownloadsViewModel
|
import app.revanced.manager.ui.viewmodel.DownloadsViewModel
|
||||||
@ -81,11 +82,16 @@ fun DownloadsSettingsScreen(
|
|||||||
onBackClick = onBackClick,
|
onBackClick = onBackClick,
|
||||||
actions = {
|
actions = {
|
||||||
if (viewModel.appSelection.isNotEmpty()) {
|
if (viewModel.appSelection.isNotEmpty()) {
|
||||||
|
TooltipWrap(
|
||||||
|
modifier = Modifier,
|
||||||
|
tooltip = stringResource(R.string.delete),
|
||||||
|
) {
|
||||||
IconButton(onClick = { showDeleteConfirmationDialog = true }) {
|
IconButton(onClick = { showDeleteConfirmationDialog = true }) {
|
||||||
Icon(Icons.Default.Delete, stringResource(R.string.delete))
|
Icon(Icons.Default.Delete, stringResource(R.string.delete))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
|
@ -317,8 +317,7 @@
|
|||||||
<string name="patcher_step_group_saving">Saving</string>
|
<string name="patcher_step_group_saving">Saving</string>
|
||||||
<string name="patcher_step_write_patched">Write patched APK file</string>
|
<string name="patcher_step_write_patched">Write patched APK file</string>
|
||||||
<string name="patcher_step_sign_apk">Sign patched APK file</string>
|
<string name="patcher_step_sign_apk">Sign patched APK file</string>
|
||||||
<string name="patcher_notification_title">Patching in progress…</string>
|
<string name="patcher_notification_message">Patching in progress…</string>
|
||||||
<string name="patcher_notification_text">Tap to return to the patcher</string>
|
|
||||||
<string name="patcher_stop_confirm_title">Stop patcher</string>
|
<string name="patcher_stop_confirm_title">Stop patcher</string>
|
||||||
<string name="patcher_stop_confirm_description">Are you sure you want to stop the patching process?</string>
|
<string name="patcher_stop_confirm_description">Are you sure you want to stop the patching process?</string>
|
||||||
<string name="execute_patches">Execute patches</string>
|
<string name="execute_patches">Execute patches</string>
|
||||||
|
Reference in New Issue
Block a user