X-Git-Url: https://gitweb.stoutner.com/?a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fcom%2Fstoutner%2Fprivacybrowser%2Fviews%2FNestedScrollWebView.kt;h=aa2ea0984035fe561888abcce7f505b635d36f16;hb=dc36dea65a4eb37496fb1ecbbd9f8e1906f50216;hp=cd00f067cd6a68273afc113eeac2234d9033042d;hpb=1d656c562831f535aa33903d44198dd890393f4f;p=PrivacyBrowserAndroid.git diff --git a/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt b/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt index cd00f067..aa2ea098 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt @@ -1,24 +1,25 @@ /* - * Copyright © 2019-2021 Soren Stoutner . + * Copyright 2019-2023 Soren Stoutner . * - * This file is part of Privacy Browser . + * This file is part of Privacy Browser Android . * - * Privacy Browser is free software: you can redistribute it and/or modify + * 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. * - * Privacy Browser is distributed in the hope that it will be useful, + * 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. * * You should have received a copy of the GNU General Public License - * along with Privacy Browser. If not, see . + * along with Privacy Browser Android. If not, see . */ package com.stoutner.privacybrowser.views +import android.animation.ObjectAnimator import android.annotation.SuppressLint import android.content.Context import android.graphics.Bitmap @@ -26,25 +27,34 @@ import android.graphics.drawable.BitmapDrawable import android.os.Bundle import android.util.AttributeSet import android.view.MotionEvent -import android.webkit.WebView -import android.webkit.SslErrorHandler import android.webkit.HttpAuthHandler +import android.webkit.SslErrorHandler +import android.webkit.WebView -import androidx.core.content.ContextCompat +import androidx.appcompat.content.res.AppCompatResources.getDrawable import androidx.core.view.NestedScrollingChild2 import androidx.core.view.NestedScrollingChildHelper import androidx.core.view.ViewCompat import com.stoutner.privacybrowser.R +import com.stoutner.privacybrowser.activities.MainWebViewActivity import java.util.Collections import java.util.Date import kotlin.collections.ArrayList -import kotlin.jvm.JvmOverloads - -// Define the saved state constants. +// Define the public constants. +const val BLOCKED_REQUESTS = 0 +const val EASYLIST = 1 +const val EASYPRIVACY = 2 +const val FANBOYS_ANNOYANCE_LIST = 3 +const val FANBOYS_SOCIAL_BLOCKING_LIST = 4 +const val ULTRALIST = 5 +const val ULTRAPRIVACY = 6 +const val THIRD_PARTY_REQUESTS = 7 + +// Define the private class constants. private const val DOMAIN_SETTINGS_APPLIED = "domain_settings_applied" private const val DOMAIN_SETTINGS_DATABASE_ID = "domain_settings_database_id" private const val CURRENT_DOMAIN_NAME = "current_domain_name" @@ -79,18 +89,6 @@ private const val FONT_SIZE = "font_size" class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null, defaultStyle: Int = android.R.attr.webViewStyle) : WebView(context, attributeSet, defaultStyle), NestedScrollingChild2 { - companion object { - // Define the public companion object blocklists constants. - const val BLOCKED_REQUESTS = 0 - const val EASYLIST = 1 - const val EASYPRIVACY = 2 - const val FANBOYS_ANNOYANCE_LIST = 3 - const val FANBOYS_SOCIAL_BLOCKING_LIST = 4 - const val ULTRALIST = 5 - const val ULTRAPRIVACY = 6 - const val THIRD_PARTY_REQUESTS = 7 - } - // Define the public variables. var acceptCookies = false var blockAllThirdPartyRequests = false @@ -113,10 +111,10 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS var waitingForProxyUrlString = "" var webViewFragmentId: Long = 0 - // Define the private variables. private val nestedScrollingChildHelper: NestedScrollingChildHelper = NestedScrollingChildHelper(this) - private lateinit var favoriteOrDefaultIcon: Bitmap + private lateinit var favoriteIcon: Bitmap + private var favoriteIconHeight = 0 private var previousYPosition = 0 // The previous Y position needs to be tracked between motion events. private var hasPinnedSslCertificate = false private var pinnedSslIssuedToCName = "" @@ -145,22 +143,27 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS initializeFavoriteIcon() } - // Favorite or default icon. fun initializeFavoriteIcon() { - // Get the default favorite icon drawable. `ContextCompat` must be used until API >= 21. - val favoriteIconDrawable = ContextCompat.getDrawable(context, R.drawable.world) + // Get the default favorite icon drawable. + val favoriteIconDrawable = getDrawable(context, R.drawable.world) // Cast the favorite icon drawable to a bitmap drawable. val favoriteIconBitmapDrawable = (favoriteIconDrawable as BitmapDrawable?)!! // Store the default icon bitmap. - favoriteOrDefaultIcon = favoriteIconBitmapDrawable.bitmap + favoriteIcon = favoriteIconBitmapDrawable.bitmap + + // Set the favorite icon height to be 0. This way any favorite icons presented by the website will overwrite it. + favoriteIconHeight = 0 } - fun setFavoriteOrDefaultIcon(icon: Bitmap) { + fun setFavoriteIcon(icon: Bitmap) { + // Store the current favorite icon height. + favoriteIconHeight = icon.height + // Scale the favorite icon bitmap down if it is larger than 256 x 256. Filtering uses bilinear interpolation. - favoriteOrDefaultIcon = if (icon.height > 256 || icon.width > 256) { + favoriteIcon = if (icon.height > 256 || icon.width > 256) { Bitmap.createScaledBitmap(icon, 256, 256, true) } else { // Store the icon as presented. @@ -168,11 +171,15 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS } } - fun getFavoriteOrDefaultIcon(): Bitmap { - // Return the favorite or default icon. This is the only way to return a non-nullable variable while retaining the custom initialization and setter functions above. - return favoriteOrDefaultIcon + fun getFavoriteIcon(): Bitmap { + // Return the favorite icon. This is the only way to return a non-nullable variable while retaining the custom initialization and setter functions above. + return favoriteIcon } + fun getFavoriteIconHeight(): Int { + // Return the favorite icon height. + return favoriteIconHeight + } // Reset the handlers. fun resetSslErrorHandler() { @@ -207,22 +214,15 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS hasPinnedSslCertificate = true } - fun getPinnedSslCertificate(): ArrayList { - // Initialize an array list. - val arrayList = ArrayList() - + fun getPinnedSslCertificate(): Pair, Array> { // Create the SSL certificate string array. val sslCertificateStringArray = arrayOf(pinnedSslIssuedToCName, pinnedSslIssuedToOName, pinnedSslIssuedToUName, pinnedSslIssuedByCName, pinnedSslIssuedByOName, pinnedSslIssuedByUName) // Create the SSL certificate date array. val sslCertificateDateArray = arrayOf(pinnedSslStartDate, pinnedSslEndDate) - // Add the arrays to the array list. - arrayList.add(sslCertificateStringArray) - arrayList.add(sslCertificateDateArray) - - // Return the pinned SSL certificate array list. - return arrayList + // Return the pinned SSL certificate pair. + return Pair(sslCertificateStringArray, sslCertificateDateArray) } fun clearPinnedSslCertificate() { @@ -312,6 +312,19 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS return computeVerticalScrollRange() } + override fun onOverScrolled(scrollX: Int, scrollY: Int, clampedX: Boolean, clampedY: Boolean) { + // Run the default commands. + super.onOverScrolled(scrollX, scrollY, clampedX, clampedY) + + // Display the bottom app bar if it has been hidden and the WebView was over-scrolled at the top of the screen. + if ((MainWebViewActivity.appBarLayout.translationY != 0f) && (scrollY == 0) && clampedY) { + // Animate the bottom app bar onto the screen. + val objectAnimator = ObjectAnimator.ofFloat(MainWebViewActivity.appBarLayout, "translationY", 0f) + + // Make it so. + objectAnimator.start() + } + } // Handle touches. @SuppressLint("ClickableViewAccessibility") @@ -376,7 +389,7 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS } - // Save and restore state. + // Save the state. fun saveNestedScrollWebViewState(): Bundle { // Create a saved state bundle. val savedState = Bundle() @@ -416,6 +429,7 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS return savedState } + // Restore the state. fun restoreNestedScrollWebViewState(savedState: Bundle) { // Restore the class variables. domainSettingsApplied = savedState.getBoolean(DOMAIN_SETTINGS_APPLIED) @@ -533,4 +547,4 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS // Dispatch a nested fling with the specified velocity. return nestedScrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed) } -} \ No newline at end of file +}