From 70fa89f618b62a9d17064699ec130341069aa77d Mon Sep 17 00:00:00 2001 From: Soren Stoutner Date: Mon, 23 Aug 2021 17:44:54 -0700 Subject: [PATCH] Add two more navigation menu entries. --- app/src/main/assets/css/theme.css | 23 +++ app/src/main/assets/en/changelog.html | 36 +++++ app/src/main/assets/en/permissions.html | 2 +- app/src/main/assets/en/privacy_policy.html | 88 ++++++++++ .../privacycell/activities/PrivacyCell.kt | 18 ++- .../privacycell/dialogs/PermissionsDialog.kt | 78 --------- .../privacycell/dialogs/WebViewDialog.kt | 153 ++++++++++++++++++ app/src/main/res/drawable/changelog.xml | 13 ++ app/src/main/res/drawable/privacy_policy.xml | 17 ++ ...missions_dialog.xml => webview_dialog.xml} | 0 .../res/menu/navigation_menu_top_appbar.xml | 4 +- 11 files changed, 348 insertions(+), 84 deletions(-) create mode 100644 app/src/main/assets/en/changelog.html create mode 100644 app/src/main/assets/en/privacy_policy.html delete mode 100644 app/src/main/java/com/stoutner/privacycell/dialogs/PermissionsDialog.kt create mode 100644 app/src/main/java/com/stoutner/privacycell/dialogs/WebViewDialog.kt create mode 100644 app/src/main/res/drawable/changelog.xml create mode 100644 app/src/main/res/drawable/privacy_policy.xml rename app/src/main/res/layout/{permissions_dialog.xml => webview_dialog.xml} (100%) diff --git a/app/src/main/assets/css/theme.css b/app/src/main/assets/css/theme.css index 2ccd34c..421f9c1 100644 --- a/app/src/main/assets/css/theme.css +++ b/app/src/main/assets/css/theme.css @@ -47,4 +47,27 @@ h3 { h3 { color: #8AB4F8; /* Violet 500 */ } +} + +/* Red bold text */ +strong.red { + color: #B71C1C; /* Red 900. */ +} + +@media (prefers-color-scheme: dark) { + strong.red { + color: #FC684E; /* Salmon. */ + } +} + +/* Blue bold text */ +strong.blue { + color: #1565C0; /* Blue 800. */ +} + + +/* List items. */ +item { + color: #1565C0; /* Blue 800. */ + font-weight: bold; } \ No newline at end of file diff --git a/app/src/main/assets/en/changelog.html b/app/src/main/assets/en/changelog.html new file mode 100644 index 0000000..f7d01a2 --- /dev/null +++ b/app/src/main/assets/en/changelog.html @@ -0,0 +1,36 @@ + + + + + + + + + + + + + +

1.0 (version code 1)

+

28 August 2021 - minimum API 30, target API 30

+ + + \ No newline at end of file diff --git a/app/src/main/assets/en/permissions.html b/app/src/main/assets/en/permissions.html index 5207e2e..3bd484a 100644 --- a/app/src/main/assets/en/permissions.html +++ b/app/src/main/assets/en/permissions.html @@ -30,7 +30,7 @@

Privacy Cell uses the following permission.

Phone

-

READ_PHONE_STATE

+

android.permission. READ_PHONE_STATE

Required to determine which protocols are being used by the cell phone network.

\ No newline at end of file diff --git a/app/src/main/assets/en/privacy_policy.html b/app/src/main/assets/en/privacy_policy.html new file mode 100644 index 0000000..376cad5 --- /dev/null +++ b/app/src/main/assets/en/privacy_policy.html @@ -0,0 +1,88 @@ + + + + + + + + + + + + + +

Privacy Cell

+

Privacy Cell does not collect any user information.

+ +

Google Play

+

Google Play has its own privacy policy. + Google provides anonymized summary installation information to developers, including the number of installs organized by the following categories.

+ + +

Google Play Ratings

+

Google Play has its own privacy policy. + Google provides developers with anonymized summaries of the following information related to user ratings.

+ + +

Google Play Reviews

+

Google Play has its own privacy policy. + In addition to the name of the reviewer, the rating, and the text of the review (which are all available publicly), Google provides some or all of the following information to the developer.

+ + +

Direct Communications

+

Users may choose to send direct communications to Stoutner, like email messages and comments on stoutner.com.

+ +

Use of Information

+

Stoutner may use this information to assist in the development of Privacy Cell and communicate the status of the project to users. + Stoutner will never sell the information nor transfer it to any third party that would use it for advertising or marketing.

+ +
+

Revision 1.0, 23 August 2021

+ + \ No newline at end of file diff --git a/app/src/main/java/com/stoutner/privacycell/activities/PrivacyCell.kt b/app/src/main/java/com/stoutner/privacycell/activities/PrivacyCell.kt index a886347..9648546 100644 --- a/app/src/main/java/com/stoutner/privacycell/activities/PrivacyCell.kt +++ b/app/src/main/java/com/stoutner/privacycell/activities/PrivacyCell.kt @@ -44,8 +44,8 @@ import androidx.drawerlayout.widget.DrawerLayout import com.google.android.material.navigation.NavigationView import com.stoutner.privacycell.R -import com.stoutner.privacycell.dialogs.PermissionsDialog import com.stoutner.privacycell.dialogs.PhonePermissionDialog +import com.stoutner.privacycell.dialogs.WebViewDialog class PrivacyCell : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener, PhonePermissionDialog.StoragePermissionDialogListener { // Declare the class variables. @@ -168,10 +168,22 @@ class PrivacyCell : AppCompatActivity(), NavigationView.OnNavigationItemSelected // Run the commands that correspond to the selected menu item. if (menuItemId == R.id.permissions) { // Permissions. // Instantiate the permissions dialog fragment. - val permissionsDialogFragment = PermissionsDialog() + val permissionsDialogFragment = WebViewDialog().type(WebViewDialog.PERMISSIONS) // Show the permissions alert dialog. - permissionsDialogFragment.show(supportFragmentManager, getString(R.string.phone_permission)) + permissionsDialogFragment.show(supportFragmentManager, getString(R.string.permissions)) + } else if (menuItemId == R.id.privacy_policy) { // Privacy Policy. + // Instantiate the privacy policy dialog fragment. + val privacyPolicyDialogFragment = WebViewDialog().type(WebViewDialog.PRIVACY_POLICY) + + // Show the privacy policy alert dialog. + privacyPolicyDialogFragment.show(supportFragmentManager, getString(R.string.privacy_policy)) + } else if (menuItemId == R.id.changelog) { // Changelog. + // Instantiate the changelog dialog fragment. + val changelogDialogFragment = WebViewDialog().type(WebViewDialog.CHANGELOG) + + // Show the changelog alert dialog. + changelogDialogFragment.show(supportFragmentManager, getString(R.string.changelog)) } // Close the navigation drawer. diff --git a/app/src/main/java/com/stoutner/privacycell/dialogs/PermissionsDialog.kt b/app/src/main/java/com/stoutner/privacycell/dialogs/PermissionsDialog.kt deleted file mode 100644 index 8cf799e..0000000 --- a/app/src/main/java/com/stoutner/privacycell/dialogs/PermissionsDialog.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright © 2021 Soren Stoutner . - * - * This file is part of Privacy Cell . - * - * Privacy Cell 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 Cell 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 . - */ - -package com.stoutner.privacycell.dialogs - -import android.app.Dialog -import android.content.res.Configuration -import android.os.Bundle -import android.webkit.WebView - -import androidx.appcompat.app.AlertDialog -import androidx.fragment.app.DialogFragment -import androidx.webkit.WebSettingsCompat -import androidx.webkit.WebViewFeature - -import com.stoutner.privacycell.R - -class PermissionsDialog : DialogFragment() { - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - // Use a builder to create the alert dialog. - val dialogBuilder = AlertDialog.Builder(requireContext(), R.style.Theme_PrivacyCellAlertDialog) - - // Set the icon. - dialogBuilder.setIcon(R.drawable.permissions) - - // Set the title. - dialogBuilder.setTitle(R.string.permissions) - - // Set the view. - dialogBuilder.setView(R.layout.permissions_dialog) - - // Set a listener on the close button. Using `null` as the listener closes the dialog without doing anything else. - dialogBuilder.setNegativeButton(R.string.close, null) - - // Create an alert dialog from the builder. - val alertDialog = dialogBuilder.create() - - // The alert dialog needs to be shown before the contents can be modified. - alertDialog.show() - - // Get a handle for the WebView. - val webView = alertDialog.findViewById(R.id.webview)!! - - // Get the current theme status. - val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK - - // Check to see if the app is in night mode. - if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES && WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) { // The app is in night mode. - // Apply the dark WebView theme. - WebSettingsCompat.setForceDark(webView.settings, WebSettingsCompat.FORCE_DARK_ON) - } - - // Create a WebView asset loader. TODO. - // val webViewAssetLoader = WebViewAssetLoader.Builder().addPathHandler("/assets/", WebViewAssetLoader.AssetsPathHandler(requireContext())).build() - - // Load the WebView data. - webView.loadUrl("file:///android_asset/en/permissions.html") - - // Return the alert dialog. - return alertDialog - } -} \ No newline at end of file diff --git a/app/src/main/java/com/stoutner/privacycell/dialogs/WebViewDialog.kt b/app/src/main/java/com/stoutner/privacycell/dialogs/WebViewDialog.kt new file mode 100644 index 0000000..5961c2e --- /dev/null +++ b/app/src/main/java/com/stoutner/privacycell/dialogs/WebViewDialog.kt @@ -0,0 +1,153 @@ +/* + * Copyright © 2021 Soren Stoutner . + * + * This file is part of Privacy Cell . + * + * Privacy Cell 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 Cell 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 . + */ + +package com.stoutner.privacycell.dialogs + +import android.app.Dialog +import android.content.res.Configuration +import android.os.Bundle +import android.webkit.WebView + +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.DialogFragment +import androidx.webkit.WebSettingsCompat +import androidx.webkit.WebViewFeature + +import com.stoutner.privacycell.R + +// Define the class constants. +private const val DIALOG_TYPE = "dialog_type" +private const val SCROLL_Y = "scroll_y" + +class WebViewDialog : DialogFragment() { + companion object { + // Define the public constants. + const val PERMISSIONS = 0 + const val PRIVACY_POLICY = 1 + const val CHANGELOG = 2 + } + + // Define the class views. + private lateinit var webView: WebView + + // Populate the WebView dialog type. + fun type(dialogType: Int): WebViewDialog { + // Create an arguments bundle. + val argumentsBundle = Bundle() + + // Add the dialog type to the bundle. + argumentsBundle.putInt(DIALOG_TYPE, dialogType) + + // Create a new instance of the WebView dialog. + val webViewDialog = WebViewDialog() + + // Add the arguments bundle to the new dialog. + webViewDialog.arguments = argumentsBundle + + // Return the new dialog. + return webViewDialog + } + + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + // Get the dialog type from the arguments bundle. + val dialogType = requireArguments().getInt(DIALOG_TYPE) + + // Use a builder to create the alert dialog. + val dialogBuilder = AlertDialog.Builder(requireContext(), R.style.Theme_PrivacyCellAlertDialog) + + // Set the icon and the title according to the dialog type. + when (dialogType) { + PERMISSIONS -> { + // Set the icon. + dialogBuilder.setIcon(R.drawable.permissions) + + // Set the title. + dialogBuilder.setTitle(R.string.permissions) + } + + PRIVACY_POLICY -> { + // Set the icon. + dialogBuilder.setIcon(R.drawable.privacy_policy) + + // Set the title. + dialogBuilder.setTitle(R.string.privacy_policy) + } + + CHANGELOG -> { + // Set the icon. + dialogBuilder.setIcon(R.drawable.changelog) + + // Set the title. + dialogBuilder.setTitle(R.string.changelog) + } + } + + // Set the view. + dialogBuilder.setView(R.layout.webview_dialog) + + // Set a listener on the close button. Using `null` as the listener closes the dialog without doing anything else. + dialogBuilder.setNegativeButton(R.string.close, null) + + // Create an alert dialog from the builder. + val alertDialog = dialogBuilder.create() + + // The alert dialog needs to be shown before the contents can be modified. + alertDialog.show() + + // Get a handle for the WebView. + webView = alertDialog.findViewById(R.id.webview)!! + + // Get the current theme status. + val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK + + // Check to see if the app is in night mode. + if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES && WebViewFeature.isFeatureSupported(WebViewFeature.FORCE_DARK)) { // The app is in night mode. + // Apply the dark WebView theme. + WebSettingsCompat.setForceDark(webView.settings, WebSettingsCompat.FORCE_DARK_ON) + } + + // Create a WebView asset loader. TODO. + // val webViewAssetLoader = WebViewAssetLoader.Builder().addPathHandler("/assets/", WebViewAssetLoader.AssetsPathHandler(requireContext())).build() + + // Load the WebView data according to the dialog type. + when (dialogType) { + PERMISSIONS -> webView.loadUrl("file:///android_asset/en/permissions.html") + PRIVACY_POLICY -> webView.loadUrl("file:///android_asset/en/privacy_policy.html") + CHANGELOG -> webView.loadUrl("file:///android_asset/en/changelog.html") + } + + // Scroll the WebView if the saved instance state is not null. + if (savedInstanceState != null) { + webView.post { + webView.scrollY = savedInstanceState.getInt(SCROLL_Y) + } + } + + // Return the alert dialog. + return alertDialog + } + + override fun onSaveInstanceState(savedInstanceState: Bundle) { + // Run the default commands. + super.onSaveInstanceState(savedInstanceState) + + // Save the scroll position. + savedInstanceState.putInt(SCROLL_Y, webView.scrollY) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/changelog.xml b/app/src/main/res/drawable/changelog.xml new file mode 100644 index 0000000..44fb1c6 --- /dev/null +++ b/app/src/main/res/drawable/changelog.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/privacy_policy.xml b/app/src/main/res/drawable/privacy_policy.xml new file mode 100644 index 0000000..720ace8 --- /dev/null +++ b/app/src/main/res/drawable/privacy_policy.xml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/permissions_dialog.xml b/app/src/main/res/layout/webview_dialog.xml similarity index 100% rename from app/src/main/res/layout/permissions_dialog.xml rename to app/src/main/res/layout/webview_dialog.xml diff --git a/app/src/main/res/menu/navigation_menu_top_appbar.xml b/app/src/main/res/menu/navigation_menu_top_appbar.xml index b4b9e73..fc91ca0 100644 --- a/app/src/main/res/menu/navigation_menu_top_appbar.xml +++ b/app/src/main/res/menu/navigation_menu_top_appbar.xml @@ -28,13 +28,13 @@