Fix issue with pagination

pull/254/head
Thomas 2 years ago
parent 1ac365befa
commit b1603894cb

@ -18,12 +18,14 @@
android:icon="@mipmap/ic_launcher"
android:usesCleartextTraffic="true"
android:label="@string/app_name"
android:configChanges="orientation|screenSize"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppThemeDark"
>
<activity
android:name=".activities.MainActivity"
android:configChanges="orientation|screenSize"
android:exported="true"
>
<intent-filter>

@ -55,6 +55,7 @@ import androidx.core.app.ActivityOptionsCompat;
import androidx.core.content.ContextCompat;
import androidx.core.view.GravityCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.ViewModelProvider;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.navigation.NavController;
@ -838,8 +839,13 @@ public abstract class BaseMainActivity extends BaseActivity implements NetworkSt
}
public void refreshFragment() {
if (binding.viewPager.getAdapter() != null) {
binding.viewPager.getAdapter().notifyDataSetChanged();
Fragment fragment = getSupportFragmentManager().findFragmentByTag("f" + binding.viewPager.getCurrentItem());
if (fragment instanceof FragmentNotificationContainer) {
FragmentTransaction fragTransaction = getSupportFragmentManager().beginTransaction();
fragTransaction.detach(fragment).commit();
FragmentTransaction fragTransaction2 = getSupportFragmentManager().beginTransaction();
fragTransaction2.attach(fragment);
fragTransaction2.commit();
}
}

@ -59,12 +59,11 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import java.util.ArrayList;
import java.util.Date;
@ -249,34 +248,28 @@ public class ProfileActivity extends BaseActivity {
binding.accountTabLayout.removeAllTabs();
//Tablayout for timelines/following/followers
FedilabProfileTLPageAdapter fedilabProfileTLPageAdapter = new FedilabProfileTLPageAdapter(ProfileActivity.this, account);
binding.accountTabLayout.addTab(binding.accountTabLayout.newTab().setText(getString(R.string.status_cnt, Helper.withSuffix(account.statuses_count))));
binding.accountTabLayout.addTab(binding.accountTabLayout.newTab().setText(getString(R.string.following_cnt, Helper.withSuffix(account.following_count))));
binding.accountTabLayout.addTab(binding.accountTabLayout.newTab().setText(getString(R.string.followers_cnt, Helper.withSuffix(account.followers_count))));
binding.accountTabLayout.addTab(binding.accountTabLayout.newTab());
binding.accountTabLayout.addTab(binding.accountTabLayout.newTab());
binding.accountTabLayout.addTab(binding.accountTabLayout.newTab());
binding.accountViewpager.setAdapter(fedilabProfileTLPageAdapter);
binding.accountViewpager.setOffscreenPageLimit(3);
binding.accountViewpager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
binding.accountTabLayout.selectTab(binding.accountTabLayout.getTabAt(position));
}
});
binding.accountTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
binding.accountViewpager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
new TabLayoutMediator(binding.accountTabLayout, binding.accountViewpager,
(tab, position) -> {
binding.accountViewpager.setCurrentItem(tab.getPosition(), true);
switch (position) {
case 0:
tab.setText(getString(R.string.status_cnt, Helper.withSuffix(account.statuses_count)));
break;
case 1:
tab.setText(getString(R.string.following_cnt, Helper.withSuffix(account.statuses_count)));
break;
case 2:
tab.setText(getString(R.string.followers_cnt, Helper.withSuffix(account.statuses_count)));
break;
}
}
).attach();
binding.accountTabLayout.setTabTextColors(ThemeHelper.getAttColor(ProfileActivity.this, R.attr.mTextColor), ContextCompat.getColor(ProfileActivity.this, R.color.cyanea_accent_dark_reference));
binding.accountTabLayout.setTabIconTint(ThemeHelper.getColorStateList(ProfileActivity.this));
boolean disableGif = sharedpreferences.getBoolean(getString(R.string.SET_DISABLE_GIF), false);

