Migrate Navigation to 2.4.0-alpha4

1. 2.4.0 introduces multistack navigation. Which removes the need for NavigationExtensions
2. Organised all nav graphs into a single graph to remove global action redundancy.
This commit is contained in:
Ammar Githam 2021-07-03 21:36:34 +09:00
parent 2f7a68341d
commit 05f8b1b8e3
57 changed files with 2523 additions and 3207 deletions

View File

@ -163,7 +163,6 @@ configurations.all {
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
def nav_version = '2.3.5'
def exoplayer_version = '2.14.1'
implementation 'com.google.android.material:material:1.4.0-rc01'
@ -175,8 +174,6 @@ dependencies {
implementation "androidx.recyclerview:recyclerview:1.2.1"
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation "androidx.viewpager2:viewpager2:1.0.0"
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
implementation "androidx.constraintlayout:constraintlayout:2.0.4"
implementation "androidx.preference:preference:1.1.1"
implementation 'androidx.palette:palette:1.0.0'
@ -195,6 +192,10 @@ dependencies {
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
// Navigation
implementation "androidx.navigation:navigation-fragment-ktx:$rootProject.nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$rootProject.nav_version"
// Room
def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version"

View File

@ -1,7 +1,6 @@
package awais.instagrabber.activities
import android.animation.LayoutTransition
import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.ComponentName
@ -16,7 +15,6 @@ import android.view.MenuItem
import android.view.View
import android.view.WindowManager
import android.widget.Toast
import androidx.annotation.IdRes
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
@ -29,22 +27,22 @@ import androidx.emoji.text.EmojiCompat
import androidx.emoji.text.EmojiCompat.InitCallback
import androidx.emoji.text.FontRequestEmojiCompatConfig
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.NavController.OnDestinationChangedListener
import androidx.navigation.NavDestination
import androidx.navigation.ui.NavigationUI
import androidx.navigation.NavGraph
import androidx.navigation.NavGraphNavigator
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.*
import awais.instagrabber.BuildConfig
import awais.instagrabber.NavGraphDirections
import awais.instagrabber.R
import awais.instagrabber.customviews.emoji.EmojiVariantManager
import awais.instagrabber.customviews.helpers.RootViewDeferringInsetsCallback
import awais.instagrabber.customviews.helpers.TextWatcherAdapter
import awais.instagrabber.databinding.ActivityMainBinding
import awais.instagrabber.fragments.PostViewV2Fragment
import awais.instagrabber.fragments.directmessages.DirectMessageInboxFragmentDirections
import awais.instagrabber.fragments.main.FeedFragment
import awais.instagrabber.fragments.settings.PreferenceKeys
import awais.instagrabber.models.IntentModel
import awais.instagrabber.models.Resource
@ -68,20 +66,22 @@ import com.google.android.material.appbar.CollapsingToolbarLayout
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.textfield.TextInputLayout
import com.google.common.collect.ImmutableList
import com.google.common.collect.Iterators
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.*
import java.util.stream.Collectors
class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedListener {
private lateinit var binding: ActivityMainBinding
private lateinit var navController: NavController
private lateinit var appBarConfiguration: AppBarConfiguration
private var currentNavControllerLiveData: LiveData<NavController>? = null
// private var currentNavControllerLiveData: LiveData<NavController>? = null
private var searchMenuItem: MenuItem? = null
private var firstFragmentGraphIndex = 0
private var startNavRootId: Int = 0
// private var firstFragmentGraphIndex = 0
private var lastSelectedNavMenuId = 0
private var isActivityCheckerServiceBound = false
private var isBackStackEmpty = false
@ -141,8 +141,10 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
// } catch (e: Exception) {
// Log.e(TAG, "onCreate: ", e)
// }
val navHostFragment = supportFragmentManager.findFragmentById(R.id.main_nav_host) as NavHostFragment
navController = navHostFragment.navController
if (savedInstanceState == null) {
setupBottomNavigationBar(true)
setupNavigation(true)
}
if (!BuildConfig.isPre) {
val checkUpdates = Utils.settingsHelper.getBoolean(PreferenceKeys.CHECK_UPDATES)
@ -233,40 +235,18 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.main_menu, menu)
searchMenuItem = menu.findItem(R.id.search)
val navController = currentNavControllerLiveData?.value
if (navController != null) {
val currentDestination = navController.currentDestination
if (currentDestination != null) {
@SuppressLint("RestrictedApi") val backStack = navController.backStack
setupMenu(backStack.size, currentDestination.id)
}
// val navController = currentNavControllerLiveData?.value
val currentDestination = navController.currentDestination
if (currentDestination != null) {
val backStack = navController.backQueue
setupMenu(backStack.size, currentDestination.id)
}
// if (binding.searchInputLayout.getVisibility() == View.VISIBLE) {
// searchMenuItem.setVisible(false).setEnabled(false);
// return true;
// }
// searchMenuItem.setVisible(true).setEnabled(true);
// if (showSearch && currentNavControllerLiveData != null) {
// final NavController navController = currentNavControllerLiveData.getValue();
// if (navController != null) {
// final NavDestination currentDestination = navController.getCurrentDestination();
// if (currentDestination != null) {
// final int destinationId = currentDestination.getId();
// showSearch = destinationId == R.id.profileFragment;
// }
// }
// }
// if (!showSearch) {
// searchMenuItem.setVisible(false);
// return true;
// }
// return setupSearchView();
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.search) {
val navController = currentNavControllerLiveData?.value ?: return false
// val navController = currentNavControllerLiveData?.value ?: return false
try {
navController.navigate(R.id.action_global_search)
return true
@ -279,20 +259,13 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
}
override fun onSaveInstanceState(outState: Bundle) {
outState.putString(FIRST_FRAGMENT_GRAPH_INDEX_KEY, firstFragmentGraphIndex.toString())
// outState.putString(FIRST_FRAGMENT_GRAPH_INDEX_KEY, firstFragmentGraphIndex.toString())
outState.putString(LAST_SELECT_NAV_MENU_ID, binding.bottomNavView.selectedItemId.toString())
super.onSaveInstanceState(outState)
}
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
val key = savedInstanceState[FIRST_FRAGMENT_GRAPH_INDEX_KEY] as String?
if (key != null) {
try {
firstFragmentGraphIndex = key.toInt()
} catch (ignored: NumberFormatException) {
}
}
val lastSelected = savedInstanceState[LAST_SELECT_NAV_MENU_ID] as String?
if (lastSelected != null) {
try {
@ -300,13 +273,11 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
} catch (ignored: NumberFormatException) {
}
}
setupBottomNavigationBar(false)
setupNavigation(false)
}
override fun onSupportNavigateUp(): Boolean {
if (currentNavControllerLiveData == null) return false
val navController = currentNavControllerLiveData?.value ?: return false
return navController.navigateUp()
return navController.navigateUp(appBarConfiguration)
}
override fun onNewIntent(intent: Intent) {
@ -331,14 +302,8 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
}
override fun onBackPressed() {
var currentNavControllerBackStack = 2
currentNavControllerLiveData?.let {
val navController = it.value
if (navController != null) {
@SuppressLint("RestrictedApi") val backStack = navController.backStack
currentNavControllerBackStack = backStack.size
}
}
val backStack = navController.backQueue
val currentNavControllerBackStack = backStack.size
if (isTaskRoot && isBackStackEmpty && currentNavControllerBackStack == 2) {
finishAfterTransition()
return
@ -391,117 +356,40 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
notificationManager.createNotificationChannel(silentNotificationChannel)
}
private fun setupBottomNavigationBar(setDefaultTabFromSettings: Boolean) {
currentTabs = if (!isLoggedIn) setupAnonBottomNav() else setupMainBottomNav()
val mainNavList = currentTabs.stream()
.map(Tab::navigationResId)
.collect(Collectors.toList())
private fun setupNavigation(setDefaultTabFromSettings: Boolean) {
currentTabs = if (isLoggedIn) setupMainBottomNav() else setupAnonBottomNav()
showBottomViewDestinations = currentTabs.asSequence().map {
it.startDestinationFragmentId
}.toMutableList().apply {
add(R.id.postViewFragment)
add(R.id.favoritesFragment)
add(R.id.profile_non_top)
}
if (setDefaultTabFromSettings) {
setSelectedTab(currentTabs)
} else {
binding.bottomNavView.selectedItemId = lastSelectedNavMenuId
}
val navControllerLiveData = NavigationExtensions.setupWithNavController(
binding.bottomNavView,
mainNavList,
supportFragmentManager,
R.id.main_nav_host,
intent,
firstFragmentGraphIndex
)
navControllerLiveData.observe(this, { navController: NavController? -> setupNavigation(binding.toolbar, navController) })
currentNavControllerLiveData = navControllerLiveData
}
private fun setSelectedTab(tabs: List<Tab>) {
val defaultTabResNameString = Utils.settingsHelper.getString(Constants.DEFAULT_TAB)
try {
var navId = 0
if (!isEmpty(defaultTabResNameString)) {
navId = resources.getIdentifier(defaultTabResNameString, "navigation", packageName)
}
val navGraph = if (isLoggedIn) R.navigation.feed_nav_graph else R.navigation.profile_nav_graph
val defaultNavId = if (navId <= 0) navGraph else navId
var index = Iterators.indexOf(tabs.iterator()) { tab: Tab? ->
if (tab == null) return@indexOf false
tab.navigationResId == defaultNavId
}
if (index < 0 || index >= tabs.size) index = 0
firstFragmentGraphIndex = index
setBottomNavSelectedTab(tabs[index])
} catch (e: Exception) {
Log.e(TAG, "Error parsing id", e)
val navigatorProvider = navController.navigatorProvider
val navigator = navigatorProvider.getNavigator<NavGraphNavigator>("navigation")
val rootNavGraph = NavGraph(navigator)
val navInflater = navController.navInflater
val destinations = currentTabs.map {
val navGraph = navInflater.inflate(R.navigation.nav_graph)
navGraph.id = it.navigationRootId
navGraph.label = "${it.title}_nav_graph".lowercase(Locale.getDefault())
navGraph.setStartDestination(it.startDestinationFragmentId)
return@map navGraph
}
}
private fun setupAnonBottomNav(): List<Tab> {
val selectedItemId = binding.bottomNavView.selectedItemId
val favoriteTab = Tab(
R.drawable.ic_star_24,
getString(R.string.title_favorites),
false,
"favorites_nav_graph",
R.navigation.favorites_nav_graph,
R.id.favorites_nav_graph,
R.id.favoritesFragment
)
val profileTab = Tab(
R.drawable.ic_person_24,
getString(R.string.profile),
false,
"profile_nav_graph",
R.navigation.profile_nav_graph,
R.id.profile_nav_graph,
R.id.profileFragment
)
val moreTab = Tab(
R.drawable.ic_more_horiz_24,
getString(R.string.more),
false,
"more_nav_graph",
R.navigation.more_nav_graph,
R.id.more_nav_graph,
R.id.morePreferencesFragment
)
val menu = binding.bottomNavView.menu
menu.clear()
menu.add(0, favoriteTab.navigationRootId, 0, favoriteTab.title).setIcon(favoriteTab.iconResId)
menu.add(0, profileTab.navigationRootId, 0, profileTab.title).setIcon(profileTab.iconResId)
menu.add(0, moreTab.navigationRootId, 0, moreTab.title).setIcon(moreTab.iconResId)
if (selectedItemId != R.id.profile_nav_graph && selectedItemId != R.id.more_nav_graph && selectedItemId != R.id.favorites_nav_graph) {
setBottomNavSelectedTab(profileTab)
}
return ImmutableList.of(favoriteTab, profileTab, moreTab)
}
private fun setupMainBottomNav(): List<Tab> {
val menu = binding.bottomNavView.menu
menu.clear()
val navTabList = Utils.getNavTabList(this).first
for ((iconResId, title, _, _, _, navigationRootId) in navTabList) {
menu.add(0, navigationRootId, 0, title).setIcon(iconResId)
}
return navTabList
}
private fun setBottomNavSelectedTab(tab: Tab) {
binding.bottomNavView.selectedItemId = tab.navigationRootId
}
private fun setBottomNavSelectedTab(@IdRes navGraphRootId: Int) {
binding.bottomNavView.selectedItemId = navGraphRootId
}
private fun setupNavigation(toolbar: Toolbar, navController: NavController?) {
if (navController == null) return
NavigationUI.setupWithNavController(toolbar, navController)
navController.addOnDestinationChangedListener(OnDestinationChangedListener { _: NavController?, destination: NavDestination, arguments: Bundle? ->
rootNavGraph.id = R.id.root_nav_graph
rootNavGraph.label = "root_nav_graph"
rootNavGraph.addDestinations(destinations)
rootNavGraph.setStartDestination(if (startNavRootId != 0) startNavRootId else R.id.profile_nav_graph)
navController.graph = rootNavGraph
binding.bottomNavView.setupWithNavController(navController)
appBarConfiguration = AppBarConfiguration(currentTabs.map { it.startDestinationFragmentId }.toSet())
setupActionBarWithNavController(navController, appBarConfiguration)
navController.addOnDestinationChangedListener { _: NavController?, destination: NavDestination, arguments: Bundle? ->
if (destination.id == R.id.directMessagesThreadFragment && arguments != null) {
// Set the thread title earlier for better ux
val title = arguments.getString("title")
@ -519,7 +407,7 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
// below is a hack to check if we are at the end of the current stack, to setup the search view
binding.appBarLayout.setExpanded(true, true)
val destinationId = destination.id
@SuppressLint("RestrictedApi") val backStack = navController.backStack
val backStack = navController.backQueue
setupMenu(backStack.size, destinationId)
val contains = showBottomViewDestinations.contains(destinationId)
binding.root.post {
@ -531,7 +419,65 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
// explicitly hide keyboard when we navigate
val view = currentFocus
Utils.hideKeyboard(view)
})
}
setupReselection()
}
private fun setupReselection() {
binding.bottomNavView.setOnItemReselectedListener {
val navHostFragment = (supportFragmentManager.primaryNavigationFragment ?: return@setOnItemReselectedListener) as NavHostFragment
val currentFragment = navHostFragment.childFragmentManager.fragments.firstOrNull() ?: return@setOnItemReselectedListener
if (currentFragment is FeedFragment) {
currentFragment.scrollToTop()
return@setOnItemReselectedListener
}
val currentDestination = navController.currentDestination ?: return@setOnItemReselectedListener
val currentTabStartDestId = (navController.getBackStackEntry(it.itemId).destination as NavGraph).startDestinationId
if (currentDestination.id == currentTabStartDestId) return@setOnItemReselectedListener
navController.popBackStack(currentTabStartDestId, false)
}
}
private fun setSelectedTab(tabs: List<Tab>) {
val defaultTabResNameString = Utils.settingsHelper.getString(Constants.DEFAULT_TAB)
try {
var navId = 0
if (defaultTabResNameString.isNotBlank()) {
navId = resources.getIdentifier(defaultTabResNameString, "id", packageName)
}
val startFragmentNavResId = if (navId <= 0) R.id.profile_nav_graph else navId
val tab = tabs.firstOrNull { it.navigationRootId == startFragmentNavResId }
// if (index < 0 || index >= tabs.size) index = 0
val firstTab = tab ?: tabs[0]
startNavRootId = firstTab.navigationRootId
binding.bottomNavView.selectedItemId = firstTab.navigationRootId
} catch (e: Exception) {
Log.e(TAG, "Error parsing id", e)
}
}
private fun setupAnonBottomNav(): List<Tab> {
val selectedItemId = binding.bottomNavView.selectedItemId
val anonNavTabs = getAnonNavTabs(this)
val menu = binding.bottomNavView.menu
menu.clear()
for (tab in anonNavTabs) {
menu.add(0, tab.navigationRootId, 0, tab.title).setIcon(tab.iconResId)
}
if (selectedItemId != R.id.profile_nav_graph && selectedItemId != R.id.more_nav_graph && selectedItemId != R.id.favorites_nav_graph) {
binding.bottomNavView.selectedItemId = R.id.profile_nav_graph
}
return anonNavTabs
}
private fun setupMainBottomNav(): List<Tab> {
val menu = binding.bottomNavView.menu
menu.clear()
val navTabList = getLoggedInNavTabs(this).first
for (tab in navTabList) {
menu.add(0, tab.navigationRootId, 0, tab.title).setIcon(tab.iconResId)
}
return navTabList
}
private fun setupMenu(backStackSize: Int, destinationId: Int) {
@ -589,47 +535,11 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
fun navigateToThread(threadId: String?, threadTitle: String?) {
if (threadId == null || threadTitle == null) return
currentNavControllerLiveData?.observe(this, object : Observer<NavController?> {
override fun onChanged(navController: NavController?) {
if (navController == null) return
if (navController.graph.id != R.id.direct_messages_nav_graph) return
try {
val currentDestination = navController.currentDestination
if (currentDestination != null && currentDestination.id == R.id.directMessagesInboxFragment) {
// if we are already on the inbox page, navigate to the thread
// need handler.post() to wait for the fragment manager to be ready to navigate
Handler(Looper.getMainLooper()).post {
val action = DirectMessageInboxFragmentDirections
.actionInboxToThread(threadId, threadTitle)
navController.navigate(action)
}
return
}
// add a destination change listener to navigate to thread once we are on the inbox page
navController.addOnDestinationChangedListener(object : OnDestinationChangedListener {
override fun onDestinationChanged(
controller: NavController,
destination: NavDestination,
arguments: Bundle?,
) {
if (destination.id == R.id.directMessagesInboxFragment) {
val action = DirectMessageInboxFragmentDirections
.actionInboxToThread(threadId, threadTitle)
controller.navigate(action)
controller.removeOnDestinationChangedListener(this)
}
}
})
// pop back stack until we reach the inbox page
navController.popBackStack(R.id.directMessagesInboxFragment, false)
} finally {
currentNavControllerLiveData?.removeObserver(this)
}
}
})
val selectedItemId = binding.bottomNavView.selectedItemId
if (selectedItemId != R.navigation.direct_messages_nav_graph) {
setBottomNavSelectedTab(R.id.direct_messages_nav_graph)
try {
val action = NavGraphDirections.actionGlobalDirectThread(threadId, threadTitle)
navController.navigate(action)
} catch (e: Exception) {
Log.e(TAG, "navigateToThread: ", e)
}
}
@ -652,14 +562,10 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
}
private fun showProfileView(intentModel: IntentModel) {
val username = intentModel.text
// Log.d(TAG, "username: " + username);
val currentNavControllerLiveData = currentNavControllerLiveData ?: return
val navController = currentNavControllerLiveData.value
val bundle = Bundle()
bundle.putString("username", "@$username")
try {
navController?.navigate(R.id.action_global_profileFragment, bundle)
val username = intentModel.text
val action = NavGraphDirections.actionGlobalProfile().setUsername(username)
navController.navigate(action)
} catch (e: Exception) {
Log.e(TAG, "showProfileView: ", e)
}
@ -681,12 +587,9 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
Toast.makeText(applicationContext, R.string.post_not_found, Toast.LENGTH_SHORT).show()
return@withContext
}
val currentNavControllerLiveData = currentNavControllerLiveData ?: return@withContext
val navController = currentNavControllerLiveData.value
val bundle = Bundle()
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media)
try {
navController?.navigate(R.id.action_global_post_view, bundle)
val action = NavGraphDirections.actionGlobalPost(media, 0)
navController.navigate(action)
} catch (e: Exception) {
Log.e(TAG, "showPostView: ", e)
}
@ -704,29 +607,32 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
private fun showLocationView(intentModel: IntentModel) {
val locationId = intentModel.text
// Log.d(TAG, "locationId: " + locationId);
val currentNavControllerLiveData = currentNavControllerLiveData ?: return
val navController = currentNavControllerLiveData.value
val bundle = Bundle()
bundle.putLong("locationId", locationId.toLong())
navController?.navigate(R.id.action_global_locationFragment, bundle)
try {
val action = NavGraphDirections.actionGlobalLocation(locationId.toLong())
navController.navigate(action)
} catch (e: Exception) {
Log.e(TAG, "showLocationView: ", e)
}
}
private fun showHashtagView(intentModel: IntentModel) {
val hashtag = intentModel.text
// Log.d(TAG, "hashtag: " + hashtag);
val currentNavControllerLiveData = currentNavControllerLiveData ?: return
val navController = currentNavControllerLiveData.value
val bundle = Bundle()
bundle.putString("hashtag", hashtag)
navController?.navigate(R.id.action_global_hashTagFragment, bundle)
try {
val action = NavGraphDirections.actionGlobalHashTag(hashtag)
navController.navigate(action)
} catch (e: Exception) {
Log.e(TAG, "showHashtagView: ", e)
}
}
private fun showActivityView() {
val currentNavControllerLiveData = currentNavControllerLiveData ?: return
val navController = currentNavControllerLiveData.value
val bundle = Bundle()
bundle.putString("type", "notif")
navController?.navigate(R.id.action_global_notificationsViewerFragment, bundle)
try {
val action = NavGraphDirections.actionGlobalNotifications().apply { type = "notif" }
navController.navigate(action)
} catch (e: Exception) {
Log.e(TAG, "showActivityView: ", e)
}
}
private fun bindActivityCheckerService() {
@ -763,8 +669,7 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
binding.appBarLayout.visibility = View.VISIBLE
setScrollingBehaviour()
setSupportActionBar(binding.toolbar)
val currentNavControllerLiveData = currentNavControllerLiveData ?: return
setupNavigation(binding.toolbar, currentNavControllerLiveData.value)
setupActionBarWithNavController(navController, appBarConfiguration)
}
val collapsingToolbarView: CollapsingToolbarLayout
@ -808,8 +713,7 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
binding.appBarLayout.visibility = View.GONE
removeScrollingBehaviour()
setSupportActionBar(toolbar)
if (currentNavControllerLiveData == null) return
setupNavigation(toolbar, currentNavControllerLiveData?.value)
NavigationUI.setupWithNavController(toolbar, navController, appBarConfiguration)
}
val rootView: View
get() = binding.root
@ -839,8 +743,8 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
companion object {
private const val TAG = "MainActivity"
private const val FIRST_FRAGMENT_GRAPH_INDEX_KEY = "firstFragmentGraphIndex"
private const val LAST_SELECT_NAV_MENU_ID = "lastSelectedNavMenuId"
private val SEARCH_VISIBLE_DESTINATIONS: List<Int> = ImmutableList.of(
R.id.feedFragment,
R.id.profileFragment,

View File

@ -1,60 +1,60 @@
package awais.instagrabber.customviews;
import android.os.Bundle;
import androidx.annotation.NavigationRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.navigation.NavController;
import androidx.navigation.Navigator;
import androidx.navigation.fragment.FragmentNavigator;
import androidx.navigation.fragment.NavHostFragment;
public class NavHostFragmentWithDefaultAnimations extends NavHostFragment {
private static final String KEY_GRAPH_ID = "android-support-nav:fragment:graphId";
private static final String KEY_START_DESTINATION_ARGS =
"android-support-nav:fragment:startDestinationArgs";
private static final String KEY_NAV_CONTROLLER_STATE =
"android-support-nav:fragment:navControllerState";
private static final String KEY_DEFAULT_NAV_HOST = "android-support-nav:fragment:defaultHost";
@NonNull
public static NavHostFragment create(@NavigationRes int graphResId) {
return create(graphResId, null);
}
@NonNull
public static NavHostFragment create(@NavigationRes int graphResId,
@Nullable Bundle startDestinationArgs) {
Bundle b = null;
if (graphResId != 0) {
b = new Bundle();
b.putInt(KEY_GRAPH_ID, graphResId);
}
if (startDestinationArgs != null) {
if (b == null) {
b = new Bundle();
}
b.putBundle(KEY_START_DESTINATION_ARGS, startDestinationArgs);
}
final NavHostFragmentWithDefaultAnimations result = new NavHostFragmentWithDefaultAnimations();
if (b != null) {
result.setArguments(b);
}
return result;
}
@NonNull
@Override
protected Navigator<? extends FragmentNavigator.Destination> createFragmentNavigator() {
return new FragmentNavigatorWithDefaultAnimations(requireContext(), getChildFragmentManager(), getId());
}
@Override
protected void onCreateNavController(@NonNull final NavController navController) {
super.onCreateNavController(navController);
navController.getNavigatorProvider()
.addNavigator(new FragmentNavigatorWithDefaultAnimations(requireContext(), getChildFragmentManager(), getId()));
}
}
// package awais.instagrabber.customviews;
//
// import android.os.Bundle;
//
// import androidx.annotation.NavigationRes;
// import androidx.annotation.NonNull;
// import androidx.annotation.Nullable;
// import androidx.navigation.NavController;
// import androidx.navigation.Navigator;
// import androidx.navigation.fragment.FragmentNavigator;
// import androidx.navigation.fragment.NavHostFragment;
//
// public class NavHostFragmentWithDefaultAnimations extends NavHostFragment {
// private static final String KEY_GRAPH_ID = "android-support-nav:fragment:graphId";
// private static final String KEY_START_DESTINATION_ARGS =
// "android-support-nav:fragment:startDestinationArgs";
// private static final String KEY_NAV_CONTROLLER_STATE =
// "android-support-nav:fragment:navControllerState";
// private static final String KEY_DEFAULT_NAV_HOST = "android-support-nav:fragment:defaultHost";
//
// @NonNull
// public static NavHostFragment create(@NavigationRes int graphResId) {
// return create(graphResId, null);
// }
//
// @NonNull
// public static NavHostFragment create(@NavigationRes int graphResId,
// @Nullable Bundle startDestinationArgs) {
// Bundle b = null;
// if (graphResId != 0) {
// b = new Bundle();
// b.putInt(KEY_GRAPH_ID, graphResId);
// }
// if (startDestinationArgs != null) {
// if (b == null) {
// b = new Bundle();
// }
// b.putBundle(KEY_START_DESTINATION_ARGS, startDestinationArgs);
// }
//
// final NavHostFragmentWithDefaultAnimations result = new NavHostFragmentWithDefaultAnimations();
// if (b != null) {
// result.setArguments(b);
// }
// return result;
// }
//
// @NonNull
// @Override
// protected Navigator<? extends FragmentNavigator.Destination> createFragmentNavigator() {
// return new FragmentNavigatorWithDefaultAnimations(requireContext(), getChildFragmentManager(), getId());
// }
//
// @Override
// protected void onCreateNavController(@NonNull final NavController navController) {
// super.onCreateNavController(navController);
// navController.getNavigatorProvider()
// .addNavigator(new FragmentNavigatorWithDefaultAnimations(requireContext(), getChildFragmentManager(), getId()));
// }
// }

View File

@ -4,7 +4,6 @@ import android.app.Dialog;
import android.content.Context;
import android.graphics.Canvas;
import android.os.Bundle;
import android.util.Pair;
import android.view.View;
import androidx.annotation.NonNull;
@ -28,7 +27,9 @@ import awais.instagrabber.adapters.TabsAdapter;
import awais.instagrabber.adapters.viewholder.TabViewHolder;
import awais.instagrabber.fragments.settings.PreferenceKeys;
import awais.instagrabber.models.Tab;
import awais.instagrabber.utils.NavigationHelperKt;
import awais.instagrabber.utils.Utils;
import kotlin.Pair;
import static androidx.recyclerview.widget.ItemTouchHelper.ACTION_STATE_DRAG;
import static androidx.recyclerview.widget.ItemTouchHelper.DOWN;
@ -235,9 +236,10 @@ public class TabOrderPreferenceDialogFragment extends DialogFragment {
}
private void saveNewOrder() {
final String newOrderString = newOrderTabs.stream()
.map(Tab::getGraphName)
.collect(Collectors.joining(","));
final String newOrderString = newOrderTabs
.stream()
.map(tab -> NavigationHelperKt.geNavGraphNameForNavRootId(tab.getNavigationRootId()))
.collect(Collectors.joining(","));
Utils.settingsHelper.putString(PreferenceKeys.PREF_TAB_ORDER, newOrderString);
}
@ -258,12 +260,12 @@ public class TabOrderPreferenceDialogFragment extends DialogFragment {
itemTouchHelper.attachToRecyclerView(list);
adapter = new TabsAdapter(tabAdapterCallback);
list.setAdapter(adapter);
final Pair<List<Tab>, List<Tab>> navTabListPair = Utils.getNavTabList(context);
tabsInPref = navTabListPair.first;
final Pair<List<Tab>, List<Tab>> navTabListPair = NavigationHelperKt.getLoggedInNavTabs(context);
tabsInPref = navTabListPair.getFirst();
// initially set newOrderTabs and newOtherTabs same as current tabs
newOrderTabs = navTabListPair.first;
newOtherTabs = navTabListPair.second;
adapter.submitList(navTabListPair.first, navTabListPair.second);
newOrderTabs = navTabListPair.getFirst();
newOtherTabs = navTabListPair.getSecond();
adapter.submitList(navTabListPair.getFirst(), navTabListPair.getSecond());
return list;
}

View File

@ -2,7 +2,6 @@ package awais.instagrabber.fragments;
import android.animation.ArgbEvaluator;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Animatable;
@ -29,7 +28,6 @@ import androidx.appcompat.app.AlertDialog;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.graphics.ColorUtils;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@ -54,7 +52,9 @@ import awais.instagrabber.databinding.FragmentCollectionPostsBinding;
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.models.enums.PostItemType;
import awais.instagrabber.repositories.responses.Location;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.saved.SavedCollection;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
@ -76,7 +76,6 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
private Set<Media> selectedFeedModels;
private CollectionService collectionService;
private PostsLayoutPreferences layoutPreferences = Utils.getPostsLayoutPreferences(Constants.PREF_SAVED_POSTS_LAYOUT);
private MenuItem deleteMenu, editMenu;
private final OnBackPressedCallback onBackPressedCallback = new OnBackPressedCallback(false) {
@Override
@ -107,22 +106,28 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
private final FeedAdapterV2.FeedItemCallback feedItemCallback = new FeedAdapterV2.FeedItemCallback() {
@Override
public void onPostClick(final Media feedModel, final View profilePicView, final View mainPostImage) {
openPostDialog(feedModel, profilePicView, mainPostImage, -1);
openPostDialog(feedModel, -1);
}
@Override
public void onSliderClick(final Media feedModel, final int position) {
openPostDialog(feedModel, null, null, position);
openPostDialog(feedModel, position);
}
@Override
public void onCommentsClick(final Media feedModel) {
final NavDirections commentsAction = CollectionPostsFragmentDirections.actionGlobalCommentsViewerFragment(
feedModel.getCode(),
feedModel.getPk(),
feedModel.getUser().getPk()
);
NavHostFragment.findNavController(CollectionPostsFragment.this).navigate(commentsAction);
final User user = feedModel.getUser();
if (user == null) return;
try {
final NavDirections commentsAction = CollectionPostsFragmentDirections.actionToComments(
feedModel.getCode(),
feedModel.getPk(),
user.getPk()
);
NavHostFragment.findNavController(CollectionPostsFragment.this).navigate(commentsAction);
} catch (Exception e) {
Log.e(TAG, "onCommentsClick: ", e);
}
}
@Override
@ -134,14 +139,24 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
@Override
public void onHashtagClick(final String hashtag) {
final NavDirections action = CollectionPostsFragmentDirections.actionGlobalHashTagFragment(hashtag);
NavHostFragment.findNavController(CollectionPostsFragment.this).navigate(action);
try {
final NavDirections action = CollectionPostsFragmentDirections.actionToHashtag(hashtag);
NavHostFragment.findNavController(CollectionPostsFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onHashtagClick: ", e);
}
}
@Override
public void onLocationClick(final Media feedModel) {
final NavDirections action = CollectionPostsFragmentDirections.actionGlobalLocationFragment(feedModel.getLocation().getPk());
NavHostFragment.findNavController(CollectionPostsFragment.this).navigate(action);
final Location location = feedModel.getLocation();
if (location == null) return;
try {
final NavDirections action = CollectionPostsFragmentDirections.actionToLocation(location.getPk());
NavHostFragment.findNavController(CollectionPostsFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onLocationClick: ", e);
}
}
@Override
@ -151,12 +166,16 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
@Override
public void onNameClick(final Media feedModel, final View profilePicView) {
navigateToProfile("@" + feedModel.getUser().getUsername());
final User user = feedModel.getUser();
if (user == null) return;
navigateToProfile("@" + user.getUsername());
}
@Override
public void onProfilePicClick(final Media feedModel, final View profilePicView) {
navigateToProfile("@" + feedModel.getUser().getUsername());
final User user = feedModel.getUser();
if (user == null) return;
navigateToProfile("@" + user.getUsername());
}
@Override
@ -169,16 +188,10 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
Utils.openEmailAddress(getContext(), emailId);
}
private void openPostDialog(final Media feedModel,
final View profilePicView,
final View mainPostImage,
final int position) {
final NavController navController = NavHostFragment.findNavController(CollectionPostsFragment.this);
final Bundle bundle = new Bundle();
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, feedModel);
bundle.putInt(PostViewV2Fragment.ARG_SLIDER_POSITION, position);
private void openPostDialog(final Media feedModel, final int position) {
try {
navController.navigate(R.id.action_global_post_view, bundle);
final NavDirections action = CollectionPostsFragmentDirections.actionToPost(feedModel, position);
NavHostFragment.findNavController(CollectionPostsFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "openPostDialog: ", e);
}
@ -265,10 +278,10 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
@Override
public void onCreateOptionsMenu(@NonNull final Menu menu, @NonNull final MenuInflater inflater) {
inflater.inflate(R.menu.collection_posts_menu, menu);
deleteMenu = menu.findItem(R.id.delete);
final MenuItem deleteMenu = menu.findItem(R.id.delete);
if (deleteMenu != null)
deleteMenu.setVisible(savedCollection.getCollectionType().equals("MEDIA"));
editMenu = menu.findItem(R.id.edit);
final MenuItem editMenu = menu.findItem(R.id.edit);
if (editMenu != null)
editMenu.setVisible(savedCollection.getCollectionType().equals("MEDIA"));
}
@ -411,9 +424,7 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
}
private void setupCover() {
final String coverUrl = ResponseBodyUtils.getImageUrl(savedCollection.getCoverMediaList() == null
? savedCollection.getCoverMedia()
: savedCollection.getCoverMediaList().get(0));
final String coverUrl = ResponseBodyUtils.getImageUrl(savedCollection.getCoverMediaList().get(0));
final DraweeController controller = Fresco
.newDraweeControllerBuilder()
.setOldController(binding.cover.getController())
@ -454,10 +465,12 @@ public class CollectionPostsFragment extends Fragment implements SwipeRefreshLay
}
private void navigateToProfile(final String username) {
final NavController navController = NavHostFragment.findNavController(this);
final Bundle bundle = new Bundle();
bundle.putString("username", username);
navController.navigate(R.id.action_global_profileFragment, bundle);
try {
final NavDirections action = CollectionPostsFragmentDirections.actionToProfile().setUsername(username);
NavHostFragment.findNavController(this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "navigateToProfile: ", e);
}
}
private void showPostsLayoutPreferences() {

View File

@ -8,7 +8,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import awais.instagrabber.R
@ -48,17 +48,17 @@ class FavoritesFragment : Fragment() {
override fun onPause() {
super.onPause()
adapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.PREVENT)
adapter.stateRestorationPolicy = RecyclerView.Adapter.StateRestorationPolicy.PREVENT
}
override fun onResume() {
super.onResume()
if (!this::adapter.isInitialized) return
// refresh list every time in onViewStateRestored since it is cheaper than implementing pull down to refresh
favoritesViewModel.list.observe(viewLifecycleOwner, {
list: List<Favorite?>? -> adapter.submitList(list, Runnable {
adapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.ALLOW)
})
favoritesViewModel.list.observe(viewLifecycleOwner, { list: List<Favorite?>? ->
adapter.submitList(list) {
adapter.stateRestorationPolicy = RecyclerView.Adapter.StateRestorationPolicy.ALLOW
}
})
}
@ -66,32 +66,31 @@ class FavoritesFragment : Fragment() {
adapter = FavoritesAdapter({ model: Favorite ->
when (model.type) {
FavoriteType.USER -> {
val username = model.query
// Log.d(TAG, "username: " + username);
val navController = NavHostFragment.findNavController(this)
val bundle = Bundle()
bundle.putString("username", "@$username")
navController.navigate(R.id.action_global_profileFragment, bundle)
try {
val username = model.query ?: return@FavoritesAdapter
val actionToProfile = FavoritesFragmentDirections.actionToProfile().apply { this.username = username }
findNavController().navigate(actionToProfile)
} catch (e: Exception) {
Log.e(TAG, "init: ", e)
}
}
FavoriteType.LOCATION -> {
val locationId = model.query ?: return@FavoritesAdapter
// Log.d(TAG, "locationId: " + locationId);
val navController = NavHostFragment.findNavController(this)
val bundle = Bundle()
try {
bundle.putLong("locationId", locationId.toLong())
navController.navigate(R.id.action_global_locationFragment, bundle)
val locationId = model.query ?: return@FavoritesAdapter
val actionToLocation = FavoritesFragmentDirections.actionToLocation(locationId.toLong())
findNavController().navigate(actionToLocation)
} catch (e: Exception) {
Log.e(TAG, "init: ", e)
}
}
FavoriteType.HASHTAG -> {
val hashtag = model.query
// Log.d(TAG, "hashtag: " + hashtag);
val navController = NavHostFragment.findNavController(this)
val bundle = Bundle()
bundle.putString("hashtag", "#$hashtag")
navController.navigate(R.id.action_global_hashTagFragment, bundle)
try {
val hashtag = model.query ?: return@FavoritesAdapter
val actionToHashtag = FavoritesFragmentDirections.actionToHashtag(hashtag)
findNavController().navigate(actionToHashtag)
} catch (e: Exception) {
Log.e(TAG, "init: ", e)
}
}
else -> {
}

View File

@ -18,6 +18,7 @@ import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@ -209,10 +210,12 @@ public final class FollowViewerFragment extends Fragment implements SwipeRefresh
final Object tag = v.getTag();
if (tag instanceof FollowModel) {
model = (FollowModel) tag;
final FollowViewerFragmentDirections.ActionFollowViewerFragmentToProfileFragment action = FollowViewerFragmentDirections
.actionFollowViewerFragmentToProfileFragment();
action.setUsername("@" + model.getUsername());
NavHostFragment.findNavController(this).navigate(action);
try {
final NavDirections action = FollowViewerFragmentDirections.actionToProfile().setUsername(model.getUsername());
NavHostFragment.findNavController(this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "init: ", e);
}
}
};
binding.swipeRefreshLayout.setOnRefreshListener(this);

View File

@ -2,7 +2,6 @@ package awais.instagrabber.fragments;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
@ -27,7 +26,6 @@ import androidx.appcompat.app.ActionBar;
import androidx.constraintlayout.motion.widget.MotionLayout;
import androidx.constraintlayout.motion.widget.MotionScene;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.RecyclerView;
@ -53,7 +51,6 @@ import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.models.enums.FavoriteType;
import awais.instagrabber.models.enums.FollowingType;
import awais.instagrabber.repositories.requests.StoryViewerOptions;
import awais.instagrabber.repositories.responses.Hashtag;
import awais.instagrabber.repositories.responses.Location;
import awais.instagrabber.repositories.responses.Media;
@ -67,7 +64,6 @@ import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
import awais.instagrabber.webservices.GraphQLRepository;
import awais.instagrabber.webservices.ServiceCallback;
import awais.instagrabber.webservices.StoriesRepository;
import awais.instagrabber.webservices.TagsService;
import kotlinx.coroutines.Dispatchers;
@ -76,22 +72,17 @@ import static awais.instagrabber.utils.Utils.settingsHelper;
public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "HashTagFragment";
public static final String ARG_HASHTAG = "hashtag";
private MainActivity fragmentActivity;
private FragmentHashtagBinding binding;
private MotionLayout root;
private boolean shouldRefresh = true;
// private boolean hasStories = false;
private boolean opening = false;
private String hashtag;
private Hashtag hashtagModel = null;
private ActionMode actionMode;
private StoriesRepository storiesRepository;
private boolean isLoggedIn;
private TagsService tagsService;
private GraphQLRepository graphQLRepository;
private boolean storiesFetching;
private Set<Media> selectedFeedModels;
private PostsLayoutPreferences layoutPreferences = Utils.getPostsLayoutPreferences(Constants.PREF_HASHTAG_POSTS_LAYOUT);
private LayoutHashtagDetailsBinding hashtagDetailsBinding;
@ -126,22 +117,28 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
private final FeedAdapterV2.FeedItemCallback feedItemCallback = new FeedAdapterV2.FeedItemCallback() {
@Override
public void onPostClick(final Media feedModel, final View profilePicView, final View mainPostImage) {
openPostDialog(feedModel, profilePicView, mainPostImage, -1);
openPostDialog(feedModel, -1);
}
@Override
public void onSliderClick(final Media feedModel, final int position) {
openPostDialog(feedModel, null, null, position);
openPostDialog(feedModel, position);
}
@Override
public void onCommentsClick(final Media feedModel) {
final NavDirections commentsAction = HashTagFragmentDirections.actionGlobalCommentsViewerFragment(
feedModel.getCode(),
feedModel.getCode(),
feedModel.getUser().getPk()
);
NavHostFragment.findNavController(HashTagFragment.this).navigate(commentsAction);
final User user = feedModel.getUser();
if (user == null) return;
try {
final NavDirections commentsAction = HashTagFragmentDirections.actionToComments(
feedModel.getCode(),
feedModel.getCode(),
user.getPk()
);
NavHostFragment.findNavController(HashTagFragment.this).navigate(commentsAction);
} catch (Exception e) {
Log.e(TAG, "onCommentsClick: ", e);
}
}
@Override
@ -153,16 +150,24 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
@Override
public void onHashtagClick(final String hashtag) {
final NavDirections action = HashTagFragmentDirections.actionGlobalHashTagFragment(hashtag);
NavHostFragment.findNavController(HashTagFragment.this).navigate(action);
try {
final NavDirections action = HashTagFragmentDirections.actionToHashtag(hashtag);
NavHostFragment.findNavController(HashTagFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onHashtagClick: ", e);
}
}
@Override
public void onLocationClick(final Media media) {
final Location location = media.getLocation();
if (location == null) return;
final NavDirections action = HashTagFragmentDirections.actionGlobalLocationFragment(location.getPk());
NavHostFragment.findNavController(HashTagFragment.this).navigate(action);
try {
final NavDirections action = HashTagFragmentDirections.actionToLocation(location.getPk());
NavHostFragment.findNavController(HashTagFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onLocationClick: ", e);
}
}
@Override
@ -172,12 +177,16 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
@Override
public void onNameClick(final Media feedModel, final View profilePicView) {
navigateToProfile("@" + feedModel.getUser().getUsername());
final User user = feedModel.getUser();
if (user == null) return;
navigateToProfile("@" + user.getUsername());
}
@Override
public void onProfilePicClick(final Media feedModel, final View profilePicView) {
navigateToProfile("@" + feedModel.getUser().getUsername());
final User user = feedModel.getUser();
if (user == null) return;
navigateToProfile("@" + user.getUsername());
}
@Override
@ -191,8 +200,6 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
}
private void openPostDialog(@NonNull final Media feedModel,
final View profilePicView,
final View mainPostImage,
final int position) {
if (opening) return;
final User user = feedModel.getUser();
@ -200,24 +207,23 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (TextUtils.isEmpty(user.getUsername())) {
// this only happens for anons
opening = true;
graphQLRepository.fetchPost(feedModel.getCode(), CoroutineUtilsKt.getContinuation((media, throwable) -> {
final String code = feedModel.getCode();
if (code == null) return;
graphQLRepository.fetchPost(code, CoroutineUtilsKt.getContinuation((media, throwable) -> {
opening = false;
if (throwable != null) {
Log.e(TAG, "Error", throwable);
return;
}
if (media == null) return;
AppExecutors.INSTANCE.getMainThread().execute(() -> openPostDialog(media, profilePicView, mainPostImage, position));
AppExecutors.INSTANCE.getMainThread().execute(() -> openPostDialog(media, position));
}, Dispatchers.getIO()));
return;
}
opening = true;
final NavController navController = NavHostFragment.findNavController(HashTagFragment.this);
final Bundle bundle = new Bundle();
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, feedModel);
bundle.putInt(PostViewV2Fragment.ARG_SLIDER_POSITION, position);
try {
navController.navigate(R.id.action_global_post_view, bundle);
final NavDirections action = HashTagFragmentDirections.actionToPost(feedModel, position);
NavHostFragment.findNavController(HashTagFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "openPostDialog: ", e);
}
@ -280,7 +286,6 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
final String cookie = settingsHelper.getString(Constants.COOKIE);
isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) > 0;
tagsService = isLoggedIn ? TagsService.getInstance() : null;
storiesRepository = isLoggedIn ? StoriesRepository.Companion.getInstance() : null;
graphQLRepository = isLoggedIn ? null : GraphQLRepository.Companion.getInstance();
setHasOptionsMenu(true);
}
@ -309,7 +314,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
@Override
public void onRefresh() {
binding.posts.refresh();
// fetchStories();
// fetchStories();
}
@Override
@ -385,7 +390,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
}
setTitle();
setupPosts();
// fetchStories();
// fetchStories();
if (isLoggedIn) {
hashtagDetailsBinding.btnFollowTag.setVisibility(View.VISIBLE);
hashtagDetailsBinding.btnFollowTag.setText(hashtagModel.getFollowing() == FollowingType.FOLLOWING
@ -519,22 +524,23 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
);
hashtagDetailsBinding.mainHashtagImage.setImageURI("res:/" + R.drawable.ic_hashtag);
final String postCount = String.valueOf(hashtagModel.getMediaCount());
final SpannableStringBuilder span = new SpannableStringBuilder(getResources().getQuantityString(R.plurals.main_posts_count_inline,
hashtagModel.getMediaCount() > 2000000000L
? 2000000000
: Long.valueOf(hashtagModel.getMediaCount()).intValue(),
postCount));
final SpannableStringBuilder span = new SpannableStringBuilder(getResources().getQuantityString(
R.plurals.main_posts_count_inline,
hashtagModel.getMediaCount() > 2000000000L ? 2000000000
: Long.valueOf(hashtagModel.getMediaCount()).intValue(),
postCount)
);
span.setSpan(new RelativeSizeSpan(1.2f), 0, postCount.length(), 0);
span.setSpan(new StyleSpan(Typeface.BOLD), 0, postCount.length(), 0);
hashtagDetailsBinding.mainTagPostCount.setText(span);
hashtagDetailsBinding.mainTagPostCount.setVisibility(View.VISIBLE);
// hashtagDetailsBinding.mainHashtagImage.setOnClickListener(v -> {
// if (!hasStories) return;
// // show stories
// final NavDirections action = HashTagFragmentDirections
// .actionHashtagFragmentToStoryViewerFragment(StoryViewerOptions.forHashtag(hashtagModel.getName()));
// NavHostFragment.findNavController(this).navigate(action);
// });
// hashtagDetailsBinding.mainHashtagImage.setOnClickListener(v -> {
// if (!hasStories) return;
// // show stories
// final NavDirections action = HashTagFragmentDirections
// .actionHashtagFragmentToStoryViewerFragment(StoryViewerOptions.forHashtag(hashtagModel.getName()));
// NavHostFragment.findNavController(this).navigate(action);
// });
}
private void showSnackbar(final String message) {
@ -545,47 +551,24 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
.show();
}
// private void fetchStories() {
// if (!isLoggedIn) return;
// storiesFetching = true;
// storiesRepository.getStories(
// StoryViewerOptions.forHashtag(hashtagModel.getName()),
// CoroutineUtilsKt.getContinuation((storyModels, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
// if (throwable != null) {
// Log.e(TAG, "Error", throwable);
// storiesFetching = false;
// return;
// }
// if (storyModels != null && !storyModels.isEmpty()) {
// hashtagDetailsBinding.mainHashtagImage.setStoriesBorder(1);
// hasStories = true;
// } else {
// hasStories = false;
// }
// storiesFetching = false;
// }), Dispatchers.getIO())
// );
// }
private void setTitle() {
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
if (actionBar != null) {
// Log.d(TAG, "setting title: " + hashtag);
actionBar.setTitle('#' + hashtag);
// final Handler handler = new Handler();
// handler.postDelayed(() -> , 1000);
}
}
private void updateSwipeRefreshState() {
binding.swipeRefreshLayout.setRefreshing(binding.posts.isFetching() || storiesFetching);
binding.swipeRefreshLayout.setRefreshing(binding.posts.isFetching());
}
private void navigateToProfile(final String username) {
final NavController navController = NavHostFragment.findNavController(this);
final Bundle bundle = new Bundle();
bundle.putString("username", username);
navController.navigate(R.id.action_global_profileFragment, bundle);
try {
final NavDirections action = HashTagFragmentDirections.actionToProfile().setUsername(username);
NavHostFragment.findNavController(this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "navigateToProfile: ", e);
}
}
private void showPostsLayoutPreferences() {

View File

@ -10,6 +10,7 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
@ -19,7 +20,6 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import java.util.List;
import awais.instagrabber.R;
import awais.instagrabber.adapters.LikesAdapter;
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
import awais.instagrabber.databinding.FragmentLikesBinding;
@ -55,9 +55,12 @@ public final class LikesViewerFragment extends BottomSheetDialogFragment impleme
final Object tag = v.getTag();
if (tag instanceof User) {
User model = (User) tag;
final Bundle bundle = new Bundle();
bundle.putString("username", "@" + model.getUsername());
NavHostFragment.findNavController(LikesViewerFragment.this).navigate(R.id.action_global_profileFragment, bundle);
try {
final NavDirections action = LikesViewerFragmentDirections.actionToProfile().setUsername(model.getUsername());
NavHostFragment.findNavController(LikesViewerFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onSuccess: ", e);
}
}
});
binding.rvLikes.setAdapter(likesAdapter);
@ -84,9 +87,12 @@ public final class LikesViewerFragment extends BottomSheetDialogFragment impleme
final Object tag = v.getTag();
if (tag instanceof User) {
User model = (User) tag;
final Bundle bundle = new Bundle();
bundle.putString("username", "@" + model.getUsername());
NavHostFragment.findNavController(LikesViewerFragment.this).navigate(R.id.action_global_profileFragment, bundle);
try {
final NavDirections action = LikesViewerFragmentDirections.actionToProfile().setUsername(model.getUsername());
NavHostFragment.findNavController(LikesViewerFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onSuccess: ", e);
}
}
});
binding.rvLikes.setAdapter(likesAdapter);

View File

@ -3,7 +3,6 @@ package awais.instagrabber.fragments;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@ -25,7 +24,6 @@ import androidx.appcompat.app.ActionBar;
import androidx.constraintlayout.motion.widget.MotionLayout;
import androidx.constraintlayout.motion.widget.MotionScene;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.RecyclerView;
@ -50,7 +48,6 @@ import awais.instagrabber.db.repositories.FavoriteRepository;
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.models.enums.FavoriteType;
import awais.instagrabber.repositories.requests.StoryViewerOptions;
import awais.instagrabber.repositories.responses.Location;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User;
@ -76,7 +73,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
private FragmentLocationBinding binding;
private MotionLayout root;
private boolean shouldRefresh = true;
// private boolean hasStories = false;
// private boolean hasStories = false;
private boolean opening = false;
private long locationId;
private Location locationModel;
@ -130,12 +127,18 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
@Override
public void onCommentsClick(final Media feedModel) {
final NavDirections commentsAction = LocationFragmentDirections.actionGlobalCommentsViewerFragment(
feedModel.getCode(),
feedModel.getPk(),
feedModel.getUser().getPk()
);
NavHostFragment.findNavController(LocationFragment.this).navigate(commentsAction);
final User user = feedModel.getUser();
if (user == null) return;
try {
final NavDirections commentsAction = LocationFragmentDirections.actionToComments(
feedModel.getCode(),
feedModel.getPk(),
user.getPk()
);
NavHostFragment.findNavController(LocationFragment.this).navigate(commentsAction);
} catch (Exception e) {
Log.e(TAG, "onCommentsClick: ", e);
}
}
@Override
@ -147,13 +150,19 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
@Override
public void onHashtagClick(final String hashtag) {
final NavDirections action = LocationFragmentDirections.actionGlobalHashTagFragment(hashtag);
NavHostFragment.findNavController(LocationFragment.this).navigate(action);
try {
final NavDirections action = LocationFragmentDirections.actionToHashtag(hashtag);
NavHostFragment.findNavController(LocationFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onHashtagClick: ", e);
}
}
@Override
public void onLocationClick(final Media feedModel) {
final NavDirections action = LocationFragmentDirections.actionGlobalLocationFragment(feedModel.getLocation().getPk());
final Location location = feedModel.getLocation();
if (location == null) return;
final NavDirections action = LocationFragmentDirections.actionToLocation(location.getPk());
NavHostFragment.findNavController(LocationFragment.this).navigate(action);
}
@ -206,12 +215,9 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
return;
}
opening = true;
final NavController navController = NavHostFragment.findNavController(LocationFragment.this);
final Bundle bundle = new Bundle();
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, feedModel);
bundle.putInt(PostViewV2Fragment.ARG_SLIDER_POSITION, position);
try {
navController.navigate(R.id.action_global_post_view, bundle);
final NavDirections action = LocationFragmentDirections.actionToPost(feedModel, position);
NavHostFragment.findNavController(LocationFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "openPostDialog: ", e);
}
@ -305,7 +311,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
@Override
public void onRefresh() {
binding.posts.refresh();
// fetchStories();
// fetchStories();
}
@Override
@ -386,7 +392,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
}
setTitle();
setupPosts();
// fetchStories();
// fetchStories();
final long locationId = locationModel.getPk();
// binding.swipeRefreshLayout.setRefreshing(true);
locationDetailsBinding.mainLocationImage.setImageURI("res:/" + R.drawable.ic_location);
@ -531,14 +537,14 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
);
}), Dispatchers.getIO())
));
// locationDetailsBinding.mainLocationImage.setOnClickListener(v -> {
// if (hasStories) {
// // show stories
// final NavDirections action = LocationFragmentDirections
// .actionLocationFragmentToStoryViewerFragment(StoryViewerOptions.forLocation(locationId, locationModel.getName()));
// NavHostFragment.findNavController(this).navigate(action);
// }
// });
// locationDetailsBinding.mainLocationImage.setOnClickListener(v -> {
// if (hasStories) {
// // show stories
// final NavDirections action = LocationFragmentDirections
// .actionLocationFragmentToStoryViewerFragment(StoryViewerOptions.forLocation(locationId, locationModel.getName()));
// NavHostFragment.findNavController(this).navigate(action);
// }
// });
}
private void showSnackbar(final String message) {
@ -549,26 +555,26 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
.show();
}
// private void fetchStories() {
// if (isLoggedIn) {
// storiesFetching = true;
// storiesRepository.getStories(
// StoryViewerOptions.forLocation(locationId, locationModel.getName()),
// CoroutineUtilsKt.getContinuation((storyModels, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
// if (throwable != null) {
// Log.e(TAG, "Error", throwable);
// storiesFetching = false;
// return;
// }
// if (storyModels != null && !storyModels.isEmpty()) {
// locationDetailsBinding.mainLocationImage.setStoriesBorder(1);
// hasStories = true;
// }
// storiesFetching = false;
// }), Dispatchers.getIO())
// );
// }
// }
// private void fetchStories() {
// if (isLoggedIn) {
// storiesFetching = true;
// storiesRepository.getStories(
// StoryViewerOptions.forLocation(locationId, locationModel.getName()),
// CoroutineUtilsKt.getContinuation((storyModels, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
// if (throwable != null) {
// Log.e(TAG, "Error", throwable);
// storiesFetching = false;
// return;
// }
// if (storyModels != null && !storyModels.isEmpty()) {
// locationDetailsBinding.mainLocationImage.setStoriesBorder(1);
// hasStories = true;
// }
// storiesFetching = false;
// }), Dispatchers.getIO())
// );
// }
// }
private void setTitle() {
final ActionBar actionBar = fragmentActivity.getSupportActionBar();
@ -582,10 +588,12 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
}
private void navigateToProfile(final String username) {
final NavController navController = NavHostFragment.findNavController(this);
final Bundle bundle = new Bundle();
bundle.putString("username", username);
navController.navigate(R.id.action_global_profileFragment, bundle);
try {
final NavDirections action = LocationFragmentDirections.actionToProfile().setUsername(username);
NavHostFragment.findNavController(this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "navigateToProfile: ", e);
}
}
private void showPostsLayoutPreferences() {

View File

@ -20,7 +20,6 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationManagerCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.LinearLayoutManager;
@ -50,8 +49,6 @@ import awais.instagrabber.webservices.NewsService;
import awais.instagrabber.webservices.ServiceCallback;
import kotlinx.coroutines.Dispatchers;
import static awais.instagrabber.utils.Utils.settingsHelper;
public final class NotificationsViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "NotificationsViewer";
@ -98,10 +95,14 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
if (model.getType() == NotificationType.RESPONDED_STORY) {
final StoryViewerOptions options = StoryViewerOptions.forStory(
mediaId,
model.getArgs().getUsername());
final Bundle bundle = new Bundle();
bundle.putSerializable("options", options);
NavHostFragment.findNavController(NotificationsViewerFragment.this).navigate(R.id.action_notifications_to_story, bundle);
model.getArgs().getUsername()
);
try {
final NavDirections action = NotificationsViewerFragmentDirections.actionToStory(options);
NavHostFragment.findNavController(NotificationsViewerFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onPreviewClick: ", e);
}
} else {
final AlertDialog alertDialog = new AlertDialog.Builder(context)
.setCancelable(false)
@ -116,14 +117,13 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
return;
}
final NavController navController = NavHostFragment.findNavController(NotificationsViewerFragment.this);
final Bundle bundle = new Bundle();
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media);
try {
navController.navigate(R.id.action_global_post_view, bundle);
alertDialog.dismiss();
final NavDirections action = NotificationsViewerFragmentDirections.actionToPost(media, 0);
NavHostFragment.findNavController(NotificationsViewerFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onSuccess: ", e);
} finally {
alertDialog.dismiss();
}
}), Dispatchers.getIO())
);
@ -257,7 +257,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
type = fragmentArgs.getType();
targetId = fragmentArgs.getTargetId();
final Context context = getContext();
CookieUtils.setupCookies(settingsHelper.getString(Constants.COOKIE));
CookieUtils.setupCookies(Utils.settingsHelper.getString(Constants.COOKIE));
binding.swipeRefreshLayout.setOnRefreshListener(this);
notificationViewModel = new ViewModelProvider(this).get(NotificationViewModel.class);
final NotificationsAdapter adapter = new NotificationsAdapter(clickListener);
@ -288,7 +288,11 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
}
private void openProfile(final String username) {
final NavDirections action = NotificationsViewerFragmentDirections.actionGlobalProfileFragment("@" + username);
NavHostFragment.findNavController(this).navigate(action);
try {
final NavDirections action = NotificationsViewerFragmentDirections.actionToProfile().setUsername(username);
NavHostFragment.findNavController(this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "openProfile: ", e);
}
}
}

View File

@ -40,6 +40,7 @@ import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavBackStackEntry;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.RecyclerView;
import androidx.transition.TransitionManager;
@ -70,7 +71,6 @@ import java.util.List;
import java.util.Set;
import awais.instagrabber.R;
import awais.instagrabber.UserSearchNavGraphDirections;
import awais.instagrabber.activities.MainActivity;
import awais.instagrabber.adapters.SliderCallbackAdapter;
import awais.instagrabber.adapters.SliderItemsAdapter;
@ -103,9 +103,7 @@ import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
import awais.instagrabber.viewmodels.PostViewV2ViewModel;
import static awais.instagrabber.fragments.HashTagFragment.ARG_HASHTAG;
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_SHOWN_COUNT_TOOLTIP;
import static awais.instagrabber.utils.Utils.settingsHelper;
public class PostViewV2Fragment extends Fragment implements EditTextDialogFragment.EditTextDialogFragmentCallback {
private static final String TAG = "PostViewV2Fragment";
@ -217,7 +215,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
public void onPause() {
super.onPause();
// wasPaused = true;
if (settingsHelper.getBoolean(PreferenceKeys.PLAY_IN_BACKGROUND)) return;
if (Utils.settingsHelper.getBoolean(PreferenceKeys.PLAY_IN_BACKGROUND)) return;
final Media media = viewModel.getMedia();
if (media.getType() == null) return;
switch (media.getType()) {
@ -333,7 +331,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
viewModel.getLikeCount().observe(getViewLifecycleOwner(), count -> {
bottom.likesCount.setNumber(getSafeCount(count));
binding.getRoot().postDelayed(() -> bottom.likesCount.setAnimateChanges(true), 1000);
if (count > 1000 && !settingsHelper.getBoolean(PREF_SHOWN_COUNT_TOOLTIP)) {
if (count > 1000 && !Utils.settingsHelper.getBoolean(PREF_SHOWN_COUNT_TOOLTIP)) {
binding.getRoot().postDelayed(this::showCountTooltip, 1000);
}
});
@ -392,7 +390,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
.setDismissWhenOverlayClicked(false)
.build();
balloon.showAlignBottom(bottom.likesCount);
settingsHelper.putBoolean(PREF_SHOWN_COUNT_TOOLTIP, true);
Utils.settingsHelper.putBoolean(PREF_SHOWN_COUNT_TOOLTIP, true);
balloon.setOnBalloonOutsideTouchListener((view, motionEvent) -> {
if (rect.contains((int) motionEvent.getRawX(), (int) motionEvent.getRawY())) {
bottom.likesCount.setShowAbbreviation(false);
@ -431,12 +429,9 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
if (user == null) return;
final NavController navController = getNavController();
if (navController == null) return;
final Bundle bundle = new Bundle();
bundle.putString("shortCode", media.getCode());
bundle.putString("postId", media.getPk());
bundle.putLong("postUserId", user.getPk());
try {
navController.navigate(R.id.action_global_commentsViewerFragment, bundle);
final NavDirections action = PostViewV2FragmentDirections.actionToComments(media.getCode(), media.getPk(), user.getPk());
navController.navigate(action);
} catch (Exception e) {
Log.e(TAG, "setupComment: ", e);
}
@ -445,9 +440,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
}
private void setupDownload() {
bottom.download.setOnClickListener(v -> {
DownloadUtils.showDownloadDialog(context, viewModel.getMedia(), sliderPosition, bottom.download);
});
bottom.download.setOnClickListener(v -> DownloadUtils.showDownloadDialog(context, viewModel.getMedia(), sliderPosition, bottom.download));
TooltipCompat.setTooltipText(bottom.download, getString(R.string.action_download));
}
@ -470,10 +463,12 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
bottom.like.setOnLongClickListener(v -> {
final NavController navController = getNavController();
if (navController != null && viewModel.isLoggedIn()) {
final Bundle bundle = new Bundle();
bundle.putString("postId", viewModel.getMedia().getPk());
bundle.putBoolean("isComment", false);
navController.navigate(R.id.action_global_likesViewerFragment, bundle);
try {
final NavDirections action = PostViewV2FragmentDirections.actionToLikes(viewModel.getMedia().getPk(), false);
navController.navigate(action);
} catch (Exception e) {
Log.e(TAG, "setupLike: ", e);
}
return true;
}
return true;
@ -543,11 +538,14 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
handleSaveUnsaveResourceLiveData(viewModel.toggleSave());
});
bottom.save.setOnLongClickListener(v -> {
final NavController navController = NavHostFragment.findNavController(this);
final Bundle bundle = new Bundle();
bundle.putBoolean("isSaving", true);
navController.navigate(R.id.action_global_savedCollectionsFragment, bundle);
return true;
try {
final NavDirections action = PostViewV2FragmentDirections.actionToSavedCollections().setIsSaving(true);
NavHostFragment.findNavController(this).navigate(action);
return true;
} catch (Exception e) {
Log.e(TAG, "setupSave: ", e);
}
return false;
});
}
@ -668,11 +666,13 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
}
final String postCaption = caption.getText();
bottom.caption.addOnHashtagListener(autoLinkItem -> {
final NavController navController = NavHostFragment.findNavController(this);
final Bundle bundle = new Bundle();
final String originalText = autoLinkItem.getOriginalText().trim();
bundle.putString(ARG_HASHTAG, originalText);
navController.navigate(R.id.action_global_hashTagFragment, bundle);
try {
final String originalText = autoLinkItem.getOriginalText().trim();
final NavDirections action = PostViewV2FragmentDirections.actionToHashtag(originalText);
NavHostFragment.findNavController(this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "setupCaption: ", e);
}
});
bottom.caption.addOnMentionClickListener(autoLinkItem -> {
final String originalText = autoLinkItem.getOriginalText().trim();
@ -701,7 +701,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
case ERROR:
bottom.translate.setEnabled(true);
String message = resource.message;
if (TextUtils.isEmpty(resource.message)) {
if (TextUtils.isEmpty(message)) {
message = getString(R.string.downloader_unknown_error);
}
final Snackbar snackbar = Snackbar.make(binding.getRoot(), message, Snackbar.LENGTH_INDEFINITE);
@ -725,11 +725,14 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
binding.location.setText(locationName);
binding.location.setVisibility(View.VISIBLE);
binding.location.setOnClickListener(v -> {
final NavController navController = getNavController();
if (navController == null) return;
final Bundle bundle = new Bundle();
bundle.putLong("locationId", location.getPk());
navController.navigate(R.id.action_global_locationFragment, bundle);
try {
final NavController navController = getNavController();
if (navController == null) return;
final NavDirections action = PostViewV2FragmentDirections.actionToLocation(location.getPk());
navController.navigate(action);
} catch (Exception e) {
Log.e(TAG, "setupLocation: ", e);
}
});
}
@ -755,16 +758,15 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
popupMenu.setOnMenuItemClickListener(item -> {
final int itemId = item.getItemId();
if (itemId == R.id.share_dm) {
final UserSearchNavGraphDirections.ActionGlobalUserSearch actionGlobalUserSearch = UserSearchFragmentDirections
.actionGlobalUserSearch()
.setTitle(getString(R.string.share))
.setActionLabel(getString(R.string.send))
.setShowGroups(true)
.setMultiple(true)
.setSearchMode(UserSearchFragment.SearchMode.RAVEN);
final NavController navController = NavHostFragment.findNavController(PostViewV2Fragment.this);
try {
navController.navigate(actionGlobalUserSearch);
final NavDirections actionGlobalUserSearch = PostViewV2FragmentDirections
.actionToUserSearch()
.setTitle(getString(R.string.share))
.setActionLabel(getString(R.string.send))
.setShowGroups(true)
.setMultiple(true)
.setSearchMode(UserSearchMode.RAVEN);
NavHostFragment.findNavController(this).navigate(actionGlobalUserSearch);
} catch (Exception e) {
Log.e(TAG, "setupShare: ", e);
}
@ -1087,7 +1089,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
// gestureDetector.onTouchEvent(event);
// return true;
// });
final float vol = settingsHelper.getBoolean(PreferenceKeys.MUTED_VIDEOS) ? 0f : 1f;
final float vol = Utils.settingsHelper.getBoolean(PreferenceKeys.MUTED_VIDEOS) ? 0f : 1f;
final VideoPlayerViewHelper.VideoPlayerCallback videoPlayerCallback = new VideoPlayerCallbackAdapter() {
@Override
public void onThumbnailLoaded() {
@ -1423,9 +1425,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
final CollapsingToolbarLayout appbarLayout = activity.getCollapsingToolbarView();
appbarLayout.setVisibility(View.GONE);
final Toolbar toolbar = activity.getToolbar();
if (toolbar != null) {
toolbar.setVisibility(View.GONE);
}
toolbar.setVisibility(View.GONE);
binding.getRoot().setPadding(binding.getRoot().getPaddingLeft(),
binding.getRoot().getPaddingTop(),
binding.getRoot().getPaddingRight(),
@ -1448,9 +1448,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
final CollapsingToolbarLayout appbarLayout = activity.getCollapsingToolbarView();
appbarLayout.setVisibility(View.VISIBLE);
final Toolbar toolbar = activity.getToolbar();
if (toolbar != null) {
toolbar.setVisibility(View.VISIBLE);
}
toolbar.setVisibility(View.VISIBLE);
final Context context = getContext();
if (context == null) return;
binding.getRoot().setPadding(binding.getRoot().getPaddingLeft(),
@ -1465,9 +1463,8 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
private void navigateToProfile(final String username) {
final NavController navController = getNavController();
if (navController == null) return;
final Bundle bundle = new Bundle();
bundle.putString("username", username);
navController.navigate(R.id.action_global_profileFragment, bundle);
final NavDirections actionToProfile = PostViewV2FragmentDirections.actionToProfile().setUsername(username);
navController.navigate(actionToProfile);
}
@Nullable

View File

@ -21,6 +21,7 @@ import androidx.lifecycle.SavedStateHandle;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavBackStackEntry;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.FragmentNavigator;
import androidx.navigation.fragment.NavHostFragment;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@ -151,8 +152,8 @@ public class SavedCollectionsFragment extends Fragment implements SwipeRefreshLa
try {
final FragmentNavigator.Extras.Builder builder = new FragmentNavigator.Extras.Builder()
.addSharedElement(cover, "collection-" + topicCluster.getCollectionId());
final SavedCollectionsFragmentDirections.ActionSavedCollectionsFragmentToCollectionPostsFragment action = SavedCollectionsFragmentDirections
.actionSavedCollectionsFragmentToCollectionPostsFragment(topicCluster, titleColor, backgroundColor);
final NavDirections action = SavedCollectionsFragmentDirections
.actionToCollectionPosts(topicCluster, titleColor, backgroundColor);
navController.navigate(action, builder.build());
} catch (Exception e) {
Log.e(TAG, "setupTopics: ", e);

View File

@ -1,7 +1,6 @@
package awais.instagrabber.fragments;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
@ -20,7 +19,6 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@ -38,7 +36,9 @@ import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
import awais.instagrabber.fragments.main.ProfileFragmentDirections;
import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.models.enums.PostItemType;
import awais.instagrabber.repositories.responses.Location;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.DownloadUtils;
@ -90,22 +90,28 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
private final FeedAdapterV2.FeedItemCallback feedItemCallback = new FeedAdapterV2.FeedItemCallback() {
@Override
public void onPostClick(final Media feedModel, final View profilePicView, final View mainPostImage) {
openPostDialog(feedModel, profilePicView, mainPostImage, -1);
openPostDialog(feedModel, -1);
}
@Override
public void onSliderClick(final Media feedModel, final int position) {
openPostDialog(feedModel, null, null, position);
openPostDialog(feedModel, position);
}
@Override
public void onCommentsClick(final Media feedModel) {
final NavDirections commentsAction = ProfileFragmentDirections.actionGlobalCommentsViewerFragment(
feedModel.getCode(),
feedModel.getPk(),
feedModel.getUser().getPk()
);
NavHostFragment.findNavController(SavedViewerFragment.this).navigate(commentsAction);
final User user = feedModel.getUser();
if (user == null) return;
try {
final NavDirections commentsAction = ProfileFragmentDirections.actionToComments(
feedModel.getCode(),
feedModel.getPk(),
user.getPk()
);
NavHostFragment.findNavController(SavedViewerFragment.this).navigate(commentsAction);
} catch (Exception e) {
Log.e(TAG, "onCommentsClick: ", e);
}
}
@Override
@ -117,14 +123,24 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
@Override
public void onHashtagClick(final String hashtag) {
final NavDirections action = ProfileFragmentDirections.actionGlobalHashTagFragment(hashtag);
NavHostFragment.findNavController(SavedViewerFragment.this).navigate(action);
try {
final NavDirections action = ProfileFragmentDirections.actionToHashtag(hashtag);
NavHostFragment.findNavController(SavedViewerFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onHashtagClick: ", e);
}
}
@Override
public void onLocationClick(final Media feedModel) {
final NavDirections action = ProfileFragmentDirections.actionGlobalLocationFragment(feedModel.getLocation().getPk());
NavHostFragment.findNavController(SavedViewerFragment.this).navigate(action);
final Location location = feedModel.getLocation();
if (location == null) return;
try {
final NavDirections action = ProfileFragmentDirections.actionToLocation(location.getPk());
NavHostFragment.findNavController(SavedViewerFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onLocationClick: ", e);
}
}
@Override
@ -134,12 +150,16 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
@Override
public void onNameClick(final Media feedModel, final View profilePicView) {
navigateToProfile("@" + feedModel.getUser().getUsername());
final User user = feedModel.getUser();
if (user == null) return;
navigateToProfile("@" + user.getUsername());
}
@Override
public void onProfilePicClick(final Media feedModel, final View profilePicView) {
navigateToProfile("@" + feedModel.getUser().getUsername());
final User user = feedModel.getUser();
if (user == null) return;
navigateToProfile("@" + user.getUsername());
}
@Override
@ -152,16 +172,10 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
Utils.openEmailAddress(getContext(), emailId);
}
private void openPostDialog(final Media feedModel,
final View profilePicView,
final View mainPostImage,
final int position) {
final NavController navController = NavHostFragment.findNavController(SavedViewerFragment.this);
final Bundle bundle = new Bundle();
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, feedModel);
bundle.putInt(PostViewV2Fragment.ARG_SLIDER_POSITION, position);
private void openPostDialog(final Media feedModel, final int position) {
try {
navController.navigate(R.id.action_global_post_view, bundle);
final NavDirections action = SavedViewerFragmentDirections.actionToPost(feedModel, position);
NavHostFragment.findNavController(SavedViewerFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "openPostDialog: ", e);
}
@ -317,10 +331,12 @@ public final class SavedViewerFragment extends Fragment implements SwipeRefreshL
}
private void navigateToProfile(final String username) {
final NavController navController = NavHostFragment.findNavController(this);
final Bundle bundle = new Bundle();
bundle.putString("username", username);
navController.navigate(R.id.action_global_profileFragment, bundle);
try {
final NavDirections action = SavedViewerFragmentDirections.actionToProfile().setUsername(username);
NavHostFragment.findNavController(this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "navigateToProfile: ", e);
}
}
private void showPostsLayoutPreferences() {

View File

@ -37,7 +37,6 @@ import awais.instagrabber.adapters.HighlightStoriesListAdapter;
import awais.instagrabber.adapters.HighlightStoriesListAdapter.OnHighlightStoryClickListener;
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
import awais.instagrabber.databinding.FragmentStoryListViewerBinding;
import awais.instagrabber.fragments.settings.MorePreferencesFragmentDirections;
import awais.instagrabber.repositories.requests.StoryViewerOptions;
import awais.instagrabber.repositories.responses.stories.ArchiveResponse;
import awais.instagrabber.repositories.responses.stories.Story;
@ -74,9 +73,12 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
if (feedStoryModels == null) return;
final int position = Iterables.indexOf(feedStoryModels, feedStoryModel -> feedStoryModel != null
&& Objects.equals(feedStoryModel.getId(), model.getId()));
final NavDirections action = StoryListViewerFragmentDirections
.actionStoryListFragmentToStoryViewerFragment(StoryViewerOptions.forFeedStoryPosition(position));
NavHostFragment.findNavController(StoryListViewerFragment.this).navigate(action);
try {
final NavDirections action = StoryListViewerFragmentDirections.actionToStory(StoryViewerOptions.forFeedStoryPosition(position));
NavHostFragment.findNavController(StoryListViewerFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onFeedStoryClick: ", e);
}
}
@Override
@ -89,9 +91,12 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
@Override
public void onHighlightClick(final Story model, final int position) {
if (model == null) return;
final NavDirections action = StoryListViewerFragmentDirections
.actionStoryListFragmentToStoryViewerFragment(StoryViewerOptions.forStoryArchive(position));
NavHostFragment.findNavController(StoryListViewerFragment.this).navigate(action);
try {
final NavDirections action = StoryListViewerFragmentDirections.actionToStory(StoryViewerOptions.forStoryArchive(position));
NavHostFragment.findNavController(StoryListViewerFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onHighlightClick: ", e);
}
}
@Override
@ -271,8 +276,11 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
}
private void openProfile(final String username) {
final NavDirections action = MorePreferencesFragmentDirections
.actionGlobalProfileFragment("@" + username);
NavHostFragment.findNavController(this).navigate(action);
try {
final NavDirections action = StoryListViewerFragmentDirections.actionToProfile().setUsername(username);
NavHostFragment.findNavController(this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "openProfile: ", e);
}
}
}

View File

@ -58,13 +58,13 @@ import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.stream.Collectors;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import awais.instagrabber.BuildConfig;
import awais.instagrabber.R;
@ -78,7 +78,16 @@ import awais.instagrabber.models.enums.MediaItemType;
import awais.instagrabber.repositories.requests.StoryViewerOptions;
import awais.instagrabber.repositories.requests.StoryViewerOptions.Type;
import awais.instagrabber.repositories.requests.directmessages.ThreadIdsOrUserIds;
import awais.instagrabber.repositories.responses.stories.*;
import awais.instagrabber.repositories.responses.stories.Broadcast;
import awais.instagrabber.repositories.responses.stories.PollSticker;
import awais.instagrabber.repositories.responses.stories.QuestionSticker;
import awais.instagrabber.repositories.responses.stories.QuizSticker;
import awais.instagrabber.repositories.responses.stories.SliderSticker;
import awais.instagrabber.repositories.responses.stories.Story;
import awais.instagrabber.repositories.responses.stories.StoryAppAttribution;
import awais.instagrabber.repositories.responses.stories.StoryCta;
import awais.instagrabber.repositories.responses.stories.StoryMedia;
import awais.instagrabber.repositories.responses.stories.Tally;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
@ -459,7 +468,8 @@ public class StoryViewerFragment extends Fragment {
final Bundle bundle = new Bundle();
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media);
try {
navController.navigate(R.id.action_global_post_view, bundle);
final NavDirections action = StoryViewerFragmentDirections.actionToPost(media, 0);
navController.navigate(action);
alertDialog.dismiss();
} catch (Exception e) {
Log.e(TAG, "openPostDialog: ", e);
@ -1243,14 +1253,13 @@ public class StoryViewerFragment extends Fragment {
}
final char t = username.charAt(0);
if (t == '@') {
final NavDirections action = HashTagFragmentDirections.actionGlobalProfileFragment(username);
final NavDirections action = HashTagFragmentDirections.actionToProfile().setUsername(username);
NavHostFragment.findNavController(this).navigate(action);
} else if (t == '#') {
final NavDirections action = HashTagFragmentDirections.actionGlobalHashTagFragment(username.substring(1));
final NavDirections action = HashTagFragmentDirections.actionToHashtag(username.substring(1));
NavHostFragment.findNavController(this).navigate(action);
} else {
final NavDirections action = ProfileFragmentDirections
.actionGlobalLocationFragment(Long.parseLong(username.split(" \\(")[1].replace(")", "")));
final NavDirections action = ProfileFragmentDirections.actionToLocation(Long.parseLong(username.split(" \\(")[1].replace(")", "")));
NavHostFragment.findNavController(this).navigate(action);
}
}

View File

@ -2,7 +2,6 @@ package awais.instagrabber.fragments;
import android.animation.ArgbEvaluator;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Animatable;
@ -26,7 +25,6 @@ import androidx.annotation.Nullable;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.graphics.ColorUtils;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@ -49,9 +47,10 @@ import awais.instagrabber.asyncs.DiscoverPostFetchService;
import awais.instagrabber.customviews.PrimaryActionModeCallback;
import awais.instagrabber.databinding.FragmentTopicPostsBinding;
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
import awais.instagrabber.fragments.main.DiscoverFragmentDirections;
import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.repositories.responses.Location;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.discover.TopicCluster;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.DownloadUtils;
@ -101,20 +100,22 @@ public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.O
private final FeedAdapterV2.FeedItemCallback feedItemCallback = new FeedAdapterV2.FeedItemCallback() {
@Override
public void onPostClick(final Media feedModel, final View profilePicView, final View mainPostImage) {
openPostDialog(feedModel, profilePicView, mainPostImage, -1);
openPostDialog(feedModel, -1);
}
@Override
public void onSliderClick(final Media feedModel, final int position) {
openPostDialog(feedModel, null, null, position);
openPostDialog(feedModel, position);
}
@Override
public void onCommentsClick(final Media feedModel) {
final NavDirections commentsAction = DiscoverFragmentDirections.actionGlobalCommentsViewerFragment(
final User user = feedModel.getUser();
if (user == null) return;
final NavDirections commentsAction = TopicPostsFragmentDirections.actionToComments(
feedModel.getCode(),
feedModel.getPk(),
feedModel.getUser().getPk()
user.getPk()
);
NavHostFragment.findNavController(TopicPostsFragment.this).navigate(commentsAction);
}
@ -128,13 +129,15 @@ public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.O
@Override
public void onHashtagClick(final String hashtag) {
final NavDirections action = DiscoverFragmentDirections.actionGlobalHashTagFragment(hashtag);
final NavDirections action = TopicPostsFragmentDirections.actionToHashtag(hashtag);
NavHostFragment.findNavController(TopicPostsFragment.this).navigate(action);
}
@Override
public void onLocationClick(final Media feedModel) {
final NavDirections action = DiscoverFragmentDirections.actionGlobalLocationFragment(feedModel.getLocation().getPk());
final Location location = feedModel.getLocation();
if (location == null) return;
final NavDirections action = TopicPostsFragmentDirections.actionToLocation(location.getPk());
NavHostFragment.findNavController(TopicPostsFragment.this).navigate(action);
}
@ -150,7 +153,9 @@ public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.O
@Override
public void onProfilePicClick(final Media feedModel, final View profilePicView) {
navigateToProfile("@" + feedModel.getUser().getUsername());
final User user = feedModel.getUser();
if (user == null) return;
navigateToProfile("@" + user.getUsername());
}
@Override
@ -163,16 +168,10 @@ public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.O
Utils.openEmailAddress(getContext(), emailId);
}
private void openPostDialog(final Media feedModel,
final View profilePicView,
final View mainPostImage,
final int position) {
final NavController navController = NavHostFragment.findNavController(TopicPostsFragment.this);
final Bundle bundle = new Bundle();
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, feedModel);
bundle.putInt(PostViewV2Fragment.ARG_SLIDER_POSITION, position);
private void openPostDialog(final Media feedModel, final int position) {
try {
navController.navigate(R.id.action_global_post_view, bundle);
final NavDirections action = TopicPostsFragmentDirections.actionGlobalPost(feedModel, position);
NavHostFragment.findNavController(TopicPostsFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "openPostDialog: ", e);
}
@ -218,11 +217,14 @@ public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.O
public void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fragmentActivity = (MainActivity) requireActivity();
final TransitionSet transitionSet = new TransitionSet();
transitionSet.addTransition(new ChangeBounds())
.addTransition(TransitionInflater.from(getContext()).inflateTransition(android.R.transition.move))
.setDuration(200);
setSharedElementEnterTransition(transitionSet);
final Context context = getContext();
if (context != null) {
final TransitionSet transitionSet = new TransitionSet();
transitionSet.addTransition(new ChangeBounds())
.addTransition(TransitionInflater.from(context).inflateTransition(android.R.transition.move))
.setDuration(200);
setSharedElementEnterTransition(transitionSet);
}
postponeEnterTransition();
setHasOptionsMenu(true);
}
@ -379,10 +381,12 @@ public class TopicPostsFragment extends Fragment implements SwipeRefreshLayout.O
}
private void navigateToProfile(final String username) {
final NavController navController = NavHostFragment.findNavController(this);
final Bundle bundle = new Bundle();
bundle.putString("username", username);
navController.navigate(R.id.action_global_profileFragment, bundle);
try {
final NavDirections action = TopicPostsFragmentDirections.actionToProfile().setUsername(username);
NavHostFragment.findNavController(this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "navigateToProfile: ", e);
}
}
private void showPostsLayoutPreferences() {

View File

@ -309,20 +309,4 @@ public class UserSearchFragment extends Fragment {
}
return null;
}
public enum SearchMode {
USER_SEARCH("user_name"),
RAVEN("raven"),
RESHARE("reshare");
private final String name;
SearchMode(final String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}

View File

@ -0,0 +1,7 @@
package awais.instagrabber.fragments
enum class UserSearchMode(name: String) {
USER_SEARCH("user_name"),
RAVEN("raven"),
RESHARE("reshare");
}

View File

@ -205,7 +205,7 @@ public final class CommentsViewerFragment extends BottomSheetDialogFragment {
viewModel,
(comment, focusInput) -> {
if (comment == null) return null;
final RepliesFragment repliesFragment = RepliesFragment.newInstance(comment, focusInput == null ? false : focusInput);
final RepliesFragment repliesFragment = RepliesFragment.newInstance(comment, focusInput != null && focusInput);
getChildFragmentManager().beginTransaction()
.setCustomAnimations(R.anim.slide_left, R.anim.slide_right, 0, R.anim.slide_right)
.add(R.id.replies_container_view, repliesFragment)

View File

@ -1,7 +1,7 @@
package awais.instagrabber.fragments.comments;
import android.content.Context;
import android.os.Bundle;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.util.Log;
import android.view.View;
@ -45,7 +45,10 @@ public final class Helper {
@NonNull final RecyclerView.OnScrollListener lazyLoader) {
list.setLayoutManager(layoutManager);
final DividerItemDecoration itemDecoration = new DividerItemDecoration(context, LinearLayoutManager.VERTICAL);
itemDecoration.setDrawable(ContextCompat.getDrawable(context, R.drawable.pref_list_divider_material));
final Drawable drawable = ContextCompat.getDrawable(context, R.drawable.pref_list_divider_material);
if (drawable != null) {
itemDecoration.setDrawable(drawable);
}
list.addItemDecoration(itemDecoration);
list.addOnScrollListener(lazyLoader);
}
@ -68,8 +71,7 @@ public final class Helper {
public void onHashtagClick(final String hashtag) {
try {
if (navController == null) return;
final NavDirections action = CommentsViewerFragmentDirections.actionGlobalHashTagFragment(hashtag);
navController.navigate(action);
navController.navigate(CommentsViewerFragmentDirections.actionToHashtag(hashtag));
} catch (Exception e) {
Log.e(TAG, "onHashtagClick: ", e);
}
@ -123,12 +125,10 @@ public final class Helper {
@Override
public void onViewLikes(final Comment comment) {
if (navController == null) return;
try {
final Bundle bundle = new Bundle();
bundle.putString("postId", comment.getPk());
bundle.putBoolean("isComment", true);
navController.navigate(R.id.action_global_likesViewerFragment, bundle);
if (navController == null) return;
final NavDirections actionToLikes = CommentsViewerFragmentDirections.actionToLikes(comment.getPk(), true);
navController.navigate(actionToLikes);
} catch (Exception e) {
Log.e(TAG, "onViewLikes: ", e);
}
@ -144,10 +144,7 @@ public final class Helper {
Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
return;
}
String username = "";
if (comment.getUser() != null) {
username = comment.getUser().getUsername();
}
final String username = comment.getUser().getUsername();
new MaterialAlertDialogBuilder(context)
.setTitle(username)
.setMessage(result)
@ -192,9 +189,9 @@ public final class Helper {
private static void openProfile(final NavController navController,
@NonNull final String username) {
if (navController == null) return;
try {
final NavDirections action = CommentsViewerFragmentDirections.actionGlobalProfileFragment(username);
if (navController == null) return;
final NavDirections action = CommentsViewerFragmentDirections.actionToProfile().setUsername(username);
navController.navigate(action);
} catch (Exception e) {
Log.e(TAG, "openProfile: ", e);

View File

@ -185,18 +185,22 @@ public class RepliesFragment extends Fragment {
private void setupAdapter(final long currentUserId) {
final Context context = getContext();
if (context == null) return;
commentsAdapter = new CommentsAdapter(currentUserId,
true,
Helper.getCommentCallback(context,
getViewLifecycleOwner(),
getNavController(),
viewModel,
(comment, focusInput) -> {
viewModel.setReplyTo(comment);
binding.commentText.setText(String.format("@%s ", comment.getUser().getUsername()));
if (focusInput) Utils.showKeyboard(binding.commentText);
return null;
}));
commentsAdapter = new CommentsAdapter(
currentUserId,
true,
Helper.getCommentCallback(
context,
getViewLifecycleOwner(),
getNavController(),
viewModel,
(comment, focusInput) -> {
viewModel.setReplyTo(comment);
binding.commentText.setText(String.format("@%s ", comment.getUser().getUsername()));
if (focusInput) Utils.showKeyboard(binding.commentText);
return null;
}
)
);
binding.comments.setAdapter(commentsAdapter);
final Resource<List<Comment>> listResource = viewModel.getReplyList().getValue();
commentsAdapter.submitList(listResource != null ? listResource.data : Collections.emptyList());

View File

@ -11,7 +11,7 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
import awais.instagrabber.R
@ -103,9 +103,9 @@ class DirectMessageInboxFragment : Fragment(), OnRefreshListener {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.pending_requests) {
val directions = DirectMessageInboxFragmentDirections.actionInboxToPendingInbox()
try {
NavHostFragment.findNavController(this).navigate(directions)
val directions = DirectMessageInboxFragmentDirections.actionToPendingInbox()
findNavController().navigate(directions)
} catch (e: Exception) {
Log.e(TAG, "onOptionsItemSelected: ", e)
}
@ -210,9 +210,9 @@ class DirectMessageInboxFragment : Fragment(), OnRefreshListener {
if (navigating || threadId.isNullOrBlank() || threadTitle.isNullOrBlank()) return@DirectMessageInboxAdapter
navigating = true
if (isAdded) {
val directions = DirectMessageInboxFragmentDirections.actionInboxToThread(threadId, threadTitle)
try {
NavHostFragment.findNavController(this).navigate(directions)
val directions = DirectMessageInboxFragmentDirections.actionToThread(threadId, threadTitle)
findNavController().navigate(directions)
} catch (e: Exception) {
Log.e(TAG, "init: ", e)
}

View File

@ -11,8 +11,8 @@ import androidx.fragment.app.activityViewModels
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import awais.instagrabber.ProfileNavGraphDirections
import awais.instagrabber.R
import awais.instagrabber.activities.MainActivity
import awais.instagrabber.adapters.DirectPendingUsersAdapter
@ -25,13 +25,11 @@ import awais.instagrabber.dialogs.ConfirmDialogFragment
import awais.instagrabber.dialogs.ConfirmDialogFragment.ConfirmDialogFragmentCallback
import awais.instagrabber.dialogs.MultiOptionDialogFragment
import awais.instagrabber.dialogs.MultiOptionDialogFragment.MultiOptionDialogSingleCallback
import awais.instagrabber.fragments.UserSearchFragment
import awais.instagrabber.fragments.UserSearchFragmentDirections
import awais.instagrabber.fragments.UserSearchMode
import awais.instagrabber.models.Resource
import awais.instagrabber.repositories.responses.User
import awais.instagrabber.repositories.responses.directmessages.DirectThreadParticipantRequestsResponse
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient
import awais.instagrabber.utils.TextUtils.isEmpty
import awais.instagrabber.utils.Utils
import awais.instagrabber.utils.extensions.TAG
import awais.instagrabber.viewmodels.AppStateViewModel
@ -203,19 +201,22 @@ class DirectMessageSettingsFragment : Fragment(), ConfirmDialogFragmentCallback
}
binding.addMembers.setOnClickListener {
if (!isAdded) return@setOnClickListener
val navController = NavHostFragment.findNavController(this)
val currentDestination = navController.currentDestination ?: return@setOnClickListener
if (currentDestination.id != R.id.directMessagesSettingsFragment) return@setOnClickListener
val users = viewModel.getUsers().value
val currentUserIds: LongArray = users?.asSequence()?.map { obj: User -> obj.pk }?.sorted()?.toList()?.toLongArray() ?: LongArray(0)
val actionGlobalUserSearch = UserSearchFragmentDirections
.actionGlobalUserSearch()
.setTitle(getString(R.string.add_members))
.setActionLabel(getString(R.string.add))
.setHideUserIds(currentUserIds)
.setSearchMode(UserSearchFragment.SearchMode.RAVEN)
.setMultiple(true)
navController.navigate(actionGlobalUserSearch)
try {
val navController = findNavController()
if (navController.currentDestination?.id != R.id.directMessagesSettingsFragment) return@setOnClickListener
val users = viewModel.getUsers().value ?: return@setOnClickListener
val currentUserIds = users.asSequence().map(User::pk).sorted().toList().toLongArray()
val actionGlobalUserSearch = DirectMessageSettingsFragmentDirections.actionToUserSearch().apply {
title = getString(R.string.add_members)
actionLabel = getString(R.string.add)
hideUserIds = currentUserIds
searchMode = UserSearchMode.RAVEN
multiple = true
}
navController.navigate(actionGlobalUserSearch)
} catch (e: Exception) {
Log.e(TAG, "setupSettings: ", e)
}
}
binding.muteMentionsLabel.setOnClickListener { binding.muteMentions.toggle() }
binding.muteMentions.setOnCheckedChangeListener { buttonView: CompoundButton, isChecked: Boolean ->
@ -300,10 +301,13 @@ class DirectMessageSettingsFragment : Fragment(), ConfirmDialogFragmentCallback
Utils.openURL(context, "https://facebook.com/" + user.interopMessagingUserFbid)
return@DirectUsersAdapter
}
if (isEmpty(user.username)) return@DirectUsersAdapter
val directions = ProfileNavGraphDirections
.actionGlobalProfileFragment("@" + user.username)
NavHostFragment.findNavController(this).navigate(directions)
if (user.username.isBlank()) return@DirectUsersAdapter
try {
val directions = DirectMessageSettingsFragmentDirections.actionToProfile().apply { this.username = user.username }
findNavController().navigate(directions)
} catch (e: Exception) {
Log.e(TAG, "setupMembers: ", e)
}
},
{ _: Int, user: User? ->
val options = viewModel.createUserOptions(user)
@ -339,9 +343,12 @@ class DirectMessageSettingsFragment : Fragment(), ConfirmDialogFragmentCallback
binding.pendingMembers.layoutManager = LinearLayoutManager(context)
pendingUsersAdapter = DirectPendingUsersAdapter(object : PendingUserCallback {
override fun onClick(position: Int, pendingUser: PendingUser) {
val directions = ProfileNavGraphDirections
.actionGlobalProfileFragment("@" + pendingUser.user.username)
NavHostFragment.findNavController(this@DirectMessageSettingsFragment).navigate(directions)
try {
val directions = DirectMessageSettingsFragmentDirections.actionToProfile().apply { this.username = pendingUser.user.username }
findNavController().navigate(directions)
} catch (e: Exception) {
Log.e(TAG, "onClick: ", e)
}
}
override fun onApprove(position: Int, pendingUser: PendingUser) {
@ -420,7 +427,7 @@ class DirectMessageSettingsFragment : Fragment(), ConfirmDialogFragmentCallback
if (resource == null) return@observe
when (resource.status) {
Resource.Status.SUCCESS -> {
val directions = DirectMessageSettingsFragmentDirections.actionSettingsToInbox()
val directions = DirectMessageSettingsFragmentDirections.actionToInbox()
NavHostFragment.findNavController(this).navigate(directions)
}
Resource.Status.ERROR -> {

View File

@ -65,9 +65,7 @@ import java.util.List;
import java.util.Set;
import java.util.function.Function;
import awais.instagrabber.ProfileNavGraphDirections;
import awais.instagrabber.R;
import awais.instagrabber.UserSearchNavGraphDirections;
import awais.instagrabber.activities.CameraActivity;
import awais.instagrabber.activities.MainActivity;
import awais.instagrabber.adapters.DirectItemsAdapter;
@ -95,9 +93,7 @@ import awais.instagrabber.customviews.helpers.TranslateDeferringInsetsAnimationC
import awais.instagrabber.databinding.FragmentDirectMessagesThreadBinding;
import awais.instagrabber.dialogs.DirectItemReactionDialogFragment;
import awais.instagrabber.dialogs.GifPickerBottomDialogFragment;
import awais.instagrabber.fragments.PostViewV2Fragment;
import awais.instagrabber.fragments.UserSearchFragment;
import awais.instagrabber.fragments.UserSearchFragmentDirections;
import awais.instagrabber.fragments.UserSearchMode;
import awais.instagrabber.fragments.settings.PreferenceKeys;
import awais.instagrabber.models.Resource;
import awais.instagrabber.models.enums.DirectItemType;
@ -107,6 +103,9 @@ import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.DirectItem;
import awais.instagrabber.repositories.responses.directmessages.DirectItemEmojiReaction;
import awais.instagrabber.repositories.responses.directmessages.DirectItemLink;
import awais.instagrabber.repositories.responses.directmessages.DirectItemReactions;
import awais.instagrabber.repositories.responses.directmessages.DirectItemReelShare;
import awais.instagrabber.repositories.responses.directmessages.DirectItemStoryShare;
import awais.instagrabber.repositories.responses.directmessages.DirectItemVisualMedia;
import awais.instagrabber.repositories.responses.directmessages.DirectThread;
@ -136,7 +135,6 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
private InsetsAnimationLinearLayout root;
private boolean shouldRefresh = true;
private List<DirectItemOrHeader> itemOrHeaders;
private List<User> users;
private FragmentDirectMessagesThreadBinding binding;
private Tooltip tooltip;
private float initialSendX;
@ -163,7 +161,6 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
private LiveData<List<User>> usersLiveData;
private boolean autoMarkAsSeen = false;
private MenuItem markAsSeenMenuItem;
private Media tempMedia;
private DirectItem addReactionItem;
private TranslateDeferringInsetsAnimationCallback inputHolderAnimationCallback;
private TranslateDeferringInsetsAnimationCallback chatsAnimationCallback;
@ -189,8 +186,12 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
private final DirectItemCallback directItemCallback = new DirectItemCallback() {
@Override
public void onHashtagClick(final String hashtag) {
final NavDirections action = DirectMessageThreadFragmentDirections.actionGlobalHashTagFragment(hashtag);
NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(action);
try {
final NavDirections action = DirectMessageThreadFragmentDirections.actionToHashtag(hashtag);
NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onHashtagClick: ", e);
}
}
@Override
@ -200,8 +201,12 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
@Override
public void onLocationClick(final long locationId) {
final NavDirections action = DirectMessageThreadFragmentDirections.actionGlobalLocationFragment(locationId);
NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(action);
try {
final NavDirections action = DirectMessageThreadFragmentDirections.actionToLocation(locationId);
NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onLocationClick: ", e);
}
}
@Override
@ -221,26 +226,23 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
@Override
public void onMediaClick(final Media media, final int index) {
if (media.isReelMedia()) {
final String pk = media.getPk();
try {
final String pk = media.getPk();
if (pk == null) return;
final long mediaId = Long.parseLong(pk);
final User user = media.getUser();
if (user == null) return;
final String username = user.getUsername();
final NavDirections action = DirectMessageThreadFragmentDirections
.actionThreadToStory(StoryViewerOptions.forStory(mediaId, username));
final NavDirections action = DirectMessageThreadFragmentDirections.actionToStory(StoryViewerOptions.forStory(mediaId, username));
NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(action);
} catch (NumberFormatException e) {
} catch (Exception e) {
Log.e(TAG, "onMediaClick (story): ", e);
}
return;
}
final NavController navController = NavHostFragment.findNavController(DirectMessageThreadFragment.this);
final Bundle bundle = new Bundle();
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media);
bundle.putInt(PostViewV2Fragment.ARG_SLIDER_POSITION, index);
try {
navController.navigate(R.id.action_global_post_view, bundle);
final NavDirections actionToPost = DirectMessageThreadFragmentDirections.actionToPost(media, index);
NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(actionToPost);
} catch (Exception e) {
Log.e(TAG, "openPostDialog: ", e);
}
@ -248,16 +250,18 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
@Override
public void onStoryClick(final DirectItemStoryShare storyShare) {
final String pk = storyShare.getReelId();
try {
final String pk = storyShare.getReelId();
if (pk == null) return;
final long mediaId = Long.parseLong(pk);
final User user = storyShare.getMedia().getUser();
final Media media = storyShare.getMedia();
if (media == null) return;
final User user = media.getUser();
if (user == null) return;
final String username = user.getUsername();
final NavDirections action = DirectMessageThreadFragmentDirections
.actionThreadToStory(StoryViewerOptions.forUser(mediaId, username));
final NavDirections action = DirectMessageThreadFragmentDirections.actionToStory(StoryViewerOptions.forUser(mediaId, username));
NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(action);
} catch (NumberFormatException e) {
} catch (Exception e) {
Log.e(TAG, "onStoryClick: ", e);
}
}
@ -266,9 +270,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
public void onReaction(final DirectItem item, final Emoji emoji) {
if (item == null || emoji == null) return;
final LiveData<Resource<Object>> resourceLiveData = viewModel.sendReaction(item, emoji);
if (resourceLiveData != null) {
resourceLiveData.observe(getViewLifecycleOwner(), directItemResource -> handleSentMessage(resourceLiveData));
}
resourceLiveData.observe(getViewLifecycleOwner(), directItemResource -> handleSentMessage(resourceLiveData));
}
@Override
@ -284,15 +286,14 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
}
if (itemId == R.id.forward) {
itemToForward = item;
final UserSearchNavGraphDirections.ActionGlobalUserSearch actionGlobalUserSearch = UserSearchFragmentDirections
.actionGlobalUserSearch()
final NavDirections actionGlobalUserSearch = DirectMessageThreadFragmentDirections
.actionToUserSearch()
.setTitle(getString(R.string.forward))
.setActionLabel(getString(R.string.send))
.setShowGroups(true)
.setMultiple(true)
.setSearchMode(UserSearchFragment.SearchMode.RAVEN);
final NavController navController = NavHostFragment.findNavController(DirectMessageThreadFragment.this);
navController.navigate(actionGlobalUserSearch);
.setSearchMode(UserSearchMode.RAVEN);
NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(actionGlobalUserSearch);
}
if (itemId == R.id.download) {
downloadItem(item);
@ -418,10 +419,10 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
final int itemId = item.getItemId();
if (itemId == R.id.info) {
final DirectMessageThreadFragmentDirections.ActionThreadToSettings directions = DirectMessageThreadFragmentDirections
.actionThreadToSettings(viewModel.getThreadId(), null);
final Boolean pending = viewModel.isPending().getValue();
directions.setPending(pending != null && pending);
final NavDirections directions = DirectMessageThreadFragmentDirections
.actionToSettings(viewModel.getThreadId(), null)
.setPending(pending != null && pending);
NavHostFragment.findNavController(this).navigate(directions);
return true;
}
@ -485,7 +486,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
}
final Uri uri = data.getData();
final String mimeType = Utils.getMimeType(uri, context.getContentResolver());
if (mimeType.startsWith("image")) {
if (mimeType != null && mimeType.startsWith("image")) {
navigateToImageEditFragment(uri);
return;
}
@ -894,19 +895,26 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
binding.gallery.setVisibility(View.GONE);
}
private String getDirectItemPreviewText(final DirectItem item) {
switch (item.getItemType()) {
private String getDirectItemPreviewText(@NonNull final DirectItem item) {
final DirectItemType itemType = item.getItemType();
if (itemType == null) return "";
switch (itemType) {
case TEXT:
return item.getText();
case LINK:
return item.getLink().getText();
final DirectItemLink link = item.getLink();
if (link == null) return "";
return link.getText();
case MEDIA: {
final Media media = item.getMedia();
if (media == null) return "";
return getMediaPreviewTextString(media);
}
case RAVEN_MEDIA: {
final DirectItemVisualMedia visualMedia = item.getVisualMedia();
if (visualMedia == null) return "";
final Media media = visualMedia.getMedia();
if (media == null) return "";
return getMediaPreviewTextString(media);
}
case VOICE_MEDIA:
@ -914,14 +922,17 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
case MEDIA_SHARE:
return getString(R.string.post);
case REEL_SHARE:
return item.getReelShare().getText();
final DirectItemReelShare reelShare = item.getReelShare();
if (reelShare == null) return "";
return reelShare.getText();
}
return "";
}
@NonNull
private String getMediaPreviewTextString(final Media media) {
private String getMediaPreviewTextString(@NonNull final Media media) {
final MediaItemType mediaType = media.getType();
if (mediaType == null) return "";
switch (mediaType) {
case MEDIA_TYPE_IMAGE:
return getString(R.string.photo);
@ -932,8 +943,11 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
}
}
private String getDirectItemPreviewImageUrl(final DirectItem item) {
switch (item.getItemType()) {
@Nullable
private String getDirectItemPreviewImageUrl(@NonNull final DirectItem item) {
final DirectItemType itemType = item.getItemType();
if (itemType == null) return null;
switch (itemType) {
case TEXT:
case LINK:
case VOICE_MEDIA:
@ -945,6 +959,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
}
case RAVEN_MEDIA: {
final DirectItemVisualMedia visualMedia = item.getVisualMedia();
if (visualMedia == null) return null;
final Media media = visualMedia.getMedia();
return ResponseBodyUtils.getThumbUrl(media);
}
@ -1009,7 +1024,6 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
itemsAdapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY);
binding.chats.setAdapter(itemsAdapter);
registerDataObserver();
users = thread.getUsers();
final List<DirectItem> items = viewModel.getItems().getValue();
if (items != null && itemsAdapter.getItems() != items) {
submitItemsToAdapter(items);
@ -1234,9 +1248,12 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
}
private void navigateToImageEditFragment(final Uri uri) {
final NavDirections navDirections = DirectMessageThreadFragmentDirections.actionThreadToImageEdit(uri);
final NavController navController = NavHostFragment.findNavController(this);
navController.navigate(navDirections);
try {
final NavDirections navDirections = DirectMessageThreadFragmentDirections.actionToImageEdit(uri);
NavHostFragment.findNavController(this).navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "navigateToImageEditFragment: ", e);
}
}
private void handleSentMessage(final LiveData<Resource<Object>> resourceLiveData) {
@ -1403,11 +1420,14 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
final Context context = getContext();
if (context == null) return;
final DirectItemType itemType = item.getItemType();
if (itemType == null) return;
//noinspection SwitchStatementWithTooFewBranches
switch (itemType) {
case VOICE_MEDIA:
downloadItem(context, item.getVoiceMedia() == null ? null : item.getVoiceMedia().getMedia());
break;
default:
break;
}
}
@ -1421,15 +1441,6 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
Toast.makeText(context, R.string.downloader_downloading_media, Toast.LENGTH_SHORT).show();
}
@Nullable
private User getUser(final long userId) {
for (final User user : users) {
if (userId != user.getPk()) continue;
return user;
}
return null;
}
// Sets the translationY of views to height with animation
private void animatePan(final int height,
@Nullable final Function<Void, Void> onAnimationStart,
@ -1476,17 +1487,22 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
final LiveData<List<User>> leftUsers = viewModel.getLeftUsers();
final ArrayList<User> allUsers = new ArrayList<>();
allUsers.add(viewModel.getCurrentUser());
if (users != null && users.getValue() != null) {
if (users.getValue() != null) {
allUsers.addAll(users.getValue());
}
if (leftUsers != null && leftUsers.getValue() != null) {
if (leftUsers.getValue() != null) {
allUsers.addAll(leftUsers.getValue());
}
reactionDialogFragment = DirectItemReactionDialogFragment
.newInstance(viewModel.getViewerId(),
allUsers,
item.getItemId(),
item.getReactions());
final String itemId = item.getItemId();
if (itemId == null) return;
final DirectItemReactions reactions = item.getReactions();
if (reactions == null) return;
reactionDialogFragment = DirectItemReactionDialogFragment.newInstance(
viewModel.getViewerId(),
allUsers,
itemId,
reactions
);
reactionDialogFragment.show(getChildFragmentManager(), "reactions_dialog");
}
@ -1498,9 +1514,7 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
if (itemId == null || reaction == null) return;
if (reaction.getSenderId() == viewModel.getViewerId()) {
final LiveData<Resource<Object>> resourceLiveData = viewModel.sendDeleteReaction(itemId);
if (resourceLiveData != null) {
resourceLiveData.observe(getViewLifecycleOwner(), directItemResource -> handleSentMessage(resourceLiveData));
}
resourceLiveData.observe(getViewLifecycleOwner(), directItemResource -> handleSentMessage(resourceLiveData));
return;
}
// navigate to user
@ -1510,17 +1524,18 @@ public class DirectMessageThreadFragment extends Fragment implements DirectReact
}
private void navigateToUser(@NonNull final String username) {
final ProfileNavGraphDirections.ActionGlobalProfileFragment direction = ProfileNavGraphDirections
.actionGlobalProfileFragment("@" + username);
NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(direction);
try {
final NavDirections direction = DirectMessageThreadFragmentDirections.actionToProfile().setUsername(username);
NavHostFragment.findNavController(DirectMessageThreadFragment.this).navigate(direction);
} catch (Exception e) {
Log.e(TAG, "navigateToUser: ", e);
}
}
@Override
public void onClick(final View view, final Emoji emoji) {
if (addReactionItem == null || emoji == null) return;
final LiveData<Resource<Object>> resourceLiveData = viewModel.sendReaction(addReactionItem, emoji);
if (resourceLiveData != null) {
resourceLiveData.observe(getViewLifecycleOwner(), directItemResource -> handleSentMessage(resourceLiveData));
}
resourceLiveData.observe(getViewLifecycleOwner(), directItemResource -> handleSentMessage(resourceLiveData));
}
}

View File

@ -134,7 +134,7 @@ class DirectPendingInboxFragment : Fragment(), OnRefreshListener {
val threadTitle = thread.threadTitle ?: return@DirectMessageInboxAdapter
navigating = true
if (isAdded) {
val directions = DirectPendingInboxFragmentDirections.actionPendingInboxToThread(threadId, threadTitle)
val directions = DirectPendingInboxFragmentDirections.actionToThread(threadId, threadTitle)
directions.pending = true
NavHostFragment.findNavController(this).navigate(directions)
}

View File

@ -13,7 +13,7 @@ import androidx.appcompat.app.AlertDialog;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.FragmentNavigator;
import androidx.navigation.fragment.NavHostFragment;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
@ -26,7 +26,6 @@ import awais.instagrabber.activities.MainActivity;
import awais.instagrabber.adapters.DiscoverTopicsAdapter;
import awais.instagrabber.customviews.helpers.GridSpacingItemDecoration;
import awais.instagrabber.databinding.FragmentDiscoverBinding;
import awais.instagrabber.fragments.PostViewV2Fragment;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.discover.TopicCluster;
import awais.instagrabber.repositories.responses.discover.TopicalExploreFeedResponse;
@ -98,11 +97,14 @@ public class DiscoverFragment extends Fragment implements SwipeRefreshLayout.OnR
binding.topicsRecyclerView.addItemDecoration(new GridSpacingItemDecoration(Utils.convertDpToPx(2)));
final DiscoverTopicsAdapter.OnTopicClickListener otcl = new DiscoverTopicsAdapter.OnTopicClickListener() {
public void onTopicClick(final TopicCluster topicCluster, final View cover, final int titleColor, final int backgroundColor) {
final FragmentNavigator.Extras.Builder builder = new FragmentNavigator.Extras.Builder()
.addSharedElement(cover, "cover-" + topicCluster.getId());
final DiscoverFragmentDirections.ActionDiscoverFragmentToTopicPostsFragment action = DiscoverFragmentDirections
.actionDiscoverFragmentToTopicPostsFragment(topicCluster, titleColor, backgroundColor);
NavHostFragment.findNavController(DiscoverFragment.this).navigate(action, builder.build());
try {
final FragmentNavigator.Extras.Builder builder = new FragmentNavigator.Extras.Builder()
.addSharedElement(cover, "cover-" + topicCluster.getId());
final NavDirections action = DiscoverFragmentDirections.actionToTopicPosts(topicCluster, titleColor, backgroundColor);
NavHostFragment.findNavController(DiscoverFragment.this).navigate(action, builder.build());
} catch (Exception e) {
Log.e(TAG, "onTopicClick: ", e);
}
}
public void onTopicLongClick(final Media coverMedia) {
@ -123,11 +125,9 @@ public class DiscoverFragment extends Fragment implements SwipeRefreshLayout.OnR
} catch (Throwable ignored) {}
return;
}
final NavController navController = NavHostFragment.findNavController(DiscoverFragment.this);
final Bundle bundle = new Bundle();
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media);
try {
navController.navigate(R.id.action_global_post_view, bundle);
final NavDirections action = DiscoverFragmentDirections.actionToPost(media, 0);
NavHostFragment.findNavController(DiscoverFragment.this).navigate(action);
alertDialog.dismiss();
} catch (Exception e) {
Log.e(TAG, "onTopicLongClick: ", e);
@ -148,11 +148,13 @@ public class DiscoverFragment extends Fragment implements SwipeRefreshLayout.OnR
public void onSuccess(final TopicalExploreFeedResponse result) {
if (result == null) return;
final List<TopicCluster> clusters = result.getClusters();
if (clusters == null || result.getItems() == null) return;
binding.swipeRefreshLayout.setRefreshing(false);
if (clusters.size() == 1 && result.getItems().size() > 0) {
final TopicCluster cluster = clusters.get(0);
if (cluster.getCoverMedia() == null)
if (cluster.getCoverMedia() == null) {
cluster.setCoverMedia(result.getItems().get(0).getMedia());
}
topicClusterViewModel.getList().postValue(Collections.singletonList(cluster));
return;
}

View File

@ -40,10 +40,11 @@ import awais.instagrabber.asyncs.FeedPostFetchService;
import awais.instagrabber.customviews.PrimaryActionModeCallback;
import awais.instagrabber.databinding.FragmentFeedBinding;
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
import awais.instagrabber.fragments.PostViewV2Fragment;
import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.repositories.requests.StoryViewerOptions;
import awais.instagrabber.repositories.responses.Location;
import awais.instagrabber.repositories.responses.Media;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.stories.Story;
import awais.instagrabber.utils.AppExecutors;
import awais.instagrabber.utils.Constants;
@ -62,7 +63,6 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
private FragmentFeedBinding binding;
private StoriesRepository storiesRepository;
private boolean shouldRefresh = true;
private final boolean isRotate = false;
private FeedStoriesViewModel feedStoriesViewModel;
private boolean storiesFetching;
private ActionMode actionMode;
@ -77,15 +77,20 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
public void onFeedStoryClick(Story model, int position) {
final NavController navController = NavHostFragment.findNavController(FeedFragment.this);
if (isSafeToNavigate(navController)) {
final NavDirections action = FeedFragmentDirections
.actionFeedFragmentToStoryViewerFragment(StoryViewerOptions.forFeedStoryPosition(position));
navController.navigate(action);
try {
final NavDirections action = FeedFragmentDirections.actionToStory(StoryViewerOptions.forFeedStoryPosition(position));
navController.navigate(action);
} catch (Exception e) {
Log.e(TAG, "onFeedStoryClick: ", e);
}
}
}
@Override
public void onFeedStoryLongClick(Story model, int position) {
navigateToProfile("@" + model.getUser().getUsername());
final User user = model.getUser();
if (user == null) return;
navigateToProfile("@" + user.getUsername());
}
}
);
@ -93,21 +98,23 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
private final FeedAdapterV2.FeedItemCallback feedItemCallback = new FeedAdapterV2.FeedItemCallback() {
@Override
public void onPostClick(final Media feedModel, final View profilePicView, final View mainPostImage) {
openPostDialog(feedModel, profilePicView, mainPostImage, -1);
openPostDialog(feedModel, -1);
}
@Override
public void onSliderClick(final Media feedModel, final int position) {
openPostDialog(feedModel, null, null, position);
openPostDialog(feedModel, position);
}
@Override
public void onCommentsClick(final Media feedModel) {
try {
final NavDirections commentsAction = FeedFragmentDirections.actionGlobalCommentsViewerFragment(
final User user = feedModel.getUser();
if (user == null) return;
final NavDirections commentsAction = FeedFragmentDirections.actionToComments(
feedModel.getCode(),
feedModel.getPk(),
feedModel.getUser().getPk()
user.getPk()
);
NavHostFragment.findNavController(FeedFragment.this).navigate(commentsAction);
} catch (Exception e) {
@ -124,14 +131,24 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
@Override
public void onHashtagClick(final String hashtag) {
final NavDirections action = FeedFragmentDirections.actionGlobalHashTagFragment(hashtag);
NavHostFragment.findNavController(FeedFragment.this).navigate(action);
try {
final NavDirections action = FeedFragmentDirections.actionToHashtag(hashtag);
NavHostFragment.findNavController(FeedFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onHashtagClick: ", e);
}
}
@Override
public void onLocationClick(final Media feedModel) {
final NavDirections action = FeedFragmentDirections.actionGlobalLocationFragment(feedModel.getLocation().getPk());
NavHostFragment.findNavController(FeedFragment.this).navigate(action);
final Location location = feedModel.getLocation();
if (location == null) return;
try {
final NavDirections action = FeedFragmentDirections.actionToLocation(location.getPk());
NavHostFragment.findNavController(FeedFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onLocationClick: ", e);
}
}
@Override
@ -161,22 +178,10 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
Utils.openEmailAddress(getContext(), emailId);
}
private void openPostDialog(final Media feedModel,
final View profilePicView,
final View mainPostImage,
final int position) {
// ViewCompat.setTransitionName(profilePicView, "profile_pic");
// ViewCompat.setTransitionName(mainPostImage, "post_image");
// final FragmentNavigator.Extras extras = new FragmentNavigator.Extras.Builder()
// .addSharedElement(profilePicView, "profile_pic")
// .addSharedElement(mainPostImage, "post_image")
// .build();
final NavController navController = NavHostFragment.findNavController(FeedFragment.this);
final Bundle bundle = new Bundle();
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, feedModel);
bundle.putInt(PostViewV2Fragment.ARG_SLIDER_POSITION, position);
private void openPostDialog(final Media feedModel, final int position) {
try {
navController.navigate(R.id.action_global_post_view, bundle);
final NavDirections action = FeedFragmentDirections.actionToPost(feedModel, position);
NavHostFragment.findNavController(FeedFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "openPostDialog: ", e);
}
@ -246,10 +251,12 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
};
private void navigateToProfile(final String username) {
final NavController navController = NavHostFragment.findNavController(this);
final Bundle bundle = new Bundle();
bundle.putString("username", username);
navController.navigate(R.id.action_global_profileFragment, bundle);
try {
final NavDirections action = FeedFragmentDirections.actionToProfile().setUsername(username);
NavHostFragment.findNavController(this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "navigateToProfile: ", e);
}
}
@Override
@ -310,8 +317,12 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
@Override
public boolean onOptionsItemSelected(@NonNull final MenuItem item) {
if (item.getItemId() == R.id.storyList) {
final NavDirections action = FeedFragmentDirections.actionGlobalStoryListViewerFragment("feed");
NavHostFragment.findNavController(FeedFragment.this).navigate(action);
try {
final NavDirections action = FeedFragmentDirections.actionToStoryList("feed");
NavHostFragment.findNavController(FeedFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onOptionsItemSelected: ", e);
}
} else if (item.getItemId() == R.id.layout) {
showPostsLayoutPreferences();
return true;
@ -331,14 +342,6 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
fetchStories();
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (storiesRecyclerView != null) {
fragmentActivity.removeCollapsingView(storiesRecyclerView);
}
}
private void setupFeed() {
binding.feedRecyclerView.setViewModelStoreOwner(this)
.setLifeCycleOwner(this)
@ -412,7 +415,8 @@ public class FeedFragment extends Fragment implements SwipeRefreshLayout.OnRefre
preferences -> {
layoutPreferences = preferences;
new Handler().postDelayed(() -> binding.feedRecyclerView.setLayoutPreferences(preferences), 200);
});
}
);
fragment.show(getChildFragmentManager(), "posts_layout_preferences");
}

View File

@ -20,6 +20,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
@ -40,10 +41,7 @@ import awais.instagrabber.dialogs.MultiOptionDialogFragment.MultiOptionDialogSin
import awais.instagrabber.dialogs.MultiOptionDialogFragment.Option
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment
import awais.instagrabber.dialogs.ProfilePicDialogFragment
import awais.instagrabber.fragments.HashTagFragment.ARG_HASHTAG
import awais.instagrabber.fragments.PostViewV2Fragment
import awais.instagrabber.fragments.UserSearchFragment
import awais.instagrabber.fragments.UserSearchFragmentDirections
import awais.instagrabber.fragments.UserSearchMode
import awais.instagrabber.managers.DirectMessagesManager
import awais.instagrabber.models.Resource
import awais.instagrabber.models.enums.PostItemType
@ -105,8 +103,12 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
}
override fun onLocationClick(media: Media?) {
val action = FeedFragmentDirections.actionGlobalLocationFragment(media?.location?.pk ?: return)
NavHostFragment.findNavController(this@ProfileFragment).navigate(action)
try {
val action = ProfileFragmentDirections.actionToLocation(media?.location?.pk ?: return)
findNavController().navigate(action)
} catch (e: Exception) {
Log.e(TAG, "onLocationClick: ", e)
}
}
override fun onMentionClick(mention: String?) {
@ -114,17 +116,25 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
}
override fun onHashtagClick(hashtag: String?) {
val action = FeedFragmentDirections.actionGlobalHashTagFragment(hashtag ?: return)
NavHostFragment.findNavController(this@ProfileFragment).navigate(action)
try {
val action = ProfileFragmentDirections.actionToHashtag(hashtag ?: return)
findNavController().navigate(action)
} catch (e: Exception) {
Log.e(TAG, "onHashtagClick: ", e)
}
}
override fun onCommentsClick(media: Media?) {
val commentsAction = ProfileFragmentDirections.actionGlobalCommentsViewerFragment(
media?.code ?: return,
media.pk ?: return,
media.user?.pk ?: return
)
NavHostFragment.findNavController(this@ProfileFragment).navigate(commentsAction)
try {
val commentsAction = ProfileFragmentDirections.actionToComments(
media?.code ?: return,
media.pk ?: return,
media.user?.pk ?: return
)
findNavController().navigate(commentsAction)
} catch (e: Exception) {
Log.e(TAG, "onCommentsClick: ", e)
}
}
override fun onDownloadClick(media: Media?, childPosition: Int, popupLocation: View) {
@ -216,24 +226,24 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
}
private val onFollowersClickListener = View.OnClickListener {
try {
val action = ProfileFragmentDirections.actionProfileFragmentToFollowViewerFragment(
val action = ProfileFragmentDirections.actionToFollowViewer(
viewModel.profile.value?.data?.pk ?: return@OnClickListener,
true,
viewModel.profile.value?.data?.username ?: return@OnClickListener
)
NavHostFragment.findNavController(this).navigate(action)
findNavController().navigate(action)
} catch (e: Exception) {
Log.e(TAG, "onFollowersClickListener: ", e)
}
}
private val onFollowingClickListener = View.OnClickListener {
try {
val action = ProfileFragmentDirections.actionProfileFragmentToFollowViewerFragment(
val action = ProfileFragmentDirections.actionToFollowViewer(
viewModel.profile.value?.data?.pk ?: return@OnClickListener,
false,
viewModel.profile.value?.data?.username ?: return@OnClickListener
)
NavHostFragment.findNavController(this).navigate(action)
findNavController().navigate(action)
} catch (e: Exception) {
Log.e(TAG, "onFollowersClickListener: ", e)
}
@ -243,9 +253,8 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
}
private val onHashtagClickListener = OnHashtagClickListener {
try {
val bundle = Bundle()
bundle.putString(ARG_HASHTAG, it.originalText.trimAll())
NavHostFragment.findNavController(this).navigate(R.id.action_global_hashTagFragment, bundle)
val actionToHashtag = ProfileFragmentDirections.actionToHashtag(it.originalText.trimAll())
findNavController().navigate(actionToHashtag)
} catch (e: Exception) {
Log.e(TAG, "onHashtagClickListener: ", e)
}
@ -280,13 +289,9 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
}
private fun openPostDialog(media: Media, position: Int) {
val bundle = Bundle().apply {
putSerializable(PostViewV2Fragment.ARG_MEDIA, media)
putInt(PostViewV2Fragment.ARG_SLIDER_POSITION, position)
}
try {
val navController = NavHostFragment.findNavController(this)
navController.navigate(R.id.action_global_post_view, bundle)
val actionToPost = ProfileFragmentDirections.actionToPost(media, position)
findNavController().navigate(actionToPost)
} catch (e: Exception) {
Log.e(TAG, "openPostDialog: ", e)
}
@ -387,16 +392,15 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
}
private fun shareProfileViaDm() {
val actionGlobalUserSearch = UserSearchFragmentDirections.actionGlobalUserSearch().apply {
setTitle(getString(R.string.share))
setActionLabel(getString(R.string.send))
showGroups = true
multiple = true
setSearchMode(UserSearchFragment.SearchMode.RAVEN)
}
try {
val navController = NavHostFragment.findNavController(this@ProfileFragment)
navController.navigate(actionGlobalUserSearch)
val actionToUserSearch = ProfileFragmentDirections.actionToUserSearch().apply {
title = getString(R.string.share)
actionLabel = getString(R.string.send)
showGroups = true
multiple = true
searchMode = UserSearchMode.RAVEN
}
findNavController().navigate(actionToUserSearch)
} catch (e: Exception) {
Log.e(TAG, "shareProfileViaDm: ", e)
}
@ -413,12 +417,12 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
private fun navigateToChaining() {
viewModel.currentUser.value?.data ?: return
val profile = viewModel.profile.value?.data ?: return
val bundle = Bundle().apply {
putString("type", "chaining")
putLong("targetId", profile.pk)
}
try {
NavHostFragment.findNavController(this).navigate(R.id.action_global_notificationsViewerFragment, bundle)
val actionToNotifications = ProfileFragmentDirections.actionToNotifications().apply {
type = "chaining"
targetId = profile.pk
}
findNavController().navigate(actionToNotifications)
} catch (e: Exception) {
Log.e(TAG, "navigateToChaining: ", e)
}
@ -426,7 +430,7 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
private fun init() {
binding.swipeRefreshLayout.setOnRefreshListener(this)
disableDm = !Utils.isNavRootInCurrentTabs("direct_messages_nav_graph")
disableDm = !isNavRootInCurrentTabs("direct_messages_nav_graph")
setupHighlights()
setupObservers()
}
@ -717,14 +721,14 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
}
binding.header.btnLiked.setOnClickListener {
try {
val action = ProfileFragmentDirections.actionProfileFragmentToSavedViewerFragment(
val action = ProfileFragmentDirections.actionToSaved(
viewModel.profile.value?.data?.username ?: return@setOnClickListener,
viewModel.profile.value?.data?.pk ?: return@setOnClickListener,
PostItemType.LIKED
)
NavHostFragment.findNavController(this).navigate(action)
findNavController().navigate(action)
} catch (e: Exception) {
Log.e(TAG, "setupTaggedButton: ", e)
Log.e(TAG, "setupLikedButton: ", e)
}
}
}
@ -738,12 +742,12 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
}
binding.header.btnTagged.setOnClickListener {
try {
val action = ProfileFragmentDirections.actionProfileFragmentToSavedViewerFragment(
val action = ProfileFragmentDirections.actionToSaved(
viewModel.profile.value?.data?.username ?: return@setOnClickListener,
viewModel.profile.value?.data?.pk ?: return@setOnClickListener,
PostItemType.TAGGED
)
NavHostFragment.findNavController(this).navigate(action)
findNavController().navigate(action)
} catch (e: Exception) {
Log.e(TAG, "setupTaggedButton: ", e)
}
@ -759,8 +763,8 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
}
binding.header.btnSaved.setOnClickListener {
try {
val action = ProfileFragmentDirections.actionGlobalSavedCollectionsFragment(false)
NavHostFragment.findNavController(this).navigate(action)
val action = ProfileFragmentDirections.actionToSavedCollections().apply { isSaving = false }
findNavController().navigate(action)
} catch (e: Exception) {
Log.e(TAG, "setupSavedButton: ", e)
}
@ -851,9 +855,8 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
private fun setupHighlights() {
val context = context ?: return
highlightsAdapter = HighlightsAdapter { model, position ->
val options = StoryViewerOptions.forHighlight(model.title)
options.currentFeedStoryIndex = position
val action = ProfileFragmentDirections.actionProfileFragmentToStoryViewerFragment(options)
val options = StoryViewerOptions.forHighlight(model.title).apply { currentFeedStoryIndex = position }
val action = ProfileFragmentDirections.actionToStory(options)
NavHostFragment.findNavController(this).navigate(action)
}
binding.header.highlightsList.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
@ -881,10 +884,9 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
private fun navigateToProfile(username: String?) {
try {
val bundle = Bundle()
bundle.putString("username", username ?: return)
val navController = NavHostFragment.findNavController(this)
navController.navigate(R.id.action_global_profileFragment, bundle)
val username1 = username ?: return
val actionToProfile = ProfileFragmentDirections.actionToProfile().apply { this.username = username1 }
findNavController().navigate(actionToProfile)
} catch (e: Exception) {
Log.e(TAG, "navigateToProfile: ", e)
}
@ -937,13 +939,13 @@ class ProfileFragment : Fragment(), OnRefreshListener, ConfirmDialogFragmentCall
"profile_pic" -> showProfilePicDialog()
"show_stories" -> {
try {
val action = ProfileFragmentDirections.actionProfileFragmentToStoryViewerFragment(
val action = ProfileFragmentDirections.actionToStory(
StoryViewerOptions.forUser(
viewModel.profile.value?.data?.pk ?: return,
viewModel.profile.value?.data?.fullName ?: return,
)
)
NavHostFragment.findNavController(this).navigate(action)
findNavController().navigate(action)
} catch (e: Exception) {
Log.e(TAG, "omPpOptionSelect: ", e)
}

View File

@ -19,7 +19,7 @@ import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment;
import com.google.android.material.snackbar.Snackbar;
@ -125,7 +125,9 @@ public class SearchFragment extends Fragment implements SearchCategoryFragment.O
mainActivity.showSearchView();
}
if (settingsHelper.getBoolean(PREF_SEARCH_FOCUS_KEYBOARD)) {
searchInput.requestFocus();
if (searchInput != null) {
searchInput.requestFocus();
}
final InputMethodManager imm = (InputMethodManager) requireContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) imm.showSoftInput(searchInput, InputMethodManager.SHOW_IMPLICIT);
}
@ -205,24 +207,23 @@ public class SearchFragment extends Fragment implements SearchCategoryFragment.O
if (!searchItem.isFavorite()) {
viewModel.saveToRecentSearches(searchItem); // insert or update recent
}
final NavController navController = NavHostFragment.findNavController(this);
final Bundle bundle = new Bundle();
final NavDirections action;
switch (type) {
case USER:
bundle.putString("username", searchItem.getUser().getUsername());
navController.navigate(R.id.action_global_profileFragment, bundle);
action = SearchFragmentDirections.actionToProfile().setUsername(searchItem.getUser().getUsername());
NavHostFragment.findNavController(this).navigate(action);
break;
case HASHTAG:
bundle.putString("hashtag", searchItem.getHashtag().getName());
navController.navigate(R.id.action_global_hashTagFragment, bundle);
action = SearchFragmentDirections.actionToHashtag(searchItem.getHashtag().getName());
NavHostFragment.findNavController(this).navigate(action);
break;
case LOCATION:
bundle.putLong("locationId", searchItem.getPlace().getLocation().getPk());
navController.navigate(R.id.action_global_locationFragment, bundle);
action = SearchFragmentDirections.actionToLocation(searchItem.getPlace().getLocation().getPk());
break;
default:
break;
return;
}
NavHostFragment.findNavController(this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onSearchItemClick: ", e);
}

View File

@ -1,7 +1,6 @@
package awais.instagrabber.fragments.settings;
import android.content.Context;
import android.util.Pair;
import androidx.annotation.NonNull;
import androidx.preference.ListPreference;
@ -17,8 +16,9 @@ import awais.instagrabber.dialogs.TabOrderPreferenceDialogFragment;
import awais.instagrabber.models.Tab;
import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.NavigationHelperKt;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
import kotlin.Pair;
import static awais.instagrabber.utils.Utils.settingsHelper;
@ -37,27 +37,28 @@ public class GeneralPreferencesFragment extends BasePreferencesFragment implemen
screen.addPreference(getUpdateCheckPreference(context));
screen.addPreference(getFlagSecurePreference(context));
screen.addPreference(getSearchFocusPreference(context));
final List<Preference> preferences = FlavorSettings.getInstance()
.getPreferences(context,
getChildFragmentManager(),
SettingCategory.GENERAL);
if (preferences != null) {
for (final Preference preference : preferences) {
screen.addPreference(preference);
}
final List<Preference> preferences = FlavorSettings
.getInstance()
.getPreferences(
context,
getChildFragmentManager(),
SettingCategory.GENERAL
);
for (final Preference preference : preferences) {
screen.addPreference(preference);
}
}
private Preference getDefaultTabPreference(@NonNull final Context context) {
final ListPreference preference = new ListPreference(context);
preference.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
final Pair<List<Tab>, List<Tab>> listPair = Utils.getNavTabList(context);
final List<Tab> tabs = listPair.first;
final Pair<List<Tab>, List<Tab>> listPair = NavigationHelperKt.getLoggedInNavTabs(context);
final List<Tab> tabs = listPair.getFirst();
final String[] titles = tabs.stream()
.map(Tab::getTitle)
.toArray(String[]::new);
final String[] navGraphFileNames = tabs.stream()
.map(Tab::getGraphName)
.map(tab -> NavigationHelperKt.geNavGraphNameForNavRootId(tab.getNavigationRootId()))
.toArray(String[]::new);
preference.setKey(Constants.DEFAULT_TAB);
preference.setTitle(R.string.pref_start_screen);

View File

@ -35,6 +35,7 @@ import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.CoroutineUtilsKt;
import awais.instagrabber.utils.FlavorTown;
import awais.instagrabber.utils.NavigationHelperKt;
import awais.instagrabber.utils.ProcessPhoenix;
import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils;
@ -174,14 +175,18 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
boolean showActivity = true;
boolean showExplore = false;
if (activity != null) {
showActivity = !Utils.isNavRootInCurrentTabs("notification_viewer_nav_graph");
showExplore = !Utils.isNavRootInCurrentTabs("discover_nav_graph");
showActivity = !NavigationHelperKt.isNavRootInCurrentTabs("notification_viewer_nav_graph");
showExplore = !NavigationHelperKt.isNavRootInCurrentTabs("discover_nav_graph");
}
if (showActivity) {
screen.addPreference(getPreference(R.string.action_notif, R.drawable.ic_not_liked, preference -> {
if (isSafeToNavigate(navController)) {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalNotificationsViewerFragment("notif");
navController.navigate(navDirections);
try {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionToNotifications().setType("notif");
navController.navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "setupPreferenceScreen: ", e);
}
}
return true;
}));
@ -197,15 +202,23 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
screen.addPreference(getPreference(R.string.action_ayml, R.drawable.ic_suggested_users, preference -> {
if (isSafeToNavigate(navController)) {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalNotificationsViewerFragment("ayml");
navController.navigate(navDirections);
try {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionToNotifications().setType("ayml");
navController.navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "setupPreferenceScreen: ", e);
}
}
return true;
}));
screen.addPreference(getPreference(R.string.action_archive, R.drawable.ic_archive, preference -> {
if (isSafeToNavigate(navController)) {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalStoryListViewerFragment("archive");
navController.navigate(navDirections);
try {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionToStoryList("archive");
navController.navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "setupPreferenceScreen: ", e);
}
}
return true;
}));
@ -214,13 +227,17 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
// Check if favorites has been added as a tab. And if so, do not add in this list
boolean showFavorites = true;
if (activity != null) {
showFavorites = !Utils.isNavRootInCurrentTabs("favorites_nav_graph");
showFavorites = !NavigationHelperKt.isNavRootInCurrentTabs("favorites_nav_graph");
}
if (showFavorites) {
screen.addPreference(getPreference(R.string.title_favorites, R.drawable.ic_star_24, preference -> {
if (isSafeToNavigate(navController)) {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionMorePreferencesFragmentToFavoritesFragment();
navController.navigate(navDirections);
try {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionToFavorites();
navController.navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "setupPreferenceScreen: ", e);
}
}
return true;
}));
@ -229,36 +246,50 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
screen.addPreference(getDivider(context));
screen.addPreference(getPreference(R.string.action_settings, R.drawable.ic_outline_settings_24, preference -> {
if (isSafeToNavigate(navController)) {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionMorePreferencesFragmentToSettingsPreferencesFragment();
navController.navigate(navDirections);
try {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionToSettings();
navController.navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "setupPreferenceScreen: ", e);
}
}
return true;
}));
screen.addPreference(getPreference(R.string.backup_and_restore, R.drawable.ic_settings_backup_restore_24, preference -> {
if (isSafeToNavigate(navController)) {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionMorePreferencesFragmentToBackupPreferencesFragment();
navController.navigate(navDirections);
try {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionToBackup();
navController.navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "setupPreferenceScreen: ", e);
}
}
return true;
}));
screen.addPreference(getPreference(R.string.action_about, R.drawable.ic_outline_info_24, preference1 -> {
if (isSafeToNavigate(navController)) {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionMorePreferencesFragmentToAboutFragment();
navController.navigate(navDirections);
try {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionToAbout();
navController.navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "setupPreferenceScreen: ", e);
}
}
return true;
}));
screen.addPreference(getDivider(context));
screen.addPreference(getPreference(R.string.version,
BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")",
-1,
preference -> {
if (BuildConfig.isPre) return true;
if (activity == null) return false;
FlavorTown.updateCheck(activity, true);
return true;
}));
screen.addPreference(getPreference(
R.string.version,
BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")",
-1,
preference -> {
if (BuildConfig.isPre) return true;
if (activity == null) return false;
FlavorTown.updateCheck(activity, true);
return true;
})
);
screen.addPreference(getDivider(context));
final Preference reminderPreference = getPreference(R.string.reminder, R.string.reminder_summary, R.drawable.ic_warning, null);
@ -285,32 +316,33 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
// adds cookies to database for quick access
final long uid = CookieUtils.getUserIdFromCookie(cookie);
final UserRepository userRepository = UserRepository.Companion.getInstance();
userRepository.getUserInfo(uid, CoroutineUtilsKt.getContinuation((user, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
Log.e(TAG, "Error fetching user info", throwable);
return;
}
if (user != null) {
accountRepository.insertOrUpdateAccount(
uid,
user.getUsername(),
cookie,
user.getFullName(),
user.getProfilePicUrl(),
CoroutineUtilsKt.getContinuation((account, throwable1) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable1 != null) {
Log.e(TAG, "onActivityResult: ", throwable1);
return;
}
AppExecutors.INSTANCE.getMainThread().execute(() -> {
final Context context = getContext();
if (context == null) return;
ProcessPhoenix.triggerRebirth(context);
}, 200);
}), Dispatchers.getIO())
);
}
}), Dispatchers.getIO()));
userRepository
.getUserInfo(uid, CoroutineUtilsKt.getContinuation((user, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable != null) {
Log.e(TAG, "Error fetching user info", throwable);
return;
}
if (user != null) {
accountRepository.insertOrUpdateAccount(
uid,
user.getUsername(),
cookie,
user.getFullName(),
user.getProfilePicUrl(),
CoroutineUtilsKt.getContinuation((account, throwable1) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (throwable1 != null) {
Log.e(TAG, "onActivityResult: ", throwable1);
return;
}
AppExecutors.INSTANCE.getMainThread().execute(() -> {
final Context context = getContext();
if (context == null) return;
ProcessPhoenix.triggerRebirth(context);
}, 200);
}), Dispatchers.getIO())
);
}
}), Dispatchers.getIO()));
}
}

View File

@ -2,24 +2,12 @@ package awais.instagrabber.models
import androidx.annotation.DrawableRes
import androidx.annotation.IdRes
import androidx.annotation.NavigationRes
data class Tab(
@param:DrawableRes val iconResId: Int,
val title: String,
val isRemovable: Boolean,
/**
* This is name part of the navigation resource
* eg: @navigation/ **graphName**
*/
val graphName: String,
/**
* This is the actual resource id of the navigation resource (R.navigation.graphName = navigationResId)
*/
@param:NavigationRes val navigationResId: Int,
/**
* This is the resource id of the root navigation tag of the navigation resource.
*

View File

@ -1,247 +1,247 @@
package awais.instagrabber.utils;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.util.Log;
import android.util.SparseArray;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
import androidx.navigation.NavGraph;
import androidx.navigation.fragment.NavHostFragment;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import java.util.List;
import awais.instagrabber.R;
import awais.instagrabber.customviews.NavHostFragmentWithDefaultAnimations;
import awais.instagrabber.fragments.main.FeedFragment;
/**
* This is a Java rewrite of <a href="https://github.com/android/architecture-components-samples/blob/master/NavigationAdvancedSample/app/src/main/java/com/example/android/navigationadvancedsample/NavigationExtensions.kt">NavigationExtensions</a>
* from architecture-components-samples. Some modifications have been done, check git history.
*/
public class NavigationExtensions {
private static final String TAG = NavigationExtensions.class.getSimpleName();
private static String selectedItemTag;
private static boolean isOnFirstFragment;
@NonNull
public static LiveData<NavController> setupWithNavController(@NonNull final BottomNavigationView bottomNavigationView,
@NonNull List<Integer> navGraphIds,
@NonNull final FragmentManager fragmentManager,
final int containerId,
@NonNull Intent intent,
final int firstFragmentGraphIndex) {
final SparseArray<String> graphIdToTagMap = new SparseArray<>();
final MutableLiveData<NavController> selectedNavController = new MutableLiveData<>();
int firstFragmentGraphId = 0;
for (int i = 0; i < navGraphIds.size(); i++) {
final int navGraphId = navGraphIds.get(i);
final String fragmentTag = getFragmentTag(navGraphId);
final NavHostFragment navHostFragment = obtainNavHostFragment(fragmentManager, fragmentTag, navGraphId, containerId);
final NavController navController = navHostFragment.getNavController();
final int graphId = navController.getGraph().getId();
if (i == firstFragmentGraphIndex) {
firstFragmentGraphId = graphId;
}
graphIdToTagMap.put(graphId, fragmentTag);
if (bottomNavigationView.getSelectedItemId() == graphId) {
selectedNavController.setValue(navHostFragment.getNavController());
attachNavHostFragment(fragmentManager, navHostFragment, i == firstFragmentGraphIndex);
} else {
detachNavHostFragment(fragmentManager, navHostFragment);
}
}
selectedItemTag = graphIdToTagMap.get(bottomNavigationView.getSelectedItemId());
final String firstFragmentTag = graphIdToTagMap.get(firstFragmentGraphId);
isOnFirstFragment = selectedItemTag != null && selectedItemTag.equals(firstFragmentTag);
bottomNavigationView.setOnItemSelectedListener(item -> {
if (fragmentManager.isStateSaved()) {
return false;
}
String newlySelectedItemTag = graphIdToTagMap.get(item.getItemId());
String tag = selectedItemTag;
if (tag != null && !tag.equals(newlySelectedItemTag)) {
fragmentManager.popBackStack(firstFragmentTag, FragmentManager.POP_BACK_STACK_INCLUSIVE);
Fragment fragment = fragmentManager.findFragmentByTag(newlySelectedItemTag);
if (fragment == null) {
return false;
// throw new RuntimeException("null cannot be cast to non-null NavHostFragment");
}
final NavHostFragment selectedFragment = (NavHostFragment) fragment;
if (firstFragmentTag != null && !firstFragmentTag.equals(newlySelectedItemTag)) {
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction()
.setCustomAnimations(
R.anim.nav_default_enter_anim,
R.anim.nav_default_exit_anim,
R.anim.nav_default_pop_enter_anim,
R.anim.nav_default_pop_exit_anim
)
.attach(selectedFragment)
.setPrimaryNavigationFragment(selectedFragment);
for (int i = 0; i < graphIdToTagMap.size(); i++) {
final int key = graphIdToTagMap.keyAt(i);
final String fragmentTagForId = graphIdToTagMap.get(key);
if (!fragmentTagForId.equals(newlySelectedItemTag)) {
final Fragment fragmentByTag = fragmentManager.findFragmentByTag(firstFragmentTag);
if (fragmentByTag == null) {
continue;
}
fragmentTransaction.detach(fragmentByTag);
}
}
fragmentTransaction.addToBackStack(firstFragmentTag)
.setReorderingAllowed(true)
.commit();
}
selectedItemTag = newlySelectedItemTag;
isOnFirstFragment = selectedItemTag.equals(firstFragmentTag);
selectedNavController.setValue(selectedFragment.getNavController());
return true;
}
return false;
});
setupItemReselected(bottomNavigationView, graphIdToTagMap, fragmentManager);
setupDeepLinks(bottomNavigationView, navGraphIds, fragmentManager, containerId, intent);
final int finalFirstFragmentGraphId = firstFragmentGraphId;
fragmentManager.addOnBackStackChangedListener(() -> {
if (!isOnFirstFragment) {
if (firstFragmentTag == null) {
return;
}
if (!isOnBackStack(fragmentManager, firstFragmentTag)) {
bottomNavigationView.setSelectedItemId(finalFirstFragmentGraphId);
}
}
final NavController navController = selectedNavController.getValue();
if (navController != null && navController.getCurrentDestination() == null) {
final NavGraph navControllerGraph = navController.getGraph();
navController.navigate(navControllerGraph.getId());
}
});
return selectedNavController;
}
private static NavHostFragment obtainNavHostFragment(final FragmentManager fragmentManager,
final String fragmentTag,
final int navGraphId,
final int containerId) {
final NavHostFragment existingFragment = (NavHostFragment) fragmentManager.findFragmentByTag(fragmentTag);
if (existingFragment != null) {
return existingFragment;
}
final NavHostFragment navHostFragment = NavHostFragmentWithDefaultAnimations.create(navGraphId);
fragmentManager.beginTransaction()
.setReorderingAllowed(true)
.add(containerId, navHostFragment, fragmentTag)
.commitNow();
return navHostFragment;
}
private static void attachNavHostFragment(final FragmentManager fragmentManager,
final NavHostFragment navHostFragment,
final boolean isPrimaryNavFragment) {
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
.attach(navHostFragment);
if (isPrimaryNavFragment) {
fragmentTransaction.setPrimaryNavigationFragment(navHostFragment);
}
fragmentTransaction.commitNow();
}
private static void detachNavHostFragment(final FragmentManager fragmentManager, final NavHostFragment navHostFragment) {
fragmentManager.beginTransaction()
.detach(navHostFragment)
.commitNow();
}
@SuppressLint("RestrictedApi")
private static void setupItemReselected(final BottomNavigationView bottomNavigationView,
final SparseArray<String> graphIdToTagMap,
final FragmentManager fragmentManager) {
bottomNavigationView.setOnItemReselectedListener(item -> {
final String newlySelectedItemTag = graphIdToTagMap.get(item.getItemId());
final Fragment fragmentByTag = fragmentManager.findFragmentByTag(newlySelectedItemTag);
if (fragmentByTag == null) {
return;
}
final NavHostFragment selectedFragment = (NavHostFragment) fragmentByTag;
final NavController navController = selectedFragment.getNavController();
final NavGraph navControllerGraph = navController.getGraph();
final NavDestination currentDestination = navController.getCurrentDestination();
final int startDestination = navControllerGraph.getStartDestination();
int backStackSize = navController.getBackStack().size();
if (currentDestination != null && backStackSize == 2 && currentDestination.getId() == startDestination) {
// scroll to top
final List<Fragment> fragments = selectedFragment.getChildFragmentManager().getFragments();
if (fragments.isEmpty()) return;
final Fragment fragment = fragments.get(0);
if (fragment instanceof FeedFragment) {
((FeedFragment) fragment).scrollToTop();
}
return;
}
final boolean popped = navController.popBackStack(startDestination, false);
backStackSize = navController.getBackStack().size();
if (!popped || backStackSize > 2) {
try {
// try loop pop
do {
navController.popBackStack();
backStackSize = navController.getBackStack().size();
} while (backStackSize > 2);
} catch (Exception e) {
Log.e(TAG, "setupItemReselected: ", e);
}
}
});
}
private static void setupDeepLinks(final BottomNavigationView bottomNavigationView,
final List<Integer> navGraphIds,
final FragmentManager fragmentManager,
final int containerId,
final Intent intent) {
for (int i = 0; i < navGraphIds.size(); i++) {
final int navGraphId = navGraphIds.get(i);
final String fragmentTag = getFragmentTag(navGraphId);
final NavHostFragment navHostFragment = obtainNavHostFragment(fragmentManager, fragmentTag, navGraphId, containerId);
if (navHostFragment.getNavController().handleDeepLink(intent)) {
final int selectedItemId = bottomNavigationView.getSelectedItemId();
NavController navController = navHostFragment.getNavController();
NavGraph graph = navController.getGraph();
if (selectedItemId != graph.getId()) {
navController = navHostFragment.getNavController();
graph = navController.getGraph();
bottomNavigationView.setSelectedItemId(graph.getId());
}
}
}
}
private static boolean isOnBackStack(final FragmentManager fragmentManager, final String backStackName) {
int backStackCount = fragmentManager.getBackStackEntryCount();
for (int i = 0; i < backStackCount; i++) {
final FragmentManager.BackStackEntry backStackEntry = fragmentManager.getBackStackEntryAt(i);
final String name = backStackEntry.getName();
if (name != null && name.equals(backStackName)) {
return true;
}
}
return false;
}
private static String getFragmentTag(final int index) {
return "bottomNavigation#" + index;
}
}
// package awais.instagrabber.utils;
//
// import android.annotation.SuppressLint;
// import android.content.Intent;
// import android.util.Log;
// import android.util.SparseArray;
//
// import androidx.annotation.NonNull;
// import androidx.fragment.app.Fragment;
// import androidx.fragment.app.FragmentManager;
// import androidx.fragment.app.FragmentTransaction;
// import androidx.lifecycle.LiveData;
// import androidx.lifecycle.MutableLiveData;
// import androidx.navigation.NavController;
// import androidx.navigation.NavDestination;
// import androidx.navigation.NavGraph;
// import androidx.navigation.fragment.NavHostFragment;
//
// import com.google.android.material.bottomnavigation.BottomNavigationView;
//
// import java.util.List;
//
// import awais.instagrabber.R;
// import awais.instagrabber.customviews.NavHostFragmentWithDefaultAnimations;
// import awais.instagrabber.fragments.main.FeedFragment;
//
// /**
// * This is a Java rewrite of <a href="https://github.com/android/architecture-components-samples/blob/master/NavigationAdvancedSample/app/src/main/java/com/example/android/navigationadvancedsample/NavigationExtensions.kt">NavigationExtensions</a>
// * from architecture-components-samples. Some modifications have been done, check git history.
// */
// public class NavigationExtensions {
// private static final String TAG = NavigationExtensions.class.getSimpleName();
// private static String selectedItemTag;
// private static boolean isOnFirstFragment;
//
// @NonNull
// public static LiveData<NavController> setupWithNavController(@NonNull final BottomNavigationView bottomNavigationView,
// @NonNull List<Integer> navGraphIds,
// @NonNull final FragmentManager fragmentManager,
// final int containerId,
// @NonNull Intent intent,
// final int firstFragmentGraphIndex) {
// final SparseArray<String> graphIdToTagMap = new SparseArray<>();
// final MutableLiveData<NavController> selectedNavController = new MutableLiveData<>();
// int firstFragmentGraphId = 0;
// for (int i = 0; i < navGraphIds.size(); i++) {
// final int navGraphId = navGraphIds.get(i);
// final String fragmentTag = getFragmentTag(navGraphId);
// final NavHostFragment navHostFragment = obtainNavHostFragment(fragmentManager, fragmentTag, navGraphId, containerId);
// final NavController navController = navHostFragment.getNavController();
// final int graphId = navController.getGraph().getId();
// if (i == firstFragmentGraphIndex) {
// firstFragmentGraphId = graphId;
// }
// graphIdToTagMap.put(graphId, fragmentTag);
// if (bottomNavigationView.getSelectedItemId() == graphId) {
// selectedNavController.setValue(navHostFragment.getNavController());
// attachNavHostFragment(fragmentManager, navHostFragment, i == firstFragmentGraphIndex);
// } else {
// detachNavHostFragment(fragmentManager, navHostFragment);
// }
// }
// selectedItemTag = graphIdToTagMap.get(bottomNavigationView.getSelectedItemId());
// final String firstFragmentTag = graphIdToTagMap.get(firstFragmentGraphId);
// isOnFirstFragment = selectedItemTag != null && selectedItemTag.equals(firstFragmentTag);
// bottomNavigationView.setOnItemSelectedListener(item -> {
// if (fragmentManager.isStateSaved()) {
// return false;
// }
// String newlySelectedItemTag = graphIdToTagMap.get(item.getItemId());
// String tag = selectedItemTag;
// if (tag != null && !tag.equals(newlySelectedItemTag)) {
// fragmentManager.popBackStack(firstFragmentTag, FragmentManager.POP_BACK_STACK_INCLUSIVE);
// Fragment fragment = fragmentManager.findFragmentByTag(newlySelectedItemTag);
// if (fragment == null) {
// return false;
// // throw new RuntimeException("null cannot be cast to non-null NavHostFragment");
// }
// final NavHostFragment selectedFragment = (NavHostFragment) fragment;
// if (firstFragmentTag != null && !firstFragmentTag.equals(newlySelectedItemTag)) {
// FragmentTransaction fragmentTransaction = fragmentManager
// .beginTransaction()
// .setCustomAnimations(
// R.anim.nav_default_enter_anim,
// R.anim.nav_default_exit_anim,
// R.anim.nav_default_pop_enter_anim,
// R.anim.nav_default_pop_exit_anim
// )
// .attach(selectedFragment)
// .setPrimaryNavigationFragment(selectedFragment);
// for (int i = 0; i < graphIdToTagMap.size(); i++) {
// final int key = graphIdToTagMap.keyAt(i);
// final String fragmentTagForId = graphIdToTagMap.get(key);
// if (!fragmentTagForId.equals(newlySelectedItemTag)) {
// final Fragment fragmentByTag = fragmentManager.findFragmentByTag(firstFragmentTag);
// if (fragmentByTag == null) {
// continue;
// }
// fragmentTransaction.detach(fragmentByTag);
// }
// }
// fragmentTransaction.addToBackStack(firstFragmentTag)
// .setReorderingAllowed(true)
// .commit();
// }
// selectedItemTag = newlySelectedItemTag;
// isOnFirstFragment = selectedItemTag.equals(firstFragmentTag);
// selectedNavController.setValue(selectedFragment.getNavController());
// return true;
// }
// return false;
// });
// setupItemReselected(bottomNavigationView, graphIdToTagMap, fragmentManager);
// setupDeepLinks(bottomNavigationView, navGraphIds, fragmentManager, containerId, intent);
// final int finalFirstFragmentGraphId = firstFragmentGraphId;
// fragmentManager.addOnBackStackChangedListener(() -> {
// if (!isOnFirstFragment) {
// if (firstFragmentTag == null) {
// return;
// }
// if (!isOnBackStack(fragmentManager, firstFragmentTag)) {
// bottomNavigationView.setSelectedItemId(finalFirstFragmentGraphId);
// }
// }
//
// final NavController navController = selectedNavController.getValue();
// if (navController != null && navController.getCurrentDestination() == null) {
// final NavGraph navControllerGraph = navController.getGraph();
// navController.navigate(navControllerGraph.getId());
// }
// });
// return selectedNavController;
// }
//
// private static NavHostFragment obtainNavHostFragment(final FragmentManager fragmentManager,
// final String fragmentTag,
// final int navGraphId,
// final int containerId) {
// final NavHostFragment existingFragment = (NavHostFragment) fragmentManager.findFragmentByTag(fragmentTag);
// if (existingFragment != null) {
// return existingFragment;
// }
// final NavHostFragment navHostFragment = NavHostFragmentWithDefaultAnimations.create(navGraphId);
// fragmentManager.beginTransaction()
// .setReorderingAllowed(true)
// .add(containerId, navHostFragment, fragmentTag)
// .commitNow();
// return navHostFragment;
// }
//
// private static void attachNavHostFragment(final FragmentManager fragmentManager,
// final NavHostFragment navHostFragment,
// final boolean isPrimaryNavFragment) {
// final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
// .attach(navHostFragment);
// if (isPrimaryNavFragment) {
// fragmentTransaction.setPrimaryNavigationFragment(navHostFragment);
// }
// fragmentTransaction.commitNow();
// }
//
// private static void detachNavHostFragment(final FragmentManager fragmentManager, final NavHostFragment navHostFragment) {
// fragmentManager.beginTransaction()
// .detach(navHostFragment)
// .commitNow();
// }
//
// @SuppressLint("RestrictedApi")
// private static void setupItemReselected(final BottomNavigationView bottomNavigationView,
// final SparseArray<String> graphIdToTagMap,
// final FragmentManager fragmentManager) {
// bottomNavigationView.setOnItemReselectedListener(item -> {
// final String newlySelectedItemTag = graphIdToTagMap.get(item.getItemId());
// final Fragment fragmentByTag = fragmentManager.findFragmentByTag(newlySelectedItemTag);
// if (fragmentByTag == null) {
// return;
// }
// final NavHostFragment selectedFragment = (NavHostFragment) fragmentByTag;
// final NavController navController = selectedFragment.getNavController();
// final NavGraph navControllerGraph = navController.getGraph();
// final NavDestination currentDestination = navController.getCurrentDestination();
// final int startDestination = navControllerGraph.getStartDestination();
// int backStackSize = navController.getBackStack().size();
// if (currentDestination != null && backStackSize == 2 && currentDestination.getId() == startDestination) {
// // scroll to top
// final List<Fragment> fragments = selectedFragment.getChildFragmentManager().getFragments();
// if (fragments.isEmpty()) return;
// final Fragment fragment = fragments.get(0);
// if (fragment instanceof FeedFragment) {
// ((FeedFragment) fragment).scrollToTop();
// }
// return;
// }
// final boolean popped = navController.popBackStack(startDestination, false);
// backStackSize = navController.getBackStack().size();
// if (!popped || backStackSize > 2) {
// try {
// // try loop pop
// do {
// navController.popBackStack();
// backStackSize = navController.getBackStack().size();
// } while (backStackSize > 2);
// } catch (Exception e) {
// Log.e(TAG, "setupItemReselected: ", e);
// }
// }
// });
// }
//
// private static void setupDeepLinks(final BottomNavigationView bottomNavigationView,
// final List<Integer> navGraphIds,
// final FragmentManager fragmentManager,
// final int containerId,
// final Intent intent) {
// for (int i = 0; i < navGraphIds.size(); i++) {
// final int navGraphId = navGraphIds.get(i);
// final String fragmentTag = getFragmentTag(navGraphId);
// final NavHostFragment navHostFragment = obtainNavHostFragment(fragmentManager, fragmentTag, navGraphId, containerId);
// if (navHostFragment.getNavController().handleDeepLink(intent)) {
// final int selectedItemId = bottomNavigationView.getSelectedItemId();
// NavController navController = navHostFragment.getNavController();
// NavGraph graph = navController.getGraph();
// if (selectedItemId != graph.getId()) {
// navController = navHostFragment.getNavController();
// graph = navController.getGraph();
// bottomNavigationView.setSelectedItemId(graph.getId());
// }
// }
// }
// }
//
// private static boolean isOnBackStack(final FragmentManager fragmentManager, final String backStackName) {
// int backStackCount = fragmentManager.getBackStackEntryCount();
// for (int i = 0; i < backStackCount; i++) {
// final FragmentManager.BackStackEntry backStackEntry = fragmentManager.getBackStackEntryAt(i);
// final String name = backStackEntry.getName();
// if (name != null && name.equals(backStackName)) {
// return true;
// }
// }
// return false;
// }
//
// private static String getFragmentTag(final int index) {
// return "bottomNavigation#" + index;
// }
// }

View File

@ -0,0 +1,162 @@
package awais.instagrabber.utils
import android.content.Context
import android.content.res.Resources
import androidx.annotation.ArrayRes
import awais.instagrabber.R
import awais.instagrabber.fragments.settings.PreferenceKeys
import awais.instagrabber.models.Tab
var tabOrderString: String? = null
private val NON_REMOVABLE_NAV_ROOT_IDS: List<Int> = listOf(R.id.profile_nav_graph, R.id.more_nav_graph)
fun getLoggedInNavTabs(context: Context): Pair<List<Tab>, List<Tab>> {
val navRootIds = getArrayResIds(context.resources, R.array.logged_in_nav_root_ids)
return getTabs(context, navRootIds)
}
fun getAnonNavTabs(context: Context): List<Tab> {
val navRootIds = getArrayResIds(context.resources, R.array.anon_nav_root_ids)
val (tabs, _) = getTabs(context, navRootIds)
return tabs
}
private fun getTabs(
context: Context,
navRootIds: IntArray,
isAnon: Boolean = false,
): Pair<List<Tab>, MutableList<Tab>> {
val navGraphNames = getResIdsForNavRootIds(navRootIds, ::geNavGraphNameForNavRootId)
val titleArray = getResIdsForNavRootIds(navRootIds, ::getTitleResIdForNavRootId)
val iconIds = getResIdsForNavRootIds(navRootIds, ::getIconResIdForNavRootId)
val startDestFragIds = getResIdsForNavRootIds(navRootIds, ::getStartDestFragIdForNavRootId)
val (orderedGraphNames, orderedNavRootIds) = if (isAnon) navGraphNames to navRootIds.toList() else getOrderedNavRootIdsFromPref(navGraphNames)
val tabs = mutableListOf<Tab>()
val otherTabs = mutableListOf<Tab>() // Will contain tabs not in current list
for (i in navRootIds.indices) {
val navRootId = navRootIds[i]
val navGraphName = navGraphNames[i]
val tab = Tab(
iconIds[i],
context.getString(titleArray[i]),
if(isAnon) false else !NON_REMOVABLE_NAV_ROOT_IDS.contains(navRootId),
navRootId,
startDestFragIds[i]
)
if (!isAnon && !orderedGraphNames.contains(navGraphName)) {
otherTabs.add(tab)
continue
}
tabs.add(tab)
}
val associateBy = tabs.associateBy { it.navigationRootId }
val orderedTabs = orderedNavRootIds.mapNotNull { associateBy[it] }
return orderedTabs to otherTabs
}
private fun getArrayResIds(resources: Resources, @ArrayRes arrayRes: Int): IntArray {
val typedArray = resources.obtainTypedArray(arrayRes)
val length = typedArray.length()
val navRootIds = IntArray(length)
for (i in 0 until length) {
val resourceId = typedArray.getResourceId(i, 0)
if (resourceId == 0) continue
navRootIds[i] = resourceId
}
typedArray.recycle()
return navRootIds
}
private fun <T> getResIdsForNavRootIds(navRootIds: IntArray, resMapper: Function1<Int, T>): List<T> = navRootIds
.asSequence()
.filterNot { it == 0 }
.map(resMapper)
.filterNot { it == 0 }
.toList()
private fun getTitleResIdForNavRootId(id: Int): Int = when (id) {
R.id.direct_messages_nav_graph -> R.string.title_dm
R.id.feed_nav_graph -> R.string.feed
R.id.profile_nav_graph -> R.string.profile
R.id.discover_nav_graph -> R.string.title_discover
R.id.more_nav_graph -> R.string.more
R.id.favorites_nav_graph -> R.string.title_favorites
R.id.notification_viewer_nav_graph -> R.string.title_notifications
else -> 0
}
private fun getIconResIdForNavRootId(id: Int): Int = when (id) {
R.id.direct_messages_nav_graph -> R.drawable.ic_message_24
R.id.feed_nav_graph -> R.drawable.ic_home_24
R.id.profile_nav_graph -> R.drawable.ic_person_24
R.id.discover_nav_graph -> R.drawable.ic_explore_24
R.id.more_nav_graph -> R.drawable.ic_more_horiz_24
R.id.favorites_nav_graph -> R.drawable.ic_star_24
R.id.notification_viewer_nav_graph -> R.drawable.ic_not_liked
else -> 0
}
private fun getStartDestFragIdForNavRootId(id: Int): Int = when (id) {
R.id.direct_messages_nav_graph -> R.id.directMessagesInboxFragment
R.id.feed_nav_graph -> R.id.feedFragment
R.id.profile_nav_graph -> R.id.profileFragment
R.id.discover_nav_graph -> R.id.discoverFragment
R.id.more_nav_graph -> R.id.morePreferencesFragment
R.id.favorites_nav_graph -> R.id.favoritesFragment
R.id.notification_viewer_nav_graph -> R.id.notificationsViewer
else -> 0
}
fun geNavGraphNameForNavRootId(id: Int): String = when (id) {
R.id.direct_messages_nav_graph -> "direct_messages_nav_graph"
R.id.feed_nav_graph -> "feed_nav_graph"
R.id.profile_nav_graph -> "profile_nav_graph"
R.id.discover_nav_graph -> "discover_nav_graph"
R.id.more_nav_graph -> "more_nav_graph"
R.id.favorites_nav_graph -> "favorites_nav_graph"
R.id.notification_viewer_nav_graph -> "notification_viewer_nav_graph"
else -> ""
}
private fun geNavGraphNameForNavRootId(navGraphName: String): Int = when (navGraphName) {
"direct_messages_nav_graph" -> R.id.direct_messages_nav_graph
"feed_nav_graph" -> R.id.feed_nav_graph
"profile_nav_graph" -> R.id.profile_nav_graph
"discover_nav_graph" -> R.id.discover_nav_graph
"more_nav_graph" -> R.id.more_nav_graph
"favorites_nav_graph" -> R.id.favorites_nav_graph
"notification_viewer_nav_graph" -> R.id.notification_viewer_nav_graph
else -> 0
}
private fun getOrderedNavRootIdsFromPref(navGraphNames: List<String>): Pair<List<String>, List<Int>> {
tabOrderString = Utils.settingsHelper.getString(PreferenceKeys.PREF_TAB_ORDER)
if (tabOrderString.isNullOrBlank()) {
// Use top 5 entries for default list
val top5navGraphNames: List<String> = navGraphNames.subList(0, 5)
val newOrderString = top5navGraphNames.joinToString(",")
Utils.settingsHelper.putString(PreferenceKeys.PREF_TAB_ORDER, newOrderString)
tabOrderString = newOrderString
return top5navGraphNames to top5navGraphNames.map(::geNavGraphNameForNavRootId)
}
val orderString = tabOrderString ?: return navGraphNames to navGraphNames.subList(0, 5).map(::geNavGraphNameForNavRootId)
// Make sure that the list from preference does not contain any invalid values
val orderGraphNames = orderString
.split(",")
.asSequence()
.filter(String::isNotBlank)
.filter(navGraphNames::contains)
.toList()
val graphNames = if (orderGraphNames.isEmpty()) {
// Use top 5 entries for default list
navGraphNames.subList(0, 5)
} else orderGraphNames
return graphNames to graphNames.map(::geNavGraphNameForNavRootId)
}
fun isNavRootInCurrentTabs(navRootString: String?): Boolean {
val navRoot = navRootString ?: return false
return tabOrderString?.contains(navRoot) ?: false
}

View File

@ -8,7 +8,6 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
@ -46,8 +45,6 @@ import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat;
import com.google.android.exoplayer2.database.ExoDatabaseProvider;
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor;
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import org.json.JSONObject;
@ -55,22 +52,15 @@ import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import awais.instagrabber.R;
import awais.instagrabber.fragments.settings.PreferenceKeys;
import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.models.Tab;
import awais.instagrabber.models.enums.FavoriteType;
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_BARINSTA_DIR_URI;
public final class Utils {
private static final String TAG = "Utils";
private static final int VIDEO_CACHE_MAX_BYTES = 10 * 1024 * 1024;
@ -85,7 +75,6 @@ public final class Utils {
private static int statusBarHeight;
private static int actionBarHeight;
public static String cacheDir;
public static String tabOrderString;
private static int defaultStatusBarColor;
private static Object[] volumes;
@ -421,115 +410,6 @@ public final class Utils {
}
}
private static final List<Integer> NON_REMOVABLE_NAV_ROOT_IDS = ImmutableList.of(R.id.profile_nav_graph, R.id.more_nav_graph);
@NonNull
public static Pair<List<Tab>, List<Tab>> getNavTabList(@NonNull final Context context) {
final Resources resources = context.getResources();
final String[] titleArray = resources.getStringArray(R.array.main_nav_titles);
TypedArray typedArray = resources.obtainTypedArray(R.array.main_nav_graphs);
int length = typedArray.length();
final String[] navGraphNames = new String[length];
final int[] navigationResIds = new int[length];
for (int i = 0; i < length; i++) {
final int resourceId = typedArray.getResourceId(i, 0);
if (resourceId == 0) continue;
navigationResIds[i] = resourceId;
navGraphNames[i] = resources.getResourceEntryName(resourceId);
}
typedArray.recycle();
typedArray = resources.obtainTypedArray(R.array.main_nav_graph_root_ids);
length = typedArray.length();
final int[] navRootIds = new int[length];
for (int i = 0; i < length; i++) {
final int resourceId = typedArray.getResourceId(i, 0);
if (resourceId == 0) continue;
navRootIds[i] = resourceId;
}
typedArray.recycle();
typedArray = resources.obtainTypedArray(R.array.main_nav_drawables);
length = typedArray.length();
final int[] iconIds = new int[length];
for (int i = 0; i < length; i++) {
final int resourceId = typedArray.getResourceId(i, 0);
if (resourceId == 0) continue;
iconIds[i] = resourceId;
}
typedArray.recycle();
typedArray = resources.obtainTypedArray(R.array.main_nav_start_dest_frag_ids);
length = typedArray.length();
final int[] startDestFragIds = new int[length];
for (int i = 0; i < length; i++) {
final int resourceId = typedArray.getResourceId(i, 0);
if (resourceId == 0) continue;
startDestFragIds[i] = resourceId;
}
typedArray.recycle();
final List<String> currentOrderGraphNames = getCurrentOrderOfGraphNamesFromPref(navGraphNames);
if (titleArray.length != iconIds.length || titleArray.length != navGraphNames.length) {
throw new RuntimeException(String.format("Array lengths don't match!: titleArray%s, navGraphNames: %s, iconIds: %s",
Arrays.toString(titleArray), Arrays.toString(navGraphNames), Arrays.toString(iconIds)));
}
final List<Tab> tabs = new ArrayList<>();
final List<Tab> otherTabs = new ArrayList<>(); // Will contain tabs not in current list
for (int i = 0; i < length; i++) {
final String navGraphName = navGraphNames[i];
final int navRootId = navRootIds[i];
final Tab tab = new Tab(iconIds[i],
titleArray[i],
!NON_REMOVABLE_NAV_ROOT_IDS.contains(navRootId),
navGraphName,
navigationResIds[i],
navRootId,
startDestFragIds[i]);
if (!currentOrderGraphNames.contains(navGraphName)) {
otherTabs.add(tab);
continue;
}
tabs.add(tab);
}
Collections.sort(tabs, Ordering.explicit(currentOrderGraphNames).onResultOf(tab -> {
if (tab == null) return null;
return tab.getGraphName();
}));
return new Pair<>(tabs, otherTabs);
}
@NonNull
private static List<String> getCurrentOrderOfGraphNamesFromPref(@NonNull final String[] navGraphNames) {
tabOrderString = settingsHelper.getString(PreferenceKeys.PREF_TAB_ORDER);
final List<String> navGraphNameList = Arrays.asList(navGraphNames);
if (TextUtils.isEmpty(tabOrderString)) {
// Use top 5 entries for default list
final List<String> top5navGraphNames = navGraphNameList.subList(0, 5);
final String newOrderString = android.text.TextUtils.join(",", top5navGraphNames);
Utils.settingsHelper.putString(PreferenceKeys.PREF_TAB_ORDER, newOrderString);
tabOrderString = newOrderString;
return top5navGraphNames;
}
// Make sure that the list from preference does not contain any invalid values
final List<String> orderGraphNames = Arrays.stream(tabOrderString.split(","))
.filter(s -> !TextUtils.isEmpty(s))
.filter(navGraphNameList::contains)
.collect(Collectors.toList());
if (orderGraphNames.isEmpty()) {
// Use top 5 entries for default list
return navGraphNameList.subList(0, 5);
}
return orderGraphNames;
}
public static boolean isNavRootInCurrentTabs(final String navRootString) {
if (navRootString == null || tabOrderString == null) return false;
return tabOrderString.contains(navRootString);
}
// public static void scanDocumentFile(@NonNull final Context context,
// @NonNull final DocumentFile documentFile,
// @NonNull final OnScanCompletedListener callback) {

View File

@ -21,7 +21,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import awais.instagrabber.R;
import awais.instagrabber.fragments.UserSearchFragment;
import awais.instagrabber.fragments.UserSearchMode;
import awais.instagrabber.models.Resource;
import awais.instagrabber.repositories.responses.User;
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient;
@ -49,7 +49,7 @@ public class UserSearchViewModel extends ViewModel {
private Call<?> searchRequest;
private long[] hideUserIds;
private String[] hideThreadIds;
private UserSearchFragment.SearchMode searchMode;
private UserSearchMode searchMode;
private boolean showGroups;
private boolean waitingForCache;
private boolean showCachedResults;
@ -192,7 +192,7 @@ public class UserSearchViewModel extends ViewModel {
private void rankedRecipientSearch() {
directMessagesRepository.rankedRecipients(
searchMode.getName(),
searchMode.name(),
showGroups,
currentQuery,
CoroutineUtilsKt.getContinuation((response, throwable) -> {
@ -290,7 +290,7 @@ public class UserSearchViewModel extends ViewModel {
return showAction;
}
public void setSearchMode(final UserSearchFragment.SearchMode searchMode) {
public void setSearchMode(final UserSearchMode searchMode) {
this.searchMode = searchMode;
}

View File

@ -60,9 +60,11 @@
<androidx.fragment.app.FragmentContainerView
android:id="@+id/main_nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:defaultNavHost="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<!--app:layout_behavior="@string/hide_bottom_view_on_scroll_behavior"-->

View File

@ -1,78 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/comments_nav_graph"
app:startDestination="@id/commentsViewerFragment">
<!--<include app:graph="@navigation/hashtag_nav_graph" />-->
<action
android:id="@+id/action_global_hashTagFragment"
app:destination="@id/hashtag_nav_graph">
<argument
android:name="hashtag"
app:argType="string"
app:nullable="false" />
</action>
<!--<include app:graph="@navigation/profile_nav_graph" />-->
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">
<argument
android:name="username"
app:argType="string"
app:nullable="true" />
</action>
<dialog
android:id="@+id/commentsViewerFragment"
android:name="awais.instagrabber.fragments.comments.CommentsViewerFragment"
android:label="Comments"
tools:layout="@layout/fragment_comments">
<argument
android:name="shortCode"
app:argType="string"
app:nullable="false" />
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="postUserId"
app:argType="long" />
</dialog>
<action
android:id="@+id/action_global_commentsViewerFragment"
app:destination="@id/commentsViewerFragment">
<argument
android:name="shortCode"
app:argType="string"
app:nullable="false" />
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="postUserId"
app:argType="long" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="isComment"
app:argType="boolean"
app:nullable="false" />
</action>
</navigation>

View File

@ -1,216 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/direct_messages_nav_graph"
app:startDestination="@id/directMessagesInboxFragment">
<include app:graph="@navigation/profile_nav_graph" />
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph" />
<include app:graph="@navigation/location_nav_graph" />
<action
android:id="@+id/action_global_locationFragment"
app:destination="@id/location_nav_graph">
<argument
android:name="locationId"
app:argType="long" />
</action>
<include app:graph="@navigation/hashtag_nav_graph" />
<action
android:id="@+id/action_global_hashTagFragment"
app:destination="@id/hashtag_nav_graph">
<argument
android:name="hashtag"
app:argType="string"
app:nullable="false" />
</action>
<include app:graph="@navigation/notification_viewer_nav_graph" />
<action
android:id="@+id/action_global_notificationsViewerFragment"
app:destination="@id/notification_viewer_nav_graph">
<argument
android:name="type"
app:argType="string"
app:nullable="false" />
<argument
android:name="targetId"
android:defaultValue="0L"
app:argType="long" />
</action>
<include app:graph="@navigation/comments_nav_graph" />
<action
android:id="@+id/action_global_commentsViewerFragment"
app:destination="@id/comments_nav_graph">
<argument
android:name="shortCode"
app:argType="string"
app:nullable="false" />
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="postUserId"
app:argType="long" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="isComment"
app:argType="boolean"
app:nullable="false" />
</action>
<include app:graph="@navigation/saved_nav_graph" />
<action
android:id="@+id/action_global_savedCollectionsFragment"
app:destination="@id/saved_nav_graph">
<argument
android:name="isSaving"
app:argType="boolean" />
</action>
<include app:graph="@navigation/user_search_nav_graph" />
<action
android:id="@+id/action_global_user_search"
app:destination="@id/user_search_nav_graph" />
<action
android:id="@+id/action_global_search"
app:destination="@id/searchFragment" />
<action
android:id="@+id/action_global_post_view"
app:destination="@id/postViewFragment">
<argument
android:name="media"
app:argType="awais.instagrabber.repositories.responses.Media"
app:nullable="false" />
<argument
android:name="position"
app:argType="integer" />
</action>
<fragment
android:id="@+id/directMessagesInboxFragment"
android:name="awais.instagrabber.fragments.directmessages.DirectMessageInboxFragment"
android:label="@string/action_dms"
tools:layout="@layout/fragment_direct_messages_inbox">
<action
android:id="@+id/action_inbox_to_thread"
app:destination="@id/directMessagesThreadFragment" />
<action
android:id="@+id/action_inbox_to_pending_inbox"
app:destination="@id/directPendingInboxFragment" />
</fragment>
<fragment
android:id="@+id/directMessagesThreadFragment"
android:name="awais.instagrabber.fragments.directmessages.DirectMessageThreadFragment"
tools:layout="@layout/fragment_direct_messages_thread">
<argument
android:name="threadId"
app:argType="string" />
<argument
android:name="title"
app:argType="string" />
<argument
android:name="pending"
android:defaultValue="false"
app:argType="boolean" />
<action
android:id="@+id/action_thread_to_settings"
app:destination="@id/directMessagesSettingsFragment" />
<action
android:id="@+id/action_thread_to_image_edit"
app:destination="@id/imageEditFragment" />
<action
android:id="@+id/action_thread_to_story"
app:destination="@id/storyViewerFragment" />
</fragment>
<fragment
android:id="@+id/directMessagesSettingsFragment"
android:name="awais.instagrabber.fragments.directmessages.DirectMessageSettingsFragment"
android:label="@string/details"
tools:layout="@layout/fragment_direct_messages_settings">
<argument
android:name="threadId"
app:argType="string"
app:nullable="false" />
<argument
android:name="title"
app:argType="string"
app:nullable="true" />
<argument
android:name="pending"
android:defaultValue="false"
app:argType="boolean" />
<action
android:id="@+id/action_settings_to_inbox"
app:destination="@id/directMessagesInboxFragment"
app:popUpTo="@+id/directMessagesInboxFragment"
app:popUpToInclusive="true" />
</fragment>
<fragment
android:id="@+id/imageEditFragment"
android:name="awais.instagrabber.fragments.imageedit.ImageEditFragment"
android:label="Edit Photo"
tools:layout="@layout/fragment_image_edit">
<argument
android:name="uri"
app:argType="android.net.Uri"
app:nullable="false" />
</fragment>
<fragment
android:id="@+id/storyViewerFragment"
android:name="awais.instagrabber.fragments.StoryViewerFragment"
android:label="StoryViewerFragment"
tools:layout="@layout/fragment_story_viewer">
<argument
android:name="options"
app:argType="awais.instagrabber.repositories.requests.StoryViewerOptions" />
</fragment>
<fragment
android:id="@+id/directPendingInboxFragment"
android:name="awais.instagrabber.fragments.directmessages.DirectPendingInboxFragment"
android:label="@string/pending_requests"
tools:layout="@layout/fragment_direct_pending_inbox">
<action
android:id="@+id/action_pending_inbox_to_thread"
app:destination="@id/directMessagesThreadFragment" />
</fragment>
<fragment
android:id="@+id/searchFragment"
android:name="awais.instagrabber.fragments.search.SearchFragment"
android:label="@string/search"
tools:layout="@layout/fragment_search" />
<fragment
android:id="@+id/postViewFragment"
android:name="awais.instagrabber.fragments.PostViewV2Fragment"
android:label="@string/post"
tools:layout="@layout/dialog_post_view" />
</navigation>

View File

@ -1,155 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/discover_nav_graph"
app:startDestination="@id/discoverFragment">
<include app:graph="@navigation/hashtag_nav_graph" />
<action
android:id="@+id/action_global_hashTagFragment"
app:destination="@id/hashtag_nav_graph">
<argument
android:name="hashtag"
app:argType="string"
app:nullable="false" />
</action>
<include app:graph="@navigation/profile_nav_graph" />
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">
<argument
android:name="username"
app:argType="string"
app:nullable="true" />
</action>
<include app:graph="@navigation/location_nav_graph" />
<action
android:id="@+id/action_global_locationFragment"
app:destination="@id/location_nav_graph">
<argument
android:name="locationId"
app:argType="long" />
</action>
<include app:graph="@navigation/comments_nav_graph" />
<action
android:id="@+id/action_global_commentsViewerFragment"
app:destination="@id/comments_nav_graph">
<argument
android:name="shortCode"
app:argType="string"
app:nullable="false" />
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="postUserId"
app:argType="long" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="isComment"
app:argType="boolean"
app:nullable="false" />
</action>
<include app:graph="@navigation/saved_nav_graph" />
<action
android:id="@+id/action_global_savedCollectionsFragment"
app:destination="@id/saved_nav_graph">
<argument
android:name="isSaving"
app:argType="boolean" />
</action>
<include app:graph="@navigation/notification_viewer_nav_graph" />
<action
android:id="@+id/action_global_notificationsViewerFragment"
app:destination="@id/notification_viewer_nav_graph">
<argument
android:name="type"
app:argType="string"
app:nullable="false" />
<argument
android:name="targetId"
android:defaultValue="0L"
app:argType="long" />
</action>
<action
android:id="@+id/action_global_search"
app:destination="@id/searchFragment" />
<action
android:id="@+id/action_global_post_view"
app:destination="@id/postViewFragment">
<argument
android:name="media"
app:argType="awais.instagrabber.repositories.responses.Media"
app:nullable="false" />
<argument
android:name="position"
app:argType="integer" />
</action>
<include app:graph="@navigation/user_search_nav_graph" />
<action
android:id="@+id/action_global_user_search"
app:destination="@id/user_search_nav_graph" />
<fragment
android:id="@+id/discoverFragment"
android:name="awais.instagrabber.fragments.main.DiscoverFragment"
android:label="@string/title_discover"
tools:layout="@layout/fragment_discover">
<action
android:id="@+id/action_discoverFragment_to_topicPostsFragment"
app:destination="@id/topicPostsFragment" />
</fragment>
<fragment
android:id="@+id/topicPostsFragment"
android:name="awais.instagrabber.fragments.TopicPostsFragment"
tools:layout="@layout/fragment_topic_posts">
<argument
android:name="topicCluster"
app:argType="awais.instagrabber.repositories.responses.discover.TopicCluster" />
<argument
android:name="titleColor"
app:argType="integer" />
<argument
android:name="backgroundColor"
app:argType="integer" />
</fragment>
<fragment
android:id="@+id/searchFragment"
android:name="awais.instagrabber.fragments.search.SearchFragment"
android:label="@string/search"
tools:layout="@layout/fragment_search" />
<fragment
android:id="@+id/postViewFragment"
android:name="awais.instagrabber.fragments.PostViewV2Fragment"
android:label="@string/post"
tools:layout="@layout/dialog_post_view" />
</navigation>

View File

@ -1,70 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/favorites_nav_graph"
app:startDestination="@id/favoritesFragment">
<include app:graph="@navigation/profile_nav_graph" />
<include app:graph="@navigation/hashtag_nav_graph" />
<include app:graph="@navigation/location_nav_graph" />
<include app:graph="@navigation/comments_nav_graph" />
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">
<argument
android:name="username"
app:argType="string"
app:nullable="true" />
</action>
<action
android:id="@+id/action_global_hashTagFragment"
app:destination="@id/hashtag_nav_graph">
<argument
android:name="hashtag"
app:argType="string"
app:nullable="false" />
</action>
<action
android:id="@+id/action_global_locationFragment"
app:destination="@id/location_nav_graph">
<argument
android:name="locationId"
app:argType="long" />
</action>
<action
android:id="@+id/action_global_search"
app:destination="@id/searchFragment" />
<action
android:id="@+id/action_global_post_view"
app:destination="@id/postViewFragment">
<argument
android:name="media"
app:argType="awais.instagrabber.repositories.responses.Media"
app:nullable="false" />
<argument
android:name="position"
app:argType="integer" />
</action>
<fragment
android:id="@+id/favoritesFragment"
android:name="awais.instagrabber.fragments.FavoritesFragment"
android:label="@string/title_favorites"
tools:layout="@layout/fragment_favorites" />
<fragment
android:id="@+id/searchFragment"
android:name="awais.instagrabber.fragments.search.SearchFragment"
android:label="@string/search"
tools:layout="@layout/fragment_search" />
<fragment
android:id="@+id/postViewFragment"
android:name="awais.instagrabber.fragments.PostViewV2Fragment"
android:label="@string/post" />
</navigation>

View File

@ -1,159 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/feed_nav_graph"
app:startDestination="@id/feedFragment">
<include app:graph="@navigation/hashtag_nav_graph" />
<action
android:id="@+id/action_global_hashTagFragment"
app:destination="@id/hashtag_nav_graph">
<argument
android:name="hashtag"
app:argType="string"
app:nullable="false" />
</action>
<include app:graph="@navigation/profile_nav_graph" />
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">
<argument
android:name="username"
app:argType="string"
app:nullable="true" />
</action>
<include app:graph="@navigation/location_nav_graph" />
<action
android:id="@+id/action_global_locationFragment"
app:destination="@id/location_nav_graph">
<argument
android:name="locationId"
app:argType="long" />
</action>
<include app:graph="@navigation/comments_nav_graph" />
<action
android:id="@+id/action_global_commentsViewerFragment"
app:destination="@id/comments_nav_graph">
<argument
android:name="shortCode"
app:argType="string"
app:nullable="false" />
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="postUserId"
app:argType="long" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="isComment"
app:argType="boolean"
app:nullable="false" />
</action>
<include app:graph="@navigation/saved_nav_graph" />
<action
android:id="@+id/action_global_savedCollectionsFragment"
app:destination="@id/saved_nav_graph">
<argument
android:name="isSaving"
app:argType="boolean" />
</action>
<include app:graph="@navigation/notification_viewer_nav_graph" />
<action
android:id="@+id/action_global_notificationsViewerFragment"
app:destination="@id/notification_viewer_nav_graph">
<argument
android:name="type"
app:argType="string"
app:nullable="false" />
<argument
android:name="targetId"
android:defaultValue="0L"
app:argType="long" />
</action>
<include app:graph="@navigation/story_list_nav_graph" />
<action
android:id="@+id/action_global_storyListViewerFragment"
app:destination="@id/story_list_nav_graph">
<argument
android:name="type"
app:argType="string"
app:nullable="false" />
</action>
<action
android:id="@+id/action_global_search"
app:destination="@id/searchFragment" />
<action
android:id="@+id/action_global_post_view"
app:destination="@id/postViewFragment">
<argument
android:name="media"
app:argType="awais.instagrabber.repositories.responses.Media"
app:nullable="false" />
<argument
android:name="position"
app:argType="integer" />
</action>
<include app:graph="@navigation/user_search_nav_graph" />
<action
android:id="@+id/action_global_user_search"
app:destination="@id/user_search_nav_graph" />
<fragment
android:id="@+id/feedFragment"
android:name="awais.instagrabber.fragments.main.FeedFragment"
android:label="@string/feed"
tools:layout="@layout/fragment_feed">
<action
android:id="@+id/action_feedFragment_to_storyViewerFragment"
app:destination="@id/storyViewerFragment" />
</fragment>
<fragment
android:id="@+id/storyViewerFragment"
android:name="awais.instagrabber.fragments.StoryViewerFragment"
android:label="StoryViewerFragment"
tools:layout="@layout/fragment_story_viewer">
<argument
android:name="options"
app:argType="awais.instagrabber.repositories.requests.StoryViewerOptions" />
</fragment>
<fragment
android:id="@+id/searchFragment"
android:name="awais.instagrabber.fragments.search.SearchFragment"
android:label="@string/search"
tools:layout="@layout/fragment_search" />
<fragment
android:id="@+id/postViewFragment"
android:name="awais.instagrabber.fragments.PostViewV2Fragment"
android:label="@string/post"
tools:layout="@layout/dialog_post_view" />
</navigation>

View File

@ -1,130 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/hashtag_nav_graph"
app:startDestination="@id/hashTagFragment">
<include app:graph="@navigation/comments_nav_graph" />
<action
android:id="@+id/action_global_commentsViewerFragment"
app:destination="@id/comments_nav_graph">
<argument
android:name="shortCode"
app:argType="string"
app:nullable="false" />
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="postUserId"
app:argType="long" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="isComment"
app:argType="boolean"
app:nullable="false" />
</action>
<include app:graph="@navigation/saved_nav_graph" />
<action
android:id="@+id/action_global_savedCollectionsFragment"
app:destination="@id/saved_nav_graph">
<argument
android:name="isSaving"
app:argType="boolean" />
</action>
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">
<argument
android:name="username"
app:argType="string"
app:nullable="true" />
</action>
<action
android:id="@+id/action_global_locationFragment"
app:destination="@id/location_nav_graph">
<argument
android:name="locationId"
app:argType="long" />
</action>
<action
android:id="@+id/action_global_search"
app:destination="@id/searchFragment" />
<action
android:id="@+id/action_global_post_view"
app:destination="@id/postViewFragment">
<argument
android:name="media"
app:argType="awais.instagrabber.repositories.responses.Media"
app:nullable="false" />
<argument
android:name="position"
app:argType="integer" />
</action>
<include app:graph="@navigation/user_search_nav_graph" />
<action
android:id="@+id/action_global_user_search"
app:destination="@id/user_search_nav_graph" />
<fragment
android:id="@+id/hashTagFragment"
android:name="awais.instagrabber.fragments.HashTagFragment"
android:label=""
tools:layout="@layout/fragment_hashtag">
<argument
android:name="hashtag"
app:argType="string"
app:nullable="false" />
<action
android:id="@+id/action_hashtagFragment_to_storyViewerFragment"
app:destination="@id/storyViewerFragment" />
</fragment>
<fragment
android:id="@+id/storyViewerFragment"
android:name="awais.instagrabber.fragments.StoryViewerFragment"
android:label="StoryViewerFragment"
tools:layout="@layout/fragment_story_viewer">
<argument
android:name="options"
app:argType="awais.instagrabber.repositories.requests.StoryViewerOptions" />
</fragment>
<fragment
android:id="@+id/searchFragment"
android:name="awais.instagrabber.fragments.search.SearchFragment"
android:label="@string/search"
tools:layout="@layout/fragment_search" />
<action
android:id="@+id/action_global_hashTagFragment"
app:destination="@id/hashTagFragment">
<argument
android:name="hashtag"
app:argType="string"
app:nullable="false" />
</action>
<fragment
android:id="@+id/postViewFragment"
android:name="awais.instagrabber.fragments.PostViewV2Fragment"
android:label="@string/post"
tools:layout="@layout/dialog_post_view" />
</navigation>

View File

@ -1,48 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/likes_nav_graph"
app:startDestination="@id/likesViewerFragment">
<!--<include app:graph="@navigation/hashtag_nav_graph" />-->
<!--<include app:graph="@navigation/profile_nav_graph" />-->
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">
<argument
android:name="username"
app:argType="string"
app:nullable="true" />
</action>
<dialog
android:id="@+id/likesViewerFragment"
android:name="awais.instagrabber.fragments.LikesViewerFragment"
android:label="Comments"
tools:layout="@layout/fragment_likes">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="isComment"
app:argType="boolean"
app:nullable="false" />
</dialog>
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likesViewerFragment">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="isComment"
app:argType="boolean"
app:nullable="false" />
</action>
</navigation>

View File

@ -1,129 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/location_nav_graph"
app:startDestination="@id/locationFragment">
<include app:graph="@navigation/comments_nav_graph" />
<action
android:id="@+id/action_global_commentsViewerFragment"
app:destination="@id/comments_nav_graph">
<argument
android:name="shortCode"
app:argType="string"
app:nullable="false" />
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="postUserId"
app:argType="long" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="isComment"
app:argType="boolean"
app:nullable="false" />
</action>
<include app:graph="@navigation/saved_nav_graph" />
<action
android:id="@+id/action_global_savedCollectionsFragment"
app:destination="@id/saved_nav_graph">
<argument
android:name="isSaving"
app:argType="boolean" />
</action>
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">
<argument
android:name="username"
app:argType="string"
app:nullable="true" />
</action>
<action
android:id="@+id/action_global_hashTagFragment"
app:destination="@id/hashtag_nav_graph">
<argument
android:name="hashtag"
app:argType="string"
app:nullable="false" />
</action>
<action
android:id="@+id/action_global_search"
app:destination="@id/searchFragment" />
<action
android:id="@+id/action_global_post_view"
app:destination="@id/postViewFragment">
<argument
android:name="media"
app:argType="awais.instagrabber.repositories.responses.Media"
app:nullable="false" />
<argument
android:name="position"
app:argType="integer" />
</action>
<include app:graph="@navigation/user_search_nav_graph" />
<action
android:id="@+id/action_global_user_search"
app:destination="@id/user_search_nav_graph" />
<fragment
android:id="@+id/locationFragment"
android:name="awais.instagrabber.fragments.LocationFragment"
android:label=""
tools:layout="@layout/fragment_location">
<argument
android:name="locationId"
app:argType="long" />
<action
android:id="@+id/action_locationFragment_to_storyViewerFragment"
app:destination="@id/storyViewerFragment" />
</fragment>
<action
android:id="@+id/action_global_locationFragment"
app:destination="@id/locationFragment">
<argument
android:name="locationId"
app:argType="long" />
</action>
<fragment
android:id="@+id/storyViewerFragment"
android:name="awais.instagrabber.fragments.StoryViewerFragment"
android:label="StoryViewerFragment"
tools:layout="@layout/fragment_story_viewer">
<argument
android:name="options"
app:argType="awais.instagrabber.repositories.requests.StoryViewerOptions" />
</fragment>
<fragment
android:id="@+id/searchFragment"
android:name="awais.instagrabber.fragments.search.SearchFragment"
android:label="@string/search"
tools:layout="@layout/fragment_search" />
<fragment
android:id="@+id/postViewFragment"
android:name="awais.instagrabber.fragments.PostViewV2Fragment"
android:label="@string/post"
tools:layout="@layout/dialog_post_view" />
</navigation>

View File

@ -1,205 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/more_nav_graph"
app:startDestination="@id/morePreferencesFragment">
<include app:graph="@navigation/profile_nav_graph" />
<include app:graph="@navigation/hashtag_nav_graph" />
<include app:graph="@navigation/location_nav_graph" />
<include app:graph="@navigation/comments_nav_graph" />
<include app:graph="@navigation/likes_nav_graph" />
<include app:graph="@navigation/notification_viewer_nav_graph" />
<include app:graph="@navigation/story_list_nav_graph" />
<include app:graph="@navigation/discover_nav_graph" />
<action
android:id="@+id/action_global_commentsViewerFragment"
app:destination="@id/comments_nav_graph">
<argument
android:name="shortCode"
app:argType="string"
app:nullable="false" />
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="postUserId"
app:argType="long" />
</action>
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="isComment"
app:argType="boolean"
app:nullable="false" />
</action>
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">
<argument
android:name="username"
app:argType="string"
app:nullable="true" />
</action>
<action
android:id="@+id/action_global_hashTagFragment"
app:destination="@id/hashtag_nav_graph">
<argument
android:name="hashtag"
app:argType="string"
app:nullable="false" />
</action>
<action
android:id="@+id/action_global_locationFragment"
app:destination="@id/location_nav_graph">
<argument
android:name="locationId"
app:argType="long" />
</action>
<action
android:id="@+id/action_global_storyListViewerFragment"
app:destination="@id/story_list_nav_graph">
<argument
android:name="type"
app:argType="string"
app:nullable="false" />
</action>
<action
android:id="@+id/action_global_notificationsViewerFragment"
app:destination="@id/notification_viewer_nav_graph">
<argument
android:name="type"
app:argType="string"
app:nullable="false" />
<argument
android:name="targetId"
android:defaultValue="0L"
app:argType="long" />
</action>
<action
android:id="@+id/action_global_post_view"
app:destination="@id/postViewFragment">
<argument
android:name="media"
app:argType="awais.instagrabber.repositories.responses.Media"
app:nullable="false" />
<argument
android:name="position"
app:argType="integer" />
</action>
<include app:graph="@navigation/user_search_nav_graph" />
<action
android:id="@+id/action_global_user_search"
app:destination="@id/user_search_nav_graph" />
<fragment
android:id="@+id/morePreferencesFragment"
android:name="awais.instagrabber.fragments.settings.MorePreferencesFragment"
android:label="@string/more">
<action
android:id="@+id/action_morePreferencesFragment_to_settingsPreferencesFragment"
app:destination="@id/settingsPreferencesFragment" />
<action
android:id="@+id/action_morePreferencesFragment_to_aboutFragment"
app:destination="@id/aboutFragment" />
<action
android:id="@+id/action_morePreferencesFragment_to_favoritesFragment"
app:destination="@id/favoritesFragment" />
<action
android:id="@+id/action_morePreferencesFragment_to_backupPreferencesFragment"
app:destination="@id/backupPreferencesFragment" />
</fragment>
<fragment
android:id="@+id/settingsPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.SettingsPreferencesFragment"
android:label="@string/action_settings">
<action
android:id="@+id/action_settings_to_theme"
app:destination="@id/themePreferencesFragment" />
<action
android:id="@+id/action_settings_to_locale"
app:destination="@id/localePreferencesFragment" />
<action
android:id="@+id/action_settings_to_general"
app:destination="@id/generalPreferencesFragment" />
<action
android:id="@+id/action_settings_to_downloads"
app:destination="@id/downloadsPreferencesFragment" />
<action
android:id="@+id/action_settings_to_dm"
app:destination="@id/DMPreferencesFragment" />
<action
android:id="@+id/action_settings_to_stories"
app:destination="@id/storiesPreferencesFragment" />
<action
android:id="@+id/action_settings_to_notifications"
app:destination="@id/notificationsPreferencesFragment" />
<action
android:id="@+id/action_settings_to_post"
app:destination="@id/postPreferencesFragment" />
</fragment>
<fragment
android:id="@+id/aboutFragment"
android:name="awais.instagrabber.fragments.settings.AboutFragment"
android:label="@string/action_about" />
<fragment
android:id="@+id/themePreferencesFragment"
android:name="awais.instagrabber.fragments.settings.ThemePreferencesFragment"
android:label="@string/theme_settings" />
<fragment
android:id="@+id/favoritesFragment"
android:name="awais.instagrabber.fragments.FavoritesFragment"
android:label="@string/title_favorites" />
<fragment
android:id="@+id/backupPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.BackupPreferencesFragment"
android:label="@string/backup_and_restore" />
<fragment
android:id="@+id/localePreferencesFragment"
android:name="awais.instagrabber.fragments.settings.LocalePreferencesFragment"
android:label="@string/pref_category_locale" />
<fragment
android:id="@+id/generalPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.GeneralPreferencesFragment"
android:label="@string/pref_category_general" />
<fragment
android:id="@+id/downloadsPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.DownloadsPreferencesFragment"
android:label="@string/pref_category_downloads" />
<fragment
android:id="@+id/DMPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.DMPreferencesFragment"
android:label="@string/pref_category_dm" />
<fragment
android:id="@+id/storiesPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.StoriesPreferencesFragment"
android:label="@string/pref_category_stories" />
<fragment
android:id="@+id/notificationsPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.NotificationsPreferencesFragment"
android:label="@string/pref_category_notifications" />
<fragment
android:id="@+id/postPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.PostPreferencesFragment"
android:label="@string/pref_category_post" />
<fragment
android:id="@+id/postViewFragment"
android:name="awais.instagrabber.fragments.PostViewV2Fragment"
android:label="@string/post" />
</navigation>

View File

@ -0,0 +1,894 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/feedFragment">
<action
android:id="@+id/action_global_hashTag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_global_profile"
app:destination="@id/profile_non_top" />
<action
android:id="@+id/action_global_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_global_notifications"
app:destination="@id/notifications_viewer_non_top" />
<action
android:id="@+id/action_global_search"
app:destination="@id/searchFragment" />
<action
android:id="@+id/action_global_post"
app:destination="@id/postViewFragment" />
<action
android:id="@+id/action_global_direct_thread"
app:destination="@id/directMessagesThreadFragment" />
<fragment
android:id="@+id/feedFragment"
android:name="awais.instagrabber.fragments.main.FeedFragment"
android:label="@string/feed"
tools:layout="@layout/fragment_feed">
<action
android:id="@+id/action_to_story"
app:destination="@id/storyViewerFragment" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
<action
android:id="@+id/action_to_post"
app:destination="@id/postViewFragment" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_comments"
app:destination="@id/commentsViewerFragment" />
<action
android:id="@+id/action_to_story_list"
app:destination="@id/storyListViewerFragment" />
</fragment>
<fragment
android:id="@+id/storyViewerFragment"
android:name="awais.instagrabber.fragments.StoryViewerFragment"
android:label="StoryViewerFragment"
tools:layout="@layout/fragment_story_viewer">
<argument
android:name="options"
app:argType="awais.instagrabber.repositories.requests.StoryViewerOptions" />
<action
android:id="@+id/action_to_post"
app:destination="@id/postViewFragment" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
</fragment>
<fragment
android:id="@+id/searchFragment"
android:name="awais.instagrabber.fragments.search.SearchFragment"
android:label="@string/search"
tools:layout="@layout/fragment_search">
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
</fragment>
<fragment
android:id="@+id/postViewFragment"
android:name="awais.instagrabber.fragments.PostViewV2Fragment"
android:label="@string/post"
tools:layout="@layout/dialog_post_view">
<argument
android:name="media"
app:argType="awais.instagrabber.repositories.responses.Media"
app:nullable="false" />
<argument
android:name="position"
app:argType="integer" />
<action
android:id="@+id/action_to_comments"
app:destination="@id/commentsViewerFragment" />
<action
android:id="@+id/action_to_likes"
app:destination="@id/likesViewerFragment" />
<action
android:id="@+id/action_to_saved_collections"
app:destination="@id/savedCollectionsFragment" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_to_user_search"
app:destination="@id/user_search" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
</fragment>
<fragment
android:id="@+id/locationFragment"
android:name="awais.instagrabber.fragments.LocationFragment"
android:label=""
tools:layout="@layout/fragment_location">
<argument
android:name="locationId"
app:argType="long" />
<action
android:id="@+id/action_to_story"
app:destination="@id/storyViewerFragment" />
<action
android:id="@+id/action_to_comments"
app:destination="@id/commentsViewerFragment" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_to_post"
app:destination="@id/postViewFragment" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
</fragment>
<fragment
android:id="@+id/hashTagFragment"
android:name="awais.instagrabber.fragments.HashTagFragment"
android:label=""
tools:layout="@layout/fragment_hashtag">
<argument
android:name="hashtag"
app:argType="string"
app:nullable="false" />
<action
android:id="@+id/action_to_story"
app:destination="@id/storyViewerFragment" />
<action
android:id="@+id/action_to_post"
app:destination="@id/postViewFragment" />
<action
android:id="@+id/action_to_comments"
app:destination="@id/commentsViewerFragment" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
</fragment>
<dialog
android:id="@+id/commentsViewerFragment"
android:name="awais.instagrabber.fragments.comments.CommentsViewerFragment"
android:label="Comments"
tools:layout="@layout/fragment_comments">
<argument
android:name="shortCode"
app:argType="string"
app:nullable="false" />
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="postUserId"
app:argType="long" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_likes"
app:destination="@id/likesViewerFragment" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
</dialog>
<fragment
android:id="@+id/profileFragment"
android:name="awais.instagrabber.fragments.main.ProfileFragment"
android:label="@string/profile"
tools:layout="@layout/fragment_profile">
<argument
android:name="username"
android:defaultValue=""
app:argType="string"
app:nullable="true" />
<action
android:id="@+id/action_to_saved"
app:destination="@id/savedViewerFragment" />
<action
android:id="@+id/action_to_saved_collections"
app:destination="@id/savedCollectionsFragment" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_follow_viewer"
app:destination="@id/followViewerFragment" />
<action
android:id="@+id/action_to_story"
app:destination="@id/storyViewerFragment" />
<action
android:id="@+id/action_to_post"
app:destination="@id/postViewFragment" />
<action
android:id="@+id/action_to_comments"
app:destination="@id/commentsViewerFragment" />
<action
android:id="@+id/action_to_user_search"
app:destination="@id/user_search" />
<action
android:id="@+id/action_to_notifications"
app:destination="@id/notifications_viewer_non_top" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
</fragment>
<!-- Copy of profile fragment tag -->
<!-- Required to get back arrow in action bar -->
<!-- See https://issuetracker.google.com/issues/192395936 -->
<fragment
android:id="@+id/profile_non_top"
android:name="awais.instagrabber.fragments.main.ProfileFragment"
android:label="@string/profile"
tools:layout="@layout/fragment_profile">
<argument
android:name="username"
android:defaultValue=""
app:argType="string"
app:nullable="true" />
<action
android:id="@+id/action_to_saved"
app:destination="@id/savedViewerFragment" />
<action
android:id="@+id/action_to_saved_collections"
app:destination="@id/savedCollectionsFragment" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_follow_viewer"
app:destination="@id/followViewerFragment" />
<action
android:id="@+id/action_to_story"
app:destination="@id/storyViewerFragment" />
<action
android:id="@+id/action_to_post"
app:destination="@id/postViewFragment" />
<action
android:id="@+id/action_to_comments"
app:destination="@id/commentsViewerFragment" />
<action
android:id="@+id/action_to_user_search"
app:destination="@id/user_search" />
<action
android:id="@+id/action_to_notifications"
app:destination="@id/notifications_viewer_non_top" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
</fragment>
<fragment
android:id="@+id/savedViewerFragment"
android:name="awais.instagrabber.fragments.SavedViewerFragment"
android:label="Saved"
tools:layout="@layout/fragment_saved">
<argument
android:name="username"
app:argType="string"
app:nullable="false" />
<argument
android:name="profileId"
app:argType="long" />
<argument
android:name="type"
app:argType="awais.instagrabber.models.enums.PostItemType"
app:nullable="false" />
<action
android:id="@+id/action_to_comments"
app:destination="@id/commentsViewerFragment" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_to_post"
app:destination="@id/postViewFragment" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
</fragment>
<fragment
android:id="@+id/followViewerFragment"
android:name="awais.instagrabber.fragments.FollowViewerFragment"
android:label=""
tools:layout="@layout/fragment_followers_viewer">
<argument
android:name="profileId"
app:argType="long" />
<argument
android:name="isFollowersList"
app:argType="boolean"
app:nullable="false" />
<argument
android:name="username"
app:argType="string"
app:nullable="false" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
</fragment>
<dialog
android:id="@+id/likesViewerFragment"
android:name="awais.instagrabber.fragments.LikesViewerFragment"
android:label="Comments"
tools:layout="@layout/fragment_likes">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="isComment"
app:argType="boolean"
app:nullable="false" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
</dialog>
<fragment
android:id="@+id/discoverFragment"
android:name="awais.instagrabber.fragments.main.DiscoverFragment"
android:label="@string/title_discover"
tools:layout="@layout/fragment_discover">
<action
android:id="@+id/action_to_topic_posts"
app:destination="@id/topicPostsFragment" />
<action
android:id="@+id/action_to_post"
app:destination="@id/postViewFragment" />
</fragment>
<fragment
android:id="@+id/topicPostsFragment"
android:name="awais.instagrabber.fragments.TopicPostsFragment"
tools:layout="@layout/fragment_topic_posts">
<argument
android:name="topicCluster"
app:argType="awais.instagrabber.repositories.responses.discover.TopicCluster" />
<argument
android:name="titleColor"
app:argType="integer" />
<argument
android:name="backgroundColor"
app:argType="integer" />
<action
android:id="@+id/action_to_comments"
app:destination="@id/commentsViewerFragment" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
</fragment>
<fragment
android:id="@+id/favoritesFragment"
android:name="awais.instagrabber.fragments.FavoritesFragment"
android:label="@string/title_favorites"
tools:layout="@layout/fragment_favorites">
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
</fragment>
<!-- Copy of favorites fragment tag -->
<!-- Required to get back arrow in action bar -->
<!-- See https://issuetracker.google.com/issues/192395936 -->
<fragment
android:id="@+id/favorites_non_top"
android:name="awais.instagrabber.fragments.FavoritesFragment"
android:label="@string/title_favorites"
tools:layout="@layout/fragment_favorites">
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
</fragment>
<fragment
android:id="@+id/notificationsViewer"
android:name="awais.instagrabber.fragments.NotificationsViewerFragment"
android:label="@string/title_notifications"
tools:layout="@layout/fragment_notifications_viewer">
<argument
android:name="type"
android:defaultValue="notif"
app:argType="string"
app:nullable="false" />
<argument
android:name="targetId"
android:defaultValue="0L"
app:argType="long" />
<action
android:id="@+id/action_to_story"
app:destination="@id/storyViewerFragment" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
<action
android:id="@+id/action_to_post"
app:destination="@id/postViewFragment" />
</fragment>
<!-- Copy of notification viewer fragment tag -->
<!-- Required to get back arrow in action bar -->
<!-- See https://issuetracker.google.com/issues/192395936 -->
<fragment
android:id="@+id/notifications_viewer_non_top"
android:name="awais.instagrabber.fragments.NotificationsViewerFragment"
android:label="@string/title_notifications"
tools:layout="@layout/fragment_notifications_viewer">
<argument
android:name="type"
android:defaultValue="notif"
app:argType="string"
app:nullable="false" />
<argument
android:name="targetId"
android:defaultValue="0L"
app:argType="long" />
<action
android:id="@+id/action_to_story"
app:destination="@id/storyViewerFragment" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
<action
android:id="@+id/action_to_post"
app:destination="@id/postViewFragment" />
</fragment>
<fragment
android:id="@+id/savedCollectionsFragment"
android:name="awais.instagrabber.fragments.SavedCollectionsFragment"
android:label="@string/saved"
tools:layout="@layout/fragment_saved_collections">
<argument
android:name="isSaving"
android:defaultValue="false"
app:argType="boolean" />
<action
android:id="@+id/action_to_collection_posts"
app:destination="@id/collectionPostsFragment" />
</fragment>
<fragment
android:id="@+id/collectionPostsFragment"
android:name="awais.instagrabber.fragments.CollectionPostsFragment"
tools:layout="@layout/fragment_collection_posts">
<argument
android:name="savedCollection"
app:argType="awais.instagrabber.repositories.responses.saved.SavedCollection" />
<argument
android:name="titleColor"
app:argType="integer" />
<argument
android:name="backgroundColor"
app:argType="integer" />
<action
android:id="@+id/action_to_comments"
app:destination="@id/commentsViewerFragment" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_to_post"
app:destination="@id/postViewFragment" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
</fragment>
<fragment
android:id="@+id/storyListViewerFragment"
android:name="awais.instagrabber.fragments.StoryListViewerFragment"
android:label="Stories"
tools:layout="@layout/fragment_story_list_viewer">
<argument
android:name="type"
app:argType="string"
app:nullable="false" />
<action
android:id="@+id/action_to_story"
app:destination="@id/storyViewerFragment" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
</fragment>
<fragment
android:id="@+id/directMessagesInboxFragment"
android:name="awais.instagrabber.fragments.directmessages.DirectMessageInboxFragment"
android:label="@string/action_dms"
tools:layout="@layout/fragment_direct_messages_inbox">
<action
android:id="@+id/action_to_thread"
app:destination="@id/directMessagesThreadFragment" />
<action
android:id="@+id/action_to_pending_inbox"
app:destination="@id/directPendingInboxFragment" />
</fragment>
<fragment
android:id="@+id/directMessagesThreadFragment"
android:name="awais.instagrabber.fragments.directmessages.DirectMessageThreadFragment"
tools:layout="@layout/fragment_direct_messages_thread">
<argument
android:name="threadId"
app:argType="string" />
<argument
android:name="title"
app:argType="string" />
<argument
android:name="pending"
android:defaultValue="false"
app:argType="boolean" />
<action
android:id="@+id/action_to_settings"
app:destination="@id/directMessagesSettingsFragment" />
<action
android:id="@+id/action_to_image_edit"
app:destination="@id/imageEditFragment" />
<action
android:id="@+id/action_to_story"
app:destination="@id/storyViewerFragment" />
<action
android:id="@+id/action_to_hashtag"
app:destination="@id/hashTagFragment" />
<action
android:id="@+id/action_to_location"
app:destination="@id/locationFragment" />
<action
android:id="@+id/action_to_post"
app:destination="@id/postViewFragment" />
<action
android:id="@+id/action_to_user_search"
app:destination="@id/user_search" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
</fragment>
<fragment
android:id="@+id/directMessagesSettingsFragment"
android:name="awais.instagrabber.fragments.directmessages.DirectMessageSettingsFragment"
android:label="@string/details"
tools:layout="@layout/fragment_direct_messages_settings">
<argument
android:name="threadId"
app:argType="string"
app:nullable="false" />
<argument
android:name="title"
app:argType="string"
app:nullable="true" />
<argument
android:name="pending"
android:defaultValue="false"
app:argType="boolean" />
<action
android:id="@+id/action_to_inbox"
app:destination="@id/directMessagesInboxFragment"
app:popUpTo="@+id/directMessagesInboxFragment"
app:popUpToInclusive="true" />
<action
android:id="@+id/action_to_user_search"
app:destination="@id/user_search" />
<action
android:id="@+id/action_to_profile"
app:destination="@id/profile_non_top" />
</fragment>
<fragment
android:id="@+id/imageEditFragment"
android:name="awais.instagrabber.fragments.imageedit.ImageEditFragment"
android:label="Edit Photo"
tools:layout="@layout/fragment_image_edit">
<argument
android:name="uri"
app:argType="android.net.Uri"
app:nullable="false" />
</fragment>
<fragment
android:id="@+id/directPendingInboxFragment"
android:name="awais.instagrabber.fragments.directmessages.DirectPendingInboxFragment"
android:label="@string/pending_requests"
tools:layout="@layout/fragment_direct_pending_inbox">
<action
android:id="@+id/action_to_thread"
app:destination="@id/directMessagesThreadFragment" />
</fragment>
<fragment
android:id="@+id/user_search"
android:name="awais.instagrabber.fragments.UserSearchFragment"
android:label="@string/search"
tools:layout="@layout/fragment_user_search">
<argument
android:name="multiple"
android:defaultValue="false"
app:argType="boolean" />
<argument
android:name="title"
android:defaultValue="@null"
app:argType="string"
app:nullable="true" />
<argument
android:name="action_label"
android:defaultValue="@null"
app:argType="string"
app:nullable="true" />
<argument
android:name="show_groups"
android:defaultValue="false"
app:argType="boolean" />
<argument
android:name="search_mode"
android:defaultValue="USER_SEARCH"
app:argType="awais.instagrabber.fragments.UserSearchMode" />
<argument
android:name="hideUserIds"
android:defaultValue="@null"
app:argType="long[]"
app:nullable="true" />
<argument
android:name="hideThreadIds"
android:defaultValue="@null"
app:argType="string[]"
app:nullable="true" />
</fragment>
<include app:graph="@navigation/settings_nav_graph" />
<fragment
android:id="@+id/morePreferencesFragment"
android:name="awais.instagrabber.fragments.settings.MorePreferencesFragment"
android:label="@string/more">
<action
android:id="@+id/action_to_settings"
app:destination="@id/settings_nav_graph" />
<action
android:id="@+id/action_to_about"
app:destination="@id/aboutFragment" />
<action
android:id="@+id/action_to_favorites"
app:destination="@id/favorites_non_top" />
<action
android:id="@+id/action_to_backup"
app:destination="@id/backupPreferencesFragment" />
<action
android:id="@+id/action_to_notifications"
app:destination="@id/notifications_viewer_non_top" />
<action
android:id="@+id/action_to_story_list"
app:destination="@id/storyListViewerFragment" />
</fragment>
</navigation>

View File

@ -1,126 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/notification_viewer_nav_graph"
app:startDestination="@id/notificationsViewer">
<include app:graph="@navigation/profile_nav_graph" />
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">
<argument
android:name="username"
app:argType="string"
app:nullable="false" />
</action>
<action
android:id="@+id/action_global_notificationsViewerFragment"
app:destination="@id/notificationsViewer">
<argument
android:name="type"
app:argType="string"
app:nullable="false" />
<argument
android:name="targetId"
android:defaultValue="0L"
app:argType="long" />
</action>
<include app:graph="@navigation/comments_nav_graph" />
<action
android:id="@+id/action_global_commentsViewerFragment"
app:destination="@id/comments_nav_graph">
<argument
android:name="shortCode"
app:argType="string"
app:nullable="false" />
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="postUserId"
app:argType="long" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="isComment"
app:argType="boolean"
app:nullable="false" />
</action>
<include app:graph="@navigation/saved_nav_graph" />
<action
android:id="@+id/action_global_savedCollectionsFragment"
app:destination="@id/saved_nav_graph">
<argument
android:name="isSaving"
app:argType="boolean" />
</action>
<action
android:id="@+id/action_global_post_view"
app:destination="@id/postViewFragment">
<argument
android:name="media"
app:argType="awais.instagrabber.repositories.responses.Media"
app:nullable="false" />
<argument
android:name="position"
app:argType="integer" />
</action>
<include app:graph="@navigation/user_search_nav_graph" />
<action
android:id="@+id/action_global_user_search"
app:destination="@id/user_search_nav_graph" />
<fragment
android:id="@+id/storyViewerFragment"
android:name="awais.instagrabber.fragments.StoryViewerFragment"
android:label="StoryViewerFragment"
tools:layout="@layout/fragment_story_viewer">
<argument
android:name="options"
app:argType="awais.instagrabber.repositories.requests.StoryViewerOptions" />
</fragment>
<fragment
android:id="@+id/notificationsViewer"
android:name="awais.instagrabber.fragments.NotificationsViewerFragment"
android:label="@string/title_notifications"
tools:layout="@layout/fragment_notifications_viewer">
<argument
android:name="type"
app:argType="string"
app:nullable="false"
android:defaultValue="notif"/>
<argument
android:name="targetId"
android:defaultValue="0L"
app:argType="long" />
<action
android:id="@+id/action_notifications_to_story"
app:destination="@id/storyViewerFragment" />
</fragment>
<fragment
android:id="@+id/postViewFragment"
android:name="awais.instagrabber.fragments.PostViewV2Fragment"
android:label="@string/post"
tools:layout="@layout/dialog_post_view" />
</navigation>

View File

@ -1,223 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/profile_nav_graph"
app:startDestination="@id/profileFragment">
<include app:graph="@navigation/comments_nav_graph" />
<action
android:id="@+id/action_global_commentsViewerFragment"
app:destination="@id/comments_nav_graph">
<argument
android:name="shortCode"
app:argType="string"
app:nullable="false" />
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="postUserId"
app:argType="long" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="isComment"
app:argType="boolean"
app:nullable="false" />
</action>
<include app:graph="@navigation/hashtag_nav_graph" />
<action
android:id="@+id/action_global_hashTagFragment"
app:destination="@id/hashtag_nav_graph">
<argument
android:name="hashtag"
app:argType="string"
app:nullable="false" />
</action>
<include app:graph="@navigation/comments_nav_graph" />
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">
<argument
android:name="username"
app:argType="string"
app:nullable="false" />
</action>
<include app:graph="@navigation/location_nav_graph" />
<action
android:id="@+id/action_global_locationFragment"
app:destination="@id/location_nav_graph">
<argument
android:name="locationId"
app:argType="long" />
</action>
<action
android:id="@+id/action_global_notificationsViewerFragment"
app:destination="@id/notificationsViewer">
<argument
android:name="type"
app:argType="string"
app:nullable="false" />
<argument
android:name="targetId"
android:defaultValue="0L"
app:argType="long" />
<action
android:id="@+id/action_notifications_to_story"
app:destination="@id/storyViewerFragment" />
</action>
<action
android:id="@+id/action_global_post_view"
app:destination="@id/postViewFragment">
<argument
android:name="media"
app:argType="awais.instagrabber.repositories.responses.Media"
app:nullable="false" />
<argument
android:name="position"
app:argType="integer" />
</action>
<include app:graph="@navigation/user_search_nav_graph" />
<action
android:id="@+id/action_global_user_search"
app:destination="@id/user_search_nav_graph" />
<fragment
android:id="@+id/notificationsViewer"
android:name="awais.instagrabber.fragments.NotificationsViewerFragment"
android:label="@string/title_notifications"
tools:layout="@layout/fragment_notifications_viewer">
<argument
android:name="type"
android:defaultValue="notif"
app:argType="string"
app:nullable="false" />
<argument
android:name="targetId"
android:defaultValue="0L"
app:argType="long" />
</fragment>
<include app:graph="@navigation/saved_nav_graph" />
<action
android:id="@+id/action_global_savedCollectionsFragment"
app:destination="@id/saved_nav_graph">
<argument
android:name="isSaving"
app:argType="boolean" />
</action>
<action
android:id="@+id/action_global_search"
app:destination="@id/searchFragment" />
<fragment
android:id="@+id/profileFragment"
android:name="awais.instagrabber.fragments.main.ProfileFragment"
android:label="@string/profile"
tools:layout="@layout/fragment_profile">
<argument
android:name="username"
android:defaultValue=""
app:argType="string"
app:nullable="true" />
<action
android:id="@+id/action_profileFragment_to_savedViewerFragment"
app:destination="@id/savedViewerFragment" />
<action
android:id="@+id/action_profileFragment_to_followViewerFragment"
app:destination="@id/followViewerFragment" />
<action
android:id="@+id/action_profileFragment_to_storyViewerFragment"
app:destination="@id/storyViewerFragment" />
<action
android:id="@+id/action_profileFragment_to_dMThreadFragment"
app:destination="@id/directMessagesThreadFragment" />
</fragment>
<fragment
android:id="@+id/savedViewerFragment"
android:name="awais.instagrabber.fragments.SavedViewerFragment"
android:label="Saved"
tools:layout="@layout/fragment_saved">
<argument
android:name="username"
app:argType="string"
app:nullable="false" />
<argument
android:name="profileId"
app:argType="long" />
<argument
android:name="type"
app:argType="awais.instagrabber.models.enums.PostItemType"
app:nullable="false" />
</fragment>
<fragment
android:id="@+id/followViewerFragment"
android:name="awais.instagrabber.fragments.FollowViewerFragment"
android:label=""
tools:layout="@layout/fragment_followers_viewer">
<argument
android:name="profileId"
app:argType="long" />
<argument
android:name="isFollowersList"
app:argType="boolean"
app:nullable="false" />
<argument
android:name="username"
app:argType="string"
app:nullable="false" />
<action
android:id="@+id/action_followViewerFragment_to_profileFragment"
app:destination="@id/profileFragment">
<argument
android:name="username"
android:defaultValue=""
app:argType="string"
app:nullable="true" />
</action>
</fragment>
<fragment
android:id="@+id/storyViewerFragment"
android:name="awais.instagrabber.fragments.StoryViewerFragment"
android:label="StoryViewerFragment"
tools:layout="@layout/fragment_story_viewer">
<argument
android:name="options"
app:argType="awais.instagrabber.repositories.requests.StoryViewerOptions" />
</fragment>
<fragment
android:id="@+id/searchFragment"
android:name="awais.instagrabber.fragments.search.SearchFragment"
android:label="@string/search"
tools:layout="@layout/fragment_search" />
<fragment
android:id="@+id/postViewFragment"
android:name="awais.instagrabber.fragments.PostViewV2Fragment"
android:label="@string/post"
tools:layout="@layout/dialog_post_view" />
</navigation>

View File

@ -1,119 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/saved_nav_graph"
app:startDestination="@id/savedCollectionsFragment">
<action
android:id="@+id/action_global_hashTagFragment"
app:destination="@id/hashtag_nav_graph">
<argument
android:name="hashtag"
app:argType="string"
app:nullable="false" />
</action>
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">
<argument
android:name="username"
app:argType="string"
app:nullable="true" />
</action>
<action
android:id="@+id/action_global_locationFragment"
app:destination="@id/location_nav_graph">
<argument
android:name="locationId"
app:argType="long" />
</action>
<include app:graph="@navigation/comments_nav_graph" />
<action
android:id="@+id/action_global_commentsViewerFragment"
app:destination="@id/comments_nav_graph">
<argument
android:name="shortCode"
app:argType="string"
app:nullable="false" />
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="postUserId"
app:argType="long" />
</action>
<include app:graph="@navigation/likes_nav_graph" />
<action
android:id="@+id/action_global_likesViewerFragment"
app:destination="@id/likes_nav_graph">
<argument
android:name="postId"
app:argType="string"
app:nullable="false" />
<argument
android:name="isComment"
app:argType="boolean"
app:nullable="false" />
</action>
<action
android:id="@+id/action_global_post_view"
app:destination="@id/postViewFragment">
<argument
android:name="media"
app:argType="awais.instagrabber.repositories.responses.Media"
app:nullable="false" />
<argument
android:name="position"
app:argType="integer" />
</action>
<include app:graph="@navigation/user_search_nav_graph" />
<action
android:id="@+id/action_global_user_search"
app:destination="@id/user_search_nav_graph" />
<fragment
android:id="@+id/savedCollectionsFragment"
android:name="awais.instagrabber.fragments.SavedCollectionsFragment"
android:label="@string/saved"
tools:layout="@layout/fragment_saved_collections">
<argument
android:name="isSaving"
android:defaultValue="false"
app:argType="boolean" />
<action
android:id="@+id/action_savedCollectionsFragment_to_collectionPostsFragment"
app:destination="@id/collectionPostsFragment" />
</fragment>
<fragment
android:id="@+id/collectionPostsFragment"
android:name="awais.instagrabber.fragments.CollectionPostsFragment"
tools:layout="@layout/fragment_collection_posts">
<argument
android:name="savedCollection"
app:argType="awais.instagrabber.repositories.responses.saved.SavedCollection" />
<argument
android:name="titleColor"
app:argType="integer" />
<argument
android:name="backgroundColor"
app:argType="integer" />
</fragment>
<fragment
android:id="@+id/postViewFragment"
android:name="awais.instagrabber.fragments.PostViewV2Fragment"
android:label="@string/post"
tools:layout="@layout/dialog_post_view" />
</navigation>

View File

@ -0,0 +1,188 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/settings_nav_graph"
app:startDestination="@id/settingsPreferencesFragment">
<!--<include app:graph="@navigation/profile_nav_graph" />-->
<!--<include app:graph="@navigation/hashtag_nav_graph" />-->
<!--<include app:graph="@navigation/location_nav_graph" />-->
<!--<include app:graph="@navigation/comments_nav_graph" />-->
<!--<include app:graph="@navigation/likes_nav_graph" />-->
<!--<include app:graph="@navigation/notification_viewer_nav_graph" />-->
<!--<include app:graph="@navigation/story_list_nav_graph" />-->
<!--<include app:graph="@navigation/discover_nav_graph" />-->
<!--<action-->
<!-- android:id="@+id/action_global_commentsViewerFragment"-->
<!-- app:destination="@id/comments_nav_graph">-->
<!-- <argument-->
<!-- android:name="shortCode"-->
<!-- app:argType="string"-->
<!-- app:nullable="false" />-->
<!-- <argument-->
<!-- android:name="postId"-->
<!-- app:argType="string"-->
<!-- app:nullable="false" />-->
<!-- <argument-->
<!-- android:name="postUserId"-->
<!-- app:argType="long" />-->
<!--</action>-->
<!--<action-->
<!-- android:id="@+id/action_global_likesViewerFragment"-->
<!-- app:destination="@id/likes_nav_graph">-->
<!-- <argument-->
<!-- android:name="postId"-->
<!-- app:argType="string"-->
<!-- app:nullable="false" />-->
<!-- <argument-->
<!-- android:name="isComment"-->
<!-- app:argType="boolean"-->
<!-- app:nullable="false" />-->
<!--</action>-->
<!--<action-->
<!-- android:id="@+id/action_global_profileFragment"-->
<!-- app:destination="@id/profile_nav_graph">-->
<!-- <argument-->
<!-- android:name="username"-->
<!-- app:argType="string"-->
<!-- app:nullable="true" />-->
<!--</action>-->
<!--<action-->
<!-- android:id="@+id/action_global_hashTagFragment"-->
<!-- app:destination="@id/hashtag_nav_graph">-->
<!-- <argument-->
<!-- android:name="hashtag"-->
<!-- app:argType="string"-->
<!-- app:nullable="false" />-->
<!--</action>-->
<!--<action-->
<!-- android:id="@+id/action_global_locationFragment"-->
<!-- app:destination="@id/location_nav_graph">-->
<!-- <argument-->
<!-- android:name="locationId"-->
<!-- app:argType="long" />-->
<!--</action>-->
<!--<action-->
<!-- android:id="@+id/action_global_storyListViewerFragment"-->
<!-- app:destination="@id/story_list_nav_graph">-->
<!-- <argument-->
<!-- android:name="type"-->
<!-- app:argType="string"-->
<!-- app:nullable="false" />-->
<!--</action>-->
<!--<action-->
<!-- android:id="@+id/action_global_notificationsViewerFragment"-->
<!-- app:destination="@id/notification_viewer_nav_graph">-->
<!-- <argument-->
<!-- android:name="type"-->
<!-- app:argType="string"-->
<!-- app:nullable="false" />-->
<!-- <argument-->
<!-- android:name="targetId"-->
<!-- android:defaultValue="0L"-->
<!-- app:argType="long" />-->
<!--</action>-->
<!--<action-->
<!-- android:id="@+id/action_global_post_view"-->
<!-- app:destination="@id/postViewFragment">-->
<!-- <argument-->
<!-- android:name="media"-->
<!-- app:argType="awais.instagrabber.repositories.responses.Media"-->
<!-- app:nullable="false" />-->
<!-- <argument-->
<!-- android:name="position"-->
<!-- app:argType="integer" />-->
<!--</action>-->
<!--<include app:graph="@navigation/user_search_nav_graph" />-->
<!--<action-->
<!-- android:id="@+id/action_global_user_search"-->
<!-- app:destination="@id/user_search_nav_graph" />-->
<fragment
android:id="@+id/settingsPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.SettingsPreferencesFragment"
android:label="@string/action_settings">
<action
android:id="@+id/action_settings_to_theme"
app:destination="@id/themePreferencesFragment" />
<action
android:id="@+id/action_settings_to_locale"
app:destination="@id/localePreferencesFragment" />
<action
android:id="@+id/action_settings_to_general"
app:destination="@id/generalPreferencesFragment" />
<action
android:id="@+id/action_settings_to_downloads"
app:destination="@id/downloadsPreferencesFragment" />
<action
android:id="@+id/action_settings_to_dm"
app:destination="@id/DMPreferencesFragment" />
<action
android:id="@+id/action_settings_to_stories"
app:destination="@id/storiesPreferencesFragment" />
<action
android:id="@+id/action_settings_to_notifications"
app:destination="@id/notificationsPreferencesFragment" />
<action
android:id="@+id/action_settings_to_post"
app:destination="@id/postPreferencesFragment" />
</fragment>
<fragment
android:id="@+id/aboutFragment"
android:name="awais.instagrabber.fragments.settings.AboutFragment"
android:label="@string/action_about" />
<fragment
android:id="@+id/themePreferencesFragment"
android:name="awais.instagrabber.fragments.settings.ThemePreferencesFragment"
android:label="@string/theme_settings" />
<fragment
android:id="@+id/favoritesFragment"
android:name="awais.instagrabber.fragments.FavoritesFragment"
android:label="@string/title_favorites" />
<fragment
android:id="@+id/backupPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.BackupPreferencesFragment"
android:label="@string/backup_and_restore" />
<fragment
android:id="@+id/localePreferencesFragment"
android:name="awais.instagrabber.fragments.settings.LocalePreferencesFragment"
android:label="@string/pref_category_locale" />
<fragment
android:id="@+id/generalPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.GeneralPreferencesFragment"
android:label="@string/pref_category_general" />
<fragment
android:id="@+id/downloadsPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.DownloadsPreferencesFragment"
android:label="@string/pref_category_downloads" />
<fragment
android:id="@+id/DMPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.DMPreferencesFragment"
android:label="@string/pref_category_dm" />
<fragment
android:id="@+id/storiesPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.StoriesPreferencesFragment"
android:label="@string/pref_category_stories" />
<fragment
android:id="@+id/notificationsPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.NotificationsPreferencesFragment"
android:label="@string/pref_category_notifications" />
<fragment
android:id="@+id/postPreferencesFragment"
android:name="awais.instagrabber.fragments.settings.PostPreferencesFragment"
android:label="@string/pref_category_post" />
<!--<fragment-->
<!-- android:id="@+id/postViewFragment"-->
<!-- android:name="awais.instagrabber.fragments.PostViewV2Fragment"-->
<!-- android:label="@string/post" />-->
</navigation>

View File

@ -1,49 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/story_list_nav_graph"
app:startDestination="@id/storyListViewerFragment">
<action
android:id="@+id/action_global_profileFragment"
app:destination="@id/profile_nav_graph">
<argument
android:name="username"
app:argType="string"
app:nullable="true" />
</action>
<fragment
android:id="@+id/storyListViewerFragment"
android:name="awais.instagrabber.fragments.StoryListViewerFragment"
android:label="Stories"
tools:layout="@layout/fragment_story_list_viewer">
<argument
android:name="type"
app:argType="string"
app:nullable="false" />
<action
android:id="@+id/action_storyListFragment_to_storyViewerFragment"
app:destination="@id/storyViewerFragment" />
</fragment>
<action
android:id="@+id/action_global_storyListViewerFragment"
app:destination="@id/storyListViewerFragment">
<argument
android:name="type"
app:argType="string"
app:nullable="false" />
</action>
<fragment
android:id="@+id/storyViewerFragment"
android:name="awais.instagrabber.fragments.StoryViewerFragment"
android:label="StoryViewerFragment"
tools:layout="@layout/fragment_story_viewer">
<argument
android:name="options"
app:argType="awais.instagrabber.repositories.requests.StoryViewerOptions" />
</fragment>
</navigation>

View File

@ -1,80 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/user_search_nav_graph"
app:startDestination="@id/user_search">
<fragment
android:id="@+id/user_search"
android:name="awais.instagrabber.fragments.UserSearchFragment"
android:label="@string/search"
tools:layout="@layout/fragment_user_search">
<argument
android:name="multiple"
android:defaultValue="false"
app:argType="boolean" />
<argument
android:name="title"
android:defaultValue="@null"
app:argType="string"
app:nullable="true" />
<argument
android:name="action_label"
android:defaultValue="@null"
app:argType="string"
app:nullable="true" />
<argument
android:name="show_groups"
android:defaultValue="false"
app:argType="boolean" />
<argument
android:name="search_mode"
android:defaultValue="USER_SEARCH"
app:argType="awais.instagrabber.fragments.UserSearchFragment$SearchMode" />
<argument
android:name="hideUserIds"
android:defaultValue="@null"
app:argType="long[]"
app:nullable="true" />
<argument
android:name="hideThreadIds"
android:defaultValue="@null"
app:argType="string[]"
app:nullable="true" />
</fragment>
<action
android:id="@+id/action_global_user_search"
app:destination="@id/user_search" />
<!--<action-->
<!-- android:id="@+id/action_global_user_search"-->
<!-- app:destination="@id/user_search_nav_graph">-->
<!-- <argument-->
<!-- android:name="multiple"-->
<!-- app:argType="boolean" />-->
<!-- <argument-->
<!-- android:name="title"-->
<!-- app:argType="string"-->
<!-- app:nullable="true" />-->
<!-- <argument-->
<!-- android:name="action_label"-->
<!-- app:argType="string"-->
<!-- app:nullable="true" />-->
<!-- <argument-->
<!-- android:name="hideUserIds"-->
<!-- app:argType="long[]" />-->
<!--</action>-->
</navigation>

View File

@ -91,61 +91,23 @@
<item>HH:mm:ss</item>
<item>H:mm:ss</item>
</string-array>
<array name="main_nav_graph_root_ids">
<array name="logged_in_nav_root_ids">
<item>@id/direct_messages_nav_graph</item>
<item>@id/feed_nav_graph</item>
<item>@id/profile_nav_graph</item>
<item>@id/discover_nav_graph</item>
<item>@id/more_nav_graph</item>
<!-- New graphs should go below -->
<item>@id/favorites_nav_graph</item>
<item>@id/notification_viewer_nav_graph</item>
</array>
<!-- Nav graphs should correspond 1-to-1 with the above nav graph ids -->
<array name="main_nav_graphs">
<item>@navigation/direct_messages_nav_graph</item>
<item>@navigation/feed_nav_graph</item>
<item>@navigation/profile_nav_graph</item>
<item>@navigation/discover_nav_graph</item>
<item>@navigation/more_nav_graph</item>
<item>@navigation/favorites_nav_graph</item>
<item>@navigation/notification_viewer_nav_graph</item>
<array name="anon_nav_root_ids">
<item>@id/favorites_nav_graph</item>
<item>@id/profile_nav_graph</item>
<item>@id/more_nav_graph</item>
</array>
<!-- Titles should correspond 1-to-1 with the above nav graphs -->
<string-array name="main_nav_titles" translatable="false">
<item>@string/title_dm</item>
<item>@string/feed</item>
<item>@string/profile</item>
<item>@string/title_discover</item>
<item>@string/more</item>
<item>@string/title_favorites</item>
<item>@string/title_notifications</item>
</string-array>
<!-- Drawable should correspond 1-to-1 with the above titles -->
<array name="main_nav_drawables" translatable="false">
<item>@drawable/ic_message_24</item>
<item>@drawable/ic_home_24</item>
<item>@drawable/ic_person_24</item>
<item>@drawable/ic_explore_24</item>
<item>@drawable/ic_more_horiz_24</item>
<item>@drawable/ic_star_24</item>
<item>@drawable/ic_not_liked</item>
</array>
<!-- fragmentIds should correspond 1-to-1 with the above drawabled -->
<!-- these are the start destination of the corresponding nav graphs -->
<array name="main_nav_start_dest_frag_ids" translatable="false">
<item>@id/directMessagesInboxFragment</item>
<item>@id/feedFragment</item>
<item>@id/profileFragment</item>
<item>@id/discoverFragment</item>
<item>@id/morePreferencesFragment</item>
<item>@id/favoritesFragment</item>
<item>@id/notificationsViewer</item>
</array>
<!--<array name="logged_out_main_nav_graphs">-->
<!-- <item>@navigation/profile_nav_graph</item>-->
<!-- <item>@navigation/more_nav_graph</item>-->
<!--</array>-->
<string-array name="light_themes" translatable="false">
<item>@string/light_white_theme</item>
<item>@string/light_barinsta_theme</item>

View File

@ -8,4 +8,15 @@
<item name="share_dm" type="id" />
<item name="download_current" type="id" />
<item name="download_all" type="id" />
<item name="root_nav_graph" type="id" />
<!-- Navigation top level root ids -->
<item name="feed_nav_graph" type="id" />
<item name="profile_nav_graph" type="id" />
<item name="direct_messages_nav_graph" type="id" />
<item name="notification_viewer_nav_graph" type="id" />
<item name="discover_nav_graph" type="id" />
<item name="favorites_nav_graph" type="id" />
<item name="more_nav_graph" type="id" />
</resources>

View File

@ -1,5 +1,8 @@
buildscript {
ext.kotlin_version = '1.5.20'
ext{
kotlin_version = '1.5.20'
nav_version = "2.4.0-alpha04"
}
repositories {
google()
@ -9,7 +12,6 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:4.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
def nav_version = "2.3.5"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}
}