import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
+import android.view.WindowInsets
+import android.view.WindowInsetsController
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.webkit.CookieManager
private lateinit var bookmarksCursorAdapter: CursorAdapter
private lateinit var bookmarksListView: ListView
private lateinit var bookmarksDrawerPinnedImageView: ImageView
+ private lateinit var bookmarksFrameLayout: FrameLayout
private lateinit var bookmarksTitleTextView: TextView
+ private lateinit var browserFrameLayout: FrameLayout
private lateinit var coordinatorLayout: CoordinatorLayout
private lateinit var cookieManager: CookieManager
private lateinit var defaultFontSizeString: String
private lateinit var navigationRequestsMenuItem: MenuItem
private lateinit var navigationScrollToBottomMenuItem: MenuItem
private lateinit var navigationView: NavigationView
+ private lateinit var oldFullScreenVideoFrameLayout: FrameLayout
private lateinit var optionsAddOrEditDomainMenuItem: MenuItem
private lateinit var optionsBlockAllThirdPartyRequestsMenuItem: MenuItem
private lateinit var optionsClearCookiesMenuItem: MenuItem
private lateinit var optionsWideViewportMenuItem: MenuItem
private lateinit var proxyHelper: ProxyHelper
private lateinit var redColorSpan: ForegroundColorSpan
- private lateinit var rootFrameLayout: FrameLayout
private lateinit var saveUrlString: String
private lateinit var searchURL: String
private lateinit var sharedPreferences: SharedPreferences
private lateinit var webViewDefaultUserAgent: String
private lateinit var webViewThemeEntryValuesStringArray: Array<String>
private lateinit var webViewViewPager2: ViewPager2
+ private lateinit var windowInsetsController: WindowInsetsController
private lateinit var ultraList: ArrayList<List<Array<String>>>
private lateinit var urlEditText: EditText
private lateinit var urlRelativeLayout: RelativeLayout
val allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false)
bottomAppBar = sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)
displayAdditionalAppBarIcons = sharedPreferences.getBoolean(getString(R.string.display_additional_app_bar_icons_key), false)
-
- // Displaying under cutouts currently only works on API < 35. <https://redmine.stoutner.com/issues/1238>
- if (Build.VERSION.SDK_INT < 35) {
- // Get the display under cutouts preference.
- displayUnderCutouts = sharedPreferences.getBoolean(getString(R.string.display_under_cutouts_key), false)
-
- // Set the display under cutouts mode. This must be done here as it doesn't appear to work correctly if handled after the app is fully initialized.
- if (displayUnderCutouts) {
- if (Build.VERSION.SDK_INT >= 30)
- window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
- else if (Build.VERSION.SDK_INT >= 28)
- window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
- }
+ displayUnderCutouts = sharedPreferences.getBoolean(getString(R.string.display_under_cutouts_key), false)
+
+ // Set the display under cutouts mode. This must be done here as it doesn't appear to work correctly if handled after the app is fully initialized.
+ if ((Build.VERSION.SDK_INT < 35) && displayUnderCutouts) {
+ if (Build.VERSION.SDK_INT >= 30)
+ window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+ else if (Build.VERSION.SDK_INT >= 28)
+ window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
}
// Get the entry values string arrays.
setContentView(R.layout.main_framelayout_top_appbar)
// Get handles for the views.
- rootFrameLayout = findViewById(R.id.root_framelayout)
+ browserFrameLayout = findViewById(R.id.browser_framelayout)
drawerLayout = findViewById(R.id.drawerlayout)
coordinatorLayout = findViewById(R.id.coordinatorlayout)
appBarLayout = findViewById(R.id.appbar_layout)
swipeRefreshLayout = findViewById(R.id.swiperefreshlayout)
webViewViewPager2 = findViewById(R.id.webview_viewpager2)
navigationView = findViewById(R.id.navigationview)
+ bookmarksFrameLayout = findViewById(R.id.bookmarks_framelayout)
bookmarksListView = findViewById(R.id.bookmarks_drawer_listview)
bookmarksTitleTextView = findViewById(R.id.bookmarks_title_textview)
bookmarksDrawerPinnedImageView = findViewById(R.id.bookmarks_drawer_pinned_imageview)
+ oldFullScreenVideoFrameLayout = findViewById(R.id.old_full_screen_video_framelayout)
fullScreenVideoFrameLayout = findViewById(R.id.full_screen_video_framelayout)
+ // Get a handle for the window inset controller.
+ if (Build.VERSION.SDK_INT >= 30)
+ windowInsetsController = browserFrameLayout.windowInsetsController!!
+
+ // Set the layout to fit the system windows according to the API.
+ if (Build.VERSION.SDK_INT >= 35) {
+ // Set the browser frame layout to fit system windows.
+ browserFrameLayout.fitsSystemWindows = true
+ } else {
+ // Set the layouts to fit system windows.
+ coordinatorLayout.fitsSystemWindows = true
+ bookmarksFrameLayout.fitsSystemWindows = true
+ }
+
// Get a handle for the navigation menu.
val navigationMenu = navigationView.menu
if (proxyMode != ProxyHelper.NONE)
applyProxy(false)
- // Reapply any system UI flags.
- if (displayingFullScreenVideo || inFullScreenBrowsingMode) { // The system is displaying a website or a video in full screen mode.
+ // Reapply any system UI flags on older APIs.
+ if ((Build.VERSION.SDK_INT < 30) && (displayingFullScreenVideo || inFullScreenBrowsingMode)) { // The system is displaying a website or a video in full screen mode.
/* Hide the system bars.
* SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
* SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
* SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
*/
- // The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30.
@Suppress("DEPRECATION")
- rootFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ browserFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
}
// Show any pending dialogs.
proxyMode = sharedPreferences.getString(getString(R.string.proxy_key), getString(R.string.proxy_default_value))!!
fullScreenBrowsingModeEnabled = sharedPreferences.getBoolean(getString(R.string.full_screen_browsing_mode_key), false)
hideAppBar = sharedPreferences.getBoolean(getString(R.string.hide_app_bar_key), true)
+ displayUnderCutouts = sharedPreferences.getBoolean(getString(R.string.display_under_cutouts_key), false)
val downloadProvider = sharedPreferences.getString(getString(R.string.download_provider_key), getString(R.string.download_provider_default_value))!!
scrollAppBar = sharedPreferences.getBoolean(getString(R.string.scroll_app_bar_key), false)
sortBookmarksAlphabetically = sharedPreferences.getBoolean(getString(R.string.sort_bookmarks_alphabetically_key), false)
}
}
+ // Force an exit of full screen browsing mode if it is now disabled in settings.
+ if (!fullScreenBrowsingModeEnabled)
+ inFullScreenBrowsingMode = false
+
// Update the full screen browsing mode settings.
- if (fullScreenBrowsingModeEnabled && inFullScreenBrowsingMode) { // Privacy Browser is currently in full screen browsing mode.
+ if (inFullScreenBrowsingMode) { // Privacy Browser is currently in full screen browsing mode.
// Update the visibility of the app bar, which might have changed in the settings.
if (hideAppBar) {
// Hide the tab linear layout.
appBar.show()
}
- /* Hide the system bars.
- * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
- * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
- * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
- * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
- */
+ // Re-enforce the fullscreen flags if the API < 30.
+ if (Build.VERSION.SDK_INT < 30) {
+ /* Hide the system bars.
+ * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
+ * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
+ * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
+ * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
+ */
- // The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30.
- @Suppress("DEPRECATION")
- rootFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ @Suppress("DEPRECATION")
+ window.addFlags(View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
+ }
} else { // Privacy Browser is not in full screen browsing mode.
- // Reset the full screen tracker, which could be true if Privacy Browser was in full screen mode before entering settings and full screen browsing was disabled.
- inFullScreenBrowsingMode = false
-
// Show the tab linear layout.
tabsLinearLayout.visibility = View.VISIBLE
// Show the app bar.
appBar.show()
- // Remove the `SYSTEM_UI` flags from the root frame layout. The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30.
- @Suppress("DEPRECATION")
- rootFrameLayout.systemUiVisibility = 0
+ // Remove the fullscreen flags if the API < 30.
+ if (Build.VERSION.SDK_INT < 30) {
+ /* Show the system bars.
+ * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
+ * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
+ * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
+ * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
+ */
+
+ @Suppress("DEPRECATION")
+ window.clearFlags(View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
+ }
}
// Load the bookmarks folder.
}
private fun exitFullScreenVideo() {
- // Re-enable the screen timeout.
- fullScreenVideoFrameLayout.keepScreenOn = false
-
// Unset the full screen video flag.
displayingFullScreenVideo = false
- // Remove all the views from the full screen video frame layout.
- fullScreenVideoFrameLayout.removeAllViews()
+ // Hide the full screen video according to the API and display under cutouts status.
+ if ((Build.VERSION.SDK_INT < 35) && displayUnderCutouts) { // The device is running API < 35 and display under cutouts is enabled.
+ // Re-enable the screen timeout.
+ oldFullScreenVideoFrameLayout.keepScreenOn = false
+
+ // Remove all the views from the full screen video frame layout.
+ oldFullScreenVideoFrameLayout.removeAllViews()
+
+ // Hide the full screen video frame layout.
+ oldFullScreenVideoFrameLayout.visibility = View.GONE
+ } else { // The device is running API >= 35 or display under cutouts is disabled.
+ // Re-enable the screen timeout.
+ fullScreenVideoFrameLayout.keepScreenOn = false
- // Hide the full screen video frame layout.
- fullScreenVideoFrameLayout.visibility = View.GONE
+ // Remove all the views from the full screen video frame layout.
+ fullScreenVideoFrameLayout.removeAllViews()
+
+ // Hide the full screen video frame layout.
+ fullScreenVideoFrameLayout.visibility = View.GONE
+ }
// Enable the sliding drawers.
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
- // Show the coordinator layout.
- coordinatorLayout.visibility = View.VISIBLE
+ // Show the browser view according to the API and display under cutouts status.
+ if ((Build.VERSION.SDK_INT < 35) && displayUnderCutouts) { // The device is running API < 35 and display under cutouts is enabled.
+ // Display the app bar if it is not supposed to be hidden, the `||` ensures that `!hideAppBar` is only evaluated in `inFullScreenBrowsingMode == true`.
+ if (!inFullScreenBrowsingMode || !hideAppBar) {
+ // Show the tab linear layout.
+ tabsLinearLayout.visibility = View.VISIBLE
- // Apply the appropriate full screen mode flags.
- if (fullScreenBrowsingModeEnabled && inFullScreenBrowsingMode) { // Privacy Browser is currently in full screen browsing mode.
- // Handle display under cutouts for API < 35. <https://redmine.stoutner.com/issues/1238>
- if (Build.VERSION.SDK_INT < 35) {
- // Disable fits system windows if display under cutouts is enabled.
- if (displayUnderCutouts)
- rootFrameLayout.fitsSystemWindows = false
+ // Show the app bar.
+ appBar.show()
}
+ // Display the swipe refresh layout (which includes the WebView).
+ swipeRefreshLayout.visibility = View.VISIBLE
+
+ // Enable fits system windows if not in full screen browsing mode.
+ if (!inFullScreenBrowsingMode) {
+ coordinatorLayout.fitsSystemWindows = true
+ bookmarksFrameLayout.fitsSystemWindows = true
+ }
+ } else { // The device is running API >= 35 or display under cutouts is disabled.
+ browserFrameLayout.visibility = View.VISIBLE
+ }
+
+ // Apply the appropriate full screen mode flags.
+ if (inFullScreenBrowsingMode) { // Privacy Browser is currently in full screen browsing mode.
// Hide the app bar if specified.
if (hideAppBar) {
// Hide the tab linear layout.
appBar.hide()
}
- /* Hide the system bars.
- * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
- * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
- * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
- * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
- */
+ if (Build.VERSION.SDK_INT < 30) {
+ /* Hide the system bars.
+ * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
+ * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
+ * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
+ * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
+ */
- // The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30.
- @Suppress("DEPRECATION")
- rootFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- } else { // Switch to normal viewing mode.
- // Handle display under cutouts for API < 35. <https://redmine.stoutner.com/issues/1238>
- if (Build.VERSION.SDK_INT < 35) {
- // Enable fits system windows if display under cutouts is enabled.
- if (displayUnderCutouts)
- rootFrameLayout.fitsSystemWindows = true
+ @Suppress("DEPRECATION")
+ window.addFlags(View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
}
+ } else { // Switch to normal viewing mode.
+ // Show the system bars according to the API.
+ if (Build.VERSION.SDK_INT >= 30) {
+ // Show the system bars.
+ windowInsetsController.show(WindowInsets.Type.systemBars())
+ } else {
+ /* Show the system bars.
+ * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
+ * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
+ * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
+ * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
+ */
- // Remove the `SYSTEM_UI` flags from the root frame layout. The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30.
- @Suppress("DEPRECATION")
- rootFrameLayout.systemUiVisibility = 0
+ @Suppress("DEPRECATION")
+ window.clearFlags(View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
+ }
}
}
// Toggle the full screen browsing mode.
if (inFullScreenBrowsingMode) { // Switch to full screen mode.
- // Handle display under cutouts for API < 35. <https://redmine.stoutner.com/issues/1238>
- if (Build.VERSION.SDK_INT < 35) {
- // Disable fits system windows if display under cutouts is enabled.
- if (displayUnderCutouts)
- rootFrameLayout.fitsSystemWindows = false
- }
-
// Hide the app bar if specified.
if (hideAppBar) { // App bar hiding is enabled.
// Close the find on page bar if it is visible.
}
}
- /* Hide the system bars.
- * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
- * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
- * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
- * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
- */
+ // Hide the system bars.
+ if (Build.VERSION.SDK_INT >= 30) {
+ // Set the system bars to display transiently when swiped.
+ windowInsetsController.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
- // The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30.
- @Suppress("DEPRECATION")
- rootFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- } else { // Switch to normal viewing mode.
- // Handle display under cutouts for API < 35. <https://redmine.stoutner.com/issues/1238>
- if (Build.VERSION.SDK_INT < 35) {
- // Enable fits system windows if display under cutouts is enabled.
- if (displayUnderCutouts)
- rootFrameLayout.fitsSystemWindows = true
+ // Hide the system bars.
+ windowInsetsController.hide(WindowInsets.Type.systemBars())
+ } else {
+ /* Hide the system bars.
+ * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
+ * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
+ * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
+ * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
+ */
+
+ @Suppress("DEPRECATION")
+ window.addFlags(View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
}
+ // Disable fits system windows according to the configuration.
+ if (displayUnderCutouts) { // Display under cutouts.
+ // Disable fits system windows according to the API.
+ if (Build.VERSION.SDK_INT >= 35) { // The device is running API >= 35.
+ // Disable fits system windows.
+ browserFrameLayout.fitsSystemWindows = false
+
+ // Manually update the padding, which isn't done on API >= 35
+ browserFrameLayout.setPadding(0, 0, 0, 0)
+ } else { // The device is running API < 35.
+ // Disable fits system windows.
+ coordinatorLayout.fitsSystemWindows = false
+ bookmarksFrameLayout.fitsSystemWindows = false
+
+ // Remove any padding on the bookmarks frame layout.
+ bookmarksFrameLayout.setPadding(0, 0, 0, 0)
+ }
+ } else if (Build.VERSION.SDK_INT < 35) { // The device is running API < 35 and display under cutouts is disabled.
+ // Disable fits system windows to display under the navigation bar.
+ coordinatorLayout.fitsSystemWindows = false
+ bookmarksFrameLayout.fitsSystemWindows = false
+
+ // Remove any padding on the bookmarks frame layout.
+ bookmarksFrameLayout.setPadding(0, 0, 0, 0)
+ }
+ } else { // Switch to normal viewing mode.
// Show the app bar if it was hidden.
if (hideAppBar) {
// Show the tab linear layout.
}
}
- // Remove the `SYSTEM_UI` flags from the root frame layout. The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30.
- @Suppress("DEPRECATION")
- rootFrameLayout.systemUiVisibility = 0
+ // Enable fits system windows if display under cutouts is enabled.
+ if (displayUnderCutouts) {
+ // Enable fits system windows according to the API.
+ if (Build.VERSION.SDK_INT >= 35) {
+ browserFrameLayout.fitsSystemWindows = true
+ } else {
+ coordinatorLayout.fitsSystemWindows = true
+ bookmarksFrameLayout.fitsSystemWindows = true
+ }
+ } else if (Build.VERSION.SDK_INT < 35) { // The device is running API < 35 and display under cutouts is disabled.
+ // Enable fits system windows.
+ coordinatorLayout.fitsSystemWindows = true
+ bookmarksFrameLayout.fitsSystemWindows = true
+ }
+
+ // Show the system bars according to the API.
+ if (Build.VERSION.SDK_INT >= 30) {
+ // Show the system bars.
+ windowInsetsController.show(WindowInsets.Type.systemBars())
+ } else {
+ /* Show the system bars.
+ * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
+ * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
+ * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
+ * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
+ */
+
+ @Suppress("DEPRECATION")
+ window.clearFlags(View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
+ }
}
// Consume the double-tap.
swipeRefreshLayout.isEnabled = nestedScrollWebView.scrollY == 0
else // Disable swipe to refresh.
swipeRefreshLayout.isEnabled = false
-
- // Reinforce the system UI visibility flags if in full screen browsing mode.
- // This hides the status and navigation bars, which are displayed if other elements are shown, like dialog boxes, the options menu, or the keyboard.
- if (inFullScreenBrowsingMode) {
- /* Hide the system bars.
- * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
- * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
- * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
- * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
- */
-
- // The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30.
- @Suppress("DEPRECATION")
- rootFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- }
}
// Set the web chrome client.
// Enter full screen video.
override fun onShowCustomView(video: View, callback: CustomViewCallback) {
- // Handle display under cutouts for API < 35. <https://redmine.stoutner.com/issues/1238>
- if (Build.VERSION.SDK_INT < 35) {
- // Disable fits system windows if display under cutouts is enabled.
- if (displayUnderCutouts)
- rootFrameLayout.fitsSystemWindows = false
- }
-
// Set the full screen video flag.
displayingFullScreenVideo = true
// Hide the keyboard.
inputMethodManager.hideSoftInputFromWindow(nestedScrollWebView.windowToken, 0)
- // Hide the coordinator layout.
- coordinatorLayout.visibility = View.GONE
+ // Hide the browser view according to the API.
+ if ((Build.VERSION.SDK_INT < 35) && displayUnderCutouts) { // The device is running API < 35 and display under cutouts is enabled.
+ // Hide the tab linear layout.
+ tabsLinearLayout.visibility = View.GONE
- /* Hide the system bars.
- * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
- * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
- * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
- * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
- */
+ // Hide the app bar.
+ appBar.hide()
- // The deprecated command can be switched to `WindowInsetsController` once the minimum API >= 30.
- @Suppress("DEPRECATION")
- rootFrameLayout.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ // Hide the swipe refresh layout (which includes the WebView).
+ swipeRefreshLayout.visibility = View.GONE
+
+ // Disable fits system windows.
+ coordinatorLayout.fitsSystemWindows = false
+ bookmarksFrameLayout.fitsSystemWindows = false
+
+ // Remove any padding from the bookmark frame layout
+ bookmarksFrameLayout.setPadding(0, 0, 0, 0)
+ } else { // The device is running API >= 35 or display under cutouts is disabled.
+ // Hide the browser view.
+ browserFrameLayout.visibility = View.GONE
+ }
+
+ // Hide the system bars according to the API.
+ if (Build.VERSION.SDK_INT >= 30) {
+ // Set the system bars to show transiently when swiped.
+ windowInsetsController.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+
+ // Hide the system bars.
+ windowInsetsController.hide(WindowInsets.Type.systemBars())
+ } else {
+ /* Hide the system bars.
+ * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen.
+ * SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN makes the root frame layout fill the area that is normally reserved for the status bar.
+ * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen.
+ * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically re-hides them after they are shown.
+ */
+
+ @Suppress("DEPRECATION")
+ window.addFlags(View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
+ }
// Disable the sliding drawers.
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
- // Add the video view to the full screen video frame layout.
- fullScreenVideoFrameLayout.addView(video)
+ if ((Build.VERSION.SDK_INT < 35) && displayUnderCutouts) {
+ // Add the video view to the full screen video frame layout.
+ oldFullScreenVideoFrameLayout.addView(video)
- // Show the full screen video frame layout.
- fullScreenVideoFrameLayout.visibility = View.VISIBLE
+ // Show the full screen video frame layout.
+ oldFullScreenVideoFrameLayout.visibility = View.VISIBLE
- // Disable the screen timeout while the video is playing. YouTube does this automatically, but not all other videos do.
- fullScreenVideoFrameLayout.keepScreenOn = true
+ // Disable the screen timeout while the video is playing. YouTube does this automatically, but not all other videos do.
+ oldFullScreenVideoFrameLayout.keepScreenOn = true
+ } else {
+ // Add the video view to the full screen video frame layout.
+ fullScreenVideoFrameLayout.addView(video)
+
+ // Show the full screen video frame layout.
+ fullScreenVideoFrameLayout.visibility = View.VISIBLE
+
+ // Disable the screen timeout while the video is playing. YouTube does this automatically, but not all other videos do.
+ fullScreenVideoFrameLayout.keepScreenOn = true
+ }
}
// Exit full screen video.
// Request an openable file.
fileChooserIntent.addCategory(Intent.CATEGORY_OPENABLE)
- // Set the file type to everything. The file chooser params cannot be used to create the intent because it only selects the first specified file type. See <https://redmine.stoutner.com/issues/1197>.
+ // Set the file type to everything. The file chooser params cannot be used to create the intent because it only selects the first specified file type.
+ // See <https://redmine.stoutner.com/issues/1197>.
fileChooserIntent.type = "*/*"
// Launch the file chooser intent.
-/*
- * Copyright 2016-2022 Soren Stoutner <soren@stoutner.com>.
+/* SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-FileCopyrightText: 2016-2024 Soren Stoutner <soren@stoutner.com>
*
* This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
*
- * Privacy Browser Android is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
*
- * Privacy Browser Android is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
*
- * You should have received a copy of the GNU General Public License
- * along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.stoutner.privacybrowser.activities
import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.Preference
-import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat
import com.stoutner.privacybrowser.R
// Set the preference dependencies.
domStoragePreference.dependency = getString(R.string.javascript_key)
hideAppBarPreference.dependency = getString(R.string.full_screen_browsing_mode_key)
- displayUnderCutoutsPreference.dependency = getString(R.string.full_screen_browsing_mode_key)
// Get strings from the preferences.
val userAgentName = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value))
val fullScreenBrowsingMode = sharedPreferences.getBoolean(getString(R.string.full_screen_browsing_mode_key), false)
val clearEverything = sharedPreferences.getBoolean(getString(R.string.clear_everything_key), true)
- // Remove the display under cutouts preferences if the API is >= 35 as Google broke this functionality. <https://redmine.stoutner.com/issues/1238>
- if (Build.VERSION.SDK_INT >= 35) {
- // Get a handle for the full screen category.
- val fullScreenCategory = findPreference<PreferenceCategory>(getString(R.string.full_screen_category_key))!!
-
- // Remove the display under cutouts preferences.
- fullScreenCategory.removePreference(displayUnderCutoutsPreference)
- }
-
// Only enable Fanboy's social blocking list preference if Fanboy's annoyance list is disabled.
fanboySocialBlockingListPreference.isEnabled = !fanboyAnnoyanceListEnabled
getString(R.string.display_under_cutouts_key) -> {
// Update the icon.
- if (sharedPreferences.getBoolean(getString(R.string.display_under_cutouts_key), true))
+ if (sharedPreferences.getBoolean(getString(R.string.display_under_cutouts_key), false))
displayUnderCutoutsPreference.setIcon(R.drawable.display_under_cutouts_enabled)
else
displayUnderCutoutsPreference.setIcon(R.drawable.display_under_cutouts_disabled)
- // Restart Privacy Browser.
- restartPrivacyBrowser()
+ // Restart Privacy Browser if the API < 35.
+ if (Build.VERSION.SDK_INT < 35)
+ restartPrivacyBrowser()
}
getString(R.string.clear_everything_key) -> {
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2017, 2019-2022, 2024 Soren Stoutner <soren@stoutner.com>.
+ SPDX-License-Identifier: GPL-3.0-or-later
+ SPDX-FileCopyrightText: 2017, 2019-2022, 2024 Soren Stoutner <soren@stoutner.com>
This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
- Privacy Browser Android is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
- Privacy Browser Android is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
- You should have received a copy of the GNU General Public License
- along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <https://www.gnu.org/licenses/>. -->
<!-- `android:layout_width="400dp"` keeps the bookmarks drawer from filling the whole screen on a tablet. -->
<FrameLayout
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2017, 2019-2020, 2022, 2024 Soren Stoutner <soren@stoutner.com>.
+ SPDX-License-Identifier: GPL-3.0-or-later
+ SPDX-FileCopyrightText: 2019-2020, 2022, 2024 Soren Stoutner <soren@stoutner.com>
This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
- Privacy Browser Android is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
- Privacy Browser Android is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
- You should have received a copy of the GNU General Public License
- along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <https://www.gnu.org/licenses/>. -->
<!-- `android:layout_width="400dp"` keeps the bookmarks drawer from filling the whole screen on a tablet. -->
<FrameLayout
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2017-2022, 2024 Soren Stoutner <soren@stoutner.com>.
+ SPDX-License-Identifier: GPL-3.0-or-later
+ SPDX-FileCopyrightText: 2017-2022, 2024 Soren Stoutner <soren@stoutner.com>
This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
- Privacy Browser Android is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
- Privacy Browser Android is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
- You should have received a copy of the GNU General Public License
- along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <https://www.gnu.org/licenses/>. -->
<FrameLayout
android:id="@+id/bookmarks_framelayout"
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent"
android:layout_width="match_parent"
- android:layout_gravity="end">
+ android:layout_gravity="end" >
<LinearLayout
android:layout_height="match_parent"
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2017-2020, 2022, 2024 Soren Stoutner <soren@stoutner.com>.
+ SPDX-License-Identifier: GPL-3.0-or-later
+ SPDX-FileCopyrightText: 2017-2020, 2022, 2024 Soren Stoutner <soren@stoutner.com>
This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
- Privacy Browser Android is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
- Privacy Browser Android is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
- You should have received a copy of the GNU General Public License
- along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <https://www.gnu.org/licenses/>. -->
<FrameLayout
android:id="@+id/bookmarks_framelayout"
You should have received a copy of the GNU General Public License along with
this program. If not, see <https://www.gnu.org/licenses/>. -->
-<!-- `android:fitsSystemWindows="true"` is required for correct layout starting with API >= 35 (Android 15) -->
<FrameLayout
- android:id="@+id/root_framelayout"
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:layout_height="match_parent"
- android:layout_width="match_parent"
- android:fitsSystemWindows="true" >
+ android:layout_width="match_parent" >
- <androidx.drawerlayout.widget.DrawerLayout
- android:id="@+id/drawerlayout"
+ <FrameLayout
+ android:id="@+id/browser_framelayout"
android:layout_height="match_parent"
android:layout_width="match_parent" >
- <!-- Setting the CoordinatorLayout to be `focusableInTouchMode` prevents the URL text box from stealing focus on launch and opening the keyboard. -->
- <androidx.coordinatorlayout.widget.CoordinatorLayout
- android:id="@+id/coordinatorlayout"
+ <androidx.drawerlayout.widget.DrawerLayout
+ android:id="@+id/drawerlayout"
android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:focusable="true"
- android:focusableInTouchMode="true" >
-
- <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
- android:id="@+id/swiperefreshlayout"
- android:layout_height="match_parent"
- android:layout_width="match_parent" >
+ android:layout_width="match_parent" >
+
+ <!-- Setting the CoordinatorLayout to be `focusableInTouchMode` prevents the URL text box from stealing focus on launch and opening the keyboard. -->
+ <androidx.coordinatorlayout.widget.CoordinatorLayout
+ android:id="@+id/coordinatorlayout"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:focusable="true"
+ android:focusableInTouchMode="true" >
+
+ <FrameLayout
+ android:id="@+id/old_full_screen_video_framelayout"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:visibility="gone"
+ android:fitsSystemWindows="false" />
- <androidx.viewpager2.widget.ViewPager2
- android:id="@+id/webview_viewpager2"
+ <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+ android:id="@+id/swiperefreshlayout"
android:layout_height="match_parent"
- android:layout_width="match_parent" />
- </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
-
- <!-- The app bar theme must be specified here because the activity uses a `NoActionBar` theme. The background is set programmatically based on the proxy status.
- `app:layout_dodgeInsetEdges="bottom"` as a child of a coordinator layout moves the view above snackbars.-->
- <com.google.android.material.appbar.AppBarLayout
- android:id="@+id/appbar_layout"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:theme="@style/PrivacyBrowserAppBar"
- android:layout_gravity="bottom"
- app:layout_dodgeInsetEdges="bottom" >
-
- <!-- The tab linear layout. It sets the background to the right of the add tab button. -->
- <LinearLayout
- android:id="@+id/tabs_linearlayout"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:orientation="horizontal" >
+ android:layout_width="match_parent" >
- <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
- <ImageView
+ <androidx.viewpager2.widget.ViewPager2
+ android:id="@+id/webview_viewpager2"
android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:layout_gravity="center_vertical"
- android:paddingStart="10dp"
- android:paddingEnd="10dp"
- android:src="@drawable/close"
- android:background="?attr/selectableItemBackground"
- android:onClick="closeTab"
- android:contentDescription="@string/close_tab" />
-
- <com.google.android.material.tabs.TabLayout
- android:id="@+id/tablayout"
- android:layout_height="wrap_content"
- android:layout_width="0dp"
- android:layout_weight="1"
- app:tabMode="scrollable" />
+ android:layout_width="match_parent" />
+ </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
- <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
- <ImageView
- android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:layout_gravity="center_vertical"
- android:paddingStart="10dp"
- android:paddingEnd="10dp"
- android:src="@drawable/add"
- android:background="?attr/selectableItemBackground"
- android:onClick="addTab"
- android:contentDescription="@string/add_tab" />
- </LinearLayout>
-
- <!-- The find on page linear layout. It is initially `visibility="gone"` and is only displayed when requested. -->
- <LinearLayout
- android:id="@+id/find_on_page_linearlayout"
+ <!-- The app bar theme must be specified here because the activity uses a `NoActionBar` theme. The background is set programmatically based on the proxy status.
+ `app:layout_dodgeInsetEdges="bottom"` as a child of a coordinator layout moves the view above snackbars.-->
+ <com.google.android.material.appbar.AppBarLayout
+ android:id="@+id/appbar_layout"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:orientation="horizontal"
- android:visibility="gone" >
+ android:theme="@style/PrivacyBrowserAppBar"
+ android:layout_gravity="bottom"
+ app:layout_dodgeInsetEdges="bottom" >
- <!-- `android:imeOptions="actionDone"` sets the keyboard to have a `check mark` key instead of a `new line` key. -->
- <EditText
- android:id="@+id/find_on_page_edittext"
- android:layout_height="wrap_content"
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_marginStart="8dp"
- android:layout_marginEnd="4dp"
- android:hint="@string/find_on_page"
- android:lines="1"
- android:imeOptions="actionDone"
- android:inputType="text"
- tools:ignore="Autofill" />
-
- <TextView
- android:id="@+id/find_on_page_count_textview"
+ <!-- The tab linear layout. It sets the background to the right of the add tab button. -->
+ <LinearLayout
+ android:id="@+id/tabs_linearlayout"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="4dp"
- android:text="@string/zero_of_zero" />
-
- <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
- <ImageView
- android:id="@+id/find_previous"
- android:layout_height="35dp"
- android:layout_width="35dp"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="4dp"
- android:layout_gravity="center_vertical"
- android:src="@drawable/previous"
- android:background="?attr/selectableItemBackground"
- android:contentDescription="@string/previous"
- android:onClick="findPreviousOnPage"
- app:tint="@color/blue_icon" />
-
- <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
- <ImageView
- android:id="@+id/find_next"
- android:layout_width="35dp"
- android:layout_height="35dp"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="4dp"
- android:layout_gravity="center_vertical"
- android:src="@drawable/next"
- android:background="?attr/selectableItemBackground"
- android:contentDescription="@string/next"
- android:onClick="findNextOnPage"
- app:tint="@color/blue_icon" />
-
- <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
- <ImageView
- android:id="@+id/close_find"
- android:layout_width="35dp"
- android:layout_height="35dp"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="8dp"
- android:layout_gravity="center_vertical"
- android:src="@drawable/close"
- android:background="?attr/selectableItemBackground"
- android:contentDescription="@string/close"
- android:onClick="closeFindOnPage"
- app:tint="@color/blue_icon" />
- </LinearLayout>
-
- <!-- The toolbar. -->
- <androidx.appcompat.widget.Toolbar
- android:id="@+id/toolbar"
- android:layout_height="wrap_content"
- android:layout_width="match_parent" />
- </com.google.android.material.appbar.AppBarLayout>
- </androidx.coordinatorlayout.widget.CoordinatorLayout>
-
- <!-- The navigation drawer. -->
- <com.google.android.material.navigation.NavigationView
- android:id="@+id/navigationview"
+ android:orientation="horizontal" >
+
+ <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+ <ImageView
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingStart="10dp"
+ android:paddingEnd="10dp"
+ android:src="@drawable/close"
+ android:background="?attr/selectableItemBackground"
+ android:onClick="closeTab"
+ android:contentDescription="@string/close_tab" />
+
+ <com.google.android.material.tabs.TabLayout
+ android:id="@+id/tablayout"
+ android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ app:tabMode="scrollable" />
+
+ <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+ <ImageView
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingStart="10dp"
+ android:paddingEnd="10dp"
+ android:src="@drawable/add"
+ android:background="?attr/selectableItemBackground"
+ android:onClick="addTab"
+ android:contentDescription="@string/add_tab" />
+ </LinearLayout>
+
+ <!-- The find on page linear layout. It is initially `visibility="gone"` and is only displayed when requested. -->
+ <LinearLayout
+ android:id="@+id/find_on_page_linearlayout"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ android:visibility="gone" >
+
+ <!-- `android:imeOptions="actionDone"` sets the keyboard to have a `check mark` key instead of a `new line` key. -->
+ <EditText
+ android:id="@+id/find_on_page_edittext"
+ android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="4dp"
+ android:hint="@string/find_on_page"
+ android:lines="1"
+ android:imeOptions="actionDone"
+ android:inputType="text"
+ tools:ignore="Autofill" />
+
+ <TextView
+ android:id="@+id/find_on_page_count_textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="4dp"
+ android:text="@string/zero_of_zero" />
+
+ <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+ <ImageView
+ android:id="@+id/find_previous"
+ android:layout_height="35dp"
+ android:layout_width="35dp"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="4dp"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/previous"
+ android:background="?attr/selectableItemBackground"
+ android:contentDescription="@string/previous"
+ android:onClick="findPreviousOnPage"
+ app:tint="@color/blue_icon" />
+
+ <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+ <ImageView
+ android:id="@+id/find_next"
+ android:layout_width="35dp"
+ android:layout_height="35dp"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="4dp"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/next"
+ android:background="?attr/selectableItemBackground"
+ android:contentDescription="@string/next"
+ android:onClick="findNextOnPage"
+ app:tint="@color/blue_icon" />
+
+ <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+ <ImageView
+ android:id="@+id/close_find"
+ android:layout_width="35dp"
+ android:layout_height="35dp"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="8dp"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/close"
+ android:background="?attr/selectableItemBackground"
+ android:contentDescription="@string/close"
+ android:onClick="closeFindOnPage"
+ app:tint="@color/blue_icon" />
+ </LinearLayout>
+
+ <!-- The toolbar. -->
+ <androidx.appcompat.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent" />
+ </com.google.android.material.appbar.AppBarLayout>
+ </androidx.coordinatorlayout.widget.CoordinatorLayout>
+
+ <!-- The navigation drawer.
+ `topInsetScrimEnabled="false"` disables the scrim that draws under display cutouts (even thought the white space is maintained).
+ bottomInsetScrimEnabled="false" disables the scrim that draws under the navigation bar. It is only needed on API < 35. -->
+ <com.google.android.material.navigation.NavigationView
+ android:id="@+id/navigationview"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_gravity="start"
+ app:menu="@menu/webview_navigation_menu_bottom_appbar"
+ app:itemIconTint="@color/blue_icon"
+ app:topInsetScrimEnabled="false"
+ app:bottomInsetScrimEnabled="false" />
+
+ <!-- Include the bookmarks drawer, which varies based on screen width. -->
+ <include layout="@layout/bookmarks_drawer_bottom_appbar" />
+ </androidx.drawerlayout.widget.DrawerLayout>
+
+ <!-- The loading filter lists relative layout displays when the app first starts. It is hidden once the filter lists are populated. -->
+ <RelativeLayout
+ android:id="@+id/loading_filterlists_relativelayout"
android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:layout_gravity="start"
- app:menu="@menu/webview_navigation_menu_bottom_appbar"
- app:itemIconTint="@color/blue_icon" />
-
- <!-- Include the bookmarks drawer, which varies based on screen width. -->
- <include layout="@layout/bookmarks_drawer_bottom_appbar" />
- </androidx.drawerlayout.widget.DrawerLayout>
+ android:layout_width="match_parent" >
+
+ <ImageView
+ android:id="@+id/privacy_browser_logo"
+ android:layout_height="256dp"
+ android:layout_width="256dp"
+ android:layout_centerInParent="true"
+ android:src="@drawable/privacy_browser_foreground"
+ tools:ignore="contentDescription" />
+
+ <TextView
+ android:id="@+id/loading_filterlist_textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_below="@id/privacy_browser_logo"
+ android:layout_centerHorizontal="true"
+ android:layout_margin="10dp"
+ android:textSize="16sp"
+ android:textAlignment="center"
+ android:textColor="?android:attr/textColorPrimary" />
+ </RelativeLayout>
+ </FrameLayout>
<!-- The full screen video frame layout is used to display full screen videos. It is initially `android:visibility="gone"` to hide it from view. -->
<FrameLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:visibility="gone" />
-
- <!-- The loading filter lists relative layout displays when the app first starts. It is hidden once the filter lists are populated. -->
- <RelativeLayout
- android:id="@+id/loading_filterlists_relativelayout"
- android:layout_height="match_parent"
- android:layout_width="match_parent" >
-
- <ImageView
- android:id="@+id/privacy_browser_logo"
- android:layout_height="256dp"
- android:layout_width="256dp"
- android:layout_centerInParent="true"
- android:src="@drawable/privacy_browser_foreground"
- tools:ignore="contentDescription" />
-
- <TextView
- android:id="@+id/loading_filterlist_textview"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_below="@id/privacy_browser_logo"
- android:layout_centerHorizontal="true"
- android:layout_margin="10dp"
- android:textSize="16sp"
- android:textAlignment="center"
- android:textColor="?android:attr/textColorPrimary" />
- </RelativeLayout>
</FrameLayout>
You should have received a copy of the GNU General Public License along with
this program. If not, see <https://www.gnu.org/licenses/>. -->
-<!-- `android:fitsSystemWindows="true"` is required for correct layout starting with API >= 35 (Android 15) -->
<FrameLayout
- android:id="@+id/root_framelayout"
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:layout_height="match_parent"
- android:layout_width="match_parent"
- android:fitsSystemWindows="true" >
+ android:layout_width="match_parent" >
- <androidx.drawerlayout.widget.DrawerLayout
- android:id="@+id/drawerlayout"
+ <FrameLayout
+ android:id="@+id/browser_framelayout"
android:layout_height="match_parent"
android:layout_width="match_parent" >
- <!-- Setting the CoordinatorLayout to be `focusableInTouchMode` prevents the URL text box from stealing focus on launch and opening the keyboard. -->
- <androidx.coordinatorlayout.widget.CoordinatorLayout
- android:id="@+id/coordinatorlayout"
+ <androidx.drawerlayout.widget.DrawerLayout
+ android:id="@+id/drawerlayout"
android:layout_height="match_parent"
- android:layout_width="match_parent"
- android:focusable="true"
- android:focusableInTouchMode="true" >
+ android:layout_width="match_parent" >
- <!-- The app bar theme must be specified here because the activity uses a `NoActionBar` theme. The background is set programmatically based on the proxy status. -->
- <com.google.android.material.appbar.AppBarLayout
- android:id="@+id/appbar_layout"
- android:layout_height="wrap_content"
+ <!-- Setting the CoordinatorLayout to be `focusableInTouchMode` prevents the URL text box from stealing focus on launch and opening the keyboard. -->
+ <androidx.coordinatorlayout.widget.CoordinatorLayout
+ android:id="@+id/coordinatorlayout"
+ android:layout_height="match_parent"
android:layout_width="match_parent"
- android:theme="@style/PrivacyBrowserAppBar" >
+ android:focusable="true"
+ android:focusableInTouchMode="true" >
- <!-- The toolbar. -->
- <androidx.appcompat.widget.Toolbar
- android:id="@+id/toolbar"
+ <!-- The app bar theme must be specified here because the activity uses a `NoActionBar` theme. The background is set programmatically based on the proxy status. -->
+ <com.google.android.material.appbar.AppBarLayout
+ android:id="@+id/appbar_layout"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- app:layout_scrollFlags="scroll|enterAlways|snap" />
+ android:theme="@style/PrivacyBrowserAppBar" >
- <!-- The find on page linear layout. It is initially `visibility="gone"` and is only displayed when requested. -->
- <LinearLayout
- android:id="@+id/find_on_page_linearlayout"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- android:orientation="horizontal"
- android:visibility="gone"
- app:layout_scrollFlags="scroll|enterAlways|snap" >
+ <!-- The toolbar. -->
+ <androidx.appcompat.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ app:layout_scrollFlags="scroll|enterAlways|snap" />
- <!-- `android:imeOptions="actionDone"` sets the keyboard to have a `check mark` key instead of a `new line` key. -->
- <EditText
- android:id="@+id/find_on_page_edittext"
+ <!-- The find on page linear layout. It is initially `visibility="gone"` and is only displayed when requested. -->
+ <LinearLayout
+ android:id="@+id/find_on_page_linearlayout"
android:layout_height="wrap_content"
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_marginStart="8dp"
- android:layout_marginEnd="4dp"
- android:hint="@string/find_on_page"
- android:lines="1"
- android:imeOptions="actionDone"
- android:inputType="text"
- tools:ignore="Autofill" />
-
- <TextView
- android:id="@+id/find_on_page_count_textview"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ android:visibility="gone"
+ app:layout_scrollFlags="scroll|enterAlways|snap" >
+
+ <!-- `android:imeOptions="actionDone"` sets the keyboard to have a `check mark` key instead of a `new line` key. -->
+ <EditText
+ android:id="@+id/find_on_page_edittext"
+ android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_marginStart="8dp"
+ android:layout_marginEnd="4dp"
+ android:hint="@string/find_on_page"
+ android:lines="1"
+ android:imeOptions="actionDone"
+ android:inputType="text"
+ tools:ignore="Autofill" />
+
+ <TextView
+ android:id="@+id/find_on_page_count_textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="4dp"
+ android:text="@string/zero_of_zero" />
+
+ <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+ <ImageView
+ android:id="@+id/find_previous"
+ android:layout_height="35dp"
+ android:layout_width="35dp"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="4dp"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/previous"
+ android:background="?attr/selectableItemBackground"
+ android:contentDescription="@string/previous"
+ android:onClick="findPreviousOnPage"
+ app:tint="@color/blue_icon" />
+
+ <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+ <ImageView
+ android:id="@+id/find_next"
+ android:layout_height="35dp"
+ android:layout_width="35dp"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="4dp"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/next"
+ android:background="?attr/selectableItemBackground"
+ android:contentDescription="@string/next"
+ android:onClick="findNextOnPage"
+ app:tint="@color/blue_icon" />
+
+ <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+ <ImageView
+ android:id="@+id/close_find"
+ android:layout_height="35dp"
+ android:layout_width="35dp"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="8dp"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/close"
+ android:background="?attr/selectableItemBackground"
+ android:contentDescription="@string/close"
+ android:onClick="closeFindOnPage"
+ app:tint="@color/blue_icon" />
+ </LinearLayout>
+
+ <!-- The tab linear layout. It sets the background to the right of the add tab button. -->
+ <LinearLayout
+ android:id="@+id/tabs_linearlayout"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="4dp"
- android:text="@string/zero_of_zero" />
-
- <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
- <ImageView
- android:id="@+id/find_previous"
- android:layout_height="35dp"
- android:layout_width="35dp"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="4dp"
- android:layout_gravity="center_vertical"
- android:src="@drawable/previous"
- android:background="?attr/selectableItemBackground"
- android:contentDescription="@string/previous"
- android:onClick="findPreviousOnPage"
- app:tint="@color/blue_icon" />
-
- <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
- <ImageView
- android:id="@+id/find_next"
- android:layout_height="35dp"
- android:layout_width="35dp"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="4dp"
- android:layout_gravity="center_vertical"
- android:src="@drawable/next"
- android:background="?attr/selectableItemBackground"
- android:contentDescription="@string/next"
- android:onClick="findNextOnPage"
- app:tint="@color/blue_icon" />
-
- <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
- <ImageView
- android:id="@+id/close_find"
- android:layout_height="35dp"
- android:layout_width="35dp"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="8dp"
- android:layout_gravity="center_vertical"
- android:src="@drawable/close"
- android:background="?attr/selectableItemBackground"
- android:contentDescription="@string/close"
- android:onClick="closeFindOnPage"
- app:tint="@color/blue_icon" />
- </LinearLayout>
-
- <!-- The tab linear layout. It sets the background to the right of the add tab button. -->
- <LinearLayout
- android:id="@+id/tabs_linearlayout"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:orientation="horizontal"
- app:layout_scrollFlags="scroll|enterAlways|snap" >
+ android:orientation="horizontal"
+ app:layout_scrollFlags="scroll|enterAlways|snap" >
+
+ <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+ <ImageView
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingStart="10dp"
+ android:paddingEnd="10dp"
+ android:src="@drawable/close"
+ android:background="?attr/selectableItemBackground"
+ android:onClick="closeTab"
+ android:contentDescription="@string/close_tab" />
+
+ <com.google.android.material.tabs.TabLayout
+ android:id="@+id/tablayout"
+ android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ app:tabIndicatorGravity="top"
+ app:tabMode="scrollable" />
+
+ <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+ <ImageView
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingStart="10dp"
+ android:paddingEnd="10dp"
+ android:src="@drawable/add"
+ android:background="?attr/selectableItemBackground"
+ android:onClick="addTab"
+ android:contentDescription="@string/add_tab" />
+ </LinearLayout>
+ </com.google.android.material.appbar.AppBarLayout>
+
+ <FrameLayout
+ android:id="@+id/old_full_screen_video_framelayout"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:visibility="gone"
+ android:fitsSystemWindows="false" />
- <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
- <ImageView
- android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:layout_gravity="center_vertical"
- android:paddingStart="10dp"
- android:paddingEnd="10dp"
- android:src="@drawable/close"
- android:background="?attr/selectableItemBackground"
- android:onClick="closeTab"
- android:contentDescription="@string/close_tab" />
-
- <com.google.android.material.tabs.TabLayout
- android:id="@+id/tablayout"
- android:layout_height="wrap_content"
- android:layout_width="0dp"
- android:layout_weight="1"
- app:tabIndicatorGravity="top"
- app:tabMode="scrollable" />
-
- <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
- <ImageView
- android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:layout_gravity="center_vertical"
- android:paddingStart="10dp"
- android:paddingEnd="10dp"
- android:src="@drawable/add"
- android:background="?attr/selectableItemBackground"
- android:onClick="addTab"
- android:contentDescription="@string/add_tab" />
- </LinearLayout>
- </com.google.android.material.appbar.AppBarLayout>
-
- <!-- `app:layout_behavior="@string/appbar_scrolling_view_behavior"` must be set on the sibling of AppBarLayout. -->
- <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
- android:id="@+id/swiperefreshlayout"
+ <!-- `app:layout_behavior="@string/appbar_scrolling_view_behavior"` must be set on the sibling of AppBarLayout. -->
+ <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+ android:id="@+id/swiperefreshlayout"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior" >
+
+ <androidx.viewpager2.widget.ViewPager2
+ android:id="@+id/webview_viewpager2"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent" />
+ </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
+ </androidx.coordinatorlayout.widget.CoordinatorLayout>
+
+ <!-- The navigation drawer.
+ `topInsetScrimEnabled="false"` disables the scrim that draws under display cutouts (even thought the white space is maintained).
+ bottomInsetScrimEnabled="false" disables the scrim that draws under the navigation bar. It is only needed on API < 35. -->
+ <com.google.android.material.navigation.NavigationView
+ android:id="@+id/navigationview"
android:layout_height="match_parent"
- android:layout_width="match_parent"
- app:layout_behavior="@string/appbar_scrolling_view_behavior" >
-
- <androidx.viewpager2.widget.ViewPager2
- android:id="@+id/webview_viewpager2"
- android:layout_height="match_parent"
- android:layout_width="match_parent" />
- </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
- </androidx.coordinatorlayout.widget.CoordinatorLayout>
-
- <!-- The navigation drawer. -->
- <com.google.android.material.navigation.NavigationView
- android:id="@+id/navigationview"
+ android:layout_width="wrap_content"
+ android:layout_gravity="start"
+ app:menu="@menu/webview_navigation_menu_top_appbar"
+ app:itemIconTint="@color/blue_icon"
+ app:topInsetScrimEnabled="false"
+ app:bottomInsetScrimEnabled="false" />
+
+ <!-- Include the bookmarks drawer, which varies based on screen width. -->
+ <include layout="@layout/bookmarks_drawer_top_appbar" />
+ </androidx.drawerlayout.widget.DrawerLayout>
+
+ <!-- The loading filter lists relative layout displays when the app first starts. It is hidden once the filter lists are populated. -->
+ <RelativeLayout
+ android:id="@+id/loading_filterlists_relativelayout"
android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:layout_gravity="start"
- app:menu="@menu/webview_navigation_menu_top_appbar"
- app:itemIconTint="@color/blue_icon" />
-
- <!-- Include the bookmarks drawer, which varies based on screen width. -->
- <include layout="@layout/bookmarks_drawer_top_appbar" />
- </androidx.drawerlayout.widget.DrawerLayout>
+ android:layout_width="match_parent" >
+
+ <ImageView
+ android:id="@+id/privacy_browser_logo"
+ android:layout_height="256dp"
+ android:layout_width="256dp"
+ android:layout_centerInParent="true"
+ android:src="@drawable/privacy_browser_foreground"
+ tools:ignore="contentDescription" />
+
+ <TextView
+ android:id="@+id/loading_filterlist_textview"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_below="@id/privacy_browser_logo"
+ android:layout_centerHorizontal="true"
+ android:layout_margin="10dp"
+ android:textSize="16sp"
+ android:textAlignment="center"
+ android:textColor="?android:attr/textColorPrimary" />
+ </RelativeLayout>
+ </FrameLayout>
<!-- The full screen video frame layout is used to display full screen videos. It is initially `android:visibility="gone"` to hide it from view. -->
<FrameLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:visibility="gone" />
-
- <!-- The loading filter lists relative layout displays when the app first starts. It is hidden once the filter lists are populated. -->
- <RelativeLayout
- android:id="@+id/loading_filterlists_relativelayout"
- android:layout_height="match_parent"
- android:layout_width="match_parent" >
-
- <ImageView
- android:id="@+id/privacy_browser_logo"
- android:layout_height="256dp"
- android:layout_width="256dp"
- android:layout_centerInParent="true"
- android:src="@drawable/privacy_browser_foreground"
- tools:ignore="contentDescription" />
-
- <TextView
- android:id="@+id/loading_filterlist_textview"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_below="@id/privacy_browser_logo"
- android:layout_centerHorizontal="true"
- android:layout_margin="10dp"
- android:textSize="16sp"
- android:textAlignment="center"
- android:textColor="?android:attr/textColorPrimary" />
- </RelativeLayout>
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2016-2024 Soren Stoutner <soren@stoutner.com>.
+ SPDX-License-Identifier: GPL-3.0-or-later
+ SPDX-FileCopyrightText: 2016-2024 Soren Stoutner <soren@stoutner.com>
Translation 2019-2024 Bernhard G. Keller. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
-
Translation 2018 Stefan Erhardt. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
-
Translation 2016 Aaron Gerlach <aaron@gerlach.com>. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
- Privacy Browser Android is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
- Privacy Browser Android is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
- You should have received a copy of the GNU General Public License
- along with Privacy Browser Android. If not, see <https://www.gnu.org/licenses/>. -->
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <https://www.gnu.org/licenses/>. -->
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Activities. -->
<string name="hide_app_bar">App-Leiste verstecken</string>
<string name="hide_app_bar_summary" tools:ignore="Typos">Versteckt die App-Leiste, die die URL enthält.</string>
<string name="display_under_cutouts">Unter Aussparungen anzeigen</string>
- <string name="display_under_cutouts_summary">Zeigt die Internetseite unterhalb von Ausschnitten wie etwa Kamera-Einbuchtungen.
- Ist diese Option aktiv, wrd Privacy Browser auch unterhalb der Tastatur dargestellt. Das Ändern dieser Einstellung startet Privacy Browser neu.</string>
<string name="clear_everything">Alles löschen</string>
<string name="clear_everything_summary">Löscht Cookies, DOM-Storage, das Logcat Systemlogbuch und den WebView-Cache, sowie die gesamten “app_webview”- und “cache”-Ordner.</string>
<string name="clear_cookies_preference">Cookies löschen</string>
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2016-2024 Soren Stoutner <soren@stoutner.com>.
+ SPDX-License-Identifier: GPL-3.0-or-later
+ SPDX-FileCopyrightText: 2016-2024 Soren Stoutner <soren@stoutner.com>
Translation 2017-2024 Jose A. León. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
- Privacy Browser Android is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
- Privacy Browser Android is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
- You should have received a copy of the GNU General Public License
- along with Privacy Browser Android. If not, see <https://www.gnu.org/licenses/>. -->
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <https://www.gnu.org/licenses/>. -->
<resources>
<!-- Activities. -->
<string name="hide_app_bar">Ocultar la barra de aplicaciones</string>
<string name="hide_app_bar_summary">Ocultar la barra de aplicaciones que contiene la URL.</string>
<string name="display_under_cutouts">Mostrar bajo los recortes</string>
- <string name="display_under_cutouts_summary">Mostrar el sitio web bajo los recortes, como las muescas de la cámara. Cuando está opción está activada, Navegador Privado también se dibujará bajo el teclado.
- Al cambiar esta configuración se reiniciará Navegador Privado.</string>
<string name="clear_everything">Borrar todo</string>
<string name="clear_everything_summary">Borra cookies, almacenamiento DOM, el logcat y la caché de WebView. A continuación borra manualmente los directorios “app_webview” y “cache”.</string>
<string name="clear_cookies_preference">Borrar cookies</string>
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2015-2024 Soren Stoutner <soren@stoutner.com>.
+ SPDX-License-Identifier: GPL-3.0-or-later
+ SPDX-FileCopyrightText: 2015-2024 Soren Stoutner <soren@stoutner.com>
Translation 2019-2024 Kévin L. <kevinliste@framalistes.org>. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
- Privacy Browser Android is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
- Privacy Browser Android is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
- You should have received a copy of the GNU General Public License
- along with Privacy Browser Android. If not, see <https://www.gnu.org/licenses/>. -->
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <https://www.gnu.org/licenses/>. -->
<!-- `tools:ignore="MissingTranslation"` allows release APKs to be built if translation strings are missing. The missing strings will fall back to English. -->
<resources>
<string name="hide_app_bar">Masquer la barre d\'application</string>
<string name="hide_app_bar_summary">Masquer la barre d\'applications contenant l\'URL.</string>
<string name="display_under_cutouts">Afficher sous les éléments découpés</string>
- <string name="display_under_cutouts_summary">Affiche le site web sous les éléments découpés, tels que les encoches d\'appareil photo.
- Lorsque ce paramètre est activé, Privacy Browser sera également affiché sous le clavier. La modification de ce paramètre entraînera le redémarrage de Privacy Browser.</string>
<string name="clear_everything">Tout effacer</string>
<string name="clear_everything_summary">Efface les cookies, le stockage DOM, le logcat et le cache de WebView. Supprime ensuite manuellement les répertoires entiers «app_webview» et «cache».</string>
<string name="clear_cookies_preference">Effacer les cookies</string>
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2017-2024 Soren Stoutner <soren@stoutner.com>.
+ SPDX-License-Identifier: GPL-3.0-or-later
+ SPDX-FileCopyrightText: 2017-2024 Soren Stoutner <soren@stoutner.com>
Translation 2017-2024 Francesco Buratti. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
- Privacy Browser Android is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
- Privacy Browser Android is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
- You should have received a copy of the GNU General Public License
- along with Privacy Browser Android. If not, see <https://www.gnu.org/licenses/>. -->
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <https://www.gnu.org/licenses/>. -->
<resources>
<!-- Activities. -->
<string name="hide_app_bar">Nascondi la barra dell\'applicazione</string>
<string name="hide_app_bar_summary">Nasconde la barra che contiene l\'URL.</string>
<string name="display_under_cutouts">Visualizza sotto i ritagli dello schermo</string>
- <string name="display_under_cutouts_summary">Visualizza il sito web sotto i ritagli dello schermo come quello della fotocamera.
- Quando questa opzione è abilitata, Privacy Browser sarà anche visualizzato sotto alla tastiera. La modifica di questa impostazione provoca il riavvio di Privacy Browser.</string>
<string name="clear_everything">Elimina tutto</string>
<string name="clear_everything_summary">Cancella i cookies, il DOM storage, il logcat e la cache di WebView. Cancella completamente le cartelle “app_webview” e “cache”.</string>
<string name="clear_cookies_preference">Elimina i cookie</string>
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2015-2024 Soren Stoutner <soren@stoutner.com>.
+ SPDX-License-Identifier: GPL-3.0-or-later
+ SPDX-FileCopyrightText: 2015-2024 Soren Stoutner <soren@stoutner.com>
Translation 2020-2022 Thiago Nazareno Conceição Silva de Jesus <mochileiro2006-trilhas@yahoo.com.br>. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
- Privacy Browser Android is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
- Privacy Browser Android is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
- You should have received a copy of the GNU General Public License
- along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <https://www.gnu.org/licenses/>. -->
<resources>
<!-- Activities. -->
<string name="add_tab">Adicionar aba</string>
<string name="close_tab">Fechar aba</string>
<string name="new_tab">Nova aba</string>
- <string name="loading">Carregando...</string>
+ <string name="loading">Carregando…</string>
<string name="error">Erro:\u0020 %1$s</string>
<string name="apply">Aplicar</string>
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2015-2024 Soren Stoutner <soren@stoutner.com>.
+ SPDX-License-Identifier: GPL-3.0-or-later
+ SPDX-FileCopyrightText: 2015-2024 Soren Stoutner <soren@stoutner.com>
This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
- Privacy Browser Android is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
- Privacy Browser Android is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
- You should have received a copy of the GNU General Public License
- along with Privacy Browser Android. If not, see <https://www.gnu.org/licenses/>. -->
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <https://www.gnu.org/licenses/>. -->
<resources>
<!-- Activities. -->
<string name="hide_app_bar">Скрыть панель приложения</string>
<string name="hide_app_bar_summary">Скрывает панель приложения, которая содержит URL.</string>
<string name="display_under_cutouts">Отображение под вырезом</string>
- <string name="display_under_cutouts_summary">Отрисовывать сайт под вырезами, например, под камерой. Если эта опция включена, Privacy Browser также будет отображаться под клавиатурой.
- Изменение этой настройки приведет к перезапуску Privacy Browser.</string>
<string name="clear_everything">Очистить все</string>
<string name="clear_everything_summary">Очищает cookie, DOM-хранилище, logcat и кэш WebView. После этого вручную удаляет каталоги "app_webview" и "cache".</string>
<string name="clear_cookies_preference">Очистить cookie</string>
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2015-2024 Soren Stoutner <soren@stoutner.com>.
+ SPDX-License-Identifier: GPL-3.0-or-later
+ SPDX-FileCopyrightText: 2015-2024 Soren Stoutner <soren@stoutner.com>
This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
- Privacy Browser Android is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
- Privacy Browser Android is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
- You should have received a copy of the GNU General Public License
- along with Privacy Browser Android. If not, see <https://www.gnu.org/licenses/>. -->
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <https://www.gnu.org/licenses/>. -->
<resources>
<!-- Activities. -->
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright 2015-2024 Soren Stoutner <soren@stoutner.com>.
+ SPDX-License-Identifier: GPL-3.0-or-later
+ SPDX-FileCopyrightText: 2015-2024 Soren Stoutner <soren@stoutner.com>
Translation 2023 Xin. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
- This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
- Privacy Browser Android is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
+ This program is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
- Privacy Browser Android is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
- You should have received a copy of the GNU General Public License
- along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>. -->
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <https://www.gnu.org/licenses/>. -->
<!-- `tools:ignore="MissingTranslation"` allows release APKs to be built if translation strings are missing. The missing strings will fall back to English. -->
<resources
<string name="hide_app_bar_summary">Hide the app bar that contains the URL.</string>
<string name="display_under_cutouts">Display under cutouts</string>
<string name="display_under_cutouts_summary">Draw the website under cutouts, like camera notches. When this is enabled, Privacy Browser will also be drawn under the keyboard.
- Changing this setting will restart Privacy Browser.</string>
+ Changing this setting will restart Privacy Browser on Android < 15.</string>
<string name="clear_everything">Clear everything</string>
<string name="clear_everything_summary">Clears cookies, DOM storage, the logcat, and WebView’s cache. Then manually deletes the entire “app_webview” and “cache” directories.</string>
<string name="clear_cookies_preference">Clear cookies</string>