Closes #449 - Adds Basic About Page with Dated Version Name
parent
c3e8e83776
commit
0c8b2a8a1e
|
@ -12,10 +12,10 @@ android {
|
||||||
compileSdkVersion 28
|
compileSdkVersion 28
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "org.mozilla.fenix"
|
applicationId "org.mozilla.fenix"
|
||||||
minSdkVersion 21
|
minSdkVersion Config.minSdkVersion
|
||||||
targetSdkVersion 28
|
targetSdkVersion Config.targetSdkVersion
|
||||||
versionCode 1
|
versionCode Config.versionCode
|
||||||
versionName "1.0"
|
versionName Config.versionName + Config.generateVersionSuffix()
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/* 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
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
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.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 -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onErrorRequest(
|
||||||
|
session: EngineSession,
|
||||||
|
errorType: ErrorType,
|
||||||
|
uri: String?
|
||||||
|
): RequestInterceptor.ErrorResponse? {
|
||||||
|
return RequestInterceptor.ErrorResponse(ErrorPages.createErrorPage(context, errorType))
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val base64 = "base64"
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ import mozilla.components.concept.engine.Engine
|
||||||
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy
|
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy
|
||||||
import mozilla.components.feature.session.HistoryDelegate
|
import mozilla.components.feature.session.HistoryDelegate
|
||||||
import mozilla.components.lib.crash.handler.CrashHandlerService
|
import mozilla.components.lib.crash.handler.CrashHandlerService
|
||||||
|
import org.mozilla.fenix.AppRequestInterceptor
|
||||||
import org.mozilla.geckoview.GeckoRuntime
|
import org.mozilla.geckoview.GeckoRuntime
|
||||||
import org.mozilla.geckoview.GeckoRuntimeSettings
|
import org.mozilla.geckoview.GeckoRuntimeSettings
|
||||||
|
|
||||||
|
@ -32,6 +33,7 @@ class Core(private val context: Context) {
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
val defaultSettings = DefaultSettings(
|
val defaultSettings = DefaultSettings(
|
||||||
|
requestInterceptor = AppRequestInterceptor(context),
|
||||||
remoteDebuggingEnabled = false,
|
remoteDebuggingEnabled = false,
|
||||||
testingModeEnabled = false,
|
testingModeEnabled = false,
|
||||||
trackingProtectionPolicy = createTrackingProtectionPolicy(prefs),
|
trackingProtectionPolicy = createTrackingProtectionPolicy(prefs),
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* 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.ext
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the keys with the values with the map provided.
|
||||||
|
*/
|
||||||
|
fun String.replace(pairs: Map<String, String>): String {
|
||||||
|
var result = this
|
||||||
|
pairs.forEach { (l, r) -> result = result.replace(l, r) }
|
||||||
|
return result
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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.R
|
||||||
|
import org.mozilla.fenix.ext.replace
|
||||||
|
import org.mozilla.geckoview.BuildConfig
|
||||||
|
|
||||||
|
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.
|
||||||
|
}
|
||||||
|
|
||||||
|
context.resources.getString(R.string.about_content, appName).also { content ->
|
||||||
|
substitutionMap["%about-content%"] = content
|
||||||
|
}
|
||||||
|
|
||||||
|
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) }
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,12 +9,16 @@ import android.os.Bundle
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.navigation.Navigation
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.Preference.OnPreferenceClickListener
|
import androidx.preference.Preference.OnPreferenceClickListener
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
import mozilla.components.browser.session.Session
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.R.string.pref_key_about
|
||||||
import org.mozilla.fenix.R.string.pref_key_make_default_browser
|
import org.mozilla.fenix.R.string.pref_key_make_default_browser
|
||||||
import org.mozilla.fenix.ext.getPreferenceKey
|
import org.mozilla.fenix.ext.getPreferenceKey
|
||||||
|
import org.mozilla.fenix.ext.requireComponents
|
||||||
|
|
||||||
class SettingsFragment : PreferenceFragmentCompat() {
|
class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
|
@ -35,10 +39,14 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
private fun setupPreferences() {
|
private fun setupPreferences() {
|
||||||
val makeDefaultBrowserKey = context?.getPreferenceKey(pref_key_make_default_browser)
|
val makeDefaultBrowserKey = context?.getPreferenceKey(pref_key_make_default_browser)
|
||||||
|
val aboutKey = context?.getPreferenceKey(pref_key_about)
|
||||||
|
|
||||||
val preferenceMakeDefaultBrowser = findPreference<Preference>(makeDefaultBrowserKey)
|
val preferenceMakeDefaultBrowser = findPreference<Preference>(makeDefaultBrowserKey)
|
||||||
|
val preferenceAbout = findPreference<Preference>(aboutKey)
|
||||||
|
|
||||||
preferenceMakeDefaultBrowser.onPreferenceClickListener = getClickListenerForMakeDefaultBrowser()
|
preferenceMakeDefaultBrowser.onPreferenceClickListener =
|
||||||
|
getClickListenerForMakeDefaultBrowser()
|
||||||
|
preferenceAbout.onPreferenceClickListener = getAboutPageListener()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val defaultClickListener = OnPreferenceClickListener { preference ->
|
private val defaultClickListener = OnPreferenceClickListener { preference ->
|
||||||
|
@ -59,4 +67,23 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
defaultClickListener
|
defaultClickListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getAboutPageListener(): OnPreferenceClickListener {
|
||||||
|
return OnPreferenceClickListener {
|
||||||
|
requireComponents.core.sessionManager.add(Session(aboutURL), true)
|
||||||
|
view?.let {
|
||||||
|
Navigation.findNavController(it)
|
||||||
|
.navigate(
|
||||||
|
SettingsFragmentDirections.actionGlobalBrowser(
|
||||||
|
requireComponents.core.sessionManager.selectedSession?.id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val aboutURL = "about:version"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
<!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/. -->
|
||||||
|
<head>
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
charset="utf-8"
|
||||||
|
content="width=device-width, initial-scale=1">
|
||||||
|
<style>
|
||||||
|
body, html {
|
||||||
|
background: #221F1F;
|
||||||
|
color: #FFFFFF;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1#wordmark {
|
||||||
|
padding-top: 24px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<html>
|
||||||
|
<body
|
||||||
|
class="about">
|
||||||
|
<h1 id="wordmark">Fenix</h1>
|
||||||
|
<p class="subtitle">%about-version%</p>
|
||||||
|
%about-content%
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -131,4 +131,10 @@
|
||||||
|
|
||||||
<!-- Content description (not visible, for screen readers etc.): "Menu icon for items on a history item" -->
|
<!-- 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>
|
<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>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
object Config {
|
||||||
|
const val versionCode = 1
|
||||||
|
const val versionName = "1.0"
|
||||||
|
|
||||||
|
// Synchronized build configuration for all modules
|
||||||
|
const val compileSdkVersion = 28
|
||||||
|
const val minSdkVersion = 21
|
||||||
|
const val targetSdkVersion = 28
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun generateVersionSuffix(): String {
|
||||||
|
val today = Date()
|
||||||
|
// Append the year (2 digits) and week in year (2 digits). This will make it easier to distinguish versions and
|
||||||
|
// identify ancient versions when debugging issues. However this will still keep the same version number during
|
||||||
|
// the week so that we do not end up with a lot of versions in tools like Sentry. As an extra this matches the
|
||||||
|
// sections we use in the changelog (weeks).
|
||||||
|
return SimpleDateFormat(".yyww", Locale.US).format(today)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue