diff --git a/core/domain/src/main/java/dev/arkbuilders/rate/core/domain/CurrUtils.kt b/core/domain/src/main/java/dev/arkbuilders/rate/core/domain/CurrUtils.kt
index ec0bd4d11..2adf09b63 100644
--- a/core/domain/src/main/java/dev/arkbuilders/rate/core/domain/CurrUtils.kt
+++ b/core/domain/src/main/java/dev/arkbuilders/rate/core/domain/CurrUtils.kt
@@ -64,7 +64,6 @@ object CurrUtils {
"#." + "#".repeat(fractionSize),
DecimalFormatSymbols(Locale.ENGLISH),
)
- df.roundingMode = RoundingMode.CEILING
return df.format(number)
}
diff --git a/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/theme/ArkColor.kt b/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/theme/ArkColor.kt
index 8d3cc6438..760b68402 100644
--- a/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/theme/ArkColor.kt
+++ b/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/theme/ArkColor.kt
@@ -40,4 +40,6 @@ object ArkColor {
val UtilitySuccess200 = Color(0xFFABEFC6)
val UtilitySuccess500 = Color(0xFF17B26A)
val UtilitySuccess700 = Color(0xFF067647)
+
+ val NeutralGray500 = Color(0xFF6C737F)
}
diff --git a/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/utils/Haptic.kt b/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/utils/Haptic.kt
new file mode 100644
index 000000000..d1fdadf54
--- /dev/null
+++ b/core/presentation/src/main/java/dev/arkbuilders/rate/core/presentation/utils/Haptic.kt
@@ -0,0 +1,53 @@
+package dev.arkbuilders.rate.core.presentation.utils
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.platform.LocalView
+import androidx.core.view.HapticFeedbackConstantsCompat
+import androidx.core.view.ViewCompat
+
+enum class ReorderHapticFeedbackType {
+ START,
+ MOVE,
+ END,
+}
+
+open class ReorderHapticFeedback {
+ open fun performHapticFeedback(type: ReorderHapticFeedbackType) {
+ // no-op
+ }
+}
+
+@Composable
+fun rememberReorderHapticFeedback(): ReorderHapticFeedback {
+ val view = LocalView.current
+
+ val reorderHapticFeedback =
+ remember {
+ object : ReorderHapticFeedback() {
+ override fun performHapticFeedback(type: ReorderHapticFeedbackType) {
+ when (type) {
+ ReorderHapticFeedbackType.START ->
+ ViewCompat.performHapticFeedback(
+ view,
+ HapticFeedbackConstantsCompat.GESTURE_START,
+ )
+
+ ReorderHapticFeedbackType.MOVE ->
+ ViewCompat.performHapticFeedback(
+ view,
+ HapticFeedbackConstantsCompat.SEGMENT_FREQUENT_TICK,
+ )
+
+ ReorderHapticFeedbackType.END ->
+ ViewCompat.performHapticFeedback(
+ view,
+ HapticFeedbackConstantsCompat.GESTURE_END,
+ )
+ }
+ }
+ }
+ }
+
+ return reorderHapticFeedback
+}
diff --git a/core/presentation/src/main/res/drawable/ic_drag.xml b/core/presentation/src/main/res/drawable/ic_drag.xml
new file mode 100644
index 000000000..443f26407
--- /dev/null
+++ b/core/presentation/src/main/res/drawable/ic_drag.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
diff --git a/core/presentation/src/main/res/drawable/ic_refresh.xml b/core/presentation/src/main/res/drawable/ic_refresh.xml
new file mode 100644
index 000000000..ad5cec5cb
--- /dev/null
+++ b/core/presentation/src/main/res/drawable/ic_refresh.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/feature/quick/build.gradle.kts b/feature/quick/build.gradle.kts
index 35017441b..b9ffb11c2 100644
--- a/feature/quick/build.gradle.kts
+++ b/feature/quick/build.gradle.kts
@@ -56,6 +56,7 @@ dependencies {
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
implementation(libs.constraintlayout.compose)
+ implementation(libs.reorderable)
implementation(libs.timber)
diff --git a/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickScreen.kt b/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickScreen.kt
index d00822d35..2f6b17b47 100644
--- a/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickScreen.kt
+++ b/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickScreen.kt
@@ -1,8 +1,10 @@
-@file:OptIn(ExperimentalMaterial3Api::class)
+@file:OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
package dev.arkbuilders.rate.feature.quick.presentation.add
import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll
@@ -16,15 +18,21 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListScope
+import androidx.compose.foundation.lazy.itemsIndexed
+import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
-import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
+import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -40,6 +48,7 @@ import androidx.compose.ui.layout.onPlaced
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
@@ -60,17 +69,24 @@ import dev.arkbuilders.rate.core.presentation.AppSharedFlowKey
import dev.arkbuilders.rate.core.presentation.R
import dev.arkbuilders.rate.core.presentation.theme.ArkColor
import dev.arkbuilders.rate.core.presentation.ui.AppButton
-import dev.arkbuilders.rate.core.presentation.ui.AppHorDiv16
+import dev.arkbuilders.rate.core.presentation.ui.AppHorDiv
import dev.arkbuilders.rate.core.presentation.ui.AppTopBarBack
import dev.arkbuilders.rate.core.presentation.ui.ArkBasicTextField
import dev.arkbuilders.rate.core.presentation.ui.DropDownWithIcon
import dev.arkbuilders.rate.core.presentation.ui.GroupCreateDialog
import dev.arkbuilders.rate.core.presentation.ui.GroupSelectPopup
import dev.arkbuilders.rate.core.presentation.ui.NotifyAddedSnackbarVisuals
+import dev.arkbuilders.rate.core.presentation.utils.ReorderHapticFeedback
+import dev.arkbuilders.rate.core.presentation.utils.ReorderHapticFeedbackType
+import dev.arkbuilders.rate.core.presentation.utils.rememberReorderHapticFeedback
import dev.arkbuilders.rate.feature.quick.di.QuickComponentHolder
import dev.arkbuilders.rate.feature.search.presentation.destinations.SearchCurrencyScreenDestination
import org.orbitmvi.orbit.compose.collectAsState
import org.orbitmvi.orbit.compose.collectSideEffect
+import sh.calvin.reorderable.ReorderableCollectionItemScope
+import sh.calvin.reorderable.ReorderableItem
+import sh.calvin.reorderable.ReorderableLazyListState
+import sh.calvin.reorderable.rememberReorderableLazyListState
@Composable
@Destination
@@ -150,6 +166,8 @@ fun AddQuickScreen(
),
)
},
+ onSwapClick = viewModel::onSwapClick,
+ onPairsSwap = viewModel::onPairsSwap,
onAddAsset = viewModel::onAddQuickPair,
)
}
@@ -165,6 +183,8 @@ private fun Content(
onCurrencyRemove: (Int) -> Unit = {},
onGroupSelect: (String) -> Unit = {},
onCodeChange: (Int) -> Unit = {},
+ onSwapClick: () -> Unit = {},
+ onPairsSwap: (from: Int, to: Int) -> Unit = { _, _ -> },
onAddAsset: () -> Unit = {},
) {
var showNewGroupDialog by remember { mutableStateOf(false) }
@@ -177,78 +197,98 @@ private fun Content(
}
}
+ val haptic = rememberReorderHapticFeedback()
+ val lazyListState = rememberLazyListState()
+ val reorderableLazyColumnState =
+ rememberReorderableLazyListState(lazyListState) { from, to ->
+ val fromIndex = state.currencies.indexOfFirst { it.code == from.key }
+ val toIndex = state.currencies.indexOfFirst { it.code == to.key }
+ onPairsSwap(fromIndex, toIndex)
+ haptic.performHapticFeedback(ReorderHapticFeedbackType.MOVE)
+ }
+
Column(modifier = Modifier.fillMaxSize()) {
- Column(
+ LazyColumn(
modifier =
Modifier
- .weight(1f)
- .verticalScroll(rememberScrollState()),
+ .weight(1f),
+ state = lazyListState,
) {
- Currencies(state, onAmountChanged, onCurrencyRemove, onCodeChange)
- Button(
- modifier = Modifier.padding(start = 16.dp, top = 16.dp),
- shape = RoundedCornerShape(8.dp),
- border = BorderStroke(1.dp, ArkColor.Border),
- colors =
- ButtonDefaults.buttonColors(
- containerColor = Color.Transparent,
- contentColor = ArkColor.FGSecondary,
- ),
- onClick = { onNewCurrencyClick() },
- contentPadding = PaddingValues(0.dp),
- ) {
- Icon(
- modifier = Modifier.padding(start = 20.dp),
- painter = painterResource(id = R.drawable.ic_add),
- contentDescription = "",
- )
- Text(
- modifier =
- Modifier.padding(
- start = 8.dp,
- top = 10.dp,
- bottom = 10.dp,
- end = 18.dp,
- ),
- text = stringResource(R.string.new_currency),
- fontWeight = FontWeight.SemiBold,
- fontSize = 16.sp,
- )
- }
- DropDownWithIcon(
- modifier =
- Modifier
- .fillMaxWidth()
- .padding(top = 16.dp, start = 16.dp, end = 16.dp)
- .onPlaced {
- addGroupBtnWidth = it.size.width
- },
- onClick = { showGroupsPopup = true },
- title =
- state.group?.let { state.group }
- ?: stringResource(R.string.add_group),
- icon = painterResource(id = R.drawable.ic_group),
+ currencies(
+ state,
+ reorderableLazyColumnState,
+ haptic,
+ onAmountChanged,
+ onCurrencyRemove,
+ onCodeChange,
+ onSwapClick,
)
- if (showGroupsPopup) {
- Box(
- modifier =
- Modifier.padding(
- start = 16.dp,
- top = 4.dp,
+ item {
+ Button(
+ modifier = Modifier.padding(start = 16.dp, top = 16.dp),
+ shape = RoundedCornerShape(8.dp),
+ border = BorderStroke(1.dp, ArkColor.Border),
+ colors =
+ ButtonDefaults.buttonColors(
+ containerColor = Color.Transparent,
+ contentColor = ArkColor.FGSecondary,
),
+ onClick = { onNewCurrencyClick() },
+ contentPadding = PaddingValues(0.dp),
) {
- Popup(
- offset = IntOffset(0, 0),
- properties = PopupProperties(),
- onDismissRequest = { showGroupsPopup = false },
+ Icon(
+ modifier = Modifier.padding(start = 20.dp),
+ painter = painterResource(id = R.drawable.ic_add),
+ contentDescription = "",
+ )
+ Text(
+ modifier =
+ Modifier.padding(
+ start = 8.dp,
+ top = 10.dp,
+ bottom = 10.dp,
+ end = 18.dp,
+ ),
+ text = stringResource(R.string.new_currency),
+ fontWeight = FontWeight.SemiBold,
+ fontSize = 16.sp,
+ )
+ }
+ DropDownWithIcon(
+ modifier =
+ Modifier
+ .fillMaxWidth()
+ .padding(top = 16.dp, start = 16.dp, end = 16.dp)
+ .onPlaced {
+ addGroupBtnWidth = it.size.width
+ },
+ onClick = { showGroupsPopup = true },
+ title =
+ state.group?.let { state.group }
+ ?: stringResource(R.string.add_group),
+ icon = painterResource(id = R.drawable.ic_group),
+ )
+ if (showGroupsPopup) {
+ Box(
+ modifier =
+ Modifier.padding(
+ start = 16.dp,
+ top = 4.dp,
+ ),
) {
- GroupSelectPopup(
- groups = state.availableGroups,
- widthPx = addGroupBtnWidth,
- onGroupSelect = { onGroupSelect(it) },
- onNewGroupClick = { showNewGroupDialog = true },
- onDismiss = { showGroupsPopup = false },
- )
+ Popup(
+ offset = IntOffset(0, 0),
+ properties = PopupProperties(),
+ onDismissRequest = { showGroupsPopup = false },
+ ) {
+ GroupSelectPopup(
+ groups = state.availableGroups,
+ widthPx = addGroupBtnWidth,
+ onGroupSelect = { onGroupSelect(it) },
+ onNewGroupClick = { showNewGroupDialog = true },
+ onDismiss = { showGroupsPopup = false },
+ )
+ }
}
}
}
@@ -271,61 +311,110 @@ private fun Content(
}
}
-@Composable
-private fun Currencies(
+private fun LazyListScope.currencies(
state: AddQuickScreenState,
+ reorderableLazyColumnState: ReorderableLazyListState,
+ haptic: ReorderHapticFeedback,
onAmountChanged: (String) -> Unit,
onCurrencyRemove: (Int) -> Unit,
onCodeChange: (Int) -> Unit,
+ onSwapClick: () -> Unit,
) {
val from = state.currencies.first()
- Text(
- modifier = Modifier.padding(top = 16.dp, start = 16.dp),
- text = "From",
- fontWeight = FontWeight.Medium,
- color = ArkColor.TextSecondary,
- )
- FromInput(
- index = 0,
- code = from.code,
- amount = from.value,
- onAmountChanged = onAmountChanged,
- onCodeChange = onCodeChange,
- )
- AppHorDiv16(modifier = Modifier.padding(top = 16.dp))
- Text(
- modifier = Modifier.padding(top = 16.dp, start = 16.dp),
- text = "To",
- fontWeight = FontWeight.Medium,
- color = ArkColor.TextSecondary,
- )
- state.currencies.forEachIndexed { index, amountStr ->
- if (index == 0)
- return@forEachIndexed
+ val to = state.currencies.drop(1)
- ToResult(
- index = index,
- code = amountStr.code,
- amount = amountStr.value,
- onCurrencyRemove = onCurrencyRemove,
- onCodeChange = onCodeChange,
+ item {
+ Text(
+ modifier = Modifier.padding(top = 16.dp, start = 52.dp),
+ text = "From",
+ fontWeight = FontWeight.Medium,
+ color = ArkColor.TextSecondary,
+ )
+ }
+ item(key = from.code) {
+ ReorderableItem(state = reorderableLazyColumnState, key = from.code) {
+ FromInput(
+ code = from.code,
+ amount = from.value,
+ haptic = haptic,
+ scope = this,
+ onAmountChanged = onAmountChanged,
+ onCodeChange = {
+ val index = state.currencies.indexOfFirst { it.code == from.code }
+ onCodeChange(index)
+ },
+ )
+ }
+ }
+ item {
+ SwapBtn(modifier = Modifier.padding(top = 16.dp), onClick = onSwapClick)
+ Text(
+ modifier = Modifier.padding(top = 16.dp, start = 52.dp),
+ text = "To",
+ fontWeight = FontWeight.Medium,
+ color = ArkColor.TextSecondary,
)
}
+ itemsIndexed(to, key = { _, amount -> amount.code }) { index, item ->
+ ReorderableItem(state = reorderableLazyColumnState, key = item.code) {
+ ToResult(
+ code = item.code,
+ amount = item.value,
+ scope = this,
+ haptic = haptic,
+ onCurrencyRemove = {
+ val index = state.currencies.indexOfFirst { it.code == item.code }
+ onCurrencyRemove(index)
+ },
+ onCodeChange = {
+ val index = state.currencies.indexOfFirst { it.code == item.code }
+ onCodeChange(index)
+ },
+ )
+ }
+ }
}
@Composable
private fun FromInput(
- index: Int,
code: CurrencyCode,
amount: String,
+ haptic: ReorderHapticFeedback,
+ scope: ReorderableCollectionItemScope,
onAmountChanged: (String) -> Unit,
- onCodeChange: (Int) -> Unit,
+ onCodeChange: () -> Unit,
) {
Row(modifier = Modifier.padding(top = 16.dp, start = 16.dp, end = 16.dp)) {
+ Box(
+ modifier =
+ with(scope) {
+ Modifier
+ .width(24.dp)
+ .height(44.dp)
+ .draggableHandle(
+ onDragStarted = {
+ haptic.performHapticFeedback(ReorderHapticFeedbackType.START)
+ },
+ onDragStopped = {
+ haptic.performHapticFeedback(ReorderHapticFeedbackType.END)
+ },
+ )
+ .clearAndSetSemantics { }
+ },
+ ) {
+ Icon(
+ modifier = Modifier.align(Alignment.Center),
+ painter = painterResource(R.drawable.ic_drag),
+ contentDescription = null,
+ tint = ArkColor.NeutralGray500,
+ )
+ }
+
Row(
modifier =
Modifier
.weight(1f)
+ .padding(start = 12.dp)
.height(44.dp)
.border(
1.dp,
@@ -340,7 +429,7 @@ private fun FromInput(
Modifier
.fillMaxHeight()
.clip(RoundedCornerShape(8.dp))
- .clickable { onCodeChange(index) },
+ .clickable { onCodeChange() },
verticalAlignment = Alignment.CenterVertically,
) {
Text(
@@ -385,24 +474,52 @@ private fun FromInput(
@Composable
private fun ToResult(
- index: Int,
code: CurrencyCode,
amount: String,
- onCurrencyRemove: (Int) -> Unit,
- onCodeChange: (Int) -> Unit,
+ haptic: ReorderHapticFeedback,
+ scope: ReorderableCollectionItemScope,
+ onCurrencyRemove: () -> Unit,
+ onCodeChange: () -> Unit,
) {
Row(modifier = Modifier.padding(top = 16.dp, start = 16.dp, end = 16.dp)) {
+ Box(
+ modifier =
+ with(scope) {
+ Modifier
+ .width(24.dp)
+ .height(44.dp)
+ .draggableHandle(
+ onDragStarted = {
+ haptic.performHapticFeedback(ReorderHapticFeedbackType.START)
+ },
+ onDragStopped = {
+ haptic.performHapticFeedback(ReorderHapticFeedbackType.END)
+ },
+ )
+ .clearAndSetSemantics { }
+ },
+ ) {
+ Icon(
+ modifier = Modifier.align(Alignment.Center),
+ painter = painterResource(R.drawable.ic_drag),
+ contentDescription = null,
+ tint = ArkColor.NeutralGray500,
+ )
+ }
+
Row(
modifier =
Modifier
.weight(1f)
+ .padding(start = 12.dp)
.height(44.dp)
.border(
1.dp,
ArkColor.Border,
RoundedCornerShape(8.dp),
)
- .clip(RoundedCornerShape(8.dp)),
+ .clip(RoundedCornerShape(8.dp))
+ .background(Color.White),
verticalAlignment = Alignment.CenterVertically,
) {
Row(
@@ -410,7 +527,7 @@ private fun ToResult(
Modifier
.fillMaxHeight()
.clip(RoundedCornerShape(8.dp))
- .clickable { onCodeChange(index) },
+ .clickable { onCodeChange() },
verticalAlignment = Alignment.CenterVertically,
) {
Text(
@@ -457,7 +574,8 @@ private fun ToResult(
RoundedCornerShape(8.dp),
)
.clip(RoundedCornerShape(8.dp))
- .clickable { onCurrencyRemove(index) },
+ .background(Color.White)
+ .clickable { onCurrencyRemove() },
contentAlignment = Alignment.Center,
) {
Icon(
@@ -468,3 +586,34 @@ private fun ToResult(
}
}
}
+
+@Composable
+private fun SwapBtn(
+ modifier: Modifier = Modifier,
+ onClick: () -> Unit,
+) {
+ Row(modifier = modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
+ AppHorDiv(
+ modifier =
+ Modifier
+ .weight(1f)
+ .padding(start = 16.dp, end = 12.dp),
+ )
+ OutlinedButton(
+ modifier = Modifier.size(40.dp),
+ shape = CircleShape,
+ border = BorderStroke(1.dp, ArkColor.BorderSecondary),
+ contentPadding = PaddingValues(0.dp),
+ onClick = onClick,
+ colors = ButtonDefaults.outlinedButtonColors(contentColor = Color.Black),
+ ) {
+ Icon(painter = painterResource(R.drawable.ic_refresh), contentDescription = null)
+ }
+ AppHorDiv(
+ modifier =
+ Modifier
+ .weight(1f)
+ .padding(start = 12.dp, end = 16.dp),
+ )
+ }
+}
diff --git a/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickViewModel.kt b/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickViewModel.kt
index 3c28d4f54..bae410aeb 100644
--- a/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickViewModel.kt
+++ b/feature/quick/src/main/java/dev/arkbuilders/rate/feature/quick/presentation/add/AddQuickViewModel.kt
@@ -138,6 +138,45 @@ class AddQuickViewModel(
checkFinishEnabled()
}
+ fun onSwapClick() =
+ intent {
+ if (state.currencies.size < 2)
+ return@intent
+
+ val newFrom =
+ state.currencies.last().let { amount ->
+ if (amount.value.isEmpty())
+ return@let amount
+
+ val withoutCommas = amount.value.replace(",", "")
+ amount.copy(value = CurrUtils.roundOff(withoutCommas.toBigDecimalArk()))
+ }
+ val newList =
+ state.currencies.toMutableList().apply {
+ removeLast()
+ add(0, newFrom)
+ }
+
+ val calc = calcToResult(newList)
+
+ reduce {
+ state.copy(currencies = calc)
+ }
+ }
+
+ fun onPairsSwap(
+ from: Int,
+ to: Int,
+ ) = intent {
+ val new =
+ state.currencies.toMutableList().apply {
+ add(to, removeAt(from))
+ }
+ reduce {
+ state.copy(currencies = new)
+ }
+ }
+
fun onAddQuickPair() =
intent {
val from = state.currencies.first()
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index d936546e6..c8fc45036 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -37,6 +37,7 @@ workRuntimeKtx = "2.8.1"
appcompat = "1.7.0"
material = "1.12.0"
gson = "2.11.0"
+reorderable = "2.4.2"
[libraries]
ark-about = { module = "dev.arkbuilders.components:about", version.ref = "arkAbout" }
@@ -85,6 +86,7 @@ timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
+reorderable = { group = "sh.calvin.reorderable", name = "reorderable", version.ref = "reorderable" }
[plugins]
android-library = { id = "com.android.library", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }