done groups
This commit is contained in:
		@@ -56,6 +56,14 @@
 | 
			
		||||
                android:name=".activities.LoginActivity"
 | 
			
		||||
                android:exported="false"
 | 
			
		||||
                android:theme="@style/Theme.BarcodeScannerForEmployees"/>
 | 
			
		||||
        <activity
 | 
			
		||||
                android:name=".activities.AccountSettingsActivity"
 | 
			
		||||
                android:exported="false"
 | 
			
		||||
                android:theme="@style/Theme.BarcodeScannerForEmployees"/>
 | 
			
		||||
        <activity
 | 
			
		||||
                android:name=".activities.GroupActivity"
 | 
			
		||||
                android:exported="false"
 | 
			
		||||
                android:theme="@style/Theme.BarcodeScannerForEmployees"/>
 | 
			
		||||
        <activity
 | 
			
		||||
                android:name=".activities.FullscreenActivity"
 | 
			
		||||
                android:configChanges="orientation|keyboardHidden|screenSize"
 | 
			
		||||
@@ -69,7 +77,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.AddAbstractProductActivity.provider;com.google.firebase.components.activities.AddProductActivity.provider;com.google.firebase.components.activities.ExpiryCalendarActivity.provider;com.google.firebase.components.activities.FindBarcodelessAbstractProduct.provider;com.google.firebase.components.activities.ExpiryCalendarGroupActivity.provider"
 | 
			
		||||
                android:authorities="com.google.firebase.components.activities.MainActivity.provider;com.google.firebase.components.activities.FullscreenActivity.provider;com.google.firebase.components.activities.AddAbstractProductActivity.provider;com.google.firebase.components.activities.AddProductActivity.provider;com.google.firebase.components.activities.ExpiryCalendarActivity.provider;com.google.firebase.components.activities.FindBarcodelessAbstractProduct.provider;com.google.firebase.components.activities.ExpiryCalendarGroupActivity.provider;com.google.firebase.components.activities.AccountSettingsActivity.provider;com.google.firebase.components.activities.GroupActivity.provider"
 | 
			
		||||
                android:exported="false"
 | 
			
		||||
                android:grantUriPermissions="true">
 | 
			
		||||
            <meta-data
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,8 @@ import kotlin.concurrent.thread
 | 
			
		||||
 | 
			
		||||
class Net {
 | 
			
		||||
    var language = "en-US"
 | 
			
		||||
    var server = "bsfe.foxarmy.org"
 | 
			
		||||
    var token = ""
 | 
			
		||||
 | 
			
