diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 07acb061..30b1a796 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -119,6 +119,7 @@
+
@@ -160,4 +161,4 @@
-
\ No newline at end of file
+
diff --git a/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt b/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt
index 36ff17d1..19114295 100644
--- a/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/AccountActivity.kt
@@ -93,6 +93,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
private var avatarSize: Float = 0f
@Px
private var titleVisibleHeight: Int = 0
+ private lateinit var domain: String
private enum class FollowState {
NOT_FOLLOWING,
@@ -601,6 +602,17 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
getString(R.string.action_mute)
}
+ if (loadedAccount != null) {
+ val muteDomain = menu.findItem(R.id.action_mute_domain)
+ domain = LinkHelper.getDomain(loadedAccount?.url)
+ if (domain.isEmpty()) {
+ // If we can't get the domain, there's no way we can mute it anyway...
+ menu.removeItem(R.id.action_mute_domain)
+ } else {
+ muteDomain.title = getString(R.string.action_mute_domain, domain)
+ }
+ }
+
if (followState == FollowState.FOLLOWING) {
val showReblogs = menu.findItem(R.id.action_show_reblogs)
showReblogs.title = if (showingReblogs) {
@@ -618,6 +630,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
menu.removeItem(R.id.action_follow)
menu.removeItem(R.id.action_block)
menu.removeItem(R.id.action_mute)
+ menu.removeItem(R.id.action_mute_domain)
menu.removeItem(R.id.action_show_reblogs)
}
@@ -640,6 +653,14 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
.show()
}
+ private fun showMuteDomainWarningDialog(instance: String) {
+ AlertDialog.Builder(this)
+ .setMessage(getString(R.string.mute_domain_warning, instance))
+ .setPositiveButton(getString(R.string.mute_domain_warning_dialog_ok)) { _, _ -> viewModel.muteDomain(instance) }
+ .setNegativeButton(android.R.string.cancel, null)
+ .show()
+ }
+
private fun mention() {
loadedAccount?.let {
val intent = ComposeActivity.IntentBuilder()
@@ -694,7 +715,10 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidI
viewModel.changeMuteState()
return true
}
-
+ R.id.action_mute_domain -> {
+ showMuteDomainWarningDialog(domain)
+ return true
+ }
R.id.action_show_reblogs -> {
viewModel.changeShowReblogsState()
return true
diff --git a/app/src/main/java/com/keylesspalace/tusky/appstore/Events.kt b/app/src/main/java/com/keylesspalace/tusky/appstore/Events.kt
index ecec9412..d7d92d49 100644
--- a/app/src/main/java/com/keylesspalace/tusky/appstore/Events.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/appstore/Events.kt
@@ -15,4 +15,5 @@ data class StatusComposedEvent(val status: Status) : Dispatchable
data class ProfileEditedEvent(val newProfileData: Account) : Dispatchable
data class PreferenceChangedEvent(val preferenceKey: String) : Dispatchable
data class MainTabsChangedEvent(val newTabs: List) : Dispatchable
-data class PollVoteEvent(val statusId: String, val poll: Poll) : Dispatchable
\ No newline at end of file
+data class PollVoteEvent(val statusId: String, val poll: Poll) : Dispatchable
+data class DomainMuteEvent(val instance: String): Dispatchable
\ No newline at end of file
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/instancemute/InstanceListActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/instancemute/InstanceListActivity.kt
new file mode 100644
index 00000000..7aa39bef
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/components/instancemute/InstanceListActivity.kt
@@ -0,0 +1,50 @@
+package com.keylesspalace.tusky.components.instancemute
+
+import android.os.Bundle
+import android.view.MenuItem
+import androidx.fragment.app.Fragment
+import com.keylesspalace.tusky.BaseActivity
+import com.keylesspalace.tusky.R
+import com.keylesspalace.tusky.components.instancemute.fragment.InstanceListFragment
+import dagger.android.AndroidInjector
+import dagger.android.DispatchingAndroidInjector
+import dagger.android.support.HasSupportFragmentInjector
+import javax.inject.Inject
+import kotlinx.android.synthetic.main.toolbar_basic.*
+
+class InstanceListActivity: BaseActivity(), HasSupportFragmentInjector {
+ @Inject
+ lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector
+
+ override fun supportFragmentInjector(): AndroidInjector? {
+ return dispatchingAndroidInjector
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_account_list)
+
+ setSupportActionBar(toolbar)
+ supportActionBar?.apply {
+ setTitle(R.string.title_domain_mutes)
+ setDisplayHomeAsUpEnabled(true)
+ setDisplayShowHomeEnabled(true)
+ }
+
+ supportFragmentManager
+ .beginTransaction()
+ .replace(R.id.fragment_container, InstanceListFragment())
+ .commit()
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ android.R.id.home -> {
+ onBackPressed()
+ return true
+ }
+ }
+ return super.onOptionsItemSelected(item)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/instancemute/adapter/DomainMutesAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/components/instancemute/adapter/DomainMutesAdapter.kt
new file mode 100644
index 00000000..62ab7ef3
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/components/instancemute/adapter/DomainMutesAdapter.kt
@@ -0,0 +1,57 @@
+package com.keylesspalace.tusky.components.instancemute.adapter
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.keylesspalace.tusky.R
+import com.keylesspalace.tusky.components.instancemute.interfaces.InstanceActionListener
+import kotlinx.android.synthetic.main.item_muted_domain.view.*
+
+class DomainMutesAdapter(private val actionListener: InstanceActionListener): RecyclerView.Adapter() {
+ var instances: MutableList = mutableListOf()
+ var bottomLoading: Boolean = false
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_muted_domain, parent, false), actionListener)
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.setupWithInstance(instances[position])
+ }
+
+ override fun getItemCount(): Int {
+ var count = instances.size
+ if (bottomLoading)
+ ++count
+ return count
+ }
+
+ fun addItems(newInstances: List) {
+ val end = instances.size
+ instances.addAll(newInstances)
+ notifyItemRangeInserted(end, instances.size)
+ }
+
+ fun addItem(instance: String) {
+ instances.add(instance)
+ notifyItemInserted(instances.size)
+ }
+
+ fun removeItem(position: Int)
+ {
+ if (position >= 0 && position < instances.size) {
+ instances.removeAt(position)
+ notifyItemRemoved(position)
+ }
+ }
+
+
+ class ViewHolder(rootView: View, private val actionListener: InstanceActionListener): RecyclerView.ViewHolder(rootView) {
+ fun setupWithInstance(instance: String) {
+ itemView.muted_domain.text = instance
+ itemView.muted_domain_unmute.setOnClickListener {
+ actionListener.mute(false, instance, adapterPosition)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/instancemute/fragment/InstanceListFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/instancemute/fragment/InstanceListFragment.kt
new file mode 100644
index 00000000..575667b6
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/components/instancemute/fragment/InstanceListFragment.kt
@@ -0,0 +1,179 @@
+package com.keylesspalace.tusky.components.instancemute.fragment
+
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.lifecycle.Lifecycle
+import androidx.recyclerview.widget.DividerItemDecoration
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.snackbar.Snackbar
+import com.keylesspalace.tusky.R
+import com.keylesspalace.tusky.components.instancemute.adapter.DomainMutesAdapter
+import com.keylesspalace.tusky.components.instancemute.interfaces.InstanceActionListener
+import com.keylesspalace.tusky.di.Injectable
+import com.keylesspalace.tusky.fragment.BaseFragment
+import com.keylesspalace.tusky.network.MastodonApi
+import com.keylesspalace.tusky.util.HttpHeaderLink
+import com.keylesspalace.tusky.util.hide
+import com.keylesspalace.tusky.util.show
+import com.keylesspalace.tusky.view.EndlessOnScrollListener
+import com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider.from
+import com.uber.autodispose.autoDisposable
+import io.reactivex.android.schedulers.AndroidSchedulers
+import kotlinx.android.synthetic.main.fragment_instance_list.*
+import retrofit2.Call
+import retrofit2.Callback
+import retrofit2.Response
+import java.io.IOException
+import javax.inject.Inject
+
+class InstanceListFragment: BaseFragment(), Injectable, InstanceActionListener {
+ @Inject
+ lateinit var api: MastodonApi
+
+ private var fetching = false
+ private var bottomId: String? = null
+ private var adapter = DomainMutesAdapter(this)
+ private lateinit var scrollListener: EndlessOnScrollListener
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ return inflater.inflate(R.layout.fragment_instance_list, container, false)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ recyclerView.setHasFixedSize(true)
+ recyclerView.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL))
+ recyclerView.adapter = adapter
+
+ val layoutManager = LinearLayoutManager(view.context)
+ recyclerView.layoutManager = layoutManager
+
+ scrollListener = object : EndlessOnScrollListener(layoutManager) {
+ override fun onLoadMore(totalItemsCount: Int, view: RecyclerView) {
+ if (bottomId != null) {
+ fetchInstances(bottomId)
+ }
+ }
+ }
+
+ recyclerView.addOnScrollListener(scrollListener)
+ fetchInstances()
+ }
+
+ override fun mute(mute: Boolean, instance: String, position: Int) {
+ if (mute) {
+ api.blockDomain(instance).enqueue(object: Callback {
+ override fun onFailure(call: Call, t: Throwable) {
+ Log.e(TAG, "Error muting domain $instance")
+ }
+
+ override fun onResponse(call: Call, response: Response) {
+ if (response.isSuccessful) {
+ adapter.addItem(instance)
+ } else {
+ Log.e(TAG, "Error muting domain $instance")
+ }
+ }
+ })
+ } else {
+ api.unblockDomain(instance).enqueue(object: Callback {
+ override fun onFailure(call: Call, t: Throwable) {
+ Log.e(TAG, "Error unmuting domain $instance")
+ }
+
+ override fun onResponse(call: Call, response: Response) {
+ if (response.isSuccessful) {
+ adapter.removeItem(position)
+ Snackbar.make(recyclerView, getString(R.string.confirmation_domain_unmuted, instance), Snackbar.LENGTH_LONG)
+ .setAction(R.string.action_undo) {
+ mute(true, instance, position)
+ }
+ .show()
+ } else {
+ Log.e(TAG, "Error unmuting domain $instance")
+ }
+ }
+ })
+ }
+ }
+
+ private fun fetchInstances(id: String? = null) {
+ if (fetching) {
+ return
+ }
+ fetching = true
+ instanceProgressBar.show()
+
+ if (id != null) {
+ recyclerView.post { adapter.bottomLoading = true }
+ }
+
+ api.domainBlocks(id, bottomId, null)
+ .observeOn(AndroidSchedulers.mainThread())
+ .autoDisposable(from(this, Lifecycle.Event.ON_DESTROY))
+ .subscribe({ response ->
+ val instances = response.body()
+
+ if (response.isSuccessful && instances != null) {
+ onFetchInstancesSuccess(instances, response.headers().get("Link"))
+ } else {
+ onFetchInstancesFailure(Exception(response.message()))
+ }
+ }, {throwable ->
+ onFetchInstancesFailure(throwable)
+ })
+ }
+
+ private fun onFetchInstancesSuccess(instances: List, linkHeader: String?) {
+ adapter.bottomLoading = false
+ instanceProgressBar.hide()
+
+ val links = HttpHeaderLink.parse(linkHeader)
+ val next = HttpHeaderLink.findByRelationType(links, "next")
+ val fromId = next?.uri?.getQueryParameter("max_id")
+ adapter.addItems(instances)
+ bottomId = fromId
+ fetching = false
+
+ if (adapter.itemCount == 0) {
+ messageView.show()
+ messageView.setup(
+ R.drawable.elephant_friend_empty,
+ R.string.message_empty,
+ null
+ )
+ } else {
+ messageView.hide()
+ }
+ }
+
+ private fun onFetchInstancesFailure(throwable: Throwable) {
+ fetching = false
+ instanceProgressBar.hide()
+ Log.e(TAG, "Fetch failure", throwable)
+
+ if (adapter.itemCount == 0) {
+ messageView.show()
+ if (throwable is IOException) {
+ messageView.setup(R.drawable.elephant_offline, R.string.error_network) {
+ messageView.hide()
+ this.fetchInstances(null)
+ }
+ } else {
+ messageView.setup(R.drawable.elephant_error, R.string.error_generic) {
+ messageView.hide()
+ this.fetchInstances(null)
+ }
+ }
+ }
+ }
+
+ companion object {
+ private const val TAG = "InstanceList" // logging tag
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/instancemute/interfaces/InstanceActionListener.kt b/app/src/main/java/com/keylesspalace/tusky/components/instancemute/interfaces/InstanceActionListener.kt
new file mode 100644
index 00000000..97d59cc9
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/components/instancemute/interfaces/InstanceActionListener.kt
@@ -0,0 +1,5 @@
+package com.keylesspalace.tusky.components.instancemute.interfaces
+
+interface InstanceActionListener {
+ fun mute(mute: Boolean, instance: String, position: Int)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt b/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt
index f516ae16..4d6e1eaf 100644
--- a/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt
@@ -16,6 +16,7 @@
package com.keylesspalace.tusky.di
import com.keylesspalace.tusky.*
+import com.keylesspalace.tusky.components.instancemute.InstanceListActivity
import com.keylesspalace.tusky.components.report.ReportActivity
import dagger.Module
import dagger.android.ContributesAndroidInjector
@@ -92,4 +93,7 @@ abstract class ActivitiesModule {
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesReportActivity(): ReportActivity
+
+ @ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
+ abstract fun contributesInstanceListActivity(): InstanceListActivity
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/di/FragmentBuildersModule.kt b/app/src/main/java/com/keylesspalace/tusky/di/FragmentBuildersModule.kt
index 05f618a9..21101fb1 100644
--- a/app/src/main/java/com/keylesspalace/tusky/di/FragmentBuildersModule.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/di/FragmentBuildersModule.kt
@@ -18,6 +18,7 @@ package com.keylesspalace.tusky.di
import com.keylesspalace.tusky.AccountsInListFragment
import com.keylesspalace.tusky.components.conversation.ConversationsFragment
+import com.keylesspalace.tusky.components.instancemute.fragment.InstanceListFragment
import com.keylesspalace.tusky.fragment.*
import com.keylesspalace.tusky.fragment.preference.AccountPreferencesFragment
import com.keylesspalace.tusky.fragment.preference.NotificationPreferencesFragment
@@ -71,4 +72,7 @@ abstract class FragmentBuildersModule {
@ContributesAndroidInjector
abstract fun reportDoneFragment(): ReportDoneFragment
-}
\ No newline at end of file
+
+ @ContributesAndroidInjector
+ abstract fun instanceListFragment(): InstanceListFragment
+}
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java
index 2c09f1eb..ac151f1a 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java
@@ -34,6 +34,7 @@ import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.adapter.StatusBaseViewHolder;
import com.keylesspalace.tusky.adapter.TimelineAdapter;
import com.keylesspalace.tusky.appstore.BlockEvent;
+import com.keylesspalace.tusky.appstore.DomainMuteEvent;
import com.keylesspalace.tusky.appstore.EventHub;
import com.keylesspalace.tusky.appstore.FavoriteEvent;
import com.keylesspalace.tusky.appstore.MuteEvent;
@@ -56,6 +57,7 @@ import com.keylesspalace.tusky.repository.Placeholder;
import com.keylesspalace.tusky.repository.TimelineRepository;
import com.keylesspalace.tusky.repository.TimelineRequestMode;
import com.keylesspalace.tusky.util.Either;
+import com.keylesspalace.tusky.util.LinkHelper;
import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate;
import com.keylesspalace.tusky.util.ListUtils;
import com.keylesspalace.tusky.util.PairedList;
@@ -526,6 +528,11 @@ public class TimelineFragment extends SFragment implements
String id = ((MuteEvent) event).getAccountId();
removeAllByAccountId(id);
}
+ } else if (event instanceof DomainMuteEvent) {
+ if (kind != Kind.USER && kind != Kind.USER_WITH_REPLIES && kind != Kind.USER_PINNED) {
+ String instance = ((DomainMuteEvent) event).getInstance();
+ removeAllByInstance(instance);
+ }
} else if (event instanceof StatusDeletedEvent) {
if (kind != Kind.USER && kind != Kind.USER_WITH_REPLIES && kind != Kind.USER_PINNED) {
String id = ((StatusDeletedEvent) event).getStatusId();
@@ -870,6 +877,18 @@ public class TimelineFragment extends SFragment implements
updateAdapter();
}
+ private void removeAllByInstance(String instance) {
+ // using iterator to safely remove items while iterating
+ Iterator> iterator = statuses.iterator();
+ while (iterator.hasNext()) {
+ Status status = iterator.next().asRightOrNull();
+ if (status != null && LinkHelper.getDomain(status.getAccount().getUrl()).equals(instance)) {
+ iterator.remove();
+ }
+ }
+ updateAdapter();
+ }
+
private void onLoadMore() {
if (didLoadEverythingBottom || bottomLoading) {
return;
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/preference/AccountPreferencesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/preference/AccountPreferencesFragment.kt
index 2da07159..409f5947 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/preference/AccountPreferencesFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/preference/AccountPreferencesFragment.kt
@@ -27,6 +27,7 @@ import com.keylesspalace.tusky.*
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
+import com.keylesspalace.tusky.components.instancemute.InstanceListActivity
import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.Account
@@ -59,6 +60,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
private lateinit var tabPreference: Preference
private lateinit var mutedUsersPreference: Preference
private lateinit var blockedUsersPreference: Preference
+ private lateinit var mutedDomainsPreference: Preference
private lateinit var defaultPostPrivacyPreference: ListPreference
private lateinit var defaultMediaSensitivityPreference: SwitchPreferenceCompat
@@ -78,6 +80,7 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
tabPreference = requirePreference("tabPreference")
mutedUsersPreference = requirePreference("mutedUsersPreference")
blockedUsersPreference = requirePreference("blockedUsersPreference")
+ mutedDomainsPreference = requirePreference("mutedDomainsPreference")
defaultPostPrivacyPreference = requirePreference("defaultPostPrivacy") as ListPreference
defaultMediaSensitivityPreference = requirePreference("defaultMediaSensitivity") as SwitchPreferenceCompat
mediaPreviewEnabledPreference = requirePreference("mediaPreviewEnabled") as SwitchPreferenceCompat
@@ -90,11 +93,13 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
notificationPreference.icon = IconicsDrawable(notificationPreference.context, GoogleMaterial.Icon.gmd_notifications).sizePx(iconSize).color(ThemeUtils.getColor(notificationPreference.context, R.attr.toolbar_icon_tint))
mutedUsersPreference.icon = getTintedIcon(R.drawable.ic_mute_24dp)
blockedUsersPreference.icon = IconicsDrawable(blockedUsersPreference.context, GoogleMaterial.Icon.gmd_block).sizePx(iconSize).color(ThemeUtils.getColor(blockedUsersPreference.context, R.attr.toolbar_icon_tint))
+ mutedDomainsPreference.icon = getTintedIcon(R.drawable.ic_mute_24dp)
notificationPreference.onPreferenceClickListener = this
tabPreference.onPreferenceClickListener = this
mutedUsersPreference.onPreferenceClickListener = this
blockedUsersPreference.onPreferenceClickListener = this
+ mutedDomainsPreference.onPreferenceClickListener = this
homeFiltersPreference.onPreferenceClickListener = this
notificationFiltersPreference.onPreferenceClickListener = this
publicFiltersPreference.onPreferenceClickListener = this
@@ -191,6 +196,12 @@ class AccountPreferencesFragment : PreferenceFragmentCompat(),
activity?.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
true
}
+ mutedDomainsPreference -> {
+ val intent = Intent(context, InstanceListActivity::class.java)
+ activity?.startActivity(intent)
+ activity?.overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left)
+ true
+ }
homeFiltersPreference -> {
launchFilterActivity(Filter.HOME, R.string.title_home)
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/network/MastodonApi.java b/app/src/main/java/com/keylesspalace/tusky/network/MastodonApi.java
index c429e272..4890ca89 100644
--- a/app/src/main/java/com/keylesspalace/tusky/network/MastodonApi.java
+++ b/app/src/main/java/com/keylesspalace/tusky/network/MastodonApi.java
@@ -47,6 +47,7 @@ import retrofit2.http.DELETE;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
+import retrofit2.http.HTTP;
import retrofit2.http.Header;
import retrofit2.http.Multipart;
import retrofit2.http.PATCH;
@@ -267,6 +268,21 @@ public interface MastodonApi {
@GET("api/v1/mutes")
Single>> mutes(@Query("max_id") String maxId);
+ @GET("api/v1/domain_blocks")
+ Single>> domainBlocks(
+ @Query("max_id") String maxId,
+ @Query("since_id") String sinceId,
+ @Query("limit") Integer limit);
+
+ @FormUrlEncoded
+ @POST("api/v1/domain_blocks")
+ Call