Compare commits
56
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f59c1e09ed | ||
|
|
54481c8dc2 | ||
|
|
0179fdbee7 | ||
|
|
375830a9bd | ||
|
|
373a56a68a | ||
|
|
c487ca644e | ||
|
|
72867a9b5e | ||
|
|
f84d44770d | ||
|
|
bd6ab50859 | ||
|
|
b9e995f30d | ||
|
|
95bdc28336 | ||
|
|
72ba99f4b6 | ||
|
|
42f67dfbe4 | ||
|
|
54ddf69afb | ||
|
|
90b5c7a6e9 | ||
|
|
805a8d0bc4 | ||
|
|
10bf854a50 | ||
|
|
e7a72bef48 | ||
|
|
e45065e3b8 | ||
|
|
db3e27a215 | ||
|
|
ad0928b719 | ||
|
|
0c700232c9 | ||
|
|
7237aedb02 | ||
|
|
4a10025c4f | ||
|
|
a3709d2f04 | ||
|
|
db6c681ac1 | ||
|
|
480a7ccdc7 | ||
|
|
d7d1e09bc8 | ||
|
|
5e43d7767f | ||
|
|
abff06ff7c | ||
|
|
986b1a537e | ||
|
|
0b20abde38 | ||
|
|
ed8b99985f | ||
|
|
11c72a0e51 | ||
|
|
46fd446b35 | ||
|
|
a0e61648c3 | ||
|
|
e8c4a5624f | ||
|
|
a98fe57734 | ||
|
|
9d258d4579 | ||
|
|
9233156ee1 | ||
|
|
a9486e4c23 | ||
|
|
c3ad7cdb4e | ||
|
|
91e39388ab | ||
|
|
c1e1e6c5d3 | ||
|
|
080db964f2 | ||
|
|
edf8303027 | ||
|
|
fb4bc50db4 | ||
|
|
80a098351d | ||
|
|
a7a69deb42 | ||
|
|
4a47b0006b | ||
|
|
6c19867df9 | ||
|
|
90ef58aa81 | ||
|
|
ef5f5fceba | ||
|
|
7f04a41d32 | ||
|
|
747b74be77 | ||
|
|
62a98c9184 |
@@ -49,12 +49,21 @@ jobs:
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v6
|
||||
|
||||
- name: Run unit tests
|
||||
run: ./gradlew testDebugUnitTest
|
||||
|
||||
- name: Build APK
|
||||
run: |
|
||||
VERSION_CODE=$(git rev-list --count HEAD)
|
||||
VERSION_NAME=$(git describe --tags --always)
|
||||
./gradlew assembleSignedRelease -PVERSION_CODE=$VERSION_CODE -PVERSION_NAME=$VERSION_NAME
|
||||
|
||||
- name: Upload APK
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Cowspent-APK
|
||||
path: app/build/outputs/apk/signedRelease/app-signedRelease.apk
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v3
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
|
||||
+43
-10
@@ -1,7 +1,8 @@
|
||||
plugins {
|
||||
id 'com.android.application' version '9.3.2'
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version '2.4.0'
|
||||
id 'org.jetbrains.kotlin.plugin.compose' version '2.4.0'
|
||||
id 'com.android.application' version '9.4.0'
|
||||
id 'org.jetbrains.kotlin.plugin.serialization' version '2.4.10'
|
||||
id 'org.jetbrains.kotlin.plugin.compose' version '2.4.10'
|
||||
id 'jacoco'
|
||||
}
|
||||
|
||||
android {
|
||||
@@ -40,6 +41,7 @@ android {
|
||||
debuggable true
|
||||
initWith(buildTypes.release)
|
||||
signingConfig = signingConfigs.debug
|
||||
enableUnitTestCoverage true
|
||||
}
|
||||
release {
|
||||
minifyEnabled true
|
||||
@@ -69,6 +71,12 @@ android {
|
||||
compose = true
|
||||
}
|
||||
|
||||
testOptions {
|
||||
unitTests {
|
||||
includeAndroidResources = true
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvmToolchain(21)
|
||||
}
|
||||
@@ -96,21 +104,21 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.compose.foundation:foundation:1.11.4'
|
||||
implementation 'androidx.compose.runtime:runtime:1.11.4'
|
||||
implementation 'androidx.compose.foundation:foundation:1.12.0'
|
||||
implementation 'androidx.compose.runtime:runtime:1.12.0'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
|
||||
|
||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||
implementation 'androidx.work:work-runtime-ktx:2.11.2'
|
||||
|
||||
implementation 'com.google.zxing:core:3.5.4'
|
||||
implementation 'androidx.camera:camera-camera2:1.6.1'
|
||||
implementation 'androidx.camera:camera-lifecycle:1.6.1'
|
||||
implementation 'androidx.camera:camera-view:1.6.1'
|
||||
implementation 'androidx.camera:camera-camera2:1.6.2'
|
||||
implementation 'androidx.camera:camera-lifecycle:1.6.2'
|
||||
implementation 'androidx.camera:camera-view:1.6.2'
|
||||
implementation 'com.github.nextcloud:Android-SingleSignOn:1.1.0'
|
||||
implementation 'com.opencsv:opencsv:5.12.0'
|
||||
|
||||
implementation platform('androidx.compose:compose-bom:2026.06.01')
|
||||
implementation platform('androidx.compose:compose-bom:2026.08.00')
|
||||
implementation 'androidx.compose.ui:ui'
|
||||
implementation 'androidx.compose.material:material'
|
||||
implementation 'androidx.compose.material:material-icons-extended'
|
||||
@@ -121,5 +129,30 @@ dependencies {
|
||||
implementation 'androidx.security:security-crypto:1.1.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.11.0'
|
||||
implementation "androidx.datastore:datastore-preferences:1.2.1"
|
||||
implementation "com.google.crypto.tink:tink-android:1.22.0"
|
||||
implementation "com.google.crypto.tink:tink-android:1.23.0"
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'io.mockk:mockk:1.14.11'
|
||||
testImplementation 'org.robolectric:robolectric:4.16.1'
|
||||
testImplementation 'androidx.test:core:1.7.0'
|
||||
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0'
|
||||
}
|
||||
|
||||
tasks.register('jacocoTestReport', JacocoReport) {
|
||||
dependsOn 'testDebugUnitTest'
|
||||
|
||||
reports {
|
||||
xml.required = true
|
||||
html.required = true
|
||||
}
|
||||
|
||||
def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*']
|
||||
def debugTree = fileTree(dir: "${project.layout.buildDirectory.asFile.get()}/intermediates/built_in_kotlinc/debug/compileDebugKotlin/classes", excludes: fileFilter)
|
||||
def mainSrc = "${project.projectDir}/src/main/java"
|
||||
|
||||
sourceDirectories.from = files([mainSrc])
|
||||
classDirectories.from = files([debugTree])
|
||||
executionData.from = fileTree(dir: project.layout.buildDirectory.asFile.get(), includes: [
|
||||
'jacoco/testDebugUnitTest.exec', 'outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec'
|
||||
])
|
||||
}
|
||||
|
||||
@@ -151,8 +151,9 @@ class EditBillActivity : AppCompatActivity() {
|
||||
val billIdToDuplicate = intent.getLongExtra(PARAM_BILL_ID_TO_DUPLICATE, 0)
|
||||
val timeNowSeconds = System.currentTimeMillis() / 1000
|
||||
if (billIdToDuplicate == 0L) {
|
||||
val project = db.getProject(projectId)
|
||||
bill = DBBill(
|
||||
0, 0, projectId, 0, 0.0, timeNowSeconds,
|
||||
0, 0, projectId, project?.lastPayerId ?: 0, 0.0, timeNowSeconds,
|
||||
"", DBBill.STATE_ADDED, DBBill.NON_REPEATED,
|
||||
DBBill.PAYMODE_NONE, DBBill.CATEGORY_NONE, "", DBBill.PAYMODE_ID_NONE
|
||||
)
|
||||
@@ -324,15 +325,25 @@ class EditBillActivity : AppCompatActivity() {
|
||||
|
||||
private suspend fun saveBill(): Long = withContext(Dispatchers.IO) {
|
||||
val groupedBillIds = intent.getLongArrayExtra(PARAM_GROUPED_BILL_IDS)
|
||||
val isCustomSplit = viewModel.isCustomSplit
|
||||
val splitMode = viewModel.splitMode
|
||||
|
||||
if (isCustomSplit) {
|
||||
val splits: Map<Long, Double> = viewModel.owersCustomSplit.filter { (id, amountStr) ->
|
||||
viewModel.owersSelection[id] == true && (amountStr.replace(',', '.').toDoubleOrNull()
|
||||
?: 0.0) > 0
|
||||
}.mapValues {
|
||||
val uiAmount = it.value.replace(',', '.').toDoubleOrNull() ?: 0.0
|
||||
SupportUtil.round2(uiAmount / viewModel.selectedCurrencyRate)
|
||||
if (splitMode != SplitMode.EVEN) {
|
||||
val splits: Map<Long, Double> = if (splitMode == SplitMode.CUSTOM) {
|
||||
viewModel.owersCustomSplit.filter { (id, amountStr) ->
|
||||
viewModel.owersSelection[id] == true && viewModel.parseAmountFromUi(amountStr) > 0
|
||||
}.mapValues {
|
||||
val uiAmount = viewModel.parseAmountFromUi(it.value)
|
||||
SupportUtil.round2(uiAmount / viewModel.selectedCurrencyRate)
|
||||
}
|
||||
} else { // PERCENT
|
||||
val totalAmount = viewModel.amountAsDouble
|
||||
viewModel.owersPercentSplit.filter { (id, percentStr) ->
|
||||
viewModel.owersSelection[id] == true && viewModel.parseAmountFromUi(percentStr) > 0
|
||||
}.mapValues {
|
||||
val percent = viewModel.parseAmountFromUi(it.value)
|
||||
val uiAmount = SupportUtil.round2(totalAmount * percent / 100.0)
|
||||
SupportUtil.round2(uiAmount / viewModel.selectedCurrencyRate)
|
||||
}
|
||||
}
|
||||
|
||||
if (splits.isEmpty()) return@withContext 0L
|
||||
@@ -405,16 +416,8 @@ class EditBillActivity : AppCompatActivity() {
|
||||
val proj = db.getProject(bill.projectId)
|
||||
if (proj != null) db.syncIfRemote(proj)
|
||||
db.updateProject(
|
||||
bill.projectId,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
viewModel.payerId,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
projId = bill.projectId,
|
||||
newLastPayerId = viewModel.payerId
|
||||
)
|
||||
|
||||
return@withContext firstSavedId
|
||||
@@ -458,16 +461,8 @@ class EditBillActivity : AppCompatActivity() {
|
||||
newOwersIds.forEach { newBill.billOwers += DBBillOwer(0, 0, it) }
|
||||
val newBillId = db.addBill(newBill)
|
||||
db.updateProject(
|
||||
bill.projectId,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
viewModel.payerId,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
projId = bill.projectId,
|
||||
newLastPayerId = viewModel.payerId
|
||||
)
|
||||
val proj = db.getProject(bill.projectId)
|
||||
if (proj != null) db.syncIfRemote(proj)
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package net.helcel.cowspent.android.bill_edit
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.*
|
||||
@@ -16,12 +18,18 @@ import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.scale
|
||||
import androidx.compose.ui.focus.FocusDirection
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
@@ -53,6 +61,13 @@ fun EditBillScreen(
|
||||
) {
|
||||
val canEdit = accessLevel == DBProject.ACCESS_LEVEL_UNKNOWN || accessLevel >= DBProject.ACCESS_LEVEL_PARTICIPANT
|
||||
val context = LocalContext.current
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
if (viewModel.isNewBill) {
|
||||
focusRequester.requestFocus()
|
||||
}
|
||||
}
|
||||
|
||||
StatefulAlertDialog(
|
||||
state = viewModel.dialogState,
|
||||
@@ -128,7 +143,8 @@ fun EditBillScreen(
|
||||
viewModel = viewModel,
|
||||
canEdit = canEdit,
|
||||
onDateClick = onDateClick,
|
||||
onTimeClick = onTimeClick
|
||||
onTimeClick = onTimeClick,
|
||||
amountFocusRequester = focusRequester
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
@@ -164,7 +180,8 @@ fun BillBasicInfoSection(
|
||||
viewModel: EditBillViewModel,
|
||||
canEdit: Boolean,
|
||||
onDateClick: () -> Unit,
|
||||
onTimeClick: () -> Unit
|
||||
onTimeClick: () -> Unit,
|
||||
amountFocusRequester: FocusRequester
|
||||
) {
|
||||
Text(
|
||||
text = "GENERAL",
|
||||
@@ -175,29 +192,20 @@ fun BillBasicInfoSection(
|
||||
)
|
||||
|
||||
val context = LocalContext.current
|
||||
val focusManager = LocalFocusManager.current
|
||||
val currencyDialogTitle =
|
||||
stringResource(R.string.currency_dialog_title, viewModel.mainCurrencyName)
|
||||
|
||||
OutlinedTextField(
|
||||
value = viewModel.what,
|
||||
onValueChange = { viewModel.what = it },
|
||||
enabled = canEdit,
|
||||
placeholder = { Text(stringResource(R.string.label_what)) },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
leadingIcon = { Icon(Icons.Default.Title, contentDescription = null) }
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
OutlinedTextField(
|
||||
value = viewModel.amount,
|
||||
onValueChange = {
|
||||
viewModel.amount = it
|
||||
onValueChange = { nv->
|
||||
val filteredValue = nv.filter { it in "0123456789.+-*/" }
|
||||
viewModel.amount = filteredValue
|
||||
viewModel.updateSplits()
|
||||
},
|
||||
enabled = canEdit,
|
||||
placeholder = { Text("0") },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
modifier = Modifier.fillMaxWidth().focusRequester(amountFocusRequester),
|
||||
leadingIcon = {
|
||||
val currencyToShow = viewModel.selectedCurrencyName.ifEmpty {
|
||||
viewModel.mainCurrencyName.ifEmpty { "$" }
|
||||
@@ -231,7 +239,21 @@ fun BillBasicInfoSection(
|
||||
Icon(Icons.Default.SwapHoriz, contentDescription = "Change Currency")
|
||||
}
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Phone, imeAction = ImeAction.Next),
|
||||
keyboardActions = KeyboardActions(onNext = { focusManager.moveFocus(FocusDirection.Next) })
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
OutlinedTextField(
|
||||
value = viewModel.what,
|
||||
onValueChange = { viewModel.what = it },
|
||||
enabled = canEdit,
|
||||
placeholder = { Text(stringResource(R.string.label_what)) },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
leadingIcon = { Icon(Icons.Default.Title, contentDescription = null) },
|
||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
|
||||
keyboardActions = KeyboardActions(onNext = { focusManager.moveFocus(FocusDirection.Next) })
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
@@ -357,34 +379,54 @@ fun OwerSelectionSection(
|
||||
)
|
||||
Spacer(Modifier.weight(1f))
|
||||
|
||||
if (viewModel.isCustomSplit) {
|
||||
if (viewModel.splitMode != SplitMode.EVEN) {
|
||||
val diff = viewModel.getDiffSplit()
|
||||
if (abs(diff) > 0.01) {
|
||||
val unit = if (viewModel.splitMode == SplitMode.PERCENT) "%" else ""
|
||||
val diffText =
|
||||
if (diff > 0) "Missing: ${SupportUtil.normalNumberFormat.format(diff)}" else "Excess: ${
|
||||
if (diff > 0) "Missing: ${SupportUtil.normalNumberFormat.format(diff)}$unit" else "Excess: ${
|
||||
SupportUtil.normalNumberFormat.format(-diff)
|
||||
}"
|
||||
}$unit"
|
||||
Text(
|
||||
diffText,
|
||||
color = MaterialTheme.colors.error,
|
||||
fontSize = 12.sp,
|
||||
modifier = Modifier.padding(horizontal = 16.dp)
|
||||
modifier = Modifier.padding(horizontal = 4.dp)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Text("Even Split", fontSize = 12.sp)
|
||||
}
|
||||
Switch(
|
||||
checked = !viewModel.isCustomSplit,
|
||||
enabled = canEdit,
|
||||
onCheckedChange = {
|
||||
viewModel.isCustomSplit = !it
|
||||
viewModel.updateSplits()
|
||||
},
|
||||
colors = SwitchDefaults.colors(
|
||||
uncheckedThumbColor = MaterialTheme.colors.onSurface,
|
||||
)
|
||||
)
|
||||
|
||||
val splitOptions = listOf(SplitMode.EVEN, SplitMode.CUSTOM, SplitMode.PERCENT)
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(start = 8.dp)
|
||||
.background(MaterialTheme.colors.onSurface.copy(alpha = 0.05f), MaterialTheme.shapes.small)
|
||||
) {
|
||||
splitOptions.forEach { mode ->
|
||||
val isSelected = viewModel.splitMode == mode
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.clip(MaterialTheme.shapes.small)
|
||||
.background(if (isSelected) MaterialTheme.colors.primary else Color.Transparent)
|
||||
.clickable(enabled = canEdit) {
|
||||
viewModel.splitMode = mode
|
||||
viewModel.updateSplits()
|
||||
}
|
||||
.padding(horizontal = 8.dp, vertical = 4.dp)
|
||||
) {
|
||||
Text(
|
||||
text = when (mode) {
|
||||
SplitMode.EVEN -> "="
|
||||
SplitMode.CUSTOM -> "#"
|
||||
SplitMode.PERCENT -> "%"
|
||||
},
|
||||
color = if (isSelected) MaterialTheme.colors.onPrimary else MaterialTheme.colors.onSurface,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.members.forEach { member ->
|
||||
@@ -410,21 +452,34 @@ fun OwerSelectionSection(
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(member.name, modifier = Modifier.weight(1f))
|
||||
|
||||
if (isSelected || viewModel.isCustomSplit) {
|
||||
if (isSelected || viewModel.splitMode != SplitMode.EVEN) {
|
||||
val focusManager = LocalFocusManager.current
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
val value = if (viewModel.splitMode == SplitMode.PERCENT) {
|
||||
viewModel.owersPercentSplit[member.id] ?: ""
|
||||
} else {
|
||||
viewModel.owersCustomSplit[member.id] ?: ""
|
||||
}
|
||||
|
||||
BasicTextField(
|
||||
value = viewModel.owersCustomSplit[member.id] ?: "",
|
||||
onValueChange = {
|
||||
viewModel.owersCustomSplit[member.id] = it
|
||||
viewModel.owersSelection[member.id] = (it != "")
|
||||
value = value,
|
||||
onValueChange = { nv ->
|
||||
val filteredValue = nv.filter { it in "0123456789.+-*/" }
|
||||
if (viewModel.splitMode == SplitMode.PERCENT) {
|
||||
viewModel.owersPercentSplit[member.id] = filteredValue
|
||||
} else {
|
||||
viewModel.owersCustomSplit[member.id] = filteredValue
|
||||
}
|
||||
viewModel.owersSelection[member.id] = (filteredValue != "")
|
||||
},
|
||||
modifier = Modifier
|
||||
.width(80.dp)
|
||||
.height(46.dp),
|
||||
interactionSource = interactionSource,
|
||||
singleLine = true,
|
||||
enabled = viewModel.isCustomSplit && canEdit,
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||
enabled = viewModel.splitMode != SplitMode.EVEN && canEdit,
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Next),
|
||||
keyboardActions = KeyboardActions(onNext = { focusManager.moveFocus(FocusDirection.Next) }),
|
||||
cursorBrush = SolidColor(MaterialTheme.colors.onSurface),
|
||||
textStyle = LocalTextStyle.current.copy(
|
||||
textAlign = TextAlign.Right,
|
||||
@@ -432,13 +487,13 @@ fun OwerSelectionSection(
|
||||
),
|
||||
) { innerTextField ->
|
||||
TextFieldDefaults.OutlinedTextFieldDecorationBox(
|
||||
value = viewModel.owersCustomSplit[member.id] ?: "",
|
||||
value = value,
|
||||
visualTransformation = VisualTransformation.None,
|
||||
innerTextField = innerTextField,
|
||||
singleLine = true,
|
||||
enabled = viewModel.isCustomSplit && canEdit,
|
||||
enabled = viewModel.splitMode != SplitMode.EVEN && canEdit,
|
||||
interactionSource = interactionSource,
|
||||
contentPadding = PaddingValues(horizontal = 12.dp, vertical = 0.dp),
|
||||
contentPadding = PaddingValues(horizontal = 8.dp, vertical = 0.dp),
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
cursorColor = MaterialTheme.colors.onSurface,
|
||||
backgroundColor = Color.Transparent,
|
||||
|
||||
@@ -16,6 +16,10 @@ import net.helcel.cowspent.model.DBMember
|
||||
import net.helcel.cowspent.util.SupportUtil
|
||||
import net.helcel.cowspent.util.evalMath
|
||||
|
||||
enum class SplitMode {
|
||||
EVEN, CUSTOM, PERCENT
|
||||
}
|
||||
|
||||
class EditBillViewModel : ViewModel() {
|
||||
var what by mutableStateOf("")
|
||||
var amount by mutableStateOf("")
|
||||
@@ -34,27 +38,36 @@ class EditBillViewModel : ViewModel() {
|
||||
var members by mutableStateOf<List<DBMember>>(emptyList())
|
||||
|
||||
var owersSelection = mutableStateMapOf<Long, Boolean>()
|
||||
var isCustomSplit by mutableStateOf(false)
|
||||
var splitMode by mutableStateOf(SplitMode.EVEN)
|
||||
var owersCustomSplit = mutableStateMapOf<Long, String>()
|
||||
var owersPercentSplit = mutableStateMapOf<Long, String>()
|
||||
|
||||
var dialogState by mutableStateOf<DialogState?>(null)
|
||||
|
||||
val amountAsDouble: Double
|
||||
get() {
|
||||
return parseAmount(amount) ?: try {
|
||||
evalMath(amount.replace(',', '.'))
|
||||
} catch (_: Exception) {
|
||||
0.0
|
||||
}
|
||||
fun parseAmountFromUi(input: String): Double {
|
||||
if (input.isBlank()) return 0.0
|
||||
val sanitized = input.replace(',', '.')
|
||||
// If it contains any math operator, try evalMath first
|
||||
if (sanitized.any { it in "+-*/" }) {
|
||||
try {
|
||||
val result = evalMath(sanitized)
|
||||
if (result != 0.0) return SupportUtil.round2(result)
|
||||
} catch (_: Exception) {}
|
||||
}
|
||||
val parsed = parseAmount(input) ?: 0.0
|
||||
return SupportUtil.round2(parsed)
|
||||
}
|
||||
|
||||
val amountAsDouble: Double
|
||||
get() = parseAmountFromUi(amount)
|
||||
|
||||
fun getEvenSplit(): Double {
|
||||
val selectedOwersCount = owersSelection.count { it.value }
|
||||
return if (selectedOwersCount > 0) amountAsDouble / selectedOwersCount else 0.0
|
||||
return if (selectedOwersCount > 0) SupportUtil.round2(amountAsDouble / selectedOwersCount) else 0.0
|
||||
}
|
||||
|
||||
fun updateSplits() {
|
||||
if (!isCustomSplit) {
|
||||
if (splitMode == SplitMode.EVEN) {
|
||||
val even = getEvenSplit()
|
||||
val evenStr = if (even == 0.0) "" else SupportUtil.round2(even).toString()
|
||||
members.forEach { m ->
|
||||
@@ -64,18 +77,36 @@ class EditBillViewModel : ViewModel() {
|
||||
owersCustomSplit.remove(m.id)
|
||||
}
|
||||
}
|
||||
} else if (splitMode == SplitMode.PERCENT) {
|
||||
val selectedCount = owersSelection.count { it.value }
|
||||
if (selectedCount > 0) {
|
||||
val evenPercent = 100.0 / selectedCount
|
||||
val evenPercentStr = SupportUtil.round2(evenPercent).toString()
|
||||
members.forEach { m ->
|
||||
if (owersSelection[m.id] == true) {
|
||||
if (owersPercentSplit[m.id].isNullOrEmpty()) {
|
||||
owersPercentSplit[m.id] = evenPercentStr
|
||||
}
|
||||
} else {
|
||||
owersPercentSplit.remove(m.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun toggleMember(id: Long, selected: Boolean) {
|
||||
owersSelection[id] = selected
|
||||
if (isCustomSplit) {
|
||||
if (splitMode != SplitMode.EVEN) {
|
||||
if (selected) {
|
||||
if (owersCustomSplit[id].isNullOrEmpty()) {
|
||||
if (splitMode == SplitMode.CUSTOM && owersCustomSplit[id].isNullOrEmpty()) {
|
||||
owersCustomSplit[id] = "0"
|
||||
} else if (splitMode == SplitMode.PERCENT && owersPercentSplit[id].isNullOrEmpty()) {
|
||||
owersPercentSplit[id] = "0"
|
||||
}
|
||||
} else {
|
||||
owersCustomSplit.remove(id)
|
||||
owersPercentSplit.remove(id)
|
||||
}
|
||||
} else {
|
||||
updateSplits()
|
||||
@@ -83,10 +114,17 @@ class EditBillViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
fun getDiffSplit(): Double {
|
||||
val customTotal = owersCustomSplit.entries
|
||||
.filter { owersSelection[it.key] == true }
|
||||
.sumOf { it.value.replace(',', '.').toDoubleOrNull() ?: 0.0 }
|
||||
return amountAsDouble - customTotal
|
||||
return if (splitMode == SplitMode.PERCENT) {
|
||||
val customTotal = owersPercentSplit.entries
|
||||
.filter { owersSelection[it.key] == true }
|
||||
.sumOf { parseAmountFromUi(it.value) }
|
||||
SupportUtil.round2(100.0 - customTotal)
|
||||
} else {
|
||||
val customTotal = owersCustomSplit.entries
|
||||
.filter { owersSelection[it.key] == true }
|
||||
.sumOf { parseAmountFromUi(it.value) }
|
||||
SupportUtil.round2(amountAsDouble - customTotal)
|
||||
}
|
||||
}
|
||||
|
||||
fun getOwersIds(): List<Long> {
|
||||
@@ -204,9 +242,10 @@ class EditBillViewModel : ViewModel() {
|
||||
|
||||
owersSelection.clear()
|
||||
owersCustomSplit.clear()
|
||||
owersPercentSplit.clear()
|
||||
|
||||
if (customSplits != null) {
|
||||
isCustomSplit = true
|
||||
splitMode = SplitMode.CUSTOM
|
||||
for (member in members) {
|
||||
val selected = customSplits.containsKey(member.id)
|
||||
owersSelection[member.id] = selected
|
||||
@@ -222,6 +261,7 @@ class EditBillViewModel : ViewModel() {
|
||||
}
|
||||
} else {
|
||||
// Even split logic
|
||||
splitMode = SplitMode.EVEN
|
||||
val billOwerIds = bill.billOwersIds
|
||||
val selectedCount = billOwerIds.size
|
||||
|
||||
|
||||
+8
-4
@@ -84,9 +84,8 @@ class ManageCurrenciesActivity : AppCompatActivity() {
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
db!!.updateProject(
|
||||
selectedProjectID, null, null, null,
|
||||
null, null, newMainCurrencyName,
|
||||
null, null, null
|
||||
projId = selectedProjectID,
|
||||
newCurrencyName = newMainCurrencyName
|
||||
)
|
||||
val project = db!!.getProject(selectedProjectID)
|
||||
if (project != null) {
|
||||
@@ -94,7 +93,12 @@ class ManageCurrenciesActivity : AppCompatActivity() {
|
||||
if (project.type == ProjectType.COSPEND) {
|
||||
withContext(Dispatchers.Main) {
|
||||
if (!db!!.cowspentServerSyncHelper
|
||||
.editRemoteProject(selectedProjectID, project.name, null, null, newMainCurrencyName, editMainCurrencyCallBack)
|
||||
.editRemoteProject(
|
||||
projId = selectedProjectID,
|
||||
newName = project.name,
|
||||
newMainCurrencyName = newMainCurrencyName,
|
||||
callback = editMainCurrencyCallBack
|
||||
)
|
||||
) {
|
||||
showToast(this@ManageCurrenciesActivity, getString(R.string.remote_project_operation_no_network), Toast.LENGTH_LONG)
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@ import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
@@ -417,6 +419,9 @@ fun BillsListScreen(
|
||||
is SectionItem -> SectionHeader(item.title)
|
||||
}
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(64.dp).fillMaxWidth())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ object BillsListUtils {
|
||||
shareIntent,
|
||||
context.getString(R.string.title_settle)
|
||||
)
|
||||
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
context.startActivity(chooserIntent)
|
||||
}
|
||||
|
||||
|
||||
@@ -427,19 +427,26 @@ class BillsListViewActivity :
|
||||
withContext(Dispatchers.IO) {
|
||||
db.updateProject(
|
||||
projId = projectId,
|
||||
newName = null,
|
||||
newEmail = null,
|
||||
newPassword = null,
|
||||
newLastPayerId = null,
|
||||
newLastSyncedTimestamp = null,
|
||||
newCurrencyName = null,
|
||||
newDeletionDisabled = null,
|
||||
newMyAccessLevel = null,
|
||||
newBearerToken = null,
|
||||
newArchivedTs = newArchivedTs
|
||||
)
|
||||
}
|
||||
|
||||
if (!proj.isLocal) {
|
||||
db.cowspentServerSyncHelper.editRemoteProject(
|
||||
projId = projectId,
|
||||
newArchivedTs = newArchivedTs,
|
||||
callback = object : ICallback {
|
||||
override fun onFinish() {}
|
||||
override fun onFinish(result: String, message: String) {
|
||||
if (message.isNotEmpty()) {
|
||||
showToast(this@BillsListViewActivity, getString(R.string.error_sync, message))
|
||||
}
|
||||
}
|
||||
override fun onScheduled() {}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
setupDrawerProjects()
|
||||
refreshLists()
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ object ProjectImportHelper {
|
||||
}
|
||||
else -> 0
|
||||
}
|
||||
val payerName = if (columns.containsKey("payer_name")) line[columns["payer_name"]!!] else ""
|
||||
val payerName = if (columns.containsKey("payer_name")) line[columns["payer_name"]!!].trim() else ""
|
||||
val payerWeight = if (columns.containsKey("payer_weight")) line[columns["payer_weight"]!!].toDouble() else 1.0
|
||||
val owersStr = if (columns.containsKey("owers")) line[columns["owers"]!!] else ""
|
||||
val payerActive = columns.containsKey("payer_active") && line[columns["payer_active"]!!] == "1"
|
||||
@@ -122,8 +122,10 @@ object ProjectImportHelper {
|
||||
val pmId = if (columns.containsKey("paymentmodeid") && line[columns["paymentmodeid"]!!].isNotEmpty()) line[columns["paymentmodeid"]!!].toLong() else 0L
|
||||
val pm = if (columns.containsKey("paymentmode")) line[columns["paymentmode"]!!] else null
|
||||
|
||||
membersActive[payerName] = payerActive
|
||||
membersWeight[payerName] = payerWeight
|
||||
if (payerName.isNotEmpty()) {
|
||||
membersActive[payerName] = payerActive
|
||||
membersWeight[payerName] = payerWeight
|
||||
}
|
||||
|
||||
if (owersStr.trim().isEmpty()) {
|
||||
onError(context.getString(R.string.import_error_owers, row))
|
||||
@@ -132,10 +134,10 @@ object ProjectImportHelper {
|
||||
|
||||
if (what != "deleteMeIfYouWant") {
|
||||
billRemoteIdToOwerStr[row.toLong()] = owersStr
|
||||
val owersArray = owersStr.split(", ").filter { it.isNotEmpty() }
|
||||
val owersArray = owersStr.split(",").map { it.trim() }.filter { it.isNotEmpty() }
|
||||
for (ower in owersArray) {
|
||||
if (!membersWeight.containsKey(ower.trim())) {
|
||||
membersWeight[ower.trim()] = 1.0
|
||||
if (!membersWeight.containsKey(ower)) {
|
||||
membersWeight[ower] = 1.0
|
||||
}
|
||||
}
|
||||
bills.add(DBBill(0, row.toLong(), 0, 0, amount, timestamp, what, DBBill.STATE_OK, "n", pm, catId, comment, pmId))
|
||||
@@ -171,8 +173,8 @@ object ProjectImportHelper {
|
||||
val localCatId = catRemoteToLocal[b.categoryId] ?: 0L
|
||||
val localPmId = pmRemoteToLocal[b.paymentModeId] ?: 0L
|
||||
val billId = db.addBill(DBBill(0, 0, pid, payerId, b.amount, b.timestamp, b.what, DBBill.STATE_OK, b.repeat, b.paymentMode, localCatId, b.comment, localPmId))
|
||||
billRemoteIdToOwerStr[b.remoteId]?.split(", ")?.filter { it.isNotEmpty() }?.forEach { ower ->
|
||||
memberNameToId[ower.trim()]?.let { owerId -> db.addBillower(billId, owerId) }
|
||||
billRemoteIdToOwerStr[b.remoteId]?.split(",")?.map { it.trim() }?.filter { it.isNotEmpty() }?.forEach { ower ->
|
||||
memberNameToId[ower]?.let { owerId -> db.addBillower(billId, owerId) }
|
||||
}
|
||||
}
|
||||
onSuccess(pid)
|
||||
|
||||
@@ -85,10 +85,11 @@ class EditProjectActivity : AppCompatActivity() {
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
db.updateProject(
|
||||
project.id, newName, newEmail, targetPwd,
|
||||
null, project.type, null,
|
||||
null, null,
|
||||
null, null
|
||||
projId = project.id,
|
||||
newName = newName,
|
||||
newEmail = newEmail,
|
||||
newPassword = targetPwd,
|
||||
projectType = project.type
|
||||
)
|
||||
}
|
||||
closeOnEdit(project.id)
|
||||
@@ -103,18 +104,21 @@ class EditProjectActivity : AppCompatActivity() {
|
||||
project.password = currentPwd
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
db.updateProject(project.id, null, null, currentPwd, null, project.type, null, null, null, null, null)
|
||||
db.updateProject(
|
||||
projId = project.id,
|
||||
newPassword = currentPwd,
|
||||
projectType = project.type
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!db.cowspentServerSyncHelper.editRemoteProject(
|
||||
project.id,
|
||||
newName,
|
||||
newEmail,
|
||||
if (pwdChanged) newPwd else null,
|
||||
null,
|
||||
editCallBack
|
||||
projId = project.id,
|
||||
newName = newName,
|
||||
newEmail = newEmail,
|
||||
newPassword = if (pwdChanged) newPwd else null,
|
||||
callback = editCallBack
|
||||
)
|
||||
) {
|
||||
showToast(this, getString(R.string.remote_project_operation_no_network), Toast.LENGTH_LONG)
|
||||
@@ -124,10 +128,9 @@ class EditProjectActivity : AppCompatActivity() {
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
db.updateProject(
|
||||
project.id, null, null, currentPwd,
|
||||
null, project.type, null,
|
||||
null, null,
|
||||
null, null
|
||||
projId = project.id,
|
||||
newPassword = currentPwd,
|
||||
projectType = project.type
|
||||
)
|
||||
}
|
||||
closeOnEdit(project.id)
|
||||
|
||||
@@ -271,12 +271,18 @@ class CowspentSQLiteOpenHelper private constructor(val context: Context) :
|
||||
}
|
||||
|
||||
fun updateProject(
|
||||
projId: Long, newName: String?, newEmail: String?,
|
||||
newPassword: String?, newLastPayerId: Long?,
|
||||
newLastSyncedTimestamp: Long?,
|
||||
newCurrencyName: String?, newDeletionDisabled: Boolean?,
|
||||
newMyAccessLevel: Int?, newBearerToken: String?,
|
||||
newArchivedTs: Long? = null
|
||||
projId: Long,
|
||||
newName: String? = null,
|
||||
newEmail: String? = null,
|
||||
newPassword: String? = null,
|
||||
newLastPayerId: Long? = null,
|
||||
newLastSyncedTimestamp: Long? = null,
|
||||
newCurrencyName: String? = null,
|
||||
newDeletionDisabled: Boolean? = null,
|
||||
newMyAccessLevel: Int? = null,
|
||||
newBearerToken: String? = null,
|
||||
newArchivedTs: Long? = null,
|
||||
projectType: ProjectType? = null
|
||||
) {
|
||||
val db = writableDatabase
|
||||
val values = ContentValues()
|
||||
@@ -290,47 +296,7 @@ class CowspentSQLiteOpenHelper private constructor(val context: Context) :
|
||||
if (newDeletionDisabled != null) values.put(key_deletionDisabled, if (newDeletionDisabled) 1 else 0)
|
||||
if (newMyAccessLevel != null) values.put(key_myAccessLevel, newMyAccessLevel)
|
||||
if (newArchivedTs != null) values.put(key_archived, newArchivedTs)
|
||||
if (values.size() > 0) {
|
||||
db.update(table_projects, values, "$key_id = ?", arrayOf(projId.toString()))
|
||||
}
|
||||
}
|
||||
|
||||
fun updateProject(
|
||||
projId: Long, newName: String?, newEmail: String?,
|
||||
newPassword: String?, newLastPayerId: Long?,
|
||||
projectType: ProjectType, newLastSyncedTimestamp: Long?,
|
||||
newCurrencyName: String?, newDeletionDisabled: Boolean?,
|
||||
newMyAccessLevel: Int?, newBearerToken: String?,
|
||||
newArchivedTs: Long? = null
|
||||
) {
|
||||
val db = writableDatabase
|
||||
updateProject(
|
||||
projId, newName, newEmail, newPassword, newLastPayerId, projectType,
|
||||
newLastSyncedTimestamp, newCurrencyName, newDeletionDisabled, newMyAccessLevel,
|
||||
newBearerToken, newArchivedTs, db
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateProject(
|
||||
projId: Long, newName: String?, newEmail: String?,
|
||||
newPassword: String?, newLastPayerId: Long?,
|
||||
projectType: ProjectType, newLastSyncedTimestamp: Long?,
|
||||
newCurrencyName: String?, newDeletionDisabled: Boolean?,
|
||||
newMyAccessLevel: Int?, newBearerToken: String?,
|
||||
newArchivedTs: Long?, db: SQLiteDatabase
|
||||
) {
|
||||
val values = ContentValues()
|
||||
if (newName != null) values.put(key_name, newName)
|
||||
if (newEmail != null) values.put(key_email, newEmail)
|
||||
if (newPassword != null) SecureStorage.savePasswordSync(context, "ProjectPassword_$projId", newPassword)
|
||||
if (newBearerToken != null) values.put(key_bearer_token, newBearerToken)
|
||||
if (newLastPayerId != null) values.put(key_lastPayerId, newLastPayerId)
|
||||
if (newLastSyncedTimestamp != null) values.put(key_lastSyncTimestamp, newLastSyncedTimestamp)
|
||||
if (newCurrencyName != null) values.put(key_currencyName, newCurrencyName)
|
||||
if (newDeletionDisabled != null) values.put(key_deletionDisabled, if (newDeletionDisabled) 1 else 0)
|
||||
if (newMyAccessLevel != null) values.put(key_myAccessLevel, newMyAccessLevel)
|
||||
if (newArchivedTs != null) values.put(key_archived, newArchivedTs)
|
||||
values.put(key_type, projectType.id)
|
||||
if (projectType != null) values.put(key_type, projectType.id)
|
||||
if (values.size() > 0) {
|
||||
db.update(table_projects, values, "$key_id = ?", arrayOf(projId.toString()))
|
||||
}
|
||||
|
||||
@@ -85,7 +85,8 @@ class CowspentServerSyncHelper private constructor(private val dbHelper: Cowspen
|
||||
val isSyncPossible: Boolean
|
||||
get() {
|
||||
updateNetworkStatus()
|
||||
return networkConnected
|
||||
val offlineMode = preferences.getBoolean(appContext.getString(R.string.pref_key_offline_mode), false)
|
||||
return networkConnected && !offlineMode
|
||||
}
|
||||
|
||||
fun addCallbackPull(callback: ICallback) {
|
||||
@@ -817,10 +818,8 @@ class CowspentServerSyncHelper private constructor(private val dbHelper: Cowspen
|
||||
}
|
||||
|
||||
dbHelper.updateProject(
|
||||
project.id, null, null,
|
||||
null, null, serverSyncTimestamp,
|
||||
null, null, null,
|
||||
null
|
||||
projId = project.id,
|
||||
newLastSyncedTimestamp = serverSyncTimestamp
|
||||
)
|
||||
LoginStatus.OK
|
||||
} catch (_: ServerResponse.NotModifiedException) {
|
||||
@@ -935,11 +934,18 @@ class CowspentServerSyncHelper private constructor(private val dbHelper: Cowspen
|
||||
return isCospend && projUrl == accountUrl
|
||||
}
|
||||
|
||||
fun editRemoteProject(projId: Long, newName: String?, newEmail: String?,
|
||||
newPassword: String?, newMainCurrencyName: String?, callback: ICallback): Boolean {
|
||||
fun editRemoteProject(
|
||||
projId: Long,
|
||||
newName: String? = null,
|
||||
newEmail: String? = null,
|
||||
newPassword: String? = null,
|
||||
newMainCurrencyName: String? = null,
|
||||
newArchivedTs: Long? = null,
|
||||
callback: ICallback
|
||||
): Boolean {
|
||||
updateNetworkStatus()
|
||||
if (isSyncPossible) {
|
||||
EditRemoteProjectTask(projId, newName, newEmail, newPassword, newMainCurrencyName, callback).execute()
|
||||
EditRemoteProjectTask(projId, newName, newEmail, newPassword, newMainCurrencyName, newArchivedTs, callback).execute()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -951,6 +957,7 @@ class CowspentServerSyncHelper private constructor(private val dbHelper: Cowspen
|
||||
private val newEmail: String?,
|
||||
private val newPassword: String?,
|
||||
private val newMainCurrencyName: String?,
|
||||
private val newArchivedTs: Long?,
|
||||
private val callback: ICallback
|
||||
) {
|
||||
private val project: DBProject? = dbHelper.getProject(projId)
|
||||
@@ -985,7 +992,7 @@ class CowspentServerSyncHelper private constructor(private val dbHelper: Cowspen
|
||||
var status = LoginStatus.OK
|
||||
try {
|
||||
val response = client!!.editRemoteProject(
|
||||
project!!, newName, newEmail, newPassword, newMainCurrencyName
|
||||
project!!, newName, newEmail, newPassword, newMainCurrencyName, newArchivedTs
|
||||
)
|
||||
if (BillsListViewActivity.DEBUG) {
|
||||
Log.i(TAG, "RESPONSE edit remote project : ${response.stringContent}")
|
||||
@@ -1025,8 +1032,11 @@ class CowspentServerSyncHelper private constructor(private val dbHelper: Cowspen
|
||||
}
|
||||
} else {
|
||||
dbHelper.updateProject(
|
||||
project!!.id, newName, newEmail, newPassword,
|
||||
null, null, null, null, null, null
|
||||
projId = project!!.id,
|
||||
newName = newName,
|
||||
newEmail = newEmail,
|
||||
newPassword = newPassword,
|
||||
newArchivedTs = newArchivedTs
|
||||
)
|
||||
}
|
||||
callback.onFinish(newName ?: "", errorString)
|
||||
@@ -1205,7 +1215,7 @@ class CowspentServerSyncHelper private constructor(private val dbHelper: Cowspen
|
||||
}
|
||||
}
|
||||
|
||||
private fun hasChanged(localBill: DBBill, remoteBill: DBBill): Boolean {
|
||||
internal fun hasChanged(localBill: DBBill, remoteBill: DBBill): Boolean {
|
||||
if (localBill.payerId == remoteBill.payerId &&
|
||||
localBill.amount == remoteBill.amount &&
|
||||
localBill.timestamp == remoteBill.timestamp &&
|
||||
|
||||
@@ -114,7 +114,7 @@ class VersatileProjectSyncClient(
|
||||
@Throws(IOException::class, TokenMismatchException::class, NextcloudHttpRequestFailedException::class)
|
||||
fun editRemoteProject(
|
||||
project: DBProject, newName: String?, newEmail: String?, newPassword: String?,
|
||||
newMainCurrencyName: String?
|
||||
newMainCurrencyName: String?, newArchivedTs: Long? = null
|
||||
): ServerResponse.EditRemoteProjectResponse {
|
||||
val paramKeys: MutableList<String> = ArrayList()
|
||||
val paramValues: MutableList<String> = ArrayList()
|
||||
@@ -130,6 +130,10 @@ class VersatileProjectSyncClient(
|
||||
paramKeys.add("password")
|
||||
paramValues.add(newPassword)
|
||||
}
|
||||
if (newArchivedTs != null) {
|
||||
paramKeys.add("archived_ts")
|
||||
paramValues.add(newArchivedTs.toString())
|
||||
}
|
||||
|
||||
var target: String
|
||||
var username: String? = null
|
||||
|
||||
@@ -5,9 +5,11 @@ fun evalMath(expression: String): Double {
|
||||
var result = 0.0
|
||||
var db: SQLiteDatabase? = null
|
||||
try {
|
||||
// Force floating point division by replacing / with * 1.0 /
|
||||
val forcedRealExpr = expression.replace("/", "* 1.0 /")
|
||||
// Opens a temporary, in-memory system database block
|
||||
db = SQLiteDatabase.create(null)
|
||||
val cursor = db.rawQuery("SELECT ($expression);", null)
|
||||
val cursor = db.rawQuery("SELECT ($forcedRealExpr);", null)
|
||||
if (cursor.moveToFirst()) {
|
||||
result = cursor.getDouble(0)
|
||||
}
|
||||
|
||||
@@ -2,240 +2,240 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">Cowspent</string>
|
||||
<!-- Actions -->
|
||||
<string name="action_new_bill">New bill</string>
|
||||
<string name="action_add_project">Add project</string>
|
||||
<string name="action_save">Save</string>
|
||||
<string name="action_edit">Edit</string>
|
||||
<string name="action_share">Share</string>
|
||||
<string name="action_search">Search</string>
|
||||
<string name="action_delete">Delete</string>
|
||||
<string name="action_archive">Archive</string>
|
||||
<string name="action_unarchive">Unarchive</string>
|
||||
<string name="action_export">Export</string>
|
||||
<string name="action_stats">Stats</string>
|
||||
<string name="action_settle">Settle</string>
|
||||
<string name="action_scan_qrcode">Scan QR Code</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
<string name="action_label_bills">Label missing categories</string>
|
||||
<string name="action_new_bill">Nuevo gasto</string>
|
||||
<string name="action_add_project">Agregar proyecto</string>
|
||||
<string name="action_save">Guardar</string>
|
||||
<string name="action_edit">Editar</string>
|
||||
<string name="action_share">Compartir</string>
|
||||
<string name="action_search">Buscar</string>
|
||||
<string name="action_delete">Borrar</string>
|
||||
<string name="action_archive">Archivar</string>
|
||||
<string name="action_unarchive">Desarchivar</string>
|
||||
<string name="action_export">Exportar</string>
|
||||
<string name="action_stats">Stadísticas</string>
|
||||
<string name="action_settle">Saldar</string>
|
||||
<string name="action_scan_qrcode">Escanear QR</string>
|
||||
<string name="action_settings">Configuraciones</string>
|
||||
<string name="action_label_bills">Categorías sin etiquetas</string>
|
||||
<string name="action_logout">Logout</string>
|
||||
<string name="action_connect">Connect</string>
|
||||
<string name="action_discard">Discard</string>
|
||||
<string name="action_members">Members</string>
|
||||
<string name="action_labels">Labels</string>
|
||||
<string name="action_currencies">Currencies</string>
|
||||
<string name="action_connect">Conectar</string>
|
||||
<string name="action_discard">Discartar</string>
|
||||
<string name="action_members">Miembros</string>
|
||||
<string name="action_labels">Etiquetas</string>
|
||||
<string name="action_currencies">Moneda</string>
|
||||
<!-- Titles -->
|
||||
<string name="title_stats">Statistics</string>
|
||||
<string name="title_edit_project">Edit project</string>
|
||||
<string name="title_label_bills">Label Bills</string>
|
||||
<string name="title_labels">Manage Labels</string>
|
||||
<string name="title_about">About</string>
|
||||
<string name="title_settle">Settle Project</string>
|
||||
<string name="title_share">Share Project</string>
|
||||
<string name="title_add_project">Add Project</string>
|
||||
<string name="title_add_category">Add Category</string>
|
||||
<string name="title_add_payment_mode">Add Payment Mode</string>
|
||||
<string name="title_account">Nextcloud Account</string>
|
||||
<string name="title_share_web">Web link</string>
|
||||
<string name="title_share_qr">Cowspent link</string>
|
||||
<string name="title_confirm">Are you sure?</string>
|
||||
<string name="title_stats">Estadísticas</string>
|
||||
<string name="title_edit_project">Editar Proyecto</string>
|
||||
<string name="title_label_bills">Etiquetar gastos</string>
|
||||
<string name="title_labels">Administrar etiquetas</string>
|
||||
<string name="title_about">Acerca de</string>
|
||||
<string name="title_settle">Saldar Proyecto</string>
|
||||
<string name="title_share">Compartir Proyecto</string>
|
||||
<string name="title_add_project">Agregar Proyecto</string>
|
||||
<string name="title_add_category">Agregar Categoría</string>
|
||||
<string name="title_add_payment_mode">Agregar Modo de Pago</string>
|
||||
<string name="title_account">Cuenta Nextcloud</string>
|
||||
<string name="title_share_web">Enlace Web</string>
|
||||
<string name="title_share_qr">Enlace Cowspent</string>
|
||||
<string name="title_confirm">Estás seguro?</string>
|
||||
<!-- Labels and Fields -->
|
||||
<string name="label_all_bills">All bills</string>
|
||||
<string name="label_categories">Categories</string>
|
||||
<string name="label_payment_modes">Payment Modes</string>
|
||||
<string name="label_name">Name</string>
|
||||
<string name="label_icon">Icon / Emoji</string>
|
||||
<string name="label_all_bills">Todos los gastos</string>
|
||||
<string name="label_categories">Categorias</string>
|
||||
<string name="label_payment_modes">Modos de Pago</string>
|
||||
<string name="label_name">Nombre</string>
|
||||
<string name="label_icon">Icono / Emoji</string>
|
||||
<string name="label_color">Color</string>
|
||||
<string name="label_weight">Weight</string>
|
||||
<string name="label_activated">Activated</string>
|
||||
<string name="label_password">Password</string>
|
||||
<string name="label_weight">Ponderación</string>
|
||||
<string name="label_activated">Activado</string>
|
||||
<string name="label_password">Contraseña</string>
|
||||
<string name="label_email">E-mail</string>
|
||||
<string name="label_url">Server address</string>
|
||||
<string name="label_username">Username</string>
|
||||
<string name="label_comment">Comment</string>
|
||||
<string name="label_what">What?</string>
|
||||
<string name="label_payer">Who paid?</string>
|
||||
<string name="label_owers">For whom?</string>
|
||||
<string name="label_repeat">Repeat every</string>
|
||||
<string name="label_mode">Mode</string>
|
||||
<string name="label_category">Category</string>
|
||||
<string name="label_project_id">Project ID/name</string>
|
||||
<string name="label_project_title">Project title</string>
|
||||
<string name="label_use_sso">Use Nextcloud App Account</string>
|
||||
<string name="label_url">Dirección del Servidor</string>
|
||||
<string name="label_username">Nombre de Usuario</string>
|
||||
<string name="label_comment">Comentario</string>
|
||||
<string name="label_what">Qué?</string>
|
||||
<string name="label_payer">Quién paga?</string>
|
||||
<string name="label_owers">Para Quién?</string>
|
||||
<string name="label_repeat">Repetir cada</string>
|
||||
<string name="label_mode">Modo</string>
|
||||
<string name="label_category">Categoría</string>
|
||||
<string name="label_project_id">ID Proyecto/Nombre</string>
|
||||
<string name="label_project_title">Título Proyecto</string>
|
||||
<string name="label_use_sso">Usar cuenta de Nextcloud App</string>
|
||||
<!-- Dialogs and Messages -->
|
||||
<string name="dialog_unsaved_changes_title">Unsaved changes</string>
|
||||
<string name="dialog_unsaved_changes_msg">Save changes before leaving?</string>
|
||||
<string name="dialog_confirm_remove_project_msg">The remote project will not be deleted.</string>
|
||||
<string name="dialog_sync_error_title">Sync error</string>
|
||||
<string name="dialog_sync_error_msg">Sync failed for %1$s.\n\n%2$s</string>
|
||||
<string name="dialog_balanced_msg">Expenses are already balanced.</string>
|
||||
<string name="msg_project_added">Project %1$s added</string>
|
||||
<string name="msg_bill_labeled_done">All bills labeled</string>
|
||||
<string name="msg_no_suggestions">No suggestions</string>
|
||||
<string name="msg_auth_warning">Requires Cospend v0.3.4+.</string>
|
||||
<string name="msg_link_copied">Link copied to clipboard</string>
|
||||
<string name="msg_share_qr">Scan QR code or share the link to join.</string>
|
||||
<string name="msg_share_web">Link for web browser access.</string>
|
||||
<string name="msg_share_qr_warn">Share this link with a Cowspent user.</string>
|
||||
<string name="msg_settle_intro">Settlement for %1$s:</string>
|
||||
<string name="msg_settle_sentence">%1$s owes %3$.2f to %2$s</string>
|
||||
<string name="msg_stats_intro">Stats for %1$s:</string>
|
||||
<string name="msg_stats_header">Member (Paid | Spent | Balance)</string>
|
||||
<string name="msg_logged_in_as">Logged in as %1$s</string>
|
||||
<string name="dialog_unsaved_changes_title">Cambios sin guardar</string>
|
||||
<string name="dialog_unsaved_changes_msg">Guardar cambios antes de salir?</string>
|
||||
<string name="dialog_confirm_remove_project_msg">El proyecto remoto no será eliminado.</string>
|
||||
<string name="dialog_sync_error_title">Error de sincronización</string>
|
||||
<string name="dialog_sync_error_msg">Falla de sincronización para %1$s.\n\n%2$s</string>
|
||||
<string name="dialog_balanced_msg">Gastos ya balanceados.</string>
|
||||
<string name="msg_project_added">Agregado proyecto %1$s</string>
|
||||
<string name="msg_bill_labeled_done">Todos los gastos etiquetados</string>
|
||||
<string name="msg_no_suggestions">Sin sugerencias</string>
|
||||
<string name="msg_auth_warning">Se requiere Cospend v0.3.4+.</string>
|
||||
<string name="msg_link_copied">Vínculo copiado al portapapeles</string>
|
||||
<string name="msg_share_qr">Escanea el QR o comparte el vínculo para unirte.</string>
|
||||
<string name="msg_share_web">Vínculo para acceso mediante navegador web.</string>
|
||||
<string name="msg_share_qr_warn">Comparte este vínculo con otro usuario de Cowspent.</string>
|
||||
<string name="msg_settle_intro">Liquidación para %1$s:</string>
|
||||
<string name="msg_settle_sentence">%1$s debe %3$.2f a %2$s</string>
|
||||
<string name="msg_stats_intro">Estadísticas para %1$s:</string>
|
||||
<string name="msg_stats_header">Miembro (Pagado | Gastado | Balance)</string>
|
||||
<string name="msg_logged_in_as">Conectado como %1$s</string>
|
||||
<!-- Errors -->
|
||||
<string name="error_generic">Error</string>
|
||||
<string name="error_loading">Loading</string>
|
||||
<string name="error_no_projects">No projects found</string>
|
||||
<string name="error_no_members">No members found</string>
|
||||
<string name="error_no_bills">No bills found</string>
|
||||
<string name="error_no_member">At least one member required</string>
|
||||
<string name="error_maintenance_mode">Server is in maintenance mode</string>
|
||||
<string name="error_loading">Cargando</string>
|
||||
<string name="error_no_projects">No se encontraron proyectos</string>
|
||||
<string name="error_no_members">No se encontraron miembros</string>
|
||||
<string name="error_no_bills">No se encontraron gastos</string>
|
||||
<string name="error_no_member">Se requiere al menos un miembro</string>
|
||||
<string name="error_maintenance_mode">Servidor en modo mantenimiento</string>
|
||||
<string name="error_400">400 Bad request</string>
|
||||
<string name="error_401">401 Unauthorized</string>
|
||||
<string name="error_403">403 Forbidden</string>
|
||||
<string name="error_404">404 Not Found</string>
|
||||
<string name="error_sync">Sync failed: %1$s</string>
|
||||
<string name="error_invalid_login">Invalid login: %1$s</string>
|
||||
<string name="error_auth">Wrong username or password</string>
|
||||
<string name="error_json">Invalid server response</string>
|
||||
<string name="error_req_failed">Request failed</string>
|
||||
<string name="error_invalid_email">Invalid e-mail</string>
|
||||
<string name="error_invalid_project_id">Invalid project ID</string>
|
||||
<string name="error_invalid_project_name">Invalid project title</string>
|
||||
<string name="error_invalid_bill_name">Invalid bill name</string>
|
||||
<string name="error_invalid_bill_date">Invalid bill date</string>
|
||||
<string name="error_invalid_bill_payer">Payer required</string>
|
||||
<string name="error_invalid_bill_owers">Owers required</string>
|
||||
<string name="error_no_network">No network connection</string>
|
||||
<string name="error_server">Server error</string>
|
||||
<string name="error_io">Server connection broken</string>
|
||||
<string name="error_share_impossible">Cannot share this project</string>
|
||||
<string name="error_sync">Fallo en sicronización: %1$s</string>
|
||||
<string name="error_invalid_login">Inicio sesión inválida: %1$s</string>
|
||||
<string name="error_auth">Usuario o contraseña incorrectos</string>
|
||||
<string name="error_json">Respuesta inválida del servidor</string>
|
||||
<string name="error_req_failed">Falla en solicitud</string>
|
||||
<string name="error_invalid_email">E-mail inválido</string>
|
||||
<string name="error_invalid_project_id">ID de proyecto inválido</string>
|
||||
<string name="error_invalid_project_name">Título de proyecto inválido</string>
|
||||
<string name="error_invalid_bill_name">Nombre de gasto inválido</string>
|
||||
<string name="error_invalid_bill_date">Fecha de gasto inválido</string>
|
||||
<string name="error_invalid_bill_payer">Se requiere pagador</string>
|
||||
<string name="error_invalid_bill_owers">Se requiere deudor</string>
|
||||
<string name="error_no_network">Sin conexión de red</string>
|
||||
<string name="error_server">Error de servidor</string>
|
||||
<string name="error_io">Conexión de servidor interrumpida</string>
|
||||
<string name="error_share_impossible">No se puede compartir este proyecto</string>
|
||||
<!-- Drawer / Common UI -->
|
||||
<string name="drawer_no_account">Connect to Nextcloud account</string>
|
||||
<string name="drawer_last_sync">Last sync: %1$02d:%2$02d</string>
|
||||
<string name="simple_cancel">Cancel</string>
|
||||
<string name="drawer_no_account">Conectar a cuenta Nextcloud</string>
|
||||
<string name="drawer_last_sync">Ultima sincronización: %1$02d:%2$02d</string>
|
||||
<string name="simple_cancel">Cancelar</string>
|
||||
<string name="simple_ok" tools:ignore="ButtonCase,Typos">Ok</string>
|
||||
<string name="simple_yes">Yes</string>
|
||||
<string name="simple_yes">Si</string>
|
||||
<string name="simple_no">No</string>
|
||||
<string name="simple_close">Close</string>
|
||||
<string name="simple_close">Cerrar</string>
|
||||
<!-- Settings -->
|
||||
<string name="settings_appearance">Appearance</string>
|
||||
<string name="settings_network">Network</string>
|
||||
<string name="settings_other">Other</string>
|
||||
<string name="settings_night_mode">Theme</string>
|
||||
<string name="settings_offline_mode">Offline mode</string>
|
||||
<string name="settings_offline_mode_summary">Only sync manually.</string>
|
||||
<string name="settings_color_custom">Custom color</string>
|
||||
<string name="settings_color_mode">Color Selection</string>
|
||||
<string name="settings_show_archived">Show archived projects</string>
|
||||
<string name="settings_beta_features">Beta Features</string>
|
||||
<string name="settings_beta_features_summary">Enable experimental features. Use at your own risk.</string>
|
||||
<string name="settings_url_warn_http">WARNING: \"http\" is unsafe. Use \"https\".</string>
|
||||
<string name="settings_colorpicker_title">Choose Color</string>
|
||||
<string name="pref_value_color_system">System</string>
|
||||
<string name="settings_appearance">Apariencia</string>
|
||||
<string name="settings_network">Red</string>
|
||||
<string name="settings_other">Otros</string>
|
||||
<string name="settings_night_mode">Tema</string>
|
||||
<string name="settings_offline_mode">Modo fuera de línea</string>
|
||||
<string name="settings_offline_mode_summary">Solo sincronización manual.</string>
|
||||
<string name="settings_color_custom">Color personalizado</string>
|
||||
<string name="settings_color_mode">Selección de color</string>
|
||||
<string name="settings_show_archived">Mostrar proyectos archivados</string>
|
||||
<string name="settings_beta_features">Funciones beta</string>
|
||||
<string name="settings_beta_features_summary">Habilitar funciones beta. Usar bajo tu propia responsabilidad.</string>
|
||||
<string name="settings_url_warn_http">ADVERTENCIA: \"http\" es inseguro. Usa \"https\".</string>
|
||||
<string name="settings_colorpicker_title">Elegir Color</string>
|
||||
<string name="pref_value_color_system">Sistema</string>
|
||||
<string name="pref_value_color_server">Nextcloud</string>
|
||||
<string name="pref_value_color_manual">Manual</string>
|
||||
<string name="pref_value_theme_light">Light</string>
|
||||
<string name="pref_value_theme_dark">Dark</string>
|
||||
<string name="pref_value_theme_system">Follow system</string>
|
||||
<string name="pref_value_theme_light">Claro</string>
|
||||
<string name="pref_value_theme_dark">Oscuro</string>
|
||||
<string name="pref_value_theme_system">Seguir sistema</string>
|
||||
<!-- Constants (Do not translate) -->
|
||||
<!-- Enums and Lists -->
|
||||
<string name="repeat_no">No repeat</string>
|
||||
<string name="repeat_day">Daily</string>
|
||||
<string name="repeat_week">Weekly</string>
|
||||
<string name="repeat_fortnight">Fortnightly</string>
|
||||
<string name="repeat_month">Monthly</string>
|
||||
<string name="repeat_year">Yearly</string>
|
||||
<string name="payment_mode_none">None</string>
|
||||
<string name="payment_mode_all">All</string>
|
||||
<string name="payment_mode_credit_card">Credit card</string>
|
||||
<string name="payment_mode_cash">Cash</string>
|
||||
<string name="payment_mode_check">Check</string>
|
||||
<string name="payment_mode_online">Online</string>
|
||||
<string name="payment_mode_transfer">Transfer</string>
|
||||
<string name="category_none">None</string>
|
||||
<string name="category_all">All</string>
|
||||
<string name="category_all_except_reimbursement">All except reimbursement</string>
|
||||
<string name="category_groceries">Grocery</string>
|
||||
<string name="category_leisure">Bar/Party</string>
|
||||
<string name="category_rent">Rent</string>
|
||||
<string name="category_bills">Bill</string>
|
||||
<string name="category_excursion">Excursion/Culture</string>
|
||||
<string name="category_health">Health</string>
|
||||
<string name="category_shopping">Shopping</string>
|
||||
<string name="category_reimbursement">Reimbursement</string>
|
||||
<string name="category_restaurant">Restaurant</string>
|
||||
<string name="category_accomodation">Accommodation</string>
|
||||
<string name="category_transport">Transport</string>
|
||||
<string name="category_sport">Sport</string>
|
||||
<string name="repeat_no">No repetir</string>
|
||||
<string name="repeat_day">Diario</string>
|
||||
<string name="repeat_week">Semanal</string>
|
||||
<string name="repeat_fortnight">Quincenal</string>
|
||||
<string name="repeat_month">Mensual</string>
|
||||
<string name="repeat_year">Anual</string>
|
||||
<string name="payment_mode_none">Ninguno</string>
|
||||
<string name="payment_mode_all">Todos</string>
|
||||
<string name="payment_mode_credit_card">Tarjeta de crédito</string>
|
||||
<string name="payment_mode_cash">Efectivo</string>
|
||||
<string name="payment_mode_check">Cheque</string>
|
||||
<string name="payment_mode_online">En línea</string>
|
||||
<string name="payment_mode_transfer">Transferencia</string>
|
||||
<string name="category_none">Ninguna</string>
|
||||
<string name="category_all">Todas</string>
|
||||
<string name="category_all_except_reimbursement">Todas excepto reembolsos</string>
|
||||
<string name="category_groceries">Supermercado</string>
|
||||
<string name="category_leisure">Bar/Fiesta</string>
|
||||
<string name="category_rent">Renta</string>
|
||||
<string name="category_bills">Facturas/Servicios</string>
|
||||
<string name="category_excursion">Excursión/Cultura</string>
|
||||
<string name="category_health">Salud</string>
|
||||
<string name="category_shopping">Compras</string>
|
||||
<string name="category_reimbursement">Reintegro</string>
|
||||
<string name="category_restaurant">Restaurante</string>
|
||||
<string name="category_accomodation">Alojamiento</string>
|
||||
<string name="category_transport">Transporte</string>
|
||||
<string name="category_sport">Deportes</string>
|
||||
<!-- Project specific -->
|
||||
<string name="new_project_action">What</string>
|
||||
<string name="new_project_where">Where</string>
|
||||
<string name="where_local">Local only</string>
|
||||
<string name="new_project_action">Qué</string>
|
||||
<string name="new_project_where">Cuando</string>
|
||||
<string name="where_local">Solo local</string>
|
||||
<string name="where_cospend">Cospend</string>
|
||||
<string name="where_ihatemoney">IHateMoney</string>
|
||||
<string name="todo_join">Join existing project</string>
|
||||
<string name="todo_create">Create new project</string>
|
||||
<string name="import_tooltip">Import from file</string>
|
||||
<string name="choose_account_project_dialog_title">Choose project</string>
|
||||
<string name="choose_account_project_dialog_impossible">No projects found on this account.</string>
|
||||
<string name="choose_project_management_action">Project</string>
|
||||
<string name="project_added_success">Project added successfully.</string>
|
||||
<string name="no_projects_text">You have no projects yet.</string>
|
||||
<string name="configure_account_choice">Configure Nextcloud account</string>
|
||||
<string name="add_project_choice">Add project manually</string>
|
||||
<string name="no_members_text">No members in this project.</string>
|
||||
<string name="no_bills_text">No bills found.</string>
|
||||
<string name="member_already_exists">Member already exists.</string>
|
||||
<string name="activity_dialog_title">Project: %1$s</string>
|
||||
<string name="remove_project_confirmation">Project %1$s removed.</string>
|
||||
<string name="file_saved_success">File saved: %1$s</string>
|
||||
<string name="import_error_header">Import failed at row %d</string>
|
||||
<string name="import_error_date">Invalid date format at row %d</string>
|
||||
<string name="import_error_owers">Invalid owers at row %d</string>
|
||||
<string name="add_member_dialog_title">Add Member</string>
|
||||
<string name="edit_member_dialog_title">Edit Member</string>
|
||||
<string name="member_edit_delete">Delete</string>
|
||||
<string name="project_edition_no_change">No changes to save.</string>
|
||||
<string name="todo_join">Unirse a proyecto existente</string>
|
||||
<string name="todo_create">Crear nuevo proyecto</string>
|
||||
<string name="import_tooltip">Importar desde archivo</string>
|
||||
<string name="choose_account_project_dialog_title">Elegir projecto</string>
|
||||
<string name="choose_account_project_dialog_impossible">No se encotraron proyectos en esta cuenta.</string>
|
||||
<string name="choose_project_management_action">Proyecto</string>
|
||||
<string name="project_added_success">Proyecto añadido correctamente.</string>
|
||||
<string name="no_projects_text">Aún no tienes proyectos.</string>
|
||||
<string name="configure_account_choice">Configurar cuenta Nextcloud</string>
|
||||
<string name="add_project_choice">Añadir proyecto manualmente</string>
|
||||
<string name="no_members_text">No hay miembros en este proyecto.</string>
|
||||
<string name="no_bills_text">No se encontraron gastos.</string>
|
||||
<string name="member_already_exists">Miembro ya existe.</string>
|
||||
<string name="activity_dialog_title">Proyecto: %1$s</string>
|
||||
<string name="remove_project_confirmation">Proyecto %1$s eliminado.</string>
|
||||
<string name="file_saved_success">Archivo guardado: %1$s</string>
|
||||
<string name="import_error_header">Importación fallida en línea %d</string>
|
||||
<string name="import_error_date">Formato de fecha inválido en línea %d</string>
|
||||
<string name="import_error_owers">Deudores inválidos en línea %d</string>
|
||||
<string name="add_member_dialog_title">Agregar Miembro</string>
|
||||
<string name="edit_member_dialog_title">Editar Miembro</string>
|
||||
<string name="member_edit_delete">Eliminar</string>
|
||||
<string name="project_edition_no_change">Sin cambios para guardar.</string>
|
||||
<!-- Settlement -->
|
||||
<string name="center_none">None (Optimal)</string>
|
||||
<string name="settle_who">Who pays</string>
|
||||
<string name="settle_to_whom">To whom</string>
|
||||
<string name="settle_how_much">Amount</string>
|
||||
<string name="simple_settle_share">Share</string>
|
||||
<string name="simple_create_bills">Create bills</string>
|
||||
<string name="settle_bill_what">Settlement</string>
|
||||
<string name="center_none">Ninguno (Optimo)</string>
|
||||
<string name="settle_who">Quién paga</string>
|
||||
<string name="settle_to_whom">A quién</string>
|
||||
<string name="settle_how_much">Monto</string>
|
||||
<string name="simple_settle_share">Compartir</string>
|
||||
<string name="simple_create_bills">Crear gastos</string>
|
||||
<string name="settle_bill_what">Liquidación</string>
|
||||
<!-- Currencies -->
|
||||
<string name="currency_dialog_title">Choose Currency (%s)</string>
|
||||
<string name="setting_none">None</string>
|
||||
<string name="setting_all">All</string>
|
||||
<string name="currency_saved_success">Currency settings saved.</string>
|
||||
<string name="main_currency">Main Currency</string>
|
||||
<string name="currency_dialog_title">Elegir moneda (%s)</string>
|
||||
<string name="setting_none">Ninguna</string>
|
||||
<string name="setting_all">Todas</string>
|
||||
<string name="currency_saved_success">Configuración de moneda guardada.</string>
|
||||
<string name="main_currency">Moneda principal</string>
|
||||
<!-- Statistics -->
|
||||
<string name="label_bills_suggested">Suggested Categories</string>
|
||||
<string name="label_bills_skip">Skip</string>
|
||||
<string name="stats_date_min">From</string>
|
||||
<string name="stats_date_max">To</string>
|
||||
<string name="stats_who">Member</string>
|
||||
<string name="stats_paid">Paid</string>
|
||||
<string name="stats_spent">Spent</string>
|
||||
<string name="label_bills_suggested">Categorías sugeridas</string>
|
||||
<string name="label_bills_skip">Saltear</string>
|
||||
<string name="stats_date_min">Desde</string>
|
||||
<string name="stats_date_max">Hasta</string>
|
||||
<string name="stats_who">Miembro</string>
|
||||
<string name="stats_paid">Pagado</string>
|
||||
<string name="stats_spent">Gastado</string>
|
||||
<string name="stats_balance">Balance</string>
|
||||
<string name="total">Total: %1$s</string>
|
||||
<!-- Errors Extra -->
|
||||
<string name="error_project_connect_check">Connection failed: %1$s</string>
|
||||
<string name="error_create_remote_project_helper">Creation failed: %1$s</string>
|
||||
<string name="error_edit_remote_project_helper">Error updating remote project: %1$s</string>
|
||||
<string name="remote_project_operation_no_network">Network unavailable for remote operation.</string>
|
||||
<string name="error_scanning_bill_qr_code">Failed to parse QR code.</string>
|
||||
<string name="error_token_mismatch">Authentication token mismatch. Please log in again.</string>
|
||||
<string name="insufficient_access_level">You don\'t have permission to perform this action.</string>
|
||||
<string name="delete_label_confirmation_title">Delete Label</string>
|
||||
<string name="delete_label_confirmation_message">Are you sure you want to delete this label?</string>
|
||||
<string name="error_project_connect_check">Conexión fallida: %1$s</string>
|
||||
<string name="error_create_remote_project_helper">Creación fallida: %1$s</string>
|
||||
<string name="error_edit_remote_project_helper">Error actualizado proyecto remoto: %1$s</string>
|
||||
<string name="remote_project_operation_no_network">Red no disponible para operación remota.</string>
|
||||
<string name="error_scanning_bill_qr_code">No se pudo interpretar el código QR.</string>
|
||||
<string name="error_token_mismatch">El token de autenticación no coincide. Inicia sesión de nuevo.</string>
|
||||
<string name="insufficient_access_level">No tienes permiso para realizar esta acción.</string>
|
||||
<string name="delete_label_confirmation_title">Eliminar Etiqueta</string>
|
||||
<string name="delete_label_confirmation_message">Seguro quieres eliminar la etiqueta?</string>
|
||||
<!-- About -->
|
||||
<string name="about_version">Version %1$s</string>
|
||||
<string name="about_maintainer_title">Maintainer</string>
|
||||
<string name="about_license_title">License</string>
|
||||
<string name="about_source_title">Source code</string>
|
||||
<string name="about_version">Versión %1$s</string>
|
||||
<string name="about_maintainer_title">Responsable</string>
|
||||
<string name="about_license_title">Licencia</string>
|
||||
<string name="about_source_title">Código fuente</string>
|
||||
<!-- New constants for backward compatibility or shared use -->
|
||||
<string name="share_intent_title">Project %1$s</string>
|
||||
<string name="share_chooser_title">Share %1$s</string>
|
||||
<string name="share_intent_title">Proyecto %1$s</string>
|
||||
<string name="share_chooser_title">Compartir %1$s</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<string name="app_name">Kuh ausgegeben</string>
|
||||
|
||||
<string name="app_name">Cowspent</string>
|
||||
|
||||
<!-- Actions -->
|
||||
<string name="action_new_bill">Neue Rechnung</string>
|
||||
<string name="action_add_project">Projekt hinzufügen</string>
|
||||
@@ -10,38 +12,40 @@
|
||||
<string name="action_search">Suchen</string>
|
||||
<string name="action_delete">Löschen</string>
|
||||
<string name="action_archive">Archivieren</string>
|
||||
<string name="action_unarchive">Archivieren</string>
|
||||
<string name="action_unarchive">Reaktivieren</string>
|
||||
<string name="action_export">Exportieren</string>
|
||||
<string name="action_stats">Statistik</string>
|
||||
<string name="action_settle">Abrechnen</string>
|
||||
<string name="action_scan_qrcode">Scan QR Code</string>
|
||||
<string name="action_scan_qrcode">QR Code einscannen</string>
|
||||
<string name="action_settings">Einstellungen</string>
|
||||
<string name="action_label_bills">Fehlende Kategorien</string>
|
||||
<string name="action_logout">Abmelden</string>
|
||||
<string name="action_connect">Verbinden</string>
|
||||
<string name="action_discard">Verwerfen</string>
|
||||
<string name="action_members">Mitglieder</string>
|
||||
<string name="action_labels">Etiketten</string>
|
||||
<string name="action_labels">Labels</string>
|
||||
<string name="action_currencies">Währungen</string>
|
||||
|
||||
<!-- Titles -->
|
||||
<string name="title_stats">Statistiken</string>
|
||||
<string name="title_edit_project">Projekt bearbeiten</string>
|
||||
<string name="title_label_bills">Etikett Rechnungen</string>
|
||||
<string name="title_label_bills">Rechnungen kennzeichnen</string>
|
||||
<string name="title_labels">Labels verwalten</string>
|
||||
<string name="title_about">Über</string>
|
||||
<string name="title_settle">Projekt regeln</string>
|
||||
<string name="title_settle">Projekt abrechnen</string>
|
||||
<string name="title_share">Projekt teilen</string>
|
||||
<string name="title_add_project">Projekt hinzufügen</string>
|
||||
<string name="title_add_category">Neue Kategorie</string>
|
||||
<string name="title_add_payment_mode">Zahlungsmodus hinzufügen</string>
|
||||
<string name="title_account">Nächstes Cloud-Konto</string>
|
||||
<string name="title_add_payment_mode">Zahlungsmethode hinzufügen</string>
|
||||
<string name="title_account">Nextloud-Konto</string>
|
||||
<string name="title_share_web">Weblink</string>
|
||||
<string name="title_share_qr">Cowspent link</string>
|
||||
<string name="title_confirm">Bist du sicher?</string>
|
||||
|
||||
<!-- Labels and Fields -->
|
||||
<string name="label_all_bills">Alle Rechnungen</string>
|
||||
<string name="label_categories">Kategorien</string>
|
||||
<string name="label_payment_modes">Zahlungsarten</string>
|
||||
<string name="label_payment_modes">Zahlungsmethoden</string>
|
||||
<string name="label_name">Name</string>
|
||||
<string name="label_icon">Icon / Emoji</string>
|
||||
<string name="label_color">Farbe</string>
|
||||
@@ -61,26 +65,28 @@
|
||||
<string name="label_project_id">Projekt-ID/Name</string>
|
||||
<string name="label_project_title">Projekttitel</string>
|
||||
<string name="label_use_sso">Nextcloud App-Konto verwenden</string>
|
||||
|
||||
<!-- Dialogs and Messages -->
|
||||
<string name="dialog_unsaved_changes_title">Ungespeicherte Änderungen</string>
|
||||
<string name="dialog_unsaved_changes_msg">Änderungen vor dem Verlassen speichern?</string>
|
||||
<string name="dialog_confirm_remove_project_msg">Das entfernte Projekt wird nicht gelöscht.</string>
|
||||
<string name="dialog_confirm_remove_project_msg">Das Remote-Projekt wird nicht gelöscht.</string>
|
||||
<string name="dialog_sync_error_title">Sync-Fehler</string>
|
||||
<string name="dialog_sync_error_msg">Synchronisation fehlgeschlagen für %1$s.\n\n%2$s</string>
|
||||
<string name="dialog_balanced_msg">Die Ausgaben sind bereits ausgeglichen.</string>
|
||||
<string name="msg_project_added">Projekt %1$s hinzugefügt</string>
|
||||
<string name="msg_bill_labeled_done">Alle Rechnungen markiert</string>
|
||||
<string name="msg_bill_labeled_done">Alle Rechnungen kategorisiert</string>
|
||||
<string name="msg_no_suggestions">Keine Vorschläge</string>
|
||||
<string name="msg_auth_warning">Benötigt Cospend v0.3.4+.</string>
|
||||
<string name="msg_link_copied">Link in Zwischenablage kopiert</string>
|
||||
<string name="msg_share_qr">Scannen Sie QR-Code oder teilen Sie den Link, um beizutreten.</string>
|
||||
<string name="msg_share_web">Link für den Zugriff auf Web-Browser.</string>
|
||||
<string name="msg_share_qr_warn">Teilen Sie diesen Link mit einem Cowspent Benutzer.</string>
|
||||
<string name="msg_share_qr">Scanne den QR-Code oder teile den Link, um beizutreten.</string>
|
||||
<string name="msg_share_web">Link für den Zugriff per Web-Browser.</string>
|
||||
<string name="msg_share_qr_warn">Teile diesen Link mit einem Cowspent Benutzer.</string>
|
||||
<string name="msg_settle_intro">Abrechnung für %1$s:</string>
|
||||
<string name="msg_settle_sentence">%1$s schuldet %3$.2f %2$s</string>
|
||||
<string name="msg_settle_sentence">%1$s schuldet %3$.2f an %2$s</string>
|
||||
<string name="msg_stats_intro">Statistiken für %1$s:</string>
|
||||
<string name="msg_stats_header">Mitglied (Paid | Ausgaben | Guthaben)</string>
|
||||
<string name="msg_stats_header">Mitglied (Gezahlt | Ausgegeben | Saldo)</string>
|
||||
<string name="msg_logged_in_as">Angemeldet als %1$s</string>
|
||||
|
||||
<!-- Errors -->
|
||||
<string name="error_generic">Fehler</string>
|
||||
<string name="error_loading">Lädt</string>
|
||||
@@ -104,11 +110,12 @@
|
||||
<string name="error_invalid_bill_name">Ungültiger Rechnungsname</string>
|
||||
<string name="error_invalid_bill_date">Ungültiges Rechnungsdatum</string>
|
||||
<string name="error_invalid_bill_payer">Zahler erforderlich</string>
|
||||
<string name="error_invalid_bill_owers">Eigene erforderlich</string>
|
||||
<string name="error_invalid_bill_owers">Schuldner erforderlich</string>
|
||||
<string name="error_no_network">Keine Netzwerkverbindung</string>
|
||||
<string name="error_server">Serverfehler</string>
|
||||
<string name="error_io">Serververbindung defekt</string>
|
||||
<string name="error_io">Serververbindung getrennt</string>
|
||||
<string name="error_share_impossible">Dieses Projekt kann nicht geteilt werden</string>
|
||||
|
||||
<!-- Drawer / Common UI -->
|
||||
<string name="drawer_no_account">Mit Nextcloud Konto verbinden</string>
|
||||
<string name="drawer_last_sync">Letzter Sync: %1$02d:%2$02d</string>
|
||||
@@ -117,6 +124,7 @@
|
||||
<string name="simple_yes">Ja</string>
|
||||
<string name="simple_no">Nein</string>
|
||||
<string name="simple_close">Schließen</string>
|
||||
|
||||
<!-- Settings -->
|
||||
<string name="settings_appearance">Erscheinung</string>
|
||||
<string name="settings_network">Netzwerk</string>
|
||||
@@ -129,20 +137,21 @@
|
||||
<string name="settings_show_archived">Archivierte Projekte anzeigen</string>
|
||||
<string name="settings_beta_features">Beta-Funktionen</string>
|
||||
<string name="settings_beta_features_summary">Experimentelle Funktionen aktivieren. Benutzung auf eigene Gefahr.</string>
|
||||
<string name="settings_url_warn_http">WARNUNG: \"http\" ist unsicher. Verwenden Sie \"https\".</string>
|
||||
<string name="settings_url_warn_http">WARNUNG: \"http\" ist unsicher. Verwende \"https\".</string>
|
||||
<string name="settings_colorpicker_title">Farbe wählen</string>
|
||||
<string name="pref_value_color_system">System</string>
|
||||
<string name="pref_value_color_server">Nächste Cloud</string>
|
||||
<string name="pref_value_color_server">Nextcloud</string>
|
||||
<string name="pref_value_color_manual">Manuell</string>
|
||||
<string name="pref_value_theme_light">Hell</string>
|
||||
<string name="pref_value_theme_dark">Dunkel</string>
|
||||
<string name="pref_value_theme_system">System folgen</string>
|
||||
|
||||
<!-- Constants (Do not translate) -->
|
||||
<!-- Enums and Lists -->
|
||||
<string name="repeat_no">Keine Wiederholung</string>
|
||||
<string name="repeat_day">Täglich</string>
|
||||
<string name="repeat_week">Wöchentlich</string>
|
||||
<string name="repeat_fortnight">Vierzehn</string>
|
||||
<string name="repeat_fortnight">Vierzehntägig</string>
|
||||
<string name="repeat_month">Monatlich</string>
|
||||
<string name="repeat_year">Jährlich</string>
|
||||
<string name="payment_mode_none">Keine</string>
|
||||
@@ -154,33 +163,34 @@
|
||||
<string name="payment_mode_transfer">Überweisung</string>
|
||||
<string name="category_none">Keine</string>
|
||||
<string name="category_all">Alle</string>
|
||||
<string name="category_all_except_reimbursement">Alle außer Rückerstattung</string>
|
||||
<string name="category_groceries">Fleischgerichte</string>
|
||||
<string name="category_all_except_reimbursement">Alle außer Erstattung</string>
|
||||
<string name="category_groceries">Lebensmittel</string>
|
||||
<string name="category_leisure">Bar/Party</string>
|
||||
<string name="category_rent">Miete</string>
|
||||
<string name="category_bills">Abrechnung</string>
|
||||
<string name="category_excursion">Ausflug/Kultur</string>
|
||||
<string name="category_health">Gesundheit</string>
|
||||
<string name="category_shopping">Einkaufen</string>
|
||||
<string name="category_reimbursement">Rückzahlung</string>
|
||||
<string name="category_reimbursement">Erstattung</string>
|
||||
<string name="category_restaurant">Restaurant</string>
|
||||
<string name="category_accomodation">Unterkunft</string>
|
||||
<string name="category_transport">Transport</string>
|
||||
<string name="category_sport">Sport</string>
|
||||
|
||||
<!-- Project specific -->
|
||||
<string name="new_project_action">Was</string>
|
||||
<string name="new_project_where">Wo</string>
|
||||
<string name="where_local">Nur lokal</string>
|
||||
<string name="where_cospend">Ko-Ausgaben</string>
|
||||
<string name="where_cospend">Cospend</string>
|
||||
<string name="where_ihatemoney">IHateMoney</string>
|
||||
<string name="todo_join">Bestehendes Projekt beitreten</string>
|
||||
<string name="todo_join">Bestehendem Projekt beitreten</string>
|
||||
<string name="todo_create">Neues Projekt erstellen</string>
|
||||
<string name="import_tooltip">Aus Datei importieren</string>
|
||||
<string name="choose_account_project_dialog_title">Projekt auswählen</string>
|
||||
<string name="choose_account_project_dialog_impossible">Keine Projekte auf diesem Konto gefunden.</string>
|
||||
<string name="choose_project_management_action">Projekt</string>
|
||||
<string name="project_added_success">Projekt erfolgreich hinzugefügt.</string>
|
||||
<string name="no_projects_text">Sie haben noch keine Projekte.</string>
|
||||
<string name="no_projects_text">Du hast noch keine Projekte.</string>
|
||||
<string name="configure_account_choice">Nextcloud-Konto konfigurieren</string>
|
||||
<string name="add_project_choice">Projekt manuell hinzufügen</string>
|
||||
<string name="no_members_text">Keine Mitglieder in diesem Projekt.</string>
|
||||
@@ -191,11 +201,12 @@
|
||||
<string name="file_saved_success">Datei gespeichert: %1$s</string>
|
||||
<string name="import_error_header">Import fehlgeschlagen in Zeile %d</string>
|
||||
<string name="import_error_date">Ungültiges Datumsformat in Zeile %d</string>
|
||||
<string name="import_error_owers">Ungültige Eigener in Zeile %d</string>
|
||||
<string name="import_error_owers">Ungültige Schuldner in Zeile %d</string>
|
||||
<string name="add_member_dialog_title">Mitglied hinzufügen</string>
|
||||
<string name="edit_member_dialog_title">Mitglied bearbeiten</string>
|
||||
<string name="member_edit_delete">Löschen</string>
|
||||
<string name="project_edition_no_change">Keine zu speichernden Änderungen.</string>
|
||||
|
||||
<!-- Settlement -->
|
||||
<string name="center_none">Keine (optimal)</string>
|
||||
<string name="settle_who">Wer zahlt</string>
|
||||
@@ -204,12 +215,14 @@
|
||||
<string name="simple_settle_share">Teilen</string>
|
||||
<string name="simple_create_bills">Rechnungen erstellen</string>
|
||||
<string name="settle_bill_what">Abrechnung</string>
|
||||
|
||||
<!-- Currencies -->
|
||||
<string name="currency_dialog_title">Währung wählen (%s)</string>
|
||||
<string name="setting_none">Keine</string>
|
||||
<string name="setting_all">Alle</string>
|
||||
<string name="currency_saved_success">Währungseinstellungen gespeichert.</string>
|
||||
<string name="main_currency">Hauptwährung</string>
|
||||
|
||||
<!-- Statistics -->
|
||||
<string name="label_bills_suggested">Empfohlene Kategorien</string>
|
||||
<string name="label_bills_skip">Überspringen</string>
|
||||
@@ -220,21 +233,24 @@
|
||||
<string name="stats_spent">Ausgegeben</string>
|
||||
<string name="stats_balance">Saldo</string>
|
||||
<string name="total">Gesamt: %1$s</string>
|
||||
|
||||
<!-- Errors Extra -->
|
||||
<string name="error_project_connect_check">Verbindung fehlgeschlagen: %1$s</string>
|
||||
<string name="error_create_remote_project_helper">Erstellung fehlgeschlagen: %1$s</string>
|
||||
<string name="error_edit_remote_project_helper">Fehler beim Aktualisieren des fernen Projekts: %1$s</string>
|
||||
<string name="error_edit_remote_project_helper">Fehler beim Aktualisieren des Remote-Projekts: %1$s</string>
|
||||
<string name="remote_project_operation_no_network">Netzwerk nicht verfügbar für Remote Operation.</string>
|
||||
<string name="error_scanning_bill_qr_code">Fehler beim Analysieren des QR-Codes.</string>
|
||||
<string name="error_token_mismatch">Authentifizierungstoken stimmen nicht überein. Bitte melden Sie sich erneut an.</string>
|
||||
<string name="insufficient_access_level">Sie haben keine Berechtigung, um diese Aktion durchzuführen.</string>
|
||||
<string name="delete_label_confirmation_title">Label löschen</string>
|
||||
<string name="delete_label_confirmation_message">Sind Sie sicher, dass Sie diese Bezeichnung löschen möchten?</string>
|
||||
<string name="error_token_mismatch">Authentifizierungstoken stimmen nicht überein. Bitte melde dich erneut an.</string>
|
||||
<string name="insufficient_access_level">Du hast keine Berechtigung, um diese Aktion durchzuführen.</string>
|
||||
<string name="delete_label_confirmation_title">Kategorie löschen</string>
|
||||
<string name="delete_label_confirmation_message">Bist du sicher, dass du diese Kategorie löschen möchtest?</string>
|
||||
|
||||
<!-- About -->
|
||||
<string name="about_version">Version %1$s</string>
|
||||
<string name="about_maintainer_title">Betreuer</string>
|
||||
<string name="about_license_title">Lizenz</string>
|
||||
<string name="about_source_title">Quellcode</string>
|
||||
|
||||
<!-- New constants for backward compatibility or shared use -->
|
||||
<string name="share_intent_title">Projekt %1$s</string>
|
||||
<string name="share_chooser_title">Teilen %1$s</string>
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip
|
||||
networkTimeout=10000
|
||||
retries=0
|
||||
retryBackOffMs=500
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
# Copyright © 2015 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
# gradlew start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
@@ -29,7 +29,7 @@
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
# ksh gradlew
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
@@ -57,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
@@ -114,7 +114,6 @@ case "$( uname )" in #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -172,7 +171,6 @@ fi
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
@@ -212,8 +210,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
|
||||
Vendored
+12
-24
@@ -19,12 +19,12 @@
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem gradlew startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
@rem Set local scope for the variables, and ensure extensions are enabled
|
||||
setlocal EnableExtensions
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@@ -51,7 +51,7 @@ echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
"%COMSPEC%" /c exit 1
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
@@ -65,30 +65,18 @@ echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
"%COMSPEC%" /c exit 1
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
@rem Execute gradlew
|
||||
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
|
||||
@rem which allows us to clear the local environment before executing the java command
|
||||
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
:exitWithErrorLevel
|
||||
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
|
||||
"%COMSPEC%" /c exit %ERRORLEVEL%
|
||||
|
||||
@@ -6,6 +6,9 @@ pluginManagement {
|
||||
maven { url = 'https://jitpack.io' }
|
||||
}
|
||||
}
|
||||
plugins {
|
||||
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
|
||||
Reference in New Issue
Block a user