working on network and UI
This commit is contained in:
parent
3d4f86085e
commit
a0d96da9e4
|
@ -50,13 +50,16 @@ dependencies {
|
||||||
implementation(libs.androidx.activity)
|
implementation(libs.androidx.activity)
|
||||||
implementation(libs.androidx.legacy.support.v4)
|
implementation(libs.androidx.legacy.support.v4)
|
||||||
implementation(libs.androidx.fragment)
|
implementation(libs.androidx.fragment)
|
||||||
|
implementation(libs.androidx.material3.android)
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
implementation(libs.volley)
|
implementation(libs.volley)
|
||||||
androidTestImplementation(libs.androidx.junit)
|
androidTestImplementation(libs.androidx.junit)
|
||||||
implementation(libs.zxing.android.embedded)
|
implementation(libs.zxing.android.embedded)
|
||||||
implementation("com.google.zxing:core:3.4.1")
|
implementation("com.google.zxing:core:3.4.1")
|
||||||
androidTestImplementation(libs.androidx.espresso.core)
|
androidTestImplementation(libs.androidx.espresso.core)
|
||||||
|
implementation("com.google.android.material:material:1.3.0-alpha03")
|
||||||
|
implementation(libs.androidx.security.crypto)
|
||||||
|
implementation(libs.okhttp)
|
||||||
// Barcode scanning API
|
// Barcode scanning API
|
||||||
implementation (libs.barcode.scanning)
|
implementation (libs.barcode.scanning)
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,14 @@
|
||||||
android:name=".activities.FindBarcodelessAbstractProduct"
|
android:name=".activities.FindBarcodelessAbstractProduct"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:theme="@style/Theme.BarcodeScannerForEmployees"/>
|
android:theme="@style/Theme.BarcodeScannerForEmployees"/>
|
||||||
|
<activity
|
||||||
|
android:name=".activities.MainActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:theme="@style/Theme.BarcodeScannerForEmployees"/>
|
||||||
|
<activity
|
||||||
|
android:name=".activities.LoginActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:theme="@style/Theme.BarcodeScannerForEmployees"/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.FullscreenActivity"
|
android:name=".activities.FullscreenActivity"
|
||||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||||
|
@ -70,7 +78,7 @@
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.MainActivity"
|
android:name=".activities.NavigatorActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:theme="@style/Theme.BarcodeScannerForEmployees">
|
android:theme="@style/Theme.BarcodeScannerForEmployees">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
package org.foxarmy.barcodescannerforemployees
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import okhttp3.*
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
|
import okhttp3.RequestBody.Companion.asRequestBody
|
||||||
|
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
|
class Net {
|
||||||
|
|
||||||
|
fun requestProductFromOnlineDB(barcode: String): String {
|
||||||
|
var response = ""
|
||||||
|
thread {
|
||||||
|
val url = "https://ean-online.ru/match.php"
|
||||||
|
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
|
val formBody = FormBody.Builder()
|
||||||
|
formBody.add("barcode", barcode)
|
||||||
|
val body = formBody.build()
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.post(body)
|
||||||
|
.addHeader("referer", "https://ean-online.ru")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
response = client.newCall(request).execute().body!!.string()
|
||||||
|
}.join()
|
||||||
|
|
||||||
|
return if (response == "") {
|
||||||
|
"Not found 404"
|
||||||
|
} else {
|
||||||
|
response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun registerAccount(server: String, username: String, password: String): String {
|
||||||
|
var token = ""
|
||||||
|
lateinit var response: Response
|
||||||
|
thread {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
|
val formBody = FormBody.Builder()
|
||||||
|
formBody.add("username", username)
|
||||||
|
formBody.add("password", password)
|
||||||
|
val body = formBody.build()
|
||||||
|
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("https://$server/api/user/register")
|
||||||
|
.post(body)
|
||||||
|
.addHeader("content-type", "application/x-www-form-urlencoded")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
response = client.newCall(request).execute()
|
||||||
|
}.join()
|
||||||
|
|
||||||
|
return when (response.code) {
|
||||||
|
200 -> {
|
||||||
|
login(server, username, password)
|
||||||
|
}
|
||||||
|
400 -> {
|
||||||
|
"Such username exists"
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
"Unknown error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun login(server: String, username: String, password: String): String {
|
||||||
|
lateinit var response: Response
|
||||||
|
thread {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
|
val formBody = FormBody.Builder()
|
||||||
|
formBody.add("username", username)
|
||||||
|
formBody.add("password", password)
|
||||||
|
val body = formBody.build()
|
||||||
|
|
||||||
|
val requestLogin = Request.Builder()
|
||||||
|
.url("https://$server/api/user/login")
|
||||||
|
.post(body)
|
||||||
|
.addHeader("content-type", "application/x-www-form-urlencoded")
|
||||||
|
.build()
|
||||||
|
response = client.newCall(requestLogin).execute()
|
||||||
|
}.join()
|
||||||
|
|
||||||
|
return response.body!!.string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun uploadAbstractProduct(server: String, groupId: Int, abstractProduct: AbstractProduct, imageFile: File, token: String): String {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
|
thread {
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
|
val body = MultipartBody.Builder()
|
||||||
|
body.setType("multipart/form-data".toMediaType())
|
||||||
|
body.addFormDataPart("file", imageFile.name, imageFile.asRequestBody("image/png".toMediaTypeOrNull()))
|
||||||
|
body.addFormDataPart("groupId", groupId.toString())
|
||||||
|
body.addFormDataPart("localId", abstractProduct.id.toString())
|
||||||
|
body.addFormDataPart("barcode", abstractProduct.barcode)
|
||||||
|
body.addFormDataPart("name", abstractProduct.name)
|
||||||
|
body.addFormDataPart("net_weight", abstractProduct.netWeight.toString())
|
||||||
|
body.addFormDataPart("image_filename", abstractProduct.imageHash)
|
||||||
|
body.addFormDataPart("category", abstractProduct.category.toString())
|
||||||
|
body.addFormDataPart("unit", abstractProduct.unit.toString())
|
||||||
|
|
||||||
|
val requestBody = body.build()
|
||||||
|
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("https://$server/api/abstractproduct/create")
|
||||||
|
.post(requestBody)
|
||||||
|
.addHeader("Authorization", "Bearer $token")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
response = client.newCall(request).execute()
|
||||||
|
}.join()
|
||||||
|
|
||||||
|
val responseText = response.body!!.string()
|
||||||
|
|
||||||
|
return responseText
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,40 +0,0 @@
|
||||||
package org.foxarmy.barcodescannerforemployees
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.widget.Toast
|
|
||||||
import com.android.volley.toolbox.StringRequest
|
|
||||||
import com.android.volley.toolbox.Volley
|
|
||||||
|
|
||||||
class Requester constructor(var siteName: String, var endpoint: String) {
|
|
||||||
var response = ""
|
|
||||||
|
|
||||||
fun request(context: Context, barcode: String) {
|
|
||||||
val url = "${siteName}/${endpoint}"
|
|
||||||
|
|
||||||
val volleyQueue = Volley.newRequestQueue(context)
|
|
||||||
val stringRequest = object: StringRequest(
|
|
||||||
Method.POST, url, { resp ->
|
|
||||||
run {
|
|
||||||
response =
|
|
||||||
if (resp == "") {
|
|
||||||
"Not found 404"
|
|
||||||
} else {
|
|
||||||
resp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Toast.makeText(context, "Cannot make request", Toast.LENGTH_LONG).show()
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
override fun getHeaders(): Map<String, String> {
|
|
||||||
return mapOf("referer" to "$siteName/")
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun getParams(): MutableMap<String, String> {
|
|
||||||
return mutableMapOf("barcode" to barcode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
volleyQueue.add(stringRequest)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -14,15 +14,19 @@ import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.widget.addTextChangedListener
|
import androidx.core.widget.addTextChangedListener
|
||||||
|
import androidx.security.crypto.EncryptedSharedPreferences
|
||||||
|
import androidx.security.crypto.MasterKeys
|
||||||
import com.journeyapps.barcodescanner.ScanContract
|
import com.journeyapps.barcodescanner.ScanContract
|
||||||
import com.journeyapps.barcodescanner.ScanIntentResult
|
import com.journeyapps.barcodescanner.ScanIntentResult
|
||||||
import com.journeyapps.barcodescanner.ScanOptions
|
import com.journeyapps.barcodescanner.ScanOptions
|
||||||
|
import okhttp3.internal.http.hasBody
|
||||||
import org.foxarmy.barcodescannerforemployees.*
|
import org.foxarmy.barcodescannerforemployees.*
|
||||||
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.StandardCopyOption
|
import java.nio.file.StandardCopyOption
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
class AddAbstractProductActivity : AppCompatActivity() {
|
class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
private lateinit var imageView: ImageView
|
private lateinit var imageView: ImageView
|
||||||
|
@ -147,7 +151,21 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
arrayOf(abstractProduct!!.id.toString())
|
arrayOf(abstractProduct!!.id.toString())
|
||||||
)
|
)
|
||||||
} else if (action == "new" || action == "new_from_barcode"){
|
} else if (action == "new" || action == "new_from_barcode"){
|
||||||
db.insert(AbstractProductContract.AbstractProductEntry.TABLE_NAME, null, values)
|
val id = db.insert(AbstractProductContract.AbstractProductEntry.TABLE_NAME, null, values)
|
||||||
|
val n = Net()
|
||||||
|
val abstractProduct = AbstractProduct(id.toInt(), barcode, productName, netWeight.toString().toDouble(), pictureFile.nameWithoutExtension, categorySpinner.selectedItemPosition, unitTypeSpinner.selectedItemPosition)
|
||||||
|
val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
|
||||||
|
|
||||||
|
val sharedPreferences = EncryptedSharedPreferences.create(
|
||||||
|
// passing a file name to share a preferences
|
||||||
|
"sensitive",
|
||||||
|
masterKeyAlias,
|
||||||
|
applicationContext,
|
||||||
|
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
||||||
|
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
||||||
|
)
|
||||||
|
val token = sharedPreferences.getString("token", "")
|
||||||
|
val response = n.uploadAbstractProduct("bsfe.foxarmy.org", 1, abstractProduct, File(pictureFile.absolutePath), token!!);
|
||||||
}
|
}
|
||||||
|
|
||||||
finish()
|
finish()
|
||||||
|
@ -165,8 +183,10 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
|
|
||||||
fun performRequest(barcode: String) {
|
fun performRequest(barcode: String) {
|
||||||
barcodeText.setText(this.barcode)
|
barcodeText.setText(this.barcode)
|
||||||
val requester = Requester("https://ean-online.ru", "match.php")
|
val net = Net();
|
||||||
requester.request(this, barcode)
|
val result = net.requestProductFromOnlineDB(barcode)
|
||||||
|
Log.d("QWERTYUIOP", "Result of request: $result")
|
||||||
|
|
||||||
var abstractProduct: AbstractProduct
|
var abstractProduct: AbstractProduct
|
||||||
|
|
||||||
if (DBStorageController(this).findAbstractProductByBarcode(
|
if (DBStorageController(this).findAbstractProductByBarcode(
|
||||||
|
@ -194,10 +214,7 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
thread {
|
thread {
|
||||||
// Я сам в ахуях какой это костыль, пока хз как фиксить, потом придумаю :))
|
if (result == "Not found 404") {
|
||||||
while (requester.response == "") {
|
|
||||||
}
|
|
||||||
if (requester.response == "Not found 404") {
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
Toast.makeText(this, getString(R.string.no_product_in_online_database), Toast.LENGTH_LONG)
|
Toast.makeText(this, getString(R.string.no_product_in_online_database), Toast.LENGTH_LONG)
|
||||||
.show()
|
.show()
|
||||||
|
@ -207,8 +224,7 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
return@thread
|
return@thread
|
||||||
}
|
}
|
||||||
|
|
||||||
abstractProduct = Parser().parse(requester.response)
|
abstractProduct = Parser().parse(result)
|
||||||
requester.response = ""
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
productNameText.text = abstractProduct.name
|
productNameText.text = abstractProduct.name
|
||||||
netWeightText.text = abstractProduct.netWeight.toString()
|
netWeightText.text = abstractProduct.netWeight.toString()
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
package org.foxarmy.barcodescannerforemployees.activities
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.security.crypto.EncryptedSharedPreferences
|
||||||
|
import androidx.security.crypto.MasterKeys
|
||||||
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
|
import org.foxarmy.barcodescannerforemployees.databinding.ActivityLoginBinding
|
||||||
|
|
||||||
|
class LoginActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private lateinit var binding: ActivityLoginBinding;
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
binding = ActivityLoginBinding.inflate(layoutInflater);
|
||||||
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
|
||||||
|
|
||||||
|
val sharedPreferences = EncryptedSharedPreferences.create(
|
||||||
|
// passing a file name to share a preferences
|
||||||
|
"sensitive",
|
||||||
|
masterKeyAlias,
|
||||||
|
applicationContext,
|
||||||
|
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
||||||
|
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
||||||
|
)
|
||||||
|
|
||||||
|
binding.loginButton.setOnClickListener {
|
||||||
|
val server = binding.serverTextEdit.text.toString()
|
||||||
|
val username = binding.usernameTextEdit.text.toString()
|
||||||
|
val password = binding.passwordTextEdit.text.toString()
|
||||||
|
|
||||||
|
val n = Net()
|
||||||
|
|
||||||
|
val response = n.login(server, username, password)
|
||||||
|
|
||||||
|
if (response == "Wrong password") {
|
||||||
|
Toast.makeText(this, getString(R.string.wrong_password), Toast.LENGTH_SHORT).show()
|
||||||
|
} else {
|
||||||
|
sharedPreferences.edit().putString("token", response).apply()
|
||||||
|
val intent = Intent(this, MainActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.registerButton.setOnClickListener {
|
||||||
|
val server = binding.serverTextEdit.text.toString()
|
||||||
|
val username = binding.usernameTextEdit.text.toString()
|
||||||
|
val password = binding.passwordTextEdit.text.toString()
|
||||||
|
|
||||||
|
val n = Net()
|
||||||
|
|
||||||
|
val response = n.registerAccount(server, username, password);
|
||||||
|
|
||||||
|
if (response == "Such username exists") {
|
||||||
|
Toast.makeText(this, getString(R.string.username_already_exists), Toast.LENGTH_SHORT).show();
|
||||||
|
} else {
|
||||||
|
sharedPreferences.edit().putString("token", response).apply()
|
||||||
|
val intent = Intent(this, MainActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -69,6 +69,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
extras.putParcelable("product", null)
|
extras.putParcelable("product", null)
|
||||||
addProductIntent.putExtras(extras)
|
addProductIntent.putExtras(extras)
|
||||||
ContextCompat.startActivity(this, addProductIntent, extras)
|
ContextCompat.startActivity(this, addProductIntent, extras)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package org.foxarmy.barcodescannerforemployees.activities
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.security.crypto.EncryptedSharedPreferences
|
||||||
|
import androidx.security.crypto.MasterKeys
|
||||||
|
|
||||||
|
class NavigatorActivity : Activity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
var intent = Intent(this, LoginActivity::class.java)
|
||||||
|
|
||||||
|
if (isAuthenticated()) {
|
||||||
|
intent = Intent(this, MainActivity::class.java);
|
||||||
|
}
|
||||||
|
|
||||||
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isAuthenticated(): Boolean {
|
||||||
|
val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
|
||||||
|
|
||||||
|
val sharedPreferences = EncryptedSharedPreferences.create(
|
||||||
|
// passing a file name to share a preferences
|
||||||
|
"sensitive",
|
||||||
|
masterKeyAlias,
|
||||||
|
applicationContext,
|
||||||
|
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
||||||
|
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
||||||
|
)
|
||||||
|
|
||||||
|
val jwt = sharedPreferences.getString("token", "")
|
||||||
|
return jwt != ""
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?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"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:text="@string/register"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" android:id="@+id/registerButton"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/loginButton" app:layout_constraintHorizontal_bias="0.15"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/offlineButton" android:layout_marginBottom="64dp"/>
|
||||||
|
<Button
|
||||||
|
android:text="@string/login"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" android:id="@+id/loginButton"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/registerButton" app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
android:layout_marginStart="2dp"
|
||||||
|
app:layout_constraintHorizontal_bias="0.1" app:layout_constraintBottom_toTopOf="@+id/offlineButton"
|
||||||
|
android:layout_marginBottom="64dp"/>
|
||||||
|
<Button
|
||||||
|
android:text="@string/offline"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" android:id="@+id/offlineButton"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
android:layout_marginBottom="300dp"/>
|
||||||
|
<EditText
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:inputType="text"
|
||||||
|
android:ems="10"
|
||||||
|
android:id="@+id/usernameTextEdit"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
android:hint="@string/username" app:layout_constraintBottom_toTopOf="@+id/passwordTextEdit"
|
||||||
|
android:layout_marginBottom="16dp"/>
|
||||||
|
<EditText
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:inputType="textPassword"
|
||||||
|
android:ems="10"
|
||||||
|
android:id="@+id/passwordTextEdit"
|
||||||
|
android:hint="@string/password" app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toTopOf="@+id/registerButton"
|
||||||
|
android:layout_marginBottom="24dp"/>
|
||||||
|
<EditText
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="text"
|
||||||
|
android:ems="10"
|
||||||
|
android:id="@+id/serverTextEdit"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/usernameTextEdit" android:layout_marginBottom="16dp"
|
||||||
|
android:hint="@string/server" android:text="bsfe.foxarmy.org"/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,61 +1,74 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
<androidx.drawerlayout.widget.DrawerLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:fitsSystemWindows="true"
|
tools:context=".activities.MainActivity"
|
||||||
tools:context=".activities.MainActivity">
|
android:fitsSystemWindows="true">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" android:id="@+id/storageLayout">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:fitsSystemWindows="true"
|
|
||||||
>
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
|
||||||
android:id="@+id/toolbar"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"/>
|
android:layout_height="match_parent" android:id="@+id/storageLayout">
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/tab_tablayout"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:fitsSystemWindows="true"
|
||||||
app:tabIndicatorColor="#FFF"
|
android:id="@+id/appBarLayout">
|
||||||
app:tabIndicatorHeight="3dp"
|
|
||||||
app:tabMode="fixed" />
|
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"/>
|
||||||
|
|
||||||
<!-- <include layout="@layout/content_storage"/>-->
|
<com.google.android.material.tabs.TabLayout
|
||||||
<androidx.viewpager.widget.ViewPager
|
android:id="@+id/tab_tablayout"
|
||||||
android:id="@+id/tab_viewpager"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"
|
||||||
|
app:tabIndicatorColor="#FFF"
|
||||||
|
app:tabIndicatorHeight="3dp"
|
||||||
|
app:tabMode="fixed"/>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
<androidx.viewpager.widget.ViewPager
|
||||||
|
android:id="@+id/tab_viewpager"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="777dp"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior" android:layout_gravity="bottom"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/appBarLayout"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="6dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="6dp"/>
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/new_element_fab"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
app:srcCompat="@android:drawable/ic_input_add"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
android:layout_marginEnd="16dp" android:layout_marginBottom="16dp"/>
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="true" app:srcCompat="@android:drawable/ic_menu_my_calendar"
|
||||||
|
android:id="@+id/expiryCalendarFab" android:layout_gravity="bottom|end"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/new_element_fab" android:layout_marginBottom="16dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="16dp"/>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<!-- <include layout="@layout/content_storage"/>-->
|
||||||
|
|
||||||
|
<com.google.android.material.navigation.NavigationView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginTop="5dp"
|
android:layout_gravity="start"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
app:menu="@menu/drawer_menu" />
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
</androidx.drawerlayout.widget.DrawerLayout>
|
||||||
android:id="@+id/new_element_fab"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom|end"
|
|
||||||
android:layout_marginEnd="@dimen/fab_margin"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
app:srcCompat="@android:drawable/ic_input_add"/>
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:clickable="true" app:srcCompat="@android:drawable/ic_menu_my_calendar"
|
|
||||||
android:id="@+id/expiryCalendarFab" android:layout_gravity="bottom|end"
|
|
||||||
tools:layout_editor_absoluteY="742dp" tools:layout_editor_absoluteX="337dp"
|
|
||||||
android:layout_marginBottom="84dp" android:layout_marginRight="16dp"/>
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_account"
|
||||||
|
android:title="@string/my_account" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_settings"
|
||||||
|
android:title="@string/settings" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/nav_logout"
|
||||||
|
android:title="@string/my_groups" />
|
||||||
|
</menu>
|
|
@ -3,7 +3,7 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:context="org.foxarmy.barcodescannerforemployees.activities.MainActivity">
|
tools:context="org.foxarmy.barcodescannerforemployees.activities.MainActivity">
|
||||||
<item android:id="@+id/action_settings"
|
<item android:id="@+id/action_settings"
|
||||||
android:title="@string/action_settings"
|
android:title="@string/settings"
|
||||||
android:orderInCategory="100"
|
android:orderInCategory="100"
|
||||||
app:showAsAction="never"/>
|
app:showAsAction="never"/>
|
||||||
<item android:id="@+id/action_delete" android:title="@string/delete_menu"/>
|
<item android:id="@+id/action_delete" android:title="@string/delete_menu"/>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">СканнерШтрихкодовДляРаботников</string>
|
<string name="app_name">СканнерШтрихкодовДляРаботников</string>
|
||||||
<string name="action_settings">Настройки</string>
|
<string name="settings">Настройки</string>
|
||||||
<string name="first_fragment_label">Добавить продукт</string>
|
<string name="first_fragment_label">Добавить продукт</string>
|
||||||
<string name="second_fragment_label">Продукты</string>
|
<string name="second_fragment_label">Продукты</string>
|
||||||
<string name="scan_label">Сканировать</string>
|
<string name="scan_label">Сканировать</string>
|
||||||
|
@ -87,6 +87,16 @@
|
||||||
ошибка сканирования или введите данные вручную
|
ошибка сканирования или введите данные вручную
|
||||||
</string>
|
</string>
|
||||||
<string name="abstract_product_request">Пожалуйста, отсканируйте штрихкод, чтобы добавить продукт</string>
|
<string name="abstract_product_request">Пожалуйста, отсканируйте штрихкод, чтобы добавить продукт</string>
|
||||||
<string name="no_barcode">No barcode present</string>
|
<string name="no_barcode">Нет штрихкода</string>
|
||||||
<string name="no_barcode_button">No barcode</string>
|
<string name="no_barcode_button">Без штрихкода</string>
|
||||||
|
<string name="register">Зарегистрироваться</string>
|
||||||
|
<string name="login">Войти</string>
|
||||||
|
<string name="offline">Оффлайн</string>
|
||||||
|
<string name="username">Имя пользователя</string>
|
||||||
|
<string name="password">Пароль</string>
|
||||||
|
<string name="username_already_exists">Имя пользователя занято</string>
|
||||||
|
<string name="wrong_password">Неправильный пароль</string>
|
||||||
|
<string name="server">Сервер</string>
|
||||||
|
<string name="my_account">Мой аккаунт</string>
|
||||||
|
<string name="my_groups">Мои группы</string>
|
||||||
</resources>
|
</resources>
|
|
@ -1,6 +1,6 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">BarcodeScannerForEmployees</string>
|
<string name="app_name">BarcodeScannerForEmployees</string>
|
||||||
<string name="action_settings">Settings</string>
|
<string name="settings">Settings</string>
|
||||||
<string name="first_fragment_label">Add new product</string>
|
<string name="first_fragment_label">Add new product</string>
|
||||||
<string name="second_fragment_label">Products</string>
|
<string name="second_fragment_label">Products</string>
|
||||||
<string name="netWeight">Net weight</string>
|
<string name="netWeight">Net weight</string>
|
||||||
|
@ -87,4 +87,14 @@
|
||||||
<string name="abstract_product_request">Please, scan a barcode in order to add product</string>
|
<string name="abstract_product_request">Please, scan a barcode in order to add product</string>
|
||||||
<string name="no_barcode">No barcode present</string>
|
<string name="no_barcode">No barcode present</string>
|
||||||
<string name="no_barcode_button">No barcode</string>
|
<string name="no_barcode_button">No barcode</string>
|
||||||
|
<string name="register">Register</string>
|
||||||
|
<string name="login">Login</string>
|
||||||
|
<string name="offline">Offline</string>
|
||||||
|
<string name="username">Username</string>
|
||||||
|
<string name="password">Password</string>
|
||||||
|
<string name="username_already_exists">Such account already exists</string>
|
||||||
|
<string name="wrong_password">Wrong password</string>
|
||||||
|
<string name="server">Server</string>
|
||||||
|
<string name="my_account">My account</string>
|
||||||
|
<string name="my_groups">My groups</string>
|
||||||
</resources>
|
</resources>
|
|
@ -17,15 +17,19 @@ gridlayout = "1.0.0"
|
||||||
activity = "1.9.2"
|
activity = "1.9.2"
|
||||||
legacySupportV4 = "1.0.0"
|
legacySupportV4 = "1.0.0"
|
||||||
fragment = "1.8.4"
|
fragment = "1.8.4"
|
||||||
|
okhttp = "4.10.0"
|
||||||
playServicesCodeScanner = "16.1.0"
|
playServicesCodeScanner = "16.1.0"
|
||||||
|
securityCrypto = "1.0.0"
|
||||||
volley = "1.2.1"
|
volley = "1.2.1"
|
||||||
zxingAndroidEmbedded = "4.3.0"
|
zxingAndroidEmbedded = "4.3.0"
|
||||||
|
material3Android = "1.3.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "cameraView" }
|
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "cameraView" }
|
||||||
androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "cameraView" }
|
androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "cameraView" }
|
||||||
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "cameraView" }
|
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "cameraView" }
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
|
androidx-security-crypto = { module = "androidx.security:security-crypto", version.ref = "securityCrypto" }
|
||||||
barcode-scanning = { module = "com.google.mlkit:barcode-scanning", version.ref = "barcodeScanning" }
|
barcode-scanning = { module = "com.google.mlkit:barcode-scanning", version.ref = "barcodeScanning" }
|
||||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||||
|
@ -40,9 +44,11 @@ androidx-gridlayout = { group = "androidx.gridlayout", name = "gridlayout", vers
|
||||||
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
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-legacy-support-v4 = { group = "androidx.legacy", name = "legacy-support-v4", version.ref = "legacySupportV4" }
|
||||||
androidx-fragment = { group = "androidx.fragment", name = "fragment", version.ref = "fragment" }
|
androidx-fragment = { group = "androidx.fragment", name = "fragment", version.ref = "fragment" }
|
||||||
|
okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
|
||||||
play-services-code-scanner = { module = "com.google.android.gms:play-services-code-scanner", version.ref = "playServicesCodeScanner" }
|
play-services-code-scanner = { module = "com.google.android.gms:play-services-code-scanner", version.ref = "playServicesCodeScanner" }
|
||||||
volley = { module = "com.android.volley:volley", version.ref = "volley" }
|
volley = { module = "com.android.volley:volley", version.ref = "volley" }
|
||||||
zxing-android-embedded = { module = "com.journeyapps:zxing-android-embedded", version.ref = "zxingAndroidEmbedded" }
|
zxing-android-embedded = { module = "com.journeyapps:zxing-android-embedded", version.ref = "zxingAndroidEmbedded" }
|
||||||
|
androidx-material3-android = { group = "androidx.compose.material3", name = "material3-android", version.ref = "material3Android" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|
Loading…
Reference in New Issue