Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
aayush262 2024-05-26 00:41:28 +05:30
commit f3f0daf7e7
17 changed files with 634 additions and 23 deletions

View file

@ -108,7 +108,7 @@ jobs:
#Telegram #Telegram
curl -F "chat_id=${{ secrets.TELEGRAM_CHANNEL_ID }}" \ curl -F "chat_id=${{ secrets.TELEGRAM_CHANNEL_ID }}" \
-F "document=@app/build/outputs/apk/google/alpha/app-google-universal-alpha.apk" \ -F "document=@app/build/outputs/apk/google/alpha/app-google-alpha.apk" \
-F "caption=Alpha-Build: ${VERSION}: ${commit_messages}" \ -F "caption=Alpha-Build: ${VERSION}: ${commit_messages}" \
https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendDocument https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendDocument

View file

@ -101,6 +101,8 @@ dependencies {
implementation 'androidx.preference:preference-ktx:1.2.1' implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.webkit:webkit:1.11.0' implementation 'androidx.webkit:webkit:1.11.0'
implementation "com.anggrayudi:storage:1.5.5" implementation "com.anggrayudi:storage:1.5.5"
implementation "androidx.biometric:biometric:1.1.0"
// Glide // Glide
ext.glide_version = '4.16.0' ext.glide_version = '4.16.0'

View file

@ -16,6 +16,8 @@ import ani.dantotsu.navBarHeight
import ani.dantotsu.profile.User import ani.dantotsu.profile.User
import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import ani.dantotsu.toast
import ani.dantotsu.util.Logger
class StatusActivity : AppCompatActivity(), StoriesCallback { class StatusActivity : AppCompatActivity(), StoriesCallback {
private lateinit var activity: ArrayList<User> private lateinit var activity: ArrayList<User>
@ -44,10 +46,14 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
val key = "activities" val key = "activities"
val watchedActivity = PrefManager.getCustomVal<Set<Int>>(key, setOf()) val watchedActivity = PrefManager.getCustomVal<Set<Int>>(key, setOf())
if (activity.getOrNull(position) != null) {
val startFrom = findFirstNonMatch(watchedActivity, activity[position].activity ) val startFrom = findFirstNonMatch(watchedActivity, activity[position].activity )
val startIndex = if ( startFrom > 0) startFrom else 0 val startIndex = if ( startFrom > 0) startFrom else 0
binding.stories.setStoriesList(activity[position].activity, this, startIndex + 1) binding.stories.setStoriesList(activity[position].activity, this, startIndex + 1)
} else {
Logger.log("index out of bounds for position $position of size ${activity.size}")
finish()
}
} }
private fun findFirstNonMatch(watchedActivity: Set<Int>, activity: List<Activity>): Int { private fun findFirstNonMatch(watchedActivity: Set<Int>, activity: List<Activity>): Int {
@ -58,12 +64,15 @@ class StatusActivity : AppCompatActivity(), StoriesCallback {
} }
return -1 return -1
} }
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
binding.stories.pause() binding.stories.pause()
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
if (hasWindowFocus())
binding.stories.resume() binding.stories.resume()
} }

View file

@ -424,6 +424,7 @@ class MediaDetailsActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedLi
} }
override fun onResume() { override fun onResume() {
if (::navBar.isInitialized)
navBar.selectTabAt(selected) navBar.selectTabAt(selected)
super.onResume() super.onResume()
} }

View file

