Rename package to com.wbrawner.twigs.android and bump dependency versions

This commit is contained in:
William Brawner 2024-03-14 21:28:27 -06:00
parent 455eed0872
commit b5f8573f75
35 changed files with 275 additions and 162 deletions

View file

@ -23,6 +23,7 @@ try {
}
android {
namespace = "com.wbrawner.twigs.android"
compileSdk = libs.versions.maxSdk.get().toInt()
defaultConfig {
applicationId = "com.wbrawner.twigs"
@ -52,11 +53,11 @@ android {
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = project.ext["jvm"] as JavaVersion
targetCompatibility = project.ext["jvm"] as JavaVersion
}
kotlinOptions {
jvmTarget = "1.8"
jvmTarget = (project.ext["jvm"] as JavaVersion).majorVersion
}
buildFeatures {
compose = true

View file

@ -1,4 +1,4 @@
package com.wbrawner.budget
package com.wbrawner.twigs
import androidx.test.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4

View file

@ -1,4 +1,8 @@
package com.wbrawner.budget;
package com.wbrawner.twigs;
import static junit.framework.Assert.assertNull;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;
import android.arch.persistence.db.SupportSQLiteDatabase;
import android.arch.persistence.db.framework.FrameworkSQLiteOpenHelperFactory;
@ -8,9 +12,9 @@ import android.database.Cursor;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.wbrawner.budget.data.BudgetDatabase;
import com.wbrawner.budget.data.migrations.MIGRATION_1_2;
import com.wbrawner.budget.data.migrations.MIGRATION_2_3;
import com.wbrawner.twigs.data.BudgetDatabase;
import com.wbrawner.twigs.data.migrations.MIGRATION_1_2;
import com.wbrawner.twigs.data.migrations.MIGRATION_2_3;
import org.junit.Rule;
import org.junit.Test;
@ -18,10 +22,6 @@ import org.junit.runner.RunWith;
import java.io.IOException;
import static junit.framework.Assert.assertNull;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;
@RunWith(AndroidJUnit4.class)
public class MigrationTests {
private static final String TEST_DB = "migration-test";

View file

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.wbrawner.budget">
xmlns:tools="http://schemas.android.com/tools">
<application
android:name=".TwigsApplication"

View file

@ -1,4 +1,4 @@
package com.wbrawner.budget
package com.wbrawner.twigs.android
import android.util.Log
import com.wbrawner.twigs.shared.ErrorHandler

View file

@ -1,4 +1,4 @@
package com.wbrawner.budget
package com.wbrawner.twigs.android
import android.app.Application
import dagger.hilt.android.HiltAndroidApp

View file

@ -1,4 +1,4 @@
package com.wbrawner.budget.ui
package com.wbrawner.twigs.android.ui
import android.os.Bundle
import androidx.activity.compose.BackHandler
@ -27,15 +27,15 @@ import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.wbrawner.budget.R
import com.wbrawner.budget.ui.auth.LoginScreen
import com.wbrawner.budget.ui.base.TwigsApp
import com.wbrawner.budget.ui.category.CategoriesScreen
import com.wbrawner.budget.ui.category.CategoryDetailsScreen
import com.wbrawner.budget.ui.recurringtransaction.RecurringTransactionDetailsScreen
import com.wbrawner.budget.ui.recurringtransaction.RecurringTransactionsScreen
import com.wbrawner.budget.ui.transaction.TransactionDetailsScreen
import com.wbrawner.budget.ui.transaction.TransactionsScreen
import com.wbrawner.twigs.android.R
import com.wbrawner.twigs.android.ui.auth.LoginScreen
import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.twigs.android.ui.category.CategoriesScreen
import com.wbrawner.twigs.android.ui.category.CategoryDetailsScreen
import com.wbrawner.twigs.android.ui.recurringtransaction.RecurringTransactionDetailsScreen
import com.wbrawner.twigs.android.ui.recurringtransaction.RecurringTransactionsScreen
import com.wbrawner.twigs.android.ui.transaction.TransactionDetailsScreen
import com.wbrawner.twigs.android.ui.transaction.TransactionsScreen
import com.wbrawner.twigs.shared.Action
import com.wbrawner.twigs.shared.Route
import com.wbrawner.twigs.shared.Store
@ -43,6 +43,7 @@ import com.wbrawner.twigs.shared.budget.BudgetAction
import com.wbrawner.twigs.shared.category.CategoryAction
import com.wbrawner.twigs.shared.recurringtransaction.RecurringTransactionAction
import com.wbrawner.twigs.shared.transaction.TransactionAction
import com.wbrawner.twigs.ui.AuthViewModel
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import javax.inject.Inject

View file

@ -1,4 +1,4 @@
package com.wbrawner.budget.ui
package com.wbrawner.twigs.android.ui
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.clickable
@ -41,9 +41,9 @@ import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.wbrawner.budget.ui.base.TwigsColors
import com.wbrawner.budget.ui.base.TwigsTheme
import com.wbrawner.budget.ui.transaction.toCurrencyString
import com.wbrawner.twigs.android.ui.base.TwigsColors
import com.wbrawner.twigs.android.ui.base.TwigsTheme
import com.wbrawner.twigs.android.ui.transaction.toCurrencyString
import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.budget.BudgetAction
import kotlinx.datetime.Month

View file

@ -1,4 +1,4 @@
package com.wbrawner.budget.ui
package com.wbrawner.twigs.android.ui
import android.content.Context
import android.text.Spannable
@ -9,7 +9,7 @@ import android.widget.EditText
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.wbrawner.budget.R
import com.wbrawner.twigs.android.R
import java.text.NumberFormat
import java.util.*

View file

@ -1,4 +1,4 @@
package com.wbrawner.budget.ui
package com.wbrawner.twigs.ui
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel

View file

@ -1,4 +1,4 @@
package com.wbrawner.budget.ui.auth
package com.wbrawner.twigs.android.ui.auth
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.animation.AnimatedVisibility
@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardActions
@ -22,9 +23,9 @@ import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
@ -49,12 +50,12 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.tooling.preview.Devices
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.wbrawner.budget.R
import com.wbrawner.budget.ui.AuthViewModel
import com.wbrawner.budget.ui.base.TwigsApp
import com.wbrawner.twigs.android.R
import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.twigs.shared.Effect
import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.user.ConfigAction
import com.wbrawner.twigs.ui.AuthViewModel
@ExperimentalAnimationApi
@Composable
@ -130,7 +131,8 @@ fun LoginForm(
modifier = Modifier
.fillMaxSize()
.verticalScroll(scrollState)
.padding(16.dp),
.padding(16.dp)
.imePadding(),
verticalArrangement = spacedBy(8.dp, Alignment.CenterVertically),
horizontalAlignment = Alignment.CenterHorizontally,
) {
@ -142,7 +144,7 @@ fun LoginForm(
if (error.isNotBlank()) {
Text(text = error, color = MaterialTheme.colorScheme.error)
}
TextField(
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.focusRequester(serverInput)
@ -172,7 +174,7 @@ fun LoginForm(
}),
maxLines = 1
)
TextField(
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.focusRequester(usernameInput)
@ -203,7 +205,7 @@ fun LoginForm(
}),
maxLines = 1
)
TextField(
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.focusRequester(passwordInput)

View file

@ -1,4 +1,4 @@
package com.wbrawner.budget.ui.base
package com.wbrawner.twigs.android.ui.base
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.Composable

View file

@ -1,4 +1,4 @@
package com.wbrawner.budget.ui.base
package com.wbrawner.twigs.android.ui.base
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
@ -10,7 +10,7 @@ import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import com.wbrawner.budget.R
import com.wbrawner.twigs.android.R
private val LightColors = lightColorScheme(
primary = md_theme_light_primary,

View file

@ -1,15 +1,28 @@
package com.wbrawner.budget.ui.category
package com.wbrawner.twigs.android.ui.category
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
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.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material3.*
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
@ -21,15 +34,14 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.wbrawner.budget.ui.TwigsScaffold
import com.wbrawner.budget.ui.base.TwigsApp
import com.wbrawner.budget.ui.transaction.toCurrencyString
import com.wbrawner.twigs.android.ui.TwigsScaffold
import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.twigs.android.ui.transaction.toCurrencyString
import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.category.Category
import com.wbrawner.twigs.shared.category.CategoryAction
import com.wbrawner.twigs.shared.category.groupByType
import com.wbrawner.twigs.shared.recurringtransaction.capitalizedName
import java.util.*
import kotlin.math.abs
import kotlin.math.max

View file

@ -1,17 +1,25 @@
package com.wbrawner.budget.ui.category
package com.wbrawner.twigs.android.ui.category
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.*
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
@ -22,12 +30,12 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.wbrawner.budget.ui.TwigsScaffold
import com.wbrawner.budget.ui.base.TwigsApp
import com.wbrawner.budget.ui.transaction.TransactionFormDialog
import com.wbrawner.budget.ui.transaction.TransactionListItem
import com.wbrawner.budget.ui.transaction.toCurrencyString
import com.wbrawner.budget.ui.util.format
import com.wbrawner.twigs.android.ui.TwigsScaffold
import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.twigs.android.ui.transaction.TransactionFormDialog
import com.wbrawner.twigs.android.ui.transaction.TransactionListItem
import com.wbrawner.twigs.android.ui.transaction.toCurrencyString
import com.wbrawner.twigs.android.ui.util.format
import com.wbrawner.twigs.shared.Action
import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.category.Category

View file

@ -1,16 +1,35 @@
package com.wbrawner.budget.ui.category
package com.wbrawner.twigs.android.ui.category
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.material3.Button
import androidx.compose.material3.Checkbox
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
@ -28,12 +47,11 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import com.wbrawner.budget.ui.base.TwigsApp
import com.wbrawner.budget.ui.transaction.toDecimalString
import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.twigs.android.ui.transaction.toDecimalString
import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.category.Category
import com.wbrawner.twigs.shared.category.CategoryAction
import java.util.*
@OptIn(ExperimentalComposeUiApi::class)
@Composable

View file

@ -1,16 +1,27 @@
package com.wbrawner.budget.ui.recurringtransaction
package com.wbrawner.twigs.android.ui.recurringtransaction
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.*
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
@ -20,10 +31,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.wbrawner.budget.ui.TwigsScaffold
import com.wbrawner.budget.ui.base.TwigsApp
import com.wbrawner.budget.ui.transaction.toCurrencyString
import com.wbrawner.budget.ui.util.format
import com.wbrawner.twigs.android.ui.TwigsScaffold
import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.twigs.android.ui.transaction.toCurrencyString
import com.wbrawner.twigs.android.ui.util.format
import com.wbrawner.twigs.shared.Action
import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.budget.Budget

View file

@ -1,16 +1,37 @@
package com.wbrawner.budget.ui.recurringtransaction
package com.wbrawner.twigs.android.ui.recurringtransaction
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.material3.Button
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
@ -28,10 +49,10 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import com.wbrawner.budget.ui.base.TwigsApp
import com.wbrawner.budget.ui.transaction.toDecimalString
import com.wbrawner.budget.ui.util.DatePicker
import com.wbrawner.budget.ui.util.FrequencyPicker
import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.twigs.android.ui.transaction.toDecimalString
import com.wbrawner.twigs.android.ui.util.DatePicker
import com.wbrawner.twigs.android.ui.util.FrequencyPicker
import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.category.Category
import com.wbrawner.twigs.shared.recurringtransaction.Frequency
@ -40,7 +61,6 @@ import com.wbrawner.twigs.shared.recurringtransaction.RecurringTransactionAction
import com.wbrawner.twigs.shared.recurringtransaction.Time
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import java.util.*
@OptIn(ExperimentalComposeUiApi::class)
@Composable

View file

@ -1,10 +1,16 @@
package com.wbrawner.budget.ui.recurringtransaction
package com.wbrawner.twigs.android.ui.recurringtransaction
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.CircularProgressIndicator
@ -21,9 +27,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.wbrawner.budget.ui.TwigsScaffold
import com.wbrawner.budget.ui.base.TwigsApp
import com.wbrawner.budget.ui.transaction.toCurrencyString
import com.wbrawner.twigs.android.ui.TwigsScaffold
import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.twigs.android.ui.transaction.toCurrencyString
import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.recurringtransaction.Frequency
import com.wbrawner.twigs.shared.recurringtransaction.RecurringTransaction

View file

@ -1,17 +1,30 @@
package com.wbrawner.budget.ui.transaction
package com.wbrawner.twigs.android.ui.transaction
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.*
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
@ -21,9 +34,9 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.wbrawner.budget.ui.TwigsScaffold
import com.wbrawner.budget.ui.base.TwigsApp
import com.wbrawner.budget.ui.util.formatWithTime
import com.wbrawner.twigs.android.ui.TwigsScaffold
import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.twigs.android.ui.util.formatWithTime
import com.wbrawner.twigs.shared.Action
import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.budget.Budget

View file

@ -1,16 +1,37 @@
package com.wbrawner.budget.ui.transaction
package com.wbrawner.twigs.android.ui.transaction
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.material3.Button
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
@ -28,16 +49,15 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import com.wbrawner.budget.ui.base.TwigsApp
import com.wbrawner.budget.ui.util.DatePicker
import com.wbrawner.budget.ui.util.TimePicker
import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.twigs.android.ui.util.DatePicker
import com.wbrawner.twigs.android.ui.util.TimePicker
import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.category.Category
import com.wbrawner.twigs.shared.transaction.Transaction
import com.wbrawner.twigs.shared.transaction.TransactionAction
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import java.util.*
@OptIn(ExperimentalComposeUiApi::class)
@Composable

View file

@ -1,12 +1,18 @@
package com.wbrawner.budget.ui.transaction
package com.wbrawner.twigs.android.ui.transaction
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.CornerSize
@ -23,9 +29,9 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.wbrawner.budget.ui.TwigsScaffold
import com.wbrawner.budget.ui.base.TwigsApp
import com.wbrawner.budget.ui.util.format
import com.wbrawner.twigs.android.ui.TwigsScaffold
import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.twigs.android.ui.util.format
import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.transaction.Transaction
import com.wbrawner.twigs.shared.transaction.TransactionAction

View file

@ -1,4 +1,4 @@
package com.wbrawner.budget.ui.util
package com.wbrawner.twigs.android.ui.util
import android.content.Context
import android.content.ContextWrapper
@ -19,7 +19,7 @@ import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalContext
import androidx.fragment.app.FragmentManager
import com.google.android.material.datepicker.MaterialDatePicker
import com.wbrawner.budget.R
import com.wbrawner.twigs.android.R
import kotlinx.datetime.Instant
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone

View file

@ -1,4 +1,4 @@
package com.wbrawner.budget.ui.util
package com.wbrawner.twigs.android.ui.util
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy

View file

@ -1,4 +1,4 @@
package com.wbrawner.budget.ui.util
package com.wbrawner.twigs.android.ui.util
import android.app.TimePickerDialog
import android.content.Context

View file

@ -6,7 +6,7 @@
app:startDestination="@id/overviewFragment">
<fragment
android:id="@+id/categoryListFragment"
android:name="com.wbrawner.budget.ui.categories.CategoryListFragment"
android:name="com.wbrawner.twigs.ui.categories.CategoryListFragment"
android:label="Categories"
tools:layout="@layout/fragment_transaction_list">
<action
@ -18,12 +18,12 @@
</fragment>
<fragment
android:id="@+id/transactionListFragment"
android:name="com.wbrawner.budget.ui.transactions.TransactionListFragment"
android:name="com.wbrawner.twigs.ui.transactions.TransactionListFragment"
android:label="@string/title_transactions"
tools:layout="@layout/fragment_transaction_list" />
<fragment
android:id="@+id/budgetsFragment"
android:name="com.wbrawner.budget.ui.budgets.BudgetListFragment"
android:name="com.wbrawner.twigs.ui.budgets.BudgetListFragment"
android:label="@string/title_budgets"
tools:layout="@layout/fragment_list_with_add_button">
<action
@ -32,31 +32,31 @@
</fragment>
<fragment
android:id="@+id/addEditBudget"
android:name="com.wbrawner.budget.ui.budgets.AddEditBudgetFragment"
android:name="com.wbrawner.twigs.ui.budgets.AddEditBudgetFragment"
android:label="@string/title_add_budget"
tools:layout="@layout/fragment_add_edit_budget" />
<fragment
android:id="@+id/overviewFragment"
android:name="com.wbrawner.budget.ui.overview.OverviewFragment"
android:name="com.wbrawner.twigs.ui.overview.OverviewFragment"
android:label="@string/title_overview"
tools:layout="@layout/fragment_overview" />
<fragment
android:id="@+id/profileFragment"
android:name="com.wbrawner.budget.ui.profile.ProfileFragment"
android:name="com.wbrawner.twigs.ui.profile.ProfileFragment"
android:label="@string/title_profile"
tools:layout="@layout/fragment_profile" />
<fragment
android:id="@+id/categoryFragment"
android:name="com.wbrawner.budget.ui.categories.CategoryDetailsFragment"
android:name="com.wbrawner.twigs.ui.categories.CategoryDetailsFragment"
android:label="fragment_category"
tools:layout="@layout/fragment_list_with_add_button" />
<activity
android:id="@+id/addEditTransactionActivity"
android:name="com.wbrawner.budget.ui.transactions.TransactionFormActivity"
android:name="com.wbrawner.twigs.ui.transactions.TransactionFormActivity"
android:label="AddEditTransactionActivity" />
<activity
android:id="@+id/addEditCategoryActivity"
android:name="com.wbrawner.budget.ui.categories.CategoryFormActivity"
android:name="com.wbrawner.twigs.ui.categories.CategoryFormActivity"
android:label="@string/title_add_category" >
<argument
android:name="categoryId"

View file

@ -9,8 +9,8 @@
tools:ignore="UnusedAttribute">
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="com.wbrawner.budget"
android:targetClass="com.wbrawner.budget.ui.transactions.TransactionFormActivity">
android:targetPackage="com.wbrawner.twigs"
android:targetClass="com.wbrawner.twigs.ui.transactions.TransactionFormActivity">
</intent>
</shortcut>
</shortcuts>

View file

@ -1,9 +1,8 @@
package com.wbrawner.budget
package com.wbrawner.twigs
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*

View file

@ -1,37 +1,36 @@
[versions]
androidx-core = "1.9.0"
androidx-core = "1.12.0"
androidx-appcompat = "1.6.1"
androidx-splash = "1.0.0"
androidx-splash = "1.0.1"
androidx-test-runner = "1.5.2"
androidx-test-orchestrator = "1.4.2"
compose = "1.3.3"
compose-compiler = "1.4.3"
compose-material = "1.3.1"
compose-material3 = "1.1.0-alpha07"
compose = "1.6.3"
compose-compiler = "1.5.10"
compose-material = "1.6.3"
compose-material3 = "1.2.1"
espresso = "3.5.1"
hilt-android = "2.44"
kotlin = "1.8.10"
kotlinx-serialization = "1.4.1"
kotlinx-coroutines = "1.6.4"
kotlinx-datetime = "0.4.0"
ktor = "2.2.3"
material = "1.8.0"
maxSdk = "33"
hilt-android = "2.49"
kotlin = "1.9.22"
kotlinx-serialization = "1.6.3"
kotlinx-coroutines = "1.8.0"
kotlinx-datetime = "0.5.0"
ktor = "2.3.4"
material = "1.11.0"
maxSdk = "34"
minSdk = "26"
navigation = "2.5.3"
okhttp = "4.2.2"
settings = "0.8.1"
versionCode = "1"
versionName = "1.0"
[libraries]
android-gradle = { module = "com.android.tools.build:gradle", version = "7.4.2" }
android-gradle = { module = "com.android.tools.build:gradle", version = "8.3.0" }
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "androidx-appcompat" }
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
androidx-splash = { module = "androidx.core:core-splashscreen", version.ref = "androidx-splash" }
androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidx-test-runner" }
androidx-test-orchestrator = { module = "androidx.test:orchestrator", version.ref = "androidx-test-orchestrator" }
compose-activity = { module = "androidx.activity:activity-compose", version = "1.6.1" }
compose-activity = { module = "androidx.activity:activity-compose", version = "1.8.2" }
compose-compiler = { module = "androidx.compose.compiler:compiler", version.ref = "compose-compiler" }
compose-material = { module = "androidx.compose.material:material", version.ref = "compose-material" }
compose-material-icons = { module = "androidx.compose.material:material-icons-extended", version.ref = "compose-material" }
compose-material3 = { module = "androidx.compose.material3:material3", version.ref = "compose-material3" }
@ -45,7 +44,7 @@ espresso = { module = "androidx.test.espresso:espresso-core", version.ref = "esp
hilt-android-core = { module = "com.google.dagger:hilt-android", version.ref = "hilt-android" }
hilt-android-kapt = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt-android" }
hilt-android-testing = { module = "com.google.dagger:hilt-android-testing", version.ref = "hilt-android" }
hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version = "1.0.0" }
hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version = "1.2.0" }
junit = { module = "junit:junit", version = "4.13.2" }
kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
@ -66,9 +65,7 @@ kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serializa
material = { module = "com.google.android.material:material", version.ref = "material" }
multiplatform-settings = { module = "com.russhwolf:multiplatform-settings-no-arg", version.ref = "settings" }
navigation-compose = { module = "androidx.navigation:navigation-compose", version = "navigation" }
navigation-fragment = { module = "androidx.navigation:navigation-fragment-ktx", version.ref = "navigation" }
navigation-ui = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "navigation" }
preference = { module = "androidx.preference:preference-ktx", version = "1.2.0" }
preference = { module = "androidx.preference:preference-ktx", version = "1.2.1" }
test-ext = { module = "androidx.test.ext:junit", version = "1.1.5" }
[bundles]

View file

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip

View file

@ -1,3 +1,2 @@
enableFeaturePreview("VERSION_CATALOGS")
rootProject.name = "Twigs"
include(":android", ":shared")

View file

@ -5,7 +5,7 @@ plugins {
}
kotlin {
android()
androidTarget()
listOf(iosArm64(), iosSimulatorArm64()).forEach {
it.binaries.framework {
baseName = "Twigs"
@ -56,15 +56,15 @@ android {
compileSdk = libs.versions.maxSdk.get().toInt()
defaultConfig {
minSdk = libs.versions.minSdk.get().toInt()
targetSdk = libs.versions.maxSdk.get().toInt()
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = project.ext["jvm"] as JavaVersion
targetCompatibility = project.ext["jvm"] as JavaVersion
}
buildTypes {
release {
consumerProguardFiles("proguard-rules.pro")
}
}
namespace = "com.wbrawner.twigs.android"
}

View file

@ -24,3 +24,5 @@
# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault
-dontwarn org.slf4j.impl.StaticLoggerBinder

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wbrawner.pihelper.shared">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View file

@ -7,6 +7,7 @@ import com.wbrawner.twigs.shared.transaction.Transaction
import com.wbrawner.twigs.shared.user.User
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@ -84,7 +85,7 @@ abstract class Reducer : CoroutineScope by CoroutineScope(Dispatchers.Main) {
class Store(
private val reducers: List<Reducer>,
initialState: State = State()
) : CoroutineScope by CoroutineScope(Dispatchers.Main) {
) : CoroutineScope by CoroutineScope(Dispatchers.IO) {
private val _state = MutableStateFlow(initialState)
val state: StateFlow<State> = _state
private val _effects = MutableSharedFlow<Effect>()
@ -112,7 +113,6 @@ class Store(
}
fun dispatch(action: Action) {
println(action)
launch {
var newState = _state.value
reducers.forEach {