Compare commits

..

9 Commits

Author SHA1 Message Date
Pun Butrach
e4d896f7f0 build: Remove style ratchet from build script again again 2025-09-03 17:16:25 +07:00
Pun Butrach
c26adf5dca chore: Ratcheteer!
This reverts commit b1e5f25341.
2025-07-15 23:10:24 +07:00
Pun Butrach
0aad586933 fix: cursed space 2025-07-15 23:08:12 +07:00
Pun Butrach
7d495e3cd2 Merge branch 'compose-dev' into build/spotless 2025-07-15 23:04:30 +07:00
Pun Butrach
b1e5f25341 build: Remove ratchet!! (sigh) 2025-07-06 02:19:42 +07:00
Pun Butrach
e85efceb39 build: Use ktlint (Android Studio configuration) 2025-07-06 02:13:33 +07:00
Pun Butrach
bfe207e682 build: Try to format when needed, not all the time (for now) 2025-07-06 01:52:37 +07:00
Pun Butrach
a150fdb147 ci: Merge Spotless CI with Build PR 2025-07-06 01:46:08 +07:00
Pun Butrach
23d39c0e93 build: Spotless check 2025-07-06 01:45:07 +07:00
29 changed files with 110 additions and 622 deletions

23
.editorconfig Normal file
View File

@@ -0,0 +1,23 @@
[*.{kt,kts}]
end_of_line = lf
ij_kotlin_allow_trailing_comma = false
ij_kotlin_allow_trailing_comma_on_call_site = false
ij_kotlin_imports_layout = *
ij_kotlin_indent_before_arrow_on_new_line = false
ij_kotlin_line_break_after_multiline_when_entry = true
ij_kotlin_packages_to_use_import_on_demand = java.util.*,kotlinx.android.synthetic.**
indent_size = 4
indent_style = space
insert_final_newline = true
ktlint_annotation_handle_annotations_with_parameters_same_as_annotations_without_parameters = [unset]
ktlint_argument_list_wrapping_ignore_when_parameter_count_greater_or_equal_than = 8
ktlint_chain_method_rule_force_multiline_when_chain_operator_count_greater_or_equal_than = 4
ktlint_class_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than = unset
ktlint_code_style = android_studio
ktlint_enum_entry_name_casing = upper_or_camel_cases
ktlint_function_naming_ignore_when_annotated_with = [unset]
ktlint_function_signature_body_expression_wrapping = default
ktlint_function_signature_rule_force_multiline_when_parameter_count_greater_or_equal_than = unset
ktlint_ignore_back_ticked_identifier = false
ktlint_property_naming_constant_naming = screaming_snake_case
max_line_length = 100

View File

@@ -19,6 +19,11 @@ jobs:
- name: Cache Gradle - name: Cache Gradle
uses: burrunan/gradle-cache-action@v1 uses: burrunan/gradle-cache-action@v1
- name: Spotless Check
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew spotlessCheck --no-daemon
- name: Build - name: Build
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -8,6 +8,7 @@ import app.revanced.manager.util.tag
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.call.body import io.ktor.client.call.body
import io.ktor.client.request.HttpRequestBuilder import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.get
import io.ktor.client.request.prepareGet import io.ktor.client.request.prepareGet
import io.ktor.client.request.request import io.ktor.client.request.request
import io.ktor.client.statement.bodyAsText import io.ktor.client.statement.bodyAsText
@@ -91,5 +92,9 @@ class HttpService(
builder: HttpRequestBuilder.() -> Unit builder: HttpRequestBuilder.() -> Unit
) = saveLocation.outputStream().use { streamTo(it, builder) } ) = saveLocation.outputStream().use { streamTo(it, builder) }
suspend fun getHtml(builder: HttpRequestBuilder.() -> Unit) = htmlDocument(
html = http.get(builder).bodyAsText()
)
class HttpException(status: HttpStatusCode) : Exception("Failed to fetch: http status: $status") class HttpException(status: HttpStatusCode) : Exception("Failed to fetch: http status: $status")
} }

View File

