2 * Copyright © 2016-2021 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
6 * Privacy Browser is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Browser is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>.
20 package com.stoutner.privacybrowser.activities
22 import android.content.Intent
23 import android.net.Uri
24 import android.os.Bundle
25 import android.view.WindowManager
26 import android.widget.EditText
27 import android.widget.LinearLayout
29 import androidx.appcompat.app.AppCompatActivity
30 import androidx.appcompat.widget.Toolbar
31 import androidx.fragment.app.DialogFragment
32 import androidx.preference.PreferenceManager
33 import androidx.viewpager.widget.ViewPager
35 import com.google.android.material.snackbar.Snackbar
36 import com.google.android.material.tabs.TabLayout
38 import com.stoutner.privacybrowser.R
39 import com.stoutner.privacybrowser.adapters.AboutPagerAdapter
40 import com.stoutner.privacybrowser.asynctasks.SaveAboutVersionImage
41 import com.stoutner.privacybrowser.dialogs.SaveDialog
42 import com.stoutner.privacybrowser.dialogs.SaveDialog.SaveListener
43 import com.stoutner.privacybrowser.fragments.AboutVersionFragment
45 import java.io.ByteArrayInputStream
46 import java.io.InputStream
47 import java.lang.Exception
48 import java.nio.charset.StandardCharsets
50 class AboutActivity : AppCompatActivity(), SaveListener {
51 // Declare the class variables.
52 private lateinit var aboutPagerAdapter: AboutPagerAdapter
55 // Define the companion object constants. These can be move to being public constants once MainWebViewActivity has been converted to Kotlin.
56 const val BLOCKLIST_VERSIONS = "blocklist_versions"
59 override fun onCreate(savedInstanceState: Bundle?) {
60 // Get a handle for the shared preferences.
61 val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
63 // Get the preferences.
64 val allowScreenshots = sharedPreferences.getBoolean(getString(R.string.allow_screenshots_key), false)
65 val bottomAppBar = sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)
67 // Disable screenshots if not allowed.
68 if (!allowScreenshots) {
69 window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
73 setTheme(R.style.PrivacyBrowser)
75 // Run the default commands.
76 super.onCreate(savedInstanceState)
78 // Get the intent that launched the activity.
79 val launchingIntent = intent
81 // Store the blocklist versions.
82 val blocklistVersions = launchingIntent.getStringArrayExtra(BLOCKLIST_VERSIONS)!!
84 // Set the content view.
86 setContentView(R.layout.about_coordinatorlayout_bottom_appbar)
88 setContentView(R.layout.about_coordinatorlayout_top_appbar)
91 // Get handles for the views.
92 val toolbar = findViewById<Toolbar>(R.id.about_toolbar)
93 val aboutTabLayout = findViewById<TabLayout>(R.id.about_tablayout)
94 val aboutViewPager = findViewById<ViewPager>(R.id.about_viewpager)
96 // Set the action bar. `SupportActionBar` must be used until the minimum API is >= 21.
97 setSupportActionBar(toolbar)
99 // Get a handle for the action bar.
100 val actionBar = supportActionBar!!
102 // Display the home arrow on action bar.
103 actionBar.setDisplayHomeAsUpEnabled(true)
105 // Initialize the about pager adapter.
106 aboutPagerAdapter = AboutPagerAdapter(supportFragmentManager, applicationContext, blocklistVersions)
108 // Set the view pager adapter.
109 aboutViewPager.adapter = aboutPagerAdapter
111 // Keep all the tabs in memory. This prevents the memory usage updater from running multiple times.
112 aboutViewPager.offscreenPageLimit = 10
114 // Connect the tab layout to the view pager.
115 aboutTabLayout.setupWithViewPager(aboutViewPager)
118 // The activity result is called after browsing for a file in the save alert dialog.
119 public override fun onActivityResult(requestCode: Int, resultCode: Int, returnedIntent: Intent?) {
120 // Run the default commands.
121 super.onActivityResult(requestCode, resultCode, returnedIntent)
123 // Only do something if the user didn't press back from the file picker.
124 if (resultCode == RESULT_OK) {
125 // Get a handle for the save dialog fragment.
126 val saveDialogFragment = supportFragmentManager.findFragmentByTag(getString(R.string.save_dialog)) as DialogFragment?
128 // Only update the file name if the dialog still exists.
129 if (saveDialogFragment != null) {
130 // Get a handle for the save dialog.
131 val saveDialog = saveDialogFragment.dialog!!
133 // Get a handle for the file name edit text.
134 val fileNameEditText = saveDialog.findViewById<EditText>(R.id.file_name_edittext)
136 // Get the file name URI from the intent.
137 val fileNameUri = returnedIntent!!.data
139 // Get the file name string from the URI.
140 val fileNameString = fileNameUri.toString()
142 // Set the file name text.
143 fileNameEditText.setText(fileNameString)
145 // Move the cursor to the end of the file name edit text.
146 fileNameEditText.setSelection(fileNameString.length)
151 override fun onSave(saveType: Int, dialogFragment: DialogFragment) {
152 // Get a handle for the dialog.
153 val dialog = dialogFragment.dialog!!
155 // Get a handle for the file name edit text.
156 val fileNameEditText = dialog.findViewById<EditText>(R.id.file_name_edittext)
158 // Get the file name string.
159 val fileNameString = fileNameEditText.text.toString()
161 // Get a handle for the about version linear layout.
162 val aboutVersionLinearLayout = findViewById<LinearLayout>(R.id.about_version_linearlayout)
164 // Process the save event according to the type.
166 SaveDialog.SAVE_ABOUT_VERSION_TEXT -> try {
167 // Get a handle for the about version fragment.
168 val aboutVersionFragment = aboutPagerAdapter.getTabFragment(0) as AboutVersionFragment
170 // Get the about version text.
171 val aboutVersionString = aboutVersionFragment.aboutVersionString
173 // Create an input stream with the contents of about version.
174 val aboutVersionInputStream: InputStream = ByteArrayInputStream(aboutVersionString.toByteArray(StandardCharsets.UTF_8))
176 // Open an output stream.
177 val outputStream = contentResolver.openOutputStream(Uri.parse(fileNameString))!!
179 // Copy the input stream to the output stream.
180 aboutVersionInputStream.copyTo(outputStream, 2048)
182 // Close the streams.
183 aboutVersionInputStream.close()
186 // Display a snackbar with the saved about version information.
187 Snackbar.make(aboutVersionLinearLayout, getString(R.string.file_saved) + " " + fileNameString, Snackbar.LENGTH_SHORT).show()
188 } catch (exception: Exception) {
189 // Display a snackbar with the error message.
190 Snackbar.make(aboutVersionLinearLayout, getString(R.string.error_saving_file) + " " + exception.toString(), Snackbar.LENGTH_INDEFINITE).show()
193 SaveDialog.SAVE_ABOUT_VERSION_IMAGE ->
194 // Save the about version image.
195 SaveAboutVersionImage(this, fileNameString, aboutVersionLinearLayout).execute()