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")
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")

View File

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

View File

@ -147,6 +147,26 @@ public class MastodonHelper {
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) {
Pagination pagination = new Pagination();
if (notificationList == null || notificationList.size() == 0) {

View File

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

View File

@ -140,9 +140,8 @@ public class FragmentLoginPickInstanceMastodon extends Fragment implements Insta
if (joinMastodonInstanceList != null) {
JoinMastodonInstance clickedInstance = joinMastodonInstanceList.get(position);
Bundle args = new Bundle();
args.putBoolean(Helper.ARG_MINIFIED, true);
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(
getParentFragmentManager(), android.R.id.content, new FragmentMastodonTimeline(),

View File

@ -299,6 +299,9 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
canBeFederated = false;
}
}
if (timelineType == Timeline.TimeLineEnum.TREND_MESSAGE_PUBLIC) {
canBeFederated = false;
}
publicTrendsDomain = getArguments().getString(Helper.ARG_REMOTE_INSTANCE_STRING, null);
isViewInitialized = getArguments().getBoolean(Helper.ARG_INITIALIZE_VIEW, true);
tagTimeline = (TagTimeline) getArguments().getSerializable(Helper.ARG_TAG_TIMELINE);
@ -360,7 +363,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
binding.loadingNextElements.setVisibility(View.GONE);
flagLoading = false;
if (timelineStatuses != null && fetched_statuses != null && fetched_statuses.statuses != null && fetched_statuses.statuses.size() > 0) {
try {
if (statusToUpdate != null) {
@ -407,7 +409,15 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
}
}
//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
if (insertedStatus >= 0 && update != null && direction != DIRECTION.FETCH_NEW && !fetchingMissing) {
update.onUpdate(insertedStatus, timelineType, slug);
@ -420,7 +430,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
if (!fetchingMissing) {
if (fetched_statuses.pagination.max_id == null) {
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;
}
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.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;
}
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) {
if (direction == null) {
timelinesVM.getStatusTrends(BaseMainActivity.currentToken, BaseMainActivity.currentInstance)
.observe(getViewLifecycleOwner(), statusesTrends -> {
Statuses statuses = new Statuses();
statuses.statuses = new ArrayList<>();
if (statusesTrends != null) {
statuses.statuses.addAll(statusesTrends);
}
statuses.pagination = new Pagination();
initializeStatusesCommonView(statuses);
});
timelinesVM.getStatusTrends(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, null, MastodonHelper.statusesPerCall(requireActivity()))
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
} else if (direction == DIRECTION.BOTTOM) {
timelinesVM.getStatusTrends(BaseMainActivity.currentToken, BaseMainActivity.currentInstance, max_id, MastodonHelper.statusesPerCall(requireActivity()))
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false));
} else {
flagLoading = false;
}
} else if (timelineType == Timeline.TimeLineEnum.PUBLIC_TREND_MESSAGE) {
} else if (timelineType == Timeline.TimeLineEnum.TREND_MESSAGE_PUBLIC) {
if (direction == null) {
timelinesVM.getStatusTrends(null, publicTrendsDomain)
.observe(getViewLifecycleOwner(), statusesTrends -> {
Statuses statuses = new Statuses();
statuses.statuses = new ArrayList<>();
if (statusesTrends != null) {
statuses.statuses.addAll(statusesTrends);
}
statuses.pagination = new Pagination();
initializeStatusesCommonView(statuses);
});
timelinesVM.getStatusTrends(null, publicTrendsDomain, null, MastodonHelper.statusesPerCall(requireActivity()))
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
} else if (direction == DIRECTION.BOTTOM) {
timelinesVM.getStatusTrends(null, publicTrendsDomain, max_id, MastodonHelper.statusesPerCall(requireActivity()))
.observe(getViewLifecycleOwner(), statusesBottom -> dealWithPagination(statusesBottom, DIRECTION.BOTTOM, false));
} else {
flagLoading = false;
}
}

View File

@ -160,28 +160,29 @@ public class TimelinesVM extends AndroidViewModel {
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);
statusListMutableLiveData = new MutableLiveData<>();
statusesMutableLiveData = new MutableLiveData<>();
new Thread(() -> {
Call<List<Status>> publicTlCall = mastodonTimelinesService.getStatusTrends(token);
List<Status> statusList = null;
Call<List<Status>> publicTlCall = mastodonTimelinesService.getStatusTrends(token, max_id, limit);
Statuses statuses = new Statuses();
if (publicTlCall != null) {
try {
Response<List<Status>> publicTlResponse = publicTlCall.execute();
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) {
e.printStackTrace();
}
}
Handler mainHandler = new Handler(Looper.getMainLooper());
List<Status> finalStatusList = statusList;
Runnable myRunnable = () -> statusListMutableLiveData.setValue(finalStatusList);
Runnable myRunnable = () -> statusesMutableLiveData.setValue(statuses);
mainHandler.post(myRunnable);
}).start();
return statusListMutableLiveData;
return statusesMutableLiveData;
}
public LiveData<List<Tag>> getTagsTrends(String token, @NonNull String instance) {

View File

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