some refactor, renaming, started working with product on shelf
This commit is contained in:
parent
926403f9ea
commit
3bfad0f6ad
|
@ -46,6 +46,8 @@ dependencies {
|
|||
implementation(libs.firebase.crashlytics.buildtools)
|
||||
implementation(libs.androidx.gridlayout)
|
||||
implementation(libs.androidx.activity)
|
||||
implementation(libs.androidx.legacy.support.v4)
|
||||
implementation(libs.androidx.fragment)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
androidTestImplementation(libs.androidx.espresso.core)
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
android:name=".activities.AddProductActivity"
|
||||
android:exported="false"
|
||||
android:theme="@style/Theme.BarcodeScannerForEmployees"/>
|
||||
<activity
|
||||
android:name=".activities.AddAbstractProductActivity"
|
||||
android:exported="false"
|
||||
android:theme="@style/Theme.BarcodeScannerForEmployees"/>
|
||||
<activity
|
||||
android:name=".activities.FullscreenActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
|
@ -40,7 +44,7 @@
|
|||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="com.google.firebase.components.activities.MainActivity.provider;com.google.firebase.components.activities.FullscreenActivity.provider;com.google.firebase.components.activities.AddProductActivity.provider"
|
||||
android:authorities="com.google.firebase.components.activities.MainActivity.provider;com.google.firebase.components.activities.FullscreenActivity.provider;com.google.firebase.components.activities.AddAbstractProductActivity.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
package org.foxarmy.barcodescannerforemployees
|
||||
|
||||
class Category(
|
||||
public var id: Int,
|
||||
public var name: String,
|
||||
) {
|
||||
|
||||
}
|
|
@ -5,11 +5,12 @@ import android.database.DatabaseUtils
|
|||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.database.sqlite.SQLiteOpenHelper
|
||||
import android.provider.BaseColumns
|
||||
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
||||
import java.io.File
|
||||
|
||||
object ProductContract {
|
||||
object ProductEntry : BaseColumns {
|
||||
const val TABLE_NAME = "products"
|
||||
object AbstractProductContract {
|
||||
object AbstractProductEntry : BaseColumns {
|
||||
const val TABLE_NAME = "abstract_products"
|
||||
const val PRODUCT_NAME = "name"
|
||||
const val PRODUCT_NET_WEIGHT = "net_weight"
|
||||
const val IMAGE_FILENAME = "image_filename"
|
||||
|
@ -17,14 +18,6 @@ object ProductContract {
|
|||
}
|
||||
}
|
||||
|
||||
object ShelfContract {
|
||||
object ShelfEntry : BaseColumns {
|
||||
const val TABLE_NAME = "shelf"
|
||||
const val PRODUCT_ID = "product_id"
|
||||
const val EXPIRE_DATE = "expire_date"
|
||||
}
|
||||
}
|
||||
|
||||
object CategoriesContract {
|
||||
object CategoryEntry : BaseColumns {
|
||||
const val TABLE_NAME = "categories"
|
||||
|
@ -32,19 +25,31 @@ object CategoriesContract {
|
|||
}
|
||||
}
|
||||
|
||||
const val SQL_CREATE_PRODUCT_TABLE =
|
||||
object ProductContract {
|
||||
object ProductEntry : BaseColumns {
|
||||
const val TABLE_NAME = "products"
|
||||
const val ABSTRACT_PRODUCT_ID = "abstract_product_id"
|
||||
const val AMOUNT = "amount"
|
||||
const val DATE_OF_PRODUCTION = "date_of_production"
|
||||
const val EXPIRY_DATE = "expiry_date"
|
||||
}
|
||||
}
|
||||
|
||||
const val SQL_CREATE_ABSTRACT_PRODUCTS_TABLE =
|
||||
"CREATE TABLE ${AbstractProductContract.AbstractProductEntry.TABLE_NAME} (" +
|
||||
"${BaseColumns._ID} INTEGER PRIMARY KEY," +
|
||||
"${AbstractProductContract.AbstractProductEntry.PRODUCT_NAME} TEXT," +
|
||||
"${AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT} REAL," +
|
||||
"${AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME} TEXT," +
|
||||
"${AbstractProductContract.AbstractProductEntry.CATEGORY} INTEGER)"
|
||||
|
||||
const val SQL_CREATE_PRODUCTS_TABLE =
|
||||
"CREATE TABLE ${ProductContract.ProductEntry.TABLE_NAME} (" +
|
||||
"${BaseColumns._ID} INTEGER PRIMARY KEY," +
|
||||
"${ProductContract.ProductEntry.PRODUCT_NAME} TEXT," +
|
||||
"${ProductContract.ProductEntry.PRODUCT_NET_WEIGHT} REAL," +
|
||||
"${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)"
|
||||
"${ProductContract.ProductEntry.ABSTRACT_PRODUCT_ID} INTEGER," +
|
||||
"${ProductContract.ProductEntry.AMOUNT} INTEGER," +
|
||||
"${ProductContract.ProductEntry.DATE_OF_PRODUCTION} DATE," +
|
||||
"${ProductContract.ProductEntry.EXPIRY_DATE} DATE)"
|
||||
|
||||
const val SQL_CREATE_CATEGORIES_TABLE =
|
||||
"CREATE TABLE ${CategoriesContract.CategoryEntry.TABLE_NAME} (" +
|
||||
|
@ -54,8 +59,8 @@ const val SQL_CREATE_CATEGORIES_TABLE =
|
|||
class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
|
||||
|
||||
override fun onCreate(db: SQLiteDatabase) {
|
||||
db.execSQL(SQL_CREATE_PRODUCT_TABLE)
|
||||
db.execSQL(SQL_CREATE_SHELF_TABLE)
|
||||
db.execSQL(SQL_CREATE_ABSTRACT_PRODUCTS_TABLE)
|
||||
db.execSQL(SQL_CREATE_PRODUCTS_TABLE)
|
||||
db.execSQL(SQL_CREATE_CATEGORIES_TABLE)
|
||||
}
|
||||
|
||||
|
@ -96,22 +101,22 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE
|
|||
var result = mutableListOf<AbstractProduct>()
|
||||
val projection = arrayOf(
|
||||
BaseColumns._ID,
|
||||
ProductContract.ProductEntry.PRODUCT_NAME,
|
||||
ProductContract.ProductEntry.IMAGE_FILENAME,
|
||||
ProductContract.ProductEntry.PRODUCT_NET_WEIGHT,
|
||||
AbstractProductContract.AbstractProductEntry.PRODUCT_NAME,
|
||||
AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME,
|
||||
AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT,
|
||||
)
|
||||
|
||||
val selection = "${ProductContract.ProductEntry.CATEGORY} = ?"
|
||||
val selection = "${AbstractProductContract.AbstractProductEntry.CATEGORY} = ?"
|
||||
val selectionArgs = arrayOf(id.toString())
|
||||
|
||||
val cursor = db.query(ProductContract.ProductEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, null)
|
||||
val cursor = db.query(AbstractProductContract.AbstractProductEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, null)
|
||||
|
||||
with(cursor) {
|
||||
while (moveToNext()) {
|
||||
val abstractProductId = getInt(getColumnIndexOrThrow(BaseColumns._ID))
|
||||
val abstractProductName = getString(getColumnIndexOrThrow(ProductContract.ProductEntry.PRODUCT_NAME))
|
||||
val abstractProductNetWeight = getDouble(getColumnIndexOrThrow(ProductContract.ProductEntry.PRODUCT_NET_WEIGHT))
|
||||
val abstractProductImageHash = getString(getColumnIndexOrThrow(ProductContract.ProductEntry.IMAGE_FILENAME))
|
||||
val abstractProductName = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME))
|
||||
val abstractProductNetWeight = getDouble(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT))
|
||||
val abstractProductImageHash = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME))
|
||||
|
||||
val abstractProduct = AbstractProduct(abstractProductId, abstractProductName, abstractProductNetWeight, abstractProductImageHash, category = id)
|
||||
|
||||
|
@ -123,17 +128,17 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE
|
|||
}
|
||||
|
||||
fun getAmountOfAbstractProductsInCategory(db:SQLiteDatabase, id: Int) : Int {
|
||||
return DatabaseUtils.longForQuery(db, "SELECT COUNT(*) FROM ${ProductContract.ProductEntry.TABLE_NAME} WHERE ${ProductContract.ProductEntry.CATEGORY} = ?", arrayOf(id.toString())).toInt()
|
||||
return DatabaseUtils.longForQuery(db, "SELECT COUNT(*) FROM ${AbstractProductContract.AbstractProductEntry.TABLE_NAME} WHERE ${AbstractProductContract.AbstractProductEntry.CATEGORY} = ?", arrayOf(id.toString())).toInt()
|
||||
}
|
||||
fun eraseAbstractProduct(db: SQLiteDatabase, id: Int, context: Context) {
|
||||
val projection = arrayOf(
|
||||
ProductContract.ProductEntry.IMAGE_FILENAME
|
||||
AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME
|
||||
)
|
||||
|
||||
val selection = "${BaseColumns._ID} = ?"
|
||||
val selectionArgs = arrayOf(id.toString())
|
||||
val cursor = db.query(
|
||||
ProductContract.ProductEntry.TABLE_NAME,
|
||||
AbstractProductContract.AbstractProductEntry.TABLE_NAME,
|
||||
projection,
|
||||
selection,
|
||||
selectionArgs,
|
||||
|
@ -145,7 +150,7 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE
|
|||
|
||||
with (cursor) {
|
||||
while(moveToNext()) {
|
||||
val productImageHash = getString(getColumnIndexOrThrow(ProductContract.ProductEntry.IMAGE_FILENAME))
|
||||
val productImageHash = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME))
|
||||
imageHash = productImageHash
|
||||
}
|
||||
}
|
||||
|
@ -154,7 +159,7 @@ class DBStorageController(context: Context) : SQLiteOpenHelper(context, DATABASE
|
|||
|
||||
File(picturesDir, "$imageHash.png").delete()
|
||||
File(thumbnailsDir, "$imageHash.webp").delete()
|
||||
db.delete(ProductContract.ProductEntry.TABLE_NAME, BaseColumns._ID + "=" + id, null)
|
||||
db.delete(AbstractProductContract.AbstractProductEntry.TABLE_NAME, BaseColumns._ID + "=" + id, null)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.foxarmy.barcodescannerforemployees
|
||||
|
||||
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
||||
|
||||
class Parser constructor(payloadStartRegex: String, payloadEndRegex: String, payloadRegex: String){
|
||||
val payloadStartRegex: String = payloadStartRegex
|
||||
val payloadEndRegex: String = payloadEndRegex
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
package org.foxarmy.barcodescannerforemployees.activities
|
||||
|
||||
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.*
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.mlkit.vision.barcode.common.Barcode
|
||||
import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions
|
||||
import com.google.mlkit.vision.codescanner.GmsBarcodeScanning
|
||||
import org.foxarmy.barcodescannerforemployees.*
|
||||
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
|
||||
class AddAbstractProductActivity : AppCompatActivity() {
|
||||
private lateinit var imageView: ImageView
|
||||
|
||||
private lateinit var saveButton: Button
|
||||
private lateinit var takePictureButton: Button
|
||||
private lateinit var scanButton: Button
|
||||
|
||||
private lateinit var productNameText: TextView
|
||||
private lateinit var netWeightText: TextView
|
||||
|
||||
private lateinit var categorySpinner: Spinner
|
||||
|
||||
private var abstractProduct: AbstractProduct? = null
|
||||
private lateinit var pictureFile: File
|
||||
private lateinit var picturesPath: File
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContentView(R.layout.fragment_add_abstract_product)
|
||||
|
||||
val extras = intent.extras
|
||||
abstractProduct = extras!!.get("abstractProduct") as AbstractProduct?
|
||||
|
||||
picturesPath = File(filesDir, "pictures")
|
||||
val thumbnailsDir = File(cacheDir, "thumbnails")
|
||||
thumbnailsDir.mkdirs()
|
||||
picturesPath.mkdirs()
|
||||
imageView = findViewById(R.id.imageView)
|
||||
|
||||
saveButton = findViewById(R.id.saveButton)
|
||||
takePictureButton = findViewById(R.id.takePictureButton)
|
||||
scanButton = findViewById(R.id.scan_button)
|
||||
|
||||
productNameText = findViewById(R.id.productName)
|
||||
netWeightText = findViewById(R.id.netWeight)
|
||||
|
||||
categorySpinner = findViewById(R.id.categorySpinner)
|
||||
|
||||
fillupCategorySpinner()
|
||||
|
||||
if (abstractProduct != null) {
|
||||
val imageThumbnailUri = getImageUri(this, File(thumbnailsDir, "${abstractProduct!!.imageHash}.webp"))
|
||||
pictureFile = File(picturesPath, "${abstractProduct!!.imageHash}.png]")
|
||||
imageView.setImageURI(imageThumbnailUri)
|
||||
imageView.rotation = 90f
|
||||
productNameText.text = abstractProduct!!.name
|
||||
netWeightText.text = abstractProduct!!.netWeight.toString()
|
||||
categorySpinner.setSelection(abstractProduct!!.category)
|
||||
}
|
||||
|
||||
saveButton.setOnClickListener {
|
||||
val productName = productNameText.text.toString()
|
||||
val netWeight = netWeightText.text
|
||||
if (!this::pictureFile.isInitialized && !pictureFile.exists()) {
|
||||
|
||||
Toast.makeText(this, "Please, make a picture of a product!", Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (productName == "") {
|
||||
Toast.makeText(this, "Please, write a name of a product!", Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
if (netWeight.toString() == "" || netWeight.toString().toDoubleOrNull() == null) {
|
||||
Toast.makeText(this, "Please, write a valid net weight of a product!", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
val db = DBStorageController(this).writableDatabase
|
||||
val values = ContentValues().apply {
|
||||
put(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME, productName)
|
||||
put(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT, netWeight.toString())
|
||||
put(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME, pictureFile.nameWithoutExtension)
|
||||
put(AbstractProductContract.AbstractProductEntry.CATEGORY, categorySpinner.selectedItemPosition)
|
||||
}
|
||||
|
||||
if (abstractProduct == null) {
|
||||
db.insert(AbstractProductContract.AbstractProductEntry.TABLE_NAME, null, values)
|
||||
} else {
|
||||
db.update(AbstractProductContract.AbstractProductEntry.TABLE_NAME, values, "${BaseColumns._ID} = ?", arrayOf(abstractProduct!!.id.toString()))
|
||||
}
|
||||
|
||||
finish()
|
||||
}
|
||||
|
||||
takePictureButton.setOnClickListener {
|
||||
requestPermissionLauncher.launch(Manifest.permission.CAMERA)
|
||||
}
|
||||
|
||||
scanButton.setOnClickListener {
|
||||
val options = GmsBarcodeScannerOptions.Builder()
|
||||
.setBarcodeFormats(
|
||||
Barcode.FORMAT_EAN_13
|
||||
)
|
||||
.build()
|
||||
val scanner = GmsBarcodeScanning.getClient(this)
|
||||
scanner.startScan()
|
||||
.addOnSuccessListener { barcode ->
|
||||
productNameText.setText(barcode.rawValue)
|
||||
}
|
||||
.addOnFailureListener { e ->
|
||||
Toast.makeText(
|
||||
this,
|
||||
"Failed to scan barcode. Please, try again or enter data manually",
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
//Move picture to a proper directory according to its calculated hash
|
||||
val tempfile = File(filesDir, "image.png")
|
||||
val imageContent = tempfile.inputStream().readBytes()
|
||||
val imageHash = imageContent.toString(Charsets.UTF_8).md5()
|
||||
|
||||
pictureFile = File(picturesPath, "$imageHash.png")
|
||||
Files.move(tempfile.toPath(), pictureFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
|
||||
tempfile.delete()
|
||||
generateThumbnailForImage(this, imageHash)
|
||||
|
||||
imageView.setImageURI(getImageUri(this, pictureFile))
|
||||
} else {
|
||||
Log.e("QWERTYUIOP", "Cannot save a picture")
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
fun getPicture () {
|
||||
//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)
|
||||
if (imageUri != null) {
|
||||
takePicture.launch(imageUri)
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
val requestPermissionLauncher =
|
||||
registerForActivityResult(
|
||||
ActivityResultContracts.RequestPermission()
|
||||
) { isGranted: Boolean ->
|
||||
if (isGranted) {
|
||||
getPicture()
|
||||
} else {
|
||||
Toast.makeText(this, "I need permission in order to take a picture", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import android.provider.BaseColumns
|
|||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import org.foxarmy.barcodescannerforemployees.CategoriesContract
|
||||
import org.foxarmy.barcodescannerforemployees.dataclasses.Category
|
||||
import org.foxarmy.barcodescannerforemployees.DBStorageController
|
||||
import org.foxarmy.barcodescannerforemployees.R
|
||||
|
||||
|
@ -17,17 +18,16 @@ class AddCategoryActivity : Activity() {
|
|||
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 category = extras!!.get("category") as Category?
|
||||
|
||||
val categoryNameTextEdit: EditText = findViewById(R.id.newCategoryName)
|
||||
|
||||
categoryNameTextEdit.setText(categoryName)
|
||||
categoryNameTextEdit.setText(category!!.name)
|
||||
|
||||
findViewById<Button>(R.id.saveButton).setOnClickListener {
|
||||
val db = DBStorageController(this).writableDatabase
|
||||
|
||||
if (categoryId == 0) { // Inserting new category
|
||||
if (category.id == 0) { // Inserting new category
|
||||
val values = ContentValues().apply {
|
||||
put(CategoriesContract.CategoryEntry.CATEGORY_NAME, categoryNameTextEdit.text.toString())
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class AddCategoryActivity : Activity() {
|
|||
val values = ContentValues().apply {
|
||||
put(CategoriesContract.CategoryEntry.CATEGORY_NAME, categoryNameTextEdit.text.toString())
|
||||
}
|
||||
db.update(CategoriesContract.CategoryEntry.TABLE_NAME, values, "${BaseColumns._ID} = ?", arrayOf(categoryId.toString()))
|
||||
db.update(CategoriesContract.CategoryEntry.TABLE_NAME, values, "${BaseColumns._ID} = ?", arrayOf(category.id.toString()))
|
||||
}
|
||||
|
||||
finish()
|
||||
|
|
|
@ -1,200 +1,18 @@
|
|||
package org.foxarmy.barcodescannerforemployees.activities
|
||||
|
||||
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.*
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.mlkit.vision.barcode.common.Barcode
|
||||
import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions
|
||||
import com.google.mlkit.vision.codescanner.GmsBarcodeScanning
|
||||
import org.foxarmy.barcodescannerforemployees.*
|
||||
import org.foxarmy.barcodescannerforemployees.databinding.ActivityAddProductBinding
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
import org.foxarmy.barcodescannerforemployees.R
|
||||
import org.foxarmy.barcodescannerforemployees.dataclasses.Product
|
||||
|
||||
class AddProductActivity : AppCompatActivity() {
|
||||
private lateinit var imageView: ImageView
|
||||
|
||||
private lateinit var saveButton: Button
|
||||
private lateinit var takePictureButton: Button
|
||||
private lateinit var scanButton: Button
|
||||
|
||||
private lateinit var productNameText: TextView
|
||||
private lateinit var netWeightText: TextView
|
||||
|
||||
private lateinit var categorySpinner: Spinner
|
||||
|
||||
private var product: AbstractProduct? = null
|
||||
private lateinit var pictureFile: File
|
||||
private lateinit var picturesPath: File
|
||||
private lateinit var binding: ActivityAddProductBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
setContentView(R.layout.fragment_add_product)
|
||||
setContentView(R.layout.activity_add_product)
|
||||
|
||||
val extras = intent.extras
|
||||
product = extras!!.get("updatingObject") as AbstractProduct?
|
||||
|
||||
picturesPath = File(filesDir, "pictures")
|
||||
val thumbnailsDir = File(cacheDir, "thumbnails")
|
||||
thumbnailsDir.mkdirs()
|
||||
picturesPath.mkdirs()
|
||||
imageView = findViewById(R.id.imageView)
|
||||
|
||||
saveButton = findViewById(R.id.saveButton)
|
||||
takePictureButton = findViewById(R.id.takePictureButton)
|
||||
scanButton = findViewById(R.id.scan_button)
|
||||
|
||||
productNameText = findViewById(R.id.productName)
|
||||
netWeightText = findViewById(R.id.netWeight)
|
||||
|
||||
categorySpinner = findViewById(R.id.categorySpinner)
|
||||
|
||||
fillupCategorySpinner()
|
||||
|
||||
if (product != null) {
|
||||
val imageThumbnailUri = getImageUri(this, File(thumbnailsDir, "${product!!.imageHash}.webp"))
|
||||
pictureFile = File(picturesPath, "${product!!.imageHash}.png]")
|
||||
imageView.setImageURI(imageThumbnailUri)
|
||||
imageView.rotation = 90f
|
||||
productNameText.text = product!!.name
|
||||
netWeightText.text = product!!.netWeight.toString()
|
||||
categorySpinner.setSelection(product!!.category)
|
||||
}
|
||||
|
||||
saveButton.setOnClickListener {
|
||||
val productName = productNameText.text.toString()
|
||||
val netWeight = netWeightText.text
|
||||
if (!this::pictureFile.isInitialized && !pictureFile.exists()) {
|
||||
|
||||
Toast.makeText(this, "Please, make a picture of a product!", Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
if (productName == "") {
|
||||
Toast.makeText(this, "Please, write a name of a product!", Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
if (netWeight.toString() == "" || netWeight.toString().toDoubleOrNull() == null) {
|
||||
Toast.makeText(this, "Please, write a valid net weight of a product!", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
val db = DBStorageController(this).writableDatabase
|
||||
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)
|
||||
}
|
||||
|
||||
if (product == null) {
|
||||
db.insert(ProductContract.ProductEntry.TABLE_NAME, null, values)
|
||||
} else {
|
||||
db.update(ProductContract.ProductEntry.TABLE_NAME, values, "${BaseColumns._ID} = ?", arrayOf(product!!.id.toString()))
|
||||
}
|
||||
|
||||
finish()
|
||||
}
|
||||
|
||||
takePictureButton.setOnClickListener {
|
||||
requestPermissionLauncher.launch(Manifest.permission.CAMERA)
|
||||
}
|
||||
|
||||
scanButton.setOnClickListener {
|
||||
val options = GmsBarcodeScannerOptions.Builder()
|
||||
.setBarcodeFormats(
|
||||
Barcode.FORMAT_EAN_13
|
||||
)
|
||||
.build()
|
||||
val scanner = GmsBarcodeScanning.getClient(this)
|
||||
scanner.startScan()
|
||||
.addOnSuccessListener { barcode ->
|
||||
productNameText.setText(barcode.rawValue)
|
||||
}
|
||||
.addOnFailureListener { e ->
|
||||
Toast.makeText(
|
||||
this,
|
||||
"Failed to scan barcode. Please, try again or enter data manually",
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
// binding = ActivityAddProductBinding.inflate(layoutInflater)
|
||||
|
||||
// setContentView(binding.root)
|
||||
val product = extras!!.get("product") as Product?
|
||||
|
||||
}
|
||||
|
||||
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) {
|
||||
//Move picture to a proper directory according to its calculated hash
|
||||
val tempfile = File(filesDir, "image.png")
|
||||
val imageContent = tempfile.inputStream().readBytes()
|
||||
val imageHash = imageContent.toString(Charsets.UTF_8).md5()
|
||||
|
||||
pictureFile = File(picturesPath, "$imageHash.png")
|
||||
Files.move(tempfile.toPath(), pictureFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
|
||||
tempfile.delete()
|
||||
generateThumbnailForImage(this, imageHash)
|
||||
|
||||
imageView.setImageURI(getImageUri(this, pictureFile))
|
||||
} else {
|
||||
Log.e("QWERTYUIOP", "Cannot save a picture")
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
fun getPicture () {
|
||||
//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)
|
||||
if (imageUri != null) {
|
||||
takePicture.launch(imageUri)
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.R)
|
||||
val requestPermissionLauncher =
|
||||
registerForActivityResult(
|
||||
ActivityResultContracts.RequestPermission()
|
||||
) { isGranted: Boolean ->
|
||||
if (isGranted) {
|
||||
getPicture()
|
||||
} else {
|
||||
Toast.makeText(this, "I need permission in order to take a picture", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,9 @@ import androidx.viewpager.widget.ViewPager
|
|||
import org.foxarmy.barcodescannerforemployees.R
|
||||
import org.foxarmy.barcodescannerforemployees.ViewPagerAdapter
|
||||
import org.foxarmy.barcodescannerforemployees.databinding.ActivityMainBinding
|
||||
import org.foxarmy.barcodescannerforemployees.dataclasses.Category
|
||||
import org.foxarmy.barcodescannerforemployees.fragments.CategoriesFragment
|
||||
import org.foxarmy.barcodescannerforemployees.fragments.ShelfFragment
|
||||
import org.foxarmy.barcodescannerforemployees.fragments.StorageFragment
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
@ -36,25 +38,34 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
when (fragment::class.simpleName.toString()) {
|
||||
"StorageFragment" -> {
|
||||
val addProductIntent = Intent(this, AddProductActivity::class.java)
|
||||
val addAbstractProductIntent = Intent(this, AddAbstractProductActivity::class.java)
|
||||
val extras = Bundle()
|
||||
// I reuse the same stuff for editing and adding new product.
|
||||
// if updatingObject == null, it means that we need to create new object
|
||||
extras.putParcelable("updatingObject", null)
|
||||
addProductIntent.putExtras(extras)
|
||||
ContextCompat.startActivity(this, addProductIntent, extras)
|
||||
// if abstractProduct == null, it means that we need to create new object
|
||||
extras.putParcelable("abstractProduct", null)
|
||||
addAbstractProductIntent.putExtras(extras)
|
||||
ContextCompat.startActivity(this, addAbstractProductIntent, extras)
|
||||
}
|
||||
|
||||
"CategoriesFragment" -> {
|
||||
val addCategoryIntent = Intent(this, AddCategoryActivity::class.java)
|
||||
val extras = Bundle()
|
||||
extras.putInt("categoryid", 0)
|
||||
extras.putString("categoryname", "New category")
|
||||
//TODO: Implement parcellable for Category class to simplify this
|
||||
// extras.putInt("categoryid", 0)
|
||||
// extras.putString("categoryname", "New category")
|
||||
extras.putParcelable("category", Category(0, "New category"))
|
||||
addCategoryIntent.putExtras(extras)
|
||||
ContextCompat.startActivity(this, addCategoryIntent, extras)
|
||||
}
|
||||
}
|
||||
|
||||
"ShelfFragment" -> {
|
||||
val addProductIntent = Intent(this, AddProductActivity::class.java)
|
||||
val extras = Bundle()
|
||||
extras.putParcelable("product", null)
|
||||
addProductIntent.putExtras(extras)
|
||||
ContextCompat.startActivity(this, addProductIntent, extras)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +74,8 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
adapter.addFragment(CategoriesFragment(), "Categories")
|
||||
adapter.addFragment(StorageFragment(), "Storage")
|
||||
//TODO: shelf and settings fragments
|
||||
adapter.addFragment(ShelfFragment(), "Shelf")
|
||||
//TODO: settings fragments
|
||||
|
||||
// setting adapter to view pager.
|
||||
viewpager.setAdapter(adapter)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package org.foxarmy.barcodescannerforemployees
|
||||
package org.foxarmy.barcodescannerforemployees.dataclasses
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
|
@ -0,0 +1,39 @@
|
|||
package org.foxarmy.barcodescannerforemployees.dataclasses
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class Category() : Parcelable {
|
||||
var id = 0
|
||||
var name = ""
|
||||
|
||||
|
||||
constructor(id: Int, name: String) : this() {
|
||||
this.id = id
|
||||
this.name = name
|
||||
}
|
||||
|
||||
constructor(parcel: Parcel) : this() {
|
||||
id = parcel.readInt()
|
||||
name = parcel.readString()!!
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(id)
|
||||
parcel.writeString(name)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Category> {
|
||||
override fun createFromParcel(parcel: Parcel): Category {
|
||||
return Category(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Category?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package org.foxarmy.barcodescannerforemployees.dataclasses
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
class Product() : Parcelable {
|
||||
var abstractProductId = 0
|
||||
var amount = 0
|
||||
|
||||
|
||||
constructor(abstractProductId: Int, amount: Int) : this() {
|
||||
this.abstractProductId = abstractProductId
|
||||
this.amount = amount
|
||||
}
|
||||
|
||||
constructor(parcel: Parcel) : this() {
|
||||
abstractProductId = parcel.readInt()
|
||||
amount = parcel.readInt()
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, flags: Int) {
|
||||
parcel.writeInt(abstractProductId)
|
||||
parcel.writeInt(amount)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<Product> {
|
||||
override fun createFromParcel(parcel: Parcel): Product {
|
||||
return Product(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<Product?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.foxarmy.barcodescannerforemployees.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
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.FragmentAddAbstractProductBinding
|
||||
|
||||
class AddAbstractProductFragment : Fragment() {
|
||||
private lateinit var binding: FragmentAddAbstractProductBinding
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = FragmentAddAbstractProductBinding.inflate(layoutInflater)
|
||||
return inflater.inflate(R.layout.fragment_add_abstract_product, container, false)
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ import androidx.core.content.ContextCompat
|
|||
import androidx.core.view.children
|
||||
import androidx.fragment.app.Fragment
|
||||
import org.foxarmy.barcodescannerforemployees.CategoriesContract
|
||||
import org.foxarmy.barcodescannerforemployees.Category
|
||||
import org.foxarmy.barcodescannerforemployees.dataclasses.Category
|
||||
import org.foxarmy.barcodescannerforemployees.DBStorageController
|
||||
import org.foxarmy.barcodescannerforemployees.R
|
||||
import org.foxarmy.barcodescannerforemployees.activities.AddCategoryActivity
|
||||
|
@ -56,8 +56,7 @@ class CategoriesFragment : Fragment() {
|
|||
if (view.isCategorySelected) {
|
||||
val addCategoryIntent = Intent(context, AddCategoryActivity::class.java)
|
||||
val extras = Bundle()
|
||||
extras.putInt("categoryid", view.category.id)
|
||||
extras.putString("categoryname", view.category.name)
|
||||
extras.putParcelable("category", view.category)
|
||||
addCategoryIntent.putExtras(extras)
|
||||
ContextCompat.startActivity(context!!, addCategoryIntent, extras)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package org.foxarmy.barcodescannerforemployees.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import org.foxarmy.barcodescannerforemployees.R
|
||||
|
||||
class ShelfFragment : Fragment() {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
return inflater.inflate(R.layout.fragment_shelf, container, false)
|
||||
}
|
||||
}
|
|
@ -12,8 +12,12 @@ import androidx.core.content.ContextCompat
|
|||
import androidx.core.view.children
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.gridlayout.widget.GridLayout
|
||||
import org.foxarmy.barcodescannerforemployees.*
|
||||
import org.foxarmy.barcodescannerforemployees.activities.AddProductActivity
|
||||
import org.foxarmy.barcodescannerforemployees.AbstractProductContract
|
||||
import org.foxarmy.barcodescannerforemployees.DBStorageController
|
||||
import org.foxarmy.barcodescannerforemployees.R
|
||||
import org.foxarmy.barcodescannerforemployees.activities.AddAbstractProductActivity
|
||||
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
||||
import org.foxarmy.barcodescannerforemployees.generateThumbnailForImage
|
||||
import org.foxarmy.barcodescannerforemployees.views.AbstractProductView
|
||||
|
||||
class StorageFragment : Fragment() {
|
||||
|
@ -39,7 +43,7 @@ class StorageFragment : Fragment() {
|
|||
for (view: AbstractProductView in grv?.children!!.iterator() as Iterator<AbstractProductView>) {
|
||||
view.findViewById<ImageView>(R.id.productPicture).setImageURI(null)
|
||||
if (view.isProductSelected) {
|
||||
db.eraseAbstractProduct(db.writableDatabase, view.product.id, requireContext())
|
||||
db.eraseAbstractProduct(db.writableDatabase, view.abstractProduct.id, requireContext())
|
||||
deleted = true
|
||||
}
|
||||
}
|
||||
|
@ -55,9 +59,9 @@ class StorageFragment : Fragment() {
|
|||
|
||||
for (view: AbstractProductView in grv?.children!!.iterator() as Iterator<AbstractProductView>) {
|
||||
if (view.isProductSelected) {
|
||||
val addProductIntent = Intent(requireContext(), AddProductActivity::class.java)
|
||||
val addProductIntent = Intent(requireContext(), AddAbstractProductActivity::class.java)
|
||||
val extras = Bundle()
|
||||
extras.putParcelable("updatingObject", view.product)
|
||||
extras.putParcelable("abstractProduct", view.abstractProduct)
|
||||
addProductIntent.putExtras(extras)
|
||||
ContextCompat.startActivity(requireContext(), addProductIntent, extras)
|
||||
}
|
||||
|
@ -72,21 +76,21 @@ class StorageFragment : Fragment() {
|
|||
|
||||
val db = DBStorageController(requireContext()).readableDatabase
|
||||
val projection = arrayOf(BaseColumns._ID,
|
||||
ProductContract.ProductEntry.PRODUCT_NAME,
|
||||
ProductContract.ProductEntry.PRODUCT_NET_WEIGHT,
|
||||
ProductContract.ProductEntry.IMAGE_FILENAME,
|
||||
ProductContract.ProductEntry.CATEGORY
|
||||
AbstractProductContract.AbstractProductEntry.PRODUCT_NAME,
|
||||
AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT,
|
||||
AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME,
|
||||
AbstractProductContract.AbstractProductEntry.CATEGORY
|
||||
)
|
||||
|
||||
val cursor = db.query(ProductContract.ProductEntry.TABLE_NAME, projection, null, null, null, null, null)
|
||||
val cursor = db.query(AbstractProductContract.AbstractProductEntry.TABLE_NAME, projection, null, null, null, null, null)
|
||||
|
||||
with (cursor) {
|
||||
while(moveToNext()) {
|
||||
val productId = getInt(getColumnIndexOrThrow(BaseColumns._ID))
|
||||
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))
|
||||
val productName = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NAME))
|
||||
val netWeight = getDouble(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.PRODUCT_NET_WEIGHT))
|
||||
val productImageHash = getString(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.IMAGE_FILENAME))
|
||||
val category = getInt(getColumnIndexOrThrow(AbstractProductContract.AbstractProductEntry.CATEGORY))
|
||||
|
||||
val product = AbstractProduct(productId, productName, netWeight, productImageHash, category)
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import android.widget.TextView
|
|||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import org.foxarmy.barcodescannerforemployees.AbstractProduct
|
||||
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
||||
import org.foxarmy.barcodescannerforemployees.DBStorageController
|
||||
import org.foxarmy.barcodescannerforemployees.R
|
||||
import org.foxarmy.barcodescannerforemployees.activities.FullscreenActivity
|
||||
|
@ -25,12 +25,12 @@ class AbstractProductView: LinearLayout {
|
|||
private var netWeightField: TextView
|
||||
private var categoryField: TextView
|
||||
private var unitField: TextView
|
||||
var product: AbstractProduct
|
||||
var abstractProduct: AbstractProduct
|
||||
var isProductSelected = false
|
||||
|
||||
constructor(activity: Activity, context: Context, product: AbstractProduct) : super(context) {
|
||||
constructor(activity: Activity, context: Context, abstractProduct: AbstractProduct) : super(context) {
|
||||
|
||||
this.product = product
|
||||
this.abstractProduct = abstractProduct
|
||||
|
||||
val inflater:LayoutInflater = activity.layoutInflater
|
||||
inflater.inflate(R.layout.abstract_product_view, this)
|
||||
|
@ -44,13 +44,13 @@ class AbstractProductView: LinearLayout {
|
|||
|
||||
val thumbnailsDir = File(context.cacheDir, "thumbnails")
|
||||
thumbnailsDir.mkdirs()
|
||||
val imageUri = getImageUri(activity, File(thumbnailsDir, "${product.imageHash}.webp"))
|
||||
val imageUri = getImageUri(activity, File(thumbnailsDir, "${abstractProduct.imageHash}.webp"))
|
||||
productPicture.setImageURI(imageUri)
|
||||
productPicture.rotation = 90f
|
||||
productPicture.setOnClickListener {
|
||||
val fullscreenIntent = Intent(activity, FullscreenActivity::class.java)
|
||||
val extras = Bundle()
|
||||
extras.putString("imagehash", product.imageHash)
|
||||
extras.putString("imagehash", abstractProduct.imageHash)
|
||||
fullscreenIntent.putExtras(extras)
|
||||
startActivity(context, fullscreenIntent, extras)
|
||||
}
|
||||
|
@ -61,9 +61,9 @@ class AbstractProductView: LinearLayout {
|
|||
|
||||
|
||||
|
||||
productNameField.text = product.name
|
||||
netWeightField.text = product.netWeight.toString()
|
||||
categoryField.text = DBStorageController(context).getCategoryNameById(DBStorageController(context).readableDatabase, product.category)
|
||||
productNameField.text = abstractProduct.name
|
||||
netWeightField.text = abstractProduct.netWeight.toString()
|
||||
categoryField.text = DBStorageController(context).getCategoryNameById(DBStorageController(context).readableDatabase, abstractProduct.category)
|
||||
|
||||
//TODO: units
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import android.view.LayoutInflater
|
|||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import org.foxarmy.barcodescannerforemployees.Category
|
||||
import org.foxarmy.barcodescannerforemployees.dataclasses.Category
|
||||
import org.foxarmy.barcodescannerforemployees.DBStorageController
|
||||
import org.foxarmy.barcodescannerforemployees.R
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".fragments.AddAbstractProductFragment">
|
||||
<include layout="@layout/content_add_abstract_product" android:id="@+id/include_content"/>
|
||||
</androidx.core.widget.NestedScrollView>
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" android:id="@+id/addAbstractProductLayout">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" app:navGraph="@navigation/nav_graph_add_abstract_product"
|
||||
app:defaultNavHost="true" android:id="@+id/fragmentContainerView"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".fragments.AddAbstractProductFragment">
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp">
|
||||
<Button
|
||||
android:id="@+id/scan_button"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="50dp"
|
||||
android:text="@string/scan_label"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/categoryTextView"
|
||||
android:layout_marginTop="15dp"/>
|
||||
<ImageView
|
||||
android:src="@android:drawable/ic_menu_camera"
|
||||
android:layout_width="356dp"
|
||||
android:layout_height="303dp" android:id="@+id/imageView"
|
||||
android:layout_marginBottom="25dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/productName" app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="15dp"/>
|
||||
<EditText
|
||||
android:layout_width="350dp"
|
||||
android:layout_height="50dp"
|
||||
android:inputType="text"
|
||||
android:ems="10"
|
||||
android:id="@+id/productName"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:layout_marginStart="8dp" android:layout_marginEnd="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/netWeight"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
android:visibility="visible" android:hint="@string/product_name_label" android:textColorHint="#737373"
|
||||
app:layout_constraintTop_toBottomOf="@+id/imageView"/>
|
||||
<EditText
|
||||
android:layout_width="350dp"
|
||||
android:layout_height="50dp"
|
||||
android:inputType="text"
|
||||
android:ems="10"
|
||||
android:id="@+id/netWeight"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
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/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/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"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
|
@ -10,74 +10,11 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp">
|
||||
<Button
|
||||
android:id="@+id/scan_button"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="50dp"
|
||||
android:text="@string/scan_label"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/categoryTextView"
|
||||
android:layout_marginTop="15dp"/>
|
||||
<ImageView
|
||||
android:src="@android:drawable/ic_menu_camera"
|
||||
android:layout_width="356dp"
|
||||
android:layout_height="303dp" android:id="@+id/imageView"
|
||||
android:layout_marginBottom="25dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/productName" app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginTop="15dp"/>
|
||||
<EditText
|
||||
android:layout_width="350dp"
|
||||
android:layout_height="50dp"
|
||||
android:inputType="text"
|
||||
android:ems="10"
|
||||
android:id="@+id/productName"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:layout_marginStart="8dp" android:layout_marginEnd="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/netWeight"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
android:visibility="visible" android:hint="@string/product_name_label" android:textColorHint="#737373"
|
||||
app:layout_constraintTop_toBottomOf="@+id/imageView"/>
|
||||
<EditText
|
||||
android:layout_width="350dp"
|
||||
android:layout_height="50dp"
|
||||
android:inputType="text"
|
||||
android:ems="10"
|
||||
android:id="@+id/netWeight"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
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/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/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"/>
|
||||
|
||||
android:layout_width="400dp"
|
||||
android:layout_height="50dp" android:id="@+id/abstractProductSelect"
|
||||
app:layout_constraintTop_toTopOf="parent" android:layout_marginTop="12dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</FrameLayout>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/nav_graph_add_abstract_product"
|
||||
app:startDestination="@id/addAbstractProductFragment">
|
||||
|
||||
<fragment android:id="@+id/addAbstractProductFragment"
|
||||
android:name="org.foxarmy.barcodescannerforemployees.fragments.AddAbstractProductFragment"
|
||||
android:label="activity_add_abstract_product" tools:layout="@layout/fragment_add_abstract_product"/>
|
||||
</navigation>
|
|
@ -5,6 +5,7 @@
|
|||
android:id="@+id/nav_graph_add_product"
|
||||
app:startDestination="@id/addProductFragment">
|
||||
|
||||
<fragment android:id="@+id/addProductFragment" android:name="org.foxarmy.barcodescannerforemployees.fragments.AddProductFragment"
|
||||
android:label="add_product_fragment" tools:layout="@layout/fragment_add_product"/>
|
||||
<fragment android:id="@+id/addProductFragment"
|
||||
android:name="org.foxarmy.barcodescannerforemployees.fragments.AddProductFragment"
|
||||
android:label="activity_add_product" tools:layout="@layout/fragment_add_product"/>
|
||||
</navigation>
|
|
@ -15,6 +15,8 @@ navigationUiKtx = "2.8.0"
|
|||
firebaseCrashlyticsBuildtools = "3.0.2"
|
||||
gridlayout = "1.0.0"
|
||||
activity = "1.9.2"
|
||||
legacySupportV4 = "1.0.0"
|
||||
fragment = "1.8.4"
|
||||
|
||||
[libraries]
|
||||
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "cameraView" }
|
||||
|
@ -31,6 +33,8 @@ androidx-navigation-ui-ktx = { group = "androidx.navigation", name = "navigation
|
|||
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" }
|
||||
androidx-legacy-support-v4 = { group = "androidx.legacy", name = "legacy-support-v4", version.ref = "legacySupportV4" }
|
||||
androidx-fragment = { group = "androidx.fragment", name = "fragment", version.ref = "fragment" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
|
|
Loading…
Reference in New Issue