Fix issue #472 - Allow to browse Mastodon instances before registering

This commit is contained in:
Thomas 2022-11-17 10:55:01 +01:00
parent 5b164d60da
commit 2593d08d20
8 changed files with 68 additions and 38 deletions

View file

@ -55,7 +55,10 @@ public interface MastodonTimelinesService {
@GET("trends/statuses") @GET("trends/statuses")
Call<List<Status>> getStatusTrends(@Header("Authorization") String token); Call<List<Status>> getStatusTrends(
@Header("Authorization") String token,
@Query("offset") String offset,
@Query("limit") Integer limit);
@GET("trends/tags") @GET("trends/tags")

View file

@ -379,7 +379,7 @@ public class Timeline {
@SerializedName("TREND_MESSAGE") @SerializedName("TREND_MESSAGE")
TREND_MESSAGE("TREND_MESSAGE"), TREND_MESSAGE("TREND_MESSAGE"),
@SerializedName("PUBLIC_TREND_MESSAGE") @SerializedName("PUBLIC_TREND_MESSAGE")
PUBLIC_TREND_MESSAGE("PUBLIC_TREND_MESSAGE"), TREND_MESSAGE_PUBLIC("TREND_MESSAGE_PUBLIC"),
@SerializedName("STATUS_HISTORY") @SerializedName("STATUS_HISTORY")
STATUS_HISTORY("STATUS_HISTORY"), STATUS_HISTORY("STATUS_HISTORY"),
@SerializedName("ACCOUNT_TIMELINE") @SerializedName("ACCOUNT_TIMELINE")
@ -394,6 +394,8 @@ public class Timeline {
FAVOURITE_TIMELINE("FAVOURITE_TIMELINE"), FAVOURITE_TIMELINE("FAVOURITE_TIMELINE"),
@SerializedName("REBLOG_TIMELINE") @SerializedName("REBLOG_TIMELINE")
REBLOG_TIMELINE("REBLOG_TIMELINE"), REBLOG_TIMELINE("REBLOG_TIMELINE"),
@SerializedName("STATUS_REPORT")
STATUS_REPORT("STATUS_REPORT"),
@SerializedName("SCHEDULED_TOOT_SERVER") @SerializedName("SCHEDULED_TOOT_SERVER")
SCHEDULED_TOOT_SERVER("SCHEDULED_TOOT_SERVER"), SCHEDULED_TOOT_SERVER("SCHEDULED_TOOT_SERVER"),
@SerializedName("SCHEDULED_TOOT_CLIENT") @SerializedName("SCHEDULED_TOOT_CLIENT")

View file

@ -147,6 +147,26 @@ public class MastodonHelper {
return pagination; return pagination;
} }
/**
* Retrieve pagination from header
*
* @param headers Headers
* @return Pagination
*/
public static Pagination getOffSetPagination(Headers headers) {
String link = headers.get("Link");
Pagination pagination = new Pagination();
if (link != null) {
Pattern patternMaxId = Pattern.compile("offset=([0-9a-zA-Z]+)\\s?>\\s?;\\s?rel=\"next\"");
Matcher matcherMaxId = patternMaxId.matcher(link);
if (matcherMaxId.find()) {
pagination.max_id = matcherMaxId.group(1);
}
}
return pagination;
}
/*public static Pagination getPaginationNotification(List<Notification> notificationList) { /*public static Pagination getPaginationNotification(List<Notification> notificationList) {
Pagination pagination = new Pagination(); Pagination pagination = new Pagination();
if (notificationList == null || notificationList.size() == 0) { if (notificationList == null || notificationList.size() == 0) {

View file

@ -641,7 +641,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
} else { } else {
holder.binding.card.setVisibility(View.GONE); holder.binding.card.setVisibility(View.GONE);
} }
if (!canBeFederated) { if (!canBeFederated && timelineType != Timeline.TimeLineEnum.TREND_MESSAGE_PUBLIC) {
holder.binding.actionShareContainer.setVisibility(View.VISIBLE); holder.binding.actionShareContainer.setVisibility(View.VISIBLE);
holder.binding.actionShare.setOnClickListener(v -> { holder.binding.actionShare.setOnClickListener(v -> {
Intent sendIntent = new Intent(Intent.ACTION_SEND); Intent sendIntent = new Intent(Intent.ACTION_SEND);

View file

@ -140,9 +140,8 @@ public class FragmentLoginPickInstanceMastodon extends Fragment implements Insta
if (joinMastodonInstanceList != null) { if (joinMastodonInstanceList != null) {
JoinMastodonInstance clickedInstance = joinMastodonInstanceList.get(position); JoinMastodonInstance clickedInstance = joinMastodonInstanceList.get(position);
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putBoolean(Helper.ARG_MINIFIED, true);
args.putSerializable(Helper.ARG_REMOTE_INSTANCE_STRING, clickedInstance.domain); args.putSerializable(Helper.ARG_REMOTE_INSTANCE_STRING, clickedInstance.domain);
args.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.TREND_MESSAGE); args.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.TREND_MESSAGE_PUBLIC);
Helper.addFragment( Helper.addFragment(
getParentFragmentManager(), android.R.id.content, new FragmentMastodonTimeline(), getParentFragmentManager(), android.R.id.content, new FragmentMastodonTimeline(),

View file

@ -299,6 +299,9 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
canBeFederated = false; canBeFederated = false;
} }
} }
if (timelineType == Timeline.TimeLineEnum.TREND_MESSAGE_PUBLIC) {
canBeFederated = false;
}
publicTrendsDomain = getArguments().getString(Helper.ARG_REMOTE_INSTANCE_STRING, null); publicTrendsDomain = getArguments().getString(Helper.ARG_REMOTE_INSTANCE_STRING, null);
isViewInitialized = getArguments().getBoolean(Helper.ARG_INITIALIZE_VIEW, true); isViewInitialized = getArguments().getBoolean(Helper.ARG_INITIALIZE_VIEW, true);
tagTimeline = (TagTimeline) getArguments().getSerializable(Helper.ARG_TAG_TIMELINE); tagTimeline = (TagTimeline) getArguments().getSerializable(Helper.ARG_TAG_TIMELINE);
@ -360,7 +363,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
binding.loadingNextElements.setVisibility(View.GONE); binding.loadingNextElements.setVisibility(View.GONE);
flagLoading = false; flagLoading = false;
if (timelineStatuses != null && fetched_statuses != null && fetched_statuses.statuses != null && fetched_statuses.statuses.size() > 0) { if (timelineStatuses != null && fetched_statuses != null && fetched_statuses.statuses != null && fetched_statuses.statuses.size() > 0) {
try { try {
if (statusToUpdate != null) { if (statusToUpdate != null) {
@ -407,7 +409,15 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
} }
} }
//Update the timeline with new statuses //Update the timeline with new statuses
int insertedStatus = updateStatusListWith(fetched_statuses.statuses); int insertedStatus;
if (timelineType != Timeline.TimeLineEnum.TREND_MESSAGE_PUBLIC && timelineType != Timeline.TimeLineEnum.TREND_MESSAGE) {
insertedStatus = updateStatusListWith(fetched_statuses.statuses);
} else { //Trends cannot be ordered by id
insertedStatus = fetched_statuses.statuses.size();
int fromPosition = timelineStatuses.size();
timelineStatuses.addAll(fetched_statuses.statuses);
statusAdapter.notifyItemRangeInserted(fromPosition, insertedStatus);
}
//For these directions, the app will display counters for new messages //For these directions, the app will display counters for new messages
if (insertedStatus >= 0 && update != null && direction != DIRECTION.FETCH_NEW && !fetchingMissing) { if (insertedStatus >= 0 && update != null && direction != DIRECTION.FETCH_NEW && !fetchingMissing) {
update.onUpdate(insertedStatus, timelineType, slug); update.onUpdate(insertedStatus, timelineType, slug);
@ -420,7 +430,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
if (!fetchingMissing) { if (!fetchingMissing) {
if (fetched_statuses.pagination.max_id == null) { if (fetched_statuses.pagination.max_id == null) {
flagLoading = true; flagLoading = true;
} else if (max_id == null || Helper.compareTo(fetched_statuses.pagination.max_id, max_id) < 0) { } else if (max_id == null || Helper.compareTo(fetched_statuses.pagination.max_id, max_id) < 0 || timelineType.getValue().startsWith("TREND_")) {
max_id = fetched_statuses.pagination.max_id; max_id = fetched_statuses.pagination.max_id;
} }
if (min_id == null || (fetched_statuses.pagination.min_id != null && Helper.compareTo(fetched_statuses.pagination.min_id, min_id) > 0)) { if (min_id == null || (fetched_statuses.pagination.min_id != null && Helper.compareTo(fetched_statuses.pagination.min_id, min_id) > 0)) {
@ -501,7 +511,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
timelineStatuses.add(statusReport); timelineStatuses.add(statusReport);
} }
timelineStatuses.addAll(statuses.statuses); timelineStatuses.addAll(statuses.statuses);
if (max_id == null || (statuses.pagination.max_id != null && Helper.compareTo(statuses.pagination.max_id, max_id) < 0)) { if (max_id == null || (statuses.pagination.max_id != null && Helper.compareTo(statuses.pagination.max_id, max_id) < 0) || timelineType.getValue().startsWith("TREND_")) {
max_id = statuses.pagination.max_id; max_id = statuses.pagination.max_id;
} }
if (min_id == null || (statuses.pagination.min_id != null && Helper.compareTo(statuses.pagination.min_id, min_id) > 0)) { if (min_id == null || (statuses.pagination.min_id != null && Helper.compareTo(statuses.pagination.min_id, min_id) > 0)) {
@ -977,29 +987,23 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
} }
} else if (timelineType == Timeline.TimeLineEnum.TREND_MESSAGE) { } else if (timelineType == Timeline.TimeLineEnum.TREND_MESSAGE) {
if (direction == null) { if (direction == null) {
timelinesVM.getStatusTrends(BaseMainActivity.currentToken, BaseMainActivity.currentInstance) timelinesVM.getStatusTrends(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, null, MastodonHelper.statusesPerCall(requireActivity()))
.observe(getViewLifecycleOwner(), statusesTrends -> { .observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
Statuses statuses = new Statuses(); } else if (direction == DIRECTION.BOTTOM) {
statuses.statuses = new ArrayList<>(); timelinesVM.getStatusTrends(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, max_id, MastodonHelper.statusesPerCall(requireActivity()))
if (statusesTrends != null) { .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false));
statuses.statuses.addAll(statusesTrends); } else {
} flagLoading = false;
statuses.pagination = new Pagination();
initializeStatusesCommonView(statuses);
});
} }
} else if (timelineType == Timeline.TimeLineEnum.PUBLIC_TREND_MESSAGE) { } else if (timelineType == Timeline.TimeLineEnum.TREND_MESSAGE_PUBLIC) {
if (direction == null) { if (direction == null) {
timelinesVM.getStatusTrends(null, publicTrendsDomain) timelinesVM.getStatusTrends(null, publicTrendsDomain, null, MastodonHelper.statusesPerCall(requireActivity()))
.observe(getViewLifecycleOwner(), statusesTrends -> { .observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
Statuses statuses = new Statuses(); } else if (direction == DIRECTION.BOTTOM) {
statuses.statuses = new ArrayList<>(); timelinesVM.getStatusTrends(null, publicTrendsDomain, max_id, MastodonHelper.statusesPerCall(requireActivity()))
if (statusesTrends != null) { .observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false));
statuses.statuses.addAll(statusesTrends); } else {
} flagLoading = false;
statuses.pagination = new Pagination();
initializeStatusesCommonView(statuses);
});
} }
} }

View file

@ -160,28 +160,29 @@ public class TimelinesVM extends AndroidViewModel {
return retrofit.create(MastodonTimelinesService.class); return retrofit.create(MastodonTimelinesService.class);
} }
public LiveData<List<Status>> getStatusTrends(String token, @NonNull String instance) { public LiveData<Statuses> getStatusTrends(String token, @NonNull String instance, String max_id, Integer limit) {
MastodonTimelinesService mastodonTimelinesService = init(instance); MastodonTimelinesService mastodonTimelinesService = init(instance);
statusListMutableLiveData = new MutableLiveData<>(); statusesMutableLiveData = new MutableLiveData<>();
new Thread(() -> { new Thread(() -> {
Call<List<Status>> publicTlCall = mastodonTimelinesService.getStatusTrends(token); Call<List<Status>> publicTlCall = mastodonTimelinesService.getStatusTrends(token, max_id, limit);
List<Status> statusList = null; Statuses statuses = new Statuses();
if (publicTlCall != null) { if (publicTlCall != null) {
try { try {
Response<List<Status>> publicTlResponse = publicTlCall.execute(); Response<List<Status>> publicTlResponse = publicTlCall.execute();
if (publicTlResponse.isSuccessful()) { if (publicTlResponse.isSuccessful()) {
statusList = publicTlResponse.body(); List<Status> statusList = publicTlResponse.body();
statuses.statuses = TimelineHelper.filterStatus(getApplication().getApplicationContext(), statusList, Timeline.TimeLineEnum.TREND_MESSAGE);
statuses.pagination = MastodonHelper.getOffSetPagination(publicTlResponse.headers());
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
Handler mainHandler = new Handler(Looper.getMainLooper()); Handler mainHandler = new Handler(Looper.getMainLooper());
List<Status> finalStatusList = statusList; Runnable myRunnable = () -> statusesMutableLiveData.setValue(statuses);
Runnable myRunnable = () -> statusListMutableLiveData.setValue(finalStatusList);
mainHandler.post(myRunnable); mainHandler.post(myRunnable);
}).start(); }).start();
return statusListMutableLiveData; return statusesMutableLiveData;
} }
public LiveData<List<Tag>> getTagsTrends(String token, @NonNull String instance) { public LiveData<List<Tag>> getTagsTrends(String token, @NonNull String instance) {

View file

@ -91,6 +91,7 @@
android:text="@string/watch_trends_for_instance" android:text="@string/watch_trends_for_instance"
android:textColor="@color/cyanea_accent_dark_reference" android:textColor="@color/cyanea_accent_dark_reference"
app:icon="@drawable/ic_baseline_remove_red_eye_24" app:icon="@drawable/ic_baseline_remove_red_eye_24"
app:iconTint="@color/cyanea_accent_dark_reference"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/instance_description" app:layout_constraintTop_toBottomOf="@+id/instance_description"
app:strokeColor="@color/cyanea_accent_dark_reference" /> app:strokeColor="@color/cyanea_accent_dark_reference" />