@ -4,6 +4,7 @@ import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
@ -24,7 +25,10 @@ class CrashActivity : AppCompatActivity() {
ThemeManager(this).applyTheme() ThemeManager(this).applyTheme()
initActivity(this) initActivity(this)
binding = ActivityCrashBinding.inflate(layoutInflater) binding = ActivityCrashBinding.inflate(layoutInflater)
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
)
setContentView(binding.root) setContentView(binding.root)
binding.root.updateLayoutParams<ViewGroup.MarginLayoutParams> { binding.root.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = statusBarHeight topMargin = statusBarHeight

View file

@ -0,0 +1,57 @@
package ani.dantotsu.others.calc
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
import ani.dantotsu.R
import ani.dantotsu.util.Logger
object BiometricPromptUtils {
private const val TAG = "BiometricPromptUtils"
/**
* Create a BiometricPrompt instance
* @param activity: AppCompatActivity
* @param processSuccess: success callback
*/
fun createBiometricPrompt(
activity: AppCompatActivity,
processSuccess: (BiometricPrompt.AuthenticationResult) -> Unit
): BiometricPrompt {
val executor = ContextCompat.getMainExecutor(activity)
val callback = object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationError(errCode: Int, errString: CharSequence) {
super.onAuthenticationError(errCode, errString)
Logger.log("$TAG errCode is $errCode and errString is: $errString")
}
override fun onAuthenticationFailed() {
super.onAuthenticationFailed()
Logger.log("$TAG User biometric rejected.")
}
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
super.onAuthenticationSucceeded(result)
Log.d(TAG, "Authentication was successful")
processSuccess(result)
}
}
return BiometricPrompt(activity, executor, callback)
}
/**
* Create a BiometricPrompt.PromptInfo instance
* @param activity: AppCompatActivity
* @return BiometricPrompt.PromptInfo: instance
*/
fun createPromptInfo(activity: AppCompatActivity): BiometricPrompt.PromptInfo =
BiometricPrompt.PromptInfo.Builder().apply {
setTitle(activity.getString(R.string.bio_prompt_info_title))
setDescription(activity.getString(R.string.bio_prompt_info_desc))
setConfirmationRequired(false)
setNegativeButtonText(activity.getString(R.string.cancel))
}.build()
}

View file

