Add schedule send message creation ui
Move android-smsmms logic into a separate file
This commit is contained in:
parent
acefd0c0f4
commit
7624174cad
|
@ -25,6 +25,7 @@ import android.view.inputmethod.EditorInfo
|
|||
import android.widget.LinearLayout
|
||||
import android.widget.LinearLayout.LayoutParams
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.DataSource
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
|
@ -37,8 +38,6 @@ import com.bumptech.glide.request.RequestOptions
|
|||
import com.bumptech.glide.request.target.Target
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.klinker.android.send_message.Transaction
|
||||
import com.klinker.android.send_message.Utils.getNumPages
|
||||
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||
import com.simplemobiletools.commons.dialogs.RadioGroupDialog
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
|
@ -50,17 +49,17 @@ import com.simplemobiletools.commons.views.MyRecyclerView
|
|||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.adapters.AutoCompleteTextViewAdapter
|
||||
import com.simplemobiletools.smsmessenger.adapters.ThreadAdapter
|
||||
import com.simplemobiletools.smsmessenger.dialogs.ScheduleSendDialog
|
||||
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_thread.*
|
||||
import kotlinx.android.synthetic.main.item_attachment.view.*
|
||||
import kotlinx.android.synthetic.main.item_selected_contact.view.*
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import org.joda.time.DateTime
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
@ -92,6 +91,9 @@ class ThreadActivity : SimpleActivity() {
|
|||
private var allMessagesFetched = false
|
||||
private var oldestMessageDate = -1
|
||||
|
||||
private var isScheduledMessage: Boolean = false
|
||||
private lateinit var scheduledDateTime: DateTime
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_thread)
|
||||
|
@ -425,6 +427,12 @@ class ThreadActivity : SimpleActivity() {
|
|||
thread_send_message.setOnClickListener {
|
||||
sendMessage()
|
||||
}
|
||||
thread_send_message.setOnLongClickListener {
|
||||
if (!isScheduledMessage) {
|
||||
launchScheduleSendDialog()
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
thread_send_message.isClickable = false
|
||||
thread_type_message.onTextChangeListener {
|
||||
|
@ -468,6 +476,8 @@ class ThreadActivity : SimpleActivity() {
|
|||
addAttachment(it)
|
||||
}
|
||||
}
|
||||
|
||||
setupScheduleSendUi()
|
||||
}
|
||||
|
||||
private fun setupAttachmentSizes() {
|
||||
|
@ -909,9 +919,11 @@ class ThreadActivity : SimpleActivity() {
|
|||
|
||||
private fun checkSendMessageAvailability() {
|
||||
if (thread_type_message.text!!.isNotEmpty() || (attachmentSelections.isNotEmpty() && !attachmentSelections.values.any { it.isPending })) {
|
||||
thread_send_message.isEnabled = true
|
||||
thread_send_message.isClickable = true
|
||||
thread_send_message.alpha = 0.9f
|
||||
} else {
|
||||
thread_send_message.isEnabled = false
|
||||
thread_send_message.isClickable = false
|
||||
thread_send_message.alpha = 0.4f
|
||||
}
|
||||
|
@ -919,53 +931,25 @@ class ThreadActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
private fun sendMessage() {
|
||||
var msg = thread_type_message.value
|
||||
if (msg.isEmpty() && attachmentSelections.isEmpty()) {
|
||||
var text = thread_type_message.value
|
||||
if (text.isEmpty() && attachmentSelections.isEmpty()) {
|
||||
showErrorToast(getString(R.string.unknown_error_occurred))
|
||||
return
|
||||
}
|
||||
|
||||
msg = removeDiacriticsIfNeeded(msg)
|
||||
text = removeDiacriticsIfNeeded(text)
|
||||
|
||||
val numbers = ArrayList<String>()
|
||||
participants.forEach { contact ->
|
||||
contact.phoneNumbers.forEach {
|
||||
numbers.add(it.normalizedNumber)
|
||||
}
|
||||
}
|
||||
val addresses = participants
|
||||
.flatMap { it.phoneNumbers }
|
||||
.map { it.normalizedNumber }
|
||||
|
||||
val settings = getSendMessageSettings()
|
||||
val currentSubscriptionId = availableSIMCards.getOrNull(currentSIMCardIndex)?.subscriptionId
|
||||
if (currentSubscriptionId != null) {
|
||||
settings.subscriptionId = currentSubscriptionId
|
||||
}
|
||||
|
||||
val transaction = Transaction(this, settings)
|
||||
val message = com.klinker.android.send_message.Message(msg, numbers.toTypedArray())
|
||||
|
||||
if (attachmentSelections.isNotEmpty()) {
|
||||
for (selection in attachmentSelections.values) {
|
||||
try {
|
||||
val byteArray = contentResolver.openInputStream(selection.uri)?.readBytes() ?: continue
|
||||
val mimeType = contentResolver.getType(selection.uri) ?: continue
|
||||
message.addMedia(byteArray, mimeType)
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
} catch (e: Error) {
|
||||
showErrorToast(e.localizedMessage ?: getString(R.string.unknown_error_occurred))
|
||||
}
|
||||
}
|
||||
}
|
||||
val attachments = attachmentSelections.values.map { it.uri }
|
||||
|
||||
try {
|
||||
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)
|
||||
sendTransactionMessage(text, addresses, currentSubscriptionId, attachments)
|
||||
|
||||
thread_type_message.setText("")
|
||||
attachmentSelections.clear()
|
||||
thread_attachments_holder.beGone()
|
||||
|
@ -1146,10 +1130,9 @@ class ThreadActivity : SimpleActivity() {
|
|||
}
|
||||
|
||||
private fun updateMessageType() {
|
||||
val settings = getSendMessageSettings()
|
||||
val text = thread_type_message.text.toString()
|
||||
val isGroupMms = participants.size > 1 && config.sendGroupMessageMMS
|
||||
val isLongMmsMessage = getNumPages(settings, text) > settings.sendLongAsMmsAfter && config.sendLongMessageMMS
|
||||
val isLongMmsMessage = isLongMmsMessage(text) && config.sendLongMessageMMS
|
||||
val stringId = if (attachmentSelections.isNotEmpty() || isGroupMms || isLongMmsMessage) {
|
||||
R.string.mms
|
||||
} else {
|
||||
|
@ -1166,4 +1149,58 @@ class ThreadActivity : SimpleActivity() {
|
|||
}
|
||||
return File.createTempFile("IMG_", ".jpg", outputDirectory)
|
||||
}
|
||||
|
||||
private fun launchScheduleSendDialog(originalDt: DateTime? = null) {
|
||||
ScheduleSendDialog(this, originalDt) { newDt ->
|
||||
if (newDt != null) {
|
||||
scheduledDateTime = newDt
|
||||
showScheduleSendUi()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupScheduleSendUi() {
|
||||
val textColor = getProperTextColor()
|
||||
scheduled_message_holder.background.applyColorFilter(getProperBackgroundColor().getContrastColor())
|
||||
scheduled_message_button.apply {
|
||||
val clockDrawable = ResourcesCompat.getDrawable(resources, R.drawable.ic_clock_vector, theme)?.apply { applyColorFilter(textColor) }
|
||||
setCompoundDrawablesWithIntrinsicBounds(clockDrawable, null, null, null)
|
||||
setTextColor(textColor)
|
||||
setOnClickListener {
|
||||
launchScheduleSendDialog(scheduledDateTime)
|
||||
}
|
||||
}
|
||||
|
||||
discard_scheduled_message.apply {
|
||||
applyColorFilter(textColor)
|
||||
setOnClickListener {
|
||||
hideScheduleSendUi()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showScheduleSendUi() {
|
||||
isScheduledMessage = true
|
||||
updateSendButton()
|
||||
scheduled_message_holder.beVisible()
|
||||
scheduled_message_button.text = scheduledDateTime.humanize(this)
|
||||
}
|
||||
|
||||
private fun hideScheduleSendUi() {
|
||||
isScheduledMessage = false
|
||||
scheduled_message_holder.beGone()
|
||||
updateSendButton()
|
||||
}
|
||||
|
||||
private fun updateSendButton() {
|
||||
val drawableResId = if (isScheduledMessage) {
|
||||
R.drawable.ic_schedule_send_vector
|
||||
} else {
|
||||
R.drawable.ic_send_vector
|
||||
}
|
||||
ResourcesCompat.getDrawable(resources, drawableResId, theme)?.apply {
|
||||
applyColorFilter(getProperTextColor())
|
||||
thread_send_message.setCompoundDrawablesWithIntrinsicBounds(null, this, null, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
package com.simplemobiletools.smsmessenger.dialogs
|
||||
|
||||
import android.app.DatePickerDialog
|
||||
import android.app.DatePickerDialog.OnDateSetListener
|
||||
import android.app.TimePickerDialog
|
||||
import android.app.TimePickerDialog.OnTimeSetListener
|
||||
import android.text.format.DateFormat
|
||||
import android.text.style.RelativeSizeSpan
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.text.toSpannable
|
||||
import com.simplemobiletools.commons.activities.BaseSimpleActivity
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.TIME_FORMAT_12
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.extensions.round
|
||||
import com.simplemobiletools.smsmessenger.helpers.DATE_FORMAT_PATTERN
|
||||
import kotlinx.android.synthetic.main.schedule_message_dialog.view.*
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
|
||||
class ScheduleSendDialog(private val activity: BaseSimpleActivity, private var dateTime: DateTime? = null, private val callback: (dt: DateTime?) -> Unit) {
|
||||
private val view = activity.layoutInflater.inflate(R.layout.schedule_message_dialog, null)
|
||||
private val textColor = activity.getProperTextColor()
|
||||
|
||||
private var previewDialog: AlertDialog? = null
|
||||
private var previewShown = false
|
||||
private var isNewMessage = dateTime == null
|
||||
|
||||
private val calendar = Calendar.getInstance()
|
||||
|
||||
init {
|
||||
arrayOf(view.subtitle, view.edit_time, view.edit_date).forEach { it.setTextColor(textColor) }
|
||||
arrayOf(view.dateIcon, view.timeIcon).forEach { it.applyColorFilter(textColor) }
|
||||
view.edit_date.setOnClickListener { showDatePicker() }
|
||||
view.edit_time.setOnClickListener { showTimePicker() }
|
||||
updateTexts(dateTime ?: DateTime.now().plusHours(1))
|
||||
|
||||
if (isNewMessage) {
|
||||
showDatePicker()
|
||||
} else {
|
||||
showPreview()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTexts(dt: DateTime) {
|
||||
val dateText = dt.toString(DATE_FORMAT_PATTERN).toSpannable()
|
||||
dateText.setSpan(RelativeSizeSpan(0.6f), 2, dateText.length, 0)
|
||||
val timeText = dt.toString(TIME_FORMAT_12).toSpannable()
|
||||
timeText.setSpan(RelativeSizeSpan(0.6f), timeText.lastIndex - 2, timeText.length, 0)
|
||||
|
||||
view.edit_date.text = dateText
|
||||
view.edit_time.text = timeText
|
||||
}
|
||||
|
||||
private fun showPreview() {
|
||||
if (previewShown) return
|
||||
activity.getAlertDialogBuilder()
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.apply {
|
||||
previewShown = true
|
||||
activity.setupDialogStuff(view, this, R.string.schedule_send) { dialog ->
|
||||
previewDialog = dialog
|
||||
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener {
|
||||
if (validateDateTime()) {
|
||||
callback(dateTime)
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
dialog.setOnDismissListener {
|
||||
previewShown = false
|
||||
previewDialog = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showDatePicker() {
|
||||
val year = dateTime?.year ?: calendar.get(Calendar.YEAR)
|
||||
val monthOfYear = dateTime?.monthOfYear?.minus(1) ?: calendar.get(Calendar.MONTH)
|
||||
val dayOfMonth = dateTime?.dayOfMonth ?: calendar.get(Calendar.DAY_OF_MONTH)
|
||||
|
||||
val dateSetListener = OnDateSetListener { _, y, m, d -> dateSet(y, m, d) }
|
||||
DatePickerDialog(
|
||||
activity, activity.getDatePickerDialogTheme(), dateSetListener, year, monthOfYear, dayOfMonth
|
||||
).apply {
|
||||
datePicker.minDate = System.currentTimeMillis()
|
||||
show()
|
||||
getButton(AlertDialog.BUTTON_NEGATIVE).apply {
|
||||
text = activity.getString(R.string.back)
|
||||
setOnClickListener {
|
||||
showPreview()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showTimePicker() {
|
||||
val hourOfDay = dateTime?.hourOfDay ?: getNextHour()
|
||||
val minute = dateTime?.minuteOfHour ?: getNextMinute()
|
||||
|
||||
val timeSetListener = OnTimeSetListener { _, h, m -> timeSet(h, m) }
|
||||
TimePickerDialog(
|
||||
activity, activity.getDatePickerDialogTheme(), timeSetListener, hourOfDay, minute, DateFormat.is24HourFormat(activity)
|
||||
).apply {
|
||||
show()
|
||||
getButton(AlertDialog.BUTTON_NEGATIVE).apply {
|
||||
text = activity.getString(R.string.back)
|
||||
setOnClickListener {
|
||||
showPreview()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun dateSet(year: Int, monthOfYear: Int, dayOfMonth: Int) {
|
||||
if (isNewMessage) {
|
||||
showTimePicker()
|
||||
}
|
||||
|
||||
dateTime = DateTime.now()
|
||||
.withDate(year, monthOfYear + 1, dayOfMonth)
|
||||
.run {
|
||||
if (dateTime != null) {
|
||||
withTime(dateTime!!.hourOfDay, dateTime!!.minuteOfHour, 0, 0)
|
||||
} else {
|
||||
withTime(getNextHour(), getNextMinute(), 0, 0)
|
||||
}
|
||||
}
|
||||
if (!isNewMessage) {
|
||||
validateDateTime()
|
||||
}
|
||||
isNewMessage = false
|
||||
updateTexts(dateTime!!)
|
||||
}
|
||||
|
||||
private fun timeSet(hourOfDay: Int, minute: Int) {
|
||||
dateTime = dateTime?.withHourOfDay(hourOfDay)?.withMinuteOfHour(minute)
|
||||
if (validateDateTime()) {
|
||||
updateTexts(dateTime!!)
|
||||
showPreview()
|
||||
} else {
|
||||
showTimePicker()
|
||||
}
|
||||
}
|
||||
|
||||
private fun validateDateTime(): Boolean {
|
||||
return if (dateTime?.isAfterNow == false) {
|
||||
activity.toast(R.string.must_pick_time_in_the_future)
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
private fun getNextHour() = calendar.get(Calendar.HOUR_OF_DAY) + 1
|
||||
|
||||
private fun getNextMinute() = (calendar.get(Calendar.MINUTE) + 5).round(5).coerceIn(0, 59)
|
||||
}
|
|
@ -26,7 +26,6 @@ import android.telephony.SubscriptionManager
|
|||
import android.text.TextUtils
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.RemoteInput
|
||||
import com.klinker.android.send_message.Settings
|
||||
import com.klinker.android.send_message.Transaction.getAddressSeparator
|
||||
import com.simplemobiletools.commons.extensions.*
|
||||
import com.simplemobiletools.commons.helpers.*
|
||||
|
@ -974,16 +973,6 @@ fun Context.getFileSizeFromUri(uri: Uri): Long {
|
|||
}
|
||||
}
|
||||
|
||||
fun Context.getSendMessageSettings(): Settings {
|
||||
val settings = Settings()
|
||||
settings.useSystemSending = true
|
||||
settings.deliveryReports = config.enableDeliveryReports
|
||||
settings.sendLongAsMms = config.sendLongMessageMMS
|
||||
settings.sendLongAsMmsAfter = 1
|
||||
settings.group = config.sendGroupMessageMMS
|
||||
return settings
|
||||
}
|
||||
|
||||
// fix a glitch at enabling Release version minifying from 5.12.3
|
||||
// reset messages in 5.14.3 again, as PhoneNumber is no longer minified
|
||||
fun Context.clearAllMessagesIfNeeded() {
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
package com.simplemobiletools.smsmessenger.extensions
|
||||
|
||||
import android.content.Context
|
||||
import android.text.format.DateFormat
|
||||
import android.text.format.DateUtils
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
|
||||
fun Date.format(pattern: String): String {
|
||||
return DateFormat.format(pattern, this).toString()
|
||||
}
|
||||
|
||||
fun DateTime.humanize(context: Context, now: DateTime = DateTime.now(), pattern: String = "EEE, MMM dd, YYYY, hh:mm a"): String {
|
||||
return if (yearOfCentury().get() > now.yearOfCentury().get()) {
|
||||
toString(pattern)
|
||||
} else {
|
||||
DateUtils.getRelativeDateTimeString(context, millis, DateUtils.MINUTE_IN_MILLIS, DateUtils.DAY_IN_MILLIS, 0).toString()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package com.simplemobiletools.smsmessenger.extensions
|
||||
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Returns the closest next number divisible by [multipleOf].
|
||||
*/
|
||||
fun Int.round(multipleOf: Int = 1) = (toDouble() / multipleOf).roundToInt() * multipleOf
|
|
@ -34,6 +34,8 @@ private const val PATH = "com.simplemobiletools.smsmessenger.action."
|
|||
const val MARK_AS_READ = PATH + "mark_as_read"
|
||||
const val REPLY = PATH + "reply"
|
||||
|
||||
const val DATE_FORMAT_PATTERN = "dd MMM, YYYY"
|
||||
|
||||
// view types for the thread list view
|
||||
const val THREAD_DATE_TIME = 1
|
||||
const val THREAD_RECEIVED_MESSAGE = 2
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package com.simplemobiletools.smsmessenger.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import com.klinker.android.send_message.Settings
|
||||
import com.klinker.android.send_message.Transaction
|
||||
import com.klinker.android.send_message.Utils
|
||||
import com.simplemobiletools.commons.extensions.showErrorToast
|
||||
import com.simplemobiletools.smsmessenger.R
|
||||
import com.simplemobiletools.smsmessenger.extensions.config
|
||||
import com.simplemobiletools.smsmessenger.receivers.SmsStatusDeliveredReceiver
|
||||
import com.simplemobiletools.smsmessenger.receivers.SmsStatusSentReceiver
|
||||
|
||||
fun Context.getSendMessageSettings(): Settings {
|
||||
val settings = Settings()
|
||||
settings.useSystemSending = true
|
||||
settings.deliveryReports = config.enableDeliveryReports
|
||||
settings.sendLongAsMms = config.sendLongMessageMMS
|
||||
settings.sendLongAsMmsAfter = 1
|
||||
settings.group = config.sendGroupMessageMMS
|
||||
return settings
|
||||
}
|
||||
|
||||
fun Context.sendTransactionMessage(text: String, addresses: List<String>, subscriptionId: Int?, attachments: List<Uri>) {
|
||||
val settings = getSendMessageSettings()
|
||||
if (subscriptionId != null) {
|
||||
settings.subscriptionId = subscriptionId
|
||||
}
|
||||
|
||||
val transaction = Transaction(this, settings)
|
||||
val message = com.klinker.android.send_message.Message(text, addresses.toTypedArray())
|
||||
|
||||
if (attachments.isNotEmpty()) {
|
||||
for (uri in attachments) {
|
||||
try {
|
||||
val byteArray = contentResolver.openInputStream(uri)?.readBytes() ?: continue
|
||||
val mimeType = contentResolver.getType(uri) ?: continue
|
||||
message.addMedia(byteArray, mimeType)
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
} catch (e: Error) {
|
||||
showErrorToast(e.localizedMessage ?: getString(R.string.unknown_error_occurred))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val smsSentIntent = Intent(this, SmsStatusSentReceiver::class.java)
|
||||
val deliveredIntent = Intent(this, SmsStatusDeliveredReceiver::class.java)
|
||||
|
||||
transaction.setExplicitBroadcastForSentSms(smsSentIntent)
|
||||
transaction.setExplicitBroadcastForDeliveredSms(deliveredIntent)
|
||||
transaction.sendNewMessage(message)
|
||||
}
|
||||
|
||||
fun Context.isLongMmsMessage(text: String): Boolean {
|
||||
val settings = getSendMessageSettings()
|
||||
return Utils.getNumPages(settings, text) > settings.sendLongAsMmsAfter
|
||||
}
|
|
@ -4,7 +4,6 @@ import android.annotation.SuppressLint
|
|||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.telephony.SubscriptionManager
|
||||
import androidx.core.app.RemoteInput
|
||||
import com.klinker.android.send_message.Transaction
|
||||
import com.simplemobiletools.commons.extensions.notificationManager
|
||||
|
@ -14,6 +13,7 @@ import com.simplemobiletools.smsmessenger.extensions.*
|
|||
import com.simplemobiletools.smsmessenger.helpers.REPLY
|
||||
import com.simplemobiletools.smsmessenger.helpers.THREAD_ID
|
||||
import com.simplemobiletools.smsmessenger.helpers.THREAD_NUMBER
|
||||
import com.simplemobiletools.smsmessenger.helpers.getSendMessageSettings
|
||||
|
||||
class DirectReplyReceiver : BroadcastReceiver() {
|
||||
@SuppressLint("MissingPermission")
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package com.simplemobiletools.smsmessenger.receivers
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
|
||||
class ScheduledMessageReceiver: BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
|
@ -4,8 +4,7 @@ import android.app.Service
|
|||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import com.klinker.android.send_message.Transaction
|
||||
import com.simplemobiletools.smsmessenger.extensions.getSendMessageSettings
|
||||
import com.simplemobiletools.smsmessenger.extensions.getThreadId
|
||||
import com.simplemobiletools.smsmessenger.helpers.getSendMessageSettings
|
||||
import com.simplemobiletools.smsmessenger.receivers.SmsStatusDeliveredReceiver
|
||||
import com.simplemobiletools.smsmessenger.receivers.SmsStatusSentReceiver
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="#FFFFFF"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19,4h-1V2h-2v2H8V2H6v2H5C3.89,4 3.01,4.9 3.01,6L3,20c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V6C21,4.9 20.1,4 19,4zM19,20H5V10h14V20zM9,14H7v-2h2V14zM13,14h-2v-2h2V14zM17,14h-2v-2h2V14zM9,18H7v-2h2V18zM13,18h-2v-2h2V18zM17,18h-2v-2h2V18z" />
|
||||
</vector>
|
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:autoMirrored="true"
|
||||
android:tint="#FFFFFF"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M16.5,12.5L15,12.5v4l3,2 0.75,-1.23 -2.25,-1.52L16.5,12.5zM16,9L2,3v7l9,2 -9,2v7l7.27,-3.11C10.09,20.83 12.79,23 16,23c3.86,0 7,-3.14 7,-7s-3.14,-7 -7,-7zM16,21c-2.75,0 -4.98,-2.22 -5,-4.97v-0.07c0.02,-2.74 2.25,-4.97 5,-4.97 2.76,0 5,2.24 5,5S18.76,21 16,21z" />
|
||||
</vector>
|
|
@ -119,7 +119,9 @@
|
|||
android:overScrollMode="ifContentScrolls"
|
||||
android:scrollbars="none"
|
||||
app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager"
|
||||
app:stackFromEnd="true" />
|
||||
app:stackFromEnd="true"
|
||||
tools:itemCount="3"
|
||||
tools:listitem="@layout/item_sent_message" />
|
||||
|
||||
</com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller>
|
||||
|
||||
|
@ -127,7 +129,7 @@
|
|||
android:id="@+id/message_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:layout_above="@+id/thread_attachments_holder"
|
||||
android:layout_above="@+id/scheduled_message_holder"
|
||||
android:background="@color/divider_grey"
|
||||
android:importantForAccessibility="no" />
|
||||
|
||||
|
@ -145,13 +147,57 @@
|
|||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_plus_vector" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/scheduled_message_holder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/thread_attachments_holder"
|
||||
android:layout_alignStart="@id/thread_type_message"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:layout_marginEnd="@dimen/medium_margin"
|
||||
android:layout_marginBottom="@dimen/small_margin"
|
||||
android:background="@drawable/section_holder_stroke"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/scheduled_message_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:drawableStart="@drawable/ic_clock_vector"
|
||||
android:drawablePadding="@dimen/normal_margin"
|
||||
android:focusable="true"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="@dimen/normal_icon_size"
|
||||
android:paddingStart="@dimen/normal_margin"
|
||||
android:paddingEnd="48dp"
|
||||
android:text="Tomorrow at 6PM GMT +05:30"
|
||||
android:textSize="@dimen/middle_text_size"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/discard_scheduled_message"
|
||||
android:layout_width="@dimen/normal_icon_size"
|
||||
android:layout_height="@dimen/normal_icon_size"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/cancel_schedule_send"
|
||||
android:padding="@dimen/normal_margin"
|
||||
android:src="@drawable/ic_cross_vector" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/thread_attachments_holder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/thread_type_message"
|
||||
android:layout_alignStart="@+id/thread_type_message"
|
||||
android:layout_marginTop="@dimen/normal_margin"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:layout_marginBottom="@dimen/small_margin"
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="none"
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/scheduled_message_dialog_holder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="@dimen/activity_margin">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/subtitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="@dimen/activity_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:includeFontPadding="false"
|
||||
android:padding="@dimen/tiny_margin"
|
||||
android:text="@string/schedule_send_warning"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/dateIcon"
|
||||
android:layout_width="@dimen/normal_icon_size"
|
||||
android:layout_height="@dimen/normal_icon_size"
|
||||
android:layout_margin="@dimen/activity_margin"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_calendar_month_vector"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/subtitle" />
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/edit_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/tiny_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:ellipsize="end"
|
||||
android:includeFontPadding="false"
|
||||
android:padding="@dimen/small_margin"
|
||||
android:textSize="@dimen/date_time_text_size"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/dateIcon"
|
||||
app:layout_constraintStart_toEndOf="@+id/dateIcon"
|
||||
app:layout_constraintTop_toTopOf="@+id/dateIcon"
|
||||
tools:text="25 sep, 2022" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/timeIcon"
|
||||
android:layout_width="@dimen/normal_icon_size"
|
||||
android:layout_height="@dimen/normal_icon_size"
|
||||
android:layout_margin="@dimen/activity_margin"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_clock_vector"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/dateIcon" />
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/edit_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/tiny_margin"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:ellipsize="end"
|
||||
android:includeFontPadding="false"
|
||||
android:padding="@dimen/small_margin"
|
||||
android:textSize="@dimen/date_time_text_size"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/timeIcon"
|
||||
app:layout_constraintStart_toEndOf="@+id/timeIcon"
|
||||
app:layout_constraintTop_toTopOf="@+id/timeIcon"
|
||||
tools:text="07:00 AM" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -7,4 +7,5 @@
|
|||
<dimen name="remove_attachment_size">24dp</dimen>
|
||||
<dimen name="pin_icon_size">15dp</dimen>
|
||||
<dimen name="vcard_property_start_margin">64dp</dimen>
|
||||
<dimen name="date_time_text_size">36sp</dimen>
|
||||
</resources>
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
<string name="unpin_conversation">Unpin</string>
|
||||
<string name="forward_message">Forward</string>
|
||||
<string name="compress_error">Unable to compress image to selected size</string>
|
||||
<string name="back">Back</string>
|
||||
<!-- vCard-->
|
||||
<plurals name="and_other_contacts">
|
||||
<item quantity="one">and %d other</item>
|
||||
|
@ -29,6 +30,11 @@
|
|||
<string name="new_conversation">New conversation</string>
|
||||
<string name="add_contact_or_number">Add Contact or Number…</string>
|
||||
<string name="suggestions">Suggestions</string>
|
||||
<!-- Schedule send -->
|
||||
<string name="schedule_send">Schedule send</string>
|
||||
<string name="cancel_schedule_send">Cancel schedule send</string>
|
||||
<string name="must_pick_time_in_the_future">You must pick a time in the future</string>
|
||||
<string name="schedule_send_warning">Keep the phone on and make sure nothing\'s killing the app in background</string>
|
||||
<!-- Notifications -->
|
||||
<string name="channel_received_sms">Received SMS</string>
|
||||
<string name="new_message">New message</string>
|
||||
|
|
Loading…
Reference in New Issue