Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Contributions dashboard] app icon #5055

Open
wants to merge 10 commits into
base: contributions-dashboard-design
Choose a base branch
from
27 changes: 25 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
android:fullBackupContent="@xml/full_backup_rules"
android:networkSecurityConfig="@xml/network_security_config"
android:supportsRtl="true"
android:icon="@mipmap/launcher"
android:label="@string/app_name"
android:name=".WikipediaApp"
android:theme="@style/AppTheme">
Expand All @@ -90,6 +89,11 @@
android:name=".main.MainActivity"
android:windowSoftInputMode="adjustResize"
android:theme="@style/AppTheme.Splash"
android:exported="true"/>
<activity-alias
android:name=".DefaultIcon"
android:targetActivity=".main.MainActivity"
android:icon="@mipmap/launcher"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
Expand All @@ -102,7 +106,26 @@
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="wikipedia" />
</intent-filter>
</activity>
</activity-alias>
<!-- @TODO: set actual image asset for donor icon -->
<activity-alias
android:name=".DonorIcon"
android:icon="@mipmap/ic_donor_test"
android:targetActivity=".main.MainActivity"
android:exported="true"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="wikipedia" />
</intent-filter>
</activity-alias>
<activity
android:name=".page.PageActivity"
android:windowSoftInputMode="stateAlwaysHidden|adjustPan"
Expand Down
Binary file added app/src/main/ic_donor_test-playstore.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 60 additions & 0 deletions app/src/main/java/org/wikipedia/LauncherController.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.wikipedia

import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager
import org.wikipedia.settings.Prefs

object LauncherController {

fun setIcon(icon: LauncherIcon) {
val context = WikipediaApp.instance.applicationContext
val packageManager = context.packageManager
LauncherIcon.entries.forEach { i ->
packageManager.setComponentEnabledSetting(
i.getComponentName(context),
if (i == icon) PackageManager.COMPONENT_ENABLED_STATE_ENABLED else
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP
)
}
}
}

enum class LauncherIcon(
val key: String,
val displayName: String,
val background: Int,
val foreground: Int,
val label: Int,
var isSelected: Boolean = false
) {
DEFAULT(
key = "DefaultIcon",
displayName = "Default Icon",
background = R.drawable.launcher_background,
foreground = R.drawable.launcher_foreground,
label = R.string.app_name
),
DONOR(
key = "DonorIcon",
displayName = "Donor Icon",
background = R.color.ic_donor_test_background,
foreground = R.drawable.ic_donor_test_foreground,
label = R.string.app_name
);

fun getComponentName(context: Context): ComponentName {
return ComponentName(context.packageName, "org.wikipedia.$key")
}

companion object {
fun initialValues(): List<LauncherIcon> {
val savedAppIcon = Prefs.currentSelectedAppIcon ?: DEFAULT.key
entries.forEach { icon ->
icon.isSelected = icon.key == savedAppIcon
}
return entries
}
}
}
137 changes: 137 additions & 0 deletions app/src/main/java/org/wikipedia/settings/AppIconDialog.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package org.wikipedia.settings

import android.content.res.ColorStateList
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.google.android.flexbox.AlignItems
import com.google.android.flexbox.FlexDirection
import com.google.android.flexbox.FlexboxLayoutManager
import com.google.android.flexbox.JustifyContent
import org.wikipedia.LauncherController
import org.wikipedia.LauncherIcon
import org.wikipedia.R
import org.wikipedia.appshortcuts.AppShortcuts
import org.wikipedia.databinding.DialogAppIconBinding
import org.wikipedia.databinding.ItemAppIconBinding
import org.wikipedia.page.ExtendedBottomSheetDialogFragment
import org.wikipedia.util.FeedbackUtil

class AppIconDialog : ExtendedBottomSheetDialogFragment() {
private var _binding: DialogAppIconBinding? = null
private val binding get() = _binding!!

private val appIconAdapter: AppIconAdapter by lazy {
AppIconAdapter().apply {
onItemClickListener { selectedIcon ->
Prefs.currentSelectedAppIcon = selectedIcon.key
LauncherController.setIcon(selectedIcon)
AppShortcuts.setShortcuts(requireContext())
updateIcons(selectedIcon)
FeedbackUtil.makeSnackbar(
binding.root,
"App icon changed to ${selectedIcon.displayName}").show()
}
}
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = DialogAppIconBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupRecyclerView()
}

private fun setupRecyclerView() {
val layoutManager = FlexboxLayoutManager(requireContext()).apply {
flexDirection = FlexDirection.ROW
justifyContent = JustifyContent.CENTER
alignItems = AlignItems.CENTER
}
binding.appIconRecyclerView.apply {
this.layoutManager = layoutManager
adapter = appIconAdapter
}
appIconAdapter.updateItems(LauncherIcon.initialValues())
}

private fun updateIcons(selectedIcon: LauncherIcon) {
val currentSelectedIcon = if (Prefs.currentSelectedAppIcon != null) Prefs.currentSelectedAppIcon
else selectedIcon.key

LauncherIcon.entries.forEach {
it.isSelected = it.key == currentSelectedIcon
}
appIconAdapter.updateItems(LauncherIcon.entries)
}

private class AppIconAdapter : RecyclerView.Adapter<AppIconAdapter.AppIconViewHolder>() {
private var list = mutableListOf<LauncherIcon>()
private var onItemClickListener: ((LauncherIcon) -> Unit)? = null

fun onItemClickListener(onItemClickListener: (LauncherIcon) -> Unit) {
this.onItemClickListener = onItemClickListener
}

fun updateItems(newList: List<LauncherIcon>) {
list.clear()
list.addAll(newList)
notifyDataSetChanged()
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppIconViewHolder {
val view = ItemAppIconBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return AppIconViewHolder(view)
}

override fun getItemCount(): Int = list.size

override fun onBindViewHolder(holder: AppIconViewHolder, position: Int) {
val item = list[position]
holder.bind(item)
}

private inner class AppIconViewHolder(val binding: ItemAppIconBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: LauncherIcon) {
binding.appIcon.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
foreground = ContextCompat.getDrawable(binding.root.context, item.foreground)
} else {
setImageDrawable(ContextCompat.getDrawable(binding.root.context, item.foreground))
}
background = ContextCompat.getDrawable(binding.root.context, item.background)
setOnClickListener {
onItemClickListener?.invoke(item)
}
val strokeColor = if (item.isSelected) {
ContextCompat.getColor(binding.root.context, R.color.blue600)
} else Color.TRANSPARENT
this.strokeColor = ColorStateList.valueOf(strokeColor)
}
}
}
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}

companion object {
fun newInstance(): AppIconDialog {
return AppIconDialog()
}
}
}
5 changes: 5 additions & 0 deletions app/src/main/java/org/wikipedia/settings/Prefs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import okhttp3.Cookie
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.logging.HttpLoggingInterceptor
import org.wikipedia.BuildConfig
import org.wikipedia.LauncherIcon
import org.wikipedia.R
import org.wikipedia.WikipediaApp
import org.wikipedia.analytics.SessionData
Expand Down Expand Up @@ -750,4 +751,8 @@ object Prefs {
var isRecurringDonor
get() = PrefsIoUtil.getBoolean(R.string.preference_key_is_recurring_donor, false)
set(value) = PrefsIoUtil.setBoolean(R.string.preference_key_is_recurring_donor, value)

var currentSelectedAppIcon
get() = PrefsIoUtil.getString(R.string.preference_key_current_selected_app_icon, LauncherIcon.DEFAULT.key)
set(value) = PrefsIoUtil.setString(R.string.preference_key_current_selected_app_icon, value)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import org.wikipedia.Constants
import org.wikipedia.R
import org.wikipedia.WikipediaApp
import org.wikipedia.auth.AccountUtil
import org.wikipedia.donate.DonorStatus
import org.wikipedia.feed.configure.ConfigureActivity
import org.wikipedia.login.LoginActivity
import org.wikipedia.page.ExclusiveBottomSheetPresenter
import org.wikipedia.readinglist.sync.ReadingListSyncAdapter
import org.wikipedia.settings.languages.WikipediaLanguagesActivity
import org.wikipedia.theme.ThemeFittingRoomActivity
Expand Down Expand Up @@ -47,6 +49,17 @@ internal class SettingsPreferenceLoader(fragment: PreferenceFragmentCompat) : Ba
true
}
}