@ -1,10 +1,14 @@
package ani.dantotsu.others.calc package ani.dantotsu.others.calc
import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.Spannable import android.text.Spannable
import android.text.SpannableString import android.text.SpannableString
import android.text.style.ForegroundColorSpan import android.text.style.ForegroundColorSpan
import android.view.MotionEvent
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@ -16,6 +20,8 @@ import ani.dantotsu.databinding.ActivityCalcBinding
import ani.dantotsu.getThemeColor import ani.dantotsu.getThemeColor
import ani.dantotsu.initActivity import ani.dantotsu.initActivity
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName
import ani.dantotsu.statusBarHeight import ani.dantotsu.statusBarHeight
import ani.dantotsu.themes.ThemeManager import ani.dantotsu.themes.ThemeManager
import ani.dantotsu.util.NumberConverter.Companion.toBinary import ani.dantotsu.util.NumberConverter.Companion.toBinary
@ -24,7 +30,13 @@ import ani.dantotsu.util.NumberConverter.Companion.toHex
class CalcActivity : AppCompatActivity() { class CalcActivity : AppCompatActivity() {
private lateinit var binding: ActivityCalcBinding private lateinit var binding: ActivityCalcBinding
private lateinit var code: String private lateinit var code: String
private val handler = Handler(Looper.getMainLooper())
private val runnable = Runnable {
success()
}
private val stack = CalcStack() private val stack = CalcStack()
@SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
ThemeManager(this).applyTheme() ThemeManager(this).applyTheme()
@ -73,6 +85,29 @@ class CalcActivity : AppCompatActivity() {
binding.displayHex.text = "" binding.displayHex.text = ""
binding.display.text = "0" binding.display.text = "0"
} }
if (PrefManager.getVal(PrefName.OverridePassword, false)) {
buttonClear.setOnTouchListener { v, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
handler.postDelayed(runnable, 10000)
true
}
MotionEvent.ACTION_UP -> {
v.performClick()
handler.removeCallbacks(runnable)
true
}
MotionEvent.ACTION_CANCEL -> {
handler.removeCallbacks(runnable)
true
}
else -> false
}
}
}
buttonBackspace.setOnClickListener { buttonBackspace.setOnClickListener {
stack.remove() stack.remove()
updateDisplay() updateDisplay()
@ -81,6 +116,20 @@ class CalcActivity : AppCompatActivity() {
} }
} }
override fun onResume() {
super.onResume()
if (hasPermission) {
success()
}
if (PrefManager.getVal(PrefName.BiometricToken, "").isNotEmpty()) {
val bioMetricPrompt = BiometricPromptUtils.createBiometricPrompt(this) {
success()
}
val promptInfo = BiometricPromptUtils.createPromptInfo(this)
bioMetricPrompt.authenticate(promptInfo)
}
}
private fun success() { private fun success() {
hasPermission = true hasPermission = true
ContextCompat.startActivity( ContextCompat.startActivity(

View file

@ -43,6 +43,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.util.Locale
class ExtensionsActivity : AppCompatActivity() { class ExtensionsActivity : AppCompatActivity() {
lateinit var binding: ActivityExtensionsBinding lateinit var binding: ActivityExtensionsBinding
@ -173,8 +174,11 @@ class ExtensionsActivity : AppCompatActivity() {
initActivity(this) initActivity(this)
binding.languageselect.setOnClickListener { binding.languageselect.setOnClickListener {
val languageOptions = val languageOptions =
LanguageMapper.Companion.Language.entries.map { it.name }.toTypedArray() LanguageMapper.Companion.Language.entries.map { entry ->
val builder = AlertDialog.Builder(currContext(), R.style.MyPopup) entry.name.lowercase().replace("_", " ")
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString() }
}.toTypedArray()
val builder = AlertDialog.Builder(this, R.style.MyPopup)
val listOrder: String = PrefManager.getVal(PrefName.LangSort) val listOrder: String = PrefManager.getVal(PrefName.LangSort)
val index = LanguageMapper.Companion.Language.entries.toTypedArray() val index = LanguageMapper.Companion.Language.entries.toTypedArray()
.indexOfFirst { it.code == listOrder } .indexOfFirst { it.code == listOrder }

View file

@ -6,6 +6,7 @@ import androidx.core.app.NotificationCompat
import ani.dantotsu.R import ani.dantotsu.R
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
import ani.dantotsu.snackString import ani.dantotsu.snackString
import ani.dantotsu.util.Logger
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.extension.InstallStep import eu.kanade.tachiyomi.extension.InstallStep
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@ -30,6 +31,7 @@ class InstallerSteps(
fun onError(error: Throwable, extra: () -> Unit) { fun onError(error: Throwable, extra: () -> Unit) {
Injekt.get<CrashlyticsInterface>().logException(error) Injekt.get<CrashlyticsInterface>().logException(error)
Logger.log(error)
val builder = NotificationCompat.Builder( val builder = NotificationCompat.Builder(
context, context,
Notifications.CHANNEL_DOWNLOADER_ERROR Notifications.CHANNEL_DOWNLOADER_ERROR

View file

@ -8,9 +8,12 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.CheckBox
import android.widget.EditText import android.widget.EditText
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.biometric.BiometricManager
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -21,6 +24,7 @@ import ani.dantotsu.databinding.DialogUserAgentBinding
import ani.dantotsu.download.DownloadsManager import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.initActivity import ani.dantotsu.initActivity
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.others.calc.BiometricPromptUtils
import ani.dantotsu.restartApp import ani.dantotsu.restartApp
import ani.dantotsu.savePrefsToDownloads import ani.dantotsu.savePrefsToDownloads
import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefManager
@ -39,6 +43,7 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.UUID
class SettingsCommonActivity : AppCompatActivity() { class SettingsCommonActivity : AppCompatActivity() {
@ -183,14 +188,47 @@ class SettingsCommonActivity : AppCompatActivity() {
(dialog as AlertDialog).findViewById<EditText>(R.id.passwordInput) (dialog as AlertDialog).findViewById<EditText>(R.id.passwordInput)
val confirmPasswordInput = val confirmPasswordInput =
dialog.findViewById<EditText>(R.id.confirmPasswordInput) dialog.findViewById<EditText>(R.id.confirmPasswordInput)
val forgotPasswordCheckbox =
dialog.findViewById<CheckBox>(R.id.forgotPasswordCheckbox)
if (forgotPasswordCheckbox?.isChecked == true) {
PrefManager.setVal(PrefName.OverridePassword, true)
}
val password = passwordInput?.text.toString() val password = passwordInput?.text.toString()
val confirmPassword = confirmPasswordInput?.text.toString() val confirmPassword = confirmPasswordInput?.text.toString()
if (password == confirmPassword && password.isNotEmpty()) { if (password == confirmPassword && password.isNotEmpty()) {
PrefManager.setVal(PrefName.AppPassword, password) PrefManager.setVal(PrefName.AppPassword, password)
if (dialog.findViewById<CheckBox>(R.id.biometricCheckbox)?.isChecked == true) {
val canBiometricPrompt =
BiometricManager.from(applicationContext)
.canAuthenticate(
BiometricManager.Authenticators.BIOMETRIC_WEAK
) == BiometricManager.BIOMETRIC_SUCCESS
if (canBiometricPrompt) {
val biometricPrompt =
BiometricPromptUtils.createBiometricPrompt(
this@SettingsCommonActivity
) { _ ->
val token = UUID.randomUUID().toString()
PrefManager.setVal(
PrefName.BiometricToken,
token
)
toast(R.string.success) toast(R.string.success)
dialog.dismiss() dialog.dismiss()
}
val promptInfo =
BiometricPromptUtils.createPromptInfo(
this@SettingsCommonActivity
)
biometricPrompt.authenticate(promptInfo)
}
} else {
PrefManager.setVal(PrefName.BiometricToken, "")
toast(R.string.success)
dialog.dismiss()
}
} else { } else {
toast(R.string.password_mismatch) toast(R.string.password_mismatch)
} }
@ -200,6 +238,8 @@ class SettingsCommonActivity : AppCompatActivity() {
} }
.setNeutralButton(R.string.remove) { dialog, _ -> .setNeutralButton(R.string.remove) { dialog, _ ->
PrefManager.setVal(PrefName.AppPassword, "") PrefManager.setVal(PrefName.AppPassword, "")
PrefManager.setVal(PrefName.BiometricToken, "")
PrefManager.setVal(PrefName.OverridePassword, false)
toast(R.string.success) toast(R.string.success)
dialog.dismiss() dialog.dismiss()
} }
@ -209,6 +249,19 @@ class SettingsCommonActivity : AppCompatActivity() {
passwordDialog.setOnShowListener { passwordDialog.setOnShowListener {
passwordDialog.findViewById<EditText>(R.id.passwordInput) passwordDialog.findViewById<EditText>(R.id.passwordInput)
?.requestFocus() ?.requestFocus()
val biometricCheckbox =
passwordDialog.findViewById<CheckBox>(R.id.biometricCheckbox)
val forgotPasswordCheckbox =
passwordDialog.findViewById<CheckBox>(R.id.forgotPasswordCheckbox)
val canAuthenticate =
BiometricManager.from(applicationContext).canAuthenticate(
BiometricManager.Authenticators.BIOMETRIC_WEAK
) == BiometricManager.BIOMETRIC_SUCCESS
biometricCheckbox?.isVisible = canAuthenticate
biometricCheckbox?.isChecked =
PrefManager.getVal(PrefName.BiometricToken, "").isNotEmpty()
forgotPasswordCheckbox?.isChecked =
PrefManager.getVal(PrefName.OverridePassword)
} }
passwordDialog.show() passwordDialog.show()
} }

View file

@ -202,4 +202,6 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
MALCodeChallenge(Pref(Location.Protected, String::class, "")), MALCodeChallenge(Pref(Location.Protected, String::class, "")),
MALToken(Pref(Location.Protected, MAL.ResponseToken::class, "")), MALToken(Pref(Location.Protected, MAL.ResponseToken::class, "")),
AppPassword(Pref(Location.Protected, String::class, "")), AppPassword(Pref(Location.Protected, String::class, "")),
BiometricToken(Pref(Location.Protected, String::class, "")),
OverridePassword(Pref(Location.Protected, Boolean::class, false)),
} }

View file

@ -0,0 +1,390 @@
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/bg">
<LinearLayout
android:id="@+id/mainContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@color/bg"
android:baselineAligned="false"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/displayContainer"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:layout_marginTop="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/display"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:background="@drawable/rounded_top_corners"
android:gravity="end"
android:maxLines="2"
app:autoSizeMaxTextSize="48sp"
app:autoSizeMinTextSize="10sp"
app:autoSizeStepGranularity="2sp"
app:autoSizeTextType="uniform"
android:textColor="?attr/colorOnSurfaceVariant"
android:textSize="48sp"
tools:ignore="ButtonStyle,HardcodedText" />
<TextView
android:id="@+id/displayBinary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="2dp"
android:background="?attr/colorSurfaceVariant"
android:gravity="end"
android:maxLines="2"
app:autoSizeMaxTextSize="48sp"
app:autoSizeMinTextSize="10sp"
app:autoSizeStepGranularity="2sp"
app:autoSizeTextType="uniform"
android:textColor="?attr/colorOnSurfaceVariant"
android:textSize="28sp"
tools:ignore="ButtonStyle,HardcodedText" />
<TextView
android:id="@+id/displayHex"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="2dp"
android:background="@drawable/rounded_bottom_corners"
android:gravity="end"
android:maxLines="2"
app:autoSizeMaxTextSize="48sp"
app:autoSizeMinTextSize="10sp"
app:autoSizeStepGranularity="2sp"
app:autoSizeTextType="uniform"
android:textColor="?attr/colorOnSurfaceVariant"
android:textSize="28sp"
tools:ignore="ButtonStyle,HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/buttonContainer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<Button
android:id="@+id/button7"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:backgroundTint="?attr/colorSurfaceVariant"
android:elegantTextHeight="true"
android:text="7"
android:textColor="?attr/colorOnSurfaceVariant"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
<Button
android:id="@+id/button8"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:backgroundTint="?attr/colorSurfaceVariant"
android:elegantTextHeight="true"
android:text="8"
android:textColor="?attr/colorOnSurfaceVariant"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
<Button
android:id="@+id/button9"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:backgroundTint="?attr/colorSurfaceVariant"
android:elegantTextHeight="true"
android:text="9"
android:textColor="?attr/colorOnSurfaceVariant"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
<Button
android:id="@+id/buttonDivide"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:layout_marginStart="16dp"
android:backgroundTint="?attr/colorPrimary"
android:elegantTextHeight="true"
android:text="÷"
android:textColor="?attr/colorOnPrimary"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<Button
android:id="@+id/button4"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:backgroundTint="?attr/colorSurfaceVariant"
android:elegantTextHeight="true"
android:text="4"
android:textColor="?attr/colorOnSurfaceVariant"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
<Button
android:id="@+id/button5"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:backgroundTint="?attr/colorSurfaceVariant"
android:elegantTextHeight="true"
android:text="5"
android:textColor="?attr/colorOnSurfaceVariant"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
<Button
android:id="@+id/button6"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:backgroundTint="?attr/colorSurfaceVariant"
android:elegantTextHeight="true"
android:text="6"
android:textColor="?attr/colorOnSurfaceVariant"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
<Button
android:id="@+id/buttonMultiply"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:layout_marginStart="16dp"
android:backgroundTint="?attr/colorPrimary"
android:elegantTextHeight="true"
android:text="×"
android:textColor="?attr/colorOnPrimary"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<Button
android:id="@+id/button1"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:backgroundTint="?attr/colorSurfaceVariant"
android:elegantTextHeight="true"
android:text="1"
android:textColor="?attr/colorOnSurfaceVariant"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
<Button
android:id="@+id/button2"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:backgroundTint="?attr/colorSurfaceVariant"
android:elegantTextHeight="true"
android:text="2"
android:textColor="?attr/colorOnSurfaceVariant"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
<Button
android:id="@+id/button3"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:backgroundTint="?attr/colorSurfaceVariant"
android:elegantTextHeight="true"
android:text="3"
android:textColor="?attr/colorOnSurfaceVariant"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
<Button
android:id="@+id/buttonSubtract"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:layout_marginStart="16dp"
android:backgroundTint="?attr/colorPrimary"
android:elegantTextHeight="true"
android:text=""
android:textColor="?attr/colorOnPrimary"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<Button
android:id="@+id/button0"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:backgroundTint="?attr/colorSurfaceVariant"
android:elegantTextHeight="true"
android:text="0"
android:textColor="?attr/colorOnSurfaceVariant"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
<Button
android:id="@+id/buttonDot"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:backgroundTint="?attr/colorSurfaceVariant"
android:elegantTextHeight="true"
android:text="."
android:textColor="?attr/colorOnSurfaceVariant"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
<Button
android:id="@+id/buttonBackspace"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:backgroundTint="?attr/colorSurfaceVariant"
android:elegantTextHeight="true"
android:text="⌫"
android:textColor="?attr/colorOnSurfaceVariant"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
<Button
android:id="@+id/buttonAdd"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:layout_marginStart="16dp"
android:backgroundTint="?attr/colorPrimary"
android:elegantTextHeight="true"
android:text="+"
android:textColor="?attr/colorOnPrimary"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<Button
android:id="@+id/buttonClear"
android:layout_width="70dp"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:backgroundTint="?attr/colorPrimary"
android:elegantTextHeight="true"
android:text="C"
android:textColor="?attr/colorOnPrimary"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
<Button
android:id="@+id/buttonEquals"
android:layout_width="match_parent"
android:layout_height="64dp"
android:layout_gravity="bottom|end"
android:layout_marginTop="16dp"
android:backgroundTint="?attr/colorPrimary"
android:elegantTextHeight="true"
android:text="="
android:textColor="?attr/colorOnPrimary"
app:cornerRadius="16dp"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="ButtonStyle,HardcodedText" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</FrameLayout>

View file

@ -33,6 +33,10 @@
android:background="@drawable/rounded_top_corners" android:background="@drawable/rounded_top_corners"
android:gravity="end" android:gravity="end"
android:maxLines="1" android:maxLines="1"
app:autoSizeMaxTextSize="48sp"
app:autoSizeMinTextSize="10sp"
app:autoSizeStepGranularity="2sp"
app:autoSizeTextType="uniform"
android:textColor="?attr/colorOnSurfaceVariant" android:textColor="?attr/colorOnSurfaceVariant"
android:textSize="48sp" android:textSize="48sp"
tools:ignore="ButtonStyle,HardcodedText" /> tools:ignore="ButtonStyle,HardcodedText" />
@ -46,7 +50,11 @@
android:layout_marginEnd="32dp" android:layout_marginEnd="32dp"
android:background="?attr/colorSurfaceVariant" android:background="?attr/colorSurfaceVariant"
android:gravity="end" android:gravity="end"
android:maxLines="1" android:maxLines="2"
app:autoSizeMaxTextSize="48sp"
app:autoSizeMinTextSize="10sp"
app:autoSizeStepGranularity="2sp"
app:autoSizeTextType="uniform"
android:textColor="?attr/colorOnSurfaceVariant" android:textColor="?attr/colorOnSurfaceVariant"
android:textSize="28sp" android:textSize="28sp"
tools:ignore="ButtonStyle,HardcodedText" /> tools:ignore="ButtonStyle,HardcodedText" />
@ -60,7 +68,11 @@
android:layout_marginEnd="32dp" android:layout_marginEnd="32dp"
android:background="@drawable/rounded_bottom_corners" android:background="@drawable/rounded_bottom_corners"
android:gravity="end" android:gravity="end"
android:maxLines="1" android:maxLines="2"
app:autoSizeMaxTextSize="48sp"
app:autoSizeMinTextSize="10sp"
app:autoSizeStepGranularity="2sp"
app:autoSizeTextType="uniform"
android:textColor="?attr/colorOnSurfaceVariant" android:textColor="?attr/colorOnSurfaceVariant"
android:textSize="28sp" android:textSize="28sp"
tools:ignore="ButtonStyle,HardcodedText" /> tools:ignore="ButtonStyle,HardcodedText" />

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -54,11 +54,14 @@
<EditText <EditText
android:id="@+id/editText" android:id="@+id/editText"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="0dp"
android:layout_weight="1"
android:layout_margin="16dp" android:layout_margin="16dp"
android:fontFamily="@font/poppins" android:fontFamily="@font/poppins"
android:inputType="textMultiLine" android:inputType="textMultiLine"
android:padding="16dp" android:padding="16dp"
android:nestedScrollingEnabled="true"
android:gravity="top|start"
android:textColor="?attr/colorOnBackground" android:textColor="?attr/colorOnBackground"
android:textIsSelectable="true" android:textIsSelectable="true"
android:textSize="12sp" android:textSize="12sp"
@ -101,4 +104,4 @@
</LinearLayout> </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </LinearLayout>

View file

@ -10,16 +10,34 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/enter_password" android:hint="@string/enter_password"
android:maxLength="32" android:inputType="numberPassword"
android:inputType="numberPassword" /> android:maxLength="32" />
<EditText <EditText
android:id="@+id/confirmPasswordInput" android:id="@+id/confirmPasswordInput"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:hint="@string/confirm_password" android:hint="@string/confirm_password"
android:inputType="numberPassword" android:inputType="numberPassword"
android:maxLength="32" android:maxLength="32" />
android:layout_marginTop="16dp" />
<CheckBox
android:id="@+id/biometricCheckbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:fontFamily="@font/poppins"
android:text="@string/enable_biometric"
android:textSize="16sp" />
<CheckBox
android:id="@+id/forgotPasswordCheckbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:fontFamily="@font/poppins"
android:text="@string/enable_forgot_password"
android:textSize="16sp" />
</LinearLayout> </LinearLayout>

View file

@ -28,7 +28,7 @@
android:src="@drawable/linear_gradient_bg" android:src="@drawable/linear_gradient_bg"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription" />
<LinearLayout <androidx.core.widget.NestedScrollView
android:id="@+id/textActivityContainer" android:id="@+id/textActivityContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -47,7 +47,7 @@
android:textSize="18sp" android:textSize="18sp"
android:visibility="gone" android:visibility="gone"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
</LinearLayout> </androidx.core.widget.NestedScrollView>
<FrameLayout <FrameLayout
android:id="@+id/leftTouchPanel" android:id="@+id/leftTouchPanel"

View file

@ -1024,4 +1024,9 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
<string name="app_lock_desc">Lock the app with a password\n( ͡° ͜ʖ ͡°)</string> <string name="app_lock_desc">Lock the app with a password\n( ͡° ͜ʖ ͡°)</string>
<string name="confirm_password">Confirm Password</string> <string name="confirm_password">Confirm Password</string>
<string name="password_mismatch">Passwords do not match or are empty!</string> <string name="password_mismatch">Passwords do not match or are empty!</string>
<string name="enable_biometric">Enable Biometric</string>
<string name="bio_prompt_info_title">Biometric Authentication</string>
<string name="bio_prompt_info_desc">Use your fingerprint or face to unlock the app</string>
<string name="enable_forgot_password">Enable Forgot Password (hold clear button for 10 seconds)</string>
</resources> </resources>