Merge pull request #7 from SimpleMobileTools/master

upd
This commit is contained in:
solokot
2021-01-02 14:04:12 +03:00
committed by GitHub
38 changed files with 389 additions and 65 deletions

View File

@@ -1,6 +1,14 @@
Changelog Changelog
========== ==========
Version 5.8.0 *(2021-01-02)*
----------------------------
* Improved delivery reports, show a notification at failed messages
* Allow resending failed messages with tapping them
* Added multiple dual-SIM related improvements
* Many other UX, stability, performance and translation improvements
Version 5.7.0 *(2020-12-30)* Version 5.7.0 *(2020-12-30)*
---------------------------- ----------------------------

View File

@@ -16,8 +16,8 @@ android {
applicationId "com.simplemobiletools.smsmessenger" applicationId "com.simplemobiletools.smsmessenger"
minSdkVersion 22 minSdkVersion 22
targetSdkVersion 30 targetSdkVersion 30
versionCode 23 versionCode 25
versionName "5.7.0" versionName "5.8.0"
setProperty("archivesBaseName", "sms-messenger") setProperty("archivesBaseName", "sms-messenger")
} }
@@ -56,7 +56,7 @@ android {
} }
dependencies { dependencies {
implementation 'com.simplemobiletools:commons:5.32.19' implementation 'com.simplemobiletools:commons:5.32.20'
implementation 'org.greenrobot:eventbus:3.2.0' implementation 'org.greenrobot:eventbus:3.2.0'
implementation 'com.klinkerapps:android-smsmms:5.2.6' implementation 'com.klinkerapps:android-smsmms:5.2.6'
implementation 'com.github.tibbi:IndicatorFastScroll:08f512858a' implementation 'com.github.tibbi:IndicatorFastScroll:08f512858a'

View File

@@ -121,6 +121,10 @@
<service android:name="com.android.mms.transaction.TransactionService" /> <service android:name="com.android.mms.transaction.TransactionService" />
<receiver android:name=".receivers.SmsStatusSentReceiver" />
<receiver android:name=".receivers.SmsStatusDeliveredReceiver" />
<receiver <receiver
android:name=".receivers.SmsReceiver" android:name=".receivers.SmsReceiver"
android:permission="android.permission.BROADCAST_SMS"> android:permission="android.permission.BROADCAST_SMS">
@@ -149,11 +153,6 @@
android:exported="true" android:exported="true"
android:taskAffinity="com.klinker.android.messaging.MMS_RECEIVED" /> android:taskAffinity="com.klinker.android.messaging.MMS_RECEIVED" />
<receiver
android:name=".receivers.SmsSentReceiver"
android:exported="true"
android:taskAffinity="${applicationId}.SMS_SENT" />
<receiver <receiver
android:name=".receivers.MarkAsReadReceiver" android:name=".receivers.MarkAsReadReceiver"
android:enabled="true" android:enabled="true"

View File

@@ -8,6 +8,7 @@ import android.graphics.drawable.Drawable
import android.media.MediaMetadataRetriever import android.media.MediaMetadataRetriever
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.os.Handler
import android.provider.Telephony import android.provider.Telephony
import android.telephony.SubscriptionManager import android.telephony.SubscriptionManager
import android.text.TextUtils import android.text.TextUtils
@@ -39,6 +40,9 @@ import com.simplemobiletools.smsmessenger.adapters.ThreadAdapter
import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.extensions.*
import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.helpers.*
import com.simplemobiletools.smsmessenger.models.* import com.simplemobiletools.smsmessenger.models.*
import com.simplemobiletools.smsmessenger.receivers.SmsStatusDeliveredReceiver
import com.simplemobiletools.smsmessenger.receivers.SmsStatusSentReceiver
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.activity_thread.* import kotlinx.android.synthetic.main.activity_thread.*
import kotlinx.android.synthetic.main.item_attachment.view.* import kotlinx.android.synthetic.main.item_attachment.view.*
import kotlinx.android.synthetic.main.item_selected_contact.view.* import kotlinx.android.synthetic.main.item_selected_contact.view.*
@@ -53,6 +57,7 @@ class ThreadActivity : SimpleActivity() {
private var threadId = 0L private var threadId = 0L
private var currentSIMCardIndex = 0 private var currentSIMCardIndex = 0
private var isActivityVisible = false private var isActivityVisible = false
private var refreshedSinceSent = false
private var threadItems = ArrayList<ThreadItem>() private var threadItems = ArrayList<ThreadItem>()
private var bus: EventBus? = null private var bus: EventBus? = null
private var participants = ArrayList<SimpleContact>() private var participants = ArrayList<SimpleContact>()
@@ -219,8 +224,18 @@ class ThreadActivity : SimpleActivity() {
invalidateOptionsMenu() invalidateOptionsMenu()
runOnUiThread { runOnUiThread {
val adapter = ThreadAdapter(this, threadItems, thread_messages_list, thread_messages_fastscroller) {} val currAdapter = thread_messages_list.adapter
thread_messages_list.adapter = adapter if (currAdapter == null) {
ThreadAdapter(this, threadItems, thread_messages_list, thread_messages_fastscroller) {
(it as? ThreadError)?.apply {
thread_type_message.setText(it.messageText)
}
}.apply {
thread_messages_list.adapter = this
}
} else {
(currAdapter as ThreadAdapter).updateMessages(threadItems)
}
} }
SimpleContactsHelper(this).getAvailableContacts(false) { contacts -> SimpleContactsHelper(this).getAvailableContacts(false) { contacts ->
@@ -509,7 +524,11 @@ class ThreadActivity : SimpleActivity() {
items.add(message) items.add(message)
if (message.type == Telephony.Sms.MESSAGE_TYPE_FAILED) { if (message.type == Telephony.Sms.MESSAGE_TYPE_FAILED) {
items.add(ThreadError(message.id)) items.add(ThreadError(message.id, message.body))
}
if (message.type == Telephony.Sms.MESSAGE_TYPE_OUTBOX) {
items.add(ThreadSending(message.id))
} }
if (!message.read) { if (!message.read) {
@@ -637,12 +656,24 @@ class ThreadActivity : SimpleActivity() {
} }
try { try {
transaction.sendNewMessage(message, threadId) val smsSentIntent = Intent(this, SmsStatusSentReceiver::class.java)
val deliveredIntent = Intent(this, SmsStatusDeliveredReceiver::class.java)
transaction.setExplicitBroadcastForSentSms(smsSentIntent)
transaction.setExplicitBroadcastForDeliveredSms(deliveredIntent)
refreshedSinceSent = false
transaction.sendNewMessage(message, threadId)
thread_type_message.setText("") thread_type_message.setText("")
attachmentUris.clear() attachmentUris.clear()
thread_attachments_holder.beGone() thread_attachments_holder.beGone()
thread_attachments_wrapper.removeAllViews() thread_attachments_wrapper.removeAllViews()
Handler().postDelayed({
if (!refreshedSinceSent) {
refreshMessages()
}
}, 2000)
} catch (e: Exception) { } catch (e: Exception) {
showErrorToast(e) showErrorToast(e)
} catch (e: Error) { } catch (e: Error) {
@@ -704,8 +735,10 @@ class ThreadActivity : SimpleActivity() {
showSelectedContacts() showSelectedContacts()
} }
@SuppressLint("MissingPermission")
@Subscribe(threadMode = ThreadMode.ASYNC) @Subscribe(threadMode = ThreadMode.ASYNC)
fun refreshMessages(event: Events.RefreshMessages) { fun refreshMessages(event: Events.RefreshMessages) {
refreshedSinceSent = true
if (isActivityVisible) { if (isActivityVisible) {
notificationManager.cancel(threadId.hashCode()) notificationManager.cancel(threadId.hashCode())
} }
@@ -713,8 +746,17 @@ class ThreadActivity : SimpleActivity() {
val lastMaxId = messages.maxByOrNull { it.id }?.id ?: 0L val lastMaxId = messages.maxByOrNull { it.id }?.id ?: 0L
messages = getMessages(threadId) messages = getMessages(threadId)
messages.filter { !it.isReceivedMessage() && it.id > lastMaxId }.forEach { messages.filter { !it.isReceivedMessage() && it.id > lastMaxId }.forEach { latestMessage ->
messagesDB.insertOrIgnore(it) // subscriptionIds seem to be not filled out at sending with multiple SIM cards, so fill it manually
if (SubscriptionManager.from(this).activeSubscriptionInfoList?.size ?: 0 > 1) {
val SIMId = availableSIMCards.getOrNull(currentSIMCardIndex)?.subscriptionId
if (SIMId != null) {
updateMessageSubscriptionId(latestMessage.id, SIMId)
latestMessage.subscriptionId = SIMId
}
}
messagesDB.insertOrIgnore(latestMessage)
} }
setupAdapter() setupAdapter()

View File

@@ -56,6 +56,7 @@ class ConversationsAdapter(activity: SimpleActivity, var conversations: ArrayLis
R.id.cab_dial_number -> dialNumber() R.id.cab_dial_number -> dialNumber()
R.id.cab_copy_number -> copyNumberToClipboard() R.id.cab_copy_number -> copyNumberToClipboard()
R.id.cab_delete -> askConfirmDelete() R.id.cab_delete -> askConfirmDelete()
R.id.cab_select_all -> selectAll()
} }
} }

View File

@@ -39,6 +39,7 @@ import kotlinx.android.synthetic.main.item_received_unknown_attachment.view.*
import kotlinx.android.synthetic.main.item_sent_unknown_attachment.view.* import kotlinx.android.synthetic.main.item_sent_unknown_attachment.view.*
import kotlinx.android.synthetic.main.item_thread_date_time.view.* import kotlinx.android.synthetic.main.item_thread_date_time.view.*
import kotlinx.android.synthetic.main.item_thread_error.view.* import kotlinx.android.synthetic.main.item_thread_error.view.*
import kotlinx.android.synthetic.main.item_thread_sending.view.*
import kotlinx.android.synthetic.main.item_thread_success.view.* import kotlinx.android.synthetic.main.item_thread_success.view.*
class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem>, recyclerView: MyRecyclerView, fastScroller: FastScroller, class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem>, recyclerView: MyRecyclerView, fastScroller: FastScroller,
@@ -74,6 +75,7 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
R.id.cab_share -> shareText() R.id.cab_share -> shareText()
R.id.cab_select_text -> selectText() R.id.cab_select_text -> selectText()
R.id.cab_delete -> askConfirmDelete() R.id.cab_delete -> askConfirmDelete()
R.id.cab_select_all -> selectAll()
} }
} }
@@ -95,6 +97,7 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
THREAD_RECEIVED_MESSAGE -> R.layout.item_received_message THREAD_RECEIVED_MESSAGE -> R.layout.item_received_message
THREAD_SENT_MESSAGE_ERROR -> R.layout.item_thread_error THREAD_SENT_MESSAGE_ERROR -> R.layout.item_thread_error
THREAD_SENT_MESSAGE_SUCCESS -> R.layout.item_thread_success THREAD_SENT_MESSAGE_SUCCESS -> R.layout.item_thread_success
THREAD_SENT_MESSAGE_SENDING -> R.layout.item_thread_sending
else -> R.layout.item_sent_message else -> R.layout.item_sent_message
} }
return createViewHolder(layout, parent) return createViewHolder(layout, parent)
@@ -102,11 +105,14 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = messages[position] val item = messages[position]
holder.bindView(item, true, item is Message) { itemView, layoutPosition -> val isClickable = item is ThreadError || item is Message
val isLongClickable = item is Message
holder.bindView(item, isClickable, isLongClickable) { itemView, layoutPosition ->
when (item) { when (item) {
is ThreadDateTime -> setupDateTime(itemView, item) is ThreadDateTime -> setupDateTime(itemView, item)
is ThreadSuccess -> setupThreadSuccess(itemView) is ThreadSuccess -> setupThreadSuccess(itemView)
is ThreadError -> setupThreadError(itemView) is ThreadError -> setupThreadError(itemView)
is ThreadSending -> setupThreadSending(itemView)
else -> setupView(itemView, item as Message) else -> setupView(itemView, item as Message)
} }
} }
@@ -122,6 +128,7 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
(messages[position] as? Message)?.isReceivedMessage() == true -> THREAD_RECEIVED_MESSAGE (messages[position] as? Message)?.isReceivedMessage() == true -> THREAD_RECEIVED_MESSAGE
item is ThreadError -> THREAD_SENT_MESSAGE_ERROR item is ThreadError -> THREAD_SENT_MESSAGE_ERROR
item is ThreadSuccess -> THREAD_SENT_MESSAGE_SUCCESS item is ThreadSuccess -> THREAD_SENT_MESSAGE_SUCCESS
item is ThreadSending -> THREAD_SENT_MESSAGE_SENDING
else -> THREAD_SENT_MESSAGE else -> THREAD_SENT_MESSAGE
} }
} }
@@ -190,10 +197,13 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
private fun isThreadDateTime(position: Int) = messages.getOrNull(position) is ThreadDateTime private fun isThreadDateTime(position: Int) = messages.getOrNull(position) is ThreadDateTime
override fun onViewRecycled(holder: ViewHolder) { fun updateMessages(newMessages: ArrayList<ThreadItem>) {
super.onViewRecycled(holder) val oldHashCode = messages.hashCode()
if (!activity.isDestroyed && !activity.isFinishing && holder.itemView.thread_message_sender_photo != null) { val newHashCode = newMessages.hashCode()
Glide.with(activity).clear(holder.itemView.thread_message_sender_photo) if (newHashCode != oldHashCode) {
messages = newMessages
notifyDataSetChanged()
recyclerView.scrollToPosition(messages.size - 1)
} }
} }
@@ -256,7 +266,9 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
} }
builder.into(imageView.attachment_image) builder.into(imageView.attachment_image)
imageView.attachment_image.setOnClickListener { launchViewIntent(uri, mimetype, attachment.filename) } imageView.attachment_image.setOnClickListener {
launchViewIntent(uri, mimetype, attachment.filename)
}
} else { } else {
if (message.isReceivedMessage()) { if (message.isReceivedMessage()) {
val attachmentView = layoutInflater.inflate(R.layout.item_received_unknown_attachment, null).apply { val attachmentView = layoutInflater.inflate(R.layout.item_received_unknown_attachment, null).apply {
@@ -265,7 +277,9 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
thread_received_attachment_label.text = attachment.filename thread_received_attachment_label.text = attachment.filename
} }
setTextColor(textColor) setTextColor(textColor)
setOnClickListener { launchViewIntent(uri, mimetype, attachment.filename) } setOnClickListener {
launchViewIntent(uri, mimetype, attachment.filename)
}
} }
} }
thread_mesage_attachments_holder.addView(attachmentView) thread_mesage_attachments_holder.addView(attachmentView)
@@ -278,7 +292,9 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
if (attachment.filename.isNotEmpty()) { if (attachment.filename.isNotEmpty()) {
thread_sent_attachment_label.text = attachment.filename thread_sent_attachment_label.text = attachment.filename
} }
setOnClickListener { launchViewIntent(uri, mimetype, attachment.filename) } setOnClickListener {
launchViewIntent(uri, mimetype, attachment.filename)
}
} }
} }
thread_mesage_attachments_holder.addView(attachmentView) thread_mesage_attachments_holder.addView(attachmentView)
@@ -333,6 +349,20 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
} }
private fun setupThreadError(view: View) { private fun setupThreadError(view: View) {
view.thread_error.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize) view.thread_error.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize - 4)
}
private fun setupThreadSending(view: View) {
view.thread_sending.apply {
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
setTextColor(textColor)
}
}
override fun onViewRecycled(holder: ViewHolder) {
super.onViewRecycled(holder)
if (!activity.isDestroyed && !activity.isFinishing && holder.itemView.thread_message_sender_photo != null) {
Glide.with(activity).clear(holder.itemView.thread_message_sender_photo)
}
} }
} }

