From af4d1bdec5259effc55f4fbe4cbd13fff32dc240 Mon Sep 17 00:00:00 2001 From: Adit Modhvadia Date: Tue, 27 Aug 2019 12:19:23 -0400 Subject: [PATCH 1/2] - add BagListActivity Boilerplate code and files - replace databasecall for Bag in ItemDetailActivity temporarily --- app/src/main/AndroidManifest.xml | 1 + .../baglist/BagListActivity.kt | 166 ++++++++++++++++++ .../baglist/BagListAdapter.kt | 89 ++++++++++ .../baglist/BagListViewModel.kt | 134 ++++++++++++++ .../baglist/BagListViewModelFactory.kt | 25 +++ .../database/InventoryItemDao.kt | 1 + .../itemdetail/ItemDetailViewModel.kt | 3 +- .../itemlist/ItemListActivity.kt | 24 +-- .../itemlist/ItemListViewModelFactory.kt | 2 - app/src/main/res/layout/activity_bag_list.xml | 16 ++ .../main/res/layout/activity_item_list.xml | 22 ++- app/src/main/res/layout/list_bag_item.xml | 83 +++++++++ app/src/main/res/menu/menu_search.xml | 11 +- app/src/main/res/values/strings.xml | 1 + 14 files changed, 555 insertions(+), 23 deletions(-) create mode 100644 app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListActivity.kt create mode 100644 app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListAdapter.kt create mode 100644 app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListViewModel.kt create mode 100644 app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListViewModelFactory.kt create mode 100644 app/src/main/res/layout/activity_bag_list.xml create mode 100644 app/src/main/res/layout/list_bag_item.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 729b4dd2..e6bfdb28 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -19,6 +19,7 @@ + \ No newline at end of file diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListActivity.kt b/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListActivity.kt new file mode 100644 index 00000000..89b0cb31 --- /dev/null +++ b/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListActivity.kt @@ -0,0 +1,166 @@ +package com.fazemeright.myinventorytracker.baglist + +import android.content.Intent +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.widget.SearchView +import androidx.databinding.DataBindingUtil +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProviders +import androidx.recyclerview.widget.LinearLayoutManager +import com.fazemeright.myinventorytracker.R +import com.fazemeright.myinventorytracker.addbag.AddBagActivity +import com.fazemeright.myinventorytracker.additem.AddItemActivity +import com.fazemeright.myinventorytracker.database.InventoryDatabase +import com.fazemeright.myinventorytracker.databinding.ActivityBagListBinding +import com.fazemeright.myinventorytracker.itemdetail.ItemDetailActivity +import com.google.android.material.snackbar.Snackbar + +class BagListActivity : AppCompatActivity() { + + private lateinit var searchView: SearchView + private lateinit var viewModel: BagListViewModel + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val binding: ActivityBagListBinding = + DataBindingUtil.setContentView(this, R.layout.activity_bag_list) + + val application = requireNotNull(this).application + + val dataSource = InventoryDatabase.getInstance(application) + + val viewModelFactory = BagListViewModelFactory(dataSource, application) + + viewModel = ViewModelProviders.of(this, viewModelFactory).get(BagListViewModel::class.java) + + binding.viewModel = viewModel + + binding.lifecycleOwner = this + + val manager = LinearLayoutManager(this) + +// binding.itemList.layoutManager = manager + + val adapter = BagListAdapter( + BagListAdapter.BagListener( + clickListener = { item -> + viewModel.onItemClicked(item) + }, + deleteClickListener = { itemId -> + showConfirmationDialog(itemId) +// TODO("Implement AlertDialog for confirmation before delete") +// viewModel.onDeleteItemClicked(itemId) + } + )) + +// binding.itemList.adapter = adapter + + viewModel.items.observe(this, Observer { + it?.let { + adapter.updateList(it) + } + }) + + viewModel.searchItems.observe(this, Observer { + it?.let { + adapter.updateList(it) + } + }) + + viewModel.deletedItem.observe(this, Observer { deletedItem -> + // Show a snack bar for undo option + Snackbar.make( + binding.root, // Parent view + "Item deleted from database.", // Message to show + Snackbar.LENGTH_LONG // + ).setAction( // Set an action for snack bar + "Undo" // Action button text + ) { + // Action button click listener + // Do something when undo action button clicked + viewModel.undoDeleteItem(deletedItem) + }.show() + }) + + viewModel.navigateToAddItemActivity.observe(this, Observer { navigate -> + if (navigate) { + startActivity(Intent(this, AddItemActivity::class.java)) + viewModel.onNavigationToAddItemFinished() + } + }) + + viewModel.navigateToItemDetailActivity.observe(this, Observer { itemInBag -> + itemInBag?.let { + val intent = Intent(this, ItemDetailActivity::class.java) + .apply { putExtra("itemInBag", it) } + startActivity(intent) + viewModel.onNavigationToItemDetailFinished() + } + }) + + viewModel.bags.observe(this, Observer { bagList -> + bagList?.let { + adapter.updateBagList(bagList) + } + }) + } + + private fun showConfirmationDialog(itemId: Long) { + // build alert dialog + val dialogBuilder = AlertDialog.Builder(this) + + // set message of alert dialog + dialogBuilder + // set title for alert dialog box + .setTitle("Are you sure") + .setMessage("Do you want to delete this entry?") + // if the dialog is cancelable + .setCancelable(false) + // positive button text and action + .setPositiveButton("Yes") { _, _ -> + viewModel.onDeleteItemClicked(itemId) + } + // negative button text and action + .setNegativeButton("No") { dialog, _ -> + dialog.cancel() + } + + // create dialog box + val alert = dialogBuilder.create() + // show alert dialog + alert.show() + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + val inflater = menuInflater + inflater.inflate(R.menu.menu_search, menu) + val searchItem = menu!!.findItem(R.id.action_search) + searchView = searchItem.actionView as SearchView + searchView.isSubmitButtonEnabled = true + searchView.queryHint = "Search Inventory for Items" + searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { + override fun onQueryTextChange(newText: String): Boolean { + viewModel.onSearchClicked(newText) + return true + } + + override fun onQueryTextSubmit(query: String): Boolean { + viewModel.onSearchClicked(query) + return true + } + }) + return super.onCreateOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + R.id.action_add_bag -> startActivity(Intent(this, AddBagActivity::class.java)) + } + return true + } +} diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListAdapter.kt b/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListAdapter.kt new file mode 100644 index 00000000..8afece00 --- /dev/null +++ b/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListAdapter.kt @@ -0,0 +1,89 @@ +package com.fazemeright.myinventorytracker.baglist + +import android.util.Log +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.fazemeright.myinventorytracker.database.BagItem +import com.fazemeright.myinventorytracker.database.InventoryItemDao +import com.fazemeright.myinventorytracker.databinding.ListBagItemBinding +import com.fazemeright.myinventorytracker.databinding.ListInventoryItemBinding +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers + +class BagListAdapter(private val clickListener: BagListener) : + ListAdapter(ItemListDiffCallback()) { + + private lateinit var bagsList: List + + private val adapterScope = CoroutineScope(Dispatchers.Default) + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder.from(parent) + } + + fun updateList(list: List?) { + Log.d("##DebugData", list.toString()) + submitList(list) + } + + fun updateBagList(updatedList: List) { + this.bagsList = updatedList + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val item = getItem(position) + holder.bind(item, clickListener) + } + + class ViewHolder private constructor(val binding: ListBagItemBinding) : + RecyclerView.ViewHolder(binding.root) { + + + fun bind( + item: InventoryItemDao.ItemInBag, + clickListener: BagListener + ) { + binding.item = item + binding.clickListener = clickListener + binding.executePendingBindings() + } + + companion object { + fun from(parent: ViewGroup): ViewHolder { + val layoutInflater = LayoutInflater.from(parent.context) + val binding = ListBagItemBinding.inflate(layoutInflater, parent, false) + return ViewHolder(binding) + } + } + } + + class ItemListDiffCallback : + DiffUtil.ItemCallback() { + override fun areItemsTheSame( + oldItem: InventoryItemDao.ItemInBag, + newItem: InventoryItemDao.ItemInBag + ): Boolean { + return oldItem.itemId == newItem.itemId + } + + override fun areContentsTheSame( + oldItem: InventoryItemDao.ItemInBag, + newItem: InventoryItemDao.ItemInBag + ): Boolean { + return oldItem == newItem + } + + } + + class BagListener( + val clickListener: (item: InventoryItemDao.ItemInBag) -> Unit, + val deleteClickListener: (itemId: Long) -> Unit + ) { + fun onClick(item: InventoryItemDao.ItemInBag) = clickListener(item) + fun onDeleteClick(item: InventoryItemDao.ItemInBag) = deleteClickListener(item.itemId) + } +} diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListViewModel.kt b/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListViewModel.kt new file mode 100644 index 00000000..185cf605 --- /dev/null +++ b/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListViewModel.kt @@ -0,0 +1,134 @@ +/* + * Copyright 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.fazemeright.myinventorytracker.baglist + +import android.app.Application +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.fazemeright.myinventorytracker.database.InventoryDatabase +import com.fazemeright.myinventorytracker.database.InventoryItem +import com.fazemeright.myinventorytracker.database.InventoryItemDao +import kotlinx.coroutines.* + +/** + * ViewModel for SleepTrackerFragment. + */ +class BagListViewModel( + val database: InventoryDatabase, + application: Application +) : AndroidViewModel(application) { + + /** + * viewModelJob allows us to cancel all coroutines started by this ViewModel. + */ + private var viewModelJob = Job() + /** + * A [CoroutineScope] keeps track of all coroutines started by this ViewModel. + * + * Because we pass it [viewModelJob], any coroutine started in this uiScope can be cancelled + * by calling `viewModelJob.cancel()` + * + * By default, all coroutines started in uiScope will launch in [Dispatchers.Main] which is + * the main thread on Android. This is a sensible default because most coroutines started by + * a [ViewModel] update the UI after performing some processing. + */ + private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob) + + val searchItems: LiveData> + get() = _searchItems + + private val _searchItems = MutableLiveData>() + +// val items = database.inventoryItemDao.getAllItems() + + val items = database.inventoryItemDao.getAllItemsWithBag() + + val bags = database.bagItemDao.getAllBags() + + val navigateToItemDetailActivity = MutableLiveData() + + val navigateToAddItemActivity = MutableLiveData() + + val deletedItem = MutableLiveData() + + init { + onSearchClicked("") + } + + fun onSearchClicked(searchText: String) { + uiScope.launch { + fetchSearchResults(searchText) + } + } + + private suspend fun fetchSearchResults(searchText: String) { + withContext(Dispatchers.IO) { + updateItems(database.inventoryItemDao.getSearchItems("%$searchText%")) + } + } + + private suspend fun updateItems(newItems: List) { + withContext(Dispatchers.Main) { + _searchItems.value = newItems + } + } + + fun addItemClicked() { + navigateToAddItemActivity.value = true + } + + fun onNavigationToAddItemFinished() { + navigateToAddItemActivity.value = false + } + + fun onItemClicked(item: InventoryItemDao.ItemInBag) { + navigateToItemDetailActivity.value = item + } + + fun onNavigationToItemDetailFinished() { + navigateToItemDetailActivity.value = null + } + + fun onDeleteItemClicked(itemId: Long) { + uiScope.launch { + deletedItem.value = deleteItem(itemId) + } + } + + private suspend fun deleteItem(itemId: Long): InventoryItem? { + return withContext(Dispatchers.IO) { + val deleteItem = database.inventoryItemDao.get(itemId) + deleteItem?.let { + database.inventoryItemDao.deleteItem(it) + } + deleteItem + } + } + + fun undoDeleteItem(deletedItem: InventoryItem?) { + uiScope.launch { + insertItemBack(deletedItem) + } + } + + private suspend fun insertItemBack(deletedItem: InventoryItem?) { + withContext(Dispatchers.IO) { + deletedItem?.let { database.inventoryItemDao.insert(it) } + } + } +} diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListViewModelFactory.kt b/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListViewModelFactory.kt new file mode 100644 index 00000000..511de05b --- /dev/null +++ b/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListViewModelFactory.kt @@ -0,0 +1,25 @@ +package com.fazemeright.myinventorytracker.baglist + +import android.app.Application +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.fazemeright.myinventorytracker.database.InventoryDatabase + +/** + * This is pretty much boiler plate code for a ViewModel Factory. + * + * Provides the SleepDatabaseDao and context to the ViewModel. + */ +class BagListViewModelFactory( + private val dataSource: InventoryDatabase, + private val application: Application +) : ViewModelProvider.Factory { + @Suppress("unchecked_cast") + override fun create(modelClass: Class): T { + if (modelClass.isAssignableFrom(BagListViewModel::class.java)) { + return BagListViewModel(dataSource, application) as T + } + throw IllegalArgumentException("Unknown ViewModel class") + } +} + diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/database/InventoryItemDao.kt b/app/src/main/java/com/fazemeright/myinventorytracker/database/InventoryItemDao.kt index 2a763509..3f35b621 100644 --- a/app/src/main/java/com/fazemeright/myinventorytracker/database/InventoryItemDao.kt +++ b/app/src/main/java/com/fazemeright/myinventorytracker/database/InventoryItemDao.kt @@ -102,6 +102,7 @@ interface InventoryItemDao { @Query("DELETE FROM my_inventory_table WHERE itemId =:itemId") fun delete(itemId: Long) + // TODO: Check why it does not return the correct bag and also update it to return LiveData @Query("SELECT * FROM my_inventory_table INNER JOIN my_bag_table WHERE itemId = :itemId") fun getItemInBagFromId(itemId: Long): ItemInBag } diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/itemdetail/ItemDetailViewModel.kt b/app/src/main/java/com/fazemeright/myinventorytracker/itemdetail/ItemDetailViewModel.kt index 4109ca68..379880b9 100644 --- a/app/src/main/java/com/fazemeright/myinventorytracker/itemdetail/ItemDetailViewModel.kt +++ b/app/src/main/java/com/fazemeright/myinventorytracker/itemdetail/ItemDetailViewModel.kt @@ -38,7 +38,8 @@ class ItemDetailViewModel( init { uiScope.launch { - item.value = getItemInBagFromId(itemInBag.itemId) + item.value = itemInBag +// item.value = getItemInBagFromId(itemInBag.itemId) TODO: Check Implementation in @BagItemDao } } diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/itemlist/ItemListActivity.kt b/app/src/main/java/com/fazemeright/myinventorytracker/itemlist/ItemListActivity.kt index 54cef0e4..95d66c01 100644 --- a/app/src/main/java/com/fazemeright/myinventorytracker/itemlist/ItemListActivity.kt +++ b/app/src/main/java/com/fazemeright/myinventorytracker/itemlist/ItemListActivity.kt @@ -12,8 +12,9 @@ import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.LinearLayoutManager import com.fazemeright.myinventorytracker.R -import com.fazemeright.myinventorytracker.additem.AddItemActivity import com.fazemeright.myinventorytracker.addbag.AddBagActivity +import com.fazemeright.myinventorytracker.additem.AddItemActivity +import com.fazemeright.myinventorytracker.baglist.BagListActivity import com.fazemeright.myinventorytracker.database.InventoryDatabase import com.fazemeright.myinventorytracker.databinding.ActivityItemListBinding import com.fazemeright.myinventorytracker.itemdetail.ItemDetailActivity @@ -27,7 +28,8 @@ class ItemListActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val binding: ActivityItemListBinding = DataBindingUtil.setContentView(this, R.layout.activity_item_list) + val binding: ActivityItemListBinding = + DataBindingUtil.setContentView(this, R.layout.activity_item_list) val application = requireNotNull(this).application @@ -45,16 +47,17 @@ class ItemListActivity : AppCompatActivity() { binding.itemList.layoutManager = manager - val adapter = ItemListAdapter(ItemListAdapter.ItemListener( - clickListener = { item -> - viewModel.onItemClicked(item) - }, - deleteClickListener = { itemId -> - showConfirmationDialog(itemId) + val adapter = ItemListAdapter( + ItemListAdapter.ItemListener( + clickListener = { item -> + viewModel.onItemClicked(item) + }, + deleteClickListener = { itemId -> + showConfirmationDialog(itemId) // TODO("Implement AlertDialog for confirmation before delete") // viewModel.onDeleteItemClicked(itemId) - } - )) + } + )) binding.itemList.adapter = adapter @@ -158,6 +161,7 @@ class ItemListActivity : AppCompatActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.action_add_bag -> startActivity(Intent(this, AddBagActivity::class.java)) + R.id.action_bag_list -> startActivity(Intent(this, BagListActivity::class.java)) } return true } diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/itemlist/ItemListViewModelFactory.kt b/app/src/main/java/com/fazemeright/myinventorytracker/itemlist/ItemListViewModelFactory.kt index e7b23d58..fa204b1e 100644 --- a/app/src/main/java/com/fazemeright/myinventorytracker/itemlist/ItemListViewModelFactory.kt +++ b/app/src/main/java/com/fazemeright/myinventorytracker/itemlist/ItemListViewModelFactory.kt @@ -1,11 +1,9 @@ - package com.fazemeright.myinventorytracker.itemlist import android.app.Application import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import com.fazemeright.myinventorytracker.database.InventoryDatabase -import com.fazemeright.myinventorytracker.database.InventoryItemDao /** * This is pretty much boiler plate code for a ViewModel Factory. diff --git a/app/src/main/res/layout/activity_bag_list.xml b/app/src/main/res/layout/activity_bag_list.xml new file mode 100644 index 00000000..8337a6cb --- /dev/null +++ b/app/src/main/res/layout/activity_bag_list.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_item_list.xml b/app/src/main/res/layout/activity_item_list.xml index 74a1ee56..9a4cbc6f 100644 --- a/app/src/main/res/layout/activity_item_list.xml +++ b/app/src/main/res/layout/activity_item_list.xml @@ -1,13 +1,20 @@ - + + - + + + + @@ -16,22 +23,23 @@ android:id="@+id/item_list" android:layout_width="match_parent" android:layout_height="0dp" + android:clipToPadding="false" android:paddingBottom="64dp" android:scrollbars="vertical" - android:clipToPadding="false" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent"/> + app:layout_constraintTop_toTopOf="parent" /> + + android:src="@drawable/ic_add_black_24dp" /> \ No newline at end of file diff --git a/app/src/main/res/layout/list_bag_item.xml b/app/src/main/res/layout/list_bag_item.xml new file mode 100644 index 00000000..972b9674 --- /dev/null +++ b/app/src/main/res/layout/list_bag_item.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_search.xml b/app/src/main/res/menu/menu_search.xml index 50497782..7fa0d09c 100644 --- a/app/src/main/res/menu/menu_search.xml +++ b/app/src/main/res/menu/menu_search.xml @@ -1,16 +1,21 @@ + xmlns:app="http://schemas.android.com/apk/res-auto"> + app:showAsAction="ifRoom|collapseActionView" /> + app:showAsAction="never" /> + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 633b564b..094df26f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -17,4 +17,5 @@ Add Item Update Item + Bag List From 9752ac23379e90f6c412923badc5ec512ab96bbf Mon Sep 17 00:00:00 2001 From: Adit Modhvadia Date: Wed, 28 Aug 2019 14:33:08 -0400 Subject: [PATCH 2/2] - add Display of all Bags - remove white textColor from Centred Edittext style --- .../myinventorytracker/BindingAdapters.kt | 13 ---- .../baglist/BagListActivity.kt | 43 ++++++------ .../baglist/BagListAdapter.kt | 30 ++++----- .../baglist/BagListViewModel.kt | 61 ++++++------------ .../myinventorytracker/database/BagItem.kt | 3 +- .../database/InventoryItemDao.kt | 3 + .../itemlist/ItemListActivity.kt | 4 +- app/src/main/res/drawable-anydpi/ic_edit.xml | 11 ++++ app/src/main/res/drawable-hdpi/ic_edit.png | Bin 0 -> 224 bytes app/src/main/res/drawable-mdpi/ic_edit.png | Bin 0 -> 163 bytes app/src/main/res/drawable-xhdpi/ic_edit.png | Bin 0 -> 251 bytes app/src/main/res/drawable-xxhdpi/ic_edit.png | Bin 0 -> 316 bytes app/src/main/res/layout/activity_bag_list.xml | 32 ++++++++- .../main/res/layout/activity_item_list.xml | 2 +- app/src/main/res/layout/list_bag_item.xml | 53 ++++----------- app/src/main/res/menu/menu_bag_list.xml | 11 ++++ .../{menu_search.xml => menu_item_list.xml} | 6 +- app/src/main/res/values/dimens.xml | 1 + 18 files changed, 127 insertions(+), 146 deletions(-) create mode 100644 app/src/main/res/drawable-anydpi/ic_edit.xml create mode 100644 app/src/main/res/drawable-hdpi/ic_edit.png create mode 100644 app/src/main/res/drawable-mdpi/ic_edit.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_edit.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_edit.png create mode 100644 app/src/main/res/menu/menu_bag_list.xml rename app/src/main/res/menu/{menu_search.xml => menu_item_list.xml} (81%) diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/BindingAdapters.kt b/app/src/main/java/com/fazemeright/myinventorytracker/BindingAdapters.kt index 890c12f8..15b31f77 100644 --- a/app/src/main/java/com/fazemeright/myinventorytracker/BindingAdapters.kt +++ b/app/src/main/java/com/fazemeright/myinventorytracker/BindingAdapters.kt @@ -1,21 +1,8 @@ package com.fazemeright.myinventorytracker -import android.graphics.Color import android.widget.TextView -import androidx.cardview.widget.CardView import androidx.databinding.BindingAdapter -@BindingAdapter("app:bgColor") -fun updateBackgroundColor(cardView: CardView, bagName: String) { - cardView.setBackgroundColor( - when (bagName) { - "Red" -> Color.parseColor("#C92214") - "Black AT" -> Color.parseColor("#000000") - else -> Color.parseColor("#0A3D62") - } - ) -} - @BindingAdapter("app:setBagName") fun setBagName(textView: TextView, bagName: String) { textView.text = bagName diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListActivity.kt b/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListActivity.kt index 89b0cb31..b6fb7eac 100644 --- a/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListActivity.kt +++ b/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListActivity.kt @@ -3,7 +3,6 @@ package com.fazemeright.myinventorytracker.baglist import android.content.Intent import android.os.Bundle import android.view.Menu -import android.view.MenuItem import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.SearchView @@ -13,11 +12,8 @@ import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.LinearLayoutManager import com.fazemeright.myinventorytracker.R import com.fazemeright.myinventorytracker.addbag.AddBagActivity -import com.fazemeright.myinventorytracker.additem.AddItemActivity import com.fazemeright.myinventorytracker.database.InventoryDatabase import com.fazemeright.myinventorytracker.databinding.ActivityBagListBinding -import com.fazemeright.myinventorytracker.itemdetail.ItemDetailActivity -import com.google.android.material.snackbar.Snackbar class BagListActivity : AppCompatActivity() { @@ -42,14 +38,20 @@ class BagListActivity : AppCompatActivity() { binding.lifecycleOwner = this + supportActionBar?.apply { + setHomeButtonEnabled(true) + setDisplayHomeAsUpEnabled(true) + title = getString(R.string.bag_list) + } + val manager = LinearLayoutManager(this) -// binding.itemList.layoutManager = manager + binding.bagList.layoutManager = manager val adapter = BagListAdapter( BagListAdapter.BagListener( clickListener = { item -> - viewModel.onItemClicked(item) + viewModel.onBagClicked(item) }, deleteClickListener = { itemId -> showConfirmationDialog(itemId) @@ -58,9 +60,9 @@ class BagListActivity : AppCompatActivity() { } )) -// binding.itemList.adapter = adapter + binding.bagList.adapter = adapter - viewModel.items.observe(this, Observer { + viewModel.bags.observe(this, Observer { it?.let { adapter.updateList(it) } @@ -72,7 +74,7 @@ class BagListActivity : AppCompatActivity() { } }) - viewModel.deletedItem.observe(this, Observer { deletedItem -> + /*viewModel.deletedItem.observe(this, Observer { deletedItem -> // Show a snack bar for undo option Snackbar.make( binding.root, // Parent view @@ -85,20 +87,20 @@ class BagListActivity : AppCompatActivity() { // Do something when undo action button clicked viewModel.undoDeleteItem(deletedItem) }.show() - }) + })*/ - viewModel.navigateToAddItemActivity.observe(this, Observer { navigate -> + viewModel.navigateToAddBagActivity.observe(this, Observer { navigate -> if (navigate) { - startActivity(Intent(this, AddItemActivity::class.java)) - viewModel.onNavigationToAddItemFinished() + startActivity(Intent(this, AddBagActivity::class.java)) + viewModel.onNavigationToAddBagFinished() } }) - viewModel.navigateToItemDetailActivity.observe(this, Observer { itemInBag -> + viewModel.navigateToBagDetailActivity.observe(this, Observer { itemInBag -> itemInBag?.let { - val intent = Intent(this, ItemDetailActivity::class.java) + /*val intent = Intent(this, ItemDetailActivity::class.java) .apply { putExtra("itemInBag", it) } - startActivity(intent) + startActivity(intent) TODO: Navigate to BagDetailActivity*/ viewModel.onNavigationToItemDetailFinished() } }) @@ -138,7 +140,7 @@ class BagListActivity : AppCompatActivity() { override fun onCreateOptionsMenu(menu: Menu?): Boolean { val inflater = menuInflater - inflater.inflate(R.menu.menu_search, menu) + inflater.inflate(R.menu.menu_bag_list, menu) val searchItem = menu!!.findItem(R.id.action_search) searchView = searchItem.actionView as SearchView searchView.isSubmitButtonEnabled = true @@ -156,11 +158,4 @@ class BagListActivity : AppCompatActivity() { }) return super.onCreateOptionsMenu(menu) } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - when (item.itemId) { - R.id.action_add_bag -> startActivity(Intent(this, AddBagActivity::class.java)) - } - return true - } } diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListAdapter.kt b/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListAdapter.kt index 8afece00..6294f772 100644 --- a/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListAdapter.kt +++ b/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListAdapter.kt @@ -7,14 +7,12 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.fazemeright.myinventorytracker.database.BagItem -import com.fazemeright.myinventorytracker.database.InventoryItemDao import com.fazemeright.myinventorytracker.databinding.ListBagItemBinding -import com.fazemeright.myinventorytracker.databinding.ListInventoryItemBinding import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers class BagListAdapter(private val clickListener: BagListener) : - ListAdapter(ItemListDiffCallback()) { private lateinit var bagsList: List @@ -25,7 +23,7 @@ class BagListAdapter(private val clickListener: BagListener) : return ViewHolder.from(parent) } - fun updateList(list: List?) { + fun updateList(list: List?) { Log.d("##DebugData", list.toString()) submitList(list) } @@ -44,7 +42,7 @@ class BagListAdapter(private val clickListener: BagListener) : fun bind( - item: InventoryItemDao.ItemInBag, + item: BagItem, clickListener: BagListener ) { binding.item = item @@ -62,28 +60,28 @@ class BagListAdapter(private val clickListener: BagListener) : } class ItemListDiffCallback : - DiffUtil.ItemCallback() { + DiffUtil.ItemCallback() { override fun areItemsTheSame( - oldItem: InventoryItemDao.ItemInBag, - newItem: InventoryItemDao.ItemInBag + oldBag: BagItem, + newBag: BagItem ): Boolean { - return oldItem.itemId == newItem.itemId + return oldBag.bagId == newBag.bagId } override fun areContentsTheSame( - oldItem: InventoryItemDao.ItemInBag, - newItem: InventoryItemDao.ItemInBag + oldBag: BagItem, + newBag: BagItem ): Boolean { - return oldItem == newItem + return oldBag == newBag } } class BagListener( - val clickListener: (item: InventoryItemDao.ItemInBag) -> Unit, - val deleteClickListener: (itemId: Long) -> Unit + val clickListener: (bag: BagItem) -> Unit, + val deleteClickListener: (bagId: Long) -> Unit ) { - fun onClick(item: InventoryItemDao.ItemInBag) = clickListener(item) - fun onDeleteClick(item: InventoryItemDao.ItemInBag) = deleteClickListener(item.itemId) + fun onClick(bag: BagItem) = clickListener(bag) + fun onDeleteClick(bag: BagItem) = deleteClickListener(bag.bagId) } } diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListViewModel.kt b/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListViewModel.kt index 185cf605..31ef3586 100644 --- a/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListViewModel.kt +++ b/app/src/main/java/com/fazemeright/myinventorytracker/baglist/BagListViewModel.kt @@ -1,32 +1,16 @@ -/* - * Copyright 2018, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.fazemeright.myinventorytracker.baglist import android.app.Application import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import com.fazemeright.myinventorytracker.database.BagItem import com.fazemeright.myinventorytracker.database.InventoryDatabase import com.fazemeright.myinventorytracker.database.InventoryItem -import com.fazemeright.myinventorytracker.database.InventoryItemDao import kotlinx.coroutines.* /** - * ViewModel for SleepTrackerFragment. + * ViewModel for BagListActivity. */ class BagListViewModel( val database: InventoryDatabase, @@ -45,26 +29,22 @@ class BagListViewModel( * * By default, all coroutines started in uiScope will launch in [Dispatchers.Main] which is * the main thread on Android. This is a sensible default because most coroutines started by - * a [ViewModel] update the UI after performing some processing. + * a [BagListViewModel] update the UI after performing some processing. */ private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob) - val searchItems: LiveData> + val searchItems: LiveData> get() = _searchItems - private val _searchItems = MutableLiveData>() - -// val items = database.inventoryItemDao.getAllItems() - - val items = database.inventoryItemDao.getAllItemsWithBag() + private val _searchItems = MutableLiveData>() val bags = database.bagItemDao.getAllBags() - val navigateToItemDetailActivity = MutableLiveData() + val navigateToBagDetailActivity = MutableLiveData() - val navigateToAddItemActivity = MutableLiveData() + val navigateToAddBagActivity = MutableLiveData() - val deletedItem = MutableLiveData() +// val deletedItem = MutableLiveData() init { onSearchClicked("") @@ -78,39 +58,40 @@ class BagListViewModel( private suspend fun fetchSearchResults(searchText: String) { withContext(Dispatchers.IO) { - updateItems(database.inventoryItemDao.getSearchItems("%$searchText%")) + updateItems(database.inventoryItemDao.getSearchBags("%$searchText%")) } } - private suspend fun updateItems(newItems: List) { + private suspend fun updateItems(newItems: List) { withContext(Dispatchers.Main) { _searchItems.value = newItems } } - fun addItemClicked() { - navigateToAddItemActivity.value = true + fun addBagClicked() { + navigateToAddBagActivity.value = true } - fun onNavigationToAddItemFinished() { - navigateToAddItemActivity.value = false + fun onNavigationToAddBagFinished() { + navigateToAddBagActivity.value = false } - fun onItemClicked(item: InventoryItemDao.ItemInBag) { - navigateToItemDetailActivity.value = item + fun onBagClicked(item: BagItem) { + navigateToBagDetailActivity.value = item } fun onNavigationToItemDetailFinished() { - navigateToItemDetailActivity.value = null + navigateToBagDetailActivity.value = null } + // TODO: Update all delete, undo and insert functions with BagItem fun onDeleteItemClicked(itemId: Long) { uiScope.launch { - deletedItem.value = deleteItem(itemId) + // deletedItem.value = deleteItem(itemId) } } - private suspend fun deleteItem(itemId: Long): InventoryItem? { + /*private suspend fun deleteItem(itemId: Long): InventoryItem? { return withContext(Dispatchers.IO) { val deleteItem = database.inventoryItemDao.get(itemId) deleteItem?.let { @@ -118,7 +99,7 @@ class BagListViewModel( } deleteItem } - } + }*/ fun undoDeleteItem(deletedItem: InventoryItem?) { uiScope.launch { diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/database/BagItem.kt b/app/src/main/java/com/fazemeright/myinventorytracker/database/BagItem.kt index d9c46122..54d12c03 100644 --- a/app/src/main/java/com/fazemeright/myinventorytracker/database/BagItem.kt +++ b/app/src/main/java/com/fazemeright/myinventorytracker/database/BagItem.kt @@ -2,6 +2,7 @@ package com.fazemeright.myinventorytracker.database import androidx.room.Entity import androidx.room.PrimaryKey +import java.io.Serializable @Entity(tableName = "my_bag_table") @@ -14,4 +15,4 @@ data class BagItem( var bagColor: Int, var bagDesc: String -) \ No newline at end of file +) : Serializable \ No newline at end of file diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/database/InventoryItemDao.kt b/app/src/main/java/com/fazemeright/myinventorytracker/database/InventoryItemDao.kt index 3f35b621..f7253b16 100644 --- a/app/src/main/java/com/fazemeright/myinventorytracker/database/InventoryItemDao.kt +++ b/app/src/main/java/com/fazemeright/myinventorytracker/database/InventoryItemDao.kt @@ -66,6 +66,9 @@ interface InventoryItemDao { @Query("SELECT * FROM my_inventory_table INNER JOIN my_bag_table WHERE itemName LIKE :searchText OR itemDesc LIKE :searchText ORDER BY itemName") fun getSearchItems(searchText: String): List + @Query("SELECT * FROM my_bag_table WHERE bagName LIKE :searchText OR bagDesc LIKE :searchText ORDER BY bagName") + fun getSearchBags(searchText: String): List + /*@Query("SELECT * FROM my_inventory_table INNER JOIN my_bag_table ON bagId = bagId") fun getAllItemsAndBags()*/ diff --git a/app/src/main/java/com/fazemeright/myinventorytracker/itemlist/ItemListActivity.kt b/app/src/main/java/com/fazemeright/myinventorytracker/itemlist/ItemListActivity.kt index 95d66c01..870a27a6 100644 --- a/app/src/main/java/com/fazemeright/myinventorytracker/itemlist/ItemListActivity.kt +++ b/app/src/main/java/com/fazemeright/myinventorytracker/itemlist/ItemListActivity.kt @@ -12,7 +12,6 @@ import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.LinearLayoutManager import com.fazemeright.myinventorytracker.R -import com.fazemeright.myinventorytracker.addbag.AddBagActivity import com.fazemeright.myinventorytracker.additem.AddItemActivity import com.fazemeright.myinventorytracker.baglist.BagListActivity import com.fazemeright.myinventorytracker.database.InventoryDatabase @@ -139,7 +138,7 @@ class ItemListActivity : AppCompatActivity() { override fun onCreateOptionsMenu(menu: Menu?): Boolean { val inflater = menuInflater - inflater.inflate(R.menu.menu_search, menu) + inflater.inflate(R.menu.menu_item_list, menu) val searchItem = menu!!.findItem(R.id.action_search) searchView = searchItem.actionView as SearchView searchView.isSubmitButtonEnabled = true @@ -160,7 +159,6 @@ class ItemListActivity : AppCompatActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { - R.id.action_add_bag -> startActivity(Intent(this, AddBagActivity::class.java)) R.id.action_bag_list -> startActivity(Intent(this, BagListActivity::class.java)) } return true diff --git a/app/src/main/res/drawable-anydpi/ic_edit.xml b/app/src/main/res/drawable-anydpi/ic_edit.xml new file mode 100644 index 00000000..b766187e --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_edit.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable-hdpi/ic_edit.png b/app/src/main/res/drawable-hdpi/ic_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..a3226fb9e794a12639c755605b5884a1c8b61566 GIT binary patch literal 224 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBmV3H5hE&{od&8Ei!GMP~!GFQ* zyIJAsABDL1;{4nXHecfqb&*=z?5SP(VVjfvFLRUADw9}})`nh?i#pa|ctLWPlX`|I zcUr3J!6mKihx?=iE;I&(+`huH$ZD1GW{2DCSN^=@s^t41n2Sh|Il{$m zrZW9N8r=s-4 XLy}&HUw6j?oy_3r>gTe~DWM4f48&2N literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_edit.png b/app/src/main/res/drawable-mdpi/ic_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..f0c1fafa7cb7c5688b565fa35bd66120d8e684f8 GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjS)MMAAr-fh6C_x-u>Jr4|2p%d zP6ruB?ZeL*KPGAPE#Agj=h1e!fMsh;9(U^R#gPURqYiH3=y-cUhq3c@pz)cBx*r#B zdnhsO!l8m$ET>mIT-^3}dqY{9v+jbq4=r>S%zGH2vtZrB#SG#M49xGZ_Ga!oTh8e2>xL;kgiwMz{KL+jkJpaZ{gGUR$C3q`6D_;93 zf3mRQ{MS?VpIXaN`EzZ@LDxFdL!Nb#7k8hEzFYZZqPrZF;OF=-^*`&6Q{ikcPK2{$ woD^q!aZ;Qm<5W7^i&N<=8K;>UWR9_1TJh~Rhy9lgK;JNUy85}Sb4q9e0C&l1mH+?% literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_edit.png b/app/src/main/res/drawable-xxhdpi/ic_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..40ef06e3673e2e0ab392503a81f2d4e278b8c59a GIT binary patch literal 316 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@Zgyv2U}W}maSW-r_4c+m*C7KDw}*VM z7nexW8KE}k?k$ozrRWfrZj4&Toj75|GLI4xXU)2!CK<#h)L=se$R-y(VV&h*an zwnq9g;?F)BZvVkI=e>o3>Vp?bxd$#fpE_{SiK|=2sNl&2y;cufkNxRezMZuUbDOoM zcEaPAKVk$kH?@3@3GrRB`s&&}Y?FS!o~!e4PH^<_#RIIw; - + @@ -8,9 +9,34 @@ type="com.fazemeright.myinventorytracker.baglist.BagListViewModel" /> - - + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_item_list.xml b/app/src/main/res/layout/activity_item_list.xml index 9a4cbc6f..92a2d174 100644 --- a/app/src/main/res/layout/activity_item_list.xml +++ b/app/src/main/res/layout/activity_item_list.xml @@ -24,7 +24,7 @@ android:layout_width="match_parent" android:layout_height="0dp" android:clipToPadding="false" - android:paddingBottom="64dp" + android:paddingBottom="@dimen/spacing_huge" android:scrollbars="vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/layout/list_bag_item.xml b/app/src/main/res/layout/list_bag_item.xml index 972b9674..8369b1b6 100644 --- a/app/src/main/res/layout/list_bag_item.xml +++ b/app/src/main/res/layout/list_bag_item.xml @@ -7,7 +7,7 @@ + type="com.fazemeright.myinventorytracker.database.BagItem" /> - - - + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:text="Bag Name" /> + android:onClick="@{() -> clickListener.onClick(item)}" + app:layout_constraintBottom_toBottomOf="@+id/tvBagName" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="@+id/tvBagName" + app:srcCompat="@drawable/ic_edit" /> \ No newline at end of file diff --git a/app/src/main/res/menu/menu_bag_list.xml b/app/src/main/res/menu/menu_bag_list.xml new file mode 100644 index 00000000..d2e1990d --- /dev/null +++ b/app/src/main/res/menu/menu_bag_list.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_search.xml b/app/src/main/res/menu/menu_item_list.xml similarity index 81% rename from app/src/main/res/menu/menu_search.xml rename to app/src/main/res/menu/menu_item_list.xml index 7fa0d09c..41288c9b 100644 --- a/app/src/main/res/menu/menu_search.xml +++ b/app/src/main/res/menu/menu_item_list.xml @@ -9,13 +9,9 @@ app:actionViewClass="androidx.appcompat.widget.SearchView" app:showAsAction="ifRoom|collapseActionView" /> - - + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 5790eb13..9a4dc882 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -2,4 +2,5 @@ 16dp 8dp + 64dp \ No newline at end of file