Rename Toots to Posts (#2396)
* rename toots -> posts in strings * extract tusky_compose_post_quicksetting_label string * rename toot -> status in code
This commit is contained in:
parent
bfcdee4a53
commit
d9931e3d2c
75 changed files with 728 additions and 726 deletions
|
@ -68,7 +68,7 @@ import com.keylesspalace.tusky.components.drafts.DraftsActivity
|
|||
import com.keylesspalace.tusky.components.login.LoginActivity
|
||||
import com.keylesspalace.tusky.components.notifications.NotificationHelper
|
||||
import com.keylesspalace.tusky.components.preference.PreferencesActivity
|
||||
import com.keylesspalace.tusky.components.scheduled.ScheduledTootActivity
|
||||
import com.keylesspalace.tusky.components.scheduled.ScheduledStatusActivity
|
||||
import com.keylesspalace.tusky.components.search.SearchActivity
|
||||
import com.keylesspalace.tusky.databinding.ActivityMainBinding
|
||||
import com.keylesspalace.tusky.db.AccountEntity
|
||||
|
@ -460,10 +460,10 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
|
|||
}
|
||||
},
|
||||
primaryDrawerItem {
|
||||
nameRes = R.string.action_access_scheduled_toot
|
||||
nameRes = R.string.action_access_scheduled_posts
|
||||
iconRes = R.drawable.ic_access_time
|
||||
onClick = {
|
||||
startActivityWithSlideInAnimation(ScheduledTootActivity.newIntent(context))
|
||||
startActivityWithSlideInAnimation(ScheduledStatusActivity.newIntent(context))
|
||||
}
|
||||
},
|
||||
primaryDrawerItem {
|
||||
|
|
|
@ -201,9 +201,9 @@ class ComposeActivity :
|
|||
|
||||
viewModel.setup(composeOptions)
|
||||
setupReplyViews(composeOptions?.replyingStatusAuthor, composeOptions?.replyingStatusContent)
|
||||
val tootText = composeOptions?.tootText
|
||||
if (!tootText.isNullOrEmpty()) {
|
||||
binding.composeEditField.setText(tootText)
|
||||
val statusContent = composeOptions?.content
|
||||
if (!statusContent.isNullOrEmpty()) {
|
||||
binding.composeEditField.setText(statusContent)
|
||||
}
|
||||
|
||||
if (!composeOptions?.scheduledAt.isNullOrEmpty()) {
|
||||
|
@ -1022,7 +1022,7 @@ class ComposeActivity :
|
|||
// Let's keep fields var until all consumers are Kotlin
|
||||
var scheduledTootId: String? = null,
|
||||
var draftId: Int? = null,
|
||||
var tootText: String? = null,
|
||||
var content: String? = null,
|
||||
var mediaUrls: List<String>? = null,
|
||||
var mediaDescriptions: List<String>? = null,
|
||||
var mentionedUsernames: Set<String>? = null,
|
||||
|
|
|
@ -34,7 +34,7 @@ import com.keylesspalace.tusky.entity.NewPoll
|
|||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.service.ServiceClient
|
||||
import com.keylesspalace.tusky.service.TootToSend
|
||||
import com.keylesspalace.tusky.service.StatusToSend
|
||||
import com.keylesspalace.tusky.util.Either
|
||||
import com.keylesspalace.tusky.util.RxAwareViewModel
|
||||
import com.keylesspalace.tusky.util.VersionUtils
|
||||
|
@ -308,7 +308,7 @@ class ComposeViewModel @Inject constructor(
|
|||
mediaDescriptions.add(item.description ?: "")
|
||||
}
|
||||
|
||||
val tootToSend = TootToSend(
|
||||
val tootToSend = StatusToSend(
|
||||
text = content,
|
||||
warningText = spoilerText,
|
||||
visibility = statusVisibility.value!!.serverString(),
|
||||
|
@ -456,7 +456,7 @@ class ComposeViewModel @Inject constructor(
|
|||
|
||||
draftId = composeOptions?.draftId ?: 0
|
||||
scheduledTootId = composeOptions?.scheduledTootId
|
||||
startingText = composeOptions?.tootText
|
||||
startingText = composeOptions?.content
|
||||
|
||||
val tootVisibility = composeOptions?.visibility ?: Status.Visibility.UNKNOWN
|
||||
if (tootVisibility.num != Status.Visibility.UNKNOWN.num) {
|
||||
|
|
|
@ -90,14 +90,14 @@ class DraftsActivity : BaseActivity(), DraftActionListener {
|
|||
|
||||
if (draft.inReplyToId != null) {
|
||||
bottomSheet.state = BottomSheetBehavior.STATE_COLLAPSED
|
||||
viewModel.getToot(draft.inReplyToId)
|
||||
viewModel.getStatus(draft.inReplyToId)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.autoDispose(from(this))
|
||||
.subscribe(
|
||||
{ status ->
|
||||
val composeOptions = ComposeActivity.ComposeOptions(
|
||||
draftId = draft.id,
|
||||
tootText = draft.content,
|
||||
content = draft.content,
|
||||
contentWarning = draft.contentWarning,
|
||||
inReplyToId = draft.inReplyToId,
|
||||
replyingStatusContent = status.content.toString(),
|
||||
|
@ -121,7 +121,7 @@ class DraftsActivity : BaseActivity(), DraftActionListener {
|
|||
if (throwable is HttpException && throwable.code() == 404) {
|
||||
// the original status to which a reply was drafted has been deleted
|
||||
// let's open the ComposeActivity without reply information
|
||||
Toast.makeText(this, getString(R.string.drafts_toot_reply_removed), Toast.LENGTH_LONG).show()
|
||||
Toast.makeText(this, getString(R.string.drafts_post_reply_removed), Toast.LENGTH_LONG).show()
|
||||
openDraftWithoutReply(draft)
|
||||
} else {
|
||||
Snackbar.make(binding.root, getString(R.string.drafts_failed_loading_reply), Snackbar.LENGTH_SHORT)
|
||||
|
@ -137,7 +137,7 @@ class DraftsActivity : BaseActivity(), DraftActionListener {
|
|||
private fun openDraftWithoutReply(draft: DraftEntity) {
|
||||
val composeOptions = ComposeActivity.ComposeOptions(
|
||||
draftId = draft.id,
|
||||
tootText = draft.content,
|
||||
content = draft.content,
|
||||
contentWarning = draft.contentWarning,
|
||||
draftAttachments = draft.attachments,
|
||||
poll = draft.poll,
|
||||
|
|
|
@ -60,8 +60,8 @@ class DraftsViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun getToot(tootId: String): Single<Status> {
|
||||
return api.status(tootId)
|
||||
fun getStatus(statusId: String): Single<Status> {
|
||||
return api.status(statusId)
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
|
|
|
@ -29,7 +29,7 @@ import com.keylesspalace.tusky.R
|
|||
import com.keylesspalace.tusky.appstore.EventHub
|
||||
import com.keylesspalace.tusky.appstore.StatusScheduledEvent
|
||||
import com.keylesspalace.tusky.components.compose.ComposeActivity
|
||||
import com.keylesspalace.tusky.databinding.ActivityScheduledTootBinding
|
||||
import com.keylesspalace.tusky.databinding.ActivityScheduledStatusBinding
|
||||
import com.keylesspalace.tusky.di.Injectable
|
||||
import com.keylesspalace.tusky.di.ViewModelFactory
|
||||
import com.keylesspalace.tusky.entity.ScheduledStatus
|
||||
|
@ -40,7 +40,7 @@ import kotlinx.coroutines.flow.collectLatest
|
|||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class ScheduledTootActivity : BaseActivity(), ScheduledTootActionListener, Injectable {
|
||||
class ScheduledStatusActivity : BaseActivity(), ScheduledStatusActionListener, Injectable {
|
||||
|
||||
@Inject
|
||||
lateinit var viewModelFactory: ViewModelFactory
|
||||
|
@ -48,19 +48,19 @@ class ScheduledTootActivity : BaseActivity(), ScheduledTootActionListener, Injec
|
|||
@Inject
|
||||
lateinit var eventHub: EventHub
|
||||
|
||||
private val viewModel: ScheduledTootViewModel by viewModels { viewModelFactory }
|
||||
private val viewModel: ScheduledStatusViewModel by viewModels { viewModelFactory }
|
||||
|
||||
private val adapter = ScheduledTootAdapter(this)
|
||||
private val adapter = ScheduledStatusAdapter(this)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val binding = ActivityScheduledTootBinding.inflate(layoutInflater)
|
||||
val binding = ActivityScheduledStatusBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
setSupportActionBar(binding.includedToolbar.toolbar)
|
||||
supportActionBar?.run {
|
||||
title = getString(R.string.title_scheduled_toot)
|
||||
title = getString(R.string.title_scheduled_posts)
|
||||
setDisplayHomeAsUpEnabled(true)
|
||||
setDisplayShowHomeEnabled(true)
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ class ScheduledTootActivity : BaseActivity(), ScheduledTootActionListener, Injec
|
|||
this,
|
||||
ComposeActivity.ComposeOptions(
|
||||
scheduledTootId = item.id,
|
||||
tootText = item.params.text,
|
||||
content = item.params.text,
|
||||
contentWarning = item.params.spoilerText,
|
||||
mediaAttachments = item.mediaAttachments,
|
||||
inReplyToId = item.params.inReplyToId,
|
||||
|
@ -138,6 +138,6 @@ class ScheduledTootActivity : BaseActivity(), ScheduledTootActionListener, Injec
|
|||
}
|
||||
|
||||
companion object {
|
||||
fun newIntent(context: Context) = Intent(context, ScheduledTootActivity::class.java)
|
||||
fun newIntent(context: Context) = Intent(context, ScheduledStatusActivity::class.java)
|
||||
}
|
||||
}
|
|
@ -20,18 +20,18 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import androidx.paging.PagingDataAdapter
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import com.keylesspalace.tusky.databinding.ItemScheduledTootBinding
|
||||
import com.keylesspalace.tusky.databinding.ItemScheduledStatusBinding
|
||||
import com.keylesspalace.tusky.entity.ScheduledStatus
|
||||
import com.keylesspalace.tusky.util.BindingHolder
|
||||
|
||||
interface ScheduledTootActionListener {
|
||||
interface ScheduledStatusActionListener {
|
||||
fun edit(item: ScheduledStatus)
|
||||
fun delete(item: ScheduledStatus)
|
||||
}
|
||||
|
||||
class ScheduledTootAdapter(
|
||||
val listener: ScheduledTootActionListener
|
||||
) : PagingDataAdapter<ScheduledStatus, BindingHolder<ItemScheduledTootBinding>>(
|
||||
class ScheduledStatusAdapter(
|
||||
val listener: ScheduledStatusActionListener
|
||||
) : PagingDataAdapter<ScheduledStatus, BindingHolder<ItemScheduledStatusBinding>>(
|
||||
object : DiffUtil.ItemCallback<ScheduledStatus>() {
|
||||
override fun areItemsTheSame(oldItem: ScheduledStatus, newItem: ScheduledStatus): Boolean {
|
||||
return oldItem.id == newItem.id
|
||||
|
@ -43,12 +43,12 @@ class ScheduledTootAdapter(
|
|||
}
|
||||
) {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingHolder<ItemScheduledTootBinding> {
|
||||
val binding = ItemScheduledTootBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingHolder<ItemScheduledStatusBinding> {
|
||||
val binding = ItemScheduledStatusBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||
return BindingHolder(binding)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: BindingHolder<ItemScheduledTootBinding>, position: Int) {
|
||||
override fun onBindViewHolder(holder: BindingHolder<ItemScheduledStatusBinding>, position: Int) {
|
||||
getItem(position)?.let { item ->
|
||||
holder.binding.edit.isEnabled = true
|
||||
holder.binding.delete.isEnabled = true
|
|
@ -22,16 +22,16 @@ import com.keylesspalace.tusky.entity.ScheduledStatus
|
|||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import kotlinx.coroutines.rx3.await
|
||||
|
||||
class ScheduledTootPagingSourceFactory(
|
||||
class ScheduledStatusPagingSourceFactory(
|
||||
private val mastodonApi: MastodonApi
|
||||
) : () -> ScheduledTootPagingSource {
|
||||
) : () -> ScheduledStatusPagingSource {
|
||||
|
||||
private val scheduledTootsCache = mutableListOf<ScheduledStatus>()
|
||||
|
||||
private var pagingSource: ScheduledTootPagingSource? = null
|
||||
private var pagingSource: ScheduledStatusPagingSource? = null
|
||||
|
||||
override fun invoke(): ScheduledTootPagingSource {
|
||||
return ScheduledTootPagingSource(mastodonApi, scheduledTootsCache).also {
|
||||
override fun invoke(): ScheduledStatusPagingSource {
|
||||
return ScheduledStatusPagingSource(mastodonApi, scheduledTootsCache).also {
|
||||
pagingSource = it
|
||||
}
|
||||
}
|
||||
|
@ -42,9 +42,9 @@ class ScheduledTootPagingSourceFactory(
|
|||
}
|
||||
}
|
||||
|
||||
class ScheduledTootPagingSource(
|
||||
class ScheduledStatusPagingSource(
|
||||
private val mastodonApi: MastodonApi,
|
||||
private val scheduledTootsCache: MutableList<ScheduledStatus>
|
||||
private val scheduledStatusesCache: MutableList<ScheduledStatus>
|
||||
) : PagingSource<String, ScheduledStatus>() {
|
||||
|
||||
override fun getRefreshKey(state: PagingState<String, ScheduledStatus>): String? {
|
||||
|
@ -52,11 +52,11 @@ class ScheduledTootPagingSource(
|
|||
}
|
||||
|
||||
override suspend fun load(params: LoadParams<String>): LoadResult<String, ScheduledStatus> {
|
||||
return if (params is LoadParams.Refresh && scheduledTootsCache.isNotEmpty()) {
|
||||
return if (params is LoadParams.Refresh && scheduledStatusesCache.isNotEmpty()) {
|
||||
LoadResult.Page(
|
||||
data = scheduledTootsCache,
|
||||
data = scheduledStatusesCache,
|
||||
prevKey = null,
|
||||
nextKey = scheduledTootsCache.lastOrNull()?.id
|
||||
nextKey = scheduledStatusesCache.lastOrNull()?.id
|
||||
)
|
||||
} else {
|
||||
try {
|
||||
|
@ -71,7 +71,7 @@ class ScheduledTootPagingSource(
|
|||
nextKey = result.lastOrNull()?.id
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.w("ScheduledTootPgngSrc", "Error loading scheduled statuses", e)
|
||||
Log.w("ScheduledStatuses", "Error loading scheduled statuses", e)
|
||||
LoadResult.Error(e)
|
||||
}
|
||||
}
|
|
@ -28,12 +28,12 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.rx3.await
|
||||
import javax.inject.Inject
|
||||
|
||||
class ScheduledTootViewModel @Inject constructor(
|
||||
class ScheduledStatusViewModel @Inject constructor(
|
||||
val mastodonApi: MastodonApi,
|
||||
val eventHub: EventHub
|
||||
) : ViewModel() {
|
||||
|
||||
private val pagingSourceFactory = ScheduledTootPagingSourceFactory(mastodonApi)
|
||||
private val pagingSourceFactory = ScheduledStatusPagingSourceFactory(mastodonApi)
|
||||
|
||||
val data = Pager(
|
||||
config = PagingConfig(pageSize = 20, initialLoadSize = 20),
|
|
@ -424,7 +424,7 @@ class SearchStatusesFragment : SearchFragment<StatusViewData.Concrete>(), Status
|
|||
private fun showConfirmDeleteDialog(id: String, position: Int) {
|
||||
context?.let {
|
||||
AlertDialog.Builder(it)
|
||||
.setMessage(R.string.dialog_delete_toot_warning)
|
||||
.setMessage(R.string.dialog_delete_post_warning)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
viewModel.deleteStatus(id)
|
||||
removeItem(position)
|
||||
|
@ -437,7 +437,7 @@ class SearchStatusesFragment : SearchFragment<StatusViewData.Concrete>(), Status
|
|||
private fun showConfirmEditDialog(id: String, position: Int, status: Status) {
|
||||
activity?.let {
|
||||
AlertDialog.Builder(it)
|
||||
.setMessage(R.string.dialog_redraft_toot_warning)
|
||||
.setMessage(R.string.dialog_redraft_post_warning)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
viewModel.deleteStatus(id)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
|
@ -455,7 +455,7 @@ class SearchStatusesFragment : SearchFragment<StatusViewData.Concrete>(), Status
|
|||
val intent = ComposeActivity.startIntent(
|
||||
requireContext(),
|
||||
ComposeOptions(
|
||||
tootText = redraftStatus.text ?: "",
|
||||
content = redraftStatus.text ?: "",
|
||||
inReplyToId = redraftStatus.inReplyToId,
|
||||
visibility = redraftStatus.visibility,
|
||||
contentWarning = redraftStatus.spoilerText,
|
||||
|
|
|
@ -36,7 +36,7 @@ import com.keylesspalace.tusky.components.login.LoginActivity
|
|||
import com.keylesspalace.tusky.components.login.LoginWebViewActivity
|
||||
import com.keylesspalace.tusky.components.preference.PreferencesActivity
|
||||
import com.keylesspalace.tusky.components.report.ReportActivity
|
||||
import com.keylesspalace.tusky.components.scheduled.ScheduledTootActivity
|
||||
import com.keylesspalace.tusky.components.scheduled.ScheduledStatusActivity
|
||||
import com.keylesspalace.tusky.components.search.SearchActivity
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
|
@ -109,7 +109,7 @@ abstract class ActivitiesModule {
|
|||
abstract fun contributesInstanceListActivity(): InstanceListActivity
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesScheduledTootActivity(): ScheduledTootActivity
|
||||
abstract fun contributesScheduledStatusActivity(): ScheduledStatusActivity
|
||||
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesAnnouncementsActivity(): AnnouncementsActivity
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
|
||||
package com.keylesspalace.tusky.di
|
||||
|
||||
import com.keylesspalace.tusky.service.SendTootService
|
||||
import com.keylesspalace.tusky.service.SendStatusService
|
||||
import dagger.Module
|
||||
import dagger.android.ContributesAndroidInjector
|
||||
|
||||
@Module
|
||||
abstract class ServicesModule {
|
||||
@ContributesAndroidInjector
|
||||
abstract fun contributesSendTootService(): SendTootService
|
||||
abstract fun contributesSendStatusService(): SendStatusService
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import com.keylesspalace.tusky.components.compose.ComposeViewModel
|
|||
import com.keylesspalace.tusky.components.conversation.ConversationsViewModel
|
||||
import com.keylesspalace.tusky.components.drafts.DraftsViewModel
|
||||
import com.keylesspalace.tusky.components.report.ReportViewModel
|
||||
import com.keylesspalace.tusky.components.scheduled.ScheduledTootViewModel
|
||||
import com.keylesspalace.tusky.components.scheduled.ScheduledStatusViewModel
|
||||
import com.keylesspalace.tusky.components.search.SearchViewModel
|
||||
import com.keylesspalace.tusky.components.timeline.viewmodel.CachedTimelineViewModel
|
||||
import com.keylesspalace.tusky.components.timeline.viewmodel.NetworkTimelineViewModel
|
||||
|
@ -85,8 +85,8 @@ abstract class ViewModelModule {
|
|||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ViewModelKey(ScheduledTootViewModel::class)
|
||||
internal abstract fun scheduledTootViewModel(viewModel: ScheduledTootViewModel): ViewModel
|
||||
@ViewModelKey(ScheduledStatusViewModel::class)
|
||||
internal abstract fun scheduledStatusViewModel(viewModel: ScheduledStatusViewModel): ViewModel
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
|
|
|
@ -380,7 +380,7 @@ public abstract class SFragment extends Fragment implements Injectable {
|
|||
|
||||
protected void showConfirmDeleteDialog(final String id, final int position) {
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setMessage(R.string.dialog_delete_toot_warning)
|
||||
.setMessage(R.string.dialog_delete_post_warning)
|
||||
.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
|
||||
timelineCases.delete(id)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
|
@ -403,7 +403,7 @@ public abstract class SFragment extends Fragment implements Injectable {
|
|||
return;
|
||||
}
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setMessage(R.string.dialog_redraft_toot_warning)
|
||||
.setMessage(R.string.dialog_redraft_post_warning)
|
||||
.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
|
||||
timelineCases.delete(id)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
|
@ -415,7 +415,7 @@ public abstract class SFragment extends Fragment implements Injectable {
|
|||
deletedStatus = status.toDeletedStatus();
|
||||
}
|
||||
ComposeOptions composeOptions = new ComposeOptions();
|
||||
composeOptions.setTootText(deletedStatus.getText());
|
||||
composeOptions.setContent(deletedStatus.getText());
|
||||
composeOptions.setInReplyToId(deletedStatus.getInReplyToId());
|
||||
composeOptions.setVisibility(deletedStatus.getVisibility());
|
||||
composeOptions.setContentWarning(deletedStatus.getSpoilerText());
|
||||
|
|
|
@ -29,8 +29,8 @@ import com.keylesspalace.tusky.R
|
|||
import com.keylesspalace.tusky.components.notifications.NotificationHelper
|
||||
import com.keylesspalace.tusky.db.AccountManager
|
||||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.service.SendTootService
|
||||
import com.keylesspalace.tusky.service.TootToSend
|
||||
import com.keylesspalace.tusky.service.SendStatusService
|
||||
import com.keylesspalace.tusky.service.StatusToSend
|
||||
import com.keylesspalace.tusky.util.randomAlphanumericString
|
||||
import dagger.android.AndroidInjection
|
||||
import javax.inject.Inject
|
||||
|
@ -82,9 +82,9 @@ class SendStatusBroadcastReceiver : BroadcastReceiver() {
|
|||
} else {
|
||||
val text = mentions.joinToString(" ", postfix = " ") { "@$it" } + message.toString()
|
||||
|
||||
val sendIntent = SendTootService.sendTootIntent(
|
||||
val sendIntent = SendStatusService.sendStatusIntent(
|
||||
context,
|
||||
TootToSend(
|
||||
StatusToSend(
|
||||
text = text,
|
||||
warningText = spoiler,
|
||||
visibility = visibility.serverString(),
|
||||
|
|
|
@ -41,7 +41,7 @@ import java.util.concurrent.ConcurrentHashMap
|
|||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
|
||||
class SendTootService : Service(), Injectable {
|
||||
class SendStatusService : Service(), Injectable {
|
||||
|
||||
@Inject
|
||||
lateinit var mastodonApi: MastodonApi
|
||||
|
@ -55,7 +55,7 @@ class SendTootService : Service(), Injectable {
|
|||
private val supervisorJob = SupervisorJob()
|
||||
private val serviceScope = CoroutineScope(Dispatchers.Main + supervisorJob)
|
||||
|
||||
private val tootsToSend = ConcurrentHashMap<Int, TootToSend>()
|
||||
private val statusesToSend = ConcurrentHashMap<Int, StatusToSend>()
|
||||
private val sendCalls = ConcurrentHashMap<Int, Call<Status>>()
|
||||
|
||||
private val timer = Timer()
|
||||
|
@ -73,38 +73,38 @@ class SendTootService : Service(), Injectable {
|
|||
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
|
||||
if (intent.hasExtra(KEY_TOOT)) {
|
||||
val tootToSend = intent.getParcelableExtra<TootToSend>(KEY_TOOT)
|
||||
?: throw IllegalStateException("SendTootService started without $KEY_TOOT extra")
|
||||
if (intent.hasExtra(KEY_STATUS)) {
|
||||
val statusToSend = intent.getParcelableExtra<StatusToSend>(KEY_STATUS)
|
||||
?: throw IllegalStateException("SendStatusService started without $KEY_STATUS extra")
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel = NotificationChannel(CHANNEL_ID, getString(R.string.send_toot_notification_channel_name), NotificationManager.IMPORTANCE_LOW)
|
||||
val channel = NotificationChannel(CHANNEL_ID, getString(R.string.send_post_notification_channel_name), NotificationManager.IMPORTANCE_LOW)
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
|
||||
var notificationText = tootToSend.warningText
|
||||
var notificationText = statusToSend.warningText
|
||||
if (notificationText.isBlank()) {
|
||||
notificationText = tootToSend.text
|
||||
notificationText = statusToSend.text
|
||||
}
|
||||
|
||||
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_notify)
|
||||
.setContentTitle(getString(R.string.send_toot_notification_title))
|
||||
.setContentTitle(getString(R.string.send_post_notification_title))
|
||||
.setContentText(notificationText)
|
||||
.setProgress(1, 0, true)
|
||||
.setOngoing(true)
|
||||
.setColor(ContextCompat.getColor(this, R.color.notification_color))
|
||||
.addAction(0, getString(android.R.string.cancel), cancelSendingIntent(sendingNotificationId))
|
||||
|
||||
if (tootsToSend.size == 0 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (statusesToSend.size == 0 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_DETACH)
|
||||
startForeground(sendingNotificationId, builder.build())
|
||||
} else {
|
||||
notificationManager.notify(sendingNotificationId, builder.build())
|
||||
}
|
||||
|
||||
tootsToSend[sendingNotificationId] = tootToSend
|
||||
sendToot(sendingNotificationId--)
|
||||
statusesToSend[sendingNotificationId] = statusToSend
|
||||
sendStatus(sendingNotificationId--)
|
||||
} else {
|
||||
|
||||
if (intent.hasExtra(KEY_CANCEL)) {
|
||||
|
@ -115,54 +115,54 @@ class SendTootService : Service(), Injectable {
|
|||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
private fun sendToot(tootId: Int) {
|
||||
private fun sendStatus(statusId: Int) {
|
||||
|
||||
// when tootToSend == null, sending has been canceled
|
||||
val tootToSend = tootsToSend[tootId] ?: return
|
||||
// when statusToSend == null, sending has been canceled
|
||||
val statusToSend = statusesToSend[statusId] ?: return
|
||||
|
||||
// when account == null, user has logged out, cancel sending
|
||||
val account = accountManager.getAccountById(tootToSend.accountId)
|
||||
val account = accountManager.getAccountById(statusToSend.accountId)
|
||||
|
||||
if (account == null) {
|
||||
tootsToSend.remove(tootId)
|
||||
notificationManager.cancel(tootId)
|
||||
statusesToSend.remove(statusId)
|
||||
notificationManager.cancel(statusId)
|
||||
stopSelfWhenDone()
|
||||
return
|
||||
}
|
||||
|
||||
tootToSend.retries++
|
||||
statusToSend.retries++
|
||||
|
||||
val newStatus = NewStatus(
|
||||
tootToSend.text,
|
||||
tootToSend.warningText,
|
||||
tootToSend.inReplyToId,
|
||||
tootToSend.visibility,
|
||||
tootToSend.sensitive,
|
||||
tootToSend.mediaIds,
|
||||
tootToSend.scheduledAt,
|
||||
tootToSend.poll
|
||||
statusToSend.text,
|
||||
statusToSend.warningText,
|
||||
statusToSend.inReplyToId,
|
||||
statusToSend.visibility,
|
||||
statusToSend.sensitive,
|
||||
statusToSend.mediaIds,
|
||||
statusToSend.scheduledAt,
|
||||
statusToSend.poll
|
||||
)
|
||||
|
||||
val sendCall = mastodonApi.createStatus(
|
||||
"Bearer " + account.accessToken,
|
||||
account.domain,
|
||||
tootToSend.idempotencyKey,
|
||||
statusToSend.idempotencyKey,
|
||||
newStatus
|
||||
)
|
||||
|
||||
sendCalls[tootId] = sendCall
|
||||
sendCalls[statusId] = sendCall
|
||||
|
||||
val callback = object : Callback<Status> {
|
||||
override fun onResponse(call: Call<Status>, response: Response<Status>) {
|
||||
|
||||
val scheduled = !tootToSend.scheduledAt.isNullOrEmpty()
|
||||
tootsToSend.remove(tootId)
|
||||
val scheduled = !statusToSend.scheduledAt.isNullOrEmpty()
|
||||
statusesToSend.remove(statusId)
|
||||
|
||||
if (response.isSuccessful) {
|
||||
// If the status was loaded from a draft, delete the draft and associated media files.
|
||||
if (tootToSend.draftId != 0) {
|
||||
if (statusToSend.draftId != 0) {
|
||||
serviceScope.launch {
|
||||
draftHelper.deleteDraftAndAttachments(tootToSend.draftId)
|
||||
draftHelper.deleteDraftAndAttachments(statusToSend.draftId)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,18 +172,18 @@ class SendTootService : Service(), Injectable {
|
|||
response.body()?.let(::StatusComposedEvent)?.let(eventHub::dispatch)
|
||||
}
|
||||
|
||||
notificationManager.cancel(tootId)
|
||||
notificationManager.cancel(statusId)
|
||||
} else {
|
||||
// the server refused to accept the toot, save toot & show error message
|
||||
saveTootToDrafts(tootToSend)
|
||||
// the server refused to accept the status, save status & show error message
|
||||
saveStatusToDrafts(statusToSend)
|
||||
|
||||
val builder = NotificationCompat.Builder(this@SendTootService, CHANNEL_ID)
|
||||
val builder = NotificationCompat.Builder(this@SendStatusService, CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_notify)
|
||||
.setContentTitle(getString(R.string.send_toot_notification_error_title))
|
||||
.setContentText(getString(R.string.send_toot_notification_saved_content))
|
||||
.setColor(ContextCompat.getColor(this@SendTootService, R.color.notification_color))
|
||||
.setContentTitle(getString(R.string.send_post_notification_error_title))
|
||||
.setContentText(getString(R.string.send_post_notification_saved_content))
|
||||
.setColor(ContextCompat.getColor(this@SendStatusService, R.color.notification_color))
|
||||
|
||||
notificationManager.cancel(tootId)
|
||||
notificationManager.cancel(statusId)
|
||||
notificationManager.notify(errorNotificationId--, builder.build())
|
||||
}
|
||||
|
||||
|
@ -191,7 +191,7 @@ class SendTootService : Service(), Injectable {
|
|||
}
|
||||
|
||||
override fun onFailure(call: Call<Status>, t: Throwable) {
|
||||
var backoff = TimeUnit.SECONDS.toMillis(tootToSend.retries.toLong())
|
||||
var backoff = TimeUnit.SECONDS.toMillis(statusToSend.retries.toLong())
|
||||
if (backoff > MAX_RETRY_INTERVAL) {
|
||||
backoff = MAX_RETRY_INTERVAL
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ class SendTootService : Service(), Injectable {
|
|||
timer.schedule(
|
||||
object : TimerTask() {
|
||||
override fun run() {
|
||||
sendToot(tootId)
|
||||
sendStatus(statusId)
|
||||
}
|
||||
},
|
||||
backoff
|
||||
|
@ -212,32 +212,32 @@ class SendTootService : Service(), Injectable {
|
|||
|
||||
private fun stopSelfWhenDone() {
|
||||
|
||||
if (tootsToSend.isEmpty()) {
|
||||
ServiceCompat.stopForeground(this@SendTootService, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
||||
if (statusesToSend.isEmpty()) {
|
||||
ServiceCompat.stopForeground(this@SendStatusService, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
||||
stopSelf()
|
||||
}
|
||||
}
|
||||
|
||||
private fun cancelSending(tootId: Int) {
|
||||
val tootToCancel = tootsToSend.remove(tootId)
|
||||
if (tootToCancel != null) {
|
||||
val sendCall = sendCalls.remove(tootId)
|
||||
private fun cancelSending(statusId: Int) {
|
||||
val statusToCancel = statusesToSend.remove(statusId)
|
||||
if (statusToCancel != null) {
|
||||
val sendCall = sendCalls.remove(statusId)
|
||||
sendCall?.cancel()
|
||||
|
||||
saveTootToDrafts(tootToCancel)
|
||||
saveStatusToDrafts(statusToCancel)
|
||||
|
||||
val builder = NotificationCompat.Builder(this@SendTootService, CHANNEL_ID)
|
||||
val builder = NotificationCompat.Builder(this@SendStatusService, CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_notify)
|
||||
.setContentTitle(getString(R.string.send_toot_notification_cancel_title))
|
||||
.setContentText(getString(R.string.send_toot_notification_saved_content))
|
||||
.setContentTitle(getString(R.string.send_post_notification_cancel_title))
|
||||
.setContentText(getString(R.string.send_post_notification_saved_content))
|
||||
.setColor(ContextCompat.getColor(this, R.color.notification_color))
|
||||
|
||||
notificationManager.notify(tootId, builder.build())
|
||||
notificationManager.notify(statusId, builder.build())
|
||||
|
||||
timer.schedule(
|
||||
object : TimerTask() {
|
||||
override fun run() {
|
||||
notificationManager.cancel(tootId)
|
||||
notificationManager.cancel(statusId)
|
||||
stopSelfWhenDone()
|
||||
}
|
||||
},
|
||||
|
@ -246,28 +246,28 @@ class SendTootService : Service(), Injectable {
|
|||
}
|
||||
}
|
||||
|
||||
private fun saveTootToDrafts(toot: TootToSend) {
|
||||
private fun saveStatusToDrafts(status: StatusToSend) {
|
||||
serviceScope.launch {
|
||||
draftHelper.saveDraft(
|
||||
draftId = toot.draftId,
|
||||
accountId = toot.accountId,
|
||||
inReplyToId = toot.inReplyToId,
|
||||
content = toot.text,
|
||||
contentWarning = toot.warningText,
|
||||
sensitive = toot.sensitive,
|
||||
visibility = Status.Visibility.byString(toot.visibility),
|
||||
mediaUris = toot.mediaUris,
|
||||
mediaDescriptions = toot.mediaDescriptions,
|
||||
poll = toot.poll,
|
||||
draftId = status.draftId,
|
||||
accountId = status.accountId,
|
||||
inReplyToId = status.inReplyToId,
|
||||
content = status.text,
|
||||
contentWarning = status.warningText,
|
||||
sensitive = status.sensitive,
|
||||
visibility = Status.Visibility.byString(status.visibility),
|
||||
mediaUris = status.mediaUris,
|
||||
mediaDescriptions = status.mediaDescriptions,
|
||||
poll = status.poll,
|
||||
failedToSend = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun cancelSendingIntent(tootId: Int): PendingIntent {
|
||||
val intent = Intent(this, SendTootService::class.java)
|
||||
intent.putExtra(KEY_CANCEL, tootId)
|
||||
return PendingIntent.getService(this, tootId, intent, NotificationHelper.pendingIntentFlags(false))
|
||||
private fun cancelSendingIntent(statusId: Int): PendingIntent {
|
||||
val intent = Intent(this, SendStatusService::class.java)
|
||||
intent.putExtra(KEY_CANCEL, statusId)
|
||||
return PendingIntent.getService(this, statusId, intent, NotificationHelper.pendingIntentFlags(false))
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
@ -277,7 +277,7 @@ class SendTootService : Service(), Injectable {
|
|||
|
||||
companion object {
|
||||
|
||||
private const val KEY_TOOT = "toot"
|
||||
private const val KEY_STATUS = "status"
|
||||
private const val KEY_CANCEL = "cancel_id"
|
||||
private const val CHANNEL_ID = "send_toots"
|
||||
|
||||
|
@ -287,21 +287,21 @@ class SendTootService : Service(), Injectable {
|
|||
private var errorNotificationId = Int.MIN_VALUE // use even more negative ids to not clash with other notis
|
||||
|
||||
@JvmStatic
|
||||
fun sendTootIntent(
|
||||
fun sendStatusIntent(
|
||||
context: Context,
|
||||
tootToSend: TootToSend
|
||||
statusToSend: StatusToSend
|
||||
): Intent {
|
||||
val intent = Intent(context, SendTootService::class.java)
|
||||
intent.putExtra(KEY_TOOT, tootToSend)
|
||||
val intent = Intent(context, SendStatusService::class.java)
|
||||
intent.putExtra(KEY_STATUS, statusToSend)
|
||||
|
||||
if (tootToSend.mediaUris.isNotEmpty()) {
|
||||
if (statusToSend.mediaUris.isNotEmpty()) {
|
||||
// forward uri permissions
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
val uriClip = ClipData(
|
||||
ClipDescription("Toot Media", arrayOf("image/*", "video/*")),
|
||||
ClipData.Item(tootToSend.mediaUris[0])
|
||||
ClipDescription("Status Media", arrayOf("image/*", "video/*")),
|
||||
ClipData.Item(statusToSend.mediaUris[0])
|
||||
)
|
||||
tootToSend.mediaUris
|
||||
statusToSend.mediaUris
|
||||
.drop(1)
|
||||
.forEach { mediaUri ->
|
||||
uriClip.addItem(ClipData.Item(mediaUri))
|
||||
|
@ -316,7 +316,7 @@ class SendTootService : Service(), Injectable {
|
|||
}
|
||||
|
||||
@Parcelize
|
||||
data class TootToSend(
|
||||
data class StatusToSend(
|
||||
val text: String,
|
||||
val warningText: String,
|
||||
val visibility: String,
|
|
@ -20,8 +20,8 @@ import androidx.core.content.ContextCompat
|
|||
import javax.inject.Inject
|
||||
|
||||
class ServiceClient @Inject constructor(private val context: Context) {
|
||||
fun sendToot(tootToSend: TootToSend) {
|
||||
val intent = SendTootService.sendTootIntent(context, tootToSend)
|
||||
fun sendToot(tootToSend: StatusToSend) {
|
||||
val intent = SendStatusService.sendStatusIntent(context, tootToSend)
|
||||
ContextCompat.startForegroundService(context, intent)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue