From 0796ff7b69b15faeeb817ea2ac8dc3c6a351c7a2 Mon Sep 17 00:00:00 2001 From: Thomas Date: Mon, 21 Nov 2022 17:43:29 +0100 Subject: [PATCH] Add classes and logic --- app/src/main/AndroidManifest.xml | 6 +- .../activities/SuggestionActivity.java | 64 ++++++++++++ .../endpoints/MastodonAccountsService.java | 3 +- .../client/entities/api/Suggestion.java | 27 +++++ .../client/entities/api/Suggestions.java | 22 +++++ .../android/client/entities/app/Timeline.java | 2 + .../timeline/FragmentMastodonAccount.java | 8 ++ .../viewmodel/mastodon/AccountsVM.java | 36 ++++--- .../viewmodel/mastodon/SuggestionVM.java | 98 +++++++++++++++++++ .../main/res/layout/activity_suggestions.xml | 31 ++++++ app/src/main/res/values/strings.xml | 1 + 11 files changed, 282 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/app/fedilab/android/activities/SuggestionActivity.java create mode 100644 app/src/main/java/app/fedilab/android/client/entities/api/Suggestion.java create mode 100644 app/src/main/java/app/fedilab/android/client/entities/api/Suggestions.java create mode 100644 app/src/main/java/app/fedilab/android/viewmodel/mastodon/SuggestionVM.java create mode 100644 app/src/main/res/layout/activity_suggestions.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8a5a34ba2..17bec2ac2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -243,7 +243,11 @@ android:configChanges="keyboardHidden|orientation|screenSize" android:label="@string/action_about" android:theme="@style/AppThemeBar" /> - + . */ + +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.view.MenuItem; + +import androidx.core.content.ContextCompat; + +import org.jetbrains.annotations.NotNull; + +import app.fedilab.android.R; +import app.fedilab.android.client.entities.app.Timeline; +import app.fedilab.android.databinding.ActivitySuggestionsBinding; +import app.fedilab.android.helper.Helper; +import app.fedilab.android.helper.ThemeHelper; +import app.fedilab.android.ui.fragment.timeline.FragmentMastodonAccount; + + +public class SuggestionActivity extends BaseActivity { + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ThemeHelper.applyThemeBar(this); + app.fedilab.android.databinding.ActivitySuggestionsBinding binding = ActivitySuggestionsBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + + if (getSupportActionBar() != null) { + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary))); + } + + Bundle bundle = new Bundle(); + bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.ACCOUNT_SUGGESTION); + Helper.addFragment(getSupportFragmentManager(), R.id.nav_host_fragment_tags, new FragmentMastodonAccount(), bundle, null, null); + } + + + @Override + public boolean onOptionsItemSelected(@NotNull MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + +} diff --git a/app/src/main/java/app/fedilab/android/client/endpoints/MastodonAccountsService.java b/app/src/main/java/app/fedilab/android/client/endpoints/MastodonAccountsService.java index b215079b5..499988c2b 100644 --- a/app/src/main/java/app/fedilab/android/client/endpoints/MastodonAccountsService.java +++ b/app/src/main/java/app/fedilab/android/client/endpoints/MastodonAccountsService.java @@ -25,6 +25,7 @@ import app.fedilab.android.client.entities.api.Preferences; import app.fedilab.android.client.entities.api.RelationShip; import app.fedilab.android.client.entities.api.Report; import app.fedilab.android.client.entities.api.Status; +import app.fedilab.android.client.entities.api.Suggestion; import app.fedilab.android.client.entities.api.Tag; import app.fedilab.android.client.entities.api.Token; import okhttp3.MultipartBody; @@ -391,7 +392,7 @@ public interface MastodonAccountsService { //Get user suggestions @GET("suggestions") - Call> getSuggestions( + Call> getSuggestions( @Header("Authorization") String token, @Query("limit") String limit ); diff --git a/app/src/main/java/app/fedilab/android/client/entities/api/Suggestion.java b/app/src/main/java/app/fedilab/android/client/entities/api/Suggestion.java new file mode 100644 index 000000000..d60128dd4 --- /dev/null +++ b/app/src/main/java/app/fedilab/android/client/entities/api/Suggestion.java @@ -0,0 +1,27 @@ +package app.fedilab.android.client.entities.api; + +import com.google.gson.annotations.SerializedName; + +import java.io.Serializable; + +/* Copyright 2022 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 . */ + +public class Suggestion implements Serializable { + @SerializedName("account") + public Account account; + @SerializedName("source") + public String source; +} diff --git a/app/src/main/java/app/fedilab/android/client/entities/api/Suggestions.java b/app/src/main/java/app/fedilab/android/client/entities/api/Suggestions.java new file mode 100644 index 000000000..1b29d7f6e --- /dev/null +++ b/app/src/main/java/app/fedilab/android/client/entities/api/Suggestions.java @@ -0,0 +1,22 @@ +package app.fedilab.android.client.entities.api; +/* Copyright 2022 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 . */ + +import java.util.List; + +public class Suggestions { + public Pagination pagination = new Pagination(); + public List suggestions; +} diff --git a/app/src/main/java/app/fedilab/android/client/entities/app/Timeline.java b/app/src/main/java/app/fedilab/android/client/entities/app/Timeline.java index d5d8ebf1c..a195daaa9 100644 --- a/app/src/main/java/app/fedilab/android/client/entities/app/Timeline.java +++ b/app/src/main/java/app/fedilab/android/client/entities/app/Timeline.java @@ -378,6 +378,8 @@ public class Timeline { TREND_TAG("TREND_TAG"), @SerializedName("TREND_MESSAGE") TREND_MESSAGE("TREND_MESSAGE"), + @SerializedName("ACCOUNT_SUGGESTION") + ACCOUNT_SUGGESTION("ACCOUNT_SUGGESTION"), @SerializedName("PUBLIC_TREND_MESSAGE") TREND_MESSAGE_PUBLIC("TREND_MESSAGE_PUBLIC"), @SerializedName("STATUS_HISTORY") diff --git a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java index 0d7f96942..f2e5fd4e3 100644 --- a/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java +++ b/app/src/main/java/app/fedilab/android/ui/fragment/timeline/FragmentMastodonAccount.java @@ -143,6 +143,14 @@ public class FragmentMastodonAccount extends Fragment { accountsVM.getBlocks(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, String.valueOf(MastodonHelper.accountsPerCall(requireActivity())), max_id, null) .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); } + } else if (timelineType == Timeline.TimeLineEnum.ACCOUNT_SUGGESTION) { + if (firstLoad) { + accountsVM.getSuggestions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, null) + .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); + } else { + accountsVM.getSuggestions(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, max_id) + .observe(getViewLifecycleOwner(), this::initializeAccountCommonView); + } } } diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java index 037da464c..627f6f5df 100644 --- a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/AccountsVM.java @@ -26,9 +26,6 @@ import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - import java.util.LinkedHashMap; import java.util.List; import java.util.concurrent.TimeUnit; @@ -50,6 +47,8 @@ import app.fedilab.android.client.entities.api.Report; import app.fedilab.android.client.entities.api.Source; import app.fedilab.android.client.entities.api.Status; import app.fedilab.android.client.entities.api.Statuses; +import app.fedilab.android.client.entities.api.Suggestion; +import app.fedilab.android.client.entities.api.Suggestions; import app.fedilab.android.client.entities.api.Tag; import app.fedilab.android.client.entities.api.Token; import app.fedilab.android.client.entities.app.StatusCache; @@ -75,6 +74,7 @@ public class AccountsVM extends AndroidViewModel { private MutableLiveData accountMutableLiveData; private MutableLiveData> accountListMutableLiveData; + private MutableLiveData suggestionsMutableLiveData; private MutableLiveData statusesMutableLiveData; private MutableLiveData accountsMutableLiveData; private MutableLiveData> statusListMutableLiveData; @@ -97,7 +97,6 @@ public class AccountsVM extends AndroidViewModel { } private MastodonAccountsService init(String instance) { - Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://" + instance + "/api/v1/") .addConverterFactory(GsonConverterFactory.create(Helper.getDateBuilder())) @@ -106,6 +105,15 @@ public class AccountsVM extends AndroidViewModel { return retrofit.create(MastodonAccountsService.class); } + private MastodonAccountsService initv2(String instance) { + Retrofit retrofit = new Retrofit.Builder() + .baseUrl("https://" + instance + "/api/v2/") + .addConverterFactory(GsonConverterFactory.create(Helper.getDateBuilder())) + .client(okHttpClient) + .build(); + return retrofit.create(MastodonAccountsService.class); + } + /** * Get connected account * @@ -1393,28 +1401,28 @@ public class AccountsVM extends AndroidViewModel { * @param limit Maximum number of results to return. Defaults to 40. * @return {@link LiveData} containing a {@link List} of {@link Account}s */ - public LiveData> getSuggestions(@NonNull String instance, String token, String limit) { - accountListMutableLiveData = new MutableLiveData<>(); - MastodonAccountsService mastodonAccountsService = init(instance); + public LiveData getSuggestions(@NonNull String instance, String token, String limit) { + suggestionsMutableLiveData = new MutableLiveData<>(); + MastodonAccountsService mastodonAccountsService = initv2(instance); new Thread(() -> { - List accountList = null; - Call> suggestionsCall = mastodonAccountsService.getSuggestions(token, limit); + Call> suggestionsCall = mastodonAccountsService.getSuggestions(token, limit); + Suggestions suggestions = new Suggestions(); if (suggestionsCall != null) { try { - Response> suggestionsResponse = suggestionsCall.execute(); + Response> suggestionsResponse = suggestionsCall.execute(); if (suggestionsResponse.isSuccessful()) { - accountList = suggestionsResponse.body(); + suggestions.pagination = MastodonHelper.getOffSetPagination(suggestionsResponse.headers()); + suggestions.suggestions = suggestionsResponse.body(); } } catch (Exception e) { e.printStackTrace(); } } Handler mainHandler = new Handler(Looper.getMainLooper()); - List finalAccountList = accountList; - Runnable myRunnable = () -> accountListMutableLiveData.setValue(finalAccountList); + Runnable myRunnable = () -> suggestionsMutableLiveData.setValue(suggestions); mainHandler.post(myRunnable); }).start(); - return accountListMutableLiveData; + return suggestionsMutableLiveData; } /** diff --git a/app/src/main/java/app/fedilab/android/viewmodel/mastodon/SuggestionVM.java b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/SuggestionVM.java new file mode 100644 index 000000000..04a0ac13f --- /dev/null +++ b/app/src/main/java/app/fedilab/android/viewmodel/mastodon/SuggestionVM.java @@ -0,0 +1,98 @@ +package app.fedilab.android.viewmodel.mastodon; +/* Copyright 2022 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 . */ + + +import android.app.Application; +import android.os.Handler; +import android.os.Looper; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +import app.fedilab.android.client.endpoints.MastodonFiltersService; +import app.fedilab.android.client.endpoints.MastodonTimelinesService; +import app.fedilab.android.client.entities.api.Filter; +import app.fedilab.android.client.entities.api.Status; +import app.fedilab.android.client.entities.api.Statuses; +import app.fedilab.android.client.entities.app.Timeline; +import app.fedilab.android.helper.Helper; +import app.fedilab.android.helper.MastodonHelper; +import app.fedilab.android.helper.TimelineHelper; +import okhttp3.OkHttpClient; +import retrofit2.Call; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +public class SuggestionVM extends AndroidViewModel { + + + final OkHttpClient okHttpClient = new OkHttpClient.Builder() + .readTimeout(60, TimeUnit.SECONDS) + .connectTimeout(60, TimeUnit.SECONDS) + .callTimeout(60, TimeUnit.SECONDS) + .proxy(Helper.getProxy(getApplication().getApplicationContext())) + .build(); + + + private MutableLiveData filterMutableLiveData; + private MutableLiveData> filterListMutableLiveData; + + public SuggestionVM(@NonNull Application application) { + super(application); + } + + private MastodonFiltersService initV2(String instance) { + Retrofit retrofit = new Retrofit.Builder() + .baseUrl("https://" + instance + "/api/v2/") + // .addConverterFactory(GsonConverterFactory.create(Helper.getDateBuilder())) + .addConverterFactory(GsonConverterFactory.create()) + .client(okHttpClient) + .build(); + return retrofit.create(MastodonFiltersService.class); + } + + + public LiveData getSuggestions(String token, @NonNull String instance, String max_id, Integer limit) { + MastodonTimelinesService mastodonTimelinesService = initV2(instance); + statusesMutableLiveData = new MutableLiveData<>(); + new Thread(() -> { + Call> publicTlCall = mastodonTimelinesService.getStatusTrends(token, max_id, limit); + Statuses statuses = new Statuses(); + if (publicTlCall != null) { + try { + Response> publicTlResponse = publicTlCall.execute(); + if (publicTlResponse.isSuccessful()) { + List 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()); + Runnable myRunnable = () -> statusesMutableLiveData.setValue(statuses); + mainHandler.post(myRunnable); + }).start(); + return statusesMutableLiveData; + } +} diff --git a/app/src/main/res/layout/activity_suggestions.xml b/app/src/main/res/layout/activity_suggestions.xml new file mode 100644 index 000000000..74fb10e77 --- /dev/null +++ b/app/src/main/res/layout/activity_suggestions.xml @@ -0,0 +1,31 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 502ec56ff..558d5b55e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1904,4 +1904,5 @@ Delete timeline Submitted a report Signed up + Suggestions \ No newline at end of file