added remove media in dm and compose
This commit is contained in:
parent
177b682d84
commit
5e5aad22a9
|
@ -25,4 +25,6 @@ Thumbs.db
|
|||
|
||||
# Private files
|
||||
/signing.properties
|
||||
/twidere.jks
|
||||
/twidere.jks
|
||||
|
||||
/captures
|
|
@ -157,7 +157,7 @@ dependencies {
|
|||
compile 'com.bluelinelabs:logansquare:1.3.7'
|
||||
compile 'com.soundcloud.android:android-crop:1.0.1@aar'
|
||||
compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.2'
|
||||
compile 'com.github.mariotaku:PickNCrop:0.9.17'
|
||||
compile 'com.github.mariotaku:PickNCrop:0.9.19'
|
||||
compile "com.github.mariotaku.RestFu:library:$mariotaku_restfu_version"
|
||||
compile "com.github.mariotaku.RestFu:okhttp3:$mariotaku_restfu_version"
|
||||
compile 'com.squareup.okhttp3:okhttp:3.5.0'
|
||||
|
|
|
@ -89,6 +89,7 @@ import org.mariotaku.twidere.preference.ServicePickerPreference
|
|||
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts
|
||||
import org.mariotaku.twidere.service.LengthyOperationsService
|
||||
import org.mariotaku.twidere.task.compose.AbsAddMediaTask
|
||||
import org.mariotaku.twidere.task.compose.AbsDeleteMediaTask
|
||||
import org.mariotaku.twidere.text.MarkForDeleteSpan
|
||||
import org.mariotaku.twidere.text.style.EmojiSpan
|
||||
import org.mariotaku.twidere.util.*
|
||||
|
@ -151,7 +152,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
REQUEST_TAKE_PHOTO, REQUEST_PICK_MEDIA -> {
|
||||
if (resultCode == Activity.RESULT_OK && intent != null) {
|
||||
val src = MediaPickerActivity.getMediaUris(intent)
|
||||
TaskStarter.execute(AddMediaTask(this, src, true))
|
||||
TaskStarter.execute(AddMediaTask(this, src, false, false))
|
||||
}
|
||||
}
|
||||
REQUEST_EDIT_IMAGE -> {
|
||||
|
@ -339,7 +340,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
IntentUtils.openDrafts(this)
|
||||
}
|
||||
R.id.delete -> {
|
||||
AsyncTaskUtils.executeTask(DeleteMediaTask(this, media))
|
||||
TaskStarter.execute(DeleteMediaTask(this, media))
|
||||
}
|
||||
R.id.toggle_sensitive -> {
|
||||
if (!hasMedia()) return false
|
||||
|
@ -807,21 +808,21 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
val stream = intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)
|
||||
if (stream != null) {
|
||||
val src = arrayOf(stream)
|
||||
TaskStarter.execute(AddMediaTask(this, src, false))
|
||||
TaskStarter.execute(AddMediaTask(this, src, true, false))
|
||||
}
|
||||
} else if (Intent.ACTION_SEND_MULTIPLE == action) {
|
||||
shouldSaveAccounts = false
|
||||
val extraStream = intent.getParcelableArrayListExtra<Uri>(Intent.EXTRA_STREAM)
|
||||
if (extraStream != null) {
|
||||
val src = extraStream.toTypedArray()
|
||||
TaskStarter.execute(AddMediaTask(this, src, false))
|
||||
TaskStarter.execute(AddMediaTask(this, src, true, false))
|
||||
}
|
||||
} else {
|
||||
shouldSaveAccounts = !hasAccountIds
|
||||
val data = intent.data
|
||||
if (data != null) {
|
||||
val src = arrayOf(data)
|
||||
TaskStarter.execute(AddMediaTask(this, src, false))
|
||||
TaskStarter.execute(AddMediaTask(this, src, true, false))
|
||||
}
|
||||
}
|
||||
val extraSubject = intent.getCharSequenceExtra(Intent.EXTRA_SUBJECT)
|
||||
|
@ -1507,8 +1508,9 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
internal class AddMediaTask(
|
||||
activity: ComposeActivity,
|
||||
sources: Array<Uri>,
|
||||
copySrc: Boolean,
|
||||
deleteSrc: Boolean
|
||||
) : AbsAddMediaTask<ComposeActivity>(activity, sources, deleteSrc) {
|
||||
) : AbsAddMediaTask<ComposeActivity>(activity, sources, copySrc, deleteSrc) {
|
||||
|
||||
init {
|
||||
callback = activity
|
||||
|
@ -1529,34 +1531,27 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
|
|||
|
||||
}
|
||||
|
||||
internal class DeleteMediaTask(activity: ComposeActivity, val media: Array<ParcelableMediaUpdate>) : AsyncTask<Any, Any, Boolean>() {
|
||||
|
||||
val activity: WeakReference<ComposeActivity>
|
||||
internal class DeleteMediaTask(
|
||||
activity: ComposeActivity,
|
||||
val media: Array<ParcelableMediaUpdate>
|
||||
) : AbsDeleteMediaTask<ComposeActivity>(activity, media.map { Uri.parse(it.uri) }.toTypedArray()) {
|
||||
|
||||
init {
|
||||
this.activity = WeakReference(activity)
|
||||
this.callback = activity
|
||||
}
|
||||
|
||||
override fun doInBackground(vararg params: Any): Boolean {
|
||||
media.forEach {
|
||||
Utils.deleteMedia(activity.get(), Uri.parse(it.uri))
|
||||
override fun beforeExecute() {
|
||||
callback?.setProgressVisible(true)
|
||||
}
|
||||
|
||||
override fun afterExecute(callback: ComposeActivity?, result: BooleanArray?) {
|
||||
if (callback == null || result == null) return
|
||||
callback.setProgressVisible(false)
|
||||
callback.removeAllMedia(media.filterIndexed { i, media -> result[i] })
|
||||
callback.setMenu()
|
||||
if (result.any { false }) {
|
||||
Toast.makeText(callback, R.string.message_toast_error_occurred, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onPostExecute(result: Boolean) {
|
||||
val activity = activity.get() ?: return
|
||||
activity.setProgressVisible(false)
|
||||
activity.removeAllMedia(Arrays.asList(*media))
|
||||
activity.setMenu()
|
||||
if (!result) {
|
||||
Toast.makeText(activity, R.string.message_toast_error_occurred, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPreExecute() {
|
||||
val activity = activity.get() ?: return
|
||||
activity.setProgressVisible(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.mariotaku.twidere.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import org.mariotaku.twidere.R
|
||||
|
@ -84,7 +85,8 @@ class MediaPreviewAdapter(
|
|||
}
|
||||
|
||||
interface Listener : SimpleItemTouchHelperCallback.OnStartDragListener {
|
||||
fun onRemoveClick(position: Int, holder: MediaPreviewViewHolder)
|
||||
fun onEditClick(position: Int, holder: MediaPreviewViewHolder)
|
||||
fun onRemoveClick(position: Int, holder: MediaPreviewViewHolder) {}
|
||||
fun onEditClick(position: Int, holder: MediaPreviewViewHolder) {}
|
||||
override fun onStartDrag(viewHolder: RecyclerView.ViewHolder) {}
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ import android.support.v4.app.Fragment
|
|||
import android.support.v4.text.BidiFormatter
|
||||
import com.squareup.otto.Bus
|
||||
import org.mariotaku.twidere.fragment.iface.IBaseFragment
|
||||
import org.mariotaku.twidere.model.DefaultFeatures
|
||||
import org.mariotaku.twidere.util.*
|
||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||
import org.mariotaku.twidere.util.premium.ExtraFeaturesService
|
||||
|
@ -61,6 +62,8 @@ open class BaseFragment : Fragment(), IBaseFragment<BaseFragment> {
|
|||
lateinit var extraFeaturesService: ExtraFeaturesService
|
||||
@Inject
|
||||
lateinit var permissionsManager: PermissionsManager
|
||||
@Inject
|
||||
lateinit var defaultFeatures: DefaultFeatures
|
||||
|
||||
private val actionHelper = IBaseFragment.ActionHelper(this)
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import android.support.v7.widget.RecyclerView
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import com.squareup.otto.Subscribe
|
||||
import kotlinx.android.synthetic.main.fragment_messages_conversation.*
|
||||
import org.mariotaku.abstask.library.TaskStarter
|
||||
|
@ -31,6 +32,7 @@ import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
|
|||
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_ACCOUNT_KEY
|
||||
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_CONVERSATION_ID
|
||||
import org.mariotaku.twidere.constant.newDocumentApiKey
|
||||
import org.mariotaku.twidere.extension.model.isOfficial
|
||||
import org.mariotaku.twidere.loader.ObjectCursorLoader
|
||||
import org.mariotaku.twidere.model.*
|
||||
import org.mariotaku.twidere.model.ParcelableMessageConversation.ConversationType
|
||||
|
@ -40,9 +42,11 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Messages
|
|||
import org.mariotaku.twidere.service.LengthyOperationsService
|
||||
import org.mariotaku.twidere.task.GetMessagesTask
|
||||
import org.mariotaku.twidere.task.compose.AbsAddMediaTask
|
||||
import org.mariotaku.twidere.task.compose.AbsDeleteMediaTask
|
||||
import org.mariotaku.twidere.util.DataStoreUtils
|
||||
import org.mariotaku.twidere.util.IntentUtils
|
||||
import org.mariotaku.twidere.util.PreviewGridItemDecoration
|
||||
import org.mariotaku.twidere.view.holder.compose.MediaPreviewViewHolder
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
class MessagesConversationFragment : AbsContentListRecyclerViewFragment<MessagesConversationAdapter>(),
|
||||
|
@ -70,6 +74,10 @@ class MessagesConversationFragment : AbsContentListRecyclerViewFragment<Messages
|
|||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
val account = this.account ?: run {
|
||||
activity?.finish()
|
||||
return
|
||||
}
|
||||
adapter.listener = object : MessagesConversationAdapter.Listener {
|
||||
override fun onMediaClick(position: Int, media: ParcelableMedia, accountKey: UserKey?) {
|
||||
val message = adapter.getMessage(position) ?: return
|
||||
|
@ -80,6 +88,15 @@ class MessagesConversationFragment : AbsContentListRecyclerViewFragment<Messages
|
|||
}
|
||||
mediaPreviewAdapter = MediaPreviewAdapter(context)
|
||||
|
||||
mediaPreviewAdapter.listener = object : MediaPreviewAdapter.Listener {
|
||||
override fun onRemoveClick(position: Int, holder: MediaPreviewViewHolder) {
|
||||
val task = DeleteMediaTask(this@MessagesConversationFragment,
|
||||
arrayOf(mediaPreviewAdapter.getItem(position)))
|
||||
TaskStarter.execute(task)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
attachedMediaPreview.layoutManager = FixedLinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
attachedMediaPreview.adapter = mediaPreviewAdapter
|
||||
attachedMediaPreview.addItemDecoration(PreviewGridItemDecoration(resources.getDimensionPixelSize(R.dimen.element_spacing_small)))
|
||||
|
@ -95,6 +112,12 @@ class MessagesConversationFragment : AbsContentListRecyclerViewFragment<Messages
|
|||
refreshEnabled = false
|
||||
adapter.loadMoreSupportedPosition = ILoadMoreSupportAdapter.NONE
|
||||
|
||||
if (account.isOfficial(context)) {
|
||||
addMedia.visibility = View.VISIBLE
|
||||
} else {
|
||||
addMedia.visibility = View.GONE
|
||||
}
|
||||
|
||||
updateMediaPreview()
|
||||
|
||||
loaderManager.initLoader(0, null, this)
|
||||
|
@ -116,7 +139,7 @@ class MessagesConversationFragment : AbsContentListRecyclerViewFragment<Messages
|
|||
REQUEST_PICK_MEDIA -> {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
val mediaUris = MediaPickerActivity.getMediaUris(data)
|
||||
TaskStarter.execute(AddMediaTask(this, mediaUris, true))
|
||||
TaskStarter.execute(AddMediaTask(this, mediaUris))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -179,13 +202,25 @@ class MessagesConversationFragment : AbsContentListRecyclerViewFragment<Messages
|
|||
|
||||
private fun performSendMessage() {
|
||||
val conversation = adapter.conversation ?: return
|
||||
val conversationAccount = this.account ?: return
|
||||
if (editText.empty && adapter.itemCount == 0) {
|
||||
editText.error = getString(R.string.hint_error_message_no_content)
|
||||
return
|
||||
}
|
||||
if (conversationAccount.isOfficial(context)) {
|
||||
if (adapter.itemCount > defaultFeatures.twitterDirectMessageMediaLimit) {
|
||||
editText.error = getString(R.string.error_message_media_message_too_many)
|
||||
return
|
||||
} else {
|
||||
editText.error = null
|
||||
}
|
||||
} else {
|
||||
editText.error = getString(R.string.error_message_media_message_attachment_not_supported)
|
||||
return
|
||||
}
|
||||
val text = editText.text.toString()
|
||||
val message = ParcelableNewMessage().apply {
|
||||
this.account = this@MessagesConversationFragment.account
|
||||
this.account = conversationAccount
|
||||
this.media = mediaPreviewAdapter.asList().toTypedArray()
|
||||
this.conversation_id = conversation.id
|
||||
this.recipient_ids = conversation.participants?.map {
|
||||
|
@ -218,12 +253,18 @@ class MessagesConversationFragment : AbsContentListRecyclerViewFragment<Messages
|
|||
updateMediaPreview()
|
||||
}
|
||||
|
||||
private fun removeMedia(media: List<ParcelableMediaUpdate>) {
|
||||
mediaPreviewAdapter.removeAll(media)
|
||||
updateMediaPreview()
|
||||
}
|
||||
|
||||
private fun updateMediaPreview() {
|
||||
attachedMediaPreview.visibility = if (mediaPreviewAdapter.itemCount > 0) {
|
||||
View.VISIBLE
|
||||
} else {
|
||||
View.GONE
|
||||
}
|
||||
editText.error = null
|
||||
}
|
||||
|
||||
private fun setProgressVisible(visible: Boolean) {
|
||||
|
@ -232,9 +273,8 @@ class MessagesConversationFragment : AbsContentListRecyclerViewFragment<Messages
|
|||
|
||||
internal class AddMediaTask(
|
||||
fragment: MessagesConversationFragment,
|
||||
sources: Array<Uri>,
|
||||
deleteSrc: Boolean
|
||||
) : AbsAddMediaTask<MessagesConversationFragment>(fragment.context, sources, deleteSrc) {
|
||||
sources: Array<Uri>
|
||||
) : AbsAddMediaTask<MessagesConversationFragment>(fragment.context, sources) {
|
||||
|
||||
init {
|
||||
callback = fragment
|
||||
|
@ -253,6 +293,32 @@ class MessagesConversationFragment : AbsContentListRecyclerViewFragment<Messages
|
|||
|
||||
}
|
||||
|
||||
internal class DeleteMediaTask(
|
||||
fragment: MessagesConversationFragment,
|
||||
val media: Array<ParcelableMediaUpdate>
|
||||
) : AbsDeleteMediaTask<MessagesConversationFragment>(fragment.context,
|
||||
media.map { Uri.parse(it.uri) }.toTypedArray()) {
|
||||
|
||||
init {
|
||||
callback = fragment
|
||||
}
|
||||
|
||||
override fun afterExecute(callback: MessagesConversationFragment?, result: BooleanArray?) {
|
||||
if (callback == null || result == null) return
|
||||
callback.setProgressVisible(false)
|
||||
callback.removeMedia(media.filterIndexed { i, media -> result[i] })
|
||||
if (result.any { false }) {
|
||||
Toast.makeText(callback.context, R.string.message_toast_error_occurred, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun beforeExecute() {
|
||||
val fragment = callback ?: return
|
||||
fragment.setProgressVisible(true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class ConversationLoader(
|
||||
context: Context,
|
||||
val accountKey: UserKey,
|
||||
|
|
|
@ -62,8 +62,8 @@ class GetMessagesTask(
|
|||
private fun getMessages(microBlog: MicroBlog, details: AccountDetails, param: RefreshMessagesTaskParam, index: Int): DatabaseUpdateData {
|
||||
when (details.type) {
|
||||
AccountType.FANFOU -> {
|
||||
// Use fanfou DM api
|
||||
return getFanfouMessages(microBlog, details, param, index)
|
||||
// Use fanfou DM api, disabled since it's conversation api is not suitable for paging
|
||||
// return getFanfouMessages(microBlog, details, param, index)
|
||||
}
|
||||
AccountType.TWITTER -> {
|
||||
// Use official DM api
|
||||
|
|
|
@ -35,7 +35,8 @@ import java.lang.ref.WeakReference
|
|||
open class AbsAddMediaTask<Callback>(
|
||||
context: Context,
|
||||
val sources: Array<Uri>,
|
||||
val deleteSrc: Boolean
|
||||
val copySrc: Boolean = false,
|
||||
val deleteSrc: Boolean = false
|
||||
) : AbstractTask<Unit, List<ParcelableMediaUpdate>?, Callback>() {
|
||||
|
||||
private val contextRef = WeakReference(context)
|
||||
|
@ -59,13 +60,17 @@ open class AbsAddMediaTask<Callback>(
|
|||
val extension = sourceMimeType?.let { mimeType ->
|
||||
MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType)
|
||||
} ?: "tmp"
|
||||
val destination = createTempImageUri(context, index, extension)
|
||||
st = resolver.openInputStream(source)
|
||||
os = resolver.openOutputStream(destination)
|
||||
if (st == null || os == null) throw FileNotFoundException()
|
||||
StreamUtils.copy(st, os, null, null)
|
||||
if (deleteSrc) {
|
||||
Utils.deleteMedia(context, source)
|
||||
st = resolver.openInputStream(source) ?: throw FileNotFoundException("Unable to open $source")
|
||||
val destination: Uri
|
||||
if (copySrc) {
|
||||
destination = createTempImageUri(context, index, extension)
|
||||
os = resolver.openOutputStream(destination) ?: throw FileNotFoundException("Unable to open $destination")
|
||||
StreamUtils.copy(st, os, null, null)
|
||||
if (deleteSrc) {
|
||||
Utils.deleteMedia(context, source)
|
||||
}
|
||||
} else {
|
||||
destination = source
|
||||
}
|
||||
return@mapIndexedNotNull ParcelableMediaUpdate(destination.toString(), mediaType)
|
||||
} catch (e: IOException) {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.task.compose
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import org.mariotaku.abstask.library.AbstractTask
|
||||
import org.mariotaku.twidere.util.Utils
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
open class AbsDeleteMediaTask<Callback>(
|
||||
context: Context,
|
||||
val sources: Array<Uri>
|
||||
) : AbstractTask<Unit, BooleanArray?, Callback>() {
|
||||
|
||||
private val contextRef = WeakReference(context)
|
||||
val context: Context? get() = contextRef.get()
|
||||
|
||||
override fun doLongOperation(params: Unit?): BooleanArray? {
|
||||
val context = contextRef.get() ?: return null
|
||||
return BooleanArray(sources.size) { Utils.deleteMedia(context, sources[it]) }
|
||||
}
|
||||
|
||||
}
|
|
@ -47,11 +47,11 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="?android:colorBackground"
|
||||
android:clipToPadding="false"
|
||||
android:gravity="bottom"
|
||||
android:orientation="horizontal"
|
||||
android:outlineProvider="bounds"
|
||||
android:paddingBottom="@dimen/element_spacing_normal"
|
||||
android:paddingTop="@dimen/element_spacing_normal"
|
||||
android:padding="@dimen/element_spacing_normal"
|
||||
tools:ignore="UnusedAttribute">
|
||||
|
||||
<org.mariotaku.twidere.view.IconActionView
|
||||
|
@ -60,25 +60,24 @@
|
|||
android:layout_height="@dimen/element_size_normal"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginEnd="@dimen/element_spacing_normal"
|
||||
android:layout_marginRight="@dimen/element_spacing_normal"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:contentDescription="@string/add_image"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/ic_action_gallery"
|
||||
android:visibility="visible"
|
||||
android:visibility="gone"
|
||||
app:iabColor="?android:textColorSecondary"
|
||||
tools:tint="?android:textColorSecondary"/>
|
||||
tools:tint="?android:textColorSecondary"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/sendMessageContainer"
|
||||
android:layout_width="@dimen/element_size_normal"
|
||||
android:layout_height="@dimen/element_size_normal"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginEnd="@dimen/element_spacing_normal"
|
||||
android:layout_marginLeft="@dimen/element_spacing_minus_normal"
|
||||
android:layout_marginRight="@dimen/element_spacing_normal"
|
||||
android:layout_marginStart="@dimen/element_spacing_minus_normal">
|
||||
android:layout_alignParentRight="true">
|
||||
|
||||
<org.mariotaku.twidere.view.IconActionView
|
||||
android:id="@+id/sendMessage"
|
||||
|
|
|
@ -425,7 +425,9 @@
|
|||
<string name="error_message_device_incompatible">This device is not compatible with Twidere, upgrade to latest Android OS is recommended.\nYou can send information below to help me report this issue to device manufacturer.</string>
|
||||
<string name="error_message_media_upload_failed">Media upload failed.</string>
|
||||
<string name="error_message_media_uploader_not_found">Media uploader not found, maybe it was uninstalled.</string>
|
||||
<string name="error_message_message_too_long">Message too long.</string>
|
||||
<string name="error_message_media_message_attachment_not_supported">Attach media to DM is not supported</string>
|
||||
<string name="error_message_media_message_too_many">Too many media</string>
|
||||
<string name="error_message_message_too_long">Message too long</string>
|
||||
<string name="error_message_no_content">No content</string>
|
||||
<string
|
||||
name="error_message_rate_limit">Twitter\'s rate limit exceeded, please retry <xliff:g id="time">%s</xliff:g>
|
||||
|
|
Loading…
Reference in New Issue