View File

@@ -8,6 +8,7 @@ import android.app.PendingIntent
import android.content.ContentValues import android.content.ContentValues
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.database.Cursor
import android.graphics.Bitmap import android.graphics.Bitmap
import android.media.AudioAttributes import android.media.AudioAttributes
import android.media.AudioManager import android.media.AudioManager
@@ -320,6 +321,28 @@ fun Context.getThreadSnippet(threadId: Long): String {
return snippet return snippet
} }
fun Context.getMessageRecipientAddress(messageId: Long): String {
val uri = Sms.CONTENT_URI
val projection = arrayOf(
Sms.ADDRESS
)
val selection = "${Sms._ID} = ?"
val selectionArgs = arrayOf(messageId.toString())
try {
val cursor = contentResolver.query(uri, projection, selection, selectionArgs, null)
cursor?.use {
if (cursor.moveToFirst()) {
return cursor.getStringValue(Sms.ADDRESS)
}
}
} catch (e: Exception) {
}
return ""
}
fun Context.getThreadParticipants(threadId: Long, contactsMap: HashMap<Int, SimpleContact>?): ArrayList<SimpleContact> { fun Context.getThreadParticipants(threadId: Long, contactsMap: HashMap<Int, SimpleContact>?): ArrayList<SimpleContact> {
val uri = Uri.parse("${MmsSms.CONTENT_CONVERSATIONS_URI}?simple=true") val uri = Uri.parse("${MmsSms.CONTENT_CONVERSATIONS_URI}?simple=true")
val projection = arrayOf( val projection = arrayOf(
@@ -554,6 +577,26 @@ fun Context.markThreadMessagesUnread(threadId: Long) {
} }
} }
fun Context.updateMessageType(id: Long, status: Int) {
val uri = Sms.CONTENT_URI
val contentValues = ContentValues().apply {
put(Sms.TYPE, status)
}
val selection = "${Sms._ID} = ?"
val selectionArgs = arrayOf(id.toString())
contentResolver.update(uri, contentValues, selection, selectionArgs)
}
fun Context.updateMessageSubscriptionId(messageId: Long, subscriptionId: Int) {
val uri = Sms.CONTENT_URI
val contentValues = ContentValues().apply {
put(Sms.SUBSCRIPTION_ID, subscriptionId)
}
val selection = "${Sms._ID} = ?"
val selectionArgs = arrayOf(messageId.toString())
contentResolver.update(uri, contentValues, selection, selectionArgs)
}
fun Context.updateUnreadCountBadge(conversations: List<Conversation>) { fun Context.updateUnreadCountBadge(conversations: List<Conversation>) {
val unreadCount = conversations.count { !it.read } val unreadCount = conversations.count { !it.read }
if (unreadCount == 0) { if (unreadCount == 0) {
@@ -592,18 +635,23 @@ fun Context.getThreadId(addresses: Set<String>): Long {
fun Context.showReceivedMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?) { fun Context.showReceivedMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?) {
val privateCursor = getMyContactsCursor()?.loadInBackground() val privateCursor = getMyContactsCursor()?.loadInBackground()
ensureBackgroundThread { ensureBackgroundThread {
var sender = getNameAndPhotoFromPhoneNumber(address).name val senderName = getNameFromAddress(address, privateCursor)
if (address == sender) {
val privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor)
sender = privateContacts.firstOrNull { it.doesContainPhoneNumber(address) }?.name ?: address
}
Handler(Looper.getMainLooper()).post { Handler(Looper.getMainLooper()).post {
showMessageNotification(address, body, threadId, bitmap, sender) showMessageNotification(address, body, threadId, bitmap, senderName)
} }
} }
} }
fun Context.getNameFromAddress(address: String, privateCursor: Cursor?): String {
var sender = getNameAndPhotoFromPhoneNumber(address).name
if (address == sender) {
val privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor)
sender = privateContacts.firstOrNull { it.doesContainPhoneNumber(address) }?.name ?: address
}
return sender
}
@SuppressLint("NewApi") @SuppressLint("NewApi")
fun Context.showMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?, sender: String) { fun Context.showMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?, sender: String) {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

View File

@@ -23,6 +23,7 @@ const val THREAD_RECEIVED_MESSAGE = 2
const val THREAD_SENT_MESSAGE = 3 const val THREAD_SENT_MESSAGE = 3
const val THREAD_SENT_MESSAGE_ERROR = 4 const val THREAD_SENT_MESSAGE_ERROR = 4
const val THREAD_SENT_MESSAGE_SUCCESS = 5 const val THREAD_SENT_MESSAGE_SUCCESS = 5
const val THREAD_SENT_MESSAGE_SENDING = 6
fun refreshMessages() { fun refreshMessages() {
EventBus.getDefault().post(Events.RefreshMessages()) EventBus.getDefault().post(Events.RefreshMessages())

View File

@@ -29,6 +29,9 @@ interface MessagesDao {
@Query("UPDATE messages SET read = 1 WHERE thread_id = :threadId") @Query("UPDATE messages SET read = 1 WHERE thread_id = :threadId")
fun markThreadRead(threadId: Long) fun markThreadRead(threadId: Long)
@Query("UPDATE messages SET type = :type WHERE id = :id")
fun updateType(id: Long, type: Int): Int
@Query("DELETE FROM messages WHERE id = :id") @Query("DELETE FROM messages WHERE id = :id")
fun delete(id: Long) fun delete(id: Long)

View File

@@ -19,7 +19,7 @@ data class Message(
@ColumnInfo(name = "attachment") val attachment: MessageAttachment?, @ColumnInfo(name = "attachment") val attachment: MessageAttachment?,
@ColumnInfo(name = "sender_name") var senderName: String, @ColumnInfo(name = "sender_name") var senderName: String,
@ColumnInfo(name = "sender_photo_uri") val senderPhotoUri: String, @ColumnInfo(name = "sender_photo_uri") val senderPhotoUri: String,
@ColumnInfo(name = "subscription_id") val subscriptionId: Int) : ThreadItem() { @ColumnInfo(name = "subscription_id") var subscriptionId: Int) : ThreadItem() {
fun isReceivedMessage() = type == Telephony.Sms.MESSAGE_TYPE_INBOX fun isReceivedMessage() = type == Telephony.Sms.MESSAGE_TYPE_INBOX
} }

View File

@@ -1,3 +1,3 @@
package com.simplemobiletools.smsmessenger.models package com.simplemobiletools.smsmessenger.models
data class ThreadError(val messageID: Long) : ThreadItem() data class ThreadError(val messageId: Long, val messageText: String) : ThreadItem()

View File

@@ -0,0 +1,3 @@
package com.simplemobiletools.smsmessenger.models
data class ThreadSending(val messageId: Long) : ThreadItem()

View File

@@ -44,7 +44,8 @@ class SmsReceiver : BroadcastReceiver() {
context.updateUnreadCountBadge(context.conversationsDB.getUnreadConversations()) context.updateUnreadCountBadge(context.conversationsDB.getUnreadConversations())
val participant = SimpleContact(0, 0, address, "", arrayListOf(address), ArrayList(), ArrayList()) val participant = SimpleContact(0, 0, address, "", arrayListOf(address), ArrayList(), ArrayList())
val message = Message(newMessageId, body, type, arrayListOf(participant), (date / 1000).toInt(), false, threadId, false, null, address, "", subscriptionId) val message = Message(newMessageId, body, type, arrayListOf(participant), (date / 1000).toInt(), false, threadId,
false, null, address, "", subscriptionId)
context.messagesDB.insertOrUpdate(message) context.messagesDB.insertOrUpdate(message)
} }

View File

@@ -1,12 +0,0 @@
package com.simplemobiletools.smsmessenger.receivers
import android.content.Context
import android.content.Intent
import com.klinker.android.send_message.SentReceiver
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
class SmsSentReceiver : SentReceiver() {
override fun onMessageStatusUpdated(context: Context, intent: Intent, receiverResultCode: Int) {
refreshMessages()
}
}

View File

@@ -0,0 +1,37 @@
package com.simplemobiletools.smsmessenger.receivers
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.provider.Telephony
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.smsmessenger.extensions.messagesDB
import com.simplemobiletools.smsmessenger.extensions.updateMessageType
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
class SmsStatusDeliveredReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.extras?.containsKey("message_uri") == true) {
val uri = Uri.parse(intent.getStringExtra("message_uri"))
val messageId = uri?.lastPathSegment?.toLong() ?: 0L
ensureBackgroundThread {
val type = Telephony.Sms.MESSAGE_TYPE_SENT
context.updateMessageType(messageId, type)
val updated = context.messagesDB.updateType(messageId, type)
if (updated == 0) {
Handler(Looper.getMainLooper()).postDelayed({
ensureBackgroundThread {
context.messagesDB.updateType(messageId, type)
}
}, 2000)
}
refreshMessages()
}
}
}
}

