Some fixes

This commit is contained in:
Thomas 2022-11-02 18:37:29 +01:00
parent 1dbc5b7a89
commit db066c6ba6
15 changed files with 290 additions and 337 deletions

View file

@ -164,8 +164,8 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
public static boolean show_boosts, show_replies, show_art_nsfw;
public static String regex_home, regex_local, regex_public;
public static BaseAccount currentAccount;
public static iconLauncher mLauncher = iconLauncher.BUBBLES;
Fragment currentFragment;
private AppBarConfiguration mAppBarConfiguration;
private ActivityMainBinding binding;
private final BroadcastReceiver broadcast_error_message = new BroadcastReceiver() {
@ -195,8 +195,101 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
}
}
};
public static iconLauncher mLauncher = iconLauncher.BUBBLES;
private Pinned pinned;
private BottomMenu bottomMenu;
private final BroadcastReceiver broadcast_data = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle b = intent.getExtras();
if (b != null) {
if (b.getBoolean(Helper.RECEIVE_REDRAW_TOPBAR, false)) {
List<MastodonList> mastodonLists = (List<MastodonList>) b.getSerializable(Helper.RECEIVE_MASTODON_LIST);
redrawPinned(mastodonLists);
}
if (b.getBoolean(Helper.RECEIVE_REDRAW_BOTTOM, false)) {
bottomMenu = new BottomMenu(BaseMainActivity.this).hydrate(currentAccount, binding.bottomNavView);
if (bottomMenu != null) {
//ManageClick on bottom menu items
if (binding.bottomNavView.findViewById(R.id.nav_home) != null) {
binding.bottomNavView.findViewById(R.id.nav_home).setOnLongClickListener(view -> {
int position = BottomMenu.getPosition(bottomMenu, R.id.nav_home);
if (position >= 0) {
manageFilters(position);
}
return false;
});
}
if (binding.bottomNavView.findViewById(R.id.nav_local) != null) {
binding.bottomNavView.findViewById(R.id.nav_local).setOnLongClickListener(view -> {
int position = BottomMenu.getPosition(bottomMenu, R.id.nav_local);
if (position >= 0) {
manageFilters(position);
}
return false;
});
}
if (binding.bottomNavView.findViewById(R.id.nav_public) != null) {
binding.bottomNavView.findViewById(R.id.nav_public).setOnLongClickListener(view -> {
int position = BottomMenu.getPosition(bottomMenu, R.id.nav_public);
if (position >= 0) {
manageFilters(position);
}
return false;
});
}
binding.bottomNavView.setOnItemSelectedListener(item -> {
int itemId = item.getItemId();
int position = BottomMenu.getPosition(bottomMenu, itemId);
if (position >= 0) {
if (binding.viewPager.getCurrentItem() == position) {
scrollToTop();
} else {
binding.viewPager.setCurrentItem(position, false);
}
}
return true;
});
}
} else if (b.getBoolean(Helper.RECEIVE_RECREATE_ACTIVITY, false)) {
Cyanea.getInstance().edit().apply().recreate(BaseMainActivity.this);
} else if (b.getBoolean(Helper.RECEIVE_NEW_MESSAGE, false)) {
Status statusSent = (Status) b.getSerializable(Helper.RECEIVE_STATUS_ACTION);
String statusEditId = b.getString(Helper.ARG_EDIT_STATUS_ID, null);
Snackbar.make(binding.displaySnackBar, getString(R.string.message_has_been_sent), Snackbar.LENGTH_LONG)
.setAction(getString(R.string.display), view -> {
Intent intentContext = new Intent(BaseMainActivity.this, ContextActivity.class);
intentContext.putExtra(Helper.ARG_STATUS, statusSent);
intentContext.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intentContext);
})
.setTextColor(ThemeHelper.getAttColor(BaseMainActivity.this, R.attr.mTextColor))
.setActionTextColor(ContextCompat.getColor(BaseMainActivity.this, R.color.cyanea_accent_reference))
.setBackgroundTint(ContextCompat.getColor(BaseMainActivity.this, R.color.cyanea_primary_dark_reference))
.show();
//The message was edited, we need to update the timeline
if (statusEditId != null) {
//Update message in cache
new Thread(() -> {
StatusCache statusCache = new StatusCache();
statusCache.instance = BaseMainActivity.currentInstance;
statusCache.user_id = BaseMainActivity.currentUserID;
statusCache.status = statusSent;
statusCache.status_id = statusEditId;
try {
new StatusCache(BaseMainActivity.this).updateIfExists(statusCache);
} catch (DBException e) {
e.printStackTrace();
}
}).start();
//Update timelines
sendAction(context, Helper.ARG_STATUS_UPDATED, statusSent, null);
}
}
}
}
};
private NetworkStateReceiver networkStateReceiver;
private boolean headerMenuOpen;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -214,7 +307,6 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
}
mamageNewIntent(getIntent());
ThemeHelper.initiliazeColors(BaseMainActivity.this);
filterFetched = false;
@ -660,102 +752,6 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
}
}
private Pinned pinned;
private BottomMenu bottomMenu;
private final BroadcastReceiver broadcast_data = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle b = intent.getExtras();
if (b != null) {
if (b.getBoolean(Helper.RECEIVE_REDRAW_TOPBAR, false)) {
List<MastodonList> mastodonLists = (List<MastodonList>) b.getSerializable(Helper.RECEIVE_MASTODON_LIST);
redrawPinned(mastodonLists);
}
if (b.getBoolean(Helper.RECEIVE_REDRAW_BOTTOM, false)) {
bottomMenu = new BottomMenu(BaseMainActivity.this).hydrate(currentAccount, binding.bottomNavView);
if (bottomMenu != null) {
//ManageClick on bottom menu items
if (binding.bottomNavView.findViewById(R.id.nav_home) != null) {
binding.bottomNavView.findViewById(R.id.nav_home).setOnLongClickListener(view -> {
int position = BottomMenu.getPosition(bottomMenu, R.id.nav_home);
if (position >= 0) {
manageFilters(position);
}
return false;
});
}
if (binding.bottomNavView.findViewById(R.id.nav_local) != null) {
binding.bottomNavView.findViewById(R.id.nav_local).setOnLongClickListener(view -> {
int position = BottomMenu.getPosition(bottomMenu, R.id.nav_local);
if (position >= 0) {
manageFilters(position);
}
return false;
});
}
if (binding.bottomNavView.findViewById(R.id.nav_public) != null) {
binding.bottomNavView.findViewById(R.id.nav_public).setOnLongClickListener(view -> {
int position = BottomMenu.getPosition(bottomMenu, R.id.nav_public);
if (position >= 0) {
manageFilters(position);
}
return false;
});
}
binding.bottomNavView.setOnItemSelectedListener(item -> {
int itemId = item.getItemId();
int position = BottomMenu.getPosition(bottomMenu, itemId);
if (position >= 0) {
if (binding.viewPager.getCurrentItem() == position) {
scrollToTop();
} else {
binding.viewPager.setCurrentItem(position, false);
}
}
return true;
});
}
} else if (b.getBoolean(Helper.RECEIVE_RECREATE_ACTIVITY, false)) {
Cyanea.getInstance().edit().apply().recreate(BaseMainActivity.this);
} else if (b.getBoolean(Helper.RECEIVE_NEW_MESSAGE, false)) {
Status statusSent = (Status) b.getSerializable(Helper.RECEIVE_STATUS_ACTION);
String statusEditId = b.getString(Helper.ARG_EDIT_STATUS_ID, null);
Snackbar.make(binding.displaySnackBar, getString(R.string.message_has_been_sent), Snackbar.LENGTH_LONG)
.setAction(getString(R.string.display), view -> {
Intent intentContext = new Intent(BaseMainActivity.this, ContextActivity.class);
intentContext.putExtra(Helper.ARG_STATUS, statusSent);
intentContext.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intentContext);
})
.setTextColor(ThemeHelper.getAttColor(BaseMainActivity.this, R.attr.mTextColor))
.setActionTextColor(ContextCompat.getColor(BaseMainActivity.this, R.color.cyanea_accent_reference))
.setBackgroundTint(ContextCompat.getColor(BaseMainActivity.this, R.color.cyanea_primary_dark_reference))
.show();
//The message was edited, we need to update the timeline
if (statusEditId != null) {
//Update message in cache
new Thread(() -> {
StatusCache statusCache = new StatusCache();
statusCache.instance = BaseMainActivity.currentInstance;
statusCache.user_id = BaseMainActivity.currentUserID;
statusCache.status = statusSent;
statusCache.status_id = statusEditId;
try {
new StatusCache(BaseMainActivity.this).updateIfExists(statusCache);
} catch (DBException e) {
e.printStackTrace();
}
}).start();
//Update timelines
sendAction(context, Helper.ARG_STATUS_UPDATED, statusSent, null);
}
}
}
}
};
private NetworkStateReceiver networkStateReceiver;
private boolean headerMenuOpen;
protected abstract void rateThisApp();
@Override
@ -987,16 +983,6 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
}
public enum iconLauncher {
BUBBLES,
FEDIVERSE,
HERO,
ATOM,
BRAINCRASH,
MASTALAB
}
private void manageFilters(int position) {
View view = binding.bottomNavView.findViewById(R.id.nav_home);
boolean showExtendedFilter = true;
@ -1338,7 +1324,6 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
}
}
public void redrawPinned(List<MastodonList> mastodonLists) {
int currentItem = binding.viewPager.getCurrentItem();
new ViewModelProvider(BaseMainActivity.this).get(TopBarVM.class).getDBPinned()
@ -1389,6 +1374,17 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
}
}
@Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
//unselect all tag elements
for (PinnedTimeline pinnedTimeline : pinned.pinnedTimelines) {
pinnedTimeline.isSelected = false;
}
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
/* @Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
@ -1418,17 +1414,6 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
return true;
}*/
@Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
//unselect all tag elements
for (PinnedTimeline pinnedTimeline : pinned.pinnedTimelines) {
pinnedTimeline.isSelected = false;
}
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
@Override
public void networkAvailable() {
networkAvailable = status.CONNECTED;
@ -1439,6 +1424,15 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
networkAvailable = DISCONNECTED;
}
public enum iconLauncher {
BUBBLES,
FEDIVERSE,
HERO,
ATOM,
BRAINCRASH,
MASTALAB
}
public enum status {
UNKNOWN,

View file

@ -41,25 +41,9 @@ public class Notification {
public boolean cached;
public PositionFetchMore positionFetchMore = PositionFetchMore.BOTTOM;
public enum PositionFetchMore {
TOP,
BOTTOM
}
@Override
public boolean equals(@Nullable Object obj) {
boolean same = false;
if (obj instanceof Notification) {
same = this.id.equals(((Notification) obj).id);
}
return same;
}
public transient List<Notification> relatedNotifications;
public boolean isFetchMore;
/**
* Serialized a list of Notification class
*
@ -91,4 +75,18 @@ public class Notification {
}
}
@Override
public boolean equals(@Nullable Object obj) {
boolean same = false;
if (obj instanceof Notification) {
same = this.id.equals(((Notification) obj).id);
}
return same;
}
public enum PositionFetchMore {
TOP,
BOTTOM
}
}

View file

@ -113,12 +113,6 @@ public class Status implements Serializable, Cloneable {
public transient boolean submitted = false;
public transient boolean spoilerChecked = false;
public enum PositionFetchMore {
TOP,
BOTTOM
}
@Override
public boolean equals(@Nullable Object obj) {
boolean same = false;
@ -127,12 +121,11 @@ public class Status implements Serializable, Cloneable {
}
return same;
}
//Some extra spannable element - They will be filled automatically when fetching the status
public synchronized Spannable getSpanContent(Context context, WeakReference<View> viewWeakReference) {
return SpannableHelper.convert(context, content, this, null, null, true, viewWeakReference);
}
//Some extra spannable element - They will be filled automatically when fetching the status
public Spannable getSpanContentNitter() {
return SpannableHelper.convertNitter(content);
@ -151,4 +144,9 @@ public class Status implements Serializable, Cloneable {
return super.clone();
}
public enum PositionFetchMore {
TOP,
BOTTOM
}
}

View file

@ -376,6 +376,8 @@ public class Helper {
};
public static int counter = 1;
private static int notificationId = 1;
//Allow to store in shared preference first visible fragment when the app starts
private static String slugOfFirstFragment;
static {
LinkedHashMap<PatternType, Pattern> aMap = new LinkedHashMap<>();
@ -1855,6 +1857,24 @@ public class Helper {
}
}
public static String getSlugOfFirstFragment(Context context, String userId, String instance) {
if (slugOfFirstFragment != null) {
return slugOfFirstFragment;
}
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
return sharedpreferences.getString(Helper.ARG_SLUG_OF_FIRST_FRAGMENT + userId + instance, Timeline.TimeLineEnum.HOME.getValue());
}
public static void setSlugOfFirstFragment(Context context, String slug, String userId, String instance) {
if (slug != null) {
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = sharedpreferences.edit();
slugOfFirstFragment = slug;
editor.putString(Helper.ARG_SLUG_OF_FIRST_FRAGMENT + userId + instance, slug);
editor.apply();
}
}
//Enum that described actions to replace inside a toot content
public enum PatternType {
@ -1876,30 +1896,7 @@ public class Helper {
TOOT
}
public interface OnAttachmentCopied {
void onAttachmentCopied(Attachment attachment);
}
//Allow to store in shared preference first visible fragment when the app starts
private static String slugOfFirstFragment;
public static String getSlugOfFirstFragment(Context context, String userId, String instance) {
if (slugOfFirstFragment != null) {
return slugOfFirstFragment;
}
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
return sharedpreferences.getString(Helper.ARG_SLUG_OF_FIRST_FRAGMENT + userId + instance, Timeline.TimeLineEnum.HOME.getValue());
}
public static void setSlugOfFirstFragment(Context context, String slug, String userId, String instance) {
if (slug != null) {
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = sharedpreferences.edit();
slugOfFirstFragment = slug;
editor.putString(Helper.ARG_SLUG_OF_FIRST_FRAGMENT + userId + instance, slug);
editor.apply();
}
}
}

View file

@ -134,12 +134,12 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
private final BaseAccount account;
private final String visibility;
private final app.fedilab.android.client.entities.api.Account mentionedAccount;
private final String editMessageId;
public ManageDrafts manageDrafts;
private int statusCount;
private Context context;
private AlertDialog alertDialogEmoji;
private List<Emoji> emojisList = new ArrayList<>();
private final String editMessageId;
public ComposeAdapter(List<Status> statusList, int statusCount, BaseAccount account, app.fedilab.android.client.entities.api.Account mentionedAccount, String visibility, String editMessageId) {
this.statusList = statusList;
@ -399,7 +399,7 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
if (position == -1) {
position = statusList.size() - 1;
}
// position = statusCount-1+position;
// position = statusCount-1+position;
if (statusList.get(position).media_attachments == null) {
statusList.get(position).media_attachments = new ArrayList<>();
}

View file

@ -56,9 +56,9 @@ import app.fedilab.android.helper.MastodonHelper;
public class ConversationAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final List<Conversation> conversationList;
public FetchMoreCallBack fetchMoreCallBack;
private Context context;
private boolean isExpended = false;
public FetchMoreCallBack fetchMoreCallBack;
public ConversationAdapter(List<Conversation> conversations) {
if (conversations == null) {
@ -284,6 +284,12 @@ public class ConversationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
}
}
public interface FetchMoreCallBack {
void onClickMinId(String min_id, Conversation conversationToUpdate);
void onClickMaxId(String max_id, Conversation conversationToUpdate);
}
static class ConversationHolder extends RecyclerView.ViewHolder {
DrawerConversationBinding binding;
Timer timer;
@ -293,10 +299,4 @@ public class ConversationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
binding = itemView;
}
}
public interface FetchMoreCallBack {
void onClickMinId(String min_id, Conversation conversationToUpdate);
void onClickMaxId(String max_id, Conversation conversationToUpdate);
}
}

View file

@ -352,13 +352,6 @@ public class NotificationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
}
}
public interface FetchMoreCallBack {
void onClickMinId(String min_id, Notification notificationToUpdate);
void onClickMaxId(String max_id, Notification notificationToUpdate);
}
public long getItemId(int position) {
return position;
}
@ -368,6 +361,11 @@ public class NotificationAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
return notificationList.size();
}
public interface FetchMoreCallBack {
void onClickMinId(String min_id, Notification notificationToUpdate);
void onClickMaxId(String max_id, Notification notificationToUpdate);
}
static class ViewHolderFollow extends RecyclerView.ViewHolder {
DrawerFollowBinding binding;

View file

@ -44,8 +44,8 @@ public class ReactionAdapter extends RecyclerView.Adapter<ReactionAdapter.Reacti
private final List<Reaction> reactions;
private final String announcementId;
private Context context;
private final boolean statusReaction;
private Context context;
ReactionAdapter(String announcementId, List<Reaction> reactions, boolean statusReaction) {
this.reactions = reactions;

View file

@ -39,7 +39,6 @@ import app.fedilab.android.BaseMainActivity;
import app.fedilab.android.R;
import app.fedilab.android.client.entities.api.Conversation;
import app.fedilab.android.client.entities.api.Conversations;
import app.fedilab.android.client.entities.api.Pagination;
import app.fedilab.android.client.entities.app.StatusCache;
import app.fedilab.android.client.entities.app.Timeline;
import app.fedilab.android.databinding.FragmentPaginationBinding;
@ -54,6 +53,7 @@ import app.fedilab.android.viewmodel.mastodon.TimelinesVM;
public class FragmentMastodonConversation extends Fragment implements ConversationAdapter.FetchMoreCallBack {
public UpdateCounters update;
private FragmentPaginationBinding binding;
private TimelinesVM timelinesVM;
private boolean flagLoading;
@ -61,10 +61,10 @@ public class FragmentMastodonConversation extends Fragment implements Conversati
private String max_id, min_id, min_id_fetch_more, max_id_fetch_more;
private ConversationAdapter conversationAdapter;
private LinearLayoutManager mLayoutManager;
public UpdateCounters update;
private boolean isViewInitialized;
private Conversations initialConversations;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
flagLoading = false;
@ -88,17 +88,7 @@ public class FragmentMastodonConversation extends Fragment implements Conversati
super.onResume();
if (Timeline.TimeLineEnum.CONVERSATION.getValue().compareTo(Helper.getSlugOfFirstFragment(requireActivity(), currentUserID, currentInstance)) != 0 && !isViewInitialized) {
isViewInitialized = true;
if (initialConversations != null && initialConversations.conversations != null && initialConversations.conversations.size() > 0) {
initializeConversationCommonView(initialConversations);
} else {
Conversations conversations = new Conversations();
if (conversationList != null && conversationList.size() > 0) {
conversations.pagination = new Pagination();
conversations.pagination.max_id = conversationList.get(conversationList.size() - 1).id;
conversations.pagination.min_id = conversationList.get(0).id;
}
initializeConversationCommonView(conversations);
}
initializeConversationCommonView(initialConversations);
}
}

View file

@ -28,6 +28,7 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
@ -45,7 +46,6 @@ import app.fedilab.android.BaseMainActivity;
import app.fedilab.android.R;
import app.fedilab.android.client.entities.api.Notification;
import app.fedilab.android.client.entities.api.Notifications;
import app.fedilab.android.client.entities.api.Pagination;
import app.fedilab.android.client.entities.api.Status;
import app.fedilab.android.client.entities.app.StatusCache;
import app.fedilab.android.client.entities.app.Timeline;
@ -67,9 +67,6 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
private boolean flagLoading;
private List<Notification> notificationList;
private NotificationAdapter notificationAdapter;
private boolean isViewInitialized;
private Notifications initialNotifications;
private final BroadcastReceiver receive_action = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@ -93,6 +90,8 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
}
}
};
private boolean isViewInitialized;
private Notifications initialNotifications;
private String max_id, min_id, min_id_fetch_more, max_id_fetch_more;
private LinearLayoutManager mLayoutManager;
private NotificationTypeEnum notificationType;
@ -136,6 +135,18 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
return found ? position : -1;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
notificationsVM = new ViewModelProvider(FragmentMastodonNotification.this).get(NotificationsVM.class);
binding.loader.setVisibility(View.VISIBLE);
binding.recyclerView.setVisibility(View.GONE);
max_id = null;
route(null, false);
}
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
@ -153,11 +164,7 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
binding.swipeContainer.setColorSchemeColors(
c1, c1, c1
);
notificationsVM = new ViewModelProvider(FragmentMastodonNotification.this).get(NotificationsVM.class);
binding.loader.setVisibility(View.VISIBLE);
binding.recyclerView.setVisibility(View.GONE);
max_id = null;
route(null, false);
LocalBroadcastManager.getInstance(requireActivity()).registerReceiver(receive_action, new IntentFilter(Helper.RECEIVE_STATUS_ACTION));
return root;
}
@ -199,6 +206,7 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
}
return excludeType;
}
/**
* Intialize the view for notifications
*
@ -298,17 +306,7 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
super.onResume();
if (Timeline.TimeLineEnum.NOTIFICATION.getValue().compareTo(Helper.getSlugOfFirstFragment(requireActivity(), currentUserID, currentInstance)) != 0 && !isViewInitialized) {
isViewInitialized = true;
if (initialNotifications != null && initialNotifications.notifications != null && initialNotifications.notifications.size() > 0) {
initializeNotificationView(initialNotifications);
} else {
Notifications notifications = new Notifications();
if (notificationList != null && notificationList.size() > 0) {
notifications.pagination = new Pagination();
notifications.pagination.max_id = notificationList.get(notificationList.size() - 1).id;
notifications.pagination.min_id = notificationList.get(0).id;
}
initializeNotificationView(notifications);
}
initializeNotificationView(initialNotifications);
}
}
@ -589,7 +587,6 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
}
@Override
public void onDestroyView() {
LocalBroadcastManager.getInstance(requireActivity()).unregisterReceiver(receive_action);

View file

@ -32,6 +32,7 @@ import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
@ -69,6 +70,7 @@ import es.dmoral.toasty.Toasty;
public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.FetchMoreCallBack {
public UpdateCounters update;
private FragmentPaginationBinding binding;
private TimelinesVM timelinesVM;
private AccountsVM accountsVM;
@ -79,10 +81,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
private StatusAdapter statusAdapter;
private Timeline.TimeLineEnum timelineType;
private List<Status> timelineStatuses;
public UpdateCounters update;
private boolean isViewInitialized;
private Statuses initialStatuses;
//Handle actions that can be done in other fragments
private final BroadcastReceiver receive_action = new BroadcastReceiver() {
@Override
@ -138,6 +136,8 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
}
}
};
private boolean isViewInitialized;
private Statuses initialStatuses;
private String list_id;
private TagTimeline tagTimeline;
private LinearLayoutManager mLayoutManager;
@ -157,17 +157,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
if (slug != null && slug.compareTo(Helper.getSlugOfFirstFragment(requireActivity(), currentUserID, currentInstance)) != 0
&& !isViewInitialized) {
isViewInitialized = true;
if (initialStatuses != null && initialStatuses.statuses != null && initialStatuses.statuses.size() > 0) {
initializeStatusesCommonView(initialStatuses);
} else {
Statuses statuses = new Statuses();
if (timelineStatuses != null && timelineStatuses.size() > 0) {
statuses.pagination = new Pagination();
statuses.pagination.max_id = timelineStatuses.get(timelineStatuses.size() - 1).id;
statuses.pagination.min_id = timelineStatuses.get(0).id;
}
initializeStatusesCommonView(statuses);
}
initializeStatusesCommonView(initialStatuses);
}
if (timelineStatuses != null && timelineStatuses.size() > 0) {
route(DIRECTION.FETCH_NEW, true);
@ -219,6 +209,35 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
}
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
timelinesVM = new ViewModelProvider(FragmentMastodonTimeline.this).get(viewModelKey, TimelinesVM.class);
accountsVM = new ViewModelProvider(FragmentMastodonTimeline.this).get(viewModelKey, AccountsVM.class);
binding.loader.setVisibility(View.VISIBLE);
binding.recyclerView.setVisibility(View.GONE);
max_id = statusReport != null ? statusReport.id : null;
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity());
rememberPosition = sharedpreferences.getBoolean(getString(R.string.SET_REMEMBER_POSITION), true);
//Inner marker are only for pinned timelines and main timelines, they have isViewInitialized set to false
if (max_id == null && !isViewInitialized && rememberPosition) {
max_id = sharedpreferences.getString(getString(R.string.SET_INNER_MARKER) + BaseMainActivity.currentUserID + BaseMainActivity.currentInstance + slug, null);
}
//Only fragment in main view pager should not have the view initialized
//AND Only the first fragment will initialize its view
if (!isViewInitialized) {
if (slug != null) {
isViewInitialized = slug.compareTo(Helper.getSlugOfFirstFragment(requireActivity(), currentUserID, currentInstance)) == 0;
}
}
flagLoading = false;
router(null);
}
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
@ -273,8 +292,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
slug = timelineType != Timeline.TimeLineEnum.ART ? timelineType.getValue() + (ident != null ? "|" + ident : "") : Timeline.TimeLineEnum.TAG.getValue() + (ident != null ? "|" + ident : "");
}
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity());
LocalBroadcastManager.getInstance(requireActivity()).registerReceiver(receive_action, new IntentFilter(Helper.RECEIVE_STATUS_ACTION));
binding = FragmentPaginationBinding.inflate(inflater, container, false);
binding.getRoot().setBackgroundColor(ThemeHelper.getBackgroundColor(requireActivity()));
@ -285,28 +302,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
c1, c1, c1
);
timelinesVM = new ViewModelProvider(FragmentMastodonTimeline.this).get(viewModelKey, TimelinesVM.class);
accountsVM = new ViewModelProvider(FragmentMastodonTimeline.this).get(viewModelKey, AccountsVM.class);
binding.loader.setVisibility(View.VISIBLE);
binding.recyclerView.setVisibility(View.GONE);
max_id = statusReport != null ? statusReport.id : null;
rememberPosition = sharedpreferences.getBoolean(getString(R.string.SET_REMEMBER_POSITION), true);
//Inner marker are only for pinned timelines and main timelines, they have isViewInitialized set to false
if (max_id == null && !isViewInitialized && rememberPosition) {
max_id = sharedpreferences.getString(getString(R.string.SET_INNER_MARKER) + BaseMainActivity.currentUserID + BaseMainActivity.currentInstance + slug, null);
}
//Only fragment in main view pager should not have the view initialized
//AND Only the first fragment will initialize its view
if (!isViewInitialized) {
if (slug != null) {
isViewInitialized = slug.compareTo(Helper.getSlugOfFirstFragment(requireActivity(), currentUserID, currentInstance)) == 0;
}
}
flagLoading = false;
router(null);
return binding.getRoot();
}
@ -693,9 +688,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
}
private void getCachedStatus(DIRECTION direction, boolean fetchingMissing, TimelinesVM.TimelineParams timelineParams) {
if (getView() == null) {
return;
}
if (direction == null) {
timelinesVM.getTimelineCache(timelineStatuses, timelineParams)
.observe(getViewLifecycleOwner(), statusesCached -> {
@ -742,9 +735,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
}
private void getLiveStatus(DIRECTION direction, boolean fetchingMissing, TimelinesVM.TimelineParams timelineParams, Status status) {
if (getView() == null) {
return;
}
if (direction == null) {
timelinesVM.getTimeline(timelineStatuses, timelineParams)
@ -770,16 +760,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
}
}
public enum DIRECTION {
TOP,
BOTTOM,
REFRESH,
SCROLL_TOP,
FETCH_NEW
}
/**
* Router for timelines
*
@ -965,9 +945,6 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
}
/**
* Refresh status in list
*/
@ -990,6 +967,14 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
route(DIRECTION.BOTTOM, true, statusToUpdate);
}
public enum DIRECTION {
TOP,
BOTTOM,
REFRESH,
SCROLL_TOP,
FETCH_NEW
}
public interface UpdateCounters {
void onUpdate(int count, Timeline.TimeLineEnum type, String slug);
}

View file

@ -53,8 +53,8 @@ import es.dmoral.toasty.Toasty;
public class FragmentNotificationContainer extends Fragment {
private FragmentNotificationContainerBinding binding;
public static UpdateCounters update;
private FragmentNotificationContainerBinding binding;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {

View file

@ -45,8 +45,8 @@ public class FedilabPageAdapter extends FragmentStatePagerAdapter {
private final BottomMenu bottomMenu;
private final int toRemove;
private final boolean singleBar;
private Fragment mCurrentFragment;
private final BaseMainActivity activity;
private Fragment mCurrentFragment;
public FedilabPageAdapter(BaseMainActivity activity, FragmentManager fm, Pinned pinned, BottomMenu bottomMenu) {
super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);

View file

@ -64,15 +64,6 @@ public class NotificationsVM extends AndroidViewModel {
super(application);
}
private MastodonNotificationsService init(@NonNull String instance) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://" + instance + "/api/v1/")
.addConverterFactory(GsonConverterFactory.create(Helper.getDateBuilder()))
.client(okHttpClient)
.build();
return retrofit.create(MastodonNotificationsService.class);
}
private static void addFetchMoreNotifications(List<Notification> notificationList, List<Notification> timelineNotifications, TimelinesVM.TimelineParams timelineParams) throws DBException {
if (notificationList != null && notificationList.size() > 0 && timelineNotifications != null && timelineNotifications.size() > 0) {
if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.REFRESH || timelineParams.direction == FragmentMastodonTimeline.DIRECTION.SCROLL_TOP || timelineParams.direction == FragmentMastodonTimeline.DIRECTION.FETCH_NEW) {
@ -95,6 +86,15 @@ public class NotificationsVM extends AndroidViewModel {
}
}
private MastodonNotificationsService init(@NonNull String instance) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://" + instance + "/api/v1/")
.addConverterFactory(GsonConverterFactory.create(Helper.getDateBuilder()))
.client(okHttpClient)
.build();
return retrofit.create(MastodonNotificationsService.class);
}
/**
* Get notifications for the authenticated account
*

View file

@ -89,6 +89,50 @@ public class TimelinesVM extends AndroidViewModel {
super(application);
}
private static void addFetchMore(List<Status> statusList, List<Status> timelineStatuses, TimelineParams timelineParams) throws DBException {
if (statusList != null && statusList.size() > 0 && timelineStatuses != null && timelineStatuses.size() > 0) {
if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.REFRESH || timelineParams.direction == FragmentMastodonTimeline.DIRECTION.SCROLL_TOP || timelineParams.direction == FragmentMastodonTimeline.DIRECTION.FETCH_NEW) {
//When refreshing/scrolling to TOP, if last statuses fetched has a greater id from newest in cache, there is potential hole
if (statusList.get(statusList.size() - 1).id.compareToIgnoreCase(timelineStatuses.get(0).id) > 0) {
statusList.get(statusList.size() - 1).isFetchMore = true;
statusList.get(statusList.size() - 1).positionFetchMore = Status.PositionFetchMore.TOP;
}
} else if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.TOP && timelineParams.fetchingMissing) {
if (!timelineStatuses.contains(statusList.get(0))) {
statusList.get(0).isFetchMore = true;
statusList.get(0).positionFetchMore = Status.PositionFetchMore.BOTTOM;
}
} else if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.BOTTOM && timelineParams.fetchingMissing) {
if (!timelineStatuses.contains(statusList.get(statusList.size() - 1))) {
statusList.get(statusList.size() - 1).isFetchMore = true;
statusList.get(statusList.size() - 1).positionFetchMore = Status.PositionFetchMore.TOP;
}
}
}
}
private static void addFetchMoreConversation(List<Conversation> conversationList, List<Conversation> timelineConversations, TimelineParams timelineParams) throws DBException {
if (conversationList != null && conversationList.size() > 0 && timelineConversations != null && timelineConversations.size() > 0) {
if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.REFRESH || timelineParams.direction == FragmentMastodonTimeline.DIRECTION.SCROLL_TOP || timelineParams.direction == FragmentMastodonTimeline.DIRECTION.FETCH_NEW) {
//When refreshing/scrolling to TOP, if last statuses fetched has a greater id from newest in cache, there is potential hole
if (conversationList.get(conversationList.size() - 1).id.compareToIgnoreCase(timelineConversations.get(0).id) > 0) {
conversationList.get(conversationList.size() - 1).isFetchMore = true;
conversationList.get(conversationList.size() - 1).positionFetchMore = Conversation.PositionFetchMore.TOP;
}
} else if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.TOP && timelineParams.fetchingMissing) {
if (!timelineConversations.contains(conversationList.get(0))) {
conversationList.get(0).isFetchMore = true;
conversationList.get(0).positionFetchMore = Conversation.PositionFetchMore.BOTTOM;
}
} else if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.BOTTOM && timelineParams.fetchingMissing) {
if (!timelineConversations.contains(conversationList.get(conversationList.size() - 1))) {
conversationList.get(conversationList.size() - 1).isFetchMore = true;
conversationList.get(conversationList.size() - 1).positionFetchMore = Conversation.PositionFetchMore.TOP;
}
}
}
}
private MastodonTimelinesService initInstanceOnly(String instance) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://" + instance)
@ -140,7 +184,6 @@ public class TimelinesVM extends AndroidViewModel {
return statusListMutableLiveData;
}
public LiveData<List<Tag>> getTagsTrends(String token, @NonNull String instance) {
MastodonTimelinesService mastodonTimelinesService = init(instance);
tagListMutableLiveData = new MutableLiveData<>();
@ -165,7 +208,6 @@ public class TimelinesVM extends AndroidViewModel {
return tagListMutableLiveData;
}
/**
* Public timeline for Nitter
*
@ -312,7 +354,6 @@ public class TimelinesVM extends AndroidViewModel {
return statusesMutableLiveData;
}
/**
* Returns details for a peertube video
*
@ -340,51 +381,6 @@ public class TimelinesVM extends AndroidViewModel {
return peertubeVideoMutableLiveData;
}
private static void addFetchMore(List<Status> statusList, List<Status> timelineStatuses, TimelineParams timelineParams) throws DBException {
if (statusList != null && statusList.size() > 0 && timelineStatuses != null && timelineStatuses.size() > 0) {
if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.REFRESH || timelineParams.direction == FragmentMastodonTimeline.DIRECTION.SCROLL_TOP || timelineParams.direction == FragmentMastodonTimeline.DIRECTION.FETCH_NEW) {
//When refreshing/scrolling to TOP, if last statuses fetched has a greater id from newest in cache, there is potential hole
if (statusList.get(statusList.size() - 1).id.compareToIgnoreCase(timelineStatuses.get(0).id) > 0) {
statusList.get(statusList.size() - 1).isFetchMore = true;
statusList.get(statusList.size() - 1).positionFetchMore = Status.PositionFetchMore.TOP;
}
} else if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.TOP && timelineParams.fetchingMissing) {
if (!timelineStatuses.contains(statusList.get(0))) {
statusList.get(0).isFetchMore = true;
statusList.get(0).positionFetchMore = Status.PositionFetchMore.BOTTOM;
}
} else if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.BOTTOM && timelineParams.fetchingMissing) {
if (!timelineStatuses.contains(statusList.get(statusList.size() - 1))) {
statusList.get(statusList.size() - 1).isFetchMore = true;
statusList.get(statusList.size() - 1).positionFetchMore = Status.PositionFetchMore.TOP;
}
}
}
}
private static void addFetchMoreConversation(List<Conversation> conversationList, List<Conversation> timelineConversations, TimelineParams timelineParams) throws DBException {
if (conversationList != null && conversationList.size() > 0 && timelineConversations != null && timelineConversations.size() > 0) {
if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.REFRESH || timelineParams.direction == FragmentMastodonTimeline.DIRECTION.SCROLL_TOP || timelineParams.direction == FragmentMastodonTimeline.DIRECTION.FETCH_NEW) {
//When refreshing/scrolling to TOP, if last statuses fetched has a greater id from newest in cache, there is potential hole
if (conversationList.get(conversationList.size() - 1).id.compareToIgnoreCase(timelineConversations.get(0).id) > 0) {
conversationList.get(conversationList.size() - 1).isFetchMore = true;
conversationList.get(conversationList.size() - 1).positionFetchMore = Conversation.PositionFetchMore.TOP;
}
} else if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.TOP && timelineParams.fetchingMissing) {
if (!timelineConversations.contains(conversationList.get(0))) {
conversationList.get(0).isFetchMore = true;
conversationList.get(0).positionFetchMore = Conversation.PositionFetchMore.BOTTOM;
}
} else if (timelineParams.direction == FragmentMastodonTimeline.DIRECTION.BOTTOM && timelineParams.fetchingMissing) {
if (!timelineConversations.contains(conversationList.get(conversationList.size() - 1))) {
conversationList.get(conversationList.size() - 1).isFetchMore = true;
conversationList.get(conversationList.size() - 1).positionFetchMore = Conversation.PositionFetchMore.TOP;
}
}
}
}
public LiveData<Statuses> getTimeline(List<Status> timelineStatuses, TimelineParams timelineParams) {
statusesMutableLiveData = new MutableLiveData<>();
MastodonTimelinesService mastodonTimelinesService = init(timelineParams.instance);