From c0ca8c8b297827f36723d9e14bb181031927040c Mon Sep 17 00:00:00 2001 From: William Brawner Date: Tue, 26 Jan 2021 21:43:33 -0700 Subject: [PATCH] Use string identifiers instead of ints --- android/build.gradle | 2 +- .../com/wbrawner/budget/ui/SplashViewModel.kt | 21 +++++--- .../wbrawner/budget/ui/auth/LoginFragment.kt | 17 ++++++ .../ui/budgets/AddEditBudgetFragment.kt | 4 +- .../budget/ui/budgets/BudgetFormViewModel.kt | 12 ++--- .../budget/ui/budgets/BudgetListFragment.kt | 2 +- .../ui/categories/CategoryDetailsFragment.kt | 6 +-- .../ui/categories/CategoryDetailsViewModel.kt | 4 +- .../ui/categories/CategoryFormActivity.kt | 4 +- .../ui/categories/CategoryFormViewModel.kt | 10 ++-- .../ui/categories/CategoryListFragment.kt | 2 +- .../transactions/TransactionFormActivity.kt | 12 ++--- .../transactions/TransactionFormViewModel.kt | 8 +-- .../transactions/TransactionListFragment.kt | 6 +-- .../transactions/TransactionListViewModel.kt | 2 +- .../budget/lib/network/BaseUrlHelper.kt | 17 ------ .../budget/lib/network/Interceptors.kt | 34 ++++++++++++ .../budget/lib/network/NetworkModule.kt | 54 ++++--------------- ...BudgetApiService.kt => TwigsApiService.kt} | 41 +++++++------- .../lib/repository/NetworkBudgetRepository.kt | 16 +++--- .../repository/NetworkCategoryRepository.kt | 13 ++--- .../NetworkTransactionRepository.kt | 12 ++--- .../lib/repository/NetworkUserRepository.kt | 29 ++++++---- .../com/wbrawner/budget/common/Repository.kt | 2 +- .../com/wbrawner/budget/common/Session.kt | 11 ++++ .../wbrawner/budget/common/budget/Budget.kt | 2 +- .../budget/common/budget/BudgetRepository.kt | 8 +-- .../budget/common/category/Category.kt | 4 +- .../common/category/CategoryRepository.kt | 6 +-- .../budget/common/transaction/Transaction.kt | 8 +-- .../transaction/TransactionRepository.kt | 6 +-- .../com/wbrawner/budget/common/user/User.kt | 6 ++- .../budget/common/user/UserRepository.kt | 4 +- .../com/wbrawner/budget/common/util/Utils.kt | 11 ++++ 34 files changed, 217 insertions(+), 179 deletions(-) delete mode 100644 budgetlib/src/main/java/com/wbrawner/budget/lib/network/BaseUrlHelper.kt create mode 100644 budgetlib/src/main/java/com/wbrawner/budget/lib/network/Interceptors.kt rename budgetlib/src/main/java/com/wbrawner/budget/lib/network/{BudgetApiService.kt => TwigsApiService.kt} (68%) create mode 100644 common/src/main/java/com/wbrawner/budget/common/Session.kt create mode 100644 common/src/main/java/com/wbrawner/budget/common/util/Utils.kt diff --git a/android/build.gradle b/android/build.gradle index 900013c..9500f32 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -57,7 +57,7 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'androidx.core:core:1.3.2' + implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.media:media:1.2.1' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'com.google.android.material:material:1.2.1' diff --git a/android/src/main/java/com/wbrawner/budget/ui/SplashViewModel.kt b/android/src/main/java/com/wbrawner/budget/ui/SplashViewModel.kt index 30d4721..7d291d4 100644 --- a/android/src/main/java/com/wbrawner/budget/ui/SplashViewModel.kt +++ b/android/src/main/java/com/wbrawner/budget/ui/SplashViewModel.kt @@ -4,12 +4,15 @@ import android.content.SharedPreferences import androidx.core.content.edit import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import com.wbrawner.budget.* +import com.wbrawner.budget.AsyncState +import com.wbrawner.budget.AsyncViewModel import com.wbrawner.budget.common.budget.BudgetRepository import com.wbrawner.budget.common.user.UserRepository +import com.wbrawner.budget.launch import com.wbrawner.budget.lib.network.BaseUrlHelper import com.wbrawner.budget.lib.network.DEFAULT_URL import com.wbrawner.budget.lib.network.PREF_KEY_BASE_URL +import com.wbrawner.budget.postValue import javax.inject.Inject class SplashViewModel : ViewModel(), AsyncViewModel { @@ -28,7 +31,7 @@ class SplashViewModel : ViewModel(), AsyncViewModel { suspend fun checkForExistingCredentials() { if (baseUrlHelper.url == DEFAULT_URL) { - state.postValue(AuthenticationState.Unauthenticated) + state.postValue(AuthenticationState.Unauthenticated()) return } state.postValue(AsyncState.Success(AuthenticationState.Splash)) @@ -36,7 +39,7 @@ class SplashViewModel : ViewModel(), AsyncViewModel { userRepository.getProfile() AuthenticationState.Authenticated } catch (ignored: Exception) { - AuthenticationState.Unauthenticated + AuthenticationState.Unauthenticated() } state.postValue(authState) } @@ -53,9 +56,9 @@ class SplashViewModel : ViewModel(), AsyncViewModel { putString(PREF_KEY_BASE_URL, correctServer) } AuthenticationState.Authenticated - } catch (ignored: Exception) { + } catch (e: Exception) { // TODO: Return error message here - AuthenticationState.Unauthenticated + AuthenticationState.Unauthenticated(server, username, password, e.message) } } @@ -66,6 +69,12 @@ class SplashViewModel : ViewModel(), AsyncViewModel { sealed class AuthenticationState { object Splash : AuthenticationState() - object Unauthenticated : AuthenticationState() + class Unauthenticated( + val server: String? = null, + val username: String? = null, + val password: String? = null, + val errorMessage: String? = null + ) : AuthenticationState() + object Authenticated : AuthenticationState() } \ No newline at end of file diff --git a/android/src/main/java/com/wbrawner/budget/ui/auth/LoginFragment.kt b/android/src/main/java/com/wbrawner/budget/ui/auth/LoginFragment.kt index 81ef6d4..207cf08 100644 --- a/android/src/main/java/com/wbrawner/budget/ui/auth/LoginFragment.kt +++ b/android/src/main/java/com/wbrawner/budget/ui/auth/LoginFragment.kt @@ -1,15 +1,18 @@ package com.wbrawner.budget.ui.auth +import android.content.DialogInterface import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.lifecycle.Observer import com.wbrawner.budget.AsyncState import com.wbrawner.budget.R +import com.wbrawner.budget.ui.AuthenticationState import com.wbrawner.budget.ui.SplashViewModel import com.wbrawner.budget.ui.ensureNotEmpty import com.wbrawner.budget.ui.show @@ -40,6 +43,20 @@ class LoginFragment : Fragment() { password.error = "Invalid username/password" state.exception.printStackTrace() } + is AsyncState.Success -> { + if (state.data is AuthenticationState.Unauthenticated) { + server.setText(state.data.server ?: "") + username.setText(state.data.username ?: "") + password.setText(state.data.password ?: "") + state.data.errorMessage?.let { + AlertDialog.Builder(view.context) + .setTitle("Login Failed") + .setMessage(it) + .setPositiveButton(android.R.string.ok) { _: DialogInterface, _: Int -> } + .show() + } + } + } } }) password.setOnEditorActionListener { _, _, _ -> diff --git a/android/src/main/java/com/wbrawner/budget/ui/budgets/AddEditBudgetFragment.kt b/android/src/main/java/com/wbrawner/budget/ui/budgets/AddEditBudgetFragment.kt index 4b9bfcb..59b533b 100644 --- a/android/src/main/java/com/wbrawner/budget/ui/budgets/AddEditBudgetFragment.kt +++ b/android/src/main/java/com/wbrawner/budget/ui/budgets/AddEditBudgetFragment.kt @@ -19,7 +19,7 @@ import kotlinx.android.synthetic.main.fragment_add_edit_budget.* class AddEditBudgetFragment : Fragment() { private val viewModel: BudgetFormViewModel by viewModels() - var id: Long? = null + var id: String? = null var menu: Menu? = null override fun onCreate(savedInstanceState: Bundle?) { @@ -32,7 +32,7 @@ class AddEditBudgetFragment : Fragment() { .appComponent .inject(viewModel) super.onAttach(context) - viewModel.getBudget(arguments?.getLong(EXTRA_BUDGET_ID)) + viewModel.getBudget(arguments?.getString(EXTRA_BUDGET_ID)) } override fun onCreateView( diff --git a/android/src/main/java/com/wbrawner/budget/ui/budgets/BudgetFormViewModel.kt b/android/src/main/java/com/wbrawner/budget/ui/budgets/BudgetFormViewModel.kt index 80ad736..e2eef65 100644 --- a/android/src/main/java/com/wbrawner/budget/ui/budgets/BudgetFormViewModel.kt +++ b/android/src/main/java/com/wbrawner/budget/ui/budgets/BudgetFormViewModel.kt @@ -9,8 +9,8 @@ import com.wbrawner.budget.common.budget.Budget import com.wbrawner.budget.common.budget.BudgetRepository import com.wbrawner.budget.common.user.User import com.wbrawner.budget.common.user.UserRepository +import com.wbrawner.budget.common.util.randomId import kotlinx.coroutines.launch -import java.lang.Exception import javax.inject.Inject class BudgetFormViewModel : ViewModel() { @@ -25,13 +25,13 @@ class BudgetFormViewModel : ViewModel() { @Inject lateinit var userRepository: UserRepository - fun getBudget(id: Long? = null) { + fun getBudget(id: String? = null) { viewModelScope.launch { state.postValue(BudgetFormState.Loading) try { val budget = id?.let { budgetRepository.findById(it) - }?: Budget(name = "") + } ?: Budget(name = "") state.postValue(BudgetFormState.Success(budget)) } catch (e: Exception) { state.postValue(BudgetFormState.Failed(e)) @@ -46,7 +46,7 @@ class BudgetFormViewModel : ViewModel() { if (budget.id != null) { budgetRepository.update(budget) } else { - budgetRepository.create(budget) + budgetRepository.create(budget.copy(id = randomId())) } state.postValue(BudgetFormState.Exit) } catch (e: Exception) { @@ -55,11 +55,11 @@ class BudgetFormViewModel : ViewModel() { } } - fun deleteBudget(accountId: Long) { + fun deleteBudget(budgetId: String) { viewModelScope.launch { state.postValue(BudgetFormState.Loading) try { - budgetRepository.delete(accountId) + budgetRepository.delete(budgetId) state.postValue(BudgetFormState.Exit) } catch (e: Exception) { state.postValue(BudgetFormState.Failed(e)) diff --git a/android/src/main/java/com/wbrawner/budget/ui/budgets/BudgetListFragment.kt b/android/src/main/java/com/wbrawner/budget/ui/budgets/BudgetListFragment.kt index b4faf89..dbad962 100644 --- a/android/src/main/java/com/wbrawner/budget/ui/budgets/BudgetListFragment.kt +++ b/android/src/main/java/com/wbrawner/budget/ui/budgets/BudgetListFragment.kt @@ -58,7 +58,7 @@ class BudgetViewHolder(itemView: View, val navController: NavController) : Binda } itemView.setOnClickListener { val bundle = Bundle().apply { - putLong(EXTRA_BUDGET_ID, budget.id!!) + putString(EXTRA_BUDGET_ID, budget.id) } navController.navigate(R.id.categoryListFragment, bundle) } diff --git a/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryDetailsFragment.kt b/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryDetailsFragment.kt index 77b74e3..74c6d16 100644 --- a/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryDetailsFragment.kt +++ b/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryDetailsFragment.kt @@ -81,8 +81,8 @@ class CategoryDetailsFragment : Fragment() { } ?: run { val transactionsFragment = TransactionListFragment().apply { arguments = Bundle().apply { - putLong(EXTRA_BUDGET_ID, category.budgetId) - putLong(EXTRA_CATEGORY_ID, category.id!!) + putString(EXTRA_BUDGET_ID, category.budgetId) + putString(EXTRA_CATEGORY_ID, category.id) } } childFragmentManager.beginTransaction() @@ -100,7 +100,7 @@ class CategoryDetailsFragment : Fragment() { } } }) - viewModel.getCategory(arguments?.getLong(EXTRA_CATEGORY_ID)) + viewModel.getCategory(arguments?.getString(EXTRA_CATEGORY_ID)) } override fun onOptionsItemSelected(item: MenuItem): Boolean { diff --git a/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryDetailsViewModel.kt b/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryDetailsViewModel.kt index a9a826c..912d774 100644 --- a/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryDetailsViewModel.kt +++ b/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryDetailsViewModel.kt @@ -15,7 +15,7 @@ class CategoryDetailsViewModel : ViewModel(), AsyncViewModel { @Inject lateinit var categoryRepo: CategoryRepository - fun getCategory(id: Long? = null) { + fun getCategory(id: String? = null) { if (id == null) { state.postValue(AsyncState.Error("Invalid category ID")) return @@ -23,7 +23,7 @@ class CategoryDetailsViewModel : ViewModel(), AsyncViewModel { launch { val category = categoryRepo.findById(id) val multiplier = if (category.expense) -1 else 1 - val balance = categoryRepo.getBalance(category.id!!) * multiplier + val balance = categoryRepo.getBalance(id) * multiplier CategoryDetails( category, balance, diff --git a/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryFormActivity.kt b/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryFormActivity.kt index cac8da2..4bbcf70 100644 --- a/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryFormActivity.kt +++ b/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryFormActivity.kt @@ -23,7 +23,7 @@ import kotlinx.android.synthetic.main.activity_add_edit_category.* class CategoryFormActivity : AppCompatActivity() { val viewModel: CategoryFormViewModel by viewModels() - var id: Long? = null + var id: String? = null var menu: Menu? = null override fun onCreate(savedInstanceState: Bundle?) { @@ -65,7 +65,7 @@ class CategoryFormActivity : AppCompatActivity() { is AsyncState.Exit -> finish() } }) - viewModel.loadCategory(intent?.extras?.getLong(EXTRA_CATEGORY_ID)) + viewModel.loadCategory(intent?.extras?.getString(EXTRA_CATEGORY_ID)) } override fun onCreateOptionsMenu(menu: Menu?): Boolean { diff --git a/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryFormViewModel.kt b/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryFormViewModel.kt index 1973987..f6bc7fb 100644 --- a/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryFormViewModel.kt +++ b/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryFormViewModel.kt @@ -11,24 +11,24 @@ import com.wbrawner.budget.common.budget.Budget import com.wbrawner.budget.common.budget.BudgetRepository import com.wbrawner.budget.common.category.Category import com.wbrawner.budget.common.category.CategoryRepository +import com.wbrawner.budget.common.util.randomId import com.wbrawner.budget.launch import kotlinx.coroutines.launch import javax.inject.Inject class CategoryFormViewModel : ViewModel(), AsyncViewModel { override val state: MutableLiveData> = MutableLiveData(AsyncState.Loading) - @Inject lateinit var categoryRepository: CategoryRepository @Inject lateinit var budgetRepository: BudgetRepository - fun loadCategory(categoryId: Long? = null) { + fun loadCategory(categoryId: String? = null) { launch { val category = categoryId?.let { categoryRepository.findById(it) - } ?: Category(-1, title = "", amount = 0) + } ?: Category("", title = "", amount = 0) CategoryFormState( category, budgetRepository.findAll().toList() @@ -41,7 +41,7 @@ class CategoryFormViewModel : ViewModel(), AsyncViewModel { state.postValue(AsyncState.Loading) try { if (category.id == null) - categoryRepository.create(category) + categoryRepository.create(category.copy(id = randomId())) else categoryRepository.update(category) state.postValue(AsyncState.Exit) @@ -51,7 +51,7 @@ class CategoryFormViewModel : ViewModel(), AsyncViewModel { } } - fun deleteCategoryById(id: Long) { + fun deleteCategoryById(id: String) { viewModelScope.launch { state.postValue(AsyncState.Loading) try { diff --git a/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryListFragment.kt b/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryListFragment.kt index def826c..623173b 100644 --- a/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryListFragment.kt +++ b/android/src/main/java/com/wbrawner/budget/ui/categories/CategoryListFragment.kt @@ -82,7 +82,7 @@ class CategoryViewHolder( } itemView.setOnClickListener { val bundle = Bundle().apply { - putLong(EXTRA_CATEGORY_ID, category.id ?: -1) + putString(EXTRA_CATEGORY_ID, category.id) putString(EXTRA_CATEGORY_NAME, category.title) } navController.navigate(R.id.categoryFragment, bundle) diff --git a/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionFormActivity.kt b/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionFormActivity.kt index 6e2e55f..e37ca81 100644 --- a/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionFormActivity.kt +++ b/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionFormActivity.kt @@ -34,7 +34,7 @@ class TransactionFormActivity : AppCompatActivity(), CoroutineScope { override val coroutineContext: CoroutineContext = Dispatchers.Main private val viewModel: TransactionFormViewModel by viewModels() - var id: Long? = null + var id: String? = null var menu: Menu? = null var transaction: Transaction? = null @@ -112,7 +112,7 @@ class TransactionFormActivity : AppCompatActivity(), CoroutineScope { private suspend fun loadTransaction() { transaction = try { - viewModel.getTransaction(intent!!.extras!!.getLong(EXTRA_TRANSACTION_ID)) + viewModel.getTransaction(intent!!.extras!!.getString(EXTRA_TRANSACTION_ID)!!) } catch (e: Exception) { menu?.findItem(R.id.action_delete)?.isVisible = false val date = Date() @@ -148,8 +148,8 @@ class TransactionFormActivity : AppCompatActivity(), CoroutineScope { this@TransactionFormActivity, android.R.layout.simple_list_item_1 ) - adapter.add(Category(id = 0, title = getString(R.string.uncategorized), - amount = 0, budgetId = 0)) + adapter.add(Category(title = getString(R.string.uncategorized), + amount = 0, budgetId = "")) adapter.addAll(categories) edit_transaction_category.adapter = adapter transaction?.categoryId?.let { @@ -190,10 +190,6 @@ class TransactionFormActivity : AppCompatActivity(), CoroutineScope { } } val categoryId = (edit_transaction_category.selectedItem as? Category)?.id - ?.let { - if (it > 0) it - else null - } launch { viewModel.saveTransaction(Transaction( id = id, diff --git a/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionFormViewModel.kt b/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionFormViewModel.kt index 4bafb3d..c242a34 100644 --- a/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionFormViewModel.kt +++ b/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionFormViewModel.kt @@ -21,7 +21,7 @@ class TransactionFormViewModel : ViewModel() { @Inject lateinit var userRepository: UserRepository - var currentUserId: Long? = null + var currentUserId: String? = null private set //TODO: Find a better way to handle this @@ -31,18 +31,18 @@ class TransactionFormViewModel : ViewModel() { } } - suspend fun getCategories(budgetId: Long, expense: Boolean) = categoryRepository.findAll(arrayOf(budgetId)).filter { + suspend fun getCategories(budgetId: String, expense: Boolean) = categoryRepository.findAll(arrayOf(budgetId)).filter { it.expense == expense } - suspend fun getTransaction(id: Long) = transactionRepository.findById(id) + suspend fun getTransaction(id: String) = transactionRepository.findById(id) suspend fun saveTransaction(transaction: Transaction) = if (transaction.id == null) transactionRepository.create(transaction) else transactionRepository.update(transaction) - suspend fun deleteTransaction(id: Long) = transactionRepository.delete(id) + suspend fun deleteTransaction(id: String) = transactionRepository.delete(id) suspend fun getAccounts() = budgetRepository.findAll() } diff --git a/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionListFragment.kt b/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionListFragment.kt index 7d1d958..c86b101 100644 --- a/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionListFragment.kt +++ b/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionListFragment.kt @@ -32,7 +32,7 @@ class TransactionListFragment : ListWithAddButtonFragment TransactionViewHolder(v, findNavController()) }) override fun reloadItems() { - viewModel.getTransactions(categoryId = arguments?.getLong(EXTRA_CATEGORY_ID)) + viewModel.getTransactions(categoryId = arguments?.getString(EXTRA_CATEGORY_ID)) } override fun bindData(data: Transaction): BindableData = BindableData(data, TRANSACTION_VIEW) @@ -96,8 +96,8 @@ class TransactionViewHolder(itemView: View, val navController: NavController) : amount.setTextColor(ContextCompat.getColor(context, color)) itemView.setOnClickListener { val bundle = Bundle().apply { - putLong(EXTRA_BUDGET_ID, transaction.budgetId) - putLong(EXTRA_TRANSACTION_ID, transaction.id ?: -1) + putString(EXTRA_BUDGET_ID, transaction.budgetId) + putString(EXTRA_TRANSACTION_ID, transaction.id) } navController.navigate(R.id.addEditTransactionActivity, bundle) } diff --git a/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionListViewModel.kt b/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionListViewModel.kt index c6df271..c7fc07f 100644 --- a/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionListViewModel.kt +++ b/android/src/main/java/com/wbrawner/budget/ui/transactions/TransactionListViewModel.kt @@ -20,7 +20,7 @@ class TransactionListViewModel : ViewModel(), AsyncViewModel> override val state: MutableLiveData>> = MutableLiveData(AsyncState.Loading) fun getTransactions( - categoryId: Long? = null, + categoryId: String? = null, start: Calendar? = null, end: Calendar? = null ) { diff --git a/budgetlib/src/main/java/com/wbrawner/budget/lib/network/BaseUrlHelper.kt b/budgetlib/src/main/java/com/wbrawner/budget/lib/network/BaseUrlHelper.kt deleted file mode 100644 index fd38fba..0000000 --- a/budgetlib/src/main/java/com/wbrawner/budget/lib/network/BaseUrlHelper.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.wbrawner.budget.lib.network - -import okhttp3.Interceptor -import okhttp3.Response - -const val DEFAULT_URL = "http://localhost" - -class BaseUrlHelper(var url: String = DEFAULT_URL) { - val interceptor = object: Interceptor { - override fun intercept(chain: Interceptor.Chain): Response { - val request = chain.request() - val newRequest = request.newBuilder() - val url = request.url.toString().replace(DEFAULT_URL, url) - return chain.proceed(newRequest.url(url).build()) - } - } -} \ No newline at end of file diff --git a/budgetlib/src/main/java/com/wbrawner/budget/lib/network/Interceptors.kt b/budgetlib/src/main/java/com/wbrawner/budget/lib/network/Interceptors.kt new file mode 100644 index 0000000..5b96fed --- /dev/null +++ b/budgetlib/src/main/java/com/wbrawner/budget/lib/network/Interceptors.kt @@ -0,0 +1,34 @@ +package com.wbrawner.budget.lib.network + +import android.content.SharedPreferences +import com.wbrawner.budget.common.PREF_KEY_TOKEN +import okhttp3.Interceptor +import okhttp3.Response +import javax.inject.Inject + +const val DEFAULT_URL = "http://localhost" + +class BaseUrlHelper(var url: String = DEFAULT_URL) { + val interceptor = object : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val request = chain.request() + val newRequest = request.newBuilder() + val url = request.url.toString().replace(DEFAULT_URL, url) + return chain.proceed(newRequest.url(url).build()) + } + } +} + +class AuthHelper @Inject constructor(val sharedPreferences: SharedPreferences) { + val interceptor = object : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val token = sharedPreferences.getString(PREF_KEY_TOKEN, null) + ?: return chain.proceed(chain.request()) + val newRequest = chain.request() + .newBuilder() + .addHeader("Authorization", "Bearer $token") + .build() + return chain.proceed(newRequest) + } + } +} \ No newline at end of file diff --git a/budgetlib/src/main/java/com/wbrawner/budget/lib/network/NetworkModule.kt b/budgetlib/src/main/java/com/wbrawner/budget/lib/network/NetworkModule.kt index 381c0b3..7d47e42 100644 --- a/budgetlib/src/main/java/com/wbrawner/budget/lib/network/NetworkModule.kt +++ b/budgetlib/src/main/java/com/wbrawner/budget/lib/network/NetworkModule.kt @@ -1,7 +1,6 @@ package com.wbrawner.budget.lib.network import android.content.SharedPreferences -import android.util.Base64 import com.squareup.moshi.Moshi import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter import com.wbrawner.budget.common.budget.BudgetRepository @@ -15,16 +14,11 @@ import com.wbrawner.budget.lib.repository.NetworkUserRepository import com.wbrawner.budgetlib.BuildConfig import dagger.Module import dagger.Provides -import okhttp3.Cookie -import okhttp3.CookieJar -import okhttp3.HttpUrl import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.converter.moshi.MoshiConverterFactory -import java.nio.charset.Charset import java.util.* -import javax.inject.Named import javax.inject.Singleton const val PREF_KEY_BASE_URL = "baseUrl" @@ -36,36 +30,6 @@ class NetworkModule { .add(Date::class.java, Rfc3339DateJsonAdapter()) .build() - @Provides - fun provideCookieJar(sharedPreferences: SharedPreferences): CookieJar { - return object : CookieJar { - override fun saveFromResponse(url: HttpUrl, cookies: List) { - sharedPreferences.edit() - .putString( - url.host, - cookies.joinToString(separator = ",") { - Base64.encode(it.toString().toByteArray(), 0) - .toString(charset = Charset.forName("UTF-8")) - } - ) - .apply() - } - - override fun loadForRequest(url: HttpUrl): MutableList { - return sharedPreferences.getString(url.host, "") - ?.split(",") - ?.mapNotNull { - Cookie.parse( - url, - Base64.decode(it, 0).toString(Charset.forName("UTF-8")) - ) - } - ?.toMutableList() - ?: mutableListOf() - } - } - } - @Singleton @Provides fun provideBaseUrlHelper(sharedPreferences: SharedPreferences) = BaseUrlHelper().apply { @@ -76,9 +40,9 @@ class NetworkModule { @Singleton @Provides - fun provideOkHttpClient(baseUrlHelper: BaseUrlHelper, cookieJar: CookieJar): OkHttpClient = OkHttpClient.Builder() - .cookieJar(cookieJar) + fun provideOkHttpClient(baseUrlHelper: BaseUrlHelper, authHelper: AuthHelper): OkHttpClient = OkHttpClient.Builder() .addInterceptor(baseUrlHelper.interceptor) + .addInterceptor(authHelper.interceptor) .apply { if (BuildConfig.DEBUG) this.addInterceptor( @@ -100,26 +64,26 @@ class NetworkModule { @Singleton @Provides - fun provideApiService(retrofit: Retrofit): BudgetApiService = - retrofit.create(BudgetApiService::class.java) + fun provideApiService(retrofit: Retrofit): TwigsApiService = + retrofit.create(TwigsApiService::class.java) @Singleton @Provides - fun provideBudgetRepository(apiService: BudgetApiService, sharedPreferences: SharedPreferences): BudgetRepository = + fun provideBudgetRepository(apiService: TwigsApiService, sharedPreferences: SharedPreferences): BudgetRepository = NetworkBudgetRepository(apiService, sharedPreferences) @Singleton @Provides - fun provideCategoryRepository(apiService: BudgetApiService): CategoryRepository = + fun provideCategoryRepository(apiService: TwigsApiService): CategoryRepository = NetworkCategoryRepository(apiService) @Singleton @Provides - fun provideTransactionRepository(apiService: BudgetApiService): TransactionRepository = + fun provideTransactionRepository(apiService: TwigsApiService): TransactionRepository = NetworkTransactionRepository(apiService) @Singleton @Provides - fun provideUserRepository(apiService: BudgetApiService): UserRepository = - NetworkUserRepository(apiService) + fun provideUserRepository(apiService: TwigsApiService, sharedPreferences: SharedPreferences): UserRepository = + NetworkUserRepository(apiService, sharedPreferences) } diff --git a/budgetlib/src/main/java/com/wbrawner/budget/lib/network/BudgetApiService.kt b/budgetlib/src/main/java/com/wbrawner/budget/lib/network/TwigsApiService.kt similarity index 68% rename from budgetlib/src/main/java/com/wbrawner/budget/lib/network/BudgetApiService.kt rename to budgetlib/src/main/java/com/wbrawner/budget/lib/network/TwigsApiService.kt index 1fb5c56..f3da7ad 100644 --- a/budgetlib/src/main/java/com/wbrawner/budget/lib/network/BudgetApiService.kt +++ b/budgetlib/src/main/java/com/wbrawner/budget/lib/network/TwigsApiService.kt @@ -1,5 +1,6 @@ package com.wbrawner.budget.lib.network +import com.wbrawner.budget.common.Session import com.wbrawner.budget.common.budget.Budget import com.wbrawner.budget.common.category.Category import com.wbrawner.budget.common.transaction.Transaction @@ -8,7 +9,7 @@ import com.wbrawner.budget.common.user.User import com.wbrawner.budget.lib.repository.NewBudgetRequest import retrofit2.http.* -interface BudgetApiService { +interface TwigsApiService { // Budgets @GET("budgets") suspend fun getBudgets( @@ -17,54 +18,54 @@ interface BudgetApiService { ): List @GET("budgets/{id}") - suspend fun getBudget(@Path("id") id: Long): Budget + suspend fun getBudget(@Path("id") id: String): Budget @GET("budgets/{id}/balance") - suspend fun getBudgetBalance(@Path("id") id: Long): BudgetBalanceResponse + suspend fun getBudgetBalance(@Path("id") id: String): BudgetBalanceResponse @POST("budgets") suspend fun newBudget(@Body budget: NewBudgetRequest): Budget @PUT("budgets/{id}") suspend fun updateBudget( - @Path("id") id: Long, + @Path("id") id: String, @Body budget: Budget ): Budget @DELETE("budgets/{id}") - suspend fun deleteBudget(@Path("id") id: Long) + suspend fun deleteBudget(@Path("id") id: String) // Categories @GET("categories") suspend fun getCategories( - @Query("budgetIds") budgetIds: Array? = null, + @Query("budgetIds") budgetIds: Array? = null, @Query("count") count: Int? = null, @Query("page") page: Int? = null ): List @GET("categories/{id}") - suspend fun getCategory(@Path("id") id: Long): Category + suspend fun getCategory(@Path("id") id: String): Category @GET("categories/{id}/balance") - suspend fun getCategoryBalance(@Path("id") id: Long): CategoryBalanceResponse + suspend fun getCategoryBalance(@Path("id") id: String): CategoryBalanceResponse @POST("categories") suspend fun newCategory(@Body category: Category): Category @PUT("categories/{id}") suspend fun updateCategory( - @Path("id") id: Long, + @Path("id") id: String, @Body category: Category ): Category @DELETE("categories/{id}") - suspend fun deleteCategory(@Path("id") id: Long) + suspend fun deleteCategory(@Path("id") id: String) // Transactions @GET("transactions") suspend fun getTransactions( - @Query("budgetIds") budgetIds: List? = null, - @Query("categoryIds") categoryIds: List? = null, + @Query("budgetIds") budgetIds: List? = null, + @Query("categoryIds") categoryIds: List? = null, @Query("from") from: String? = null, @Query("to") to: String? = null, @Query("count") count: Int? = null, @@ -72,30 +73,30 @@ interface BudgetApiService { ): List @GET("transactions/{id}") - suspend fun getTransaction(@Path("id") id: Long): Transaction + suspend fun getTransaction(@Path("id") id: String): Transaction @POST("transactions") suspend fun newTransaction(@Body transaction: Transaction): Transaction @PUT("transactions/{id}") suspend fun updateTransaction( - @Path("id") id: Long, + @Path("id") id: String, @Body transaction: Transaction ): Transaction @DELETE("transactions/{id}") - suspend fun deleteTransaction(@Path("id") id: Long) + suspend fun deleteTransaction(@Path("id") id: String) // Users @GET("users") suspend fun getUsers( - @Query("budgetId") budgetId: Long? = null, + @Query("budgetId") budgetid: String? = null, @Query("count") count: Int? = null, @Query("page") page: Int? = null ): List @POST("users/login") - suspend fun login(@Body request: LoginRequest): User + suspend fun login(@Body request: LoginRequest): Session @GET("users/me") suspend fun getProfile(): User @@ -104,17 +105,17 @@ interface BudgetApiService { suspend fun searchUsers(@Query("query") query: String): List @GET("users/{id}") - suspend fun getUser(@Path("id") id: Long): User + suspend fun getUser(@Path("id") id: String): User @POST("users") suspend fun newUser(@Body user: User): User @PUT("users/{id}") suspend fun updateUser( - @Path("id") id: Long, + @Path("id") id: String, @Body user: User ): User @DELETE("users/{id}") - suspend fun deleteUser(@Path("id") id: Long) + suspend fun deleteUser(@Path("id") id: String) } \ No newline at end of file diff --git a/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkBudgetRepository.kt b/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkBudgetRepository.kt index ce67f77..72a160f 100644 --- a/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkBudgetRepository.kt +++ b/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkBudgetRepository.kt @@ -5,7 +5,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.wbrawner.budget.common.budget.Budget import com.wbrawner.budget.common.budget.BudgetRepository -import com.wbrawner.budget.lib.network.BudgetApiService +import com.wbrawner.budget.lib.network.TwigsApiService import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex @@ -14,7 +14,7 @@ import kotlinx.coroutines.sync.withLock const val KEY_DEFAULT_BUDGET = "defaultBudget" class NetworkBudgetRepository( - private val apiService: BudgetApiService, + private val apiService: TwigsApiService, private val sharedPreferences: SharedPreferences ) : BudgetRepository { private val mutex = Mutex() @@ -25,7 +25,7 @@ class NetworkBudgetRepository( currentBudget.observeForever { budget -> sharedPreferences.edit().apply { budget?.id?.let { - putLong(KEY_DEFAULT_BUDGET, it) + putString(KEY_DEFAULT_BUDGET, it) } ?: remove(KEY_DEFAULT_BUDGET) apply() } @@ -42,7 +42,7 @@ class NetworkBudgetRepository( emptyList() } if (budgets.isEmpty()) return - val budgetId = sharedPreferences.getLong(KEY_DEFAULT_BUDGET, budgets.first().id!!) + val budgetId = sharedPreferences.getString(KEY_DEFAULT_BUDGET, budgets.first().id)!! val budget = try { findById(budgetId) } catch (e: Exception) { @@ -67,7 +67,7 @@ class NetworkBudgetRepository( } } - override suspend fun findById(id: Long, setCurrent: Boolean): Budget = (mutex.withLock { + override suspend fun findById(id: String, setCurrent: Boolean): Budget = (mutex.withLock { budgets.firstOrNull { it.id == id } } ?: apiService.getBudget(id).apply { mutex.withLock { @@ -87,19 +87,19 @@ class NetworkBudgetRepository( } } - override suspend fun delete(id: Long) = apiService.deleteBudget(id).apply { + override suspend fun delete(id: String) = apiService.deleteBudget(id).apply { mutex.withLock { budgets.removeAll { it.id == id } } } - override suspend fun getBalance(id: Long): Long = apiService.getBudgetBalance(id).balance + override suspend fun getBalance(id: String): Long = apiService.getBudgetBalance(id).balance } data class NewBudgetRequest( val name: String, val description: String? = null, - val userIds: List + val userIds: List ) { constructor(budget: Budget) : this(budget.name, budget.description, budget.users.map { it.id!! }) } \ No newline at end of file diff --git a/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkCategoryRepository.kt b/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkCategoryRepository.kt index 5554585..9afa793 100644 --- a/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkCategoryRepository.kt +++ b/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkCategoryRepository.kt @@ -2,23 +2,24 @@ package com.wbrawner.budget.lib.repository import com.wbrawner.budget.common.category.Category import com.wbrawner.budget.common.category.CategoryRepository -import com.wbrawner.budget.lib.network.BudgetApiService +import com.wbrawner.budget.lib.network.TwigsApiService import javax.inject.Inject -class NetworkCategoryRepository @Inject constructor(private val apiService: BudgetApiService) : CategoryRepository { + +class NetworkCategoryRepository @Inject constructor(private val apiService: TwigsApiService) : CategoryRepository { override suspend fun create(newItem: Category): Category = apiService.newCategory(newItem) - override suspend fun findAll(budgetIds: Array?): List = apiService.getCategories(budgetIds).sortedBy { it.title } + override suspend fun findAll(budgetIds: Array?): List = apiService.getCategories(budgetIds).sortedBy { it.title } override suspend fun findAll(): List = findAll(null) - override suspend fun findById(id: Long): Category = apiService.getCategory(id) + override suspend fun findById(id: String): Category = apiService.getCategory(id) override suspend fun update(updatedItem: Category): Category = apiService.updateCategory(updatedItem.id!!, updatedItem) - override suspend fun delete(id: Long) = apiService.deleteCategory(id) + override suspend fun delete(id: String) = apiService.deleteCategory(id) // TODO: Implement this method server-side and then here - override suspend fun getBalance(id: Long): Long = apiService.getCategoryBalance(id).balance + override suspend fun getBalance(id: String): Long = apiService.getCategoryBalance(id).balance } diff --git a/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkTransactionRepository.kt b/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkTransactionRepository.kt index a46a949..ef79387 100644 --- a/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkTransactionRepository.kt +++ b/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkTransactionRepository.kt @@ -2,19 +2,19 @@ package com.wbrawner.budget.lib.repository import com.wbrawner.budget.common.transaction.Transaction import com.wbrawner.budget.common.transaction.TransactionRepository -import com.wbrawner.budget.lib.network.BudgetApiService +import com.wbrawner.budget.lib.network.TwigsApiService import java.text.SimpleDateFormat import java.util.* import javax.inject.Inject -class NetworkTransactionRepository @Inject constructor(private val apiService: BudgetApiService) : TransactionRepository { +class NetworkTransactionRepository @Inject constructor(private val apiService: TwigsApiService) : TransactionRepository { private val dateFormatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH) override suspend fun create(newItem: Transaction): Transaction = apiService.newTransaction(newItem) override suspend fun findAll( - budgetIds: List?, - categoryIds: List?, + budgetIds: List?, + categoryIds: List?, start: Calendar?, end: Calendar? ): List = apiService.getTransactions( @@ -30,10 +30,10 @@ class NetworkTransactionRepository @Inject constructor(private val apiService: B override suspend fun findAll(): List = findAll(null) - override suspend fun findById(id: Long): Transaction = apiService.getTransaction(id) + override suspend fun findById(id: String): Transaction = apiService.getTransaction(id) override suspend fun update(updatedItem: Transaction): Transaction = apiService.updateTransaction(updatedItem.id!!, updatedItem) - override suspend fun delete(id: Long) = apiService.deleteTransaction(id) + override suspend fun delete(id: String) = apiService.deleteTransaction(id) } diff --git a/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkUserRepository.kt b/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkUserRepository.kt index dd12f35..7b5f627 100644 --- a/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkUserRepository.kt +++ b/budgetlib/src/main/java/com/wbrawner/budget/lib/repository/NetworkUserRepository.kt @@ -1,16 +1,21 @@ package com.wbrawner.budget.lib.repository +import android.content.SharedPreferences import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import com.wbrawner.budget.common.PREF_KEY_TOKEN import com.wbrawner.budget.common.user.LoginRequest import com.wbrawner.budget.common.user.User import com.wbrawner.budget.common.user.UserRepository -import com.wbrawner.budget.lib.network.BudgetApiService +import com.wbrawner.budget.lib.network.TwigsApiService import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import javax.inject.Inject -class NetworkUserRepository @Inject constructor(private val apiService: BudgetApiService) : UserRepository { +class NetworkUserRepository @Inject constructor( + private val apiService: TwigsApiService, + private val sharedPreferences: SharedPreferences +) : UserRepository { override val currentUser: LiveData = MutableLiveData() @@ -23,10 +28,14 @@ class NetworkUserRepository @Inject constructor(private val apiService: BudgetAp } } - override suspend fun login(username: String, password: String): User = - apiService.login(LoginRequest(username, password)).also { - (currentUser as MutableLiveData).postValue(it) - } + override suspend fun login(username: String, password: String): User { + apiService.login(LoginRequest(username, password)).also { + sharedPreferences.edit() + .putString(PREF_KEY_TOKEN, it.token) + .apply() + } + return getProfile() + } override suspend fun getProfile(): User = apiService.getProfile().also { (currentUser as MutableLiveData).postValue(it) @@ -34,11 +43,11 @@ class NetworkUserRepository @Inject constructor(private val apiService: BudgetAp override suspend fun create(newItem: User): User = apiService.newUser(newItem) - override suspend fun findAll(accountId: Long?): List = apiService.getUsers(accountId) + override suspend fun findAll(budgetId: String?): List = apiService.getUsers(budgetId) override suspend fun findAll(): List = findAll(null) - override suspend fun findById(id: Long): User = apiService.getUser(id) + override suspend fun findById(id: String): User = apiService.getUser(id) override suspend fun findAllByNameLike(query: String): List = apiService.searchUsers(query) @@ -46,5 +55,5 @@ class NetworkUserRepository @Inject constructor(private val apiService: BudgetAp override suspend fun update(updatedItem: User): User = apiService.updateUser(updatedItem.id!!, updatedItem) - override suspend fun delete(id: Long) = apiService.deleteUser(id) -} \ No newline at end of file + override suspend fun delete(id: String) = apiService.deleteUser(id) +} diff --git a/common/src/main/java/com/wbrawner/budget/common/Repository.kt b/common/src/main/java/com/wbrawner/budget/common/Repository.kt index 651078b..ead7ead 100644 --- a/common/src/main/java/com/wbrawner/budget/common/Repository.kt +++ b/common/src/main/java/com/wbrawner/budget/common/Repository.kt @@ -15,5 +15,5 @@ interface Repository { } interface Identifiable { - val id: Long? + val id: String? } diff --git a/common/src/main/java/com/wbrawner/budget/common/Session.kt b/common/src/main/java/com/wbrawner/budget/common/Session.kt new file mode 100644 index 0000000..dccbc89 --- /dev/null +++ b/common/src/main/java/com/wbrawner/budget/common/Session.kt @@ -0,0 +1,11 @@ +package com.wbrawner.budget.common + +import java.util.* + +const val PREF_KEY_TOKEN = "sessionToken" + +data class Session( + val id: String, + val token: String, + val expiration: Date +) \ No newline at end of file diff --git a/common/src/main/java/com/wbrawner/budget/common/budget/Budget.kt b/common/src/main/java/com/wbrawner/budget/common/budget/Budget.kt index b5d952a..1b1830f 100644 --- a/common/src/main/java/com/wbrawner/budget/common/budget/Budget.kt +++ b/common/src/main/java/com/wbrawner/budget/common/budget/Budget.kt @@ -4,7 +4,7 @@ import com.wbrawner.budget.common.Identifiable import com.wbrawner.budget.common.user.User data class Budget( - override val id: Long? = null, + override val id: String? = null, val name: String, val description: String? = null, val users: List = emptyList() diff --git a/common/src/main/java/com/wbrawner/budget/common/budget/BudgetRepository.kt b/common/src/main/java/com/wbrawner/budget/common/budget/BudgetRepository.kt index 771089c..e2a927b 100644 --- a/common/src/main/java/com/wbrawner/budget/common/budget/BudgetRepository.kt +++ b/common/src/main/java/com/wbrawner/budget/common/budget/BudgetRepository.kt @@ -3,10 +3,10 @@ package com.wbrawner.budget.common.budget import androidx.lifecycle.LiveData import com.wbrawner.budget.common.Repository -interface BudgetRepository : Repository { +interface BudgetRepository : Repository { val currentBudget: LiveData - override suspend fun findById(id: Long): Budget = findById(id, false) - suspend fun findById(id: Long, setCurrent: Boolean = false): Budget + override suspend fun findById(id: String): Budget = findById(id, false) + suspend fun findById(id: String, setCurrent: Boolean = false): Budget suspend fun prefetchData() - suspend fun getBalance(id: Long): Long + suspend fun getBalance(id: String): Long } \ No newline at end of file diff --git a/common/src/main/java/com/wbrawner/budget/common/category/Category.kt b/common/src/main/java/com/wbrawner/budget/common/category/Category.kt index c336512..3f69fa6 100644 --- a/common/src/main/java/com/wbrawner/budget/common/category/Category.kt +++ b/common/src/main/java/com/wbrawner/budget/common/category/Category.kt @@ -3,8 +3,8 @@ package com.wbrawner.budget.common.category import com.wbrawner.budget.common.Identifiable data class Category( - val budgetId: Long, - override val id: Long? = null, + val budgetId: String, + override val id: String? = null, val title: String, val description: String? = null, val amount: Long, diff --git a/common/src/main/java/com/wbrawner/budget/common/category/CategoryRepository.kt b/common/src/main/java/com/wbrawner/budget/common/category/CategoryRepository.kt index dac1fa6..5ce1784 100644 --- a/common/src/main/java/com/wbrawner/budget/common/category/CategoryRepository.kt +++ b/common/src/main/java/com/wbrawner/budget/common/category/CategoryRepository.kt @@ -2,7 +2,7 @@ package com.wbrawner.budget.common.category import com.wbrawner.budget.common.Repository -interface CategoryRepository : Repository { - suspend fun findAll(budgetIds: Array? = null): List - suspend fun getBalance(id: Long): Long +interface CategoryRepository : Repository { + suspend fun findAll(budgetIds: Array? = null): List + suspend fun getBalance(id: String): Long } \ No newline at end of file diff --git a/common/src/main/java/com/wbrawner/budget/common/transaction/Transaction.kt b/common/src/main/java/com/wbrawner/budget/common/transaction/Transaction.kt index 163a648..c96a24c 100644 --- a/common/src/main/java/com/wbrawner/budget/common/transaction/Transaction.kt +++ b/common/src/main/java/com/wbrawner/budget/common/transaction/Transaction.kt @@ -4,13 +4,13 @@ import com.wbrawner.budget.common.Identifiable import java.util.* data class Transaction( - override val id: Long? = null, + override val id: String? = null, val title: String, val date: Date, val description: String, val amount: Long, - val categoryId: Long? = null, - val budgetId: Long, + val categoryId: String? = null, + val budgetId: String, val expense: Boolean, - val createdBy: Long + val createdBy: String ): Identifiable \ No newline at end of file diff --git a/common/src/main/java/com/wbrawner/budget/common/transaction/TransactionRepository.kt b/common/src/main/java/com/wbrawner/budget/common/transaction/TransactionRepository.kt index ffc68c1..7954ec8 100644 --- a/common/src/main/java/com/wbrawner/budget/common/transaction/TransactionRepository.kt +++ b/common/src/main/java/com/wbrawner/budget/common/transaction/TransactionRepository.kt @@ -3,10 +3,10 @@ package com.wbrawner.budget.common.transaction import com.wbrawner.budget.common.Repository import java.util.* -interface TransactionRepository : Repository { +interface TransactionRepository : Repository { suspend fun findAll( - budgetIds: List? = null, - categoryIds: List? = null, + budgetIds: List? = null, + categoryIds: List? = null, start: Calendar? = GregorianCalendar.getInstance().apply { set(Calendar.DAY_OF_MONTH, 1) set(Calendar.HOUR_OF_DAY, 0) diff --git a/common/src/main/java/com/wbrawner/budget/common/user/User.kt b/common/src/main/java/com/wbrawner/budget/common/user/User.kt index 8f2fb0b..02a9a8d 100644 --- a/common/src/main/java/com/wbrawner/budget/common/user/User.kt +++ b/common/src/main/java/com/wbrawner/budget/common/user/User.kt @@ -1,11 +1,13 @@ package com.wbrawner.budget.common.user +import com.wbrawner.budget.common.Identifiable + data class User( - val id: Long? = null, + override val id: String? = null, val username: String, val email: String? = null, val avatar: String? = null -) { +) : Identifiable { override fun toString(): String = username } diff --git a/common/src/main/java/com/wbrawner/budget/common/user/UserRepository.kt b/common/src/main/java/com/wbrawner/budget/common/user/UserRepository.kt index d257fc2..301908d 100644 --- a/common/src/main/java/com/wbrawner/budget/common/user/UserRepository.kt +++ b/common/src/main/java/com/wbrawner/budget/common/user/UserRepository.kt @@ -3,10 +3,10 @@ package com.wbrawner.budget.common.user import androidx.lifecycle.LiveData import com.wbrawner.budget.common.Repository -interface UserRepository : Repository { +interface UserRepository : Repository { val currentUser: LiveData suspend fun login(username: String, password: String): User suspend fun getProfile(): User - suspend fun findAll(accountId: Long? = null): List + suspend fun findAll(budgetId: String? = null): List suspend fun findAllByNameLike(query: String): List } \ No newline at end of file diff --git a/common/src/main/java/com/wbrawner/budget/common/util/Utils.kt b/common/src/main/java/com/wbrawner/budget/common/util/Utils.kt new file mode 100644 index 0000000..eb4a4c3 --- /dev/null +++ b/common/src/main/java/com/wbrawner/budget/common/util/Utils.kt @@ -0,0 +1,11 @@ +package com.wbrawner.budget.common.util + +private const val CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + +fun randomId(): String { + val id = StringBuilder() + repeat(32) { + id.append(CHARACTERS.random()) + } + return id.toString() +} \ No newline at end of file