diff --git a/README.md b/README.md index 539da16..3677543 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ message with authentication code. On trigger, using locks a device and optionally runs wipe. Also you can: -* wipe a device when it was not unlocked for N days +* wipe a device when it was not unlocked for N time * wipe a device using a duress password (companion app: [Duress](https://github.com/x13a/Duress)) The app works in `Work Profile` too. Use [Shelter](https://github.com/PeterCxy/Shelter) to install diff --git a/SECURITY.md b/SECURITY.md index 5cddaaa..90eec2c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -9,4 +9,4 @@ ## Reporting a Vulnerability -Contact: mailto:44uaanjm0@relay.firefox.com +Contact: 44uaanjm0@relay.firefox.com diff --git a/app/build.gradle b/app/build.gradle index 0b59314..fa940c7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "me.lucky.wasted" minSdk 23 targetSdk 32 - versionCode 25 - versionName "1.4.0" + versionCode 26 + versionName "1.4.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/me/lucky/wasted/MainActivity.kt b/app/src/main/java/me/lucky/wasted/MainActivity.kt index 66c6b8f..499b829 100644 --- a/app/src/main/java/me/lucky/wasted/MainActivity.kt +++ b/app/src/main/java/me/lucky/wasted/MainActivity.kt @@ -12,9 +12,11 @@ import android.view.View import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat +import androidx.core.widget.doAfterTextChanged import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import java.util.* +import java.util.regex.Pattern import kotlin.concurrent.timerTask import me.lucky.wasted.databinding.ActivityMainBinding @@ -22,6 +24,9 @@ import me.lucky.wasted.databinding.ActivityMainBinding open class MainActivity : AppCompatActivity() { companion object { private const val CLIPBOARD_CLEAR_DELAY = 30_000L + private const val MODIFIER_DAYS = 'd' + private const val MODIFIER_HOURS = 'h' + private const val MODIFIER_MINUTES = 'm' } private lateinit var binding: ActivityMainBinding @@ -29,6 +34,8 @@ open class MainActivity : AppCompatActivity() { private lateinit var admin: DeviceAdminManager private val shortcut by lazy { ShortcutManager(this) } private val job by lazy { WipeJobManager(this) } + private val wipeOnInactivityTimeRegex by lazy { + Pattern.compile("^[1-9]\\d*[$MODIFIER_DAYS$MODIFIER_HOURS$MODIFIER_MINUTES]$") } private var clipboardManager: ClipboardManager? = null private var clipboardClearTask: Timer? = null @@ -81,6 +88,7 @@ open class MainActivity : AppCompatActivity() { wipeOnInactivitySwitch.isChecked = prefs.isWipeOnInactivity toggle.isChecked = prefs.isEnabled } + initWipeOnInactivityTime() } private fun hideEmbeddedSim() { @@ -96,22 +104,23 @@ open class MainActivity : AppCompatActivity() { } } + private fun initWipeOnInactivityTime() { + val count = prefs.wipeOnInactivityCount + val time = when { + count % (24 * 60) == 0 -> "${count / 24 / 60}$MODIFIER_DAYS" + count % 60 == 0 -> "${count / 60}$MODIFIER_HOURS" + else -> "$count$MODIFIER_MINUTES" + } + binding.wipeOnInactivityTime.editText?.setText(time) + } + private fun setup() { binding.apply { authenticationCode.setOnClickListener { showTriggersSettings() } authenticationCode.setOnLongClickListener { - clipboardManager - ?.setPrimaryClip(ClipData.newPlainText("", prefs.authenticationCode)) - if (clipboardManager != null) { - scheduleClipboardClear() - Snackbar.make( - authenticationCode, - R.string.copied_popup, - Snackbar.LENGTH_SHORT, - ).show() - } + copyAuthenticationCode() true } wipeData.setOnCheckedChangeListener { _, isChecked -> @@ -125,9 +134,32 @@ open class MainActivity : AppCompatActivity() { setWipeOnInactivityState(prefs.isEnabled && isChecked) prefs.isWipeOnInactivity = isChecked } - wipeOnInactivitySwitch.setOnLongClickListener { - showWipeOnInactivitySettings() - true + wipeOnInactivityTime.editText?.doAfterTextChanged { + if (wipeOnInactivityTimeRegex.matcher(it?.toString() ?: "").matches()) { + wipeOnInactivityTime.error = null + } else { + wipeOnInactivityTime.error = getString(R.string.wipe_on_inactivity_time_error) + } + } + wipeOnInactivityTime.setEndIconOnClickListener { + if (wipeOnInactivityTime.error != null) return@setEndIconOnClickListener + val time = wipeOnInactivityTime.editText?.text?.toString() ?: "" + if (time.length < 2) return@setEndIconOnClickListener + val modifier = time.last() + val i: Int + try { + i = time.dropLast(1).toInt() + } catch (exc: NumberFormatException) { return@setEndIconOnClickListener } + prefs.wipeOnInactivityCount = when (modifier) { + MODIFIER_DAYS -> i * 24 * 60 + MODIFIER_HOURS -> i * 60 + MODIFIER_MINUTES -> i + else -> return@setEndIconOnClickListener + } + if (prefs.isEnabled && prefs.isWipeOnInactivity) { + if (job.schedule() == JobScheduler.RESULT_FAILURE) + showWipeJobScheduleFailedPopup() + } } toggle.setOnCheckedChangeListener { _, isChecked -> if (isChecked) requestAdmin() else setOff() @@ -135,6 +167,18 @@ open class MainActivity : AppCompatActivity() { } } + private fun copyAuthenticationCode() { + clipboardManager?.setPrimaryClip(ClipData.newPlainText("", prefs.authenticationCode)) + if (clipboardManager != null) { + scheduleClipboardClear() + Snackbar.make( + binding.authenticationCode, + R.string.copied_popup, + Snackbar.LENGTH_SHORT, + ).show() + } + } + private fun scheduleClipboardClear() { clipboardClearTask?.cancel() clipboardClearTask = Timer() @@ -174,27 +218,6 @@ open class MainActivity : AppCompatActivity() { .show() } - private fun showWipeOnInactivitySettings() { - val items = resources.getStringArray(R.array.wipe_on_inactivity_days) - var days = prefs.wipeOnInactivityCount / 24 / 60 - var checked = items.indexOf(days.toString()) - if (checked == -1) checked = items - .indexOf((Preferences.DEFAULT_WIPE_ON_INACTIVITY_COUNT / 24 / 60).toString()) - MaterialAlertDialogBuilder(this) - .setTitle(R.string.wipe_on_inactivity_days) - .setSingleChoiceItems(items, checked) { _, which -> - days = items[which].toInt() - } - .setPositiveButton(android.R.string.ok) { _, _ -> - prefs.wipeOnInactivityCount = days * 24 * 60 - if (prefs.isEnabled && prefs.isWipeOnInactivity) { - if (job.schedule() == JobScheduler.RESULT_FAILURE) - showWipeJobScheduleFailedPopup() - } - } - .show() - } - private fun updateCodeColorState() { binding.authenticationCode.setBackgroundColor(getColor( if (prefs.triggers != 0) R.color.code_on else R.color.code_off diff --git a/app/src/main/res/drawable/ic_baseline_check_circle_24.xml b/app/src/main/res/drawable/ic_baseline_check_circle_24.xml new file mode 100644 index 0000000..b83d1bc --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_check_circle_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 72c84e2..8f5d226 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -21,6 +21,7 @@ android:layout_width="0dp" android:layout_height="0dp" android:layout_marginVertical="16dp" + android:isScrollContainer="false" app:layout_constraintBottom_toTopOf="@+id/toggle" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -91,6 +92,28 @@ android:layout_height="wrap_content" android:text="@string/wipe_on_inactivity_description" /> + + + + + + + + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 171b266..073aefd 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -15,7 +15,6 @@ Panik Bei Inaktivität löschen Den Speicher des Geräts löschen, wenn es für N Tage nicht entsperrt wurde. - Tage Standard Den Speicher bei Inaktivität löschen Fehler bei der Durchführung des Wipes diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index bbad40a..d0a949d 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -15,7 +15,6 @@ Pánico Borrar por inactividad Limpia un dispositivo cuando no fue desbloqueado por N días. - Días Predeterminado Borrar un dispositivo por inactividad Error al programar un trabajo de borrado diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index f4d69d1..e0bd6f7 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -15,7 +15,6 @@ Panico Cancella in caso di inattività Cancella i dati quando il dispositivo non viene sbloccato per N giorni. - Giorni Predefinito Cancella i dati in caso di inattività Impossibile pianificare un processo di cancellazione diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index de7be17..521d906 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -15,7 +15,6 @@ Тревога Стереть при неактивности Стереть данные когда устройство не разблокируется N дней. - Дней По умолчанию Стереть данные при неактивности Не удалось запланировать сервис стирания данных diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 14803d6..1f59349 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -15,7 +15,6 @@ Panik Kullanılmadığında sil N gün boyunca kilidi açılmamış bir cihazı silin. - Gün Varsayılan Cihaz kullanılmadığında siler Silme işi zamanlanamadı diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index fab2407..23a1565 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -15,7 +15,6 @@ Тривога Wipe on inactivity Видалення пристрою, коли його не було розблоковано протягом N днів. - Днів За замовчуванням Wipe a device on inactivity Failed to schedule a wipe job diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 7ded256..035437d 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -15,7 +15,6 @@ 紧急 在不使用时擦除 当设备在N天内没被解锁时擦除 - 天数 默认设置 擦除不使用的设备 无法制定擦除计划 diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml deleted file mode 100644 index 4db1e11..0000000 --- a/app/src/main/res/values/arrays.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - 1 - 2 - 3 - 5 - 7 - 10 - 15 - 30 - - \ 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 06f6e5b..dbec6a7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -14,8 +14,10 @@ Airplane mode Panic Wipe on inactivity - Wipe a device when it was not unlocked for N days. - Days + Wipe a device when it was not unlocked for N time. + time + 7d / 48h / 120m + [d]ays [h]ours [m]inutes Default Wipe a device on inactivity Failed to schedule a wipe job diff --git a/fastlane/metadata/android/en-US/changelogs/26.txt b/fastlane/metadata/android/en-US/changelogs/26.txt new file mode 100644 index 0000000..9244f92 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/26.txt @@ -0,0 +1 @@ +add custom wipe on inactivity timings diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt index 3c93ad3..51c4fbe 100644 --- a/fastlane/metadata/android/en-US/full_description.txt +++ b/fastlane/metadata/android/en-US/full_description.txt @@ -4,7 +4,7 @@ You can use PanicKit, tile, shortcut or send a message with authentication code. Device Administration API, it locks a device and optionally runs wipe. Also you can: -* wipe a device when it was not unlocked for N days +* wipe a device when it was not unlocked for N time * wipe a device using a duress password (companion app: [Duress](https://github.com/x13a/Duress)) The app works in Work Profile too. Use Shelter to install risky apps and Wasted in it. Then you can diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png index 5828436..b016d6a 100644 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png and b/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png differ diff --git a/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png b/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png deleted file mode 100644 index 950510e..0000000 Binary files a/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png and /dev/null differ