working on network and UI
This commit is contained in:
		@@ -48,6 +48,14 @@
 | 
			
		||||
                android:name=".activities.FindBarcodelessAbstractProduct"
 | 
			
		||||
                android:exported="false"
 | 
			
		||||
                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
 | 
			
		||||
                android:name=".activities.FullscreenActivity"
 | 
			
		||||
                android:configChanges="orientation|keyboardHidden|screenSize"
 | 
			
		||||
@@ -70,7 +78,7 @@
 | 
			
		||||
        </provider>
 | 
			
		||||
 | 
			
		||||
        <activity
 | 
			
		||||
                android:name=".activities.MainActivity"
 | 
			
		||||
                android:name=".activities.NavigatorActivity"
 | 
			
		||||
                android:exported="true"
 | 
			
		||||
                android:theme="@style/Theme.BarcodeScannerForEmployees">
 | 
			
		||||
            <intent-filter>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										127
									
								
								app/src/main/java/org/foxarmy/barcodescannerforemployees/Net.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								app/src/main/java/org/foxarmy/barcodescannerforemployees/Net.kt
									
									
									
									
									
										Normal file
									
								
							@@ -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.core.content.ContextCompat
 | 
			
		||||
import androidx.core.widget.addTextChangedListener
 | 
			
		||||
import androidx.security.crypto.EncryptedSharedPreferences
 | 
			
		||||
import androidx.security.crypto.MasterKeys
 | 
			
		||||
import com.journeyapps.barcodescanner.ScanContract
 | 
			
		||||
import com.journeyapps.barcodescanner.ScanIntentResult
 | 
			
		||||
import com.journeyapps.barcodescanner.ScanOptions
 | 
			
		||||
import okhttp3.internal.http.hasBody
 | 
			
		||||
import org.foxarmy.barcodescannerforemployees.*
 | 
			
		||||
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
 | 
			
		||||
import java.io.File
 | 
			
		||||
import java.nio.file.Files
 | 
			
		||||
import java.nio.file.StandardCopyOption
 | 
			
		||||
import kotlin.concurrent.thread
 | 
			
		||||
import kotlin.math.abs
 | 
			
		||||
 | 
			
		||||
class AddAbstractProductActivity : AppCompatActivity() {
 | 
			
		||||
    private lateinit var imageView: ImageView
 | 
			
		||||
@@ -147,7 +151,21 @@ class AddAbstractProductActivity : AppCompatActivity() {
 | 
			
		||||
                    arrayOf(abstractProduct!!.id.toString())
 | 
			
		||||
                )
 | 
			
		||||
            } 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()
 | 
			
		||||