when (DonorStatus.donorStatus()) {
DonorStatus.DONOR -> {
findPreference(R.string.preference_key_app_icon).onPreferenceClickListener = Preference.OnPreferenceClickListener {
ExclusiveBottomSheetPresenter.show(fragment.parentFragmentManager, AppIconDialog.newInstance())
true
}
}
else -> { findPreference(R.string.preference_key_app_icon).isVisible = false }
}

findPreference(R.string.preference_key_about_wikipedia_app).onPreferenceClickListener = Preference.OnPreferenceClickListener {
activity.startActivity(Intent(activity, AboutActivity::class.java))
true
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/res/drawable/ic_donor_test_foreground.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#ECECEC">
<group android:scaleX="0.58"
android:scaleY="0.58"
android:translateX="5.04"
android:translateY="5.04">
<path
android:fillColor="@android:color/white"
android:pathData="M11.8,10.9c-2.27,-0.59 -3,-1.2 -3,-2.15 0,-1.09 1.01,-1.85 2.7,-1.85 1.78,0 2.44,0.85 2.5,2.1h2.21c-0.07,-1.72 -1.12,-3.3 -3.21,-3.81V3h-3v2.16c-1.94,0.42 -3.5,1.68 -3.5,3.61 0,2.31 1.91,3.46 4.7,4.13 2.5,0.6 3,1.48 3,2.41 0,0.69 -0.49,1.79 -2.7,1.79 -2.06,0 -2.87,-0.92 -2.98,-2.1h-2.2c0.12,2.19 1.76,3.42 3.68,3.83V21h3v-2.15c1.95,-0.37 3.5,-1.5 3.5,-3.55 0,-2.84 -2.43,-3.81 -4.7,-4.4z"/>
</group>
</vector>
48 changes: 48 additions & 0 deletions app/src/main/res/layout/dialog_app_icon.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools">

<TextView
android:id="@+id/app_icon_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginStart="16dp"
android:fontFamily="sans-serif-medium"
android:gravity="center_vertical"
android:text="@string/contributions_dashboard_app_icon_title"
android:textColor="?attr/primary_color"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>

<TextView
android:id="@+id/app_icon_sub_title"
style="@style/Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:textAllCaps="true"
android:text="@string/contributions_dashboard_app_icon_subtitle"
android:textColor="?attr/primary_color"
app:layout_constraintBaseline_toBaselineOf="@+id/app_icon_title"
app:layout_constraintBottom_toBottomOf="@+id/app_icon_title"
app:layout_constraintStart_toEndOf="@+id/app_icon_title"
app:layout_constraintTop_toTopOf="@+id/app_icon_title" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/appIconRecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/app_icon_title"
tools:itemCount="2"
tools:listitem="@layout/item_app_icon"
/>

</androidx.constraintlayout.widget.ConstraintLayout>
16 changes: 16 additions & 0 deletions app/src/main/res/layout/item_app_icon.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.imageview.ShapeableImageView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/app_icon"
android:layout_width="52dp"
android:layout_height="52dp"
android:layout_margin="12dp"
android:scaleType="centerCrop"
android:padding="2dp"
app:shapeAppearanceOverlay="@style/CircularImageView"
app:strokeWidth="2dp"
android:clipToOutline="false"
xmlns:tools="http://schemas.android.com/tools"
tools:srcCompat="@tools:sample/avatars">

</com.google.android.material.imageview.ShapeableImageView>
5 changes: 5 additions & 0 deletions app/src/main/res/mipmap-anydpi-v26/ic_donor_test.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_donor_test_background"/>
<foreground android:drawable="@drawable/ic_donor_test_foreground"/>
</adaptive-icon>
5 changes: 5 additions & 0 deletions app/src/main/res/mipmap-anydpi-v26/ic_donor_test_round.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_donor_test_background"/>
<foreground android:drawable="@drawable/ic_donor_test_foreground"/>
</adaptive-icon>
Binary file added app/src/main/res/mipmap-hdpi/ic_donor_test.webp
Binary file not shown.
Binary file not shown.
Binary file added app/src/main/res/mipmap-mdpi/ic_donor_test.webp
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
4 changes: 4 additions & 0 deletions app/src/main/res/values/ic_donor_test_background.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_donor_test_background">#2F8743</color>
</resources>
Loading
Loading