diff --git a/app/src/main/java/itb/bos/bondoman/SplashScreenActivity.kt b/app/src/main/java/itb/bos/bondoman/SplashScreenActivity.kt index a12bb357781d41feb47b9d07c21f5343b75824e5..992041b3c38868ba2492078ec262d4f5f4cf66b3 100644 --- a/app/src/main/java/itb/bos/bondoman/SplashScreenActivity.kt +++ b/app/src/main/java/itb/bos/bondoman/SplashScreenActivity.kt @@ -23,7 +23,7 @@ class SplashScreenActivity : AppCompatActivity() { start = findViewById(R.id.start) start.setOnClickListener{ - val login = Intent(this@SplashScreenActivity, MainActivity::class.java) + val login = Intent(this@SplashScreenActivity, LoginActivity::class.java) startActivity(login) } } diff --git a/app/src/main/java/itb/bos/bondoman/fragment/ui/qr/QrCapturedFragment.kt b/app/src/main/java/itb/bos/bondoman/fragment/ui/qr/QrCapturedFragment.kt index 165cd1921b52623b4b49bea2b08b7738b279dabe..60aba9eebb38c7ad461a7a27c3ce6e0fe59ccfee 100644 --- a/app/src/main/java/itb/bos/bondoman/fragment/ui/qr/QrCapturedFragment.kt +++ b/app/src/main/java/itb/bos/bondoman/fragment/ui/qr/QrCapturedFragment.kt @@ -13,18 +13,28 @@ import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController import itb.bos.bondoman.R import itb.bos.bondoman.databinding.FragmentQrCapturedBinding +import itb.bos.bondoman.helper.ImageUtils.uploadImage import itb.bos.bondoman.helper.NetworkObserver import itb.bos.bondoman.helper.TokenHelper import itb.bos.bondoman.helper.uploadScannedBill +import itb.bos.bondoman.retrofit.data.TransactionData +import itb.bos.bondoman.retrofit.data.models.SqlTransaction +import itb.bos.bondoman.retrofit.data.models.TransactionCategory import kotlinx.coroutines.launch import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MultipartBody import okhttp3.RequestBody.Companion.asRequestBody +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale +import kotlin.math.roundToInt +import kotlin.random.Random class QrCapturedFragment : Fragment() { private lateinit var binding: FragmentQrCapturedBinding private lateinit var tokenHelper: TokenHelper private lateinit var networkObserver: NetworkObserver + private lateinit var database: TransactionData override fun onCreateView( inflater: LayoutInflater, @@ -32,7 +42,7 @@ class QrCapturedFragment : Fragment() { savedInstanceState: Bundle? ): View? { binding = FragmentQrCapturedBinding.inflate(inflater, container, false) - tokenHelper = TokenHelper(requireContext()) // Initialize TokenHelper + tokenHelper = TokenHelper(requireContext()) return binding.root } @@ -41,19 +51,13 @@ class QrCapturedFragment : Fragment() { networkObserver = NetworkObserver(requireContext()) networkObserver.observeNetworkChanges() + database = TransactionData.getInstance(requireContext()) + // Retrieve the captured image bitmap from arguments val bitmap = arguments?.getParcelable<Bitmap>("capturedImage") bitmap?.let { - // Set the captured image bitmap to the ImageView val rotatedBitmap = rotateBitmap(it, 90f) - // Set the rotated image bitmap to the ImageView binding.capturedImageView.setImageBitmap(rotatedBitmap) - - if (networkObserver.isConnected.value == true) { - uploadImage(it) - } else { - Toast.makeText(requireContext(), "No Connection. Image not uploaded", Toast.LENGTH_SHORT).show() - } } binding.retakeButton.setOnClickListener { @@ -64,6 +68,18 @@ class QrCapturedFragment : Fragment() { .commit() } + binding.finishButton.setOnClickListener { + bitmap?.let { + networkObserver.isConnected.observe(viewLifecycleOwner) { isConnected -> + if (isConnected) { + uploadImage(it,requireContext(),database,tokenHelper,lifecycleScope) + } else { + Toast.makeText(requireContext(), "No network connection. Image upload failed.", Toast.LENGTH_SHORT).show() + } + } + } + } + } private fun rotateBitmap(bitmap: Bitmap, degrees: Float): Bitmap { @@ -71,67 +87,5 @@ class QrCapturedFragment : Fragment() { matrix.postRotate(degrees) return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true) } - - private fun uploadImage(bitmap: Bitmap) { - val imageFile = createImageFile(bitmap) - val requestFile = imageFile.asRequestBody("image/jpeg".toMediaTypeOrNull()) - val body = MultipartBody.Part.createFormData("file", imageFile.name, requestFile) - - lifecycleScope.launch { - val token = tokenHelper.getToken() - - if (token.isNullOrEmpty()) { - Toast.makeText(requireContext(), "Token is missing or invalid", Toast.LENGTH_SHORT).show() - return@launch - } - - try { - val response = uploadScannedBill(body, token) - if (response.isSuccessful) { - // Handle successful response - // You can show a message or navigate to another screen - Log.d("UploadImage", "Success in upload image with response : $response") - Toast.makeText(requireContext(), "Image uploaded successfully", Toast.LENGTH_SHORT).show() - } else { - // Handle error response - val errorBody = response.errorBody()?.string() - Log.e("UploadImage", "Failed to upload image: $errorBody with response : $response") - Toast.makeText(requireContext(), "Failed to upload image", Toast.LENGTH_SHORT).show() - } - } catch (e: Exception) { - Log.e("UploadImage", "Failed to upload image", e) - Toast.makeText(requireContext(), "Failed to upload image", Toast.LENGTH_SHORT).show() - } - } - } - - - private fun createImageFile(bitmap: Bitmap): java.io.File { - // Define the maximum dimensions for the compressed image - val maxWidth = 128 - val maxHeight = 128 - - // Resize the bitmap while maintaining aspect ratio - val resizedBitmap = if (bitmap.width > maxWidth || bitmap.height > maxHeight) { - val aspectRatio = bitmap.width.toFloat() / bitmap.height.toFloat() - if (bitmap.width > bitmap.height) { - Bitmap.createScaledBitmap(bitmap, maxWidth, (maxWidth / aspectRatio).toInt(), false) - } else { - Bitmap.createScaledBitmap(bitmap, (maxHeight * aspectRatio).toInt(), maxHeight, false) - } - } else { - bitmap - } - - // Create a temporary file to save the compressed image - val imageFile = java.io.File.createTempFile("image", ".jpg", requireContext().cacheDir) - - // Compress the bitmap and save it to the file - imageFile.outputStream().use { out -> - resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out) // Adjust compression quality as needed - } - - return imageFile - } } diff --git a/app/src/main/java/itb/bos/bondoman/fragment/ui/qr/QrFragment.kt b/app/src/main/java/itb/bos/bondoman/fragment/ui/qr/QrFragment.kt index d92a3ac1848c2d993a963e4dd5a2ee0c98a18f22..9504d1e7439c6d63c06c5123cbfc8a24a324a62a 100644 --- a/app/src/main/java/itb/bos/bondoman/fragment/ui/qr/QrFragment.kt +++ b/app/src/main/java/itb/bos/bondoman/fragment/ui/qr/QrFragment.kt @@ -27,16 +27,12 @@ import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope -import androidx.navigation.fragment.findNavController import itb.bos.bondoman.R import itb.bos.bondoman.databinding.FragmentQrBinding +import itb.bos.bondoman.helper.ImageUtils.uploadImage import itb.bos.bondoman.helper.NetworkObserver import itb.bos.bondoman.helper.TokenHelper -import itb.bos.bondoman.helper.uploadScannedBill -import kotlinx.coroutines.launch -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody.Companion.asRequestBody +import itb.bos.bondoman.retrofit.data.TransactionData class QrFragment : Fragment() { private lateinit var binding: FragmentQrBinding @@ -45,6 +41,7 @@ class QrFragment : Fragment() { private var imageCapture: ImageCapture? = null private lateinit var tokenHelper: TokenHelper private lateinit var networkObserver: NetworkObserver + private lateinit var database: TransactionData private val CAMERA_PERMISSION_REQUEST_CODE = 100 private val galleryActivityResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> @@ -57,14 +54,13 @@ class QrFragment : Fragment() { } } - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = FragmentQrBinding.inflate(inflater, container, false) - tokenHelper = TokenHelper(requireContext()) // Initialize TokenHelper + tokenHelper = TokenHelper(requireContext()) return binding.root } @@ -75,6 +71,8 @@ class QrFragment : Fragment() { networkObserver = NetworkObserver(requireContext()) networkObserver.observeNetworkChanges() + database = TransactionData.getInstance(requireContext()) + if (ContextCompat.checkSelfPermission( requireContext(), Manifest.permission.CAMERA @@ -107,7 +105,7 @@ class QrFragment : Fragment() { if (networkObserver.isConnected.value == true) { bitmap?.let { - uploadImage(it) + uploadImage(it,requireContext(),database,tokenHelper,lifecycleScope) } } else { Toast.makeText(requireContext(), "No Connection. Image not uploaded", Toast.LENGTH_SHORT).show() @@ -117,7 +115,6 @@ class QrFragment : Fragment() { private fun startCamera() { if (!::previewView.isInitialized) { - // previewView is not initialized yet return } @@ -143,7 +140,6 @@ class QrFragment : Fragment() { } private fun captureImage() { - // Check if the camera and imageCapture are initialized if (camera == null || imageCapture == null) { Toast.makeText(requireContext(), "Camera is not initialized", Toast.LENGTH_SHORT).show() return @@ -153,7 +149,6 @@ class QrFragment : Fragment() { imageCapture?.takePicture(ContextCompat.getMainExecutor(requireContext()), object : ImageCapture.OnImageCapturedCallback() { override fun onCaptureSuccess(image: ImageProxy) { val bitmap = image.toBitmap() - // Pass the captured image bitmap to the CapturedImageFragment navigateToCapturedFragment(bitmap) image.close() } @@ -165,7 +160,6 @@ class QrFragment : Fragment() { }) } - // Inside QrFragment private fun navigateToCapturedFragment(bitmap: Bitmap) { val capturedFragment = QrCapturedFragment().apply { // Pass the captured image bitmap as an argument @@ -178,10 +172,7 @@ class QrFragment : Fragment() { .addToBackStack(null) .commit() } - - - - + private fun requestCameraPermission() { ActivityCompat.requestPermissions( requireActivity(), @@ -204,67 +195,5 @@ class QrFragment : Fragment() { } } - private fun uploadImage(bitmap: Bitmap) { - val imageFile = createImageFile(bitmap) - val requestFile = imageFile.asRequestBody("image/jpeg".toMediaTypeOrNull()) - val body = MultipartBody.Part.createFormData("file", imageFile.name, requestFile) - - lifecycleScope.launch { - val token = tokenHelper.getToken() - - if (token.isNullOrEmpty()) { - Toast.makeText(requireContext(), "Token is missing or invalid", Toast.LENGTH_SHORT).show() - return@launch - } - - try { - val response = uploadScannedBill(body, token) - if (response.isSuccessful) { - // Handle successful response - // You can show a message or navigate to another screen - Log.d("UploadImage", "Success in upload image with response : $response") - Toast.makeText(requireContext(), "Image uploaded successfully", Toast.LENGTH_SHORT).show() - } else { - // Handle error response - val errorBody = response.errorBody()?.string() - Log.e("UploadImage", "Failed to upload image: $errorBody with response : $response") - Toast.makeText(requireContext(), "Failed to upload image", Toast.LENGTH_SHORT).show() - } - } catch (e: Exception) { - Log.e("UploadImage", "Failed to upload image", e) - Toast.makeText(requireContext(), "Failed to upload image", Toast.LENGTH_SHORT).show() - } - } - } - - - private fun createImageFile(bitmap: Bitmap): java.io.File { - // Define the maximum dimensions for the compressed image - val maxWidth = 128 - val maxHeight = 128 - - // Resize the bitmap while maintaining aspect ratio - val resizedBitmap = if (bitmap.width > maxWidth || bitmap.height > maxHeight) { - val aspectRatio = bitmap.width.toFloat() / bitmap.height.toFloat() - if (bitmap.width > bitmap.height) { - Bitmap.createScaledBitmap(bitmap, maxWidth, (maxWidth / aspectRatio).toInt(), false) - } else { - Bitmap.createScaledBitmap(bitmap, (maxHeight * aspectRatio).toInt(), maxHeight, false) - } - } else { - bitmap - } - - // Create a temporary file to save the compressed image - val imageFile = java.io.File.createTempFile("image", ".jpg", requireContext().cacheDir) - - // Compress the bitmap and save it to the file - imageFile.outputStream().use { out -> - resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out) // Adjust compression quality as needed - } - - return imageFile - } - } diff --git a/app/src/main/java/itb/bos/bondoman/fragment/ui/qr/QrViewModel.kt b/app/src/main/java/itb/bos/bondoman/fragment/ui/qr/QrViewModel.kt index e19b509189cc6bb254e3230efe46ac03bba8227c..b641c8caa5804c61eafb0ed33d55010afc7725c7 100644 --- a/app/src/main/java/itb/bos/bondoman/fragment/ui/qr/QrViewModel.kt +++ b/app/src/main/java/itb/bos/bondoman/fragment/ui/qr/QrViewModel.kt @@ -10,4 +10,36 @@ class QrViewModel : ViewModel() { value = "This is qr Fragment" } val text: LiveData<String> = _text + + // { +// "items": { +// "items": [ +// { +// "name": "sauce", +// "qty": 3, +// "price": 33.26 +// }, +// { +// "name": "goldfish", +// "qty": 8, +// "price": 83.11 +// }, +// { +// "name": "hostess", +// "qty": 10, +// "price": 33.52 +// }, +// { +// "name": "lion", +// "qty": 10, +// "price": 43.4 +// }, +// { +// "name": "call", +// "qty": 2, +// "price": 38.58 +// } +// ] +// } +// } } \ No newline at end of file diff --git a/app/src/main/java/itb/bos/bondoman/helper/ImageUtils.kt b/app/src/main/java/itb/bos/bondoman/helper/ImageUtils.kt new file mode 100644 index 0000000000000000000000000000000000000000..68bcd6b3d2a2da9fac2f301b44882ab409d2e75b --- /dev/null +++ b/app/src/main/java/itb/bos/bondoman/helper/ImageUtils.kt @@ -0,0 +1,123 @@ +package itb.bos.bondoman.helper + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Bitmap.CompressFormat +import android.util.Log +import android.widget.Toast +import androidx.lifecycle.LifecycleCoroutineScope +import itb.bos.bondoman.retrofit.data.TransactionData +import itb.bos.bondoman.retrofit.data.models.SqlTransaction +import itb.bos.bondoman.retrofit.data.models.TransactionCategory +import kotlinx.coroutines.launch +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody.Companion.asRequestBody +import java.io.File +import java.text.SimpleDateFormat +import java.util.* +import kotlin.random.Random +import kotlin.math.roundToInt + +object ImageUtils { + + fun uploadImage(bitmap: Bitmap, context: Context, database: TransactionData, tokenHelper: TokenHelper, lifecycleScope: LifecycleCoroutineScope) { + val imageFile = createImageFile(bitmap, context) + val requestFile = imageFile.asRequestBody("image/jpeg".toMediaTypeOrNull()) + val body = MultipartBody.Part.createFormData("file", imageFile.name, requestFile) + + lifecycleScope.launch { + val token = tokenHelper.getToken() + + if (token.isNullOrEmpty()) { + showToast(context, "Token is missing or invalid") + return@launch + } + + try { + val response = uploadScannedBill(body, token) + if (response.isSuccessful) { + // Handle successful response + val scanUploadResponse = response.body() + scanUploadResponse?.let { uploadResponse -> + val items = uploadResponse.items.items // List of items + // Now you can loop through the list of items and access each item + val currentDate = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format( + Date() + ) + items.forEach { item -> + val itemName = item.name + val itemQty = item.qty + val itemPrice = item.price + val category = if (Random.nextBoolean()) { + TransactionCategory.PEMASUKAN + } else { + TransactionCategory.PENGELUARAN + } + + val newTransaction = SqlTransaction( + name = itemName, + category = category, + date = currentDate, + price = (itemPrice * itemQty).roundToInt(), + location = "Unknown" + ) + database.transactionDao().insertAll(newTransaction) + Log.d("ScanUpload", "Item: $itemName, Qty: $itemQty, Price: $itemPrice") + } + + } + Log.d("UploadImage", "Success in upload image with response : $response") + showToast(context, "Image uploaded successfully") + } else { + // Handle error response + val errorBody = response.errorBody()?.string() + Log.e("UploadImage", "Failed to upload image: $errorBody with response : $response") + showToast(context, "Failed to upload image") + } + } catch (e: Exception) { + Log.e("UploadImage", "Failed to upload image", e) + showToast(context, "Failed to upload image") + } + } + } + + private fun showToast(context: Context, message: String) { + Toast.makeText(context, message, Toast.LENGTH_SHORT).show() + } + + private fun resizeBitmap(bitmap: Bitmap): Bitmap? { + val maxWidth = 64 + val maxHeight = 64 + + val width = bitmap.width + val height = bitmap.height + + // Calculate the scale factor to fit within maxWidth and maxHeight while maintaining aspect ratio + val scaleFactor = if (width > height) { + maxWidth.toFloat() / width + } else { + maxHeight.toFloat() / height + } + + val newWidth = (width * scaleFactor).toInt() + val newHeight = (height * scaleFactor).toInt() + return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true) + } + + private fun createImageFile(bitmap: Bitmap, context: Context): File { + val resizedBitmap = resizeBitmap(bitmap) + + // Create a temporary file to save the compressed image + val imageFile = File.createTempFile("image", ".jpg", context.cacheDir) + + // Compress the bitmap and save it to the file + if (resizedBitmap != null) { + imageFile.outputStream().use { out -> + resizedBitmap.compress(CompressFormat.JPEG, 80, out) // Adjust compression quality as needed + } + } + + return imageFile + } +} diff --git a/app/src/main/java/itb/bos/bondoman/helper/LocationUtils.kt b/app/src/main/java/itb/bos/bondoman/helper/LocationUtils.kt new file mode 100644 index 0000000000000000000000000000000000000000..c9c43221eaff82a0d8c2a0d01dcf6c17ef5a1277 --- /dev/null +++ b/app/src/main/java/itb/bos/bondoman/helper/LocationUtils.kt @@ -0,0 +1,99 @@ +package itb.bos.bondoman.helper + +import android.content.Context +import android.content.pm.PackageManager +import android.location.Geocoder +import android.util.Log +import android.widget.Toast +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat.checkSelfPermission +import androidx.fragment.app.Fragment +import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationServices +import java.util.* + +object LocationUtils { + const val LOCATION_PERMISSION_REQUEST_CODE = 1001 + + private lateinit var fusedLocationClient: FusedLocationProviderClient + private lateinit var geocoder: Geocoder + + fun initialize(context: Context) { + fusedLocationClient = LocationServices.getFusedLocationProviderClient(context) + geocoder = Geocoder(context, Locale.getDefault()) + } + + fun fetchLocation(fragment: Fragment, callback: (String) -> Unit) { + val address = "Unknown" + // Check for both ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions + when { + checkSelfPermission(fragment.requireContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED -> { + fetchPreciseLocation(fragment, callback) + } + checkSelfPermission(fragment.requireContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED -> { + fetchApproximateLocation(fragment, callback) + } + else -> { + // Request location permissions for both fine and coarse locations + ActivityCompat.requestPermissions(fragment.requireActivity(), arrayOf( + android.Manifest.permission.ACCESS_FINE_LOCATION, + android.Manifest.permission.ACCESS_COARSE_LOCATION), LOCATION_PERMISSION_REQUEST_CODE) + callback(address) + } + } + } + + private fun fetchPreciseLocation(fragment: Fragment, callback: (String) -> Unit) { + if (checkSelfPermission(fragment.requireContext(), android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { + fusedLocationClient.lastLocation.addOnSuccessListener(fragment.requireActivity()) { location -> + location?.let { + Log.e("fetchLocation", "Fetching precise location") + val latitude = location.latitude + val longitude = location.longitude + val address = getAddress(latitude, longitude, true) + callback(address) + } + }.addOnFailureListener { e -> + // Handle failure to fetch location + Log.e("fetchLocation", "Failed to fetch precise location: ${e.message}") + Toast.makeText(fragment.requireContext(), "Failed to fetch location", Toast.LENGTH_SHORT) + .show() + callback("Unknown") + } + } + } + + private fun fetchApproximateLocation(fragment: Fragment, callback: (String) -> Unit) { + if (checkSelfPermission(fragment.requireContext(), android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) { + fusedLocationClient.lastLocation.addOnSuccessListener(fragment.requireActivity()) { location -> + location?.let { + Log.e("fetchLocation", "Fetching approximate location") + val latitude = location.latitude + val longitude = location.longitude + val address = getAddress(latitude, longitude, false) + callback(address) + } + }.addOnFailureListener { e -> + // Handle failure to fetch location + Log.e("fetchLocation", "Failed to fetch approximate location: ${e.message}") + Toast.makeText(fragment.requireContext(), "Failed to fetch location", Toast.LENGTH_SHORT) + .show() + callback("Unknown") + } + } + } + + private fun getAddress(latitude: Double, longitude: Double, isPreciseLocation: Boolean): String { + val addresses = geocoder.getFromLocation(latitude, longitude, 1) + return if (!addresses.isNullOrEmpty()) { + val address = addresses[0] + if (isPreciseLocation) { + "${address.getAddressLine(0)}, ${address.locality}, ${address.adminArea}, ${address.countryName}" + } else { + "${address.locality}, ${address.adminArea}, ${address.countryName}" + } + } else { + "Unknown Location" + } + } +} diff --git a/app/src/main/java/itb/bos/bondoman/helper/ScanHelper.kt b/app/src/main/java/itb/bos/bondoman/helper/ScanHelper.kt index aea855964a994afd1e1bb8fb090449e9dd8574de..c1e5143bff3cae7ddd14a03675d3c7123d0c3e6c 100644 --- a/app/src/main/java/itb/bos/bondoman/helper/ScanHelper.kt +++ b/app/src/main/java/itb/bos/bondoman/helper/ScanHelper.kt @@ -16,7 +16,6 @@ suspend fun uploadScannedBill(file: MultipartBody.Part, token: String): Response val response = endpoint.uploadBill("Bearer $token", file) Log.d("UploadImage", "The response is : $response") - response } } diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 1bd10d5511305ab4e4cea6ad3a99e65af18b33fa..3da4ec5d19e5627a378ac2f641326b8de2ca652e 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -106,8 +106,10 @@ android:id="@+id/email" android:layout_width="match_parent" android:layout_height="match_parent" + android:textColor="@color/dark_grey" android:background="@android:color/transparent" android:hint="Email" + android:textColorHint="@color/dark_grey" android:inputType="textEmailAddress" android:paddingHorizontal="20dp" /> @@ -130,10 +132,12 @@ <EditText android:id="@+id/password" - android:layout_width="match_parent" + android:layout_width="0dp" android:layout_height="match_parent" + android:textColor="@color/dark_grey" android:background="@android:color/transparent" android:hint="Password" + android:textColorHint="@color/dark_grey" android:layout_weight="1" android:inputType="textPassword" android:paddingHorizontal="20dp" /> @@ -154,7 +158,8 @@ android:layout_marginTop="64dp" android:background="@drawable/cornered_login" android:text="Log In" - android:textStyle="bold" /> + android:textStyle="bold" + /> </LinearLayout> </RelativeLayout> diff --git a/app/src/main/res/layout/fragment_header_qr.xml b/app/src/main/res/layout/fragment_header_qr.xml index 677050e255776bd358e63681768c87291d21596e..5fbd76c6bd9bbebdc1edba4b18f83ed35af0d9bb 100644 --- a/app/src/main/res/layout/fragment_header_qr.xml +++ b/app/src/main/res/layout/fragment_header_qr.xml @@ -3,6 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" + android:id="@+id/qr_fragment_header" android:background="@color/black" > diff --git a/app/src/main/res/layout/fragment_qr_captured.xml b/app/src/main/res/layout/fragment_qr_captured.xml index def43d508794496c6fd471814ec4de1e094e6243..7dfba4ae210cb716d57e76d7b0df1af3476ad625 100644 --- a/app/src/main/res/layout/fragment_qr_captured.xml +++ b/app/src/main/res/layout/fragment_qr_captured.xml @@ -60,7 +60,14 @@ android:id="@+id/retakeButton" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginEnd="8dp" android:text="Retake" /> + <Button + android:id="@+id/finishButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="8dp" + android:text="Finish" /> </LinearLayout> diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index 57d437159e59c9f115b5e907e464a32874852577..7d4b5d27fd36a6a0a1ad95f8d73eb88a577c360b 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -49,6 +49,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Save Transaction" + android:textColor="@color/dark_grey" android:layout_marginHorizontal="16dp" android:layout_weight="1" android:layout_gravity="center" @@ -77,6 +78,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Send Email" + android:textColor="@color/dark_grey" android:layout_marginHorizontal="16dp" android:layout_weight="1" android:layout_gravity="center" @@ -105,6 +107,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Randomize Transaction" + android:textColor="@color/dark_grey" android:layout_marginHorizontal="16dp" android:layout_weight="1" android:layout_gravity="center" @@ -127,6 +130,7 @@ android:layout_height="wrap_content" android:layout_gravity="bottom" android:text="Logout" + android:textColor="@color/white" android:backgroundTint="@color/red" /> </LinearLayout> diff --git a/app/src/main/res/layout/fragment_transaction.xml b/app/src/main/res/layout/fragment_transaction.xml index dd01c88ae5dea36aa00458c3c6f031025ac5c95a..75024e335aa2511ac31f724952178c568b2fbb4a 100644 --- a/app/src/main/res/layout/fragment_transaction.xml +++ b/app/src/main/res/layout/fragment_transaction.xml @@ -46,7 +46,6 @@ android:layout_height="match_parent" android:textColor="@color/dark_grey" android:background="@android:color/transparent" - android:hint="Search" android:inputType="textEmailAddress" android:paddingHorizontal="20dp" />