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

View file

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

View file

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

View file

@ -1,4 +1,4 @@
package com.wbrawner.budget package com.wbrawner.twigs.android
import android.util.Log import android.util.Log
import com.wbrawner.twigs.shared.ErrorHandler 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 android.app.Application
import dagger.hilt.android.HiltAndroidApp 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 android.os.Bundle
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
@ -27,15 +27,15 @@ import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument import androidx.navigation.navArgument
import com.wbrawner.budget.R import com.wbrawner.twigs.android.R
import com.wbrawner.budget.ui.auth.LoginScreen import com.wbrawner.twigs.android.ui.auth.LoginScreen
import com.wbrawner.budget.ui.base.TwigsApp import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.budget.ui.category.CategoriesScreen import com.wbrawner.twigs.android.ui.category.CategoriesScreen
import com.wbrawner.budget.ui.category.CategoryDetailsScreen import com.wbrawner.twigs.android.ui.category.CategoryDetailsScreen
import com.wbrawner.budget.ui.recurringtransaction.RecurringTransactionDetailsScreen import com.wbrawner.twigs.android.ui.recurringtransaction.RecurringTransactionDetailsScreen
import com.wbrawner.budget.ui.recurringtransaction.RecurringTransactionsScreen import com.wbrawner.twigs.android.ui.recurringtransaction.RecurringTransactionsScreen
import com.wbrawner.budget.ui.transaction.TransactionDetailsScreen import com.wbrawner.twigs.android.ui.transaction.TransactionDetailsScreen
import com.wbrawner.budget.ui.transaction.TransactionsScreen import com.wbrawner.twigs.android.ui.transaction.TransactionsScreen
import com.wbrawner.twigs.shared.Action import com.wbrawner.twigs.shared.Action
import com.wbrawner.twigs.shared.Route import com.wbrawner.twigs.shared.Route
import com.wbrawner.twigs.shared.Store 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.category.CategoryAction
import com.wbrawner.twigs.shared.recurringtransaction.RecurringTransactionAction import com.wbrawner.twigs.shared.recurringtransaction.RecurringTransactionAction
import com.wbrawner.twigs.shared.transaction.TransactionAction import com.wbrawner.twigs.shared.transaction.TransactionAction
import com.wbrawner.twigs.ui.AuthViewModel
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject 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 android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.clickable 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.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.wbrawner.budget.ui.base.TwigsColors import com.wbrawner.twigs.android.ui.base.TwigsColors
import com.wbrawner.budget.ui.base.TwigsTheme import com.wbrawner.twigs.android.ui.base.TwigsTheme
import com.wbrawner.budget.ui.transaction.toCurrencyString import com.wbrawner.twigs.android.ui.transaction.toCurrencyString
import com.wbrawner.twigs.shared.Store import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.budget.BudgetAction import com.wbrawner.twigs.shared.budget.BudgetAction
import kotlinx.datetime.Month 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.content.Context
import android.text.Spannable import android.text.Spannable
@ -9,7 +9,7 @@ import android.widget.EditText
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.floatingactionbutton.FloatingActionButton import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.wbrawner.budget.R import com.wbrawner.twigs.android.R
import java.text.NumberFormat import java.text.NumberFormat
import java.util.* 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.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel 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 android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.animation.AnimatedVisibility 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.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardActions
@ -22,9 +23,9 @@ import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue 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.Devices
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.wbrawner.budget.R import com.wbrawner.twigs.android.R
import com.wbrawner.budget.ui.AuthViewModel import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.budget.ui.base.TwigsApp
import com.wbrawner.twigs.shared.Effect import com.wbrawner.twigs.shared.Effect
import com.wbrawner.twigs.shared.Store import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.user.ConfigAction import com.wbrawner.twigs.shared.user.ConfigAction
import com.wbrawner.twigs.ui.AuthViewModel
@ExperimentalAnimationApi @ExperimentalAnimationApi
@Composable @Composable
@ -130,7 +131,8 @@ fun LoginForm(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.verticalScroll(scrollState) .verticalScroll(scrollState)
.padding(16.dp), .padding(16.dp)
.imePadding(),
verticalArrangement = spacedBy(8.dp, Alignment.CenterVertically), verticalArrangement = spacedBy(8.dp, Alignment.CenterVertically),
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
) { ) {
@ -142,7 +144,7 @@ fun LoginForm(
if (error.isNotBlank()) { if (error.isNotBlank()) {
Text(text = error, color = MaterialTheme.colorScheme.error) Text(text = error, color = MaterialTheme.colorScheme.error)
} }
TextField( OutlinedTextField(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.focusRequester(serverInput) .focusRequester(serverInput)
@ -172,7 +174,7 @@ fun LoginForm(
}), }),
maxLines = 1 maxLines = 1
) )
TextField( OutlinedTextField(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.focusRequester(usernameInput) .focusRequester(usernameInput)
@ -203,7 +205,7 @@ fun LoginForm(
}), }),
maxLines = 1 maxLines = 1
) )
TextField( OutlinedTextField(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.focusRequester(passwordInput) .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.foundation.isSystemInDarkTheme
import androidx.compose.runtime.Composable 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.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme 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.FontFamily
import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import com.wbrawner.budget.R import com.wbrawner.twigs.android.R
private val LightColors = lightColorScheme( private val LightColors = lightColorScheme(
primary = md_theme_light_primary, 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_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.clickable 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.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.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.CircularProgressIndicator 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.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue 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.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.wbrawner.budget.ui.TwigsScaffold import com.wbrawner.twigs.android.ui.TwigsScaffold
import com.wbrawner.budget.ui.base.TwigsApp import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.budget.ui.transaction.toCurrencyString import com.wbrawner.twigs.android.ui.transaction.toCurrencyString
import com.wbrawner.twigs.shared.Store import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.category.Category import com.wbrawner.twigs.shared.category.Category
import com.wbrawner.twigs.shared.category.CategoryAction import com.wbrawner.twigs.shared.category.CategoryAction
import com.wbrawner.twigs.shared.category.groupByType import com.wbrawner.twigs.shared.category.groupByType
import com.wbrawner.twigs.shared.recurringtransaction.capitalizedName import com.wbrawner.twigs.shared.recurringtransaction.capitalizedName
import java.util.*
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.max 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_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.ExperimentalFoundationApi 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.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.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Edit 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.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue 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.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.wbrawner.budget.ui.TwigsScaffold import com.wbrawner.twigs.android.ui.TwigsScaffold
import com.wbrawner.budget.ui.base.TwigsApp import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.budget.ui.transaction.TransactionFormDialog import com.wbrawner.twigs.android.ui.transaction.TransactionFormDialog
import com.wbrawner.budget.ui.transaction.TransactionListItem import com.wbrawner.twigs.android.ui.transaction.TransactionListItem
import com.wbrawner.budget.ui.transaction.toCurrencyString import com.wbrawner.twigs.android.ui.transaction.toCurrencyString
import com.wbrawner.budget.ui.util.format import com.wbrawner.twigs.android.ui.util.format
import com.wbrawner.twigs.shared.Action import com.wbrawner.twigs.shared.Action
import com.wbrawner.twigs.shared.Store import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.category.Category 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_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.* import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy 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.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.* import androidx.compose.material3.Button
import androidx.compose.runtime.* 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.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier 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.unit.dp
import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import com.wbrawner.budget.ui.base.TwigsApp import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.budget.ui.transaction.toDecimalString import com.wbrawner.twigs.android.ui.transaction.toDecimalString
import com.wbrawner.twigs.shared.Store import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.category.Category import com.wbrawner.twigs.shared.category.Category
import com.wbrawner.twigs.shared.category.CategoryAction import com.wbrawner.twigs.shared.category.CategoryAction
import java.util.*
@OptIn(ExperimentalComposeUiApi::class) @OptIn(ExperimentalComposeUiApi::class)
@Composable @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_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.scrollable 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.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.foundation.rememberScrollState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Edit 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.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -20,10 +31,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.wbrawner.budget.ui.TwigsScaffold import com.wbrawner.twigs.android.ui.TwigsScaffold
import com.wbrawner.budget.ui.base.TwigsApp import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.budget.ui.transaction.toCurrencyString import com.wbrawner.twigs.android.ui.transaction.toCurrencyString
import com.wbrawner.budget.ui.util.format import com.wbrawner.twigs.android.ui.util.format
import com.wbrawner.twigs.shared.Action import com.wbrawner.twigs.shared.Action
import com.wbrawner.twigs.shared.Store import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.budget.Budget 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_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.* import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy 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.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.* import androidx.compose.material3.Button
import androidx.compose.runtime.* 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.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier 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.unit.dp
import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import com.wbrawner.budget.ui.base.TwigsApp import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.budget.ui.transaction.toDecimalString import com.wbrawner.twigs.android.ui.transaction.toDecimalString
import com.wbrawner.budget.ui.util.DatePicker import com.wbrawner.twigs.android.ui.util.DatePicker
import com.wbrawner.budget.ui.util.FrequencyPicker import com.wbrawner.twigs.android.ui.util.FrequencyPicker
import com.wbrawner.twigs.shared.Store import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.category.Category import com.wbrawner.twigs.shared.category.Category
import com.wbrawner.twigs.shared.recurringtransaction.Frequency 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 com.wbrawner.twigs.shared.recurringtransaction.Time
import kotlinx.datetime.Clock import kotlinx.datetime.Clock
import kotlinx.datetime.Instant import kotlinx.datetime.Instant
import java.util.*
@OptIn(ExperimentalComposeUiApi::class) @OptIn(ExperimentalComposeUiApi::class)
@Composable @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_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy 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.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.CircularProgressIndicator 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.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.wbrawner.budget.ui.TwigsScaffold import com.wbrawner.twigs.android.ui.TwigsScaffold
import com.wbrawner.budget.ui.base.TwigsApp import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.budget.ui.transaction.toCurrencyString import com.wbrawner.twigs.android.ui.transaction.toCurrencyString
import com.wbrawner.twigs.shared.Store import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.recurringtransaction.Frequency import com.wbrawner.twigs.shared.recurringtransaction.Frequency
import com.wbrawner.twigs.shared.recurringtransaction.RecurringTransaction 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_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.scrollable 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.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.foundation.rememberScrollState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Edit 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.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -21,9 +34,9 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.wbrawner.budget.ui.TwigsScaffold import com.wbrawner.twigs.android.ui.TwigsScaffold
import com.wbrawner.budget.ui.base.TwigsApp import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.budget.ui.util.formatWithTime import com.wbrawner.twigs.android.ui.util.formatWithTime
import com.wbrawner.twigs.shared.Action import com.wbrawner.twigs.shared.Action
import com.wbrawner.twigs.shared.Store import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.budget.Budget 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_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.* import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy 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.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.* import androidx.compose.material3.Button
import androidx.compose.runtime.* 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.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier 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.unit.dp
import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import com.wbrawner.budget.ui.base.TwigsApp import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.budget.ui.util.DatePicker import com.wbrawner.twigs.android.ui.util.DatePicker
import com.wbrawner.budget.ui.util.TimePicker import com.wbrawner.twigs.android.ui.util.TimePicker
import com.wbrawner.twigs.shared.Store import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.category.Category import com.wbrawner.twigs.shared.category.Category
import com.wbrawner.twigs.shared.transaction.Transaction import com.wbrawner.twigs.shared.transaction.Transaction
import com.wbrawner.twigs.shared.transaction.TransactionAction import com.wbrawner.twigs.shared.transaction.TransactionAction
import kotlinx.datetime.Clock import kotlinx.datetime.Clock
import kotlinx.datetime.Instant import kotlinx.datetime.Instant
import java.util.*
@OptIn(ExperimentalComposeUiApi::class) @OptIn(ExperimentalComposeUiApi::class)
@Composable @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_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy 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.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.CornerSize 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.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.wbrawner.budget.ui.TwigsScaffold import com.wbrawner.twigs.android.ui.TwigsScaffold
import com.wbrawner.budget.ui.base.TwigsApp import com.wbrawner.twigs.android.ui.base.TwigsApp
import com.wbrawner.budget.ui.util.format import com.wbrawner.twigs.android.ui.util.format
import com.wbrawner.twigs.shared.Store import com.wbrawner.twigs.shared.Store
import com.wbrawner.twigs.shared.transaction.Transaction import com.wbrawner.twigs.shared.transaction.Transaction
import com.wbrawner.twigs.shared.transaction.TransactionAction 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.Context
import android.content.ContextWrapper import android.content.ContextWrapper
@ -19,7 +19,7 @@ import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import com.google.android.material.datepicker.MaterialDatePicker 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.Instant
import kotlinx.datetime.LocalDateTime import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone 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.horizontalScroll
import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy 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.app.TimePickerDialog
import android.content.Context import android.content.Context

View file

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

View file

@ -9,8 +9,8 @@
tools:ignore="UnusedAttribute"> tools:ignore="UnusedAttribute">
<intent <intent
android:action="android.intent.action.VIEW" android:action="android.intent.action.VIEW"
android:targetPackage="com.wbrawner.budget" android:targetPackage="com.wbrawner.twigs"
android:targetClass="com.wbrawner.budget.ui.transactions.TransactionFormActivity"> android:targetClass="com.wbrawner.twigs.ui.transactions.TransactionFormActivity">
</intent> </intent>
</shortcut> </shortcut>
</shortcuts> </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.Test
import org.junit.Assert.*
/** /**
* Example local unit test, which will execute on the development machine (host). * Example local unit test, which will execute on the development machine (host).
* *

View file

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

View file

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists 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" rootProject.name = "Twigs"
include(":android", ":shared") include(":android", ":shared")

View file

@ -5,7 +5,7 @@ plugins {
} }
kotlin { kotlin {
android() androidTarget()
listOf(iosArm64(), iosSimulatorArm64()).forEach { listOf(iosArm64(), iosSimulatorArm64()).forEach {
it.binaries.framework { it.binaries.framework {
baseName = "Twigs" baseName = "Twigs"
@ -56,15 +56,15 @@ android {
compileSdk = libs.versions.maxSdk.get().toInt() compileSdk = libs.versions.maxSdk.get().toInt()
defaultConfig { defaultConfig {
minSdk = libs.versions.minSdk.get().toInt() minSdk = libs.versions.minSdk.get().toInt()
targetSdk = libs.versions.maxSdk.get().toInt()
} }
compileOptions { compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = project.ext["jvm"] as JavaVersion
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = project.ext["jvm"] as JavaVersion
} }
buildTypes { buildTypes {
release { release {
consumerProguardFiles("proguard-rules.pro") 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. # @Serializable and @Polymorphic are used at runtime for polymorphic serialization.
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault -keepattributes RuntimeVisibleAnnotations,AnnotationDefault
-dontwarn org.slf4j.impl.StaticLoggerBinder

View file

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

View file

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