View File

@@ -0,0 +1,109 @@
package com.simplemobiletools.smsmessenger.receivers
import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.media.AudioAttributes
import android.media.AudioManager
import android.media.RingtoneManager
import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.provider.Telephony
import androidx.core.app.NotificationCompat
import com.simplemobiletools.commons.extensions.getMyContactsCursor
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.helpers.isOreoPlus
import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.activities.ThreadActivity
import com.simplemobiletools.smsmessenger.extensions.*
import com.simplemobiletools.smsmessenger.helpers.NOTIFICATION_CHANNEL
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
class SmsStatusSentReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.extras?.containsKey("message_uri") == true) {
val uri = Uri.parse(intent.getStringExtra("message_uri"))
val messageId = uri?.lastPathSegment?.toLong() ?: 0L
ensureBackgroundThread {
val type = if (intent.extras!!.containsKey("errorCode")) {
showSendingFailedNotification(context, messageId)
Telephony.Sms.MESSAGE_TYPE_FAILED
} else {
Telephony.Sms.MESSAGE_TYPE_OUTBOX
}
context.updateMessageType(messageId, type)
context.messagesDB.updateType(messageId, type)
refreshMessages()
}
}
}
private fun showSendingFailedNotification(context: Context, messageId: Long) {
Handler(Looper.getMainLooper()).post {
val privateCursor = context.getMyContactsCursor()?.loadInBackground()
ensureBackgroundThread {
val address = context.getMessageRecipientAddress(messageId)
val threadId = context.getThreadId(address)
val senderName = context.getNameFromAddress(address, privateCursor)
showNotification(context, senderName, threadId)
}
}
}
@SuppressLint("NewApi")
private fun showNotification(context: Context, recipientName: String, threadId: Long) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
if (isOreoPlus()) {
val audioAttributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setLegacyStreamType(AudioManager.STREAM_NOTIFICATION)
.build()
val name = context.getString(R.string.message_not_sent_short)
val importance = NotificationManager.IMPORTANCE_HIGH
NotificationChannel(NOTIFICATION_CHANNEL, name, importance).apply {
setBypassDnd(false)
enableLights(true)
setSound(soundUri, audioAttributes)
enableVibration(true)
notificationManager.createNotificationChannel(this)
}
}
val intent = Intent(context, ThreadActivity::class.java).apply {
putExtra(THREAD_ID, threadId)
}
val pendingIntent = PendingIntent.getActivity(context, threadId.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT)
val summaryText = String.format(context.getString(R.string.message_sending_error), recipientName)
val largeIcon = SimpleContactsHelper(context).getContactLetterIcon(recipientName)
val builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL)
.setContentTitle(context.getString(R.string.message_not_sent_short))
.setContentText(summaryText)
.setColor(context.config.primaryColor)
.setSmallIcon(R.drawable.ic_messenger)
.setLargeIcon(largeIcon)
.setStyle(NotificationCompat.BigTextStyle().bigText(summaryText))
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setDefaults(Notification.DEFAULT_LIGHTS)
.setCategory(Notification.CATEGORY_MESSAGE)
.setAutoCancel(true)
.setSound(soundUri, AudioManager.STREAM_NOTIFICATION)
.setChannelId(NOTIFICATION_CHANNEL)
notificationManager.notify(threadId.hashCode(), builder.build())
}
}

