Merge pull request #4 from SimpleMobileTools/master

upd
This commit is contained in:
solokot
2020-06-21 16:02:01 +03:00
committed by GitHub
30 changed files with 370 additions and 118 deletions

View File

@@ -1,6 +1,15 @@
Changelog Changelog
========== ==========
Version 5.3.0 *(2020-06-18)*
----------------------------
* Allow changing the text size
* Allow replying to incoming messages directly from the notification on Android 7+
* Make emails and urls clickable at messages
* Allow marking conversations as Unread
* Many other UX, stability and translation improvements
Version 5.2.0 *(2020-05-30)* Version 5.2.0 *(2020-05-30)*
---------------------------- ----------------------------

View File

@@ -17,8 +17,8 @@ android {
applicationId "com.simplemobiletools.smsmessenger" applicationId "com.simplemobiletools.smsmessenger"
minSdkVersion 22 minSdkVersion 22
targetSdkVersion 29 targetSdkVersion 29
versionCode 9 versionCode 10
versionName "5.2.0" versionName "5.3.0"
setProperty("archivesBaseName", "sms-messenger") setProperty("archivesBaseName", "sms-messenger")
} }
@@ -57,7 +57,7 @@ android {
} }
dependencies { dependencies {
implementation 'com.simplemobiletools:commons:5.28.25' implementation 'com.simplemobiletools:commons:5.29.7'
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

@@ -163,6 +163,15 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver
android:name=".receivers.DirectReplyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.simplemobiletools.smsmessenger.action.reply" />
</intent-filter>
</receiver>
<activity-alias <activity-alias
android:name=".activities.SplashActivity.Red" android:name=".activities.SplashActivity.Red"
android:enabled="false" android:enabled="false"

View File

@@ -35,6 +35,7 @@ class MainActivity : SimpleActivity() {
private val MAKE_DEFAULT_APP_REQUEST = 1 private val MAKE_DEFAULT_APP_REQUEST = 1
private var storedTextColor = 0 private var storedTextColor = 0
private var storedFontSize = 0
private var bus: EventBus? = null private var bus: EventBus? = null
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
@@ -77,6 +78,10 @@ class MainActivity : SimpleActivity() {
(conversations_list.adapter as? ConversationsAdapter)?.updateTextColor(config.textColor) (conversations_list.adapter as? ConversationsAdapter)?.updateTextColor(config.textColor)
} }
if (storedFontSize != config.fontSize) {
(conversations_list.adapter as? ConversationsAdapter)?.updateFontSize()
}
updateTextColors(main_coordinator) updateTextColors(main_coordinator)
no_conversations_placeholder_2.setTextColor(getAdjustedPrimaryColor()) no_conversations_placeholder_2.setTextColor(getAdjustedPrimaryColor())
no_conversations_placeholder_2.underlineText() no_conversations_placeholder_2.underlineText()
@@ -120,6 +125,7 @@ class MainActivity : SimpleActivity() {
private fun storeStateVariables() { private fun storeStateVariables() {
storedTextColor = config.textColor storedTextColor = config.textColor
storedFontSize = config.fontSize
} }
// while SEND_SMS and READ_SMS permissions are mandatory, READ_CONTACTS is optional. If we don't have it, we just won't be able to show the contact name in some cases // while SEND_SMS and READ_SMS permissions are mandatory, READ_CONTACTS is optional. If we don't have it, we just won't be able to show the contact name in some cases

View File

@@ -7,8 +7,10 @@ import android.os.Bundle
import android.view.Menu import android.view.Menu
import com.simplemobiletools.commons.activities.ManageBlockedNumbersActivity import com.simplemobiletools.commons.activities.ManageBlockedNumbersActivity
import com.simplemobiletools.commons.dialogs.ChangeDateTimeFormatDialog import com.simplemobiletools.commons.dialogs.ChangeDateTimeFormatDialog
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.isNougatPlus import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.config
import com.simplemobiletools.smsmessenger.helpers.refreshMessages import com.simplemobiletools.smsmessenger.helpers.refreshMessages
@@ -31,6 +33,7 @@ class SettingsActivity : SimpleActivity() {
setupUseEnglish() setupUseEnglish()
setupManageBlockedNumbers() setupManageBlockedNumbers()
setupChangeDateTimeFormat() setupChangeDateTimeFormat()
setupFontSize()
updateTextColors(settings_scrollview) updateTextColors(settings_scrollview)
if (blockedNumbersAtPause != -1 && blockedNumbersAtPause != getBlockedNumbers().hashCode()) { if (blockedNumbersAtPause != -1 && blockedNumbersAtPause != getBlockedNumbers().hashCode()) {
@@ -87,4 +90,20 @@ class SettingsActivity : SimpleActivity() {
} }
} }
} }
private fun setupFontSize() {
settings_font_size.text = getFontSizeText()
settings_font_size_holder.setOnClickListener {
val items = arrayListOf(
RadioItem(FONT_SIZE_SMALL, getString(R.string.small)),
RadioItem(FONT_SIZE_MEDIUM, getString(R.string.medium)),
RadioItem(FONT_SIZE_LARGE, getString(R.string.large)),
RadioItem(FONT_SIZE_EXTRA_LARGE, getString(R.string.extra_large)))
RadioGroupDialog(this@SettingsActivity, items, config.fontSize) {
config.fontSize = it as Int
settings_font_size.text = getFontSizeText()
}
}
}
} }

View File