@@ -165,8 +183,10 @@ class AddAbstractProductActivity : AppCompatActivity() {
 | 
			
		||||
 | 
			
		||||
    fun performRequest(barcode: String) {
 | 
			
		||||
        barcodeText.setText(this.barcode)
 | 
			
		||||
        val requester = Requester("https://ean-online.ru", "match.php")
 | 
			
		||||
        requester.request(this, barcode)
 | 
			
		||||
        val net = Net();
 | 
			
		||||
        val result = net.requestProductFromOnlineDB(barcode)
 | 
			
		||||
        Log.d("QWERTYUIOP", "Result of request: $result")
 | 
			
		||||
 | 
			
		||||
        var abstractProduct: AbstractProduct
 | 
			
		||||
 | 
			
		||||
        if (DBStorageController(this).findAbstractProductByBarcode(
 | 
			
		||||
@@ -194,10 +214,7 @@ class AddAbstractProductActivity : AppCompatActivity() {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        thread {
 | 
			
		||||
            // Я сам в ахуях какой это костыль, пока хз как фиксить, потом придумаю :))
 | 
			
		||||
            while (requester.response == "") {
 | 
			
		||||
            }
 | 
			
		||||
            if (requester.response == "Not found 404") {
 | 
			
		||||
            if (result == "Not found 404") {
 | 
			
		||||
                runOnUiThread {
 | 
			
		||||
                    Toast.makeText(this, getString(R.string.no_product_in_online_database), Toast.LENGTH_LONG)
 | 
			
		||||
                        .show()
 | 
			
		||||
@@ -207,8 +224,7 @@ class AddAbstractProductActivity : AppCompatActivity() {
 | 
			
		||||
                return@thread
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            abstractProduct = Parser().parse(requester.response)
 | 
			
		||||
            requester.response = ""
 | 
			
		||||
            abstractProduct = Parser().parse(result)
 | 
			
		||||
            runOnUiThread {
 | 
			
		||||
                productNameText.text = abstractProduct.name
 | 
			
		||||
                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)
 | 
			
		||||
                    addProductIntent.putExtras(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 != ""
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										56
									
								
								app/src/main/res/layout/activity_login.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								app/src/main/res/layout/activity_login.xml
									
									
									
									
									
										Normal file
									
								
							@@ -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"?>
 | 
			
		||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
 | 
			
		||||
<androidx.drawerlayout.widget.DrawerLayout
 | 
			
		||||
        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"
 | 
			
		||||
        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_height="match_parent" android:id="@+id/storageLayout">
 | 
			
		||||
            android:layout_height="match_parent">
 | 
			
		||||
 | 
			
		||||
    </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"
 | 
			
		||||
        <androidx.constraintlayout.widget.ConstraintLayout
 | 
			
		||||
                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
 | 
			
		||||
                android:id="@+id/tab_tablayout"
 | 
			
		||||
                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
 | 
			
		||||
                    android:layout_height="wrap_content"
 | 
			
		||||
                    android:layout_width="match_parent"
 | 
			
		||||
                    android:fitsSystemWindows="true"
 | 
			
		||||
                    android:id="@+id/appBarLayout">
 | 
			
		||||
 | 
			
		||||
    </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"/>-->
 | 
			
		||||
    <androidx.viewpager.widget.ViewPager
 | 
			
		||||
            android:id="@+id/tab_viewpager"
 | 
			
		||||
            android:layout_width="match_parent"
 | 
			
		||||
                <com.google.android.material.tabs.TabLayout
 | 
			
		||||
                        android:id="@+id/tab_tablayout"
 | 
			
		||||
                        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_marginTop="5dp"
 | 
			
		||||
            app:layout_behavior="@string/appbar_scrolling_view_behavior" />
 | 
			
		||||
            android:layout_gravity="start"
 | 
			
		||||
            app:menu="@menu/drawer_menu" />
 | 
			
		||||
 | 
			
		||||
    <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"
 | 
			
		||||
            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>
 | 
			
		||||
</androidx.drawerlayout.widget.DrawerLayout>
 | 
			
		||||
							
								
								
									
										16
									
								
								app/src/main/res/menu/drawer_menu.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								app/src/main/res/menu/drawer_menu.xml
									
									
									
									
									
										Normal file
									
								
							@@ -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"
 | 
			
		||||
      tools:context="org.foxarmy.barcodescannerforemployees.activities.MainActivity">
 | 
			
		||||
    <item android:id="@+id/action_settings"
 | 
			
		||||
          android:title="@string/action_settings"
 | 
			
		||||
          android:title="@string/settings"
 | 
			
		||||
          android:orderInCategory="100"
 | 
			
		||||
          app:showAsAction="never"/>
 | 
			
		||||
    <item android:id="@+id/action_delete" android:title="@string/delete_menu"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<resources>
 | 
			
		||||
    <string name="app_name">СканнерШтрихкодовДляРаботников</string>
 | 
			
		||||
    <string name="action_settings">Настройки</string>
 | 
			
		||||
    <string name="settings">Настройки</string>
 | 
			
		||||
    <string name="first_fragment_label">Добавить продукт</string>
 | 
			
		||||
    <string name="second_fragment_label">Продукты</string>
 | 
			
		||||
    <string name="scan_label">Сканировать</string>
 | 
			
		||||
@@ -87,6 +87,16 @@
 | 
			
		||||
        ошибка сканирования или введите данные вручную
 | 
			
		||||
    </string>
 | 
			
		||||
    <string name="abstract_product_request">Пожалуйста, отсканируйте штрихкод, чтобы добавить продукт</string>
 | 
			
		||||
    <string name="no_barcode">No barcode present</string>
 | 
			
		||||
    <string name="no_barcode_button">No barcode</string>
 | 
			
		||||
    <string name="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>
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<resources>
 | 
			
		||||
    <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="second_fragment_label">Products</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="no_barcode">No barcode present</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>
 | 
			
		||||
		Reference in New Issue
	
	Block a user