View File

@@ -42,7 +42,7 @@
android:id="@+id/no_contacts_placeholder" android:id="@+id/no_contacts_placeholder"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/message_divider_two" android:layout_below="@+id/suggestions_scrollview"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/bigger_margin" android:layout_marginTop="@dimen/bigger_margin"
android:alpha="0.8" android:alpha="0.8"

View File

@@ -6,6 +6,6 @@
android:gravity="end" android:gravity="end"
android:paddingStart="@dimen/activity_margin" android:paddingStart="@dimen/activity_margin"
android:paddingEnd="@dimen/activity_margin" android:paddingEnd="@dimen/activity_margin"
android:text="@string/message_not_sent" android:text="@string/message_not_sent_touch_retry"
android:textColor="@color/theme_dark_red_primary_color" android:textColor="@color/theme_dark_red_primary_color"
android:textSize="@dimen/normal_text_size" /> android:textSize="@dimen/normal_text_size" />

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/thread_sending"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:paddingStart="@dimen/activity_margin"
android:paddingEnd="@dimen/activity_margin"
android:text="@string/sending"
android:textSize="@dimen/normal_text_size" />

View File

@@ -25,4 +25,8 @@
android:id="@+id/cab_copy_number" android:id="@+id/cab_copy_number"
android:title="@string/copy_number_to_clipboard" android:title="@string/copy_number_to_clipboard"
app:showAsAction="never" /> app:showAsAction="never" />
<item
android:id="@+id/cab_select_all"
android:title="@string/select_all"
app:showAsAction="never" />
</menu> </menu>

