import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
+import androidx.core.content.ContextCompat
import androidx.core.view.GravityCompat
import androidx.cursoradapter.widget.CursorAdapter
import androidx.drawerlayout.widget.DrawerLayout
import androidx.fragment.app.DialogFragment
import androidx.preference.PreferenceManager
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import androidx.viewpager2.widget.ViewPager2
import androidx.webkit.WebSettingsCompat
private lateinit var navigationForwardMenuItem: MenuItem
private lateinit var navigationHistoryMenuItem: MenuItem
private lateinit var navigationRequestsMenuItem: MenuItem
+ private lateinit var navigationView: NavigationView
private lateinit var optionsAddOrEditDomainMenuItem: MenuItem
private lateinit var optionsBlockAllThirdPartyRequestsMenuItem: MenuItem
private lateinit var optionsClearCookiesMenuItem: MenuItem
private var inFullScreenBrowsingMode = false
private var incognitoModeEnabled = false
private var loadingNewIntent = false
+ private var navigationDrawerFirstView = true
private var objectAnimator = ObjectAnimator()
private var optionsMenu: Menu? = null
private var orbotStatusBroadcastReceiver: BroadcastReceiver? = null
tabLayout = findViewById(R.id.tablayout)
swipeRefreshLayout = findViewById(R.id.swiperefreshlayout)
webViewViewPager2 = findViewById(R.id.webview_viewpager2)
- val navigationView = findViewById<NavigationView>(R.id.navigationview)
+ navigationView = findViewById(R.id.navigationview)
bookmarksListView = findViewById(R.id.bookmarks_drawer_listview)
bookmarksTitleTextView = findViewById(R.id.bookmarks_title_textview)
bookmarksDrawerPinnedImageView = findViewById(R.id.bookmarks_drawer_pinned_imageview)
// Run the default commands.
super.onConfigurationChanged(newConfig)
+ // Reset the navigation drawer first view flag.
+ navigationDrawerFirstView = true
+
// Get the current page.
val currentPage = webViewViewPager2.currentItem
// Get the package manager.
val packageManager = packageManager
- // Check to see if Orbot is in the list. This will throw an error and drop to the catch section if it isn't installed. The deprecated method must be used until the minimum API >= 33.
- @Suppress("DEPRECATION")
+ // Check to see if Orbot is in the list. This will throw an error and drop to the catch section if it isn't installed.
packageManager.getPackageInfo("org.torproject.android", 0)
// Check to see if the proxy is ready.
// Check to see if I2P is installed.
try {
// Check to see if the F-Droid flavor is installed. This will throw an error and drop to the catch section if it isn't installed.
- // The deprecated method must be used until the minimum API >= 33.
- @Suppress("DEPRECATION")
packageManager.getPackageInfo("net.i2p.android.router", 0)
} catch (fdroidException: PackageManager.NameNotFoundException) { // The F-Droid flavor is not installed.
try {
// Check to see if the Google Play flavor is installed. This will throw an error and drop to the catch section if it isn't installed.
- // The deprecated method must be used until the minimum API >= 33.
- @Suppress("DEPRECATION")
packageManager.getPackageInfo("net.i2p.android", 0)
} catch (googlePlayException: PackageManager.NameNotFoundException) { // The Google Play flavor is not installed.
// Sow the I2P not installed dialog if it is not already displayed.
}
}
- // Register the Orbot status broadcast receiver.
- registerReceiver(orbotStatusBroadcastReceiver, IntentFilter("org.torproject.android.intent.action.STATUS"))
+ // Register the Orbot status broadcast receiver. `ContextCompat` must be used until the minimum API >= 34.
+ ContextCompat.registerReceiver(this, orbotStatusBroadcastReceiver, IntentFilter("org.torproject.android.intent.action.STATUS"), ContextCompat.RECEIVER_EXPORTED)
// Get handles for views that need to be modified.
val bookmarksHeaderLinearLayout = findViewById<LinearLayout>(R.id.bookmarks_header_linearlayout)
// Close the find on page bar if it is open.
closeFindOnPage(null)
- // Select the same page in the view pager.
- webViewViewPager2.currentItem = tab.position
+ // Update the view pager when it has quiesced. Otherwise, if a page launched by a new intent on restart has not yet been created, the view pager will not be updated to match the tab layout.
+ webViewViewPager2.post {
+ // Select the same page in the view pager.
+ webViewViewPager2.currentItem = tab.position
- // Set the current WebView.
- setCurrentWebView(tab.position)
+ // Set the current WebView.
+ setCurrentWebView(tab.position)
+ }
}
override fun onTabUnselected(tab: TabLayout.Tab) {}
// Calculate the milliseconds since the last restart. This can be replaced by the simpler LocalDateTime once the minimum API >= 26.
val millisecondsSinceLastRestart = Date().time - restartTime.time
- // Only display the SSL certificate dialog if it has been at least 1 second since the last restart as deep restarts sometimes end up selecting a tab twice.
- if (millisecondsSinceLastRestart > 1000) {
+ // Only display the SSL certificate dialog if it has been at least 3 seconds since the last restart as deep restarts sometimes end up selecting a tab twice.
+ if (millisecondsSinceLastRestart > 3000) {
// Instantiate the View SSL Certificate dialog.
val viewSslCertificateDialogFragment: DialogFragment = ViewSslCertificateDialog.displayDialog(currentWebView!!.webViewFragmentId, currentWebView!!.getFavoriteIcon())
// Clear the focus from from the WebView if it is not null, which can happen if a user opens a drawer while the browser is being resumed.
// Clearing the focus from the WebView removes any text selection markers and context menus, which otherwise draw above the open drawers.
currentWebView?.clearFocus()
+
+ if (bottomAppBar && navigationDrawerFirstView) {
+ // Reset the navigation drawer first view flag.
+ navigationDrawerFirstView = false
+
+ // Get a handle for the navigation recycler view.
+ val navigationRecyclerView = navigationView.getChildAt(0) as RecyclerView
+
+ // Get the navigation linear layout manager.
+ val navigationLinearLayoutManager = navigationRecyclerView.layoutManager as LinearLayoutManager
+
+ // Scroll the navigation drawer to the bottom.
+ navigationLinearLayoutManager.scrollToPositionWithOffset(13, 0)
+ }
}
}
})
}
}
- override fun onFling(motionEvent1: MotionEvent, motionEvent2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
+ override fun onFling(motionEvent1: MotionEvent?, motionEvent2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
// Scroll the bottom app bar if enabled.
- if (bottomAppBar && scrollAppBar && !objectAnimator.isRunning) {
+ if (bottomAppBar && scrollAppBar && !objectAnimator.isRunning && (motionEvent1 != null)) {
// Calculate the Y change.
val motionY = motionEvent2.y - motionEvent1.y