mirror of https://github.com/x13a/Wasted.git
add custom wipe on inactivity timings
This commit is contained in:
parent
1abfef163a
commit
4e8737e50e
|
@ -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
|
||||
|
|
|
@ -9,4 +9,4 @@
|
|||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Contact: mailto:44uaanjm0@relay.firefox.com
|
||||
Contact: 44uaanjm0@relay.firefox.com
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#000000"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
|
||||
</vector>
|
|
@ -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" />
|
||||
|
||||
<Space
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="8dp"/>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/wipeOnInactivityTime"
|
||||
app:helperText="@string/wipe_on_inactivity_time_helper_text"
|
||||
app:helperTextEnabled="true"
|
||||
app:errorEnabled="true"
|
||||
app:endIconMode="custom"
|
||||
app:endIconDrawable="@drawable/ic_baseline_check_circle_24"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/wipe_on_inactivity_time_hint" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
<string name="shortcut_label">Panik</string>
|
||||
<string name="wipe_on_inactivity_switch">Bei Inaktivität löschen</string>
|
||||
<string name="wipe_on_inactivity_description">Den Speicher des Geräts löschen, wenn es für N Tage nicht entsperrt wurde.</string>
|
||||
<string name="wipe_on_inactivity_days">Tage</string>
|
||||
<string name="notification_channel_default_name">Standard</string>
|
||||
<string name="wipe_job_description">Den Speicher bei Inaktivität löschen</string>
|
||||
<string name="wipe_job_schedule_failed_popup">Fehler bei der Durchführung des Wipes</string>
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
<string name="shortcut_label">Pánico</string>
|
||||
<string name="wipe_on_inactivity_switch">Borrar por inactividad</string>
|
||||
<string name="wipe_on_inactivity_description">Limpia un dispositivo cuando no fue desbloqueado por N días.</string>
|
||||
<string name="wipe_on_inactivity_days">Días</string>
|
||||
<string name="notification_channel_default_name">Predeterminado</string>
|
||||
<string name="wipe_job_description">Borrar un dispositivo por inactividad</string>
|
||||
<string name="wipe_job_schedule_failed_popup">Error al programar un trabajo de borrado</string>
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
<string name="shortcut_label">Panico</string>
|
||||
<string name="wipe_on_inactivity_switch">Cancella in caso di inattività</string>
|
||||
<string name="wipe_on_inactivity_description">Cancella i dati quando il dispositivo non viene sbloccato per N giorni.</string>
|
||||
<string name="wipe_on_inactivity_days">Giorni</string>
|
||||
<string name="notification_channel_default_name">Predefinito</string>
|
||||
<string name="wipe_job_description">Cancella i dati in caso di inattività</string>
|
||||
<string name="wipe_job_schedule_failed_popup">Impossibile pianificare un processo di cancellazione</string>
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
<string name="shortcut_label">Тревога</string>
|
||||
<string name="wipe_on_inactivity_switch">Стереть при неактивности</string>
|
||||
<string name="wipe_on_inactivity_description">Стереть данные когда устройство не разблокируется N дней.</string>
|
||||
<string name="wipe_on_inactivity_days">Дней</string>
|
||||
<string name="notification_channel_default_name">По умолчанию</string>
|
||||
<string name="wipe_job_description">Стереть данные при неактивности</string>
|
||||
<string name="wipe_job_schedule_failed_popup">Не удалось запланировать сервис стирания данных</string>
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
<string name="shortcut_label">Panik</string>
|
||||
<string name="wipe_on_inactivity_switch">Kullanılmadığında sil</string>
|
||||
<string name="wipe_on_inactivity_description">N gün boyunca kilidi açılmamış bir cihazı silin.</string>
|
||||
<string name="wipe_on_inactivity_days">Gün</string>
|
||||
<string name="notification_channel_default_name">Varsayılan</string>
|
||||
<string name="wipe_job_description">Cihaz kullanılmadığında siler</string>
|
||||
<string name="wipe_job_schedule_failed_popup">Silme işi zamanlanamadı</string>
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
<string name="shortcut_label">Тривога</string>
|
||||
<string name="wipe_on_inactivity_switch">Wipe on inactivity</string>
|
||||
<string name="wipe_on_inactivity_description">Видалення пристрою, коли його не було розблоковано протягом N днів.</string>
|
||||
<string name="wipe_on_inactivity_days">Днів</string>
|
||||
<string name="notification_channel_default_name">За замовчуванням</string>
|
||||
<string name="wipe_job_description">Wipe a device on inactivity</string>
|
||||
<string name="wipe_job_schedule_failed_popup">Failed to schedule a wipe job</string>
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
<string name="shortcut_label">紧急</string>
|
||||
<string name="wipe_on_inactivity_switch">在不使用时擦除</string>
|
||||
<string name="wipe_on_inactivity_description">当设备在N天内没被解锁时擦除</string>
|
||||
<string name="wipe_on_inactivity_days">天数</string>
|
||||
<string name="notification_channel_default_name">默认设置</string>
|
||||
<string name="wipe_job_description">擦除不使用的设备</string>
|
||||
<string name="wipe_job_schedule_failed_popup">无法制定擦除计划</string>
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string-array name="wipe_on_inactivity_days">
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>5</item>
|
||||
<item>7</item>
|
||||
<item>10</item>
|
||||
<item>15</item>
|
||||
<item>30</item>
|
||||
</string-array>
|
||||
</resources>
|
|
@ -14,8 +14,10 @@
|
|||
<string name="tile_label">Airplane mode</string>
|
||||
<string name="shortcut_label">Panic</string>
|
||||
<string name="wipe_on_inactivity_switch">Wipe on inactivity</string>
|
||||
<string name="wipe_on_inactivity_description">Wipe a device when it was not unlocked for N days.</string>
|
||||
<string name="wipe_on_inactivity_days">Days</string>
|
||||
<string name="wipe_on_inactivity_description">Wipe a device when it was not unlocked for N time.</string>
|
||||
<string name="wipe_on_inactivity_time_hint">time</string>
|
||||
<string name="wipe_on_inactivity_time_error">7d / 48h / 120m</string>
|
||||
<string name="wipe_on_inactivity_time_helper_text">[d]ays [h]ours [m]inutes</string>
|
||||
<string name="notification_channel_default_name">Default</string>
|
||||
<string name="wipe_job_description">Wipe a device on inactivity</string>
|
||||
<string name="wipe_job_schedule_failed_popup">Failed to schedule a wipe job</string>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
add custom wipe on inactivity timings
|
|
@ -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
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 110 KiB |
Binary file not shown.
Before Width: | Height: | Size: 100 KiB |
Loading…
Reference in New Issue