diff --git a/.idea/misc.xml b/.idea/misc.xml
index caf674bd0..8309c45df 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,13 +3,15 @@
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5c6214466..78f461918 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -78,6 +78,10 @@
android:label="@string/search" />
+
-
-
diff --git a/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt b/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt
index 63a8692b7..d0d21eb6f 100644
--- a/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/KotatsuApp.kt
@@ -23,6 +23,7 @@ import org.koitharu.kotatsu.local.data.PagesCache
import org.koitharu.kotatsu.local.domain.LocalMangaRepository
import org.koitharu.kotatsu.local.localModule
import org.koitharu.kotatsu.main.mainModule
+import org.koitharu.kotatsu.main.ui.protect.AppProtectHelper
import org.koitharu.kotatsu.reader.readerModule
import org.koitharu.kotatsu.remotelist.remoteListModule
import org.koitharu.kotatsu.search.searchModule
@@ -55,6 +56,7 @@ class KotatsuApp : Application() {
initKoin()
Thread.setDefaultUncaughtExceptionHandler(AppCrashHandler(applicationContext))
AppCompatDelegate.setDefaultNightMode(get().theme)
+ registerActivityLifecycleCallbacks(get())
val widgetUpdater = WidgetUpdater(applicationContext)
FavouritesRepository.subscribe(widgetUpdater)
HistoryRepository.subscribe(widgetUpdater)
diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt
index dae9da771..b4c3ae13d 100644
--- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt
@@ -27,7 +27,6 @@ abstract class BaseActivity : AppCompatActivity(), OnApplyWindo
protected lateinit var binding: B
private set
-
protected val exceptionResolver by lazy(LazyThreadSafetyMode.NONE) {
ExceptionResolver(this, supportFragmentManager)
}
@@ -60,7 +59,9 @@ abstract class BaseActivity : AppCompatActivity(), OnApplyWindo
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
- onWindowInsetsChanged(insets.getInsets(WindowInsetsCompat.Type.systemBars()))
+ val baseInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars())
+ val imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime())
+ onWindowInsetsChanged(Insets.max(baseInsets, imeInsets))
return insets
}
diff --git a/app/src/main/java/org/koitharu/kotatsu/main/MainModule.kt b/app/src/main/java/org/koitharu/kotatsu/main/MainModule.kt
index f8a46d4d6..e8c69d824 100644
--- a/app/src/main/java/org/koitharu/kotatsu/main/MainModule.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/main/MainModule.kt
@@ -13,5 +13,5 @@ val mainModule
single { AppProtectHelper(get()) }
single { ShortcutsRepository(androidContext(), get(), get(), get()) }
viewModel { MainViewModel(get(), get()) }
- viewModel { ProtectViewModel(get()) }
+ viewModel { ProtectViewModel(get(), get()) }
}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt
index e86308b7d..4bb59dd74 100644
--- a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt
@@ -17,7 +17,6 @@ import androidx.fragment.app.Fragment
import androidx.swiperefreshlayout.widget.CircularProgressDrawable
import com.google.android.material.navigation.NavigationView
import com.google.android.material.snackbar.Snackbar
-import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseActivity
@@ -28,7 +27,6 @@ import org.koitharu.kotatsu.databinding.ActivityMainBinding
import org.koitharu.kotatsu.favourites.ui.FavouritesContainerFragment
import org.koitharu.kotatsu.history.ui.HistoryListFragment
import org.koitharu.kotatsu.local.ui.LocalListFragment
-import org.koitharu.kotatsu.main.ui.protect.AppProtectHelper
import org.koitharu.kotatsu.reader.ui.ReaderActivity
import org.koitharu.kotatsu.remotelist.ui.RemoteListFragment
import org.koitharu.kotatsu.search.ui.SearchHelper
@@ -45,17 +43,12 @@ class MainActivity : BaseActivity(),
View.OnClickListener {
private val viewModel by viewModel()
- private val protectHelper by inject()
private lateinit var drawerToggle: ActionBarDrawerToggle
private var closeable: Closeable? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- if (protectHelper.check(this)) {
- finish()
- return
- }
setContentView(ActivityMainBinding.inflate(layoutInflater))
drawerToggle =
ActionBarDrawerToggle(
@@ -93,7 +86,6 @@ class MainActivity : BaseActivity(),
override fun onDestroy() {
closeable?.close()
- protectHelper.lock()
super.onDestroy()
}
diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/AppProtectHelper.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/AppProtectHelper.kt
index 0b71f21bf..ac0172d03 100644
--- a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/AppProtectHelper.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/AppProtectHelper.kt
@@ -1,33 +1,58 @@
package org.koitharu.kotatsu.main.ui.protect
import android.app.Activity
+import android.app.Application
import android.content.Intent
+import android.os.Bundle
import org.koitharu.kotatsu.core.prefs.AppSettings
-import org.koitharu.kotatsu.main.ui.MainActivity
-class AppProtectHelper(private val settings: AppSettings) {
+class AppProtectHelper(private val settings: AppSettings) : Application.ActivityLifecycleCallbacks {
private var isUnlocked = settings.appPassword.isNullOrEmpty()
+ private var activityCounter = 0
- fun unlock(activity: Activity) {
- isUnlocked = true
- with(activity) {
- startActivity(Intent(this, MainActivity::class.java)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
+ override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
+ if (activity is ProtectActivity) {
+ return
+ }
+ activityCounter++
+ if (!isUnlocked) {
+ val sourceIntent = Intent(activity, activity.javaClass)
+ activity.intent?.let {
+ sourceIntent.putExtras(it)
+ sourceIntent.action = it.action
+ sourceIntent.setDataAndType(it.data, it.type)
+ }
+ activity.startActivity(ProtectActivity.newIntent(activity, sourceIntent))
+ activity.finishAfterTransition()
}
}
- fun lock() {
+ override fun onActivityStarted(activity: Activity) = Unit
+
+ override fun onActivityResumed(activity: Activity) = Unit
+
+ override fun onActivityPaused(activity: Activity) = Unit
+
+ override fun onActivityStopped(activity: Activity) = Unit
+
+ override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) = Unit
+
+ override fun onActivityDestroyed(activity: Activity) {
+ if (activity is ProtectActivity) {
+ return
+ }
+ activityCounter--
+ if (activityCounter == 0) {
+ restoreLock()
+ }
+ }
+
+ fun unlock() {
+ isUnlocked = true
+ }
+
+ private fun restoreLock() {
isUnlocked = settings.appPassword.isNullOrEmpty()
}
-
- fun check(activity: Activity): Boolean {
- return if (!isUnlocked) {
- activity.startActivity(ProtectActivity.newIntent(activity)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))
- true
- } else {
- false
- }
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt
index 595defa76..97ca1df3a 100644
--- a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt
@@ -6,13 +6,10 @@ import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.KeyEvent
-import android.view.Menu
-import android.view.MenuItem
+import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.TextView
import androidx.core.graphics.Insets
-import androidx.core.view.updatePadding
-import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseActivity
@@ -20,50 +17,49 @@ import org.koitharu.kotatsu.databinding.ActivityProtectBinding
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
class ProtectActivity : BaseActivity(), TextView.OnEditorActionListener,
- TextWatcher {
+ TextWatcher, View.OnClickListener {
private val viewModel by viewModel()
- private val appProtectHelper by inject()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivityProtectBinding.inflate(layoutInflater))
binding.editPassword.setOnEditorActionListener(this)
binding.editPassword.addTextChangedListener(this)
- supportActionBar?.run {
- setDisplayHomeAsUpEnabled(true)
- setHomeAsUpIndicator(R.drawable.ic_cross)
- }
+ binding.buttonNext.setOnClickListener(this)
+ binding.buttonCancel.setOnClickListener(this)
viewModel.onError.observe(this, this::onError)
viewModel.isLoading.observe(this, this::onLoadingStateChanged)
- viewModel.onUnlockSuccess.observe(this, this::onUnlockSuccess)
- }
-
- override fun onCreateOptionsMenu(menu: Menu?): Boolean {
- menuInflater.inflate(R.menu.opt_protect, menu)
- return super.onCreateOptionsMenu(menu)
- }
-
- override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
- R.id.action_done -> {
- viewModel.tryUnlock(binding.editPassword.text.toString().orEmpty())
- true
+ viewModel.onUnlockSuccess.observe(this) {
+ val intent = intent.getParcelableExtra(EXTRA_INTENT)
+ startActivity(intent)
+ finishAfterTransition()
}
- else -> super.onOptionsItemSelected(item)
+
+ binding.editPassword.requestFocus()
}
override fun onWindowInsetsChanged(insets: Insets) {
- binding.toolbar.updatePadding(
- left = insets.left,
- right = insets.right,
- top = insets.top
+ val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
+ binding.root.setPadding(
+ basePadding + insets.left,
+ basePadding + insets.top,
+ basePadding + insets.right,
+ basePadding + insets.bottom
)
}
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_next -> viewModel.tryUnlock(binding.editPassword.text?.toString().orEmpty())
+ R.id.button_cancel -> finish()
+ }
+ }
+
override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
- return if (actionId == EditorInfo.IME_ACTION_DONE) {
- viewModel.tryUnlock(binding.editPassword.text.toString().orEmpty())
+ return if (actionId == EditorInfo.IME_ACTION_DONE && binding.buttonNext.isEnabled) {
+ binding.buttonNext.performClick()
true
} else {
false
@@ -76,10 +72,7 @@ class ProtectActivity : BaseActivity(), TextView.OnEdito
override fun afterTextChanged(s: Editable?) {
binding.layoutPassword.error = null
- }
-
- private fun onUnlockSuccess(unit: Unit) {
- appProtectHelper.unlock(this)
+ binding.buttonNext.isEnabled = !s.isNullOrEmpty()
}
private fun onError(e: Throwable) {
@@ -92,6 +85,11 @@ class ProtectActivity : BaseActivity(), TextView.OnEdito
companion object {
- fun newIntent(context: Context) = Intent(context, ProtectActivity::class.java)
+ private const val EXTRA_INTENT = "src_intent"
+
+ fun newIntent(context: Context, sourceIntent: Intent): Intent {
+ return Intent(context, ProtectActivity::class.java)
+ .putExtra(EXTRA_INTENT, sourceIntent)
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt
index 3957fa797..ca1c9cbd1 100644
--- a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt
@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.main.ui.protect
+import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import org.koitharu.kotatsu.base.ui.BaseViewModel
import org.koitharu.kotatsu.core.exceptions.WrongPasswordException
@@ -8,16 +9,23 @@ import org.koitharu.kotatsu.utils.SingleLiveEvent
import org.koitharu.kotatsu.utils.ext.md5
class ProtectViewModel(
- private val settings: AppSettings
+ private val settings: AppSettings,
+ private val protectHelper: AppProtectHelper,
) : BaseViewModel() {
+ private var job: Job? = null
+
val onUnlockSuccess = SingleLiveEvent()
fun tryUnlock(password: String) {
- launchLoadingJob {
+ if (job?.isActive == true) {
+ return
+ }
+ job = launchLoadingJob {
val passwordHash = password.md5()
val appPasswordHash = settings.appPassword
if (passwordHash == appPasswordHash) {
+ protectHelper.unlock()
onUnlockSuccess.call(Unit)
} else {
delay(PASSWORD_COMPARE_DELAY)
diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/MainSettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/MainSettingsFragment.kt
index 0d6223e85..c1a4a104d 100644
--- a/app/src/main/java/org/koitharu/kotatsu/settings/MainSettingsFragment.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/settings/MainSettingsFragment.kt
@@ -1,6 +1,7 @@
package org.koitharu.kotatsu.settings
import android.content.DialogInterface
+import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import android.text.InputType
@@ -17,6 +18,7 @@ import org.koitharu.kotatsu.base.ui.dialog.TextInputDialog
import org.koitharu.kotatsu.core.model.MangaSource
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.ListMode
+import org.koitharu.kotatsu.settings.protect.ProtectSetupActivity
import org.koitharu.kotatsu.utils.ext.*
import java.io.File
@@ -77,6 +79,10 @@ class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
?: getString(R.string.not_available)
}
}
+ AppSettings.KEY_APP_PASSWORD -> {
+ findPreference(AppSettings.KEY_PROTECT_APP)
+ ?.isChecked = !settings.appPassword.isNullOrEmpty()
+ }
}
}
@@ -102,8 +108,10 @@ class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
true
}
AppSettings.KEY_PROTECT_APP -> {
- if ((preference as? SwitchPreference ?: return false).isChecked) {
- enableAppProtection(preference)
+ val pref = (preference as? SwitchPreference ?: return false)
+ if (pref.isChecked) {
+ pref.isChecked = false
+ startActivity(Intent(preference.context, ProtectSetupActivity::class.java))
} else {
settings.appPassword = null
}
diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/SettingsModule.kt b/app/src/main/java/org/koitharu/kotatsu/settings/SettingsModule.kt
index 3e45efd24..222f20258 100644
--- a/app/src/main/java/org/koitharu/kotatsu/settings/SettingsModule.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/settings/SettingsModule.kt
@@ -9,6 +9,7 @@ import org.koitharu.kotatsu.core.backup.RestoreRepository
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.settings.backup.BackupViewModel
import org.koitharu.kotatsu.settings.backup.RestoreViewModel
+import org.koitharu.kotatsu.settings.protect.ProtectSetupViewModel
val settingsModule
get() = module {
@@ -19,4 +20,5 @@ val settingsModule
viewModel { BackupViewModel(get(), androidContext()) }
viewModel { (uri: Uri?) -> RestoreViewModel(uri, get(), androidContext()) }
+ viewModel { ProtectSetupViewModel(get()) }
}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt b/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt
new file mode 100644
index 000000000..5ab950d69
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt
@@ -0,0 +1,97 @@
+package org.koitharu.kotatsu.settings.protect
+
+import android.os.Bundle
+import android.text.Editable
+import android.text.TextWatcher
+import android.view.KeyEvent
+import android.view.View
+import android.view.inputmethod.EditorInfo
+import android.widget.TextView
+import androidx.core.graphics.Insets
+import androidx.core.view.isGone
+import org.koin.androidx.viewmodel.ext.android.viewModel
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.base.ui.BaseActivity
+import org.koitharu.kotatsu.databinding.ActivitySetupProtectBinding
+
+class ProtectSetupActivity : BaseActivity(), TextWatcher,
+ View.OnClickListener, TextView.OnEditorActionListener {
+
+ private val viewModel by viewModel()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(ActivitySetupProtectBinding.inflate(layoutInflater))
+ binding.editPassword.addTextChangedListener(this)
+ binding.editPassword.setOnEditorActionListener(this)
+ binding.buttonNext.setOnClickListener(this)
+ binding.buttonCancel.setOnClickListener(this)
+
+ viewModel.isSecondStep.observe(this, this::onStepChanged)
+ viewModel.onPasswordSet.observe(this) {
+ finishAfterTransition()
+ }
+ viewModel.onPasswordMismatch.observe(this) {
+ binding.editPassword.error = getString(R.string.passwords_mismatch)
+ }
+ viewModel.onClearText.observe(this) {
+ binding.editPassword.text?.clear()
+ }
+ }
+
+ override fun onWindowInsetsChanged(insets: Insets) {
+ val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
+ binding.root.setPadding(
+ basePadding + insets.left,
+ basePadding + insets.top,
+ basePadding + insets.right,
+ basePadding + insets.bottom
+ )
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_cancel -> finish()
+ R.id.button_next -> viewModel.onNextClick(
+ password = binding.editPassword.text?.toString() ?: return
+ )
+ }
+ }
+
+ override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
+ return if (actionId == EditorInfo.IME_ACTION_DONE && binding.buttonNext.isEnabled) {
+ binding.buttonNext.performClick()
+ true
+ } else {
+ false
+ }
+ }
+
+ override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
+
+ override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
+
+ override fun afterTextChanged(s: Editable?) {
+ binding.editPassword.error = null
+ val isEnoughLength = (s?.length ?: 0) >= MIN_PASSWORD_LENGTH
+ binding.buttonNext.isEnabled = isEnoughLength
+ binding.layoutPassword.isHelperTextEnabled =
+ !isEnoughLength || viewModel.isSecondStep.value == true
+ }
+
+ private fun onStepChanged(isSecondStep: Boolean) {
+ binding.buttonCancel.isGone = isSecondStep
+ if (isSecondStep) {
+ binding.layoutPassword.helperText = getString(R.string.repeat_password)
+ binding.buttonNext.setText(R.string.confirm)
+ } else {
+ binding.layoutPassword.helperText = getString(R.string.password_length_hint)
+ binding.buttonNext.setText(R.string.next)
+ }
+ }
+
+ private companion object {
+
+ const val MIN_PASSWORD_LENGTH = 4
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt
new file mode 100644
index 000000000..0e3950a24
--- /dev/null
+++ b/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt
@@ -0,0 +1,38 @@
+package org.koitharu.kotatsu.settings.protect
+
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.map
+import org.koitharu.kotatsu.base.ui.BaseViewModel
+import org.koitharu.kotatsu.core.prefs.AppSettings
+import org.koitharu.kotatsu.utils.SingleLiveEvent
+import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
+import org.koitharu.kotatsu.utils.ext.md5
+
+class ProtectSetupViewModel(
+ private val settings: AppSettings
+) : BaseViewModel() {
+
+ private val firstPassword = MutableStateFlow(null)
+
+ val isSecondStep = firstPassword.map {
+ it != null
+ }.asLiveDataDistinct(viewModelScope.coroutineContext)
+ val onPasswordSet = SingleLiveEvent()
+ val onPasswordMismatch = SingleLiveEvent()
+ val onClearText = SingleLiveEvent()
+
+ fun onNextClick(password: String) {
+ if (firstPassword.value == null) {
+ firstPassword.value = password
+ onClearText.call(Unit)
+ } else {
+ if (firstPassword.value == password) {
+ settings.appPassword = password.md5()
+ onPasswordSet.call(Unit)
+ } else {
+ onPasswordMismatch.call(Unit)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml
new file mode 100644
index 000000000..220e1b503
--- /dev/null
+++ b/app/src/main/res/drawable/ic_lock.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_protect.xml b/app/src/main/res/layout/activity_protect.xml
index a218369c1..b17229948 100644
--- a/app/src/main/res/layout/activity_protect.xml
+++ b/app/src/main/res/layout/activity_protect.xml
@@ -1,47 +1,80 @@
-
+ android:padding="@dimen/screen_padding">
-
+ android:layout_marginTop="8dp"
+ android:drawablePadding="16dp"
+ android:gravity="center_horizontal"
+ android:text="@string/app_name"
+ android:textAppearance="?textAppearanceHeadline5"
+ app:drawableTint="?colorPrimary"
+ app:drawableTopCompat="@drawable/ic_lock"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
-
-
-
+
+ android:layout_marginTop="30dp"
+ app:errorIconDrawable="@null"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/textView_subtitle">
+ android:inputType="textPassword"
+ android:maxLength="24"
+ android:singleLine="true"
+ android:textAlignment="center"
+ android:textSize="16sp"
+ tools:text="1234" />
-
\ No newline at end of file
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_setup_protect.xml b/app/src/main/res/layout/activity_setup_protect.xml
new file mode 100644
index 000000000..7f3aae3c8
--- /dev/null
+++ b/app/src/main/res/layout/activity_setup_protect.xml
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/opt_protect.xml b/app/src/main/res/menu/opt_protect.xml
deleted file mode 100644
index 425f8e7dc..000000000
--- a/app/src/main/res/menu/opt_protect.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 5b8286062..68cbcb6e9 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -201,4 +201,8 @@
Для просмотра этого контента требуется авторизация
По умолчанию: %s
…и ещё %1$d
+ Далее
+ Enter password that will be required when the application starts
+ Confirm
+ Password must be at least 4 characters
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 1c8ad4b37..ee61388a6 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -9,4 +9,5 @@
34dp
16dp
48dp
+ 16dp
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9ecd2811c..161e209c5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -203,4 +203,8 @@
You should authorize to view this content
Default: %s
…and %1$d more
+ Next
+ Enter password that will be required when the application starts
+ Confirm
+ Password must be at least 4 characters
\ No newline at end of file