@@ -6,6 +6,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
@@ -21,7 +22,6 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource 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.R
import app.revanced.manager.ui.component.tooltip.TooltipIconButton
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@@ -69,10 +69,7 @@ fun AppTopBar(
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
navigationIcon = { navigationIcon = {
if (onBackClick != null) { if (onBackClick != null) {
TooltipIconButton( IconButton(onClick = onBackClick) {
onClick = onBackClick,
tooltip = stringResource(R.string.back),
) {
backIcon() backIcon()
} }
} }
@@ -111,10 +108,7 @@ fun AppTopBar(
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
navigationIcon = { navigationIcon = {
if (onBackClick != null) { if (onBackClick != null) {
TooltipIconButton( IconButton(onClick = onBackClick) {
onClick = onBackClick,
tooltip = stringResource(R.string.back),
) {
backIcon() backIcon()
} }
} }

View File

@@ -4,13 +4,13 @@ import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.KeyboardArrowUp import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate import androidx.compose.ui.draw.rotate
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import app.revanced.manager.R import app.revanced.manager.R
import app.revanced.manager.ui.component.tooltip.TooltipIconButton
@Composable @Composable
fun ArrowButton( fun ArrowButton(
@@ -27,11 +27,7 @@ fun ArrowButton(
) )
onClick?.let { onClick?.let {
TooltipIconButton( IconButton(onClick = it) {
modifier = Modifier,
onClick = it,
tooltip = stringResource(description),
) {
Icon( Icon(
imageVector = Icons.Filled.KeyboardArrowUp, imageVector = Icons.Filled.KeyboardArrowUp,
contentDescription = stringResource(description), contentDescription = stringResource(description),

View File

@@ -9,6 +9,7 @@ import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.outlined.Share import androidx.compose.material.icons.outlined.Share
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -17,7 +18,6 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import app.revanced.manager.R import app.revanced.manager.R
import app.revanced.manager.ui.component.bundle.BundleTopBar import app.revanced.manager.ui.component.bundle.BundleTopBar
import app.revanced.manager.ui.component.tooltip.TooltipIconButton
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@@ -39,8 +39,7 @@ fun ExceptionViewerDialog(text: String, onDismiss: () -> Unit) {
) )
}, },
actions = { actions = {
TooltipIconButton( IconButton(
modifier = Modifier,
onClick = { onClick = {
val sendIntent: Intent = Intent().apply { val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND action = Intent.ACTION_SEND
@@ -53,8 +52,7 @@ fun ExceptionViewerDialog(text: String, onDismiss: () -> Unit) {
val shareIntent = Intent.createChooser(sendIntent, null) val shareIntent = Intent.createChooser(sendIntent, null)
context.startActivity(shareIntent) context.startActivity(shareIntent)
}, }
tooltip = stringResource(R.string.share),
) { ) {
Icon( Icon(
Icons.Outlined.Share, Icons.Outlined.Share,

View File

@@ -14,6 +14,7 @@ import androidx.compose.material.icons.outlined.Close
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -24,7 +25,6 @@ import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource 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.R
import app.revanced.manager.ui.component.tooltip.TooltipIconButton
@Composable @Composable
fun NotificationCard( fun NotificationCard(
@@ -138,10 +138,7 @@ fun NotificationCard(
) )
} }
if (onDismiss != null) { if (onDismiss != null) {
TooltipIconButton( IconButton(onClick = onDismiss) {
onClick = onDismiss,
tooltip = stringResource(R.string.close),
) {
Icon( Icon(
imageVector = Icons.Outlined.Close, imageVector = Icons.Outlined.Close,
contentDescription = stringResource(R.string.close), contentDescription = stringResource(R.string.close),

View File

@@ -5,6 +5,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Visibility import androidx.compose.material.icons.outlined.Visibility
import androidx.compose.material.icons.outlined.VisibilityOff import androidx.compose.material.icons.outlined.VisibilityOff
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@@ -18,7 +19,6 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.input.VisualTransformation
import app.revanced.manager.R import app.revanced.manager.R
import app.revanced.manager.ui.component.tooltip.TooltipIconButton
@Composable @Composable
fun PasswordField(modifier: Modifier = Modifier, value: String, onValueChange: (String) -> Unit, label: @Composable (() -> Unit)? = null, placeholder: @Composable (() -> Unit)? = null) { fun PasswordField(modifier: Modifier = Modifier, value: String, onValueChange: (String) -> Unit, label: @Composable (() -> Unit)? = null, placeholder: @Composable (() -> Unit)? = null) {
@@ -33,15 +33,9 @@ fun PasswordField(modifier: Modifier = Modifier, value: String, onValueChange: (
label = label, label = label,
modifier = modifier, modifier = modifier,
trailingIcon = { trailingIcon = {
TooltipIconButton( IconButton(onClick = {
modifier = Modifier, visible = !visible
onClick = { }) {
visible = !visible
},
tooltip = if (visible) stringResource(R.string.show_password_field) else stringResource(
R.string.hide_password_field
),
) {
val (icon, description) = remember(visible) { val (icon, description) = remember(visible) {
if (visible) Icons.Outlined.VisibilityOff to R.string.hide_password_field else Icons.Outlined.Visibility to R.string.show_password_field if (visible) Icons.Outlined.VisibilityOff to R.string.hide_password_field else Icons.Outlined.Visibility to R.string.show_password_field
} }

View File

@@ -5,6 +5,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SearchBar import androidx.compose.material3.SearchBar
import androidx.compose.material3.SearchBarColors import androidx.compose.material3.SearchBarColors
@@ -18,7 +19,6 @@ import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import app.revanced.manager.R import app.revanced.manager.R
import app.revanced.manager.ui.component.tooltip.TooltipIconButton
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@@ -48,10 +48,7 @@ fun SearchView(
onExpandedChange = onActiveChange, onExpandedChange = onActiveChange,
placeholder = placeholder, placeholder = placeholder,
leadingIcon = { leadingIcon = {
TooltipIconButton( IconButton(onClick = { onActiveChange(false) }) {
tooltip = stringResource(R.string.back),
onClick = { onActiveChange(false) }
) {
Icon( Icon(
Icons.AutoMirrored.Filled.ArrowBack, Icons.AutoMirrored.Filled.ArrowBack,
stringResource(R.string.back) stringResource(R.string.back)

View File

@@ -49,7 +49,6 @@ import app.revanced.manager.domain.repository.PatchBundleRepository
import app.revanced.manager.ui.component.ColumnWithScrollbar import app.revanced.manager.ui.component.ColumnWithScrollbar
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.tooltip.TooltipIconButton
import app.revanced.manager.ui.component.TextInputDialog import app.revanced.manager.ui.component.TextInputDialog
import app.revanced.manager.ui.component.haptics.HapticSwitch import app.revanced.manager.ui.component.haptics.HapticSwitch
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -104,11 +103,7 @@ fun BundleInformationDialog(
}, },
actions = { actions = {
if (!src.isDefault) { if (!src.isDefault) {
TooltipIconButton( IconButton(onClick = onDeleteRequest) {
modifier = Modifier,
onClick = onDeleteRequest,
tooltip = stringResource(R.string.delete),
) {
Icon( Icon(
Icons.Outlined.DeleteOutline, Icons.Outlined.DeleteOutline,
stringResource(R.string.delete) stringResource(R.string.delete)
@@ -116,11 +111,7 @@ fun BundleInformationDialog(
} }
} }
if (!isLocal && hasNetwork) { if (!isLocal && hasNetwork) {
TooltipIconButton( IconButton(onClick = onUpdate) {
modifier = Modifier,
onClick = onUpdate,
tooltip = stringResource(R.string.refresh),
) {
Icon( Icon(
Icons.Outlined.Update, Icons.Outlined.Update,
stringResource(R.string.refresh) stringResource(R.string.refresh)

View File

@@ -2,6 +2,7 @@ package app.revanced.manager.ui.component.bundle
import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.RowScope
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
@@ -9,11 +10,7 @@ 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.tooltip.TooltipIconButton
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@@ -36,10 +33,7 @@ fun BundleTopBar(
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
navigationIcon = { navigationIcon = {
if (onBackClick != null) { if (onBackClick != null) {
TooltipIconButton( IconButton(onClick = onBackClick) {
tooltip = stringResource(R.string.back),
onClick = onBackClick
) {
backIcon() backIcon()
} }
} }

View File

@@ -193,7 +193,6 @@ private 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)
} }

View File

@@ -1,38 +0,0 @@
package app.revanced.manager.ui.component.haptics
import android.view.HapticFeedbackConstants
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.FloatingActionButtonElevation
import androidx.compose.material3.SmallFloatingActionButton
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import app.revanced.manager.util.withHapticFeedback
@Composable
fun HapticSmallFloatingActionButton (
onClick: () -> Unit,
modifier: Modifier = Modifier,
shape: Shape = FloatingActionButtonDefaults.smallShape,
containerColor: Color = FloatingActionButtonDefaults.containerColor,
contentColor: Color = contentColorFor(containerColor),
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
content: @Composable () -> Unit,
) {
SmallFloatingActionButton(
onClick = onClick.withHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY),
modifier = modifier,
shape = shape,
containerColor = containerColor,
contentColor = contentColor,
elevation = elevation,
interactionSource = interactionSource,
content = content
)
}

View File

@@ -67,7 +67,6 @@ import app.revanced.manager.ui.component.LongInputDialog
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
import app.revanced.manager.ui.component.tooltip.TooltipIconButton
import app.revanced.manager.util.isScrollingUp import app.revanced.manager.util.isScrollingUp
import app.revanced.manager.util.mutableStateSetOf import app.revanced.manager.util.mutableStateSetOf
import app.revanced.manager.util.saver.snapshotStateListSaver import app.revanced.manager.util.saver.snapshotStateListSaver
@@ -124,11 +123,7 @@ private interface OptionEditor<T : Any> {
@Composable @Composable
fun ListItemTrailingContent(scope: OptionEditorScope<T>) { fun ListItemTrailingContent(scope: OptionEditorScope<T>) {
TooltipIconButton( IconButton(onClick = { scope.checkSafeguard { clickAction(scope) } }) {
modifier = Modifier,
tooltip = stringResource(R.string.edit),
onClick = { scope.checkSafeguard { clickAction(scope) } }
) {
Icon(Icons.Outlined.Edit, stringResource(R.string.edit)) Icon(Icons.Outlined.Edit, stringResource(R.string.edit))
} }
} }
@@ -275,9 +270,7 @@ private object StringOptionEditor : OptionEditor<String> {
}, },
trailingIcon = { trailingIcon = {
var showDropdownMenu by rememberSaveable { mutableStateOf(false) } var showDropdownMenu by rememberSaveable { mutableStateOf(false) }
TooltipIconButton( IconButton(
modifier = Modifier,
tooltip = stringResource(R.string.string_option_menu_description),
onClick = { showDropdownMenu = true } onClick = { showDropdownMenu = true }
) { ) {
Icon( Icon(
@@ -587,9 +580,7 @@ private class ListOptionEditor<T : Serializable>(private val elementEditor: Opti
}, },
actions = { actions = {
if (deleteMode) { if (deleteMode) {
TooltipIconButton( IconButton(
modifier = Modifier,
tooltip = stringResource(R.string.select_deselect_all),
onClick = { onClick = {
if (items.size == deletionTargets.size) deletionTargets.clear() if (items.size == deletionTargets.size) deletionTargets.clear()
else deletionTargets.addAll(items.map { it.key }) else deletionTargets.addAll(items.map { it.key })
@@ -600,9 +591,7 @@ private class ListOptionEditor<T : Serializable>(private val elementEditor: Opti
stringResource(R.string.select_deselect_all) stringResource(R.string.select_deselect_all)
) )
} }
TooltipIconButton( IconButton(
modifier = Modifier,
tooltip = stringResource(R.string.delete),
onClick = { onClick = {
items.removeIf { it.key in deletionTargets } items.removeIf { it.key in deletionTargets }
deletionTargets.clear() deletionTargets.clear()
@@ -615,15 +604,8 @@ private class ListOptionEditor<T : Serializable>(private val elementEditor: Opti
) )
} }
} else { } else {
TooltipIconButton( IconButton(onClick = items::clear) {
modifier = Modifier, Icon(Icons.Outlined.Restore, stringResource(R.string.reset))
tooltip = stringResource(R.string.reset),
onClick = items::clear
) {
Icon(
Icons.Outlined.Restore,
stringResource(R.string.reset)
)
} }
} }
} }
@@ -691,10 +673,9 @@ 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 = {
TooltipIconButton( IconButton(
modifier = Modifier.draggableHandle(interactionSource = interactionSource), modifier = Modifier.draggableHandle(interactionSource = interactionSource),
tooltip = stringResource(R.string.delete), onClick = {},
onClick = { }
) { ) {
Icon( Icon(
Icons.Filled.DragHandle, Icons.Filled.DragHandle,

View File

@@ -5,6 +5,7 @@ import androidx.compose.foundation.clickable
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Edit import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@@ -16,7 +17,6 @@ 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.tooltip.TooltipIconButton
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -65,14 +65,10 @@ fun IntegerItem(
headlineContent = stringResource(headline), headlineContent = stringResource(headline),
supportingContent = stringResource(description), supportingContent = stringResource(description),
trailingContent = { trailingContent = {
TooltipIconButton( IconButton(onClick = { dialogOpen = true }) {
modifier = modifier,
onClick = { dialogOpen = true },
tooltip = stringResource(R.string.edit),
) {
Icon( Icon(
imageVector = Icons.Outlined.Edit, Icons.Outlined.Edit,
contentDescription = stringResource(R.string.edit), contentDescription = stringResource(R.string.edit)
) )
} }
} }

View File

@@ -1,107 +0,0 @@
package app.revanced.manager.ui.component.tooltip
import androidx.annotation.StringRes
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.FloatingActionButtonElevation
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.window.PopupPositionProvider
import app.revanced.manager.ui.component.haptics.HapticFloatingActionButton
/**
* [HapticFloatingActionButton] with tooltip-specific params.
*
* @param tooltip [String] text to show in a tooltip.
* @param positionProvider [PopupPositionProvider] Anchor point for the tooltip.
* @param haptic Whether to perform haptic feedback when the tooltip shown.
* @param hapticFeedbackType The type of haptic feedback to perform.
*
* @see [HapticFloatingActionButton]
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TooltipFloatingActionButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
shape: Shape = FloatingActionButtonDefaults.shape,
containerColor: Color = FloatingActionButtonDefaults.containerColor,
contentColor: Color = contentColorFor(containerColor),
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
tooltip: String,
positionProvider: PopupPositionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
haptic: Boolean = true,
hapticFeedbackType: HapticFeedbackType = HapticFeedbackType.LongPress,
content: @Composable (() -> Unit)
) {
TooltipWrap(
tooltip = tooltip,
positionProvider = positionProvider,
haptic = haptic,
hapticFeedbackType = hapticFeedbackType,
) {
HapticFloatingActionButton(
onClick = onClick,
modifier = modifier,
shape = shape,
containerColor = containerColor,
contentColor = contentColor,
elevation = elevation,
interactionSource = interactionSource,
content = content,
)
}
}
/**
* [HapticFloatingActionButton] with tooltip-specific params.
*
* @param tooltip [Int] or `id` string resource to show in a tooltip.
* @param positionProvider [PopupPositionProvider] Anchor point for the tooltip.
* @param haptic Whether to perform haptic feedback when the tooltip shown.
* @param hapticFeedbackType The type of haptic feedback to perform.
*
* @see [HapticFloatingActionButton]
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TooltipFloatingActionButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
shape: Shape = FloatingActionButtonDefaults.shape,
containerColor: Color = FloatingActionButtonDefaults.containerColor,
contentColor: Color = contentColorFor(containerColor),
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
@StringRes tooltip: Int,
positionProvider: PopupPositionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
haptic: Boolean = true,
hapticFeedbackType: HapticFeedbackType = HapticFeedbackType.LongPress,
content: @Composable (() -> Unit)
) {
TooltipWrap(
tooltip = tooltip,
positionProvider = positionProvider,
haptic = haptic,
hapticFeedbackType = hapticFeedbackType,
) {
HapticFloatingActionButton(
onClick = onClick,
modifier = modifier,
shape = shape,
containerColor = containerColor,
contentColor = contentColor,
elevation = elevation,
interactionSource = interactionSource,
content = content,
)
}
}

View File

@@ -1,96 +0,0 @@
package app.revanced.manager.ui.component.tooltip
import androidx.annotation.StringRes
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonColors
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.TooltipDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.window.PopupPositionProvider
/**
* [IconButton] with tooltip-specific params.
*
* @param tooltip [String] text to show in a tooltip.
* @param positionProvider [PopupPositionProvider] Anchor point for the tooltip.
* @param haptic Whether to perform haptic feedback when the tooltip shown.
* @param hapticFeedbackType The type of haptic feedback to perform.
*
* @see [IconButton]
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TooltipIconButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
colors: IconButtonColors = IconButtonDefaults.iconButtonColors(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
tooltip: String,
positionProvider: PopupPositionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
haptic: Boolean = true,
hapticFeedbackType: HapticFeedbackType = HapticFeedbackType.LongPress,
content: @Composable (() -> Unit),
) {
TooltipWrap(
tooltip = tooltip,
positionProvider = positionProvider,
haptic = haptic,
hapticFeedbackType = hapticFeedbackType,
) {
IconButton(
onClick = onClick,
modifier = modifier,
enabled = enabled,
colors = colors,
interactionSource = interactionSource,
content = content,
)
}
}
/**
* [IconButton] with tooltip-specific params.
*
* @param tooltip [Int] or `id` string resource to show in a tooltip.
* @param positionProvider [PopupPositionProvider] Anchor point for the tooltip.
* @param haptic Whether to perform haptic feedback when the tooltip shown.
* @param hapticFeedbackType The type of haptic feedback to perform.
*
* @see [IconButton]
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TooltipIconButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
colors: IconButtonColors = IconButtonDefaults.iconButtonColors(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
@StringRes tooltip: Int,
positionProvider: PopupPositionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
haptic: Boolean = true,
hapticFeedbackType: HapticFeedbackType = HapticFeedbackType.LongPress,
content: @Composable (() -> Unit),
) {
TooltipWrap(
tooltip = tooltip,
positionProvider = positionProvider,
haptic = haptic,
hapticFeedbackType = hapticFeedbackType,
) {
IconButton(
onClick = onClick,
modifier = modifier,
enabled = enabled,
colors = colors,
interactionSource = interactionSource,
content = content,
)
}
}

View File

@@ -1,107 +0,0 @@
package app.revanced.manager.ui.component.tooltip
import androidx.annotation.StringRes
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.FloatingActionButtonElevation
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.window.PopupPositionProvider
import app.revanced.manager.ui.component.haptics.HapticSmallFloatingActionButton
/**
* [HapticSmallFloatingActionButton] with tooltip-specific params.
*
* @param tooltip [String] text to show in a tooltip.
* @param positionProvider [PopupPositionProvider] Anchor point for the tooltip.
* @param haptic Whether to perform haptic feedback when the tooltip shown.
* @param hapticFeedbackType The type of haptic feedback to perform.
*
* @see [HapticSmallFloatingActionButton]
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TooltipSmallFloatingActionButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
shape: Shape = FloatingActionButtonDefaults.smallShape,
containerColor: Color = FloatingActionButtonDefaults.containerColor,
contentColor: Color = contentColorFor(containerColor),
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
tooltip: String,
positionProvider: PopupPositionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
haptic: Boolean = true,
hapticFeedbackType: HapticFeedbackType = HapticFeedbackType.LongPress,
content: @Composable (() -> Unit)
) {
TooltipWrap(
tooltip = tooltip,
positionProvider = positionProvider,
haptic = haptic,
hapticFeedbackType = hapticFeedbackType,
) {
HapticSmallFloatingActionButton(
onClick = onClick,
modifier = modifier,
shape = shape,
containerColor = containerColor,
contentColor = contentColor,
elevation = elevation,
interactionSource = interactionSource,
content = content,
)
}
}
/**
* [HapticSmallFloatingActionButton] with tooltip-specific params.
*
* @param tooltip [Int] or `id` string resource to show in a tooltip.
* @param positionProvider [PopupPositionProvider] Anchor point for the tooltip.
* @param haptic Whether to perform haptic feedback when the tooltip shown.
* @param hapticFeedbackType The type of haptic feedback to perform.
*
* @see [HapticSmallFloatingActionButton]
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TooltipSmallFloatingActionButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
shape: Shape = FloatingActionButtonDefaults.smallShape,
containerColor: Color = FloatingActionButtonDefaults.containerColor,
contentColor: Color = contentColorFor(containerColor),
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
@StringRes tooltip: Int,
positionProvider: PopupPositionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
haptic: Boolean = true,
hapticFeedbackType: HapticFeedbackType = HapticFeedbackType.LongPress,
content: @Composable (() -> Unit)
) {
TooltipWrap(
tooltip = tooltip,
positionProvider = positionProvider,
haptic = haptic,
hapticFeedbackType = hapticFeedbackType,
) {
HapticSmallFloatingActionButton(
onClick = onClick,
modifier = modifier,
shape = shape,
containerColor = containerColor,
contentColor = contentColor,
elevation = elevation,
interactionSource = interactionSource,
content = content,
)
}
}

View File

@@ -1,96 +0,0 @@
package app.revanced.manager.ui.component.tooltip
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 applied to Tooltip.
* @param tooltip [String] text to show in a tooltip.
* @param positionProvider [PopupPositionProvider] Anchor point for the tooltip.
* @param content The composable UI to wrapped with.
* @param haptic Whether to perform haptic feedback when the tooltip shown.
* @param hapticFeedbackType The type of haptic feedback to perform.
*
* @see [TooltipBox]
*/
@Composable
@OptIn(ExperimentalMaterial3Api::class)
fun TooltipWrap(
modifier: Modifier = Modifier,
tooltip: String,
positionProvider: PopupPositionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
haptic: Boolean = true,
hapticFeedbackType: HapticFeedbackType = HapticFeedbackType.LongPress,
content: @Composable () -> Unit
) {
val tooltipState = rememberTooltipState()
val localHaptic = LocalHapticFeedback.current
LaunchedEffect(tooltipState.isVisible) {
if (tooltipState.isVisible && haptic) {
localHaptic.performHapticFeedback(hapticFeedbackType)
}
}
TooltipBox(
modifier = modifier,
positionProvider = positionProvider,
tooltip = { PlainTooltip { Text(tooltip) } },
state = tooltipState,
content = content,
)
}
/**
* Wraps a composable with a tooltip.
*
* @param modifier the [Modifier] to applied to tooltip.
* @param tooltip [Int] or `id` string resource to show in a tooltip.
* @param positionProvider [PopupPositionProvider] Anchor point for the tooltip.
* @param content The composable UI to wrapped with.
* @param haptic Whether to perform haptic feedback when the tooltip shown.
* @param hapticFeedbackType The type of haptic feedback to perform.
*
* @see [TooltipBox]
*/
@Composable
@OptIn(ExperimentalMaterial3Api::class)
fun TooltipWrap(
modifier: Modifier = Modifier,
@StringRes tooltip: Int,
positionProvider: PopupPositionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
haptic: Boolean = true,
hapticFeedbackType: HapticFeedbackType = HapticFeedbackType.LongPress,
content: @Composable () -> Unit
) {
val tooltipState = rememberTooltipState()
val localHaptic = LocalHapticFeedback.current
LaunchedEffect(tooltipState.isVisible) {
if (tooltipState.isVisible && haptic) {
localHaptic.performHapticFeedback(hapticFeedbackType)
}
}
TooltipBox(
modifier = modifier,
positionProvider = positionProvider,
tooltip = { PlainTooltip { Text(stringResource(tooltip)) } },
state = tooltipState,
content = content,
)
}

View File

@@ -16,6 +16,7 @@ import androidx.compose.material.icons.outlined.Search
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
@@ -43,7 +44,6 @@ 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.tooltip.TooltipIconButton
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,14 +162,8 @@ fun AppSelectorScreen(
scrollBehavior = scrollBehavior, scrollBehavior = scrollBehavior,
onBackClick = onBackClick, onBackClick = onBackClick,
actions = { actions = {
TooltipIconButton( IconButton(onClick = { search = true }) {
tooltip = stringResource(R.string.search_patches), Icon(Icons.Outlined.Search, stringResource(R.string.search))
onClick = { search = true }
) {
Icon(
Icons.Outlined.Search,
stringResource(R.string.search)
)
} }
} }
) )

View File

@@ -66,9 +66,8 @@ 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.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.HapticTab import app.revanced.manager.ui.component.haptics.HapticTab
import app.revanced.manager.ui.component.tooltip.TooltipFloatingActionButton
import app.revanced.manager.ui.component.tooltip.TooltipIconButton
import app.revanced.manager.ui.viewmodel.DashboardViewModel import app.revanced.manager.ui.viewmodel.DashboardViewModel
import app.revanced.manager.util.RequestInstallAppsContract import app.revanced.manager.util.RequestInstallAppsContract
import app.revanced.manager.util.toast import app.revanced.manager.util.toast
@@ -182,20 +181,18 @@ fun DashboardScreen(
) )
}, },
actions = { actions = {
TooltipIconButton( IconButton(
onClick = { onClick = {
showDeleteConfirmationDialog = true showDeleteConfirmationDialog = true
}, }
tooltip = stringResource(R.string.delete),
) { ) {
Icon( Icon(
Icons.Outlined.DeleteOutline, Icons.Outlined.DeleteOutline,
stringResource(R.string.delete) stringResource(R.string.delete)
) )
} }
TooltipIconButton( IconButton(
onClick = vm::updateSources, onClick = vm::updateSources
tooltip = stringResource(R.string.refresh)
) { ) {
Icon( Icon(
Icons.Outlined.Refresh, Icons.Outlined.Refresh,
@@ -209,9 +206,8 @@ fun DashboardScreen(
title = stringResource(R.string.app_name), title = stringResource(R.string.app_name),
actions = { actions = {
if (!vm.updatedManagerVersion.isNullOrEmpty()) { if (!vm.updatedManagerVersion.isNullOrEmpty()) {
TooltipIconButton( IconButton(
onClick = onUpdateClick, onClick = onUpdateClick,
tooltip = stringResource(R.string.update),
) { ) {
BadgedBox( BadgedBox(
badge = { badge = {
@@ -222,17 +218,8 @@ fun DashboardScreen(
} }
} }
} }
TooltipIconButton( IconButton(onClick = onSettingsClick) {
onClick = onSettingsClick, Icon(Icons.Outlined.Settings, stringResource(R.string.settings))
tooltip = stringResource(R.string.settings),
) {
BadgedBox(
badge = {
Badge(modifier = Modifier.size(6.dp))
}
) {
Icon(Icons.Outlined.Settings, stringResource(R.string.settings))
}
} }
}, },
applyContainerColor = true applyContainerColor = true
@@ -240,8 +227,7 @@ fun DashboardScreen(
} }
}, },
floatingActionButton = { floatingActionButton = {
TooltipFloatingActionButton( HapticFloatingActionButton(
tooltip = stringResource(R.string.add),
onClick = { onClick = {
vm.cancelSourceSelection() vm.cancelSourceSelection()
@@ -254,11 +240,11 @@ fun DashboardScreen(
DashboardPage.BUNDLES.ordinal DashboardPage.BUNDLES.ordinal
) )
} }
return@TooltipFloatingActionButton return@HapticFloatingActionButton
} }
if (vm.android11BugActive) { if (vm.android11BugActive) {
showAndroid11Dialog = true showAndroid11Dialog = true
return@TooltipFloatingActionButton return@HapticFloatingActionButton
} }
onAppSelectorClick() onAppSelectorClick()

View File

@@ -25,6 +25,7 @@ import androidx.compose.material3.AlertDialog
import androidx.compose.material3.BottomAppBar import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
@@ -50,7 +51,6 @@ import app.revanced.manager.ui.component.InstallerStatusDialog
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
import app.revanced.manager.ui.component.tooltip.TooltipIconButton
import app.revanced.manager.ui.model.StepCategory import app.revanced.manager.ui.model.StepCategory
import app.revanced.manager.ui.viewmodel.PatcherViewModel import app.revanced.manager.ui.viewmodel.PatcherViewModel
import app.revanced.manager.util.APK_MIMETYPE import app.revanced.manager.util.APK_MIMETYPE
@@ -164,17 +164,15 @@ fun PatcherScreen(
bottomBar = { bottomBar = {
BottomAppBar( BottomAppBar(
actions = { actions = {
TooltipIconButton( 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
tooltip = stringResource(R.string.save_apk),
) { ) {
Icon(Icons.Outlined.Save, stringResource(id = R.string.save_apk)) Icon(Icons.Outlined.Save, stringResource(id = R.string.save_apk))
} }
TooltipIconButton( IconButton(
onClick = { viewModel.exportLogs(context) }, onClick = { viewModel.exportLogs(context) },
enabled = patcherSucceeded != null, enabled = patcherSucceeded != null
tooltip = stringResource(R.string.save_logs),
) { ) {
Icon(Icons.Outlined.PostAdd, stringResource(id = R.string.save_logs)) Icon(Icons.Outlined.PostAdd, stringResource(id = R.string.save_logs))
} }

View File

@@ -41,6 +41,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.ScrollableTabRow import androidx.compose.material3.ScrollableTabRow
import androidx.compose.material3.SmallFloatingActionButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.material3.surfaceColorAtElevation
@@ -72,9 +73,6 @@ 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
import app.revanced.manager.ui.component.patches.OptionItem import app.revanced.manager.ui.component.patches.OptionItem
import app.revanced.manager.ui.component.tooltip.TooltipFloatingActionButton
import app.revanced.manager.ui.component.tooltip.TooltipIconButton
import app.revanced.manager.ui.component.tooltip.TooltipSmallFloatingActionButton
import app.revanced.manager.ui.component.patches.SelectionWarningDialog import app.revanced.manager.ui.component.patches.SelectionWarningDialog
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel.Companion.SHOW_INCOMPATIBLE import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel.Companion.SHOW_INCOMPATIBLE
@@ -261,15 +259,14 @@ fun PatchesSelectorScreen(
animationSpec = tween(durationMillis = 400, easing = EaseInOut), animationSpec = tween(durationMillis = 400, easing = EaseInOut),
label = "SearchBar back button" label = "SearchBar back button"
) )
TooltipIconButton( IconButton(
onClick = { onClick = {
if (searchExpanded) { if (searchExpanded) {
setSearchExpanded(false) setSearchExpanded(false)
} else { } else {
onBackClick() onBackClick()
} }
}, }
tooltip = stringResource(R.string.back),
) { ) {
Icon( Icon(
modifier = Modifier.rotate(rotation), modifier = Modifier.rotate(rotation),
@@ -285,10 +282,9 @@ fun PatchesSelectorScreen(
transitionSpec = { fadeIn() togetherWith fadeOut() } transitionSpec = { fadeIn() togetherWith fadeOut() }
) { searchExpanded -> ) { searchExpanded ->
if (searchExpanded) { if (searchExpanded) {
TooltipIconButton( IconButton(
onClick = { setQuery("") }, onClick = { setQuery("") },
enabled = query.isNotEmpty(), enabled = query.isNotEmpty()
tooltip = stringResource(R.string.clear),
) { ) {
Icon( Icon(
imageVector = Icons.Filled.Close, imageVector = Icons.Filled.Close,
@@ -296,10 +292,7 @@ fun PatchesSelectorScreen(
) )
} }
} else { } else {
TooltipIconButton( IconButton(onClick = { showBottomSheet = true }) {
onClick = { showBottomSheet = true },
tooltip = stringResource(R.string.more),
) {
Icon( Icon(
imageVector = Icons.Outlined.FilterList, imageVector = Icons.Outlined.FilterList,
contentDescription = stringResource(R.string.more) contentDescription = stringResource(R.string.more)
@@ -361,8 +354,7 @@ fun PatchesSelectorScreen(
horizontalAlignment = Alignment.End, horizontalAlignment = Alignment.End,
verticalArrangement = Arrangement.spacedBy(4.dp) verticalArrangement = Arrangement.spacedBy(4.dp)
) { ) {
TooltipSmallFloatingActionButton( SmallFloatingActionButton(
tooltip = stringResource(R.string.reset),
onClick = viewModel::reset, onClick = viewModel::reset,
containerColor = MaterialTheme.colorScheme.tertiaryContainer containerColor = MaterialTheme.colorScheme.tertiaryContainer
) { ) {
@@ -514,7 +506,6 @@ 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)
} }
@@ -538,10 +529,7 @@ fun ListHeader(
}, },
trailingContent = onHelpClick?.let { trailingContent = onHelpClick?.let {
{ {
TooltipIconButton( IconButton(onClick = it) {
tooltip = stringResource(R.string.help),
onClick = it
) {
Icon( Icon(
Icons.AutoMirrored.Outlined.HelpOutline, Icons.AutoMirrored.Outlined.HelpOutline,
stringResource(R.string.help) stringResource(R.string.help)
@@ -621,10 +609,7 @@ private fun OptionsDialog(
title = patch.name, title = patch.name,
onBackClick = onDismissRequest, onBackClick = onDismissRequest,
actions = { actions = {
TooltipIconButton( IconButton(onClick = reset) {
tooltip = stringResource(R.string.reset),
onClick = reset
) {
Icon(Icons.Outlined.Restore, stringResource(R.string.reset)) Icon(Icons.Outlined.Restore, stringResource(R.string.reset))
} }
} }

View File

@@ -19,6 +19,7 @@ import androidx.compose.material.icons.outlined.MailOutline
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedCard import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
@@ -49,7 +50,6 @@ 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.settings.SettingsListItem import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.component.tooltip.TooltipIconButton
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
import app.revanced.manager.ui.viewmodel.AboutViewModel.Companion.DEVELOPER_OPTIONS_TAPS import app.revanced.manager.ui.viewmodel.AboutViewModel.Companion.DEVELOPER_OPTIONS_TAPS
@@ -252,10 +252,9 @@ 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) ->
TooltipIconButton( IconButton(
onClick = onClick,
modifier = Modifier.padding(end = 8.dp), modifier = Modifier.padding(end = 8.dp),
tooltip = text,
onClick = onClick
) { ) {
Icon( Icon(
icon, icon,

View File

@@ -21,6 +21,7 @@ import androidx.compose.material.icons.outlined.Restore
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
@@ -51,7 +52,6 @@ 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
import app.revanced.manager.ui.component.settings.SettingsListItem import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.component.tooltip.TooltipIconButton
import app.revanced.manager.ui.viewmodel.AdvancedSettingsViewModel import app.revanced.manager.ui.viewmodel.AdvancedSettingsViewModel
import app.revanced.manager.util.toast import app.revanced.manager.util.toast
import app.revanced.manager.util.withHapticFeedback import app.revanced.manager.util.withHapticFeedback
@@ -243,11 +243,7 @@ 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 = {
TooltipIconButton( IconButton(onClick = { url = defaultUrl }) {
modifier = Modifier,
tooltip = stringResource(R.string.api_url_dialog_reset),
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))
} }
} }

View File

@@ -9,7 +9,6 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.outlined.Delete import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.Search
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
@@ -41,10 +40,8 @@ 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.tooltip.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.component.tooltip.TooltipIconButton
import app.revanced.manager.ui.viewmodel.DownloadsViewModel import app.revanced.manager.ui.viewmodel.DownloadsViewModel
import org.koin.androidx.compose.koinViewModel import org.koin.androidx.compose.koinViewModel
import java.security.MessageDigest import java.security.MessageDigest
@@ -78,10 +75,7 @@ fun DownloadsSettingsScreen(
onBackClick = onBackClick, onBackClick = onBackClick,
actions = { actions = {
if (viewModel.appSelection.isNotEmpty()) { if (viewModel.appSelection.isNotEmpty()) {
TooltipIconButton( IconButton(onClick = { showDeleteConfirmationDialog = true }) {
tooltip = stringResource(R.string.delete),
onClick = { showDeleteConfirmationDialog = true }
) {
Icon(Icons.Default.Delete, stringResource(R.string.delete)) Icon(Icons.Default.Delete, stringResource(R.string.delete))
} }
} }

View File

@@ -3,4 +3,4 @@
<background android:drawable="@color/ic_launcher_background"/> <background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/> <foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_foreground"/> <monochrome android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon> </adaptive-icon>

View File

@@ -7,4 +7,12 @@ plugins {
alias(libs.plugins.kotlin.parcelize) apply false alias(libs.plugins.kotlin.parcelize) apply false
alias(libs.plugins.about.libraries) apply false alias(libs.plugins.about.libraries) apply false
alias(libs.plugins.compose.compiler) apply false alias(libs.plugins.compose.compiler) apply false
alias(libs.plugins.spotless)
}
spotless {
kotlin {
target("app/src/*/java/**/*.kt", "api/src/*/kotlin/**/*.kt")
ktlint().setEditorConfigPath("$projectDir/.editorconfig")
}
} }

View File

@@ -36,6 +36,7 @@ compose-icons = "1.2.4"
kotlin-process = "1.5.1" kotlin-process = "1.5.1"
hidden-api-stub = "4.3.3" hidden-api-stub = "4.3.3"
binary-compatibility-validator = "0.17.0" binary-compatibility-validator = "0.17.0"
spotless-gradle-plugin = "7.0.4"
[libraries] [libraries]
# AndroidX Core # AndroidX Core
@@ -139,3 +140,4 @@ compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "
devtools = { id = "com.google.devtools.ksp", version.ref = "dev-tools-gradle-plugin" } devtools = { id = "com.google.devtools.ksp", version.ref = "dev-tools-gradle-plugin" }
about-libraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "about-libraries-gradle-plugin" } about-libraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "about-libraries-gradle-plugin" }
binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" } binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }
spotless = { id = "com.diffplug.spotless", version.ref = "spotless-gradle-plugin" }