From ceb16a7b23dfc8f45d0e26085b8cde2c13f26b50 Mon Sep 17 00:00:00 2001 From: Thomas Date: Fri, 29 Jan 2021 18:02:32 +0100 Subject: [PATCH] More Pixelfed improvements --- app/build.gradle | 4 +- .../android/drawers/StatusListAdapter.java | 1 + app/src/main/AndroidManifest.xml | 5 + .../android/activities/BaseMainActivity.java | 24 +- .../android/activities/BookmarkActivity.java | 25 +- .../activities/LiveBookmarkActivity.java | 319 +++++---- .../android/activities/LoginActivity.java | 18 +- .../activities/ShowConversationActivity.java | 158 +++-- .../RetrieveAccountsForReplyAsyncTask.java | 4 +- .../asynctasks/RetrieveContextAsyncTask.java | 8 +- .../asynctasks/RetrieveFeedsAsyncTask.java | 41 +- .../asynctasks/SyncBookmarksAsyncTask.java | 14 - .../java/app/fedilab/android/client/API.java | 81 ++- .../android/client/Entities/Status.java | 12 +- .../fedilab/android/client/PixelfedAPI.java | 24 +- .../android/drawers/PixelfedListAdapter.java | 645 ++++++++---------- .../android/drawers/SliderAdapter.java | 1 - .../fragments/ContentSettingsFragment.java | 3 - .../DisplayBookmarksPixelfedFragment.java | 13 +- .../fragments/DisplayStatusFragment.java | 6 +- .../fedilab/android/helper/BaseHelper.java | 14 +- .../fedilab/android/helper/CrossActions.java | 60 ++ app/src/main/res/layout/activity_about.xml | 11 - .../res/layout/activity_live_bookmark.xml | 52 +- .../res/layout/activity_show_conversation.xml | 25 +- app/src/main/res/layout/drawer_pixelfed.xml | 155 +++-- .../res/layout/drawer_pixelfed_comment.xml | 240 ++----- .../res/layout/fragment_settings_menu.xml | 22 - .../main/res/menu/activity_main_drawer.xml | 16 - app/src/main/res/menu/bookmarks.xml | 7 +- app/src/main/res/menu/option_pixelfed.xml | 47 -- 31 files changed, 1014 insertions(+), 1041 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 67770a5d1..0decc8ecc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -57,7 +57,9 @@ android { resValue "string", "app_name", "Fedilab" } } - + buildFeatures { + viewBinding = true + } sourceSets { playstore { manifest.srcFile "src/common/AndroidManifest.xml" diff --git a/app/src/common/java/app/fedilab/android/drawers/StatusListAdapter.java b/app/src/common/java/app/fedilab/android/drawers/StatusListAdapter.java index 4dd77b9b8..9fd0b3e1d 100644 --- a/app/src/common/java/app/fedilab/android/drawers/StatusListAdapter.java +++ b/app/src/common/java/app/fedilab/android/drawers/StatusListAdapter.java @@ -33,6 +33,7 @@ import app.fedilab.android.client.Entities.StatusDrawerParams; import static android.content.Context.INPUT_METHOD_SERVICE; public class StatusListAdapter extends BaseStatusListAdapter { + public StatusListAdapter(StatusDrawerParams statusDrawerParams) { super(statusDrawerParams); } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e370273dc..140b7d0cb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -351,6 +351,11 @@ android:configChanges="orientation|screenSize" android:theme="@style/AppThemeDark_NoActionBar" android:windowSoftInputMode="stateAlwaysHidden" /> + . */ package app.fedilab.android.activities; -import android.content.Context; import android.content.SharedPreferences; import android.database.sqlite.SQLiteDatabase; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.view.LayoutInflater; -import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; -import android.widget.RelativeLayout; import android.widget.TextView; +import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; -import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.google.android.material.floatingactionbutton.FloatingActionButton; - -import org.jetbrains.annotations.NotNull; +import com.bumptech.glide.Glide; +import com.bumptech.glide.ListPreloader; +import com.bumptech.glide.RequestBuilder; +import com.bumptech.glide.integration.recyclerview.RecyclerViewPreloader; +import com.bumptech.glide.util.FixedPreloadSizeProvider; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import app.fedilab.android.R; -import app.fedilab.android.asynctasks.PostActionAsyncTask; import app.fedilab.android.asynctasks.RetrieveFeedsAsyncTask; -import app.fedilab.android.asynctasks.SyncBookmarksAsyncTask; -import app.fedilab.android.client.API; +import app.fedilab.android.asynctasks.UpdateAccountInfoAsyncTask; import app.fedilab.android.client.APIResponse; import app.fedilab.android.client.Entities.Account; +import app.fedilab.android.client.Entities.Attachment; import app.fedilab.android.client.Entities.Status; import app.fedilab.android.client.Entities.StatusDrawerParams; +import app.fedilab.android.databinding.ActivityLiveBookmarkBinding; +import app.fedilab.android.drawers.PixelfedListAdapter; import app.fedilab.android.drawers.StatusListAdapter; +import app.fedilab.android.fragments.DisplayStatusFragment; import app.fedilab.android.helper.Helper; import app.fedilab.android.interfaces.OnRetrieveFeedsInterface; -import app.fedilab.android.interfaces.OnSyncBookmarksInterface; import app.fedilab.android.sqlite.AccountDAO; import app.fedilab.android.sqlite.Sqlite; +import es.dmoral.toasty.Toasty; /** - * Created by Thomas on 15/11/2019. - * Bookmark activity + * Created by Thomas on 28/01/2021. + * Bookmark activity that are directly taken from the server */ -public class BookmarkActivity extends BaseActivity implements OnRetrieveFeedsInterface, OnSyncBookmarksInterface { +public class LiveBookmarkActivity extends BaseActivity implements OnRetrieveFeedsInterface { private List statuses; private StatusListAdapter statusListAdapter; - private RelativeLayout textviewNoAction; - private RelativeLayout mainLoader; - private RecyclerView lv_status; + private PixelfedListAdapter pixelfedListAdapter; private ImageView pp_actionBar; + private ActivityLiveBookmarkBinding binding; + private boolean isSwipped, flag_loading, firstLoad; + private String max_id; @Override protected void onCreate(Bundle savedInstanceState) { @@ -89,16 +93,23 @@ public class BookmarkActivity extends BaseActivity implements OnRetrieveFeedsInt default: setTheme(R.style.AppThemeDark_NoActionBar); } - setContentView(R.layout.activity_bookmark); - Toolbar toolbar = findViewById(R.id.toolbar); - setSupportActionBar(toolbar); + + isSwipped = false; + max_id = null; + flag_loading = true; + firstLoad = true; + + binding = ActivityLiveBookmarkBinding.inflate(getLayoutInflater()); + View viewRoot = binding.getRoot(); + setContentView(viewRoot); + setSupportActionBar(binding.toolbar); ActionBar actionBar = getSupportActionBar(); if (actionBar != null) { LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE); assert inflater != null; - View view = inflater.inflate(R.layout.simple_action_bar, new LinearLayout(BookmarkActivity.this), false); - toolbar.setBackgroundColor(ContextCompat.getColor(BookmarkActivity.this, R.color.cyanea_primary)); - view.setBackground(new ColorDrawable(ContextCompat.getColor(BookmarkActivity.this, R.color.cyanea_primary))); + View view = inflater.inflate(R.layout.simple_action_bar, new LinearLayout(LiveBookmarkActivity.this), false); + binding.toolbar.setBackgroundColor(ContextCompat.getColor(LiveBookmarkActivity.this, R.color.cyanea_primary)); + view.setBackground(new ColorDrawable(ContextCompat.getColor(LiveBookmarkActivity.this, R.color.cyanea_primary))); actionBar.setCustomView(view, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); TextView title = actionBar.getCustomView().findViewById(R.id.toolbar_title); @@ -115,16 +126,76 @@ public class BookmarkActivity extends BaseActivity implements OnRetrieveFeedsInt SQLiteDatabase db = Sqlite.getInstance(getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); String instance = sharedpreferences.getString(Helper.PREF_INSTANCE, null); - Account account = new AccountDAO(BookmarkActivity.this, db).getUniqAccount(userId, instance); + Account account = new AccountDAO(LiveBookmarkActivity.this, db).getUniqAccount(userId, instance); - Helper.loadGiF(BookmarkActivity.this, account, pp_actionBar); + Helper.loadGiF(LiveBookmarkActivity.this, account, pp_actionBar); - lv_status = findViewById(R.id.lv_status); + binding.loader.setVisibility(View.VISIBLE); + + this.statuses = new ArrayList<>(); + + boolean isOnWifi = Helper.isOnWIFI(LiveBookmarkActivity.this); + StatusDrawerParams statusDrawerParams = new StatusDrawerParams(); + statusDrawerParams.setType(RetrieveFeedsAsyncTask.Type.BOOKMARKS); + statusDrawerParams.setOnWifi(isOnWifi); + statusDrawerParams.setStatuses(this.statuses); + + if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { + statusListAdapter = new StatusListAdapter(statusDrawerParams); + binding.lvStatus.setAdapter(statusListAdapter); + } else { + pixelfedListAdapter = new PixelfedListAdapter(statusDrawerParams); + binding.lvStatus.setAdapter(pixelfedListAdapter); + } + LinearLayoutManager mLayoutManager = new LinearLayoutManager(LiveBookmarkActivity.this); + binding.lvStatus.setLayoutManager(mLayoutManager); + + ListPreloader.PreloadSizeProvider sizeProvider = + new FixedPreloadSizeProvider(640, 480); + ListPreloader.PreloadModelProvider modelProvider = new MyPreloadModelProvider(); + RecyclerViewPreloader preloader = + new RecyclerViewPreloader<>(Glide.with(LiveBookmarkActivity.this), modelProvider, sizeProvider, 20); + binding.lvStatus.addOnScrollListener(preloader); + + binding.swipeContainer.setOnRefreshListener(() -> { + if (statuses.size() > 0) { + int size = statuses.size(); + isSwipped = true; + statuses.clear(); + statuses = new ArrayList<>(); + max_id = null; + if (statusListAdapter != null) { + statusListAdapter.notifyItemRangeRemoved(0, size); + } else if (pixelfedListAdapter != null) { + pixelfedListAdapter.notifyItemRangeRemoved(0, size); + } + firstLoad = true; + new RetrieveFeedsAsyncTask(LiveBookmarkActivity.this, RetrieveFeedsAsyncTask.Type.BOOKMARKS, null, LiveBookmarkActivity.this); + } + + }); + + binding.lvStatus.addOnScrollListener(new RecyclerView.OnScrollListener() { + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition(); + if (dy > 0) { + int visibleItemCount = mLayoutManager.getChildCount(); + int totalItemCount = mLayoutManager.getItemCount(); + if (firstVisibleItem + visibleItemCount == totalItemCount) { + if (!flag_loading) { + flag_loading = true; + new RetrieveFeedsAsyncTask(LiveBookmarkActivity.this, RetrieveFeedsAsyncTask.Type.BOOKMARKS, max_id, LiveBookmarkActivity.this); + binding.loadingNextStatus.setVisibility(View.VISIBLE); + } + } else { + binding.loadingNextStatus.setVisibility(View.GONE); + } + } + } + }); + + new RetrieveFeedsAsyncTask(LiveBookmarkActivity.this, RetrieveFeedsAsyncTask.Type.BOOKMARKS, null, LiveBookmarkActivity.this); - mainLoader = findViewById(R.id.loader); - textviewNoAction = findViewById(R.id.no_action); - mainLoader.setVisibility(View.VISIBLE); - new RetrieveFeedsAsyncTask(BookmarkActivity.this, RetrieveFeedsAsyncTask.Type.CACHE_BOOKMARKS, null, BookmarkActivity.this); } @@ -135,103 +206,113 @@ public class BookmarkActivity extends BaseActivity implements OnRetrieveFeedsInt if (itemId == android.R.id.home) { finish(); return true; - } else if (itemId == R.id.action_import_bookmarks) { - new SyncBookmarksAsyncTask(BookmarkActivity.this, SyncBookmarksAsyncTask.sync.IMPORT, BookmarkActivity.this); - return true; } return super.onOptionsItemSelected(item); } - @Override - public boolean onCreateOptionsMenu(@NotNull Menu menu) { - getMenuInflater().inflate(R.menu.bookmarks, menu); - return true; - } - - - @Override - public void onResume() { - super.onResume(); - } - - @Override public void onRetrieveFeeds(APIResponse apiResponse) { - mainLoader.setVisibility(View.GONE); - FloatingActionButton delete_all = null; - try { - delete_all = findViewById(R.id.delete_all); - } catch (Exception ignored) { - } - final boolean isOnWifi = Helper.isOnWIFI(BookmarkActivity.this); - statuses = apiResponse.getStatuses(); - if (statuses != null && statuses.size() > 0) { - LinearLayoutManager mLayoutManager = new LinearLayoutManager(BookmarkActivity.this); - StatusDrawerParams statusDrawerParams = new StatusDrawerParams(); - statusDrawerParams.setType(RetrieveFeedsAsyncTask.Type.CACHE_BOOKMARKS); - statusDrawerParams.setTargetedId(null); - statusDrawerParams.setOnWifi(isOnWifi); - statusDrawerParams.setStatuses(this.statuses); - statusListAdapter = new StatusListAdapter(statusDrawerParams); - lv_status.setAdapter(statusListAdapter); - lv_status.setLayoutManager(mLayoutManager); - } else { - textviewNoAction.setVisibility(View.VISIBLE); - } - - if (delete_all != null) - delete_all.setOnClickListener(view -> { - final SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); - int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); - int style; - if (theme == Helper.THEME_DARK) { - style = R.style.DialogDark; - } else if (theme == Helper.THEME_BLACK) { - style = R.style.DialogBlack; + binding.loader.setVisibility(View.GONE); + binding.loadingNextStatus.setVisibility(View.GONE); + //handle other API error but discards 404 - error which can often happen due to toots which have been deleted + if (this.statuses == null || apiResponse == null || (apiResponse.getError() != null && apiResponse.getError().getStatusCode() != 404 && apiResponse.getError().getStatusCode() != 501)) { + if (apiResponse == null) + Toasty.error(LiveBookmarkActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show(); + else { + if (apiResponse.getError().getError().length() < 100) { + Toasty.error(LiveBookmarkActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); } else { - style = R.style.Dialog; + Toasty.error(LiveBookmarkActivity.this, getString(R.string.long_api_error, "\ud83d\ude05"), Toast.LENGTH_LONG).show(); } - AlertDialog.Builder builder = new AlertDialog.Builder(BookmarkActivity.this, style); - builder.setTitle(R.string.delete_all); - builder.setIcon(android.R.drawable.ic_dialog_alert) - .setPositiveButton(R.string.yes, (dialogConfirm, which) -> { - statuses = new ArrayList<>(); - statuses.clear(); - StatusDrawerParams statusDrawerParams = new StatusDrawerParams(); - statusDrawerParams.setType(RetrieveFeedsAsyncTask.Type.CACHE_BOOKMARKS); - statusDrawerParams.setTargetedId(null); - statusDrawerParams.setOnWifi(isOnWifi); - statusDrawerParams.setStatuses(this.statuses); - statusListAdapter = new StatusListAdapter(statusDrawerParams); - lv_status.setAdapter(statusListAdapter); - statusListAdapter.notifyDataSetChanged(); - textviewNoAction.setVisibility(View.VISIBLE); - new PostActionAsyncTask(BookmarkActivity.this, API.StatusAction.UNBOOKMARK); - dialogConfirm.dismiss(); - }) - .setNegativeButton(R.string.no, (dialogConfirm, which) -> dialogConfirm.dismiss()) - .show(); - }); - } + } + binding.swipeContainer.setRefreshing(false); + flag_loading = false; + return; + } - @Override - public void onRetrieveBookmarks(List bookmarks) { - if (bookmarks != null) { - statuses = new ArrayList<>(); - statuses.clear(); - statuses.addAll(bookmarks); - final boolean isOnWifi = Helper.isOnWIFI(BookmarkActivity.this); - StatusDrawerParams statusDrawerParams = new StatusDrawerParams(); - statusDrawerParams.setType(RetrieveFeedsAsyncTask.Type.CACHE_BOOKMARKS); - statusDrawerParams.setTargetedId(null); - statusDrawerParams.setOnWifi(isOnWifi); - statusDrawerParams.setStatuses(this.statuses); - statusListAdapter = new StatusListAdapter(statusDrawerParams); - lv_status.setAdapter(statusListAdapter); - statusListAdapter.notifyDataSetChanged(); - if (statuses.size() == 0) { - textviewNoAction.setVisibility(View.VISIBLE); + int previousPosition = this.statuses.size(); + List statuses; + + if (apiResponse.getResults() != null && apiResponse.getResults().getStatuses() != null) + statuses = apiResponse.getResults().getStatuses(); + else + statuses = apiResponse.getStatuses(); + + //At this point all statuses are in "List statuses" + max_id = apiResponse.getMax_id(); + + //while max_id is different from null, there are some more toots to load when scrolling + flag_loading = (max_id == null); + //If it's the first load and the reply doesn't contain any toots, a message is displayed. + if (firstLoad && (statuses == null || statuses.size() == 0)) { + binding.noAction.setVisibility(View.VISIBLE); + binding.lvStatus.setVisibility(View.GONE); + } else { + binding.lvStatus.setVisibility(View.VISIBLE); + binding.noAction.setVisibility(View.GONE); + } + + //Let's deal with statuses + if (statuses != null && statuses.size() > 0) { + this.statuses.addAll(statuses); + if (!isSwipped) { + if (statusListAdapter != null) { + statusListAdapter.notifyItemRangeInserted(previousPosition, statuses.size()); + } else if (pixelfedListAdapter != null) { + + pixelfedListAdapter.notifyItemRangeInserted(previousPosition, statuses.size()); + } + } else { + isSwipped = false; + boolean isOnWifi = Helper.isOnWIFI(LiveBookmarkActivity.this); + StatusDrawerParams statusDrawerParams = new StatusDrawerParams(); + statusDrawerParams.setType(RetrieveFeedsAsyncTask.Type.BOOKMARKS); + statusDrawerParams.setOnWifi(isOnWifi); + statusDrawerParams.setStatuses(this.statuses); + + if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { + statusListAdapter = new StatusListAdapter(statusDrawerParams); + binding.lvStatus.setAdapter(statusListAdapter); + } else { + pixelfedListAdapter = new PixelfedListAdapter(statusDrawerParams); + binding.lvStatus.setAdapter(pixelfedListAdapter); + } + LinearLayoutManager mLayoutManager = new LinearLayoutManager(LiveBookmarkActivity.this); + binding.lvStatus.setLayoutManager(mLayoutManager); } } + binding.swipeContainer.setRefreshing(false); + firstLoad = false; + + } + + + private class MyPreloadModelProvider implements ListPreloader.PreloadModelProvider { + @Override + @NonNull + public List getPreloadItems(int position) { + if (statuses == null || statuses.size() == 0) { + return Collections.emptyList(); + } + Status status = statuses.get(position); + if (status.getMedia_attachments() == null || status.getMedia_attachments().size() == 0) { + return Collections.emptyList(); + } + List preloaded_urls = new ArrayList<>(); + for (Attachment attachment : status.getMedia_attachments()) { + preloaded_urls.add(attachment.getPreview_url()); + } + return preloaded_urls; + } + + @Nullable + @Override + public RequestBuilder getPreloadRequestBuilder(@NonNull String url) { + return Glide.with(LiveBookmarkActivity.this) + .load(url) + .thumbnail(0.1f) + .override(640, 480); + } + } } diff --git a/app/src/main/java/app/fedilab/android/activities/LoginActivity.java b/app/src/main/java/app/fedilab/android/activities/LoginActivity.java index c6446b8ed..62ac6706a 100644 --- a/app/src/main/java/app/fedilab/android/activities/LoginActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/LoginActivity.java @@ -650,16 +650,14 @@ public class LoginActivity extends BaseActivity { e.printStackTrace(); runOnUiThread(() -> { connectionButton.setEnabled(true); - runOnUiThread(() -> { - String message; - if (e.getLocalizedMessage() != null && e.getLocalizedMessage().trim().length() > 0) - message = e.getLocalizedMessage(); - else if (e.getMessage() != null && e.getMessage().trim().length() > 0) - message = e.getMessage(); - else - message = getString(R.string.client_error); - Toasty.error(LoginActivity.this, message, Toast.LENGTH_LONG).show(); - }); + String message; + if (e.getLocalizedMessage() != null && e.getLocalizedMessage().trim().length() > 0) + message = e.getLocalizedMessage(); + else if (e.getMessage() != null && e.getMessage().trim().length() > 0) + message = e.getMessage(); + else + message = getString(R.string.client_error); + Toasty.error(LoginActivity.this, message, Toast.LENGTH_LONG).show(); }); } }).start(); diff --git a/app/src/main/java/app/fedilab/android/activities/ShowConversationActivity.java b/app/src/main/java/app/fedilab/android/activities/ShowConversationActivity.java index 6f571c08d..5f41bc550 100644 --- a/app/src/main/java/app/fedilab/android/activities/ShowConversationActivity.java +++ b/app/src/main/java/app/fedilab/android/activities/ShowConversationActivity.java @@ -23,18 +23,16 @@ import android.database.sqlite.SQLiteDatabase; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.view.View; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; import android.widget.Toast; -import androidx.appcompat.widget.Toolbar; import androidx.core.content.ContextCompat; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import org.json.JSONException; +import org.json.JSONObject; + import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; @@ -47,6 +45,9 @@ import app.fedilab.android.client.APIResponse; import app.fedilab.android.client.Entities.Account; import app.fedilab.android.client.Entities.Status; import app.fedilab.android.client.Entities.StatusDrawerParams; +import app.fedilab.android.client.PixelfedAPI; +import app.fedilab.android.databinding.ActivityShowConversationBinding; +import app.fedilab.android.drawers.PixelfedListAdapter; import app.fedilab.android.drawers.StatusListAdapter; import app.fedilab.android.helper.Helper; import app.fedilab.android.interfaces.OnRetrieveContextInterface; @@ -66,19 +67,18 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve private Status initialStatus; private Status detailsStatus; private SwipeRefreshLayout swipeRefreshLayout; - private RecyclerView lv_status; private List statuses; private StatusListAdapter statusListAdapter; + private PixelfedListAdapter pixelfedListAdapter; private boolean expanded; private BroadcastReceiver receive_action; private String conversationId; private boolean spoilerShown, spoilerBehaviour; - private LinearLayout loader; + private ActivityShowConversationBinding binding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); switch (theme) { @@ -91,8 +91,10 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve default: setTheme(R.style.AppThemeDark_NoActionBar); } - setContentView(R.layout.activity_show_conversation); - lv_status = findViewById(R.id.lv_status); + binding = ActivityShowConversationBinding.inflate(getLayoutInflater()); + View viewRoot = binding.getRoot(); + setContentView(viewRoot); + spoilerShown = spoilerBehaviour = sharedpreferences.getBoolean(Helper.SET_EXPAND_CW, false); Bundle b = getIntent().getExtras(); statuses = new ArrayList<>(); @@ -105,8 +107,8 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve if (detailsStatus == null || detailsStatus.getId() == null) finish(); - loader = findViewById(R.id.loader); - loader.setVisibility(View.VISIBLE); + + binding.loader.setVisibility(View.VISIBLE); detailsStatus.setFocused(true); //Some spannable Status.fillSpan(new WeakReference<>(ShowConversationActivity.this), detailsStatus); @@ -123,35 +125,30 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve Status status = b.getParcelable("status"); if (status != null && statusListAdapter != null) { statusListAdapter.notifyStatusChanged(status); + } else if (status != null && pixelfedListAdapter != null) { + pixelfedListAdapter.notifyStatusChanged(status); } } }; LocalBroadcastManager.getInstance(ShowConversationActivity.this).registerReceiver(receive_action, new IntentFilter(Helper.RECEIVE_ACTION)); } - Toolbar actionBar = findViewById(R.id.toolbar); - if (actionBar != null) { - actionBar.setBackground(new ColorDrawable(ContextCompat.getColor(ShowConversationActivity.this, R.color.cyanea_primary))); - } - TextView title = findViewById(R.id.toolbar_title); - ImageView pp_actionBar = findViewById(R.id.pp_actionBar); - ImageView action_refresh = findViewById(R.id.action_refresh); - ImageView action_expand = findViewById(R.id.action_expand); - title.setText(R.string.conversation); - ImageView close_conversation = findViewById(R.id.close_conversation); - ImageView action_unhide = findViewById(R.id.action_unhide); + + binding.incToolbar.toolbar.setBackground(new ColorDrawable(ContextCompat.getColor(ShowConversationActivity.this, R.color.cyanea_primary))); + binding.incToolbar.toolbarTitle.setText(R.string.conversation); if (expanded) - action_expand.setImageResource(R.drawable.ic_expand_less); + binding.incToolbar.actionExpand.setImageResource(R.drawable.ic_expand_less); else - action_expand.setImageResource(R.drawable.ic_expand_more); - title.setOnClickListener(view -> { - if (lv_status != null) { - lv_status.setAdapter(statusListAdapter); + binding.incToolbar.actionExpand.setImageResource(R.drawable.ic_expand_more); + //Scroll to top + binding.incToolbar.toolbarTitle.setOnClickListener(view -> { + if (statusListAdapter != null) { + binding.lvStatus.setAdapter(statusListAdapter); + } else if (pixelfedListAdapter != null) { + binding.lvStatus.setAdapter(pixelfedListAdapter); } }); - if (close_conversation != null) { - close_conversation.setOnClickListener(v -> finish()); - } - action_refresh.setOnClickListener(view -> { + binding.incToolbar.closeConversation.setOnClickListener(v -> finish()); + binding.incToolbar.actionRefresh.setOnClickListener(view -> { Intent intent = new Intent(ShowConversationActivity.this, ShowConversationActivity.class); Bundle b1 = new Bundle(); b1.putParcelable("status", detailsStatus); @@ -164,7 +161,7 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); }); - action_unhide.setOnClickListener(v -> { + binding.incToolbar.actionUnhide.setOnClickListener(v -> { if (statuses != null && statuses.size() > 0) { spoilerShown = !spoilerShown; for (Status status : statuses) { @@ -172,11 +169,15 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve status.setSpoilerShown(spoilerShown); status.setShowSpoiler(spoilerShown); } - statusListAdapter.notifyItemRangeChanged(0, statuses.size()); + if (statusListAdapter != null) { + statusListAdapter.notifyItemRangeChanged(0, statuses.size()); + } else if (pixelfedListAdapter != null) { + pixelfedListAdapter.notifyItemRangeChanged(0, statuses.size()); + } } }); - action_expand.setOnClickListener(v -> { + binding.incToolbar.actionExpand.setOnClickListener(v -> { expanded = !expanded; Intent intent = new Intent(ShowConversationActivity.this, ShowConversationActivity.class); Bundle b12 = new Bundle(); @@ -199,7 +200,7 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve Toasty.error(ShowConversationActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show(); finish(); } - Helper.loadGiF(ShowConversationActivity.this, account, pp_actionBar); + Helper.loadGiF(ShowConversationActivity.this, account, binding.incToolbar.ppActionBar); swipeRefreshLayout = findViewById(R.id.swipeContainer); @@ -222,12 +223,19 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve statusDrawerParams.setOnWifi(isOnWifi); statusDrawerParams.setStatuses(statuses); statusDrawerParams.setType(RetrieveFeedsAsyncTask.Type.CONTEXT); - statusListAdapter = new StatusListAdapter(statusDrawerParams); final LinearLayoutManager mLayoutManager; mLayoutManager = new LinearLayoutManager(this); - lv_status.setLayoutManager(mLayoutManager); - lv_status.setAdapter(statusListAdapter); + binding.lvStatus.setLayoutManager(mLayoutManager); + if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { + pixelfedListAdapter = new PixelfedListAdapter(statusDrawerParams); + binding.lvStatus.setAdapter(pixelfedListAdapter); + } else { + statusListAdapter = new StatusListAdapter(statusDrawerParams); + binding.lvStatus.setAdapter(statusListAdapter); + } + + String statusIdToFetch = null; if (initialStatus != null) statusIdToFetch = initialStatus.getId(); @@ -238,7 +246,7 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve if (conversationId != null) statusIdToFetch = conversationId; - new RetrieveContextAsyncTask(ShowConversationActivity.this, expanded, detailsStatus.getVisibility().equals("direct"), statusIdToFetch, ShowConversationActivity.this); + new RetrieveContextAsyncTask(ShowConversationActivity.this, expanded, detailsStatus.getVisibility().equals("direct"), detailsStatus.getAccount().getId(), statusIdToFetch, ShowConversationActivity.this); swipeRefreshLayout.setDistanceToTriggerSync(500); swipeRefreshLayout.setOnRefreshListener(() -> { Intent intent = new Intent(ShowConversationActivity.this, ShowConversationActivity.class); @@ -254,6 +262,23 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); }); + //Searching some pixelfed info (bookmarked?) + if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { + new Thread(() -> { + JSONObject result = new PixelfedAPI(ShowConversationActivity.this).getPostDetails(detailsStatus.getAccount().getUsername(), detailsStatus.getId()); + if (result != null && result.has("bookmarked")) { + try { + boolean bookmarked = result.getBoolean("bookmarked"); + statuses.get(0).setBookmarked(bookmarked); + runOnUiThread(() -> { + pixelfedListAdapter.notifyItemChanged(0); + }); + } catch (JSONException e) { + e.printStackTrace(); + } + } + }).start(); + } } @@ -263,7 +288,11 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve for (Status s : this.statuses) { if (status.getIn_reply_to_id().equals(s.getId())) { this.statuses.add(position + 1, status); - statusListAdapter.notifyItemInserted(position + 1); + if (statusListAdapter != null) { + statusListAdapter.notifyItemInserted(position + 1); + } else if (pixelfedListAdapter != null) { + pixelfedListAdapter.notifyItemInserted(position + 1); + } break; } position++; @@ -291,7 +320,7 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve @Override public void onRetrieveContext(APIResponse apiResponse) { swipeRefreshLayout.setRefreshing(false); - loader.setVisibility(View.GONE); + binding.loader.setVisibility(View.GONE); if (apiResponse.getError() != null) { if (apiResponse.getError().getError() != null) { Toasty.error(ShowConversationActivity.this, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); @@ -304,16 +333,28 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve return; } if (BaseMainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.GNU && BaseMainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.FRIENDICA) { - statusListAdapter.setConversationPosition(apiResponse.getContext().getAncestors().size()); + if (statusListAdapter != null) { + statusListAdapter.setConversationPosition(apiResponse.getContext().getAncestors().size()); + } if (!expanded) { if (apiResponse.getContext().getAncestors() != null && apiResponse.getContext().getAncestors().size() > 0) { - statuses.addAll(0, apiResponse.getContext().getAncestors()); - statusListAdapter.notifyItemRangeInserted(0, apiResponse.getContext().getAncestors().size()); + if (statusListAdapter != null) { + statuses.addAll(0, apiResponse.getContext().getAncestors()); + statusListAdapter.notifyItemRangeInserted(0, apiResponse.getContext().getAncestors().size()); + } else if (pixelfedListAdapter != null) { + statuses.addAll(1, apiResponse.getContext().getAncestors()); + pixelfedListAdapter.notifyItemRangeInserted(1, apiResponse.getContext().getAncestors().size()); + } } int targetedPosition = statuses.size() - 1; if (apiResponse.getContext().getDescendants() != null && apiResponse.getContext().getDescendants().size() > 0) { statuses.addAll(apiResponse.getContext().getAncestors().size() + 1, apiResponse.getContext().getDescendants()); - statusListAdapter.notifyItemRangeChanged(apiResponse.getContext().getAncestors().size() + 1, apiResponse.getContext().getDescendants().size()); + if (statusListAdapter != null) { + statusListAdapter.notifyItemRangeChanged(apiResponse.getContext().getAncestors().size() + 1, apiResponse.getContext().getDescendants().size()); + } else if (pixelfedListAdapter != null) { + pixelfedListAdapter.notifyItemRangeChanged(apiResponse.getContext().getAncestors().size() + 1, apiResponse.getContext().getDescendants().size()); + } + } decorate(targetedPosition); } else { @@ -323,15 +364,22 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve for (Status status : statusesTemp) { statuses.add(status); if (status.getId().equals(detailsStatus.getId())) { - statusListAdapter.setConversationPosition(i); + + if (statusListAdapter != null) { + statusListAdapter.setConversationPosition(i); + } detailsStatus = status; position = i; } i++; } decorate(position); - statusListAdapter.notifyItemRangeChanged(1, apiResponse.getContext().getDescendants().size()); - lv_status.scrollToPosition(position); + if (statusListAdapter != null) { + statusListAdapter.notifyItemRangeChanged(1, apiResponse.getContext().getDescendants().size()); + } else if (pixelfedListAdapter != null) { + pixelfedListAdapter.notifyItemRangeChanged(1, apiResponse.getContext().getDescendants().size()); + } + binding.lvStatus.scrollToPosition(position); } } else { int i = 0; @@ -359,15 +407,15 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve decorate(0); final LinearLayoutManager mLayoutManager; mLayoutManager = new LinearLayoutManager(this); - lv_status.setLayoutManager(mLayoutManager); + binding.lvStatus.setLayoutManager(mLayoutManager); - lv_status.setAdapter(statusListAdapter); + binding.lvStatus.setAdapter(statusListAdapter); } } } - + //Add lines and offset to messages private void decorate(int targetedPosition) { for (int i = 0; i < statuses.size(); i++) { if (i == targetedPosition) { @@ -384,7 +432,11 @@ public class ShowConversationActivity extends BaseActivity implements OnRetrieve } } } - statusListAdapter.notifyItemRangeChanged(0, statuses.size()); + if (statusListAdapter != null) { + statusListAdapter.notifyItemRangeChanged(0, statuses.size()); + } else if (pixelfedListAdapter != null) { + pixelfedListAdapter.notifyItemRangeChanged(0, statuses.size()); + } } } diff --git a/app/src/main/java/app/fedilab/android/asynctasks/RetrieveAccountsForReplyAsyncTask.java b/app/src/main/java/app/fedilab/android/asynctasks/RetrieveAccountsForReplyAsyncTask.java index f900a45ba..da8ceb207 100644 --- a/app/src/main/java/app/fedilab/android/asynctasks/RetrieveAccountsForReplyAsyncTask.java +++ b/app/src/main/java/app/fedilab/android/asynctasks/RetrieveAccountsForReplyAsyncTask.java @@ -56,14 +56,14 @@ public class RetrieveAccountsForReplyAsyncTask { new Thread(() -> { API api = new API(this.contextReference.get()); - app.fedilab.android.client.Entities.Context statusContext = api.getStatusContext(status.getId()); + app.fedilab.android.client.Entities.Context statusContext = api.getStatusContext(null, status.getId()); addedAccounts = new ArrayList<>(); accounts.add(status.getAccount()); addedAccounts.add(status.getAccount().getAcct()); //Retrieves the first toot if (statusContext.getAncestors().size() > 0) { - statusContext = api.getStatusContext(statusContext.getAncestors().get(0).getId()); + statusContext = api.getStatusContext(null, statusContext.getAncestors().get(0).getId()); } if (statusContext != null && statusContext.getDescendants().size() > 0) { for (app.fedilab.android.client.Entities.Status status : statusContext.getDescendants()) { diff --git a/app/src/main/java/app/fedilab/android/asynctasks/RetrieveContextAsyncTask.java b/app/src/main/java/app/fedilab/android/asynctasks/RetrieveContextAsyncTask.java index 23401f7f1..701205f48 100644 --- a/app/src/main/java/app/fedilab/android/asynctasks/RetrieveContextAsyncTask.java +++ b/app/src/main/java/app/fedilab/android/asynctasks/RetrieveContextAsyncTask.java @@ -39,15 +39,17 @@ public class RetrieveContextAsyncTask { private final OnRetrieveContextInterface listener; private final WeakReference contextReference; private final boolean expanded; + private final String userId; private final boolean directtimeline; private APIResponse apiResponse; - public RetrieveContextAsyncTask(Context context, boolean expanded, boolean directtimeline, String statusId, OnRetrieveContextInterface onRetrieveContextInterface) { + public RetrieveContextAsyncTask(Context context, boolean expanded, boolean directtimeline, String userId, String statusId, OnRetrieveContextInterface onRetrieveContextInterface) { this.contextReference = new WeakReference<>(context); this.statusId = statusId; this.listener = onRetrieveContextInterface; this.expanded = expanded; this.directtimeline = directtimeline; + this.userId = userId; doInBackground(); } @@ -59,10 +61,10 @@ public class RetrieveContextAsyncTask { Error error; if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.GNU && MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.FRIENDICA) { API api = new API(this.contextReference.get()); - statusContext = api.getStatusContext(statusId); + statusContext = api.getStatusContext(userId, statusId); //Retrieves the first toot if (expanded && statusContext != null && statusContext.getAncestors() != null && statusContext.getAncestors().size() > 0) { - statusContext = api.getStatusContext(statusContext.getAncestors().get(0).getId()); + statusContext = api.getStatusContext(userId, statusContext.getAncestors().get(0).getId()); } error = api.getError(); } else { diff --git a/app/src/main/java/app/fedilab/android/asynctasks/RetrieveFeedsAsyncTask.java b/app/src/main/java/app/fedilab/android/asynctasks/RetrieveFeedsAsyncTask.java index 607355496..2f96dfde1 100644 --- a/app/src/main/java/app/fedilab/android/asynctasks/RetrieveFeedsAsyncTask.java +++ b/app/src/main/java/app/fedilab/android/asynctasks/RetrieveFeedsAsyncTask.java @@ -31,6 +31,7 @@ import app.fedilab.android.client.Entities.Peertube; import app.fedilab.android.client.Entities.RemoteInstance; import app.fedilab.android.client.Entities.Results; import app.fedilab.android.client.Entities.RetrieveFeedsParam; +import app.fedilab.android.client.Entities.Status; import app.fedilab.android.client.GNUAPI; import app.fedilab.android.client.PeertubeAPI; import app.fedilab.android.helper.FilterToots; @@ -222,9 +223,9 @@ public class RetrieveFeedsAsyncTask { if (this.social != null && this.social.equals("MASTODON")) { apiResponse = api.getPublicTimelineTag(this.currentfilter, true, max_id, this.remoteInstance); if (apiResponse != null) { - List statusesTemp = apiResponse.getStatuses(); + List statusesTemp = apiResponse.getStatuses(); if (statusesTemp != null) { - for (app.fedilab.android.client.Entities.Status status : statusesTemp) { + for (Status status : statusesTemp) { status.setType(action); } } @@ -243,25 +244,25 @@ public class RetrieveFeedsAsyncTask { List remoteInstanceObj = new InstancesDAO(this.contextReference.get(), db).getInstanceByName(this.instanceName); if (remoteInstanceObj != null && remoteInstanceObj.size() > 0 && remoteInstanceObj.get(0).getType().equals("MASTODON")) { apiResponse = api.getPublicTimeline(this.instanceName, true, max_id); - List statusesTemp = apiResponse.getStatuses(); + List statusesTemp = apiResponse.getStatuses(); if (statusesTemp != null) { - for (app.fedilab.android.client.Entities.Status status : statusesTemp) { + for (Status status : statusesTemp) { status.setType(action); } } } else if (remoteInstanceObj != null && remoteInstanceObj.size() > 0 && remoteInstanceObj.get(0).getType().equals("MISSKEY")) { apiResponse = api.getMisskey(this.instanceName, max_id); - List statusesTemp = apiResponse.getStatuses(); + List statusesTemp = apiResponse.getStatuses(); if (statusesTemp != null) { - for (app.fedilab.android.client.Entities.Status status : statusesTemp) { + for (Status status : statusesTemp) { status.setType(action); } } } else if (remoteInstanceObj != null && remoteInstanceObj.size() > 0 && remoteInstanceObj.get(0).getType().equals("NITTER")) { apiResponse = api.getNitter(this.instanceName, max_id); - List statusesTemp = apiResponse.getStatuses(); + List statusesTemp = apiResponse.getStatuses(); if (statusesTemp != null) { - for (app.fedilab.android.client.Entities.Status status : statusesTemp) { + for (Status status : statusesTemp) { status.setType(action); } } @@ -326,14 +327,14 @@ public class RetrieveFeedsAsyncTask { tag = tag.replace("_cache_", ""); apiResponse = new APIResponse(); Results results = new Results(); - List statuses = new TimelineCacheDAO(contextReference.get(), db).search(tag, max_id); + List statuses = new TimelineCacheDAO(contextReference.get(), db).search(tag, max_id); if (statuses != null && statuses.size() > 0) { apiResponse.setMax_id(statuses.get(statuses.size() - 1).getId()); } - List statusesNew = null; + List statusesNew = null; if (statuses != null) { statusesNew = new ArrayList<>(); - for (app.fedilab.android.client.Entities.Status status : statuses) { + for (Status status : statuses) { if (tag != null && !tag.contains("\"")) { String[] searches = tag.split(" "); for (String search : searches) { @@ -372,14 +373,17 @@ public class RetrieveFeedsAsyncTask { case ART: apiResponse = api.getArtTimeline(false, max_id, null, null, null); break; + case BOOKMARKS: + apiResponse = api.getBookmarks(max_id); + break; case CACHE_BOOKMARKS: apiResponse = new APIResponse(); db = Sqlite.getInstance(contextReference.get().getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); - List statuses = new StatusCacheDAO(contextReference.get(), db).getAllStatus(StatusCacheDAO.BOOKMARK_CACHE); + List statuses = new StatusCacheDAO(contextReference.get(), db).getAllStatus(StatusCacheDAO.BOOKMARK_CACHE); if (statuses != null) { - for (app.fedilab.android.client.Entities.Status status : statuses) { - app.fedilab.android.client.Entities.Status.fillSpan(contextReference, status); + for (Status status : statuses) { + Status.fillSpan(contextReference, status); } } else { statuses = new ArrayList<>(); @@ -397,8 +401,8 @@ public class RetrieveFeedsAsyncTask { db = Sqlite.getInstance(contextReference.get().getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); statuses = new StatusCacheDAO(contextReference.get(), db).getStatusFromID(StatusCacheDAO.ARCHIVE_CACHE, filterToots, max_id); if (statuses != null && statuses.size() > 0) { - for (app.fedilab.android.client.Entities.Status status : statuses) { - app.fedilab.android.client.Entities.Status.fillSpan(contextReference, status); + for (Status status : statuses) { + Status.fillSpan(contextReference, status); } apiResponse.setStatuses(statuses); apiResponse.setSince_id(statuses.get(0).getId()); @@ -474,8 +478,8 @@ public class RetrieveFeedsAsyncTask { if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA || MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { List bookmarks = new StatusCacheDAO(contextReference.get(), db).getAllStatusId(StatusCacheDAO.BOOKMARK_CACHE); if (apiResponse != null && apiResponse.getStatuses() != null && bookmarks != null && apiResponse.getStatuses().size() > 0) { - List statuses = apiResponse.getStatuses(); - for (app.fedilab.android.client.Entities.Status status : statuses) { + List statuses = apiResponse.getStatuses(); + for (Status status : statuses) { status.setBookmarked(bookmarks.contains(status.getId())); } } @@ -538,6 +542,7 @@ public class RetrieveFeedsAsyncTask { GNU_GROUP_TIMELINE, SCHEDULED_TOOTS, + BOOKMARKS, CACHE_BOOKMARKS, CACHE_BOOKMARKS_PEERTUBE, CACHE_STATUS, diff --git a/app/src/main/java/app/fedilab/android/asynctasks/SyncBookmarksAsyncTask.java b/app/src/main/java/app/fedilab/android/asynctasks/SyncBookmarksAsyncTask.java index 50aa466ae..b6963a91e 100644 --- a/app/src/main/java/app/fedilab/android/asynctasks/SyncBookmarksAsyncTask.java +++ b/app/src/main/java/app/fedilab/android/asynctasks/SyncBookmarksAsyncTask.java @@ -83,19 +83,6 @@ public class SyncBookmarksAsyncTask { } } while (max_id != null); statusList = new StatusCacheDAO(contextReference.get(), db).getAllStatus(BOOKMARK_CACHE); - } else if (type == sync.EXPORT) { - List statuses = new StatusCacheDAO(contextReference.get(), db).getAllStatus(BOOKMARK_CACHE); - if (statuses != null) { - for (app.fedilab.android.client.Entities.Status tmpStatus : statuses) { - new API(contextReference.get()).postAction(API.StatusAction.BOOKMARK, tmpStatus.getId()); - try { - Thread.sleep(200); - } catch (InterruptedException e) { - SystemClock.sleep(200); - } - } - } - statusList = new StatusCacheDAO(contextReference.get(), db).getAllStatus(BOOKMARK_CACHE); } else { APIResponse apiResponse = new API(contextReference.get()).getStatusbyIdAndCache(statusId); app.fedilab.android.client.Entities.Status refreshedStatus = apiResponse.getStatuses().get(0); @@ -111,7 +98,6 @@ public class SyncBookmarksAsyncTask { public enum sync { - EXPORT, IMPORT, REFRESH } diff --git a/app/src/main/java/app/fedilab/android/client/API.java b/app/src/main/java/app/fedilab/android/client/API.java index dd76ffc53..269d9c173 100644 --- a/app/src/main/java/app/fedilab/android/client/API.java +++ b/app/src/main/java/app/fedilab/android/client/API.java @@ -136,8 +136,8 @@ public class API { } SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); tootPerPage = sharedpreferences.getInt(Helper.SET_TOOT_PER_PAGE, Helper.TOOTS_PER_PAGE); - if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED && tootPerPage > 30) { - tootPerPage = 30; + if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED && tootPerPage > 20) { + tootPerPage = 20; } accountPerPage = Helper.ACCOUNTS_PER_PAGE; notificationPerPage = Helper.NOTIFICATIONS_PER_PAGE; @@ -169,8 +169,8 @@ public class API { } SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); tootPerPage = sharedpreferences.getInt(Helper.SET_TOOT_PER_PAGE, Helper.TOOTS_PER_PAGE); - if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED && tootPerPage > 30) { - tootPerPage = 30; + if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED && tootPerPage > 20) { + tootPerPage = 20; } accountPerPage = Helper.ACCOUNTS_PER_PAGE; notificationPerPage = Helper.NOTIFICATIONS_PER_PAGE; @@ -2834,12 +2834,11 @@ public class API { params.put("max_id", max_id); if (since_id != null) params.put("since_id", since_id); - if (0 < limit || limit > 40) + if (0 > limit || limit > 40) limit = 40; if (pinned) params.put("pinned", Boolean.toString(true)); if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { - limit = 20; params.put("only_media", Boolean.toString(true)); if (max_id == null) { params.put("min_id", "1"); @@ -2987,11 +2986,16 @@ public class API { * @param statusId Id of the status * @return List */ - public app.fedilab.android.client.Entities.Context getStatusContext(String statusId) { + public app.fedilab.android.client.Entities.Context getStatusContext(String userId, String statusId) { app.fedilab.android.client.Entities.Context statusContext = new app.fedilab.android.client.Entities.Context(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); - String response = httpsConnection.get(getAbsoluteUrl(String.format("/statuses/%s/context", statusId)), 10, null, prefKeyOauthTokenT); + String response; + if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { + response = httpsConnection.get(getAbsoluteUrl(String.format("/statuses/%s/context", statusId)), 10, null, prefKeyOauthTokenT); + } else { + response = httpsConnection.get(getAbsoluteUr2l(String.format("/comments/%s/status/%s", userId, statusId)), 10, null, prefKeyOauthTokenT); + } statusContext = parseContext(new JSONObject(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); @@ -3332,6 +3336,10 @@ public class API { apiResponse.setSince_id(statuses.get(0).getId()); apiResponse.setMax_id(statuses.get(statuses.size() - 1).getId()); } + if (statuses.size() < tootPerPage) { + apiResponse.setSince_id(null); + apiResponse.setMax_id(null); + } } } } @@ -3350,6 +3358,10 @@ public class API { apiResponse.setMax_id(notifications.get(notifications.size() - 1).getId()); } } + if (notifications.size() < tootPerPage) { + apiResponse.setSince_id(null); + apiResponse.setMax_id(null); + } } } @@ -3366,6 +3378,10 @@ public class API { apiResponse.setSince_id(accounts.get(0).getId()); apiResponse.setMax_id(accounts.get(accounts.size() - 1).getId()); } + if (accounts.size() < tootPerPage) { + apiResponse.setSince_id(null); + apiResponse.setMax_id(null); + } } } } @@ -4240,6 +4256,7 @@ public class API { return apiResponse; } + /** * Retrieves bookmarked status for the authenticated account *synchronously* * @@ -4250,13 +4267,21 @@ public class API { public APIResponse getBookmarks(String max_id) { HashMap params = new HashMap<>(); - if (max_id != null) - params.put("max_id", max_id); - params.put("limit", "40"); statuses = new ArrayList<>(); try { + String response; HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); - String response = httpsConnection.get(getAbsoluteUrl("/bookmarks"), 10, params, prefKeyOauthTokenT); + if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { + if (max_id != null) + params.put("max_id", max_id); + params.put("limit", "40"); + response = httpsConnection.get(getAbsoluteUrl("/bookmarks"), 10, params, prefKeyOauthTokenT); + } else { + params.put("max_id", max_id); + params.put("limit", String.valueOf(tootPerPage)); + response = httpsConnection.get(Helper.instanceWithProtocol(this.context, this.instance) + "/api/local/bookmarks", 10, params, prefKeyOauthTokenT); + } + statuses = parseStatuses(context, new JSONArray(response)); setStatusesMaxId(httpsConnection, statuses); } catch (HttpsConnection.HttpsConnectionException e) { @@ -4352,7 +4377,6 @@ public class API { * @return in status code - Should be equal to 200 when action is done */ private int postAction(StatusAction statusAction, String targetedId, Status status, String comment) { - String action; HashMap params = null; switch (statusAction) { @@ -4375,10 +4399,22 @@ public class API { } break; case BOOKMARK: - action = String.format("/statuses/%s/bookmark", targetedId); + if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { + action = String.format("/statuses/%s/bookmark", targetedId); + } else { + action = "/i/bookmark"; + params = new HashMap<>(); + params.put("item", targetedId); + } break; case UNBOOKMARK: - action = String.format("/statuses/%s/unbookmark", targetedId); + if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { + action = String.format("/statuses/%s/unbookmark", targetedId); + } else { + action = "/i/bookmark"; + params = new HashMap<>(); + params.put("item", targetedId); + } break; case REBLOG: if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { @@ -4574,6 +4610,7 @@ public class API { default: return -1; } + if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED || (statusAction != StatusAction.UNSTATUS && statusAction != StatusAction.ADD_REACTION && statusAction != StatusAction.REMOVE_REACTION && statusAction != StatusAction.ADD_PLEROMA_REACTION && statusAction != StatusAction.REMOVE_PLEROMA_REACTION)) { @@ -4624,6 +4661,7 @@ public class API { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); httpsConnection.delete(getAbsoluteUrl(action), 10, null, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); + //Delete a status (Mastodon or Pleroma) if (statusAction != StatusAction.REMOVE_REACTION && statusAction != StatusAction.REMOVE_PLEROMA_REACTION) { SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); new TimelineCacheDAO(context, db).remove(targetedId); @@ -4637,7 +4675,6 @@ public class API { return actionCode; } - @SuppressWarnings("unused") public int reportStatus(List statuses, String comment, boolean forward) { String action; HashMap params; @@ -4880,7 +4917,6 @@ public class API { if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { Status statusreturned = parseStatuses(context, new JSONObject(response)); statuses.add(statusreturned); - setStatusesMaxId(httpsConnection, statuses); } else { final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); @@ -4889,8 +4925,8 @@ public class API { Account account = new AccountDAO(context, db).getUniqAccount(userId, instance); status.setAccount(account); statuses.add(status); - setStatusesMaxId(httpsConnection, statuses); } + setStatusesMaxId(httpsConnection, statuses); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); @@ -6370,8 +6406,13 @@ public class API { app.fedilab.android.client.Entities.Context context = new app.fedilab.android.client.Entities.Context(); try { - context.setAncestors(parseStatuses(this.context, jsonObject.getJSONArray("ancestors"))); - context.setDescendants(parseStatuses(this.context, jsonObject.getJSONArray("descendants"))); + if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { + context.setAncestors(parseStatuses(this.context, jsonObject.getJSONArray("data"))); + } else { + context.setAncestors(parseStatuses(this.context, jsonObject.getJSONArray("ancestors"))); + context.setDescendants(parseStatuses(this.context, jsonObject.getJSONArray("descendants"))); + } + } catch (JSONException e) { setDefaultError(e); } diff --git a/app/src/main/java/app/fedilab/android/client/Entities/Status.java b/app/src/main/java/app/fedilab/android/client/Entities/Status.java index 878c917d7..282e925d5 100644 --- a/app/src/main/java/app/fedilab/android/client/Entities/Status.java +++ b/app/src/main/java/app/fedilab/android/client/Entities/Status.java @@ -164,7 +164,7 @@ public class Status implements Parcelable { private List conversationProfilePicture; private String webviewURL = null; - private boolean isBoostAnimated = false, isFavAnimated = false; + private boolean isBoostAnimated = false, isFavAnimated = false, isBookmarkAnimated; private String scheduled_at; private String contentType; private boolean isNotice = false; @@ -239,6 +239,7 @@ public class Status implements Parcelable { this.webviewURL = in.readString(); this.isBoostAnimated = in.readByte() != 0; this.isFavAnimated = in.readByte() != 0; + this.isBookmarkAnimated = in.readByte() != 0; this.scheduled_at = in.readString(); this.contentType = in.readString(); this.showSpoiler = in.readByte() != 0; @@ -1022,6 +1023,7 @@ public class Status implements Parcelable { dest.writeString(this.webviewURL); dest.writeByte(this.isBoostAnimated ? (byte) 1 : (byte) 0); dest.writeByte(this.isFavAnimated ? (byte) 1 : (byte) 0); + dest.writeByte(this.isBookmarkAnimated ? (byte) 1 : (byte) 0); dest.writeString(this.scheduled_at); dest.writeString(this.contentType); dest.writeByte(this.showSpoiler ? (byte) 1 : (byte) 0); @@ -1476,6 +1478,14 @@ public class Status implements Parcelable { isFavAnimated = favAnimated; } + public boolean isBookmarkAnimated() { + return isBookmarkAnimated; + } + + public void setBookmarkAnimated(boolean bookmarkAnimated) { + isBookmarkAnimated = bookmarkAnimated; + } + public Attachment getArt_attachment() { return art_attachment; } diff --git a/app/src/main/java/app/fedilab/android/client/PixelfedAPI.java b/app/src/main/java/app/fedilab/android/client/PixelfedAPI.java index dd5857a59..c45f8e2fe 100644 --- a/app/src/main/java/app/fedilab/android/client/PixelfedAPI.java +++ b/app/src/main/java/app/fedilab/android/client/PixelfedAPI.java @@ -3,7 +3,6 @@ package app.fedilab.android.client; import android.content.Context; import android.content.SharedPreferences; import android.database.sqlite.SQLiteDatabase; -import android.util.Log; import com.google.gson.JsonArray; @@ -197,6 +196,29 @@ public class PixelfedAPI { return apiResponse; }*/ + + /** + * Retrieves Pixelfed Own Stories *synchronously* + * + * @return APIResponse + */ + public JSONObject getPostDetails(String username, String targertedId) { + try { + HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); + String response = httpsConnection.get(Helper.getLiveInstanceWithProtocol(context) + String.format("/api/v2/profile/%s/status/%s/state", username, targertedId), 10, null, prefKeyOauthTokenT); + apiResponse.setSince_id(httpsConnection.getSince_id()); + apiResponse.setMax_id(httpsConnection.getMax_id()); + return new JSONObject(response).getJSONObject("reactions"); + } catch (HttpsConnection.HttpsConnectionException e) { + setError(e.getStatusCode(), e); + e.printStackTrace(); + } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { + e.printStackTrace(); + } + return null; + } + + /** * Retrieves Pixelfed Own Stories *synchronously* * diff --git a/app/src/main/java/app/fedilab/android/drawers/PixelfedListAdapter.java b/app/src/main/java/app/fedilab/android/drawers/PixelfedListAdapter.java index 28ff0f064..3af9f6487 100644 --- a/app/src/main/java/app/fedilab/android/drawers/PixelfedListAdapter.java +++ b/app/src/main/java/app/fedilab/android/drawers/PixelfedListAdapter.java @@ -36,7 +36,6 @@ import android.widget.Button; import android.widget.DatePicker; import android.widget.EditText; import android.widget.ImageButton; -import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.TimePicker; @@ -45,8 +44,6 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.PopupMenu; -import androidx.cardview.widget.CardView; -import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.app.ActivityOptionsCompat; import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.LinearLayoutManager; @@ -62,8 +59,6 @@ import com.github.stom79.mytransl.client.Results; import com.github.stom79.mytransl.translate.Translate; import com.smarteist.autoimageslider.IndicatorAnimations; import com.smarteist.autoimageslider.SliderAnimations; -import com.smarteist.autoimageslider.SliderView; -import com.varunest.sparkbutton.SparkButton; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -93,6 +88,9 @@ import app.fedilab.android.client.Entities.Error; import app.fedilab.android.client.Entities.Notification; import app.fedilab.android.client.Entities.Status; import app.fedilab.android.client.Entities.StatusDrawerParams; +import app.fedilab.android.databinding.DrawerEmptyBinding; +import app.fedilab.android.databinding.DrawerPixelfedBinding; +import app.fedilab.android.databinding.DrawerPixelfedCommentBinding; import app.fedilab.android.helper.CrossActions; import app.fedilab.android.helper.Helper; import app.fedilab.android.helper.MastalabAutoCompleteTextView; @@ -124,23 +122,22 @@ import static app.fedilab.android.activities.BaseMainActivity.social; */ public class PixelfedListAdapter extends RecyclerView.Adapter implements OnPostActionInterface, OnRetrieveEmojiInterface, OnPostStatusActionInterface, OnRetrieveSearchInterface, OnRetrieveSearcAccountshInterface, OnRetrieveContextInterface, OnRetrieveFeedsInterface { + private static final int COMMENT_STATUS = 2; private static final int DISPLAYED_STATUS = 1; private final int HIDDEN_STATUS = 0; private final List statuses; - private final PixelfedListAdapter pixelfedListAdapter; private final RetrieveFeedsAsyncTask.Type type; private Context context; private MastalabAutoCompleteTextView comment_content; private String in_reply_to_status; private String visibility; - private boolean redraft = false; + private final boolean redraft; private Status toot; - public PixelfedListAdapter(RetrieveFeedsAsyncTask.Type type, List statuses) { - super(); - this.statuses = statuses; - this.type = type; - pixelfedListAdapter = this; + public PixelfedListAdapter(StatusDrawerParams statusDrawerParams) { + statuses = statusDrawerParams.getStatuses(); + type = statusDrawerParams.getType(); + redraft = false; } @@ -362,6 +359,8 @@ public class PixelfedListAdapter extends RecyclerView.Adapter 0 && type == RetrieveFeedsAsyncTask.Type.CONTEXT) { + return COMMENT_STATUS; } else { return DISPLAYED_STATUS; } @@ -371,11 +370,16 @@ public class PixelfedListAdapter extends RecyclerView.Adapter 0) + holder.binding.pfUsername.setText(status.getAccount().getDisplayNameSpan(), TextView.BufferType.SPANNABLE); + else + holder.binding.pfUsername.setText(status.getAccount().getUsername()); + + holder.binding.pfDate.setText(Helper.longDateToString(status.getCreated_at())); + holder.binding.pfDescription.setText(status.getContentSpan(), TextView.BufferType.SPANNABLE); + } else if (viewHolder.getItemViewType() == DISPLAYED_STATUS) { + final ViewHolderPixelfed holder = (ViewHolderPixelfed) viewHolder; + final Status status = statuses.get(viewHolder.getAdapterPosition()); + + if (type == RetrieveFeedsAsyncTask.Type.CONTEXT) { + holder.binding.pfBookmark.setVisibility(View.VISIBLE); + } + if (status.getAccount() != null && status.getAccount().getAvatar() != null) + Glide.with(context) + .load(status.getAccount().getAvatar()) + .apply(new RequestOptions().transform(new FitCenter(), new RoundedCorners(270))) + .into(holder.binding.pfPp); - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); int iconColor = prefs.getInt("theme_icons_color", -1); if (iconColor == -1) { iconColor = ThemeHelper.getAttColor(context, R.attr.iconColor); } - holder.pf_likes.setTextColor(iconColor); + holder.binding.pfLikes.setTextColor(iconColor); int statusColor = prefs.getInt("theme_statuses_color", -1); - if (holder.pf_cardview != null && statusColor != -1) { - holder.pf_cardview.setCardBackgroundColor(statusColor); - } else if (holder.pf_cardview != null) { - holder.pf_cardview.setCardBackgroundColor(ThemeHelper.getAttColor(context, R.attr.cardviewColor)); + if (statusColor != -1) { + holder.binding.pfCardview.setCardBackgroundColor(statusColor); + } else { + holder.binding.pfCardview.setCardBackgroundColor(ThemeHelper.getAttColor(context, R.attr.cardviewColor)); } int theme_text_color = prefs.getInt("theme_text_color", -1); - if (holder.pf_description != null && theme_text_color != -1) { - holder.pf_description.setTextColor(theme_text_color); + if (theme_text_color != -1) { + holder.binding.pfDescription.setTextColor(theme_text_color); } int theme_text_header_2_line = prefs.getInt("theme_text_header_2_line", -1); @@ -416,16 +450,16 @@ public class PixelfedListAdapter extends RecyclerView.Adapter { + holder.binding.artMedia.setOnClickListener(v -> { if (expand_media || !status.isSensitive() || status.isAttachmentShown()) { Intent intent = new Intent(context, SlideMediaActivity.class); Bundle b = new Bundle(); @@ -543,7 +577,7 @@ public class PixelfedListAdapter extends RecyclerView.Adapter= android.os.Build.VERSION_CODES.LOLLIPOP) { ActivityOptionsCompat options = ActivityOptionsCompat - .makeSceneTransitionAnimation((Activity) context, holder.art_media, status.getMedia_attachments().get(0).getUrl()); + .makeSceneTransitionAnimation((Activity) context, holder.binding.artMedia, status.getMedia_attachments().get(0).getUrl()); // start the new activity context.startActivity(intent, options.toBundle()); } else { @@ -571,16 +605,16 @@ public class PixelfedListAdapter extends RecyclerView.Adapter 1) { SliderAdapter sliderAdapter = new SliderAdapter(new WeakReference<>((Activity) context), false, status); - holder.imageSlider.setSliderAdapter(sliderAdapter); - holder.imageSlider.setIndicatorAnimation(IndicatorAnimations.WORM); - holder.imageSlider.setSliderTransformAnimation(SliderAnimations.SIMPLETRANSFORMATION); - holder.art_media.setVisibility(View.GONE); - holder.imageSlider.setVisibility(View.VISIBLE); + holder.binding.imageSlider.setSliderAdapter(sliderAdapter); + holder.binding.imageSlider.setIndicatorAnimation(IndicatorAnimations.WORM); + holder.binding.imageSlider.setSliderTransformAnimation(SliderAnimations.SIMPLETRANSFORMATION); + holder.binding.artMedia.setVisibility(View.GONE); + holder.binding.imageSlider.setVisibility(View.VISIBLE); } else if (status.getMedia_attachments() != null && status.getMedia_attachments().size() > 0) { - holder.art_media.setVisibility(View.VISIBLE); - holder.imageSlider.setVisibility(View.GONE); + holder.binding.artMedia.setVisibility(View.VISIBLE); + holder.binding.imageSlider.setVisibility(View.GONE); if (status.getMedia_attachments().get(0).getType() != null && status.getMedia_attachments().get(0).getType().toLowerCase().equals("video")) { - holder.art_media_play.setVisibility(View.VISIBLE); + holder.binding.artMediaPlay.setVisibility(View.VISIBLE); } String url; if (status.getMedia_attachments().get(0).getPreview_url() != null && status.getMedia_attachments().get(0).getPreview_url().endsWith("no-preview.png")) { @@ -593,19 +627,19 @@ public class PixelfedListAdapter extends RecyclerView.Adapter { + holder.binding.pfLikes.setText(context.getResources().getQuantityString(R.plurals.likes, status.getFavourites_count(), status.getFavourites_count())); + holder.binding.pfPp.setOnClickListener(v -> { if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { CrossActions.doCrossProfile(context, status.getAccount()); } else { @@ -618,25 +652,25 @@ public class PixelfedListAdapter extends RecyclerView.Adapter { + holder.binding.incQuickReply.quickReplyButton.setOnClickListener(view -> { sendToot(status); status.setShortReply(false); - holder.quick_reply_container.setVisibility(View.GONE); + holder.binding.incQuickReply.quickReplyContainer.setVisibility(View.GONE); InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE); assert imm != null; - imm.hideSoftInputFromWindow(holder.quick_reply_button.getWindowToken(), 0); + imm.hideSoftInputFromWindow(holder.binding.incQuickReply.quickReplyButton.getWindowToken(), 0); }); - holder.pf_description.setText(status.getContentSpan(), TextView.BufferType.SPANNABLE); - holder.pf_date.setText(Helper.longDateToString(status.getCreated_at())); - holder.quick_reply_text.setHint(R.string.leave_a_comment); - holder.quick_reply_button.setText(R.string.post); - holder.pf_comment.setOnClickListener(v -> { + holder.binding.pfDescription.setText(status.getContentSpan(), TextView.BufferType.SPANNABLE); + holder.binding.pfDate.setText(Helper.longDateToString(status.getCreated_at())); + holder.binding.incQuickReply.quickReplyText.setHint(R.string.leave_a_comment); + holder.binding.incQuickReply.quickReplyButton.setText(R.string.post); + holder.binding.pfComment.setOnClickListener(v -> { boolean currentValue = status.isShortReply(); for (Status s : statuses) { if (s.isShortReply() && !s.getId().equals(status.getId())) { @@ -648,29 +682,21 @@ public class PixelfedListAdapter extends RecyclerView.Adapter { + final View attached = holder.binding.statusMore; + holder.binding.statusMore.setOnClickListener(v -> { PopupMenu popup = new PopupMenu(context, attached); final boolean isOwner = status.getReblog() != null ? status.getReblog().getAccount().getId().equals(userId) : status.getAccount().getId().equals(userId); popup.getMenuInflater() - .inflate(R.menu.option_toot, popup.getMenu()); + .inflate(R.menu.option_pixelfed, popup.getMenu()); if (status.getVisibility().equals("private") || status.getVisibility().equals("direct")) { popup.getMenu().findItem(R.id.action_mention).setVisible(false); } - if (status.isBookmarked()) - popup.getMenu().findItem(R.id.action_bookmark).setTitle(R.string.bookmark_remove); - else - popup.getMenu().findItem(R.id.action_bookmark).setTitle(R.string.bookmark_add); - if (status.isMuted()) - popup.getMenu().findItem(R.id.action_mute_conversation).setTitle(R.string.unmute_conversation); - else - popup.getMenu().findItem(R.id.action_mute_conversation).setTitle(R.string.mute_conversation); final String[] stringArrayConf; @@ -679,37 +705,12 @@ public class PixelfedListAdapter extends RecyclerView.Adapter { AlertDialog.Builder builderInner; final API.StatusAction doAction; int itemId = item.getItemId(); - if (itemId == R.id.action_redraft) { - builderInner = new AlertDialog.Builder(context, style); - builderInner.setTitle(stringArrayConf[1]); - redraft = true; - doAction = API.StatusAction.UNSTATUS; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - builderInner.setMessage(Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_LEGACY)); - else - builderInner.setMessage(Html.fromHtml(status.getContent())); - } else if (itemId == R.id.action_schedule_boost) { - scheduleBoost(status); - return true; - } else if (itemId == R.id.action_info) { + if (itemId == R.id.action_info) { tootInformation(status); return true; } else if (itemId == R.id.action_open_browser) { @@ -759,60 +741,11 @@ public class PixelfedListAdapter extends RecyclerView.Adapter= Build.VERSION_CODES.N) - builderInner.setMessage(Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_LEGACY)); - else - builderInner.setMessage(Html.fromHtml(status.getContent())); } else if (itemId == R.id.action_copy_link) { ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); @@ -883,18 +808,7 @@ public class PixelfedListAdapter extends RecyclerView.Adapter dialog.dismiss()); - final EditText finalInput = input; builderInner.setPositiveButton(R.string.yes, (dialog, which) -> { if (doAction == API.StatusAction.UNSTATUS) { String targetedId = status.getId(); @@ -938,11 +852,6 @@ public class PixelfedListAdapter extends RecyclerView.Adapter { - Intent intent = new Intent(context, ShowConversationActivity.class); - Bundle b = new Bundle(); - if (status.getReblog() == null) - b.putParcelable("status", status); - else - b.putParcelable("status", status.getReblog()); - intent.putExtras(b); - context.startActivity(intent); + holder.binding.pfCardview.setOnClickListener(view -> { + //For Pixelfed conversations can't be open several times + if (type != RetrieveFeedsAsyncTask.Type.CONTEXT) { + Intent intent = new Intent(context, ShowConversationActivity.class); + Bundle b = new Bundle(); + if (status.getReblog() == null) + b.putParcelable("status", status); + else + b.putParcelable("status", status.getReblog()); + intent.putExtras(b); + context.startActivity(intent); + } }); - if (status.getAccount().getDisplayNameSpan() != null && status.getAccount().getDisplayNameSpan().toString().trim().length() > 0) - holder.pf_username.setText(status.getAccount().getDisplayNameSpan(), TextView.BufferType.SPANNABLE); + holder.binding.pfUsername.setText(status.getAccount().getDisplayNameSpan(), TextView.BufferType.SPANNABLE); else - holder.pf_username.setText(status.getAccount().getUsername()); + holder.binding.pfUsername.setText(status.getAccount().getUsername()); - holder.pf_fav.setInActiveImageTintColor(iconColor); - holder.pf_share.setInActiveImageTintColor(iconColor); - Helper.changeDrawableColor(context, holder.pf_comment, iconColor); - Helper.changeDrawableColor(context, holder.status_more, iconColor); + holder.binding.pfFav.setInActiveImageTintColor(iconColor); + holder.binding.pfShare.setInActiveImageTintColor(iconColor); + holder.binding.pfBookmark.setInActiveImageTintColor(iconColor); + + Helper.changeDrawableColor(context, holder.binding.pfComment, iconColor); + Helper.changeDrawableColor(context, holder.binding.statusMore, iconColor); Helper.changeDrawableColor(context, R.drawable.ic_pixelfed_favorite_border, iconColor); - holder.pf_fav.pressOnTouch(false); - holder.pf_fav.setActiveImage(R.drawable.ic_pixelfed_favorite); - holder.pf_fav.setInactiveImage(R.drawable.ic_pixelfed_favorite_border); - holder.pf_fav.setDisableCircle(true); - holder.pf_fav.setActiveImageTint(R.color.pixelfed_like); - holder.pf_fav.setColors(R.color.pixelfed_like, R.color.pixelfed_like); + holder.binding.pfFav.pressOnTouch(false); + holder.binding.pfFav.setActiveImage(R.drawable.ic_pixelfed_favorite); + holder.binding.pfFav.setInactiveImage(R.drawable.ic_pixelfed_favorite_border); + holder.binding.pfFav.setDisableCircle(true); + holder.binding.pfFav.setActiveImageTint(R.color.pixelfed_like); + holder.binding.pfFav.setColors(R.color.pixelfed_like, R.color.pixelfed_like); - holder.pf_share.pressOnTouch(false); - holder.pf_share.setActiveImage(R.drawable.ic_repeat_boost); - holder.pf_share.setInactiveImage(R.drawable.ic_repeat_boost); - holder.pf_share.setDisableCircle(true); - holder.pf_share.setActiveImageTint(R.color.boost_icon); - holder.pf_share.setColors(R.color.boost_icon, R.color.boost_icon); + holder.binding.pfShare.pressOnTouch(false); + holder.binding.pfShare.setActiveImage(R.drawable.ic_repeat_boost); + holder.binding.pfShare.setInactiveImage(R.drawable.ic_repeat_boost); + holder.binding.pfShare.setDisableCircle(true); + holder.binding.pfShare.setActiveImageTint(R.color.boost_icon); + holder.binding.pfShare.setColors(R.color.boost_icon, R.color.boost_icon); + + + holder.binding.pfBookmark.pressOnTouch(false); + holder.binding.pfBookmark.setActiveImage(R.drawable.ic_bookmark_white_full); + holder.binding.pfBookmark.setInactiveImage(R.drawable.ic_bookmark_white); + holder.binding.pfBookmark.setDisableCircle(true); + holder.binding.pfBookmark.setActiveImageTint(R.color.marked_icon); + holder.binding.pfBookmark.setColors(R.color.marked_icon, R.color.marked_icon); if (!status.isFavAnimated()) { - holder.pf_fav.setChecked(status.isFavourited() || (status.getReblog() != null && status.getReblog().isFavourited())); + holder.binding.pfFav.setChecked(status.isFavourited() || (status.getReblog() != null && status.getReblog().isFavourited())); } else { status.setFavAnimated(false); - holder.pf_fav.setChecked(true); - holder.pf_fav.setAnimationSpeed(1.0f); - holder.pf_fav.playAnimation(); + holder.binding.pfFav.setChecked(true); + holder.binding.pfFav.setAnimationSpeed(1.0f); + holder.binding.pfFav.playAnimation(); } if (!status.isBoostAnimated()) { - holder.pf_share.setChecked(status.isReblogged() || (status.getReblog() != null && status.getReblog().isReblogged())); + holder.binding.pfShare.setChecked(status.isReblogged() || (status.getReblog() != null && status.getReblog().isReblogged())); } else { status.setBoostAnimated(false); - holder.pf_share.setChecked(true); - holder.pf_share.setAnimationSpeed(1.0f); - holder.pf_share.playAnimation(); + holder.binding.pfShare.setChecked(true); + holder.binding.pfShare.setAnimationSpeed(1.0f); + holder.binding.pfShare.playAnimation(); } + + if (!status.isBookmarkAnimated()) { + holder.binding.pfBookmark.setChecked(status.isBookmarked() || (status.getReblog() != null && status.getReblog().isBookmarked())); + } else { + status.setBookmarkAnimated(false); + holder.binding.pfBookmark.setChecked(true); + holder.binding.pfBookmark.setAnimationSpeed(1.0f); + holder.binding.pfBookmark.playAnimation(); + } + boolean confirmFav = sharedpreferences.getBoolean(Helper.SET_NOTIF_VALIDATION_FAV, false); - holder.pf_fav.setOnClickListener(v -> { + holder.binding.pfFav.setOnClickListener(v -> { if (!status.isFavourited() && confirmFav) status.setFavAnimated(true); if (!status.isFavourited() && !confirmFav) { status.setFavAnimated(true); notifyStatusChanged(status); } - CrossActions.doCrossAction(context, type, status, null, (status.isFavourited() || (status.getReblog() != null && status.getReblog().isFavourited())) ? API.StatusAction.UNFAVOURITE : API.StatusAction.FAVOURITE, pixelfedListAdapter, PixelfedListAdapter.this, true); + CrossActions.doCrossAction(context, type, status, null, (status.isFavourited() || (status.getReblog() != null && status.getReblog().isFavourited())) ? API.StatusAction.UNFAVOURITE : API.StatusAction.FAVOURITE, this, PixelfedListAdapter.this, true); }); boolean confirmBoost = sharedpreferences.getBoolean(Helper.SET_NOTIF_VALIDATION, false); - holder.pf_share.setOnClickListener(v -> { + holder.binding.pfShare.setOnClickListener(v -> { if (!status.isReblogged() && confirmBoost) status.setBoostAnimated(true); if (!status.isReblogged() && !confirmBoost) { status.setBoostAnimated(true); notifyStatusChanged(status); } - CrossActions.doCrossAction(context, type, status, null, (status.isReblogged() || (status.getReblog() != null && status.getReblog().isReblogged())) ? API.StatusAction.UNREBLOG : API.StatusAction.REBLOG, pixelfedListAdapter, PixelfedListAdapter.this, true); + CrossActions.doCrossAction(context, type, status, null, (status.isReblogged() || (status.getReblog() != null && status.getReblog().isReblogged())) ? API.StatusAction.UNREBLOG : API.StatusAction.REBLOG, this, PixelfedListAdapter.this, true); + }); + + holder.binding.pfBookmark.setOnClickListener(v -> { + if (!status.isBookmarked()) { + status.setBookmarkAnimated(true); + notifyStatusChanged(status); + } + CrossActions.doCrossAction(context, type, status, null, (status.isBookmarked() || (status.getReblog() != null && status.getReblog().isBookmarked())) ? API.StatusAction.UNBOOKMARK : API.StatusAction.BOOKMARK, this, PixelfedListAdapter.this, true); }); } } + @Override + public void onPostAction(int statusCode, API.StatusAction statusAction, String targetedId, Error error) { + + if (error != null) { + Toasty.error(context, error.getError(), Toast.LENGTH_LONG).show(); + return; + } + Helper.manageMessageStatusCode(context, statusCode, statusAction); + //When muting or blocking an account, its status are removed from the list + List statusesToRemove = new ArrayList<>(); + if (statusAction == API.StatusAction.MUTE || statusAction == API.StatusAction.BLOCK) { + for (Status status : statuses) { + if (status.getAccount().getId().equals(targetedId)) + statusesToRemove.add(status); + } + statuses.removeAll(statusesToRemove); + notifyDataSetChanged(); + } else if (statusAction == API.StatusAction.UNSTATUS) { + int position = 0; + for (Status status : statuses) { + if (status.getId().equals(targetedId)) { + statuses.remove(status); + notifyItemRemoved(position); + SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + //Remove the status from cache also + try { + new StatusCacheDAO(context, db).remove(StatusCacheDAO.ARCHIVE_CACHE, status); + } catch (Exception ignored) { + } + break; + } + position++; + } + } else if (statusAction == API.StatusAction.PIN || statusAction == API.StatusAction.UNPIN) { + int position = 0; + for (Status status : statuses) { + if (status.getId().equals(targetedId)) { + status.setPinned(statusAction == API.StatusAction.PIN); + notifyItemChanged(position); + break; + } + position++; + } + } + } + + private void send_delete_statuses(String targetedId) { + //Delete in the current timeline + List statusesToRemove = new ArrayList<>(); + for (Status status : statuses) { + if (status.getAccount().getId().equals(targetedId)) + statusesToRemove.add(status); + } + statuses.removeAll(statusesToRemove); + notifyDataSetChanged(); + //Send an intent to delete in every timelines + Bundle b = new Bundle(); + b.putString("receive_action", targetedId); + Intent intentBC = new Intent(Helper.RECEIVE_ACTION); + intentBC.putExtras(b); + } + + public void notifyStatusChanged(Status status) { + for (int i = 0; i < getItemCount(); i++) { + if (getItemAt(i) != null && getItemAt(i).getId().equals(status.getId())) { + try { + notifyItemChanged(i); + } catch (Exception ignored) { + } + } + } + } + + private void translateToot(Status status) { //Manages translations SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); @@ -1146,49 +1158,12 @@ public class PixelfedListAdapter extends RecyclerView.Adapter statusesToRemove = new ArrayList<>(); - if (statusAction == API.StatusAction.MUTE || statusAction == API.StatusAction.BLOCK) { - for (Status status : statuses) { - if (status.getAccount().getId().equals(targetedId)) - statusesToRemove.add(status); - } - statuses.removeAll(statusesToRemove); - pixelfedListAdapter.notifyDataSetChanged(); - } else if (statusAction == API.StatusAction.UNSTATUS) { - int position = 0; - for (Status status : statuses) { - if (status.getId().equals(targetedId)) { - statuses.remove(status); - pixelfedListAdapter.notifyItemRemoved(position); - SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); - //Remove the status from cache also - try { - new StatusCacheDAO(context, db).remove(StatusCacheDAO.ARCHIVE_CACHE, status); - } catch (Exception ignored) { - } - break; - } - position++; - } - } else if (statusAction == API.StatusAction.PIN || statusAction == API.StatusAction.UNPIN) { - int position = 0; - for (Status status : statuses) { - if (status.getId().equals(targetedId)) { - status.setPinned(statusAction == API.StatusAction.PIN); - pixelfedListAdapter.notifyItemChanged(position); - break; - } - position++; - } + ViewHolderEmpty(DrawerEmptyBinding itemView) { + super(itemView.getRoot()); + binding = itemView; } } @@ -1272,20 +1247,13 @@ public class PixelfedListAdapter extends RecyclerView.Adapter statusesToRemove = new ArrayList<>(); - for (Status status : statuses) { - if (status.getAccount().getId().equals(targetedId)) - statusesToRemove.add(status); + static class ViewHolderPixelfed extends RecyclerView.ViewHolder { + DrawerPixelfedBinding binding; + + ViewHolderPixelfed(DrawerPixelfedBinding itemView) { + super(itemView.getRoot()); + binding = itemView; } - statuses.removeAll(statusesToRemove); - pixelfedListAdapter.notifyDataSetChanged(); - //Send an intent to delete in every timelines - Bundle b = new Bundle(); - b.putString("receive_action", targetedId); - Intent intentBC = new Intent(Helper.RECEIVE_ACTION); - intentBC.putExtras(b); } private void scheduleBoost(Status status) { @@ -1359,15 +1327,12 @@ public class PixelfedListAdapter extends RecyclerView.Adapter { @@ -2361,7 +2359,6 @@ public class ContentSettingsFragment extends Fragment implements OnRetrieveRemot mainMenuItem.setNav_blocked(nav_blocked.isChecked()); mainMenuItem.setNav_muted(nav_muted.isChecked()); mainMenuItem.setNav_blocked_domains(nav_blocked_domains.isChecked()); - mainMenuItem.setNav_howto(nav_how_to.isChecked()); MainMenuItem mainMenuItem1 = new MainMenuDAO(context, db).getMainMenu(); if (mainMenuItem1 != null) { diff --git a/app/src/main/java/app/fedilab/android/fragments/DisplayBookmarksPixelfedFragment.java b/app/src/main/java/app/fedilab/android/fragments/DisplayBookmarksPixelfedFragment.java index e6b922887..f3f877c6b 100644 --- a/app/src/main/java/app/fedilab/android/fragments/DisplayBookmarksPixelfedFragment.java +++ b/app/src/main/java/app/fedilab/android/fragments/DisplayBookmarksPixelfedFragment.java @@ -42,6 +42,7 @@ import app.fedilab.android.activities.MainActivity; import app.fedilab.android.asynctasks.RetrieveFeedsAsyncTask; import app.fedilab.android.client.APIResponse; import app.fedilab.android.client.Entities.Status; +import app.fedilab.android.client.Entities.StatusDrawerParams; import app.fedilab.android.drawers.PixelfedListAdapter; import app.fedilab.android.helper.Helper; import app.fedilab.android.interfaces.OnRetrieveFeedsInterface; @@ -108,7 +109,11 @@ public class DisplayBookmarksPixelfedFragment extends Fragment implements OnRetr statuses = apiResponse.getStatuses(); if (statuses != null && statuses.size() > 0) { LinearLayoutManager mLayoutManager = new LinearLayoutManager(context); - pixelfedListAdapter = new PixelfedListAdapter(RetrieveFeedsAsyncTask.Type.CACHE_BOOKMARKS, this.statuses); + StatusDrawerParams statusDrawerParams = new StatusDrawerParams(); + statusDrawerParams.setOnWifi(isOnWifi); + statusDrawerParams.setStatuses(this.statuses); + statusDrawerParams.setType(RetrieveFeedsAsyncTask.Type.CACHE_BOOKMARKS); + pixelfedListAdapter = new PixelfedListAdapter(statusDrawerParams); lv_status.setAdapter(pixelfedListAdapter); lv_status.setLayoutManager(mLayoutManager); } else { @@ -138,7 +143,11 @@ public class DisplayBookmarksPixelfedFragment extends Fragment implements OnRetr new StatusCacheDAO(context, db).removeAllStatus(StatusCacheDAO.BOOKMARK_CACHE); statuses = new ArrayList<>(); statuses.clear(); - pixelfedListAdapter = new PixelfedListAdapter(RetrieveFeedsAsyncTask.Type.CACHE_BOOKMARKS, statuses); + StatusDrawerParams statusDrawerParams = new StatusDrawerParams(); + statusDrawerParams.setOnWifi(isOnWifi); + statusDrawerParams.setStatuses(statuses); + statusDrawerParams.setType(RetrieveFeedsAsyncTask.Type.CACHE_BOOKMARKS); + pixelfedListAdapter = new PixelfedListAdapter(statusDrawerParams); lv_status.setAdapter(pixelfedListAdapter); pixelfedListAdapter.notifyDataSetChanged(); textviewNoAction.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/app/fedilab/android/fragments/DisplayStatusFragment.java b/app/src/main/java/app/fedilab/android/fragments/DisplayStatusFragment.java index 8a23fab96..6b21b7c88 100644 --- a/app/src/main/java/app/fedilab/android/fragments/DisplayStatusFragment.java +++ b/app/src/main/java/app/fedilab/android/fragments/DisplayStatusFragment.java @@ -269,7 +269,11 @@ public class DisplayStatusFragment extends Fragment implements OnPostActionInter } else if (instanceType.equals("PIXELFED")) { if (remoteInstance != null && MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) //if it's a Peertube account connected remoteInstance = instance; - pixelfedListAdapter = new PixelfedListAdapter(type, this.statuses); + StatusDrawerParams statusDrawerParams = new StatusDrawerParams(); + statusDrawerParams.setOnWifi(isOnWifi); + statusDrawerParams.setStatuses(this.statuses); + statusDrawerParams.setType(type); + pixelfedListAdapter = new PixelfedListAdapter(statusDrawerParams); lv_status.setAdapter(pixelfedListAdapter); } else if (instanceType.equals("ART")) { if (type == RetrieveFeedsAsyncTask.Type.TAG) { diff --git a/app/src/main/java/app/fedilab/android/helper/BaseHelper.java b/app/src/main/java/app/fedilab/android/helper/BaseHelper.java index 012dc2b71..64f29ff19 100644 --- a/app/src/main/java/app/fedilab/android/helper/BaseHelper.java +++ b/app/src/main/java/app/fedilab/android/helper/BaseHelper.java @@ -1451,6 +1451,16 @@ public class BaseHelper { MenuItem itemPCom = menu.findItem(R.id.nav_peertube_comm); if (itemPCom != null) itemPCom.setVisible(false); + MenuItem nav_scheduled = menu.findItem(R.id.nav_scheduled); + if (nav_scheduled != null) + nav_scheduled.setVisible(false); + if (nav_scheduled != null) + nav_scheduled.setVisible(false); + MenuItem nav_blocked_domains = menu.findItem(R.id.nav_blocked_domains); + if (nav_blocked_domains != null) + nav_blocked_domains.setVisible(false); + + } else if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.FRIENDICA || BaseMainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.GNU || BaseMainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON || BaseMainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { MenuItem itemCom = menu.findItem(R.id.nav_peertube_comm); if (itemCom != null) @@ -1523,9 +1533,6 @@ public class BaseHelper { if (!mainMenuItem.isNav_how_to_follow()) { menu.findItem(R.id.nav_who_to_follow).setVisible(false); } - if (!mainMenuItem.isNav_howto()) { - menu.findItem(R.id.nav_how_to).setVisible(false); - } if (!mainMenuItem.isNav_muted()) { menu.findItem(R.id.nav_muted).setVisible(false); } @@ -1567,7 +1574,6 @@ public class BaseHelper { menu.findItem(R.id.nav_archive).setVisible(false); menu.findItem(R.id.nav_archive_notifications).setVisible(false); menu.findItem(R.id.nav_who_to_follow).setVisible(false); - menu.findItem(R.id.nav_how_to).setVisible(false); menu.findItem(R.id.nav_partnership).setVisible(false); menu.findItem(R.id.nav_news).setVisible(false); menu.findItem(R.id.nav_trends).setVisible(false); diff --git a/app/src/main/java/app/fedilab/android/helper/CrossActions.java b/app/src/main/java/app/fedilab/android/helper/CrossActions.java index bd29489d4..65b0b4325 100644 --- a/app/src/main/java/app/fedilab/android/helper/CrossActions.java +++ b/app/src/main/java/app/fedilab/android/helper/CrossActions.java @@ -178,6 +178,18 @@ public class CrossActions { ((PixelfedListAdapter) baseAdapter).notifyStatusChanged(status); else if (baseAdapter instanceof StatusListAdapter) ((StatusListAdapter) baseAdapter).notifyStatusChanged(status); + } else if (doAction == API.StatusAction.BOOKMARK || doAction == API.StatusAction.UNBOOKMARK) { + if (doAction == API.StatusAction.BOOKMARK) { + status.setBookmarked(true); + status.setBookmarkAnimated(true); + } else { + status.setBookmarked(false); + status.setBookmarkAnimated(false); + } + if (baseAdapter instanceof PixelfedListAdapter) + ((PixelfedListAdapter) baseAdapter).notifyStatusChanged(status); + else if (baseAdapter instanceof StatusListAdapter) + ((StatusListAdapter) baseAdapter).notifyStatusChanged(status); } } } else if (accounts.size() == 1 || undoAction) { @@ -190,6 +202,8 @@ public class CrossActions { favouriteAction(context, status, onPostActionInterface); else if (doAction == API.StatusAction.PIN || doAction == API.StatusAction.UNPIN) pinAction(context, status, baseAdapter, onPostActionInterface); + else if (doAction == API.StatusAction.BOOKMARK || doAction == API.StatusAction.UNBOOKMARK) + bookmarkAction(context, status, onPostActionInterface); if (doAction == API.StatusAction.FAVOURITE || doAction == API.StatusAction.UNFAVOURITE) { if (doAction == API.StatusAction.FAVOURITE) { @@ -215,6 +229,18 @@ public class CrossActions { ((PixelfedListAdapter) baseAdapter).notifyStatusChanged(status); else if (baseAdapter instanceof StatusListAdapter) ((StatusListAdapter) baseAdapter).notifyStatusChanged(status); + } else if (doAction == API.StatusAction.BOOKMARK || doAction == API.StatusAction.UNBOOKMARK) { + if (doAction == API.StatusAction.BOOKMARK) { + status.setBookmarked(true); + status.setBookmarkAnimated(true); + } else { + status.setBookmarked(false); + status.setBookmarkAnimated(false); + } + if (baseAdapter instanceof PixelfedListAdapter) + ((PixelfedListAdapter) baseAdapter).notifyStatusChanged(status); + else if (baseAdapter instanceof StatusListAdapter) + ((StatusListAdapter) baseAdapter).notifyStatusChanged(status); } } } else { @@ -250,6 +276,10 @@ public class CrossActions { status.setFavourited(true); if (type == RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE || type == RetrieveFeedsAsyncTask.Type.NEWS) status.setFavAnimated(true); + } else if (doAction == API.StatusAction.BOOKMARK) { + status.setBookmarked(true); + if (type == RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE || type == RetrieveFeedsAsyncTask.Type.NEWS) + status.setBookmarkAnimated(true); } else if (doAction == API.StatusAction.PIN) { status.setPinned(true); } @@ -747,6 +777,8 @@ public class CrossActions { favouriteAction(context, status, onPostActionInterface); else if (action == API.StatusAction.PIN || action == API.StatusAction.UNPIN) pinAction(context, status, baseAdapter, onPostActionInterface); + else if (action == API.StatusAction.BOOKMARK || action == API.StatusAction.UNBOOKMARK) + bookmarkAction(context, status, onPostActionInterface); if (action == API.StatusAction.FAVOURITE || action == API.StatusAction.UNFAVOURITE) { if (action == API.StatusAction.FAVOURITE) { @@ -772,6 +804,18 @@ public class CrossActions { ((PixelfedListAdapter) baseAdapter).notifyStatusChanged(status); else if (baseAdapter instanceof StatusListAdapter) ((StatusListAdapter) baseAdapter).notifyStatusChanged(status); + } else if (action == API.StatusAction.BOOKMARK || action == API.StatusAction.UNBOOKMARK) { + if (action == API.StatusAction.BOOKMARK) { + status.setBookmarked(true); + status.setBookmarkAnimated(true); + } else { + status.setBookmarked(false); + status.setBookmarkAnimated(false); + } + if (baseAdapter instanceof PixelfedListAdapter) + ((PixelfedListAdapter) baseAdapter).notifyStatusChanged(status); + else if (baseAdapter instanceof StatusListAdapter) + ((StatusListAdapter) baseAdapter).notifyStatusChanged(status); } dialog.dismiss(); }) @@ -860,6 +904,22 @@ public class CrossActions { } } + /** + * Bookmark/Unbookmark a status + * + * @param status Status + */ + private static void bookmarkAction(Context context, Status status, OnPostActionInterface onPostActionInterface) { + + if (status.isFavourited() || (status.getReblog() != null && status.getReblog().isFavourited())) { + new PostActionAsyncTask(context, API.StatusAction.UNBOOKMARK, status.getId(), onPostActionInterface); + status.setBookmarked(false); + } else { + new PostActionAsyncTask(context, API.StatusAction.BOOKMARK, status.getId(), onPostActionInterface); + status.setBookmarked(true); + } + } + /** * Reblog/Unreblog a status * diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml index 8e2835155..0a15f051a 100644 --- a/app/src/main/res/layout/activity_about.xml +++ b/app/src/main/res/layout/activity_about.xml @@ -89,17 +89,6 @@ android:text="PayPal" tools:ignore="HardcodedText" /> - - - + + android:layout_height="match_parent"> + + + + + + @@ -84,17 +96,21 @@ android:layout_height="wrap_content" android:indeterminate="true" /> - + + - + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_show_conversation.xml b/app/src/main/res/layout/activity_show_conversation.xml index 4c5d3264a..ee22d0cf7 100644 --- a/app/src/main/res/layout/activity_show_conversation.xml +++ b/app/src/main/res/layout/activity_show_conversation.xml @@ -17,11 +17,13 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> - + - + + @@ -44,6 +60,9 @@ - + \ No newline at end of file diff --git a/app/src/main/res/layout/drawer_pixelfed.xml b/app/src/main/res/layout/drawer_pixelfed.xml index c964cec6f..14389190a 100644 --- a/app/src/main/res/layout/drawer_pixelfed.xml +++ b/app/src/main/res/layout/drawer_pixelfed.xml @@ -101,87 +101,109 @@ - - + + + android:layout_marginTop="5dp" + android:singleLine="true" + android:textStyle="bold" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/pf_fav" /> - + - + - - - + - + + + android:layout_marginTop="5dp" + android:textIsSelectable="true" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/pf_likes" /> - - - - - - - - + + - + android:layout_marginBottom="5dp" + android:orientation="vertical"> + android:layout_gravity="center" + android:gravity="center" + android:orientation="horizontal" + android:paddingLeft="10dp" + android:paddingTop="5dp" + android:paddingRight="10dp" + android:paddingBottom="10dp" + tools:ignore="UseCompoundDrawables"> - + android:contentDescription="@string/profile_picture" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_marginStart="15dp" + android:layout_marginLeft="15dp" + android:textSize="16sp" + android:textStyle="bold" + tools:ignore="RtlHardcoded" /> - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_settings_menu.xml b/app/src/main/res/layout/fragment_settings_menu.xml index 4e30ccba6..9a38a2591 100644 --- a/app/src/main/res/layout/fragment_settings_menu.xml +++ b/app/src/main/res/layout/fragment_settings_menu.xml @@ -403,28 +403,6 @@ android:background="?colorAccent" /> - - - - - - -