View File

@@ -20,4 +20,8 @@
android:icon="@drawable/ic_delete_vector" android:icon="@drawable/ic_delete_vector"
android:title="@string/delete" android:title="@string/delete"
app:showAsAction="ifRoom" /> app:showAsAction="ifRoom" />
<item
android:id="@+id/cab_select_all"
android:title="@string/select_all"
app:showAsAction="never" />
</menu> </menu>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Schlichter SMS Messenger</string> <string name="app_name">Schlichter SMS Messenger</string>
<string name="app_launcher_name">SMS Messenger</string> <string name="app_launcher_name">SMS Messenger</string>
<string name="type_a_message">Schreibe eine Nachricht…</string> <string name="type_a_message">Schreibe eine Nachricht…</string>
<string name="message_not_sent">Nachricht wurde nicht gesendet.</string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">Person hinzufügen</string> <string name="add_person">Person hinzufügen</string>
<string name="attachment">Anhang</string> <string name="attachment">Anhang</string>
<string name="no_conversations_found">Keine gespeicherten Chats gefunden</string> <string name="no_conversations_found">Keine gespeicherten Chats gefunden</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Απλός SMS Messenger</string> <string name="app_name">Απλός SMS Messenger</string>
<string name="app_launcher_name">SMS Messenger</string> <string name="app_launcher_name">SMS Messenger</string>
<string name="type_a_message">Πληκτρολογήστε ένα μήνυμα…</string> <string name="type_a_message">Πληκτρολογήστε ένα μήνυμα…</string>
<string name="message_not_sent">Το μήνυμα δεν έχει σταλεί.</string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">Προσθήκη ατόμου</string> <string name="add_person">Προσθήκη ατόμου</string>
<string name="attachment">Συνημμένο</string> <string name="attachment">Συνημμένο</string>
<string name="no_conversations_found">Δεν βρέθηκαν αποθηκευμένες συνομιλίες</string> <string name="no_conversations_found">Δεν βρέθηκαν αποθηκευμένες συνομιλίες</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Mensajería SMS Simple</string> <string name="app_name">Mensajería SMS Simple</string>
<string name="app_launcher_name">Mensajería SMS</string> <string name="app_launcher_name">Mensajería SMS</string>
<string name="type_a_message">Escribe un mensaje…</string> <string name="type_a_message">Escribe un mensaje…</string>
<string name="message_not_sent">El mensaje no se ha enviado.</string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">Añadir persona</string> <string name="add_person">Añadir persona</string>
<string name="attachment">Archivo adjunto</string> <string name="attachment">Archivo adjunto</string>
<string name="no_conversations_found">No se han encontrado conversaciones</string> <string name="no_conversations_found">No se han encontrado conversaciones</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Simple SMS Messenger</string> <string name="app_name">Simple SMS Messenger</string>
<string name="app_launcher_name">SMS Messenger</string> <string name="app_launcher_name">SMS Messenger</string>
<string name="type_a_message">Écrivez un message…</string> <string name="type_a_message">Écrivez un message…</string>
<string name="message_not_sent">Le message n\'a pas été envoyé.</string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">Ajouter une personne</string> <string name="add_person">Ajouter une personne</string>
<string name="attachment">Pièce jointe</string> <string name="attachment">Pièce jointe</string>
<string name="no_conversations_found">Aucune conversation enregistrée n\'a été trouvée</string> <string name="no_conversations_found">Aucune conversation enregistrée n\'a été trouvée</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Simple SMS Messenger</string> <string name="app_name">Simple SMS Messenger</string>
<string name="app_launcher_name">SMS Messenger</string> <string name="app_launcher_name">SMS Messenger</string>
<string name="type_a_message">Ketik pesan…</string> <string name="type_a_message">Ketik pesan…</string>
<string name="message_not_sent">Pesan belum terkirim.</string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">Tambahkan Orang</string> <string name="add_person">Tambahkan Orang</string>
<string name="attachment">Lampiran</string> <string name="attachment">Lampiran</string>
<string name="no_conversations_found">Tidak ada percakapan tersimpan yang ditemukan</string> <string name="no_conversations_found">Tidak ada percakapan tersimpan yang ditemukan</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Simple ショートメール</string> <string name="app_name">Simple ショートメール</string>
<string name="app_launcher_name">ショートメール</string> <string name="app_launcher_name">ショートメール</string>
<string name="type_a_message">メッセージを入力してください…</string> <string name="type_a_message">メッセージを入力してください…</string>
<string name="message_not_sent">送信されませんでした。</string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">宛先を追加</string> <string name="add_person">宛先を追加</string>
<string name="attachment">添付</string> <string name="attachment">添付</string>
<string name="no_conversations_found">保存された会話はありません</string> <string name="no_conversations_found">保存された会話はありません</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Paprastas SMS Siuntiklis</string> <string name="app_name">Paprastas SMS Siuntiklis</string>
<string name="app_launcher_name">SMS Siuntiklis</string> <string name="app_launcher_name">SMS Siuntiklis</string>
<string name="type_a_message">Rašykite žinutę…</string> <string name="type_a_message">Rašykite žinutę…</string>
<string name="message_not_sent">Žinutė neišsiųsta.</string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">Pridėti žmogų</string> <string name="add_person">Pridėti žmogų</string>
<string name="attachment">Priedas</string> <string name="attachment">Priedas</string>
<string name="no_conversations_found">Nebuvo rasta išsaugotų pokalbių</string> <string name="no_conversations_found">Nebuvo rasta išsaugotų pokalbių</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Simple SMS Messenger</string> <string name="app_name">Simple SMS Messenger</string>
<string name="app_launcher_name">SMS മെസഞ്ചർ</string> <string name="app_launcher_name">SMS മെസഞ്ചർ</string>
<string name="type_a_message">മെസ്സേജ് ടൈപ്പ് ചെയ്യുക</string> <string name="type_a_message">മെസ്സേജ് ടൈപ്പ് ചെയ്യുക</string>
<string name="message_not_sent">മെസ്സേജ് അയച്ചിട്ടില്ല.</string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">വ്യക്തിയെ ചേർക്കുക</string> <string name="add_person">വ്യക്തിയെ ചേർക്കുക</string>
<string name="attachment">അറ്റാച്ചുമെന്റ്</string> <string name="attachment">അറ്റാച്ചുമെന്റ്</string>
<string name="no_conversations_found">സ്റ്റോർ ചെയ്ത സംഭാഷണങ്ങളൊന്നും കണ്ടെത്തിയില്ല</string> <string name="no_conversations_found">സ്റ്റോർ ചെയ്ത സംഭാഷണങ്ങളൊന്നും കണ്ടെത്തിയില്ല</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Eenvoudig Berichtenbeheer (SMS)</string> <string name="app_name">Eenvoudig Berichtenbeheer (SMS)</string>
<string name="app_launcher_name">Berichten</string> <string name="app_launcher_name">Berichten</string>
<string name="type_a_message">Typ een bericht…</string> <string name="type_a_message">Typ een bericht…</string>
<string name="message_not_sent">Bericht niet verzonden.</string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">Persoon toevoegen</string> <string name="add_person">Persoon toevoegen</string>
<string name="attachment">Bijlage</string> <string name="attachment">Bijlage</string>
<string name="no_conversations_found">Geen opgeslagen berichten gevonden</string> <string name="no_conversations_found">Geen opgeslagen berichten gevonden</string>
@@ -10,9 +12,9 @@
<string name="reply">Beantwoorden</string> <string name="reply">Beantwoorden</string>
<string name="show_character_counter">Teller voor het aantal tekens weergeven</string> <string name="show_character_counter">Teller voor het aantal tekens weergeven</string>
<string name="loading_messages">Berichten laden…</string> <string name="loading_messages">Berichten laden…</string>
<string name="no_reply_support">Sender doesn\'t support replies</string> <string name="no_reply_support">Afzender ondersteunt geen antwoorden</string>
<string name="draft">Draft</string> <string name="draft">Concept</string>
<string name="sending">Sending</string> <string name="sending">Versturen</string>
<!-- New conversation --> <!-- New conversation -->
<string name="new_conversation">Nieuw gesprek</string> <string name="new_conversation">Nieuw gesprek</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Simple SMS Messenger</string> <string name="app_name">Simple SMS Messenger</string>
<string name="app_launcher_name">SMS Messenger</string> <string name="app_launcher_name">SMS Messenger</string>
<string name="type_a_message">Escrever uma mensagem…</string> <string name="type_a_message">Escrever uma mensagem…</string>
<string name="message_not_sent">Mensagem não enviada</string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">Adicionar pessoa</string> <string name="add_person">Adicionar pessoa</string>
<string name="attachment">Anexo</string> <string name="attachment">Anexo</string>
<string name="no_conversations_found">Não foram encontradas conversas</string> <string name="no_conversations_found">Não foram encontradas conversas</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Simple SMS Messenger</string> <string name="app_name">Simple SMS Messenger</string>
<string name="app_launcher_name">Сообщения</string> <string name="app_launcher_name">Сообщения</string>
<string name="type_a_message">Введите сообщение…</string> <string name="type_a_message">Введите сообщение…</string>
<string name="message_not_sent">Сообщение не отправлено.</string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">Добавить участника</string> <string name="add_person">Добавить участника</string>
<string name="attachment">Вложение</string> <string name="attachment">Вложение</string>
<string name="no_conversations_found">Нет сохранённых переписок</string> <string name="no_conversations_found">Нет сохранённых переписок</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Jednoduché SMS správy</string> <string name="app_name">Jednoduché SMS správy</string>
<string name="app_launcher_name">SMS správy</string> <string name="app_launcher_name">SMS správy</string>
<string name="type_a_message">Zadajte správu…</string> <string name="type_a_message">Zadajte správu…</string>
<string name="message_not_sent">Správa nebola odoslaná.</string> <string name="message_not_sent_short">Správa nebola odoslaná</string>
<string name="message_not_sent_touch_retry">Správa neodoslaná. Dotykom to skúste znova.</string>
<string name="message_sending_error">Vaša správa pre \'%s\' nebola odoslaná</string>
<string name="add_person">Pridať osobu</string> <string name="add_person">Pridať osobu</string>
<string name="attachment">Príloha</string> <string name="attachment">Príloha</string>
<string name="no_conversations_found">Nenašli sa žiadne uložené konverzácie</string> <string name="no_conversations_found">Nenašli sa žiadne uložené konverzácie</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Basit SMS Messenger</string> <string name="app_name">Basit SMS Messenger</string>
<string name="app_launcher_name">SMS Messenger</string> <string name="app_launcher_name">SMS Messenger</string>
<string name="type_a_message">Bir mesaj yazın…</string> <string name="type_a_message">Bir mesaj yazın…</string>
<string name="message_not_sent">Mesaj gönderilmedi.</string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">Kişi Ekle</string> <string name="add_person">Kişi Ekle</string>
<string name="attachment">Ek</string> <string name="attachment">Ek</string>
<string name="no_conversations_found">Kaydedilmiş görüşme bulunamadı</string> <string name="no_conversations_found">Kaydedilmiş görüşme bulunamadı</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Simple SMS Messenger</string> <string name="app_name">Simple SMS Messenger</string>
<string name="app_launcher_name">Повідомлення</string> <string name="app_launcher_name">Повідомлення</string>
<string name="type_a_message">Введіть повідомлення…</string> <string name="type_a_message">Введіть повідомлення…</string>
<string name="message_not_sent">Повідомлення не надіслано. </string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">Додати учасник а</string> <string name="add_person">Додати учасник а</string>
<string name="attachment">Вкладення</string> <string name="attachment">Вкладення</string>
<string name="no_conversations_found">Немає збережених листувань</string> <string name="no_conversations_found">Немає збережених листувань</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">简易短信</string> <string name="app_name">简易短信</string>
<string name="app_launcher_name">短信</string> <string name="app_launcher_name">短信</string>
<string name="type_a_message">输入一个消息…</string> <string name="type_a_message">输入一个消息…</string>
<string name="message_not_sent">消息尚未发送。</string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">添加人</string> <string name="add_person">添加人</string>
<string name="attachment">附件</string> <string name="attachment">附件</string>
<string name="no_conversations_found">未找到保存的对话</string> <string name="no_conversations_found">未找到保存的对话</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Simple SMS Messenger</string> <string name="app_name">Simple SMS Messenger</string>
<string name="app_launcher_name">SMS Messenger</string> <string name="app_launcher_name">SMS Messenger</string>
<string name="type_a_message">Type a message…</string> <string name="type_a_message">Type a message…</string>
<string name="message_not_sent">Message has not been sent.</string> <string name="message_not_sent_short">Message not sent</string>
<string name="message_not_sent_touch_retry">Not sent. Touch to retry.</string>
<string name="message_sending_error">Your message to \'%s\' has not been sent</string>
<string name="add_person">Add Person</string> <string name="add_person">Add Person</string>
<string name="attachment">Attachment</string> <string name="attachment">Attachment</string>
<string name="no_conversations_found">No stored conversations have been found</string> <string name="no_conversations_found">No stored conversations have been found</string>

View File

@@ -0,0 +1,4 @@
* Improved delivery reports, show a notification at failed messages
* Allow resending failed messages with tapping them
* Added multiple dual-SIM related improvements
* Many other UX, stability, performance and translation improvements