		||||
    fun requestProductFromOnlineDB(barcode: String): String {
 | 
			
		||||
        var response = ""
 | 
			
		||||
@@ -38,8 +40,7 @@ class Net {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun registerAccount(server: String, username: String, password: String): String {
 | 
			
		||||
        var token = ""
 | 
			
		||||
    fun registerAccount(username: String, password: String): Response {
 | 
			
		||||
        lateinit var response: Response
 | 
			
		||||
        thread {
 | 
			
		||||
            val client = OkHttpClient()
 | 
			
		||||
@@ -59,10 +60,10 @@ class Net {
 | 
			
		||||
            response = client.newCall(request).execute()
 | 
			
		||||
        }.join()
 | 
			
		||||
 | 
			
		||||
        return response.body!!.string()
 | 
			
		||||
        return response
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun login(server: String, username: String, password: String): String {
 | 
			
		||||
    fun login(username: String, password: String): Response {
 | 
			
		||||
        lateinit var response: Response
 | 
			
		||||
        thread {
 | 
			
		||||
            val client = OkHttpClient()
 | 
			
		||||
@@ -81,10 +82,10 @@ class Net {
 | 
			
		||||
            response = client.newCall(requestLogin).execute()
 | 
			
		||||
        }.join()
 | 
			
		||||
 | 
			
		||||
        return response.body!!.string()
 | 
			
		||||
        return response
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun uploadAbstractProduct(server: String, groupId: Int, abstractProduct: AbstractProduct, imageFile: File, token: String): String {
 | 
			
		||||
    fun uploadAbstractProduct(groupId: Int, abstractProduct: AbstractProduct, imageFile: File): Response {
 | 
			
		||||
        lateinit var response: Response
 | 
			
		||||
 | 
			
		||||
        thread {
 | 
			
		||||
@@ -113,12 +114,10 @@ class Net {
 | 
			
		||||
            response = client.newCall(request).execute()
 | 
			
		||||
        }.join()
 | 
			
		||||
 | 
			
		||||
        val responseText = response.body!!.string()
 | 
			
		||||
 | 
			
		||||
        return responseText
 | 
			
		||||
        return response
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun changeUsername(server: String, token: String, newUsername: String): String {
 | 
			
		||||
    fun changeUsername( newUsername: String): Response {
 | 
			
		||||
 | 
			
		||||
        lateinit var response: Response
 | 
			
		||||
 | 
			
		||||
@@ -138,12 +137,10 @@ class Net {
 | 
			
		||||
            response = client.newCall(request).execute()
 | 
			
		||||
        }.join()
 | 
			
		||||
 | 
			
		||||
        val responseText = response.body!!.string()
 | 
			
		||||
 | 
			
		||||
        return responseText
 | 
			
		||||
        return response
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun changePassword(server: String, token: String, newPassword: String): String {
 | 
			
		||||
    fun changePassword(newPassword: String): Response {
 | 
			
		||||
 | 
			
		||||
        lateinit var response: Response
 | 
			
		||||
 | 
			
		||||
@@ -163,6 +160,70 @@ class Net {
 | 
			
		||||
            response = client.newCall(request).execute()
 | 
			
		||||
        }.join()
 | 
			
		||||
 | 
			
		||||
        return response
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun createGroup(name: String, password: String): Response {
 | 
			
		||||
        lateinit var response: Response
 | 
			
		||||
 | 
			
		||||
        thread {
 | 
			
		||||
            val client = OkHttpClient()
 | 
			
		||||
 | 
			
		||||
            val body = FormBody.Builder()
 | 
			
		||||
 | 
			
		||||
            val requestBody = body.build()
 | 
			
		||||
 | 
			
		||||
            val request = Request.Builder().url("https://$server/api/group/create/$name")
 | 
			
		||||
                .post(requestBody)
 | 
			
		||||
                .addHeader("Authorization", "Bearer $token")
 | 
			
		||||
                .addHeader("accept-language", language)
 | 
			
		||||
                .build()
 | 
			
		||||
            response = client.newCall(request).execute()
 | 
			
		||||
        }.join()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        return changeGroupPassword(name, password)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun changeGroupPassword(name: String, password: String): Response {
 | 
			
		||||
        lateinit var response: Response
 | 
			
		||||
 | 
			
		||||
        thread {
 | 
			
		||||
 | 
			
		||||
            val groupId = getGroupId(name);
 | 
			
		||||
 | 
			
		||||
            val client = OkHttpClient()
 | 
			
		||||
 | 
			
		||||
            val body = FormBody.Builder()
 | 
			
		||||
            body.add("password", password)
 | 
			
		||||
 | 
			
		||||
            val requestBody = body.build()
 | 
			
		||||
 | 
			
		||||
            val request = Request.Builder().url("https://$server/api/group/password/$groupId")
 | 
			
		||||
                .post(requestBody)
 | 
			
		||||
                .addHeader("Authorization", "Bearer $token")
 | 
			
		||||
                .addHeader("accept-language", language)
 | 
			
		||||
                .build()
 | 
			
		||||
            response = client.newCall(request).execute()
 | 
			
		||||
        }.join()
 | 
			
		||||
 | 
			
		||||
        return response
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun getGroupId(name: String): String {
 | 
			
		||||
        lateinit var response: Response
 | 
			
		||||
 | 
			
		||||
        thread {
 | 
			
		||||
            val client = OkHttpClient()
 | 
			
		||||
 | 
			
		||||
            val request = Request.Builder().url("https://$server/api/group/byName/$name")
 | 
			
		||||
                .get()
 | 
			
		||||
                .addHeader("Authorization", "Bearer $token")
 | 
			
		||||
                .addHeader("accept-language", language)
 | 
			
		||||
                .build()
 | 
			
		||||
            response = client.newCall(request).execute()
 | 
			
		||||
        }.join()
 | 
			
		||||
 | 
			
		||||
        val responseText = response.body!!.string()
 | 
			
		||||
 | 
			
		||||
        return responseText
 | 
			
		||||
 
 | 
			
		||||
@@ -29,16 +29,20 @@ class AccountSettingsActivity : AppCompatActivity() {
 | 
			
		||||
            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        val server = sharedPreferences.getString("server", "bsfe.foxarmy.org")
 | 
			
		||||
        val token = sharedPreferences.getString("token", "")
 | 
			
		||||
        val net = Net()
 | 
			
		||||
 | 
			
		||||
        net.server = sharedPreferences.getString("server", "bsfe.foxarmy.org")!!
 | 
			
		||||
        net.language = sharedPreferences.getString("language", "")!!
 | 
			
		||||
        net.token = sharedPreferences.getString("token", "")!!
 | 
			
		||||
 | 
			
		||||
        binding.saveUsernameButton.setOnClickListener {
 | 
			
		||||
            Toast.makeText(this, net.changeUsername(server!!, token!!, binding.newUsernameTextEdit.text.toString()), Toast.LENGTH_LONG).show()
 | 
			
		||||
            val response = net.changeUsername(binding.newUsernameTextEdit.text.toString())
 | 
			
		||||
            Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        binding.savePasswordButton.setOnClickListener {
 | 
			
		||||
            Toast.makeText(this, net.changePassword(server!!, token!!, binding.newPasswordTextEdit.text.toString()), Toast.LENGTH_LONG).show()
 | 
			
		||||
            val response = net.changePassword(binding.newPasswordTextEdit.text.toString())
 | 
			
		||||
            Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -161,14 +161,14 @@ class AddAbstractProductActivity : AppCompatActivity() {
 | 
			
		||||
                    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
 | 
			
		||||
                    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
 | 
			
		||||
                )
 | 
			
		||||
                val language = sharedPreferences.getString("language", "en-US")
 | 
			
		||||
                n.language = language!!
 | 
			
		||||
                val token = sharedPreferences.getString("token", "")
 | 
			
		||||
                val response = n.uploadAbstractProduct("bsfe.foxarmy.org", 1, abstractProduct, File(pictureFile.absolutePath), token!!);
 | 
			
		||||
 | 
			
		||||
                Toast.makeText(this, response, Toast.LENGTH_LONG).show()
 | 
			
		||||
                n.language = sharedPreferences.getString("language", "en-US")!!
 | 
			
		||||
                n.server = sharedPreferences.getString("server", "")!!
 | 
			
		||||
                n.token = sharedPreferences.getString("token", "")!!
 | 
			
		||||
                val response = n.uploadAbstractProduct(1, abstractProduct, File(pictureFile.absolutePath));
 | 
			
		||||
 | 
			
		||||
                Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show()
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            finish()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,54 @@
 | 
			
		||||
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.databinding.ActivityGroupBinding
 | 
			
		||||
 | 
			
		||||
class GroupActivity : AppCompatActivity() {
 | 
			
		||||
 | 
			
		||||
    private lateinit var binding: ActivityGroupBinding
 | 
			
		||||
 | 
			
		||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
			
		||||
        super.onCreate(savedInstanceState)
 | 
			
		||||
 | 
			
		||||
        binding = ActivityGroupBinding.inflate(layoutInflater)
 | 
			
		||||
        setContentView(binding.root)
 | 
			
		||||
 | 
			
		||||
        val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
 | 
			
		||||
 | 
			
		||||
        val sharedPreferences = EncryptedSharedPreferences.create(
 | 
			
		||||
            "sensitive",
 | 
			
		||||
            masterKeyAlias,
 | 
			
		||||
            applicationContext,
 | 
			
		||||
            EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
 | 
			
		||||
            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        binding.createGroupButton.setOnClickListener {
 | 
			
		||||
            val groupName = binding.groupNameTextEdit.text.toString()
 | 
			
		||||
            val groupPassword = binding.groupPasswordTextEdit.text.toString()
 | 
			
		||||
 | 
			
		||||
            val n = Net()
 | 
			
		||||
            n.language = sharedPreferences.getString("language", "en-US")!!
 | 
			
		||||
            n.server = sharedPreferences.getString("server", "")!!
 | 
			
		||||
            n.token = sharedPreferences.getString("token", "")!!
 | 
			
		||||
 | 
			
		||||
            val response = n.createGroup(groupName, groupPassword)
 | 
			
		||||
            val responseText = response.body!!.string()
 | 
			
		||||
            Toast.makeText(this, responseText, Toast.LENGTH_LONG).show()
 | 
			
		||||
 | 
			
		||||
            if (response.code == 200) {
 | 
			
		||||
                Toast.makeText(this, responseText, Toast.LENGTH_LONG).show()
 | 
			
		||||
                sharedPreferences.edit().putStringSet("groups", setOf(responseText))
 | 
			
		||||
                val intent = Intent(this, MainActivity::class.java)
 | 
			
		||||
                startActivity(intent)
 | 
			
		||||
                finish()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -41,13 +41,16 @@ class LoginActivity : AppCompatActivity() {
 | 
			
		||||
            sharedPreferences.edit().putString("language", language).apply()
 | 
			
		||||
 | 
			
		||||
            val n = Net()
 | 
			
		||||
            n.language = language
 | 
			
		||||
            n.language = sharedPreferences.getString("language", "en-US")!!
 | 
			
		||||
            n.server = server
 | 
			
		||||
 | 
			
		||||
            val response = n.login(server, username, password)
 | 
			
		||||
            if (response.length < 40) {
 | 
			
		||||
                Toast.makeText(this, response, Toast.LENGTH_SHORT).show()
 | 
			
		||||
            val response = n.login(username, password)
 | 
			
		||||
            val responseText = response.body!!.string()
 | 
			
		||||
            if (response.code != 200) {
 | 
			
		||||
                Toast.makeText(this, responseText, Toast.LENGTH_SHORT).show()
 | 
			
		||||
            } else {
 | 
			
		||||
                sharedPreferences.edit().putString("token", response).apply()
 | 
			
		||||
                sharedPreferences.edit().putString("token", responseText).apply()
 | 
			
		||||
                sharedPreferences.edit().putString("servre", server).apply()
 | 
			
		||||
                val intent = Intent(this, MainActivity::class.java)
 | 
			
		||||
                startActivity(intent)
 | 
			
		||||
                finish()
 | 
			
		||||
@@ -60,18 +63,21 @@ class LoginActivity : AppCompatActivity() {
 | 
			
		||||
            val password = binding.passwordTextEdit.text.toString()
 | 
			
		||||
            val language = resources.getStringArray(R.array.languages)[binding.languageSpinner.selectedItemPosition]
 | 
			
		||||
            sharedPreferences.edit().putString("language", language).apply()
 | 
			
		||||
            sharedPreferences.edit().putString("server", server).apply()
 | 
			
		||||
 | 
			
		||||
            val n = Net()
 | 
			
		||||
            n.language = language
 | 
			
		||||
 | 
			
		||||
            val response = n.registerAccount(server, username, password);
 | 
			
		||||
 | 
			
		||||
            if (response.length < 40) {
 | 
			
		||||
                Toast.makeText(this, response, Toast.LENGTH_SHORT).show();
 | 
			
		||||
            n.server = server
 | 
			
		||||
            val response = n.registerAccount(username, password);
 | 
			
		||||
            val responseText = response.body!!.string()
 | 
			
		||||
            if (response.code != 200) {
 | 
			
		||||
                Toast.makeText(this, responseText, Toast.LENGTH_SHORT).show();
 | 
			
		||||
            } else {
 | 
			
		||||
                sharedPreferences.edit().putString("token", response).apply()
 | 
			
		||||
                val token = n.login(username, password)
 | 
			
		||||
                sharedPreferences.edit().putString("token", token.body!!.string()).apply()
 | 
			
		||||
 | 
			
		||||
                sharedPreferences.edit().putString("server", server).apply()
 | 
			
		||||
                val intent = Intent(this, MainActivity::class.java)
 | 
			
		||||
                val intent = Intent(this, GroupActivity::class.java)
 | 
			
		||||
                startActivity(intent)
 | 
			
		||||
                finish()
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -10,21 +10,25 @@ class NavigatorActivity : Activity() {
 | 
			
		||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
			
		||||
        super.onCreate(savedInstanceState)
 | 
			
		||||
 | 
			
		||||
        var intent = Intent(this, LoginActivity::class.java)
 | 
			
		||||
        var intent = Intent(this, MainActivity::class.java)
 | 
			
		||||
 | 
			
		||||
        if (isAuthenticated()) {
 | 
			
		||||
            intent = Intent(this, MainActivity::class.java);
 | 
			
		||||
        if (!isInGroup()) {
 | 
			
		||||
            intent = Intent(this, GroupActivity::class.java)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!isAuthenticated()) {
 | 
			
		||||
            intent = Intent(this, LoginActivity::class.java);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        startActivity(intent);
 | 
			
		||||
        finish();
 | 
			
		||||
//        finish();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private 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,
 | 
			
		||||
@@ -35,4 +39,19 @@ class NavigatorActivity : Activity() {
 | 
			
		||||
        val jwt = sharedPreferences.getString("token", "")
 | 
			
		||||
        return jwt != ""
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun isInGroup(): Boolean {
 | 
			
		||||
        val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
 | 
			
		||||
 | 
			
		||||
        val sharedPreferences = EncryptedSharedPreferences.create(
 | 
			
		||||
            "sensitive",
 | 
			
		||||
            masterKeyAlias,
 | 
			
		||||
            applicationContext,
 | 
			
		||||
            EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
 | 
			
		||||
            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        val groups = sharedPreferences.getStringSet("groups", emptySet())
 | 
			
		||||
        return groups!!.isNotEmpty()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								app/src/main/res/layout/activity_group.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app/src/main/res/layout/activity_group.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
<?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">
 | 
			
		||||
    <EditText
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:inputType="text"
 | 
			
		||||
            android:ems="10"
 | 
			
		||||
            android:id="@+id/groupNameTextEdit"
 | 
			
		||||
            app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"
 | 
			
		||||
            android:hint="@string/group_name" app:layout_constraintTop_toTopOf="parent"
 | 
			
		||||
            android:layout_marginTop="210dp"/>
 | 
			
		||||
    <EditText
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:inputType="textPassword"
 | 
			
		||||
            android:ems="10"
 | 
			
		||||
            android:id="@+id/groupPasswordTextEdit"
 | 
			
		||||
            android:layout_marginTop="27dp"
 | 
			
		||||
            app:layout_constraintTop_toBottomOf="@+id/groupNameTextEdit" android:hint="@string/group_password"
 | 
			
		||||
            app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"/>
 | 
			
		||||
    <Button
 | 
			
		||||
            android:text="@string/create_group"
 | 
			
		||||
            android:layout_width="91dp"
 | 
			
		||||
            android:layout_height="wrap_content" android:id="@+id/createGroupButton"
 | 
			
		||||
            app:layout_constraintStart_toStartOf="parent"
 | 
			
		||||
            app:layout_constraintTop_toBottomOf="@+id/groupPasswordTextEdit"
 | 
			
		||||
            android:layout_marginTop="24dp" app:layout_constraintEnd_toStartOf="@+id/joinGroupButton"
 | 
			
		||||
            android:layout_marginEnd="12dp"/>
 | 
			
		||||
    <Button
 | 
			
		||||
            android:text="@string/join_group"
 | 
			
		||||
            android:layout_width="91dp"
 | 
			
		||||
            android:layout_height="wrap_content" android:id="@+id/joinGroupButton"
 | 
			
		||||
            app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/groupPasswordTextEdit"
 | 
			
		||||
            android:layout_marginTop="24dp" android:layout_marginStart="12dp"
 | 
			
		||||
            app:layout_constraintStart_toEndOf="@+id/createGroupButton"/>
 | 
			
		||||
</androidx.constraintlayout.widget.ConstraintLayout>
 | 
			
		||||
@@ -103,6 +103,10 @@
 | 
			
		||||
    <string name="nav_close">Navigation close</string>
 | 
			
		||||
    <string name="new_name">New name</string>
 | 
			
		||||
    <string name="new_password">New password</string>
 | 
			
		||||
    <string name="group_name">Group name</string>
 | 
			
		||||
    <string name="group_password">Group password</string>
 | 
			
		||||
    <string name="create_group">Create group</string>
 | 
			
		||||
    <string name="join_group">Join group</string>
 | 
			
		||||
    <string-array name="languages">
 | 
			
		||||
        <item>en-US</item>
 | 
			
		||||
        <item>ru-RU</item>
 | 
			
		||||
 
 | 
			
		||||
@@ -101,6 +101,10 @@
 | 
			
		||||
    <string name="nav_close">Navigation close</string>
 | 
			
		||||
    <string name="new_name">New name</string>
 | 
			
		||||
    <string name="new_password">New password</string>
 | 
			
		||||
    <string name="group_name">Group name</string>
 | 
			
		||||
    <string name="group_password">Group password</string>
 | 
			
		||||
    <string name="create_group">Create group</string>
 | 
			
		||||
    <string name="join_group">Join group</string>
 | 
			
		||||
    <string-array name="languages">
 | 
			
		||||
        <item>en-US</item>
 | 
			
		||||
        <item>ru-RU</item>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user