@ -24,7 +24,7 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.core.content.ContextCompat;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import app.fedilab.android.R;
import app.fedilab.android.databinding.ActivityScheduledBinding;
@ -56,31 +56,31 @@ public class ScheduledActivity extends BaseActivity {
MastodonHelper.loadPPMastodon(binding.profilePicture, currentAccount.mastodon_account);
binding.title.setText(R.string.scheduled);
binding.scheduleTablayout.addTab(binding.scheduleTablayout.newTab().setText(getString(R.string.toots_server)));
binding.scheduleTablayout.addTab(binding.scheduleTablayout.newTab().setText(getString(R.string.toots_client)));
binding.scheduleTablayout.addTab(binding.scheduleTablayout.newTab().setText(getString(R.string.reblog)));
binding.scheduleTablayout.addTab(binding.scheduleTablayout.newTab());
binding.scheduleTablayout.addTab(binding.scheduleTablayout.newTab());
binding.scheduleTablayout.addTab(binding.scheduleTablayout.newTab());
binding.scheduleViewpager.setAdapter(new FedilabScheduledPageAdapter(ScheduledActivity.this));
binding.scheduleViewpager.setOffscreenPageLimit(3);
binding.scheduleTablayout.setTabTextColors(ThemeHelper.getAttColor(ScheduledActivity.this, R.attr.mTextColor), ContextCompat.getColor(ScheduledActivity.this, R.color.cyanea_accent_dark_reference));
binding.scheduleTablayout.setTabIconTint(ThemeHelper.getColorStateList(ScheduledActivity.this));
binding.scheduleTablayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
binding.scheduleViewpager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
new TabLayoutMediator(binding.scheduleTablayout, binding.scheduleViewpager,
(tab, position) -> {
binding.scheduleViewpager.setCurrentItem(tab.getPosition(), true);
switch (position) {
case 0:
tab.setText(getString(R.string.toots_server));
break;
case 1:
tab.setText(getString(R.string.toots_client));
break;
case 2:
tab.setText(getString(R.string.reblog));
break;
}
}
).attach();
}
@Override

@ -30,9 +30,9 @@ import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import org.jetbrains.annotations.NotNull;
@ -75,13 +75,34 @@ public class SearchResultTabActivity extends BaseActivity {
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary)));
}
setTitle(search);
binding.searchTabLayout.addTab(binding.searchTabLayout.newTab().setText(getString(R.string.tags)));
binding.searchTabLayout.addTab(binding.searchTabLayout.newTab().setText(getString(R.string.accounts)));
binding.searchTabLayout.addTab(binding.searchTabLayout.newTab().setText(getString(R.string.toots)));
binding.searchTabLayout.addTab(binding.searchTabLayout.newTab().setText(getString(R.string.action_cache)));
binding.searchTabLayout.addTab(binding.searchTabLayout.newTab());
binding.searchTabLayout.addTab(binding.searchTabLayout.newTab());
binding.searchTabLayout.addTab(binding.searchTabLayout.newTab());
binding.searchTabLayout.addTab(binding.searchTabLayout.newTab());
binding.searchTabLayout.setTabTextColors(ThemeHelper.getAttColor(SearchResultTabActivity.this, R.attr.mTextColor), ContextCompat.getColor(SearchResultTabActivity.this, R.color.cyanea_accent_dark_reference));
binding.searchTabLayout.setTabIconTint(ThemeHelper.getColorStateList(SearchResultTabActivity.this));
ScreenSlidePagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(SearchResultTabActivity.this);
binding.searchViewpager.setAdapter(mPagerAdapter);
binding.searchViewpager.setOffscreenPageLimit(3);
new TabLayoutMediator(binding.searchTabLayout, binding.searchViewpager,
(tab, position) -> {
binding.searchViewpager.setCurrentItem(tab.getPosition(), true);
switch (position) {
case 0:
tab.setText(getString(R.string.tags));
break;
case 1:
tab.setText(getString(R.string.accounts));
break;
case 2:
tab.setText(getString(R.string.toots));
break;
case 3:
tab.setText(getString(R.string.action_cache));
break;
}
}
).attach();
binding.searchTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
@ -95,19 +116,16 @@ public class SearchResultTabActivity extends BaseActivity {
@Override
public void onTabReselected(TabLayout.Tab tab) {
Fragment fragment;
if (binding.searchViewpager.getAdapter() != null) {
fragment = (Fragment) getSupportFragmentManager().findFragmentByTag("f" + binding.searchViewpager.getCurrentItem());
if (fragment instanceof FragmentMastodonAccount) {
FragmentMastodonAccount fragmentMastodonAccount = ((FragmentMastodonAccount) fragment);
fragmentMastodonAccount.scrollToTop();
} else if (fragment instanceof FragmentMastodonTimeline) {
FragmentMastodonTimeline fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment);
fragmentMastodonTimeline.scrollToTop();
} else if (fragment instanceof FragmentMastodonTag) {
FragmentMastodonTag fragmentMastodonTag = ((FragmentMastodonTag) fragment);
fragmentMastodonTag.scrollToTop();
}
Fragment fragment = getSupportFragmentManager().findFragmentByTag("f" + binding.searchViewpager.getCurrentItem());
if (fragment instanceof FragmentMastodonAccount) {
FragmentMastodonAccount fragmentMastodonAccount = ((FragmentMastodonAccount) fragment);
fragmentMastodonAccount.scrollToTop();
} else if (fragment instanceof FragmentMastodonTimeline) {
FragmentMastodonTimeline fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment);
fragmentMastodonTimeline.scrollToTop();
} else if (fragment instanceof FragmentMastodonTag) {
FragmentMastodonTag fragmentMastodonTag = ((FragmentMastodonTag) fragment);
fragmentMastodonTag.scrollToTop();
}
}
});
@ -122,8 +140,6 @@ public class SearchResultTabActivity extends BaseActivity {
SearchView searchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setIconifiedByDefault(false);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
@ -156,29 +172,7 @@ public class SearchResultTabActivity extends BaseActivity {
});
ScreenSlidePagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(SearchResultTabActivity.this);
binding.searchViewpager.setAdapter(mPagerAdapter);
binding.searchViewpager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
binding.searchTabLayout.selectTab(binding.searchTabLayout.getTabAt(position));
}
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
TabLayout.Tab tab = binding.searchTabLayout.getTabAt(position);
if (tab != null)
tab.select();
}
@Override
public void onPageScrollStateChanged(int state) {
super.onPageScrollStateChanged(state);
}
});
return true;
}

