categories

This commit is contained in:
leca 2024-10-08 02:24:16 +03:00
parent a6c21f05f9
commit 5fb481a0d5
21 changed files with 297 additions and 90 deletions

View File

@ -45,6 +45,7 @@ dependencies {
implementation(libs.androidx.navigation.ui.ktx)
implementation(libs.firebase.crashlytics.buildtools)
implementation(libs.androidx.gridlayout)
implementation(libs.androidx.activity)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)

View File

@ -24,6 +24,9 @@
android:supportsRtl="true"
android:theme="@style/Theme.BarcodeScannerForEmployees"
tools:targetApi="31">
<activity
android:name=".activities.AddCategoryActivity"
android:exported="false"/>
<activity
android:name=".activities.AddProductActivity"
android:exported="false"

View File

@ -5,7 +5,7 @@ class AbstractProduct(
public var name: String,
public var netWeight: Double,
public var imageHash: String,
public var category: Int
public var categoryName: String
) {
}

View File

@ -0,0 +1,8 @@
package org.foxarmy.barcodescannerforemployees
class Category(
public var id: Int,
public var name: String,
) {
}

View File

@ -13,6 +13,7 @@ object ProductContract {
const val PRODUCT_NAME = "name"
const val PRODUCT_NET_WEIGHT = "net_weight"
const val IMAGE_FILENAME = "image_filename"
const val CATEGORY = "category"
}
}
@ -36,35 +37,38 @@ const val SQL_CREATE_PRODUCT_TABLE =
"${BaseColumns._ID} INTEGER PRIMARY KEY," +
"${ProductContract.ProductEntry.PRODUCT_NAME} TEXT," +
"${ProductContract.ProductEntry.PRODUCT_NET_WEIGHT} REAL," +
"${ProductContract.ProductEntry.IMAGE_FILENAME} TEXT)"
"${ProductContract.ProductEntry.IMAGE_FILENAME} TEXT," +
"${ProductContract.ProductEntry.CATEGORY} INTEGER)"
const val SQL_CREATE_SHELF_TABLE =
"CREATE TABLE ${ShelfContract.ShelfEntry.TABLE_NAME} (" +
"${BaseColumns._ID} INTEGER PRIMARY KEY," +
"${ShelfContract.ShelfEntry.PRODUCT_ID} INTEGER," +
"${ShelfContract.ShelfEntry.EXPIRE_DATE} DATE)"
const val SQL_CREATE_CATEGORIES_TABLE =
"CREATE TABLE ${CategoriesContract.CategoryEntry.TABLE_NAME} (" +
"${BaseColumns._ID} INTEGER PRIMARY KEY," +
"${CategoriesContract.CategoryEntry.CATEGORY_NAME} TEXT)"
class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
override fun onCreate(db: SQLiteDatabase) {
Log.d("QWERTYUIOP", SQL_CREATE_PRODUCT_TABLE)
db.execSQL(SQL_CREATE_PRODUCT_TABLE)
db.execSQL(SQL_CREATE_SHELF_TABLE)
db.execSQL(SQL_CREATE_CATEGORIES_TABLE)
}
override fun onUpgrade(p0: SQLiteDatabase?, p1: Int, p2: Int) {
override fun onUpgrade(db: SQLiteDatabase?, oldV: Int, newV: Int) {
TODO("Not yet implemented")
}
public fun eraseAbstractProduct(db: SQLiteDatabase, id: Int, context: Context) {
val projection = arrayOf(BaseColumns._ID,
val projection = arrayOf(
ProductContract.ProductEntry.IMAGE_FILENAME
)
// val cursor = db.query(ProductContract.ProductEntry.TABLE_NAME, projection, null, , null, null, null)
val selection = "${BaseColumns._ID} = ?"
val selectionArgs = arrayOf(id.toString())
val cursor = db.query(
@ -76,12 +80,10 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE
null,
null
)
// val cursor = db.rawQuery("SELECT image_filename FROM ${ProductContract.ProductEntry.TABLE_NAME} WHERE ${BaseColumns._ID}=$id", null)
var imageHash: String = ""
with (cursor) {
while(moveToNext()) {
val productId = getInt(getColumnIndexOrThrow(BaseColumns._ID))
val productImageHash = getString(getColumnIndexOrThrow(ProductContract.ProductEntry.IMAGE_FILENAME))
imageHash = productImageHash
}

View File

@ -0,0 +1,46 @@
package org.foxarmy.barcodescannerforemployees.activities
import android.app.Activity
import android.content.ContentValues
import android.os.Bundle
import android.provider.BaseColumns
import android.widget.Button
import android.widget.EditText
import org.foxarmy.barcodescannerforemployees.CategoriesContract
import org.foxarmy.barcodescannerforemployees.DBStorageController
import org.foxarmy.barcodescannerforemployees.R
class AddCategoryActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_category)
val extras = intent.extras
val categoryId = extras!!.get("categoryid") as Int?
val categoryName = extras.get("categoryname") as String?
val categoryNameTextEdit: EditText = findViewById(R.id.newCategoryName)
categoryNameTextEdit.setText(categoryName)
findViewById<Button>(R.id.saveButton).setOnClickListener {
val db = DBStorageController(this).writableDatabase
if (categoryId == 0) { // Inserting new category
val values = ContentValues().apply {
put(CategoriesContract.CategoryEntry.CATEGORY_NAME, categoryNameTextEdit.text.toString())
}
db.insert(CategoriesContract.CategoryEntry.TABLE_NAME, null, values)
} else { // Updating existing category
val values = ContentValues().apply {
put(CategoriesContract.CategoryEntry.CATEGORY_NAME, categoryNameTextEdit.text.toString())
}
db.update(CategoriesContract.CategoryEntry.TABLE_NAME, values, "${BaseColumns._ID} = ?", arrayOf(categoryId.toString()))
}
finish()
}
}
}

View File

@ -4,11 +4,9 @@ import android.Manifest
import android.content.ContentValues
import android.os.Build
import android.os.Bundle
import android.provider.BaseColumns
import android.util.Log
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import android.widget.*
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
@ -31,6 +29,8 @@ class AddProductActivity : AppCompatActivity() {
private lateinit var productNameText: TextView
private lateinit var netWeightText: TextView
private lateinit var categorySpinner: Spinner
private lateinit var pictureFile: File
private lateinit var picturesPath: File
private lateinit var binding: ActivityAddProductBinding
@ -43,7 +43,6 @@ class AddProductActivity : AppCompatActivity() {
picturesPath = File(filesDir, "pictures")
picturesPath.mkdirs()
// imageView = binding.includeContent.addProductLayout
imageView = findViewById(R.id.imageView)
saveButton = findViewById(R.id.saveButton)
@ -53,6 +52,10 @@ class AddProductActivity : AppCompatActivity() {
productNameText = findViewById(R.id.productName)
netWeightText = findViewById(R.id.netWeight)
categorySpinner = findViewById(R.id.categorySpinner)
fillupCategorySpinner()
saveButton.setOnClickListener {
val productName = productNameText.text.toString()
val netWeight = netWeightText.text
@ -70,13 +73,15 @@ class AddProductActivity : AppCompatActivity() {
}
val db = DBStorageController(this).writableDatabase
Log.d("QWERTYUIOP", "Putting ${pictureFile.name}")
val values = ContentValues().apply {
put(ProductContract.ProductEntry.PRODUCT_NAME, productName)
put(ProductContract.ProductEntry.PRODUCT_NET_WEIGHT, netWeight.toString())
put(ProductContract.ProductEntry.IMAGE_FILENAME, pictureFile.nameWithoutExtension)
put(ProductContract.ProductEntry.CATEGORY, categorySpinner.selectedItemPosition)
}
Log.d("QWERTYUIOP", "SIP ${categorySpinner.selectedItemPosition}")
db.insert(ProductContract.ProductEntry.TABLE_NAME, null, values)
finish()
@ -112,6 +117,29 @@ class AddProductActivity : AppCompatActivity() {
// setContentView(binding.root)
}
fun fillupCategorySpinner() {
val db = DBStorageController(this).readableDatabase
val categories = mutableListOf("")
val projection = arrayOf(
CategoriesContract.CategoryEntry.CATEGORY_NAME
)
val cursor = db.query(CategoriesContract.CategoryEntry.TABLE_NAME, projection, null, null, null, null, BaseColumns._ID+" ASC")
with (cursor) {
while (moveToNext()) {
categories.add(getString(getColumnIndexOrThrow(CategoriesContract.CategoryEntry.CATEGORY_NAME)))
}
}
val arrayAdapter = ArrayAdapter<String>(this, androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, categories)
arrayAdapter.setDropDownViewResource(androidx.appcompat.R.layout.support_simple_spinner_dropdown_item)
categorySpinner.adapter = arrayAdapter
}
@RequiresApi(Build.VERSION_CODES.R)
val takePicture = registerForActivityResult(ActivityResultContracts.TakePicture()) { success: Boolean ->
if (success) {
@ -137,7 +165,9 @@ class AddProductActivity : AppCompatActivity() {
//Saving picture to a temp file for further hash calculation and moving to a proper directory
val imageFile = File(this.filesDir, "image.png")
val imageUri = getImageUri(this, imageFile)
takePicture.launch(imageUri)
if (imageUri != null) {
takePicture.launch(imageUri)
}
}
@RequiresApi(Build.VERSION_CODES.R)

View File

@ -28,7 +28,7 @@ class FullscreenActivity : Activity() {
fullscreenImageView = findViewById(R.id.fullscreenImageView)
val extras = intent.extras
val imageHash = extras!!.get("imagehash") as String? //extras!!.getParcelable<Parcelable>("imagehash") as String?
val imageHash = extras!!.get("imagehash") as String?
val picturesDir = File(filesDir, "pictures")

View File

@ -33,10 +33,26 @@ class MainActivity : AppCompatActivity() {
// appBarConfiguration = AppBarConfiguration(navController.graph)
// setupActionBarWithNavController(navController, appBarConfiguration)
binding.addProductFab.setOnClickListener { view ->
val addProductIntent = Intent(this, AddProductActivity::class.java)
val extras = Bundle()
ContextCompat.startActivity(this, addProductIntent, extras)
binding.newElementFab.setOnClickListener { view ->
val currentPosition = binding.tabTablayout.selectedTabPosition
val fragment = adapter.getItem(currentPosition)
when (fragment::class.simpleName.toString()) {
"StorageFragment" -> {
val addProductIntent = Intent(this, AddProductActivity::class.java)
val extras = Bundle()
ContextCompat.startActivity(this, addProductIntent, extras)
}
"CategoriesFragment" -> {
val addCategoryIntent = Intent(this, AddCategoryActivity::class.java)
val extras = Bundle()
extras.putInt("categoryid", 0)
extras.putString("categoryname", "New category")
addCategoryIntent.putExtras(extras)
ContextCompat.startActivity(this, addCategoryIntent, extras)
}
}
}
}
@ -69,7 +85,6 @@ class MainActivity : AppCompatActivity() {
"StorageFragment" -> {
val storageFragment = fragment as StorageFragment
storageFragment.removeSelected()
}
}
true

View File

@ -1,29 +1,20 @@
package org.foxarmy.barcodescannerforemployees.fragments
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import org.foxarmy.barcodescannerforemployees.R
import org.foxarmy.barcodescannerforemployees.databinding.FragmentAddProductBinding
import java.io.File
class AddProductFragment : Fragment() {
private lateinit var binding: FragmentAddProductBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
Log.d("QWERTYUIOP", "хуета1")
binding = FragmentAddProductBinding.inflate(layoutInflater)
return inflater.inflate(R.layout.fragment_add_product, container, false)
}

View File

@ -1,11 +1,17 @@
package org.foxarmy.barcodescannerforemployees.fragments
import android.os.Bundle
import android.provider.BaseColumns
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.fragment.app.Fragment
import org.foxarmy.barcodescannerforemployees.CategoriesContract
import org.foxarmy.barcodescannerforemployees.Category
import org.foxarmy.barcodescannerforemployees.DBStorageController
import org.foxarmy.barcodescannerforemployees.R
import org.foxarmy.barcodescannerforemployees.views.CategoryView
class CategoriesFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
@ -23,9 +29,34 @@ class CategoriesFragment : Fragment() {
override fun onResume() {
super.onResume()
// updateContent()
updateContent()
}
fun updateContent() {
val layout = view?.findViewById<LinearLayout>(R.id.categoriesLayout)
layout?.removeAllViews()
val db = DBStorageController(requireContext()).readableDatabase
val projection = arrayOf(
BaseColumns._ID,
CategoriesContract.CategoryEntry.CATEGORY_NAME
)
val cursor = db.query(CategoriesContract.CategoryEntry.TABLE_NAME, projection, null, null, null, null, null)
with (cursor) {
while(moveToNext()) {
val categoryId = getInt(getColumnIndexOrThrow(BaseColumns._ID))
val categoryName = getString(getColumnIndexOrThrow(CategoriesContract.CategoryEntry.CATEGORY_NAME))
val category = Category(categoryId, categoryName)
val categoryView = CategoryView(requireActivity(), requireContext(), category)
layout?.addView(categoryView)
}
}
}
// public fun updateContent() {
//
// val grv = getView()?.findViewById<GridLayout>(R.id.contentGridLayout)
@ -65,6 +96,6 @@ class CategoriesFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// updateContent()
updateContent()
}
}

View File

@ -13,24 +13,12 @@ import androidx.gridlayout.widget.GridLayout
import org.foxarmy.barcodescannerforemployees.*
import org.foxarmy.barcodescannerforemployees.views.AbstractProductView
/**
* A simple [Fragment] subclass.
* Use the [StorageFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class StorageFragment : Fragment() {
public var test_value = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_storage, container, false)
}
@ -41,7 +29,7 @@ class StorageFragment : Fragment() {
}
fun removeSelected() {
val grv = getView()?.findViewById<GridLayout>(R.id.contentGridLayout)
val grv = view?.findViewById<GridLayout>(R.id.contentGridLayout)
val db = DBStorageController(requireContext())
var deleted = false
@ -61,7 +49,7 @@ class StorageFragment : Fragment() {
fun updateContent() {
val grv = getView()?.findViewById<GridLayout>(R.id.contentGridLayout)
val grv = view?.findViewById<GridLayout>(R.id.contentGridLayout)
grv?.removeAllViews()
val db = DBStorageController(requireContext()).readableDatabase
@ -79,8 +67,20 @@ class StorageFragment : Fragment() {
val productName = getString(getColumnIndexOrThrow(ProductContract.ProductEntry.PRODUCT_NAME))
val netWeight = getDouble(getColumnIndexOrThrow(ProductContract.ProductEntry.PRODUCT_NET_WEIGHT))
val productImageHash = getString(getColumnIndexOrThrow(ProductContract.ProductEntry.IMAGE_FILENAME))
val category = getInt(getColumnIndexOrThrow(ProductContract.ProductEntry.CATEGORY))
var categoryName = ""
val product = AbstractProduct(productId, productName, netWeight, productImageHash, 1)
val projection2 = arrayOf(CategoriesContract.CategoryEntry.CATEGORY_NAME)
val cursor2 = db.query(CategoriesContract.CategoryEntry.TABLE_NAME, projection2, "${BaseColumns._ID} = ?",
arrayOf(category.toString()), null, null, BaseColumns._ID+" ASC")
with (cursor2) {
while (moveToNext()) {
categoryName = getString(getColumnIndexOrThrow(CategoriesContract.CategoryEntry.CATEGORY_NAME))
}
}
val product = AbstractProduct(productId, productName, netWeight, productImageHash, categoryName)
generateThumbnailForImage(context!!, productImageHash)

View File

@ -61,8 +61,9 @@ class AbstractProductView: LinearLayout {
productNameField.text = product.name
netWeightField.text = product.netWeight.toString()
categoryField.text = product.categoryName
//TODO: category and units
//TODO: units
productLayout.setOnLongClickListener {
isProductSelected = !isProductSelected

View File

@ -0,0 +1,47 @@
package org.foxarmy.barcodescannerforemployees.views
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import org.foxarmy.barcodescannerforemployees.Category
import org.foxarmy.barcodescannerforemployees.R
import org.foxarmy.barcodescannerforemployees.activities.AddCategoryActivity
class CategoryView : LinearLayout {
var category: Category
val categoryName: TextView
val updateButton: Button
val deleteButton: Button
constructor(activity: Activity, context: Context, category: Category) : super(context) {
this.category = category
val inflater: LayoutInflater = activity.layoutInflater
inflater.inflate(R.layout.category_view, this)
categoryName = findViewById(R.id.categoryNameTextView)
updateButton = findViewById(R.id.updateButton)
deleteButton = findViewById(R.id.deleteButton)
categoryName.text = category.name
updateButton.setOnClickListener {
val addCategoryIntent = Intent(context, AddCategoryActivity::class.java)
val extras = Bundle()
extras.putInt("categoryid", category.id)
extras.putString("categoryname", category.name)
addCategoryIntent.putExtras(extras)
ContextCompat.startActivity(context, addCategoryIntent, extras)
}
deleteButton.setOnClickListener {
TODO("implement delete button")
}
}
}

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.AddCategoryActivity">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="text"
android:text="@string/sample_category"
android:ems="10"
android:id="@+id/newCategoryName" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="20dp"/>
<Button
android:text="@string/saveButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/saveButton"
app:layout_constraintTop_toBottomOf="@+id/newCategoryName" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" android:layout_marginTop="40dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -43,7 +43,7 @@
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/add_product_fab"
android:id="@+id/new_element_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:text="@string/sample_category"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/categoryNameTextView" android:layout_weight="1"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content" android:id="@+id/updateButton" android:layout_weight="1"
android:text="@string/update" android:lines="1"/>
<Button
android:text="@string/delete"
android:layout_width="0dp"
android:layout_height="wrap_content" android:id="@+id/deleteButton" android:layout_weight="1"/>
</LinearLayout>

View File

@ -16,8 +16,8 @@
android:layout_height="50dp"
android:text="@string/scan_label"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/netWeight"
android:layout_marginTop="25dp"/>
app:layout_constraintTop_toBottomOf="@+id/categoryTextView"
android:layout_marginTop="15dp"/>
<ImageView
android:src="@android:drawable/ic_menu_camera"
android:layout_width="356dp"
@ -51,18 +51,31 @@
app:layout_constraintEnd_toEndOf="parent"
android:visibility="visible" android:hint="@string/netWeight" android:textColorHint="#737373"
app:layout_constraintTop_toBottomOf="@+id/productName"/>
<TextView
android:text="@string/category"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/categoryTextView"
app:layout_constraintTop_toBottomOf="@+id/netWeight"
android:layout_marginTop="20dp" app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp"/>
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content" android:id="@+id/categorySpinner"
app:layout_constraintStart_toEndOf="@+id/categoryTextView"
app:layout_constraintTop_toBottomOf="@+id/netWeight" android:layout_marginStart="8dp"
android:layout_marginTop="20dp"/>
<Button
android:text="@string/saveButton"
android:layout_width="100dp"
android:layout_height="50dp" android:id="@+id/saveButton"
app:layout_constraintTop_toBottomOf="@+id/netWeight"
android:layout_marginTop="25dp" app:layout_constraintEnd_toEndOf="parent"/>
app:layout_constraintTop_toBottomOf="@+id/categoryTextView"
android:layout_marginTop="15dp" app:layout_constraintEnd_toEndOf="parent"/>
<Button
android:text="@string/takePicture"
android:layout_width="100dp"
android:layout_height="55dp" android:id="@+id/takePictureButton"
app:layout_constraintTop_toBottomOf="@+id/netWeight"
android:layout_marginTop="24dp" app:layout_constraintStart_toEndOf="@+id/scan_button"
app:layout_constraintTop_toBottomOf="@+id/categoryTextView"
android:layout_marginTop="15dp" app:layout_constraintStart_toEndOf="@+id/scan_button"
android:layout_marginStart="33dp" app:layout_constraintEnd_toStartOf="@+id/saveButton"
android:layout_marginEnd="6dp" app:layout_constraintHorizontal_bias="0.0"/>

View File

@ -5,9 +5,9 @@
android:layout_height="match_parent"
android:id="@+id/fragment_storage"
tools:context=".fragments.CategoriesFragment">
<ScrollView
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/categoriesLayout">
</ScrollView>
android:layout_height="match_parent" android:id="@+id/categoriesLayout">
</LinearLayout>
</FrameLayout>

View File

@ -22,36 +22,8 @@
<string name="dummy_content">DUMMY\nCONTENT</string>
<string name="fullscreen_image">Fullscreen image</string>
<string name="next">Next</string>
<string name="lorem_ipsum">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam in scelerisque sem. Mauris volutpat, dolor id
interdum ullamcorper, risus dolor egestas lectus, sit amet mattis purus dui nec risus. Maecenas non sodales
nisi, vel dictum dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
himenaeos. Suspendisse blandit eleifend diam, vel rutrum tellus vulputate quis. Aliquam eget libero aliquet,
imperdiet nisl a, ornare ex. Sed rhoncus est ut libero porta lobortis. Fusce in dictum tellus.\n\n
Suspendisse interdum ornare ante. Aliquam nec cursus lorem. Morbi id magna felis. Vivamus egestas, est a
condimentum egestas, turpis nisl iaculis ipsum, in dictum tellus dolor sed neque. Morbi tellus erat, dapibus ut
sem a, iaculis tincidunt dui. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur et eros
porttitor, ultricies urna vitae, molestie nibh. Phasellus at commodo eros, non aliquet metus. Sed maximus nisl
nec dolor bibendum, vel congue leo egestas.\n\n
Sed interdum tortor nibh, in sagittis risus mollis quis. Curabitur mi odio, condimentum sit amet auctor at,
mollis non turpis. Nullam pretium libero vestibulum, finibus orci vel, molestie quam. Fusce blandit tincidunt
nulla, quis sollicitudin libero facilisis et. Integer interdum nunc ligula, et fermentum metus hendrerit id.
Vestibulum lectus felis, dictum at lacinia sit amet, tristique id quam. Cras eu consequat dui. Suspendisse
sodales nunc ligula, in lobortis sem porta sed. Integer id ultrices magna, in luctus elit. Sed a pellentesque
est.\n\n
Aenean nunc velit, lacinia sed dolor sed, ultrices viverra nulla. Etiam a venenatis nibh. Morbi laoreet, tortor
sed facilisis varius, nibh orci rhoncus nulla, id elementum leo dui non lorem. Nam mollis ipsum quis auctor
varius. Quisque elementum eu libero sed commodo. In eros nisl, imperdiet vel imperdiet et, scelerisque a mauris.
Pellentesque varius ex nunc, quis imperdiet eros placerat ac. Duis finibus orci et est auctor tincidunt. Sed non
viverra ipsum. Nunc quis augue egestas, cursus lorem at, molestie sem. Morbi a consectetur ipsum, a placerat
diam. Etiam vulputate dignissim convallis. Integer faucibus mauris sit amet finibus convallis.\n\n
Phasellus in aliquet mi. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis
egestas. In volutpat arcu ut felis sagittis, in finibus massa gravida. Pellentesque id tellus orci. Integer
dictum, lorem sed efficitur ullamcorper, libero justo consectetur ipsum, in mollis nisl ex sed nisl. Donec
maximus ullamcorper sodales. Praesent bibendum rhoncus tellus nec feugiat. In a ornare nulla. Donec rhoncus
libero vel nunc consequat, quis tincidunt nisl eleifend. Cras bibendum enim a justo luctus vestibulum. Fusce
dictum libero quis erat maximus, vitae volutpat diam dignissim.
</string>
<string name="delete_menu">Delete item(s)...</string>
<string name="delete_menu">Delete item(s)…</string>
<string name="update">update</string>
<string name="delete">delete</string>
<string name="category">Category</string>
</resources>

View File

@ -14,6 +14,7 @@ navigationFragmentKtx = "2.8.0"
navigationUiKtx = "2.8.0"
firebaseCrashlyticsBuildtools = "3.0.2"
gridlayout = "1.0.0"
activity = "1.9.2"
[libraries]
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "cameraView" }
@ -29,6 +30,7 @@ androidx-navigation-fragment-ktx = { group = "androidx.navigation", name = "navi
androidx-navigation-ui-ktx = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigationUiKtx" }
firebase-crashlytics-buildtools = { group = "com.google.firebase", name = "firebase-crashlytics-buildtools", version.ref = "firebaseCrashlyticsBuildtools" }
androidx-gridlayout = { group = "androidx.gridlayout", name = "gridlayout", version.ref = "gridlayout" }
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }