Compare commits
11 Commits
alpha-0.0.
...
master
Author | SHA1 | Date |
---|---|---|
leca | edd9c666ac | |
leca | 6bbf436f45 | |
leca | a860e4d59f | |
leca | 37e52b3f2f | |
leca | f18d7ad1e0 | |
leca | 1d7050c687 | |
leca | 153506fc83 | |
leca | abe2a850d6 | |
leca | 58a7ea7357 | |
leca | 2ebcfff51a | |
leca | 2676d8083e |
|
@ -0,0 +1,14 @@
|
||||||
|
package org.foxarmy.barcodescannerforemployees
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
|
||||||
|
class LoadingDialog : DialogFragment() {
|
||||||
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return super.onCreateDialog(savedInstanceState)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
package org.foxarmy.barcodescannerforemployees
|
package org.foxarmy.barcodescannerforemployees
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import okhttp3.*
|
import okhttp3.*
|
||||||
import okhttp3.MediaType.Companion.toMediaType
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
|
@ -11,19 +14,19 @@ import org.foxarmy.barcodescannerforemployees.dataclasses.Product
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import kotlin.concurrent.thread
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class Net {
|
class Net {
|
||||||
var language = "en-US"
|
var language = "en-US"
|
||||||
var server = "bsfe.foxarmy.org"
|
var server = "bsfe.foxarmy.org"
|
||||||
var token = ""
|
var token = ""
|
||||||
|
|
||||||
fun serverIsAvailable(context: Context): Boolean {
|
fun serverIsAvailable(context: Context, callback: (Boolean) -> Unit) {
|
||||||
if (!isInternetConnectionAvailable(context)) {
|
if (!isInternetConnectionAvailable(context)) {
|
||||||
return false
|
callback(false)
|
||||||
}
|
}
|
||||||
var flag = false
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
thread {
|
var flag = false
|
||||||
val client = OkHttpClient();
|
val client = OkHttpClient();
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url("https://$server/status")
|
.url("https://$server/status")
|
||||||
|
@ -32,17 +35,17 @@ class Net {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val response = client.newCall(request).execute();
|
val response = client.newCall(request).execute();
|
||||||
flag = response.code == 200;
|
flag = response.code == 200;
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
flag = false;
|
flag = false;
|
||||||
}
|
}
|
||||||
}.join()
|
callback(flag)
|
||||||
return flag
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestProductFromOnlineDB(barcode: String): String {
|
fun requestProductFromOnlineDB(barcode: String, callback: (Response) -> Unit) {
|
||||||
var response = ""
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
thread {
|
lateinit var response: Response
|
||||||
val url = "https://ean-online.ru/match.php"
|
val url = "https://ean-online.ru/match.php"
|
||||||
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
@ -58,19 +61,15 @@ class Net {
|
||||||
.addHeader("accept-language", language)
|
.addHeader("accept-language", language)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute().body!!.string()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
|
||||||
return if (response == "") {
|
|
||||||
"Not found 404"
|
|
||||||
} else {
|
|
||||||
response
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun registerAccount(username: String, password: String): Response {
|
fun registerAccount(username: String, password: String, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
thread {
|
lateinit var response: Response
|
||||||
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val body = FormBody.Builder()
|
val body = FormBody.Builder()
|
||||||
|
@ -86,14 +85,13 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun login(username: String, password: String): Response {
|
fun login(username: String, password: String, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
thread {
|
lateinit var response: Response
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val body = FormBody.Builder()
|
val body = FormBody.Builder()
|
||||||
|
@ -107,15 +105,19 @@ class Net {
|
||||||
.addHeader("accept-language", language)
|
.addHeader("accept-language", language)
|
||||||
.build()
|
.build()
|
||||||
response = client.newCall(requestLogin).execute()
|
response = client.newCall(requestLogin).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun uploadAbstractProduct(groupId: Int, abstractProduct: AbstractProduct, imageFile: File): Response {
|
fun uploadAbstractProduct(
|
||||||
lateinit var response: Response
|
groupId: Int,
|
||||||
|
abstractProduct: AbstractProduct,
|
||||||
|
imageFile: File,
|
||||||
|
callback: (Response) -> Unit,
|
||||||
|
) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val body = MultipartBody.Builder()
|
val body = MultipartBody.Builder()
|
||||||
|
@ -138,16 +140,14 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun changeUsername(newUsername: String): Response {
|
fun changeUsername(newUsername: String, callback: (Response) -> Unit) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
lateinit var response: Response
|
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val body = FormBody.Builder()
|
val body = FormBody.Builder()
|
||||||
|
@ -162,16 +162,14 @@ class Net {
|
||||||
.addHeader("accept-language", language)
|
.addHeader("accept-language", language)
|
||||||
.build()
|
.build()
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun changePassword(newPassword: String): Response {
|
fun changePassword(newPassword: String, callback: (Response) -> Unit) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
lateinit var response: Response
|
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val body = FormBody.Builder()
|
val body = FormBody.Builder()
|
||||||
|
@ -186,15 +184,12 @@ class Net {
|
||||||
.addHeader("accept-language", language)
|
.addHeader("accept-language", language)
|
||||||
.build()
|
.build()
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createGroup(name: String, password: String): Response {
|
fun createGroup(name: String, password: String, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val body = FormBody.Builder()
|
val body = FormBody.Builder()
|
||||||
|
@ -207,19 +202,19 @@ class Net {
|
||||||
.addHeader("Authorization", "Bearer $token")
|
.addHeader("Authorization", "Bearer $token")
|
||||||
.addHeader("accept-language", language)
|
.addHeader("accept-language", language)
|
||||||
.build()
|
.build()
|
||||||
response = client.newCall(request).execute()
|
val response = client.newCall(request).execute()
|
||||||
}.join()
|
|
||||||
|
|
||||||
|
changeGroupPassword(name, password, { responseFromPassword ->
|
||||||
|
callback(response)
|
||||||
|
})
|
||||||
|
|
||||||
changeGroupPassword(name, password)
|
}
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun joinGroup(id: Int, password: String): Response {
|
fun joinGroup(id: Int, password: String, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val body = FormBody.Builder()
|
val body = FormBody.Builder()
|
||||||
|
@ -233,41 +228,38 @@ class Net {
|
||||||
.addHeader("accept-language", language)
|
.addHeader("accept-language", language)
|
||||||
.build()
|
.build()
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun changeGroupPassword(name: String, password: String): Response {
|
fun changeGroupPassword(name: String, password: String, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
getGroupId(name, { groupId ->
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val groupId = getGroupId(name);
|
val body = FormBody.Builder()
|
||||||
|
body.add("password", password)
|
||||||
|
|
||||||
val client = OkHttpClient()
|
val requestBody = body.build()
|
||||||
|
|
||||||
val body = FormBody.Builder()
|
val request = Request.Builder()
|
||||||
body.add("password", password)
|
.url("https://$server/api/group/password/$groupId")
|
||||||
|
.post(requestBody)
|
||||||
val requestBody = body.build()
|
.addHeader("Authorization", "Bearer $token")
|
||||||
|
.addHeader("accept-language", language)
|
||||||
val request = Request.Builder()
|
.build()
|
||||||
.url("https://$server/api/group/password/$groupId")
|
response = client.newCall(request).execute()
|
||||||
.post(requestBody)
|
callback(response)
|
||||||
.addHeader("Authorization", "Bearer $token")
|
});
|
||||||
.addHeader("accept-language", language)
|
}
|
||||||
.build()
|
|
||||||
response = client.newCall(request).execute()
|
|
||||||
}.join()
|
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGroupId(name: String): String {
|
fun getGroupId(name: String, callback: (String) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
|
@ -277,17 +269,14 @@ class Net {
|
||||||
.addHeader("accept-language", language)
|
.addHeader("accept-language", language)
|
||||||
.build()
|
.build()
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response.body!!.string())
|
||||||
|
}
|
||||||
val responseText = response.body!!.string()
|
|
||||||
|
|
||||||
return responseText
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGroupName(id: Int): String {
|
fun getGroupName(id: Int, callback: (String) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
|
@ -297,17 +286,14 @@ class Net {
|
||||||
.addHeader("accept-language", language)
|
.addHeader("accept-language", language)
|
||||||
.build()
|
.build()
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response.body!!.string())
|
||||||
|
}
|
||||||
val responseText = response.body!!.string()
|
|
||||||
|
|
||||||
return responseText
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getUsersInGroup(groupId: Int): Response {
|
fun getUsersInGroup(groupId: Int, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
|
@ -318,15 +304,14 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMyGroups(): Response {
|
fun getMyGroups(callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
|
@ -337,15 +322,14 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getUsernameById(userId: Int): Response {
|
fun getUsernameById(userId: Int, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
|
@ -356,15 +340,14 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getGroupAdminId(groupId: Int): Response {
|
fun getGroupAdminId(groupId: Int, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
|
@ -375,15 +358,19 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateAbstractProduct(groupId: Int, abstractProduct: AbstractProduct, imageFile: File): Response {
|
fun updateAbstractProduct(
|
||||||
lateinit var response: Response
|
groupId: Int,
|
||||||
|
abstractProduct: AbstractProduct,
|
||||||
|
imageFile: File,
|
||||||
|
callback: (Response) -> Unit,
|
||||||
|
) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val body = MultipartBody.Builder()
|
val body = MultipartBody.Builder()
|
||||||
|
@ -406,15 +393,14 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun uploadCategory(groupId: Int, category: Category): Response {
|
fun uploadCategory(groupId: Int, category: Category, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val body = FormBody.Builder()
|
val body = FormBody.Builder()
|
||||||
|
@ -431,15 +417,14 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateCategory(groupId: Int, category: Category): Response {
|
fun updateCategory(groupId: Int, category: Category, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val body = FormBody.Builder()
|
val body = FormBody.Builder()
|
||||||
|
@ -456,15 +441,14 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun uploadProduct(groupId: Int, product: Product): Response {
|
fun uploadProduct(groupId: Int, product: Product, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val body = FormBody.Builder()
|
val body = FormBody.Builder()
|
||||||
|
@ -484,15 +468,14 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateProduct(groupId: Int, product: Product): Response {
|
fun updateProduct(groupId: Int, product: Product, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val body = FormBody.Builder()
|
val body = FormBody.Builder()
|
||||||
|
@ -512,15 +495,14 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun synchronize(groupId: Int): Response {
|
fun synchronize(groupId: Int, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
|
@ -531,76 +513,41 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getProduct(groupId: Int, localId: Int): Response {
|
fun downloadImage(url: String, file: File, callback: () -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
val client = OkHttpClient.Builder()
|
||||||
thread {
|
.connectTimeout(30, TimeUnit.SECONDS)
|
||||||
val client = OkHttpClient()
|
.readTimeout(10, TimeUnit.MINUTES)
|
||||||
|
|
||||||
val request = Request.Builder()
|
|
||||||
.url("https://$server/api/product/$groupId/$localId")
|
|
||||||
.get()
|
|
||||||
.addHeader("Authorization", "Bearer $token")
|
|
||||||
.addHeader("accept-language", language)
|
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
|
||||||
}.join()
|
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getAbstractProduct(groupId: Int, localId: Int): Response {
|
|
||||||
lateinit var response: Response
|
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
|
||||||
|
|
||||||
val request = Request.Builder()
|
|
||||||
.url("https://$server/api/abstractproduct/$groupId/$localId")
|
|
||||||
.get()
|
|
||||||
.addHeader("Authorization", "Bearer $token")
|
|
||||||
.addHeader("accept-language", language)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
|
||||||
}.join()
|
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
fun downloadImage(url: String, file: File) {
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.addHeader("Authorization", "Bearer $token")
|
.addHeader("Authorization", "Bearer $token")
|
||||||
.addHeader("accept-language", language)
|
.addHeader("accept-language", language)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
client.newCall(request).execute().use { response ->
|
val response = client.newCall(request).execute()
|
||||||
if (!response.isSuccessful) throw IOException("Unexpected code $response")
|
if (!response.isSuccessful) throw IOException("Unexpected code $response")
|
||||||
|
|
||||||
val fos = FileOutputStream(file)
|
val fos = FileOutputStream(file)
|
||||||
|
|
||||||
response.body?.byteStream()?.use { inputStream ->
|
response.body?.byteStream()?.use { inputStream ->
|
||||||
fos.use {
|
fos.use {
|
||||||
inputStream.copyTo(fos)
|
inputStream.copyTo(fos)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.join()
|
callback()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteCategory(groupId: Int, localId: Int): Response {
|
fun deleteCategory(groupId: Int, localId: Int, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
|
@ -611,15 +558,14 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteAbstractProduct(groupId: Int, localId: Int): Response {
|
fun deleteAbstractProduct(groupId: Int, localId: Int, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
|
@ -630,15 +576,14 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
return response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteProduct(groupId: Int, localId: Int): Response {
|
fun deleteProduct(groupId: Int, localId: Int, callback: (Response) -> Unit) {
|
||||||
lateinit var response: Response
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
thread {
|
|
||||||
val client = OkHttpClient()
|
val client = OkHttpClient()
|
||||||
|
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
|
@ -649,8 +594,69 @@ class Net {
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
response = client.newCall(request).execute()
|
response = client.newCall(request).execute()
|
||||||
}.join()
|
callback(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return response
|
fun renameGroup(groupId: Int, newName: String, callback: (Response) -> Unit) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
|
val body = FormBody.Builder()
|
||||||
|
.add("name", newName)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("https://$server/api/group/rename/$groupId")
|
||||||
|
.post(body)
|
||||||
|
.addHeader("Authorization", "Bearer $token")
|
||||||
|
.addHeader("accept-language", language)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
response = client.newCall(request).execute()
|
||||||
|
callback(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun transfer_ownership(groupId: Int, userId: Int, callback: (Response) -> Unit) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
|
val body = FormBody.Builder()
|
||||||
|
.add("userId", userId.toString())
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("https://$server/api/group/transferOwnership/$groupId")
|
||||||
|
.post(body)
|
||||||
|
.addHeader("Authorization", "Bearer $token")
|
||||||
|
.addHeader("accept-language", language)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
response = client.newCall(request).execute()
|
||||||
|
callback(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun leaveGroup(groupId: Int, callback: (Response) -> Unit) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
lateinit var response: Response
|
||||||
|
|
||||||
|
val client = OkHttpClient()
|
||||||
|
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url("https://$server/api/group/leave/$groupId")
|
||||||
|
.get()
|
||||||
|
.addHeader("Authorization", "Bearer $token")
|
||||||
|
.addHeader("accept-language", language)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
response = client.newCall(request).execute()
|
||||||
|
callback(response)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,8 +14,6 @@ class Parser constructor() {
|
||||||
text = text.replace(found, "")
|
text = text.replace(found, "")
|
||||||
netWeight = stripNetWeight(found)
|
netWeight = stripNetWeight(found)
|
||||||
return Triple(text, netWeight, found)
|
return Triple(text, netWeight, found)
|
||||||
} else {
|
|
||||||
return Triple(text, 0.0, "")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Triple("", 0.0, "")
|
return Triple("", 0.0, "")
|
||||||
|
|
|
@ -3,6 +3,8 @@ package org.foxarmy.barcodescannerforemployees
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.ContextWrapper
|
import android.content.ContextWrapper
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.SharedPreferences
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.graphics.Matrix
|
import android.graphics.Matrix
|
||||||
|
@ -17,6 +19,7 @@ import androidx.core.content.FileProvider
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
import androidx.security.crypto.EncryptedSharedPreferences
|
||||||
import androidx.security.crypto.MasterKeys
|
import androidx.security.crypto.MasterKeys
|
||||||
import com.google.firebase.components.BuildConfig
|
import com.google.firebase.components.BuildConfig
|
||||||
|
import org.foxarmy.barcodescannerforemployees.activities.LoginActivity
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
|
@ -114,36 +117,28 @@ fun calculateProductFreshness(dateOfProduction: Long, dateOfExpiry: Long): Doubl
|
||||||
|
|
||||||
fun getUnitNameById(context: Context, id: Int): String {
|
fun getUnitNameById(context: Context, id: Int): String {
|
||||||
return when (id) {
|
return when (id) {
|
||||||
0 -> {
|
0 -> { context.getString(R.string.kilogram) }
|
||||||
context.getString(R.string.kilogram)
|
|
||||||
}
|
|
||||||
|
|
||||||
1 -> {
|
1 -> { context.getString(R.string.gram) }
|
||||||
context.getString(R.string.gram)
|
|
||||||
}
|
|
||||||
|
|
||||||
2 -> {
|
2 -> { context.getString(R.string.liter) }
|
||||||
context.getString(R.string.liter)
|
|
||||||
}
|
|
||||||
|
|
||||||
3 -> {
|
3 -> { context.getString(R.string.milliliter) }
|
||||||
context.getString(R.string.milliliter)
|
|
||||||
}
|
|
||||||
|
|
||||||
4 -> {
|
4 -> { context.getString(R.string.pieces) }
|
||||||
context.getString(R.string.pieces)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
else -> { "" }
|
||||||
""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseArray(input: String): IntArray {
|
fun parseIntArray(input: String): IntArray {
|
||||||
return input.trim('[', ']').split(",").map { it.trim().toInt() }.toIntArray()
|
return input.trim('[', ']').split(",").map { it.trim().toInt() }.toIntArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun parseStringList(input: String): List<String> {
|
||||||
|
return input.trim('[', ']').split(",").map { it.trim() }.toList()
|
||||||
|
}
|
||||||
|
|
||||||
fun calculateMd5Hash(file: File): String {
|
fun calculateMd5Hash(file: File): String {
|
||||||
val digest = MessageDigest.getInstance("MD5")
|
val digest = MessageDigest.getInstance("MD5")
|
||||||
val fis = FileInputStream(file)
|
val fis = FileInputStream(file)
|
||||||
|
@ -193,23 +188,30 @@ fun noInternetConnectionAvailableNotification(context: Context) {
|
||||||
(context as Activity).runOnUiThread {
|
(context as Activity).runOnUiThread {
|
||||||
AlertDialog.Builder(context)
|
AlertDialog.Builder(context)
|
||||||
.setMessage(context.getString(R.string.no_internet_connection))
|
.setMessage(context.getString(R.string.no_internet_connection))
|
||||||
|
.setCancelable(false)
|
||||||
.setPositiveButton(R.string.quit) { _, _ ->
|
.setPositiveButton(R.string.quit) { _, _ ->
|
||||||
exitProcess(0)
|
exitProcess(0)
|
||||||
}
|
}
|
||||||
.setNeutralButton(R.string.logout) { _, _ ->
|
.setNeutralButton(R.string.logout) { _, _ ->
|
||||||
val sharedPreferences = EncryptedSharedPreferences.create(
|
val sharedPreferences = getPreferences(context)
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
context,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
sharedPreferences.edit().putString("token", "").apply()
|
sharedPreferences.edit().putString("token", "").apply()
|
||||||
sharedPreferences.edit().putString("server", "").apply()
|
sharedPreferences.edit().putString("server", "").apply()
|
||||||
sharedPreferences.edit().putStringSet("groups", emptySet()).apply()
|
sharedPreferences.edit().putStringSet("groups", emptySet()).apply()
|
||||||
sharedPreferences.edit().putString("currentGroup", "").apply()
|
sharedPreferences.edit().putString("currentGroup", "").apply()
|
||||||
exitProcess(0)
|
val intent = Intent(context, LoginActivity::class.java)
|
||||||
|
context.startActivity(intent)
|
||||||
|
context.finish()
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getPreferences(context: Context): SharedPreferences {
|
||||||
|
return EncryptedSharedPreferences.create(
|
||||||
|
"sensitive",
|
||||||
|
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
||||||
|
context,
|
||||||
|
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
||||||
|
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
||||||
|
)
|
||||||
|
}
|
|
@ -20,8 +20,13 @@ import java.util.concurrent.TimeUnit
|
||||||
class WebSocketClient(private val context: Context, private val server: String) {
|
class WebSocketClient(private val context: Context, private val server: String) {
|
||||||
|
|
||||||
private lateinit var webSocket: WebSocket
|
private lateinit var webSocket: WebSocket
|
||||||
|
private lateinit var token: String
|
||||||
|
private lateinit var currentGroup: String
|
||||||
|
|
||||||
fun connect(token: String, currentGroup: String) {
|
fun connect(token: String, currentGroup: String) {
|
||||||
|
this.token = token
|
||||||
|
this.currentGroup = currentGroup
|
||||||
|
|
||||||
val client = OkHttpClient.Builder()
|
val client = OkHttpClient.Builder()
|
||||||
.connectTimeout(5, TimeUnit.SECONDS)
|
.connectTimeout(5, TimeUnit.SECONDS)
|
||||||
.readTimeout(1, TimeUnit.MINUTES)
|
.readTimeout(1, TimeUnit.MINUTES)
|
||||||
|
@ -70,19 +75,22 @@ class WebSocketClient(private val context: Context, private val server: String)
|
||||||
val pictureFile =
|
val pictureFile =
|
||||||
File(picturesDir, "${data["image_filename"]}.png")
|
File(picturesDir, "${data["image_filename"]}.png")
|
||||||
val url = "https://${net.server}/api/abstractproduct/getImage/${currentGroup}/${data["local_id"]}"
|
val url = "https://${net.server}/api/abstractproduct/getImage/${currentGroup}/${data["local_id"]}"
|
||||||
net.downloadImage(url, pictureFile)
|
net.downloadImage(url, pictureFile, {
|
||||||
|
abstractProductDAO.addAbstractProduct(newAbstractProduct)
|
||||||
abstractProductDAO.addAbstractProduct(newAbstractProduct)
|
(context as MainActivity).updateAll()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
"product" -> {
|
"product" -> {
|
||||||
val newProduct = Product.createFromJSON(data)
|
val newProduct = Product.createFromJSON(data)
|
||||||
productDAO.insertNewProduct(newProduct)
|
productDAO.insertNewProduct(newProduct)
|
||||||
|
(context as MainActivity).updateAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
"category" -> {
|
"category" -> {
|
||||||
val newCategory = Category.createFromJSON(data)
|
val newCategory = Category.createFromJSON(data)
|
||||||
categoryDAO.addCategory(newCategory)
|
categoryDAO.addCategory(newCategory)
|
||||||
|
(context as MainActivity).updateAll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,17 +110,21 @@ class WebSocketClient(private val context: Context, private val server: String)
|
||||||
val pictureFile =
|
val pictureFile =
|
||||||
File(picturesDir, "${data["image_filename"]}.png")
|
File(picturesDir, "${data["image_filename"]}.png")
|
||||||
val url = "https://${net.server}/api/abstractproduct/getImage/${currentGroup}/${data["local_id"]}"
|
val url = "https://${net.server}/api/abstractproduct/getImage/${currentGroup}/${data["local_id"]}"
|
||||||
net.downloadImage(url, pictureFile)
|
net.downloadImage(url, pictureFile, {
|
||||||
|
abstractProductDAO.updateAbstractProduct(updatedAbstractProduct)
|
||||||
|
(context as MainActivity).updateAll()
|
||||||
|
})
|
||||||
|
|
||||||
abstractProductDAO.updateAbstractProduct(updatedAbstractProduct)
|
|
||||||
}
|
}
|
||||||
"product" -> {
|
"product" -> {
|
||||||
val updatedProduct = Product.createFromJSON(data)
|
val updatedProduct = Product.createFromJSON(data)
|
||||||
productDAO.updateProduct(updatedProduct)
|
productDAO.updateProduct(updatedProduct)
|
||||||
|
(context as MainActivity).updateAll()
|
||||||
}
|
}
|
||||||
"category" -> {
|
"category" -> {
|
||||||
val updatedCategory = Category.createFromJSON(data)
|
val updatedCategory = Category.createFromJSON(data)
|
||||||
categoryDAO.updateCategory(updatedCategory)
|
categoryDAO.updateCategory(updatedCategory)
|
||||||
|
(context as MainActivity).updateAll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,23 +135,25 @@ class WebSocketClient(private val context: Context, private val server: String)
|
||||||
when(item) {
|
when(item) {
|
||||||
"abstractproduct" -> {
|
"abstractproduct" -> {
|
||||||
abstractProductDAO.eraseAbstractProduct(id.toInt(), context)
|
abstractProductDAO.eraseAbstractProduct(id.toInt(), context)
|
||||||
|
(context as MainActivity).updateAll()
|
||||||
}
|
}
|
||||||
"product" -> {
|
"product" -> {
|
||||||
productDAO.eraseProduct(id.toInt())
|
productDAO.eraseProduct(id.toInt())
|
||||||
|
(context as MainActivity).updateAll()
|
||||||
}
|
}
|
||||||
"category" -> {
|
"category" -> {
|
||||||
categoryDAO.eraseCategory(id.toInt(), context)
|
categoryDAO.eraseCategory(id.toInt(), context)
|
||||||
|
(context as MainActivity).updateAll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(context as MainActivity).updateAll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
|
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
|
||||||
Log.d("QWERTYUIOP", "Closing ws. Reason: $reason")
|
Log.d("QWERTYUIOP", "Closing ws. Reason: $reason")
|
||||||
noInternetConnectionAvailableNotification(context)
|
// noInternetConnectionAvailableNotification(context)
|
||||||
|
this@WebSocketClient.connect(token, currentGroup)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
|
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package org.foxarmy.barcodescannerforemployees.activities
|
package org.foxarmy.barcodescannerforemployees.activities
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.Net
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.databinding.ActivityAccountSettingsBinding
|
import org.foxarmy.barcodescannerforemployees.databinding.ActivityAccountSettingsBinding
|
||||||
|
|
||||||
class AccountSettingsActivity : AppCompatActivity() {
|
class AccountSettingsActivity : AppCompatActivity() {
|
||||||
|
@ -19,15 +19,7 @@ class AccountSettingsActivity : AppCompatActivity() {
|
||||||
|
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
|
val sharedPreferences = org.foxarmy.barcodescannerforemployees.getPreferences(this)
|
||||||
|
|
||||||
val sharedPreferences = EncryptedSharedPreferences.create(
|
|
||||||
"sensitive",
|
|
||||||
masterKeyAlias,
|
|
||||||
applicationContext,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
val net = Net()
|
val net = Net()
|
||||||
|
|
||||||
|
@ -36,13 +28,39 @@ class AccountSettingsActivity : AppCompatActivity() {
|
||||||
net.token = sharedPreferences.getString("token", "")!!
|
net.token = sharedPreferences.getString("token", "")!!
|
||||||
|
|
||||||
binding.saveUsernameButton.setOnClickListener {
|
binding.saveUsernameButton.setOnClickListener {
|
||||||
val response = net.changeUsername(binding.newUsernameTextEdit.text.toString())
|
net.changeUsername(binding.newUsernameTextEdit.text.toString(), { response ->
|
||||||
Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show()
|
if (response.code == 200) {
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(this, getString(R.string.username_changed), Toast.LENGTH_LONG).show()
|
||||||
|
val intent = Intent(this, LoginActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.savePasswordButton.setOnClickListener {
|
binding.savePasswordButton.setOnClickListener {
|
||||||
val response = net.changePassword(binding.newPasswordTextEdit.text.toString())
|
net.changePassword(binding.newPasswordTextEdit.text.toString(), { response ->
|
||||||
Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show()
|
if (response.code == 200) {
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(this, getString(R.string.password_changed), Toast.LENGTH_LONG).show()
|
||||||
|
val intent = Intent(this, LoginActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package org.foxarmy.barcodescannerforemployees.activities
|
package org.foxarmy.barcodescannerforemployees.activities
|
||||||
|
|
||||||
|
import android.app.ProgressDialog
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
@ -17,8 +18,6 @@ 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
|
||||||
|
@ -32,7 +31,6 @@ import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.StandardCopyOption
|
import java.nio.file.StandardCopyOption
|
||||||
import kotlin.concurrent.thread
|
|
||||||
|
|
||||||
class AddAbstractProductActivity : AppCompatActivity() {
|
class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
private lateinit var imageView: ImageView
|
private lateinit var imageView: ImageView
|
||||||
|
@ -60,18 +58,19 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
private lateinit var DAO: AbstractProductDAO
|
private lateinit var DAO: AbstractProductDAO
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
|
|
||||||
|
private lateinit var loadingDialog: ProgressDialog
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
setContentView(R.layout.fragment_add_abstract_product)
|
setContentView(R.layout.fragment_add_abstract_product)
|
||||||
|
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
loadingDialog = ProgressDialog(this)
|
||||||
"sensitive",
|
loadingDialog.setMessage(getString(R.string.loading_please_wait))
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
loadingDialog.setCancelable(false)
|
||||||
applicationContext,
|
loadingDialog.setTitle(getString(R.string.loading))
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
sharedPreferences = getPreferences(this)
|
||||||
)
|
|
||||||
|
|
||||||
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "offline")!!)
|
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "offline")!!)
|
||||||
DAO = AbstractProductDAO(dbHelper)
|
DAO = AbstractProductDAO(dbHelper)
|
||||||
|
@ -128,6 +127,9 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
netWeightText.text = abstractProduct!!.netWeight.toString()
|
netWeightText.text = abstractProduct!!.netWeight.toString()
|
||||||
categorySpinner.setSelection(abstractProduct!!.category - 1)
|
categorySpinner.setSelection(abstractProduct!!.category - 1)
|
||||||
unitTypeSpinner.setSelection(abstractProduct!!.unit)
|
unitTypeSpinner.setSelection(abstractProduct!!.unit)
|
||||||
|
if (abstractProduct!!.barcode == "" || abstractProduct!!.barcode == " ") {
|
||||||
|
noBarcodeCheckBox.isChecked = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
saveButton.setOnClickListener {
|
saveButton.setOnClickListener {
|
||||||
|
@ -152,18 +154,26 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadingDialog.show()
|
||||||
|
|
||||||
|
val currentGroup: Int
|
||||||
|
val currentGroupString = sharedPreferences.getString("currentGroup", "offline")!!
|
||||||
|
|
||||||
val net = Net()
|
val net = Net()
|
||||||
|
|
||||||
net.token = sharedPreferences.getString("token", "")!!
|
if (currentGroupString != "offline") {
|
||||||
net.server = sharedPreferences.getString("server", "")!!
|
currentGroup = currentGroupString.toInt()
|
||||||
net.language = sharedPreferences.getString("language", "en-US")!!
|
|
||||||
|
|
||||||
val currentGroup: Int = if (sharedPreferences.getString("currentGroup", "offline")!! == "offline") 0 else sharedPreferences.getString("currentGroup", "")!!.toInt()
|
net.token = sharedPreferences.getString("token", "")!!
|
||||||
|
net.server = sharedPreferences.getString("server", "")!!
|
||||||
|
net.language = sharedPreferences.getString("language", "en-US")!!
|
||||||
|
|
||||||
lateinit var response: Response
|
} else {
|
||||||
|
currentGroup = 0
|
||||||
|
}
|
||||||
|
|
||||||
abstractProduct = AbstractProduct(
|
abstractProduct = AbstractProduct(
|
||||||
if(abstractProduct == null) 0 else abstractProduct!!.id,
|
if (abstractProduct == null) 0 else abstractProduct!!.id,
|
||||||
if (noBarcodeCheckBox.isChecked) "" else barcode,
|
if (noBarcodeCheckBox.isChecked) "" else barcode,
|
||||||
productName,
|
productName,
|
||||||
netWeight.toString().toDouble(),
|
netWeight.toString().toDouble(),
|
||||||
|
@ -171,18 +181,17 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
categorySpinner.selectedItemPosition + 1,
|
categorySpinner.selectedItemPosition + 1,
|
||||||
unitTypeSpinner.selectedItemPosition
|
unitTypeSpinner.selectedItemPosition
|
||||||
)
|
)
|
||||||
|
|
||||||
val pictureFile = File(File(filesDir, "pictures"), "${abstractProduct!!.imageHash}.png")
|
val pictureFile = File(File(filesDir, "pictures"), "${abstractProduct!!.imageHash}.png")
|
||||||
|
|
||||||
if (action == "update") {
|
if (action == "update") {
|
||||||
DAO.updateAbstractProduct(abstractProduct!!)
|
DAO.updateAbstractProduct(abstractProduct!!)
|
||||||
response = net.updateAbstractProduct(currentGroup, abstractProduct!!, pictureFile)
|
if (currentGroup > 0) net.updateAbstractProduct(currentGroup, abstractProduct!!, pictureFile, this::notifyUserAndExit)
|
||||||
} else if (action == "new" || action == "new_from_barcode") {
|
} else if (action == "new" || action == "new_from_barcode") {
|
||||||
abstractProduct!!.id = DAO.addAbstractProduct(abstractProduct!!).toInt()
|
abstractProduct!!.id = DAO.addAbstractProduct(abstractProduct!!).toInt()
|
||||||
response = net.uploadAbstractProduct(currentGroup, abstractProduct!!, pictureFile);
|
if (currentGroup > 0)
|
||||||
|
net.uploadAbstractProduct(currentGroup, abstractProduct!!, pictureFile, this::notifyUserAndExit)
|
||||||
}
|
}
|
||||||
Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show()
|
|
||||||
|
|
||||||
finish()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
takePictureButton.setOnClickListener {
|
takePictureButton.setOnClickListener {
|
||||||
|
@ -195,10 +204,16 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun notifyUserAndExit(response: Response) {
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show()
|
||||||
|
loadingDialog.dismiss()
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun performRequest(barcode: String) {
|
fun performRequest(barcode: String) {
|
||||||
barcodeText.setText(this.barcode)
|
barcodeText.setText(this.barcode)
|
||||||
val net = Net();
|
|
||||||
val result = net.requestProductFromOnlineDB(barcode)
|
|
||||||
|
|
||||||
var abstractProduct: AbstractProduct
|
var abstractProduct: AbstractProduct
|
||||||
|
|
||||||
|
@ -220,24 +235,25 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
thread {
|
val net = Net();
|
||||||
if (result == "Not found 404") {
|
net.requestProductFromOnlineDB(barcode, {response ->
|
||||||
|
if (response.code == 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()
|
||||||
productNameText.setText("")
|
productNameText.setText("")
|
||||||
netWeightText.setText("")
|
netWeightText.setText("")
|
||||||
}
|
}
|
||||||
return@thread
|
return@requestProductFromOnlineDB
|
||||||
}
|
}
|
||||||
|
|
||||||
abstractProduct = Parser().parse(result)
|
abstractProduct = Parser().parse(response.body!!.string())
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
productNameText.text = abstractProduct.name
|
productNameText.text = abstractProduct.name
|
||||||
netWeightText.text = abstractProduct.netWeight.toString()
|
netWeightText.text = abstractProduct.netWeight.toString()
|
||||||
unitTypeSpinner.setSelection(abstractProduct.unit)
|
unitTypeSpinner.setSelection(abstractProduct.unit)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fillupUnitsSpinner() {
|
private fun fillupUnitsSpinner() {
|
||||||
|
@ -257,7 +273,8 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
|
|
||||||
fun fillupCategorySpinner() {
|
fun fillupCategorySpinner() {
|
||||||
|
|
||||||
val categoriesDAO = CategoryDAO(DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!))
|
val categoriesDAO =
|
||||||
|
CategoryDAO(DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!))
|
||||||
|
|
||||||
val categories = categoriesDAO.getAllCategories().map { category -> category.name }
|
val categories = categoriesDAO.getAllCategories().map { category -> category.name }
|
||||||
|
|
||||||
|
@ -280,7 +297,7 @@ class AddAbstractProductActivity : AppCompatActivity() {
|
||||||
val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
|
val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
|
||||||
val matrix = Matrix()
|
val matrix = Matrix()
|
||||||
|
|
||||||
when(orientation){
|
when (orientation) {
|
||||||
ExifInterface.ORIENTATION_ROTATE_90 -> matrix.postRotate(90F)
|
ExifInterface.ORIENTATION_ROTATE_90 -> matrix.postRotate(90F)
|
||||||
ExifInterface.ORIENTATION_ROTATE_180 -> matrix.postRotate(180F)
|
ExifInterface.ORIENTATION_ROTATE_180 -> matrix.postRotate(180F)
|
||||||
ExifInterface.ORIENTATION_ROTATE_270 -> matrix.postRotate(270F)
|
ExifInterface.ORIENTATION_ROTATE_270 -> matrix.postRotate(270F)
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package org.foxarmy.barcodescannerforemployees.activities
|
package org.foxarmy.barcodescannerforemployees.activities
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.app.ProgressDialog
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Button
|
import android.widget.Button
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
import okhttp3.Response
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.Net
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
import org.foxarmy.barcodescannerforemployees.R
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.database.CategoryDAO
|
import org.foxarmy.barcodescannerforemployees.database.CategoryDAO
|
||||||
|
@ -18,19 +18,19 @@ class AddCategoryActivity : Activity() {
|
||||||
|
|
||||||
private lateinit var DAO: CategoryDAO
|
private lateinit var DAO: CategoryDAO
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
|
private lateinit var loadingDialog: ProgressDialog
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
setContentView(R.layout.activity_add_category)
|
setContentView(R.layout.activity_add_category)
|
||||||
|
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
loadingDialog = ProgressDialog(this)
|
||||||
"sensitive",
|
loadingDialog.setMessage(getString(R.string.loading_please_wait))
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
loadingDialog.setCancelable(false)
|
||||||
applicationContext,
|
loadingDialog.setTitle(getString(R.string.loading))
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
sharedPreferences = org.foxarmy.barcodescannerforemployees.getPreferences(this)
|
||||||
)
|
|
||||||
|
|
||||||
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "offline")!!)
|
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "offline")!!)
|
||||||
DAO = CategoryDAO(dbHelper)
|
DAO = CategoryDAO(dbHelper)
|
||||||
|
@ -48,25 +48,35 @@ class AddCategoryActivity : Activity() {
|
||||||
net.server = sharedPreferences.getString("server", "")!!
|
net.server = sharedPreferences.getString("server", "")!!
|
||||||
net.language = sharedPreferences.getString("language", "")!!
|
net.language = sharedPreferences.getString("language", "")!!
|
||||||
|
|
||||||
val currentGroup: Int = if (sharedPreferences.getString("currentGroup", "offline")!! == "offline") 0 else sharedPreferences.getString("currentGroup", "")!!.toInt()
|
val currentGroup: Int = if (sharedPreferences.getString(
|
||||||
|
"currentGroup",
|
||||||
|
"offline"
|
||||||
|
)!! == "offline"
|
||||||
|
) 0 else sharedPreferences.getString("currentGroup", "")!!.toInt()
|
||||||
|
|
||||||
findViewById<Button>(R.id.saveButton).setOnClickListener {
|
findViewById<Button>(R.id.saveButton).setOnClickListener {
|
||||||
if (categoryNameTextEdit.text.toString() == "") {
|
if (categoryNameTextEdit.text.toString() == "") {
|
||||||
Toast.makeText(this, getString(R.string.category_name_required), Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, getString(R.string.category_name_required), Toast.LENGTH_SHORT).show()
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
|
loadingDialog.show()
|
||||||
|
|
||||||
if (category.id == 0) { // Inserting new category
|
if (category.id == 0) { // Inserting new category
|
||||||
val newCategory = Category(0, categoryNameTextEdit.text.toString())
|
val newCategory = Category(0, categoryNameTextEdit.text.toString())
|
||||||
newCategory.id = DAO.addCategory(newCategory).toInt()
|
newCategory.id = DAO.addCategory(newCategory).toInt()
|
||||||
if (currentGroup > 0) net.uploadCategory(currentGroup, newCategory)
|
if (currentGroup > 0) net.uploadCategory(currentGroup, newCategory, this::notifyUserAndExit)
|
||||||
} else { // Updating existing category
|
} else { // Updating existing category
|
||||||
category.name = categoryNameTextEdit.text.toString()
|
category.name = categoryNameTextEdit.text.toString()
|
||||||
DAO.updateCategory(category)
|
DAO.updateCategory(category)
|
||||||
if (currentGroup > 0) net.updateCategory(currentGroup, category)
|
if (currentGroup > 0) net.updateCategory(currentGroup, category, this::notifyUserAndExit)
|
||||||
}
|
}
|
||||||
|
|
||||||
finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun notifyUserAndExit(response: Response) {
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(this, response.body!!.string(), Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
loadingDialog.dismiss()
|
||||||
|
finish()
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package org.foxarmy.barcodescannerforemployees.activities
|
package org.foxarmy.barcodescannerforemployees.activities
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.app.ProgressDialog
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
@ -13,8 +14,6 @@ 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
|
||||||
|
@ -56,18 +55,19 @@ class AddProductActivity : AppCompatActivity() {
|
||||||
private lateinit var abstractProductDAO: AbstractProductDAO
|
private lateinit var abstractProductDAO: AbstractProductDAO
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
|
|
||||||
|
private lateinit var loadingDialog: ProgressDialog
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
setContentView(R.layout.fragment_add_product)
|
setContentView(R.layout.fragment_add_product)
|
||||||
|
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
loadingDialog = ProgressDialog(this)
|
||||||
"sensitive",
|
loadingDialog.setMessage(getString(R.string.loading_please_wait))
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
loadingDialog.setCancelable(false)
|
||||||
applicationContext,
|
loadingDialog.setTitle(getString(R.string.loading))
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
sharedPreferences = org.foxarmy.barcodescannerforemployees.getPreferences(this)
|
||||||
)
|
|
||||||
|
|
||||||
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "offline")!!)
|
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "offline")!!)
|
||||||
productDAO = ProductDAO(dbHelper)
|
productDAO = ProductDAO(dbHelper)
|
||||||
|
@ -177,23 +177,17 @@ class AddProductActivity : AppCompatActivity() {
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentGroup: Int = if (sharedPreferences.getString("currentGroup", "offline")!! == "offline") 0 else sharedPreferences.getString("currentGroup", "")!!.toInt()
|
loadingDialog.show()
|
||||||
|
|
||||||
var response: Response? = null
|
val currentGroup: Int = if (sharedPreferences.getString("currentGroup", "offline")!! == "offline") 0 else sharedPreferences.getString("currentGroup", "")!!.toInt()
|
||||||
|
|
||||||
if (updatingExistentProduct) {
|
if (updatingExistentProduct) {
|
||||||
productDAO.updateProduct(product!!)
|
productDAO.updateProduct(product!!)
|
||||||
if (currentGroup > 0) response = net.updateProduct(currentGroup, product!!)
|
if (currentGroup > 0) net.updateProduct(currentGroup, product!!, this::notifyUserAndExit)
|
||||||
} else {
|
} else {
|
||||||
product!!.id = productDAO.insertNewProduct(product!!).toInt()
|
product!!.id = productDAO.insertNewProduct(product!!).toInt()
|
||||||
if (currentGroup > 0) response = net.uploadProduct(currentGroup, product!!)
|
if (currentGroup > 0) net.uploadProduct(currentGroup, product!!, this::notifyUserAndExit)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response != null) {
|
|
||||||
Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
finish()
|
|
||||||
}
|
}
|
||||||
update()
|
update()
|
||||||
|
|
||||||
|
@ -207,6 +201,14 @@ class AddProductActivity : AppCompatActivity() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun notifyUserAndExit(response: Response) {
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show()
|
||||||
|
loadingDialog.dismiss()
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val intentLauncher =
|
private val intentLauncher =
|
||||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
|
||||||
if (result.resultCode == Activity.RESULT_OK) {
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
|
|
|
@ -7,8 +7,6 @@ import android.os.Bundle
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.R
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
||||||
import org.foxarmy.barcodescannerforemployees.database.ProductDAO
|
import org.foxarmy.barcodescannerforemployees.database.ProductDAO
|
||||||
|
@ -26,13 +24,7 @@ class ExpiryCalendarActivity : AppCompatActivity() {
|
||||||
|
|
||||||
setContentView(R.layout.fragment_expiry_dates)
|
setContentView(R.layout.fragment_expiry_dates)
|
||||||
|
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
sharedPreferences = org.foxarmy.barcodescannerforemployees.getPreferences(this)
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
applicationContext,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!)
|
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "database")!!)
|
||||||
productDAO = ProductDAO(dbHelper)
|
productDAO = ProductDAO(dbHelper)
|
||||||
|
|
|
@ -18,7 +18,7 @@ class FindBarcodelessAbstractProduct() : AppCompatActivity() {
|
||||||
binding = ActivityFindBarcodelessAbstractProductBinding.inflate(layoutInflater)
|
binding = ActivityFindBarcodelessAbstractProductBinding.inflate(layoutInflater)
|
||||||
|
|
||||||
val ft = supportFragmentManager.beginTransaction()
|
val ft = supportFragmentManager.beginTransaction()
|
||||||
val fragment = StorageFragment.newInstance("barcodeless", arrayOf("", " "))
|
val fragment = StorageFragment.newInstance("barcodeless", arrayOf("", " ", " "))
|
||||||
ft.replace(R.id.content, fragment)
|
ft.replace(R.id.content, fragment)
|
||||||
ft.commit()
|
ft.commit()
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,7 @@ import java.io.File
|
||||||
|
|
||||||
class FullscreenActivity : Activity() {
|
class FullscreenActivity : Activity() {
|
||||||
|
|
||||||
private lateinit var binding: ActivityFullscreenBinding
|
|
||||||
private lateinit var fullscreenImageView: ImageView
|
private lateinit var fullscreenImageView: ImageView
|
||||||
private lateinit var fullscreenContentControls: LinearLayout
|
|
||||||
private val hideHandler = Handler(Looper.myLooper()!!)
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package org.foxarmy.barcodescannerforemployees.activities
|
package org.foxarmy.barcodescannerforemployees.activities
|
||||||
|
|
||||||
|
import android.app.ProgressDialog
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.Net
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.databinding.ActivityGroupBinding
|
import org.foxarmy.barcodescannerforemployees.databinding.ActivityGroupBinding
|
||||||
import org.foxarmy.barcodescannerforemployees.noInternetConnectionAvailableNotification
|
import org.foxarmy.barcodescannerforemployees.noInternetConnectionAvailableNotification
|
||||||
|
|
||||||
|
@ -20,13 +20,12 @@ class GroupActivity : AppCompatActivity() {
|
||||||
binding = ActivityGroupBinding.inflate(layoutInflater)
|
binding = ActivityGroupBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
val sharedPreferences = EncryptedSharedPreferences.create(
|
val loadingDialog = ProgressDialog(this)
|
||||||
"sensitive",
|
loadingDialog.setMessage(getString(R.string.loading_please_wait))
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
loadingDialog.setCancelable(false)
|
||||||
applicationContext,
|
loadingDialog.setTitle(getString(R.string.loading))
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
val sharedPreferences = org.foxarmy.barcodescannerforemployees.getPreferences(this)
|
||||||
)
|
|
||||||
|
|
||||||
binding.createGroupButton.setOnClickListener {
|
binding.createGroupButton.setOnClickListener {
|
||||||
val groupName = binding.groupNameTextEdit.text.toString()
|
val groupName = binding.groupNameTextEdit.text.toString()
|
||||||
|
@ -36,24 +35,36 @@ class GroupActivity : AppCompatActivity() {
|
||||||
net.server = sharedPreferences.getString("server", "")!!
|
net.server = sharedPreferences.getString("server", "")!!
|
||||||
net.token = sharedPreferences.getString("token", "")!!
|
net.token = sharedPreferences.getString("token", "")!!
|
||||||
|
|
||||||
if (!net.serverIsAvailable(this)) {
|
net.serverIsAvailable(this, { isServerAvailable ->
|
||||||
noInternetConnectionAvailableNotification(this)
|
if (!isServerAvailable) {
|
||||||
} else {
|
noInternetConnectionAvailableNotification(this)
|
||||||
val response = net.createGroup(groupName, groupPassword)
|
|
||||||
val responseText = response.body!!.string()
|
|
||||||
|
|
||||||
if (response.code == 200) {
|
|
||||||
val currentGroups = sharedPreferences.getStringSet("groups", mutableSetOf())
|
|
||||||
currentGroups!!.add(responseText)
|
|
||||||
sharedPreferences.edit().putStringSet("groups", currentGroups).apply()
|
|
||||||
sharedPreferences.edit().putString("currentGroup", responseText).apply()
|
|
||||||
val intent = Intent(this, MainActivity::class.java)
|
|
||||||
startActivity(intent)
|
|
||||||
finish()
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, responseText, Toast.LENGTH_LONG).show()
|
runOnUiThread {
|
||||||
|
loadingDialog.show()
|
||||||
|
}
|
||||||
|
net.createGroup(groupName, groupPassword, { response ->
|
||||||
|
val responseText = response.body!!.string()
|
||||||
|
|
||||||
|
if (response.code == 200) {
|
||||||
|
val currentGroups = sharedPreferences.getStringSet("groups", mutableSetOf())
|
||||||
|
currentGroups!!.add(responseText)
|
||||||
|
sharedPreferences.edit().putStringSet("groups", currentGroups).apply()
|
||||||
|
sharedPreferences.edit().putString("currentGroup", responseText).apply()
|
||||||
|
runOnUiThread {
|
||||||
|
val intent = Intent(this, MainActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
loadingDialog.dismiss()
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
runOnUiThread {
|
||||||
|
loadingDialog.dismiss()
|
||||||
|
Toast.makeText(this, responseText, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.joinGroupButton.setOnClickListener {
|
binding.joinGroupButton.setOnClickListener {
|
||||||
|
@ -65,30 +76,46 @@ class GroupActivity : AppCompatActivity() {
|
||||||
net.server = sharedPreferences.getString("server", "")!!
|
net.server = sharedPreferences.getString("server", "")!!
|
||||||
net.token = sharedPreferences.getString("token", "")!!
|
net.token = sharedPreferences.getString("token", "")!!
|
||||||
|
|
||||||
if (!net.serverIsAvailable(this)) {
|
net.serverIsAvailable(this) { isServerAvailable ->
|
||||||
noInternetConnectionAvailableNotification(this)
|
if (!isServerAvailable) {
|
||||||
} else {
|
noInternetConnectionAvailableNotification(this)
|
||||||
val requestGroupIdResponse = net.getGroupId(groupName)
|
|
||||||
var groupId: Int
|
|
||||||
try {
|
|
||||||
groupId = requestGroupIdResponse.toInt()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Toast.makeText(this, requestGroupIdResponse, Toast.LENGTH_SHORT).show()
|
|
||||||
return@setOnClickListener
|
|
||||||
}
|
|
||||||
val response = net.joinGroup(groupId, groupPassword)
|
|
||||||
val responseText = response.body!!.string()
|
|
||||||
|
|
||||||
if (response.code == 200) {
|
|
||||||
val currentGroups = sharedPreferences.getStringSet("groups", mutableSetOf())
|
|
||||||
currentGroups!!.add(groupId.toString())
|
|
||||||
sharedPreferences.edit().putStringSet("groups", currentGroups).apply()
|
|
||||||
sharedPreferences.edit().putString("currentGroup", groupId.toString()).apply()
|
|
||||||
val intent = Intent(this, MainActivity::class.java)
|
|
||||||
startActivity(intent)
|
|
||||||
finish()
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, responseText, Toast.LENGTH_LONG).show()
|
runOnUiThread {
|
||||||
|
loadingDialog.show()
|
||||||
|
}
|
||||||
|
net.getGroupId(groupName, { requestGroupIdResponse ->
|
||||||
|
var groupId: Int
|
||||||
|
try {
|
||||||
|
groupId = requestGroupIdResponse.toInt()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
runOnUiThread {
|
||||||
|
loadingDialog.dismiss()
|
||||||
|
Toast.makeText(this, requestGroupIdResponse, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
return@getGroupId
|
||||||
|
}
|
||||||
|
net.joinGroup(groupId, groupPassword, { response ->
|
||||||
|
val responseText = response.body!!.string()
|
||||||
|
|
||||||
|
if (response.code == 200) {
|
||||||
|
val currentGroups = sharedPreferences.getStringSet("groups", mutableSetOf())
|
||||||
|
currentGroups!!.add(groupId.toString())
|
||||||
|
sharedPreferences.edit().putStringSet("groups", currentGroups).apply()
|
||||||
|
sharedPreferences.edit().putString("currentGroup", groupId.toString()).apply()
|
||||||
|
runOnUiThread {
|
||||||
|
val intent = Intent(this, MainActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
loadingDialog.dismiss()
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
runOnUiThread {
|
||||||
|
loadingDialog.dismiss()
|
||||||
|
Toast.makeText(this, responseText, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
package org.foxarmy.barcodescannerforemployees.activities
|
package org.foxarmy.barcodescannerforemployees.activities
|
||||||
|
|
||||||
|
import android.app.ProgressDialog
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.Net
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
import org.foxarmy.barcodescannerforemployees.R
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.databinding.ActivityLoginBinding
|
import org.foxarmy.barcodescannerforemployees.databinding.ActivityLoginBinding
|
||||||
import org.foxarmy.barcodescannerforemployees.noInternetConnectionAvailableNotification
|
import org.foxarmy.barcodescannerforemployees.noInternetConnectionAvailableNotification
|
||||||
import org.foxarmy.barcodescannerforemployees.parseArray
|
import org.foxarmy.barcodescannerforemployees.parseIntArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
|
||||||
class LoginActivity : AppCompatActivity() {
|
class LoginActivity : AppCompatActivity() {
|
||||||
|
@ -24,15 +23,14 @@ class LoginActivity : AppCompatActivity() {
|
||||||
binding = ActivityLoginBinding.inflate(layoutInflater);
|
binding = ActivityLoginBinding.inflate(layoutInflater);
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
val loadingDialog = ProgressDialog(this)
|
||||||
|
loadingDialog.setMessage(getString(R.string.loading_please_wait))
|
||||||
|
loadingDialog.setCancelable(false)
|
||||||
|
loadingDialog.setTitle(getString(R.string.loading))
|
||||||
|
|
||||||
fillUpLanguagesSpinner()
|
fillUpLanguagesSpinner()
|
||||||
|
|
||||||
val sharedPreferences = EncryptedSharedPreferences.create(
|
val sharedPreferences = org.foxarmy.barcodescannerforemployees.getPreferences(this)
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
applicationContext,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
binding.loginButton.setOnClickListener {
|
binding.loginButton.setOnClickListener {
|
||||||
val server = binding.serverTextEdit.text.toString()
|
val server = binding.serverTextEdit.text.toString()
|
||||||
|
@ -45,32 +43,45 @@ class LoginActivity : AppCompatActivity() {
|
||||||
net.language = sharedPreferences.getString("language", "en-US")!!
|
net.language = sharedPreferences.getString("language", "en-US")!!
|
||||||
net.server = server
|
net.server = server
|
||||||
|
|
||||||
if (!net.serverIsAvailable(this)) {
|
net.serverIsAvailable(this, { isServerAvailable ->
|
||||||
noInternetConnectionAvailableNotification(this)
|
if (!isServerAvailable) {
|
||||||
} else {
|
noInternetConnectionAvailableNotification(this)
|
||||||
val response = net.login(username, password)
|
|
||||||
val responseText = response.body!!.string()
|
|
||||||
if (response.code != 200) {
|
|
||||||
Toast.makeText(this, responseText, Toast.LENGTH_SHORT).show()
|
|
||||||
} else {
|
} else {
|
||||||
val json = JSONObject(responseText)
|
runOnUiThread {
|
||||||
sharedPreferences.edit().putString("token", json["token"].toString()).apply()
|
loadingDialog.show()
|
||||||
net.token = json["token"].toString()
|
}
|
||||||
sharedPreferences.edit().putInt("userId", json["id"].toString().toInt()).apply()
|
net.login(username, password, { response ->
|
||||||
sharedPreferences.edit().putString("server", server).apply()
|
val responseText = response.body!!.string()
|
||||||
|
if (response.code != 200) {
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(this, responseText, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val json = JSONObject(responseText)
|
||||||
|
sharedPreferences.edit().putString("token", json["token"].toString()).apply()
|
||||||
|
net.token = json["token"].toString()
|
||||||
|
sharedPreferences.edit().putInt("userId", json["id"].toString().toInt()).apply()
|
||||||
|
sharedPreferences.edit().putString("server", server).apply()
|
||||||
|
|
||||||
|
net.getMyGroups({ response ->
|
||||||
|
runOnUiThread {
|
||||||
|
loadingDialog.dismiss()
|
||||||
|
}
|
||||||
|
val r = response.body!!.string()
|
||||||
|
if (r == "" || r == "[]") {
|
||||||
|
goToActivity("GroupActivity")
|
||||||
|
}
|
||||||
|
val myGroups = parseIntArray(r).map { a -> a.toString() }
|
||||||
|
|
||||||
val r = net.getMyGroups().body!!.string()
|
sharedPreferences.edit().putStringSet("groups", myGroups.toSet()).apply()
|
||||||
val myGroups = parseArray(r).map { a -> a.toString()}
|
sharedPreferences.edit().putString("currentGroup", myGroups[0]).apply()
|
||||||
|
|
||||||
sharedPreferences.edit().putStringSet("groups", myGroups.toSet()).apply()
|
goToActivity("MainActivity")
|
||||||
sharedPreferences.edit().putString("currentGroup", myGroups[0]).apply()
|
})
|
||||||
|
}
|
||||||
val intent = Intent(this, MainActivity::class.java)
|
})
|
||||||
startActivity(intent)
|
|
||||||
finish()
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.registerButton.setOnClickListener {
|
binding.registerButton.setOnClickListener {
|
||||||
|
@ -85,24 +96,30 @@ class LoginActivity : AppCompatActivity() {
|
||||||
net.language = language
|
net.language = language
|
||||||
net.server = server
|
net.server = server
|
||||||
|
|
||||||
if (!net.serverIsAvailable(this)) {
|
net.serverIsAvailable(this, {isServerAvailable ->
|
||||||
noInternetConnectionAvailableNotification(this)
|
if (!isServerAvailable) {
|
||||||
} else {
|
noInternetConnectionAvailableNotification(this)
|
||||||
val response = net.registerAccount(username, password);
|
|
||||||
val responseText = response.body!!.string()
|
|
||||||
if (response.code != 200) {
|
|
||||||
Toast.makeText(this, responseText, Toast.LENGTH_SHORT).show();
|
|
||||||
} else {
|
} else {
|
||||||
sharedPreferences.edit().putInt("userId", responseText.toInt()).apply()
|
net.registerAccount(username, password, {response ->
|
||||||
val token = JSONObject(net.login(username, password).body!!.string())["token"].toString()
|
val responseText = response.body!!.string()
|
||||||
sharedPreferences.edit().putString("token", token).apply()
|
if (response.code != 200) {
|
||||||
|
Toast.makeText(this, responseText, Toast.LENGTH_SHORT).show();
|
||||||
|
} else {
|
||||||
|
sharedPreferences.edit().putInt("userId", responseText.toInt()).apply()
|
||||||
|
net.login(username, password, {response ->
|
||||||
|
val token = JSONObject(response.body!!.string())["token"].toString()
|
||||||
|
sharedPreferences.edit().putString("token", token).apply()
|
||||||
|
|
||||||
sharedPreferences.edit().putString("server", server).apply()
|
sharedPreferences.edit().putString("server", server).apply()
|
||||||
val intent = Intent(this, GroupActivity::class.java)
|
runOnUiThread {
|
||||||
startActivity(intent)
|
loadingDialog.dismiss()
|
||||||
finish()
|
}
|
||||||
|
goToActivity("GroupActivity")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.offlineButton.setOnClickListener {
|
binding.offlineButton.setOnClickListener {
|
||||||
|
@ -117,9 +134,22 @@ class LoginActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private fun fillUpLanguagesSpinner() {
|
private fun fillUpLanguagesSpinner() {
|
||||||
val languages = resources.getStringArray(R.array.languages)
|
val languages = resources.getStringArray(R.array.languages)
|
||||||
val arrayAdapter = ArrayAdapter(this, androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, languages)
|
val arrayAdapter =
|
||||||
|
ArrayAdapter(this, androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, languages)
|
||||||
arrayAdapter.setDropDownViewResource(androidx.appcompat.R.layout.support_simple_spinner_dropdown_item)
|
arrayAdapter.setDropDownViewResource(androidx.appcompat.R.layout.support_simple_spinner_dropdown_item)
|
||||||
binding.languageSpinner.adapter = arrayAdapter
|
binding.languageSpinner.adapter = arrayAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun goToActivity(activityName: String) {
|
||||||
|
runOnUiThread {
|
||||||
|
val intent = Intent(this, when(activityName) {
|
||||||
|
"MainActivity" -> MainActivity::class.java
|
||||||
|
"GroupActivity" -> GroupActivity::class.java
|
||||||
|
"LoginActivity" -> LoginActivity::class.java
|
||||||
|
else -> LoginActivity::class.java
|
||||||
|
})
|
||||||
|
startActivity(intent)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
package org.foxarmy.barcodescannerforemployees.activities
|
package org.foxarmy.barcodescannerforemployees.activities
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.app.ProgressDialog
|
||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.SharedPreferences
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
@ -14,8 +16,6 @@ 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.drawerlayout.widget.DrawerLayout
|
import androidx.drawerlayout.widget.DrawerLayout
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import androidx.viewpager.widget.ViewPager
|
import androidx.viewpager.widget.ViewPager
|
||||||
import com.google.android.material.navigation.NavigationView
|
import com.google.android.material.navigation.NavigationView
|
||||||
import org.foxarmy.barcodescannerforemployees.*
|
import org.foxarmy.barcodescannerforemployees.*
|
||||||
|
@ -43,16 +43,36 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
private var actionBarDrawerToggle: ActionBarDrawerToggle? = null
|
private var actionBarDrawerToggle: ActionBarDrawerToggle? = null
|
||||||
private lateinit var ws: WebSocketClient
|
private lateinit var ws: WebSocketClient
|
||||||
|
|
||||||
|
var selectionMode = false
|
||||||
|
private var selectedAmount = 0
|
||||||
|
|
||||||
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
|
|
||||||
|
private lateinit var loadingDialog: ProgressDialog
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
loadingDialog = ProgressDialog(this)
|
||||||
|
loadingDialog.setMessage(getString(R.string.loading_please_wait))
|
||||||
|
loadingDialog.setCancelable(false)
|
||||||
|
loadingDialog.setTitle(getString(R.string.loading))
|
||||||
|
|
||||||
|
sharedPreferences = getPreferences(this)
|
||||||
|
|
||||||
setSupportActionBar(binding.toolbar)
|
setSupportActionBar(binding.toolbar)
|
||||||
setupViewPager(binding.tabViewpager)
|
setupViewPager(binding.tabViewpager)
|
||||||
binding.tabTablayout.setupWithViewPager(binding.tabViewpager)
|
binding.tabTablayout.setupWithViewPager(binding.tabViewpager)
|
||||||
|
|
||||||
|
binding.tabTablayout.setOnDragListener { _, _ ->
|
||||||
|
selectionMode = false
|
||||||
|
selectedAmount = 0
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
drawerLayout = binding.drawerLayout
|
drawerLayout = binding.drawerLayout
|
||||||
actionBarDrawerToggle = ActionBarDrawerToggle(this, drawerLayout, R.string.nav_open, R.string.nav_close)
|
actionBarDrawerToggle = ActionBarDrawerToggle(this, drawerLayout, R.string.nav_open, R.string.nav_close)
|
||||||
|
|
||||||
|
@ -62,14 +82,6 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
|
|
||||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||||
|
|
||||||
val sharedPreferences = EncryptedSharedPreferences.create(
|
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
applicationContext,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
binding.expiryCalendarFab.setOnClickListener { _ ->
|
binding.expiryCalendarFab.setOnClickListener { _ ->
|
||||||
val expiryCalendarIntent = Intent(this, ExpiryCalendarActivity::class.java)
|
val expiryCalendarIntent = Intent(this, ExpiryCalendarActivity::class.java)
|
||||||
val extras = Bundle()
|
val extras = Bundle()
|
||||||
|
@ -77,7 +89,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
ContextCompat.startActivity(this, expiryCalendarIntent, extras)
|
ContextCompat.startActivity(this, expiryCalendarIntent, extras)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.newElementFab.setOnClickListener { view ->
|
binding.newElementFab.setOnClickListener { _ ->
|
||||||
val currentPosition = binding.tabTablayout.selectedTabPosition
|
val currentPosition = binding.tabTablayout.selectedTabPosition
|
||||||
val fragment = adapter.getItem(currentPosition)
|
val fragment = adapter.getItem(currentPosition)
|
||||||
|
|
||||||
|
@ -112,26 +124,21 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
val net = Net()
|
val net = Net()
|
||||||
net.server = sharedPreferences.getString("server", "")!!
|
net.server = sharedPreferences.getString("server", "")!!
|
||||||
val currentGroup = sharedPreferences.getString("currentGroup", "offline")!!
|
val currentGroup = sharedPreferences.getString("currentGroup", "offline")!!
|
||||||
if ( currentGroup != "offline" && !net.serverIsAvailable(this)) {
|
net.serverIsAvailable(this, {isServerAvailable ->
|
||||||
noInternetConnectionAvailableNotification(this)
|
if ( currentGroup != "offline" && !isServerAvailable) {
|
||||||
} else if (currentGroup != "offline" && net.serverIsAvailable(this)) {
|
runOnUiThread {
|
||||||
synchronize()
|
noInternetConnectionAvailableNotification(this)
|
||||||
ws = WebSocketClient(this, sharedPreferences.getString("server", "")!!)
|
}
|
||||||
val token = sharedPreferences.getString("token", "")!!
|
} else if (currentGroup != "offline" && isServerAvailable) {
|
||||||
ws.connect(token, currentGroup)
|
synchronize()
|
||||||
}
|
ws = WebSocketClient(this, sharedPreferences.getString("server", "")!!)
|
||||||
|
val token = sharedPreferences.getString("token", "")!!
|
||||||
|
ws.connect(token, currentGroup)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun synchronize() {
|
private fun synchronize() {
|
||||||
|
|
||||||
val sharedPreferences = EncryptedSharedPreferences.create(
|
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
applicationContext,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
if (sharedPreferences.getString("currentGroup", "offline")!! == "offline") return
|
if (sharedPreferences.getString("currentGroup", "offline")!! == "offline") return
|
||||||
|
|
||||||
val net = Net()
|
val net = Net()
|
||||||
|
@ -142,26 +149,27 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
|
|
||||||
val currentGroup = sharedPreferences.getString("currentGroup", "")!!.toInt()
|
val currentGroup = sharedPreferences.getString("currentGroup", "")!!.toInt()
|
||||||
|
|
||||||
val data = JSONObject(net.synchronize(currentGroup).body!!.string())
|
net.synchronize(currentGroup, {response ->
|
||||||
|
val data = JSONObject(response.body!!.string())
|
||||||
|
|
||||||
val remoteAbstractProducts = data["abstract_products"] as JSONArray
|
val remoteAbstractProducts = data["abstract_products"] as JSONArray
|
||||||
val remoteProducts = data["products"] as JSONArray
|
val remoteProducts = data["products"] as JSONArray
|
||||||
val remoteCategories = data["categories"] as JSONArray
|
val remoteCategories = data["categories"] as JSONArray
|
||||||
|
|
||||||
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "")!!)
|
val dbHelper = DBStorageController(this, sharedPreferences.getString("currentGroup", "")!!)
|
||||||
|
|
||||||
val abstractProductDAO = AbstractProductDAO(dbHelper)
|
val abstractProductDAO = AbstractProductDAO(dbHelper)
|
||||||
val productDAO = ProductDAO(dbHelper)
|
val productDAO = ProductDAO(dbHelper)
|
||||||
val categoryDAO = CategoryDAO(dbHelper)
|
val categoryDAO = CategoryDAO(dbHelper)
|
||||||
|
|
||||||
val localAbstractProducts = abstractProductDAO.getSortedListOfAbstractProducts(0, "", arrayOf(""))
|
val localAbstractProducts = abstractProductDAO.getSortedListOfAbstractProducts(0, "", arrayOf(""))
|
||||||
val localProducts = productDAO.getSortedListOfProducts(0, "", "")
|
val localProducts = productDAO.getSortedListOfProducts(0, "", "")
|
||||||
val localCategories = categoryDAO.getAllCategories()
|
val localCategories = categoryDAO.getAllCategories()
|
||||||
|
|
||||||
syncAbstractProducts(net, currentGroup, abstractProductDAO, remoteAbstractProducts, localAbstractProducts)
|
|
||||||
syncProducts(productDAO, remoteProducts, localProducts)
|
|
||||||
syncCategories(categoryDAO, remoteCategories, localCategories)
|
|
||||||
|
|
||||||
|
syncAbstractProducts(net, currentGroup, abstractProductDAO, remoteAbstractProducts, localAbstractProducts)
|
||||||
|
syncProducts(productDAO, remoteProducts, localProducts)
|
||||||
|
syncCategories(categoryDAO, remoteCategories, localCategories)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun syncCategories(
|
private fun syncCategories(
|
||||||
|
@ -304,12 +312,11 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
val pictureFile =
|
val pictureFile =
|
||||||
File(picturesDir, "${remoteAbstractProduct["image_filename"]}.png")
|
File(picturesDir, "${remoteAbstractProduct["image_filename"]}.png")
|
||||||
val url = "https://${net.server}/api/abstractproduct/getImage/${currentGroup}/${localId}"
|
val url = "https://${net.server}/api/abstractproduct/getImage/${currentGroup}/${localId}"
|
||||||
net.downloadImage(url, pictureFile)
|
net.downloadImage(url, pictureFile, {
|
||||||
|
val newAbstractProduct = AbstractProduct.createFromJSON(remoteAbstractProduct)
|
||||||
val newAbstractProduct = AbstractProduct.createFromJSON(remoteAbstractProduct)
|
|
||||||
|
|
||||||
abstractProductDAO.addAbstractProduct(newAbstractProduct)
|
|
||||||
|
|
||||||
|
abstractProductDAO.addAbstractProduct(newAbstractProduct)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abstractProductInRemoteDB != null && abstractProductInLocalDB != null) {
|
if (abstractProductInRemoteDB != null && abstractProductInLocalDB != null) {
|
||||||
|
@ -319,11 +326,11 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
val pictureFile =
|
val pictureFile =
|
||||||
File(File(filesDir, "pictures"), "${abstractProductInRemoteDB["image_filename"]}.png")
|
File(File(filesDir, "pictures"), "${abstractProductInRemoteDB["image_filename"]}.png")
|
||||||
val url = "https://${net.server}/api/abstractproduct/getImage/${currentGroup}/${localId}"
|
val url = "https://${net.server}/api/abstractproduct/getImage/${currentGroup}/${localId}"
|
||||||
net.downloadImage(url, pictureFile)
|
net.downloadImage(url, pictureFile, {
|
||||||
|
val updatedData = AbstractProduct.createFromJSON(abstractProductInRemoteDB)
|
||||||
|
|
||||||
val updatedData = AbstractProduct.createFromJSON(abstractProductInRemoteDB)
|
abstractProductDAO.updateAbstractProduct(updatedData)
|
||||||
|
})
|
||||||
abstractProductDAO.updateAbstractProduct(updatedData)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -337,6 +344,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
adapter.addFragment(CategoriesFragment(), getString(R.string.categories_title))
|
adapter.addFragment(CategoriesFragment(), getString(R.string.categories_title))
|
||||||
|
|
||||||
viewpager.adapter = adapter
|
viewpager.adapter = adapter
|
||||||
|
viewpager.offscreenPageLimit = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
|
@ -346,13 +354,6 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isOffline(): Boolean {
|
private fun isOffline(): Boolean {
|
||||||
val sharedPreferences = EncryptedSharedPreferences.create(
|
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
applicationContext,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
return sharedPreferences.getString("currentGroup", "") == "offline"
|
return sharedPreferences.getString("currentGroup", "") == "offline"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,6 +381,15 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
R.id.nav_settings -> {
|
R.id.nav_settings -> {
|
||||||
intent = Intent(this, SettingsActivity::class.java)
|
intent = Intent(this, SettingsActivity::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
R.id.nav_logout -> {
|
||||||
|
sharedPreferences.edit().putString("currentGroup", "").apply()
|
||||||
|
sharedPreferences.edit().putStringSet("groups", emptySet()).apply()
|
||||||
|
sharedPreferences.edit().putString("token", "").apply()
|
||||||
|
sharedPreferences.edit().putString("server", "").apply()
|
||||||
|
|
||||||
|
intent = Intent(this, LoginActivity::class.java)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
|
|
||||||
|
@ -495,4 +505,17 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
||||||
val storageFragment = fragment as StorageFragment
|
val storageFragment = fragment as StorageFragment
|
||||||
storageFragment.filterByCategory(id)
|
storageFragment.filterByCategory(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addSelection() {
|
||||||
|
selectionMode = true
|
||||||
|
selectedAmount ++
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeSelection() {
|
||||||
|
selectedAmount --
|
||||||
|
if (selectedAmount <= 0) {
|
||||||
|
selectedAmount = 0
|
||||||
|
selectionMode = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,19 +1,27 @@
|
||||||
package org.foxarmy.barcodescannerforemployees.activities
|
package org.foxarmy.barcodescannerforemployees.activities
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.SharedPreferences
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.EditText
|
||||||
|
import android.widget.PopupMenu
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.Net
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.databinding.ActivityManageGroupBinding
|
import org.foxarmy.barcodescannerforemployees.databinding.ActivityManageGroupBinding
|
||||||
import org.foxarmy.barcodescannerforemployees.parseArray
|
import org.foxarmy.barcodescannerforemployees.parseIntArray
|
||||||
import org.foxarmy.barcodescannerforemployees.views.GroupMemberView
|
import org.foxarmy.barcodescannerforemployees.views.GroupMemberView
|
||||||
|
|
||||||
class ManageGroupActivity : AppCompatActivity(){
|
class ManageGroupActivity : AppCompatActivity() {
|
||||||
private lateinit var binding: ActivityManageGroupBinding
|
private lateinit var binding: ActivityManageGroupBinding
|
||||||
private var isAdmin: Boolean = true
|
private var isAdmin: Boolean = false
|
||||||
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
|
private lateinit var net: Net
|
||||||
|
private var groupId: Int = 0
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -21,56 +29,150 @@ class ManageGroupActivity : AppCompatActivity(){
|
||||||
binding = ActivityManageGroupBinding.inflate(layoutInflater)
|
binding = ActivityManageGroupBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
val groupId = intent.extras!!.getInt("groupId")
|
groupId = intent.extras!!.getInt("groupId")
|
||||||
|
|
||||||
val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
|
sharedPreferences = org.foxarmy.barcodescannerforemployees.getPreferences(this)
|
||||||
|
|
||||||
val sharedPreferences = EncryptedSharedPreferences.create(
|
net = Net()
|
||||||
"sensitive",
|
|
||||||
masterKeyAlias,
|
|
||||||
applicationContext,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
val net = Net()
|
|
||||||
|
|
||||||
net.token = sharedPreferences.getString("token", "")!!
|
net.token = sharedPreferences.getString("token", "")!!
|
||||||
net.server = sharedPreferences.getString("server", "")!!
|
net.server = sharedPreferences.getString("server", "")!!
|
||||||
net.language = sharedPreferences.getString("language", "en-US")!!
|
net.language = sharedPreferences.getString("language", "en-US")!!
|
||||||
|
|
||||||
|
|
||||||
val users = parseArray(net.getUsersInGroup(groupId).body!!.string())
|
setUpMembers()
|
||||||
|
|
||||||
for (user in users) {
|
binding.renameButton.setOnClickListener {
|
||||||
val groupMemberView = GroupMemberView(this, this as Context, net.getUsernameById(user).body!!.string(), user)
|
val input = EditText(this)
|
||||||
|
AlertDialog.Builder(this)
|
||||||
|
.setTitle(getString(R.string.new_group_name))
|
||||||
|
.setView(input)
|
||||||
|
.setPositiveButton(getString(R.string.ok)) { _, _ ->
|
||||||
|
val newName = input.text.toString()
|
||||||
|
net.renameGroup(groupId, newName, { response ->
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(this, response.body!!.string(), Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
binding.groupsContent.addView(groupMemberView)
|
}
|
||||||
|
.setNegativeButton(getString(R.string.cancel)) { _, _ ->
|
||||||
|
|
||||||
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
isAdmin = amIAnAdminIn(groupId)
|
binding.leaveButton.setOnClickListener {
|
||||||
|
net.leaveGroup(groupId, { response ->
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(this, response.body!!.string(), Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
if (response.code == 200) {
|
||||||
|
val groups = sharedPreferences.getStringSet("groups", emptySet())!!
|
||||||
|
groups.remove(groupId.toString())
|
||||||
|
sharedPreferences.edit().putStringSet("groups", groups).apply()
|
||||||
|
sharedPreferences.edit().putString("currentGroup", "").apply()
|
||||||
|
|
||||||
if (!isAdmin) {
|
if (groups.isEmpty()) {
|
||||||
binding.renameButton.visibility = View.GONE
|
runOnUiThread {
|
||||||
|
val intent = Intent(this, GroupActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sharedPreferences.edit().putString("currentGroup", groups.toList()[0]).apply()
|
||||||
|
runOnUiThread {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setUpAdminRelatedButtons()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun amIAnAdminIn(groupId: Int): Boolean {
|
private fun setUpMembers() {
|
||||||
val sharedPreferences = EncryptedSharedPreferences.create(
|
net.getUsersInGroup(groupId, { response ->
|
||||||
"sensitive",
|
val users = parseIntArray(response.body!!.string())
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
for (user in users) {
|
||||||
applicationContext,
|
net.getUsernameById(user, { response ->
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
val groupMemberView = GroupMemberView(this, this as Context, response.body!!.string(), user)
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
|
groupMemberView.setOnLongClickListener { view ->
|
||||||
|
amIAnAdminIn(groupId, { amIAnAdmin ->
|
||||||
|
if (!amIAnAdmin) return@amIAnAdminIn
|
||||||
|
runOnUiThread {
|
||||||
|
val popupMenu = PopupMenu(this, groupMemberView)
|
||||||
|
popupMenu.inflate(R.menu.user_pop_menu)
|
||||||
|
popupMenu.setOnMenuItemClickListener { item ->
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.kick -> {
|
||||||
|
|
||||||
|
setUpMembers()
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.transfer_ownership -> {
|
||||||
|
AlertDialog.Builder(this)
|
||||||
|
.setMessage(getString(R.string.transfer_ownership_confirmation))
|
||||||
|
.setPositiveButton(R.string.yes) { _, _ ->
|
||||||
|
net.transfer_ownership(
|
||||||
|
groupId,
|
||||||
|
(view as GroupMemberView).userId,
|
||||||
|
{ response ->
|
||||||
|
runOnUiThread {
|
||||||
|
Toast.makeText(
|
||||||
|
this,
|
||||||
|
response.body!!.string(),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
setUpAdminRelatedButtons()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.no) { _, _ -> }
|
||||||
|
.show()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
runOnUiThread {
|
||||||
|
popupMenu.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
true
|
||||||
|
}
|
||||||
|
runOnUiThread {
|
||||||
|
binding.groupsContent.addView(groupMemberView)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun amIAnAdminIn(groupId: Int, callback: (Boolean) -> Unit) {
|
||||||
val net = Net()
|
val net = Net()
|
||||||
|
|
||||||
net.token = sharedPreferences.getString("token", "")!!
|
net.token = sharedPreferences.getString("token", "")!!
|
||||||
net.server = sharedPreferences.getString("server", "")!!
|
net.server = sharedPreferences.getString("server", "")!!
|
||||||
net.language = sharedPreferences.getString("language", "en-US")!!
|
net.language = sharedPreferences.getString("language", "en-US")!!
|
||||||
|
|
||||||
val result = sharedPreferences.getInt("userId", 0) == net.getGroupAdminId(groupId).body!!.string().toInt()
|
net.getGroupAdminId(groupId, { response ->
|
||||||
return result
|
val result = sharedPreferences.getInt("userId", 0) == response.body!!.string().toInt()
|
||||||
|
callback(result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setUpAdminRelatedButtons() {
|
||||||
|
amIAnAdminIn(groupId, { isAdmin ->
|
||||||
|
runOnUiThread {
|
||||||
|
if (!isAdmin) {
|
||||||
|
binding.renameButton.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,12 +5,10 @@ import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.Net
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
import org.foxarmy.barcodescannerforemployees.R
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.databinding.ActivityMyGroupsBinding
|
import org.foxarmy.barcodescannerforemployees.databinding.ActivityMyGroupsBinding
|
||||||
import org.foxarmy.barcodescannerforemployees.parseArray
|
import org.foxarmy.barcodescannerforemployees.parseIntArray
|
||||||
import org.foxarmy.barcodescannerforemployees.views.GroupView
|
import org.foxarmy.barcodescannerforemployees.views.GroupView
|
||||||
|
|
||||||
class MyGroupsActivity : AppCompatActivity(){
|
class MyGroupsActivity : AppCompatActivity(){
|
||||||
|
@ -22,13 +20,7 @@ class MyGroupsActivity : AppCompatActivity(){
|
||||||
binding = ActivityMyGroupsBinding.inflate(layoutInflater)
|
binding = ActivityMyGroupsBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
val sharedPreferences = EncryptedSharedPreferences.create(
|
val sharedPreferences = org.foxarmy.barcodescannerforemployees.getPreferences(this)
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
applicationContext,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
val net = Net()
|
val net = Net()
|
||||||
|
|
||||||
|
@ -36,20 +28,28 @@ class MyGroupsActivity : AppCompatActivity(){
|
||||||
net.server = sharedPreferences.getString("server", "")!!
|
net.server = sharedPreferences.getString("server", "")!!
|
||||||
net.language = sharedPreferences.getString("language", "en-US")!!
|
net.language = sharedPreferences.getString("language", "en-US")!!
|
||||||
|
|
||||||
val groups = parseArray(net.getMyGroups().body!!.string())
|
net.getMyGroups { response ->
|
||||||
|
val groups = parseIntArray(response.body!!.string())
|
||||||
val container = findViewById<LinearLayout>(R.id.groupsLayout)
|
|
||||||
|
|
||||||
for (group in groups) {
|
|
||||||
val groupView = GroupView(this, this as Context, net.getGroupName(group), group)
|
|
||||||
|
|
||||||
|
|
||||||
container.addView(groupView)
|
val container = findViewById<LinearLayout>(R.id.groupsLayout)
|
||||||
}
|
|
||||||
|
|
||||||
binding.newGroup.setOnClickListener {
|
for (group in groups) {
|
||||||
val intent = Intent(this, GroupActivity::class.java)
|
net.getGroupName(group, {response ->
|
||||||
startActivity(intent)
|
val groupView = GroupView(this, this as Context, response, group)
|
||||||
|
|
||||||
|
runOnUiThread {
|
||||||
|
container.addView(groupView)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.newGroup.setOnClickListener {
|
||||||
|
runOnUiThread {
|
||||||
|
val intent = Intent(this, GroupActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,8 +4,8 @@ import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
import androidx.security.crypto.MasterKeys
|
import org.foxarmy.barcodescannerforemployees.parseStringList
|
||||||
|
|
||||||
class NavigatorActivity : Activity() {
|
class NavigatorActivity : Activity() {
|
||||||
|
|
||||||
|
@ -14,26 +14,23 @@ class NavigatorActivity : Activity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
sharedPreferences = org.foxarmy.barcodescannerforemployees.getPreferences(this)
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
applicationContext,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
var intent = Intent(this, MainActivity::class.java)
|
var intent = Intent(this, MainActivity::class.java)
|
||||||
|
|
||||||
if (!isInGroup() && !isOffline()) {
|
isInGroup { flag ->
|
||||||
intent = Intent(this, GroupActivity::class.java)
|
if (!flag && !isOffline()) {
|
||||||
}
|
intent = Intent(this, GroupActivity::class.java)
|
||||||
|
}
|
||||||
|
if (!isAuthenticated() && !isOffline()) {
|
||||||
|
intent = Intent(this, LoginActivity::class.java);
|
||||||
|
}
|
||||||
|
|
||||||
if (!isAuthenticated() && !isOffline()) {
|
runOnUiThread {
|
||||||
intent = Intent(this, LoginActivity::class.java);
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startActivity(intent);
|
|
||||||
finish();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isOffline(): Boolean {
|
private fun isOffline(): Boolean {
|
||||||
|
@ -44,7 +41,28 @@ class NavigatorActivity : Activity() {
|
||||||
return sharedPreferences.getString("token", "") != ""
|
return sharedPreferences.getString("token", "") != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isInGroup(): Boolean {
|
private fun isInGroup(callback: (Boolean) -> Unit) {
|
||||||
return sharedPreferences.getStringSet("groups", emptySet())!!.isNotEmpty()
|
val groups = sharedPreferences.getStringSet("groups", emptySet())!!
|
||||||
|
if (groups.isEmpty()) {
|
||||||
|
if (sharedPreferences.getString("token", "")!! == "") callback(false)
|
||||||
|
val net = Net()
|
||||||
|
net.language = sharedPreferences.getString("language", "")!!
|
||||||
|
net.server = sharedPreferences.getString("server", "")!!
|
||||||
|
net.token = sharedPreferences.getString("token", "")!!
|
||||||
|
|
||||||
|
net.getMyGroups { response ->
|
||||||
|
val responseBody = response.body!!.string()
|
||||||
|
if (responseBody == "" || responseBody == "[]") callback(false)
|
||||||
|
val groupsFromServer = parseStringList(responseBody)
|
||||||
|
if (groupsFromServer.isNotEmpty()) {
|
||||||
|
sharedPreferences.edit().putStringSet("groups", groupsFromServer.toSet()).apply()
|
||||||
|
sharedPreferences.edit().putString("currentGroup", groupsFromServer[0]).apply()
|
||||||
|
callback(true)
|
||||||
|
} else {
|
||||||
|
callback(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,8 +6,6 @@ import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.Net
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
import org.foxarmy.barcodescannerforemployees.databinding.ActivitySettingsBinding
|
import org.foxarmy.barcodescannerforemployees.databinding.ActivitySettingsBinding
|
||||||
|
|
||||||
|
@ -17,17 +15,12 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
lateinit var myGroups: List<String>
|
lateinit var myGroups: List<String>
|
||||||
lateinit var currentGroup: String
|
lateinit var currentGroup: String
|
||||||
lateinit var groupsNames: MutableList<String>
|
lateinit var groupsNames: MutableList<String>
|
||||||
|
lateinit var namesMap: MutableMap<Int, String>
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
sharedPreferences = org.foxarmy.barcodescannerforemployees.getPreferences(this)
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
applicationContext,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
myGroups = sharedPreferences.getStringSet("groups", emptySet())!!.toList()
|
myGroups = sharedPreferences.getStringSet("groups", emptySet())!!.toList()
|
||||||
currentGroup = sharedPreferences.getString("currentGroup", "offline")!!
|
currentGroup = sharedPreferences.getString("currentGroup", "offline")!!
|
||||||
|
@ -46,20 +39,26 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
if (isOffline()) {
|
if (isOffline()) {
|
||||||
binding.currentGroupSetting.visibility = View.GONE
|
binding.currentGroupSetting.visibility = View.GONE
|
||||||
} else {
|
} else {
|
||||||
groupsNames = mutableListOf()
|
namesMap = mutableMapOf()
|
||||||
|
|
||||||
for (myGroup in myGroups) {
|
for (myGroup in myGroups) {
|
||||||
groupsNames.add(net.getGroupName(myGroup.toInt()))
|
net.getGroupName(myGroup.toInt(), { name ->
|
||||||
|
namesMap[myGroup.toInt()] = name
|
||||||
|
fillUpCurrentGroupSpinner()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fillUpCurrentGroupSpinner()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.saveButton.setOnClickListener {
|
binding.saveButton.setOnClickListener {
|
||||||
sharedPreferences.edit().putString("currentGroup", net.getGroupId(binding.currentGroupSpinner.selectedItem.toString())).apply()
|
net.getGroupId(binding.currentGroupSpinner.selectedItem.toString(), { groupId ->
|
||||||
sharedPreferences.edit().putInt("imageCompression", binding.imageCompressionFactorSeekBar.progress + 1).apply()
|
sharedPreferences.edit().putString("currentGroup", groupId).apply()
|
||||||
setResult(Activity.RESULT_OK)
|
sharedPreferences.edit().putInt("imageCompression", binding.imageCompressionFactorSeekBar.progress + 1)
|
||||||
finish()
|
.apply()
|
||||||
|
runOnUiThread {
|
||||||
|
setResult(Activity.RESULT_OK)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.cancelButton.setOnClickListener {
|
binding.cancelButton.setOnClickListener {
|
||||||
|
@ -78,14 +77,27 @@ class SettingsActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fillUpCurrentGroupSpinner() {
|
private fun fillUpCurrentGroupSpinner() {
|
||||||
if (currentGroup == "offline") {
|
runOnUiThread {
|
||||||
binding.currentGroupSetting.visibility = View.GONE
|
if (currentGroup == "offline") {
|
||||||
|
binding.currentGroupSetting.visibility = View.GONE
|
||||||
|
}
|
||||||
|
groupsNames = mutableListOf()
|
||||||
|
groupsNames.clear()
|
||||||
|
val sortedMap = namesMap.entries.sortedBy { it.key }.associate { it.toPair() }
|
||||||
|
for ((id, name) in sortedMap) {
|
||||||
|
groupsNames.add(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
val arrayAdapter =
|
||||||
|
ArrayAdapter(this, androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, groupsNames)
|
||||||
|
arrayAdapter.setDropDownViewResource(androidx.appcompat.R.layout.support_simple_spinner_dropdown_item)
|
||||||
|
binding.currentGroupSpinner.adapter = arrayAdapter
|
||||||
|
if (myGroups.indexOf(currentGroup) < groupsNames.size) binding.currentGroupSpinner.setSelection(
|
||||||
|
myGroups.indexOf(
|
||||||
|
currentGroup
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val arrayAdapter =
|
|
||||||
ArrayAdapter(this, androidx.appcompat.R.layout.support_simple_spinner_dropdown_item, groupsNames)
|
|
||||||
arrayAdapter.setDropDownViewResource(androidx.appcompat.R.layout.support_simple_spinner_dropdown_item)
|
|
||||||
binding.currentGroupSpinner.adapter = arrayAdapter
|
|
||||||
binding.currentGroupSpinner.setSelection(myGroups.indexOf(currentGroup))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -308,7 +308,7 @@ class AbstractProductDAO(private val dbHelper: DBStorageController) {
|
||||||
}
|
}
|
||||||
|
|
||||||
"barcodeless" -> {
|
"barcodeless" -> {
|
||||||
selection = "${AbstractProductContract.AbstractProductEntry.BARCODE} = ? OR ${AbstractProductContract.AbstractProductEntry.BARCODE} = ?"
|
selection = "${AbstractProductContract.AbstractProductEntry.BARCODE} = ? OR ${AbstractProductContract.AbstractProductEntry.BARCODE} = ? OR ${AbstractProductContract.AbstractProductEntry.BARCODE} = ?"
|
||||||
selectionArgs = filter
|
selectionArgs = filter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,36 +11,31 @@ import android.widget.Toast
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.Net
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
import org.foxarmy.barcodescannerforemployees.R
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.activities.AddCategoryActivity
|
import org.foxarmy.barcodescannerforemployees.activities.AddCategoryActivity
|
||||||
import org.foxarmy.barcodescannerforemployees.database.CategoryDAO
|
import org.foxarmy.barcodescannerforemployees.database.CategoryDAO
|
||||||
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
||||||
|
import org.foxarmy.barcodescannerforemployees.getPreferences
|
||||||
import org.foxarmy.barcodescannerforemployees.views.CategoryView
|
import org.foxarmy.barcodescannerforemployees.views.CategoryView
|
||||||
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
class CategoriesFragment : Fragment() {
|
class CategoriesFragment : Fragment() {
|
||||||
|
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
private lateinit var categoryDAO: CategoryDAO
|
private lateinit var categoryDAO: CategoryDAO
|
||||||
|
private var updateInProgress = false
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
sharedPreferences = getPreferences(requireContext())
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
requireContext(),
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
prepareDatabaseConnection()
|
prepareDatabaseConnection()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun prepareDatabaseConnection() {
|
private fun prepareDatabaseConnection() {
|
||||||
val dbHelper = DBStorageController(requireContext(), sharedPreferences.getString("currentGroup", "database")!!)
|
val dbHelper = DBStorageController(requireContext(), sharedPreferences.getString("currentGroup", "offline")!!)
|
||||||
categoryDAO = CategoryDAO(dbHelper)
|
categoryDAO = CategoryDAO(dbHelper)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,56 +53,75 @@ class CategoriesFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeSelected() {
|
fun removeSelected() {
|
||||||
val layout = view?.findViewById<LinearLayout>(R.id.categoriesLayout)
|
thread {
|
||||||
|
val layout = view?.findViewById<LinearLayout>(R.id.categoriesLayout)
|
||||||
|
|
||||||
var deleted = false
|
var deleted = false
|
||||||
for (view: CategoryView in layout?.children!!.iterator() as Iterator<CategoryView>) {
|
for (view: CategoryView in layout?.children!!.iterator() as Iterator<CategoryView>) {
|
||||||
if (view.isCategorySelected) {
|
if (view.isCategorySelected) {
|
||||||
val net = Net()
|
val net = Net()
|
||||||
net.token = sharedPreferences.getString("token", "")!!
|
net.token = sharedPreferences.getString("token", "")!!
|
||||||
net.server = sharedPreferences.getString("server", "")!!
|
net.server = sharedPreferences.getString("server", "")!!
|
||||||
net.language = sharedPreferences.getString("language", "en-US")!!
|
net.language = sharedPreferences.getString("language", "en-US")!!
|
||||||
val currentGroup = sharedPreferences.getString("currentGroup", "")!!.toInt()
|
val currentGroup = sharedPreferences.getString("currentGroup", "")!!.toInt()
|
||||||
|
|
||||||
categoryDAO.eraseCategory(view.category.id, requireContext())
|
categoryDAO.eraseCategory(view.category.id, requireContext())
|
||||||
val response = net.deleteCategory(currentGroup, view.category.id)
|
net.deleteCategory(currentGroup, view.category.id, {response ->
|
||||||
activity!!.runOnUiThread{
|
activity!!.runOnUiThread{
|
||||||
Toast.makeText(context, response.body!!.string(), Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, response.body!!.string(), Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
deleted = true
|
||||||
}
|
}
|
||||||
|
|
||||||
deleted = true
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!deleted) {
|
if (!deleted) {
|
||||||
Toast.makeText(requireContext(), getString(R.string.nothing_to_delete), Toast.LENGTH_SHORT).show()
|
activity!!.runOnUiThread {
|
||||||
|
Toast.makeText(requireContext(), getString(R.string.nothing_to_delete), Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateContent()
|
||||||
}
|
}
|
||||||
updateContent()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateSelected() {
|
fun updateSelected() {
|
||||||
val layout = view?.findViewById<LinearLayout>(R.id.categoriesLayout)
|
thread {
|
||||||
for (view: CategoryView in layout?.children!!.iterator() as Iterator<CategoryView>) {
|
val layout = view?.findViewById<LinearLayout>(R.id.categoriesLayout)
|
||||||
if (view.isCategorySelected) {
|
for (view: CategoryView in layout?.children!!.iterator() as Iterator<CategoryView>) {
|
||||||
val addCategoryIntent = Intent(context, AddCategoryActivity::class.java)
|
if (view.isCategorySelected) {
|
||||||
val extras = Bundle()
|
val addCategoryIntent = Intent(context, AddCategoryActivity::class.java)
|
||||||
extras.putParcelable("category", view.category)
|
val extras = Bundle()
|
||||||
addCategoryIntent.putExtras(extras)
|
extras.putParcelable("category", view.category)
|
||||||
ContextCompat.startActivity(context!!, addCategoryIntent, extras)
|
addCategoryIntent.putExtras(extras)
|
||||||
|
activity!!.runOnUiThread {
|
||||||
|
ContextCompat.startActivity(context!!, addCategoryIntent, extras)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateContent() {
|
fun updateContent() {
|
||||||
prepareDatabaseConnection()
|
thread {
|
||||||
val layout = view?.findViewById<LinearLayout>(R.id.categoriesLayout)
|
if (updateInProgress) return@thread
|
||||||
layout?.removeAllViews()
|
updateInProgress = true
|
||||||
|
prepareDatabaseConnection()
|
||||||
|
val layout = view?.findViewById<LinearLayout>(R.id.categoriesLayout)
|
||||||
|
activity!!.runOnUiThread {
|
||||||
|
layout?.removeAllViews()
|
||||||
|
}
|
||||||
|
|
||||||
val categories = categoryDAO.getAllCategories()
|
val categories = categoryDAO.getAllCategories()
|
||||||
|
|
||||||
for (category in categories) {
|
for (category in categories) {
|
||||||
val categoryView = CategoryView(requireActivity(), requireContext(), category)
|
val categoryView = CategoryView(requireActivity(), requireContext(), category)
|
||||||
layout?.addView(categoryView)
|
activity!!.runOnUiThread {
|
||||||
|
layout?.addView(categoryView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateInProgress = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,14 +14,13 @@ import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.gridlayout.widget.GridLayout
|
import androidx.gridlayout.widget.GridLayout
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.Net
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
import org.foxarmy.barcodescannerforemployees.R
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.activities.AddProductActivity
|
import org.foxarmy.barcodescannerforemployees.activities.AddProductActivity
|
||||||
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
||||||
import org.foxarmy.barcodescannerforemployees.database.ProductDAO
|
import org.foxarmy.barcodescannerforemployees.database.ProductDAO
|
||||||
import org.foxarmy.barcodescannerforemployees.databinding.FragmentShelfBinding
|
import org.foxarmy.barcodescannerforemployees.databinding.FragmentShelfBinding
|
||||||
|
import org.foxarmy.barcodescannerforemployees.getPreferences
|
||||||
import org.foxarmy.barcodescannerforemployees.views.ProductView
|
import org.foxarmy.barcodescannerforemployees.views.ProductView
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
|
@ -38,16 +37,9 @@ class ShelfFragment : Fragment() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
sharedPreferences = getPreferences(requireContext())
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
requireContext(),
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
prepareDatabaseConnection()
|
prepareDatabaseConnection()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@ -122,11 +114,12 @@ class ShelfFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateContent() {
|
fun updateContent() {
|
||||||
prepareDatabaseConnection()
|
|
||||||
thread {
|
thread {
|
||||||
if (updateInProgress) return@thread
|
if (updateInProgress) return@thread
|
||||||
updateInProgress = true
|
updateInProgress = true
|
||||||
|
prepareDatabaseConnection()
|
||||||
val grv = view?.findViewById<GridLayout>(R.id.contentGridLayout)
|
val grv = view?.findViewById<GridLayout>(R.id.contentGridLayout)
|
||||||
|
|
||||||
activity!!.runOnUiThread {
|
activity!!.runOnUiThread {
|
||||||
grv?.removeAllViews()
|
grv?.removeAllViews()
|
||||||
}
|
}
|
||||||
|
@ -144,7 +137,6 @@ class ShelfFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateInProgress = false
|
updateInProgress = false
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,10 +157,11 @@ class ShelfFragment : Fragment() {
|
||||||
val currentGroup = sharedPreferences.getString("currentGroup", "")!!.toInt()
|
val currentGroup = sharedPreferences.getString("currentGroup", "")!!.toInt()
|
||||||
|
|
||||||
productDAO.eraseProduct(view.product.id)
|
productDAO.eraseProduct(view.product.id)
|
||||||
val response = net.deleteProduct(currentGroup, view.product.id)
|
net.deleteProduct(currentGroup, view.product.id, {response ->
|
||||||
activity!!.runOnUiThread{
|
activity!!.runOnUiThread{
|
||||||
Toast.makeText(context, response.body!!.string(), Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, response.body!!.string(), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
deleted = true
|
deleted = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,10 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.Net
|
import org.foxarmy.barcodescannerforemployees.Net
|
||||||
import org.foxarmy.barcodescannerforemployees.R
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.activities.AddAbstractProductActivity
|
import org.foxarmy.barcodescannerforemployees.activities.AddAbstractProductActivity
|
||||||
|
@ -20,6 +19,7 @@ import org.foxarmy.barcodescannerforemployees.database.AbstractProductDAO
|
||||||
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
||||||
import org.foxarmy.barcodescannerforemployees.databinding.FragmentStorageBinding
|
import org.foxarmy.barcodescannerforemployees.databinding.FragmentStorageBinding
|
||||||
import org.foxarmy.barcodescannerforemployees.generateThumbnailForImage
|
import org.foxarmy.barcodescannerforemployees.generateThumbnailForImage
|
||||||
|
import org.foxarmy.barcodescannerforemployees.getPreferences
|
||||||
import org.foxarmy.barcodescannerforemployees.views.AbstractProductView
|
import org.foxarmy.barcodescannerforemployees.views.AbstractProductView
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
|
@ -32,23 +32,18 @@ class StorageFragment : Fragment() {
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
private lateinit var abstractProductDAO: AbstractProductDAO
|
private lateinit var abstractProductDAO: AbstractProductDAO
|
||||||
|
|
||||||
|
private var updateInProcess = false
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View {
|
): View {
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
binding = FragmentStorageBinding.inflate(inflater)
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
sharedPreferences = getPreferences(requireContext())
|
||||||
requireContext(),
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
prepareDatabaseConnection()
|
prepareDatabaseConnection()
|
||||||
|
|
||||||
binding = FragmentStorageBinding.inflate(inflater)
|
|
||||||
|
|
||||||
fillUpSortBySpinner()
|
fillUpSortBySpinner()
|
||||||
|
|
||||||
binding.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
binding.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||||
|
@ -107,10 +102,12 @@ class StorageFragment : Fragment() {
|
||||||
val currentGroup = sharedPreferences.getString("currentGroup", "")!!.toInt()
|
val currentGroup = sharedPreferences.getString("currentGroup", "")!!.toInt()
|
||||||
|
|
||||||
abstractProductDAO.eraseAbstractProduct(view.abstractProduct.id, requireContext())
|
abstractProductDAO.eraseAbstractProduct(view.abstractProduct.id, requireContext())
|
||||||
val response = net.deleteAbstractProduct(currentGroup, view.abstractProduct.id)
|
net.deleteAbstractProduct(currentGroup, view.abstractProduct.id, {response ->
|
||||||
activity!!.runOnUiThread{
|
activity!!.runOnUiThread{
|
||||||
Toast.makeText(context, response.body!!.string(), Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, response.body!!.string(), Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
deleted = true
|
deleted = true
|
||||||
}
|
}
|
||||||
|
@ -141,10 +138,14 @@ class StorageFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateContent() {
|
fun updateContent() {
|
||||||
prepareDatabaseConnection()
|
|
||||||
thread {
|
thread {
|
||||||
|
if (updateInProcess) return@thread
|
||||||
|
updateInProcess = true
|
||||||
|
prepareDatabaseConnection()
|
||||||
|
|
||||||
val grv = binding.contentGridLayout
|
val grv = binding.contentGridLayout
|
||||||
activity!!.runOnUiThread{
|
|
||||||
|
activity!!.runOnUiThread {
|
||||||
grv.removeAllViews()
|
grv.removeAllViews()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,11 +161,25 @@ class StorageFragment : Fragment() {
|
||||||
)
|
)
|
||||||
|
|
||||||
if (filterBy == "barcodeless") {
|
if (filterBy == "barcodeless") {
|
||||||
abstractProductView.setOnClickListener {
|
abstractProductView.also {
|
||||||
(activity as FindBarcodelessAbstractProduct).selected(abstractProductView.abstractProduct)
|
it.setOnClickListener {
|
||||||
}
|
(activity as FindBarcodelessAbstractProduct).selected(abstractProductView.abstractProduct)
|
||||||
abstractProductView.findViewById<TextView>(R.id.productNameView).setOnClickListener {
|
}
|
||||||
(activity as FindBarcodelessAbstractProduct).selected(abstractProductView.abstractProduct)
|
it.findViewById<TextView>(R.id.productNameView).setOnClickListener {
|
||||||
|
(activity as FindBarcodelessAbstractProduct).selected(abstractProductView.abstractProduct)
|
||||||
|
}
|
||||||
|
it.findViewById<ConstraintLayout>(R.id.productLayout).setOnClickListener {
|
||||||
|
(activity as FindBarcodelessAbstractProduct).selected(abstractProductView.abstractProduct)
|
||||||
|
}
|
||||||
|
it.findViewById<TextView>(R.id.categoryView).setOnClickListener {
|
||||||
|
(activity as FindBarcodelessAbstractProduct).selected(abstractProductView.abstractProduct)
|
||||||
|
}
|
||||||
|
it.findViewById<TextView>(R.id.unitView).setOnClickListener {
|
||||||
|
(activity as FindBarcodelessAbstractProduct).selected(abstractProductView.abstractProduct)
|
||||||
|
}
|
||||||
|
it.findViewById<TextView>(R.id.productNetWeightView).setOnClickListener {
|
||||||
|
(activity as FindBarcodelessAbstractProduct).selected(abstractProductView.abstractProduct)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,14 +187,10 @@ class StorageFragment : Fragment() {
|
||||||
grv.addView(abstractProductView)
|
grv.addView(abstractProductView)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.join()
|
updateInProcess = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
|
|
||||||
updateContent()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun filterByCategory(id: Int) {
|
fun filterByCategory(id: Int) {
|
||||||
filterBy = "category"
|
filterBy = "category"
|
||||||
|
@ -194,7 +205,7 @@ class StorageFragment : Fragment() {
|
||||||
val args = Bundle()
|
val args = Bundle()
|
||||||
args.putString("filterBy", filterBy)
|
args.putString("filterBy", filterBy)
|
||||||
args.putStringArray("filter", filter)
|
args.putStringArray("filter", filter)
|
||||||
fragment.setArguments(args)
|
fragment.arguments = args
|
||||||
|
|
||||||
return fragment
|
return fragment
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,19 +14,15 @@ import android.widget.Toast
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.ContextCompat.startActivity
|
import androidx.core.content.ContextCompat.startActivity
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
import org.foxarmy.barcodescannerforemployees.*
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.R
|
|
||||||
import org.foxarmy.barcodescannerforemployees.activities.FullscreenActivity
|
import org.foxarmy.barcodescannerforemployees.activities.FullscreenActivity
|
||||||
|
import org.foxarmy.barcodescannerforemployees.activities.MainActivity
|
||||||
import org.foxarmy.barcodescannerforemployees.database.CategoryDAO
|
import org.foxarmy.barcodescannerforemployees.database.CategoryDAO
|
||||||
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
||||||
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
||||||
import org.foxarmy.barcodescannerforemployees.getActivity
|
|
||||||
import org.foxarmy.barcodescannerforemployees.getImageUri
|
|
||||||
import org.foxarmy.barcodescannerforemployees.getUnitNameById
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class AbstractProductView: LinearLayout {
|
class AbstractProductView : LinearLayout {
|
||||||
private var productLayout: ConstraintLayout? = null
|
private var productLayout: ConstraintLayout? = null
|
||||||
private var productPicture: ImageView? = null
|
private var productPicture: ImageView? = null
|
||||||
private var productNameField: TextView? = null
|
private var productNameField: TextView? = null
|
||||||
|
@ -42,16 +38,10 @@ class AbstractProductView: LinearLayout {
|
||||||
|
|
||||||
constructor(context: Context, a: AttributeSet) : super(context, a) {
|
constructor(context: Context, a: AttributeSet) : super(context, a) {
|
||||||
activity = getActivity(context)!!
|
activity = getActivity(context)!!
|
||||||
val inflater:LayoutInflater = activity.layoutInflater
|
val inflater: LayoutInflater = activity.layoutInflater
|
||||||
inflater.inflate(R.layout.abstract_product_view, this)
|
inflater.inflate(R.layout.abstract_product_view, this)
|
||||||
|
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
sharedPreferences = getPreferences(context)
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
context,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "database")!!)
|
val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "database")!!)
|
||||||
categoryDAO = CategoryDAO(dbHelper)
|
categoryDAO = CategoryDAO(dbHelper)
|
||||||
|
@ -60,23 +50,17 @@ class AbstractProductView: LinearLayout {
|
||||||
constructor(activity: Activity, context: Context, abstractProduct: AbstractProduct) : super(context) {
|
constructor(activity: Activity, context: Context, abstractProduct: AbstractProduct) : super(context) {
|
||||||
this.abstractProduct = abstractProduct
|
this.abstractProduct = abstractProduct
|
||||||
this.activity = activity
|
this.activity = activity
|
||||||
val inflater:LayoutInflater = activity.layoutInflater
|
val inflater: LayoutInflater = activity.layoutInflater
|
||||||
inflater.inflate(R.layout.abstract_product_view, this)
|
inflater.inflate(R.layout.abstract_product_view, this)
|
||||||
|
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
sharedPreferences = getPreferences(context)
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
context,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "database")!!)
|
val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "database")!!)
|
||||||
categoryDAO = CategoryDAO(dbHelper)
|
categoryDAO = CategoryDAO(dbHelper)
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun init () {
|
private fun init() {
|
||||||
productLayout = findViewById(R.id.productLayout)
|
productLayout = findViewById(R.id.productLayout)
|
||||||
productPicture = findViewById(R.id.productPicture)
|
productPicture = findViewById(R.id.productPicture)
|
||||||
productNameField = findViewById(R.id.productNameView)
|
productNameField = findViewById(R.id.productNameView)
|
||||||
|
@ -84,30 +68,8 @@ class AbstractProductView: LinearLayout {
|
||||||
categoryField = findViewById(R.id.categoryView)
|
categoryField = findViewById(R.id.categoryView)
|
||||||
unitField = findViewById(R.id.unitView)
|
unitField = findViewById(R.id.unitView)
|
||||||
|
|
||||||
|
setUpClicks()
|
||||||
productPicture!!.setOnClickListener {
|
|
||||||
val fullscreenIntent = Intent(activity, FullscreenActivity::class.java)
|
|
||||||
val extras = Bundle()
|
|
||||||
extras.putString("imagehash", abstractProduct.imageHash)
|
|
||||||
fullscreenIntent.putExtras(extras)
|
|
||||||
startActivity(context, fullscreenIntent, extras)
|
|
||||||
}
|
|
||||||
|
|
||||||
productLayout!!.setOnClickListener {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
unitField?.text = getUnitNameById(context, abstractProduct.unit)
|
unitField?.text = getUnitNameById(context, abstractProduct.unit)
|
||||||
|
|
||||||
productLayout!!.setOnLongClickListener {
|
|
||||||
isProductSelected = !isProductSelected
|
|
||||||
this.background = ContextCompat.getDrawable(context, if (isProductSelected) R.drawable.outline_selected else R.drawable.outline)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
productNameField!!.setOnClickListener {
|
|
||||||
Toast.makeText(activity, productNameField!!.text, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update() {
|
fun update() {
|
||||||
|
@ -117,10 +79,126 @@ class AbstractProductView: LinearLayout {
|
||||||
thumbnailsDir.mkdirs()
|
thumbnailsDir.mkdirs()
|
||||||
val imageUri = getImageUri(activity, File(thumbnailsDir, "${abstractProduct.imageHash}.webp"))
|
val imageUri = getImageUri(activity, File(thumbnailsDir, "${abstractProduct.imageHash}.webp"))
|
||||||
productPicture!!.setImageURI(imageUri)
|
productPicture!!.setImageURI(imageUri)
|
||||||
// productPicture!!.rotation = 90f
|
|
||||||
|
|
||||||
productNameField!!.text = abstractProduct.name
|
productNameField!!.text = abstractProduct.name
|
||||||
netWeightField!!.text = abstractProduct.netWeight.toString()
|
netWeightField!!.text = abstractProduct.netWeight.toString()
|
||||||
categoryField!!.text = categoryDAO.getCategoryNameById(abstractProduct.category)
|
categoryField!!.text = categoryDAO.getCategoryNameById(abstractProduct.category)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun setUpClicks() {
|
||||||
|
productLayout!!.setOnLongClickListener { onAnyLongClick() }
|
||||||
|
productNameField!!.setOnLongClickListener { onNameLongClick() }
|
||||||
|
productPicture!!.setOnLongClickListener { onImageLongClick() }
|
||||||
|
netWeightField!!.setOnLongClickListener { onAnyLongClick() }
|
||||||
|
categoryField!!.setOnLongClickListener { onAnyLongClick() }
|
||||||
|
unitField!!.setOnLongClickListener { onAnyLongClick() }
|
||||||
|
|
||||||
|
productLayout!!.setOnClickListener { onAnyClick() }
|
||||||
|
netWeightField!!.setOnClickListener { onAnyClick() }
|
||||||
|
categoryField!!.setOnClickListener { onAnyClick() }
|
||||||
|
unitField!!.setOnClickListener { onAnyClick() }
|
||||||
|
productPicture!!.setOnClickListener { onImageLongClick() }
|
||||||
|
productNameField!!.setOnClickListener { onNameLongClick() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onAnyClick(): Boolean {
|
||||||
|
if (activity !is MainActivity) return false
|
||||||
|
val mainActivity = activity as MainActivity
|
||||||
|
|
||||||
|
if (mainActivity.selectionMode) {
|
||||||
|
isProductSelected = !isProductSelected
|
||||||
|
|
||||||
|
if (isProductSelected) {
|
||||||
|
mainActivity.addSelection()
|
||||||
|
} else {
|
||||||
|
mainActivity.removeSelection()
|
||||||
|
}
|
||||||
|
activity.runOnUiThread {
|
||||||
|
this.background = ContextCompat.getDrawable(
|
||||||
|
context,
|
||||||
|
if (isProductSelected) R.drawable.outline_selected else R.drawable.outline
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onAnyLongClick(): Boolean {
|
||||||
|
if (activity !is MainActivity) return false
|
||||||
|
val mainActivity = activity as MainActivity
|
||||||
|
|
||||||
|
if (mainActivity.selectionMode) {
|
||||||
|
isProductSelected = !isProductSelected
|
||||||
|
|
||||||
|
if (isProductSelected) {
|
||||||
|
mainActivity.addSelection()
|
||||||
|
} else {
|
||||||
|
mainActivity.removeSelection()
|
||||||
|
}
|
||||||
|
activity.runOnUiThread {
|
||||||
|
this.background = ContextCompat.getDrawable(
|
||||||
|
context,
|
||||||
|
if (isProductSelected) R.drawable.outline_selected else R.drawable.outline
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
mainActivity.addSelection()
|
||||||
|
|
||||||
|
isProductSelected = !isProductSelected
|
||||||
|
activity.runOnUiThread {
|
||||||
|
|
||||||
|
this.background = ContextCompat.getDrawable(
|
||||||
|
context,
|
||||||
|
if (isProductSelected) R.drawable.outline_selected else R.drawable.outline
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onImageLongClick(): Boolean {
|
||||||
|
if (activity !is MainActivity) {
|
||||||
|
val fullscreenIntent = Intent(activity, FullscreenActivity::class.java)
|
||||||
|
val extras = Bundle()
|
||||||
|
extras.putString("imagehash", abstractProduct.imageHash)
|
||||||
|
fullscreenIntent.putExtras(extras)
|
||||||
|
startActivity(context, fullscreenIntent, extras)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
val mainActivity = activity as MainActivity
|
||||||
|
|
||||||
|
if (mainActivity.selectionMode) {
|
||||||
|
return onAnyLongClick()
|
||||||
|
} else {
|
||||||
|
val fullscreenIntent = Intent(activity, FullscreenActivity::class.java)
|
||||||
|
val extras = Bundle()
|
||||||
|
extras.putString("imagehash", abstractProduct.imageHash)
|
||||||
|
fullscreenIntent.putExtras(extras)
|
||||||
|
startActivity(context, fullscreenIntent, extras)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onNameLongClick(): Boolean {
|
||||||
|
if (activity !is MainActivity) {
|
||||||
|
activity.runOnUiThread {
|
||||||
|
Toast.makeText(activity, productNameField!!.text, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
val mainActivity = activity as MainActivity
|
||||||
|
|
||||||
|
if (mainActivity.selectionMode) {
|
||||||
|
return onAnyLongClick()
|
||||||
|
} else {
|
||||||
|
activity.runOnUiThread {
|
||||||
|
Toast.makeText(activity, productNameField!!.text, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,16 +7,16 @@ import android.view.LayoutInflater
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.R
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.activities.MainActivity
|
import org.foxarmy.barcodescannerforemployees.activities.MainActivity
|
||||||
import org.foxarmy.barcodescannerforemployees.database.AbstractProductDAO
|
import org.foxarmy.barcodescannerforemployees.database.AbstractProductDAO
|
||||||
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
||||||
import org.foxarmy.barcodescannerforemployees.dataclasses.Category
|
import org.foxarmy.barcodescannerforemployees.dataclasses.Category
|
||||||
|
import org.foxarmy.barcodescannerforemployees.getPreferences
|
||||||
|
|
||||||
class CategoryView : LinearLayout {
|
class CategoryView : LinearLayout {
|
||||||
var category: Category
|
var category: Category
|
||||||
|
|
||||||
val categoryName: TextView
|
val categoryName: TextView
|
||||||
val amountOfProducts: TextView
|
val amountOfProducts: TextView
|
||||||
var isCategorySelected = false
|
var isCategorySelected = false
|
||||||
|
@ -27,13 +27,7 @@ class CategoryView : LinearLayout {
|
||||||
constructor(activity: Activity, context: Context, category: Category) : super(context) {
|
constructor(activity: Activity, context: Context, category: Category) : super(context) {
|
||||||
this.category = category
|
this.category = category
|
||||||
|
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
sharedPreferences = getPreferences(context)
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
context,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "database")!!)
|
val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "database")!!)
|
||||||
abstractProductDAO = AbstractProductDAO(dbHelper)
|
abstractProductDAO = AbstractProductDAO(dbHelper)
|
||||||
|
@ -41,7 +35,7 @@ class CategoryView : LinearLayout {
|
||||||
val inflater: LayoutInflater = activity.layoutInflater
|
val inflater: LayoutInflater = activity.layoutInflater
|
||||||
inflater.inflate(R.layout.category_view, this)
|
inflater.inflate(R.layout.category_view, this)
|
||||||
|
|
||||||
this.background = ContextCompat.getDrawable(context, if (isCategorySelected) R.drawable.outline_selected else R.drawable.outline)
|
updateStroke()
|
||||||
|
|
||||||
categoryName = findViewById(R.id.categoryNameTextView)
|
categoryName = findViewById(R.id.categoryNameTextView)
|
||||||
amountOfProducts = findViewById(R.id.amountOfProducts)
|
amountOfProducts = findViewById(R.id.amountOfProducts)
|
||||||
|
@ -49,13 +43,47 @@ class CategoryView : LinearLayout {
|
||||||
categoryName.text = category.name
|
categoryName.text = category.name
|
||||||
amountOfProducts.text = abstractProductDAO.getAmountOfAbstractProductsInCategory(category.id).toString()
|
amountOfProducts.text = abstractProductDAO.getAmountOfAbstractProductsInCategory(category.id).toString()
|
||||||
|
|
||||||
setOnLongClickListener {
|
setUpClicks()
|
||||||
isCategorySelected = !isCategorySelected
|
}
|
||||||
this.background = ContextCompat.getDrawable(context, if (isCategorySelected) R.drawable.outline_selected else R.drawable.outline)
|
|
||||||
true
|
private fun setUpClicks() {
|
||||||
|
categoryName.setOnClickListener { onCategoryClick() }
|
||||||
|
amountOfProducts.setOnClickListener { onCategoryClick() }
|
||||||
|
|
||||||
|
categoryName.setOnLongClickListener { onAnyLongClick() }
|
||||||
|
amountOfProducts.setOnLongClickListener { onAnyLongClick() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onCategoryClick(): Boolean {
|
||||||
|
if (context !is MainActivity) return false
|
||||||
|
val mainActivity = context as MainActivity
|
||||||
|
|
||||||
|
if (mainActivity.selectionMode) return onAnyLongClick()
|
||||||
|
else (context as MainActivity).filterAbstractProductsByCategory(category.id)
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onAnyLongClick(): Boolean {
|
||||||
|
if (context !is MainActivity) return false
|
||||||
|
val mainActivity = context as MainActivity
|
||||||
|
|
||||||
|
isCategorySelected = !isCategorySelected
|
||||||
|
updateStroke()
|
||||||
|
|
||||||
|
if (mainActivity.selectionMode) {
|
||||||
|
if (isCategorySelected) mainActivity.addSelection()
|
||||||
|
else mainActivity.removeSelection()
|
||||||
|
} else {
|
||||||
|
mainActivity.addSelection()
|
||||||
}
|
}
|
||||||
setOnClickListener {
|
return true
|
||||||
(activity as MainActivity).filterAbstractProductsByCategory(category.id)
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateStroke() {
|
||||||
|
(context as Activity).runOnUiThread {
|
||||||
|
this.background = ContextCompat.getDrawable(context, if (isCategorySelected) R.drawable.outline_selected else R.drawable.outline)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,12 +7,11 @@ import android.view.LayoutInflater
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.R
|
import org.foxarmy.barcodescannerforemployees.R
|
||||||
import org.foxarmy.barcodescannerforemployees.activities.ExpiryCalendarActivity
|
import org.foxarmy.barcodescannerforemployees.activities.ExpiryCalendarActivity
|
||||||
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
||||||
import org.foxarmy.barcodescannerforemployees.database.ProductDAO
|
import org.foxarmy.barcodescannerforemployees.database.ProductDAO
|
||||||
|
import org.foxarmy.barcodescannerforemployees.getPreferences
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
|
|
||||||
class ExpiryGroupView : LinearLayout {
|
class ExpiryGroupView : LinearLayout {
|
||||||
|
@ -24,13 +23,7 @@ class ExpiryGroupView : LinearLayout {
|
||||||
|
|
||||||
constructor(activity: Activity, context: Context, representingDate: Long) : super(context) {
|
constructor(activity: Activity, context: Context, representingDate: Long) : super(context) {
|
||||||
|
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
sharedPreferences = getPreferences(context)
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
context,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "database")!!)
|
val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "database")!!)
|
||||||
productDAO = ProductDAO(dbHelper)
|
productDAO = ProductDAO(dbHelper)
|
||||||
|
|
|
@ -10,7 +10,7 @@ import org.foxarmy.barcodescannerforemployees.R
|
||||||
class GroupMemberView : LinearLayout {
|
class GroupMemberView : LinearLayout {
|
||||||
|
|
||||||
private var username: String
|
private var username: String
|
||||||
private var userId: Int
|
var userId: Int
|
||||||
|
|
||||||
constructor(activity: Activity, context: Context, username: String, userId: Int) : super(context) {
|
constructor(activity: Activity, context: Context, username: String, userId: Int) : super(context) {
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import android.view.LayoutInflater
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
@ -21,29 +22,26 @@ import androidx.core.graphics.blue
|
||||||
import androidx.core.graphics.green
|
import androidx.core.graphics.green
|
||||||
import androidx.core.graphics.red
|
import androidx.core.graphics.red
|
||||||
import androidx.core.math.MathUtils.clamp
|
import androidx.core.math.MathUtils.clamp
|
||||||
import androidx.security.crypto.EncryptedSharedPreferences
|
import org.foxarmy.barcodescannerforemployees.*
|
||||||
import androidx.security.crypto.MasterKeys
|
|
||||||
import org.foxarmy.barcodescannerforemployees.R
|
|
||||||
import org.foxarmy.barcodescannerforemployees.activities.FullscreenActivity
|
import org.foxarmy.barcodescannerforemployees.activities.FullscreenActivity
|
||||||
import org.foxarmy.barcodescannerforemployees.calculateProductFreshness
|
import org.foxarmy.barcodescannerforemployees.activities.MainActivity
|
||||||
import org.foxarmy.barcodescannerforemployees.database.AbstractProductDAO
|
import org.foxarmy.barcodescannerforemployees.database.AbstractProductDAO
|
||||||
import org.foxarmy.barcodescannerforemployees.database.CategoryDAO
|
import org.foxarmy.barcodescannerforemployees.database.CategoryDAO
|
||||||
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
import org.foxarmy.barcodescannerforemployees.database.DBStorageController
|
||||||
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct
|
||||||
import org.foxarmy.barcodescannerforemployees.dataclasses.Product
|
import org.foxarmy.barcodescannerforemployees.dataclasses.Product
|
||||||
import org.foxarmy.barcodescannerforemployees.getActivity
|
|
||||||
import org.foxarmy.barcodescannerforemployees.getImageUri
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
class ProductView: LinearLayout {
|
class ProductView : LinearLayout {
|
||||||
var product: Product = Product()
|
var product: Product = Product()
|
||||||
var isProductSelected = false
|
var isProductSelected = false
|
||||||
private var activity: Activity
|
private var activity: Activity
|
||||||
|
|
||||||
|
private lateinit var productLayout: ConstraintLayout
|
||||||
private lateinit var productImageView: ImageView
|
private lateinit var productImageView: ImageView
|
||||||
private lateinit var productNameTextView: TextView
|
private lateinit var productNameTextView: TextView
|
||||||
private lateinit var productNetWeightTextView: TextView
|
private lateinit var productNetWeightTextView: TextView
|
||||||
|
@ -63,13 +61,7 @@ class ProductView: LinearLayout {
|
||||||
constructor(context: Context, a: AttributeSet) : super(context, a) {
|
constructor(context: Context, a: AttributeSet) : super(context, a) {
|
||||||
activity = getActivity(context)!!
|
activity = getActivity(context)!!
|
||||||
|
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
sharedPreferences = getPreferences(context)
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
context,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "offline")!!)
|
val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "offline")!!)
|
||||||
abstractProductDAO = AbstractProductDAO(dbHelper)
|
abstractProductDAO = AbstractProductDAO(dbHelper)
|
||||||
|
@ -86,18 +78,13 @@ class ProductView: LinearLayout {
|
||||||
val inflater: LayoutInflater = activity.layoutInflater
|
val inflater: LayoutInflater = activity.layoutInflater
|
||||||
inflater.inflate(R.layout.product_view, this)
|
inflater.inflate(R.layout.product_view, this)
|
||||||
|
|
||||||
sharedPreferences = EncryptedSharedPreferences.create(
|
sharedPreferences = getPreferences(context)
|
||||||
"sensitive",
|
|
||||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
|
||||||
context,
|
|
||||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
|
||||||
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
|
|
||||||
)
|
|
||||||
|
|
||||||
val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "offline")!!)
|
val dbHelper = DBStorageController(context, sharedPreferences.getString("currentGroup", "offline")!!)
|
||||||
abstractProductDAO = AbstractProductDAO(dbHelper)
|
abstractProductDAO = AbstractProductDAO(dbHelper)
|
||||||
categoryDAO = CategoryDAO(dbHelper)
|
categoryDAO = CategoryDAO(dbHelper)
|
||||||
|
|
||||||
|
productLayout = findViewById(R.id.productLayout)
|
||||||
productImageView = findViewById(R.id.productPicture)
|
productImageView = findViewById(R.id.productPicture)
|
||||||
productNameTextView = findViewById(R.id.productNameView)
|
productNameTextView = findViewById(R.id.productNameView)
|
||||||
productNetWeightTextView = findViewById(R.id.productNetWeightView)
|
productNetWeightTextView = findViewById(R.id.productNetWeightView)
|
||||||
|
@ -106,68 +93,152 @@ class ProductView: LinearLayout {
|
||||||
productLifeSpan = findViewById(R.id.dateSpan)
|
productLifeSpan = findViewById(R.id.dateSpan)
|
||||||
productFreshnessTextView = findViewById(R.id.freshnessPercentTextView)
|
productFreshnessTextView = findViewById(R.id.freshnessPercentTextView)
|
||||||
|
|
||||||
findViewById<ConstraintLayout>(R.id.productLayout).setOnLongClickListener {
|
setUpClicks()
|
||||||
isProductSelected = !isProductSelected
|
|
||||||
updateStroke()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
productImageView.setOnClickListener {
|
|
||||||
val fullscreenIntent = Intent(activity, FullscreenActivity::class.java)
|
|
||||||
val extras = Bundle()
|
|
||||||
val abstractProduct = abstractProductDAO.findAbstractProductById(product.abstractProductId)
|
|
||||||
extras.putString("imagehash", abstractProduct!!.imageHash)
|
|
||||||
fullscreenIntent.putExtras(extras)
|
|
||||||
startActivity(context, fullscreenIntent, extras)
|
|
||||||
}
|
|
||||||
|
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
fun update () {
|
private fun setUpClicks() {
|
||||||
val linkedAbstractProduct: AbstractProduct = abstractProductDAO.findAbstractProductById(product.abstractProductId) ?: return
|
productLayout.setOnLongClickListener { onAnyLongClick() }
|
||||||
|
productImageView.setOnLongClickListener { onImageLongClick() }
|
||||||
|
productNameTextView.setOnLongClickListener { onNameLongClick() }
|
||||||
|
productNetWeightTextView.setOnLongClickListener { onAnyLongClick() }
|
||||||
|
productAmountTextView.setOnLongClickListener { onAnyLongClick() }
|
||||||
|
productCategoryView.setOnLongClickListener { onAnyLongClick() }
|
||||||
|
productLifeSpan.setOnLongClickListener { onAnyLongClick() }
|
||||||
|
productFreshnessTextView.setOnLongClickListener { onAnyLongClick() }
|
||||||
|
|
||||||
|
productLayout.setOnClickListener { onAnyClick() }
|
||||||
|
productImageView.setOnClickListener { onImageLongClick() }
|
||||||
|
productNameTextView.setOnClickListener { onNameLongClick() }
|
||||||
|
productNetWeightTextView.setOnClickListener { onAnyClick() }
|
||||||
|
productAmountTextView.setOnClickListener { onAnyClick() }
|
||||||
|
productCategoryView.setOnClickListener { onAnyClick() }
|
||||||
|
productLifeSpan.setOnClickListener { onAnyClick() }
|
||||||
|
productFreshnessTextView.setOnClickListener { onAnyClick() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
private fun onAnyClick(): Boolean {
|
||||||
|
if (activity !is MainActivity) return false
|
||||||
|
val mainActivity = activity as MainActivity
|
||||||
|
|
||||||
|
if (mainActivity.selectionMode) {
|
||||||
|
isProductSelected = !isProductSelected
|
||||||
|
|
||||||
|
if (isProductSelected) mainActivity.addSelection()
|
||||||
|
else mainActivity.removeSelection()
|
||||||
|
|
||||||
|
updateStroke()
|
||||||
|
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
private fun onAnyLongClick(): Boolean {
|
||||||
|
if (activity !is MainActivity) return false
|
||||||
|
val mainActivity = activity as MainActivity
|
||||||
|
|
||||||
|
isProductSelected = !isProductSelected
|
||||||
|
updateStroke()
|
||||||
|
|
||||||
|
if (mainActivity.selectionMode) {
|
||||||
|
if (isProductSelected) mainActivity.addSelection()
|
||||||
|
else mainActivity.removeSelection()
|
||||||
|
} else {
|
||||||
|
mainActivity.addSelection()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onNameLongClick(): Boolean {
|
||||||
|
if (activity !is MainActivity) {
|
||||||
|
Toast.makeText(activity, productNameTextView.text, Toast.LENGTH_SHORT).show()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
val mainActivity = activity as MainActivity
|
||||||
|
|
||||||
|
if (mainActivity.selectionMode) return onAnyLongClick()
|
||||||
|
else Toast.makeText(activity, productNameTextView.text, Toast.LENGTH_SHORT).show()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onImageLongClick(): Boolean {
|
||||||
|
val abstractProduct = abstractProductDAO.findAbstractProductById(product.abstractProductId)
|
||||||
|
|
||||||
|
if (activity !is MainActivity) {
|
||||||
|
val fullscreenIntent = Intent(activity, FullscreenActivity::class.java)
|
||||||
|
val extras = Bundle()
|
||||||
|
extras.putString("imagehash", abstractProduct!!.imageHash)
|
||||||
|
fullscreenIntent.putExtras(extras)
|
||||||
|
startActivity(context, fullscreenIntent, extras)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
val mainActivity = activity as MainActivity
|
||||||
|
|
||||||
|
if (mainActivity.selectionMode) {
|
||||||
|
return onAnyLongClick()
|
||||||
|
} else {
|
||||||
|
val fullscreenIntent = Intent(activity, FullscreenActivity::class.java)
|
||||||
|
val extras = Bundle()
|
||||||
|
extras.putString("imagehash", abstractProduct!!.imageHash)
|
||||||
|
fullscreenIntent.putExtras(extras)
|
||||||
|
startActivity(context, fullscreenIntent, extras)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
fun update() {
|
||||||
|
val linkedAbstractProduct: AbstractProduct =
|
||||||
|
abstractProductDAO.findAbstractProductById(product.abstractProductId) ?: return
|
||||||
|
|
||||||
val thumbnailsDir = File(activity.cacheDir, "thumbnails")
|
val thumbnailsDir = File(activity.cacheDir, "thumbnails")
|
||||||
thumbnailsDir.mkdirs()
|
thumbnailsDir.mkdirs()
|
||||||
val pictureFile = File(thumbnailsDir, "${linkedAbstractProduct.imageHash}.webp")
|
val pictureFile = File(thumbnailsDir, "${linkedAbstractProduct.imageHash}.webp")
|
||||||
val imageUri = getImageUri(activity, pictureFile)
|
val imageUri = getImageUri(activity, pictureFile)
|
||||||
productImageView.setImageURI(imageUri)
|
productImageView.setImageURI(imageUri)
|
||||||
// productImageView.rotation = 90f
|
|
||||||
|
|
||||||
productNameTextView.text = linkedAbstractProduct.name
|
productNameTextView.text = linkedAbstractProduct.name
|
||||||
productNetWeightTextView.text = linkedAbstractProduct.netWeight.toString()
|
productNetWeightTextView.text = linkedAbstractProduct.netWeight.toString()
|
||||||
productAmountTextView.text = product.amount.toString()
|
productAmountTextView.text = product.amount.toString()
|
||||||
productCategoryView.text = categoryDAO.getCategoryNameById(linkedAbstractProduct.category)
|
productCategoryView.text = categoryDAO.getCategoryNameById(linkedAbstractProduct.category)
|
||||||
productLifeSpan.text = "${SimpleDateFormat("dd.MM.yyyy").format(Date(product.dateOfProduction*1000))}-${SimpleDateFormat("dd.MM.yyyy").format(Date(product.dateOfExpiry*1000))}"
|
productLifeSpan.text = "${SimpleDateFormat("dd.MM.yyyy").format(Date(product.dateOfProduction * 1000))}-${
|
||||||
|
SimpleDateFormat("dd.MM.yyyy").format(Date(product.dateOfExpiry * 1000))
|
||||||
|
}"
|
||||||
productFreshnessTextView.text =
|
productFreshnessTextView.text =
|
||||||
if (product.freshness == Double.NEGATIVE_INFINITY || product.freshness == Double.POSITIVE_INFINITY || product.freshness < 0) {
|
if (product.freshness == Double.NEGATIVE_INFINITY || product.freshness == Double.POSITIVE_INFINITY || product.freshness < 0) {
|
||||||
context.getString(R.string.expired)
|
context.getString(R.string.expired)
|
||||||
} else {
|
} else {
|
||||||
"${DecimalFormat("#.#").format(product.freshness*100)}%"
|
"${DecimalFormat("#.#").format(product.freshness * 100)}%"
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStroke()
|
updateStroke()
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
fun updateStroke() {
|
fun updateStroke() {
|
||||||
if (isProductSelected) {
|
activity.runOnUiThread {
|
||||||
this.background = ContextCompat.getDrawable(context, R.drawable.outline_selected)
|
if (isProductSelected) {
|
||||||
} else {
|
this.background = ContextCompat.getDrawable(context, R.drawable.outline_selected)
|
||||||
if (product.id != 0) {
|
} else {
|
||||||
thread {
|
if (product.id != 0) {
|
||||||
this.outline = GradientDrawable()
|
this.outline = GradientDrawable()
|
||||||
backgroundColor = evaluateColor()
|
backgroundColor = evaluateColor()
|
||||||
strokeColor = darkenColor(backgroundColor, 0.25) // (backgroundColor and 0xfefefe ) shr 1
|
strokeColor = darkenColor(backgroundColor, 0.25) // (backgroundColor and 0xfefefe ) shr 1
|
||||||
this.outline.setColor(backgroundColor)
|
this.outline.setColor(backgroundColor)
|
||||||
this.outline.setStroke(4, strokeColor)
|
this.outline.setStroke(4, strokeColor)
|
||||||
this.outline.alpha = 84
|
this.outline.alpha = 84
|
||||||
this.background = outline
|
this.background = outline
|
||||||
}
|
} else {
|
||||||
} else {
|
this.background = ContextCompat.getDrawable(context, R.drawable.outline)
|
||||||
this.background = ContextCompat.getDrawable(context, R.drawable.outline)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,13 +249,15 @@ class ProductView: LinearLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculateFreshnessGradient(percentage: Double): Int {
|
fun calculateFreshnessGradient(percentage: Double): Int {
|
||||||
val startColor = ContextCompat.getColor(context, if (percentage > 0.5) R.color.full_freshness else R.color.half_freshness)
|
val startColor =
|
||||||
val endColor = ContextCompat.getColor(context, if (percentage > 0.5) R.color.half_freshness else R.color.expired_freshness)
|
ContextCompat.getColor(context, if (percentage > 0.5) R.color.full_freshness else R.color.half_freshness)
|
||||||
|
val endColor =
|
||||||
|
ContextCompat.getColor(context, if (percentage > 0.5) R.color.half_freshness else R.color.expired_freshness)
|
||||||
|
|
||||||
val gradientPosition = 1 - if (percentage > 0.5) (percentage - 0.5) * 2 else percentage * 2
|
val gradientPosition = 1 - if (percentage > 0.5) (percentage - 0.5) * 2 else percentage * 2
|
||||||
|
|
||||||
val red = clamp((startColor.red + gradientPosition * (endColor.red - startColor.red )).toInt(), 0, 255)
|
val red = clamp((startColor.red + gradientPosition * (endColor.red - startColor.red)).toInt(), 0, 255)
|
||||||
val green = clamp((startColor.green + gradientPosition * (endColor.green - startColor.green)).toInt(), 0, 255)
|
val green = clamp((startColor.green + gradientPosition * (endColor.green - startColor.green)).toInt(), 0, 255)
|
||||||
val blue = clamp((startColor.blue + gradientPosition * (endColor.blue - startColor.blue)).toInt(), 0, 255)
|
val blue = clamp((startColor.blue + gradientPosition * (endColor.blue - startColor.blue)).toInt(), 0, 255)
|
||||||
|
|
||||||
var redHex = Integer.toHexString(red)
|
var redHex = Integer.toHexString(red)
|
||||||
|
@ -194,7 +267,7 @@ class ProductView: LinearLayout {
|
||||||
if (greenHex.length == 1) greenHex = "0$greenHex"
|
if (greenHex.length == 1) greenHex = "0$greenHex"
|
||||||
|
|
||||||
var blueHex = Integer.toHexString(blue)
|
var blueHex = Integer.toHexString(blue)
|
||||||
if (blueHex.length == 1 ) blueHex = "0$blueHex"
|
if (blueHex.length == 1) blueHex = "0$blueHex"
|
||||||
|
|
||||||
|
|
||||||
val colorString = "#$redHex$greenHex$blueHex"
|
val colorString = "#$redHex$greenHex$blueHex"
|
||||||
|
@ -202,7 +275,7 @@ class ProductView: LinearLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
fun darkenColor(color: Int, darkPercent: Double) : Int {
|
fun darkenColor(color: Int, darkPercent: Double): Int {
|
||||||
val c = Color.valueOf(color)
|
val c = Color.valueOf(color)
|
||||||
|
|
||||||
val red = c.red() * (1 - darkPercent)
|
val red = c.red() * (1 - darkPercent)
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" android:id="@+id/productLayout" android:outlineProvider="bounds"
|
android:layout_height="match_parent" android:id="@+id/productLayout" android:outlineProvider="bounds"
|
||||||
android:background="#00FFFEFE" android:clickable="true">
|
android:background="#00FFFEFE" android:clickable="true" android:translationZ="0sp">
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="200dp" app:srcCompat="@android:drawable/ic_menu_gallery"
|
android:layout_height="200dp" app:srcCompat="@android:drawable/ic_menu_gallery"
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:app="http://schemas.android.com/apk/res-auto" 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"
|
|
||||||
tools:context=".fragments.ShelfFragment"
|
|
||||||
android:id="@+id/content">
|
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:layout_height="0dp"
|
||||||
|
tools:context=".fragments.ShelfFragment"
|
||||||
|
android:id="@+id/content" android:layout_width="0dp" app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
|
@ -39,12 +39,13 @@
|
||||||
<androidx.viewpager.widget.ViewPager
|
<androidx.viewpager.widget.ViewPager
|
||||||
android:id="@+id/tab_viewpager"
|
android:id="@+id/tab_viewpager"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="777dp"
|
android:layout_height="0dp"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" android:layout_gravity="bottom"
|
app:layout_behavior="@string/appbar_scrolling_view_behavior" android:layout_gravity="bottom"
|
||||||
android:layout_marginTop="2dp"
|
android:layout_marginTop="2dp"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/appBarLayout"
|
app:layout_constraintTop_toBottomOf="@+id/appBarLayout"
|
||||||
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="6dp"
|
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="6dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="6dp"/>
|
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="6dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:id="@+id/new_element_fab"
|
android:id="@+id/new_element_fab"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" android:id="@+id/storageLayout">
|
|
||||||
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/nav_host_fragment_content_storage"
|
|
||||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:defaultNavHost="true"
|
|
||||||
app:navGraph="@navigation/nav_graph_main"/>
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
|
@ -26,7 +26,8 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" app:layout_constraintTop_toBottomOf="@+id/spinner"
|
android:layout_height="match_parent" app:layout_constraintTop_toBottomOf="@+id/spinner"
|
||||||
android:layout_marginTop="32dp" app:layout_constraintStart_toStartOf="parent"
|
android:layout_marginTop="32dp" app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent" android:id="@+id/scrollView">
|
app:layout_constraintEnd_toEndOf="parent" android:id="@+id/scrollView"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent">
|
||||||
<androidx.gridlayout.widget.GridLayout
|
<androidx.gridlayout.widget.GridLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" android:id="@+id/contentGridLayout" app:columnCount="2"
|
android:layout_height="wrap_content" android:id="@+id/contentGridLayout" app:columnCount="2"
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout 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"
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:id="@+id/fragment_storage"
|
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
tools:context=".fragments.StorageFragment">
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:text="@string/sort_by"
|
android:text="@string/sort_by"
|
||||||
|
@ -16,7 +12,7 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/scrollView2"/>
|
app:layout_constraintBottom_toTopOf="@+id/scrollView2"/>
|
||||||
<Spinner
|
<Spinner
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="32dp" android:id="@+id/spinner"
|
android:layout_height="32dp" android:id="@+id/spinner"
|
||||||
|
@ -34,15 +30,16 @@
|
||||||
android:layout_marginEnd="10dp" app:layout_constraintTop_toTopOf="parent"/>
|
android:layout_marginEnd="10dp" app:layout_constraintTop_toTopOf="parent"/>
|
||||||
<ScrollView
|
<ScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="0dp"
|
||||||
android:id="@+id/scrollView2"
|
android:id="@+id/scrollView2"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/dropFiltersButton">
|
app:layout_constraintTop_toBottomOf="@+id/dropFiltersButton"
|
||||||
|
android:layout_marginTop="4dp" app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
<androidx.gridlayout.widget.GridLayout
|
<androidx.gridlayout.widget.GridLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" android:id="@+id/contentGridLayout" app:columnCount="2"
|
android:layout_height="match_parent" android:id="@+id/contentGridLayout" app:columnCount="2"
|
||||||
app:rowCount="100" android:nestedScrollingEnabled="true">
|
app:rowCount="100" android:nestedScrollingEnabled="true">
|
||||||
|
|
||||||
</androidx.gridlayout.widget.GridLayout>
|
</androidx.gridlayout.widget.GridLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</FrameLayout>
|
|
|
@ -12,4 +12,5 @@
|
||||||
<item
|
<item
|
||||||
android:id="@+id/nav_settings"
|
android:id="@+id/nav_settings"
|
||||||
android:title="@string/settings"/>
|
android:title="@string/settings"/>
|
||||||
|
<item android:title="@string/logout" android:id="@+id/nav_logout"/>
|
||||||
</menu>
|
</menu>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item android:title="@string/kick" android:id="@+id/kick"/>
|
||||||
|
<item android:title="@string/transfer_ownership" android:id="@+id/transfer_ownership"/>
|
||||||
|
</menu>
|
|
@ -118,6 +118,14 @@
|
||||||
<string name="ok">Ок</string>
|
<string name="ok">Ок</string>
|
||||||
<string name="logout">Выйти</string>
|
<string name="logout">Выйти</string>
|
||||||
<string name="online_only_feature">Эта возможность доступна только с онлайн аккаунтом</string>
|
<string name="online_only_feature">Эта возможность доступна только с онлайн аккаунтом</string>
|
||||||
|
<string name="username_changed">Имя пользователя изменено. Пожалуйста, перезайдите</string>
|
||||||
|
<string name="password_changed">Пароль изменён. Пожалуйста, перезайдите</string>
|
||||||
|
<string name="new_group_name">Введите новое имя группы</string>
|
||||||
|
<string name="kick">Выгнать</string>
|
||||||
|
<string name="transfer_ownership">Передать владение группой</string>
|
||||||
|
<string name="transfer_ownership_confirmation">Вы увереных, что хотите передать владение группой этому пользователю?</string>
|
||||||
|
<string name="loading_please_wait">Загрузка, пожалуйста ждите</string>
|
||||||
|
<string name="loading">Загрузка</string>
|
||||||
<string-array name="languages">
|
<string-array name="languages">
|
||||||
<item>en-US</item>
|
<item>en-US</item>
|
||||||
<item>ru-RU</item>
|
<item>ru-RU</item>
|
||||||
|
|
|
@ -116,6 +116,14 @@
|
||||||
<string name="ok">OK</string>
|
<string name="ok">OK</string>
|
||||||
<string name="logout">Log out</string>
|
<string name="logout">Log out</string>
|
||||||
<string name="online_only_feature">This feature is online only</string>
|
<string name="online_only_feature">This feature is online only</string>
|
||||||
|
<string name="username_changed">Your username has been changed. Please, relogin</string>
|
||||||
|
<string name="password_changed">You password was changed. Please, relogin</string>
|
||||||
|
<string name="new_group_name">Enter new group name</string>
|
||||||
|
<string name="kick">Kick</string>
|
||||||
|
<string name="transfer_ownership">Transfer ownership</string>
|
||||||
|
<string name="transfer_ownership_confirmation">Are you sure you want to transfer ownership on current group to that user?</string>
|
||||||
|
<string name="loading_please_wait">Loading, please wait</string>
|
||||||
|
<string name="loading">Loading</string>
|
||||||
<string-array name="languages">
|
<string-array name="languages">
|
||||||
<item>en-US</item>
|
<item>en-US</item>
|
||||||
<item>ru-RU</item>
|
<item>ru-RU</item>
|
||||||
|
|
Loading…
Reference in New Issue