@ -0,0 +1,113 @@
package app.fedilab.android.helper
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
import android.widget.FrameLayout
import androidx.viewpager2.widget.ViewPager2
import androidx.viewpager2.widget.ViewPager2.ORIENTATION_HORIZONTAL
import kotlin.math.absoluteValue
import kotlin.math.sign
/**
* Layout to wrap a scrollable component inside a ViewPager2. Provided as a solution to the problem
* where pages of ViewPager2 have nested scrollable elements that scroll in the same direction as
* ViewPager2. The scrollable element needs to be the immediate and only child of this host layout.
*
* This solution has limitations when using multiple levels of nested scrollable elements
* (e.g. a horizontal RecyclerView in a vertical RecyclerView in a horizontal ViewPager2).
*/
class NestedScrollableHost : FrameLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
private var touchSlop = 0
private var initialX = 0f
private var initialY = 0f
private val parentViewPager: ViewPager2?
get() {
var v: View? = parent as? View
while (v != null && v !is ViewPager2) {
v = v.parent as? View
}
return v as? ViewPager2
}
private val child: View? get() = if (childCount > 0) getChildAt(0) else null
init {
touchSlop = ViewConfiguration.get(context).scaledTouchSlop
}
private fun canChildScroll(orientation: Int, delta: Float): Boolean {
val direction = -delta.sign.toInt()
return when (orientation) {
0 -> child?.canScrollHorizontally(direction) ?: false
1 -> child?.canScrollVertically(direction) ?: false
else -> throw IllegalArgumentException()
}
}
override fun onInterceptTouchEvent(e: MotionEvent): Boolean {
handleInterceptTouchEvent(e)
return super.onInterceptTouchEvent(e)
}
private fun handleInterceptTouchEvent(e: MotionEvent) {
val orientation = parentViewPager?.orientation ?: return
// Early return if child can't scroll in same direction as parent
if (!canChildScroll(orientation, -1f) && !canChildScroll(orientation, 1f)) {
return
}
if (e.action == MotionEvent.ACTION_DOWN) {
initialX = e.x
initialY = e.y
parent.requestDisallowInterceptTouchEvent(true)
} else if (e.action == MotionEvent.ACTION_MOVE) {
val dx = e.x - initialX
val dy = e.y - initialY
val isVpHorizontal = orientation == ORIENTATION_HORIZONTAL
// assuming ViewPager2 touch-slop is 2x touch-slop of child
val scaledDx = dx.absoluteValue * if (isVpHorizontal) .5f else 1f
val scaledDy = dy.absoluteValue * if (isVpHorizontal) 1f else .5f
if (scaledDx > touchSlop || scaledDy > touchSlop) {
if (isVpHorizontal == (scaledDy > scaledDx)) {
// Gesture is perpendicular, allow all parents to intercept
parent.requestDisallowInterceptTouchEvent(false)
} else {
// Gesture is parallel, query child if movement in that direction is possible
if (canChildScroll(orientation, if (isVpHorizontal) dx else dy)) {
// Child can scroll, disallow all parents to intercept
parent.requestDisallowInterceptTouchEvent(true)
} else {
// Child cannot scroll, allow all parents to intercept
parent.requestDisallowInterceptTouchEvent(false)
}
}
}
}
}
}

