1
0
mirror of https://github.com/KokaKiwi/BarInsta synced 2024-11-22 06:37:30 +00:00

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 { dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
def nav_version = '2.3.5'
def exoplayer_version = '2.14.1' def exoplayer_version = '2.14.1'
implementation 'com.google.android.material:material:1.4.0-rc01' implementation 'com.google.android.material:material:1.4.0-rc01'
@ -175,8 +174,6 @@ dependencies {
implementation "androidx.recyclerview:recyclerview:1.2.1" implementation "androidx.recyclerview:recyclerview:1.2.1"
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation "androidx.viewpager2:viewpager2:1.0.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.constraintlayout:constraintlayout:2.0.4"
implementation "androidx.preference:preference:1.1.1" implementation "androidx.preference:preference:1.1.1"
implementation 'androidx.palette:palette:1.0.0' 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-viewmodel-ktx:2.3.1"
implementation "androidx.lifecycle:lifecycle-livedata-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 // Room
def room_version = "2.3.0" def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version" implementation "androidx.room:room-runtime:$room_version"

View File

@ -1,7 +1,6 @@
package awais.instagrabber.activities package awais.instagrabber.activities
import android.animation.LayoutTransition import android.animation.LayoutTransition
import android.annotation.SuppressLint
import android.app.NotificationChannel import android.app.NotificationChannel
import android.app.NotificationManager import android.app.NotificationManager
import android.content.ComponentName import android.content.ComponentName
@ -16,7 +15,6 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
import android.widget.Toast import android.widget.Toast
import androidx.annotation.IdRes
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
@ -29,22 +27,22 @@ import androidx.emoji.text.EmojiCompat
import androidx.emoji.text.EmojiCompat.InitCallback import androidx.emoji.text.EmojiCompat.InitCallback
import androidx.emoji.text.FontRequestEmojiCompatConfig import androidx.emoji.text.FontRequestEmojiCompatConfig
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavController.OnDestinationChangedListener
import androidx.navigation.NavDestination 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.BuildConfig
import awais.instagrabber.NavGraphDirections
import awais.instagrabber.R import awais.instagrabber.R
import awais.instagrabber.customviews.emoji.EmojiVariantManager import awais.instagrabber.customviews.emoji.EmojiVariantManager
import awais.instagrabber.customviews.helpers.RootViewDeferringInsetsCallback import awais.instagrabber.customviews.helpers.RootViewDeferringInsetsCallback
import awais.instagrabber.customviews.helpers.TextWatcherAdapter import awais.instagrabber.customviews.helpers.TextWatcherAdapter
import awais.instagrabber.databinding.ActivityMainBinding import awais.instagrabber.databinding.ActivityMainBinding
import awais.instagrabber.fragments.PostViewV2Fragment import awais.instagrabber.fragments.main.FeedFragment
import awais.instagrabber.fragments.directmessages.DirectMessageInboxFragmentDirections
import awais.instagrabber.fragments.settings.PreferenceKeys import awais.instagrabber.fragments.settings.PreferenceKeys
import awais.instagrabber.models.IntentModel import awais.instagrabber.models.IntentModel
import awais.instagrabber.models.Resource 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.bottomnavigation.BottomNavigationView
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
import com.google.common.collect.ImmutableList import com.google.common.collect.ImmutableList
import com.google.common.collect.Iterators
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.util.* import java.util.*
import java.util.stream.Collectors
class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedListener { class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedListener {
private lateinit var binding: ActivityMainBinding 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 searchMenuItem: MenuItem? = null
private var firstFragmentGraphIndex = 0 private var startNavRootId: Int = 0
// private var firstFragmentGraphIndex = 0
private var lastSelectedNavMenuId = 0 private var lastSelectedNavMenuId = 0
private var isActivityCheckerServiceBound = false private var isActivityCheckerServiceBound = false
private var isBackStackEmpty = false private var isBackStackEmpty = false
@ -141,8 +141,10 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
// } catch (e: Exception) { // } catch (e: Exception) {
// Log.e(TAG, "onCreate: ", e) // Log.e(TAG, "onCreate: ", e)
// } // }
val navHostFragment = supportFragmentManager.findFragmentById(R.id.main_nav_host) as NavHostFragment
navController = navHostFragment.navController
if (savedInstanceState == null) { if (savedInstanceState == null) {
setupBottomNavigationBar(true) setupNavigation(true)
} }
if (!BuildConfig.isPre) { if (!BuildConfig.isPre) {
val checkUpdates = Utils.settingsHelper.getBoolean(PreferenceKeys.CHECK_UPDATES) val checkUpdates = Utils.settingsHelper.getBoolean(PreferenceKeys.CHECK_UPDATES)
@ -233,40 +235,18 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.main_menu, menu) menuInflater.inflate(R.menu.main_menu, menu)
searchMenuItem = menu.findItem(R.id.search) searchMenuItem = menu.findItem(R.id.search)
val navController = currentNavControllerLiveData?.value // val navController = currentNavControllerLiveData?.value
if (navController != null) { val currentDestination = navController.currentDestination
val currentDestination = navController.currentDestination if (currentDestination != null) {
if (currentDestination != null) { val backStack = navController.backQueue
@SuppressLint("RestrictedApi") val backStack = navController.backStack setupMenu(backStack.size, currentDestination.id)
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 return true
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.search) { if (item.itemId == R.id.search) {
val navController = currentNavControllerLiveData?.value ?: return false // val navController = currentNavControllerLiveData?.value ?: return false
try { try {
navController.navigate(R.id.action_global_search) navController.navigate(R.id.action_global_search)
return true return true
@ -279,20 +259,13 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
} }
override fun onSaveInstanceState(outState: Bundle) { 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()) outState.putString(LAST_SELECT_NAV_MENU_ID, binding.bottomNavView.selectedItemId.toString())
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
} }
override fun onRestoreInstanceState(savedInstanceState: Bundle) { override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState) 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? val lastSelected = savedInstanceState[LAST_SELECT_NAV_MENU_ID] as String?
if (lastSelected != null) { if (lastSelected != null) {
try { try {
@ -300,13 +273,11 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
} catch (ignored: NumberFormatException) { } catch (ignored: NumberFormatException) {
} }
} }
setupBottomNavigationBar(false) setupNavigation(false)
} }
override fun onSupportNavigateUp(): Boolean { override fun onSupportNavigateUp(): Boolean {
if (currentNavControllerLiveData == null) return false return navController.navigateUp(appBarConfiguration)
val navController = currentNavControllerLiveData?.value ?: return false
return navController.navigateUp()
} }
override fun onNewIntent(intent: Intent) { override fun onNewIntent(intent: Intent) {
@ -331,14 +302,8 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
} }
override fun onBackPressed() { override fun onBackPressed() {
var currentNavControllerBackStack = 2 val backStack = navController.backQueue
currentNavControllerLiveData?.let { val currentNavControllerBackStack = backStack.size
val navController = it.value
if (navController != null) {
@SuppressLint("RestrictedApi") val backStack = navController.backStack
currentNavControllerBackStack = backStack.size
}
}
if (isTaskRoot && isBackStackEmpty && currentNavControllerBackStack == 2) { if (isTaskRoot && isBackStackEmpty && currentNavControllerBackStack == 2) {
finishAfterTransition() finishAfterTransition()
return return
@ -391,117 +356,40 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
notificationManager.createNotificationChannel(silentNotificationChannel) notificationManager.createNotificationChannel(silentNotificationChannel)
} }
private fun setupBottomNavigationBar(setDefaultTabFromSettings: Boolean) { private fun setupNavigation(setDefaultTabFromSettings: Boolean) {
currentTabs = if (!isLoggedIn) setupAnonBottomNav() else setupMainBottomNav() currentTabs = if (isLoggedIn) setupMainBottomNav() else setupAnonBottomNav()
val mainNavList = currentTabs.stream()
.map(Tab::navigationResId)
.collect(Collectors.toList())
showBottomViewDestinations = currentTabs.asSequence().map { showBottomViewDestinations = currentTabs.asSequence().map {
it.startDestinationFragmentId it.startDestinationFragmentId
}.toMutableList().apply { }.toMutableList().apply {
add(R.id.postViewFragment) add(R.id.postViewFragment)
add(R.id.favoritesFragment) add(R.id.favoritesFragment)
add(R.id.profile_non_top)
} }
if (setDefaultTabFromSettings) { if (setDefaultTabFromSettings) {
setSelectedTab(currentTabs) setSelectedTab(currentTabs)
} else { } else {
binding.bottomNavView.selectedItemId = lastSelectedNavMenuId binding.bottomNavView.selectedItemId = lastSelectedNavMenuId
} }
val navControllerLiveData = NavigationExtensions.setupWithNavController( val navigatorProvider = navController.navigatorProvider
binding.bottomNavView, val navigator = navigatorProvider.getNavigator<NavGraphNavigator>("navigation")
mainNavList, val rootNavGraph = NavGraph(navigator)
supportFragmentManager, val navInflater = navController.navInflater
R.id.main_nav_host, val destinations = currentTabs.map {
intent, val navGraph = navInflater.inflate(R.navigation.nav_graph)
firstFragmentGraphIndex navGraph.id = it.navigationRootId
) navGraph.label = "${it.title}_nav_graph".lowercase(Locale.getDefault())
navControllerLiveData.observe(this, { navController: NavController? -> setupNavigation(binding.toolbar, navController) }) navGraph.setStartDestination(it.startDestinationFragmentId)
currentNavControllerLiveData = navControllerLiveData return@map navGraph
}
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)
} }
} rootNavGraph.id = R.id.root_nav_graph
rootNavGraph.label = "root_nav_graph"
private fun setupAnonBottomNav(): List<Tab> { rootNavGraph.addDestinations(destinations)
val selectedItemId = binding.bottomNavView.selectedItemId rootNavGraph.setStartDestination(if (startNavRootId != 0) startNavRootId else R.id.profile_nav_graph)
val favoriteTab = Tab( navController.graph = rootNavGraph
R.drawable.ic_star_24, binding.bottomNavView.setupWithNavController(navController)
getString(R.string.title_favorites), appBarConfiguration = AppBarConfiguration(currentTabs.map { it.startDestinationFragmentId }.toSet())
false, setupActionBarWithNavController(navController, appBarConfiguration)
"favorites_nav_graph", navController.addOnDestinationChangedListener { _: NavController?, destination: NavDestination, arguments: Bundle? ->
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? ->
if (destination.id == R.id.directMessagesThreadFragment && arguments != null) { if (destination.id == R.id.directMessagesThreadFragment && arguments != null) {
// Set the thread title earlier for better ux // Set the thread title earlier for better ux
val title = arguments.getString("title") 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 // 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) binding.appBarLayout.setExpanded(true, true)
val destinationId = destination.id val destinationId = destination.id
@SuppressLint("RestrictedApi") val backStack = navController.backStack val backStack = navController.backQueue
setupMenu(backStack.size, destinationId) setupMenu(backStack.size, destinationId)
val contains = showBottomViewDestinations.contains(destinationId) val contains = showBottomViewDestinations.contains(destinationId)
binding.root.post { binding.root.post {
@ -531,7 +419,65 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
// explicitly hide keyboard when we navigate // explicitly hide keyboard when we navigate
val view = currentFocus val view = currentFocus
Utils.hideKeyboard(view) 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) { private fun setupMenu(backStackSize: Int, destinationId: Int) {
@ -589,47 +535,11 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
fun navigateToThread(threadId: String?, threadTitle: String?) { fun navigateToThread(threadId: String?, threadTitle: String?) {
if (threadId == null || threadTitle == null) return if (threadId == null || threadTitle == null) return
currentNavControllerLiveData?.observe(this, object : Observer<NavController?> { try {
override fun onChanged(navController: NavController?) { val action = NavGraphDirections.actionGlobalDirectThread(threadId, threadTitle)
if (navController == null) return navController.navigate(action)
if (navController.graph.id != R.id.direct_messages_nav_graph) return } catch (e: Exception) {
try { Log.e(TAG, "navigateToThread: ", e)
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)
} }
} }
@ -652,14 +562,10 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
} }
private fun showProfileView(intentModel: IntentModel) { 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 { 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) { } catch (e: Exception) {
Log.e(TAG, "showProfileView: ", e) 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() Toast.makeText(applicationContext, R.string.post_not_found, Toast.LENGTH_SHORT).show()
return@withContext return@withContext
} }
val currentNavControllerLiveData = currentNavControllerLiveData ?: return@withContext
val navController = currentNavControllerLiveData.value
val bundle = Bundle()
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media)
try { try {
navController?.navigate(R.id.action_global_post_view, bundle) val action = NavGraphDirections.actionGlobalPost(media, 0)
navController.navigate(action)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "showPostView: ", e) Log.e(TAG, "showPostView: ", e)
} }
@ -704,29 +607,32 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
private fun showLocationView(intentModel: IntentModel) { private fun showLocationView(intentModel: IntentModel) {
val locationId = intentModel.text val locationId = intentModel.text
// Log.d(TAG, "locationId: " + locationId); // Log.d(TAG, "locationId: " + locationId);
val currentNavControllerLiveData = currentNavControllerLiveData ?: return try {
val navController = currentNavControllerLiveData.value val action = NavGraphDirections.actionGlobalLocation(locationId.toLong())
val bundle = Bundle() navController.navigate(action)
bundle.putLong("locationId", locationId.toLong()) } catch (e: Exception) {
navController?.navigate(R.id.action_global_locationFragment, bundle) Log.e(TAG, "showLocationView: ", e)
}
} }
private fun showHashtagView(intentModel: IntentModel) { private fun showHashtagView(intentModel: IntentModel) {
val hashtag = intentModel.text val hashtag = intentModel.text
// Log.d(TAG, "hashtag: " + hashtag); // Log.d(TAG, "hashtag: " + hashtag);
val currentNavControllerLiveData = currentNavControllerLiveData ?: return try {
val navController = currentNavControllerLiveData.value val action = NavGraphDirections.actionGlobalHashTag(hashtag)
val bundle = Bundle() navController.navigate(action)
bundle.putString("hashtag", hashtag) } catch (e: Exception) {
navController?.navigate(R.id.action_global_hashTagFragment, bundle) Log.e(TAG, "showHashtagView: ", e)
}
} }
private fun showActivityView() { private fun showActivityView() {
val currentNavControllerLiveData = currentNavControllerLiveData ?: return try {
val navController = currentNavControllerLiveData.value val action = NavGraphDirections.actionGlobalNotifications().apply { type = "notif" }
val bundle = Bundle() navController.navigate(action)
bundle.putString("type", "notif") } catch (e: Exception) {
navController?.navigate(R.id.action_global_notificationsViewerFragment, bundle) Log.e(TAG, "showActivityView: ", e)
}
} }
private fun bindActivityCheckerService() { private fun bindActivityCheckerService() {
@ -763,8 +669,7 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
binding.appBarLayout.visibility = View.VISIBLE binding.appBarLayout.visibility = View.VISIBLE
setScrollingBehaviour() setScrollingBehaviour()
setSupportActionBar(binding.toolbar) setSupportActionBar(binding.toolbar)
val currentNavControllerLiveData = currentNavControllerLiveData ?: return setupActionBarWithNavController(navController, appBarConfiguration)
setupNavigation(binding.toolbar, currentNavControllerLiveData.value)
} }
val collapsingToolbarView: CollapsingToolbarLayout val collapsingToolbarView: CollapsingToolbarLayout
@ -808,8 +713,7 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
binding.appBarLayout.visibility = View.GONE binding.appBarLayout.visibility = View.GONE
removeScrollingBehaviour() removeScrollingBehaviour()
setSupportActionBar(toolbar) setSupportActionBar(toolbar)
if (currentNavControllerLiveData == null) return NavigationUI.setupWithNavController(toolbar, navController, appBarConfiguration)
setupNavigation(toolbar, currentNavControllerLiveData?.value)
} }
val rootView: View val rootView: View
get() = binding.root get() = binding.root
@ -839,8 +743,8 @@ class MainActivity : BaseLanguageActivity(), FragmentManager.OnBackStackChangedL
companion object { companion object {
private const val TAG = "MainActivity" private const val TAG = "MainActivity"
private const val FIRST_FRAGMENT_GRAPH_INDEX_KEY = "firstFragmentGraphIndex"
private const val LAST_SELECT_NAV_MENU_ID = "lastSelectedNavMenuId" private const val LAST_SELECT_NAV_MENU_ID = "lastSelectedNavMenuId"
private val SEARCH_VISIBLE_DESTINATIONS: List<Int> = ImmutableList.of( private val SEARCH_VISIBLE_DESTINATIONS: List<Int> = ImmutableList.of(
R.id.feedFragment, R.id.feedFragment,
R.id.profileFragment, R.id.profileFragment,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,7 +20,6 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationManagerCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.NavController;
import androidx.navigation.NavDirections; import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
@ -50,8 +49,6 @@ import awais.instagrabber.webservices.NewsService;
import awais.instagrabber.webservices.ServiceCallback; import awais.instagrabber.webservices.ServiceCallback;
import kotlinx.coroutines.Dispatchers; import kotlinx.coroutines.Dispatchers;
import static awais.instagrabber.utils.Utils.settingsHelper;
public final class NotificationsViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { public final class NotificationsViewerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "NotificationsViewer"; private static final String TAG = "NotificationsViewer";
@ -98,10 +95,14 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
if (model.getType() == NotificationType.RESPONDED_STORY) { if (model.getType() == NotificationType.RESPONDED_STORY) {
final StoryViewerOptions options = StoryViewerOptions.forStory( final StoryViewerOptions options = StoryViewerOptions.forStory(
mediaId, mediaId,
model.getArgs().getUsername()); model.getArgs().getUsername()
final Bundle bundle = new Bundle(); );
bundle.putSerializable("options", options); try {
NavHostFragment.findNavController(NotificationsViewerFragment.this).navigate(R.id.action_notifications_to_story, bundle); final NavDirections action = NotificationsViewerFragmentDirections.actionToStory(options);
NavHostFragment.findNavController(NotificationsViewerFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onPreviewClick: ", e);
}
} else { } else {
final AlertDialog alertDialog = new AlertDialog.Builder(context) final AlertDialog alertDialog = new AlertDialog.Builder(context)
.setCancelable(false) .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(); Toast.makeText(context, R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
return; return;
} }
final NavController navController = NavHostFragment.findNavController(NotificationsViewerFragment.this);
final Bundle bundle = new Bundle();
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media);
try { try {
navController.navigate(R.id.action_global_post_view, bundle); final NavDirections action = NotificationsViewerFragmentDirections.actionToPost(media, 0);
alertDialog.dismiss(); NavHostFragment.findNavController(NotificationsViewerFragment.this).navigate(action);
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "onSuccess: ", e); Log.e(TAG, "onSuccess: ", e);
} finally {
alertDialog.dismiss();
} }
}), Dispatchers.getIO()) }), Dispatchers.getIO())
); );
@ -257,7 +257,7 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
type = fragmentArgs.getType(); type = fragmentArgs.getType();
targetId = fragmentArgs.getTargetId(); targetId = fragmentArgs.getTargetId();
final Context context = getContext(); final Context context = getContext();
CookieUtils.setupCookies(settingsHelper.getString(Constants.COOKIE)); CookieUtils.setupCookies(Utils.settingsHelper.getString(Constants.COOKIE));
binding.swipeRefreshLayout.setOnRefreshListener(this); binding.swipeRefreshLayout.setOnRefreshListener(this);
notificationViewModel = new ViewModelProvider(this).get(NotificationViewModel.class); notificationViewModel = new ViewModelProvider(this).get(NotificationViewModel.class);
final NotificationsAdapter adapter = new NotificationsAdapter(clickListener); final NotificationsAdapter adapter = new NotificationsAdapter(clickListener);
@ -288,7 +288,11 @@ public final class NotificationsViewerFragment extends Fragment implements Swipe
} }
private void openProfile(final String username) { private void openProfile(final String username) {
final NavDirections action = NotificationsViewerFragmentDirections.actionGlobalProfileFragment("@" + username); try {
NavHostFragment.findNavController(this).navigate(action); 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.lifecycle.ViewModelProvider;
import androidx.navigation.NavBackStackEntry; import androidx.navigation.NavBackStackEntry;
import androidx.navigation.NavController; import androidx.navigation.NavController;
import androidx.navigation.NavDirections;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import androidx.transition.TransitionManager; import androidx.transition.TransitionManager;
@ -70,7 +71,6 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import awais.instagrabber.R; import awais.instagrabber.R;
import awais.instagrabber.UserSearchNavGraphDirections;
import awais.instagrabber.activities.MainActivity; import awais.instagrabber.activities.MainActivity;
import awais.instagrabber.adapters.SliderCallbackAdapter; import awais.instagrabber.adapters.SliderCallbackAdapter;
import awais.instagrabber.adapters.SliderItemsAdapter; import awais.instagrabber.adapters.SliderItemsAdapter;
@ -103,9 +103,7 @@ import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils; import awais.instagrabber.utils.Utils;
import awais.instagrabber.viewmodels.PostViewV2ViewModel; 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.fragments.settings.PreferenceKeys.PREF_SHOWN_COUNT_TOOLTIP;
import static awais.instagrabber.utils.Utils.settingsHelper;
public class PostViewV2Fragment extends Fragment implements EditTextDialogFragment.EditTextDialogFragmentCallback { public class PostViewV2Fragment extends Fragment implements EditTextDialogFragment.EditTextDialogFragmentCallback {
private static final String TAG = "PostViewV2Fragment"; private static final String TAG = "PostViewV2Fragment";
@ -217,7 +215,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
public void onPause() { public void onPause() {
super.onPause(); super.onPause();
// wasPaused = true; // wasPaused = true;
if (settingsHelper.getBoolean(PreferenceKeys.PLAY_IN_BACKGROUND)) return; if (Utils.settingsHelper.getBoolean(PreferenceKeys.PLAY_IN_BACKGROUND)) return;
final Media media = viewModel.getMedia(); final Media media = viewModel.getMedia();
if (media.getType() == null) return; if (media.getType() == null) return;
switch (media.getType()) { switch (media.getType()) {
@ -333,7 +331,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
viewModel.getLikeCount().observe(getViewLifecycleOwner(), count -> { viewModel.getLikeCount().observe(getViewLifecycleOwner(), count -> {
bottom.likesCount.setNumber(getSafeCount(count)); bottom.likesCount.setNumber(getSafeCount(count));
binding.getRoot().postDelayed(() -> bottom.likesCount.setAnimateChanges(true), 1000); 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); binding.getRoot().postDelayed(this::showCountTooltip, 1000);
} }
}); });
@ -392,7 +390,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
.setDismissWhenOverlayClicked(false) .setDismissWhenOverlayClicked(false)
.build(); .build();
balloon.showAlignBottom(bottom.likesCount); balloon.showAlignBottom(bottom.likesCount);
settingsHelper.putBoolean(PREF_SHOWN_COUNT_TOOLTIP, true); Utils.settingsHelper.putBoolean(PREF_SHOWN_COUNT_TOOLTIP, true);
balloon.setOnBalloonOutsideTouchListener((view, motionEvent) -> { balloon.setOnBalloonOutsideTouchListener((view, motionEvent) -> {
if (rect.contains((int) motionEvent.getRawX(), (int) motionEvent.getRawY())) { if (rect.contains((int) motionEvent.getRawX(), (int) motionEvent.getRawY())) {
bottom.likesCount.setShowAbbreviation(false); bottom.likesCount.setShowAbbreviation(false);
@ -431,12 +429,9 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
if (user == null) return; if (user == null) return;
final NavController navController = getNavController(); final NavController navController = getNavController();
if (navController == null) return; 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 { 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) { } catch (Exception e) {
Log.e(TAG, "setupComment: ", e); Log.e(TAG, "setupComment: ", e);
} }
@ -445,9 +440,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
} }
private void setupDownload() { private void setupDownload() {
bottom.download.setOnClickListener(v -> { bottom.download.setOnClickListener(v -> DownloadUtils.showDownloadDialog(context, viewModel.getMedia(), sliderPosition, bottom.download));
DownloadUtils.showDownloadDialog(context, viewModel.getMedia(), sliderPosition, bottom.download);
});
TooltipCompat.setTooltipText(bottom.download, getString(R.string.action_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 -> { bottom.like.setOnLongClickListener(v -> {
final NavController navController = getNavController(); final NavController navController = getNavController();
if (navController != null && viewModel.isLoggedIn()) { if (navController != null && viewModel.isLoggedIn()) {
final Bundle bundle = new Bundle(); try {
bundle.putString("postId", viewModel.getMedia().getPk()); final NavDirections action = PostViewV2FragmentDirections.actionToLikes(viewModel.getMedia().getPk(), false);
bundle.putBoolean("isComment", false); navController.navigate(action);
navController.navigate(R.id.action_global_likesViewerFragment, bundle); } catch (Exception e) {
Log.e(TAG, "setupLike: ", e);
}
return true; return true;
} }
return true; return true;
@ -543,11 +538,14 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
handleSaveUnsaveResourceLiveData(viewModel.toggleSave()); handleSaveUnsaveResourceLiveData(viewModel.toggleSave());
}); });
bottom.save.setOnLongClickListener(v -> { bottom.save.setOnLongClickListener(v -> {
final NavController navController = NavHostFragment.findNavController(this); try {
final Bundle bundle = new Bundle(); final NavDirections action = PostViewV2FragmentDirections.actionToSavedCollections().setIsSaving(true);
bundle.putBoolean("isSaving", true); NavHostFragment.findNavController(this).navigate(action);
navController.navigate(R.id.action_global_savedCollectionsFragment, bundle); return true;
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(); final String postCaption = caption.getText();
bottom.caption.addOnHashtagListener(autoLinkItem -> { bottom.caption.addOnHashtagListener(autoLinkItem -> {
final NavController navController = NavHostFragment.findNavController(this); try {
final Bundle bundle = new Bundle(); final String originalText = autoLinkItem.getOriginalText().trim();
final String originalText = autoLinkItem.getOriginalText().trim(); final NavDirections action = PostViewV2FragmentDirections.actionToHashtag(originalText);
bundle.putString(ARG_HASHTAG, originalText); NavHostFragment.findNavController(this).navigate(action);
navController.navigate(R.id.action_global_hashTagFragment, bundle); } catch (Exception e) {
Log.e(TAG, "setupCaption: ", e);
}
}); });
bottom.caption.addOnMentionClickListener(autoLinkItem -> { bottom.caption.addOnMentionClickListener(autoLinkItem -> {
final String originalText = autoLinkItem.getOriginalText().trim(); final String originalText = autoLinkItem.getOriginalText().trim();
@ -701,7 +701,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
case ERROR: case ERROR:
bottom.translate.setEnabled(true); bottom.translate.setEnabled(true);
String message = resource.message; String message = resource.message;
if (TextUtils.isEmpty(resource.message)) { if (TextUtils.isEmpty(message)) {
message = getString(R.string.downloader_unknown_error); message = getString(R.string.downloader_unknown_error);
} }
final Snackbar snackbar = Snackbar.make(binding.getRoot(), message, Snackbar.LENGTH_INDEFINITE); 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.setText(locationName);
binding.location.setVisibility(View.VISIBLE); binding.location.setVisibility(View.VISIBLE);
binding.location.setOnClickListener(v -> { binding.location.setOnClickListener(v -> {
final NavController navController = getNavController(); try {
if (navController == null) return; final NavController navController = getNavController();
final Bundle bundle = new Bundle(); if (navController == null) return;
bundle.putLong("locationId", location.getPk()); final NavDirections action = PostViewV2FragmentDirections.actionToLocation(location.getPk());
navController.navigate(R.id.action_global_locationFragment, bundle); 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 -> { popupMenu.setOnMenuItemClickListener(item -> {
final int itemId = item.getItemId(); final int itemId = item.getItemId();
if (itemId == R.id.share_dm) { 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 { 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) { } catch (Exception e) {
Log.e(TAG, "setupShare: ", e); Log.e(TAG, "setupShare: ", e);
} }
@ -1087,7 +1089,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
// gestureDetector.onTouchEvent(event); // gestureDetector.onTouchEvent(event);
// return true; // 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() { final VideoPlayerViewHelper.VideoPlayerCallback videoPlayerCallback = new VideoPlayerCallbackAdapter() {
@Override @Override
public void onThumbnailLoaded() { public void onThumbnailLoaded() {
@ -1423,9 +1425,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
final CollapsingToolbarLayout appbarLayout = activity.getCollapsingToolbarView(); final CollapsingToolbarLayout appbarLayout = activity.getCollapsingToolbarView();
appbarLayout.setVisibility(View.GONE); appbarLayout.setVisibility(View.GONE);
final Toolbar toolbar = activity.getToolbar(); final Toolbar toolbar = activity.getToolbar();
if (toolbar != null) { toolbar.setVisibility(View.GONE);
toolbar.setVisibility(View.GONE);
}
binding.getRoot().setPadding(binding.getRoot().getPaddingLeft(), binding.getRoot().setPadding(binding.getRoot().getPaddingLeft(),
binding.getRoot().getPaddingTop(), binding.getRoot().getPaddingTop(),
binding.getRoot().getPaddingRight(), binding.getRoot().getPaddingRight(),
@ -1448,9 +1448,7 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
final CollapsingToolbarLayout appbarLayout = activity.getCollapsingToolbarView(); final CollapsingToolbarLayout appbarLayout = activity.getCollapsingToolbarView();
appbarLayout.setVisibility(View.VISIBLE); appbarLayout.setVisibility(View.VISIBLE);
final Toolbar toolbar = activity.getToolbar(); final Toolbar toolbar = activity.getToolbar();
if (toolbar != null) { toolbar.setVisibility(View.VISIBLE);
toolbar.setVisibility(View.VISIBLE);
}
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
binding.getRoot().setPadding(binding.getRoot().getPaddingLeft(), binding.getRoot().setPadding(binding.getRoot().getPaddingLeft(),
@ -1465,9 +1463,8 @@ public class PostViewV2Fragment extends Fragment implements EditTextDialogFragme
private void navigateToProfile(final String username) { private void navigateToProfile(final String username) {
final NavController navController = getNavController(); final NavController navController = getNavController();
if (navController == null) return; if (navController == null) return;
final Bundle bundle = new Bundle(); final NavDirections actionToProfile = PostViewV2FragmentDirections.actionToProfile().setUsername(username);
bundle.putString("username", username); navController.navigate(actionToProfile);
navController.navigate(R.id.action_global_profileFragment, bundle);
} }
@Nullable @Nullable

View File

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

View File

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

View File

@ -37,7 +37,6 @@ import awais.instagrabber.adapters.HighlightStoriesListAdapter;
import awais.instagrabber.adapters.HighlightStoriesListAdapter.OnHighlightStoryClickListener; import awais.instagrabber.adapters.HighlightStoriesListAdapter.OnHighlightStoryClickListener;
import awais.instagrabber.customviews.helpers.RecyclerLazyLoader; import awais.instagrabber.customviews.helpers.RecyclerLazyLoader;
import awais.instagrabber.databinding.FragmentStoryListViewerBinding; import awais.instagrabber.databinding.FragmentStoryListViewerBinding;
import awais.instagrabber.fragments.settings.MorePreferencesFragmentDirections;
import awais.instagrabber.repositories.requests.StoryViewerOptions; import awais.instagrabber.repositories.requests.StoryViewerOptions;
import awais.instagrabber.repositories.responses.stories.ArchiveResponse; import awais.instagrabber.repositories.responses.stories.ArchiveResponse;
import awais.instagrabber.repositories.responses.stories.Story; import awais.instagrabber.repositories.responses.stories.Story;
@ -74,9 +73,12 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
if (feedStoryModels == null) return; if (feedStoryModels == null) return;
final int position = Iterables.indexOf(feedStoryModels, feedStoryModel -> feedStoryModel != null final int position = Iterables.indexOf(feedStoryModels, feedStoryModel -> feedStoryModel != null
&& Objects.equals(feedStoryModel.getId(), model.getId())); && Objects.equals(feedStoryModel.getId(), model.getId()));
final NavDirections action = StoryListViewerFragmentDirections try {
.actionStoryListFragmentToStoryViewerFragment(StoryViewerOptions.forFeedStoryPosition(position)); final NavDirections action = StoryListViewerFragmentDirections.actionToStory(StoryViewerOptions.forFeedStoryPosition(position));
NavHostFragment.findNavController(StoryListViewerFragment.this).navigate(action); NavHostFragment.findNavController(StoryListViewerFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onFeedStoryClick: ", e);
}
} }
@Override @Override
@ -89,9 +91,12 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
@Override @Override
public void onHighlightClick(final Story model, final int position) { public void onHighlightClick(final Story model, final int position) {
if (model == null) return; if (model == null) return;
final NavDirections action = StoryListViewerFragmentDirections try {
.actionStoryListFragmentToStoryViewerFragment(StoryViewerOptions.forStoryArchive(position)); final NavDirections action = StoryListViewerFragmentDirections.actionToStory(StoryViewerOptions.forStoryArchive(position));
NavHostFragment.findNavController(StoryListViewerFragment.this).navigate(action); NavHostFragment.findNavController(StoryListViewerFragment.this).navigate(action);
} catch (Exception e) {
Log.e(TAG, "onHighlightClick: ", e);
}
} }
@Override @Override
@ -271,8 +276,11 @@ public final class StoryListViewerFragment extends Fragment implements SwipeRefr
} }
private void openProfile(final String username) { private void openProfile(final String username) {
final NavDirections action = MorePreferencesFragmentDirections try {
.actionGlobalProfileFragment("@" + username); final NavDirections action = StoryListViewerFragmentDirections.actionToProfile().setUsername(username);
NavHostFragment.findNavController(this).navigate(action); 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.io.IOException;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.Arrays;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.stream.Collectors;
import java.util.List; import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors;
import awais.instagrabber.BuildConfig; import awais.instagrabber.BuildConfig;
import awais.instagrabber.R; 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;
import awais.instagrabber.repositories.requests.StoryViewerOptions.Type; import awais.instagrabber.repositories.requests.StoryViewerOptions.Type;
import awais.instagrabber.repositories.requests.directmessages.ThreadIdsOrUserIds; 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.AppExecutors;
import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils; import awais.instagrabber.utils.CookieUtils;
@ -459,7 +468,8 @@ public class StoryViewerFragment extends Fragment {
final Bundle bundle = new Bundle(); final Bundle bundle = new Bundle();
bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media); bundle.putSerializable(PostViewV2Fragment.ARG_MEDIA, media);
try { try {
navController.navigate(R.id.action_global_post_view, bundle); final NavDirections action = StoryViewerFragmentDirections.actionToPost(media, 0);
navController.navigate(action);
alertDialog.dismiss(); alertDialog.dismiss();
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "openPostDialog: ", e); Log.e(TAG, "openPostDialog: ", e);
@ -1243,14 +1253,13 @@ public class StoryViewerFragment extends Fragment {
} }
final char t = username.charAt(0); final char t = username.charAt(0);
if (t == '@') { if (t == '@') {
final NavDirections action = HashTagFragmentDirections.actionGlobalProfileFragment(username); final NavDirections action = HashTagFragmentDirections.actionToProfile().setUsername(username);
NavHostFragment.findNavController(this).navigate(action); NavHostFragment.findNavController(this).navigate(action);
} else if (t == '#') { } else if (t == '#') {
final NavDirections action = HashTagFragmentDirections.actionGlobalHashTagFragment(username.substring(1)); final NavDirections action = HashTagFragmentDirections.actionToHashtag(username.substring(1));
NavHostFragment.findNavController(this).navigate(action); NavHostFragment.findNavController(this).navigate(action);
} else { } else {
final NavDirections action = ProfileFragmentDirections final NavDirections action = ProfileFragmentDirections.actionToLocation(Long.parseLong(username.split(" \\(")[1].replace(")", "")));
.actionGlobalLocationFragment(Long.parseLong(username.split(" \\(")[1].replace(")", "")));
NavHostFragment.findNavController(this).navigate(action); NavHostFragment.findNavController(this).navigate(action);
} }
} }

View File

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

View File

@ -309,20 +309,4 @@ public class UserSearchFragment extends Fragment {
} }
return null; 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, viewModel,
(comment, focusInput) -> { (comment, focusInput) -> {
if (comment == null) return null; 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() getChildFragmentManager().beginTransaction()
.setCustomAnimations(R.anim.slide_left, R.anim.slide_right, 0, R.anim.slide_right) .setCustomAnimations(R.anim.slide_left, R.anim.slide_right, 0, R.anim.slide_right)
.add(R.id.replies_container_view, repliesFragment) .add(R.id.replies_container_view, repliesFragment)

View File

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

View File

@ -185,18 +185,22 @@ public class RepliesFragment extends Fragment {
private void setupAdapter(final long currentUserId) { private void setupAdapter(final long currentUserId) {
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
commentsAdapter = new CommentsAdapter(currentUserId, commentsAdapter = new CommentsAdapter(
true, currentUserId,
Helper.getCommentCallback(context, true,
getViewLifecycleOwner(), Helper.getCommentCallback(
getNavController(), context,
viewModel, getViewLifecycleOwner(),
(comment, focusInput) -> { getNavController(),
viewModel.setReplyTo(comment); viewModel,
binding.commentText.setText(String.format("@%s ", comment.getUser().getUsername())); (comment, focusInput) -> {
if (focusInput) Utils.showKeyboard(binding.commentText); viewModel.setReplyTo(comment);
return null; binding.commentText.setText(String.format("@%s ", comment.getUser().getUsername()));
})); if (focusInput) Utils.showKeyboard(binding.commentText);
return null;
}
)
);
binding.comments.setAdapter(commentsAdapter); binding.comments.setAdapter(commentsAdapter);
final Resource<List<Comment>> listResource = viewModel.getReplyList().getValue(); final Resource<List<Comment>> listResource = viewModel.getReplyList().getValue();
commentsAdapter.submitList(listResource != null ? listResource.data : Collections.emptyList()); 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.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
import awais.instagrabber.R import awais.instagrabber.R
@ -103,9 +103,9 @@ class DirectMessageInboxFragment : Fragment(), OnRefreshListener {
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.pending_requests) { if (item.itemId == R.id.pending_requests) {
val directions = DirectMessageInboxFragmentDirections.actionInboxToPendingInbox()
try { try {
NavHostFragment.findNavController(this).navigate(directions) val directions = DirectMessageInboxFragmentDirections.actionToPendingInbox()
findNavController().navigate(directions)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "onOptionsItemSelected: ", e) Log.e(TAG, "onOptionsItemSelected: ", e)
} }
@ -210,9 +210,9 @@ class DirectMessageInboxFragment : Fragment(), OnRefreshListener {
if (navigating || threadId.isNullOrBlank() || threadTitle.isNullOrBlank()) return@DirectMessageInboxAdapter if (navigating || threadId.isNullOrBlank() || threadTitle.isNullOrBlank()) return@DirectMessageInboxAdapter
navigating = true navigating = true
if (isAdded) { if (isAdded) {
val directions = DirectMessageInboxFragmentDirections.actionInboxToThread(threadId, threadTitle)
try { try {
NavHostFragment.findNavController(this).navigate(directions) val directions = DirectMessageInboxFragmentDirections.actionToThread(threadId, threadTitle)
findNavController().navigate(directions)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "init: ", e) Log.e(TAG, "init: ", e)
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,6 @@
package awais.instagrabber.fragments.settings; package awais.instagrabber.fragments.settings;
import android.content.Context; import android.content.Context;
import android.util.Pair;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.preference.ListPreference; import androidx.preference.ListPreference;
@ -17,8 +16,9 @@ import awais.instagrabber.dialogs.TabOrderPreferenceDialogFragment;
import awais.instagrabber.models.Tab; import awais.instagrabber.models.Tab;
import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.Constants;
import awais.instagrabber.utils.CookieUtils; import awais.instagrabber.utils.CookieUtils;
import awais.instagrabber.utils.NavigationHelperKt;
import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils; import kotlin.Pair;
import static awais.instagrabber.utils.Utils.settingsHelper; import static awais.instagrabber.utils.Utils.settingsHelper;
@ -37,27 +37,28 @@ public class GeneralPreferencesFragment extends BasePreferencesFragment implemen
screen.addPreference(getUpdateCheckPreference(context)); screen.addPreference(getUpdateCheckPreference(context));
screen.addPreference(getFlagSecurePreference(context)); screen.addPreference(getFlagSecurePreference(context));
screen.addPreference(getSearchFocusPreference(context)); screen.addPreference(getSearchFocusPreference(context));
final List<Preference> preferences = FlavorSettings.getInstance() final List<Preference> preferences = FlavorSettings
.getPreferences(context, .getInstance()
getChildFragmentManager(), .getPreferences(
SettingCategory.GENERAL); context,
if (preferences != null) { getChildFragmentManager(),
for (final Preference preference : preferences) { SettingCategory.GENERAL
screen.addPreference(preference); );
} for (final Preference preference : preferences) {
screen.addPreference(preference);
} }
} }
private Preference getDefaultTabPreference(@NonNull final Context context) { private Preference getDefaultTabPreference(@NonNull final Context context) {
final ListPreference preference = new ListPreference(context); final ListPreference preference = new ListPreference(context);
preference.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance()); preference.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
final Pair<List<Tab>, List<Tab>> listPair = Utils.getNavTabList(context); final Pair<List<Tab>, List<Tab>> listPair = NavigationHelperKt.getLoggedInNavTabs(context);
final List<Tab> tabs = listPair.first; final List<Tab> tabs = listPair.getFirst();
final String[] titles = tabs.stream() final String[] titles = tabs.stream()
.map(Tab::getTitle) .map(Tab::getTitle)
.toArray(String[]::new); .toArray(String[]::new);
final String[] navGraphFileNames = tabs.stream() final String[] navGraphFileNames = tabs.stream()
.map(Tab::getGraphName) .map(tab -> NavigationHelperKt.geNavGraphNameForNavRootId(tab.getNavigationRootId()))
.toArray(String[]::new); .toArray(String[]::new);
preference.setKey(Constants.DEFAULT_TAB); preference.setKey(Constants.DEFAULT_TAB);
preference.setTitle(R.string.pref_start_screen); 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.CookieUtils;
import awais.instagrabber.utils.CoroutineUtilsKt; import awais.instagrabber.utils.CoroutineUtilsKt;
import awais.instagrabber.utils.FlavorTown; import awais.instagrabber.utils.FlavorTown;
import awais.instagrabber.utils.NavigationHelperKt;
import awais.instagrabber.utils.ProcessPhoenix; import awais.instagrabber.utils.ProcessPhoenix;
import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.TextUtils;
import awais.instagrabber.utils.Utils; import awais.instagrabber.utils.Utils;
@ -174,14 +175,18 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
boolean showActivity = true; boolean showActivity = true;
boolean showExplore = false; boolean showExplore = false;
if (activity != null) { if (activity != null) {
showActivity = !Utils.isNavRootInCurrentTabs("notification_viewer_nav_graph"); showActivity = !NavigationHelperKt.isNavRootInCurrentTabs("notification_viewer_nav_graph");
showExplore = !Utils.isNavRootInCurrentTabs("discover_nav_graph"); showExplore = !NavigationHelperKt.isNavRootInCurrentTabs("discover_nav_graph");
} }
if (showActivity) { if (showActivity) {
screen.addPreference(getPreference(R.string.action_notif, R.drawable.ic_not_liked, preference -> { screen.addPreference(getPreference(R.string.action_notif, R.drawable.ic_not_liked, preference -> {
if (isSafeToNavigate(navController)) { if (isSafeToNavigate(navController)) {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalNotificationsViewerFragment("notif"); try {
navController.navigate(navDirections); final NavDirections navDirections = MorePreferencesFragmentDirections.actionToNotifications().setType("notif");
navController.navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "setupPreferenceScreen: ", e);
}
} }
return true; return true;
})); }));
@ -197,15 +202,23 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
screen.addPreference(getPreference(R.string.action_ayml, R.drawable.ic_suggested_users, preference -> { screen.addPreference(getPreference(R.string.action_ayml, R.drawable.ic_suggested_users, preference -> {
if (isSafeToNavigate(navController)) { if (isSafeToNavigate(navController)) {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalNotificationsViewerFragment("ayml"); try {
navController.navigate(navDirections); final NavDirections navDirections = MorePreferencesFragmentDirections.actionToNotifications().setType("ayml");
navController.navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "setupPreferenceScreen: ", e);
}
} }
return true; return true;
})); }));
screen.addPreference(getPreference(R.string.action_archive, R.drawable.ic_archive, preference -> { screen.addPreference(getPreference(R.string.action_archive, R.drawable.ic_archive, preference -> {
if (isSafeToNavigate(navController)) { if (isSafeToNavigate(navController)) {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionGlobalStoryListViewerFragment("archive"); try {
navController.navigate(navDirections); final NavDirections navDirections = MorePreferencesFragmentDirections.actionToStoryList("archive");
navController.navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "setupPreferenceScreen: ", e);
}
} }
return true; 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 // Check if favorites has been added as a tab. And if so, do not add in this list
boolean showFavorites = true; boolean showFavorites = true;
if (activity != null) { if (activity != null) {
showFavorites = !Utils.isNavRootInCurrentTabs("favorites_nav_graph"); showFavorites = !NavigationHelperKt.isNavRootInCurrentTabs("favorites_nav_graph");
} }
if (showFavorites) { if (showFavorites) {
screen.addPreference(getPreference(R.string.title_favorites, R.drawable.ic_star_24, preference -> { screen.addPreference(getPreference(R.string.title_favorites, R.drawable.ic_star_24, preference -> {
if (isSafeToNavigate(navController)) { if (isSafeToNavigate(navController)) {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionMorePreferencesFragmentToFavoritesFragment(); try {
navController.navigate(navDirections); final NavDirections navDirections = MorePreferencesFragmentDirections.actionToFavorites();
navController.navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "setupPreferenceScreen: ", e);
}
} }
return true; return true;
})); }));
@ -229,36 +246,50 @@ public class MorePreferencesFragment extends BasePreferencesFragment {
screen.addPreference(getDivider(context)); screen.addPreference(getDivider(context));
screen.addPreference(getPreference(R.string.action_settings, R.drawable.ic_outline_settings_24, preference -> { screen.addPreference(getPreference(R.string.action_settings, R.drawable.ic_outline_settings_24, preference -> {
if (isSafeToNavigate(navController)) { if (isSafeToNavigate(navController)) {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionMorePreferencesFragmentToSettingsPreferencesFragment(); try {
navController.navigate(navDirections); final NavDirections navDirections = MorePreferencesFragmentDirections.actionToSettings();
navController.navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "setupPreferenceScreen: ", e);
}
} }
return true; return true;
})); }));
screen.addPreference(getPreference(R.string.backup_and_restore, R.drawable.ic_settings_backup_restore_24, preference -> { screen.addPreference(getPreference(R.string.backup_and_restore, R.drawable.ic_settings_backup_restore_24, preference -> {
if (isSafeToNavigate(navController)) { if (isSafeToNavigate(navController)) {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionMorePreferencesFragmentToBackupPreferencesFragment(); try {
navController.navigate(navDirections); final NavDirections navDirections = MorePreferencesFragmentDirections.actionToBackup();
navController.navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "setupPreferenceScreen: ", e);
}
} }
return true; return true;
})); }));
screen.addPreference(getPreference(R.string.action_about, R.drawable.ic_outline_info_24, preference1 -> { screen.addPreference(getPreference(R.string.action_about, R.drawable.ic_outline_info_24, preference1 -> {
if (isSafeToNavigate(navController)) { if (isSafeToNavigate(navController)) {
final NavDirections navDirections = MorePreferencesFragmentDirections.actionMorePreferencesFragmentToAboutFragment(); try {
navController.navigate(navDirections); final NavDirections navDirections = MorePreferencesFragmentDirections.actionToAbout();
navController.navigate(navDirections);
} catch (Exception e) {
Log.e(TAG, "setupPreferenceScreen: ", e);
}
} }
return true; return true;
})); }));
screen.addPreference(getDivider(context)); screen.addPreference(getDivider(context));
screen.addPreference(getPreference(R.string.version, screen.addPreference(getPreference(
BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")", R.string.version,
-1, BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")",
preference -> { -1,
if (BuildConfig.isPre) return true; preference -> {
if (activity == null) return false; if (BuildConfig.isPre) return true;
FlavorTown.updateCheck(activity, true); if (activity == null) return false;
return true; FlavorTown.updateCheck(activity, true);
})); return true;
})
);
screen.addPreference(getDivider(context)); screen.addPreference(getDivider(context));
final Preference reminderPreference = getPreference(R.string.reminder, R.string.reminder_summary, R.drawable.ic_warning, null); 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 // adds cookies to database for quick access
final long uid = CookieUtils.getUserIdFromCookie(cookie); final long uid = CookieUtils.getUserIdFromCookie(cookie);
final UserRepository userRepository = UserRepository.Companion.getInstance(); final UserRepository userRepository = UserRepository.Companion.getInstance();
userRepository.getUserInfo(uid, CoroutineUtilsKt.getContinuation((user, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { userRepository
if (throwable != null) { .getUserInfo(uid, CoroutineUtilsKt.getContinuation((user, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
Log.e(TAG, "Error fetching user info", throwable); if (throwable != null) {
return; Log.e(TAG, "Error fetching user info", throwable);
} return;
if (user != null) { }
accountRepository.insertOrUpdateAccount( if (user != null) {
uid, accountRepository.insertOrUpdateAccount(
user.getUsername(), uid,
cookie, user.getUsername(),
user.getFullName(), cookie,
user.getProfilePicUrl(), user.getFullName(),
CoroutineUtilsKt.getContinuation((account, throwable1) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { user.getProfilePicUrl(),
if (throwable1 != null) { CoroutineUtilsKt.getContinuation((account, throwable1) -> AppExecutors.INSTANCE.getMainThread().execute(() -> {
Log.e(TAG, "onActivityResult: ", throwable1); if (throwable1 != null) {
return; Log.e(TAG, "onActivityResult: ", throwable1);
} return;
AppExecutors.INSTANCE.getMainThread().execute(() -> { }
final Context context = getContext(); AppExecutors.INSTANCE.getMainThread().execute(() -> {
if (context == null) return; final Context context = getContext();
ProcessPhoenix.triggerRebirth(context); if (context == null) return;
}, 200); ProcessPhoenix.triggerRebirth(context);
}), Dispatchers.getIO()) }, 200);
); }), Dispatchers.getIO())
} );
}), Dispatchers.getIO())); }
}), Dispatchers.getIO()));
} }
} }

View File

@ -2,24 +2,12 @@ package awais.instagrabber.models
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.IdRes import androidx.annotation.IdRes
import androidx.annotation.NavigationRes
data class Tab( data class Tab(
@param:DrawableRes val iconResId: Int, @param:DrawableRes val iconResId: Int,
val title: String, val title: String,
val isRemovable: Boolean, 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. * This is the resource id of the root navigation tag of the navigation resource.
* *

View File

@ -1,247 +1,247 @@
package awais.instagrabber.utils; // package awais.instagrabber.utils;
//
import android.annotation.SuppressLint; // import android.annotation.SuppressLint;
import android.content.Intent; // import android.content.Intent;
import android.util.Log; // import android.util.Log;
import android.util.SparseArray; // import android.util.SparseArray;
//
import androidx.annotation.NonNull; // import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; // import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; // import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction; // import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.LiveData; // import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; // import androidx.lifecycle.MutableLiveData;
import androidx.navigation.NavController; // import androidx.navigation.NavController;
import androidx.navigation.NavDestination; // import androidx.navigation.NavDestination;
import androidx.navigation.NavGraph; // import androidx.navigation.NavGraph;
import androidx.navigation.fragment.NavHostFragment; // import androidx.navigation.fragment.NavHostFragment;
//
import com.google.android.material.bottomnavigation.BottomNavigationView; // import com.google.android.material.bottomnavigation.BottomNavigationView;
//
import java.util.List; // import java.util.List;
//
import awais.instagrabber.R; // import awais.instagrabber.R;
import awais.instagrabber.customviews.NavHostFragmentWithDefaultAnimations; // import awais.instagrabber.customviews.NavHostFragmentWithDefaultAnimations;
import awais.instagrabber.fragments.main.FeedFragment; // 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> // * 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. // * from architecture-components-samples. Some modifications have been done, check git history.
*/ // */
public class NavigationExtensions { // public class NavigationExtensions {
private static final String TAG = NavigationExtensions.class.getSimpleName(); // private static final String TAG = NavigationExtensions.class.getSimpleName();
private static String selectedItemTag; // private static String selectedItemTag;
private static boolean isOnFirstFragment; // private static boolean isOnFirstFragment;
//
@NonNull // @NonNull
public static LiveData<NavController> setupWithNavController(@NonNull final BottomNavigationView bottomNavigationView, // public static LiveData<NavController> setupWithNavController(@NonNull final BottomNavigationView bottomNavigationView,
@NonNull List<Integer> navGraphIds, // @NonNull List<Integer> navGraphIds,
@NonNull final FragmentManager fragmentManager, // @NonNull final FragmentManager fragmentManager,
final int containerId, // final int containerId,
@NonNull Intent intent, // @NonNull Intent intent,
final int firstFragmentGraphIndex) { // final int firstFragmentGraphIndex) {
final SparseArray<String> graphIdToTagMap = new SparseArray<>(); // final SparseArray<String> graphIdToTagMap = new SparseArray<>();
final MutableLiveData<NavController> selectedNavController = new MutableLiveData<>(); // final MutableLiveData<NavController> selectedNavController = new MutableLiveData<>();
int firstFragmentGraphId = 0; // int firstFragmentGraphId = 0;
for (int i = 0; i < navGraphIds.size(); i++) { // for (int i = 0; i < navGraphIds.size(); i++) {
final int navGraphId = navGraphIds.get(i); // final int navGraphId = navGraphIds.get(i);
final String fragmentTag = getFragmentTag(navGraphId); // final String fragmentTag = getFragmentTag(navGraphId);
final NavHostFragment navHostFragment = obtainNavHostFragment(fragmentManager, fragmentTag, navGraphId, containerId); // final NavHostFragment navHostFragment = obtainNavHostFragment(fragmentManager, fragmentTag, navGraphId, containerId);
final NavController navController = navHostFragment.getNavController(); // final NavController navController = navHostFragment.getNavController();
final int graphId = navController.getGraph().getId(); // final int graphId = navController.getGraph().getId();
if (i == firstFragmentGraphIndex) { // if (i == firstFragmentGraphIndex) {
firstFragmentGraphId = graphId; // firstFragmentGraphId = graphId;
} // }
graphIdToTagMap.put(graphId, fragmentTag); // graphIdToTagMap.put(graphId, fragmentTag);
if (bottomNavigationView.getSelectedItemId() == graphId) { // if (bottomNavigationView.getSelectedItemId() == graphId) {
selectedNavController.setValue(navHostFragment.getNavController()); // selectedNavController.setValue(navHostFragment.getNavController());
attachNavHostFragment(fragmentManager, navHostFragment, i == firstFragmentGraphIndex); // attachNavHostFragment(fragmentManager, navHostFragment, i == firstFragmentGraphIndex);
} else { // } else {
detachNavHostFragment(fragmentManager, navHostFragment); // detachNavHostFragment(fragmentManager, navHostFragment);
} // }
} // }
selectedItemTag = graphIdToTagMap.get(bottomNavigationView.getSelectedItemId()); // selectedItemTag = graphIdToTagMap.get(bottomNavigationView.getSelectedItemId());
final String firstFragmentTag = graphIdToTagMap.get(firstFragmentGraphId); // final String firstFragmentTag = graphIdToTagMap.get(firstFragmentGraphId);
isOnFirstFragment = selectedItemTag != null && selectedItemTag.equals(firstFragmentTag); // isOnFirstFragment = selectedItemTag != null && selectedItemTag.equals(firstFragmentTag);
bottomNavigationView.setOnItemSelectedListener(item -> { // bottomNavigationView.setOnItemSelectedListener(item -> {
if (fragmentManager.isStateSaved()) { // if (fragmentManager.isStateSaved()) {
return false; // return false;
} // }
String newlySelectedItemTag = graphIdToTagMap.get(item.getItemId()); // String newlySelectedItemTag = graphIdToTagMap.get(item.getItemId());
String tag = selectedItemTag; // String tag = selectedItemTag;
if (tag != null && !tag.equals(newlySelectedItemTag)) { // if (tag != null && !tag.equals(newlySelectedItemTag)) {
fragmentManager.popBackStack(firstFragmentTag, FragmentManager.POP_BACK_STACK_INCLUSIVE); // fragmentManager.popBackStack(firstFragmentTag, FragmentManager.POP_BACK_STACK_INCLUSIVE);
Fragment fragment = fragmentManager.findFragmentByTag(newlySelectedItemTag); // Fragment fragment = fragmentManager.findFragmentByTag(newlySelectedItemTag);
if (fragment == null) { // if (fragment == null) {
return false; // return false;
// throw new RuntimeException("null cannot be cast to non-null NavHostFragment"); // // throw new RuntimeException("null cannot be cast to non-null NavHostFragment");
} // }
final NavHostFragment selectedFragment = (NavHostFragment) fragment; // final NavHostFragment selectedFragment = (NavHostFragment) fragment;
if (firstFragmentTag != null && !firstFragmentTag.equals(newlySelectedItemTag)) { // if (firstFragmentTag != null && !firstFragmentTag.equals(newlySelectedItemTag)) {
FragmentTransaction fragmentTransaction = fragmentManager // FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction() // .beginTransaction()
.setCustomAnimations( // .setCustomAnimations(
R.anim.nav_default_enter_anim, // R.anim.nav_default_enter_anim,
R.anim.nav_default_exit_anim, // R.anim.nav_default_exit_anim,
R.anim.nav_default_pop_enter_anim, // R.anim.nav_default_pop_enter_anim,
R.anim.nav_default_pop_exit_anim // R.anim.nav_default_pop_exit_anim
) // )
.attach(selectedFragment) // .attach(selectedFragment)
.setPrimaryNavigationFragment(selectedFragment); // .setPrimaryNavigationFragment(selectedFragment);
for (int i = 0; i < graphIdToTagMap.size(); i++) { // for (int i = 0; i < graphIdToTagMap.size(); i++) {
final int key = graphIdToTagMap.keyAt(i); // final int key = graphIdToTagMap.keyAt(i);
final String fragmentTagForId = graphIdToTagMap.get(key); // final String fragmentTagForId = graphIdToTagMap.get(key);
if (!fragmentTagForId.equals(newlySelectedItemTag)) { // if (!fragmentTagForId.equals(newlySelectedItemTag)) {
final Fragment fragmentByTag = fragmentManager.findFragmentByTag(firstFragmentTag); // final Fragment fragmentByTag = fragmentManager.findFragmentByTag(firstFragmentTag);
if (fragmentByTag == null) { // if (fragmentByTag == null) {
continue; // continue;
} // }
fragmentTransaction.detach(fragmentByTag); // fragmentTransaction.detach(fragmentByTag);
} // }
} // }
fragmentTransaction.addToBackStack(firstFragmentTag) // fragmentTransaction.addToBackStack(firstFragmentTag)
.setReorderingAllowed(true) // .setReorderingAllowed(true)
.commit(); // .commit();
} // }
selectedItemTag = newlySelectedItemTag; // selectedItemTag = newlySelectedItemTag;
isOnFirstFragment = selectedItemTag.equals(firstFragmentTag); // isOnFirstFragment = selectedItemTag.equals(firstFragmentTag);
selectedNavController.setValue(selectedFragment.getNavController()); // selectedNavController.setValue(selectedFragment.getNavController());
return true; // return true;
} // }
return false; // return false;
}); // });
setupItemReselected(bottomNavigationView, graphIdToTagMap, fragmentManager); // setupItemReselected(bottomNavigationView, graphIdToTagMap, fragmentManager);
setupDeepLinks(bottomNavigationView, navGraphIds, fragmentManager, containerId, intent); // setupDeepLinks(bottomNavigationView, navGraphIds, fragmentManager, containerId, intent);
final int finalFirstFragmentGraphId = firstFragmentGraphId; // final int finalFirstFragmentGraphId = firstFragmentGraphId;
fragmentManager.addOnBackStackChangedListener(() -> { // fragmentManager.addOnBackStackChangedListener(() -> {
if (!isOnFirstFragment) { // if (!isOnFirstFragment) {
if (firstFragmentTag == null) { // if (firstFragmentTag == null) {
return; // return;
} // }
if (!isOnBackStack(fragmentManager, firstFragmentTag)) { // if (!isOnBackStack(fragmentManager, firstFragmentTag)) {
bottomNavigationView.setSelectedItemId(finalFirstFragmentGraphId); // bottomNavigationView.setSelectedItemId(finalFirstFragmentGraphId);
} // }
} // }
//
final NavController navController = selectedNavController.getValue(); // final NavController navController = selectedNavController.getValue();
if (navController != null && navController.getCurrentDestination() == null) { // if (navController != null && navController.getCurrentDestination() == null) {
final NavGraph navControllerGraph = navController.getGraph(); // final NavGraph navControllerGraph = navController.getGraph();
navController.navigate(navControllerGraph.getId()); // navController.navigate(navControllerGraph.getId());
} // }
}); // });
return selectedNavController; // return selectedNavController;
} // }
//
private static NavHostFragment obtainNavHostFragment(final FragmentManager fragmentManager, // private static NavHostFragment obtainNavHostFragment(final FragmentManager fragmentManager,
final String fragmentTag, // final String fragmentTag,
final int navGraphId, // final int navGraphId,
final int containerId) { // final int containerId) {
final NavHostFragment existingFragment = (NavHostFragment) fragmentManager.findFragmentByTag(fragmentTag); // final NavHostFragment existingFragment = (NavHostFragment) fragmentManager.findFragmentByTag(fragmentTag);
if (existingFragment != null) { // if (existingFragment != null) {
return existingFragment; // return existingFragment;
} // }
final NavHostFragment navHostFragment = NavHostFragmentWithDefaultAnimations.create(navGraphId); // final NavHostFragment navHostFragment = NavHostFragmentWithDefaultAnimations.create(navGraphId);
fragmentManager.beginTransaction() // fragmentManager.beginTransaction()
.setReorderingAllowed(true) // .setReorderingAllowed(true)
.add(containerId, navHostFragment, fragmentTag) // .add(containerId, navHostFragment, fragmentTag)
.commitNow(); // .commitNow();
return navHostFragment; // return navHostFragment;
} // }
//
private static void attachNavHostFragment(final FragmentManager fragmentManager, // private static void attachNavHostFragment(final FragmentManager fragmentManager,
final NavHostFragment navHostFragment, // final NavHostFragment navHostFragment,
final boolean isPrimaryNavFragment) { // final boolean isPrimaryNavFragment) {
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction() // final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
.attach(navHostFragment); // .attach(navHostFragment);
if (isPrimaryNavFragment) { // if (isPrimaryNavFragment) {
fragmentTransaction.setPrimaryNavigationFragment(navHostFragment); // fragmentTransaction.setPrimaryNavigationFragment(navHostFragment);
} // }
fragmentTransaction.commitNow(); // fragmentTransaction.commitNow();
} // }
//
private static void detachNavHostFragment(final FragmentManager fragmentManager, final NavHostFragment navHostFragment) { // private static void detachNavHostFragment(final FragmentManager fragmentManager, final NavHostFragment navHostFragment) {
fragmentManager.beginTransaction() // fragmentManager.beginTransaction()
.detach(navHostFragment) // .detach(navHostFragment)
.commitNow(); // .commitNow();
} // }
//
@SuppressLint("RestrictedApi") // @SuppressLint("RestrictedApi")
private static void setupItemReselected(final BottomNavigationView bottomNavigationView, // private static void setupItemReselected(final BottomNavigationView bottomNavigationView,
final SparseArray<String> graphIdToTagMap, // final SparseArray<String> graphIdToTagMap,
final FragmentManager fragmentManager) { // final FragmentManager fragmentManager) {
bottomNavigationView.setOnItemReselectedListener(item -> { // bottomNavigationView.setOnItemReselectedListener(item -> {
final String newlySelectedItemTag = graphIdToTagMap.get(item.getItemId()); // final String newlySelectedItemTag = graphIdToTagMap.get(item.getItemId());
final Fragment fragmentByTag = fragmentManager.findFragmentByTag(newlySelectedItemTag); // final Fragment fragmentByTag = fragmentManager.findFragmentByTag(newlySelectedItemTag);
if (fragmentByTag == null) { // if (fragmentByTag == null) {
return; // return;
} // }
final NavHostFragment selectedFragment = (NavHostFragment) fragmentByTag; // final NavHostFragment selectedFragment = (NavHostFragment) fragmentByTag;
final NavController navController = selectedFragment.getNavController(); // final NavController navController = selectedFragment.getNavController();
final NavGraph navControllerGraph = navController.getGraph(); // final NavGraph navControllerGraph = navController.getGraph();
final NavDestination currentDestination = navController.getCurrentDestination(); // final NavDestination currentDestination = navController.getCurrentDestination();
final int startDestination = navControllerGraph.getStartDestination(); // final int startDestination = navControllerGraph.getStartDestination();
int backStackSize = navController.getBackStack().size(); // int backStackSize = navController.getBackStack().size();
if (currentDestination != null && backStackSize == 2 && currentDestination.getId() == startDestination) { // if (currentDestination != null && backStackSize == 2 && currentDestination.getId() == startDestination) {
// scroll to top // // scroll to top
final List<Fragment> fragments = selectedFragment.getChildFragmentManager().getFragments(); // final List<Fragment> fragments = selectedFragment.getChildFragmentManager().getFragments();
if (fragments.isEmpty()) return; // if (fragments.isEmpty()) return;
final Fragment fragment = fragments.get(0); // final Fragment fragment = fragments.get(0);
if (fragment instanceof FeedFragment) { // if (fragment instanceof FeedFragment) {
((FeedFragment) fragment).scrollToTop(); // ((FeedFragment) fragment).scrollToTop();
} // }
return; // return;
} // }
final boolean popped = navController.popBackStack(startDestination, false); // final boolean popped = navController.popBackStack(startDestination, false);
backStackSize = navController.getBackStack().size(); // backStackSize = navController.getBackStack().size();
if (!popped || backStackSize > 2) { // if (!popped || backStackSize > 2) {
try { // try {
// try loop pop // // try loop pop
do { // do {
navController.popBackStack(); // navController.popBackStack();
backStackSize = navController.getBackStack().size(); // backStackSize = navController.getBackStack().size();
} while (backStackSize > 2); // } while (backStackSize > 2);
} catch (Exception e) { // } catch (Exception e) {
Log.e(TAG, "setupItemReselected: ", e); // Log.e(TAG, "setupItemReselected: ", e);
} // }
} // }
}); // });
} // }
//
private static void setupDeepLinks(final BottomNavigationView bottomNavigationView, // private static void setupDeepLinks(final BottomNavigationView bottomNavigationView,
final List<Integer> navGraphIds, // final List<Integer> navGraphIds,
final FragmentManager fragmentManager, // final FragmentManager fragmentManager,
final int containerId, // final int containerId,
final Intent intent) { // final Intent intent) {
for (int i = 0; i < navGraphIds.size(); i++) { // for (int i = 0; i < navGraphIds.size(); i++) {
final int navGraphId = navGraphIds.get(i); // final int navGraphId = navGraphIds.get(i);
final String fragmentTag = getFragmentTag(navGraphId); // final String fragmentTag = getFragmentTag(navGraphId);
final NavHostFragment navHostFragment = obtainNavHostFragment(fragmentManager, fragmentTag, navGraphId, containerId); // final NavHostFragment navHostFragment = obtainNavHostFragment(fragmentManager, fragmentTag, navGraphId, containerId);
if (navHostFragment.getNavController().handleDeepLink(intent)) { // if (navHostFragment.getNavController().handleDeepLink(intent)) {
final int selectedItemId = bottomNavigationView.getSelectedItemId(); // final int selectedItemId = bottomNavigationView.getSelectedItemId();
NavController navController = navHostFragment.getNavController(); // NavController navController = navHostFragment.getNavController();
NavGraph graph = navController.getGraph(); // NavGraph graph = navController.getGraph();
if (selectedItemId != graph.getId()) { // if (selectedItemId != graph.getId()) {
navController = navHostFragment.getNavController(); // navController = navHostFragment.getNavController();
graph = navController.getGraph(); // graph = navController.getGraph();
bottomNavigationView.setSelectedItemId(graph.getId()); // bottomNavigationView.setSelectedItemId(graph.getId());
} // }
} // }
} // }
} // }
//
private static boolean isOnBackStack(final FragmentManager fragmentManager, final String backStackName) { // private static boolean isOnBackStack(final FragmentManager fragmentManager, final String backStackName) {
int backStackCount = fragmentManager.getBackStackEntryCount(); // int backStackCount = fragmentManager.getBackStackEntryCount();
for (int i = 0; i < backStackCount; i++) { // for (int i = 0; i < backStackCount; i++) {
final FragmentManager.BackStackEntry backStackEntry = fragmentManager.getBackStackEntryAt(i); // final FragmentManager.BackStackEntry backStackEntry = fragmentManager.getBackStackEntryAt(i);
final String name = backStackEntry.getName(); // final String name = backStackEntry.getName();
if (name != null && name.equals(backStackName)) { // if (name != null && name.equals(backStackName)) {
return true; // return true;
} // }
} // }
return false; // return false;
} // }
//
private static String getFragmentTag(final int index) { // private static String getFragmentTag(final int index) {
return "bottomNavigation#" + 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.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; 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.database.ExoDatabaseProvider;
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor; import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor;
import com.google.android.exoplayer2.upstream.cache.SimpleCache; import com.google.android.exoplayer2.upstream.cache.SimpleCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import org.json.JSONObject; import org.json.JSONObject;
@ -55,22 +52,15 @@ import java.io.File;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import awais.instagrabber.R; import awais.instagrabber.R;
import awais.instagrabber.fragments.settings.PreferenceKeys;
import awais.instagrabber.models.PostsLayoutPreferences; import awais.instagrabber.models.PostsLayoutPreferences;
import awais.instagrabber.models.Tab;
import awais.instagrabber.models.enums.FavoriteType; import awais.instagrabber.models.enums.FavoriteType;
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_BARINSTA_DIR_URI;
public final class Utils { public final class Utils {
private static final String TAG = "Utils"; private static final String TAG = "Utils";
private static final int VIDEO_CACHE_MAX_BYTES = 10 * 1024 * 1024; 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 statusBarHeight;
private static int actionBarHeight; private static int actionBarHeight;
public static String cacheDir; public static String cacheDir;
public static String tabOrderString;
private static int defaultStatusBarColor; private static int defaultStatusBarColor;
private static Object[] volumes; 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, // public static void scanDocumentFile(@NonNull final Context context,
// @NonNull final DocumentFile documentFile, // @NonNull final DocumentFile documentFile,
// @NonNull final OnScanCompletedListener callback) { // @NonNull final OnScanCompletedListener callback) {

View File

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

View File

@ -60,9 +60,11 @@
<androidx.fragment.app.FragmentContainerView <androidx.fragment.app.FragmentContainerView
android:id="@+id/main_nav_host" android:id="@+id/main_nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clipToPadding="false" android:clipToPadding="false"
app:defaultNavHost="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior" /> app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<!--app:layout_behavior="@string/hide_bottom_view_on_scroll_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>HH:mm:ss</item>
<item>H:mm:ss</item> <item>H:mm:ss</item>
</string-array> </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/direct_messages_nav_graph</item>
<item>@id/feed_nav_graph</item> <item>@id/feed_nav_graph</item>
<item>@id/profile_nav_graph</item> <item>@id/profile_nav_graph</item>
<item>@id/discover_nav_graph</item> <item>@id/discover_nav_graph</item>
<item>@id/more_nav_graph</item> <item>@id/more_nav_graph</item>
<!-- New graphs should go below -->
<item>@id/favorites_nav_graph</item> <item>@id/favorites_nav_graph</item>
<item>@id/notification_viewer_nav_graph</item> <item>@id/notification_viewer_nav_graph</item>
</array> </array>
<!-- Nav graphs should correspond 1-to-1 with the above nav graph ids -->
<array name="main_nav_graphs"> <array name="anon_nav_root_ids">
<item>@navigation/direct_messages_nav_graph</item> <item>@id/favorites_nav_graph</item>
<item>@navigation/feed_nav_graph</item> <item>@id/profile_nav_graph</item>
<item>@navigation/profile_nav_graph</item> <item>@id/more_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> </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"> <string-array name="light_themes" translatable="false">
<item>@string/light_white_theme</item> <item>@string/light_white_theme</item>
<item>@string/light_barinsta_theme</item> <item>@string/light_barinsta_theme</item>

View File

@ -8,4 +8,15 @@
<item name="share_dm" type="id" /> <item name="share_dm" type="id" />
<item name="download_current" type="id" /> <item name="download_current" type="id" />
<item name="download_all" 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> </resources>

View File

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