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
private lateinit var navigationForwardMenuItem: MenuItem
private lateinit var navigationHistoryMenuItem: MenuItem
private lateinit var navigationRequestsMenuItem: MenuItem
+ private lateinit var navigationScrollToBottomMenuItem: MenuItem
private lateinit var navigationView: NavigationView
private lateinit var optionsAddOrEditDomainMenuItem: MenuItem
private lateinit var optionsBlockAllThirdPartyRequestsMenuItem: MenuItem
// Get handles for the navigation menu items.
navigationBackMenuItem = navigationMenu.findItem(R.id.back)
navigationForwardMenuItem = navigationMenu.findItem(R.id.forward)
+ navigationScrollToBottomMenuItem = navigationMenu.findItem(R.id.scroll_to_bottom)
navigationHistoryMenuItem = navigationMenu.findItem(R.id.history)
navigationRequestsMenuItem = navigationMenu.findItem(R.id.requests)
// Run the default commands.
super.onNewIntent(intent)
+ // Close the navigation drawer if it is open.
+ if (drawerLayout.isDrawerVisible(GravityCompat.START))
+ drawerLayout.closeDrawer(GravityCompat.START)
+
+ // Close the bookmarks drawer if it is open.
+ if (drawerLayout.isDrawerVisible(GravityCompat.END))
+ drawerLayout.closeDrawer(GravityCompat.END)
+
// Get the information from the intent.
val intentAction = intent.action
val intentUriData = intent.data
// Make it so.
loadUrl(currentWebView!!, url!!)
}
-
- // Close the navigation drawer if it is open.
- if (drawerLayout.isDrawerVisible(GravityCompat.START))
- drawerLayout.closeDrawer(GravityCompat.START)
-
- // Close the bookmarks drawer if it is open.
- if (drawerLayout.isDrawerVisible(GravityCompat.END))
- drawerLayout.closeDrawer(GravityCompat.END)
}
} else { // The app has been restarted.
// If the new intent will open a new tab, set the saved tab position to be the size of the saved state array list.
}
}
+ R.id.scroll_to_bottom -> { // Scroll to Bottom.
+ // Check if the WebView is scrolled to the top.
+ if (currentWebView!!.scrollY == 0) { // The WebView is at the top; scroll to the bottom. Using a large Y number is more efficient than trying to calculate the exact WebView length.
+ currentWebView!!.scrollTo(0, 1_000_000_000)
+ } else { // The WebView is not at the top; scroll to the top.
+ currentWebView!!.scrollTo(0, 0)
+ }
+ }
+
R.id.history -> { // History.
// Instantiate the URL history dialog.
val urlHistoryDialogFragment: DialogFragment = UrlHistoryDialog.loadBackForwardList(currentWebView!!.webViewFragmentId)
// 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)
if (newState == DrawerLayout.STATE_SETTLING || newState == DrawerLayout.STATE_DRAGGING) { // A drawer is opening or closing.
// Update the navigation menu items if the WebView is not null.
if (currentWebView != null) {
+ // Set the enabled status of the menu items.
navigationBackMenuItem.isEnabled = currentWebView!!.canGoBack()
navigationForwardMenuItem.isEnabled = currentWebView!!.canGoForward()
+ navigationScrollToBottomMenuItem.isEnabled = (currentWebView!!.canScrollVertically(-1) || currentWebView!!.canScrollVertically(1))
navigationHistoryMenuItem.isEnabled = currentWebView!!.canGoBack() || currentWebView!!.canGoForward()
+
+ // Update the scroll menu item.
+ if (currentWebView!!.scrollY == 0) { // The WebView is scrolled to the top.
+ // Set the title.
+ navigationScrollToBottomMenuItem.title = getString(R.string.scroll_to_bottom)
+
+ // Set the icon.
+ navigationScrollToBottomMenuItem.icon = AppCompatResources.getDrawable(applicationContext, R.drawable.move_down_enabled)
+ } else { // The WebView is not scrolled to the top.
+ // Set the title.
+ navigationScrollToBottomMenuItem.title = getString(R.string.scroll_to_top)
+
+ // Set the icon.
+ navigationScrollToBottomMenuItem.icon = AppCompatResources.getDrawable(applicationContext, R.drawable.move_up_enabled)
+ }
+
+ // Display the number of blocked requests.
navigationRequestsMenuItem.title = getString(R.string.requests) + " - " + currentWebView!!.getRequestsCount(BLOCKED_REQUESTS)
// Hide the keyboard (if displayed).
}
}
- 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