Fix issue #1130 - Follow Pixelfed instance from the discover timeline

This commit is contained in:
Thomas 2025-03-01 16:06:39 +01:00
parent 885e8eb5d8
commit e0b8b60fed
7 changed files with 123 additions and 45 deletions

View file

@ -100,7 +100,7 @@ allprojects {
} }
} }
dependencies { dependencies {
implementation 'org.unifiedpush.android:connector:3.0.4' implementation 'org.unifiedpush.android:connector:3.0.5'
playstoreImplementation('org.unifiedpush.android:embedded-fcm-distributor:3.0.0') playstoreImplementation('org.unifiedpush.android:embedded-fcm-distributor:3.0.0')

View file

@ -200,7 +200,7 @@ public class ReorderTimelinesActivity extends BaseBarActivity implements OnStart
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.peertube_instance) { } else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.peertube_instance) {
url = "https://" + instanceName + "/api/v1/videos/"; url = "https://" + instanceName + "/api/v1/videos/";
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.pixelfed_instance) { } else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.pixelfed_instance) {
url = "https://" + instanceName + "/api/v1/timelines/public"; url = "https://" + instanceName + "/api/pixelfed/v2/discover/posts/trending?range=daily";
} else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.misskey_instance) { } else if (popupSearchInstanceBinding.setAttachmentGroup.getCheckedRadioButtonId() == R.id.misskey_instance) {
url = "https://" + instanceName + "/api/notes/local-timeline"; url = "https://" + instanceName + "/api/notes/local-timeline";
getCall = false; getCall = false;

View file

@ -231,6 +231,11 @@ public interface MastodonTimelinesService {
Call<List<MisskeyNote>> getMisskey(@Body MisskeyNote.MisskeyParams params); Call<List<MisskeyNote>> getMisskey(@Body MisskeyNote.MisskeyParams params);
@GET("discover/posts/trending")
Call<List<Status>> getPixelDiscoverTrending(
@Query("range") String range
);
@GET("api/v3/post/list?sort=New") @GET("api/v3/post/list?sort=New")
Call<LemmyPost.LemmyPosts> getLemmyMain(@Query("limit") Integer limit, Call<LemmyPost.LemmyPosts> getLemmyMain(@Query("limit") Integer limit,
@Query("page") String page); @Query("page") String page);

View file

@ -0,0 +1,32 @@
package app.fedilab.android.mastodon.client.endpoints;
/* Copyright 2025 Thomas Schneider
*
* This file is a part of Fedilab
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
import java.util.List;
import app.fedilab.android.mastodon.client.entities.api.Status;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface PixelfedTimelinesService {
//Public timelines
@GET("discover/posts/trending")
Call<List<Status>> getTrending(
@Query("range") String range
);
}

View file

@ -1127,7 +1127,12 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
} }
}); });
} }
} else { //Other remote timelines } else if (pinnedTimeline != null && pinnedTimeline.remoteInstance.type == RemoteInstance.InstanceType.PIXELFED) {
if (direction == null) {
timelinesVM.getPixelfedDiscoverTrending(remoteInstance)
.observe(getViewLifecycleOwner(), this::initializeStatusesCommonView);
}
}else { //Other remote timelines
routeCommon(direction, fetchingMissing, fetchStatus); routeCommon(direction, fetchingMissing, fetchStatus);
} }
} else if (timelineType == Timeline.TimeLineEnum.LIST) { //LIST TIMELINE } else if (timelineType == Timeline.TimeLineEnum.LIST) { //LIST TIMELINE

View file

@ -39,6 +39,7 @@ import java.util.List;
import app.fedilab.android.R; import app.fedilab.android.R;
import app.fedilab.android.activities.MainActivity; import app.fedilab.android.activities.MainActivity;
import app.fedilab.android.mastodon.client.endpoints.MastodonTimelinesService; import app.fedilab.android.mastodon.client.endpoints.MastodonTimelinesService;
import app.fedilab.android.mastodon.client.endpoints.PixelfedTimelinesService;
import app.fedilab.android.mastodon.client.entities.api.Account; import app.fedilab.android.mastodon.client.entities.api.Account;
import app.fedilab.android.mastodon.client.entities.api.Conversation; import app.fedilab.android.mastodon.client.entities.api.Conversation;
import app.fedilab.android.mastodon.client.entities.api.Conversations; import app.fedilab.android.mastodon.client.entities.api.Conversations;
@ -330,6 +331,35 @@ public class TimelinesVM extends AndroidViewModel {
return statusesMutableLiveData; return statusesMutableLiveData;
} }
/**
* Public discover timeline for Pixelfed
*
* @param instance String Pixelfed instance
* @return {@link LiveData} containing a {@link Statuses}
*/
public LiveData<Statuses> getPixelfedDiscoverTrending(String instance) {
statusesMutableLiveData = new MutableLiveData<>();
MastodonTimelinesService mastodonTimelinesService = initInstanceOnly(instance+"/api/pixelfed/v2/");
new Thread(() -> {
Statuses statuses = new Statuses();
Call<List<Status>> timelineCall = mastodonTimelinesService.getPixelDiscoverTrending("daily");
if (timelineCall != null) {
try {
Response<List<Status>> timelineResponse = timelineCall.execute();
if (timelineResponse.isSuccessful()) {
statuses.statuses = timelineResponse.body();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Handler mainHandler = new Handler(Looper.getMainLooper());
Runnable myRunnable = () -> statusesMutableLiveData.setValue(statuses);
mainHandler.post(myRunnable);
}).start();
return statusesMutableLiveData;
}
/** /**
* Public timeline for Lemmy * Public timeline for Lemmy

View file

@ -2,63 +2,69 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="16dp"
android:orientation="vertical"> android:orientation="vertical">
<AutoCompleteTextView <AutoCompleteTextView
android:layout_marginTop="10dp"
android:id="@+id/search_instance" android:id="@+id/search_instance"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/instance" android:hint="@string/instance"
android:inputType="textWebEmailAddress" android:inputType="textWebEmailAddress"
android:singleLine="true" /> android:singleLine="true" />
<ScrollView
<RadioGroup
android:id="@+id/set_attachment_group"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:orientation="vertical"> <RadioGroup
android:layout_marginTop="5dp"
<RadioButton android:id="@+id/set_attachment_group"
android:id="@+id/mastodon_instance" android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:checked="true" android:orientation="vertical">
android:text="@string/mastodon_instance" />
<RadioButton <RadioButton
android:id="@+id/peertube_instance" android:id="@+id/mastodon_instance"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/peertube_instance" /> android:checked="true"
android:text="@string/mastodon_instance" />
<RadioButton <RadioButton
android:id="@+id/pixelfed_instance" android:id="@+id/peertube_instance"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/pixelfed_instance" /> android:text="@string/peertube_instance" />
<RadioButton <RadioButton
android:id="@+id/misskey_instance" android:id="@+id/pixelfed_instance"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/misskey_instance" /> android:text="@string/pixelfed_instance" />
<RadioButton <RadioButton
android:id="@+id/lemmy_instance" android:id="@+id/misskey_instance"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/lemmy_instance" /> android:text="@string/misskey_instance" />
<RadioButton <RadioButton
android:id="@+id/gnu_instance" android:id="@+id/lemmy_instance"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/gnu_instance" /> android:text="@string/lemmy_instance" />
<RadioButton <RadioButton
android:id="@+id/twitter_accounts" android:id="@+id/gnu_instance"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/twitter_accounts" /> android:text="@string/gnu_instance" />
</RadioGroup>
<RadioButton
android:id="@+id/twitter_accounts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/twitter_accounts" />
</RadioGroup>
</ScrollView>
</LinearLayout> </LinearLayout>