Loading app/build.gradle +1 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ dependencies { implementation "com.google.code.gson:gson:2.8.6" implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.retrofit2:converter-simplexml:2.9.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.preference:preference:1.2.0' implementation "org.conscrypt:conscrypt-android:2.5.2" Loading app/src/main/java/app/fedilab/android/client/endpoints/MastodonTimelinesService.java +13 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ import app.fedilab.android.client.entities.api.Marker; import app.fedilab.android.client.entities.api.MastodonList; import app.fedilab.android.client.entities.api.Status; import app.fedilab.android.client.entities.misskey.MisskeyNote; import app.fedilab.android.client.entities.nitter.Nitter; import app.fedilab.android.client.entities.nitter.NitterAccount; import app.fedilab.android.client.entities.peertube.PeertubeVideo; import retrofit2.Call; import retrofit2.http.Body; Loading Loading @@ -224,6 +226,17 @@ public interface MastodonTimelinesService { @Query("count") int count ); @GET("{names}/rss") Call<Nitter> getNitter( @Path("names") String id, @Query("max_position") String max_position ); @GET("{account}/rss") Call<NitterAccount> getNitterAccount( @Path("account") String account ); @GET("api/v1/videos/{id}") Call<PeertubeVideo.Video> getPeertubeVideo( @Path("id") String id Loading app/src/main/java/app/fedilab/android/client/entities/nitter/Nitter.java 0 → 100644 +136 −0 Original line number Diff line number Diff line package app.fedilab.android.client.entities.nitter; import android.content.Context; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import org.simpleframework.xml.Element; import org.simpleframework.xml.ElementList; import org.simpleframework.xml.Root; import java.io.Serializable; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; import app.fedilab.android.client.endpoints.MastodonTimelinesService; import app.fedilab.android.client.entities.api.Attachment; import app.fedilab.android.client.entities.api.Status; import app.fedilab.android.helper.Helper; import okhttp3.OkHttpClient; import retrofit2.Call; import retrofit2.Response; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.simplexml.SimpleXmlConverterFactory; @Root(name = "rss", strict = false) public class Nitter implements Serializable { public static HashMap<String, NitterAccount> accounts = new HashMap<>(); @Element(name = "channel") public Channel channel; public static MastodonTimelinesService initInstanceXMLOnly(Context context, String instance) { Gson gson = new GsonBuilder().setDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz").create(); OkHttpClient okHttpClient = new OkHttpClient.Builder() .readTimeout(60, TimeUnit.SECONDS) .connectTimeout(60, TimeUnit.SECONDS) .callTimeout(60, TimeUnit.SECONDS) .proxy(Helper.getProxy(context)) .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://" + instance) .addConverterFactory(GsonConverterFactory.create(gson)) .addConverterFactory(SimpleXmlConverterFactory.create()) .client(okHttpClient) .build(); return retrofit.create(MastodonTimelinesService.class); } public static Status convert(Context context, String instance, FeedItem feedItem) { Status status = new Status(); status.id = feedItem.pubDate.toString(); status.content = feedItem.title; status.text = feedItem.title; status.visibility = "public"; status.created_at = feedItem.pubDate; status.uri = feedItem.guid; status.url = feedItem.link; if (feedItem.creator != null && !accounts.containsValue(feedItem.creator)) { MastodonTimelinesService mastodonTimelinesService = initInstanceXMLOnly(context, instance); Call<NitterAccount> accountCall = mastodonTimelinesService.getNitterAccount(instance); if (accountCall != null) { try { Response<NitterAccount> publicTlResponse = accountCall.execute(); if (publicTlResponse.isSuccessful()) { NitterAccount nitterAccount = publicTlResponse.body(); accounts.put(feedItem.creator, nitterAccount); } } catch (Exception e) { e.printStackTrace(); } } } NitterAccount nitterAccount = accounts.get(feedItem.creator); if (nitterAccount != null) { app.fedilab.android.client.entities.api.Account account = new app.fedilab.android.client.entities.api.Account(); String[] names = nitterAccount.channel.image.title.split("/"); account.id = feedItem.guid; account.acct = names[1]; account.username = names[1]; account.display_name = names[0]; account.avatar = nitterAccount.channel.image.url; account.avatar_static = nitterAccount.channel.image.url; account.url = nitterAccount.channel.image.link; status.account = account; } Pattern imgPattern = Pattern.compile("<img [^>]*src=\"([^\"]+)\"[^>]*>"); Matcher matcher = imgPattern.matcher(feedItem.description); String description = feedItem.description; ArrayList<Attachment> attachmentList = new ArrayList<>(); while (matcher.find()) { description = description.replaceAll(Pattern.quote(matcher.group()), ""); Attachment attachment = new Attachment(); attachment.type = "image"; attachment.url = matcher.group(1); attachment.preview_url = matcher.group(1); attachment.id = matcher.group(1); attachmentList.add(attachment); } status.media_attachments = attachmentList; return status; } @Root(name = "channel", strict = false) public static class Channel implements Serializable { @ElementList(name = "item") public List<FeedItem> mFeedItems; } @Root(name = "item", strict = false) public static class FeedItem implements Serializable { @ElementList(name = "dc:creator", required = false) public String creator; @ElementList(name = "title") public String title; @ElementList(name = "description", required = false) public String description; @ElementList(name = "pubDate") public Date pubDate; @ElementList(name = "guid", required = false) public String guid; @ElementList(name = "link", required = false) public String link; } } app/src/main/java/app/fedilab/android/client/entities/nitter/NitterAccount.java 0 → 100644 +36 −0 Original line number Diff line number Diff line package app.fedilab.android.client.entities.nitter; import org.simpleframework.xml.Element; import org.simpleframework.xml.Root; import java.io.Serializable; import java.util.HashMap; @Root(name = "rss", strict = false) public class NitterAccount implements Serializable { public static HashMap<String, NitterAccount> accounts = new HashMap<>(); @Element(name = "channel") public Channel channel; @Root(name = "channel", strict = false) public static class Channel implements Serializable { @Element(name = "image") public Image image; } @Root(name = "image", strict = false) public static class Image implements Serializable { @Element(name = "title") public String title; @Element(name = "url") public String url; @Element(name = "link") public String link; } } app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java +1 −1 Original line number Diff line number Diff line Loading @@ -447,7 +447,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> attachment.peertubeId = matcherLink.group(3); attachmentList.add(attachment); statusToDeal.media_attachments = attachmentList; adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, statusToDeal)); //adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, statusToDeal)); } } Loading Loading
app/build.gradle +1 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ dependencies { implementation "com.google.code.gson:gson:2.8.6" implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.retrofit2:converter-simplexml:2.9.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.preference:preference:1.2.0' implementation "org.conscrypt:conscrypt-android:2.5.2" Loading
app/src/main/java/app/fedilab/android/client/endpoints/MastodonTimelinesService.java +13 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ import app.fedilab.android.client.entities.api.Marker; import app.fedilab.android.client.entities.api.MastodonList; import app.fedilab.android.client.entities.api.Status; import app.fedilab.android.client.entities.misskey.MisskeyNote; import app.fedilab.android.client.entities.nitter.Nitter; import app.fedilab.android.client.entities.nitter.NitterAccount; import app.fedilab.android.client.entities.peertube.PeertubeVideo; import retrofit2.Call; import retrofit2.http.Body; Loading Loading @@ -224,6 +226,17 @@ public interface MastodonTimelinesService { @Query("count") int count ); @GET("{names}/rss") Call<Nitter> getNitter( @Path("names") String id, @Query("max_position") String max_position ); @GET("{account}/rss") Call<NitterAccount> getNitterAccount( @Path("account") String account ); @GET("api/v1/videos/{id}") Call<PeertubeVideo.Video> getPeertubeVideo( @Path("id") String id Loading
app/src/main/java/app/fedilab/android/client/entities/nitter/Nitter.java 0 → 100644 +136 −0 Original line number Diff line number Diff line package app.fedilab.android.client.entities.nitter; import android.content.Context; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import org.simpleframework.xml.Element; import org.simpleframework.xml.ElementList; import org.simpleframework.xml.Root; import java.io.Serializable; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; import app.fedilab.android.client.endpoints.MastodonTimelinesService; import app.fedilab.android.client.entities.api.Attachment; import app.fedilab.android.client.entities.api.Status; import app.fedilab.android.helper.Helper; import okhttp3.OkHttpClient; import retrofit2.Call; import retrofit2.Response; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.simplexml.SimpleXmlConverterFactory; @Root(name = "rss", strict = false) public class Nitter implements Serializable { public static HashMap<String, NitterAccount> accounts = new HashMap<>(); @Element(name = "channel") public Channel channel; public static MastodonTimelinesService initInstanceXMLOnly(Context context, String instance) { Gson gson = new GsonBuilder().setDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz").create(); OkHttpClient okHttpClient = new OkHttpClient.Builder() .readTimeout(60, TimeUnit.SECONDS) .connectTimeout(60, TimeUnit.SECONDS) .callTimeout(60, TimeUnit.SECONDS) .proxy(Helper.getProxy(context)) .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://" + instance) .addConverterFactory(GsonConverterFactory.create(gson)) .addConverterFactory(SimpleXmlConverterFactory.create()) .client(okHttpClient) .build(); return retrofit.create(MastodonTimelinesService.class); } public static Status convert(Context context, String instance, FeedItem feedItem) { Status status = new Status(); status.id = feedItem.pubDate.toString(); status.content = feedItem.title; status.text = feedItem.title; status.visibility = "public"; status.created_at = feedItem.pubDate; status.uri = feedItem.guid; status.url = feedItem.link; if (feedItem.creator != null && !accounts.containsValue(feedItem.creator)) { MastodonTimelinesService mastodonTimelinesService = initInstanceXMLOnly(context, instance); Call<NitterAccount> accountCall = mastodonTimelinesService.getNitterAccount(instance); if (accountCall != null) { try { Response<NitterAccount> publicTlResponse = accountCall.execute(); if (publicTlResponse.isSuccessful()) { NitterAccount nitterAccount = publicTlResponse.body(); accounts.put(feedItem.creator, nitterAccount); } } catch (Exception e) { e.printStackTrace(); } } } NitterAccount nitterAccount = accounts.get(feedItem.creator); if (nitterAccount != null) { app.fedilab.android.client.entities.api.Account account = new app.fedilab.android.client.entities.api.Account(); String[] names = nitterAccount.channel.image.title.split("/"); account.id = feedItem.guid; account.acct = names[1]; account.username = names[1]; account.display_name = names[0]; account.avatar = nitterAccount.channel.image.url; account.avatar_static = nitterAccount.channel.image.url; account.url = nitterAccount.channel.image.link; status.account = account; } Pattern imgPattern = Pattern.compile("<img [^>]*src=\"([^\"]+)\"[^>]*>"); Matcher matcher = imgPattern.matcher(feedItem.description); String description = feedItem.description; ArrayList<Attachment> attachmentList = new ArrayList<>(); while (matcher.find()) { description = description.replaceAll(Pattern.quote(matcher.group()), ""); Attachment attachment = new Attachment(); attachment.type = "image"; attachment.url = matcher.group(1); attachment.preview_url = matcher.group(1); attachment.id = matcher.group(1); attachmentList.add(attachment); } status.media_attachments = attachmentList; return status; } @Root(name = "channel", strict = false) public static class Channel implements Serializable { @ElementList(name = "item") public List<FeedItem> mFeedItems; } @Root(name = "item", strict = false) public static class FeedItem implements Serializable { @ElementList(name = "dc:creator", required = false) public String creator; @ElementList(name = "title") public String title; @ElementList(name = "description", required = false) public String description; @ElementList(name = "pubDate") public Date pubDate; @ElementList(name = "guid", required = false) public String guid; @ElementList(name = "link", required = false) public String link; } }
app/src/main/java/app/fedilab/android/client/entities/nitter/NitterAccount.java 0 → 100644 +36 −0 Original line number Diff line number Diff line package app.fedilab.android.client.entities.nitter; import org.simpleframework.xml.Element; import org.simpleframework.xml.Root; import java.io.Serializable; import java.util.HashMap; @Root(name = "rss", strict = false) public class NitterAccount implements Serializable { public static HashMap<String, NitterAccount> accounts = new HashMap<>(); @Element(name = "channel") public Channel channel; @Root(name = "channel", strict = false) public static class Channel implements Serializable { @Element(name = "image") public Image image; } @Root(name = "image", strict = false) public static class Image implements Serializable { @Element(name = "title") public String title; @Element(name = "url") public String url; @Element(name = "link") public String link; } }
app/src/main/java/app/fedilab/android/ui/drawer/StatusAdapter.java +1 −1 Original line number Diff line number Diff line Loading @@ -447,7 +447,7 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> attachment.peertubeId = matcherLink.group(3); attachmentList.add(attachment); statusToDeal.media_attachments = attachmentList; adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, statusToDeal)); //adapter.notifyItemChanged(getPositionAsync(notificationList, statusList, statusToDeal)); } } Loading