diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0a842620b0d1eb4d5e5e51fdcbb05d8ed2da7063..d6fce9db744553188ef4d74e238c9888fa3c413d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -32,7 +32,6 @@ </activity> <activity android:name=".ui.hub.HubActivity" android:configChanges="orientation|screenSize"/> <activity android:name=".ui.login.LoginActivity"/> - <activity android:name=".ui.transaction.TransactionActivity"/> <provider android:name="androidx.core.content.FileProvider" diff --git a/app/src/main/java/com/example/bondoman/BondomanApp.kt b/app/src/main/java/com/example/bondoman/BondomanApp.kt index e95390f5cddf71c499b69340d1d97aee4bfa45df..035197a39cc37fa76494acfa84ec2b807a9b7fe9 100644 --- a/app/src/main/java/com/example/bondoman/BondomanApp.kt +++ b/app/src/main/java/com/example/bondoman/BondomanApp.kt @@ -1,25 +1,13 @@ package com.example.bondoman import android.app.Application -import android.content.IntentFilter -import android.os.Build import com.example.bondoman.database.AppDatabase -import com.example.bondoman.ui.transaction.RandomBroadcastReceiver class BondomanApp : Application() { - private val randomReceiver = RandomBroadcastReceiver() override fun onCreate() { super.onCreate() AppDatabase.getInstance(this) - - val filter = IntentFilter(ACTION_RANDOM_TRANSACTION) - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - registerReceiver(randomReceiver, filter, RECEIVER_EXPORTED) - } else { - registerReceiver(randomReceiver, filter) - } } // Global statics should be here diff --git a/app/src/main/java/com/example/bondoman/ui/hub/HubActivity.kt b/app/src/main/java/com/example/bondoman/ui/hub/HubActivity.kt index 121ebf8ed37bd761c53d10da5a403117b381a7c3..81bdfac56dd9f75fca1de88d9b5dff8842f51037 100644 --- a/app/src/main/java/com/example/bondoman/ui/hub/HubActivity.kt +++ b/app/src/main/java/com/example/bondoman/ui/hub/HubActivity.kt @@ -1,63 +1,93 @@ package com.example.bondoman.ui.hub +import android.content.IntentFilter import android.content.res.Configuration +import android.os.Build import android.os.Bundle import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.ViewModelProvider import androidx.navigation.findNavController import androidx.navigation.ui.setupWithNavController -import androidx.viewbinding.ViewBinding +import com.example.bondoman.BondomanApp import com.example.bondoman.R import com.example.bondoman.database.AppDatabase import com.example.bondoman.database.repository.TransactionRepository import com.example.bondoman.databinding.ActivityHubBinding -import com.example.bondoman.databinding.ActivityHubLandscapeBinding +import com.example.bondoman.viewmodel.transaction.LocationViewModel +import com.example.bondoman.viewmodel.transaction.LocationViewModelFactory import com.example.bondoman.viewmodel.transaction.TransactionViewModel import com.example.bondoman.viewmodel.transaction.TransactionViewModelFactory -import com.google.android.material.bottomnavigation.BottomNavigationView -import com.google.android.material.navigation.NavigationView class HubActivity : AppCompatActivity() { - private lateinit var viewBinding: ViewBinding + private val randomReceiver = RandomBroadcastReceiver(supportFragmentManager) + + lateinit var binding: ActivityHubBinding lateinit var transactionViewModel: TransactionViewModel + lateinit var locationViewModel: LocationViewModel + var configurationLock: Boolean = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - // Initialize database + // Initialize database and viewmodels val database = AppDatabase.getInstance(this) val transactionRepo = TransactionRepository(database.transactionDao) val transactionModelFactory = TransactionViewModelFactory(transactionRepo) - transactionViewModel = - ViewModelProvider(this, transactionModelFactory)[TransactionViewModel::class.java] + transactionViewModel = ViewModelProvider(this, transactionModelFactory)[TransactionViewModel::class.java] + val locationModelFactory = LocationViewModelFactory() + locationViewModel = ViewModelProvider(this, locationModelFactory)[LocationViewModel::class.java] - // Initialize navbar and fragments - val orientation = resources.configuration.orientation - if (orientation == Configuration.ORIENTATION_LANDSCAPE) { - viewBinding = ActivityHubLandscapeBinding.inflate(layoutInflater) - setContentView(viewBinding.root) + // Initialize binding + binding = ActivityHubBinding.inflate(layoutInflater) + setContentView(binding.root) + + // Initialize header + binding.headerContent.navBackButton.visibility = View.GONE + binding.headerContent.navBackButton.setOnClickListener(::onBackClick) - // Initialize header - (viewBinding as ActivityHubLandscapeBinding).headerContentLandscape.navBackButton.visibility = View.GONE + // Initialize navbars + val navController = findNavController(R.id.nav_host_fragment_activity_main) + binding.navView.setupWithNavController(navController) + binding.navViewLandscape.setupWithNavController(navController) - val navView: NavigationView = (viewBinding as ActivityHubLandscapeBinding).navViewLandscape - val navController = findNavController(R.id.nav_host_fragment_activity_main) - navView.setupWithNavController(navController) + // Setup orientation + configurationLock = false + val orientation = resources.configuration.orientation + + if (orientation == Configuration.ORIENTATION_LANDSCAPE) { + binding.navView.visibility = View.GONE + binding.navViewLandscape.visibility = View.VISIBLE } else { - viewBinding = ActivityHubBinding.inflate(layoutInflater) - setContentView(viewBinding.root) + binding.navViewLandscape.visibility = View.GONE + binding.navView.visibility = View.VISIBLE + } + - // Initialize header - (viewBinding as ActivityHubBinding).headerContent.navBackButton.visibility = View.GONE + // Setup broadcast receiver + val filter = IntentFilter(BondomanApp.ACTION_RANDOM_TRANSACTION) - val navView: BottomNavigationView = (viewBinding as ActivityHubBinding).navView - val navController = findNavController(R.id.nav_host_fragment_activity_main) - navView.setupWithNavController(navController) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + registerReceiver(randomReceiver, filter, RECEIVER_EXPORTED) + } else { + registerReceiver(randomReceiver, filter) } } override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) - recreate() + + if(!configurationLock){ + if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){ + binding.navView.visibility = View.GONE + binding.navViewLandscape.visibility = View.VISIBLE + } else { + binding.navViewLandscape.visibility = View.GONE + binding.navView.visibility = View.VISIBLE + } + } + } + + private fun onBackClick(view: View) { + onBackPressed() } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/ui/hub/RandomBroadcastReceiver.kt b/app/src/main/java/com/example/bondoman/ui/hub/RandomBroadcastReceiver.kt new file mode 100644 index 0000000000000000000000000000000000000000..76b1bbdd870c54e4e8ff7d39629c74f4761b901a --- /dev/null +++ b/app/src/main/java/com/example/bondoman/ui/hub/RandomBroadcastReceiver.kt @@ -0,0 +1,42 @@ +package com.example.bondoman.ui.hub + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.os.Bundle +import androidx.fragment.app.FragmentManager +import androidx.navigation.fragment.findNavController +import com.example.bondoman.R +import com.example.bondoman.ui.hub.addtransaction.AddTransactionFragment + +class RandomBroadcastReceiver(private val fragmentManager: FragmentManager) : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + val bundle = Bundle() + bundle.putInt(AddTransactionFragment.KEY_ACTION, AddTransactionFragment.ACTION_ADD) + + // TODO: Consider serializing or just pass the id and read it from the transaction page. Might offer better performance though + // TODO: Randomizer + bundle.putString(AddTransactionFragment.KEY_TITLE, "apa") + bundle.putInt(AddTransactionFragment.KEY_AMOUNT, 0) + bundle.putInt(AddTransactionFragment.KEY_CATEGORY, AddTransactionFragment.CATEGORY_INCOME) + + val transaction = fragmentManager.beginTransaction() + val fragment = AddTransactionFragment() + fragment.arguments = bundle + + val navHostFragment = fragmentManager.findFragmentById(R.id.nav_host_fragment_activity_main) + navHostFragment?.let { + val navController = navHostFragment.findNavController() + try { + navController.popBackStack() + }catch (error: Error){ + println("NavController don't have extra back stack") + } + } + + transaction.add(R.id.nav_host_fragment_activity_main, fragment) + + transaction.addToBackStack(null) + transaction.commit() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/ui/transaction/TransactionActivity.kt b/app/src/main/java/com/example/bondoman/ui/hub/addtransaction/AddTransactionFragment.kt similarity index 50% rename from app/src/main/java/com/example/bondoman/ui/transaction/TransactionActivity.kt rename to app/src/main/java/com/example/bondoman/ui/hub/addtransaction/AddTransactionFragment.kt index 125c50968bb14c77d1fc3f759fcb57e265c49dc2..0188fdb674edc09c3e6924823a1d42e8059609f1 100644 --- a/app/src/main/java/com/example/bondoman/ui/transaction/TransactionActivity.kt +++ b/app/src/main/java/com/example/bondoman/ui/hub/addtransaction/AddTransactionFragment.kt @@ -1,71 +1,76 @@ -package com.example.bondoman.ui.transaction +package com.example.bondoman.ui.hub.addtransaction import android.Manifest +import android.content.Context import android.content.pm.PackageManager +import android.content.res.Configuration import android.location.Location import android.os.Bundle +import android.view.LayoutInflater import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.InputMethodManager import android.widget.TextView import android.widget.Toast -import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat -import androidx.lifecycle.ViewModelProvider +import androidx.fragment.app.Fragment import com.example.bondoman.R -import com.example.bondoman.database.AppDatabase import com.example.bondoman.database.entity.TransactionEntity -import com.example.bondoman.database.repository.TransactionRepository -import com.example.bondoman.databinding.ActivityTransactionBinding +import com.example.bondoman.databinding.FragmentAddTransactionBinding +import com.example.bondoman.ui.hub.HubActivity import com.example.bondoman.viewmodel.transaction.LocationViewModel -import com.example.bondoman.viewmodel.transaction.LocationViewModelFactory import com.example.bondoman.viewmodel.transaction.TransactionViewModel -import com.example.bondoman.viewmodel.transaction.TransactionViewModelFactory import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.LocationServices import java.text.SimpleDateFormat import java.util.Date import java.util.Locale -class TransactionActivity : AppCompatActivity() { - private lateinit var binding: ActivityTransactionBinding - private lateinit var transactionViewModel: TransactionViewModel +class AddTransactionFragment : Fragment() { + private lateinit var binding: FragmentAddTransactionBinding + private lateinit var hubActivity: HubActivity + private lateinit var savedContext: Context private var actionCode: Int = 0 + + private lateinit var transactionViewModel: TransactionViewModel private var transactionId: Int = 0 - + private lateinit var fusedLocationClient: FusedLocationProviderClient private lateinit var locationViewModel: LocationViewModel private var savedLat: Double? = null private var savedLng: Double? = null - override fun onCreate(savedInstanceState: Bundle?){ - super.onCreate(savedInstanceState) - binding = ActivityTransactionBinding.inflate(layoutInflater) - setContentView(binding.root) - - // Initialize database - val database = AppDatabase.getInstance(this) - val transactionRepo = TransactionRepository(database.transactionDao) - val transactionModelFactory = TransactionViewModelFactory(transactionRepo) - transactionViewModel = ViewModelProvider(this, transactionModelFactory)[TransactionViewModel::class.java] + override fun onAttach(context: Context) { + super.onAttach(context) + savedContext = requireContext() + } - // Location VM - val locationModelFactory = LocationViewModelFactory() - locationViewModel = ViewModelProvider(this, locationModelFactory)[LocationViewModel::class.java] - locationViewModel.location.observe(this) { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + super.onCreateView(inflater, container, savedInstanceState) + + // Initialize view + binding = FragmentAddTransactionBinding.inflate(layoutInflater) + hubActivity = requireActivity() as HubActivity + hubActivity.configurationLock = true + hubActivity.binding.navView.visibility = View.GONE + hubActivity.binding.navViewLandscape.visibility = View.GONE + hubActivity.binding.headerContent.navBackButton.visibility = View.VISIBLE + + // Initialize viewmodel + transactionViewModel = hubActivity.transactionViewModel + locationViewModel = hubActivity.locationViewModel + + // Observe location + locationViewModel.location.observe(hubActivity) { observeLocation(it) } - // Initialize header - binding.header.navTitle.text = getString(R.string.hub_nav_transaction) - val backButton = binding.header.navBackButton - backButton.setOnClickListener(::onBackClick) - - // Initialize category dropdown - val spinner = binding.categoryInput - spinner.setSelection(0, true); - (spinner.selectedView as TextView).setTextColor(ContextCompat.getColor(this, R.color.black)) - // Locate button val locateButton = binding.btnLocate locateButton.setOnClickListener(::onLocateClick) @@ -74,16 +79,15 @@ class TransactionActivity : AppCompatActivity() { val deleteButton = binding.btnDelete deleteButton.setOnClickListener(::onDeleteClick) - // Initialize category dropdown + // Submit button val submitButton = binding.submitButton - backButton.setOnClickListener(::onBackClick) submitButton.setOnClickListener(::onSubmitClick) // Initialize initial values - val titleInitial = intent.getStringExtra(KEY_TITLE) - val amountInitial = intent.getIntExtra(KEY_AMOUNT, 0) - val categoryInitial = intent.getIntExtra(KEY_CATEGORY, 0) - var locationInitial = intent.getStringExtra(KEY_LOCATION) + val titleInitial = arguments?.getString(KEY_TITLE) ?: "" + val amountInitial = arguments?.getInt(KEY_AMOUNT, 0) ?: 0 + val categoryInitial = arguments?.getInt(KEY_CATEGORY, 0) ?: 0 + val locationInitial = arguments?.getString(KEY_LOCATION) ?: "" binding.titleInput.setText(titleInitial) binding.amountInput.setText(amountInitial.toString()) @@ -91,14 +95,43 @@ class TransactionActivity : AppCompatActivity() { binding.locationText.text = locationInitial // Initialize category dropdown color - (binding.categoryInput.selectedView as TextView).setTextColor(ContextCompat.getColor(this, R.color.black)) + (binding.categoryInput.selectedView as TextView).setTextColor(ContextCompat.getColor(requireContext(), R.color.black)) + + // Get action codes + actionCode = arguments?.getInt(KEY_ACTION, 0) ?: 0 + transactionId = arguments?.getInt(KEY_TRANSACTION_ID, 0) ?: 0 - actionCode = intent.getIntExtra(KEY_ACTION, 0) - transactionId = intent.getIntExtra(KEY_TRANSACTION_ID, 0) + if(actionCode == ACTION_EDIT) { + binding.categoryInput.isEnabled = false + locateButton.isEnabled = false + deleteButton.isEnabled = false + } - if(actionCode == ACTION_EDIT) binding.categoryInput.isEnabled = false + fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireContext()) - fusedLocationClient = LocationServices.getFusedLocationProviderClient(this) + return binding.root + } + + override fun onDestroyView() { + super.onDestroyView() + hubActivity.configurationLock = false + + // Also hide keyboard if it's visible + val imm = requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + val currentFocus = requireActivity().currentFocus + currentFocus?.let { + imm.hideSoftInputFromWindow(it.windowToken, 0) + } + + val orientation = resources.configuration.orientation + hubActivity.binding.headerContent.navBackButton.visibility = View.GONE + if (orientation == Configuration.ORIENTATION_LANDSCAPE) { + hubActivity.binding.navView.visibility = View.GONE + hubActivity.binding.navViewLandscape.visibility = View.VISIBLE + } else { + hubActivity.binding.navViewLandscape.visibility = View.GONE + hubActivity.binding.navView.visibility = View.VISIBLE + } } private fun onDeleteClick(view: View) { @@ -111,14 +144,14 @@ class TransactionActivity : AppCompatActivity() { private fun getLastLocation() { if (ActivityCompat.checkSelfPermission( - this, + savedContext, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( - this, + savedContext, Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) { - ActivityCompat.requestPermissions(this, + ActivityCompat.requestPermissions(hubActivity, arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION @@ -127,10 +160,10 @@ class TransactionActivity : AppCompatActivity() { ) if (ActivityCompat.checkSelfPermission( - this, + savedContext, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( - this, + savedContext, Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED) { @@ -139,10 +172,10 @@ class TransactionActivity : AppCompatActivity() { } if (ActivityCompat.checkSelfPermission( - this, + savedContext, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(this, + ActivityCompat.requestPermissions(hubActivity, arrayOf( Manifest.permission.ACCESS_FINE_LOCATION ), @@ -164,59 +197,56 @@ class TransactionActivity : AppCompatActivity() { if (lat != null && lng != null) { binding.locationText.text = loc.toString() } else { - binding.locationText.text = getString(R.string.no_location_data) + binding.locationText.text = savedContext.getString(R.string.no_location_data) } } - // Header back button - private fun onBackClick(view: View) { - onBackPressed() - } - private fun onSubmitClick(view: View){ val title = binding.titleInput.text.toString() val category = binding.categoryInput.selectedItem.toString() val amount = binding.amountInput.text.toString() if (title.isEmpty()){ - Toast.makeText(this, getString(R.string.transaction_add_toast_error_title), Toast.LENGTH_SHORT).show() + Toast.makeText(savedContext, savedContext.getString(R.string.transaction_add_toast_error_title), Toast.LENGTH_SHORT).show() } else if (amount.isEmpty()){ - Toast.makeText(this, getString(R.string.transaction_add_toast_error_amount), Toast.LENGTH_SHORT).show() + Toast.makeText(savedContext, savedContext.getString(R.string.transaction_add_toast_error_amount), Toast.LENGTH_SHORT).show() } else{ when (actionCode){ ACTION_ADD -> { - transactionViewModel.insert( - TransactionEntity( - id = 0, - title = title, - category = category, - amount = amount.toInt(), - timestamp = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(Date()), - latitude = savedLat, - longitude = savedLng - ) + transactionViewModel.insert( + TransactionEntity( + id = 0, + title = title, + category = category, + amount = amount.toInt(), + timestamp = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format( + Date() + ), + latitude = savedLat, + longitude = savedLng ) - Toast.makeText(this, getString(R.string.transaction_add_toast_success), Toast.LENGTH_SHORT).show() - } + ) + Toast.makeText(savedContext, savedContext.getString(R.string.transaction_add_toast_success), Toast.LENGTH_SHORT).show() + } ACTION_EDIT -> { transactionViewModel.update( TransactionEntity( - id = intent.getIntExtra(KEY_TRANSACTION_ID, 0), + id = requireArguments().getInt(KEY_TRANSACTION_ID, 0), title = title, category = category, amount = amount.toInt(), - timestamp = intent.getStringExtra(KEY_TIMESTAMP)!!, + timestamp = requireArguments().getString(KEY_TIMESTAMP)!!, latitude = savedLat, longitude = savedLng ) ) - Toast.makeText(this, getString(R.string.transaction_edit_toast_success), Toast.LENGTH_SHORT).show() + Toast.makeText(savedContext, savedContext.getString(R.string.transaction_edit_toast_success), Toast.LENGTH_SHORT).show() } } - onBackPressed() + hubActivity.onBackPressed() } } diff --git a/app/src/main/java/com/example/bondoman/ui/hub/settings/ExcelDialogFragment.kt b/app/src/main/java/com/example/bondoman/ui/hub/settings/ExcelDialogFragment.kt index 75766a8695ab6b1820f13982e33e1d3109fc8bf9..fe77a8cb53b73e8724549179a9fa24bc40d54b3b 100644 --- a/app/src/main/java/com/example/bondoman/ui/hub/settings/ExcelDialogFragment.kt +++ b/app/src/main/java/com/example/bondoman/ui/hub/settings/ExcelDialogFragment.kt @@ -2,7 +2,6 @@ package com.example.bondoman.ui.hub.settings import android.app.AlertDialog import android.app.Dialog -import android.content.DialogInterface import android.os.Bundle import androidx.fragment.app.DialogFragment import com.example.bondoman.R @@ -21,11 +20,10 @@ class ExcelDialogFragment : DialogFragment() { val builder = AlertDialog.Builder(it) builder .setTitle(R.string.excel_dialog_label) - .setPositiveButton(R.string.excel_dialog_positive, DialogInterface.OnClickListener { _, _ -> listener.onExcelDialogPositiveClick(this)}) - .setNegativeButton(R.string.excel_dialog_negative, DialogInterface.OnClickListener { _, _ -> listener.onExcelDialogNegativeClick(this)}) - .setSingleChoiceItems( - arrayOf(".xlsx", ".xls"), 0 - ) { _, index -> listener.onExcelDialogChoiceClick(this, index) } + .setPositiveButton(R.string.excel_dialog_positive) { _, _ -> listener.onExcelDialogPositiveClick(this) } + .setNegativeButton(R.string.excel_dialog_negative) { _, _ -> listener.onExcelDialogNegativeClick(this) } + .setSingleChoiceItems(arrayOf(".xlsx", ".xls"), 0) + { _, index -> listener.onExcelDialogChoiceClick(this, index) } builder.create() } ?: throw IllegalStateException("Activity cannot be null") } diff --git a/app/src/main/java/com/example/bondoman/ui/hub/transaction/DeleteConfirmDialogFragment.kt b/app/src/main/java/com/example/bondoman/ui/hub/transaction/DeleteConfirmDialogFragment.kt index 9259d4b088f5a410cd53e75f3668ba48bd599af7..cf3d11ce3eb2d7079e9a36d5cd5c19614d255d74 100644 --- a/app/src/main/java/com/example/bondoman/ui/hub/transaction/DeleteConfirmDialogFragment.kt +++ b/app/src/main/java/com/example/bondoman/ui/hub/transaction/DeleteConfirmDialogFragment.kt @@ -2,7 +2,6 @@ package com.example.bondoman.ui.hub.transaction import android.app.AlertDialog import android.app.Dialog -import android.content.DialogInterface import android.os.Bundle import androidx.fragment.app.DialogFragment import com.example.bondoman.R @@ -20,8 +19,8 @@ class DeleteConfirmDialogFragment : DialogFragment() { val builder = AlertDialog.Builder(it) builder .setTitle(R.string.delete_confirm_dialog_label) - .setPositiveButton(R.string.delete_confirm_dialog_positive, DialogInterface.OnClickListener { _, _ -> listener.onDeleteDialogPositiveClick(this)}) - .setNegativeButton(R.string.delete_confirm_dialog_negative, DialogInterface.OnClickListener { _, _ -> listener.onDeleteDialogNegativeClick(this)}) + .setPositiveButton(R.string.delete_confirm_dialog_positive) { _, _ -> listener.onDeleteDialogPositiveClick(this) } + .setNegativeButton(R.string.delete_confirm_dialog_negative) { _, _ -> listener.onDeleteDialogNegativeClick(this) } builder.create() } ?: throw IllegalStateException("Activity cannot be null") } diff --git a/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionAdapter.kt b/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionAdapter.kt index bee7390ac2810cd9f03a70356bac39eb81b87f8e..1836697ba7133d747da397e5e2fe4058e5859a0c 100644 --- a/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionAdapter.kt +++ b/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionAdapter.kt @@ -6,6 +6,7 @@ import android.location.Geocoder import android.location.Geocoder.GeocodeListener import android.net.Uri import android.os.Build +import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -15,7 +16,7 @@ import androidx.recyclerview.widget.RecyclerView import com.example.bondoman.R import com.example.bondoman.database.entity.TransactionEntity import com.example.bondoman.databinding.ItemTransactionBinding -import com.example.bondoman.ui.transaction.TransactionActivity +import com.example.bondoman.ui.hub.addtransaction.AddTransactionFragment import com.example.bondoman.viewmodel.transaction.TransactionViewModel import java.text.NumberFormat import java.util.Locale @@ -89,18 +90,24 @@ class TransactionAdapter( } btnEdit.setOnClickListener { - val intent = Intent(context, TransactionActivity::class.java) - intent.putExtra(TransactionActivity.KEY_ACTION, TransactionActivity.ACTION_EDIT) + val bundle = Bundle() + bundle.putInt(AddTransactionFragment.KEY_ACTION, AddTransactionFragment.ACTION_EDIT) // TODO: Consider serializing or just pass the id and read it from the transaction page. Might offer better performance though - intent.putExtra(TransactionActivity.KEY_TRANSACTION_ID, tsList[position].id) - intent.putExtra(TransactionActivity.KEY_TITLE, tsList[position].title) - intent.putExtra(TransactionActivity.KEY_AMOUNT, tsList[position].amount) - intent.putExtra(TransactionActivity.KEY_CATEGORY, context.resources.getStringArray(R.array.category_choices).indexOf(tsList[position].category)) - intent.putExtra(TransactionActivity.KEY_LOCATION, location) - intent.putExtra(TransactionActivity.KEY_TIMESTAMP, tsList[position].timestamp) - - context.startActivity(intent) + bundle.putInt(AddTransactionFragment.KEY_TRANSACTION_ID, tsList[position].id) + bundle.putString(AddTransactionFragment.KEY_TITLE, tsList[position].title) + bundle.putInt(AddTransactionFragment.KEY_AMOUNT, tsList[position].amount) + bundle.putInt(AddTransactionFragment.KEY_CATEGORY, context.resources.getStringArray(R.array.category_choices).indexOf(tsList[position].category)) + bundle.putString(AddTransactionFragment.KEY_LOCATION, location) + bundle.putString(AddTransactionFragment.KEY_TIMESTAMP, tsList[position].timestamp) + + val transaction = fragmentManager.beginTransaction() + val fragment = AddTransactionFragment() + fragment.arguments = bundle + + transaction.replace(R.id.nav_host_fragment_activity_main, fragment) + transaction.addToBackStack(null) + transaction.commit() } btnDelete.setOnClickListener { diff --git a/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionFragment.kt b/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionFragment.kt index 860e0025e60c6081c3b6568e2d59ac4691b50d4b..4b06671e6ed5a1c6d92d40b24cc776f40c8137f4 100644 --- a/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionFragment.kt +++ b/app/src/main/java/com/example/bondoman/ui/hub/transaction/TransactionFragment.kt @@ -1,6 +1,5 @@ package com.example.bondoman.ui.hub.transaction -import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,7 +11,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.example.bondoman.R import com.example.bondoman.databinding.FragmentTransactionBinding import com.example.bondoman.ui.hub.HubActivity -import com.example.bondoman.ui.transaction.TransactionActivity +import com.example.bondoman.ui.hub.addtransaction.AddTransactionFragment import com.example.bondoman.viewmodel.transaction.TransactionViewModel class TransactionFragment : Fragment(){ @@ -36,7 +35,7 @@ class TransactionFragment : Fragment(){ tsViewModel = (requireActivity() as HubActivity).transactionViewModel viewLifecycleOwner.lifecycleScope.launchWhenStarted { - val header = requireActivity().findViewById<TextView>(R.id.nav_title) + val header = (requireActivity() as HubActivity).findViewById<TextView>(R.id.nav_title) header.text = getString(R.string.hub_nav_transaction) } @@ -47,7 +46,10 @@ class TransactionFragment : Fragment(){ } private fun onAddClick(view: View){ - val intent = Intent(requireContext(), TransactionActivity::class.java) - startActivity(intent) + val transaction = requireActivity().supportFragmentManager.beginTransaction() + val fragment = AddTransactionFragment() + transaction.replace(R.id.nav_host_fragment_activity_main, fragment) + transaction.addToBackStack(null) + transaction.commit() } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoman/ui/transaction/RandomBroadcastReceiver.kt b/app/src/main/java/com/example/bondoman/ui/transaction/RandomBroadcastReceiver.kt deleted file mode 100644 index 8f2996d1548ff56bc61d7c095c7ee133d7e1d9d6..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/bondoman/ui/transaction/RandomBroadcastReceiver.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.example.bondoman.ui.transaction - -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent - -class RandomBroadcastReceiver : BroadcastReceiver() { - override fun onReceive(context: Context?, intent: Intent?) { - val randomIntent = Intent(context, TransactionActivity::class.java) - randomIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - randomIntent.putExtra(TransactionActivity.KEY_TITLE, "apa") - randomIntent.putExtra(TransactionActivity.KEY_AMOUNT, 0) - randomIntent.putExtra(TransactionActivity.KEY_CATEGORY, TransactionActivity.CATEGORY_INCOME) - context?.startActivity(randomIntent) - } -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_hub.xml b/app/src/main/res/layout/activity_hub.xml index 3b97449bd165b4aaf7d94803b087ae73a25575b8..0fdc1afb812c3cf721a7ca6a92473c865367dc8c 100644 --- a/app/src/main/res/layout/activity_hub.xml +++ b/app/src/main/res/layout/activity_hub.xml @@ -10,7 +10,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" + app:layout_constraintStart_toEndOf="@id/nav_view_landscape" app:layout_constraintTop_toTopOf="parent"> <include @@ -30,6 +30,17 @@ app:layout_constraintRight_toRightOf="parent" app:menu="@menu/menu_hub_bottom_nav" /> + <com.google.android.material.navigation.NavigationView + android:id="@+id/nav_view_landscape" + android:layout_width="70dp" + android:layout_height="match_parent" + android:background="?android:attr/windowBackground" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:menu="@menu/menu_hub_bottom_nav" + /> + <fragment android:id="@+id/nav_host_fragment_activity_main" android:name="androidx.navigation.fragment.NavHostFragment" @@ -37,7 +48,7 @@ android:layout_height="0dp" app:defaultNavHost="true" app:layout_constraintBottom_toTopOf="@id/nav_view" - app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintLeft_toRightOf="@id/nav_view_landscape" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/header" app:navGraph="@navigation/hub_navigation" /> diff --git a/app/src/main/res/layout/fragment_add_transaction.xml b/app/src/main/res/layout/fragment_add_transaction.xml new file mode 100644 index 0000000000000000000000000000000000000000..3cfb989a35e5db882711e8d7e2491128c3baeff9 --- /dev/null +++ b/app/src/main/res/layout/fragment_add_transaction.xml @@ -0,0 +1,151 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="?attr/background"> + + <ScrollView + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toTopOf="parent"> + + <LinearLayout + android:id="@+id/login_cluster" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginHorizontal="30dp" + android:layout_marginTop="20dp" + android:orientation="vertical"> + + <TextView + android:id="@+id/title_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/transaction_label_title" + android:textColor="?android:textColorPrimary" + android:textSize="10pt" /> + + <EditText + android:id="@+id/title_input" + android:layout_width="match_parent" + android:layout_height="16pt" + android:background="@color/gray" + android:ems="10" + android:inputType="text" + android:paddingHorizontal="10sp" + android:textColor="@color/black" /> + + <TextView + android:id="@+id/amount_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="5pt" + android:text="@string/transaction_label_amount" + android:textColor="?android:textColorPrimary" + android:textSize="10pt" /> + + <EditText + android:id="@+id/amount_input" + android:layout_width="match_parent" + android:layout_height="16pt" + android:background="@color/gray" + android:ems="10" + android:inputType="numberDecimal" + android:paddingHorizontal="10sp" + android:textColor="@color/black" /> + + <TextView + android:id="@+id/category_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="5pt" + android:text="@string/transaction_label_category" + android:textColor="?android:textColorPrimary" + android:textSize="10pt" /> + + <Spinner + android:id="@+id/category_input" + android:layout_width="match_parent" + android:layout_height="16pt" + android:background="@color/gray" + android:entries="@array/category_choices" /> + + <TextView + android:id="@+id/location_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="5pt" + android:text="@string/transaction_label_location" + android:textColor="?android:textColorPrimary" + android:textSize="10pt" /> + + <androidx.constraintlayout.widget.ConstraintLayout + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <TextView + android:id="@+id/location_text" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginEnd="8dp" + android:paddingHorizontal="0dp" + android:text="@string/no_location_data" + android:textColor="?android:textColorPrimary" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toStartOf="@+id/btnLocate" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <ImageButton + android:id="@+id/btnLocate" + android:layout_width="48dp" + android:layout_height="40dp" + android:adjustViewBounds="true" + android:backgroundTint="@color/purple_500" + android:contentDescription="@string/get_latest_location" + android:paddingHorizontal="5dp" + android:paddingVertical="10dp" + android:scaleType="centerInside" + app:layout_constraintBottom_toBottomOf="@+id/location_text" + app:layout_constraintEnd_toStartOf="@+id/btnDelete" + app:layout_constraintTop_toTopOf="@+id/location_text" + app:srcCompat="@drawable/ic_hub_location" + app:tint="@color/white" /> + + <ImageButton + android:id="@+id/btnDelete" + android:layout_width="48dp" + android:layout_height="40dp" + android:adjustViewBounds="true" + android:backgroundTint="@color/red" + android:contentDescription="@string/delete_location" + android:paddingHorizontal="5dp" + android:paddingVertical="10dp" + android:scaleType="centerInside" + app:layout_constraintBottom_toBottomOf="@+id/btnLocate" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="@+id/btnLocate" + app:srcCompat="@drawable/ic_trash" + app:tint="@color/white" /> + + </androidx.constraintlayout.widget.ConstraintLayout> + + <Button + android:id="@+id/submit_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginTop="10pt" + android:layout_marginBottom="60dp" + android:text="@string/transaction_label_submit" /> + + </LinearLayout> + + </ScrollView> + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_scan.xml b/app/src/main/res/layout/fragment_scan.xml index 4d56e0d9535751fae3b7e28577aae031c85a812f..b41fe01cf251c62d6cfa3ac9888b78ef2fc503ff 100644 --- a/app/src/main/res/layout/fragment_scan.xml +++ b/app/src/main/res/layout/fragment_scan.xml @@ -4,7 +4,8 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ui.hub.scan.ScanFragment"> + tools:context=".ui.hub.scan.ScanFragment" + android:background="?attr/background"> <androidx.camera.view.PreviewView android:id="@+id/viewFinder" diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index 76c0fba574571cf1cf6bce1811063c147be50790..774eef39214c96bcccc8343c89444e9e0c84b6c0 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -4,7 +4,8 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ui.hub.settings.SettingsFragment"> + tools:context=".ui.hub.settings.SettingsFragment" + android:background="?attr/background"> <com.google.android.material.button.MaterialButton android:id="@+id/button_save_transaction" diff --git a/app/src/main/res/layout/fragment_stats.xml b/app/src/main/res/layout/fragment_stats.xml index 01af542cc2023f0eb2386abb72a8289336949223..f712137eaf2a542aaf9823b7a4cd1b546c6e1c50 100644 --- a/app/src/main/res/layout/fragment_stats.xml +++ b/app/src/main/res/layout/fragment_stats.xml @@ -4,7 +4,8 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ui.hub.stats.StatsFragment"> + tools:context=".ui.hub.stats.StatsFragment" + android:background="?attr/background"> <com.github.mikephil.charting.charts.PieChart android:id="@+id/pieChart" diff --git a/app/src/main/res/layout/fragment_transaction.xml b/app/src/main/res/layout/fragment_transaction.xml index a82a41380a0dd8756bfd533d41f984f6fe854cc9..6817c6d6d135834159416b7476b4757e31c12191 100644 --- a/app/src/main/res/layout/fragment_transaction.xml +++ b/app/src/main/res/layout/fragment_transaction.xml @@ -4,13 +4,15 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ui.hub.transaction.TransactionFragment"> + tools:context=".ui.hub.transaction.TransactionFragment" + android:background="?attr/background"> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/add_transaction" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="20dp" + android:layout_marginBottom="20dp" android:backgroundTint="?android:attr/colorSecondary" android:clickable="true" android:src="@drawable/ic_plus" @@ -22,7 +24,6 @@ android:id="@+id/rvTransaction" android:layout_width="0dp" android:layout_height="0dp" - android:layout_marginBottom="40dp" tools:listitem="@layout/item_transaction" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/layout/fragment_twibbon.xml b/app/src/main/res/layout/fragment_twibbon.xml index 92b5b90663d4e37a556dace740c07ce502e9ef11..dc1071a5cf06f035fcc7a10292298563fc690683 100644 --- a/app/src/main/res/layout/fragment_twibbon.xml +++ b/app/src/main/res/layout/fragment_twibbon.xml @@ -4,7 +4,8 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ui.hub.twibbon.TwibbonFragment"> + tools:context=".ui.hub.twibbon.TwibbonFragment" + android:background="?attr/background"> <androidx.camera.view.PreviewView android:id="@+id/viewFinder" diff --git a/app/src/main/res/layout/item_transaction.xml b/app/src/main/res/layout/item_transaction.xml index 095653939d97577d5e7cacdd76a0ee6cca8e93d2..214c48502ca3a0f0f966e226568d67ef5bc9063b 100644 --- a/app/src/main/res/layout/item_transaction.xml +++ b/app/src/main/res/layout/item_transaction.xml @@ -96,6 +96,7 @@ app:layout_constraintBottom_toBottomOf="@+id/tvAmount" app:layout_constraintEnd_toStartOf="@+id/tvLocation" app:layout_constraintTop_toTopOf="@+id/tvAmount" + android:tint="?android:textColorPrimary" app:srcCompat="@drawable/ic_hub_location" /> <TextView diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml index a1c01f4a6eea8189e2f65ff7e3c4de8750814fca..38874c82718cc9edef41c7f3efc2f2360a8f5153 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/app/src/main/res/values-night/themes.xml @@ -1,6 +1,6 @@ <resources xmlns:tools="http://schemas.android.com/tools"> <!-- Base application theme. --> - <style name="Theme.BondoMan" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> + <style name="Theme.BondoMan" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <!-- Primary brand color. --> <item name="colorPrimary">@color/purple_200</item> <item name="colorPrimaryVariant">@color/purple_700</item> @@ -12,5 +12,6 @@ <!-- Status bar color. --> <item name="android:statusBarColor">?attr/colorPrimaryVariant</item> <!-- Customize your theme here. --> + <item name="background">@color/black</item> </style> </resources> \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 53c454ef290773897ca1ff0bc6e0de1c9400b71c..e25d3b98bc0198973ba5689df186f4cbbf8d78fb 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -12,5 +12,6 @@ <!-- Status bar color. --> <item name="android:statusBarColor">?attr/colorPrimaryVariant</item> <!-- Customize your theme here. --> + <item name="background">@color/white</item> </style> </resources> \ No newline at end of file