@@ -199,6 +199,7 @@ class ThreadActivity : SimpleActivity() {
R.id.block_number -> blockNumber() R.id.block_number -> blockNumber()
R.id.delete -> askConfirmDelete() R.id.delete -> askConfirmDelete()
R.id.manage_people -> managePeople() R.id.manage_people -> managePeople()
R.id.mark_as_unread -> markAsUnread()
else -> return super.onOptionsItemSelected(item) else -> return super.onOptionsItemSelected(item)
} }
return true return true
@@ -392,8 +393,24 @@ class ThreadActivity : SimpleActivity() {
showSelectedContacts() showSelectedContacts()
} }
private fun markAsUnread() {
ensureBackgroundThread {
conversationsDB.markUnread(threadId.toLong())
markThreadMessagesUnread(threadId)
runOnUiThread {
finish()
bus?.post(Events.RefreshMessages())
}
}
}
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
private fun getThreadItems(): ArrayList<ThreadItem> { private fun getThreadItems(): ArrayList<ThreadItem> {
val items = ArrayList<ThreadItem>()
if (isFinishing) {
return items
}
messages.sortBy { it.date } messages.sortBy { it.date }
val subscriptionIdToSimId = HashMap<Int, String>() val subscriptionIdToSimId = HashMap<Int, String>()
@@ -402,7 +419,6 @@ class ThreadActivity : SimpleActivity() {
subscriptionIdToSimId[subscriptionInfo.subscriptionId] = "${index + 1}" subscriptionIdToSimId[subscriptionInfo.subscriptionId] = "${index + 1}"
} }
val items = ArrayList<ThreadItem>()
var prevDateTime = 0 var prevDateTime = 0
var hadUnreadItems = false var hadUnreadItems = false
messages.forEach { messages.forEach {
@@ -597,6 +613,7 @@ class ThreadActivity : SimpleActivity() {
@Subscribe(threadMode = ThreadMode.ASYNC) @Subscribe(threadMode = ThreadMode.ASYNC)
fun refreshMessages(event: Events.RefreshMessages) { fun refreshMessages(event: Events.RefreshMessages) {
notificationManager.cancel(threadId)
messages = getMessages(threadId) messages = getMessages(threadId)
setupAdapter() setupAdapter()
} }

View File

@@ -1,5 +1,6 @@
package com.simplemobiletools.smsmessenger.adapters package com.simplemobiletools.smsmessenger.adapters
import android.util.TypedValue
import android.view.Menu import android.view.Menu
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -7,6 +8,7 @@ import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.extensions.getTextSize
import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.models.SimpleContact import com.simplemobiletools.commons.models.SimpleContact
import com.simplemobiletools.commons.views.FastScroller import com.simplemobiletools.commons.views.FastScroller
@@ -17,6 +19,7 @@ import java.util.*
class ContactsAdapter(activity: SimpleActivity, var contacts: ArrayList<SimpleContact>, recyclerView: MyRecyclerView, fastScroller: FastScroller?, class ContactsAdapter(activity: SimpleActivity, var contacts: ArrayList<SimpleContact>, recyclerView: MyRecyclerView, fastScroller: FastScroller?,
itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) { itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
private var fontSize = activity.getTextSize()
override fun getActionMenuId() = 0 override fun getActionMenuId() = 0
@@ -57,11 +60,17 @@ class ContactsAdapter(activity: SimpleActivity, var contacts: ArrayList<SimpleCo
private fun setupView(view: View, contact: SimpleContact) { private fun setupView(view: View, contact: SimpleContact) {
view.apply { view.apply {
findViewById<TextView>(R.id.item_contact_name).text = contact.name findViewById<TextView>(R.id.item_contact_name).apply {
findViewById<TextView>(R.id.item_contact_name).setTextColor(textColor) text = contact.name
setTextColor(textColor)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.2f)
}
findViewById<TextView>(R.id.item_contact_number).text = contact.phoneNumber findViewById<TextView>(R.id.item_contact_number).apply {
findViewById<TextView>(R.id.item_contact_number).setTextColor(textColor) text = contact.phoneNumber
setTextColor(textColor)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
}
SimpleContactsHelper(context).loadContactImage(contact.photoUri, findViewById(R.id.item_contact_image), contact.name) SimpleContactsHelper(context).loadContactImage(contact.photoUri, findViewById(R.id.item_contact_image), contact.name)
} }

View File

@@ -3,6 +3,7 @@ package com.simplemobiletools.smsmessenger.adapters
import android.content.Intent import android.content.Intent
import android.graphics.Typeface import android.graphics.Typeface
import android.text.TextUtils import android.text.TextUtils
import android.util.TypedValue
import android.view.Menu import android.view.Menu
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -10,9 +11,7 @@ import android.widget.TextView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter
import com.simplemobiletools.commons.dialogs.ConfirmationDialog import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.extensions.addBlockedNumber import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.extensions.formatDateOrTime
import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.commons.helpers.KEY_PHONE import com.simplemobiletools.commons.helpers.KEY_PHONE
import com.simplemobiletools.commons.helpers.SimpleContactsHelper import com.simplemobiletools.commons.helpers.SimpleContactsHelper
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
@@ -28,6 +27,7 @@ import kotlinx.android.synthetic.main.item_conversation.view.*
class ConversationsAdapter(activity: SimpleActivity, var conversations: ArrayList<Conversation>, recyclerView: MyRecyclerView, fastScroller: FastScroller, class ConversationsAdapter(activity: SimpleActivity, var conversations: ArrayList<Conversation>, recyclerView: MyRecyclerView, fastScroller: FastScroller,
itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) { itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
private var fontSize = activity.getTextSize()
init { init {
setupDragListener(true) setupDragListener(true)
@@ -133,6 +133,7 @@ class ConversationsAdapter(activity: SimpleActivity, var conversations: ArrayLis
val positions = getSelectedItemPositions() val positions = getSelectedItemPositions()
conversationsToRemove.forEach { conversationsToRemove.forEach {
activity.deleteConversation(it.thread_id) activity.deleteConversation(it.thread_id)
activity.notificationManager.cancel(it.thread_id)
} }
conversations.removeAll(conversationsToRemove) conversations.removeAll(conversationsToRemove)
@@ -173,6 +174,11 @@ class ConversationsAdapter(activity: SimpleActivity, var conversations: ArrayLis
} }
} }
fun updateFontSize() {
fontSize = activity.getTextSize()
notifyDataSetChanged()
}
fun updateConversations(newConversations: ArrayList<Conversation>) { fun updateConversations(newConversations: ArrayList<Conversation>) {
val oldHashCode = conversations.hashCode() val oldHashCode = conversations.hashCode()
val newHashCode = newConversations.hashCode() val newHashCode = newConversations.hashCode()
@@ -186,9 +192,20 @@ class ConversationsAdapter(activity: SimpleActivity, var conversations: ArrayLis
view.apply { view.apply {
conversation_frame.isSelected = selectedKeys.contains(conversation.thread_id) conversation_frame.isSelected = selectedKeys.contains(conversation.thread_id)
conversation_address.text = conversation.title conversation_address.apply {
conversation_body_short.text = conversation.snippet text = conversation.title
conversation_date.text = conversation.date.formatDateOrTime(context, true) setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 1.2f)
}
conversation_body_short.apply {
text = conversation.snippet
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.9f)
}
conversation_date.apply {
text = conversation.date.formatDateOrTime(context, true)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize * 0.8f)
}
if (conversation.read) { if (conversation.read) {
conversation_address.setTypeface(null, Typeface.NORMAL) conversation_address.setTypeface(null, Typeface.NORMAL)

View File

@@ -5,6 +5,7 @@ import android.content.Intent
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import android.telephony.SubscriptionManager import android.telephony.SubscriptionManager
import android.util.TypedValue
import android.view.Menu import android.view.Menu
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -42,8 +43,8 @@ import kotlinx.android.synthetic.main.item_thread_date_time.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,
itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) { itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
private val roundedCornersRadius = resources.getDimension(R.dimen.normal_margin).toInt() private val roundedCornersRadius = resources.getDimension(R.dimen.normal_margin).toInt()
private var fontSize = activity.getTextSize()
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
private val hasMultipleSIMCards = SubscriptionManager.from(activity).activeSubscriptionInfoList?.size ?: 0 > 1 private val hasMultipleSIMCards = SubscriptionManager.from(activity).activeSubscriptionInfoList?.size ?: 0 > 1
@@ -181,18 +182,25 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
private fun setupView(view: View, message: Message) { private fun setupView(view: View, message: Message) {
view.apply { view.apply {
thread_message_holder.isSelected = selectedKeys.contains(message.id) thread_message_holder.isSelected = selectedKeys.contains(message.id)
thread_message_body.text = message.body thread_message_body.apply {
text = message.body
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
}
thread_message_body.beVisibleIf(message.body.isNotEmpty()) thread_message_body.beVisibleIf(message.body.isNotEmpty())
if (message.isReceivedMessage()) { if (message.isReceivedMessage()) {
thread_message_sender_photo.beVisible() thread_message_sender_photo.beVisible()
thread_message_body.setTextColor(textColor) thread_message_body.setTextColor(textColor)
thread_message_body.setLinkTextColor(context.getAdjustedPrimaryColor())
SimpleContactsHelper(context).loadContactImage(message.senderPhotoUri, thread_message_sender_photo, message.senderName) SimpleContactsHelper(context).loadContactImage(message.senderPhotoUri, thread_message_sender_photo, message.senderName)
} else { } else {
thread_message_sender_photo?.beGone() thread_message_sender_photo?.beGone()
val background = context.getAdjustedPrimaryColor() val background = context.getAdjustedPrimaryColor()
thread_message_body.background.applyColorFilter(background.adjustAlpha(0.8f)) thread_message_body.background.applyColorFilter(background.adjustAlpha(0.8f))
thread_message_body.setTextColor(background.getContrastColor())
val contrastColor = background.getContrastColor()
thread_message_body.setTextColor(contrastColor)
thread_message_body.setLinkTextColor(contrastColor)
} }
thread_mesage_attachments_holder.removeAllViews() thread_mesage_attachments_holder.removeAllViews()
@@ -286,7 +294,10 @@ class ThreadAdapter(activity: SimpleActivity, var messages: ArrayList<ThreadItem
private fun setupDateTime(view: View, dateTime: ThreadDateTime) { private fun setupDateTime(view: View, dateTime: ThreadDateTime) {
view.apply { view.apply {
thread_date_time.text = dateTime.date.formatDateOrTime(context, false) thread_date_time.apply {
text = dateTime.date.formatDateOrTime(context, false)
setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize)
}
thread_date_time.setTextColor(textColor) thread_date_time.setTextColor(textColor)
thread_sim_icon.beVisibleIf(hasMultipleSIMCards) thread_sim_icon.beVisibleIf(hasMultipleSIMCards)

View File

@@ -17,6 +17,7 @@ import android.provider.ContactsContract.PhoneLookup
import android.provider.Telephony.* import android.provider.Telephony.*
import android.text.TextUtils import android.text.TextUtils
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.RemoteInput
import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.* import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.SimpleContact import com.simplemobiletools.commons.models.SimpleContact
@@ -26,6 +27,7 @@ import com.simplemobiletools.smsmessenger.databases.MessagesDatabase
import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.helpers.*
import com.simplemobiletools.smsmessenger.interfaces.ConversationsDao import com.simplemobiletools.smsmessenger.interfaces.ConversationsDao
import com.simplemobiletools.smsmessenger.models.* import com.simplemobiletools.smsmessenger.models.*
import com.simplemobiletools.smsmessenger.receivers.DirectReplyReceiver
import com.simplemobiletools.smsmessenger.receivers.MarkAsReadReceiver import com.simplemobiletools.smsmessenger.receivers.MarkAsReadReceiver
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
@@ -227,7 +229,6 @@ fun Context.getConversations(threadId: Long? = null): ArrayList<Conversation> {
val isGroupConversation = phoneNumbers.size > 1 val isGroupConversation = phoneNumbers.size > 1
val read = cursor.getIntValue(Threads.READ) == 1 val read = cursor.getIntValue(Threads.READ) == 1
val conversation = Conversation(null, id, snippet, date.toInt(), read, title, photoUri, isGroupConversation, phoneNumbers.first()) val conversation = Conversation(null, id, snippet, date.toInt(), read, title, photoUri, isGroupConversation, phoneNumbers.first())
conversations.add(conversation) conversations.add(conversation)
} }
@@ -497,29 +498,60 @@ fun Context.markMessageRead(id: Int, isMMS: Boolean) {
contentResolver.update(uri, contentValues, selection, selectionArgs) contentResolver.update(uri, contentValues, selection, selectionArgs)
} }
fun Context.markThreadMessagesRead(threadId: Int) {
arrayOf(Sms.CONTENT_URI, Mms.CONTENT_URI).forEach { uri ->
val contentValues = ContentValues().apply {
put(Sms.READ, 1)
put(Sms.SEEN, 1)
}
val selection = "${Sms.THREAD_ID} = ?"
val selectionArgs = arrayOf(threadId.toString())
contentResolver.update(uri, contentValues, selection, selectionArgs)
}
}
fun Context.markThreadMessagesUnread(threadId: Int) {
arrayOf(Sms.CONTENT_URI, Mms.CONTENT_URI).forEach { uri ->
val contentValues = ContentValues().apply {
put(Sms.READ, 0)
put(Sms.SEEN, 0)
}
val selection = "${Sms.THREAD_ID} = ?"
val selectionArgs = arrayOf(threadId.toString())
contentResolver.update(uri, contentValues, selection, selectionArgs)
}
}
@SuppressLint("NewApi") @SuppressLint("NewApi")
fun Context.getThreadId(address: String): Long { fun Context.getThreadId(address: String): Long {
return if (isMarshmallowPlus()) { return if (isMarshmallowPlus()) {
Threads.getOrCreateThreadId(this, address) try {
Threads.getOrCreateThreadId(this, address)
} catch (e: Exception) {
0L
}
} else { } else {
0 0L
} }
} }
@SuppressLint("NewApi") @SuppressLint("NewApi")
fun Context.getThreadId(addresses: Set<String>): Long { fun Context.getThreadId(addresses: Set<String>): Long {
return if (isMarshmallowPlus()) { return if (isMarshmallowPlus()) {
Threads.getOrCreateThreadId(this, addresses) try {
Threads.getOrCreateThreadId(this, addresses)
} catch (e: Exception) {
0L
}
} else { } else {
0 0L
} }
} }
@SuppressLint("NewApi") @SuppressLint("NewApi")
fun Context.showReceivedMessageNotification(address: String, body: String, threadID: Int, bitmap: Bitmap?, messageId: Int, isMMS: Boolean) { fun Context.showReceivedMessageNotification(address: String, body: String, threadID: Int, bitmap: Bitmap?) {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) val soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val channelId = "simple_sms_messenger"
if (isOreoPlus()) { if (isOreoPlus()) {
val audioAttributes = AudioAttributes.Builder() val audioAttributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION) .setUsage(AudioAttributes.USAGE_NOTIFICATION)
@@ -529,7 +561,7 @@ fun Context.showReceivedMessageNotification(address: String, body: String, threa
val name = getString(R.string.channel_received_sms) val name = getString(R.string.channel_received_sms)
val importance = NotificationManager.IMPORTANCE_HIGH val importance = NotificationManager.IMPORTANCE_HIGH
NotificationChannel(channelId, name, importance).apply { NotificationChannel(NOTIFICATION_CHANNEL, name, importance).apply {
setBypassDnd(false) setBypassDnd(false)
enableLights(true) enableLights(true)
setSound(soundUri, audioAttributes) setSound(soundUri, audioAttributes)
@@ -548,16 +580,34 @@ fun Context.showReceivedMessageNotification(address: String, body: String, threa
val markAsReadIntent = Intent(this, MarkAsReadReceiver::class.java).apply { val markAsReadIntent = Intent(this, MarkAsReadReceiver::class.java).apply {
action = MARK_AS_READ action = MARK_AS_READ
putExtra(MESSAGE_ID, messageId)
putExtra(MESSAGE_IS_MMS, isMMS)
putExtra(THREAD_ID, threadID) putExtra(THREAD_ID, threadID)
} }
val markAsReadPendingIntent = PendingIntent.getBroadcast(this, 0, markAsReadIntent, PendingIntent.FLAG_CANCEL_CURRENT) val markAsReadPendingIntent = PendingIntent.getBroadcast(this, 0, markAsReadIntent, PendingIntent.FLAG_CANCEL_CURRENT)
var replyAction: NotificationCompat.Action? = null
if (isNougatPlus()) {
val replyLabel = getString(R.string.reply)
val remoteInput = RemoteInput.Builder(REPLY)
.setLabel(replyLabel)
.build()
val replyIntent = Intent(this, DirectReplyReceiver::class.java).apply {
putExtra(THREAD_ID, threadID)
putExtra(THREAD_NUMBER, address)
}
val replyPendingIntent = PendingIntent.getBroadcast(applicationContext, threadID, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT)
replyAction = NotificationCompat.Action.Builder(R.drawable.ic_send_vector, replyLabel, replyPendingIntent)
.addRemoteInput(remoteInput)
.build()
}
val largeIcon = bitmap ?: SimpleContactsHelper(this).getContactLetterIcon(sender) val largeIcon = bitmap ?: SimpleContactsHelper(this).getContactLetterIcon(sender)
val builder = NotificationCompat.Builder(this, channelId) val builder = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL)
.setContentTitle(sender) .setContentTitle(sender)
.setContentText(body) .setContentText(body)
.setColor(config.primaryColor)
.setSmallIcon(R.drawable.ic_messenger) .setSmallIcon(R.drawable.ic_messenger)
.setLargeIcon(largeIcon) .setLargeIcon(largeIcon)
.setStyle(NotificationCompat.BigTextStyle().setSummaryText(summaryText).bigText(body)) .setStyle(NotificationCompat.BigTextStyle().setSummaryText(summaryText).bigText(body))
@@ -568,7 +618,11 @@ fun Context.showReceivedMessageNotification(address: String, body: String, threa
.setAutoCancel(true) .setAutoCancel(true)
.setSound(soundUri, AudioManager.STREAM_NOTIFICATION) .setSound(soundUri, AudioManager.STREAM_NOTIFICATION)
.addAction(R.drawable.ic_check_vector, getString(R.string.mark_as_read), markAsReadPendingIntent) .addAction(R.drawable.ic_check_vector, getString(R.string.mark_as_read), markAsReadPendingIntent)
.setChannelId(channelId) .setChannelId(NOTIFICATION_CHANNEL)
notificationManager.notify(messageId, builder.build()) if (replyAction != null) {
builder.addAction(replyAction)
}
notificationManager.notify(threadID, builder.build())
} }

View File

@@ -10,11 +10,11 @@ const val THREAD_NUMBER = "thread_number"
const val THREAD_ATTACHMENT_URI = "thread_attachment_uri" const val THREAD_ATTACHMENT_URI = "thread_attachment_uri"
const val THREAD_ATTACHMENT_URIS = "thread_attachment_uris" const val THREAD_ATTACHMENT_URIS = "thread_attachment_uris"
const val USE_SIM_ID_PREFIX = "use_sim_id_" const val USE_SIM_ID_PREFIX = "use_sim_id_"
const val NOTIFICATION_CHANNEL = "simple_sms_messenger"
private const val PATH = "com.simplemobiletools.smsmessenger.action." private const val PATH = "com.simplemobiletools.smsmessenger.action."
const val MARK_AS_READ = PATH + "mark_as_read" const val MARK_AS_READ = PATH + "mark_as_read"
const val MESSAGE_ID = "message_id" const val REPLY = PATH + "reply"
const val MESSAGE_IS_MMS = "message_is_mms"
// view types for the thread list view // view types for the thread list view
const val THREAD_DATE_TIME = 1 const val THREAD_DATE_TIME = 1

View File

@@ -17,6 +17,9 @@ interface ConversationsDao {
@Query("UPDATE conversations SET read = 1 WHERE thread_id = :threadId") @Query("UPDATE conversations SET read = 1 WHERE thread_id = :threadId")
fun markRead(threadId: Long) fun markRead(threadId: Long)
@Query("UPDATE conversations SET read = 0 WHERE thread_id = :threadId")
fun markUnread(threadId: Long)
@Query("DELETE FROM conversations WHERE id = :id") @Query("DELETE FROM conversations WHERE id = :id")
fun delete(id: Long) fun delete(id: Long)

View File

@@ -0,0 +1,51 @@
package com.simplemobiletools.smsmessenger.receivers
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.core.app.NotificationCompat
import androidx.core.app.RemoteInput
import com.klinker.android.send_message.Settings
import com.klinker.android.send_message.Transaction
import com.simplemobiletools.commons.extensions.notificationManager
import com.simplemobiletools.commons.extensions.showErrorToast
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.extensions.conversationsDB
import com.simplemobiletools.smsmessenger.extensions.markThreadMessagesRead
import com.simplemobiletools.smsmessenger.helpers.NOTIFICATION_CHANNEL
import com.simplemobiletools.smsmessenger.helpers.REPLY
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
import com.simplemobiletools.smsmessenger.helpers.THREAD_NUMBER
class DirectReplyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val address = intent.getStringExtra(THREAD_NUMBER)
val threadId = intent.getIntExtra(THREAD_ID, 0)
val msg = RemoteInput.getResultsFromIntent(intent).getCharSequence(REPLY).toString()
val settings = Settings()
settings.useSystemSending = true
val transaction = Transaction(context, settings)
val message = com.klinker.android.send_message.Message(msg, address)
try {
transaction.sendNewMessage(message, threadId.toLong())
} catch (e: Exception) {
context.showErrorToast(e)
}
val repliedNotification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL)
.setSmallIcon(R.drawable.ic_messenger)
.setContentText(msg)
.build()
context.notificationManager.notify(threadId, repliedNotification)
ensureBackgroundThread {
context.markThreadMessagesRead(threadId)
context.conversationsDB.markRead(threadId.toLong())
}
}
}

View File

@@ -6,23 +6,18 @@ import android.content.Intent
import com.simplemobiletools.commons.extensions.notificationManager import com.simplemobiletools.commons.extensions.notificationManager
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.smsmessenger.extensions.conversationsDB import com.simplemobiletools.smsmessenger.extensions.conversationsDB
import com.simplemobiletools.smsmessenger.extensions.markMessageRead import com.simplemobiletools.smsmessenger.extensions.markThreadMessagesRead
import com.simplemobiletools.smsmessenger.helpers.MARK_AS_READ import com.simplemobiletools.smsmessenger.helpers.MARK_AS_READ
import com.simplemobiletools.smsmessenger.helpers.MESSAGE_ID
import com.simplemobiletools.smsmessenger.helpers.MESSAGE_IS_MMS
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
class MarkAsReadReceiver : BroadcastReceiver() { class MarkAsReadReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
when (intent.action) { when (intent.action) {
MARK_AS_READ -> { MARK_AS_READ -> {
val messageId = intent.getIntExtra(MESSAGE_ID, 0) val threadId = intent.getIntExtra(THREAD_ID, 0)
context.notificationManager.cancel(messageId) context.notificationManager.cancel(threadId)
ensureBackgroundThread { ensureBackgroundThread {
val isMMS = intent.getBooleanExtra(MESSAGE_IS_MMS, false) context.markThreadMessagesRead(threadId)
context.markMessageRead(messageId, isMMS)
val threadId = intent.getIntExtra(THREAD_ID, 0)
context.conversationsDB.markRead(threadId.toLong()) context.conversationsDB.markRead(threadId.toLong())
} }
} }

View File

@@ -33,7 +33,7 @@ class MmsReceiver : com.klinker.android.send_message.MmsReceivedReceiver() {
null null
} }
context.showReceivedMessageNotification(address, mms.body, mms.thread, glideBitmap, mms.id, true) context.showReceivedMessageNotification(address, mms.body, mms.thread, glideBitmap)
val conversation = context.getConversations(mms.thread.toLong()).firstOrNull() ?: return@ensureBackgroundThread val conversation = context.getConversations(mms.thread.toLong()).firstOrNull() ?: return@ensureBackgroundThread
context.conversationsDB.insertOrUpdate(conversation) context.conversationsDB.insertOrUpdate(conversation)
} }

View File

@@ -30,8 +30,8 @@ class SmsReceiver : BroadcastReceiver() {
} }
if (!context.isNumberBlocked(address)) { if (!context.isNumberBlocked(address)) {
val messageId = context.insertNewSMS(address, subject, body, date, read, threadId, type, subscriptionId) context.insertNewSMS(address, subject, body, date, read, threadId, type, subscriptionId)
context.showReceivedMessageNotification(address, body, threadId.toInt(), null, messageId, false) context.showReceivedMessageNotification(address, body, threadId.toInt(), null)
refreshMessages() refreshMessages()
ensureBackgroundThread { ensureBackgroundThread {

View File

@@ -117,5 +117,37 @@
app:switchPadding="@dimen/medium_margin" /> app:switchPadding="@dimen/medium_margin" />
</RelativeLayout> </RelativeLayout>
<RelativeLayout
android:id="@+id/settings_font_size_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/medium_margin"
android:background="?attr/selectableItemBackground"
android:paddingLeft="@dimen/normal_margin"
android:paddingTop="@dimen/activity_margin"
android:paddingRight="@dimen/normal_margin"
android:paddingBottom="@dimen/activity_margin">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/settings_font_size_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toStartOf="@+id/settings_font_size"
android:paddingLeft="@dimen/medium_margin"
android:paddingRight="@dimen/medium_margin"
android:text="@string/font_size" />
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/settings_font_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginEnd="@dimen/medium_margin"
android:background="@null"
android:clickable="false" />
</RelativeLayout>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View File

@@ -53,6 +53,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/thread_mesage_attachments_holder" android:layout_below="@+id/thread_mesage_attachments_holder"
android:layout_toEndOf="@+id/thread_message_sender_photo" android:layout_toEndOf="@+id/thread_message_sender_photo"
android:autoLink="email|web"
android:background="@drawable/item_received_background" android:background="@drawable/item_received_background"
android:padding="@dimen/normal_margin" android:padding="@dimen/normal_margin"
android:textSize="@dimen/normal_text_size" android:textSize="@dimen/normal_text_size"

View File

@@ -43,6 +43,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/thread_mesage_attachments_holder" android:layout_below="@+id/thread_mesage_attachments_holder"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:autoLink="email|web"
android:background="@drawable/item_sent_background" android:background="@drawable/item_sent_background"
android:padding="@dimen/normal_margin" android:padding="@dimen/normal_margin"
android:textSize="@dimen/normal_text_size" android:textSize="@dimen/normal_text_size"

View File

@@ -16,4 +16,8 @@
android:icon="@drawable/ic_block_vector" android:icon="@drawable/ic_block_vector"
android:title="@string/block_number" android:title="@string/block_number"
app:showAsAction="never" /> app:showAsAction="never" />
<item
android:id="@+id/mark_as_unread"
android:title="@string/mark_as_unread"
app:showAsAction="never" />
</menu> </menu>

View File

@@ -7,6 +7,7 @@
<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>
<string name="start_conversation">einen neuen Chat beginnen</string> <string name="start_conversation">einen neuen Chat beginnen</string>
<string name="reply">Reply</string>
<!-- New conversation --> <!-- New conversation -->
<string name="new_conversation">neuer Chat</string> <string name="new_conversation">neuer Chat</string>

View File

@@ -1,72 +1,73 @@
<resources> <resources>
<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">Το μήνυμα δεν έχει σταλεί.</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>
<string name="start_conversation">Έναρξη συνομιλίας</string> <string name="start_conversation">Έναρξη συνομιλίας</string>
<string name="reply">Reply</string>
<!-- New conversation -->
<string name="new_conversation">Νέα συνομιλία</string> <!-- New conversation -->
<string name="add_contact_or_number">Προσθήκη επαφής ή αριθμού…</string> <string name="new_conversation">Νέα συνομιλία</string>
<string name="suggestions">Προτάσεις</string> <string name="add_contact_or_number">Προσθήκη επαφής ή αριθμού…</string>
<string name="suggestions">Προτάσεις</string>
<!-- Notifications -->
<string name="channel_received_sms">Ελήφθη SMS</string> <!-- Notifications -->
<string name="new_message">Νέο μήνυμα</string> <string name="channel_received_sms">Ελήφθη SMS</string>
<string name="mark_as_read">Σήμανση ως αναγνωσμένου</string> <string name="new_message">Νέο μήνυμα</string>
<string name="mark_as_read">Σήμανση ως αναγνωσμένου</string>
<string name="mark_as_unread">Mark as Unread</string> <string name="mark_as_unread">Mark as Unread</string>
<!-- Confirmation dialog --> <!-- Confirmation dialog -->
<string name="delete_whole_conversation_confirmation">Είστε βέβαιοι ότι θέλετε να διαγράψετε όλα τα μηνύματα αυτής της συνομιλίας;</string> <string name="delete_whole_conversation_confirmation">Είστε βέβαιοι ότι θέλετε να διαγράψετε όλα τα μηνύματα αυτής της συνομιλίας;</string>
<!-- Are you sure you want to delete 5 conversations? --> <!-- Are you sure you want to delete 5 conversations? -->
<plurals name="delete_conversations"> <plurals name="delete_conversations">
<item quantity="one">%d συνομιλία</item> <item quantity="one">%d συνομιλία</item>
<item quantity="other">%d συνομιλίες</item> <item quantity="other">%d συνομιλίες</item>
</plurals> </plurals>
<!-- Are you sure you want to delete 5 messages? --> <!-- Are you sure you want to delete 5 messages? -->
<plurals name="delete_messages"> <plurals name="delete_messages">
<item quantity="one">%d μήνυμα</item> <item quantity="one">%d μήνυμα</item>
<item quantity="other">%d μηνύματα</item> <item quantity="other">%d μηνύματα</item>
</plurals> </plurals>
<!-- FAQ --> <!-- FAQ -->
<string name="faq_1_title">Γιατί η εφαρμογή απαιτεί πρόσβαση στο Internet;</string> <string name="faq_1_title">Γιατί η εφαρμογή απαιτεί πρόσβαση στο Internet;</string>
<string name="faq_1_text">Δυστυχώς, απαιτείται για την αποστολή συνημμένων MMS. Το να μην είμαστε σε θέση να στείλουμε MMS θα αποτελούσε πραγματικά τεράστιο μειονέκτημα σε σύγκριση με άλλες εφαρμογές, επομένως αποφασίσαμε να ακολουθήσουμε αυτόν τον δρόμο. <string name="faq_1_text">Δυστυχώς, απαιτείται για την αποστολή συνημμένων MMS. Το να μην είμαστε σε θέση να στείλουμε MMS θα αποτελούσε πραγματικά τεράστιο μειονέκτημα σε σύγκριση με άλλες εφαρμογές, επομένως αποφασίσαμε να ακολουθήσουμε αυτόν τον δρόμο.
Ωστόσο, όπως συνήθως, δεν υπάρχουν καθόλου διαφημίσεις, παρακολούθηση ή αναλύσεις, το διαδίκτυο χρησιμοποιείται μόνο για την αποστολή MMS.</string> Ωστόσο, όπως συνήθως, δεν υπάρχουν καθόλου διαφημίσεις, παρακολούθηση ή αναλύσεις, το διαδίκτυο χρησιμοποιείται μόνο για την αποστολή MMS.</string>
<!-- Strings displayed only on Google Playstore. Optional, but good to have --> <!-- Strings displayed only on Google Playstore. Optional, but good to have -->
<!-- App title has to have less than 50 characters. If you cannot squeeze it, just remove a part of it --> <!-- App title has to have less than 50 characters. If you cannot squeeze it, just remove a part of it -->
<string name="app_title">Απλός SMS Messenger - Εύκολη διαχείριση μηνυμάτων</string> <string name="app_title">Απλός SMS Messenger - Εύκολη διαχείριση μηνυμάτων</string>
<!-- Short description has to have max 80 characters --> <!-- Short description has to have max 80 characters -->
<string name="app_short_description">Ένας εύκολος και γρήγορος τρόπος διαχείρισης SMS και MMS χωρίς διαφημίσεις.</string> <string name="app_short_description">Ένας εύκολος και γρήγορος τρόπος διαχείρισης SMS και MMS χωρίς διαφημίσεις.</string>
<string name="app_long_description"> <string name="app_long_description">
Ένας εξαιρετικός τρόπος για να μείνετε σε επαφή με τους συγγενείς σας, στέλνοντας μηνύματα SMS και MMS. Η εφαρμογή χειρίζεται σωστά και την ομαδική ανταλλαγή μηνυμάτων, όπως και τον αποκλεισμό αριθμών από Android 7+. Ένας εξαιρετικός τρόπος για να μείνετε σε επαφή με τους συγγενείς σας, στέλνοντας μηνύματα SMS και MMS. Η εφαρμογή χειρίζεται σωστά και την ομαδική ανταλλαγή μηνυμάτων, όπως και τον αποκλεισμό αριθμών από Android 7+.
Προσφέρει πολλές μορφές ημερομηνίας για να διαλέξετε, ώστε να αισθάνεστε άνετα να τις χρησιμοποιήσετε. Μπορείτε επίσης να κάνετε εναλλαγή μεταξύ 12 και 24 ωρών. Προσφέρει πολλές μορφές ημερομηνίας για να διαλέξετε, ώστε να αισθάνεστε άνετα να τις χρησιμοποιήσετε. Μπορείτε επίσης να κάνετε εναλλαγή μεταξύ 12 και 24 ωρών.
Έχει πραγματικά πολύ μικρό μέγεθος εφαρμογής σε σύγκριση με τον ανταγωνισμό, καθιστώντας την πραγματικά γρήγορη στη λήψη της. Έχει πραγματικά πολύ μικρό μέγεθος εφαρμογής σε σύγκριση με τον ανταγωνισμό, καθιστώντας την πραγματικά γρήγορη στη λήψη της.
Διατίθεται με σχεδίαση υλικού και σκούρο θέμα από προεπιλογή, παρέχει εξαιρετική εμπειρία χρήστη για εύκολη χρήση. Η έλλειψη πρόσβασης στο διαδίκτυο σάς παρέχει περισσότερο απόρρητο, ασφάλεια και σταθερότητα από ό,τι άλλες εφαρμογές. Διατίθεται με σχεδίαση υλικού και σκούρο θέμα από προεπιλογή, παρέχει εξαιρετική εμπειρία χρήστη για εύκολη χρήση. Η έλλειψη πρόσβασης στο διαδίκτυο σάς παρέχει περισσότερο απόρρητο, ασφάλεια και σταθερότητα από ό,τι άλλες εφαρμογές.
Δεν περιέχει διαφημίσεις ή περιττά δικαιώματα. Είναι πλήρως ανοιχτού κώδικα, παρέχει προσαρμόσιμα χρώματα. Δεν περιέχει διαφημίσεις ή περιττά δικαιώματα. Είναι πλήρως ανοιχτού κώδικα, παρέχει προσαρμόσιμα χρώματα.
<b>Δείτε την πλήρη σειρά Simple Tools here:</b> <b>Δείτε την πλήρη σειρά Simple Tools here:</b>
https://www.simplemobiletools.com https://www.simplemobiletools.com
<b>Facebook:</b> <b>Facebook:</b>
https://www.facebook.com/simplemobiletools https://www.facebook.com/simplemobiletools
<b>Reddit:</b> <b>Reddit:</b>
https://www.reddit.com/r/SimpleMobileTools https://www.reddit.com/r/SimpleMobileTools
</string> </string>
<!-- <!--
Haven't found some strings? There's more at Haven't found some strings? There's more at
https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res https://github.com/SimpleMobileTools/Simple-Commons/tree/master/commons/src/main/res
--> -->
</resources> </resources>

View File

@@ -7,6 +7,7 @@
<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>
<string name="start_conversation">Inicia una conversación</string> <string name="start_conversation">Inicia una conversación</string>
<string name="reply">Reply</string>
<!-- New conversation --> <!-- New conversation -->
<string name="new_conversation">Nueva conversación</string> <string name="new_conversation">Nueva conversación</string>

View File

@@ -7,6 +7,7 @@
<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>
<string name="start_conversation">Pradėtipokalbį</string> <string name="start_conversation">Pradėtipokalbį</string>
<string name="reply">Reply</string>
<!-- New conversation --> <!-- New conversation -->
<string name="new_conversation">Naujas pokalbis</string> <string name="new_conversation">Naujas pokalbis</string>

View File

@@ -7,6 +7,7 @@
<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>
<string name="start_conversation">Een gesprek starten</string> <string name="start_conversation">Een gesprek starten</string>
<string name="reply">Beantwoorden</string>
<!-- New conversation --> <!-- New conversation -->
<string name="new_conversation">Nieuw gesprek</string> <string name="new_conversation">Nieuw gesprek</string>

View File

@@ -7,8 +7,9 @@
<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>
<string name="start_conversation">Iniciar uma conversa</string> <string name="start_conversation">Iniciar uma conversa</string>
<string name="reply">Reply</string>
<!-- New message --> <!-- New conversation -->
<string name="new_conversation">Nova conversa</string> <string name="new_conversation">Nova conversa</string>
<string name="add_contact_or_number">Adicionar contacto ou número…</string> <string name="add_contact_or_number">Adicionar contacto ou número…</string>
<string name="suggestions">Sugestões</string> <string name="suggestions">Sugestões</string>

View File

@@ -7,6 +7,7 @@
<string name="attachment">Вложение</string> <string name="attachment">Вложение</string>
<string name="no_conversations_found">Нет сохранённых переписок</string> <string name="no_conversations_found">Нет сохранённых переписок</string>
<string name="start_conversation">Начать переписку</string> <string name="start_conversation">Начать переписку</string>
<string name="reply">Reply</string>
<!-- New conversation --> <!-- New conversation -->
<string name="new_conversation">Новая переписка</string> <string name="new_conversation">Новая переписка</string>

View File

@@ -7,6 +7,7 @@
<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>
<string name="start_conversation">Začať konverzáciu</string> <string name="start_conversation">Začať konverzáciu</string>
<string name="reply">Odpovedať</string>
<!-- New conversation --> <!-- New conversation -->
<string name="new_conversation">Nová konverzácia</string> <string name="new_conversation">Nová konverzácia</string>

View File

@@ -7,6 +7,7 @@
<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>
<string name="start_conversation">Start a conversation</string> <string name="start_conversation">Start a conversation</string>
<string name="reply">Reply</string>
<!-- New conversation --> <!-- New conversation -->
<string name="new_conversation">New conversation</string> <string name="new_conversation">New conversation</string>

View File

@@ -0,0 +1,5 @@
* Allow changing the text size
* Allow replying to incoming messages directly from the notification on Android 7+
* Make emails and urls clickable at messages
* Allow marking conversations as Unread
* Many other UX, stability and translation improvements