diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ThreadActivity.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ThreadActivity.kt index 59c66ebd..b9575c04 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ThreadActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ThreadActivity.kt @@ -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() - 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) + } + } } diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ScheduleSendDialog.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ScheduleSendDialog.kt new file mode 100644 index 00000000..6f0b0808 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/dialogs/ScheduleSendDialog.kt @@ -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) +} diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Context.kt index ddde568f..4dd05681 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Context.kt @@ -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() { diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Date.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Date.kt index 7cde1a5b..49182867 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Date.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Date.kt @@ -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() + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Math.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Math.kt new file mode 100644 index 00000000..e3e61e2e --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Math.kt @@ -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 diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Constants.kt index 973e56bc..f3711dec 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Constants.kt @@ -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 diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Messaging.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Messaging.kt new file mode 100644 index 00000000..2f0ed4c7 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Messaging.kt @@ -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, subscriptionId: Int?, attachments: List) { + 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 +} diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/DirectReplyReceiver.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/DirectReplyReceiver.kt index caac5115..81114a0f 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/DirectReplyReceiver.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/DirectReplyReceiver.kt @@ -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") diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/ScheduledMessageReceiver.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/ScheduledMessageReceiver.kt new file mode 100644 index 00000000..72aa53d1 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/ScheduledMessageReceiver.kt @@ -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") + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/services/HeadlessSmsSendService.kt b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/services/HeadlessSmsSendService.kt index 1ebf9d7a..bdea1dbe 100644 --- a/app/src/main/kotlin/com/simplemobiletools/smsmessenger/services/HeadlessSmsSendService.kt +++ b/app/src/main/kotlin/com/simplemobiletools/smsmessenger/services/HeadlessSmsSendService.kt @@ -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 diff --git a/app/src/main/res/drawable/ic_calendar_month_vector.xml b/app/src/main/res/drawable/ic_calendar_month_vector.xml new file mode 100644 index 00000000..cf05bd36 --- /dev/null +++ b/app/src/main/res/drawable/ic_calendar_month_vector.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_schedule_send_vector.xml b/app/src/main/res/drawable/ic_schedule_send_vector.xml new file mode 100644 index 00000000..4d46188f --- /dev/null +++ b/app/src/main/res/drawable/ic_schedule_send_vector.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/layout/activity_thread.xml b/app/src/main/res/layout/activity_thread.xml index 7854987f..fde37255 100644 --- a/app/src/main/res/layout/activity_thread.xml +++ b/app/src/main/res/layout/activity_thread.xml @@ -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" /> @@ -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" /> + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 68e9a072..b8a87de9 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -7,4 +7,5 @@ 24dp 15dp 64dp + 36sp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 762434d8..4e7ca0ba 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -20,6 +20,7 @@ Unpin Forward Unable to compress image to selected size + Back and %d other @@ -29,6 +30,11 @@ New conversation Add Contact or Number… Suggestions + + Schedule send + Cancel schedule send + You must pick a time in the future + Keep the phone on and make sure nothing\'s killing the app in background Received SMS New message