[fenix] For https://github.com/mozilla-mobile/fenix/issues/4776: Redesign and refactor the About Page
Added new items to be displayed.pull/600/head
parent
d467ebf6b3
commit
abb0295559
@ -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