@ -43,10 +43,9 @@ import android.widget.TextView;
import com.keylesspalace.tusky.MainActivity ;
import com.keylesspalace.tusky.MainActivity ;
import com.keylesspalace.tusky.R ;
import com.keylesspalace.tusky.R ;
import com.keylesspalace.tusky.adapter.FooterViewHolder ;
import com.keylesspalace.tusky.adapter.NotificationsAdapter ;
import com.keylesspalace.tusky.adapter.NotificationsAdapter ;
import com.keylesspalace.tusky.appstore.EventHub ;
import com.keylesspalace.tusky.appstore.BlockEvent ;
import com.keylesspalace.tusky.appstore.BlockEvent ;
import com.keylesspalace.tusky.appstore.EventHub ;
import com.keylesspalace.tusky.appstore.FavoriteEvent ;
import com.keylesspalace.tusky.appstore.FavoriteEvent ;
import com.keylesspalace.tusky.appstore.ReblogEvent ;
import com.keylesspalace.tusky.appstore.ReblogEvent ;
import com.keylesspalace.tusky.db.AccountEntity ;
import com.keylesspalace.tusky.db.AccountEntity ;
@ -69,6 +68,7 @@ import com.keylesspalace.tusky.viewdata.NotificationViewData;
import com.keylesspalace.tusky.viewdata.StatusViewData ;
import com.keylesspalace.tusky.viewdata.StatusViewData ;
import java.math.BigInteger ;
import java.math.BigInteger ;
import java.util.Collections ;
import java.util.Iterator ;
import java.util.Iterator ;
import java.util.List ;
import java.util.List ;
import java.util.Objects ;
import java.util.Objects ;
@ -132,9 +132,7 @@ public class NotificationsFragment extends SFragment implements
private TabLayout . OnTabSelectedListener onTabSelectedListener ;
private TabLayout . OnTabSelectedListener onTabSelectedListener ;
private boolean hideFab ;
private boolean hideFab ;
private boolean topLoading ;
private boolean topLoading ;
private int topFetches ;
private boolean bottomLoading ;
private boolean bottomLoading ;
private int bottomFetches ;
private String bottomId ;
private String bottomId ;
private String topId ;
private String topId ;
private boolean alwaysShowSensitiveMedia ;
private boolean alwaysShowSensitiveMedia ;
@ -202,15 +200,15 @@ public class NotificationsFragment extends SFragment implements
notifications . clear ( ) ;
notifications . clear ( ) ;
topLoading = false ;
topLoading = false ;
topFetches = 0 ;
bottomLoading = false ;
bottomLoading = false ;
bottomFetches = 0 ;
bottomId = null ;
bottomId = null ;
topId = null ;
topId = null ;
( ( SimpleItemAnimator ) recyclerView . getItemAnimator ( ) ) . setSupportsChangeAnimations ( false ) ;
( ( SimpleItemAnimator ) recyclerView . getItemAnimator ( ) ) . setSupportsChangeAnimations ( false ) ;
setupNothingView ( ) ;
setupNothingView ( ) ;
sendFetchNotificationsRequest ( null , topId , FetchEnd . TOP , - 1 ) ;
return rootView ;
return rootView ;
}
}
@ -551,6 +549,14 @@ public class NotificationsFragment extends SFragment implements
}
}
private void onLoadMore ( ) {
private void onLoadMore ( ) {
Either < Placeholder , Notification > last = notifications . get ( notifications . size ( ) - 1 ) ;
if ( last . isRight ( ) ) {
notifications . add ( Either . left ( Placeholder . getInstance ( ) ) ) ;
NotificationViewData viewData = new NotificationViewData . Placeholder ( true ) ;
notifications . setPairedItem ( notifications . size ( ) - 1 , viewData ) ;
recyclerView . post ( ( ) - > adapter . addItems ( Collections . singletonList ( viewData ) ) ) ;
}
sendFetchNotificationsRequest ( bottomId , null , FetchEnd . BOTTOM , - 1 ) ;
sendFetchNotificationsRequest ( bottomId , null , FetchEnd . BOTTOM , - 1 ) ;
}
}
@ -564,19 +570,16 @@ public class NotificationsFragment extends SFragment implements
/ * If there is a fetch already ongoing , record however many fetches are requested and
/ * If there is a fetch already ongoing , record however many fetches are requested and
* fulfill them after it ' s complete . * /
* fulfill them after it ' s complete . * /
if ( fetchEnd = = FetchEnd . TOP & & topLoading ) {
if ( fetchEnd = = FetchEnd . TOP & & topLoading ) {
topFetches + + ;
return ;
return ;
}
}
if ( fetchEnd = = FetchEnd . BOTTOM & & bottomLoading ) {
if ( fetchEnd = = FetchEnd . BOTTOM & & bottomLoading ) {
bottomFetches + + ;
return ;
return ;
}
}
if ( fetchEnd = = FetchEnd . TOP ) {
if ( fromId ! = null | | adapter . getItemCount ( ) < = 1 ) {
topLoading = true ;
/ * When this is called by the EndlessScrollListener it cannot refresh the footer state
}
* using adapter . notifyItemChanged . So its necessary to postpone doing so until a
if ( fetchEnd = = FetchEnd . BOTTOM ) {
* convenient time for the UI thread using a Runnable . * /
bottomLoading = true ;
recyclerView . post ( ( ) - > adapter . setFooterState ( FooterViewHolder . State . LOADING ) ) ;
}
}
Call < List < Notification > > call = mastodonApi . notifications ( fromId , uptoId , LOAD_AT_ONCE ) ;
Call < List < Notification > > call = mastodonApi . notifications ( fromId , uptoId , LOAD_AT_ONCE ) ;
@ -624,6 +627,13 @@ public class NotificationsFragment extends SFragment implements
if ( next ! = null ) {
if ( next ! = null ) {
fromId = next . uri . getQueryParameter ( "max_id" ) ;
fromId = next . uri . getQueryParameter ( "max_id" ) ;
}
}
if ( ! this . notifications . isEmpty ( )
& & ! this . notifications . get ( this . notifications . size ( ) - 1 ) . isRight ( ) ) {
this . notifications . remove ( this . notifications . size ( ) - 1 ) ;
adapter . removeItemAndNotify ( this . notifications . size ( ) ) ;
}
if ( adapter . getItemCount ( ) > 1 ) {
if ( adapter . getItemCount ( ) > 1 ) {
addItems ( notifications , fromId ) ;
addItems ( notifications , fromId ) ;
} else {
} else {
@ -644,11 +654,17 @@ public class NotificationsFragment extends SFragment implements
saveNewestNotificationId ( notifications ) ;
saveNewestNotificationId ( notifications ) ;
fulfillAnyQueuedFetches ( fetchEnd ) ;
if ( fetchEnd = = FetchEnd . TOP ) {
if ( notifications . size ( ) = = 0 & & adapter . getItemCount ( ) = = 1 ) {
topLoading = false ;
adapter . setFooterState ( FooterViewHolder . State . EMPTY ) ;
}
if ( fetchEnd = = FetchEnd . BOTTOM ) {
bottomLoading = false ;
}
if ( notifications . size ( ) = = 0 & & adapter . getItemCount ( ) = = 0 ) {
nothingMessageView . setVisibility ( View . VISIBLE ) ;
} else {
} else {
adapter . setFooterState ( FooterViewHolder . State . END ) ;
nothingMessageView . setVisibility ( View . GONE ) ;
}
}
swipeRefreshLayout . setRefreshing ( false ) ;
swipeRefreshLayout . setRefreshing ( false ) ;
progressBar . setVisibility ( View . GONE ) ;
progressBar . setVisibility ( View . GONE ) ;
@ -663,7 +679,6 @@ public class NotificationsFragment extends SFragment implements
adapter . updateItemWithNotify ( position , placeholderVD , true ) ;
adapter . updateItemWithNotify ( position , placeholderVD , true ) ;
}
}
Log . e ( TAG , "Fetch failure: " + exception . getMessage ( ) ) ;
Log . e ( TAG , "Fetch failure: " + exception . getMessage ( ) ) ;
fulfillAnyQueuedFetches ( fetchEnd ) ;
progressBar . setVisibility ( View . GONE ) ;
progressBar . setVisibility ( View . GONE ) ;
}
}
@ -710,7 +725,6 @@ public class NotificationsFragment extends SFragment implements
notifications . remove ( 0 ) ;
notifications . remove ( 0 ) ;
}
}
int newIndex = liftedNew . indexOf ( notifications . get ( 0 ) ) ;
int newIndex = liftedNew . indexOf ( notifications . get ( 0 ) ) ;
if ( newIndex = = - 1 ) {
if ( newIndex = = - 1 ) {
if ( index = = - 1 & & liftedNew . size ( ) > = LOAD_AT_ONCE ) {
if ( index = = - 1 & & liftedNew . size ( ) > = LOAD_AT_ONCE ) {
@ -743,27 +757,6 @@ public class NotificationsFragment extends SFragment implements
}
}
}
}
private void fulfillAnyQueuedFetches ( FetchEnd fetchEnd ) {
switch ( fetchEnd ) {
case BOTTOM : {
bottomLoading = false ;
if ( bottomFetches > 0 ) {
bottomFetches - - ;
onLoadMore ( ) ;
}
break ;
}
case TOP : {
topLoading = false ;
if ( topFetches > 0 ) {
topFetches - - ;
onRefresh ( ) ;
}
break ;
}
}
}
private void replacePlaceholderWithNotifications ( List < Notification > newNotifications , int pos ) {
private void replacePlaceholderWithNotifications ( List < Notification > newNotifications , int pos ) {
// Remove placeholder
// Remove placeholder
notifications . remove ( pos ) ;
notifications . remove ( pos ) ;