From 2feb2c1b5e5c659cf60654081449232543a6c83e Mon Sep 17 00:00:00 2001 From: leca Date: Thu, 31 Oct 2024 04:03:33 +0300 Subject: [PATCH] working on user settings --- .../foxarmy/barcodescannerforemployees/Net.kt | 49 +++++- .../activities/AccountSettingsActivity.kt | 44 +++++ .../activities/AddAbstractProductActivity.kt | 5 +- .../activities/LoginActivity.kt | 6 +- .../activities/MainActivity.kt | 157 +++++++++++------- .../activities/NavigatorActivity.kt | 2 +- .../res/layout/activity_account_settings.xml | 35 ++++ app/src/main/res/layout/activity_main.xml | 4 +- app/src/main/res/menu/drawer_menu.xml | 9 +- app/src/main/res/values-ru/strings.xml | 4 + app/src/main/res/values/strings.xml | 4 + 11 files changed, 246 insertions(+), 73 deletions(-) create mode 100644 app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AccountSettingsActivity.kt create mode 100644 app/src/main/res/layout/activity_account_settings.xml diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/Net.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/Net.kt index b14b377..ac1edc8 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/Net.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/Net.kt @@ -1,6 +1,5 @@ package org.foxarmy.barcodescannerforemployees -import android.util.Log import okhttp3.* import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaTypeOrNull @@ -124,4 +123,52 @@ class Net { return responseText } + + fun changeUsername(server: String, token: String, newUsername: String): String { + + lateinit var response: Response + + thread { + val client = OkHttpClient() + + val body = FormBody.Builder() + body.add("username", newUsername) + + val requestBody = body.build() + + val request = Request.Builder().url("https://$server/api/user/changeUsername") + .post(requestBody) + .addHeader("Authorization", "Bearer $token") + .build() + response = client.newCall(request).execute() + }.join() + + val responseText = response.body!!.string() + + return responseText + } + + fun changePassword(server: String, token: String, newPassword: String): String { + + lateinit var response: Response + + thread { + val client = OkHttpClient() + + val body = FormBody.Builder() + body.add("password", newPassword) + + val requestBody = body.build() + + val request = Request.Builder().url("https://$server/api/user/changePassword") + .post(requestBody) + .addHeader("Authorization", "Bearer $token") + .build() + response = client.newCall(request).execute() + }.join() + + val responseText = response.body!!.string() + + return responseText + } } \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AccountSettingsActivity.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AccountSettingsActivity.kt new file mode 100644 index 0000000..1e26791 --- /dev/null +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AccountSettingsActivity.kt @@ -0,0 +1,44 @@ +package org.foxarmy.barcodescannerforemployees.activities + +import android.os.Bundle +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import androidx.security.crypto.EncryptedSharedPreferences +import androidx.security.crypto.MasterKeys +import org.foxarmy.barcodescannerforemployees.Net +import org.foxarmy.barcodescannerforemployees.databinding.ActivityAccountSettingsBinding + +class AccountSettingsActivity : AppCompatActivity() { + + private lateinit var binding: ActivityAccountSettingsBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + binding = ActivityAccountSettingsBinding.inflate(layoutInflater) + + setContentView(binding.root) + + val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC) + + val sharedPreferences = EncryptedSharedPreferences.create( + "sensitive", + masterKeyAlias, + applicationContext, + EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, + EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM + ) + + val server = sharedPreferences.getString("server", "bsfe.foxarmy.org") + val token = sharedPreferences.getString("token", "") + val net = Net() + + binding.saveUsernameButton.setOnClickListener { + Toast.makeText(this, net.changeUsername(server!!, token!!, binding.newUsernameTextEdit.text.toString()), Toast.LENGTH_LONG).show() + } + + binding.savePasswordButton.setOnClickListener { + Toast.makeText(this, net.changePassword(server!!, token!!, binding.newPasswordTextEdit.text.toString()), Toast.LENGTH_LONG).show() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt index 28924b9..4ae19f0 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/AddAbstractProductActivity.kt @@ -19,14 +19,12 @@ import androidx.security.crypto.MasterKeys import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanIntentResult import com.journeyapps.barcodescanner.ScanOptions -import okhttp3.internal.http.hasBody import org.foxarmy.barcodescannerforemployees.* import org.foxarmy.barcodescannerforemployees.dataclasses.AbstractProduct import java.io.File import java.nio.file.Files import java.nio.file.StandardCopyOption import kotlin.concurrent.thread -import kotlin.math.abs class AddAbstractProductActivity : AppCompatActivity() { private lateinit var imageView: ImageView @@ -157,7 +155,6 @@ class AddAbstractProductActivity : AppCompatActivity() { val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC) val sharedPreferences = EncryptedSharedPreferences.create( - // passing a file name to share a preferences "sensitive", masterKeyAlias, applicationContext, @@ -166,6 +163,8 @@ class AddAbstractProductActivity : AppCompatActivity() { ) val token = sharedPreferences.getString("token", "") val response = n.uploadAbstractProduct("bsfe.foxarmy.org", 1, abstractProduct, File(pictureFile.absolutePath), token!!); + + Toast.makeText(this, response, Toast.LENGTH_LONG).show() } finish() diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/LoginActivity.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/LoginActivity.kt index 37f9d43..609da8a 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/LoginActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/LoginActivity.kt @@ -23,7 +23,6 @@ class LoginActivity : AppCompatActivity() { val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC) val sharedPreferences = EncryptedSharedPreferences.create( - // passing a file name to share a preferences "sensitive", masterKeyAlias, applicationContext, @@ -39,7 +38,7 @@ class LoginActivity : AppCompatActivity() { val n = Net() val response = n.login(server, username, password) - + //TODO: handle it properly when server will support Accept-Language header if (response == "Wrong password") { Toast.makeText(this, getString(R.string.wrong_password), Toast.LENGTH_SHORT).show() } else { @@ -58,11 +57,12 @@ class LoginActivity : AppCompatActivity() { val n = Net() val response = n.registerAccount(server, username, password); - + //TODO: handle it properly when server will support Accept-Language header if (response == "Such username exists") { Toast.makeText(this, getString(R.string.username_already_exists), Toast.LENGTH_SHORT).show(); } else { sharedPreferences.edit().putString("token", response).apply() + sharedPreferences.edit().putString("server", server).apply() val intent = Intent(this, MainActivity::class.java) startActivity(intent) finish() diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/MainActivity.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/MainActivity.kt index 0f47b05..199751b 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/MainActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/MainActivity.kt @@ -1,14 +1,18 @@ package org.foxarmy.barcodescannerforemployees.activities +//import android.R import android.content.DialogInterface import android.content.Intent import android.os.Bundle import android.view.Menu import android.view.MenuItem +import androidx.appcompat.app.ActionBarDrawerToggle import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat +import androidx.drawerlayout.widget.DrawerLayout import androidx.viewpager.widget.ViewPager +import com.google.android.material.navigation.NavigationView import org.foxarmy.barcodescannerforemployees.R import org.foxarmy.barcodescannerforemployees.ViewPagerAdapter import org.foxarmy.barcodescannerforemployees.databinding.ActivityMainBinding @@ -17,10 +21,13 @@ import org.foxarmy.barcodescannerforemployees.fragments.CategoriesFragment import org.foxarmy.barcodescannerforemployees.fragments.ShelfFragment import org.foxarmy.barcodescannerforemployees.fragments.StorageFragment -class MainActivity : AppCompatActivity() { + +class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener { private lateinit var binding: ActivityMainBinding lateinit var adapter: ViewPagerAdapter + var drawerLayout: DrawerLayout? = null + var actionBarDrawerToggle: ActionBarDrawerToggle? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -32,6 +39,16 @@ class MainActivity : AppCompatActivity() { setupViewPager(binding.tabViewpager) binding.tabTablayout.setupWithViewPager(binding.tabViewpager) + drawerLayout = binding.drawerLayout + actionBarDrawerToggle = ActionBarDrawerToggle(this, drawerLayout, R.string.nav_open, R.string.nav_close) + + drawerLayout!!.addDrawerListener(actionBarDrawerToggle!!) + actionBarDrawerToggle!!.syncState() + binding.navView.setNavigationItemSelectedListener(this) + + // to make the Navigation drawer icon always appear on the action bar + supportActionBar!!.setDisplayHomeAsUpEnabled(true) + binding.expiryCalendarFab.setOnClickListener { _ -> val expiryCalendarIntent = Intent(this, ExpiryCalendarActivity::class.java) val extras = Bundle() @@ -82,7 +99,7 @@ class MainActivity : AppCompatActivity() { adapter.addFragment(ShelfFragment(), getString(R.string.shelf_title)) adapter.addFragment(CategoriesFragment(), getString(R.string.categories_title)) - //TODO: settings fragments + //TODO: Settings // setting adapter to view pager. viewpager.adapter = adapter @@ -90,76 +107,100 @@ class MainActivity : AppCompatActivity() { override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.menu_main, menu) + + return true + } + + override fun onNavigationItemSelected(item: MenuItem): Boolean { + lateinit var intent: Intent + when (item.itemId) { + R.id.nav_account -> { + intent = Intent(this, AccountSettingsActivity::class.java) + } + R.id.nav_groups -> { + intent = Intent(this, AccountSettingsActivity::class.java) + } + R.id.nav_settings -> { + //TODO: Settings + return false + } + } + startActivity(intent) + return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { - val currentPosition = binding.tabTablayout.selectedTabPosition - val fragment = adapter.getItem(currentPosition) + if (actionBarDrawerToggle!!.onOptionsItemSelected(item)) { + return true + } else { - return when (item.itemId) { + val currentPosition = binding.tabTablayout.selectedTabPosition + val fragment = adapter.getItem(currentPosition) - - R.id.action_settings -> { - true - } - - R.id.action_delete -> { - - when (fragment::class.simpleName.toString()) { - "StorageFragment" -> { - AlertDialog.Builder(this) - .setMessage(getString(R.string.deleting_abstract_product_warning)) - .setPositiveButton(getString(R.string.yes)) { _: DialogInterface, _: Int -> - val storageFragment = fragment as StorageFragment - storageFragment.removeSelected() - } - .setNegativeButton(getString(R.string.no)) { _: DialogInterface, _: Int -> - - }.show() - } - - "CategoriesFragment" -> { - AlertDialog.Builder(this) - .setMessage(getString(R.string.deleting_category_warning)) - .setPositiveButton(getString(R.string.yes)) { _: DialogInterface, _: Int -> - val categoriesFragment = fragment as CategoriesFragment - categoriesFragment.removeSelected() - } - .setNegativeButton(getString(R.string.no)) { _: DialogInterface, _: Int -> - - }.show() - } - "ShelfFragment" -> { - val shelfFragment = fragment as ShelfFragment - shelfFragment.removeSelected() - } + return when (item.itemId) { + R.id.action_settings -> { + true } - true - } - R.id.action_update -> { - when (fragment::class.simpleName.toString()) { - "StorageFragment" -> { - val storageFragment = fragment as StorageFragment - storageFragment.updateSelected() - } + R.id.action_delete -> { - "CategoriesFragment" -> { - val categoriesFragment = fragment as CategoriesFragment - categoriesFragment.updateSelected() - } + when (fragment::class.simpleName.toString()) { + "StorageFragment" -> { + AlertDialog.Builder(this) + .setMessage(getString(R.string.deleting_abstract_product_warning)) + .setPositiveButton(getString(R.string.yes)) { _: DialogInterface, _: Int -> + val storageFragment = fragment as StorageFragment + storageFragment.removeSelected() + } + .setNegativeButton(getString(R.string.no)) { _: DialogInterface, _: Int -> - "ShelfFragment" -> { - val shelfFragment = fragment as ShelfFragment - shelfFragment.updateSelected() + }.show() + } + + "CategoriesFragment" -> { + AlertDialog.Builder(this) + .setMessage(getString(R.string.deleting_category_warning)) + .setPositiveButton(getString(R.string.yes)) { _: DialogInterface, _: Int -> + val categoriesFragment = fragment as CategoriesFragment + categoriesFragment.removeSelected() + } + .setNegativeButton(getString(R.string.no)) { _: DialogInterface, _: Int -> + + }.show() + } + "ShelfFragment" -> { + val shelfFragment = fragment as ShelfFragment + shelfFragment.removeSelected() + } } + true } - true - } - else -> super.onOptionsItemSelected(item) + R.id.action_update -> { + when (fragment::class.simpleName.toString()) { + "StorageFragment" -> { + val storageFragment = fragment as StorageFragment + storageFragment.updateSelected() + } + + "CategoriesFragment" -> { + val categoriesFragment = fragment as CategoriesFragment + categoriesFragment.updateSelected() + } + + "ShelfFragment" -> { + val shelfFragment = fragment as ShelfFragment + shelfFragment.updateSelected() + } + } + true + } + + else -> super.onOptionsItemSelected(item) + } } + } fun filterAbstractProductsByCategory(id: Int) { diff --git a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/NavigatorActivity.kt b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/NavigatorActivity.kt index 871244f..c2befda 100644 --- a/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/NavigatorActivity.kt +++ b/app/src/main/java/org/foxarmy/barcodescannerforemployees/activities/NavigatorActivity.kt @@ -20,7 +20,7 @@ class NavigatorActivity : Activity() { finish(); } - fun isAuthenticated(): Boolean { + private fun isAuthenticated(): Boolean { val masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC) val sharedPreferences = EncryptedSharedPreferences.create( diff --git a/app/src/main/res/layout/activity_account_settings.xml b/app/src/main/res/layout/activity_account_settings.xml new file mode 100644 index 0000000..78b4a9c --- /dev/null +++ b/app/src/main/res/layout/activity_account_settings.xml @@ -0,0 +1,35 @@ + + + + + +