mirror of
https://github.com/twofas/2fas-android.git
synced 2025-01-05 14:05:30 +01:00
Update strings and clean up
This commit is contained in:
parent
2c268ea70e
commit
cc96b58f1f
@ -118,11 +118,6 @@
|
||||
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".features.main.MainServicesActivity"
|
||||
android:label="Services List"
|
||||
android:launchMode="singleTask" />
|
||||
|
||||
<activity
|
||||
android:name=".features.addserviceqr.AddServiceQrActivity"
|
||||
android:label="Add service by scanning QR Code" />
|
||||
|
@ -12,9 +12,6 @@ import com.twofasapp.features.backup.BackupPresenter
|
||||
import com.twofasapp.features.backup.import.ImportBackupActivity
|
||||
import com.twofasapp.features.backup.import.ImportBackupContract
|
||||
import com.twofasapp.features.backup.import.ImportBackupPresenter
|
||||
import com.twofasapp.features.main.MainContract
|
||||
import com.twofasapp.features.main.MainPresenter
|
||||
import com.twofasapp.features.main.MainServicesActivity
|
||||
import com.twofasapp.features.navigator.ActivityScopedNavigator
|
||||
import com.twofasapp.prefs.ScopedNavigator
|
||||
import com.twofasapp.widgets.configure.WidgetSettingsActivity
|
||||
@ -38,23 +35,6 @@ val activityScopeModule = module {
|
||||
|
||||
factory<ScopedNavigator> { ActivityScopedNavigator(get(), get()) }
|
||||
|
||||
activityScope<MainServicesActivity> {
|
||||
scoped<MainContract.Presenter> {
|
||||
MainPresenter(
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
get(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
activityScope<AddServiceQrActivity> {
|
||||
scoped<AddServiceQrContract.Presenter> {
|
||||
AddServiceQrPresenter(
|
||||
|
@ -1,38 +0,0 @@
|
||||
package com.twofasapp.features.main
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Point
|
||||
import android.util.AttributeSet
|
||||
import android.view.WindowManager
|
||||
import androidx.customview.widget.ViewDragHelper
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
import kotlin.math.max
|
||||
|
||||
class EdgeDrawerLayout : DrawerLayout {
|
||||
|
||||
private val swipeEdgeSize by lazy {
|
||||
val displaySize = Point()
|
||||
(context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay.getSize(displaySize)
|
||||
(displaySize.x * 0.2).toInt()
|
||||
}
|
||||
|
||||
constructor(context: Context) : this(context, null, 0)
|
||||
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
|
||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
||||
context,
|
||||
attrs,
|
||||
defStyleAttr
|
||||
)
|
||||
|
||||
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
|
||||
super.onLayout(changed, l, t, r, b)
|
||||
val leftDraggerField = DrawerLayout::class.java.getDeclaredField("mLeftDragger")
|
||||
leftDraggerField.isAccessible = true
|
||||
val viewDragHelper = leftDraggerField[this] as ViewDragHelper
|
||||
|
||||
val edgeSizeField = ViewDragHelper::class.java.getDeclaredField("mEdgeSize")
|
||||
edgeSizeField.isAccessible = true
|
||||
val origEdgeSize = edgeSizeField[viewDragHelper] as Int
|
||||
edgeSizeField.setInt(viewDragHelper, max(swipeEdgeSize, origEdgeSize))
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package com.twofasapp.features.main
|
||||
|
||||
import com.twofasapp.design.dialogs.CancelAction
|
||||
import com.twofasapp.design.dialogs.ConfirmAction
|
||||
import com.twofasapp.prefs.model.ServiceDto
|
||||
|
||||
interface MainContract {
|
||||
|
||||
interface View {
|
||||
fun showRateApp()
|
||||
fun showUpgradeAppNoticeDialog(action: () -> Unit)
|
||||
fun showServiceExistsDialog(confirmAction: ConfirmAction, cancelAction: CancelAction)
|
||||
fun showRemoveQrReminder(serviceDto: ServiceDto)
|
||||
}
|
||||
|
||||
abstract class Presenter : com.twofasapp.base.BasePresenter() {
|
||||
abstract fun startObservingPushes()
|
||||
abstract fun stopObservingPushes()
|
||||
abstract fun onReviewSuccess()
|
||||
abstract fun onReviewFailed(exception: Exception?)
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
package com.twofasapp.features.main
|
||||
|
||||
import com.twofasapp.core.analytics.AnalyticsService
|
||||
import com.twofasapp.prefs.ScopedNavigator
|
||||
import com.twofasapp.services.domain.ConvertOtpLinkToService
|
||||
import com.twofasapp.services.domain.StoreHotpServices
|
||||
import com.twofasapp.usecases.rateapp.RateAppCondition
|
||||
import com.twofasapp.usecases.rateapp.UpdateRateAppStatus
|
||||
import com.twofasapp.usecases.services.AddService
|
||||
import com.twofasapp.usecases.services.GetServices
|
||||
import com.twofasapp.usecases.totp.ParseOtpAuthLink
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
|
||||
class MainPresenter(
|
||||
private val view: MainContract.View,
|
||||
private val navigator: ScopedNavigator,
|
||||
private val getServices: GetServices,
|
||||
private val updateRateAppStatus: UpdateRateAppStatus,
|
||||
private val storeHotpServices: StoreHotpServices,
|
||||
private val addService: AddService,
|
||||
private val parseOtpAuthLink: ParseOtpAuthLink,
|
||||
private val convertOtpLinkToService: ConvertOtpLinkToService,
|
||||
private val rateAppCondition: RateAppCondition,
|
||||
private val analyticsService: AnalyticsService,
|
||||
) : MainContract.Presenter() {
|
||||
|
||||
private val watchDisposables = CompositeDisposable()
|
||||
|
||||
override fun onViewAttached() {
|
||||
storeHotpServices.clear()
|
||||
updateRateAppStatus.incrementCounter()
|
||||
|
||||
when {
|
||||
rateAppCondition.execute() -> view.showRateApp()
|
||||
}
|
||||
}
|
||||
|
||||
override fun startObservingPushes() {
|
||||
}
|
||||
|
||||
override fun stopObservingPushes() {
|
||||
watchDisposables.clear()
|
||||
}
|
||||
|
||||
private fun saveService(incomingData: String) {
|
||||
parseOtpAuthLink.execute(ParseOtpAuthLink.Params(incomingData))
|
||||
.map { convertOtpLinkToService.execute(it) }
|
||||
.flatMapCompletable { addService.execute(AddService.Params(it)) }
|
||||
.andThen(getServices.execute())
|
||||
.subscribe({ }, {})
|
||||
.addToDisposables()
|
||||
}
|
||||
|
||||
override fun onReviewSuccess() {
|
||||
updateRateAppStatus.markShown()
|
||||
}
|
||||
|
||||
override fun onReviewFailed(exception: Exception?) {
|
||||
analyticsService.captureException(exception)
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,218 +0,0 @@
|
||||
package com.twofasapp.features.main
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.google.android.play.core.review.ReviewManagerFactory
|
||||
import com.twofasapp.base.BaseActivityPresenter
|
||||
import com.twofasapp.base.lifecycle.AuthAware
|
||||
import com.twofasapp.databinding.ActivityMainBinding
|
||||
import com.twofasapp.design.dialogs.CancelAction
|
||||
import com.twofasapp.design.dialogs.ConfirmAction
|
||||
import com.twofasapp.design.dialogs.ConfirmDialog
|
||||
import com.twofasapp.features.addserviceqr.AddServiceQrActivity
|
||||
import com.twofasapp.features.addserviceqr.ScanInfoDialog
|
||||
import com.twofasapp.prefs.model.ServiceDto
|
||||
import com.twofasapp.resources.R
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import lt.neworld.spanner.Spanner
|
||||
import lt.neworld.spanner.Spans
|
||||
|
||||
class MainServicesActivity : BaseActivityPresenter<ActivityMainBinding>(), MainContract.View, AuthAware {
|
||||
|
||||
private val presenter: MainContract.Presenter by injectThis()
|
||||
|
||||
// private val fetchTokenRequestsCase: FetchTokenRequestsCase by inject()
|
||||
// private val observeMobileDeviceCase: ObserveMobileDeviceCase by inject()
|
||||
private val authenticationDialogs = mutableMapOf<String, MaterialDialog>()
|
||||
private val removeQrReminderDialog: ScanInfoDialog by lazy { ScanInfoDialog(this) }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(ActivityMainBinding::inflate)
|
||||
setPresenter(presenter)
|
||||
|
||||
|
||||
lifecycleScope.launch {
|
||||
lifecycle.repeatOnLifecycle(Lifecycle.State.CREATED) {
|
||||
launch(Dispatchers.IO) {
|
||||
// launch(Dispatchers.IO) {
|
||||
//
|
||||
// try {
|
||||
// val mobileDevice = observeMobileDeviceCase.invoke().first()
|
||||
// val tokenRequests = fetchTokenRequestsCase(mobileDevice.id)
|
||||
//
|
||||
//
|
||||
// tokenRequests.forEach { tokenRequest ->
|
||||
// val domain = DomainMatcher.extractDomain(tokenRequest.domain)
|
||||
// val matchedServices = DomainMatcher.findServicesMatchingDomain(
|
||||
// getServicesCase(),
|
||||
// domain
|
||||
// )
|
||||
//
|
||||
// runOnUiThread {
|
||||
// if (authenticationDialogs.containsKey(tokenRequest.requestId)
|
||||
// .not()
|
||||
// ) {
|
||||
// authenticationDialogs.put(
|
||||
// tokenRequest.requestId,
|
||||
// MaterialDialog(this@MainServicesActivity)
|
||||
// .title(text = getString(R.string.browser__2fa_token_request_title))
|
||||
// .message(text = getString(R.string.browser__2fa_token_request_content).plus(" ${tokenRequest.domain}?"))
|
||||
// .cancelable(false)
|
||||
// .positiveButton(text = getString(R.string.extension__approve)) {
|
||||
// val isOneDomainMatched =
|
||||
// matchedServices.size == 1
|
||||
// val serviceId =
|
||||
// if (matchedServices.size == 1) matchedServices.first().id else null
|
||||
//
|
||||
// if (isOneDomainMatched) {
|
||||
// val payload =
|
||||
// BrowserExtensionRequestPayload(
|
||||
// action = BrowserExtensionRequestPayload.Action.Approve,
|
||||
// notificationId = -1,
|
||||
// extensionId = tokenRequest.extensionId,
|
||||
// requestId = tokenRequest.requestId,
|
||||
// serviceId = serviceId ?: -1,
|
||||
// domain = domain,
|
||||
// )
|
||||
// sendBroadcast(
|
||||
// BrowserExtensionRequestReceiver.createIntent(
|
||||
// this@MainServicesActivity,
|
||||
// payload
|
||||
// )
|
||||
// )
|
||||
// } else {
|
||||
//
|
||||
// val contentIntent = Intent(
|
||||
// this@MainServicesActivity,
|
||||
// BrowserExtensionRequestActivity::class.java
|
||||
// ).apply {
|
||||
// flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||
//
|
||||
// putExtra(
|
||||
// BrowserExtensionRequestPayload.Key,
|
||||
// BrowserExtensionRequestPayload(
|
||||
// action = BrowserExtensionRequestPayload.Action.Approve,
|
||||
// notificationId = -1,
|
||||
// extensionId = tokenRequest.extensionId,
|
||||
// requestId = tokenRequest.requestId,
|
||||
// serviceId = serviceId ?: -1,
|
||||
// domain = domain,
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// startActivity(contentIntent)
|
||||
// }
|
||||
// }
|
||||
// .negativeButton(text = getString(R.string.extension__deny)) {
|
||||
// val payload = BrowserExtensionRequestPayload(
|
||||
// action = BrowserExtensionRequestPayload.Action.Deny,
|
||||
// notificationId = -1,
|
||||
// extensionId = tokenRequest.extensionId,
|
||||
// requestId = tokenRequest.requestId,
|
||||
// serviceId = -1,
|
||||
// domain = domain,
|
||||
// )
|
||||
// sendBroadcast(
|
||||
// BrowserExtensionRequestReceiver.createIntent(
|
||||
// this@MainServicesActivity,
|
||||
// payload
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
// .show { }
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } catch (e: Exception) {
|
||||
// e.printStackTrace()
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAuthenticated() {
|
||||
presenter.startObservingPushes()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
presenter.stopObservingPushes()
|
||||
authenticationDialogs.forEach { it.value.dismiss() }
|
||||
authenticationDialogs.clear()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
|
||||
if (resultCode != RESULT_OK) return
|
||||
|
||||
|
||||
if (requestCode == AddServiceQrActivity.REQUEST_CODE) {
|
||||
val isFromGallery =
|
||||
data?.getBooleanExtra(AddServiceQrActivity.RESULT_IS_FROM_GALLERY, false) ?: false
|
||||
data?.getParcelableExtra<ServiceDto>(AddServiceQrActivity.RESULT_SERVICE)?.let {
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
override fun showRemoveQrReminder(serviceDto: ServiceDto) {
|
||||
val desc = Spanner()
|
||||
.append(getString(R.string.tokens__gallery_advice_content_first))
|
||||
.append(getString(R.string.tokens__gallery_advice_content_middle_bold), Spans.bold())
|
||||
.append(getString(R.string.tokens__gallery_advice_content_last))
|
||||
|
||||
removeQrReminderDialog.show(
|
||||
title = getString(R.string.tokens__gallery_advice_title),
|
||||
desc = "",
|
||||
descSpan = desc,
|
||||
okText = getString(R.string.commons__got_it),
|
||||
imageRes = R.drawable.remove_qr_reminder_image,
|
||||
showCancel = false,
|
||||
action = { removeQrReminderDialog.dismiss() },
|
||||
actionDismiss = { },
|
||||
)
|
||||
}
|
||||
|
||||
override fun showRateApp() {
|
||||
val manager = ReviewManagerFactory.create(this)
|
||||
val request = manager.requestReviewFlow()
|
||||
request.addOnCompleteListener { task ->
|
||||
if (task.isSuccessful) {
|
||||
val flow = manager.launchReviewFlow(this, task.result)
|
||||
flow.addOnCompleteListener {
|
||||
presenter.onReviewSuccess()
|
||||
}
|
||||
} else {
|
||||
presenter.onReviewFailed(task.exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun showUpgradeAppNoticeDialog(action: () -> Unit) {
|
||||
ConfirmDialog(
|
||||
context = this,
|
||||
title = getString(R.string.update_app_title),
|
||||
msg = getString(R.string.update_app_msg),
|
||||
positiveButtonText = "Update",
|
||||
negativeButtonText = "Later",
|
||||
).show(
|
||||
confirmAction = { action() }
|
||||
)
|
||||
}
|
||||
|
||||
override fun showServiceExistsDialog(confirmAction: ConfirmAction, cancelAction: CancelAction) {
|
||||
ConfirmDialog(this, R.string.commons__warning, R.string.tokens__service_already_exists)
|
||||
.show(confirmAction = confirmAction, cancelAction = cancelAction)
|
||||
}
|
||||
}
|
@ -14,13 +14,13 @@ import com.twofasapp.extensions.toastLong
|
||||
import com.twofasapp.features.addserviceqr.AddServiceQrActivity
|
||||
import com.twofasapp.features.backup.BackupActivity
|
||||
import com.twofasapp.features.backup.import.ImportBackupActivity
|
||||
import com.twofasapp.features.main.MainServicesActivity
|
||||
import com.twofasapp.prefs.ScopedNavigator
|
||||
import com.twofasapp.prefs.model.CheckLockStatus
|
||||
import com.twofasapp.prefs.model.LockMethodEntity
|
||||
import com.twofasapp.prefs.model.ServiceDto
|
||||
import com.twofasapp.resources.R
|
||||
import com.twofasapp.security.ui.lock.LockActivity
|
||||
import com.twofasapp.ui.main.MainActivity
|
||||
|
||||
|
||||
class ActivityScopedNavigator(
|
||||
@ -58,7 +58,7 @@ class ActivityScopedNavigator(
|
||||
}
|
||||
|
||||
override fun openMain() {
|
||||
activity.startActivity<MainServicesActivity>()
|
||||
activity.startActivity<MainActivity>()
|
||||
}
|
||||
|
||||
override fun openGooglePlay() {
|
||||
|
@ -154,4 +154,71 @@ class MainActivity : AppCompatActivity(), AuthAware {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
// super.onActivityResult(requestCode, resultCode, data)
|
||||
//
|
||||
// if (resultCode != RESULT_OK) return
|
||||
//
|
||||
//
|
||||
// if (requestCode == AddServiceQrActivity.REQUEST_CODE) {
|
||||
// val isFromGallery =
|
||||
// data?.getBooleanExtra(AddServiceQrActivity.RESULT_IS_FROM_GALLERY, false) ?: false
|
||||
// data?.getParcelableExtra<ServiceDto>(AddServiceQrActivity.RESULT_SERVICE)?.let {
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun showRemoveQrReminder(serviceDto: ServiceDto) {
|
||||
// val desc = Spanner()
|
||||
// .append(getString(R.string.tokens__gallery_advice_content_first))
|
||||
// .append(getString(R.string.tokens__gallery_advice_content_middle_bold), Spans.bold())
|
||||
// .append(getString(R.string.tokens__gallery_advice_content_last))
|
||||
//
|
||||
// removeQrReminderDialog.show(
|
||||
// title = getString(R.string.tokens__gallery_advice_title),
|
||||
// desc = "",
|
||||
// descSpan = desc,
|
||||
// okText = getString(R.string.commons__got_it),
|
||||
// imageRes = R.drawable.remove_qr_reminder_image,
|
||||
// showCancel = false,
|
||||
// action = { removeQrReminderDialog.dismiss() },
|
||||
// actionDismiss = { },
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// override fun showRateApp() {
|
||||
// val manager = ReviewManagerFactory.create(this)
|
||||
// val request = manager.requestReviewFlow()
|
||||
// request.addOnCompleteListener { task ->
|
||||
// if (task.isSuccessful) {
|
||||
// val flow = manager.launchReviewFlow(this, task.result)
|
||||
// flow.addOnCompleteListener {
|
||||
// presenter.onReviewSuccess()
|
||||
// }
|
||||
// } else {
|
||||
// presenter.onReviewFailed(task.exception)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun showUpgradeAppNoticeDialog(action: () -> Unit) {
|
||||
// ConfirmDialog(
|
||||
// context = this,
|
||||
// title = getString(R.string.update_app_title),
|
||||
// msg = getString(R.string.update_app_msg),
|
||||
// positiveButtonText = "Update",
|
||||
// negativeButtonText = "Later",
|
||||
// ).show(
|
||||
// confirmAction = { action() }
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// override fun showServiceExistsDialog(confirmAction: ConfirmAction, cancelAction: CancelAction) {
|
||||
// ConfirmDialog(this, R.string.commons__warning, R.string.tokens__service_already_exists)
|
||||
// .show(confirmAction = confirmAction, cancelAction = cancelAction)
|
||||
// }
|
||||
}
|
@ -1,176 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.twofasapp.features.main.EdgeDrawerLayout 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:id="@+id/drawerLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="false">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/coordinator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/Toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:menu="@menu/menu_services"
|
||||
app:title=" " />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<fragment
|
||||
android:name="com.twofasapp.features.services.ServicesFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:tag="ServicesFragment"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||
|
||||
<View
|
||||
android:id="@+id/fabMenuMask"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#78000000"
|
||||
android:contentDescription="@string/commons__cancel"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/fabLayout1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginBottom="@dimen/fab_distance_second"
|
||||
android:contentDescription="@string/tokens__fab_addmanually"
|
||||
android:gravity="center_vertical"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fab1Label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_fab_label"
|
||||
android:clickable="false"
|
||||
android:paddingStart="@dimen/fab_label_padding_horizontal"
|
||||
android:paddingTop="@dimen/fab_label_padding_vertical"
|
||||
android:paddingEnd="@dimen/fab_label_padding_horizontal"
|
||||
android:paddingBottom="@dimen/fab_label_padding_vertical"
|
||||
android:text="@string/tokens__fab_addmanually"
|
||||
android:textColor="#FFF"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
android:clickable="false"
|
||||
android:contentDescription="@string/tokens__fab_addmanually"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/ic_add_service_manually"
|
||||
app:backgroundTint="@color/material_white"
|
||||
app:fabSize="mini" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/fabLayout2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginBottom="@dimen/fab_distance_first"
|
||||
android:contentDescription="@string/commons__scan_qr_code"
|
||||
android:gravity="center_vertical"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fab2Label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_fab_label"
|
||||
android:clickable="false"
|
||||
android:paddingStart="@dimen/fab_label_padding_horizontal"
|
||||
android:paddingTop="@dimen/fab_label_padding_vertical"
|
||||
android:paddingEnd="@dimen/fab_label_padding_horizontal"
|
||||
android:paddingBottom="@dimen/fab_label_padding_vertical"
|
||||
android:text="@string/commons__scan_qr_code"
|
||||
android:textColor="#FFF"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
android:clickable="false"
|
||||
android:contentDescription="@string/commons__scan_qr_code"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/ic_add_service_qr"
|
||||
app:backgroundTint="@color/material_white"
|
||||
app:fabSize="mini" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
android:contentDescription="@string/commons__add"
|
||||
android:src="@drawable/ic_add_old"
|
||||
app:backgroundTint="@color/colorAccent"
|
||||
app:fabSize="normal"
|
||||
app:tint="@color/white" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/syncFab"
|
||||
style="@style/ImageButtonIcon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_gravity="bottom|start"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
android:background="@drawable/fab_sync"
|
||||
android:elevation="8dp"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_sync_off"
|
||||
android:visibility="gone"
|
||||
app:layout_dodgeInsetEdges="bottom"
|
||||
app:tint="@color/fabNeutralIcon" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/toolbarTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?android:actionBarSize"
|
||||
android:gravity="center"
|
||||
android:paddingHorizontal="72dp"
|
||||
android:text="@string/commons__2fas_toolbar"
|
||||
android:textAppearance="@style/Toolbar.Title.TextAppearance"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</com.twofasapp.features.main.EdgeDrawerLayout>
|
@ -6,8 +6,8 @@ object AppConfig {
|
||||
const val compileSdk = 33
|
||||
|
||||
private const val verMajor = 4
|
||||
private const val verMinor = 2
|
||||
private const val verPatch = 8
|
||||
private const val verMinor = 5
|
||||
private const val verPatch = 0
|
||||
private const val verInternal = 0
|
||||
|
||||
const val versionCode = verMajor * 1000000 + verMinor * 10000 + verPatch * 100 + verInternal
|
||||
|
@ -11,6 +11,7 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.twofasapp.designsystem.TwTheme
|
||||
|
||||
@ -38,7 +39,7 @@ fun RowScope.TwNavigationBarItem(
|
||||
NavigationBarItem(
|
||||
selected = selected,
|
||||
onClick = onClick,
|
||||
label = { Text(text) },
|
||||
label = { Text(text, maxLines = 1, overflow = TextOverflow.Ellipsis) },
|
||||
icon = {
|
||||
BadgedBox(badge = {
|
||||
if (showBadge) {
|
||||
|
@ -89,12 +89,14 @@ fun DsService(
|
||||
.background(containerColor)
|
||||
.combinedClickable(
|
||||
enabled = onClick != null,
|
||||
onClick = { onClick?.invoke() },
|
||||
onLongClick = {
|
||||
onClick = {
|
||||
if (editMode.not()) {
|
||||
onLongClick?.invoke()
|
||||
onClick?.invoke()
|
||||
}
|
||||
},
|
||||
onLongClick = {
|
||||
onLongClick?.invoke()
|
||||
},
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp)
|
||||
|
@ -28,6 +28,10 @@ class Strings(c: Context) {
|
||||
val commonApprove = c.getString(R.string.commons__approve)
|
||||
val commonDeny = c.getString(R.string.commons__deny)
|
||||
|
||||
val bottomBarTokens = c.getString(R.string.commons__tokens)
|
||||
val bottomBarSettings = c.getString(R.string.settings__settings)
|
||||
val bottomBarNotifications = c.getString(R.string.commons__notifications)
|
||||
|
||||
val startupTermsLabel = c.getString(R.string.introduction__tos)
|
||||
val startupStepOneHeader = c.getString(R.string.introduction__page_1_title)
|
||||
val startupStepOneBody = c.getString(R.string.introduction__page_1_content)
|
||||
@ -45,7 +49,7 @@ class Strings(c: Context) {
|
||||
val servicesEmptySearch = c.getString(R.string.tokens__service_not_found_search)
|
||||
val servicesEmptySearchBody = c.getString(R.string.tokens__try_different_search_term)
|
||||
val servicesMyTokens = c.getString(R.string.tokens__my_tokens)
|
||||
val servicesManageList = "Manage list"
|
||||
val servicesManageList = c.getString(R.string.tokens__manage_list)
|
||||
val servicesSortBy = c.getString(R.string.tokens__sort_by)
|
||||
val servicesSortByOptions = listOf(c.getString(R.string.tokens__sort_by_a_to_z), c.getString(R.string.tokens__sort_by_manual))
|
||||
val servicesCopyToken = c.getString(R.string.tokens__copied_clipboard)
|
||||
@ -53,6 +57,10 @@ class Strings(c: Context) {
|
||||
val groupsAdd = c.getString(R.string.tokens__add_group)
|
||||
val groupsEdit = c.getString(R.string.commons__edit)
|
||||
val groupsName = c.getString(R.string.tokens__group_name)
|
||||
val addManually = c.getString(R.string.tokens__fab_addmanually)
|
||||
val addQr = c.getString(R.string.commons__scan_qr_code)
|
||||
val editService = c.getString(R.string.commons__edit)
|
||||
val copyToken = c.getString(R.string.tokens__copy_token)
|
||||
|
||||
val externalImportTitle = c.getString(R.string.settings__external_import)
|
||||
val externalImportHeader = c.getString(R.string.externalimport_select_app)
|
||||
@ -82,7 +90,7 @@ class Strings(c: Context) {
|
||||
val settingsBackup = c.getString(R.string.backup__2fas_backup)
|
||||
val settingsSecurity = c.getString(R.string.settings__security)
|
||||
val settingsSettings = c.getString(R.string.settings__settings)
|
||||
val settingsAppearance = "Appearance"
|
||||
val settingsAppearance = c.getString(R.string.settings__appearance)
|
||||
val settingsExternalImport = c.getString(R.string.settings__external_import)
|
||||
val settingsBrowserExt = c.getString(R.string.browser__browser_extension)
|
||||
val settingsTrash = c.getString(R.string.settings__trash)
|
||||
@ -104,15 +112,15 @@ class Strings(c: Context) {
|
||||
|
||||
val settingsTheme = c.getString(R.string.settings__option_theme)
|
||||
val settingsShowNextCode = c.getString(R.string.settings__show_next_token)
|
||||
val settingsShowNextCodeBody = "Show next token when current one is about to expire."
|
||||
val settingsShowNextCodeBody = c.getString(R.string.settings__show_next_token_desc)
|
||||
val settingsAutoFocusSearch = c.getString(R.string.appearance__toggle_active_search)
|
||||
val settingsAutoFocusSearchBody = c.getString(R.string.appearance__active_search_description)
|
||||
val settingsServicesStyle = "List style"
|
||||
val settingsServicesStyle = c.getString(R.string.settings__list_style)
|
||||
val settingsShowBackupNotice = c.getString(R.string.settings__gd_sync_info)
|
||||
val settingsShowBackupNoticeConfirmBody = c.getString(R.string.settings__gd_sync_disable_confirm)
|
||||
|
||||
val backupSyncNotice = "Google Drive not synced."
|
||||
val backupSyncCta = "Go to backup settings "
|
||||
val backupSyncNotice = c.getString(R.string.backup__reminder_msg)
|
||||
val backupSyncCta = c.getString(R.string.backup__reminder_cta)
|
||||
val backupReminder = c.getString(R.string.backup_notice_title)
|
||||
val backupReminderBody = c.getString(R.string.backup_notice_msg)
|
||||
val backupReminderDismiss = c.getString(R.string.backup_notice_later)
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: de-DE, German (Germany)
|
||||
Exported by: rafakob
|
||||
Exported at: Sat, 25 Mar 2023 14:49:44 -0700
|
||||
Exported at: Sun, 26 Mar 2023 13:20:22 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -721,4 +721,12 @@
|
||||
<string name="commons__best_match">Bester Treffer</string>
|
||||
<string name="settings__enable_crashlytics">Anonyme Absturzberichte senden</string>
|
||||
<string name="settings__enable_crashlytics_description">Sende anonyme Absturzberichte, um 2FAS beim Identifizieren und Lösen von Fehlern in der App zu helfen (App Neustart erforderlich).</string>
|
||||
<string name="tokens__manage_list">Manage list</string>
|
||||
<string name="settings__appearance">Appearance</string>
|
||||
<string name="settings__show_next_token_desc">Show next token when current one is about to expire.</string>
|
||||
<string name="settings__list_style">List style</string>
|
||||
<string name="backup__reminder_msg">Google Drive not synced.</string>
|
||||
<string name="backup__reminder_cta">Go to backup settings</string>
|
||||
<string name="settings__list_style_option_default">Default</string>
|
||||
<string name="settings__list_style_option_compact">Compact</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: fr-FR, French (France)
|
||||
Exported by: rafakob
|
||||
Exported at: Sat, 25 Mar 2023 14:49:44 -0700
|
||||
Exported at: Sun, 26 Mar 2023 13:20:22 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -147,7 +147,7 @@
|
||||
<string name="settings__display_selected_services">Afficher les services sélectionnés pour les widgets de l\'écran d\'accueil.</string>
|
||||
<!-- settings__after_you_enable_widgets -->
|
||||
<string name="settings__widgets_title">Après avoir activé les widgets, toutes vos codes 2FA seront accessibles sans code PIN. Êtes-vous sur de vouloir activer les widgets ?</string>
|
||||
<string name="settings__show_next_token">Afficher le code suivant</string>
|
||||
<string name="settings__show_next_token">Afficher le prochain code</string>
|
||||
<string name="settings__see_incoming_tokens">Voir les prochains codes sur la liste.</string>
|
||||
<string name="settings__trash">Corbeille</string>
|
||||
<string name="settings__restore">Restaurer</string>
|
||||
@ -371,7 +371,7 @@
|
||||
<string name="backup__newer_format_not_supported">Ce fichier est dans un format plus récent que celui que l\'application supporte.</string>
|
||||
<!-- backup__encrypted_unsupported -->
|
||||
<string name="backup__encrypted_files_not_supported">Ce fichier est crypté. Nous ne supportons que les fichiers non cryptés</string>
|
||||
<string name="tokens__copy_token">Copié le code</string>
|
||||
<string name="tokens__copy_token">Code copié</string>
|
||||
<!-- tokens__i_want_to_delete_this_servie -->
|
||||
<string name="tokens__i_want_to_delete_this_token">Oui, je veux supprimer ce service</string>
|
||||
<string name="color__neutral">Neutre</string>
|
||||
@ -719,6 +719,14 @@
|
||||
<string name="errors__input_empty">Le champ ne peut être vide</string>
|
||||
<string name="errors__input_too_long">La valeur saisie est trop longue. Limite : %d</string>
|
||||
<string name="commons__best_match">Meilleur correspondance</string>
|
||||
<string name="settings__enable_crashlytics">Send anonymous crash reports</string>
|
||||
<string name="settings__enable_crashlytics_description">Send anonymous crash reports to help 2FAS identify and solve issues in the app (app restart required).</string>
|
||||
<string name="settings__enable_crashlytics">Envoyer des rapports d\'erreur anonymes</string>
|
||||
<string name="settings__enable_crashlytics_description">Envoyer des rapports d\'erreur anonymes pour aider 2FAS à identifier et à résoudre les erreurs dans l\'application (redémarrage de l\'application nécessaire).</string>
|
||||
<string name="tokens__manage_list">Manage list</string>
|
||||
<string name="settings__appearance">Appearance</string>
|
||||
<string name="settings__show_next_token_desc">Show next token when current one is about to expire.</string>
|
||||
<string name="settings__list_style">List style</string>
|
||||
<string name="backup__reminder_msg">Google Drive not synced.</string>
|
||||
<string name="backup__reminder_cta">Go to backup settings</string>
|
||||
<string name="settings__list_style_option_default">Default</string>
|
||||
<string name="settings__list_style_option_compact">Compact</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: pt-PT, Portuguese (Portugal)
|
||||
Exported by: rafakob
|
||||
Exported at: Sat, 25 Mar 2023 14:49:44 -0700
|
||||
Exported at: Sun, 26 Mar 2023 13:20:22 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -719,6 +719,14 @@
|
||||
<string name="errors__input_empty">O valor não pode estar vazio</string>
|
||||
<string name="errors__input_too_long">O valor é muito longo. Limite: %d</string>
|
||||
<string name="commons__best_match">Melhor correspondência</string>
|
||||
<string name="settings__enable_crashlytics">Send anonymous crash reports</string>
|
||||
<string name="settings__enable_crashlytics_description">Send anonymous crash reports to help 2FAS identify and solve issues in the app (app restart required).</string>
|
||||
<string name="settings__enable_crashlytics">Envia relatórios anônimos de falhas</string>
|
||||
<string name="settings__enable_crashlytics_description">Envia relatórios anônimos de falhas para ajudar a 2FAS a identificar e resolver problemas na aplicação (é necessário reiniciar a aplicação).</string>
|
||||
<string name="tokens__manage_list">Manage list</string>
|
||||
<string name="settings__appearance">Appearance</string>
|
||||
<string name="settings__show_next_token_desc">Show next token when current one is about to expire.</string>
|
||||
<string name="settings__list_style">List style</string>
|
||||
<string name="backup__reminder_msg">Google Drive not synced.</string>
|
||||
<string name="backup__reminder_cta">Go to backup settings</string>
|
||||
<string name="settings__list_style_option_default">Default</string>
|
||||
<string name="settings__list_style_option_compact">Compact</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: en, English
|
||||
Exported by: rafakob
|
||||
Exported at: Sat, 25 Mar 2023 14:49:44 -0700
|
||||
Exported at: Sun, 26 Mar 2023 13:20:22 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -697,7 +697,7 @@
|
||||
<string name="externalimport__aegis_success_msg">This JSON file allows importing tokens from Aegis.</string>
|
||||
<string name="externalimport__raivo_success_msg">This JSON file allows importing tokens from Raivo.</string>
|
||||
<string name="externalimport__read_error">Could not read any tokens. Try to select a different file.</string>
|
||||
<string name="settings__gd_sync_info">Google Drive sync info</string>
|
||||
<string name="settings__gd_sync_info">Google Drive sync reminder</string>
|
||||
<string name="settings__gd_sync_disable_confirm">Are you sure? Without Google Drive sync, you won\'t be able to restore your tokens if you lose or reset your phone!</string>
|
||||
<string name="extension__code_sent_msg">Code sent successfully</string>
|
||||
<string name="extension__code_sent_error_msg">Error occurred when sending code</string>
|
||||
@ -721,4 +721,12 @@
|
||||
<string name="commons__best_match">Best match</string>
|
||||
<string name="settings__enable_crashlytics">Send anonymous crash reports</string>
|
||||
<string name="settings__enable_crashlytics_description">Send anonymous crash reports to help 2FAS identify and solve issues in the app (app restart required).</string>
|
||||
<string name="tokens__manage_list">Manage list</string>
|
||||
<string name="settings__appearance">Appearance</string>
|
||||
<string name="settings__show_next_token_desc">Show next token when current one is about to expire.</string>
|
||||
<string name="settings__list_style">List style</string>
|
||||
<string name="backup__reminder_msg">Google Drive not synced.</string>
|
||||
<string name="backup__reminder_cta">Go to backup settings</string>
|
||||
<string name="settings__list_style_option_default">Default</string>
|
||||
<string name="settings__list_style_option_compact">Compact</string>
|
||||
</resources>
|
||||
|
@ -9,6 +9,7 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.twofasapp.data.session.domain.SelectedTheme
|
||||
import com.twofasapp.data.session.domain.ServicesStyle
|
||||
@ -18,6 +19,7 @@ import com.twofasapp.designsystem.dialog.ConfirmDialog
|
||||
import com.twofasapp.designsystem.dialog.ListRadioDialog
|
||||
import com.twofasapp.designsystem.settings.SettingsLink
|
||||
import com.twofasapp.designsystem.settings.SettingsSwitch
|
||||
import com.twofasapp.locale.R
|
||||
import com.twofasapp.locale.TwLocale
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@ -110,11 +112,12 @@ private fun AppSettingsScreen(
|
||||
}
|
||||
|
||||
if (showThemeDialog) {
|
||||
|
||||
ListRadioDialog(
|
||||
onDismissRequest = { showThemeDialog = false },
|
||||
title = TwLocale.strings.settingsTheme,
|
||||
options = SelectedTheme.values().map { it.name },
|
||||
selectedOption = uiState.appSettings.selectedTheme.name,
|
||||
options = SelectedTheme.values().map { it.toStringResource() },
|
||||
selectedOption = uiState.appSettings.selectedTheme.toStringResource(),
|
||||
onOptionSelected = { index, _ -> onSelectedThemeChange(SelectedTheme.values()[index]) },
|
||||
)
|
||||
}
|
||||
@ -123,8 +126,8 @@ private fun AppSettingsScreen(
|
||||
ListRadioDialog(
|
||||
onDismissRequest = { showServicesStyleDialog = false },
|
||||
title = TwLocale.strings.settingsServicesStyle,
|
||||
options = ServicesStyle.values().map { it.name },
|
||||
selectedOption = uiState.appSettings.servicesStyle.name,
|
||||
options = ServicesStyle.values().map { it.toStringResource() },
|
||||
selectedOption = uiState.appSettings.servicesStyle.toStringResource(),
|
||||
onOptionSelected = { index, _ -> onServicesStyleChange(ServicesStyle.values()[index]) },
|
||||
)
|
||||
}
|
||||
@ -139,3 +142,20 @@ private fun AppSettingsScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SelectedTheme.toStringResource(): String {
|
||||
return when (this) {
|
||||
SelectedTheme.Auto -> stringResource(id = R.string.settings__theme_option_auto)
|
||||
SelectedTheme.Light -> stringResource(id = R.string.settings__theme_option_light)
|
||||
SelectedTheme.Dark -> stringResource(id = R.string.settings__theme_option_dark)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ServicesStyle.toStringResource(): String {
|
||||
return when (this) {
|
||||
ServicesStyle.Default -> stringResource(id = R.string.settings__list_style_option_default)
|
||||
ServicesStyle.Compact -> stringResource(id = R.string.settings__list_style_option_compact)
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ import com.twofasapp.designsystem.TwIcons
|
||||
import com.twofasapp.designsystem.common.TwNavigationBar
|
||||
import com.twofasapp.designsystem.common.TwNavigationBarItem
|
||||
import com.twofasapp.feature.home.navigation.HomeNode
|
||||
import com.twofasapp.locale.TwLocale
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
@ -18,19 +19,19 @@ private val bottomNavItems
|
||||
@Composable
|
||||
get() = listOf(
|
||||
BottomNavItem(
|
||||
title = "Tokens",
|
||||
title = TwLocale.strings.bottomBarTokens,
|
||||
icon = TwIcons.Home,
|
||||
iconSelected = TwIcons.HomeFilled,
|
||||
route = HomeNode.Services.route,
|
||||
),
|
||||
BottomNavItem(
|
||||
title = "Settings",
|
||||
title = TwLocale.strings.bottomBarSettings,
|
||||
icon = TwIcons.Settings,
|
||||
iconSelected = TwIcons.SettingsFilled,
|
||||
route = HomeNode.Settings.route,
|
||||
),
|
||||
BottomNavItem(
|
||||
title = "Notifications",
|
||||
title = TwLocale.strings.bottomBarNotifications,
|
||||
icon = TwIcons.Notification,
|
||||
iconSelected = TwIcons.NotificationFilled,
|
||||
route = HomeNode.Notifications.route,
|
||||
|
@ -422,13 +422,13 @@ private fun ServicesScreen(
|
||||
modifier = Modifier,
|
||||
dragHandleVisible = uiState.appSettings.servicesSort == ServicesSort.Manual,
|
||||
dragModifier = Modifier.detectReorder(state = reorderableState),
|
||||
onClick = {
|
||||
onLongClick = {
|
||||
scope.launch {
|
||||
modalType = ModalType.FocusService(service.id, false)
|
||||
modalState.show()
|
||||
}
|
||||
},
|
||||
onLongClick = {
|
||||
onClick = {
|
||||
state.copyToClipboard(activity, uiState.appSettings.showNextCode)
|
||||
},
|
||||
onIncrementCounterClick = {
|
||||
|
@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable
|
||||
import com.twofasapp.designsystem.TwIcons
|
||||
import com.twofasapp.designsystem.common.ModalList
|
||||
import com.twofasapp.designsystem.settings.SettingsLink
|
||||
import com.twofasapp.locale.TwLocale
|
||||
|
||||
@Composable
|
||||
internal fun AddServiceModal(
|
||||
@ -11,7 +12,7 @@ internal fun AddServiceModal(
|
||||
onScanQrClick: () -> Unit = {},
|
||||
) {
|
||||
ModalList {
|
||||
SettingsLink(title = "Add manually", icon = TwIcons.Edit) { onAddManuallyClick() }
|
||||
SettingsLink(title = "Scan QR code", icon = TwIcons.Qr) { onScanQrClick() }
|
||||
SettingsLink(title = TwLocale.strings.addManually, icon = TwIcons.Edit) { onAddManuallyClick() }
|
||||
SettingsLink(title = TwLocale.strings.addQr, icon = TwIcons.Qr) { onScanQrClick() }
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ import com.twofasapp.designsystem.service.DsServiceModal
|
||||
import com.twofasapp.designsystem.service.ServiceState
|
||||
import com.twofasapp.designsystem.settings.SettingsDivider
|
||||
import com.twofasapp.designsystem.settings.SettingsLink
|
||||
import com.twofasapp.locale.TwLocale
|
||||
|
||||
@Composable
|
||||
internal fun FocusServiceModal(
|
||||
@ -29,8 +30,8 @@ internal fun FocusServiceModal(
|
||||
SettingsDivider()
|
||||
|
||||
ModalList {
|
||||
SettingsLink(title = "Edit", icon = TwIcons.Edit) { onEditClick() }
|
||||
SettingsLink(title = "Copy token", icon = TwIcons.Copy) { onCopyClick() }
|
||||
SettingsLink(title = TwLocale.strings.editService, icon = TwIcons.Edit) { onEditClick() }
|
||||
SettingsLink(title = TwLocale.strings.copyToken, icon = TwIcons.Copy) { onCopyClick() }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
[versions]
|
||||
accompanist = "0.27.0"
|
||||
agp = "8.1.0-alpha08"
|
||||
agp = "7.4.1"
|
||||
coil = "2.2.2"
|
||||
compose = "1.4.0-rc01"
|
||||
composeActivity = "1.6.1"
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: de-DE, German (Germany)
|
||||
Exported by: rafakob
|
||||
Exported at: Sat, 25 Mar 2023 14:49:44 -0700
|
||||
Exported at: Sun, 26 Mar 2023 13:20:22 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -721,4 +721,12 @@
|
||||
<string name="commons__best_match">Bester Treffer</string>
|
||||
<string name="settings__enable_crashlytics">Anonyme Absturzberichte senden</string>
|
||||
<string name="settings__enable_crashlytics_description">Sende anonyme Absturzberichte, um 2FAS beim Identifizieren und Lösen von Fehlern in der App zu helfen (App Neustart erforderlich).</string>
|
||||
<string name="tokens__manage_list">Manage list</string>
|
||||
<string name="settings__appearance">Appearance</string>
|
||||
<string name="settings__show_next_token_desc">Show next token when current one is about to expire.</string>
|
||||
<string name="settings__list_style">List style</string>
|
||||
<string name="backup__reminder_msg">Google Drive not synced.</string>
|
||||
<string name="backup__reminder_cta">Go to backup settings</string>
|
||||
<string name="settings__list_style_option_default">Default</string>
|
||||
<string name="settings__list_style_option_compact">Compact</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: fr-FR, French (France)
|
||||
Exported by: rafakob
|
||||
Exported at: Sat, 25 Mar 2023 14:49:44 -0700
|
||||
Exported at: Sun, 26 Mar 2023 13:20:22 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -147,7 +147,7 @@
|
||||
<string name="settings__display_selected_services">Afficher les services sélectionnés pour les widgets de l\'écran d\'accueil.</string>
|
||||
<!-- settings__after_you_enable_widgets -->
|
||||
<string name="settings__widgets_title">Après avoir activé les widgets, toutes vos codes 2FA seront accessibles sans code PIN. Êtes-vous sur de vouloir activer les widgets ?</string>
|
||||
<string name="settings__show_next_token">Afficher le code suivant</string>
|
||||
<string name="settings__show_next_token">Afficher le prochain code</string>
|
||||
<string name="settings__see_incoming_tokens">Voir les prochains codes sur la liste.</string>
|
||||
<string name="settings__trash">Corbeille</string>
|
||||
<string name="settings__restore">Restaurer</string>
|
||||
@ -371,7 +371,7 @@
|
||||
<string name="backup__newer_format_not_supported">Ce fichier est dans un format plus récent que celui que l\'application supporte.</string>
|
||||
<!-- backup__encrypted_unsupported -->
|
||||
<string name="backup__encrypted_files_not_supported">Ce fichier est crypté. Nous ne supportons que les fichiers non cryptés</string>
|
||||
<string name="tokens__copy_token">Copié le code</string>
|
||||
<string name="tokens__copy_token">Code copié</string>
|
||||
<!-- tokens__i_want_to_delete_this_servie -->
|
||||
<string name="tokens__i_want_to_delete_this_token">Oui, je veux supprimer ce service</string>
|
||||
<string name="color__neutral">Neutre</string>
|
||||
@ -719,6 +719,14 @@
|
||||
<string name="errors__input_empty">Le champ ne peut être vide</string>
|
||||
<string name="errors__input_too_long">La valeur saisie est trop longue. Limite : %d</string>
|
||||
<string name="commons__best_match">Meilleur correspondance</string>
|
||||
<string name="settings__enable_crashlytics">Send anonymous crash reports</string>
|
||||
<string name="settings__enable_crashlytics_description">Send anonymous crash reports to help 2FAS identify and solve issues in the app (app restart required).</string>
|
||||
<string name="settings__enable_crashlytics">Envoyer des rapports d\'erreur anonymes</string>
|
||||
<string name="settings__enable_crashlytics_description">Envoyer des rapports d\'erreur anonymes pour aider 2FAS à identifier et à résoudre les erreurs dans l\'application (redémarrage de l\'application nécessaire).</string>
|
||||
<string name="tokens__manage_list">Manage list</string>
|
||||
<string name="settings__appearance">Appearance</string>
|
||||
<string name="settings__show_next_token_desc">Show next token when current one is about to expire.</string>
|
||||
<string name="settings__list_style">List style</string>
|
||||
<string name="backup__reminder_msg">Google Drive not synced.</string>
|
||||
<string name="backup__reminder_cta">Go to backup settings</string>
|
||||
<string name="settings__list_style_option_default">Default</string>
|
||||
<string name="settings__list_style_option_compact">Compact</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: pt-PT, Portuguese (Portugal)
|
||||
Exported by: rafakob
|
||||
Exported at: Sat, 25 Mar 2023 14:49:44 -0700
|
||||
Exported at: Sun, 26 Mar 2023 13:20:22 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -719,6 +719,14 @@
|
||||
<string name="errors__input_empty">O valor não pode estar vazio</string>
|
||||
<string name="errors__input_too_long">O valor é muito longo. Limite: %d</string>
|
||||
<string name="commons__best_match">Melhor correspondência</string>
|
||||
<string name="settings__enable_crashlytics">Send anonymous crash reports</string>
|
||||
<string name="settings__enable_crashlytics_description">Send anonymous crash reports to help 2FAS identify and solve issues in the app (app restart required).</string>
|
||||
<string name="settings__enable_crashlytics">Envia relatórios anônimos de falhas</string>
|
||||
<string name="settings__enable_crashlytics_description">Envia relatórios anônimos de falhas para ajudar a 2FAS a identificar e resolver problemas na aplicação (é necessário reiniciar a aplicação).</string>
|
||||
<string name="tokens__manage_list">Manage list</string>
|
||||
<string name="settings__appearance">Appearance</string>
|
||||
<string name="settings__show_next_token_desc">Show next token when current one is about to expire.</string>
|
||||
<string name="settings__list_style">List style</string>
|
||||
<string name="backup__reminder_msg">Google Drive not synced.</string>
|
||||
<string name="backup__reminder_cta">Go to backup settings</string>
|
||||
<string name="settings__list_style_option_default">Default</string>
|
||||
<string name="settings__list_style_option_compact">Compact</string>
|
||||
</resources>
|
||||
|
@ -5,7 +5,7 @@
|
||||
Release: Working copy
|
||||
Locale: en, English
|
||||
Exported by: rafakob
|
||||
Exported at: Sat, 25 Mar 2023 14:49:44 -0700
|
||||
Exported at: Sun, 26 Mar 2023 13:20:22 -0700
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<!-- InfoPlist.strings
|
||||
@ -697,7 +697,7 @@
|
||||
<string name="externalimport__aegis_success_msg">This JSON file allows importing tokens from Aegis.</string>
|
||||
<string name="externalimport__raivo_success_msg">This JSON file allows importing tokens from Raivo.</string>
|
||||
<string name="externalimport__read_error">Could not read any tokens. Try to select a different file.</string>
|
||||
<string name="settings__gd_sync_info">Google Drive sync info</string>
|
||||
<string name="settings__gd_sync_info">Google Drive sync reminder</string>
|
||||
<string name="settings__gd_sync_disable_confirm">Are you sure? Without Google Drive sync, you won\'t be able to restore your tokens if you lose or reset your phone!</string>
|
||||
<string name="extension__code_sent_msg">Code sent successfully</string>
|
||||
<string name="extension__code_sent_error_msg">Error occurred when sending code</string>
|
||||
@ -721,4 +721,12 @@
|
||||
<string name="commons__best_match">Best match</string>
|
||||
<string name="settings__enable_crashlytics">Send anonymous crash reports</string>
|
||||
<string name="settings__enable_crashlytics_description">Send anonymous crash reports to help 2FAS identify and solve issues in the app (app restart required).</string>
|
||||
<string name="tokens__manage_list">Manage list</string>
|
||||
<string name="settings__appearance">Appearance</string>
|
||||
<string name="settings__show_next_token_desc">Show next token when current one is about to expire.</string>
|
||||
<string name="settings__list_style">List style</string>
|
||||
<string name="backup__reminder_msg">Google Drive not synced.</string>
|
||||
<string name="backup__reminder_cta">Go to backup settings</string>
|
||||
<string name="settings__list_style_option_default">Default</string>
|
||||
<string name="settings__list_style_option_compact">Compact</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user