Add support for recycle bin for messages

This adds support for moving messages to recycle bin instead of
deleting them right away. The feature is not active by default.

This closes #451
This commit is contained in:
Ensar Sarajčić 2023-07-18 11:34:25 +02:00
parent 53aa4495a0
commit 555b6ebea3
13 changed files with 274 additions and 20 deletions

View File

@ -64,6 +64,7 @@ class MainActivity : SimpleActivity() {
updateMaterialActivityViews(main_coordinator, conversations_list, useTransparentNavigation = true, useTopSearchMenu = true) updateMaterialActivityViews(main_coordinator, conversations_list, useTransparentNavigation = true, useTopSearchMenu = true)
if (savedInstanceState == null) { if (savedInstanceState == null) {
checkAndDeleteOldRecycleBinMessages()
handleAppPasswordProtection { handleAppPasswordProtection {
wasProtectionHandled = it wasProtectionHandled = it
if (it) { if (it) {

View File

@ -11,12 +11,15 @@ import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.config
import com.simplemobiletools.smsmessenger.extensions.emptyMessagesRecycleBin
import com.simplemobiletools.smsmessenger.extensions.messagesDB
import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.helpers.*
import kotlinx.android.synthetic.main.activity_settings.* import kotlinx.android.synthetic.main.activity_settings.*
import java.util.* import java.util.*
class SettingsActivity : SimpleActivity() { class SettingsActivity : SimpleActivity() {
private var blockedNumbersAtPause = -1 private var blockedNumbersAtPause = -1
private var recycleBinMessages = 0
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true isMaterialActivity = true
@ -48,6 +51,8 @@ class SettingsActivity : SimpleActivity() {
setupGroupMessageAsMMS() setupGroupMessageAsMMS()
setupLockScreenVisibility() setupLockScreenVisibility()
setupMMSFileSizeLimit() setupMMSFileSizeLimit()
setupUseRecycleBin()
setupEmptyRecycleBin()
setupAppPasswordProtection() setupAppPasswordProtection()
updateTextColors(settings_nested_scrollview) updateTextColors(settings_nested_scrollview)
@ -60,6 +65,7 @@ class SettingsActivity : SimpleActivity() {
settings_general_settings_label, settings_general_settings_label,
settings_outgoing_messages_label, settings_outgoing_messages_label,
settings_notifications_label, settings_notifications_label,
settings_recycle_bin_label,
settings_security_label settings_security_label
).forEach { ).forEach {
it.setTextColor(getProperPrimaryColor()) it.setTextColor(getProperPrimaryColor())
@ -259,6 +265,43 @@ class SettingsActivity : SimpleActivity() {
} }
} }
private fun setupUseRecycleBin() {
updateRecycleBinButtons()
settings_use_recycle_bin.isChecked = config.useRecycleBin
settings_use_recycle_bin_holder.setOnClickListener {
settings_use_recycle_bin.toggle()
config.useRecycleBin = settings_use_recycle_bin.isChecked
updateRecycleBinButtons()
}
}
private fun updateRecycleBinButtons() {
settings_empty_recycle_bin_holder.beVisibleIf(config.useRecycleBin)
}
private fun setupEmptyRecycleBin() {
ensureBackgroundThread {
recycleBinMessages = messagesDB.getArchivedCount()
runOnUiThread {
settings_empty_recycle_bin_size.text =
resources.getQuantityString(R.plurals.delete_messages, recycleBinMessages, recycleBinMessages)
}
}
settings_empty_recycle_bin_holder.setOnClickListener {
if (recycleBinMessages == 0) {
toast(R.string.recycle_bin_empty)
} else {
ConfirmationDialog(this, "", R.string.empty_recycle_bin_confirmation, R.string.yes, R.string.no) {
emptyMessagesRecycleBin()
recycleBinMessages = 0
settings_empty_recycle_bin_size.text =
resources.getQuantityString(R.plurals.delete_messages, recycleBinMessages, recycleBinMessages)
}
}
}
}
private fun setupAppPasswordProtection() { private fun setupAppPasswordProtection() {
settings_app_password_protection.isChecked = config.isAppPasswordProtectionOn settings_app_password_protection.isChecked = config.isAppPasswordProtectionOn
settings_app_password_protection_holder.setOnClickListener { settings_app_password_protection_holder.setOnClickListener {

View File

@ -402,7 +402,7 @@ class ThreadActivity : SimpleActivity() {
activity = this, activity = this,
recyclerView = thread_messages_list, recyclerView = thread_messages_list,
itemClick = { handleItemClick(it) }, itemClick = { handleItemClick(it) },
deleteMessages = { deleteMessages(it) } deleteMessages = { messages, toRecycleBin -> deleteMessages(messages, toRecycleBin) }
) )
thread_messages_list.adapter = currAdapter thread_messages_list.adapter = currAdapter
@ -489,7 +489,7 @@ class ThreadActivity : SimpleActivity() {
} }
} }
private fun deleteMessages(messagesToRemove: List<Message>) { private fun deleteMessages(messagesToRemove: List<Message>, toRecycleBin: Boolean) {
val deletePosition = threadItems.indexOf(messagesToRemove.first()) val deletePosition = threadItems.indexOf(messagesToRemove.first())
messages.removeAll(messagesToRemove.toSet()) messages.removeAll(messagesToRemove.toSet())
threadItems = getThreadItems() threadItems = getThreadItems()
@ -508,10 +508,15 @@ class ThreadActivity : SimpleActivity() {
messagesToRemove.forEach { message -> messagesToRemove.forEach { message ->
val messageId = message.id val messageId = message.id
if (message.isScheduled) { if (message.isScheduled) {
// TODO: Moving scheduled messages to recycle bin maybe doesn't make sense
deleteScheduledMessage(messageId) deleteScheduledMessage(messageId)
cancelScheduleSendPendingIntent(messageId) cancelScheduleSendPendingIntent(messageId)
} else { } else {
deleteMessage(messageId, message.isMMS) if (toRecycleBin) {
moveMessageToRecycleBin(messageId)
} else {
deleteMessage(messageId, message.isMMS)
}
} }
} }
updateLastConversationMessage(threadId) updateLastConversationMessage(threadId)

View File

@ -23,7 +23,6 @@ import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.Target import com.bumptech.glide.request.target.Target
import com.simplemobiletools.commons.adapters.MyRecyclerViewListAdapter import com.simplemobiletools.commons.adapters.MyRecyclerViewListAdapter
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
@ -33,6 +32,7 @@ import com.simplemobiletools.smsmessenger.activities.NewConversationActivity
import com.simplemobiletools.smsmessenger.activities.SimpleActivity import com.simplemobiletools.smsmessenger.activities.SimpleActivity
import com.simplemobiletools.smsmessenger.activities.ThreadActivity import com.simplemobiletools.smsmessenger.activities.ThreadActivity
import com.simplemobiletools.smsmessenger.activities.VCardViewerActivity import com.simplemobiletools.smsmessenger.activities.VCardViewerActivity
import com.simplemobiletools.smsmessenger.dialogs.DeleteConfirmationDialog
import com.simplemobiletools.smsmessenger.dialogs.MessageDetailsDialog import com.simplemobiletools.smsmessenger.dialogs.MessageDetailsDialog
import com.simplemobiletools.smsmessenger.dialogs.SelectTextDialog import com.simplemobiletools.smsmessenger.dialogs.SelectTextDialog
import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.extensions.*
@ -58,7 +58,7 @@ class ThreadAdapter(
activity: SimpleActivity, activity: SimpleActivity,
recyclerView: MyRecyclerView, recyclerView: MyRecyclerView,
itemClick: (Any) -> Unit, itemClick: (Any) -> Unit,
val deleteMessages: (messages: List<Message>) -> Unit val deleteMessages: (messages: List<Message>, toRecycleBin: Boolean) -> Unit
) : MyRecyclerViewListAdapter<ThreadItem>(activity, recyclerView, ThreadItemDiffCallback(), itemClick) { ) : MyRecyclerViewListAdapter<ThreadItem>(activity, recyclerView, ThreadItemDiffCallback(), itemClick) {
private var fontSize = activity.getTextSize() private var fontSize = activity.getTextSize()
@ -206,11 +206,12 @@ class ThreadAdapter(
val baseString = R.string.deletion_confirmation val baseString = R.string.deletion_confirmation
val question = String.format(resources.getString(baseString), items) val question = String.format(resources.getString(baseString), items)
ConfirmationDialog(activity, question) { DeleteConfirmationDialog(activity, question, activity.config.useRecycleBin) { skipRecycleBin ->
ensureBackgroundThread { ensureBackgroundThread {
val messagesToRemove = getSelectedItems() val messagesToRemove = getSelectedItems()
if (messagesToRemove.isNotEmpty()) { if (messagesToRemove.isNotEmpty()) {
deleteMessages(messagesToRemove.filterIsInstance<Message>()) val toRecycleBin = !skipRecycleBin && activity.config.useRecycleBin
deleteMessages(messagesToRemove.filterIsInstance<Message>(), toRecycleBin)
} }
} }
} }

View File

@ -12,12 +12,9 @@ import com.simplemobiletools.smsmessenger.interfaces.AttachmentsDao
import com.simplemobiletools.smsmessenger.interfaces.ConversationsDao import com.simplemobiletools.smsmessenger.interfaces.ConversationsDao
import com.simplemobiletools.smsmessenger.interfaces.MessageAttachmentsDao import com.simplemobiletools.smsmessenger.interfaces.MessageAttachmentsDao
import com.simplemobiletools.smsmessenger.interfaces.MessagesDao import com.simplemobiletools.smsmessenger.interfaces.MessagesDao
import com.simplemobiletools.smsmessenger.models.Attachment import com.simplemobiletools.smsmessenger.models.*
import com.simplemobiletools.smsmessenger.models.Conversation
import com.simplemobiletools.smsmessenger.models.Message
import com.simplemobiletools.smsmessenger.models.MessageAttachment
@Database(entities = [Conversation::class, Attachment::class, MessageAttachment::class, Message::class], version = 7) @Database(entities = [Conversation::class, Attachment::class, MessageAttachment::class, Message::class, RecycleBinMessage::class], version = 8)
@TypeConverters(Converters::class) @TypeConverters(Converters::class)
abstract class MessagesDatabase : RoomDatabase() { abstract class MessagesDatabase : RoomDatabase() {
@ -44,6 +41,7 @@ abstract class MessagesDatabase : RoomDatabase() {
.addMigrations(MIGRATION_4_5) .addMigrations(MIGRATION_4_5)
.addMigrations(MIGRATION_5_6) .addMigrations(MIGRATION_5_6)
.addMigrations(MIGRATION_6_7) .addMigrations(MIGRATION_6_7)
.addMigrations(MIGRATION_7_8)
.build() .build()
} }
} }
@ -115,5 +113,14 @@ abstract class MessagesDatabase : RoomDatabase() {
} }
} }
} }
private val MIGRATION_7_8 = object : Migration(7, 8) {
override fun migrate(database: SupportSQLiteDatabase) {
database.apply {
execSQL("CREATE TABLE IF NOT EXISTS `recycle_bin_messages` (`id` INTEGER PRIMARY KEY, `deleted_ts` INTEGER NOT NULL)")
execSQL("CREATE UNIQUE INDEX `index_recycle_bin_messages_id` ON `recycle_bin_messages` (`id`)")
}
}
}
} }
} }

View File

@ -0,0 +1,39 @@
package com.simplemobiletools.smsmessenger.dialogs
import android.app.Activity
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.beGoneIf
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.smsmessenger.R
import kotlinx.android.synthetic.main.dialog_delete_confirmation.view.delete_remember_title
import kotlinx.android.synthetic.main.dialog_delete_confirmation.view.skip_the_recycle_bin_checkbox
class DeleteConfirmationDialog(
private val activity: Activity,
private val message: String,
private val showSkipRecycleBinOption: Boolean,
private val callback: (skipRecycleBin: Boolean) -> Unit
) {
private var dialog: AlertDialog? = null
val view = activity.layoutInflater.inflate(R.layout.dialog_delete_confirmation, null)!!
init {
view.delete_remember_title.text = message
view.skip_the_recycle_bin_checkbox.beGoneIf(!showSkipRecycleBinOption)
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.yes) { _, _ -> dialogConfirmed() }
.setNegativeButton(R.string.no, null)
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
dialog = alertDialog
}
}
}
private fun dialogConfirmed() {
dialog?.dismiss()
callback(view.skip_the_recycle_bin_checkbox.isChecked)
}
}

