|
|
@ -18,6 +18,7 @@ package com.keylesspalace.tusky.fragment; |
|
|
|
import android.content.Context; |
|
|
|
import android.content.Context; |
|
|
|
import android.content.Intent; |
|
|
|
import android.content.Intent; |
|
|
|
import android.content.SharedPreferences; |
|
|
|
import android.content.SharedPreferences; |
|
|
|
|
|
|
|
import android.net.Uri; |
|
|
|
import android.os.Bundle; |
|
|
|
import android.os.Bundle; |
|
|
|
import android.util.Log; |
|
|
|
import android.util.Log; |
|
|
|
import android.view.LayoutInflater; |
|
|
|
import android.view.LayoutInflater; |
|
|
@ -62,6 +63,7 @@ import com.keylesspalace.tusky.repository.TimelineRepository; |
|
|
|
import com.keylesspalace.tusky.repository.TimelineRequestMode; |
|
|
|
import com.keylesspalace.tusky.repository.TimelineRequestMode; |
|
|
|
import com.keylesspalace.tusky.util.CardViewMode; |
|
|
|
import com.keylesspalace.tusky.util.CardViewMode; |
|
|
|
import com.keylesspalace.tusky.util.Either; |
|
|
|
import com.keylesspalace.tusky.util.Either; |
|
|
|
|
|
|
|
import com.keylesspalace.tusky.util.HttpHeaderLink; |
|
|
|
import com.keylesspalace.tusky.util.LinkHelper; |
|
|
|
import com.keylesspalace.tusky.util.LinkHelper; |
|
|
|
import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate; |
|
|
|
import com.keylesspalace.tusky.util.ListStatusAccessibilityDelegate; |
|
|
|
import com.keylesspalace.tusky.util.ListUtils; |
|
|
|
import com.keylesspalace.tusky.util.ListUtils; |
|
|
@ -151,6 +153,10 @@ public class TimelineFragment extends SFragment implements |
|
|
|
private Kind kind; |
|
|
|
private Kind kind; |
|
|
|
private String id; |
|
|
|
private String id; |
|
|
|
private List<String> tags; |
|
|
|
private List<String> tags; |
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* For some timeline kinds we must use LINK headers and not just status ids. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private String nextId; |
|
|
|
private LinearLayoutManager layoutManager; |
|
|
|
private LinearLayoutManager layoutManager; |
|
|
|
private EndlessOnScrollListener scrollListener; |
|
|
|
private EndlessOnScrollListener scrollListener; |
|
|
|
private boolean filterRemoveReplies; |
|
|
|
private boolean filterRemoveReplies; |
|
|
@ -220,7 +226,7 @@ public class TimelineFragment extends SFragment implements |
|
|
|
|| kind == Kind.LIST) { |
|
|
|
|| kind == Kind.LIST) { |
|
|
|
id = arguments.getString(ID_ARG); |
|
|
|
id = arguments.getString(ID_ARG); |
|
|
|
} |
|
|
|
} |
|
|
|
if(kind == Kind.TAG) { |
|
|
|
if (kind == Kind.TAG) { |
|
|
|
tags = arguments.getStringArrayList(HASHTAGS_ARG); |
|
|
|
tags = arguments.getStringArrayList(HASHTAGS_ARG); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -974,13 +980,17 @@ public class TimelineFragment extends SFragment implements |
|
|
|
updateAdapter(); |
|
|
|
updateAdapter(); |
|
|
|
|
|
|
|
|
|
|
|
String bottomId = null; |
|
|
|
String bottomId = null; |
|
|
|
final ListIterator<Either<Placeholder, Status>> iterator = |
|
|
|
if (kind == Kind.FAVOURITES || kind == Kind.BOOKMARKS) { |
|
|
|
this.statuses.listIterator(this.statuses.size()); |
|
|
|
bottomId = this.nextId; |
|
|
|
while (iterator.hasPrevious()) { |
|
|
|
} else { |
|
|
|
Either<Placeholder, Status> previous = iterator.previous(); |
|
|
|
final ListIterator<Either<Placeholder, Status>> iterator = |
|
|
|
if (previous.isRight()) { |
|
|
|
this.statuses.listIterator(this.statuses.size()); |
|
|
|
bottomId = previous.asRight().getId(); |
|
|
|
while (iterator.hasPrevious()) { |
|
|
|
break; |
|
|
|
Either<Placeholder, Status> previous = iterator.previous(); |
|
|
|
|
|
|
|
if (previous.isRight()) { |
|
|
|
|
|
|
|
bottomId = previous.asRight().getId(); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
sendFetchTimelineRequest(bottomId, null, null, FetchEnd.BOTTOM, -1); |
|
|
|
sendFetchTimelineRequest(bottomId, null, null, FetchEnd.BOTTOM, -1); |
|
|
@ -1063,6 +1073,14 @@ public class TimelineFragment extends SFragment implements |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void onResponse(@NonNull Call<List<Status>> call, @NonNull Response<List<Status>> response) { |
|
|
|
public void onResponse(@NonNull Call<List<Status>> call, @NonNull Response<List<Status>> response) { |
|
|
|
if (response.isSuccessful()) { |
|
|
|
if (response.isSuccessful()) { |
|
|
|
|
|
|
|
@Nullable |
|
|
|
|
|
|
|
String newNextId = extractNextId(response); |
|
|
|
|
|
|
|
if (newNextId != null) { |
|
|
|
|
|
|
|
// when we reach the bottom of the list, we won't have a new link. If
|
|
|
|
|
|
|
|
// we blindly write `null` here we will start loading from the top
|
|
|
|
|
|
|
|
// again.
|
|
|
|
|
|
|
|
nextId = newNextId; |
|
|
|
|
|
|
|
} |
|
|
|
onFetchTimelineSuccess(liftStatusList(response.body()), fetchEnd, pos); |
|
|
|
onFetchTimelineSuccess(liftStatusList(response.body()), fetchEnd, pos); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
onFetchTimelineFailure(new Exception(response.message()), fetchEnd, pos); |
|
|
|
onFetchTimelineFailure(new Exception(response.message()), fetchEnd, pos); |
|
|
@ -1081,6 +1099,24 @@ public class TimelineFragment extends SFragment implements |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Nullable |
|
|
|
|
|
|
|
private String extractNextId(Response<?> response) { |
|
|
|
|
|
|
|
String linkHeader = response.headers().get("Link"); |
|
|
|
|
|
|
|
if (linkHeader == null) { |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
List<HttpHeaderLink> links = HttpHeaderLink.parse(linkHeader); |
|
|
|
|
|
|
|
HttpHeaderLink nextHeader = HttpHeaderLink.findByRelationType(links, "next"); |
|
|
|
|
|
|
|
if (nextHeader == null) { |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Uri nextLink = nextHeader.uri; |
|
|
|
|
|
|
|
if (nextLink == null) { |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return nextLink.getQueryParameter("max_id"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void onFetchTimelineSuccess(List<Either<Placeholder, Status>> statuses, |
|
|
|
private void onFetchTimelineSuccess(List<Either<Placeholder, Status>> statuses, |
|
|
|
FetchEnd fetchEnd, int pos) { |
|
|
|
FetchEnd fetchEnd, int pos) { |
|
|
|
|
|
|
|
|
|
|
|