Implement proper hiding muted users and conversations
This commit is contained in:
parent
ed16f1b2bc
commit
ed7bfa182b
|
@ -13,7 +13,7 @@ data class MuteStatusEvent(val statusId: String, val mute: Boolean) : Dispatchab
|
|||
data class EmojiReactEvent(val newStatus: Status) : Dispatchable
|
||||
data class UnfollowEvent(val accountId: String) : Dispatchable
|
||||
data class BlockEvent(val accountId: String) : Dispatchable
|
||||
data class MuteEvent(val accountId: String) : Dispatchable
|
||||
data class MuteEvent(val accountId: String, val mute: Boolean) : Dispatchable
|
||||
data class StatusDeletedEvent(val statusId: String) : Dispatchable
|
||||
data class StatusPreviewEvent(val status: Status) : Dispatchable
|
||||
data class StatusComposedEvent(val status: Status) : Dispatchable
|
||||
|
|
|
@ -42,7 +42,6 @@ class NotificationFetcher @Inject constructor(
|
|||
authHeader,
|
||||
account.domain,
|
||||
account.lastNotificationId,
|
||||
true,
|
||||
Notification.Type.asStringList
|
||||
).blockingGet()
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ class PreferencesActivity : BaseActivity(), SharedPreferences.OnSharedPreference
|
|||
|
||||
}
|
||||
"statusTextSize", "absoluteTimeView", "showBotOverlay", "animateGifAvatars",
|
||||
"useBlurhash", "showCardsInTimelines", "confirmReblogs", "hideMutedUsers",
|
||||
"useBlurhash", "showCardsInTimelines", "confirmReblogs",
|
||||
"enableSwipeForTabs", "bigEmojis", "mainNavPosition", PrefKeys.HIDE_TOP_TOOLBAR -> {
|
||||
restartActivitiesOnExit = true
|
||||
}
|
||||
|
|
|
@ -165,6 +165,13 @@ class PreferencesFragment : PreferenceFragmentCompat(), Injectable {
|
|||
isSingleLineTitle = false
|
||||
}
|
||||
|
||||
switchPreference {
|
||||
setDefaultValue(false)
|
||||
key = PrefKeys.HIDE_MUTED_USERS
|
||||
setTitle(R.string.pref_title_hide_muted_users)
|
||||
isSingleLineTitle = true
|
||||
}
|
||||
|
||||
switchPreference {
|
||||
setDefaultValue(true)
|
||||
key = PrefKeys.ENABLE_SWIPE_FOR_TABS
|
||||
|
|
|
@ -140,7 +140,7 @@ class ReportViewModel @Inject constructor(
|
|||
val muting = relationship?.muting == true
|
||||
muteStateMutable.value = Success(muting)
|
||||
if (muting) {
|
||||
eventHub.dispatch(MuteEvent(accountId))
|
||||
eventHub.dispatch(MuteEvent(accountId, true))
|
||||
}
|
||||
},
|
||||
{ error ->
|
||||
|
|
|
@ -73,12 +73,11 @@ class StatusesDataSource(private val accountId: String,
|
|||
retryInitial = null
|
||||
initialLoad.postValue(NetworkState.LOADING)
|
||||
val initialKey = params.requestedInitialKey
|
||||
val withMuted = true // TODO: configurable
|
||||
if (initialKey == null) {
|
||||
mastodonApi.accountStatusesObservable(accountId, null, null, params.requestedLoadSize, true, withMuted)
|
||||
mastodonApi.accountStatusesObservable(accountId, null, null, params.requestedLoadSize, true)
|
||||
} else {
|
||||
mastodonApi.statusObservable(initialKey).zipWith(
|
||||
mastodonApi.accountStatusesObservable(accountId, params.requestedInitialKey, null, params.requestedLoadSize - 1, true, withMuted),
|
||||
mastodonApi.accountStatusesObservable(accountId, params.requestedInitialKey, null, params.requestedLoadSize - 1, true),
|
||||
BiFunction { status: Status, list: List<Status> ->
|
||||
val ret = ArrayList<Status>()
|
||||
ret.add(status)
|
||||
|
@ -107,8 +106,7 @@ class StatusesDataSource(private val accountId: String,
|
|||
override fun loadAfter(params: LoadParams<String>, callback: LoadCallback<Status>) {
|
||||
networkStateAfter.postValue(NetworkState.LOADING)
|
||||
retryAfter = null
|
||||
val withMuted = true // TODO: configurable
|
||||
mastodonApi.accountStatusesObservable(accountId, params.key, null, params.requestedLoadSize, true, withMuted)
|
||||
mastodonApi.accountStatusesObservable(accountId, params.key, null, params.requestedLoadSize, true)
|
||||
.doOnSubscribe {
|
||||
disposables.add(it)
|
||||
}
|
||||
|
@ -130,8 +128,7 @@ class StatusesDataSource(private val accountId: String,
|
|||
override fun loadBefore(params: LoadParams<String>, callback: LoadCallback<Status>) {
|
||||
networkStateBefore.postValue(NetworkState.LOADING)
|
||||
retryBefore = null
|
||||
val withMuted = true // TODO: configurable
|
||||
mastodonApi.accountStatusesObservable(accountId, null, params.key, params.requestedLoadSize, true, withMuted)
|
||||
mastodonApi.accountStatusesObservable(accountId, null, params.key, params.requestedLoadSize, true)
|
||||
.doOnSubscribe {
|
||||
disposables.add(it)
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import android.view.ViewGroup
|
|||
import android.widget.ImageView
|
||||
import androidx.core.app.ActivityOptionsCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.Glide
|
||||
|
@ -34,6 +35,7 @@ import com.keylesspalace.tusky.entity.Attachment
|
|||
import com.keylesspalace.tusky.entity.Status
|
||||
import com.keylesspalace.tusky.interfaces.RefreshableFragment
|
||||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.settings.PrefKeys
|
||||
import com.keylesspalace.tusky.util.ThemeUtils
|
||||
import com.keylesspalace.tusky.util.hide
|
||||
import com.keylesspalace.tusky.util.show
|
||||
|
@ -72,6 +74,7 @@ class AccountMediaFragment : BaseFragment(), RefreshableFragment, Injectable {
|
|||
|
||||
private var isSwipeToRefreshEnabled: Boolean = true
|
||||
private var needToRefresh = false
|
||||
private var filterMuted = false
|
||||
|
||||
@Inject
|
||||
lateinit var api: MastodonApi
|
||||
|
@ -115,10 +118,12 @@ class AccountMediaFragment : BaseFragment(), RefreshableFragment, Injectable {
|
|||
|
||||
val body = response.body()
|
||||
body?.let { fetched ->
|
||||
statuses.addAll(0, fetched)
|
||||
// filter muted statuses if needed
|
||||
val filtered = fetched.filter { !(filterMuted && it.muted) }
|
||||
statuses.addAll(0, filtered)
|
||||
// flatMap requires iterable but I don't want to box each array into list
|
||||
val result = mutableListOf<AttachmentViewData>()
|
||||
for (status in fetched) {
|
||||
for (status in filtered) {
|
||||
result.addAll(AttachmentViewData.list(status))
|
||||
}
|
||||
adapter.addTop(result)
|
||||
|
@ -148,11 +153,15 @@ class AccountMediaFragment : BaseFragment(), RefreshableFragment, Injectable {
|
|||
body?.let { fetched ->
|
||||
Log.d(TAG, "fetched ${fetched.size} statuses")
|
||||
if (fetched.isNotEmpty()) Log.d(TAG, "first: ${fetched.first().id}, last: ${fetched.last().id}")
|
||||
statuses.addAll(fetched)
|
||||
|
||||
// filter muted statuses if needed
|
||||
val filtered = fetched.filter { !(filterMuted && it.muted) }
|
||||
|
||||
statuses.addAll(filtered)
|
||||
Log.d(TAG, "now there are ${statuses.size} statuses")
|
||||
// flatMap requires iterable but I don't want to box each array into list
|
||||
val result = mutableListOf<AttachmentViewData>()
|
||||
for (status in fetched) {
|
||||
for (status in filtered) {
|
||||
result.addAll(AttachmentViewData.list(status))
|
||||
}
|
||||
adapter.addBottom(result)
|
||||
|
@ -201,8 +210,7 @@ class AccountMediaFragment : BaseFragment(), RefreshableFragment, Injectable {
|
|||
statuses.lastOrNull()?.let { last ->
|
||||
Log.d(TAG, "Requesting statuses with max_id: ${last.id}, (bottom)")
|
||||
fetchingStatus = FetchingStatus.FETCHING_BOTTOM
|
||||
val withMuted = true // TODO: configurable
|
||||
currentCall = api.accountStatuses(accountId, last.id, null, null, null, true, null, withMuted)
|
||||
currentCall = api.accountStatuses(accountId, last.id, null, null, null, true, null)
|
||||
currentCall?.enqueue(bottomCallback)
|
||||
}
|
||||
}
|
||||
|
@ -210,19 +218,22 @@ class AccountMediaFragment : BaseFragment(), RefreshableFragment, Injectable {
|
|||
}
|
||||
})
|
||||
|
||||
filterMuted = PreferenceManager.getDefaultSharedPreferences(requireContext()).getBoolean(
|
||||
PrefKeys.HIDE_MUTED_USERS, false
|
||||
)
|
||||
|
||||
doInitialLoadingIfNeeded()
|
||||
}
|
||||
|
||||
private fun refresh() {
|
||||
statusView.hide()
|
||||
val withMuted = true // TODO: configurable
|
||||
if (fetchingStatus != FetchingStatus.NOT_FETCHING) return
|
||||
currentCall = if (statuses.isEmpty()) {
|
||||
fetchingStatus = FetchingStatus.INITIAL_FETCHING
|
||||
api.accountStatuses(accountId, null, null, null, null, true, null, withMuted)
|
||||
api.accountStatuses(accountId, null, null, null, null, true, null)
|
||||
} else {
|
||||
fetchingStatus = FetchingStatus.REFRESHING
|
||||
api.accountStatuses(accountId, null, statuses[0].id, null, null, true, null, withMuted)
|
||||
api.accountStatuses(accountId, null, statuses[0].id, null, null, true, null)
|
||||
}
|
||||
currentCall?.enqueue(callback)
|
||||
|
||||
|
@ -236,8 +247,7 @@ class AccountMediaFragment : BaseFragment(), RefreshableFragment, Injectable {
|
|||
}
|
||||
if (fetchingStatus == FetchingStatus.NOT_FETCHING && statuses.isEmpty()) {
|
||||
fetchingStatus = FetchingStatus.INITIAL_FETCHING
|
||||
val withMuted = true // TODO: configurable
|
||||
currentCall = api.accountStatuses(accountId, null, null, null, null, true, null, withMuted)
|
||||
currentCall = api.accountStatuses(accountId, null, null, null, null, true, null)
|
||||
currentCall?.enqueue(callback)
|
||||
}
|
||||
else if (needToRefresh)
|
||||
|
|
|
@ -67,6 +67,7 @@ import com.keylesspalace.tusky.interfaces.AccountActionListener;
|
|||
import com.keylesspalace.tusky.interfaces.ActionButtonActivity;
|
||||
import com.keylesspalace.tusky.interfaces.ReselectableFragment;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
import com.keylesspalace.tusky.settings.PrefKeys;
|
||||
import com.keylesspalace.tusky.util.CardViewMode;
|
||||
import com.keylesspalace.tusky.util.Either;
|
||||
import com.keylesspalace.tusky.util.HttpHeaderLink;
|
||||
|
@ -168,6 +169,7 @@ public class NotificationsFragment extends SFragment implements
|
|||
private boolean alwaysOpenSpoiler;
|
||||
private boolean showNotificationsFilter;
|
||||
private boolean showingError;
|
||||
private boolean withMuted;
|
||||
|
||||
// Each element is either a Notification for loading data or a Placeholder
|
||||
private final PairedList<Either<Placeholder, Notification>, NotificationViewData> notifications
|
||||
|
@ -201,7 +203,7 @@ public class NotificationsFragment extends SFragment implements
|
|||
View rootView = inflater.inflate(R.layout.fragment_timeline_notifications, container, false);
|
||||
|
||||
@NonNull Context context = inflater.getContext(); // from inflater to silence warning
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
boolean showNotificationsFilterSetting = preferences.getBoolean("showNotificationsFilter", true);
|
||||
//Clear notifications on filter visibility change to force refresh
|
||||
|
@ -247,6 +249,7 @@ public class NotificationsFragment extends SFragment implements
|
|||
CardViewMode.NONE,
|
||||
preferences.getBoolean("confirmReblogs", true)
|
||||
);
|
||||
withMuted = !preferences.getBoolean(PrefKeys.HIDE_MUTED_USERS, false);
|
||||
|
||||
adapter = new NotificationsAdapter(accountManager.getActiveAccount().getAccountId(),
|
||||
dataSource, statusDisplayOptions, this, this, this);
|
||||
|
@ -340,22 +343,50 @@ public class NotificationsFragment extends SFragment implements
|
|||
int conversationId = posAndNotification.second.getStatus().getConversationId();
|
||||
|
||||
if(conversationId == -1) { // invalid conversation ID
|
||||
setMutedStatusForStatus(posAndNotification.first, posAndNotification.second.getStatus(), event.getMute());
|
||||
if(withMuted) {
|
||||
setMutedStatusForStatus(posAndNotification.first, posAndNotification.second.getStatus(), event.getMute(), event.getMute());
|
||||
} else {
|
||||
notifications.remove(posAndNotification.first);
|
||||
}
|
||||
} else {
|
||||
//noinspection ConstantConditions
|
||||
// using iterator to safely remove items while iterating
|
||||
for (int i = 0; i < notifications.size(); i++) {
|
||||
Notification notification = notifications.get(i).asRightOrNull();
|
||||
if (notification != null && notification.getStatus() != null
|
||||
&& notification.getType() == Notification.Type.MENTION &&
|
||||
notification.getStatus().getConversationId() == conversationId) {
|
||||
setMutedStatusForStatus(i, notification.getStatus(), event.getMute());
|
||||
if(withMuted) {
|
||||
for (int i = 0; i < notifications.size(); i++) {
|
||||
Notification notification = notifications.get(i).asRightOrNull();
|
||||
if (notification != null && notification.getStatus() != null
|
||||
&& notification.getType() == Notification.Type.MENTION &&
|
||||
notification.getStatus().getConversationId() == conversationId) {
|
||||
setMutedStatusForStatus(i, notification.getStatus(), event.getMute(), event.getMute());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
removeAllByConversationId(conversationId);
|
||||
}
|
||||
}
|
||||
updateAdapter();
|
||||
}
|
||||
|
||||
private void handleMuteEvent(MuteEvent event) {
|
||||
String id = event.getAccountId();
|
||||
boolean mute = event.getMute();
|
||||
|
||||
if(withMuted) {
|
||||
for (int i = 0; i < notifications.size(); i++) {
|
||||
Notification notification = notifications.get(i).asRightOrNull();
|
||||
if (notification != null
|
||||
&& notification.getStatus() != null
|
||||
&& notification.getType() == Notification.Type.MENTION
|
||||
&& notification.getAccount().getId().equals(id)
|
||||
&& !notification.getStatus().isThreadMuted()) {
|
||||
setMutedStatusForStatus(i, notification.getStatus(), mute, false);
|
||||
}
|
||||
}
|
||||
updateAdapter();
|
||||
} else {
|
||||
removeAllByAccountId(id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
@ -411,6 +442,8 @@ public class NotificationsFragment extends SFragment implements
|
|||
handleMuteStatusEvent((MuteStatusEvent) event);
|
||||
} else if (event instanceof BlockEvent) {
|
||||
removeAllByAccountId(((BlockEvent) event).getAccountId());
|
||||
} else if (event instanceof MuteEvent) {
|
||||
handleMuteEvent((MuteEvent)event);
|
||||
} else if (event instanceof PreferenceChangedEvent) {
|
||||
onPreferenceChanged(((PreferenceChangedEvent) event).getPreferenceKey());
|
||||
} else if (event instanceof EmojiReactEvent) {
|
||||
|
@ -645,13 +678,13 @@ public class NotificationsFragment extends SFragment implements
|
|||
updateAdapter();
|
||||
}
|
||||
|
||||
private void setMutedStatusForStatus(int position, Status status, boolean muted) {
|
||||
status.setThreadMuted(muted);
|
||||
private void setMutedStatusForStatus(int position, Status status, boolean muted, boolean threadMuted) {
|
||||
status.setThreadMuted(threadMuted);
|
||||
|
||||
NotificationViewData.Concrete viewdata = (NotificationViewData.Concrete) notifications.getPairedItem(position);
|
||||
|
||||
StatusViewData.Builder viewDataBuilder = new StatusViewData.Builder(viewdata.getStatusViewData());
|
||||
viewDataBuilder.setThreadMuted(muted);
|
||||
viewDataBuilder.setThreadMuted(threadMuted);
|
||||
viewDataBuilder.setMuted(muted);
|
||||
|
||||
NotificationViewData.Concrete newViewData = new NotificationViewData.Concrete(
|
||||
|
@ -924,9 +957,11 @@ public class NotificationsFragment extends SFragment implements
|
|||
}
|
||||
|
||||
private void onPreferenceChanged(String key) {
|
||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
|
||||
switch (key) {
|
||||
case "fabHide": {
|
||||
hideFab = PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean("fabHide", false);
|
||||
hideFab = sharedPreferences.getBoolean("fabHide", false);
|
||||
break;
|
||||
}
|
||||
case "mediaPreviewEnabled": {
|
||||
|
@ -938,11 +973,15 @@ public class NotificationsFragment extends SFragment implements
|
|||
}
|
||||
case "showNotificationsFilter": {
|
||||
if (isAdded()) {
|
||||
showNotificationsFilter = PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean("showNotificationsFilter", true);
|
||||
showNotificationsFilter = sharedPreferences.getBoolean("showNotificationsFilter", true);
|
||||
updateFilterVisibility();
|
||||
fullyRefreshWithProgressBar(true);
|
||||
}
|
||||
}
|
||||
case PrefKeys.HIDE_MUTED_USERS: {
|
||||
withMuted = !sharedPreferences.getBoolean(PrefKeys.HIDE_MUTED_USERS, false);
|
||||
fullyRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -952,6 +991,21 @@ public class NotificationsFragment extends SFragment implements
|
|||
updateAdapter();
|
||||
}
|
||||
|
||||
private void removeAllByConversationId(int conversationId) {
|
||||
// using iterator to safely remove items while iterating
|
||||
Iterator<Either<Placeholder, Notification>> iterator = notifications.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Either<Placeholder, Notification> placeholderOrNotification = iterator.next();
|
||||
Notification notification = placeholderOrNotification.asRightOrNull();
|
||||
if (notification != null && notification.getStatus() != null
|
||||
&& notification.getType() == Notification.Type.MENTION &&
|
||||
notification.getStatus().getConversationId() == conversationId) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
updateAdapter();
|
||||
}
|
||||
|
||||
private void removeAllByAccountId(String accountId) {
|
||||
// using iterator to safely remove items while iterating
|
||||
Iterator<Either<Placeholder, Notification>> iterator = notifications.iterator();
|
||||
|
@ -1020,8 +1074,6 @@ public class NotificationsFragment extends SFragment implements
|
|||
bottomLoading = true;
|
||||
}
|
||||
|
||||
boolean withMuted = true; // TODO: configurable
|
||||
|
||||
Call<List<Notification>> call = mastodonApi.notifications(fromId, uptoId, LOAD_AT_ONCE, showNotificationsFilter ? notificationFilter : null, withMuted);
|
||||
|
||||
call.enqueue(new Callback<List<Notification>>() {
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.content.ClipData;
|
|||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
|
@ -62,6 +63,7 @@ import com.keylesspalace.tusky.entity.Status;
|
|||
import com.keylesspalace.tusky.entity.EmojiReaction;
|
||||
import com.keylesspalace.tusky.network.MastodonApi;
|
||||
import com.keylesspalace.tusky.network.TimelineCases;
|
||||
import com.keylesspalace.tusky.settings.PrefKeys;
|
||||
import com.keylesspalace.tusky.util.LinkHelper;
|
||||
import com.keylesspalace.tusky.viewdata.AttachmentViewData;
|
||||
import com.keylesspalace.tusky.interfaces.StatusActionListener;
|
||||
|
@ -101,6 +103,7 @@ public abstract class SFragment extends BaseFragment implements Injectable {
|
|||
private boolean filterRemoveRegex;
|
||||
private Matcher filterRemoveRegexMatcher;
|
||||
private static Matcher alphanumeric = Pattern.compile("^\\w+$").matcher("");
|
||||
private boolean filterMuted;
|
||||
|
||||
@Inject
|
||||
public MastodonApi mastodonApi;
|
||||
|
@ -543,8 +546,23 @@ public abstract class SFragment extends BaseFragment implements Injectable {
|
|||
});
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void reloadFilters(boolean forceRefresh) {
|
||||
public boolean isFilteringMuted() {
|
||||
return filterMuted;
|
||||
}
|
||||
|
||||
public void updateMuteFilter(@NonNull SharedPreferences pref, boolean reload) {
|
||||
filterMuted = pref.getBoolean(PrefKeys.HIDE_MUTED_USERS, false);
|
||||
|
||||
if(reload) {
|
||||
refreshAfterApplyingFilters();
|
||||
}
|
||||
}
|
||||
|
||||
public void reloadFilters(SharedPreferences pref, boolean forceRefresh) {
|
||||
if(pref != null) {
|
||||
updateMuteFilter(pref, false); // will be reloaded later
|
||||
}
|
||||
|
||||
if (filters != null && !forceRefresh) {
|
||||
applyFilters(forceRefresh);
|
||||
return;
|
||||
|
@ -581,6 +599,9 @@ public abstract class SFragment extends BaseFragment implements Injectable {
|
|||
|
||||
@VisibleForTesting
|
||||
public boolean shouldFilterStatus(Status status) {
|
||||
if (filterMuted && status.getMuted()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (filterRemoveRegex && status.getPoll() != null) {
|
||||
for (PollOption option : status.getPoll().getOptions()) {
|
||||
|
@ -594,7 +615,7 @@ public abstract class SFragment extends BaseFragment implements Injectable {
|
|||
|| (!status.getSpoilerText().isEmpty() && filterRemoveRegexMatcher.reset(status.getActionableStatus().getSpoilerText()).find())));
|
||||
}
|
||||
|
||||
private void applyFilters(boolean refresh) {
|
||||
public void applyFilters(boolean refresh) {
|
||||
List<String> tokens = new ArrayList<>();
|
||||
for (Filter filter : filters) {
|
||||
if (filterIsRelevant(filter)) {
|
||||
|
|
|
@ -61,6 +61,7 @@ import com.keylesspalace.tusky.network.MastodonApi;
|
|||
import com.keylesspalace.tusky.repository.Placeholder;
|
||||
import com.keylesspalace.tusky.repository.TimelineRepository;
|
||||
import com.keylesspalace.tusky.repository.TimelineRequestMode;
|
||||
import com.keylesspalace.tusky.settings.PrefKeys;
|
||||
import com.keylesspalace.tusky.util.CardViewMode;
|
||||
import com.keylesspalace.tusky.util.Either;
|
||||
import com.keylesspalace.tusky.util.HttpHeaderLink;
|
||||
|
@ -245,7 +246,6 @@ public class TimelineFragment extends SFragment implements
|
|||
adapter = new TimelineAdapter(dataSource, statusDisplayOptions, this);
|
||||
|
||||
isSwipeToRefreshEnabled = arguments.getBoolean(ARG_ENABLE_SWIPE_TO_REFRESH, true);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -288,7 +288,7 @@ public class TimelineFragment extends SFragment implements
|
|||
private void tryCache() {
|
||||
// Request timeline from disk to make it quick, then replace it with timeline from
|
||||
// the server to update it
|
||||
this.timelineRepo.getStatuses(null, null, null, LOAD_AT_ONCE,
|
||||
timelineRepo.getStatuses(null, null, null, LOAD_AT_ONCE,
|
||||
TimelineRequestMode.DISK)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.as(autoDisposable(from(this, Lifecycle.Event.ON_DESTROY)))
|
||||
|
@ -373,7 +373,8 @@ public class TimelineFragment extends SFragment implements
|
|||
|
||||
filter = preferences.getBoolean("tabFilterHomeBoosts", true);
|
||||
filterRemoveReblogs = kind == Kind.HOME && !filter;
|
||||
reloadFilters(false);
|
||||
|
||||
reloadFilters(preferences,false);
|
||||
}
|
||||
|
||||
private static boolean filterContextMatchesKind(Kind kind, List<String> filterContext) {
|
||||
|
@ -455,12 +456,13 @@ public class TimelineFragment extends SFragment implements
|
|||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
|
||||
/* This is delayed until onActivityCreated solely because MainActivity.composeButton isn't
|
||||
* guaranteed to be set until then. */
|
||||
if (actionButtonPresent()) {
|
||||
/* Use a modified scroll listener that both loads more statuses as it goes, and hides
|
||||
* the follow button on down-scroll. */
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
hideFab = preferences.getBoolean("fabHide", false);
|
||||
scrollListener = new EndlessOnScrollListener(layoutManager) {
|
||||
@Override
|
||||
|
@ -530,8 +532,7 @@ public class TimelineFragment extends SFragment implements
|
|||
}
|
||||
} else if (event instanceof MuteEvent) {
|
||||
if (kind != Kind.USER && kind != Kind.USER_WITH_REPLIES && kind != Kind.USER_PINNED) {
|
||||
String id = ((MuteEvent) event).getAccountId();
|
||||
removeAllByAccountId(id);
|
||||
handleMuteEvent((MuteEvent)event);
|
||||
}
|
||||
} else if (event instanceof DomainMuteEvent) {
|
||||
if (kind != Kind.USER && kind != Kind.USER_WITH_REPLIES && kind != Kind.USER_PINNED) {
|
||||
|
@ -700,12 +701,12 @@ public class TimelineFragment extends SFragment implements
|
|||
updateAdapter();
|
||||
}
|
||||
|
||||
private void setMutedStatusForStatus(int position, Status status, boolean muted) {
|
||||
status.setThreadMuted(muted);
|
||||
private void setMutedStatusForStatus(int position, Status status, boolean muted, boolean threadMuted) {
|
||||
status.setThreadMuted(threadMuted);
|
||||
|
||||
StatusViewData.Builder statusViewData = new StatusViewData.Builder((StatusViewData.Concrete)statuses.getPairedItem(position));
|
||||
statusViewData.setMuted(muted);
|
||||
statusViewData.setThreadMuted(muted);
|
||||
statusViewData.setThreadMuted(threadMuted);
|
||||
|
||||
statuses.setPairedItem(position, statusViewData.createStatusViewData());
|
||||
}
|
||||
|
@ -912,13 +913,17 @@ public class TimelineFragment extends SFragment implements
|
|||
}
|
||||
break;
|
||||
}
|
||||
case PrefKeys.HIDE_MUTED_USERS: {
|
||||
updateMuteFilter(sharedPreferences, true);
|
||||
break;
|
||||
}
|
||||
case Filter.HOME:
|
||||
case Filter.NOTIFICATIONS:
|
||||
case Filter.THREAD:
|
||||
case Filter.PUBLIC:
|
||||
case Filter.ACCOUNT: {
|
||||
if (filterContextMatchesKind(kind, Collections.singletonList(key))) {
|
||||
reloadFilters(true);
|
||||
reloadFilters(sharedPreferences, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -936,6 +941,19 @@ public class TimelineFragment extends SFragment implements
|
|||
updateAdapter();
|
||||
}
|
||||
|
||||
private void removeAllByConversationId(int conversationId) {
|
||||
// using iterator to safely remove items while iterating
|
||||
Iterator<Either<Placeholder, Status>> iterator = statuses.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Status status = iterator.next().asRightOrNull();
|
||||
if (status != null &&
|
||||
(status.getConversationId() == conversationId) || status.getActionableStatus().getConversationId() == conversationId) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
updateAdapter();
|
||||
}
|
||||
|
||||
private void removeAllByAccountId(String accountId) {
|
||||
// using iterator to safely remove items while iterating
|
||||
Iterator<Either<Placeholder, Status>> iterator = statuses.iterator();
|
||||
|
@ -1026,32 +1044,30 @@ public class TimelineFragment extends SFragment implements
|
|||
|
||||
private Call<List<Status>> getFetchCallByTimelineType(String fromId, String uptoId) {
|
||||
MastodonApi api = mastodonApi;
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
boolean withMuted = !preferences.getBoolean("hideMutedUsers", false);
|
||||
switch (kind) {
|
||||
default:
|
||||
case HOME:
|
||||
return api.homeTimeline(fromId, uptoId, LOAD_AT_ONCE, withMuted);
|
||||
return api.homeTimeline(fromId, uptoId, LOAD_AT_ONCE);
|
||||
case PUBLIC_FEDERATED:
|
||||
return api.publicTimeline(null, fromId, uptoId, LOAD_AT_ONCE, withMuted);
|
||||
return api.publicTimeline(null, fromId, uptoId, LOAD_AT_ONCE);
|
||||
case PUBLIC_LOCAL:
|
||||
return api.publicTimeline(true, fromId, uptoId, LOAD_AT_ONCE, withMuted);
|
||||
return api.publicTimeline(true, fromId, uptoId, LOAD_AT_ONCE);
|
||||
case TAG:
|
||||
String firstHashtag = tags.get(0);
|
||||
List<String> additionalHashtags = tags.subList(1, tags.size());
|
||||
return api.hashtagTimeline(firstHashtag, additionalHashtags, null, fromId, uptoId, LOAD_AT_ONCE, withMuted);
|
||||
return api.hashtagTimeline(firstHashtag, additionalHashtags, null, fromId, uptoId, LOAD_AT_ONCE);
|
||||
case USER:
|
||||
return api.accountStatuses(id, fromId, uptoId, LOAD_AT_ONCE, true, null, null, withMuted);
|
||||
return api.accountStatuses(id, fromId, uptoId, LOAD_AT_ONCE, true, null, null);
|
||||
case USER_PINNED:
|
||||
return api.accountStatuses(id, fromId, uptoId, LOAD_AT_ONCE, null, null, true, withMuted);
|
||||
return api.accountStatuses(id, fromId, uptoId, LOAD_AT_ONCE, null, null, true);
|
||||
case USER_WITH_REPLIES:
|
||||
return api.accountStatuses(id, fromId, uptoId, LOAD_AT_ONCE, null, null, null, withMuted);
|
||||
return api.accountStatuses(id, fromId, uptoId, LOAD_AT_ONCE, null, null, null);
|
||||
case FAVOURITES:
|
||||
return api.favourites(fromId, uptoId, LOAD_AT_ONCE, withMuted);
|
||||
return api.favourites(fromId, uptoId, LOAD_AT_ONCE);
|
||||
case BOOKMARKS:
|
||||
return api.bookmarks(fromId, uptoId, LOAD_AT_ONCE, withMuted);
|
||||
return api.bookmarks(fromId, uptoId, LOAD_AT_ONCE);
|
||||
case LIST:
|
||||
return api.listTimeline(id, fromId, uptoId, LOAD_AT_ONCE, withMuted);
|
||||
return api.listTimeline(id, fromId, uptoId, LOAD_AT_ONCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1421,17 +1437,45 @@ public class TimelineFragment extends SFragment implements
|
|||
int conversationId = eventStatus.getConversationId();
|
||||
|
||||
if(conversationId == -1) { // invalid conversation ID
|
||||
setMutedStatusForStatus(pos, eventStatus, event.getMute());
|
||||
if(isFilteringMuted()) {
|
||||
statuses.remove(pos);
|
||||
} else {
|
||||
setMutedStatusForStatus(pos, eventStatus, event.getMute(), event.getMute());
|
||||
}
|
||||
updateAdapter();
|
||||
} else {
|
||||
//noinspection ConstantConditions
|
||||
for (int i = 0; i < statuses.size(); i++) {
|
||||
Status status = statuses.get(i).asRightOrNull();
|
||||
if (status != null && status.getConversationId() == conversationId) {
|
||||
setMutedStatusForStatus(i, status, event.getMute());
|
||||
if(isFilteringMuted()) {
|
||||
removeAllByConversationId(conversationId);
|
||||
} else {
|
||||
for (int i = 0; i < statuses.size(); i++) {
|
||||
Status status = statuses.get(i).asRightOrNull();
|
||||
if (status != null && status.getConversationId() == conversationId) {
|
||||
setMutedStatusForStatus(i, status, event.getMute(), event.getMute());
|
||||
}
|
||||
}
|
||||
updateAdapter();
|
||||
}
|
||||
}
|
||||
updateAdapter();
|
||||
}
|
||||
|
||||
private void handleMuteEvent(MuteEvent event) {
|
||||
String id = event.getAccountId();
|
||||
boolean muting = event.getMute();
|
||||
|
||||
if(isFilteringMuted() && muting) {
|
||||
removeAllByAccountId(id);
|
||||
} else {
|
||||
for (int i = 0; i < statuses.size(); i++) {
|
||||
Status status = statuses.get(i).asRightOrNull();
|
||||
if (status != null
|
||||
&& status.getAccount().getId().equals(id)
|
||||
&& !status.isThreadMuted()) {
|
||||
setMutedStatusForStatus(i, status, muting, false);
|
||||
}
|
||||
}
|
||||
updateAdapter();
|
||||
}
|
||||
}
|
||||
|
||||
private List<Either<Placeholder, Status>> liftStatusList(List<Status> list) {
|
||||
|
|
|
@ -53,7 +53,6 @@ import com.keylesspalace.tusky.util.CardViewMode;
|
|||
import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate;
|
||||
import com.keylesspalace.tusky.util.PairedList;
|
||||
import com.keylesspalace.tusky.util.StatusDisplayOptions;
|
||||
import com.keylesspalace.tusky.util.ThemeUtils;
|
||||
import com.keylesspalace.tusky.util.ViewDataUtils;
|
||||
import com.keylesspalace.tusky.view.ConversationLineItemDecoration;
|
||||
import com.keylesspalace.tusky.viewdata.StatusViewData;
|
||||
|
@ -155,7 +154,7 @@ public final class ViewThreadFragment extends SFragment implements
|
|||
recyclerView.addItemDecoration(new ConversationLineItemDecoration(context));
|
||||
alwaysShowSensitiveMedia = accountManager.getActiveAccount().getAlwaysShowSensitiveMedia();
|
||||
alwaysOpenSpoiler = accountManager.getActiveAccount().getAlwaysOpenSpoiler();
|
||||
reloadFilters(false);
|
||||
reloadFilters(PreferenceManager.getDefaultSharedPreferences(context), false);
|
||||
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
|
@ -184,6 +183,8 @@ public final class ViewThreadFragment extends SFragment implements
|
|||
handleBookmarkEvent((BookmarkEvent) event);
|
||||
} else if (event instanceof BlockEvent) {
|
||||
removeAllByAccountId(((BlockEvent) event).getAccountId());
|
||||
} else if (event instanceof MuteEvent) {
|
||||
handleMuteEvent((MuteEvent) event);
|
||||
} else if (event instanceof StatusComposedEvent) {
|
||||
handleStatusComposedEvent((StatusComposedEvent) event);
|
||||
} else if (event instanceof StatusDeletedEvent) {
|
||||
|
@ -207,7 +208,7 @@ public final class ViewThreadFragment extends SFragment implements
|
|||
.createStatusViewData();
|
||||
statuses.setPairedItem(i, newViewData);
|
||||
}
|
||||
adapter.setStatuses(statuses.getPairedCopy());
|
||||
updateAdapter();
|
||||
updateRevealIcon();
|
||||
}
|
||||
|
||||
|
@ -411,7 +412,7 @@ public final class ViewThreadFragment extends SFragment implements
|
|||
getActivity().finish();
|
||||
}
|
||||
statuses.remove(position);
|
||||
adapter.setStatuses(statuses.getPairedCopy());
|
||||
updateAdapter();
|
||||
}
|
||||
|
||||
public void onVoteInPoll(int position, @NonNull List<Integer> choices) {
|
||||
|
@ -441,6 +442,10 @@ public final class ViewThreadFragment extends SFragment implements
|
|||
adapter.setItem(position, newViewData, true);
|
||||
}
|
||||
|
||||
private void updateAdapter() {
|
||||
adapter.setStatuses(statuses.getPairedCopy());
|
||||
}
|
||||
|
||||
private void removeAllByAccountId(String accountId) {
|
||||
Status status = null;
|
||||
if (!statuses.isEmpty()) {
|
||||
|
@ -461,7 +466,7 @@ public final class ViewThreadFragment extends SFragment implements
|
|||
return;
|
||||
}
|
||||
adapter.setDetailedStatusPosition(statusIndex);
|
||||
adapter.setStatuses(statuses.getPairedCopy());
|
||||
updateAdapter();
|
||||
}
|
||||
|
||||
private void sendStatusRequest(final String id) {
|
||||
|
@ -602,6 +607,33 @@ public final class ViewThreadFragment extends SFragment implements
|
|||
updateRevealIcon();
|
||||
}
|
||||
|
||||
private void setMutedStatusForStatus(int position, Status status, boolean muted) {
|
||||
StatusViewData.Builder statusViewData = new StatusViewData.Builder(statuses.getPairedItem(position));
|
||||
statusViewData.setMuted(muted);
|
||||
|
||||
statuses.setPairedItem(position, statusViewData.createStatusViewData());
|
||||
}
|
||||
|
||||
private void handleMuteEvent(MuteEvent event) {
|
||||
String id = event.getAccountId();
|
||||
boolean muting = event.getMute();
|
||||
|
||||
if(isFilteringMuted()) {
|
||||
removeAllByAccountId(id);
|
||||
} else {
|
||||
for (int i = 0; i < statuses.size(); i++) {
|
||||
Status status = statuses.get(i);
|
||||
if (status != null
|
||||
&& status.getAccount().getId().equals(id)
|
||||
&& !status.isThreadMuted()) {
|
||||
setMutedStatusForStatus(i, status, muting);
|
||||
}
|
||||
}
|
||||
updateAdapter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void handleFavEvent(FavoriteEvent event) {
|
||||
Pair<Integer, Status> posAndStatus = findStatusAndPos(event.getStatusId());
|
||||
if (posAndStatus == null) return;
|
||||
|
|
|
@ -51,49 +51,44 @@ interface MastodonApi {
|
|||
@GET("api/v1/filters")
|
||||
fun getFilters(): Call<List<Filter>>
|
||||
|
||||
@GET("api/v1/timelines/home")
|
||||
@GET("api/v1/timelines/home?with_muted=true")
|
||||
fun homeTimeline(
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("with_muted") withMuted: Boolean?
|
||||
@Query("limit") limit: Int?
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("api/v1/timelines/home")
|
||||
@GET("api/v1/timelines/home?with_muted=true")
|
||||
fun homeTimelineSingle(
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("with_muted") withMuted: Boolean?
|
||||
@Query("limit") limit: Int?
|
||||
): Single<List<Status>>
|
||||
|
||||
@GET("api/v1/timelines/public")
|
||||
@GET("api/v1/timelines/public?with_muted=true")
|
||||
fun publicTimeline(
|
||||
@Query("local") local: Boolean?,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("with_muted") withMuted: Boolean?
|
||||
@Query("limit") limit: Int?
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("api/v1/timelines/tag/{hashtag}")
|
||||
@GET("api/v1/timelines/tag/{hashtag}?with_muted=true")
|
||||
fun hashtagTimeline(
|
||||
@Path("hashtag") hashtag: String,
|
||||
@Query("any[]") any: List<String>?,
|
||||
@Query("local") local: Boolean?,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("with_muted") withMuted: Boolean?
|
||||
@Query("limit") limit: Int?
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("api/v1/timelines/list/{listId}")
|
||||
@GET("api/v1/timelines/list/{listId}?with_muted=true")
|
||||
fun listTimeline(
|
||||
@Path("listId") listId: String,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("with_muted") withMuted: Boolean?
|
||||
@Query("limit") limit: Int?
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("api/v1/notifications")
|
||||
|
@ -112,12 +107,11 @@ interface MastodonApi {
|
|||
@Query("timeline[]") timelines: List<String>
|
||||
): Single<Map<String, Marker>>
|
||||
|
||||
@GET("api/v1/notifications")
|
||||
@GET("api/v1/notifications?with_muted=true")
|
||||
fun notificationsWithAuth(
|
||||
@Header("Authorization") auth: String,
|
||||
@Header(DOMAIN_HEADER) domain: String,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("with_muted") withMuted: Boolean?,
|
||||
@Query("include_types[]") includeTypes: List<String>?
|
||||
): Single<List<Notification>>
|
||||
|
||||
|
@ -288,7 +282,7 @@ interface MastodonApi {
|
|||
* @param excludeReplies only return statuses that are no replies
|
||||
* @param onlyMedia only return statuses that have media attached
|
||||
*/
|
||||
@GET("api/v1/accounts/{id}/statuses")
|
||||
@GET("api/v1/accounts/{id}/statuses?with_muted=true")
|
||||
fun accountStatuses(
|
||||
@Path("id") accountId: String,
|
||||
@Query("max_id") maxId: String?,
|
||||
|
@ -296,8 +290,7 @@ interface MastodonApi {
|
|||
@Query("limit") limit: Int?,
|
||||
@Query("exclude_replies") excludeReplies: Boolean?,
|
||||
@Query("only_media") onlyMedia: Boolean?,
|
||||
@Query("pinned") pinned: Boolean?,
|
||||
@Query("with_muted") withMuted: Boolean?
|
||||
@Query("pinned") pinned: Boolean?
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("api/v1/accounts/{id}/followers")
|
||||
|
@ -392,20 +385,18 @@ interface MastodonApi {
|
|||
@HTTP(method = "DELETE", path = "api/v1/domain_blocks", hasBody = true)
|
||||
fun unblockDomain(@Field("domain") domain: String): Call<Any>
|
||||
|
||||
@GET("api/v1/favourites")
|
||||
@GET("api/v1/favourites?with_muted=true")
|
||||
fun favourites(
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("with_muted") withMuted: Boolean?
|
||||
@Query("limit") limit: Int?
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("api/v1/bookmarks")
|
||||
@GET("api/v1/bookmarks?with_muted=true")
|
||||
fun bookmarks(
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("with_muted") withMuted: Boolean?
|
||||
@Query("limit") limit: Int?
|
||||
): Call<List<Status>>
|
||||
|
||||
@GET("api/v1/follow_requests")
|
||||
|
@ -572,14 +563,13 @@ interface MastodonApi {
|
|||
@Field("forward") isNotifyRemote: Boolean?
|
||||
): Single<ResponseBody>
|
||||
|
||||
@GET("api/v1/accounts/{id}/statuses")
|
||||
@GET("api/v1/accounts/{id}/statuses?with_muted=true")
|
||||
fun accountStatusesObservable(
|
||||
@Path("id") accountId: String,
|
||||
@Query("max_id") maxId: String?,
|
||||
@Query("since_id") sinceId: String?,
|
||||
@Query("limit") limit: Int?,
|
||||
@Query("exclude_reblogs") excludeReblogs: Boolean?,
|
||||
@Query("with_muted") withMuted: Boolean?
|
||||
@Query("exclude_reblogs") excludeReblogs: Boolean?
|
||||
): Single<List<Status>>
|
||||
|
||||
@GET("api/v1/statuses/{id}")
|
||||
|
|
|
@ -103,7 +103,7 @@ class TimelineCasesImpl(
|
|||
|
||||
override fun onFailure(call: Call<Relationship>, t: Throwable) {}
|
||||
})
|
||||
eventHub.dispatch(MuteEvent(id))
|
||||
eventHub.dispatch(MuteEvent(id, true))
|
||||
}
|
||||
|
||||
override fun muteStatus(status: Status, mute: Boolean) {
|
||||
|
@ -115,7 +115,7 @@ class TimelineCasesImpl(
|
|||
mastodonApi.unmuteStatus(id)
|
||||
}).subscribe( { status ->
|
||||
eventHub.dispatch(MuteStatusEvent(status.id, mute))
|
||||
}, {})
|
||||
}, {}).addTo(this.cancelDisposable)
|
||||
}
|
||||
|
||||
override fun block(id: String) {
|
||||
|
@ -126,7 +126,6 @@ class TimelineCasesImpl(
|
|||
override fun onFailure(call: Call<Relationship>, t: Throwable) {}
|
||||
})
|
||||
eventHub.dispatch(BlockEvent(id))
|
||||
|
||||
}
|
||||
|
||||
override fun delete(id: String): Single<DeletedStatus> {
|
||||
|
|
|
@ -66,8 +66,7 @@ class TimelineRepositoryImpl(
|
|||
sinceIdMinusOne: String?, limit: Int,
|
||||
accountId: Long, requestMode: TimelineRequestMode
|
||||
): Single<out List<TimelineStatus>> {
|
||||
val withMuted = true // TODO: configurable
|
||||
return mastodonApi.homeTimelineSingle(maxId, sinceIdMinusOne, limit + 1, withMuted)
|
||||
return mastodonApi.homeTimelineSingle(maxId, sinceIdMinusOne, limit + 1)
|
||||
.map { statuses ->
|
||||
this.saveStatusesToDb(accountId, statuses, maxId, sinceId)
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ object PrefKeys {
|
|||
const val BIG_EMOJIS = "bigEmojis"
|
||||
const val STICKERS = "stickers"
|
||||
const val ANONYMIZE_FILENAMES = "anonymizeFilenames"
|
||||
const val HIDE_MUTED_USERS = "hideMutedUsers"
|
||||
|
||||
const val CUSTOM_TABS = "customTabs"
|
||||
|
||||
|
|
|
@ -247,7 +247,8 @@ class AccountViewModel @Inject constructor(
|
|||
when (relationshipAction) {
|
||||
RelationShipAction.UNFOLLOW -> eventHub.dispatch(UnfollowEvent(accountId))
|
||||
RelationShipAction.BLOCK -> eventHub.dispatch(BlockEvent(accountId))
|
||||
RelationShipAction.MUTE -> eventHub.dispatch(MuteEvent(accountId))
|
||||
RelationShipAction.MUTE -> eventHub.dispatch(MuteEvent(accountId, true))
|
||||
RelationShipAction.UNMUTE -> eventHub.dispatch(MuteEvent(accountId, false))
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
@ -276,7 +277,6 @@ class AccountViewModel @Inject constructor(
|
|||
|
||||
call.enqueue(callback)
|
||||
callList.add(call)
|
||||
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
|
@ -299,7 +299,6 @@ class AccountViewModel @Inject constructor(
|
|||
if (!isSelf)
|
||||
obtainRelationship(isReload)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun setAccountInfo(accountId: String) {
|
||||
|
|
Loading…
Reference in New Issue