View File

@ -641,6 +641,36 @@ fun Context.deleteConversation(threadId: Long) {
messagesDB.deleteThreadMessages(threadId) messagesDB.deleteThreadMessages(threadId)
} }
fun Context.checkAndDeleteOldRecycleBinMessages(callback: (() -> Unit)? = null) {
if (config.useRecycleBin && config.lastRecycleBinCheck < System.currentTimeMillis() - DAY_SECONDS * 1000) {
config.lastRecycleBinCheck = System.currentTimeMillis()
ensureBackgroundThread {
try {
for (message in messagesDB.getOldRecycleBinMessages(System.currentTimeMillis() - MONTH_SECONDS * 1000L)) {
deleteMessage(message.id, message.isMMS)
}
callback?.invoke()
} catch (e: Exception) {
}
}
}
}
fun Context.emptyMessagesRecycleBin() {
val messages = messagesDB.getAllRecycleBinMessages()
for (message in messages) {
deleteMessage(message.id, message.isMMS)
}
}
fun Context.moveMessageToRecycleBin(id: Long) {
try {
messagesDB.insertRecycleBinEntry(RecycleBinMessage(id, System.currentTimeMillis()))
} catch (e: Exception) {
showErrorToast(e)
}
}
fun Context.deleteMessage(id: Long, isMMS: Boolean) { fun Context.deleteMessage(id: Long, isMMS: Boolean) {
val uri = if (isMMS) Mms.CONTENT_URI else Sms.CONTENT_URI val uri = if (isMMS) Mms.CONTENT_URI else Sms.CONTENT_URI
val selection = "${Sms._ID} = ?" val selection = "${Sms._ID} = ?"

View File

@ -103,4 +103,12 @@ class Config(context: Context) : BaseConfig(context) {
var keyboardHeight: Int var keyboardHeight: Int
get() = prefs.getInt(SOFT_KEYBOARD_HEIGHT, context.getDefaultKeyboardHeight()) get() = prefs.getInt(SOFT_KEYBOARD_HEIGHT, context.getDefaultKeyboardHeight())
set(keyboardHeight) = prefs.edit().putInt(SOFT_KEYBOARD_HEIGHT, keyboardHeight).apply() set(keyboardHeight) = prefs.edit().putInt(SOFT_KEYBOARD_HEIGHT, keyboardHeight).apply()
var useRecycleBin: Boolean
get() = prefs.getBoolean(USE_RECYCLE_BIN, false)
set(useRecycleBin) = prefs.edit().putBoolean(USE_RECYCLE_BIN, useRecycleBin).apply()
var lastRecycleBinCheck: Long
get() = prefs.getLong(LAST_RECYCLE_BIN_CHECK, 0L)
set(lastRecycleBinCheck) = prefs.edit().putLong(LAST_RECYCLE_BIN_CHECK, lastRecycleBinCheck).apply()
} }

View File

@ -40,6 +40,8 @@ const val SCHEDULED_MESSAGE_ID = "scheduled_message_id"
const val SOFT_KEYBOARD_HEIGHT = "soft_keyboard_height" const val SOFT_KEYBOARD_HEIGHT = "soft_keyboard_height"
const val IS_MMS = "is_mms" const val IS_MMS = "is_mms"
const val MESSAGE_ID = "message_id" const val MESSAGE_ID = "message_id"
const val USE_RECYCLE_BIN = "use_recycle_bin"
const val LAST_RECYCLE_BIN_CHECK = "last_recycle_bin_check"
private const val PATH = "com.simplemobiletools.smsmessenger.action." private const val PATH = "com.simplemobiletools.smsmessenger.action."
const val MARK_AS_READ = PATH + "mark_as_read" const val MARK_AS_READ = PATH + "mark_as_read"

View File

@ -1,9 +1,7 @@
package com.simplemobiletools.smsmessenger.interfaces package com.simplemobiletools.smsmessenger.interfaces
import androidx.room.Dao import androidx.room.*
import androidx.room.Insert import com.simplemobiletools.smsmessenger.models.RecycleBinMessage
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.simplemobiletools.smsmessenger.models.Message import com.simplemobiletools.smsmessenger.models.Message
@Dao @Dao
@ -11,6 +9,9 @@ interface MessagesDao {
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertOrUpdate(message: Message) fun insertOrUpdate(message: Message)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertRecycleBinEntry(recycleBinMessage: RecycleBinMessage)
@Insert(onConflict = OnConflictStrategy.IGNORE) @Insert(onConflict = OnConflictStrategy.IGNORE)
fun insertOrIgnore(message: Message): Long fun insertOrIgnore(message: Message): Long
@ -20,15 +21,24 @@ interface MessagesDao {
@Query("SELECT * FROM messages") @Query("SELECT * FROM messages")
fun getAll(): List<Message> fun getAll(): List<Message>
@Query("SELECT * FROM messages WHERE thread_id = :threadId") @Query("SELECT messages.* FROM messages LEFT OUTER JOIN recycle_bin_messages ON messages.id = recycle_bin_messages.id WHERE recycle_bin_messages.id IS NOT NULL")
fun getAllRecycleBinMessages(): List<Message>
@Query("SELECT messages.* FROM messages LEFT OUTER JOIN recycle_bin_messages ON messages.id = recycle_bin_messages.id WHERE recycle_bin_messages.id IS NOT NULL AND recycle_bin_messages.deleted_ts < :timestamp")
fun getOldRecycleBinMessages(timestamp: Long): List<Message>
@Query("SELECT messages.* FROM messages LEFT OUTER JOIN recycle_bin_messages ON messages.id = recycle_bin_messages.id WHERE recycle_bin_messages.id IS NULL AND thread_id = :threadId")
fun getThreadMessages(threadId: Long): List<Message> fun getThreadMessages(threadId: Long): List<Message>
@Query("SELECT * FROM messages WHERE thread_id = :threadId AND is_scheduled = 1") @Query("SELECT messages.* FROM messages LEFT OUTER JOIN recycle_bin_messages ON messages.id = recycle_bin_messages.id WHERE recycle_bin_messages.id IS NULL AND thread_id = :threadId AND is_scheduled = 1")
fun getScheduledThreadMessages(threadId: Long): List<Message> fun getScheduledThreadMessages(threadId: Long): List<Message>
@Query("SELECT * FROM messages WHERE thread_id = :threadId AND id = :messageId AND is_scheduled = 1") @Query("SELECT * FROM messages WHERE thread_id = :threadId AND id = :messageId AND is_scheduled = 1")
fun getScheduledMessageWithId(threadId: Long, messageId: Long): Message fun getScheduledMessageWithId(threadId: Long, messageId: Long): Message
@Query("SELECT COUNT(*) FROM recycle_bin_messages")
fun getArchivedCount(): Int
@Query("SELECT * FROM messages WHERE body LIKE :text") @Query("SELECT * FROM messages WHERE body LIKE :text")
fun getMessagesWithText(text: String): List<Message> fun getMessagesWithText(text: String): List<Message>
@ -44,11 +54,29 @@ interface MessagesDao {
@Query("UPDATE messages SET status = :status WHERE id = :id") @Query("UPDATE messages SET status = :status WHERE id = :id")
fun updateStatus(id: Long, status: Int): Int fun updateStatus(id: Long, status: Int): Int
@Transaction
fun delete(id: Long) {
deleteFromMessages(id)
deleteFromRecycleBin(id)
}
@Query("DELETE FROM messages WHERE id = :id") @Query("DELETE FROM messages WHERE id = :id")
fun delete(id: Long) fun deleteFromMessages(id: Long)
@Query("DELETE FROM recycle_bin_messages WHERE id = :id")
fun deleteFromRecycleBin(id: Long)
@Transaction
fun deleteThreadMessages(threadId: Long) {
deleteThreadMessagesFromRecycleBin(threadId)
deleteAllThreadMessages(threadId)
}
@Query("DELETE FROM messages WHERE thread_id = :threadId") @Query("DELETE FROM messages WHERE thread_id = :threadId")
fun deleteThreadMessages(threadId: Long) fun deleteAllThreadMessages(threadId: Long)
@Query("DELETE FROM recycle_bin_messages WHERE id IN (SELECT id FROM messages WHERE thread_id = :threadId)")
fun deleteThreadMessagesFromRecycleBin(threadId: Long)
@Query("DELETE FROM messages") @Query("DELETE FROM messages")
fun deleteAll() fun deleteAll()

View File

@ -0,0 +1,15 @@
package com.simplemobiletools.smsmessenger.models
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
@Entity(
tableName = "recycle_bin_messages",
indices = [(Index(value = ["id"], unique = true))]
)
data class RecycleBinMessage(
@PrimaryKey val id: Long,
@ColumnInfo(name = "deleted_ts") var deletedTS: Long
)

View File

@ -361,6 +361,55 @@
android:id="@+id/settings_outgoing_messages_divider" android:id="@+id/settings_outgoing_messages_divider"
layout="@layout/divider" /> layout="@layout/divider" />
<TextView
android:id="@+id/settings_recycle_bin_label"
style="@style/SettingsSectionLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/recycle_bin" />
<RelativeLayout
android:id="@+id/settings_use_recycle_bin_holder"
style="@style/SettingsHolderCheckboxStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
android:id="@+id/settings_use_recycle_bin"
style="@style/SettingsCheckboxStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/move_items_into_recycle_bin" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_empty_recycle_bin_holder"
style="@style/SettingsHolderTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/settings_empty_recycle_bin_label"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/empty_recycle_bin" />
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/settings_empty_recycle_bin_size"
style="@style/SettingsTextValueStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/settings_empty_recycle_bin_label"
tools:text="0 B" />
</RelativeLayout>
<include
android:id="@+id/settings_recycle_bin_divider"
layout="@layout/divider" />
<TextView <TextView
android:id="@+id/settings_security_label" android:id="@+id/settings_security_label"
style="@style/SettingsSectionLabelStyle" style="@style/SettingsSectionLabelStyle"

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/delete_remember_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/big_margin"
android:paddingTop="@dimen/big_margin"
android:paddingRight="@dimen/big_margin">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/delete_remember_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="@dimen/small_margin"
android:paddingBottom="@dimen/activity_margin"
android:text="@string/delete_whole_conversation_confirmation"
android:textSize="@dimen/bigger_text_size" />
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
android:id="@+id/skip_the_recycle_bin_checkbox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/delete_remember_title"
android:text="@string/skip_the_recycle_bin" />
</RelativeLayout>