Fixes #1162 - replaces about page with an Android Fragment
parent
5f5bb47706
commit
379875a62a
|
@ -9,25 +9,8 @@ import mozilla.components.browser.errorpages.ErrorPages
|
|||
import mozilla.components.browser.errorpages.ErrorType
|
||||
import mozilla.components.concept.engine.EngineSession
|
||||
import mozilla.components.concept.engine.request.RequestInterceptor
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.settings.AboutPage
|
||||
import org.mozilla.fenix.settings.SettingsFragment
|
||||
|
||||
class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
|
||||
override fun onLoadRequest(
|
||||
session: EngineSession,
|
||||
uri: String
|
||||
): RequestInterceptor.InterceptionResponse? {
|
||||
return when (uri) {
|
||||
SettingsFragment.aboutURL -> {
|
||||
val page = AboutPage.createAboutPage(context)
|
||||
return RequestInterceptor.InterceptionResponse.Content(page, encoding = base64)
|
||||
}
|
||||
|
||||
else -> context.components.services.accountsAuthFeature.interceptor.onLoadRequest(session, uri)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onErrorRequest(
|
||||
session: EngineSession,
|
||||
errorType: ErrorType,
|
||||
|
@ -35,8 +18,4 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
|
|||
): RequestInterceptor.ErrorResponse? {
|
||||
return RequestInterceptor.ErrorResponse(ErrorPages.createErrorPage(context, errorType))
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val base64 = "base64"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.fenix.settings
|
||||
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import kotlinx.android.synthetic.main.fragment_about.*
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.geckoview.BuildConfig
|
||||
|
||||
class AboutFragment : Fragment() {
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.fragment_about, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val appName = requireContext().resources.getString(R.string.app_name)
|
||||
(activity as AppCompatActivity).title = getString(R.string.preferences_about, appName)
|
||||
|
||||
val aboutText = try {
|
||||
val packageInfo = requireContext().packageManager.getPackageInfo(requireContext().packageName, 0)
|
||||
val geckoVersion = packageInfo.versionCode.toString() + " \uD83E\uDD8E " +
|
||||
BuildConfig.MOZ_APP_VERSION + "-" + BuildConfig.MOZ_APP_BUILDID
|
||||
String.format(
|
||||
"%s (Build #%s)",
|
||||
packageInfo.versionName,
|
||||
geckoVersion
|
||||
)
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
""
|
||||
}
|
||||
|
||||
val buildDate = org.mozilla.fenix.BuildConfig.BUILD_DATE
|
||||
val content = resources.getString(R.string.about_content, appName)
|
||||
|
||||
about_text.text = aboutText
|
||||
about_content.text = content
|
||||
build_date.text = buildDate
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package org.mozilla.fenix.settings
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import androidx.annotation.RawRes
|
||||
import org.mozilla.fenix.BuildConfig.BUILD_DATE
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.replace
|
||||
import org.mozilla.fenix.settings.SettingsFragment.Companion.wordmarkPath
|
||||
import org.mozilla.geckoview.BuildConfig
|
||||
import java.io.File
|
||||
|
||||
object AboutPage {
|
||||
fun createAboutPage(context: Context): String {
|
||||
val substitutionMap = mutableMapOf<String, String>()
|
||||
val appName = context.resources.getString(R.string.app_name)
|
||||
|
||||
try {
|
||||
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
|
||||
val geckoVersion = packageInfo.versionCode.toString() + " \uD83E\uDD8E " +
|
||||
BuildConfig.MOZ_APP_VERSION + "-" + BuildConfig.MOZ_APP_BUILDID
|
||||
String.format(
|
||||
"%s (Build #%s)",
|
||||
packageInfo.versionName,
|
||||
geckoVersion
|
||||
).also { aboutVersion ->
|
||||
substitutionMap["%about-version%"] = aboutVersion
|
||||
}
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
// Nothing to do if we can't find the package name.
|
||||
}
|
||||
|
||||
substitutionMap["%build-date%"] = BUILD_DATE
|
||||
|
||||
context.resources.getString(R.string.about_content, appName, SupportUtils.MOZILLA_MANIFESTO_URL)
|
||||
.also { content ->
|
||||
substitutionMap["%about-content%"] = content
|
||||
}
|
||||
|
||||
substitutionMap["%wordmark%"] = File(context.filesDir, wordmarkPath).readText()
|
||||
|
||||
return loadResourceFile(context, R.raw.about, substitutionMap)
|
||||
}
|
||||
|
||||
private fun loadResourceFile(
|
||||
context: Context,
|
||||
@RawRes resId: Int,
|
||||
replacements: Map<String, String>
|
||||
): String {
|
||||
context.resources.openRawResource(resId)
|
||||
.bufferedReader()
|
||||
.use { it.readText() }
|
||||
.also { return it.replace(replacements) }
|
||||
}
|
||||
}
|
|
@ -5,7 +5,6 @@
|
|||
package org.mozilla.fenix.settings
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.BitmapFactory
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
|
@ -18,16 +17,13 @@ import androidx.preference.PreferenceCategory
|
|||
import androidx.preference.PreferenceFragmentCompat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import mozilla.components.concept.sync.AccountObserver
|
||||
import mozilla.components.concept.sync.OAuthAccount
|
||||
import mozilla.components.concept.sync.Profile
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import java.io.File
|
||||
import mozilla.components.service.fxa.FxaUnauthorizedException
|
||||
import mozilla.components.support.ktx.android.graphics.toDataUri
|
||||
import org.mozilla.fenix.BuildConfig
|
||||
import org.mozilla.fenix.FenixApplication
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
|
@ -85,7 +81,6 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
|
|||
val appName = getString(R.string.app_name)
|
||||
aboutPreference?.title = getString(R.string.preferences_about, appName)
|
||||
|
||||
generateWordmark()
|
||||
setupPreferences()
|
||||
setupAccountUI()
|
||||
}
|
||||
|
@ -122,8 +117,7 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
|
|||
navigateToSettingsArticle()
|
||||
}
|
||||
resources.getString(pref_key_about) -> {
|
||||
requireComponents.useCases.tabsUseCases.addTab.invoke(aboutURL, true)
|
||||
navigateToSettingsArticle()
|
||||
navigateToAbout()
|
||||
}
|
||||
resources.getString(pref_key_account) -> {
|
||||
navigateToAccountSettings()
|
||||
|
@ -164,30 +158,6 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shrinks the wordmark resolution on first run to ensure About Page loads quickly
|
||||
*/
|
||||
private fun generateWordmark() {
|
||||
val path = context?.filesDir
|
||||
val file = File(path, wordmarkPath)
|
||||
path?.let {
|
||||
if (!file.exists()) {
|
||||
launch(IO) {
|
||||
val options = BitmapFactory.Options().apply {
|
||||
inSampleSize = wordmarkScalingFactor
|
||||
inJustDecodeBounds = false
|
||||
}
|
||||
file.appendText(
|
||||
BitmapFactory.decodeResource(
|
||||
resources,
|
||||
R.drawable.ic_logo_wordmark, options
|
||||
).toDataUri()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupPreferences() {
|
||||
val makeDefaultBrowserKey = context!!.getPreferenceKey(pref_key_make_default_browser)
|
||||
val leakKey = context!!.getPreferenceKey(pref_key_leakcanary)
|
||||
|
@ -263,6 +233,11 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
|
|||
}
|
||||
}
|
||||
|
||||
private fun navigateToAbout() {
|
||||
val directions = SettingsFragmentDirections.actionSettingsFragmentToAboutFragment()
|
||||
Navigation.findNavController(view!!).navigate(directions)
|
||||
}
|
||||
|
||||
private fun navigateToAccountSettings() {
|
||||
val directions =
|
||||
SettingsFragmentDirections.actionSettingsFragmentToAccountSettingsFragment()
|
||||
|
@ -319,10 +294,4 @@ class SettingsFragment : PreferenceFragmentCompat(), CoroutineScope, AccountObse
|
|||
preferenceFirefoxAccount?.summary = profile.email.orEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val wordmarkScalingFactor = 2
|
||||
const val wordmarkPath = "wordmark.b64"
|
||||
const val aboutURL = "about:version"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
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_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="org.mozilla.fenix.settings.AboutFragment">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/wordmark"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="?attr/fenixLogo"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
app:layout_constraintWidth_percent="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginTop="24dp"
|
||||
app:layout_constraintWidth_percent="0.8"
|
||||
app:layout_constraintTop_toBottomOf="@id/wordmark"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:textAlignment="center" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/about_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="18sp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintWidth_percent="0.8"
|
||||
app:layout_constraintTop_toBottomOf="@id/about_text"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/build_date"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintWidth_percent="0.8"
|
||||
app:layout_constraintTop_toBottomOf="@id/about_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:textAlignment="center" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -106,6 +106,9 @@
|
|||
<action
|
||||
android:id="@+id/action_settingsFragment_to_searchEngineFragment"
|
||||
app:destination="@id/searchEngineFragment" />
|
||||
<action
|
||||
android:id="@+id/action_settingsFragment_to_aboutFragment"
|
||||
app:destination="@id/aboutFragment" />
|
||||
</fragment>
|
||||
<fragment android:id="@+id/dataChoicesFragment" android:name="org.mozilla.fenix.settings.DataChoicesFragment"
|
||||
android:label="DataChoicesFragment"/>
|
||||
|
@ -120,6 +123,11 @@
|
|||
android:id="@+id/searchEngineFragment"
|
||||
android:name="org.mozilla.fenix.settings.SearchEngineFragment"
|
||||
android:label="SearchEngineFragment" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/aboutFragment"
|
||||
android:name="org.mozilla.fenix.settings.AboutFragment"
|
||||
android:label="AboutFragment" />
|
||||
<fragment android:id="@+id/crashReporterFragment" android:name="org.mozilla.fenix.crashes.CrashReporterFragment"
|
||||
android:label="CrashReporterFragment">
|
||||
<action
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
<!doctype html>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<html>
|
||||
<head>
|
||||
<meta
|
||||
name="viewport"
|
||||
charset="utf-8"
|
||||
content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
body, html {
|
||||
background: #f9f9fa;
|
||||
color: #0C0C0D;
|
||||
font-family: sans-serif;
|
||||
line-height: 24px;
|
||||
font-size: 14px;
|
||||
}
|
||||
body{
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
a {
|
||||
color: #0A9AF4;
|
||||
}
|
||||
p.subtitle {
|
||||
text-align: center;
|
||||
opacity: .7;
|
||||
margin: 0;
|
||||
}
|
||||
img#wordmark {
|
||||
/* We need to set the dp size here, because by default webview assumes the image is not
|
||||
density specific (but since it's an android resource, we get a density specific version). */
|
||||
width: 180px;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-top: 24px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="about">
|
||||
<br>
|
||||
<img src="%wordmark%" id="wordmark"/>
|
||||
<br>
|
||||
<p class="subtitle">%about-version%</p>
|
||||
%about-content%
|
||||
<p class="subtitle">Built on: %build-date%</p>
|
||||
</body>
|
||||
</html>
|
|
@ -14,7 +14,9 @@
|
|||
<!-- Content description (not visible, for screen readers etc.): "Private Browsing" menu button. -->
|
||||
<string name="content_description_disable_private_browsing_button">Disable private browsing</string>
|
||||
<!-- Explanation for how sessions work -->
|
||||
<string name="sessions_intro_description">Sessions help you return to the sites you visit often and those you\'ve just discovered. Start browsing and they\'ll begin to appear here. </string>
|
||||
<string name="sessions_intro_description">Sessions help you return to the sites you visit often and those you\'ve
|
||||
just discovered. Start browsing and they\'ll begin to appear here.
|
||||
</string>
|
||||
<!-- Placeholder text shown in the search bar before a user enters text -->
|
||||
<string name="search_hint">Search or enter address</string>
|
||||
|
||||
|
@ -23,7 +25,11 @@
|
|||
<string name="private_browsing_title">You\'re in a private session</string>
|
||||
<!-- Explanation for private browsing displayed to users on home view when they first enable private mode
|
||||
The first parameter is the name of the app defined in app_name (for example: Fenix) -->
|
||||
<string name="private_browsing_explanation">%1$s clears your search and browsing history when you close your private session. While this doesn\'t make you anonymous to websites or your internet service provider, it makes it easier to keep what you do online private from anyone else who uses this device.\n\nCommon myths about private browsing</string>
|
||||
<string name="private_browsing_explanation">%1$s clears your search and browsing history when you close your private
|
||||
session. While this doesn\'t make you anonymous to websites or your internet service provider, it makes it
|
||||
easier to keep what you do online private from anyone else who uses this device.\n\nCommon myths about private
|
||||
browsing
|
||||
</string>
|
||||
<!-- Delete session button to erase your history in a private session -->
|
||||
<string name="private_browsing_delete_session">Delete session</string>
|
||||
|
||||
|
@ -132,7 +138,9 @@
|
|||
<!-- Preference for reducing image sizes, bandwidth and platform-level optimizations -->
|
||||
<string name="preference_optimize">Optimize</string>
|
||||
<!-- Label summary to explain how the optimize preference works -->
|
||||
<string name="preference_optimize_summary">Lower image quality, throttle streaming bandwidth, and platform-level optimizations</string>
|
||||
<string name="preference_optimize_summary">Lower image quality, throttle streaming bandwidth, and platform-level
|
||||
optimizations
|
||||
</string>
|
||||
<!-- Preference for showing a list of websites that the default configurations won't apply to them -->
|
||||
<string name="preference_exceptions">Exceptions</string>
|
||||
<!-- Preference for applying recommend rules to all sites -->
|
||||
|
@ -141,11 +149,15 @@
|
|||
<string name="preference_recommended_settings_summary">
|
||||
<b>Blocked</b>
|
||||
|
||||
\n Ads, autoplay sound and video (block playing media with sound), cookies (block third-party trackers cookies), trackers (allow some trackers), pop-up, website redirects. \n\n <b>Ask to allow</b>
|
||||
\n Ads, autoplay sound and video (block playing media with sound), cookies (block third-party trackers cookies),
|
||||
trackers (allow some trackers), pop-up, website redirects. \n\n
|
||||
<b>Ask to allow</b>
|
||||
|
||||
\n Camera, location, microphone and notification. \n\n <b>Allowed</b>
|
||||
\n Camera, location, microphone and notification. \n\n
|
||||
<b>Allowed</b>
|
||||
|
||||
\n DRM audio and video, JavaScript, cache and site data, images.</string>
|
||||
\n DRM audio and video, JavaScript, cache and site data, images.
|
||||
</string>
|
||||
<!-- Preference for applying custom rules to all sites -->
|
||||
<string name="preference_custom_settings">Use custom settings</string>
|
||||
<!-- Preference category for feature phone permissions likes Camera,Microphone, Location ... etc -->
|
||||
|
@ -226,11 +238,12 @@
|
|||
<string name="settings_title">Settings</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): "Menu icon for items on a history item" -->
|
||||
<string name="content_description_history_menu">History item menu</string>
|
||||
<!-- About content -->
|
||||
<string name="about_content"><![CDATA[
|
||||
<p>%1$s puts you in control.</p>
|
||||
<p>%1$s is produced by Mozilla. Our mission is to foster a healthy, open Internet.<br/>
|
||||
]]></string>
|
||||
<!-- About content. Sentences are separated by two new lines -->
|
||||
<string name="about_content">
|
||||
%1$s puts you in control.
|
||||
\n\n
|
||||
%1$s is produced by Mozilla. Our mission is to foster a healthy, open Internet.
|
||||
</string>
|
||||
|
||||
<!-- Sessions -->
|
||||
<!-- Title for the list of tabs in the current session -->
|
||||
|
|
Loading…
Reference in New Issue