@ -35,6 +35,7 @@ import androidx.fragment.app.FragmentTransaction;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import java.util.ArrayList;
import java.util.Arrays;
@ -147,11 +148,14 @@ public class PinnedTimelineHelper {
activityMainBinding.tabLayout.removeAllTabs();
//Small hack to hide first tabs (they represent the item of the bottom menu)
int toRemove = itemToRemoveInBottomMenu(activity);
List<String> tabTitle = new ArrayList<>();
for (int i = 0; i < (BOTTOM_TIMELINE_COUNT - toRemove); i++) {
activityMainBinding.tabLayout.addTab(activityMainBinding.tabLayout.newTab());
tabTitle.add("");
((ViewGroup) activityMainBinding.tabLayout.getChildAt(0)).getChildAt(i).setVisibility(View.GONE);
}
List<PinnedTimeline> pinnedTimelineVisibleList = new ArrayList<>();
for (PinnedTimeline pinnedTimeline : pinned.pinnedTimelines) {
if (pinnedTimeline.displayed) {
TabLayout.Tab tab = activityMainBinding.tabLayout.newTab();
@ -172,7 +176,7 @@ public class PinnedTimelineHelper {
}
TextView tv = (TextView) LayoutInflater.from(activity).inflate(R.layout.custom_tab_instance, new LinearLayout(activity), false);
tv.setText(name);
tabTitle.add(name);
tab.setCustomView(tv);
activityMainBinding.tabLayout.addTab(tab);
@ -205,16 +209,10 @@ public class PinnedTimelineHelper {
FedilabPageAdapter fedilabPageAdapter = new FedilabPageAdapter(activity, activity, pinned, bottomMenu);
activityMainBinding.viewPager.setAdapter(fedilabPageAdapter);
activityMainBinding.viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
activityMainBinding.tabLayout.selectTab(activityMainBinding.tabLayout.getTabAt(position));
}
activityMainBinding.viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
super.onPageSelected(position);
if (position < BOTTOM_TIMELINE_COUNT - toRemove) {
activityMainBinding.bottomNavView.getMenu().getItem(position).setChecked(true);
} else {
@ -225,18 +223,14 @@ public class PinnedTimelineHelper {
activityMainBinding.bottomNavView.getMenu().setGroupCheckable(0, true, true);
}
}
@Override
public void onPageScrollStateChanged(int state) {
super.onPageScrollStateChanged(state);
}
});
new TabLayoutMediator(activityMainBinding.tabLayout, activityMainBinding.viewPager,
(tab, position) -> tab.setText(tabTitle.get(position))
).attach();
activityMainBinding.tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
activityMainBinding.viewPager.setCurrentItem(tab.getPosition());
}
@Override
@ -245,7 +239,7 @@ public class PinnedTimelineHelper {
@Override
public void onTabReselected(TabLayout.Tab tab) {
Fragment fragment = (Fragment) activity.getSupportFragmentManager().findFragmentByTag("f" + activityMainBinding.viewPager.getCurrentItem());
Fragment fragment = activity.getSupportFragmentManager().findFragmentByTag("f" + activityMainBinding.viewPager.getCurrentItem());
if (fragment instanceof FragmentMastodonTimeline) {
((FragmentMastodonTimeline) fragment).scrollToTop();
} else if (fragment instanceof FragmentMastodonConversation) {
@ -319,7 +313,7 @@ public class PinnedTimelineHelper {
if (changes[0]) {
FragmentMastodonTimeline fragmentMastodonTimeline;
if (activityMainBinding.viewPager.getAdapter() != null) {
Fragment fragment = (Fragment) activity.getSupportFragmentManager().findFragmentByTag("f" + activityMainBinding.viewPager.getCurrentItem());
Fragment fragment = activity.getSupportFragmentManager().findFragmentByTag("f" + activityMainBinding.viewPager.getCurrentItem());
if (fragment instanceof FragmentMastodonTimeline && fragment.isVisible()) {
fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment);
FragmentTransaction fragTransaction = activity.getSupportFragmentManager().beginTransaction();
@ -376,7 +370,7 @@ public class PinnedTimelineHelper {
}
} else if (itemId == R.id.action_any) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(activity, Helper.dialogStyle());
LayoutInflater inflater = ((BaseMainActivity) activity).getLayoutInflater();
LayoutInflater inflater = activity.getLayoutInflater();
View dialogView = inflater.inflate(R.layout.tags_any, new LinearLayout(activity), false);
dialogBuilder.setView(dialogView);
final EditText editText = dialogView.findViewById(R.id.filter_any);
@ -405,7 +399,7 @@ public class PinnedTimelineHelper {
View dialogView;
AlertDialog alertDialog;
dialogBuilder = new AlertDialog.Builder(activity, Helper.dialogStyle());
inflater = ((BaseMainActivity) activity).getLayoutInflater();
inflater = activity.getLayoutInflater();
dialogView = inflater.inflate(R.layout.tags_all, new LinearLayout(activity), false);
dialogBuilder.setView(dialogView);
final EditText editTextAll = dialogView.findViewById(R.id.filter_all);
@ -434,7 +428,7 @@ public class PinnedTimelineHelper {
View dialogView;
AlertDialog alertDialog;
dialogBuilder = new AlertDialog.Builder(activity, Helper.dialogStyle());
inflater = ((BaseMainActivity) activity).getLayoutInflater();
inflater = activity.getLayoutInflater();
dialogView = inflater.inflate(R.layout.tags_all, new LinearLayout(activity), false);
dialogBuilder.setView(dialogView);
final EditText editTextNone = dialogView.findViewById(R.id.filter_all);
@ -463,7 +457,7 @@ public class PinnedTimelineHelper {
View dialogView;
AlertDialog alertDialog;
dialogBuilder = new AlertDialog.Builder(activity, Helper.dialogStyle());
inflater = ((BaseMainActivity) activity).getLayoutInflater();
inflater = activity.getLayoutInflater();
dialogView = inflater.inflate(R.layout.tags_name, new LinearLayout(activity), false);
dialogBuilder.setView(dialogView);
final EditText editTextName = dialogView.findViewById(R.id.column_name);
@ -536,14 +530,14 @@ public class PinnedTimelineHelper {
changes[0] = true;
FragmentMastodonTimeline fragmentMastodonTimeline = null;
if (activityMainBinding.viewPager.getAdapter() != null) {
Fragment fragment = (Fragment) activity.getSupportFragmentManager().findFragmentByTag("f" + activityMainBinding.viewPager.getCurrentItem());
Fragment fragment = activity.getSupportFragmentManager().findFragmentByTag("f" + activityMainBinding.viewPager.getCurrentItem());
if (fragment instanceof FragmentMastodonTimeline && fragment.isVisible()) {
fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment);
}
}
if (fragmentMastodonTimeline == null)
return false;
FragmentTransaction fragTransaction1 = ((BaseMainActivity) activity).getSupportFragmentManager().beginTransaction();
FragmentTransaction fragTransaction1 = activity.getSupportFragmentManager().beginTransaction();
pinned.pinnedTimelines.get(offSetPosition).remoteInstance.filteredWith = null;
remoteInstance.filteredWith = null;
@ -561,7 +555,7 @@ public class PinnedTimelineHelper {
bundle.putString("timelineId", remoteInstance.id);
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.REMOTE);
fragmentMastodonTimeline.setArguments(bundle);
FragmentTransaction fragTransaction2 = ((BaseMainActivity) activity).getSupportFragmentManager().beginTransaction();
FragmentTransaction fragTransaction2 = activity.getSupportFragmentManager().beginTransaction();
fragTransaction2.attach(fragmentMastodonTimeline);
fragTransaction2.commit();
popup.getMenu().close();
@ -583,13 +577,13 @@ public class PinnedTimelineHelper {
item.setOnMenuItemClickListener(item1 -> {
FragmentMastodonTimeline fragmentMastodonTimeline = null;
if (activityMainBinding.viewPager.getAdapter() != null) {
Fragment fragment = (Fragment) activity.getSupportFragmentManager().findFragmentByTag("f" + activityMainBinding.viewPager.getCurrentItem());
Fragment fragment = activity.getSupportFragmentManager().findFragmentByTag("f" + activityMainBinding.viewPager.getCurrentItem());
if (fragment instanceof FragmentMastodonTimeline && fragment.isVisible()) {
fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment);
fragmentMastodonTimeline.refreshAllAdapters();
}
}
FragmentTransaction fragTransaction1 = ((BaseMainActivity) activity).getSupportFragmentManager().beginTransaction();
FragmentTransaction fragTransaction1 = activity.getSupportFragmentManager().beginTransaction();
if (fragmentMastodonTimeline == null)
return false;
pinned.pinnedTimelines.get(offSetPosition).remoteInstance.filteredWith = tag;
@ -608,7 +602,7 @@ public class PinnedTimelineHelper {
bundle.putString("currentfilter", remoteInstance.filteredWith);
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.REMOTE);
fragmentMastodonTimeline.setArguments(bundle);
FragmentTransaction fragTransaction2 = ((BaseMainActivity) activity).getSupportFragmentManager().beginTransaction();
FragmentTransaction fragTransaction2 = activity.getSupportFragmentManager().beginTransaction();
fragTransaction2.attach(fragmentMastodonTimeline);
fragTransaction2.commit();
return false;
@ -634,7 +628,7 @@ public class PinnedTimelineHelper {
});
changes[0] = true;
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(activity, Helper.dialogStyle());
LayoutInflater inflater = ((BaseMainActivity) activity).getLayoutInflater();
LayoutInflater inflater = activity.getLayoutInflater();
View dialogView = inflater.inflate(R.layout.tags_instance, new LinearLayout(activity), false);
dialogBuilder.setView(dialogView);
final EditText editText = dialogView.findViewById(R.id.filter_words);
@ -666,13 +660,13 @@ public class PinnedTimelineHelper {
if (changes[0]) {
FragmentMastodonTimeline fragmentMastodonTimeline = null;
if (activityMainBinding.viewPager.getAdapter() != null) {
Fragment fragment = (Fragment) activity.getSupportFragmentManager().findFragmentByTag("f" + activityMainBinding.viewPager.getCurrentItem());
Fragment fragment = activity.getSupportFragmentManager().findFragmentByTag("f" + activityMainBinding.viewPager.getCurrentItem());
if (fragment instanceof FragmentMastodonTimeline && fragment.isVisible()) {
fragmentMastodonTimeline = ((FragmentMastodonTimeline) fragment);
fragmentMastodonTimeline.refreshAllAdapters();
}
}
FragmentTransaction fragTransaction1 = ((BaseMainActivity) activity).getSupportFragmentManager().beginTransaction();
FragmentTransaction fragTransaction1 = activity.getSupportFragmentManager().beginTransaction();
if (fragmentMastodonTimeline == null)
return;
fragTransaction1.detach(fragmentMastodonTimeline).commit();
@ -685,7 +679,7 @@ public class PinnedTimelineHelper {
}
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, Timeline.TimeLineEnum.REMOTE);
fragmentMastodonTimeline.setArguments(bundle);
FragmentTransaction fragTransaction2 = ((BaseMainActivity) activity).getSupportFragmentManager().beginTransaction();
FragmentTransaction fragTransaction2 = activity.getSupportFragmentManager().beginTransaction();
fragTransaction2.attach(fragmentMastodonTimeline);
fragTransaction2.commit();
}

@ -0,0 +1,44 @@
package app.fedilab.android.helper;
import android.view.View;
import androidx.viewpager2.widget.ViewPager2;
public class ZoomOutPageTransformer implements ViewPager2.PageTransformer {
private static final float MIN_SCALE = 0.85f;
private static final float MIN_ALPHA = 0.5f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0f);
} else if (position <= 1) { // [-1,1]
// Modify the default slide transition to shrink the page as well
float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (position < 0) {
view.setTranslationX(horzMargin - vertMargin / 2);
} else {
view.setTranslationX(-horzMargin + vertMargin / 2);
}
// Scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
// Fade the page relative to its size.
view.setAlpha(MIN_ALPHA +
(scaleFactor - MIN_SCALE) /
(1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0f);
}
}
}

@ -177,7 +177,7 @@ public class FragmentAdminAccount extends Fragment {
* @param adminAccounts AdminAccounts
*/
private void dealWithPagination(AdminAccounts adminAccounts) {
if (binding == null) {
if (binding == null || !isAdded() || getActivity() == null) {
return;
}
binding.loadingNextElements.setVisibility(View.GONE);

@ -98,7 +98,7 @@ public class FragmentAdminReport extends Fragment {
* @param adminReports {@link AdminReports}
*/
private void initializeStatusesCommonView(final AdminReports adminReports) {
if (binding == null) {
if (binding == null || !isAdded() || getActivity() == null) {
return;
}
binding.loader.setVisibility(View.GONE);
@ -180,7 +180,7 @@ public class FragmentAdminReport extends Fragment {
*/
private void dealWithPagination(AdminReports admReports) {
if (binding == null) {
if (binding == null || !isAdded() || getActivity() == null) {
return;
}
binding.loadingNextElements.setVisibility(View.GONE);

@ -172,7 +172,7 @@ public class FragmentMastodonAccount extends Fragment {
*/
private void initializeAccountCommonView(final Accounts accounts) {
flagLoading = false;
if (binding == null) {
if (binding == null || !isAdded() || getActivity() == null) {
return;
}
binding.loader.setVisibility(View.GONE);
@ -242,7 +242,7 @@ public class FragmentMastodonAccount extends Fragment {
*/
private void dealWithPagination(Accounts fetched_accounts) {
flagLoading = false;
if (binding == null) {
if (binding == null || !isAdded() || getActivity() == null) {
return;
}
binding.loadingNextElements.setVisibility(View.GONE);

@ -227,6 +227,9 @@ public class FragmentMastodonContext extends Fragment {
Helper.sendToastMessage(requireActivity(), Helper.RECEIVE_TOAST_TYPE_ERROR, getString(R.string.toast_error));
return;
}
if (binding == null || !isAdded() || getActivity() == null) {
return;
}
if (pullToRefresh) {
pullToRefresh = false;
int size = this.statuses.size();

@ -192,7 +192,7 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
*/
private void initializeNotificationView(final Notifications notifications) {
flagLoading = false;
if (binding == null) {
if (binding == null || !isAdded() || getActivity() == null) {
return;
}
binding.loader.setVisibility(View.GONE);
@ -283,10 +283,10 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
* @param direction - DIRECTION null if first call, then is set to TOP or BOTTOM depending of scroll
*/
private void route(FragmentMastodonTimeline.DIRECTION direction, boolean fetchingMissing) {
if (binding == null || !isAdded() || getActivity() == null) {
return;
}
new Thread(() -> {
if (binding == null) {
return;
}
QuickLoad quickLoad = new QuickLoad(requireActivity()).getSavedValue(MainActivity.currentUserID, MainActivity.currentInstance, notificationType);
if (direction != FragmentMastodonTimeline.DIRECTION.REFRESH && !fetchingMissing && !binding.swipeContainer.isRefreshing() && direction == null && quickLoad != null && quickLoad.notifications != null && quickLoad.notifications.size() > 0) {
Notifications notifications = new Notifications();
@ -365,10 +365,9 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
* @param fetched_notifications Notifications
*/
private synchronized void dealWithPagination(Notifications fetched_notifications, FragmentMastodonTimeline.DIRECTION direction, boolean fetchingMissing) {
if (binding == null) {
if (binding == null || !isAdded() || getActivity() == null) {
return;
}
int currentPosition = mLayoutManager.findFirstVisibleItemPosition();
binding.swipeContainer.setRefreshing(false);
binding.loadingNextElements.setVisibility(View.GONE);
flagLoading = false;
@ -376,10 +375,7 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
flagLoading = fetched_notifications.pagination.max_id == null;
binding.noAction.setVisibility(View.GONE);
//Update the timeline with new statuses
int inserted = updateNotificationListWith(direction, fetched_notifications.notifications, fetchingMissing);
if (fetchingMissing) {
// binding.recyclerView.scrollToPosition(currentPosition + inserted);
}
updateNotificationListWith(direction, fetched_notifications.notifications, fetchingMissing);
if (!fetchingMissing) {
if (fetched_notifications.pagination.max_id == null) {
flagLoading = true;
@ -400,9 +396,8 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
*
* @param notificationsReceived - List<Notification> Notifications received
* @param fetchingMissing - boolean if the call concerns fetching messages (ie: refresh of from fetch more button)
* @return int - Number of messages that have been inserted in the middle of the timeline (ie between other statuses)
*/
private int updateNotificationListWith(FragmentMastodonTimeline.DIRECTION direction, List<Notification> notificationsReceived, boolean fetchingMissing) {
private void updateNotificationListWith(FragmentMastodonTimeline.DIRECTION direction, List<Notification> notificationsReceived, boolean fetchingMissing) {
int numberInserted = 0;
int lastInsertedPosition = 0;
int initialInsertedPosition = NOTIFICATION_PRESENT;
@ -438,7 +433,6 @@ public class FragmentMastodonNotification extends Fragment implements Notificati
notificationAdapter.notifyItemInserted(insertAt);
}
}
return numberInserted;
}
/**

@ -95,6 +95,9 @@ public class FragmentMastodonTag extends Fragment {
* @param tags List of {@link Tag}
*/
private void initializeTagCommonView(final List<Tag> tags) {
if (binding == null || !isAdded() || getActivity() == null) {
return;
}
binding.loader.setVisibility(View.GONE);
binding.noAction.setVisibility(View.GONE);
binding.swipeContainer.setRefreshing(false);

@ -260,7 +260,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
*/
private void initializeStatusesCommonView(final Statuses statuses, int position) {
flagLoading = false;
if (binding == null) {
if (binding == null || !isAdded() || getActivity() == null) {
return;
}
binding.loader.setVisibility(View.GONE);
@ -376,7 +376,7 @@ public class FragmentMastodonTimeline extends Fragment implements StatusAdapter.
* @param fetched_statuses Statuses
*/
private synchronized void dealWithPagination(Statuses fetched_statuses, DIRECTION direction, boolean fetchingMissing) {
if (binding == null) {
if (binding == null || !isAdded() || getActivity() == null) {
return;
}
binding.swipeContainer.setRefreshing(false);

@ -33,6 +33,7 @@ import androidx.preference.PreferenceManager;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import java.util.ArrayList;
import java.util.List;
@ -60,19 +61,19 @@ public class FragmentNotificationContainer extends Fragment {
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(requireActivity());
boolean display_all_notification = sharedpreferences.getBoolean(getString(R.string.SET_DISPLAY_ALL_NOTIFICATIONS_TYPE) + BaseMainActivity.currentUserID + BaseMainActivity.currentInstance, false);
if (!display_all_notification) {
binding.tabLayout.addTab(binding.tabLayout.newTab().setText(getString(R.string.all)));
binding.tabLayout.addTab(binding.tabLayout.newTab().setText(getString(R.string.mention)));
binding.tabLayout.addTab(binding.tabLayout.newTab());
binding.tabLayout.addTab(binding.tabLayout.newTab());
binding.tabLayout.setTabMode(TabLayout.MODE_FIXED);
binding.viewpager.setAdapter(new FedilabNotificationPageAdapter(requireActivity(), false));
} else {
binding.tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
binding.tabLayout.addTab(binding.tabLayout.newTab().setText(getString(R.string.all)));
binding.tabLayout.addTab(binding.tabLayout.newTab().setIcon(R.drawable.ic_baseline_reply_24));
binding.tabLayout.addTab(binding.tabLayout.newTab().setIcon(R.drawable.ic_baseline_star_24));
binding.tabLayout.addTab(binding.tabLayout.newTab().setIcon(R.drawable.ic_repeat));
binding.tabLayout.addTab(binding.tabLayout.newTab().setIcon(R.drawable.ic_baseline_poll_24));
binding.tabLayout.addTab(binding.tabLayout.newTab().setIcon(R.drawable.ic_baseline_home_24));
binding.tabLayout.addTab(binding.tabLayout.newTab().setIcon(R.drawable.ic_baseline_person_add_alt_1_24));
binding.tabLayout.addTab(binding.tabLayout.newTab());
binding.tabLayout.addTab(binding.tabLayout.newTab());
binding.tabLayout.addTab(binding.tabLayout.newTab());
binding.tabLayout.addTab(binding.tabLayout.newTab());
binding.tabLayout.addTab(binding.tabLayout.newTab());
binding.tabLayout.addTab(binding.tabLayout.newTab());
binding.tabLayout.addTab(binding.tabLayout.newTab());
binding.viewpager.setAdapter(new FedilabNotificationPageAdapter(requireActivity(), true));
}
AtomicBoolean changes = new AtomicBoolean(false);
@ -187,7 +188,6 @@ public class FragmentNotificationContainer extends Fragment {
}
});
dialogBuilder.setPositiveButton(R.string.close, (dialog, id) -> {
if (changes.get()) {
SharedPreferences.Editor editor = sharedpreferences.edit();
if (excludedCategoriesList.size() > 0) {
@ -202,7 +202,6 @@ public class FragmentNotificationContainer extends Fragment {
} else {
editor.putString(getString(R.string.SET_EXCLUDED_NOTIFICATIONS_TYPE) + BaseMainActivity.currentUserID + BaseMainActivity.currentInstance, null);
}
editor.commit();
((BaseMainActivity) requireActivity()).refreshFragment();
}
@ -214,6 +213,47 @@ public class FragmentNotificationContainer extends Fragment {
binding.tabLayout.setTabTextColors(ThemeHelper.getAttColor(requireActivity(), R.attr.mTextColor), ContextCompat.getColor(requireActivity(), R.color.cyanea_accent_dark_reference));
binding.tabLayout.setTabIconTint(ThemeHelper.getColorStateList(requireActivity()));
new TabLayoutMediator(binding.tabLayout, binding.viewpager,
(tab, position) -> {
binding.viewpager.setCurrentItem(tab.getPosition(), true);
if (!display_all_notification) {
switch (position) {
case 0:
tab.setText(getString(R.string.all));
break;
case 1:
tab.setText(getString(R.string.mention));
break;
}
} else {
switch (position) {
case 0:
tab.setText(getString(R.string.all));
break;
case 1:
tab.setIcon(R.drawable.ic_baseline_reply_24);
break;
case 2:
tab.setIcon(R.drawable.ic_baseline_star_24);
break;
case 3:
tab.setIcon(R.drawable.ic_repeat);
break;
case 4:
tab.setIcon(R.drawable.ic_baseline_poll_24);
break;
case 5:
tab.setIcon(R.drawable.ic_baseline_home_24);
break;
case 6:
tab.setIcon(R.drawable.ic_baseline_person_add_alt_1_24);
break;
}
}
}
).attach();
binding.tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
@ -227,15 +267,11 @@ public class FragmentNotificationContainer extends Fragment {
@Override
public void onTabReselected(TabLayout.Tab tab) {
Fragment fragment;
if (binding.viewpager.getAdapter() != null) {
fragment = (Fragment) requireActivity().getSupportFragmentManager().findFragmentByTag("f" + binding.viewpager.getCurrentItem());
if (fragment instanceof FragmentMastodonNotification) {
FragmentMastodonNotification fragmentMastodonNotification = ((FragmentMastodonNotification) fragment);
fragmentMastodonNotification.scrollToTop();
}
Fragment fragment = requireActivity().getSupportFragmentManager().findFragmentByTag("f" + binding.viewpager.getCurrentItem());
if (fragment instanceof FragmentMastodonNotification) {
FragmentMastodonNotification fragmentMastodonNotification = ((FragmentMastodonNotification) fragment);
fragmentMastodonNotification.scrollToTop();
}
}
});
return binding.getRoot();
@ -244,9 +280,9 @@ public class FragmentNotificationContainer extends Fragment {
public void scrollToTop() {
if (binding != null) {
FragmentMastodonNotification fragmentMastodonNotification = (FragmentMastodonNotification) requireActivity().getSupportFragmentManager().findFragmentByTag("f" + binding.viewpager.getCurrentItem());
if (fragmentMastodonNotification != null) {
fragmentMastodonNotification.scrollToTop();
Fragment fragment = requireActivity().getSupportFragmentManager().findFragmentByTag("f" + binding.viewpager.getCurrentItem());
if (fragment instanceof FragmentMastodonNotification) {
((FragmentMastodonNotification) fragment).scrollToTop();
}
}
}

@ -532,6 +532,14 @@
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<com.google.android.material.tabs.TabLayout
android:id="@+id/account_tabLayout"
android:layout_width="match_parent"
@ -539,13 +547,11 @@
android:background="?backgroundColorLight"
app:tabGravity="fill"
app:tabMode="fixed" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/account_viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/account_viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

@ -30,9 +30,15 @@
app:tabIndicatorColor="@color/cyanea_accent_dark_reference"
app:tabMode="scrollable" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/search_viewpager"
<app.fedilab.android.helper.NestedScrollableHost
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
android:layout_height="wrap_content">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/search_viewpager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</app.fedilab.android.helper.NestedScrollableHost>
>
</LinearLayout>
Loading…
Cancel
Save