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
==========
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)*
----------------------------

View File

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

View File

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

View File

@@ -8,6 +8,7 @@ import android.graphics.drawable.Drawable
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.provider.Telephony
import android.telephony.SubscriptionManager
import android.text.TextUtils
@@ -39,6 +40,9 @@ import com.simplemobiletools.smsmessenger.adapters.ThreadAdapter
import com.simplemobiletools.smsmessenger.extensions.*
import com.simplemobiletools.smsmessenger.helpers.*
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.item_attachment.view.*
import kotlinx.android.synthetic.main.item_selected_contact.view.*
@@ -53,6 +57,7 @@ class ThreadActivity : SimpleActivity() {
private var threadId = 0L
private var currentSIMCardIndex = 0
private var isActivityVisible = false
private var refreshedSinceSent = false
private var threadItems = ArrayList<ThreadItem>()
private var bus: EventBus? = null
private var participants = ArrayList<SimpleContact>()
@@ -219,8 +224,18 @@ class ThreadActivity : SimpleActivity() {
invalidateOptionsMenu()
runOnUiThread {
val adapter = ThreadAdapter(this, threadItems, thread_messages_list, thread_messages_fastscroller) {}
thread_messages_list.adapter = adapter
val currAdapter = thread_messages_list.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 ->
@@ -509,7 +524,11 @@ class ThreadActivity : SimpleActivity() {
items.add(message)
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) {
@@ -637,12 +656,24 @@ class ThreadActivity : SimpleActivity() {
}
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("")
attachmentUris.clear()
thread_attachments_holder.beGone()
thread_attachments_wrapper.removeAllViews()
Handler().postDelayed({
if (!refreshedSinceSent) {
refreshMessages()
}
}, 2000)
} catch (e: Exception) {
showErrorToast(e)
} catch (e: Error) {
@@ -704,8 +735,10 @@ class ThreadActivity : SimpleActivity() {
showSelectedContacts()
}
@SuppressLint("MissingPermission")
@Subscribe(threadMode = ThreadMode.ASYNC)
fun refreshMessages(event: Events.RefreshMessages) {
refreshedSinceSent = true
if (isActivityVisible) {
notificationManager.cancel(threadId.hashCode())
}
@@ -713,8 +746,17 @@ class ThreadActivity : SimpleActivity() {
val lastMaxId = messages.maxByOrNull { it.id }?.id ?: 0L
messages = getMessages(threadId)
messages.filter { !it.isReceivedMessage() && it.id > lastMaxId }.forEach {
messagesDB.insertOrIgnore(it)
messages.filter { !it.isReceivedMessage() && it.id > lastMaxId }.forEach { latestMessage ->
// 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()

View File

@@ -56,6 +56,7 @@ class ConversationsAdapter(activity: SimpleActivity, var conversations: ArrayLis
R.id.cab_dial_number -> dialNumber()
R.id.cab_copy_number -> copyNumberToClipboard()
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_thread_date_time.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.*
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_select_text -> selectText()
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_SENT_MESSAGE_ERROR -> R.layout.item_thread_error
THREAD_SENT_MESSAGE_SUCCESS -> R.layout.item_thread_success
THREAD_SENT_MESSAGE_SENDING -> R.layout.item_thread_sending
else -> R.layout.item_sent_message
}
return createViewHolder(layout, parent)
@@ -102,11 +105,14 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
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) {
is ThreadDateTime -> setupDateTime(itemView, item)
is ThreadSuccess -> setupThreadSuccess(itemView)
is ThreadError -> setupThreadError(itemView)
is ThreadSending -> setupThreadSending(itemView)
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
item is ThreadError -> THREAD_SENT_MESSAGE_ERROR
item is ThreadSuccess -> THREAD_SENT_MESSAGE_SUCCESS
item is ThreadSending -> THREAD_SENT_MESSAGE_SENDING
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
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)
fun updateMessages(newMessages: ArrayList<ThreadItem>) {
val oldHashCode = messages.hashCode()
val newHashCode = newMessages.hashCode()
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)
imageView.attachment_image.setOnClickListener { launchViewIntent(uri, mimetype, attachment.filename) }
imageView.attachment_image.setOnClickListener {
launchViewIntent(uri, mimetype, attachment.filename)
}
} else {
if (message.isReceivedMessage()) {
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
}
setTextColor(textColor)
setOnClickListener { launchViewIntent(uri, mimetype, attachment.filename) }
setOnClickListener {
launchViewIntent(uri, mimetype, attachment.filename)
}
}
}
thread_mesage_attachments_holder.addView(attachmentView)
@@ -278,7 +292,9 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
if (attachment.filename.isNotEmpty()) {
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)
@@ -333,6 +349,20 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
}
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.Context
import android.content.Intent
import android.database.Cursor
import android.graphics.Bitmap
import android.media.AudioAttributes
import android.media.AudioManager
@@ -320,6 +321,28 @@ fun Context.getThreadSnippet(threadId: Long): String {
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> {
val uri = Uri.parse("${MmsSms.CONTENT_CONVERSATIONS_URI}?simple=true")
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>) {
val unreadCount = conversations.count { !it.read }
if (unreadCount == 0) {
@@ -592,16 +635,21 @@ fun Context.getThreadId(addresses: Set<String>): Long {
fun Context.showReceivedMessageNotification(address: String, body: String, threadId: Long, bitmap: Bitmap?) {
val privateCursor = getMyContactsCursor()?.loadInBackground()
ensureBackgroundThread {
val senderName = getNameFromAddress(address, privateCursor)
Handler(Looper.getMainLooper()).post {
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
}
Handler(Looper.getMainLooper()).post {
showMessageNotification(address, body, threadId, bitmap, sender)
}
}
return sender
}
@SuppressLint("NewApi")

View File

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

View File

@@ -29,6 +29,9 @@ interface MessagesDao {
@Query("UPDATE messages SET read = 1 WHERE thread_id = :threadId")
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")
fun delete(id: Long)

View File

@@ -19,7 +19,7 @@ data class Message(
@ColumnInfo(name = "attachment") val attachment: MessageAttachment?,
@ColumnInfo(name = "sender_name") var senderName: 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
}

View File

@@ -1,3 +1,3 @@
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())
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)
}

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:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/message_divider_two"
android:layout_below="@+id/suggestions_scrollview"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/bigger_margin"
android:alpha="0.8"

View File

@@ -6,6 +6,6 @@
android:gravity="end"
android:paddingStart="@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: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:title="@string/copy_number_to_clipboard"
app:showAsAction="never" />
<item
android:id="@+id/cab_select_all"
android:title="@string/select_all"
app:showAsAction="never" />
</menu>

View File

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

View File

@@ -2,7 +2,9 @@
<string name="app_name">Schlichter SMS Messenger</string>
<string name="app_launcher_name">SMS Messenger</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="attachment">Anhang</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_launcher_name">SMS Messenger</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="attachment">Συνημμένο</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_launcher_name">Mensajería SMS</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="attachment">Archivo adjunto</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_launcher_name">SMS Messenger</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="attachment">Pièce jointe</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_launcher_name">SMS Messenger</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="attachment">Lampiran</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_launcher_name">ショートメール</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="attachment">添付</string>
<string name="no_conversations_found">保存された会話はありません</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Paprastas SMS Siuntiklis</string>
<string name="app_launcher_name">SMS Siuntiklis</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="attachment">Priedas</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_launcher_name">SMS മെസഞ്ചർ</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="attachment">അറ്റാച്ചുമെന്റ്</string>
<string name="no_conversations_found">സ്റ്റോർ ചെയ്ത സംഭാഷണങ്ങളൊന്നും കണ്ടെത്തിയില്ല</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Eenvoudig Berichtenbeheer (SMS)</string>
<string name="app_launcher_name">Berichten</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="attachment">Bijlage</string>
<string name="no_conversations_found">Geen opgeslagen berichten gevonden</string>
@@ -10,9 +12,9 @@
<string name="reply">Beantwoorden</string>
<string name="show_character_counter">Teller voor het aantal tekens weergeven</string>
<string name="loading_messages">Berichten laden…</string>
<string name="no_reply_support">Sender doesn\'t support replies</string>
<string name="draft">Draft</string>
<string name="sending">Sending</string>
<string name="no_reply_support">Afzender ondersteunt geen antwoorden</string>
<string name="draft">Concept</string>
<string name="sending">Versturen</string>
<!-- New conversation -->
<string name="new_conversation">Nieuw gesprek</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Simple SMS Messenger</string>
<string name="app_launcher_name">SMS Messenger</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="attachment">Anexo</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_launcher_name">Сообщения</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="attachment">Вложение</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_launcher_name">SMS správy</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="attachment">Príloha</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_launcher_name">SMS Messenger</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="attachment">Ek</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_launcher_name">Повідомлення</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="attachment">Вкладення</string>
<string name="no_conversations_found">Немає збережених листувань</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">简易短信</string>
<string name="app_launcher_name">短信</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="attachment">附件</string>
<string name="no_conversations_found">未找到保存的对话</string>

View File

@@ -2,7 +2,9 @@
<string name="app_name">Simple SMS Messenger</string>
<string name="app_launcher_name">SMS Messenger</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="attachment">Attachment</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