Merge branch 'master' into export_import_settings
This commit is contained in:
commit
321e4f11ff
76 changed files with 1266 additions and 63 deletions
|
|
@ -0,0 +1,89 @@
|
|||
package com.simplemobiletools.smsmessenger.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.beVisibleIf
|
||||
import com.simplemobiletools.commons.extensions.getProperPrimaryColor
|
||||
import com.simplemobiletools.commons.extensions.underlineText
|
||||
import com.simplemobiletools.commons.extensions.updateTextColors
|
||||
import com.simplemobiletools.commons.helpers.APP_ICON_IDS
|
||||
import com.simplemobiletools.commons.helpers.APP_LAUNCHER_NAME
|
||||
import com.simplemobiletools.commons.helpers.NavigationIcon
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.dialogs.AddBlockedKeywordDialog
|
||||
import com.simplemobiletools.smsmessenger.dialogs.ManageBlockedKeywordsAdapter
|
||||
import com.simplemobiletools.smsmessenger.extensions.config
|
||||
import com.simplemobiletools.smsmessenger.extensions.toArrayList
|
||||
import kotlinx.android.synthetic.main.activity_manage_blocked_keywords.*
|
||||
|
||||
class ManageBlockedKeywordsActivity : BaseSimpleActivity(), RefreshRecyclerViewListener {
|
||||
override fun getAppIconIDs() = intent.getIntegerArrayListExtra(APP_ICON_IDS) ?: ArrayList()
|
||||
|
||||
override fun getAppLauncherName() = intent.getStringExtra(APP_LAUNCHER_NAME) ?: ""
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
isMaterialActivity = true
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_manage_blocked_keywords)
|
||||
updateBlockedKeywords()
|
||||
setupOptionsMenu()
|
||||
|
||||
updateMaterialActivityViews(block_keywords_coordinator, manage_blocked_keywords_list, useTransparentNavigation = true, useTopSearchMenu = false)
|
||||
setupMaterialScrollListener(manage_blocked_keywords_list, block_keywords_toolbar)
|
||||
updateTextColors(manage_blocked_keywords_wrapper)
|
||||
|
||||
manage_blocked_keywords_placeholder_2.apply {
|
||||
underlineText()
|
||||
setTextColor(getProperPrimaryColor())
|
||||
setOnClickListener {
|
||||
addOrEditBlockedKeyword()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
setupToolbar(block_keywords_toolbar, NavigationIcon.Arrow)
|
||||
}
|
||||
|
||||
private fun setupOptionsMenu() {
|
||||
block_keywords_toolbar.setOnMenuItemClickListener { menuItem ->
|
||||
when (menuItem.itemId) {
|
||||
R.id.add_blocked_keyword -> {
|
||||
addOrEditBlockedKeyword()
|
||||
true
|
||||
}
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun refreshItems() {
|
||||
updateBlockedKeywords()
|
||||
}
|
||||
|
||||
private fun updateBlockedKeywords() {
|
||||
ensureBackgroundThread {
|
||||
val blockedKeywords = config.blockedKeywords
|
||||
runOnUiThread {
|
||||
ManageBlockedKeywordsAdapter(this, blockedKeywords.toArrayList(), this, manage_blocked_keywords_list) {
|
||||
addOrEditBlockedKeyword(it as String)
|
||||
}.apply {
|
||||
manage_blocked_keywords_list.adapter = this
|
||||
}
|
||||
|
||||
manage_blocked_keywords_placeholder.beVisibleIf(blockedKeywords.isEmpty())
|
||||
manage_blocked_keywords_placeholder_2.beVisibleIf(blockedKeywords.isEmpty())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addOrEditBlockedKeyword(keyword: String? = null) {
|
||||
AddBlockedKeywordDialog(this, keyword) {
|
||||
updateBlockedKeywords()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -48,6 +48,7 @@ class SettingsActivity : SimpleActivity() {
|
|||
setupUseEnglish()
|
||||
setupLanguage()
|
||||
setupManageBlockedNumbers()
|
||||
setupManageBlockedKeywords()
|
||||
setupChangeDateTimeFormat()
|
||||
setupFontSize()
|
||||
setupShowCharacterCounter()
|
||||
|
|
@ -212,6 +213,20 @@ class SettingsActivity : SimpleActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun setupManageBlockedKeywords() {
|
||||
settings_manage_blocked_keywords.text = addLockedLabelIfNeeded(R.string.manage_blocked_keywords)
|
||||
|
||||
settings_manage_blocked_keywords_holder.setOnClickListener {
|
||||
if (isOrWasThankYouInstalled()) {
|
||||
Intent(this, ManageBlockedKeywordsActivity::class.java).apply {
|
||||
startActivity(this)
|
||||
}
|
||||
} else {
|
||||
FeatureLockedDialog(this) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupChangeDateTimeFormat() {
|
||||
settings_change_date_time_format_holder.setOnClickListener {
|
||||
ChangeDateTimeFormatDialog(this) {
|
||||
|
|
|
|||
|
|
@ -1606,6 +1606,7 @@ class ThreadActivity : SimpleActivity() {
|
|||
threadId = threadId,
|
||||
isMMS = isMmsMessage(text),
|
||||
attachment = MessageAttachment(messageId, text, buildMessageAttachments(messageId)),
|
||||
senderPhoneNumber = "",
|
||||
senderName = "",
|
||||
senderPhotoUri = "",
|
||||
subscriptionId = subscriptionId,
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import com.simplemobiletools.smsmessenger.activities.NewConversationActivity
|
|||
import com.simplemobiletools.smsmessenger.activities.SimpleActivity
|
||||
import com.simplemobiletools.smsmessenger.activities.ThreadActivity
|
||||
import com.simplemobiletools.smsmessenger.activities.VCardViewerActivity
|
||||
import com.simplemobiletools.smsmessenger.dialogs.MessageDetailsDialog
|
||||
import com.simplemobiletools.smsmessenger.dialogs.SelectTextDialog
|
||||
import com.simplemobiletools.smsmessenger.extensions.*
|
||||
import com.simplemobiletools.smsmessenger.helpers.*
|
||||
|
|
@ -82,6 +83,7 @@ class ThreadAdapter(
|
|||
findItem(R.id.cab_share).isVisible = isOneItemSelected && hasText
|
||||
findItem(R.id.cab_forward_message).isVisible = isOneItemSelected
|
||||
findItem(R.id.cab_select_text).isVisible = isOneItemSelected && hasText
|
||||
findItem(R.id.cab_properties).isVisible = isOneItemSelected
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -98,6 +100,7 @@ class ThreadAdapter(
|
|||
R.id.cab_select_text -> selectText()
|
||||
R.id.cab_delete -> askConfirmDelete()
|
||||
R.id.cab_select_all -> selectAll()
|
||||
R.id.cab_properties -> showMessageDetails()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -184,6 +187,11 @@ class ThreadAdapter(
|
|||
}
|
||||
}
|
||||
|
||||
private fun showMessageDetails() {
|
||||
val message = getSelectedItems().firstOrNull() as? Message ?: return
|
||||
MessageDetailsDialog(activity, message)
|
||||
}
|
||||
|
||||
private fun askConfirmDelete() {
|
||||
val itemsCnt = selectedKeys.size
|
||||
|
||||
|
|
@ -283,7 +291,7 @@ class ThreadAdapter(
|
|||
view.apply {
|
||||
thread_message_sender_photo.beVisible()
|
||||
thread_message_sender_photo.setOnClickListener {
|
||||
val contact = message.participants.first()
|
||||
val contact = message.getSender()!!
|
||||
context.getContactFromAddress(contact.phoneNumbers.first().normalizedNumber) {
|
||||
if (it != null) {
|
||||
activity.startContactDetailsIntent(it)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ 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 = 6)
|
||||
@Database(entities = [Conversation::class, Attachment::class, MessageAttachment::class, Message::class], version = 7)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class MessagesDatabase : RoomDatabase() {
|
||||
|
||||
|
|
@ -43,6 +43,7 @@ abstract class MessagesDatabase : RoomDatabase() {
|
|||
.addMigrations(MIGRATION_3_4)
|
||||
.addMigrations(MIGRATION_4_5)
|
||||
.addMigrations(MIGRATION_5_6)
|
||||
.addMigrations(MIGRATION_6_7)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
|
@ -106,5 +107,13 @@ abstract class MessagesDatabase : RoomDatabase() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val MIGRATION_6_7 = object : Migration(6, 7) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.apply {
|
||||
execSQL("ALTER TABLE messages ADD COLUMN sender_phone_number TEXT NOT NULL DEFAULT ''")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
package com.simplemobiletools.smsmessenger.dialogs
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import com.simplemobiletools.commons.extensions.showKeyboard
|
||||
import com.simplemobiletools.commons.extensions.value
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.extensions.config
|
||||
import kotlinx.android.synthetic.main.dialog_add_blocked_keyword.view.add_blocked_keyword_edittext
|
||||
|
||||
class AddBlockedKeywordDialog(val activity: BaseSimpleActivity, private val originalKeyword: String? = null, val callback: () -> Unit) {
|
||||
init {
|
||||
val view = activity.layoutInflater.inflate(R.layout.dialog_add_blocked_keyword, null).apply {
|
||||
if (originalKeyword != null) {
|
||||
add_blocked_keyword_edittext.setText(originalKeyword)
|
||||
}
|
||||
}
|
||||
|
||||
activity.getAlertDialogBuilder()
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.apply {
|
||||
activity.setupDialogStuff(view, this) { alertDialog ->
|
||||
alertDialog.showKeyboard(view.add_blocked_keyword_edittext)
|
||||
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||
val newBlockedKeyword = view.add_blocked_keyword_edittext.value
|
||||
if (originalKeyword != null && newBlockedKeyword != originalKeyword) {
|
||||
activity.config.removeBlockedKeyword(originalKeyword)
|
||||
}
|
||||
|
||||
if (newBlockedKeyword.isNotEmpty()) {
|
||||
activity.config.addBlockedKeyword(newBlockedKeyword)
|
||||
}
|
||||
|
||||
callback()
|
||||
alertDialog.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ import kotlinx.android.synthetic.main.dialog_export_messages.view.export_message
|
|||
import kotlinx.android.synthetic.main.dialog_export_messages.view.export_mms_checkbox
|
||||
import kotlinx.android.synthetic.main.dialog_export_messages.view.export_sms_checkbox
|
||||
|
||||
|
||||
class ExportMessagesDialog(
|
||||
private val activity: SimpleActivity,
|
||||
private val callback: (fileName: String) -> Unit,
|
||||
|
|
@ -39,6 +40,7 @@ class ExportMessagesDialog(
|
|||
filename.isAValidFilename() -> {
|
||||
callback(filename)
|
||||
alertDialog.dismiss()
|
||||
|
||||
}
|
||||
|
||||
else -> activity.toast(R.string.invalid_name)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,148 @@
|
|||
package com.simplemobiletools.smsmessenger.dialogs
|
||||
|
||||
import android.view.*
|
||||
import android.widget.PopupMenu
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
|
||||
import com.simplemobiletools.commons.extensions.copyToClipboard
|
||||
import com.simplemobiletools.commons.extensions.getPopupMenuTheme
|
||||
import com.simplemobiletools.commons.extensions.getProperTextColor
|
||||
import com.simplemobiletools.commons.extensions.setupViewBackground
|
||||
import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener
|
||||
import com.simplemobiletools.commons.views.MyRecyclerView
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.extensions.config
|
||||
import kotlinx.android.synthetic.main.item_manage_blocked_keyword.view.manage_blocked_keyword_holder
|
||||
import kotlinx.android.synthetic.main.item_manage_blocked_keyword.view.manage_blocked_keyword_title
|
||||
import kotlinx.android.synthetic.main.item_manage_blocked_keyword.view.overflow_menu_anchor
|
||||
import kotlinx.android.synthetic.main.item_manage_blocked_keyword.view.overflow_menu_icon
|
||||
|
||||
class ManageBlockedKeywordsAdapter(
|
||||
activity: BaseSimpleActivity, var blockedKeywords: ArrayList<String>, val listener: RefreshRecyclerViewListener?,
|
||||
recyclerView: MyRecyclerView, itemClick: (Any) -> Unit
|
||||
) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) {
|
||||
init {
|
||||
setupDragListener(true)
|
||||
}
|
||||
|
||||
override fun getActionMenuId() = R.menu.cab_blocked_keywords
|
||||
|
||||
override fun prepareActionMode(menu: Menu) {
|
||||
menu.apply {
|
||||
findItem(R.id.cab_copy_keyword).isVisible = isOneItemSelected()
|
||||
}
|
||||
}
|
||||
|
||||
override fun actionItemPressed(id: Int) {
|
||||
if (selectedKeys.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
when (id) {
|
||||
R.id.cab_copy_keyword -> copyKeywordToClipboard()
|
||||
R.id.cab_delete -> deleteSelection()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSelectableItemCount() = blockedKeywords.size
|
||||
|
||||
override fun getIsItemSelectable(position: Int) = true
|
||||
|
||||
override fun getItemSelectionKey(position: Int) = blockedKeywords.getOrNull(position)?.hashCode()
|
||||
|
||||
override fun getItemKeyPosition(key: Int) = blockedKeywords.indexOfFirst { it.hashCode() == key }
|
||||
|
||||
override fun onActionModeCreated() {}
|
||||
|
||||
override fun onActionModeDestroyed() {}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = createViewHolder(R.layout.item_manage_blocked_keyword, parent)
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val blockedKeyword = blockedKeywords[position]
|
||||
holder.bindView(blockedKeyword, true, true) { itemView, _ ->
|
||||
setupView(itemView, blockedKeyword)
|
||||
}
|
||||
bindViewHolder(holder)
|
||||
}
|
||||
|
||||
override fun getItemCount() = blockedKeywords.size
|
||||
|
||||
private fun getSelectedItems() = blockedKeywords.filter { selectedKeys.contains(it.hashCode()) }
|
||||
|
||||
private fun setupView(view: View, blockedKeyword: String) {
|
||||
view.apply {
|
||||
setupViewBackground(activity)
|
||||
manage_blocked_keyword_holder?.isSelected = selectedKeys.contains(blockedKeyword.hashCode())
|
||||
manage_blocked_keyword_title.apply {
|
||||
text = blockedKeyword
|
||||
setTextColor(textColor)
|
||||
}
|
||||
|
||||
overflow_menu_icon.drawable.apply {
|
||||
mutate()
|
||||
setTint(activity.getProperTextColor())
|
||||
}
|
||||
|
||||
overflow_menu_icon.setOnClickListener {
|
||||
showPopupMenu(overflow_menu_anchor, blockedKeyword)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPopupMenu(view: View, blockedKeyword: String) {
|
||||
finishActMode()
|
||||
val theme = activity.getPopupMenuTheme()
|
||||
val contextTheme = ContextThemeWrapper(activity, theme)
|
||||
|
||||
PopupMenu(contextTheme, view, Gravity.END).apply {
|
||||
inflate(getActionMenuId())
|
||||
setOnMenuItemClickListener { item ->
|
||||
val blockedKeywordId = blockedKeyword.hashCode()
|
||||
when (item.itemId) {
|
||||
R.id.cab_copy_keyword -> {
|
||||
executeItemMenuOperation(blockedKeywordId) {
|
||||
copyKeywordToClipboard()
|
||||
}
|
||||
}
|
||||
|
||||
R.id.cab_delete -> {
|
||||
executeItemMenuOperation(blockedKeywordId) {
|
||||
deleteSelection()
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun executeItemMenuOperation(blockedKeywordId: Int, callback: () -> Unit) {
|
||||
selectedKeys.add(blockedKeywordId)
|
||||
callback()
|
||||
selectedKeys.remove(blockedKeywordId)
|
||||
}
|
||||
|
||||
private fun copyKeywordToClipboard() {
|
||||
val selectedKeyword = getSelectedItems().firstOrNull() ?: return
|
||||
activity.copyToClipboard(selectedKeyword)
|
||||
finishActMode()
|
||||
}
|
||||
|
||||
private fun deleteSelection() {
|
||||
val deleteBlockedKeywords = HashSet<String>(selectedKeys.size)
|
||||
val positions = getSelectedItemPositions()
|
||||
|
||||
getSelectedItems().forEach {
|
||||
deleteBlockedKeywords.add(it)
|
||||
activity.config.removeBlockedKeyword(it)
|
||||
}
|
||||
|
||||
blockedKeywords.removeAll(deleteBlockedKeywords)
|
||||
removeSelectedItems(positions)
|
||||
if (blockedKeywords.isEmpty()) {
|
||||
listener?.refreshItems()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package com.simplemobiletools.smsmessenger.dialogs
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.telephony.SubscriptionInfo
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.dialogs.BasePropertiesDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.extensions.config
|
||||
import com.simplemobiletools.smsmessenger.extensions.subscriptionManagerCompat
|
||||
import com.simplemobiletools.smsmessenger.models.Message
|
||||
import org.joda.time.DateTime
|
||||
|
||||
class MessageDetailsDialog(val activity: BaseSimpleActivity, val message: Message) : BasePropertiesDialog(activity) {
|
||||
init {
|
||||
@SuppressLint("MissingPermission")
|
||||
val availableSIMs = activity.subscriptionManagerCompat().activeSubscriptionInfoList
|
||||
|
||||
addProperty(message.getSenderOrReceiverLabel(), message.getSenderOrReceiverPhoneNumbers())
|
||||
if (availableSIMs.count() > 1) {
|
||||
addProperty(R.string.message_details_sim, message.getSIM(availableSIMs))
|
||||
}
|
||||
addProperty(message.getSentOrReceivedAtLabel(), message.getSentOrReceivedAt())
|
||||
|
||||
activity.getAlertDialogBuilder()
|
||||
.setPositiveButton(R.string.ok) { _, _ -> }
|
||||
.apply {
|
||||
activity.setupDialogStuff(mDialogView, this, R.string.message_details)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Message.getSenderOrReceiverLabel(): Int {
|
||||
return if (isReceivedMessage()) {
|
||||
R.string.message_details_sender
|
||||
} else {
|
||||
R.string.message_details_receiver
|
||||
}
|
||||
}
|
||||
|
||||
private fun Message.getSenderOrReceiverPhoneNumbers(): String {
|
||||
return if (isReceivedMessage()) {
|
||||
formatContactInfo(senderName, senderPhoneNumber)
|
||||
} else {
|
||||
participants.joinToString(", ") {
|
||||
formatContactInfo(it.name, it.phoneNumbers.first().value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun formatContactInfo(name: String, phoneNumber: String): String {
|
||||
return if (name != phoneNumber) {
|
||||
"$name ($phoneNumber)"
|
||||
} else {
|
||||
phoneNumber
|
||||
}
|
||||
}
|
||||
|
||||
private fun Message.getSIM(availableSIMs: List<SubscriptionInfo>): String {
|
||||
return availableSIMs.firstOrNull { it.subscriptionId == subscriptionId }?.displayName?.toString() ?: activity.getString(R.string.unknown)
|
||||
}
|
||||
|
||||
private fun Message.getSentOrReceivedAtLabel(): Int {
|
||||
return if (isReceivedMessage()) {
|
||||
R.string.message_details_received_at
|
||||
} else {
|
||||
R.string.message_details_sent_at
|
||||
}
|
||||
}
|
||||
|
||||
private fun Message.getSentOrReceivedAt(): String {
|
||||
return DateTime(date * 1000L).toString("${activity.config.dateFormat} ${activity.getTimeFormat()}")
|
||||
}
|
||||
}
|
||||
|
|
@ -116,7 +116,23 @@ fun Context.getMessages(
|
|||
SimpleContact(0, 0, participantPhoto.name, photoUri, arrayListOf(phoneNumber), ArrayList(), ArrayList())
|
||||
}
|
||||
val isMMS = false
|
||||
val message = Message(id, body, type, status, ArrayList(participants), date, read, thread, isMMS, null, senderName, photoUri, subscriptionId)
|
||||
val message =
|
||||
Message(
|
||||
id,
|
||||
body,
|
||||
type,
|
||||
status,
|
||||
ArrayList(participants),
|
||||
date,
|
||||
read,
|
||||
thread,
|
||||
isMMS,
|
||||
null,
|
||||
senderNumber,
|
||||
senderName,
|
||||
photoUri,
|
||||
subscriptionId
|
||||
)
|
||||
messages.add(message)
|
||||
}
|
||||
|
||||
|
|
@ -189,17 +205,34 @@ fun Context.getMMS(threadId: Long? = null, getImageResolutions: Boolean = false,
|
|||
val isMMS = true
|
||||
val attachment = getMmsAttachment(mmsId, getImageResolutions)
|
||||
val body = attachment.text
|
||||
var senderNumber = ""
|
||||
var senderName = ""
|
||||
var senderPhotoUri = ""
|
||||
|
||||
if (type != Mms.MESSAGE_BOX_SENT && type != Mms.MESSAGE_BOX_FAILED) {
|
||||
val number = getMMSSender(mmsId)
|
||||
val namePhoto = getNameAndPhotoFromPhoneNumber(number)
|
||||
senderNumber = getMMSSender(mmsId)
|
||||
val namePhoto = getNameAndPhotoFromPhoneNumber(senderNumber)
|
||||
senderName = namePhoto.name
|
||||
senderPhotoUri = namePhoto.photoUri ?: ""
|
||||
}
|
||||
|
||||
val message = Message(mmsId, body, type, status, participants, date, read, threadId, isMMS, attachment, senderName, senderPhotoUri, subscriptionId)
|
||||
val message =
|
||||
Message(
|
||||
mmsId,
|
||||
body,
|
||||
type,
|
||||
status,
|
||||
participants,
|
||||
date,
|
||||
read,
|
||||
threadId,
|
||||
isMMS,
|
||||
attachment,
|
||||
senderNumber,
|
||||
senderName,
|
||||
senderPhotoUri,
|
||||
subscriptionId
|
||||
)
|
||||
messages.add(message)
|
||||
|
||||
participants.forEach {
|
||||
|
|
@ -557,7 +590,16 @@ fun Context.getNameAndPhotoFromPhoneNumber(number: String): NamePhoto {
|
|||
return NamePhoto(number, null)
|
||||
}
|
||||
|
||||
fun Context.insertNewSMS(address: String, subject: String, body: String, date: Long, read: Int, threadId: Long, type: Int, subscriptionId: Int): Long {
|
||||
fun Context.insertNewSMS(
|
||||
address: String,
|
||||
subject: String,
|
||||
body: String,
|
||||
date: Long,
|
||||
read: Int,
|
||||
threadId: Long,
|
||||
type: Int,
|
||||
subscriptionId: Int
|
||||
): Long {
|
||||
val uri = Sms.CONTENT_URI
|
||||
val contentValues = ContentValues().apply {
|
||||
put(Sms.ADDRESS, address)
|
||||
|
|
|
|||
|
|
@ -68,6 +68,18 @@ class Config(context: Context) : BaseConfig(context) {
|
|||
pinnedConversations = pinnedConversations.minus(conversations.map { it.threadId.toString() })
|
||||
}
|
||||
|
||||
var blockedKeywords: Set<String>
|
||||
get() = prefs.getStringSet(BLOCKED_KEYWORDS, HashSet<String>())!!
|
||||
set(blockedKeywords) = prefs.edit().putStringSet(BLOCKED_KEYWORDS, blockedKeywords).apply()
|
||||
|
||||
fun addBlockedKeyword(keyword: String) {
|
||||
blockedKeywords = blockedKeywords.plus(keyword)
|
||||
}
|
||||
|
||||
fun removeBlockedKeyword(keyword: String) {
|
||||
blockedKeywords = blockedKeywords.minus(keyword)
|
||||
}
|
||||
|
||||
var exportSms: Boolean
|
||||
get() = prefs.getBoolean(EXPORT_SMS, true)
|
||||
set(exportSms) = prefs.edit().putBoolean(EXPORT_SMS, exportSms).apply()
|
||||
|
|
|
|||
|
|
@ -25,10 +25,13 @@ const val SEND_LONG_MESSAGE_MMS = "send_long_message_mms"
|
|||
const val SEND_GROUP_MESSAGE_MMS = "send_group_message_mms"
|
||||
const val MMS_FILE_SIZE_LIMIT = "mms_file_size_limit"
|
||||
const val PINNED_CONVERSATIONS = "pinned_conversations"
|
||||
const val BLOCKED_KEYWORDS = "blocked_keywords"
|
||||
const val EXPORT_SMS = "export_sms"
|
||||
const val EXPORT_MMS = "export_mms"
|
||||
const val EXPORT_MIME_TYPE = "application/json"
|
||||
const val EXPORT_FILE_EXT = ".json"
|
||||
const val JSON_FILE_EXTENSION = ".json"
|
||||
const val JSON_MIME_TYPE = "application/json"
|
||||
const val XML_MIME_TYPE = "text/xml"
|
||||
const val TXT_MIME_TYPE = "text/plain"
|
||||
const val IMPORT_SMS = "import_sms"
|
||||
const val IMPORT_MMS = "import_mms"
|
||||
const val WAS_DB_CLEARED = "was_db_cleared_2"
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
|||
import com.simplemobiletools.smsmessenger.extensions.config
|
||||
import com.simplemobiletools.smsmessenger.models.*
|
||||
|
||||
|
||||
class MessagesImporter(private val context: Context) {
|
||||
|
||||
private val messageWriter = MessagesWriter(context)
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ class MessagesReader(private val context: Context) {
|
|||
smsList.add(SmsBackup(subscriptionId, address, body, date, dateSent, locked, protocol, read, status, type, serviceCenter))
|
||||
}
|
||||
}
|
||||
|
||||
return smsList
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ data class Message(
|
|||
@ColumnInfo(name = "thread_id") val threadId: Long,
|
||||
@ColumnInfo(name = "is_mms") val isMMS: Boolean,
|
||||
@ColumnInfo(name = "attachment") val attachment: MessageAttachment?,
|
||||
@ColumnInfo(name = "sender_phone_number") val senderPhoneNumber: String,
|
||||
@ColumnInfo(name = "sender_name") var senderName: String,
|
||||
@ColumnInfo(name = "sender_photo_uri") val senderPhotoUri: String,
|
||||
@ColumnInfo(name = "subscription_id") var subscriptionId: Int,
|
||||
|
|
@ -28,6 +29,11 @@ data class Message(
|
|||
|
||||
fun millis() = date * 1000L
|
||||
|
||||
fun getSender(): SimpleContact? =
|
||||
participants.firstOrNull { it.doesHavePhoneNumber(senderPhoneNumber) }
|
||||
?: participants.firstOrNull { it.name == senderName }
|
||||
?: participants.firstOrNull()
|
||||
|
||||
companion object {
|
||||
|
||||
fun getStableId(message: Message): Long {
|
||||
|
|
@ -37,6 +43,7 @@ data class Message(
|
|||
result = 31 * result + message.threadId.hashCode()
|
||||
result = 31 * result + message.isMMS.hashCode()
|
||||
result = 31 * result + (message.attachment?.hashCode() ?: 0)
|
||||
result = 31 * result + message.senderPhoneNumber.hashCode()
|
||||
result = 31 * result + message.senderName.hashCode()
|
||||
result = 31 * result + message.senderPhotoUri.hashCode()
|
||||
result = 31 * result + message.isScheduled.hashCode()
|
||||
|
|
@ -53,6 +60,7 @@ data class Message(
|
|||
old.date == new.date &&
|
||||
old.isMMS == new.isMMS &&
|
||||
old.attachment == new.attachment &&
|
||||
old.senderPhoneNumber == new.senderPhoneNumber &&
|
||||
old.senderName == new.senderName &&
|
||||
old.senderPhotoUri == new.senderPhotoUri &&
|
||||
old.isScheduled == new.isScheduled
|
||||
|
|
|
|||
|
|
@ -37,13 +37,15 @@ class DirectReplyReceiver : BroadcastReceiver() {
|
|||
}
|
||||
|
||||
ensureBackgroundThread {
|
||||
var messageId: Long = 0L
|
||||
var messageId = 0L
|
||||
try {
|
||||
context.sendMessageCompat(body, listOf(address), subscriptionId, emptyList())
|
||||
val message = context.getMessages(threadId, getImageResolutions = false, includeScheduledMessages = false, limit = 1).lastOrNull()
|
||||
if (message != null) {
|
||||
context.messagesDB.insertOrUpdate(message)
|
||||
messageId = message.id
|
||||
|
||||
context.updateLastConversationMessage(threadId)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
context.showErrorToast(e)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import android.net.Uri
|
|||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import com.bumptech.glide.Glide
|
||||
import com.klinker.android.send_message.MmsReceivedReceiver
|
||||
import com.simplemobiletools.commons.extensions.isNumberBlocked
|
||||
import com.simplemobiletools.commons.extensions.normalizePhoneNumber
|
||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||
|
|
@ -13,7 +14,7 @@ import com.simplemobiletools.smsmessenger.extensions.*
|
|||
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
||||
|
||||
// more info at https://github.com/klinker41/android-smsmms
|
||||
class MmsReceiver : com.klinker.android.send_message.MmsReceivedReceiver() {
|
||||
class MmsReceiver : MmsReceivedReceiver() {
|
||||
|
||||
override fun isAddressBlocked(context: Context, address: String): Boolean {
|
||||
val normalizedAddress = address.normalizePhoneNumber()
|
||||
|
|
@ -22,7 +23,7 @@ class MmsReceiver : com.klinker.android.send_message.MmsReceivedReceiver() {
|
|||
|
||||
override fun onMessageReceived(context: Context, messageUri: Uri) {
|
||||
val mms = context.getLatestMMS() ?: return
|
||||
val address = mms.participants.firstOrNull()?.phoneNumbers?.first()?.normalizedNumber ?: ""
|
||||
val address = mms.getSender()?.phoneNumbers?.first()?.normalizedNumber ?: ""
|
||||
|
||||
val size = context.resources.getDimension(R.dimen.notification_large_icon_size).toInt()
|
||||
ensureBackgroundThread {
|
||||
|
|
|
|||
|
|
@ -55,8 +55,21 @@ class SmsReceiver : BroadcastReceiver() {
|
|||
}
|
||||
|
||||
private fun handleMessage(
|
||||
context: Context, address: String, subject: String, body: String, date: Long, read: Int, threadId: Long, type: Int, subscriptionId: Int, status: Int
|
||||
context: Context,
|
||||
address: String,
|
||||
subject: String,
|
||||
body: String,
|
||||
date: Long,
|
||||
read: Int,
|
||||
threadId: Long,
|
||||
type: Int,
|
||||
subscriptionId: Int,
|
||||
status: Int
|
||||
) {
|
||||
if (isMessageFilteredOut(context, body)) {
|
||||
return
|
||||
}
|
||||
|
||||
val photoUri = SimpleContactsHelper(context).getPhotoUriFromPhoneNumber(address)
|
||||
val bitmap = context.getNotificationBitmap(photoUri)
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
|
|
@ -83,7 +96,22 @@ class SmsReceiver : BroadcastReceiver() {
|
|||
val messageDate = (date / 1000).toInt()
|
||||
|
||||
val message =
|
||||
Message(newMessageId, body, type, status, participants, messageDate, false, threadId, false, null, senderName, photoUri, subscriptionId)
|
||||
Message(
|
||||
newMessageId,
|
||||
body,
|
||||
type,
|
||||
status,
|
||||
participants,
|
||||
messageDate,
|
||||
false,
|
||||
threadId,
|
||||
false,
|
||||
null,
|
||||
address,
|
||||
senderName,
|
||||
photoUri,
|
||||
subscriptionId
|
||||
)
|
||||
context.messagesDB.insertOrUpdate(message)
|
||||
refreshMessages()
|
||||
context.showReceivedMessageNotification(newMessageId, address, body, threadId, bitmap)
|
||||
|
|
@ -91,4 +119,14 @@ class SmsReceiver : BroadcastReceiver() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isMessageFilteredOut(context: Context, body: String): Boolean {
|
||||
for (blockedKeyword in context.config.blockedKeywords) {
|
||||
if (body.contains(blockedKeyword, ignoreCase = true)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue