parent
72d8dfb976
commit
c6c827f693
@ -1,95 +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.Intent
|
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Build.VERSION.SDK_INT
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.View
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.core.content.pm.PackageInfoCompat
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity
|
|
||||||
import kotlinx.android.synthetic.main.fragment_about.*
|
|
||||||
import org.mozilla.fenix.BrowserDirection
|
|
||||||
import org.mozilla.fenix.BuildConfig
|
|
||||||
import org.mozilla.fenix.HomeActivity
|
|
||||||
import org.mozilla.fenix.R
|
|
||||||
import org.mozilla.fenix.components.metrics.Event
|
|
||||||
import org.mozilla.fenix.ext.metrics
|
|
||||||
import org.mozilla.fenix.whatsnew.WhatsNew
|
|
||||||
import org.mozilla.geckoview.BuildConfig as GeckoViewBuildConfig
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the logo and information about the app, including library versions.
|
|
||||||
*/
|
|
||||||
class AboutFragment : Fragment(R.layout.fragment_about) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the activity title, displays library version strings, and sets up the [view_licenses_button].
|
|
||||||
*/
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
|
|
||||||
val appName = getString(R.string.app_name)
|
|
||||||
activity?.title = getString(R.string.preferences_about, appName)
|
|
||||||
|
|
||||||
val aboutText = try {
|
|
||||||
val packageInfo = requireContext().packageManager.getPackageInfo(requireContext().packageName, 0)
|
|
||||||
val versionCode = PackageInfoCompat.getLongVersionCode(packageInfo).toString()
|
|
||||||
val componentsVersion = mozilla.components.Build.version + ", " + mozilla.components.Build.gitHash
|
|
||||||
val maybeGecko = if (SDK_INT >= Build.VERSION_CODES.N) GECKO_EMOJI else "GV"
|
|
||||||
val geckoVersion = GeckoViewBuildConfig.MOZ_APP_VERSION + "-" + GeckoViewBuildConfig.MOZ_APP_BUILDID
|
|
||||||
|
|
||||||
String.format(
|
|
||||||
"%s (Build #%s)\n%s: %s\n%s: %s",
|
|
||||||
packageInfo.versionName,
|
|
||||||
versionCode,
|
|
||||||
COMPONENTS_EMOJI,
|
|
||||||
componentsVersion,
|
|
||||||
maybeGecko,
|
|
||||||
geckoVersion
|
|
||||||
)
|
|
||||||
} catch (e: PackageManager.NameNotFoundException) {
|
|
||||||
""
|
|
||||||
}
|
|
||||||
|
|
||||||
val content = getString(R.string.about_content, appName)
|
|
||||||
val buildDate = BuildConfig.BUILD_DATE
|
|
||||||
|
|
||||||
about_text.text = aboutText
|
|
||||||
about_content.text = content
|
|
||||||
build_date.text = buildDate
|
|
||||||
|
|
||||||
view_licenses_button.setOnClickListener {
|
|
||||||
startActivity(Intent(context, OssLicensesMenuActivity::class.java))
|
|
||||||
OssLicensesMenuActivity.setActivityTitle(getString(R.string.open_source_licenses_title, appName))
|
|
||||||
}
|
|
||||||
|
|
||||||
with(whats_new_button) {
|
|
||||||
text = getString(R.string.about_whats_new, getString(R.string.app_name))
|
|
||||||
setOnClickListener {
|
|
||||||
context.metrics.track(Event.WhatsNewTapped(Event.WhatsNewTapped.Source.ABOUT))
|
|
||||||
WhatsNew.userViewedWhatsNew(context!!)
|
|
||||||
(activity as HomeActivity).openToBrowserAndLoad(
|
|
||||||
searchTermOrURL = SupportUtils.getSumoURLForTopic(
|
|
||||||
context!!,
|
|
||||||
SupportUtils.SumoTopic.WHATS_NEW
|
|
||||||
),
|
|
||||||
newTab = true,
|
|
||||||
from = BrowserDirection.FromAbout
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val COMPONENTS_EMOJI = "\uD83D\uDCE6"
|
|
||||||
@RequiresApi(Build.VERSION_CODES.N)
|
|
||||||
private const val GECKO_EMOJI = "\uD83E\uDD8E"
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,168 @@
|
|||||||
|
/* 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.about
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.content.pm.PackageInfoCompat
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.recyclerview.widget.DividerItemDecoration
|
||||||
|
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity
|
||||||
|
import kotlinx.android.synthetic.main.fragment_about.*
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import org.mozilla.fenix.BuildConfig
|
||||||
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.components.metrics.Event
|
||||||
|
import org.mozilla.fenix.ext.requireComponents
|
||||||
|
import org.mozilla.fenix.lib.Do
|
||||||
|
import org.mozilla.fenix.settings.SupportUtils
|
||||||
|
import org.mozilla.fenix.settings.about.AboutItemType.LICENSING_INFO
|
||||||
|
import org.mozilla.fenix.settings.about.AboutItemType.PRIVACY_NOTICE
|
||||||
|
import org.mozilla.fenix.settings.about.AboutItemType.RIGHTS
|
||||||
|
import org.mozilla.fenix.settings.about.AboutItemType.SUPPORT
|
||||||
|
import org.mozilla.fenix.settings.about.AboutItemType.WHATS_NEW
|
||||||
|
import org.mozilla.fenix.whatsnew.WhatsNew
|
||||||
|
import org.mozilla.geckoview.BuildConfig as GeckoViewBuildConfig
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the logo and information about the app, including library versions.
|
||||||
|
*/
|
||||||
|
class AboutFragment : Fragment(), AboutPageListener {
|
||||||
|
private lateinit var appName: String
|
||||||
|
private val aboutPageAdapter: AboutPageAdapter = AboutPageAdapter(this)
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
val rootView = inflater.inflate(R.layout.fragment_about, container, false)
|
||||||
|
appName = getString(R.string.app_name)
|
||||||
|
activity?.title = getString(R.string.preferences_about, appName)
|
||||||
|
|
||||||
|
return rootView
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExperimentalCoroutinesApi
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
about_list.run {
|
||||||
|
adapter = aboutPageAdapter
|
||||||
|
addItemDecoration(
|
||||||
|
DividerItemDecoration(
|
||||||
|
context,
|
||||||
|
DividerItemDecoration.VERTICAL
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
populateAboutHeader()
|
||||||
|
aboutPageAdapter.updateData(populateAboutList())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun populateAboutHeader() {
|
||||||
|
val aboutText = try {
|
||||||
|
val packageInfo = requireContext().packageManager.getPackageInfo(requireContext().packageName, 0)
|
||||||
|
val versionCode = PackageInfoCompat.getLongVersionCode(packageInfo).toString()
|
||||||
|
val componentsVersion = mozilla.components.Build.version + ", " + mozilla.components.Build.gitHash
|
||||||
|
val maybeGecko = getString(R.string.gecko_view_abbreviation)
|
||||||
|
val geckoVersion = GeckoViewBuildConfig.MOZ_APP_VERSION + "-" + GeckoViewBuildConfig.MOZ_APP_BUILDID
|
||||||
|
|
||||||
|
String.format(
|
||||||
|
"%s (Build #%s)\n%s\n%s: %s",
|
||||||
|
packageInfo.versionName,
|
||||||
|
versionCode,
|
||||||
|
componentsVersion,
|
||||||
|
maybeGecko,
|
||||||
|
geckoVersion
|
||||||
|
)
|
||||||
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
|
val content = getString(R.string.about_content, appName)
|
||||||
|
val buildDate = BuildConfig.BUILD_DATE
|
||||||
|
|
||||||
|
about_text.text = aboutText
|
||||||
|
about_content.text = content
|
||||||
|
build_date.text = buildDate
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun populateAboutList(): List<AboutPageItem> {
|
||||||
|
val context = requireContext()
|
||||||
|
|
||||||
|
return listOf(
|
||||||
|
AboutPageItem.Item(
|
||||||
|
AboutItem.ExternalLink(
|
||||||
|
WHATS_NEW,
|
||||||
|
SupportUtils.getSumoURLForTopic(context, SupportUtils.SumoTopic.WHATS_NEW)
|
||||||
|
), getString(R.string.about_whats_new, getString(R.string.app_name))
|
||||||
|
),
|
||||||
|
AboutPageItem.Item(
|
||||||
|
AboutItem.ExternalLink(
|
||||||
|
SUPPORT,
|
||||||
|
SupportUtils.getSumoURLForTopic(context, SupportUtils.SumoTopic.HELP)
|
||||||
|
), getString(R.string.about_support)
|
||||||
|
),
|
||||||
|
AboutPageItem.Item(
|
||||||
|
AboutItem.ExternalLink(
|
||||||
|
PRIVACY_NOTICE,
|
||||||
|
SupportUtils.getPrivacyNoticeUrl()
|
||||||
|
), getString(R.string.about_privacy_notice)
|
||||||
|
),
|
||||||
|
AboutPageItem.Item(
|
||||||
|
AboutItem.ExternalLink(
|
||||||
|
RIGHTS,
|
||||||
|
SupportUtils.getSumoURLForTopic(context, SupportUtils.SumoTopic.YOUR_RIGHTS)
|
||||||
|
), getString(R.string.about_know_your_rights)
|
||||||
|
),
|
||||||
|
AboutPageItem.Item(
|
||||||
|
AboutItem.ExternalLink(LICENSING_INFO, ABOUT_LICENSE_URL),
|
||||||
|
getString(R.string.about_licensing_information)
|
||||||
|
),
|
||||||
|
AboutPageItem.Item(
|
||||||
|
AboutItem.Libraries,
|
||||||
|
getString(R.string.about_other_open_source_libraries)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openLinkInCustomTab(url: String) {
|
||||||
|
context?.let { context ->
|
||||||
|
val intent = SupportUtils.createCustomTabIntent(context, url)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openLibrariesPage() {
|
||||||
|
startActivity(Intent(context, OssLicensesMenuActivity::class.java))
|
||||||
|
OssLicensesMenuActivity.setActivityTitle(getString(R.string.open_source_licenses_title, appName))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAboutItemClicked(item: AboutItem) {
|
||||||
|
Do exhaustive when (item) {
|
||||||
|
is AboutItem.ExternalLink -> {
|
||||||
|
if (item.type == WHATS_NEW) {
|
||||||
|
WhatsNew.userViewedWhatsNew(requireContext())
|
||||||
|
requireComponents.analytics.metrics.track(Event.WhatsNewTapped(Event.WhatsNewTapped.Source.ABOUT))
|
||||||
|
}
|
||||||
|
|
||||||
|
openLinkInCustomTab(item.url)
|
||||||
|
}
|
||||||
|
is AboutItem.Libraries -> {
|
||||||
|
openLibrariesPage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ABOUT_LICENSE_URL = "about:license"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
/* 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.about
|
||||||
|
|
||||||
|
sealed class AboutItem {
|
||||||
|
data class ExternalLink(val type: AboutItemType, val url: String) : AboutItem()
|
||||||
|
object Libraries : AboutItem()
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class AboutItemType {
|
||||||
|
WHATS_NEW, SUPPORT, PRIVACY_NOTICE, RIGHTS, LICENSING_INFO
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class AboutPageItem {
|
||||||
|
data class Item(val type: AboutItem, val title: String) : AboutPageItem()
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
/* 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.about
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import org.mozilla.fenix.settings.about.viewholders.AboutItemViewHolder
|
||||||
|
|
||||||
|
class AboutPageAdapter(private val listener: AboutPageListener) : RecyclerView.Adapter<AboutItemViewHolder>() {
|
||||||
|
|
||||||
|
private var aboutList: List<AboutPageItem>? = null
|
||||||
|
|
||||||
|
fun updateData(items: List<AboutPageItem>) {
|
||||||
|
this.aboutList = items
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AboutItemViewHolder {
|
||||||
|
val view = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(AboutItemViewHolder.LAYOUT_ID, parent, false)
|
||||||
|
|
||||||
|
return AboutItemViewHolder(view, listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = aboutList?.size ?: 0
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: AboutItemViewHolder, position: Int) {
|
||||||
|
(aboutList?.get(position) as AboutPageItem.Item).also {
|
||||||
|
holder.bind(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AboutPageListener {
|
||||||
|
fun onAboutItemClicked(item: AboutItem)
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
/* 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.about.viewholders
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import kotlinx.android.synthetic.main.about_list_item.view.*
|
||||||
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.settings.about.AboutPageItem
|
||||||
|
import org.mozilla.fenix.settings.about.AboutPageListener
|
||||||
|
|
||||||
|
class AboutItemViewHolder(
|
||||||
|
view: View,
|
||||||
|
listener: AboutPageListener
|
||||||
|
) : RecyclerView.ViewHolder(view) {
|
||||||
|
|
||||||
|
private val title = view.about_item_title
|
||||||
|
private lateinit var item: AboutPageItem.Item
|
||||||
|
|
||||||
|
init {
|
||||||
|
itemView.setOnClickListener {
|
||||||
|
listener.onAboutItemClicked(item.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bind(item: AboutPageItem.Item) {
|
||||||
|
this.item = item
|
||||||
|
title.text = item.title
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val LAYOUT_ID = R.layout.about_list_item
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
<?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="@dimen/about_list_item_height"
|
||||||
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/about_item_title"
|
||||||
|
style="@style/AboutItemText"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:gravity="center"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="What's new in Firefox Preview" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
Reference in New Issue